#[cfg(not(feature = "std"))] use crate::scalar::{Scalar, Value}; use crate::{ f16::F16, traits::{ConvertFrom, ConvertTo}, }; use core::{fmt, hash, ops}; mod sealed { use crate::f16::F16; pub trait Sealed {} impl Sealed for F16 {} impl Sealed for f32 {} impl Sealed for f64 {} impl Sealed for u8 {} impl Sealed for u16 {} impl Sealed for u32 {} impl Sealed for u64 {} impl Sealed for i8 {} impl Sealed for i16 {} impl Sealed for i32 {} impl Sealed for i64 {} } pub trait PrimBase: sealed::Sealed + Copy + 'static + Send + Sync + PartialOrd + fmt::Debug + fmt::Display + ops::Add + ops::Sub + ops::Mul + ops::Div + ops::Rem + ops::AddAssign + ops::SubAssign + ops::MulAssign + ops::DivAssign + ops::RemAssign + ConvertFrom + ConvertFrom + ConvertFrom + ConvertFrom + ConvertFrom + ConvertFrom + ConvertFrom + ConvertFrom + ConvertFrom + ConvertFrom + ConvertFrom + ConvertTo + ConvertTo + ConvertTo + ConvertTo + ConvertTo + ConvertTo + ConvertTo + ConvertTo + ConvertTo + ConvertTo + ConvertTo { } pub trait PrimInt: PrimBase + Ord + hash::Hash + fmt::Binary + fmt::LowerHex + fmt::Octal + fmt::UpperHex + ops::BitAnd + ops::BitOr + ops::BitXor + ops::Shl + ops::Shr + ops::Not + ops::BitAndAssign + ops::BitOrAssign + ops::BitXorAssign + ops::ShlAssign + ops::ShrAssign { const ZERO: Self; const ONE: Self; const MIN: Self; const MAX: Self; } pub trait PrimUInt: PrimInt + ConvertFrom { type SignedType: PrimSInt + ConvertFrom; } pub trait PrimSInt: PrimInt + ops::Neg + ConvertFrom { type UnsignedType: PrimUInt + ConvertFrom; } macro_rules! impl_int { ($uint:ident, $sint:ident) => { impl PrimBase for $uint {} impl PrimBase for $sint {} impl PrimInt for $uint { const ZERO: Self = 0; const ONE: Self = 1; const MIN: Self = 0; const MAX: Self = !0; } impl PrimInt for $sint { const ZERO: Self = 0; const ONE: Self = 1; const MIN: Self = $sint::MIN; const MAX: Self = $sint::MAX; } impl PrimUInt for $uint { type SignedType = $sint; } impl PrimSInt for $sint { type UnsignedType = $uint; } }; } impl_int!(u8, i8); impl_int!(u16, i16); impl_int!(u32, i32); impl_int!(u64, i64); pub trait PrimFloat: PrimBase + ops::Neg + ConvertFrom + ConvertFrom { type BitsType: PrimUInt + ConvertFrom; type SignedBitsType: PrimSInt + ConvertFrom; const EXPONENT_BIAS_UNSIGNED: Self::BitsType; const EXPONENT_BIAS_SIGNED: Self::SignedBitsType; const SIGN_FIELD_WIDTH: Self::BitsType; const EXPONENT_FIELD_WIDTH: Self::BitsType; const MANTISSA_FIELD_WIDTH: Self::BitsType; const SIGN_FIELD_SHIFT: Self::BitsType; const EXPONENT_FIELD_SHIFT: Self::BitsType; const MANTISSA_FIELD_SHIFT: Self::BitsType; const SIGN_FIELD_MASK: Self::BitsType; const EXPONENT_FIELD_MASK: Self::BitsType; const MANTISSA_FIELD_MASK: Self::BitsType; const IMPLICIT_MANTISSA_BIT: Self::BitsType; const ZERO_SUBNORMAL_EXPONENT: Self::BitsType; const NAN_INFINITY_EXPONENT: Self::BitsType; const INFINITY_BITS: Self::BitsType; const NAN_BITS: Self::BitsType; fn is_nan(self) -> bool; fn from_bits(bits: Self::BitsType) -> Self; fn to_bits(self) -> Self::BitsType; fn abs(self) -> Self; fn max_contiguous_integer() -> Self { (Self::BitsType::cvt_from(1) << (Self::MANTISSA_FIELD_WIDTH + 1.to())).to() } fn is_finite(self) -> bool; fn trunc(self) -> Self; /// round to nearest, ties to unspecified fn round(self) -> Self; fn floor(self) -> Self; fn ceil(self) -> Self; fn copy_sign(self, sign: Self) -> Self; } macro_rules! impl_float { ( impl PrimFloat for $float:ident { type BitsType = $bits_type:ident; type SignedBitsType = $signed_bits_type:ident; const EXPONENT_FIELD_WIDTH: u32 = $exponent_field_width:literal; const MANTISSA_FIELD_WIDTH: u32 = $mantissa_field_width:literal; } ) => { impl PrimBase for $float {} impl PrimFloat for $float { type BitsType = $bits_type; type SignedBitsType = $signed_bits_type; const EXPONENT_BIAS_UNSIGNED: Self::BitsType = (1 << (Self::EXPONENT_FIELD_WIDTH - 1)) - 1; const EXPONENT_BIAS_SIGNED: Self::SignedBitsType = Self::EXPONENT_BIAS_UNSIGNED as _; const SIGN_FIELD_WIDTH: Self::BitsType = 1; const EXPONENT_FIELD_WIDTH: Self::BitsType = $exponent_field_width; const MANTISSA_FIELD_WIDTH: Self::BitsType = $mantissa_field_width; const SIGN_FIELD_SHIFT: Self::BitsType = Self::EXPONENT_FIELD_SHIFT + Self::EXPONENT_FIELD_WIDTH; const EXPONENT_FIELD_SHIFT: Self::BitsType = Self::MANTISSA_FIELD_WIDTH; const MANTISSA_FIELD_SHIFT: Self::BitsType = 0; const SIGN_FIELD_MASK: Self::BitsType = 1 << Self::SIGN_FIELD_SHIFT; const EXPONENT_FIELD_MASK: Self::BitsType = ((1 << Self::EXPONENT_FIELD_WIDTH) - 1) << Self::EXPONENT_FIELD_SHIFT; const MANTISSA_FIELD_MASK: Self::BitsType = (1 << Self::MANTISSA_FIELD_WIDTH) - 1; const IMPLICIT_MANTISSA_BIT: Self::BitsType = 1 << Self::MANTISSA_FIELD_WIDTH; const ZERO_SUBNORMAL_EXPONENT: Self::BitsType = 0; const NAN_INFINITY_EXPONENT: Self::BitsType = (1 << Self::EXPONENT_FIELD_WIDTH) - 1; const INFINITY_BITS: Self::BitsType = Self::NAN_INFINITY_EXPONENT << Self::EXPONENT_FIELD_SHIFT; const NAN_BITS: Self::BitsType = Self::INFINITY_BITS | (1 << (Self::MANTISSA_FIELD_WIDTH - 1)); fn is_nan(self) -> bool { $float::is_nan(self) } fn from_bits(bits: Self::BitsType) -> Self { $float::from_bits(bits) } fn to_bits(self) -> Self::BitsType { self.to_bits() } fn abs(self) -> Self { #[cfg(feature = "std")] return $float::abs(self); #[cfg(not(feature = "std"))] return crate::algorithms::base::abs(Scalar, Value(self)).0; } fn is_finite(self) -> bool { $float::is_finite(self) } fn trunc(self) -> Self { #[cfg(feature = "std")] return $float::trunc(self); #[cfg(not(feature = "std"))] return crate::algorithms::base::trunc(Scalar, Value(self)).0; } fn round(self) -> Self { #[cfg(feature = "std")] return $float::round(self); #[cfg(not(feature = "std"))] return crate::algorithms::base::round_to_nearest_ties_to_even(Scalar, Value(self)) .0; } fn floor(self) -> Self { #[cfg(feature = "std")] return $float::floor(self); #[cfg(not(feature = "std"))] return crate::algorithms::base::floor(Scalar, Value(self)).0; } fn ceil(self) -> Self { #[cfg(feature = "std")] return $float::ceil(self); #[cfg(not(feature = "std"))] return crate::algorithms::base::ceil(Scalar, Value(self)).0; } fn copy_sign(self, sign: Self) -> Self { #[cfg(feature = "std")] return $float::copysign(self, sign); #[cfg(not(feature = "std"))] return crate::algorithms::base::copy_sign(Scalar, Value(self), Value(sign)).0; } } }; } impl_float! { impl PrimFloat for F16 { type BitsType = u16; type SignedBitsType = i16; const EXPONENT_FIELD_WIDTH: u32 = 5; const MANTISSA_FIELD_WIDTH: u32 = 10; } } impl_float! { impl PrimFloat for f32 { type BitsType = u32; type SignedBitsType = i32; const EXPONENT_FIELD_WIDTH: u32 = 8; const MANTISSA_FIELD_WIDTH: u32 = 23; } } impl_float! { impl PrimFloat for f64 { type BitsType = u64; type SignedBitsType = i64; const EXPONENT_FIELD_WIDTH: u32 = 11; const MANTISSA_FIELD_WIDTH: u32 = 52; } }