Particularly, the default `from_f64` used `n as i64`, which has
undefined behavior on overflow, kind of defeating the purpose here.
Now we use a checked `to_i64()` for this, and even try `to_u64()` as a
fallback for completeness.
(All of the primitive implementations already do better, at least.)
This includes new conditional methods `ToPrimitive::{to_i128,to_u128}`
and `FromPrimitive::{from_i128,from_u128}`. Since features can only be
additive, these methods must not cause a breaking change to anyone when
enabled -- thus they have a default implementation that converts through
64-bit values. Types that can do better with a full 128-bit integer,
like bigint or floating-point, will probably want to override these.
We don't actually need to compute the `trunc()` value, as long as we can
figure out the right values for the exclusive range `(MIN-1, MAX+1)` to
measure the same truncation effect.
This change adds some new macro rules used when converting from floats
to integers. There are two macro rule variants, one for signed ints, one
for unsigned ints.
Among other things, this change specifically addresses the overflow case
documented in https://github.com/rust-num/num-traits/issues/12
We don't have implementations for many of the methods in `no_std`. It's
hostile to external implementors if some trait methods are conditional
on a feature, as that feature could be added by anyone in a dependency
tree. Instead, let's just live without these traits for now.