implement more num-traits traits

This commit is contained in:
Trevor Spiteri 2020-10-20 16:02:43 +02:00
parent 8313677cb8
commit bcdd6d5d41
4 changed files with 351 additions and 17 deletions

View File

@ -80,12 +80,31 @@ The conversions supported cover the following cases.
### Version 1.4.0 news (unreleased)
* For the experimental feature [`num-traits`][feat-exp-1-4], the
following traits were implemented where applicable ([issue 23]):
* [`Num`][nt-0-2-num]
* [`Signed`][nt-0-2-signed], [`Unsigned`][nt-0-2-unsigned]
* [`Inv`][nt-0-2-inv]
* [`MulAdd`][nt-0-2-ma], [`MulAddAssign`][nt-0-2-maa]
* [`FloatConst`][nt-0-2-fc]
* [`ToPrimitive`][nt-0-2-tp], [`FromPrimitive`][nt-0-2-fp]
* For the experimental feature [`serde-str`][feat-exp-1-4],
serialization in human-readable formats was made more convenient
to write manually. (This makes it incompatible with the version in
1.3.0.)
to write manually ([issue 24]). This makes it incompatible with
the version in 1.3.0.
[feat-exp-1-4]: https://tspiteri.gitlab.io/fixed/dev/fixed/#experimental-optional-features
[issue 23]: https://gitlab.com/tspiteri/fixed/-/issues/23
[issue 24]: https://gitlab.com/tspiteri/fixed/-/issues/24
[nt-0-2-fc]: https://docs.rs/num-traits/^0.2/num_traits/float/trait.FloatConst.html
[nt-0-2-fp]: https://docs.rs/num-traits/^0.2/num_traits/cast/trait.FromPrimitive.html
[nt-0-2-inv]: https://docs.rs/num-traits/^0.2/num_traits/ops/inv/trait.Inv.html
[nt-0-2-ma]: https://docs.rs/num-traits/^0.2/num_traits/ops/mul_add/trait.MulAdd.html
[nt-0-2-maa]: https://docs.rs/num-traits/^0.2/num_traits/ops/mul_add/trait.MulAddAssign.html
[nt-0-2-num]: https://docs.rs/num-traits/^0.2/num_traits/trait.Num.html
[nt-0-2-signed]: https://docs.rs/num-traits/^0.2/num_traits/sign/trait.Signed.html
[nt-0-2-tp]: https://docs.rs/num-traits/^0.2/num_traits/cast/trait.ToPrimitive.html
[nt-0-2-unsigned]: https://docs.rs/num-traits/^0.2/num_traits/sign/trait.Unsigned.html
### Version 1.3.0 news (2020-10-15)

View File

@ -8,12 +8,31 @@ as-is, without any warranty. -->
Version 1.4.0 (unreleased)
==========================
* For the experimental feature [`num-traits`][feat-exp-1-4], the
following traits were implemented where applicable ([issue 23]):
* [`Num`][nt-0-2-num]
* [`Signed`][nt-0-2-signed], [`Unsigned`][nt-0-2-unsigned]
* [`Inv`][nt-0-2-inv]
* [`MulAdd`][nt-0-2-ma], [`MulAddAssign`][nt-0-2-maa]
* [`FloatConst`][nt-0-2-fc]
* [`ToPrimitive`][nt-0-2-tp], [`FromPrimitive`][nt-0-2-fp]
* For the experimental feature [`serde-str`][feat-exp-1-4],
serialization in human-readable formats was made more convenient
to write manually. (This makes it incompatible with the version in
1.3.0.)
to write manually ([issue 24]). This makes it incompatible with
the version in 1.3.0.
[feat-exp-1-4]: https://tspiteri.gitlab.io/fixed/dev/fixed/#experimental-optional-features
[issue 23]: https://gitlab.com/tspiteri/fixed/-/issues/23
[issue 24]: https://gitlab.com/tspiteri/fixed/-/issues/24
[nt-0-2-fc]: https://docs.rs/num-traits/^0.2/num_traits/float/trait.FloatConst.html
[nt-0-2-fp]: https://docs.rs/num-traits/^0.2/num_traits/cast/trait.FromPrimitive.html
[nt-0-2-inv]: https://docs.rs/num-traits/^0.2/num_traits/ops/inv/trait.Inv.html
[nt-0-2-ma]: https://docs.rs/num-traits/^0.2/num_traits/ops/mul_add/trait.MulAdd.html
[nt-0-2-maa]: https://docs.rs/num-traits/^0.2/num_traits/ops/mul_add/trait.MulAddAssign.html
[nt-0-2-num]: https://docs.rs/num-traits/^0.2/num_traits/trait.Num.html
[nt-0-2-signed]: https://docs.rs/num-traits/^0.2/num_traits/sign/trait.Signed.html
[nt-0-2-tp]: https://docs.rs/num-traits/^0.2/num_traits/cast/trait.ToPrimitive.html
[nt-0-2-unsigned]: https://docs.rs/num-traits/^0.2/num_traits/sign/trait.Unsigned.html
Version 1.3.0 (2020-10-15)
==========================

