--- /dev/null
+use crate::{
+ f16::F16,
+ scalar::Scalar,
+ traits::{Float, Make},
+};
+
+mod sealed {
+ use crate::f16::F16;
+
+ pub trait Sealed {}
+ impl Sealed for F16 {}
+ impl Sealed for f32 {}
+ impl Sealed for f64 {}
+}
+
+pub trait FloatEncoding:
+ sealed::Sealed + Copy + 'static + Send + Sync + Float<u32> + Make<Context = Scalar>
+{
+ const EXPONENT_BIAS_UNSIGNED: Self::BitsType;
+ const EXPONENT_BIAS_SIGNED: Self::SignedBitsType;
+ const SIGN_FIELD_WIDTH: u32;
+ const EXPONENT_FIELD_WIDTH: u32;
+ const MANTISSA_FIELD_WIDTH: u32;
+ const SIGN_FIELD_SHIFT: u32;
+ const EXPONENT_FIELD_SHIFT: u32;
+ const MANTISSA_FIELD_SHIFT: u32;
+ 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_encoding {
+ (
+ impl FloatEncoding for $float:ident {
+ const EXPONENT_FIELD_WIDTH: u32 = $exponent_field_width:literal;
+ const MANTISSA_FIELD_WIDTH: u32 = $mantissa_field_width:literal;
+ }
+ ) => {
+ impl FloatEncoding for $float {
+ 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: u32 = 1;
+ const EXPONENT_FIELD_WIDTH: u32 = $exponent_field_width;
+ const MANTISSA_FIELD_WIDTH: u32 = $mantissa_field_width;
+ const SIGN_FIELD_SHIFT: u32 = Self::EXPONENT_FIELD_SHIFT + Self::EXPONENT_FIELD_WIDTH;
+ const EXPONENT_FIELD_SHIFT: u32 = Self::MANTISSA_FIELD_WIDTH;
+ const MANTISSA_FIELD_SHIFT: u32 = 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_encoding! {
+ impl FloatEncoding for F16 {
+ const EXPONENT_FIELD_WIDTH: u32 = 5;
+ const MANTISSA_FIELD_WIDTH: u32 = 10;
+ }
+}
+
+impl_float_encoding! {
+ impl FloatEncoding for f32 {
+ const EXPONENT_FIELD_WIDTH: u32 = 8;
+ const MANTISSA_FIELD_WIDTH: u32 = 23;
+ }
+}
+
+impl_float_encoding! {
+ impl FloatEncoding for f64 {
+ const EXPONENT_FIELD_WIDTH: u32 = 11;
+ const MANTISSA_FIELD_WIDTH: u32 = 52;
+ }
+}