This crate is a replacement for the popular num ecosystem.
It allows much more (almost maximal) flexibility with the defined algebraic structures.
Due to it's more general type handling, this crate doesn't add much weight, even though it
contains both complex numbers and rational numbers. In particular there is only a few places,
where things had to be defined for all available integer types and the implementations are trivially small.
There is no dependence on Copy anywhere and nothing is limited to buildin types.
A central objective of this crate is to only have traits which are essential, or very useful.
- Essential traits are e.g.
Zero,One,Num,NumAlgebraic,NumElementaryandEuclid. (these need to be implemented) - Grouping/alias traits are
Ring,Field,AlgebraicFieldandAddMulSubDiv(+ lesser variants). - Derived traits are
Cancel,SafeDiv,PowerU,PowerI,IntMul.
After implementing ring and field traits, one might ask for a commutative marker trait for multiplication and addition, however that is explicitly not implemented, as it's not essential to a functioning type system in Rust. Algorithms should tell in their description if they work for commutative types only, if not obvious.
All operator implementations, which mix references and owned structs are considered bloat, as the
real world performance benefit hasn't been demonstrated. Note that any type with expensive clone
could just internally use Arc or Cow to make it cheap again. Usually one can already write equations
optimal with non-mixed operations. Moreover, no crates (should) depend on having the mixed operators.
Similarly the assign operators like AssignAdd are implemented based on the reference Add operation.
This is done without cloning thanks to take_mut.
Whenever deciding between precision and performance, the question of what is required more frequently
and what can be implemented outside of this library is asked. E.g. the Ratio type does expensive
canceling to get the most range out of its integers, whereas Complex doesn't do that, as it's usually
used with floats.
The resulting Complex and Ratio types are slightly different in some places, but largely compatible with num.
E.g. The multiplicative inverse on these commutative fields is called recip instead of inv, as some type might be an invertible
function (e.g. Moebius transform), which needs inv for inversion wrt composition, but can still have recip.
Float approximations of numbers are implemented using the trait ApproxFloat. They can be chained through types.
E.g. a Ratio with SqrtExt as numerator and denominator can directly be converted to a float.
std(default, however not required)libmas a replacement forstdwhen using floats.quaternionfor theQuaterniontype.rationalfor theRatioandSqrtExttypes.randfor uniform, normal and unitary random distributions for complex types.bytemuckibigto include trait implementations foribigserde
The tests from num_complex and num_rational are copied where applicable.
In this process, bugs in their testing code have been found. The improved testing code
is no longer fully succeeding for num_complex and num_rational.
Note, that it is impossible to test all combinations, which are allowed in this crate.
There is many cases in the rational part, where the gcd doesn't converge (infinite loop),
because e.g. it is evaluated on a domain which is not Euclidean. Some functions have relaxed
trait bounds to the point, where they can be called on types that don't work.
E.g. SqrtExt in large part only works for types with commutative multiplication.
Be careful and respect math.
To make other crates, which are not considered in this one, work, one needs to implement Num for them.
This can only be done in said crate, or by creating a wrapper and forwarding all functionallity.
For complex numbers, binary operations like T + Complex<T> are not implemented,
as that would require an implementation for every specific type (bloat for nothing).
Overflows are well avoided in rational, but no checked functions are implemented.
Other places, like complex and extension are prone to integer overflow.
Use custom wrappers on the int types. E.g. enum Checked<T> { Value(T), Overflow } to manage the overflows.
- As an improvement, implement a
Gaussiantype for integral complex numbers, which uses canceling to avoid overflows. Zero,ConjugateandEuclidshould have derive macros just likeClone, currently there isimpl_zero_default!,impl_conjugate_real!andimpl_euclid_field!.- Add a macro, which, based on Deref, forwards all arithmetic operations of a wrapper type automatically.
- Hide approximation from floats for rational and sqrt types behind a feature flag (test if this is beneficial for compile times).
- Add string parsing for complex and rational types (and hide it behind a feature flag to avoid bloat)
- The reference implementation need to use the non reference implementations to avoid recursive trait evaluations by SIMD types. Make sure to never do clones for nothing and use optimal operations as much as possible!
License: MIT OR Apache-2.0