const _: () = assert!(
(-1 >> 1) == -1,
"right-shift for signed integers must be arithmetic",
);
trait TierInfo {
const TIER: usize;
const MULTIPLY: u32;
const SUBTRACT: u32;
const SHIFT: u32;
const MIN_EXPONENT: i32;
const MAX_EXPONENT: i32;
type Next: TierInfo;
}
const fn is_in_range<Info: TierInfo, const MIN_EXPONENT: i32, const MAX_EXPONENT: i32>() -> bool {
MIN_EXPONENT >= Info::MIN_EXPONENT && MAX_EXPONENT <= Info::MAX_EXPONENT
}
const fn compute<Info: TierInfo, const MIN_EXPONENT: i32, const MAX_EXPONENT: i32>(e: i32) -> i32 {
if is_in_range::<Info, MIN_EXPONENT, MAX_EXPONENT>() {
debug_assert!(MIN_EXPONENT <= e && e <= MAX_EXPONENT);
(e * Info::MULTIPLY as i32 - Info::SUBTRACT as i32) >> Info::SHIFT
} else {
debug_assert!(Info::TIER < Info::Next::TIER);
compute::<Info::Next, MIN_EXPONENT, MAX_EXPONENT>(e)
}
}
pub(crate) const FLOOR_LOG10_POW2_MIN_EXPONENT: i32 = -2620;
pub(crate) const FLOOR_LOG10_POW2_MAX_EXPONENT: i32 = 2620;
pub(crate) const fn floor_log10_pow2<const MIN_EXPONENT: i32, const MAX_EXPONENT: i32>(
e: i32,
) -> i32 {
enum Info0 {}
impl TierInfo for Info0 {
const TIER: usize = 0;
const MULTIPLY: u32 = 77;
const SUBTRACT: u32 = 0;
const SHIFT: u32 = 8;
const MIN_EXPONENT: i32 = -102;
const MAX_EXPONENT: i32 = 102;
type Next = Info1;
}
enum Info1 {}
impl TierInfo for Info1 {
const TIER: usize = 1;
const MULTIPLY: u32 = 1233;
const SUBTRACT: u32 = 0;
const SHIFT: u32 = 12;
const MIN_EXPONENT: i32 = -425;
const MAX_EXPONENT: i32 = 425;
type Next = Info2;
}
enum Info2 {}
impl TierInfo for Info2 {
const TIER: usize = 2;
const MULTIPLY: u32 = 315653;
const SUBTRACT: u32 = 0;
const SHIFT: u32 = 20;
const MIN_EXPONENT: i32 = -2620;
const MAX_EXPONENT: i32 = 2620;
type Next = Self;
}
compute::<Info0, MIN_EXPONENT, MAX_EXPONENT>(e)
}
pub(crate) const FLOOR_LOG2_POW10_MIN_EXPONENT: i32 = -1233;
pub(crate) const FLOOR_LOG2_POW10_MAX_EXPONENT: i32 = 1233;
pub(crate) const fn floor_log2_pow10<const MIN_EXPONENT: i32, const MAX_EXPONENT: i32>(
e: i32,
) -> i32 {
enum Info0 {}
impl TierInfo for Info0 {
const TIER: usize = 0;
const MULTIPLY: u32 = 53;
const SUBTRACT: u32 = 0;
const SHIFT: u32 = 4;
const MIN_EXPONENT: i32 = -15;
const MAX_EXPONENT: i32 = 18;
type Next = Info1;
}
enum Info1 {}
impl TierInfo for Info1 {
const TIER: usize = 1;
const MULTIPLY: u32 = 1701;
const SUBTRACT: u32 = 0;
const SHIFT: u32 = 9;
const MIN_EXPONENT: i32 = -58;
const MAX_EXPONENT: i32 = 58;
type Next = Info2;
}
enum Info2 {}
impl TierInfo for Info2 {
const TIER: usize = 2;
const MULTIPLY: u32 = 1741647;
const SUBTRACT: u32 = 0;
const SHIFT: u32 = 19;
const MIN_EXPONENT: i32 = -1233;
const MAX_EXPONENT: i32 = 1233;
type Next = Self;
}
compute::<Info0, MIN_EXPONENT, MAX_EXPONENT>(e)
}
pub(crate) const FLOOR_LOG10_POW2_MINUS_LOG10_4_OVER_3_MIN_EXPONENT: i32 = -2985;
pub(crate) const FLOOR_LOG10_POW2_MINUS_LOG10_4_OVER_3_MAX_EXPONENT: i32 = 2936;
pub(crate) const fn floor_log10_pow2_minus_log10_4_over_3<
const MIN_EXPONENT: i32,
const MAX_EXPONENT: i32,
>(
e: i32,
) -> i32 {
enum Info0 {}
impl TierInfo for Info0 {
const TIER: usize = 0;
const MULTIPLY: u32 = 77;
const SUBTRACT: u32 = 31;
const SHIFT: u32 = 8;
const MIN_EXPONENT: i32 = -75;
const MAX_EXPONENT: i32 = 129;
type Next = Info1;
}
enum Info1 {}
impl TierInfo for Info1 {
const TIER: usize = 1;
const MULTIPLY: u32 = 19728;
const SUBTRACT: u32 = 8241;
const SHIFT: u32 = 16;
const MIN_EXPONENT: i32 = -424;
const MAX_EXPONENT: i32 = 315;
type Next = Info2;
}
enum Info2 {}
impl TierInfo for Info2 {
const TIER: usize = 2;
const MULTIPLY: u32 = 631305;
const SUBTRACT: u32 = 261663;
const SHIFT: u32 = 21;
const MIN_EXPONENT: i32 = -2985;
const MAX_EXPONENT: i32 = 2936;
type Next = Self;
}
compute::<Info0, MIN_EXPONENT, MAX_EXPONENT>(e)
}
pub(crate) const fn floor_log5_pow2(e: i32) -> i32 {
enum Info0 {}
impl TierInfo for Info0 {
const TIER: usize = 0;
const MULTIPLY: u32 = 225799;
const SUBTRACT: u32 = 0;
const SHIFT: u32 = 19;
const MIN_EXPONENT: i32 = -1831;
const MAX_EXPONENT: i32 = 1831;
type Next = Self;
}
compute::<Info0, -1831, 1831>(e)
}
pub(crate) const fn floor_log5_pow2_minus_log5_3(e: i32) -> i32 {
enum Info0 {}
impl TierInfo for Info0 {
const TIER: usize = 0;
const MULTIPLY: u32 = 451597;
const SUBTRACT: u32 = 715764;
const SHIFT: u32 = 20;
const MIN_EXPONENT: i32 = -3543;
const MAX_EXPONENT: i32 = 2427;
type Next = Self;
}
compute::<Info0, -3543, 2427>(e)
}