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.
Being a wrapper has many advantages for the matrix struct:
it takes nothing to create and destroy
it can eventually wrap any user array type
it doesn't add too much verbosity to the definition of the underlying type
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:
array storage types cannot implement array traits multiple types (because traits are using attributes rather than parameters), but who needs that ?
Matrix type cannot specialize according to dimensionalities:
Since rust's current trait solver does not detect exclusive traits it is not able to detect that Matrix<SomeTrait<R=Dyn>> is different from Matrix<SomeTrait<R=Const>> giving that Dyn and Const are types.
Whereas currently in nalgebra it is able to detect that Matrix<T,Dyn,...> is different than Matrix<T,Const,...>
So in flexalgebra there can be only one method or trait implementation for dimensions and types, as long as the array storage type is generic.
It is a bit bothering because it requires to implement matrix constructors specifically for each matrix type. But I think this is not a great limitation since most methods are fully generic and other could be named differently according to dimensionality
This raises however the following limitations compared to nalgebra:
no more need to specify 10 generics in each function impl
very easy to implement array storage traits for user types
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.
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 structI 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 likeIndex
orMul
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 innalgebra
but without any generic parameters or additional private fieldsBeing 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:
array storage types cannot implement array traits multiple types (because traits are using attributes rather than parameters), but who needs that ?
Matrix
type cannot specialize according to dimensionalities:Matrix<SomeTrait<R=Dyn>>
is different fromMatrix<SomeTrait<R=Const>>
giving thatDyn
andConst
are types.Matrix<T,Dyn,...>
is different thanMatrix<T,Const,...>
So in flexalgebra there can be only one method or trait implementation for dimensions and types, as long as the array storage type is generic.
It is a bit bothering because it requires to implement matrix constructors specifically for each matrix type. But I think this is not a great limitation since most methods are fully generic and other could be named differently according to dimensionality
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 !