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);
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<const SCALE: u32> LnPolicy for crate::types::widths::D57<SCALE> {
#[inline]
fn ln_impl(self, mode: RoundingMode) -> Self {
if matches!(SCALE, 18..=22) {
return Self(ln::lookup_d57_s18_22_tang::ln_strict::<SCALE>(self.0, mode));
}
Self(ln::wide_kernel::ln_strict_d57(self.0, mode, SCALE))
}
#[inline]
fn ln_with_impl(self, _working_digits: u32, mode: RoundingMode) -> Self {
if matches!(SCALE, 18..=22) {
return Self(ln::lookup_d57_s18_22_tang::ln_strict::<SCALE>(self.0, mode));
}
Self(ln::wide_kernel::ln_strict_d57(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 = "d76", feature = "wide"))]
impl_wide_ln!(D76, ln::wide_kernel::ln_strict_d76);
#[cfg(any(feature = "d115", feature = "wide"))]
impl<const SCALE: u32> LnPolicy for crate::types::widths::D115<SCALE> {
#[inline]
fn ln_impl(self, mode: RoundingMode) -> Self {
if matches!(SCALE, 50..=60) {
return Self(ln::lookup_d115_s57_tang::ln_strict::<SCALE>(self.0, mode));
}
Self(ln::wide_kernel::ln_strict_d115(self.0, mode, SCALE))
}
#[inline]
fn ln_with_impl(self, _working_digits: u32, mode: RoundingMode) -> Self {
if matches!(SCALE, 50..=60) {
return Self(ln::lookup_d115_s57_tang::ln_strict::<SCALE>(self.0, mode));
}
Self(ln::wide_kernel::ln_strict_d115(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 = "d153", feature = "wide"))]
impl<const SCALE: u32> LnPolicy for crate::types::widths::D153<SCALE> {
#[inline]
fn ln_impl(self, mode: RoundingMode) -> Self {
if matches!(SCALE, 70..=82) {
return Self(ln::lookup_d153_s70_82_tang::ln_strict::<SCALE>(self.0, mode));
}
Self(ln::wide_kernel::ln_strict_d153(self.0, mode, SCALE))
}
#[inline]
fn ln_with_impl(self, _working_digits: u32, mode: RoundingMode) -> Self {
if matches!(SCALE, 70..=82) {
return Self(ln::lookup_d153_s70_82_tang::ln_strict::<SCALE>(self.0, mode));
}
Self(ln::wide_kernel::ln_strict_d153(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 = "d230", feature = "wide"))]
impl_wide_ln!(D230, ln::wide_kernel::ln_strict_d230);
#[cfg(any(feature = "d307", feature = "wide", feature = "x-wide"))]
impl<const SCALE: u32> LnPolicy for crate::types::widths::D307<SCALE> {
#[inline]
fn ln_impl(self, mode: RoundingMode) -> Self {
if matches!(SCALE, 140..=160) {
return Self(ln::lookup_d307_s140_160_tang::ln_strict::<SCALE>(self.0, mode));
}
Self(ln::wide_kernel::ln_strict_d307(self.0, mode, SCALE))
}
#[inline]
fn ln_with_impl(self, _working_digits: u32, mode: RoundingMode) -> Self {
if matches!(SCALE, 140..=160) {
return Self(ln::lookup_d307_s140_160_tang::ln_strict::<SCALE>(self.0, mode));
}
Self(ln::wide_kernel::ln_strict_d307(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 = "d462", feature = "x-wide"))]
impl<const SCALE: u32> LnPolicy for crate::types::widths::D462<SCALE> {
#[inline]
fn ln_impl(self, mode: RoundingMode) -> Self {
if matches!(SCALE, 225..=235) {
return Self(ln::lookup_d462_s225_235_tang::ln_strict::<SCALE>(self.0, mode));
}
Self(ln::wide_kernel::ln_strict_d462(self.0, mode, SCALE))
}
#[inline]
fn ln_with_impl(self, _working_digits: u32, mode: RoundingMode) -> Self {
if matches!(SCALE, 225..=235) {
return Self(ln::lookup_d462_s225_235_tang::ln_strict::<SCALE>(self.0, mode));
}
Self(ln::wide_kernel::ln_strict_d462(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 = "d616", feature = "x-wide"))]
impl<const SCALE: u32> LnPolicy for crate::types::widths::D616<SCALE> {
#[inline]
fn ln_impl(self, mode: RoundingMode) -> Self {
if matches!(SCALE, 300..=315) {
return Self(ln::lookup_d616_s300_315_tang::ln_strict::<SCALE>(self.0, mode));
}
Self(ln::wide_kernel::ln_strict_d616(self.0, mode, SCALE))
}
#[inline]
fn ln_with_impl(self, _working_digits: u32, mode: RoundingMode) -> Self {
if matches!(SCALE, 300..=315) {
return Self(ln::lookup_d616_s300_315_tang::ln_strict::<SCALE>(self.0, mode));
}
Self(ln::wide_kernel::ln_strict_d616(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 = "d924", feature = "xx-wide"))]
impl<const SCALE: u32> LnPolicy for crate::types::widths::D924<SCALE> {
#[inline]
fn ln_impl(self, mode: RoundingMode) -> Self {
if matches!(SCALE, 455..=465) {
return Self(ln::lookup_d924_s455_465_tang::ln_strict::<SCALE>(self.0, mode));
}
Self(ln::wide_kernel::ln_strict_d924(self.0, mode, SCALE))
}
#[inline]
fn ln_with_impl(self, _working_digits: u32, mode: RoundingMode) -> Self {
if matches!(SCALE, 455..=465) {
return Self(ln::lookup_d924_s455_465_tang::ln_strict::<SCALE>(self.0, mode));
}
Self(ln::wide_kernel::ln_strict_d924(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 = "d1232", feature = "xx-wide"))]
impl<const SCALE: u32> LnPolicy for crate::types::widths::D1232<SCALE> {
#[inline]
fn ln_impl(self, mode: RoundingMode) -> Self {
if matches!(SCALE, 610..=620) {
return Self(ln::lookup_d1232_s610_620_tang::ln_strict::<SCALE>(self.0, mode));
}
Self(ln::wide_kernel::ln_strict_d1232(self.0, mode, SCALE))
}
#[inline]
fn ln_with_impl(self, _working_digits: u32, mode: RoundingMode) -> Self {
if matches!(SCALE, 610..=620) {
return Self(ln::lookup_d1232_s610_620_tang::ln_strict::<SCALE>(self.0, mode));
}
Self(ln::wide_kernel::ln_strict_d1232(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)
}
}