use core::ops::Mul;
#[cfg(all(not(feature = "std"), feature = "libm"))]
mod libm;
#[cfg(feature = "wide")]
mod wide;
pub trait One {
#[must_use]
fn one() -> Self;
}
pub trait Powf {
#[must_use]
fn powf(self, exp: Self) -> Self;
}
pub trait Powi {
#[must_use]
fn powi(self, exp: i32) -> Self;
}
pub trait Powu {
#[must_use]
fn powu(self, exp: u32) -> Self;
}
pub trait Recip {
#[must_use]
fn recip(self) -> Self;
}
macro_rules! impl_uint {
($($ty: ident),+) => {
$(
impl One for $ty {
#[inline]
fn one() -> Self {
1
}
}
impl Powu for $ty {
#[inline]
fn powu(self, exp: u32) -> Self {
pow(self, exp)
}
}
)+
};
}
macro_rules! impl_float {
($($ty: ident),+) => {
$(
impl One for $ty {
#[inline]
fn one() -> Self {
1.0
}
}
#[cfg(any(feature = "std", all(test, not(feature = "libm"))))]
impl Powf for $ty {
#[inline]
fn powf(self, exp: Self) -> Self {
$ty::powf(self, exp)
}
}
#[cfg(any(feature = "std", all(test, not(feature = "libm"))))]
impl Powi for $ty {
#[inline]
fn powi(self, exp: i32) -> Self {
$ty::powi(self, exp)
}
}
impl Powu for $ty {
#[inline]
fn powu(self, exp: u32) -> Self {
pow(self, exp)
}
}
#[cfg(any(feature = "std", all(test, not(feature = "libm"))))]
impl Recip for $ty {
#[inline]
fn recip(self) -> Self {
$ty::recip(self)
}
}
)+
};
}
impl_uint!(u8, u16, u32, u64, u128);
impl_float!(f32, f64);
#[inline]
fn pow<T: Clone + One + Mul<T, Output = T>>(mut base: T, mut exp: u32) -> T {
if exp == 0 {
return T::one();
}
while exp & 1 == 0 {
base = base.clone() * base;
exp >>= 1;
}
if exp == 1 {
return base;
}
let mut acc = base.clone();
while exp > 1 {
exp >>= 1;
base = base.clone() * base;
if exp & 1 == 1 {
acc = acc * base.clone();
}
}
acc
}