use core::ops;
const F32_POW10: [f32; 11] = [
    1.0,
    10.0,
    100.0,
    1000.0,
    10000.0,
    100000.0,
    1000000.0,
    10000000.0,
    100000000.0,
    1000000000.0,
    10000000000.0,
];
const F64_POW10: [f64; 23] = [
    1.0,
    10.0,
    100.0,
    1000.0,
    10000.0,
    100000.0,
    1000000.0,
    10000000.0,
    100000000.0,
    1000000000.0,
    10000000000.0,
    100000000000.0,
    1000000000000.0,
    10000000000000.0,
    100000000000000.0,
    1000000000000000.0,
    10000000000000000.0,
    100000000000000000.0,
    1000000000000000000.0,
    10000000000000000000.0,
    100000000000000000000.0,
    1000000000000000000000.0,
    10000000000000000000000.0,
];
pub trait AsPrimitive: Sized + Copy + PartialOrd {
    fn as_u32(self) -> u32;
    fn as_u64(self) -> u64;
    fn as_u128(self) -> u128;
    fn as_usize(self) -> usize;
    fn as_f32(self) -> f32;
    fn as_f64(self) -> f64;
}
macro_rules! as_primitive_impl {
    ($($ty:ident)*) => {
        $(
            impl AsPrimitive for $ty {
                #[inline]
                fn as_u32(self) -> u32 {
                    self as u32
                }
                #[inline]
                fn as_u64(self) -> u64 {
                    self as u64
                }
                #[inline]
                fn as_u128(self) -> u128 {
                    self as u128
                }
                #[inline]
                fn as_usize(self) -> usize {
                    self as usize
                }
                #[inline]
                fn as_f32(self) -> f32 {
                    self as f32
                }
                #[inline]
                fn as_f64(self) -> f64 {
                    self as f64
                }
            }
        )*
    };
}
as_primitive_impl! { u32 u64 u128 usize f32 f64 }
pub trait AsCast: AsPrimitive {
            fn as_cast<N: AsPrimitive>(n: N) -> Self;
}
macro_rules! as_cast_impl {
    ($ty:ident, $method:ident) => {
        impl AsCast for $ty {
            #[inline]
            fn as_cast<N: AsPrimitive>(n: N) -> Self {
                n.$method()
            }
        }
    };
}
as_cast_impl!(u32, as_u32);
as_cast_impl!(u64, as_u64);
as_cast_impl!(u128, as_u128);
as_cast_impl!(usize, as_usize);
as_cast_impl!(f32, as_f32);
as_cast_impl!(f64, as_f64);
pub trait Number: AsCast + ops::Add<Output = Self> {}
macro_rules! number_impl {
    ($($ty:ident)*) => {
        $(
            impl Number for $ty {}
        )*
    };
}
number_impl! { u32 u64 u128 usize f32 f64 }
pub trait Integer: Number + ops::BitAnd<Output = Self> + ops::Shr<i32, Output = Self> {
    const ZERO: Self;
}
macro_rules! integer_impl {
    ($($ty:tt)*) => {
        $(
            impl Integer for $ty {
                const ZERO: Self = 0;
            }
        )*
    };
}
integer_impl! { u32 u64 u128 usize }
pub trait Mantissa: Integer {
        const HIMASK: Self;
        const LOMASK: Self;
        const FULL: i32;
        const HALF: i32 = Self::FULL / 2;
}
impl Mantissa for u64 {
    const HIMASK: u64 = 0xFFFFFFFF00000000;
    const LOMASK: u64 = 0x00000000FFFFFFFF;
    const FULL: i32 = 64;
}
pub trait Float: Number {
        type Unsigned: Integer;
        const ZERO: Self;
                                                                                                    const MAX_DIGITS: usize;
    
        const SIGN_MASK: Self::Unsigned;
        const EXPONENT_MASK: Self::Unsigned;
        const HIDDEN_BIT_MASK: Self::Unsigned;
        const MANTISSA_MASK: Self::Unsigned;
    
        const INFINITY_BITS: Self::Unsigned;
        const NEGATIVE_INFINITY_BITS: Self::Unsigned;
        const MANTISSA_SIZE: i32;
        const EXPONENT_BIAS: i32;
        const DENORMAL_EXPONENT: i32;
        const MAX_EXPONENT: i32;
    
