use crate::types::widths::{D9, D18, D38};
use crate::support::rounding::RoundingMode;
use super::fixed_d38::INT_FAST_PATH_THRESHOLD;
#[inline]
fn exp_as_small_int_i128<const SCALE: u32>(exp_raw: i128) -> Option<i32> {
let mult = 10_i128.pow(SCALE);
if exp_raw % mult != 0 {
return None;
}
let q = exp_raw / mult;
if !(i32::MIN as i128..=i32::MAX as i128).contains(&q) {
return None;
}
let n = q as i32;
if n.unsigned_abs() <= INT_FAST_PATH_THRESHOLD as u32 {
Some(n)
} else {
None
}
}
#[inline]
#[must_use]
pub(crate) fn powf_strict_d9<const SCALE: u32>(
base: D9<SCALE>,
exp: D9<SCALE>,
mode: RoundingMode,
) -> D9<SCALE> {
if base.to_bits() > 0 {
if let Some(n) = exp_as_small_int_i128::<SCALE>(exp.to_bits() as i128) {
return base.powi(n);
}
}
let base_w: D38<SCALE> = base.into();
let exp_w: D38<SCALE> = exp.into();
let raw = super::fixed_d38::powf_strict::<SCALE>(base_w.0, exp_w.0, mode);
D38::<SCALE>::from_bits(raw)
.try_into()
.unwrap_or_else(|_| crate::support::diagnostics::overflow_panic_with_scale("powf_strict", SCALE))
}
#[inline]
#[must_use]
pub(crate) fn powf_with_d9<const SCALE: u32>(
base: D9<SCALE>,
exp: D9<SCALE>,
working_digits: u32,
mode: RoundingMode,
) -> D9<SCALE> {
if base.to_bits() > 0 {
if let Some(n) = exp_as_small_int_i128::<SCALE>(exp.to_bits() as i128) {
return base.powi(n);
}
}
let base_w: D38<SCALE> = base.into();
let exp_w: D38<SCALE> = exp.into();
let raw = super::fixed_d38::powf_with::<SCALE>(base_w.0, exp_w.0, working_digits, mode);
D38::<SCALE>::from_bits(raw)
.try_into()
.unwrap_or_else(|_| crate::support::diagnostics::overflow_panic_with_scale("powf_with", SCALE))
}
#[inline]
#[must_use]
pub(crate) fn powf_strict_d18<const SCALE: u32>(
base: D18<SCALE>,
exp: D18<SCALE>,
mode: RoundingMode,
) -> D18<SCALE> {
if base.to_bits() > 0 {
if let Some(n) = exp_as_small_int_i128::<SCALE>(exp.to_bits() as i128) {
return base.powi(n);
}
}
let base_w: D38<SCALE> = base.into();
let exp_w: D38<SCALE> = exp.into();
let raw = super::fixed_d38::powf_strict::<SCALE>(base_w.0, exp_w.0, mode);
D38::<SCALE>::from_bits(raw)
.try_into()
.unwrap_or_else(|_| crate::support::diagnostics::overflow_panic_with_scale("powf_strict", SCALE))
}
#[inline]
#[must_use]
pub(crate) fn powf_with_d18<const SCALE: u32>(
base: D18<SCALE>,
exp: D18<SCALE>,
working_digits: u32,
mode: RoundingMode,
) -> D18<SCALE> {
if base.to_bits() > 0 {
if let Some(n) = exp_as_small_int_i128::<SCALE>(exp.to_bits() as i128) {
return base.powi(n);
}
}
let base_w: D38<SCALE> = base.into();
let exp_w: D38<SCALE> = exp.into();
let raw = super::fixed_d38::powf_with::<SCALE>(base_w.0, exp_w.0, working_digits, mode);
D38::<SCALE>::from_bits(raw)
.try_into()
.unwrap_or_else(|_| crate::support::diagnostics::overflow_panic_with_scale("powf_with", SCALE))
}