99: Revive Float+Real in no_std thanks to libm r=cuviper a=yoanlcq
Greetings,
This is a hopeful fix for #75.
Basically: Add `libm` as an optional dependency, and handle three possible cases depending on which features are enabled:
- std and libm: std is used;
- std and not libm: std is used;
- libm and not std: libm and FloatCore are used.
It was briefly mentioned that `libm` wasn't ready yet, but this was months ago, and I believe it is better not to wait for too long.
If anything, bugs in `libm` should be fixed in `libm`; `num-traits` is only delegating its implementations to it; not to mention that the more `libm` is used, the likelier issues are to be found and hopefully fixed.
Thanks in advance!
Co-authored-by: Yoan Lecoq <yoanlecoq.io@gmail.com>
Co-authored-by: Josh Stone <cuviper@gmail.com>
Fix#57 and more:
- CheckedShl was hinting that None was returned on overflow rather than
on too large a rhs.
- Ditto for CheckedShr.
- CheckedShr documentation erroneously indicated that a left shift was
going to be performed instead of a right shift.
Add traits `WrappingShl` and `WrappingShr` corresponding to the
standard library `wrapping_shl` and `wrapping_shr` methods. Implement
the trait on all primitive integer types as well as on `Wrapping`.
59: Added `MulAdd` and `MulAddAssign` traits r=cuviper a=regexident
Both `f32` and `f64` implement fused multiply-add, which computes `(self * a) + b` with only one rounding error. This produces a more accurate result with better performance than a separate multiplication operation followed by an add:
```rust
fn mul_add(self, a: f32, b: f32) -> f32[src]
```
It is however not possible to make use of this in a generic context by abstracting over a trait.
My concrete use-case is machine learning, [gradient descent](https://en.wikipedia.org/wiki/Gradient_descent) to be specific,
where the core operation of updating the gradient could make use of `mul_add` for both its `weights: Vector` as well as its `bias: f32`:
```rust
struct Perceptron {
weights: Vector,
bias: f32,
}
impl MulAdd<f32, Self> for Vector {
// ...
}
impl Perceptron {
fn learn(&mut self, example: Vector, expected: f32, learning_rate: f32) {
let alpha = self.error(example, expected, learning_rate);
self.weights = example.mul_add(alpha, self.weights);
self.bias = self.bias.mul_add(alpha, self.bias)
}
}
```
(The actual impl of `Vector` would be generic over its value type: `Vector<T>`, thus requiring the trait.)
Co-authored-by: Vincent Esche <regexident@gmail.com>
Co-authored-by: Josh Stone <cuviper@gmail.com>
Make the checked left and right shifts take a `u32` as right-hand side,
which is more consistent with the other checked operations. Also drop
`CheckedShl` and `CheckedShr` from the `PrimInt` trait, to not break
existing code. Add doctests for the two traits.
Add traits `CheckedShl` and `CheckedShr` that correspond to the standard
library's `checked_shl` and `checked_shr` functions. Implement the trait
on all primitive integer types by default, akin to what the standard
library does.
The stdlib is somewhat inconsistent when it comes to the type of the
shift amount. The `checked_*` functions have a `u32` shift amount, but
the `std::ops::{Shl,Shr}` traits are generic over the shift amount. Also
the stdlib implements these traits for all primitive integer types as
right-hand sides. Our implementation mimics this behaviour.