use core::mem; use super::int::Int; pub mod conv; pub mod add; pub mod pow; pub mod sub; /// Trait for some basic operations on floats pub trait Float: Sized + Copy { /// A uint of the same with as the float type Int: Int; /// The bitwidth of the float type const BITS: u32; /// The bitwidth of the significand const SIGNIFICAND_BITS: u32; /// The bitwidth of the exponent const EXPONENT_BITS: u32 = Self::BITS - Self::SIGNIFICAND_BITS - 1; /// The maximum value of the exponent const EXPONENT_MAX: u32 = (1 << Self::EXPONENT_BITS) - 1; /// The exponent bias value const EXPONENT_BIAS: u32 = Self::EXPONENT_MAX >> 1; /// A mask for the sign bit const SIGN_MASK: Self::Int; /// A mask for the significand const SIGNIFICAND_MASK: Self::Int; // The implicit bit of the float format const IMPLICIT_BIT: Self::Int; /// A mask for the exponent const EXPONENT_MASK: Self::Int; /// Returns `self` transmuted to `Self::Int` fn repr(self) -> Self::Int; #[cfg(test)] /// Checks if two floats have the same bit representation. *Except* for NaNs! NaN can be /// represented in multiple different ways. This method returns `true` if two NaNs are /// compared. fn eq_repr(self, rhs: Self) -> bool; /// Returns a `Self::Int` transmuted back to `Self` fn from_repr(a: Self::Int) -> Self; /// Constructs a `Self` from its parts. Inputs are treated as bits and shifted into position. fn from_parts(sign: bool, exponent: Self::Int, significand: Self::Int) -> Self; /// Returns (normalized exponent, normalized significand) fn normalize(significand: Self::Int) -> (i32, Self::Int); } // FIXME: Some of this can be removed if RFC Issue #1424 is resolved // https://github.com/rust-lang/rfcs/issues/1424 impl Float for f32 { type Int = u32; const BITS: u32 = 32; const SIGNIFICAND_BITS: u32 = 23; const SIGN_MASK: Self::Int = 1 << (Self::BITS - 1); const SIGNIFICAND_MASK: Self::Int = (1 << Self::SIGNIFICAND_BITS) - 1; const IMPLICIT_BIT: Self::Int = 1 << Self::SIGNIFICAND_BITS; const EXPONENT_MASK: Self::Int = !(Self::SIGN_MASK | Self::SIGNIFICAND_MASK); fn repr(self) -> Self::Int { unsafe { mem::transmute(self) } } #[cfg(test)] fn eq_repr(self, rhs: Self) -> bool { if self.is_nan() && rhs.is_nan() { true } else { self.repr() == rhs.repr() } } fn from_repr(a: Self::Int) -> Self { unsafe { mem::transmute(a) } } fn from_parts(sign: bool, exponent: Self::Int, significand: Self::Int) -> Self { Self::from_repr(((sign as Self::Int) << (Self::BITS - 1)) | ((exponent << Self::SIGNIFICAND_BITS) & Self::EXPONENT_MASK) | (significand & Self::SIGNIFICAND_MASK)) } fn normalize(significand: Self::Int) -> (i32, Self::Int) { let shift = significand.leading_zeros() .wrapping_sub((1u32 << Self::SIGNIFICAND_BITS).leading_zeros()); (1i32.wrapping_sub(shift as i32), significand << shift as Self::Int) } } impl Float for f64 { type Int = u64; const BITS: u32 = 64; const SIGNIFICAND_BITS: u32 = 52; const SIGN_MASK: Self::Int = 1 << (Self::BITS - 1); const SIGNIFICAND_MASK: Self::Int = (1 << Self::SIGNIFICAND_BITS) - 1; const IMPLICIT_BIT: Self::Int = 1 << Self::SIGNIFICAND_BITS; const EXPONENT_MASK: Self::Int = !(Self::SIGN_MASK | Self::SIGNIFICAND_MASK); fn repr(self) -> Self::Int { unsafe { mem::transmute(self) } } #[cfg(test)] fn eq_repr(self, rhs: Self) -> bool { if self.is_nan() && rhs.is_nan() { true } else { self.repr() == rhs.repr() } } fn from_repr(a: Self::Int) -> Self { unsafe { mem::transmute(a) } } fn from_parts(sign: bool, exponent: Self::Int, significand: Self::Int) -> Self { Self::from_repr(((sign as Self::Int) << (Self::BITS - 1)) | ((exponent << Self::SIGNIFICAND_BITS) & Self::EXPONENT_MASK) | (significand & Self::SIGNIFICAND_MASK)) } fn normalize(significand: Self::Int) -> (i32, Self::Int) { let shift = significand.leading_zeros() .wrapping_sub((1u64 << Self::SIGNIFICAND_BITS).leading_zeros()); (1i32.wrapping_sub(shift as i32), significand << shift as Self::Int) } }