Open mgeier opened 5 years ago
There should be implementation of NormedSpace
for f32
and f64
: https://github.com/rustsim/alga/blob/dev/alga/src/linear/vector.rs#L286
And yes real numbers form a normed space over multiple different norms.
(I wouldn't call floating point numbers real numbers, but it is what it is.)
Thanks for the answer, I'm glad that my question wasn't complete nonsense ...
It turns out that the implementation in question was added in #86, only 13 days ago!
I was using the latest alga
release, that's why I didn't see it.
Using the dev
branch I can now do what I was asking for, but I'm still wondering:
Wouldn't it be possible to add this as a blanket implementation for all types T
that implement alga::general::ComplexField
(instead of just the concrete implementations for f32
and f64
)?
And since ComplexField
is already implemented for num_complex::Complex
, wouldn't this also make the implementation of NormedSpace
for Complex
(https://github.com/rustsim/alga/blob/dev/alga/src/linear/vector.rs#L292-L339) obsolete?
Wouldn't it be possible to add this as a blanket implementation for all types T that implement alga::general::ComplexField
I believe this would prevent implementation for, e.g., Vector3<T>
because writing impl VectorSpace for Vector3<T>
would be detected as a conflicting impl by the compiler (even though it does not actually conflicts with the blanket impl).
Sorry for the late response!
I came up with a simplified example where I think the aforementioned blanket implementation is missing:
use alga::general::RealField;
use alga::linear::VectorSpace;
struct SomeStruct<S: RealField, V: VectorSpace<Field = S>> {
s: S,
v: V,
}
struct LimitedStruct<S: RealField> {
inner: SomeStruct<S, S>,
}
This fails to compile:
error[E0277]: the trait bound `S: alga::linear::vector::VectorSpace` is not satisfied
I don't know how this could be implemented, but I think theoretically this should work, because anything that is a RealField
should also be a (albeit trivial) VectorSpace
, shouldn't it?
How could I make this work?
In case you are wondering what my concrete application is, you can have a look at https://github.com/AudioSceneDescriptionFormat/asdfspline-rust/blob/master/src/monotonecubicspline.rs.
There I have a MonotoneCubicSpline
, which only really makes sense with scalar values, but I would like to implement it based on the more generic PiecewiseCubicCurve
, which is implemented for vector values.
I still think a blanket implementation would make sense (if it would be possible), but in the meantime, there is a work-around for my example above, just adding the "vector" requirement to the "scalar" type:
struct LimitedStruct<S: RealField + VectorSpace<Field = S>> {
inner: SomeStruct<S, S>,
}
To me, this looks a bit recursive (S
appearing in the trait bounds of S
), but the compiler seems to accept it.
In my actual use case this got a bit too complicated (I've not fully implemented it, so I don't know whether it would have actually worked), so I came up with an alternative approach:
I just added a new type parameter F: Fn(V) -> S
which is used to pass/store a function that calculates the norm of a vector of type V
. Now a user has to manually pass this function in a few places and handle an additional type parameter, both of which is a little annoying (but it works). The big advantage of this approach, though, is that now a user can implement a "norm" function for any foreign vector type without violating Rust's orphan rule.
Sorry for the comment-spam, but just after posting my previous comment, I've read https://blog.mgattozzi.dev/orphan-rules/, which explains a nice work-around to avoid the limitations of Rust's orphan rule.
I've implemented this in my project and it works very well, for details see this commit: https://github.com/AudioSceneDescriptionFormat/asdfspline-rust/commit/c75463a1c084c38d8cb06c4f3ee3025fba71b074.
Instead of providing a function multiple times (as in my above-mentioned work-around), the user creates a dummy struct (to have something to implement a trait on) and implements a trait (involving their dummy struct) for the type in question that should get a norm()
function:
pub struct DummyVec3;
impl NormWrapper<DummyVec3> for Vec3 {
type Norm = f32;
fn norm(&self) -> Self::Norm {
self.norm()
}
}
I think in my case this work-around is nicer than the function-passing work-around. There are very few situations where the dummy struct has to be specified with a turbofish (which is a little ugly), but most of the times, everything is deduced automatically.
I'm very much not a mathematician, nor am I a Rust expert, so please forgive me if this is a silly question.
I'm working on a spline implementation which I will mostly use for 3D curves, but I would also like it to work for 2D curves and for 1D (I don't know if those can still be called "curves").
For 2D and 3D I'm using vector types from the
nalgebra
crate (which implement severalalga
traits).Since my implementation is supposed to work on any vector space that has a norm, I think it would make sense to use the
alga::linear::NormedSpace
trait bound.For the 1D case I could of course use a 1D vector from
nalgebra
, but I think it would be much nicer if I could also use a "normal" scalar type, like e.g.f64
.This doesn't work though, because
NormedSpace
doesn't seem to be implemented forf64
(it looks like it's only implemented forComplex<N>
).Now my question: are real numbers a normed space? I would think so, but what do I know ...
If that makes at least some mathematical sense, would it be possible to implement
NormedSpace
for scalars?I'm thinking about something like this:
Or probably this should use
ComplexField
instead?