#![cfg_attr(any(), rustfmt::skip)]
use core::{fmt, mem, ops};
#[cfg(feature = "f16")]
use crate::bf16::bf16;
#[cfg(feature = "f16")]
use crate::f16::f16;
pub trait AsPrimitive: Copy + PartialEq + PartialOrd + Send + Sync + Sized {
    fn as_u8(self) -> u8;
    fn as_u16(self) -> u16;
    fn as_u32(self) -> u32;
    fn as_u64(self) -> u64;
    fn as_u128(self) -> u128;
    fn as_usize(self) -> usize;
    fn as_i8(self) -> i8;
    fn as_i16(self) -> i16;
    fn as_i32(self) -> i32;
    fn as_i64(self) -> i64;
    fn as_i128(self) -> i128;
    fn as_isize(self) -> isize;
    fn as_f32(self) -> f32;
    fn as_f64(self) -> f64;
    fn from_u32(value: u32) -> Self;
    fn from_u64(value: u64) -> Self;
    #[cfg(feature = "f16")]
    fn as_f16(self) -> f16;
    #[cfg(feature = "f16")]
    fn as_bf16(self) -> bf16;
}
macro_rules! as_primitive {
    ($($t:ty)*) => ($(
        impl AsPrimitive for $t {
            #[inline(always)]
            fn as_u8(self) -> u8 {
                self as _
            }
            #[inline(always)]
            fn as_u16(self) -> u16 {
                self as _
            }
            #[inline(always)]
            fn as_u32(self) -> u32 {
                self as _
            }
            #[inline(always)]
            fn as_u64(self) -> u64 {
                self as _
            }
            #[inline(always)]
            fn as_u128(self) -> u128 {
                self as _
            }
            #[inline(always)]
            fn as_usize(self) -> usize {
                self as _
            }
            #[inline(always)]
            fn as_i8(self) -> i8 {
                self as _
            }
            #[inline(always)]
            fn as_i16(self) -> i16 {
                self as _
            }
            #[inline(always)]
            fn as_i32(self) -> i32 {
                self as _
            }
            #[inline(always)]
            fn as_i64(self) -> i64 {
                self as _
            }
            #[inline(always)]
            fn as_i128(self) -> i128 {
                self as _
            }
            #[inline(always)]
            fn as_isize(self) -> isize {
                self as _
            }
            #[inline(always)]
            fn as_f32(self) -> f32 {
                self as _
            }
            #[inline(always)]
            fn as_f64(self) -> f64 {
                self as _
            }
            #[inline(always)]
            fn from_u32(value: u32) -> Self {
                value as _
            }
            #[inline(always)]
            fn from_u64(value: u64) -> Self {
                value as _
            }
            #[cfg(feature = "f16")]
            #[inline(always)]
            fn as_f16(self) -> f16 {
                f16::from_f32(self as f32)
            }
            #[cfg(feature = "f16")]
            #[inline(always)]
            fn as_bf16(self) -> bf16 {
                bf16::from_f32(self as f32)
            }
        }
    )*)
}
as_primitive! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize f32 f64 }
#[cfg(feature = "f16")]
macro_rules! half_as_primitive {
    ($($t:ty)*) => ($(
        impl AsPrimitive for $t {
            #[inline(always)]
            fn as_u8(self) -> u8 {
                self.as_f32() as _
            }
            #[inline(always)]
            fn as_u16(self) -> u16 {
                self.as_f32() as _
            }
            #[inline(always)]
            fn as_u32(self) -> u32 {
                self.as_f32() as _
            }
            #[inline(always)]
            fn as_u64(self) -> u64 {
                self.as_f32() as _
            }
            #[inline(always)]
            fn as_u128(self) -> u128 {
                self.as_f32() as _
            }
            #[inline(always)]
            fn as_usize(self) -> usize {
                self.as_f32() as _
            }
            #[inline(always)]
            fn as_i8(self) -> i8 {
                self.as_f32() as _
            }
            #[inline(always)]
            fn as_i16(self) -> i16 {
                self.as_f32() as _
            }
            #[inline(always)]
            fn as_i32(self) -> i32 {
                self.as_f32() as _
            }
            #[inline(always)]
            fn as_i64(self) -> i64 {
                self.as_f32() as _
            }
            #[inline(always)]
            fn as_i128(self) -> i128 {
                self.as_f32() as _
            }
            #[inline(always)]
            fn as_isize(self) -> isize {
                self.as_f32() as _
            }
            #[inline(always)]
            fn as_f32(self) -> f32 {
                self.as_f32() as _
            }
            #[inline(always)]
            fn as_f64(self) -> f64 {
                self.as_f32() as _
            }
            #[inline(always)]
            fn from_u32(value: u32) -> Self {
                Self::from_f32(value as _)
            }
            #[inline(always)]
            fn from_u64(value: u64) -> Self {
                _ = value;
                unimplemented!()
            }
            #[inline(always)]
            fn as_f16(self) -> f16 {
                f16::from_f32(self.as_f32())
            }
            #[inline(always)]
            fn as_bf16(self) -> bf16 {
                bf16::from_f32(self.as_f32())
            }
        }
    )*)
}
#[cfg(feature = "f16")]
half_as_primitive! { f16 bf16 }
pub trait AsCast: AsPrimitive {
    fn as_cast<N: AsPrimitive>(n: N) -> Self;
}
#[inline(always)]
pub fn as_cast<U: AsCast, T: AsCast>(t: T) -> U {
    U::as_cast(t)
}
macro_rules! as_cast {
    ($($t:ty, $meth:ident ; )*) => ($(
        impl AsCast for $t {
            #[inline(always)]
            fn as_cast<N: AsPrimitive>(n: N) -> $t {
                n.$meth() as _
            }
        }
    )*);
}
as_cast!(
    u8, as_u8 ;
    u16, as_u16 ;
    u32, as_u32 ;
    u64, as_u64 ;
    u128, as_u128 ;
    usize, as_usize ;
    i8, as_i8 ;
    i16, as_i16 ;
    i32, as_i32 ;
    i64, as_i64 ;
    i128, as_i128 ;
    isize, as_isize ;
    f32, as_f32 ;
    f64, as_f64 ;
);
#[cfg(feature = "f16")]
as_cast!(
    f16, as_f16 ;
    bf16, as_bf16 ;
);
pub trait Primitive: 'static + fmt::Debug + fmt::Display + AsCast {}
macro_rules! primitive {
    ($($t:ty)*) => ($(
        impl Primitive for $t {}
    )*)
}
primitive! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize f32 f64 }
#[cfg(feature = "f16")]
primitive! { f16 bf16 }
pub trait Number:
    Default +
    Primitive +
    ops::Add<Output=Self> +
    ops::AddAssign +
    ops::Div<Output=Self> +
    ops::DivAssign +
    ops::Mul<Output=Self> +
    ops::MulAssign +
    ops::Rem<Output=Self> +
    ops::RemAssign +
    ops::Sub<Output=Self> +
    ops::SubAssign
{
    const IS_SIGNED: bool;
}
macro_rules! number_impl {
    ($($t:tt $is_signed:literal ; )*) => ($(
        impl Number for $t {
            const IS_SIGNED: bool = $is_signed;
        }
    )*)
}
number_impl! {
    u8 false ;
    u16 false ;
    u32 false ;
    u64 false ;
    u128 false ;
    usize false ;
    i8 true ;
    i16 true ;
    i32 true ;
    i64 true ;
    i128 true ;
    isize true ;
    f32 true ;
    f64 true ;
    }
