dimforge / alga

Abstract algebra for Rust.
194 stars 40 forks source link

RealField/ComplexField traits #71

Open Coder-256 opened 5 years ago

Coder-256 commented 5 years ago

Thank you all so much for adding in complex support! It makes my project 100x easier now that I can use existing matrix functions with complex numbers. I have just a few lingering concerns about the traits.

First of all, would it be possible to remove the Bounded requirement of RealField? Although this would be a breaking change, it would allow using arbitrary-size numbers or rationals, as long as they implement Copy. I understand the argument that they should probably implement Clone instead, but on the other hand, I seriously doubt that many functions rely on Bounded, and that could be added as a generic requirement for those limited cases. Furthermore, using Bounded does not really make much sense for floating point numbers anyway since it is almost always impractical that any number should ever come even close to the maximum possible float (since they store an exponent and significand rather than a binary number like u8; f64::MAX > 10308).

Second, is the 'static requirement for ComplexField really necessary? Yes, I know that removing this would be very breaking, and make things a bit more difficult to write, but I IMHO at least eventually it is a necessary step in order to write any performant code using alga in order to avoid memory leaks. Same goes for Send, Sync, Any, and Debug/Display. As is the case for Bounded, I think it would make more sense for rarely-used requirements like these to be specified for individual functions and to only require the real necessities like arithmetic as a requirement for all ComplexField and thereby RealField numbers.

Third, one more breaking change: would it be possible to eventually refactor the requirements for trigonometric/hyperbolic/exponential/logarithmic, etc. functions into requirements for the corresponding traits in num_traits? This would make implementing those functions easier. Or better yet, at least for RealField, would it be possible to remove those requirements except for the functions that use them?


Overall, the most important request I have is removing 'static. Everything else is just a suggestion/proposal, but IMHO removing 'static is essential for proper memory management even if it makes generics a bit more difficult.

Thank you again, and please note that everything here is just ideas for consideration and not feature requests. I understand if not everything here would make sense to implement.

sebcrozet commented 5 years ago

Thank you for your feedback!

Overall, the most important request I have is removing 'static. Everything else is just a suggestion/proposal, but IMHO removing 'static is essential for proper memory management even if it makes generics a bit more difficult.

The 'static marker has nothing to do with memory leaks. It only means one thing: that the type implementing the trait does not contain any pointer/reference to another structure. It other words it means that the lifetime of an instance of the type is not tied to the lifetime of any other variable. This seems to be a reasonable requirement for a scalar.

remove the Bounded requirement

As long as we only accept Copy types, it is technically impossible to implement an unbounded type. Though removing it could be considered if a practical problematic case shows up.

Third, one more breaking change: would it be possible to eventually refactor the requirements for trigonometric/hyperbolic/exponential/logarithmic, etc. functions into requirements for the corresponding traits in num_traits? This would make implementing those functions easier. Or better yet, at least for RealField, would it be possible to remove those requirements except for the functions that use them?

That's something we would like to do eventually, yes. This is not the case currently because the corresponding traits in num_traits require the std feature. So we can't do that yet since we want alga and nalgebra to remain usable in a #[no-std] context. I believe the main blocker is https://github.com/rust-num/num-traits/issues/75.

Coder-256 commented 5 years ago

@sebcrozet Thank you. However the main reason I was suggesting removing 'static and Bounded is in order to use dynamically sized numbers or symbolic math. Both of these requirements are barriers to that. I am not asking for alga to explicitly add support for those, just wondering about the purpose/necessity of some trait requirements that would be difficult to implement. I hope that makes things a bit clearer.

Also note that in terms of the Copy vs Clone issue, correct me if I'm wrong but couldn't references to dynamically sized numbers implement Copy? (for example, backed by Vec). For example, String is only Clone but you can have multiple &str as long as the String lives.

sebcrozet commented 5 years ago

However the main reason I was suggesting removing 'static and Bounded is in order to use dynamically sized numbers or symbolic math. Both of these requirements are barriers to that. I am not asking for alga to explicitly add support for those, just wondering about the purpose/necessity of some trait requirements that would be difficult to implement. I hope that makes things a bit clearer.

I agree Bounded could make implementing dynamically sized numbers or symbolic math more difficult.

However 'static should not cause any issue. For example types like BigInt or BigDecimal are 'static. And more generally so is Vec<T> as long as T: 'static. Even Arc<RwLock<T>> is 'static! The only thing that would be prevented are structs containing references.

However allowing structs containing non-'static references is a much much more difficult topic since there is no way of creating such a struct from nothing. Even fundamental traits like Zero and One could not be implemented for those, and I'm pretty confident none of the operator overloading traits could be implemented in any useful way either.

In the end 'static is not something I'd find worth removing unless someone can provide a concrete example (with actual code that compile including example of simple math traits without the 'static bound) where a non-'static type would work is a useful way.