        const DEFAULT_SHIFT: i32;
        const CARRY_MASK: u64;
        fn exponent_limit() -> (i32, i32);
        fn mantissa_limit() -> i32;
        fn pow10(self, n: i32) -> Self;
    fn from_bits(u: Self::Unsigned) -> Self;
    fn to_bits(self) -> Self::Unsigned;
    fn is_sign_positive(self) -> bool;
    fn is_sign_negative(self) -> bool;
        #[inline]
    fn is_denormal(self) -> bool {
        self.to_bits() & Self::EXPONENT_MASK == Self::Unsigned::ZERO
    }
        #[inline]
    fn is_special(self) -> bool {
        self.to_bits() & Self::EXPONENT_MASK == Self::EXPONENT_MASK
    }
        #[inline]
    fn is_inf(self) -> bool {
        self.is_special() && (self.to_bits() & Self::MANTISSA_MASK) == Self::Unsigned::ZERO
    }
        #[inline]
    fn exponent(self) -> i32 {
        if self.is_denormal() {
            return Self::DENORMAL_EXPONENT;
        }
        let bits = self.to_bits();
        let biased_e = ((bits & Self::EXPONENT_MASK) >> Self::MANTISSA_SIZE).as_u32();
        biased_e as i32 - Self::EXPONENT_BIAS
    }
        #[inline]
    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]
    fn next_positive(self) -> Self {
        debug_assert!(self.is_sign_positive() && !self.is_inf());
        Self::from_bits(self.to_bits() + Self::Unsigned::as_cast(1u32))
    }
        #[inline]
    fn round_positive_even(self) -> Self {
        if self.mantissa() & Self::Unsigned::as_cast(1u32) == Self::Unsigned::as_cast(1u32) {
            self.next_positive()
        } else {
            self
        }
    }
}
impl Float for f32 {
    type Unsigned = u32;
    const ZERO: f32 = 0.0;
    const MAX_DIGITS: usize = 114;
    const SIGN_MASK: u32 = 0x80000000;
    const EXPONENT_MASK: u32 = 0x7F800000;
    const HIDDEN_BIT_MASK: u32 = 0x00800000;
    const MANTISSA_MASK: u32 = 0x007FFFFF;
    const INFINITY_BITS: u32 = 0x7F800000;
    const NEGATIVE_INFINITY_BITS: u32 = Self::INFINITY_BITS | Self::SIGN_MASK;
    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;
    const DEFAULT_SHIFT: i32 = u64::FULL - f32::MANTISSA_SIZE - 1;
    const CARRY_MASK: u64 = 0x1000000;
    #[inline]
    fn exponent_limit() -> (i32, i32) {
        (-10, 10)
    }
    #[inline]
    fn mantissa_limit() -> i32 {
        7
    }
    #[inline]
    fn pow10(self, n: i32) -> f32 {
                debug_assert!({
            let (min, max) = Self::exponent_limit();
            n >= min && n <= max
        });
        if n > 0 {
            self * F32_POW10[n as usize]
        } else {
            self / F32_POW10[-n as usize]
        }
    }
    #[inline]
    fn from_bits(u: u32) -> f32 {
        f32::from_bits(u)
    }
    #[inline]
    fn to_bits(self) -> u32 {
        f32::to_bits(self)
    }
    #[inline]
    fn is_sign_positive(self) -> bool {
        f32::is_sign_positive(self)
    }
    #[inline]
    fn is_sign_negative(self) -> bool {
        f32::is_sign_negative(self)
    }
}
impl Float for f64 {
    type Unsigned = u64;
    const ZERO: f64 = 0.0;
    const MAX_DIGITS: usize = 769;
    const SIGN_MASK: u64 = 0x8000000000000000;
    const EXPONENT_MASK: u64 = 0x7FF0000000000000;
    const HIDDEN_BIT_MASK: u64 = 0x0010000000000000;
    const MANTISSA_MASK: u64 = 0x000FFFFFFFFFFFFF;
    const INFINITY_BITS: u64 = 0x7FF0000000000000;
    const NEGATIVE_INFINITY_BITS: u64 = Self::INFINITY_BITS | Self::SIGN_MASK;
    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;
    const DEFAULT_SHIFT: i32 = u64::FULL - f64::MANTISSA_SIZE - 1;
    const CARRY_MASK: u64 = 0x20000000000000;
    #[inline]
    fn exponent_limit() -> (i32, i32) {
        (-22, 22)
    }
    #[inline]
    fn mantissa_limit() -> i32 {
        15
    }
    #[inline]
    fn pow10(self, n: i32) -> f64 {
                debug_assert!({
            let (min, max) = Self::exponent_limit();
            n >= min && n <= max
        });
        if n > 0 {
            self * F64_POW10[n as usize]
        } else {
            self / F64_POW10[-n as usize]
        }
    }
    #[inline]
    fn from_bits(u: u64) -> f64 {
        f64::from_bits(u)
    }
    #[inline]
    fn to_bits(self) -> u64 {
        f64::to_bits(self)
    }
    #[inline]
    fn is_sign_positive(self) -> bool {
        f64::is_sign_positive(self)
    }
    #[inline]
    fn is_sign_negative(self) -> bool {
        f64::is_sign_negative(self)
    }
}