#![cfg(any(feature = "d153", feature = "wide"))]
use crate::types::widths::wide_trig_d153 as core;
use crate::support::rounding::RoundingMode;
use crate::wide_int::Int512;
const GUARD_NARROW: u32 = 10;
#[derive(Copy, Clone)]
pub(crate) enum Which {
Sin,
Cos,
}
#[inline]
#[must_use]
pub(crate) fn sin_cos_strict<const SCALE: u32>(
raw: Int512,
mode: RoundingMode,
which: Which,
) -> Int512 {
if raw == Int512::ZERO {
return match which {
Which::Sin => Int512::ZERO,
Which::Cos => {
let ten: Int512 = crate::wide_int::wide_cast::<u128, Int512>(10);
ten.pow(SCALE)
}
};
}
let w = SCALE + GUARD_NARROW;
let v_w = core::to_work_w(raw, GUARD_NARROW);
let result = match which {
Which::Sin => core::sin_fixed(v_w, w),
Which::Cos => core::cos_fixed(v_w, w),
};
core::round_to_storage_with(result, w, SCALE, mode)
}
#[inline]
#[must_use]
pub(crate) fn sin_strict<const SCALE: u32>(raw: Int512, mode: RoundingMode) -> Int512 {
sin_cos_strict::<SCALE>(raw, mode, Which::Sin)
}
#[inline]
#[must_use]
pub(crate) fn cos_strict<const SCALE: u32>(raw: Int512, mode: RoundingMode) -> Int512 {
sin_cos_strict::<SCALE>(raw, mode, Which::Cos)
}
#[inline]
#[must_use]
pub(crate) fn tan_strict<const SCALE: u32>(raw: Int512, mode: RoundingMode) -> Int512 {
if raw == Int512::ZERO {
return Int512::ZERO;
}
let w = SCALE + GUARD_NARROW;
let v_w = core::to_work_w(raw, GUARD_NARROW);
let (sin_w, cos_w) = core::sin_cos_fixed(v_w, w);
if cos_w == core::zero() {
panic!("D153::tan: cosine is zero (argument is an odd multiple of pi/2)");
}
let r = core::div(sin_w, cos_w, w);
core::round_to_storage_with(r, w, SCALE, mode)
}