use crate::support::rounding::RoundingMode;
macro_rules! decl_trig_kernel {
(
$sin_name:ident,
$cos_name:ident,
$tan_name:ident,
$atan_name:ident,
$Storage:ty,
$core_path:path,
$tier_label:literal
) => {
#[inline]
#[must_use]
pub(crate) fn $sin_name(raw: $Storage, mode: RoundingMode, scale: u32) -> $Storage {
use $core_path as core;
core::round_to_storage_directed(core::GUARD, scale, mode, |guard| {
core::sin_fixed(core::to_work_w(raw, guard), scale + guard)
})
}
#[inline]
#[must_use]
pub(crate) fn $cos_name(raw: $Storage, mode: RoundingMode, scale: u32) -> $Storage {
use $core_path as core;
core::round_to_storage_directed(core::GUARD, scale, mode, |guard| {
core::cos_fixed(core::to_work_w(raw, guard), scale + guard)
})
}
#[inline]
#[must_use]
pub(crate) fn $tan_name(raw: $Storage, mode: RoundingMode, scale: u32) -> $Storage {
use $core_path as core;
let w0 = scale + core::GUARD;
let (sin0, cos0) = core::sin_cos_fixed(core::to_work(raw), w0);
if cos0 == core::zero() {
panic!(concat!(
$tier_label,
"::tan: cosine is zero (argument is an odd multiple of pi/2)"
));
}
let probe = core::div(sin0, cos0, w0);
let extra = crate::algos::trig::near_pole_tan::tan_extra_digits(
core::bit_length(probe),
w0,
)
.saturating_sub(core::GUARD);
if extra == 0 {
return core::round_to_storage_with(probe, w0, scale, mode);
}
let w = w0 + extra;
let (sin_w, cos_w) = core::sin_cos_fixed(core::to_work_w(raw, core::GUARD + extra), w);
let r = core::div(sin_w, cos_w, w);
core::round_to_storage_with(r, w, scale, mode)
}
#[inline]
#[must_use]
pub(crate) fn $atan_name(raw: $Storage, mode: RoundingMode, scale: u32) -> $Storage {
use $core_path as core;
core::round_to_storage_directed(core::GUARD, scale, mode, |guard| {
core::atan_fixed(core::to_work_w(raw, guard), scale + guard)
})
}
};
}
#[cfg(any(feature = "d57", feature = "wide"))]
decl_trig_kernel!(
sin_strict_d57,
cos_strict_d57,
tan_strict_d57,
atan_strict_d57,
crate::wide_int::I192,
crate::types::widths::wide_trig_d57,
"D57"
);
#[cfg(any(feature = "d76", feature = "wide"))]
decl_trig_kernel!(
sin_strict_d76,
cos_strict_d76,
tan_strict_d76,
atan_strict_d76,
crate::wide_int::I256,
crate::types::widths::wide_trig_d76,
"D76"
);
#[cfg(any(feature = "d115", feature = "wide"))]
decl_trig_kernel!(
sin_strict_d115,
cos_strict_d115,
tan_strict_d115,
atan_strict_d115,
crate::wide_int::I384,
crate::types::widths::wide_trig_d115,
"D115"
);
#[cfg(any(feature = "d153", feature = "wide"))]
decl_trig_kernel!(
sin_strict_d153,
cos_strict_d153,
tan_strict_d153,
atan_strict_d153,
crate::wide_int::I512,
crate::types::widths::wide_trig_d153,
"D153"
);
#[cfg(any(feature = "d230", feature = "wide"))]
decl_trig_kernel!(
sin_strict_d230,
cos_strict_d230,
tan_strict_d230,
atan_strict_d230,
crate::wide_int::I768,
crate::types::widths::wide_trig_d230,
"D230"
);
#[cfg(any(feature = "d307", feature = "wide", feature = "x-wide"))]
decl_trig_kernel!(
sin_strict_d307,
cos_strict_d307,
tan_strict_d307,
atan_strict_d307,
crate::wide_int::I1024,
crate::types::widths::wide_trig_d307,
"D307"
);
#[cfg(any(feature = "d462", feature = "x-wide"))]
decl_trig_kernel!(
sin_strict_d462,
cos_strict_d462,
tan_strict_d462,
atan_strict_d462,
crate::wide_int::I1536,
crate::types::widths::wide_trig_d462,
"D462"
);
#[cfg(any(feature = "d616", feature = "x-wide"))]
decl_trig_kernel!(
sin_strict_d616,
cos_strict_d616,
tan_strict_d616,
atan_strict_d616,
crate::wide_int::I2048,
crate::types::widths::wide_trig_d616,
"D616"
);
#[cfg(any(feature = "d924", feature = "xx-wide"))]
decl_trig_kernel!(
sin_strict_d924,
cos_strict_d924,
tan_strict_d924,
atan_strict_d924,
crate::wide_int::I3072,
crate::types::widths::wide_trig_d924,
"D924"
);
#[cfg(any(feature = "d1232", feature = "xx-wide"))]
decl_trig_kernel!(
sin_strict_d1232,
cos_strict_d1232,
tan_strict_d1232,
atan_strict_d1232,
crate::wide_int::I4096,
crate::types::widths::wide_trig_d1232,
"D1232"
);