#![doc(hidden)]
#[cfg(feature = "f16")]
use lexical_util::bf16::bf16;
use lexical_util::extended_float::ExtendedFloat;
#[cfg(feature = "f16")]
use lexical_util::f16::f16;
use lexical_util::num::{AsCast, Float};
#[cfg(all(not(feature = "std"), feature = "compact"))]
use crate::libm::{powd, powf};
use crate::limits::{ExactFloat, MaxDigits};
#[cfg(not(feature = "compact"))]
use crate::table::{get_small_f32_power, get_small_f64_power, get_small_int_power};
pub type ExtendedFloat80 = ExtendedFloat<u64>;
pub trait RawFloat: Float + ExactFloat + MaxDigits {
const MAX_MANTISSA_FAST_PATH: u64 = 2_u64 << Self::MANTISSA_SIZE;
const INFINITE_POWER: i32 = Self::MAX_EXPONENT + Self::EXPONENT_BIAS;
#[must_use]
#[inline(always)]
fn min_exponent_fast_path(radix: u32) -> i64 {
Self::exponent_limit(radix).0
}
#[must_use]
#[inline(always)]
fn max_exponent_fast_path(radix: u32) -> i64 {
Self::exponent_limit(radix).1
}
#[must_use]
#[inline(always)]
fn max_exponent_disguised_fast_path(radix: u32) -> i64 {
Self::max_exponent_fast_path(radix) + Self::mantissa_limit(radix)
}
fn pow_fast_path(exponent: usize, radix: u32) -> Self;
#[must_use]
#[inline(always)]
fn int_pow_fast_path(exponent: usize, radix: u32) -> u64 {
#[cfg(not(feature = "compact"))]
return get_small_int_power(exponent, radix);
#[cfg(feature = "compact")]
return (radix as u64).wrapping_pow(exponent as u32);
}
}
impl RawFloat for f32 {
#[inline(always)]
fn pow_fast_path(exponent: usize, radix: u32) -> Self {
#[cfg(not(feature = "compact"))]
return get_small_f32_power(exponent, radix);
#[cfg(feature = "compact")]
return powf(radix as f32, exponent as f32);
}
}
impl RawFloat for f64 {
#[inline(always)]
fn pow_fast_path(exponent: usize, radix: u32) -> Self {
#[cfg(not(feature = "compact"))]
return get_small_f64_power(exponent, radix);
#[cfg(feature = "compact")]
return powd(radix as f64, exponent as f64);
}
}
#[cfg(feature = "f16")]
impl RawFloat for f16 {
#[inline(always)]
fn pow_fast_path(_: usize, _: u32) -> Self {
unimplemented!()
}
}
#[cfg(feature = "f16")]
impl RawFloat for bf16 {
#[inline(always)]
fn pow_fast_path(_: usize, _: u32) -> Self {
unimplemented!()
}
}
pub trait LemireFloat: RawFloat {
const MIN_EXPONENT_ROUND_TO_EVEN: i32;
const MAX_EXPONENT_ROUND_TO_EVEN: i32;
const MINIMUM_EXPONENT: i32;
const SMALLEST_POWER_OF_TEN: i32;
const LARGEST_POWER_OF_TEN: i32;
}
impl LemireFloat for f32 {
const MIN_EXPONENT_ROUND_TO_EVEN: i32 = -17;
const MAX_EXPONENT_ROUND_TO_EVEN: i32 = 10;
const MINIMUM_EXPONENT: i32 = -127;
const SMALLEST_POWER_OF_TEN: i32 = -65;
const LARGEST_POWER_OF_TEN: i32 = 38;
}
impl LemireFloat for f64 {
const MIN_EXPONENT_ROUND_TO_EVEN: i32 = -4;
const MAX_EXPONENT_ROUND_TO_EVEN: i32 = 23;
const MINIMUM_EXPONENT: i32 = -1023;
const SMALLEST_POWER_OF_TEN: i32 = -342;
const LARGEST_POWER_OF_TEN: i32 = 308;
}
#[cfg(feature = "f16")]
impl LemireFloat for f16 {
const MIN_EXPONENT_ROUND_TO_EVEN: i32 = 0;
const MAX_EXPONENT_ROUND_TO_EVEN: i32 = 0;
const MINIMUM_EXPONENT: i32 = 0;
const SMALLEST_POWER_OF_TEN: i32 = 0;
const LARGEST_POWER_OF_TEN: i32 = 0;
}
#[cfg(feature = "f16")]
impl LemireFloat for bf16 {
const MIN_EXPONENT_ROUND_TO_EVEN: i32 = 0;
const MAX_EXPONENT_ROUND_TO_EVEN: i32 = 0;
const MINIMUM_EXPONENT: i32 = 0;
const SMALLEST_POWER_OF_TEN: i32 = 0;
const LARGEST_POWER_OF_TEN: i32 = 0;
}
#[inline(always)]
#[cfg(all(feature = "std", feature = "compact"))]
pub fn powf(x: f32, y: f32) -> f32 {
x.powf(y)
}
#[inline(always)]
#[cfg(all(feature = "std", feature = "compact"))]
pub fn powd(x: f64, y: f64) -> f64 {
x.powf(y)
}
#[must_use]
#[inline(always)]
pub fn extended_to_float<F: Float>(x: ExtendedFloat80) -> F {
let mut word = x.mant;
word |= (x.exp as u64) << F::MANTISSA_SIZE;
F::from_bits(F::Unsigned::as_cast(word))
}