dimforge / nalgebra

Linear algebra library for Rust.
https://nalgebra.org
Apache License 2.0
4.05k stars 485 forks source link

Concept for reducing the verbosity of generics #1419

Open jimy-byerley opened 5 months ago

jimy-byerley commented 5 months ago

Concept for reducing the verbosity of generics

Hello nalgebra maintainers This weekend I have been doing some experiments in designing a matrix structure with the same goals as nalgebra's (static & dynamic arrays, small & large dimensions, ergonomics ...) but with the less possible verbosity due to generics. (I must admit I often have been bored by the complexity of specifying generics before starting implementing a generic function using nalgebra)

I ended up in a good proof of concept, I called flexalgebra. For the moment it only has implementations for scalar, elementwise and matrix operations for all the type of matrices and vectors and their constructors. I assume they are the most relevant operations for what I'm talking about.

I share it with you in case it might be of some use. I would be very interested in having your opinion anyway

failed concepts

I started defining Matrix<T,R,C> as a trait with type and shape arguments, so any crate could implement it on array structures and benefit from all matrix methods and traits implementations, and compatibility with other matrices. It did not worked for obvious reasons: the trait matrix could be implemented multiple times for the same struct

I then defined the type and shape as trait attributes rather than trait arguments: Matrix<Element=T, Rows=R, Columns=C> so without arguments the trait could be implemented only once. It did not worked either for obvious reasons: implementing foreign traits like Index or Mul on possibly foreign types is not allowed.

So I adopted the newtype pattern as recommended for such issue. making struct Matrix(array) a wrapper.

key concepts

The Matrix type is only a wrapper of its array storage, a bit like currently in nalgebra but without any generic parameters or additional private fields

Being a wrapper has many advantages for the matrix struct:

Without any generics, this type wrapper rely only on the genericity of its underlying array. The matrix properties then only depends on the traits implemented by this array. In a way nalgebra does this, but at the same type keeps generics at the matrix level, generating lot of clauses to make a matrix compatible with its array.

For the array traits, I set the generics also as attributes rather than parameters. This allows to omit these parameters and mention them in generics clauses only when we need to constrain them. This way writing code with high degree of genericity (with less constraints on generics) is very simple. This is the point that greatly simplified my library.

limitations

This concept brings two minor limitations to what nalgebra currently does:

This raises however the following limitations compared to nalgebra:

In addition the core set of structs and traits defining a matrix becomes minimalistic, which is good I think !

conclusion

I know that nalgebra is already well diffused and complete, I do not ask any of this to land one day in nalgebra. Even though I would appreciate an improvement regarding the initial verbosity concerns . This is just a proof of concept for reducing this concern.

Check the code, tell me what you think !