use core::fmt::LowerHex;
use core::num::FpCategory;
use core::ops::{Shl, Shr};
#[doc(hidden)]
pub trait MantissaOps:
Shl<u32, Output = Self> + Shr<u32, Output = Self> + LowerHex + TryFrom<u64>
{
#[allow(dead_code, reason = "used only when 'alloc' feature is enabled")]
fn trailing_zeroes(self) -> u32;
}
#[doc(hidden)]
pub trait ExponentOps: Into<i32> + TryFrom<i32> {}
impl MantissaOps for u32 {
fn trailing_zeroes(self) -> u32 {
u32::trailing_zeros(self)
}
}
impl ExponentOps for u8 {}
impl MantissaOps for u64 {
fn trailing_zeroes(self) -> u32 {
u64::trailing_zeros(self)
}
}
impl ExponentOps for u16 {}
#[doc(hidden)]
pub trait FloatBits {
const BITS: u32;
const EXPONENT_BITS: u8;
const MANTISSA_BITS: u8;
const EXPONENT_BIAS: u16;
const INFINITY: Self;
const NEG_INFINITY: Self;
const NAN: Self;
type IntegerBits;
type ExponentType: ExponentOps;
type MantissaType: MantissaOps + Copy;
fn zero(sign: bool) -> Self;
fn from_parts(sign: bool, exponent: Self::ExponentType, mantissa: Self::MantissaType) -> Self;
fn to_parts(&self) -> (bool, Self::ExponentType, Self::MantissaType);
fn category(&self) -> FpCategory;
}
impl FloatBits for f32 {
const BITS: u32 = 32;
const EXPONENT_BITS: u8 = 8;
const MANTISSA_BITS: u8 = 23;
const EXPONENT_BIAS: u16 = 127;
const INFINITY: Self = f32::INFINITY;
const NEG_INFINITY: Self = f32::NEG_INFINITY;
const NAN: Self = f32::NAN;
type IntegerBits = u32;
type ExponentType = u8;
type MantissaType = u32;
fn zero(sign: bool) -> Self {
if sign {
-0.0
} else {
0.0
}
}
fn from_parts(sign: bool, exponent: u8, mantissa: u32) -> Self {
let bits: u32 = (u32::from(sign) << 31) + (u32::from(exponent) << 23) + mantissa;
f32::from_bits(bits)
}
fn to_parts(&self) -> (bool, u8, u32) {
let bits = self.to_bits();
let sign: bool = (bits >> 31) == 1;
let exponent = u8::try_from((bits >> 23) & 0xFF).unwrap();
let mantissa = bits & 0x7F_FFFF;
(sign, exponent, mantissa)
}
fn category(&self) -> FpCategory {
self.classify()
}
}
impl FloatBits for f64 {
const BITS: u32 = 64;
const EXPONENT_BITS: u8 = 11;
const MANTISSA_BITS: u8 = 52;
const EXPONENT_BIAS: u16 = 1023;
const INFINITY: Self = f64::INFINITY;
const NEG_INFINITY: Self = f64::NEG_INFINITY;
const NAN: Self = f64::NAN;
type IntegerBits = u64;
type ExponentType = u16;
type MantissaType = u64;
fn zero(sign: bool) -> Self {
if sign {
-0.0
} else {
0.0
}
}
fn from_parts(sign: bool, exponent: u16, mantissa: u64) -> Self {
let bits: u64 = (u64::from(sign) << 63) + (u64::from(exponent) << 52) + mantissa;
f64::from_bits(bits)
}
fn to_parts(&self) -> (bool, u16, u64) {
let bits = self.to_bits();
let sign: bool = (bits >> 63) == 1;
let exponent = ((bits >> 52) & 0x7FF) as u16;
let mantissa = bits & 0x000F_FFFF_FFFF_FFFF;
(sign, exponent, mantissa)
}
fn category(&self) -> FpCategory {
self.classify()
}
}