use crate::algos::ln;
use crate::types::widths::{D9, D18, D38};
use crate::support::rounding::RoundingMode;
pub(crate) trait LnPolicy: Sized {
fn ln_impl(self, mode: RoundingMode) -> Self;
fn ln_with_impl(self, working_digits: u32, mode: RoundingMode) -> Self;
fn log_impl(self, base: Self, mode: RoundingMode) -> Self;
fn log_with_impl(self, base: Self, working_digits: u32, mode: RoundingMode) -> Self;
fn log2_impl(self, mode: RoundingMode) -> Self;
fn log2_with_impl(self, working_digits: u32, mode: RoundingMode) -> Self;
fn log10_impl(self, mode: RoundingMode) -> Self;
fn log10_with_impl(self, working_digits: u32, mode: RoundingMode) -> Self;
}
macro_rules! impl_log_widen {
($T:ident, $ln_strict:path, $ln_with:path) => {
impl<const SCALE: u32> LnPolicy for $T<SCALE> {
#[inline]
fn ln_impl(self, mode: RoundingMode) -> Self {
$ln_strict(self, mode)
}
#[inline]
fn ln_with_impl(self, working_digits: u32, mode: RoundingMode) -> Self {
$ln_with(self, working_digits, mode)
}
#[inline]
fn log_impl(self, base: Self, mode: RoundingMode) -> Self {
let wide: D38<SCALE> = self.into();
let wbase: D38<SCALE> = base.into();
::core::convert::TryInto::try_into(wide.log_strict_with(wbase, mode))
.unwrap_or_else(|_| crate::support::diagnostics::overflow_panic_with_scale(
concat!(stringify!($T), "::log"), SCALE,
))
}
#[inline]
fn log_with_impl(self, base: Self, working_digits: u32, mode: RoundingMode) -> Self {
let wide: D38<SCALE> = self.into();
let wbase: D38<SCALE> = base.into();
::core::convert::TryInto::try_into(
wide.log_approx_with(wbase, working_digits, mode),
)
.unwrap_or_else(|_| crate::support::diagnostics::overflow_panic_with_scale(
concat!(stringify!($T), "::log"), SCALE,
))
}
#[inline]
fn log2_impl(self, mode: RoundingMode) -> Self {
let wide: D38<SCALE> = self.into();
::core::convert::TryInto::try_into(wide.log2_strict_with(mode))
.unwrap_or_else(|_| crate::support::diagnostics::overflow_panic_with_scale(
concat!(stringify!($T), "::log2"), SCALE,
))
}
#[inline]
fn log2_with_impl(self, working_digits: u32, mode: RoundingMode) -> Self {
let wide: D38<SCALE> = self.into();
::core::convert::TryInto::try_into(wide.log2_approx_with(working_digits, mode))
.unwrap_or_else(|_| crate::support::diagnostics::overflow_panic_with_scale(
concat!(stringify!($T), "::log2"), SCALE,
))
}
#[inline]
fn log10_impl(self, mode: RoundingMode) -> Self {
let wide: D38<SCALE> = self.into();
::core::convert::TryInto::try_into(wide.log10_strict_with(mode))
.unwrap_or_else(|_| crate::support::diagnostics::overflow_panic_with_scale(
concat!(stringify!($T), "::log10"), SCALE,
))
}
#[inline]
fn log10_with_impl(self, working_digits: u32, mode: RoundingMode) -> Self {
let wide: D38<SCALE> = self.into();
::core::convert::TryInto::try_into(wide.log10_approx_with(working_digits, mode))
.unwrap_or_else(|_| crate::support::diagnostics::overflow_panic_with_scale(
concat!(stringify!($T), "::log10"), SCALE,
))
}
}
};
}
impl_log_widen!(D9, ln::widen_to_d38::ln_strict_d9, ln::widen_to_d38::ln_with_d9);
impl_log_widen!(D18, ln::widen_to_d38::ln_strict_d18, ln::widen_to_d38::ln_with_d18);
#[cfg(any(feature = "d57", feature = "wide"))]
impl<const SCALE: u32> LnPolicy for D38<SCALE> {
#[inline]
fn ln_impl(self, mode: RoundingMode) -> Self {
Self(ln::borrow_d57::ln_strict::<SCALE>(self.0, mode))
}
#[inline]
fn ln_with_impl(self, _working_digits: u32, mode: RoundingMode) -> Self {
Self(ln::borrow_d57::ln_strict::<SCALE>(self.0, mode))
}
#[inline]
fn log_impl(self, base: Self, mode: RoundingMode) -> Self {
Self(ln::borrow_d57::log_strict::<SCALE>(self.0, base.0, mode))
}
#[inline]
fn log_with_impl(self, base: Self, _working_digits: u32, mode: RoundingMode) -> Self {
Self(ln::borrow_d57::log_strict::<SCALE>(self.0, base.0, mode))
}
#[inline]
fn log2_impl(self, mode: RoundingMode) -> Self {
Self(ln::borrow_d57::log2_strict::<SCALE>(self.0, mode))
}
#[inline]
fn log2_with_impl(self, _working_digits: u32, mode: RoundingMode) -> Self {
Self(ln::borrow_d57::log2_strict::<SCALE>(self.0, mode))
}
#[inline]
fn log10_impl(self, mode: RoundingMode) -> Self {
Self(ln::borrow_d57::log10_strict::<SCALE>(self.0, mode))
}
#[inline]
fn log10_with_impl(self, _working_digits: u32, mode: RoundingMode) -> Self {
Self(ln::borrow_d57::log10_strict::<SCALE>(self.0, mode))
}
}
#[cfg(not(any(feature = "d57", feature = "wide")))]
impl<const SCALE: u32> LnPolicy for D38<SCALE> {
#[inline]
fn ln_impl(self, mode: RoundingMode) -> Self {
Self(ln::fixed_d38::ln_strict::<SCALE>(self.0, mode))
}
#[inline]
fn ln_with_impl(self, working_digits: u32, mode: RoundingMode) -> Self {
Self(ln::fixed_d38::ln_with(self.0, SCALE, working_digits, mode))
}
#[inline]
fn log_impl(self, base: Self, mode: RoundingMode) -> Self {
Self(ln::fixed_d38::log_strict::<SCALE>(self.0, base.0, mode))
}
#[inline]
fn log_with_impl(self, base: Self, working_digits: u32, mode: RoundingMode) -> Self {
Self(ln::fixed_d38::log_with(self.0, base.0, SCALE, working_digits, mode))
}
#[inline]
fn log2_impl(self, mode: RoundingMode) -> Self {
Self(ln::fixed_d38::log2_strict::<SCALE>(self.0, mode))
}
#[inline]
fn log2_with_impl(self, working_digits: u32, mode: RoundingMode) -> Self {
Self(ln::fixed_d38::log2_with(self.0, SCALE, working_digits, mode))
}
#[inline]
fn log10_impl(self, mode: RoundingMode) -> Self {
Self(ln::fixed_d38::log10_strict::<SCALE>(self.0, mode))
}
#[inline]
fn log10_with_impl(self, working_digits: u32, mode: RoundingMode) -> Self {
Self(ln::fixed_d38::log10_with(self.0, SCALE, working_digits, mode))
}
}
macro_rules! impl_wide_ln {
($T:ident, $ln:path) => {
impl<const SCALE: u32> LnPolicy for crate::types::widths::$T<SCALE> {
#[inline]
fn ln_impl(self, mode: RoundingMode) -> Self {
Self($ln(self.0, mode, SCALE))
}
#[inline]
fn ln_with_impl(self, _working_digits: u32, mode: RoundingMode) -> Self {
Self($ln(self.0, mode, SCALE))
}
#[inline]
fn log_impl(self, base: Self, mode: RoundingMode) -> Self {
self.log_strict_with(base, mode)
}
#[inline]
fn log_with_impl(self, base: Self, _working_digits: u32, mode: RoundingMode) -> Self {
self.log_strict_with(base, mode)
}
#[inline]
fn log2_impl(self, mode: RoundingMode) -> Self {
self.log2_strict_with(mode)
}
#[inline]
fn log2_with_impl(self, _working_digits: u32, mode: RoundingMode) -> Self {
self.log2_strict_with(mode)
}
#[inline]
fn log10_impl(self, mode: RoundingMode) -> Self {
self.log10_strict_with(mode)
}
#[inline]
fn log10_with_impl(self, _working_digits: u32, mode: RoundingMode) -> Self {
self.log10_strict_with(mode)
}
}
};
}
#[cfg(any(feature = "d57", feature = "wide"))]
impl_wide_ln!(D57, ln::wide_kernel::ln_strict_d57);
#[cfg(any(feature = "d76", feature = "wide"))]
impl_wide_ln!(D76, ln::wide_kernel::ln_strict_d76);
#[cfg(any(feature = "d115", feature = "wide"))]
impl_wide_ln!(D115, ln::wide_kernel::ln_strict_d115);
#[cfg(any(feature = "d153", feature = "wide"))]
impl_wide_ln!(D153, ln::wide_kernel::ln_strict_d153);
#[cfg(any(feature = "d230", feature = "wide"))]
impl_wide_ln!(D230, ln::wide_kernel::ln_strict_d230);
#[cfg(any(feature = "d307", feature = "wide", feature = "x-wide"))]
impl_wide_ln!(D307, ln::wide_kernel::ln_strict_d307);
#[cfg(any(feature = "d462", feature = "x-wide"))]
impl_wide_ln!(D462, ln::wide_kernel::ln_strict_d462);
#[cfg(any(feature = "d616", feature = "x-wide"))]
impl_wide_ln!(D616, ln::wide_kernel::ln_strict_d616);
#[cfg(any(feature = "d924", feature = "xx-wide"))]
impl_wide_ln!(D924, ln::wide_kernel::ln_strict_d924);
#[cfg(any(feature = "d1232", feature = "xx-wide"))]
impl_wide_ln!(D1232, ln::wide_kernel::ln_strict_d1232);