i_float 3.0.0

This fixed float math library provides an efficient and deterministic solution for arithmetic and geometric operations.
Documentation
use crate::int::number::product_uint::{CompositeUIntProduct, UIntProduct, UIntProduct64};
use core::fmt::Display;
use core::ops::{Add, AddAssign, BitAnd, BitOr, BitOrAssign, Div, Mul, Shl, ShlAssign, Shr, Sub};

pub trait UIntNumber:
    Copy
    + Clone
    + Ord
    + Send
    + Sync
    + Display
    + Add<Output = Self>
    + Sub<Output = Self>
    + Mul<Output = Self>
    + Div<Output = Self>
    + BitAnd<Output = Self>
    + BitOr<Output = Self>
    + BitOrAssign
    + Shl<u32, Output = Self>
    + Shr<u32, Output = Self>
    + ShlAssign
    + AddAssign
{
    type Product: UIntProduct<Self>;
    const BITS: u32;
    const HALF_BITS: u32;
    const HALF_MASK: Self;
    const LAST_BIT_INDEX: u32;
    const ZERO: Self;
    const ONE: Self;
    const MAX: Self;
    const LAST_BIT: Self;

    fn overflowing_add(self, rhs: Self) -> (Self, bool);
    fn from_u64(value: u64) -> Self;
    fn wrapping_sub(self, rhs: Self) -> Self;
    fn leading_zeros(self) -> u32;
    fn ilog2(self) -> u32;
    fn to_f64(self) -> f64;
}

impl UIntNumber for u32 {
    type Product = UIntProduct64;
    const BITS: u32 = 32;
    const HALF_BITS: u32 = 16;
    const HALF_MASK: Self = 0xFFFF;
    const LAST_BIT_INDEX: u32 = 31;
    const ZERO: Self = 0;
    const ONE: Self = 1;
    const MAX: Self = Self::MAX;
    const LAST_BIT: Self = Self::ONE << Self::LAST_BIT_INDEX;

    #[inline(always)]
    fn overflowing_add(self, rhs: Self) -> (Self, bool) {
        self.overflowing_add(rhs)
    }
    #[inline(always)]
    fn from_u64(value: u64) -> Self {
        value as Self
    }

    #[inline(always)]
    fn wrapping_sub(self, rhs: Self) -> Self {
        self.wrapping_sub(rhs)
    }

    #[inline(always)]
    fn leading_zeros(self) -> u32 {
        self.leading_zeros()
    }

    #[inline(always)]
    fn ilog2(self) -> u32 {
        self.ilog2()
    }

    #[inline(always)]
    fn to_f64(self) -> f64 {
        self as f64
    }
}

impl UIntNumber for u64 {
    type Product = CompositeUIntProduct<Self>;
    const BITS: u32 = 64;
    const HALF_BITS: u32 = 32;
    const HALF_MASK: Self = 0xFFFF_FFFF;
    const LAST_BIT_INDEX: u32 = 63;
    const ZERO: Self = 0;
    const ONE: Self = 1;
    const MAX: Self = Self::MAX;
    const LAST_BIT: Self = Self::ONE << Self::LAST_BIT_INDEX;

    #[inline(always)]
    fn overflowing_add(self, rhs: Self) -> (Self, bool) {
        self.overflowing_add(rhs)
    }

    #[inline(always)]
    fn from_u64(value: u64) -> Self {
        value
    }

    #[inline(always)]
    fn wrapping_sub(self, rhs: Self) -> Self {
        self.wrapping_sub(rhs)
    }

    #[inline(always)]
    fn leading_zeros(self) -> u32 {
        self.leading_zeros()
    }

    #[inline(always)]
    fn ilog2(self) -> u32 {
        self.ilog2()
    }

    #[inline(always)]
    fn to_f64(self) -> f64 {
        self as f64
    }
}

impl UIntNumber for u128 {
    type Product = CompositeUIntProduct<Self>;
    const BITS: u32 = 128;
    const HALF_BITS: u32 = 64;
    const HALF_MASK: Self = 0xFFFF_FFFF_FFFF_FFFF;
    const LAST_BIT_INDEX: u32 = 127;
    const ZERO: Self = 0;
    const ONE: Self = 1;
    const MAX: Self = Self::MAX;
    const LAST_BIT: Self = Self::ONE << Self::LAST_BIT_INDEX;
    #[inline(always)]
    fn overflowing_add(self, rhs: Self) -> (Self, bool) {
        self.overflowing_add(rhs)
    }

    #[inline(always)]
    fn from_u64(value: u64) -> Self {
        value as Self
    }

    #[inline(always)]
    fn wrapping_sub(self, rhs: Self) -> Self {
        self.wrapping_sub(rhs)
    }

    #[inline(always)]
    fn leading_zeros(self) -> u32 {
        self.leading_zeros()
    }

    #[inline(always)]
    fn ilog2(self) -> u32 {
        self.ilog2()
    }

    #[inline(always)]
    fn to_f64(self) -> f64 {
        self as f64
    }
}