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 { } 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 {} impl PrimInt for $sint {} 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; } 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)); } }; } 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; } }