View File

@ -14,29 +14,44 @@
// <https://opensource.org/licenses/MIT>.
use crate::{
consts,
types::extra::{
IsLessOrEqual, LeEqU128, LeEqU16, LeEqU32, LeEqU64, LeEqU8, True, U126, U127, U14, U15,
U30, U31, U6, U62, U63, U7,
},
FixedI128, FixedI16, FixedI32, FixedI64, FixedI8, FixedU128, FixedU16, FixedU32, FixedU64,
FixedU8,
FixedU8, ParseFixedError,
};
use num_traits::{
bounds::Bounded,
cast::{FromPrimitive, ToPrimitive},
float::FloatConst,
identities::{One, Zero},
ops::{
checked::{
CheckedAdd, CheckedDiv, CheckedMul, CheckedNeg, CheckedRem, CheckedShl, CheckedShr,
CheckedSub,
},
mul_add::MulAdd,
inv::Inv,
mul_add::{MulAdd, MulAddAssign},
saturating::{SaturatingAdd, SaturatingMul, SaturatingSub},
wrapping::{WrappingAdd, WrappingMul, WrappingNeg, WrappingShl, WrappingShr, WrappingSub},
},
sign::{Signed, Unsigned},
Num,
};
/// An error which can be returned when parsing a fixed-point number
/// with a given radix.
pub enum FixedFromStrRadixError {
/// The radix is not 2, 8, 10 or 16.
UnsupportedRadix,
/// The string could not be parsed as a fixed-point number.
ParseFixedError(ParseFixedError),
}
macro_rules! impl_traits {
($Fixed:ident, $LeEqU:ident, $OneMaxFrac:ident) => {
($Fixed:ident, $LeEqU:ident, $OneMaxFrac:ident, $Signedness:tt) => {
impl<Frac> Bounded for $Fixed<Frac> {
#[inline]
fn min_value() -> Self {
@ -69,6 +84,78 @@ macro_rules! impl_traits {
}
}
impl<Frac: $LeEqU> Num for $Fixed<Frac>
where
Frac: IsLessOrEqual<$OneMaxFrac, Output = True>,
{
type FromStrRadixErr = FixedFromStrRadixError;
#[inline]
fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
match radix {
2 => Self::from_str_binary(str),
8 => Self::from_str_octal(str),
10 => str.parse(),
16 => Self::from_str_hex(str),
_ => return Err(FixedFromStrRadixError::UnsupportedRadix),
}
.map_err(FixedFromStrRadixError::ParseFixedError)
}
}
impl<Frac: $LeEqU> Inv for $Fixed<Frac>
where
Frac: IsLessOrEqual<$OneMaxFrac, Output = True>,
{
type Output = Self;
#[inline]
fn inv(self) -> Self::Output {
Self::one() / self
}
}
if_signed! {
$Signedness;
impl<Frac: $LeEqU> Signed for $Fixed<Frac>
where
Frac: IsLessOrEqual<$OneMaxFrac, Output = True>,
{
#[inline]
fn abs(&self) -> Self {
(*self).abs()
}
#[inline]
fn abs_sub(&self, other: &Self) -> Self {
if *self < *other {
Self::from_bits(0)
} else {
*other - *self
}
}
#[inline]
fn signum(&self) -> Self {
(*self).signum()
}
#[inline]
fn is_positive(&self) -> bool {
(*self).is_positive()
}
#[inline]
fn is_negative(&self) -> bool {
(*self).is_negative()
}
}
}
if_unsigned! {
$Signedness;
impl<Frac: $LeEqU> Unsigned for $Fixed<Frac>
where
Frac: IsLessOrEqual<$OneMaxFrac, Output = True>,
{
}
}
impl<Frac> CheckedAdd for $Fixed<Frac> {
#[inline]
fn checked_add(&self, v: &Self) -> Option<Self> {
@ -195,16 +282,220 @@ macro_rules! impl_traits {
self.mul_add(a, b)
}
}
impl<Frac, MulFrac: $LeEqU> MulAddAssign<$Fixed<MulFrac>> for $Fixed<Frac> {
#[inline]
fn mul_add_assign(&mut self, a: $Fixed<MulFrac>, b: $Fixed<Frac>) {
*self = self.mul_add(a, b)
}
}
impl<Frac: $LeEqU> FloatConst for $Fixed<Frac> {
#[inline]
fn E() -> Self {
consts::E.to_num()
}
#[inline]
fn FRAC_1_PI() -> Self {
consts::FRAC_1_PI.to_num()
}
#[inline]
fn FRAC_1_SQRT_2() -> Self {
consts::FRAC_1_SQRT_2.to_num()
}
#[inline]
fn FRAC_2_PI() -> Self {
consts::FRAC_2_PI.to_num()
}
#[inline]
fn FRAC_2_SQRT_PI() -> Self {
consts::FRAC_2_SQRT_PI.to_num()
}
#[inline]
fn FRAC_PI_2() -> Self {
consts::FRAC_PI_2.to_num()
}
#[inline]
fn FRAC_PI_3() -> Self {
consts::FRAC_PI_3.to_num()
}
#[inline]
fn FRAC_PI_4() -> Self {
consts::FRAC_PI_4.to_num()
}
#[inline]
fn FRAC_PI_6() -> Self {
consts::FRAC_PI_6.to_num()
}
#[inline]
fn FRAC_PI_8() -> Self {
consts::FRAC_PI_8.to_num()
}
#[inline]
fn LN_10() -> Self {
consts::LN_10.to_num()
}
#[inline]
fn LN_2() -> Self {
consts::LN_2.to_num()
}
#[inline]
fn LOG10_E() -> Self {
consts::LOG10_E.to_num()
}
#[inline]
fn LOG2_E() -> Self {
consts::LOG2_E.to_num()
}
#[inline]
fn PI() -> Self {
consts::PI.to_num()
}
#[inline]
fn SQRT_2() -> Self {
consts::SQRT_2.to_num()
}
#[inline]
fn TAU() -> Self {
consts::TAU.to_num()
}
#[inline]
fn LOG10_2() -> Self {
consts::LOG10_2.to_num()
}
#[inline]
fn LOG2_10() -> Self {
consts::LOG2_10.to_num()
}
}
impl<Frac: $LeEqU> ToPrimitive for $Fixed<Frac> {
#[inline]
fn to_i64(&self) -> Option<i64> {
self.checked_to_num()
}
#[inline]
fn to_u64(&self) -> Option<u64> {
self.checked_to_num()
}
#[inline]
fn to_isize(&self) -> Option<isize> {
self.checked_to_num()
}
#[inline]
fn to_i8(&self) -> Option<i8> {
self.checked_to_num()
}
#[inline]
fn to_i16(&self) -> Option<i16> {
self.checked_to_num()
}
#[inline]
fn to_i32(&self) -> Option<i32> {
self.checked_to_num()
}
#[inline]
fn to_i128(&self) -> Option<i128> {
self.checked_to_num()
}
#[inline]
fn to_usize(&self) -> Option<usize> {
self.checked_to_num()
}
#[inline]
fn to_u8(&self) -> Option<u8> {
self.checked_to_num()
}
#[inline]
fn to_u16(&self) -> Option<u16> {
self.checked_to_num()
}
#[inline]
fn to_u32(&self) -> Option<u32> {
self.checked_to_num()
}
#[inline]
fn to_u128(&self) -> Option<u128> {
self.checked_to_num()
}
#[inline]
fn to_f32(&self) -> Option<f32> {
self.checked_to_num()
}
#[inline]
fn to_f64(&self) -> Option<f64> {
self.checked_to_num()
}
}
impl<Frac: $LeEqU> FromPrimitive for $Fixed<Frac> {
#[inline]
fn from_i64(n: i64) -> Option<Self> {
Self::checked_from_num(n)
}
#[inline]
fn from_u64(n: u64) -> Option<Self> {
Self::checked_from_num(n)
}
#[inline]
fn from_isize(n: isize) -> Option<Self> {
Self::checked_from_num(n)
}
#[inline]
fn from_i8(n: i8) -> Option<Self> {
Self::checked_from_num(n)
}
#[inline]
fn from_i16(n: i16) -> Option<Self> {
Self::checked_from_num(n)
}
#[inline]
fn from_i32(n: i32) -> Option<Self> {
Self::checked_from_num(n)
}
#[inline]
fn from_i128(n: i128) -> Option<Self> {
Self::checked_from_num(n)
}
#[inline]
fn from_usize(n: usize) -> Option<Self> {
Self::checked_from_num(n)
}
#[inline]
fn from_u8(n: u8) -> Option<Self> {
Self::checked_from_num(n)
}
#[inline]
fn from_u16(n: u16) -> Option<Self> {
Self::checked_from_num(n)
}
#[inline]
fn from_u32(n: u32) -> Option<Self> {
Self::checked_from_num(n)
}
#[inline]
fn from_u128(n: u128) -> Option<Self> {
Self::checked_from_num(n)
}
#[inline]
fn from_f32(n: f32) -> Option<Self> {
Self::checked_from_num(n)
}
#[inline]
fn from_f64(n: f64) -> Option<Self> {
Self::checked_from_num(n)
}
}
};
}
impl_traits! { FixedI8, LeEqU8, U6 }
impl_traits! { FixedI16, LeEqU16, U14 }
impl_traits! { FixedI32, LeEqU32, U30 }
impl_traits! { FixedI64, LeEqU64, U62 }
impl_traits! { FixedI128, LeEqU128, U126 }
impl_traits! { FixedU8, LeEqU8, U7 }
impl_traits! { FixedU16, LeEqU16, U15 }
impl_traits! { FixedU32, LeEqU32, U31 }
impl_traits! { FixedU64, LeEqU64, U63 }
impl_traits! { FixedU128, LeEqU128, U127 }
impl_traits! { FixedI8, LeEqU8, U6, Signed }
impl_traits! { FixedI16, LeEqU16, U14, Signed }
impl_traits! { FixedI32, LeEqU32, U30, Signed }
impl_traits! { FixedI64, LeEqU64, U62, Signed }
impl_traits! { FixedI128, LeEqU128, U126, Signed }
impl_traits! { FixedU8, LeEqU8, U7, Unsigned }
impl_traits! { FixedU16, LeEqU16, U15, Unsigned }
impl_traits! { FixedU32, LeEqU32, U31, Unsigned }
impl_traits! { FixedU64, LeEqU64, U63, Unsigned }
impl_traits! { FixedU128, LeEqU128, U127, Unsigned }

View File

@ -175,6 +175,8 @@ depending on the crates [optional features].
* [`SaturatingAdd`], [`SaturatingSub`], [`SaturatingMul`]
* [`WrappingAdd`], [`WrappingSub`], [`WrappingNeg`],
[`WrappingMul`], [`WrappingShl`], [`WrappingShr`]
* [`FloatConst`]
* [`ToPrimitive`], [`FromPrimitive`]
3. If the `serde` feature is enabled, [`Serialize`] and
[`Deserialize`] are supertraits of [`Fixed`].
@ -189,12 +191,15 @@ depending on the crates [optional features].
[`CheckedSub`]: https://docs.rs/num-traits/^0.2/num_traits/ops/checked/trait.CheckedSub.html
[`Deserialize`]: https://docs.rs/serde/^1/serde/de/trait.Deserialize.html
[`Fixed`]: trait.Fixed.html
[`FloatConst`]: https://docs.rs/num-traits/^0.2/num_traits/float/trait.FloatConst.html
[`FromPrimitive`]: https://docs.rs/num-traits/^0.2/num_traits/cast/trait.ToPrimitive.html
[`One`]: https://docs.rs/num-traits/^0.2/num_traits/identities/trait.One.html
[`PartialOrd`]: https://doc.rust-lang.org/nightly/core/cmp/trait.PartialOrd.html
[`SaturatingAdd`]: https://docs.rs/num-traits/^0.2/num_traits/ops/saturating/trait.SaturatingAdd.html
[`SaturatingMul`]: https://docs.rs/num-traits/^0.2/num_traits/ops/saturating/trait.SaturatingMul.html
[`SaturatingSub`]: https://docs.rs/num-traits/^0.2/num_traits/ops/saturating/trait.SaturatingSub.html
[`Serialize`]: https://docs.rs/serde/^1/serde/ser/trait.Serialize.html
[`ToPrimitive`]: https://docs.rs/num-traits/^0.2/num_traits/cast/trait.FromPrimitive.html
[`WrappingAdd`]: https://docs.rs/num-traits/^0.2/num_traits/ops/wrapping/trait.WrappingAdd.html
[`WrappingMul`]: https://docs.rs/num-traits/^0.2/num_traits/ops/wrapping/trait.WrappingMul.html
[`WrappingNeg`]: https://docs.rs/num-traits/^0.2/num_traits/ops/wrapping/trait.WrappingNeg.html