add ilogb
[vector-math.git] / src / ieee754.rs
diff --git a/src/ieee754.rs b/src/ieee754.rs
new file mode 100644 (file)
index 0000000..0da587d
--- /dev/null
@@ -0,0 +1,88 @@
+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;
+    }
+}