#[cfg(feature = "f16")]
number_impl! {
    f16 true ;
    bf16 true ;
}
pub trait Integer:
    Number + Eq + Ord +
    ops::BitAnd<Output=Self> +
    ops::BitAndAssign +
    ops::BitOr<Output=Self> +
    ops::BitOrAssign +
    ops::BitXor<Output=Self> +
    ops::BitXorAssign +
    ops::Not<Output=Self> +
    ops::Shl<Self, Output=Self> +
    ops::Shl<i32, Output=Self> +
    ops::ShlAssign<i32> +
    ops::Shr<i32, Output=Self> +
    ops::ShrAssign<i32> +
{
    const ZERO: Self;
    const ONE: Self;
    const TWO: Self;
    const MAX: Self;
    const MIN: Self;
    const BITS: usize;
    fn leading_zeros(self) -> u32;
    fn trailing_zeros(self) -> u32;
    fn pow(self, exp: u32) -> Self;
    fn checked_pow(self, exp: u32) -> Option<Self>;
    fn overflowing_pow(self, exp: u32) -> (Self, bool);
    fn checked_add(self, i: Self) -> Option<Self>;
    fn checked_sub(self, i: Self) -> Option<Self>;
    fn checked_mul(self, i: Self) -> Option<Self>;
    fn overflowing_add(self, i: Self) -> (Self, bool);
    fn overflowing_sub(self, i: Self) -> (Self, bool);
    fn overflowing_mul(self, i: Self) -> (Self, bool);
    fn wrapping_add(self, i: Self) -> Self;
    fn wrapping_sub(self, i: Self) -> Self;
    fn wrapping_mul(self, i: Self) -> Self;
    fn wrapping_neg(self) -> Self;
    fn saturating_add(self, i: Self) -> Self;
    fn saturating_sub(self, i: Self) -> Self;
    fn saturating_mul(self, i: Self) -> Self;
    #[inline(always)]
    fn ceil_divmod(self, y: Self) -> (Self, i32) {
        let q = self / y;
        let r = self % y;
        match r == Self::ZERO {
            true  => (q, i32::as_cast(r)),
            false => (q + Self::ONE, i32::as_cast(r) - i32::as_cast(y))
        }
    }
    #[inline(always)]
    fn ceil_div(self, y: Self) -> Self {
        self.ceil_divmod(y).0
    }
    #[inline(always)]
    fn ceil_mod(self, y: Self) -> i32 {
        self.ceil_divmod(y).1
    }
    #[inline(always)]
    fn bit_length(self) -> u32 {
        Self::BITS as u32 - self.leading_zeros()
    }
    #[inline(always)]
    fn is_odd(self) -> bool {
        self & Self::ONE == Self::ONE
    }
    #[inline(always)]
    fn is_even(self) -> bool {
        !self.is_odd()
    }
    #[inline(always)]
    fn overflow_digits(radix: u32) -> usize {
        if radix <= 16 {
            core::mem::size_of::<Self>() * 2 - Self::IS_SIGNED as usize
        } else {
            core::mem::size_of::<Self>()
        }
    }
}
macro_rules! integer_impl {
($($t:tt)*) => ($(
    impl Integer for $t {
        const ZERO: $t = 0;
        const ONE: $t = 1;
        const TWO: $t = 2;
        const MAX: $t = $t::MAX;
        const MIN: $t = $t::MIN;
        const BITS: usize = mem::size_of::<$t>() * 8;
        #[inline(always)]
        fn leading_zeros(self) -> u32 {
            $t::leading_zeros(self)
        }
        #[inline(always)]
        fn trailing_zeros(self) -> u32 {
            $t::trailing_zeros(self)
        }
        #[inline(always)]
        fn checked_add(self, i: Self) -> Option<Self> {
            $t::checked_add(self, i)
        }
        #[inline(always)]
        fn checked_sub(self, i: Self) -> Option<Self> {
            $t::checked_sub(self, i)
        }
        #[inline(always)]
        fn checked_mul(self, i: Self) -> Option<Self> {
            $t::checked_mul(self, i)
        }
        #[inline(always)]
        fn overflowing_add(self, i: Self) -> (Self, bool) {
            $t::overflowing_add(self, i)
        }
        #[inline(always)]
        fn overflowing_sub(self, i: Self) -> (Self, bool) {
            $t::overflowing_sub(self, i)
        }
        #[inline(always)]
        fn overflowing_mul(self, i: Self) -> (Self, bool) {
            $t::overflowing_mul(self, i)
        }
        #[inline(always)]
        fn wrapping_add(self, i: Self) -> Self {
            $t::wrapping_add(self, i)
        }
        #[inline(always)]
        fn wrapping_sub(self, i: Self) -> Self {
            $t::wrapping_sub(self, i)
        }
        #[inline(always)]
        fn wrapping_mul(self, i: Self) -> Self {
            $t::wrapping_mul(self, i)
        }
        #[inline(always)]
        fn wrapping_neg(self) -> Self {
            $t::wrapping_neg(self)
        }
        #[inline(always)]
        fn pow(self, exp: u32) -> Self {
            Self::pow(self, exp)
        }
        #[inline(always)]
        fn checked_pow(self, exp: u32) -> Option<Self> {
            Self::checked_pow(self, exp)
        }
        #[inline(always)]
        fn overflowing_pow(self, exp: u32) -> (Self, bool) {
            Self::overflowing_pow(self, exp)
        }
        #[inline(always)]
        fn saturating_add(self, i: Self) -> Self {
            $t::saturating_add(self, i)
        }
        #[inline(always)]
        fn saturating_sub(self, i: Self) -> Self {
            $t::saturating_sub(self, i)
        }
        #[inline(always)]
        fn saturating_mul(self, i: Self) -> Self {
            $t::saturating_mul(self, i)
        }
    }
)*)
}
integer_impl! { u8 u16 u32 u64 u128 i8 i16 i32 i64 i128 usize isize }
pub trait SignedInteger: Integer + ops::Neg<Output = Self> {}
macro_rules! signed_integer_impl {
($($t:tt)*) => ($(
    impl SignedInteger for $t {}
)*)
}
signed_integer_impl! { i8 i16 i32 i64 i128 isize }
pub trait UnsignedInteger: Integer {}
macro_rules! unsigned_integer_impl {
($($t:ty)*) => ($(
    impl UnsignedInteger for $t {}
)*)
}
unsigned_integer_impl! { u8 u16 u32 u64 u128 usize }
#[cfg(feature = "floats")]
pub trait Float: Number + ops::Neg<Output = Self> {
    type Unsigned: UnsignedInteger;
    const ZERO: Self;
    const ONE: Self;
    const TWO: Self;
    const MAX: Self;
    const MIN: Self;
    const INFINITY: Self;
    const NEG_INFINITY: Self;
    const NAN: Self;
    const BITS: usize;
    const SIGN_MASK: Self::Unsigned;
    const EXPONENT_MASK: Self::Unsigned;
    const HIDDEN_BIT_MASK: Self::Unsigned;
    const MANTISSA_MASK: Self::Unsigned;
    const CARRY_MASK: Self::Unsigned;
    const INFINITY_BITS: Self::Unsigned;
    const NEGATIVE_INFINITY_BITS: Self::Unsigned;
    const EXPONENT_SIZE: i32;
    const MANTISSA_SIZE: i32;
    const EXPONENT_BIAS: i32;
    const DENORMAL_EXPONENT: i32;
    const MAX_EXPONENT: i32;
    fn to_bits(self) -> Self::Unsigned;
    fn from_bits(u: Self::Unsigned) -> Self;
    fn ln(self) -> Self;
    fn floor(self) -> Self;
    fn is_sign_positive(self) -> bool;
    fn is_sign_negative(self) -> bool;
    #[inline(always)]
    fn is_denormal(self) -> bool {
        self.to_bits() & Self::EXPONENT_MASK == Self::Unsigned::ZERO
    }
    #[inline(always)]
    fn is_special(self) -> bool {
        self.to_bits() & Self::EXPONENT_MASK == Self::EXPONENT_MASK
    }
    #[inline(always)]
    fn is_nan(self) -> bool {
        self.is_special() && (self.to_bits() & Self::MANTISSA_MASK) != Self::Unsigned::ZERO
    }
    #[inline(always)]
    fn is_inf(self) -> bool {
        self.is_special() && (self.to_bits() & Self::MANTISSA_MASK) == Self::Unsigned::ZERO
    }
    #[inline(always)]
    fn is_odd(self) -> bool {
        self.to_bits().is_odd()
    }
    #[inline(always)]
    fn is_even(self) -> bool {
        !self.is_odd()
    }
    #[inline(always)]
    fn needs_negative_sign(self) -> bool {
        self.is_sign_negative() && !self.is_nan()
    }
    #[inline(always)]
    fn exponent(self) -> i32 {
        if self.is_denormal() {
            return Self::DENORMAL_EXPONENT;
        }
        let bits = self.to_bits();
        let biased_e = i32::as_cast((bits & Self::EXPONENT_MASK) >> Self::MANTISSA_SIZE).as_i32();
        biased_e - Self::EXPONENT_BIAS
    }
    #[inline(always)]
    fn mantissa(self) -> Self::Unsigned {
        let bits = self.to_bits();
        let s = bits & Self::MANTISSA_MASK;
        if !self.is_denormal() {
            s + Self::HIDDEN_BIT_MASK
        } else {
            s
        }
    }
    #[inline(always)]
    fn next(self) -> Self {
        let bits = self.to_bits();
        if self.is_sign_negative() && self == Self::ZERO {
            Self::ZERO
        } else if bits == Self::INFINITY_BITS {
            Self::from_bits(Self::INFINITY_BITS)
        } else if self.is_sign_negative() {
            Self::from_bits(bits.saturating_sub(Self::Unsigned::ONE))
        } else {
            Self::from_bits(bits.saturating_add(Self::Unsigned::ONE))
        }
    }
    #[inline(always)]
    fn next_positive(self) -> Self {
        debug_assert!(self.is_sign_positive() && !self.is_inf());
        Self::from_bits(self.to_bits() + Self::Unsigned::ONE)
    }
    #[inline(always)]
    fn prev(self) -> Self {
        let bits = self.to_bits();
        if self.is_sign_positive() && self == Self::ZERO {
            -Self::ZERO
        } else if bits == Self::NEGATIVE_INFINITY_BITS {
            Self::from_bits(Self::NEGATIVE_INFINITY_BITS)
        } else if self.is_sign_negative() {
            Self::from_bits(bits.saturating_add(Self::Unsigned::ONE))
        } else {
            Self::from_bits(bits.saturating_sub(Self::Unsigned::ONE))
        }
    }
    #[inline(always)]
    fn prev_positive(self) -> Self {
        debug_assert!(self.is_sign_positive() && self != Self::ZERO);
        Self::from_bits(self.to_bits() - Self::Unsigned::ONE)
    }
    #[inline(always)]
    fn round_positive_even(self) -> Self {
        if self.mantissa().is_odd() {
            self.next_positive()
        } else {
            self
        }
    }
    #[inline(always)]
    fn max_finite(self, f: Self) -> Self {
        debug_assert!(!self.is_special() && !f.is_special(), "max_finite self={} f={}", self, f);
        if self < f {
            f
        } else {
            self
        }
    }
    #[inline(always)]
    fn min_finite(self, f: Self) -> Self {
        debug_assert!(!self.is_special() && !f.is_special(), "min_finite self={} f={}", self, f);
        if self < f {
            self
        } else {
            f
        }
    }
}
#[cfg(feature = "floats")]
macro_rules! float_literals {
    ($float:ty) => {
        const ZERO: $float = 0.0;
        const ONE: $float = 1.0;
        const TWO: $float = 2.0;
        const MAX: $float = <$float>::MAX;
        const MIN: $float = <$float>::MIN;
        const INFINITY: $float = <$float>::INFINITY;
        const NEG_INFINITY: $float = <$float>::NEG_INFINITY;
        const NAN: $float = <$float>::NAN;
        const BITS: usize = mem::size_of::<$float>() * 8;
    };
}
#[cfg(feature = "floats")]
macro_rules! float_masks {
    (
        float =>
        $float:ty,sign_mask =>
        $sign:literal,exponent_mask =>
        $exponent:literal,hidden_bit_mask =>
        $hidden:literal,mantissa_mask =>
        $mantissa:literal,
    ) => {
        const SIGN_MASK: <$float>::Unsigned = $sign;
        const EXPONENT_MASK: <$float>::Unsigned = $exponent;
        const HIDDEN_BIT_MASK: <$float>::Unsigned = $hidden;
        const MANTISSA_MASK: <$float>::Unsigned = $mantissa;
        const CARRY_MASK: <$float>::Unsigned = $hidden << 1;
        const INFINITY_BITS: <$float>::Unsigned = $exponent;
        const NEGATIVE_INFINITY_BITS: <$float>::Unsigned = $exponent | $sign;
    };
}
#[cfg(feature = "f16")]
macro_rules! float_one {
    ($f:ident) => {
        (($f::EXPONENT_BIAS - $f::MANTISSA_SIZE) as u16) << $f::MANTISSA_SIZE
    };
}
#[cfg(feature = "f16")]
macro_rules! float_two {
    ($f:ident) => {
        (($f::EXPONENT_BIAS - $f::MANTISSA_SIZE + 1) as u16) << $f::MANTISSA_SIZE
    };
}
#[cfg(feature = "f16")]
macro_rules! float_max {
    ($f:ident) => {
        ($f::EXPONENT_MASK ^ $f::HIDDEN_BIT_MASK) | $f::MANTISSA_MASK
    };
}
#[cfg(feature = "f16")]
macro_rules! float_min {
    ($f:ident) => {
        $f::MAX.to_bits() | $f::SIGN_MASK
    };
}
#[cfg(feature = "f16")]
macro_rules! float_nan {
    ($f:ident) => {
        $f::EXPONENT_MASK | ($f::HIDDEN_BIT_MASK >> 1)
    };
}
#[cfg(feature = "f16")]
impl Float for f16 {
    type Unsigned = u16;
    const ZERO: Self = Self::from_bits(0);
    const ONE: Self = Self::from_bits(float_one!(Self));
    const TWO: Self = Self::from_bits(float_two!(Self));
    const MAX: Self = Self::from_bits(float_max!(Self));
    const MIN: Self = Self::from_bits(float_min!(Self));
    const INFINITY: Self = Self::from_bits(Self::INFINITY_BITS);
    const NEG_INFINITY: Self = Self::from_bits(Self::NEGATIVE_INFINITY_BITS);
    const NAN: Self = Self::from_bits(float_nan!(Self));
    const BITS: usize = mem::size_of::<Self>() * 8;
    float_masks!(
        float => Self,
        sign_mask => 0x8000,
        exponent_mask => 0x7C00,
        hidden_bit_mask => 0x0400,
        mantissa_mask => 0x03FF,
    );
    const EXPONENT_SIZE: i32 = 5;
    const MANTISSA_SIZE: i32 = 10;
    const EXPONENT_BIAS: i32 = 15 + Self::MANTISSA_SIZE;
    const DENORMAL_EXPONENT: i32 = 1 - Self::EXPONENT_BIAS;
    const MAX_EXPONENT: i32 = 0x1F - Self::EXPONENT_BIAS;
    #[inline(always)]
    fn to_bits(self) -> u16 {
        f16::to_bits(self)
    }
    #[inline(always)]
    fn from_bits(u: u16) -> f16 {
        f16::from_bits(u)
    }
    #[inline(always)]
    fn ln(self) -> f16 {
        f16::from_f32(self.as_f32().ln())
    }
    #[inline(always)]
    fn floor(self) -> f16 {
        f16::from_f32(self.as_f32().floor())
    }
    #[inline(always)]
    fn is_sign_positive(self) -> bool {
        self.to_bits() & Self::SIGN_MASK == 0
    }
    #[inline(always)]
    fn is_sign_negative(self) -> bool {
        !self.is_sign_positive()
    }
}
#[cfg(feature = "f16")]
impl Float for bf16 {
    type Unsigned = u16;
    const ZERO: Self = Self::from_bits(0);
    const ONE: Self = Self::from_bits(float_one!(Self));
    const TWO: Self = Self::from_bits(float_two!(Self));
    const MAX: Self = Self::from_bits(float_max!(Self));
    const MIN: Self = Self::from_bits(float_min!(Self));
    const INFINITY: Self = Self::from_bits(Self::INFINITY_BITS);
    const NEG_INFINITY: Self = Self::from_bits(Self::NEGATIVE_INFINITY_BITS);
    const NAN: Self = Self::from_bits(float_nan!(Self));
    const BITS: usize = mem::size_of::<Self>() * 8;
    float_masks!(
        float => Self,
        sign_mask => 0x8000,
        exponent_mask => 0x7F80,
        hidden_bit_mask => 0x0080,
        mantissa_mask => 0x007F,
    );
    const EXPONENT_SIZE: i32 = 8;
    const MANTISSA_SIZE: i32 = 7;
    const EXPONENT_BIAS: i32 = 127 + Self::MANTISSA_SIZE;
    const DENORMAL_EXPONENT: i32 = 1 - Self::EXPONENT_BIAS;
    const MAX_EXPONENT: i32 = 0xFF - Self::EXPONENT_BIAS;
    #[inline(always)]
    fn to_bits(self) -> u16 {
        bf16::to_bits(self)
    }
    #[inline(always)]
    fn from_bits(u: u16) -> bf16 {
        bf16::from_bits(u)
    }
    #[inline(always)]
    fn ln(self) -> bf16 {
        bf16::from_f32(self.as_f32().ln())
    }
    #[inline(always)]
    fn floor(self) -> bf16 {
        bf16::from_f32(self.as_f32().floor())
    }
    #[inline(always)]
    fn is_sign_positive(self) -> bool {
        self.to_bits() & Self::SIGN_MASK == 0
    }
    #[inline(always)]
    fn is_sign_negative(self) -> bool {
        !self.is_sign_positive()
    }
}
#[cfg(feature = "floats")]
impl Float for f32 {
    type Unsigned = u32;
    float_literals!(f32);
    float_masks!(
        float => Self,
        sign_mask => 0x80000000,
        exponent_mask => 0x7F800000,
        hidden_bit_mask => 0x00800000,
        mantissa_mask => 0x007FFFFF,
    );
    const EXPONENT_SIZE: i32 = 8;
    const MANTISSA_SIZE: i32 = 23;
    const EXPONENT_BIAS: i32 = 127 + Self::MANTISSA_SIZE;
    const DENORMAL_EXPONENT: i32 = 1 - Self::EXPONENT_BIAS;
    const MAX_EXPONENT: i32 = 0xFF - Self::EXPONENT_BIAS;
    #[inline(always)]
    fn to_bits(self) -> u32 {
        f32::to_bits(self)
    }
    #[inline(always)]
    fn from_bits(u: u32) -> f32 {
        f32::from_bits(u)
    }
    #[inline(always)]
    fn ln(self) -> f32 {
        #[cfg(feature = "std")]
        return f32::ln(self);
        #[cfg(not(feature = "std"))]
        return logf(self);
    }
    #[inline(always)]
    fn floor(self) -> f32 {
        #[cfg(feature = "std")]
        return f32::floor(self);
        #[cfg(not(feature = "std"))]
        return floorf(self);
    }
    #[inline(always)]
    fn is_sign_positive(self) -> bool {
        f32::is_sign_positive(self)
    }
    #[inline(always)]
    fn is_sign_negative(self) -> bool {
        f32::is_sign_negative(self)
    }
}
#[cfg(feature = "floats")]
impl Float for f64 {
    type Unsigned = u64;
    float_literals!(f64);
    float_masks!(
        float => Self,
        sign_mask => 0x8000000000000000,
        exponent_mask => 0x7FF0000000000000,
        hidden_bit_mask => 0x0010000000000000,
        mantissa_mask => 0x000FFFFFFFFFFFFF,
    );
    const EXPONENT_SIZE: i32 = 11;
    const MANTISSA_SIZE: i32 = 52;
    const EXPONENT_BIAS: i32 = 1023 + Self::MANTISSA_SIZE;
    const DENORMAL_EXPONENT: i32 = 1 - Self::EXPONENT_BIAS;
    const MAX_EXPONENT: i32 = 0x7FF - Self::EXPONENT_BIAS;
    #[inline(always)]
    fn to_bits(self) -> u64 {
        f64::to_bits(self)
    }
    #[inline(always)]
    fn from_bits(u: u64) -> f64 {
        f64::from_bits(u)
    }
    #[inline(always)]
    fn ln(self) -> f64 {
        #[cfg(feature = "std")]
        return f64::ln(self);
        #[cfg(not(feature = "std"))]
        return logd(self);
    }
    #[inline(always)]
    fn floor(self) -> f64 {
        #[cfg(feature = "std")]
        return f64::floor(self);
        #[cfg(not(feature = "std"))]
        return floord(self);
    }
    #[inline(always)]
    fn is_sign_positive(self) -> bool {
        f64::is_sign_positive(self)
    }
    #[inline(always)]
    fn is_sign_negative(self) -> bool {
        f64::is_sign_negative(self)
    }
}
#[cfg(all(not(feature = "std"), feature = "floats"))]
macro_rules! volatile {
($e:expr) => {
    unsafe {
        core::ptr::read_volatile(&$e);
    }
};
}
#[cfg(all(not(feature = "std"), feature = "floats"))]
fn floord(x: f64) -> f64 {
    const TOINT: f64 = 1. / f64::EPSILON;
    let ui = x.to_bits();
    let e = ((ui >> 52) & 0x7ff) as i32;
    if (e >= 0x3ff + 52) || (x == 0.) {
        return x;
    }
    let y = if (ui >> 63) != 0 {
        x - TOINT + TOINT - x
    } else {
        x + TOINT - TOINT - x
    };
    if e < 0x3ff {
        volatile!(y);
        return if (ui >> 63) != 0 {
            -1.
        } else {
            0.
        };
    }
    if y > 0. {
        x + y - 1.
    } else {
        x + y
    }
}
#[cfg(all(not(feature = "std"), feature = "floats"))]
fn floorf(x: f32) -> f32 {
    let mut ui = x.to_bits();
    let e = (((ui >> 23) as i32) & 0xff) - 0x7f;
    if e >= 23 {
        return x;
    }
    if e >= 0 {
        let m: u32 = 0x007fffff >> e;
        if (ui & m) == 0 {
            return x;
        }
        volatile!(x + f32::from_bits(0x7b800000));
        if ui >> 31 != 0 {
            ui += m;
        }
        ui &= !m;
    } else {
        volatile!(x + f32::from_bits(0x7b800000));
        if ui >> 31 == 0 {
            ui = 0;
        } else if ui << 1 != 0 {
            return -1.0;
        }
    }
    f32::from_bits(ui)
}
#[allow(clippy::eq_op, clippy::excessive_precision)]
#[cfg(all(not(feature = "std"), feature = "floats"))]
fn logd(mut x: f64) -> f64 {
    const LN2_HI: f64 = 6.93147180369123816490e-01; const LN2_LO: f64 = 1.90821492927058770002e-10; const LG1: f64 = 6.666666666666735130e-01; const LG2: f64 = 3.999999999940941908e-01; const LG3: f64 = 2.857142874366239149e-01; const LG4: f64 = 2.222219843214978396e-01; const LG5: f64 = 1.818357216161805012e-01; const LG6: f64 = 1.531383769920937332e-01; const LG7: f64 = 1.479819860511658591e-01; let x1p54 = f64::from_bits(0x4350000000000000); let mut ui = x.to_bits();
    let mut hx: u32 = (ui >> 32) as u32;
    let mut k: i32 = 0;
    if (hx < 0x00100000) || ((hx >> 31) != 0) {
        if ui << 1 == 0 {
            return -1. / (x * x); }
        if hx >> 31 != 0 {
            return (x - x) / 0.0; }
        k -= 54;
        x *= x1p54;
        ui = x.to_bits();
        hx = (ui >> 32) as u32;
    } else if hx >= 0x7ff00000 {
        return x;
    } else if hx == 0x3ff00000 && ui << 32 == 0 {
        return 0.;
    }
    hx += 0x3ff00000 - 0x3fe6a09e;
    k += ((hx >> 20) as i32) - 0x3ff;
    hx = (hx & 0x000fffff) + 0x3fe6a09e;
    ui = ((hx as u64) << 32) | (ui & 0xffffffff);
    x = f64::from_bits(ui);
    let f: f64 = x - 1.0;
    let hfsq: f64 = 0.5 * f * f;
    let s: f64 = f / (2.0 + f);
    let z: f64 = s * s;
    let w: f64 = z * z;
    let t1: f64 = w * (LG2 + w * (LG4 + w * LG6));
    let t2: f64 = z * (LG1 + w * (LG3 + w * (LG5 + w * LG7)));
    let r: f64 = t2 + t1;
    let dk: f64 = k as f64;
    s * (hfsq + r) + dk * LN2_LO - hfsq + f + dk * LN2_HI
}
#[allow(clippy::eq_op, clippy::excessive_precision)]
#[cfg(all(not(feature = "std"), feature = "floats"))]
fn logf(mut x: f32) -> f32 {
    const LN2_HI: f32 = 6.9313812256e-01; const LN2_LO: f32 = 9.0580006145e-06; const LG1: f32 = 0.66666662693; const LG2: f32 = 0.40000972152; const LG3: f32 = 0.28498786688; const LG4: f32 = 0.24279078841; let x1p25 = f32::from_bits(0x4c000000); let mut ix = x.to_bits();
    let mut k = 0i32;
    if (ix < 0x00800000) || ((ix >> 31) != 0) {
        if ix << 1 == 0 {
            return -1. / (x * x); }
        if (ix >> 31) != 0 {
            return (x - x) / 0.; }
        k -= 25;
        x *= x1p25;
        ix = x.to_bits();
    } else if ix >= 0x7f800000 {
        return x;
    } else if ix == 0x3f800000 {
        return 0.;
    }
    ix += 0x3f800000 - 0x3f3504f3;
    k += ((ix >> 23) as i32) - 0x7f;
    ix = (ix & 0x007fffff) + 0x3f3504f3;
    x = f32::from_bits(ix);
    let f = x - 1.;
    let s = f / (2. + f);
    let z = s * s;
    let w = z * z;
    let t1 = w * (LG2 + w * LG4);
    let t2 = z * (LG1 + w * LG3);
    let r = t2 + t1;
    let hfsq = 0.5 * f * f;
    let dk = k as f32;
    s * (hfsq + r) + dk * LN2_LO - hfsq + f + dk * LN2_HI
}