-
-
Notifications
You must be signed in to change notification settings - Fork 484
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Generics with 0.11 become really hard #222
Comments
I agree that using the generic matrix and vector types is too difficult to be verry useful at the moment. The bounds on the data storage type are not always easy to set and are the one thing I did not document on the users guide yet... The closest to the old Regarding number conversion, the old |
sounds great. i'm using this at the moment to bring back BaseNum, NumVec and FloatVec in case it's useful:
|
The traits you are proposing for vectors are interesting and I would be willing to add them (under the name Is there any specific reason (or issue you might have faced) why you implement them for specific vector types instead of implementing for any type |
with any type T do you mean implementing them for VectorN<T,D>? that would make sense, i think i just did it like this cause the requirements for the D in VectorN are also really hard to get right. btw there was an error in the original post where NumVector was only accepting real numbers, the correct implementation would be: pub trait BaseNum: Scalar +
alga::general::Identity<alga::general::Additive> +
alga::general::Identity<alga::general::Multiplicative> +
num::Zero +
num::One +
Add<Self, Output = Self> + Sub<Self, Output = Self> +
Mul<Self, Output = Self> + Div<Self, Output = Self> +
Rem<Self, Output = Self> +
AddAssign<Self> + SubAssign<Self> +
MulAssign<Self> + DivAssign<Self> +
RemAssign<Self> +
PartialOrd +
'static{
}
impl BaseNum for i8 { }
impl BaseNum for i16 { }
impl BaseNum for i32 { }
impl BaseNum for i64 { }
impl BaseNum for isize { }
impl BaseNum for u8 { }
impl BaseNum for u16 { }
impl BaseNum for u32 { }
impl BaseNum for u64 { }
impl BaseNum for usize { }
impl BaseNum for f32 { }
impl BaseNum for f64 { }
pub trait BaseInt: BaseNum +
Shl<Self, Output = Self> +
ShlAssign<Self> +
Shr<Self, Output=Self> +
ShrAssign<Self>{}
impl BaseInt for i8 { }
impl BaseInt for i16 { }
impl BaseInt for i32 { }
impl BaseInt for i64 { }
impl BaseInt for isize { }
impl BaseInt for u8 { }
impl BaseInt for u16 { }
impl BaseInt for u32 { }
impl BaseInt for u64 { }
impl BaseInt for usize { }
/*
* Vector related traits.
*/
/// Trait grouping most common operations on vectors.
pub trait NumVector<N>: Add<Self, Output = Self> + Sub<Self, Output = Self> +
// Mul<Self, Output = Self> + Div<Self, Output = Self> +
// Add<N, Output = Self> + Sub<N, Output = Self> +
Mul<N, Output = Self> + Div<N, Output = Self> +
AddAssign<Self> + SubAssign<Self> +
// MulAssign<Self> + DivAssign<Self> +
// AddAssign<N> + SubAssign<N> +
MulAssign<N> + DivAssign<N> +
alga::general::Identity<alga::general::Additive> +
PartialEq
where Self: Sized {
}
/// Trait of vector with components implementing the `BaseFloat` trait.
pub trait FloatVector<N: alga::general::Real>: NumVec<N> +
alga::linear::NormedSpace +
Neg<Output = Self> +
Axpy<N> +
alga::linear::FiniteDimVectorSpace +
alga::linear::FiniteDimInnerSpace {
}
impl<N: BaseNum> NumVector<N> for Vector1<N>{}
impl<N: BaseNum> NumVector<N> for Vector2<N>{}
impl<N: BaseNum> NumVector<N> for Vector3<N>{}
impl<N: BaseNum> NumVector<N> for Vector4<N>{}
impl<N: BaseNum> NumVector<N> for Vector5<N>{}
impl<N: BaseNum> NumVector<N> for Vector6<N>{}
impl<N: BaseNum + alga::general::Real> FloatVector<N> for Vector1<N>{}
impl<N: BaseNum + alga::general::Real> FloatVector<N> for Vector2<N>{}
impl<N: BaseNum + alga::general::Real> FloatVector<N> for Vector3<N>{}
impl<N: BaseNum + alga::general::Real> FloatVector<N> for Vector4<N>{}
impl<N: BaseNum + alga::general::Real> FloatVector<N> for Vector5<N>{}
impl<N: BaseNum + alga::general::Real> FloatVector<N> for Vector6<N>{}
pub trait NumPoint<N>: // Sub<Self, Output = NumVector<N>> + //TODO: Output Vec
// Mul<Self, Output = Self> + Div<Self, Output = Self> +
// Add<N, Output = Self> + Sub<N, Output = Self> +
Mul<N, Output = Self> + Div<N, Output = Self> +
// MulAssign<Self> + DivAssign<Self> +
// AddAssign<N> + SubAssign<N> +
MulAssign<N> + DivAssign<N> +
PartialEq
where Self: Sized {
}
pub trait FloatPoint<N: alga::general::Real>: NumPoint<N> +
Neg<Output = Self> +
Axpy<N> +
alga::linear::AffineSpace +
alga::linear::EuclideanSpace {
}
impl<N: BaseNum> NumPoint<N> for Point1<N>{}
impl<N: BaseNum> NumPoint<N> for Point2<N>{}
impl<N: BaseNum> NumPoint<N> for Point3<N>{}
impl<N: BaseNum> NumPoint<N> for Point4<N>{}
impl<N: BaseNum> NumPoint<N> for Point5<N>{}
impl<N: BaseNum> NumPoint<N> for Point6<N>{}
impl<N: BaseNum + alga::general::Real> FloatPoint<N> for Point1<N>{}
impl<N: BaseNum + alga::general::Real> FloatPoint<N> for Point2<N>{}
impl<N: BaseNum + alga::general::Real> FloatPoint<N> for Point3<N>{}
impl<N: BaseNum + alga::general::Real> FloatPoint<N> for Point4<N>{}
impl<N: BaseNum + alga::general::Real> FloatPoint<N> for Point5<N>{}
impl<N: BaseNum + alga::general::Real> FloatPoint<N> for Point6<N>{} |
@arturoc have you been doing anything further on this issue? It might be worth starting with the specialized impls and then replacing them with the more general version, once it is clear, how to do that. That should be a compatible extension, as far as I can see. |
i have something working here: https://github.com/arturoc/na/blob/master/src/lib.rs#L397-L526 that is a library i did a while ago when nalgebra changed to long names (Vec3 -> Vector3...) since i had a large codebase using the old naming and i wasn't sure i wanted to change everything to the new naming so that library wraps nalgebra to keep the old short names for the elements most used in graphics programming. if there's any interest i can create a pull request for the part related to this (of course using long names not the ones i have) apart from that over time i've also implemented:
let xy = v3.xy()
let xz = v3.xz()
.... which work for Vector2/3/4 and Point2/3/4
let one = vec3!(1.); //sets all components to 1
let composed = vec3!(v2, z); // creates a Vector3 from a Vector2 and a float
... I can create a PR for any of those features if they seem interesting or feel free to pull them from my repo and adapt them if you prefer |
It might be of interest, if it facilitates generic programming. How does this relate to our existing integration with Regarding the other features, I would just open a new issue and see whether there is general interest in it. It seems nice in terms of ergonomics, but I wonder how often it would really be used. |
I haven't followed that but most probably is already covered then (can you point me to it?) i did this a while ago and never sent a PR cause i wasn't sure it was complete, i've been using it for a while now and haven't had any trouble. |
You can find We could make use of these existing abstractions instead of creating our own, where possible. That's also more interoperable with other crates providing generic code for these abstractions. |
Recently, I have tried to create generic structs that contain I'm trying to achieve things similar to this post: https://discourse.nphysics.org/t/using-nalgebra-in-generics/90/3 |
@grtlr Right now the best you can do is the solution based on extern crate nalgebra as na;
use na::{DefaultAllocator, Scalar, Dim, VectorN, MatrixN};
use na::allocator::Allocator;
fn main() {}
struct NPoint<N: Dim>(VectorN<usize, N>)
where DefaultAllocator: Allocator<usize, N> ;
struct Container<T: Scalar, D: Dim>
where DefaultAllocator: Allocator<T, D, D>
{
x: MatrixN<T, D>
} The two features from the language that would significantly improve this are const-generics and specialization. AFAIK const-generics are being worked on actively: rust-lang/rust#53645. Not sure about specialization though. |
@sebcrozet Sorry for resuscitating this thread. How would you go about making a generic implementation of a struct like this? struct Container<T: Scalar, D: Dim>
where DefaultAllocator: Allocator<T, D, D>
{
x: MatrixN<T, D>
} Is it possible? Thanks! |
Hi @nravic! Yes, such a container is possible as long as you have the right trait bounds. The struct you are suggesting is the right way of doing it. |
I might be missing some new trait that might make this easier but things seem to have got really complicated when using generics and nalgebra 0.11
I have code like this in 0.10:
extern crate nalgebra;
extern crate num;
where a function takes a vector of any dimension U and it's type T and internally casts some real numbers to T and does some basic operations with the vector type and the numbers.
in 0.11 that becomes something like:
which is already way more complex than before, needing to specify every operation used over the vector, again i'm not sure if there's any new class that does something similar to FloatVector but is suspect there's not since the storage type makes it harder to generalize every possible vector.
i also guess that using the num crate for number casting shouldn't be needed anymore with alga? but can't find anything to substitute it, have tried with supersetOf but can't get it to work.
now if i try to add a line of code where i get a zero vector things get even more complicated:
now i get:
if i add to the where clause of the function
S: storage::Storage<T,D,U1>
then i get:which doesn't give a clear hint of a possible solution anymore.
the real solution is not to add an storage type but instead add
alga::general::Identity<alga::general::Additive>
to the ColumnVector where clauseI've found similar problems while trying to port some code to 0.11 where adding some trait to solve some error triggers another to a point where the signature of every function becomes extra long and it's really hard to figure out but even once you figure it out then calling two functions from a thrid becomes another problem cause the requirements of the two functions somehow clash.
Not sure if there's already something like that in alga or nalgebra but if would be useful to have something similar to the old FloatVector that allows to specify the most commonly used VectorN without having to worry about specifying all the possible operations, storage type...
error messages have also become really cryptic because of the usage of Matrix for every type although i guess there's no solution for that unless the rust compiler optionally allowed to show aliases for types in errors instead of the original type
The text was updated successfully, but these errors were encountered: