use crate::types::widths::{D38, D57};
use crate::support::rounding::RoundingMode;
use crate::wide_int::I192;
#[inline]
fn narrow<const SCALE: u32>(raw_wide: I192, op: &'static str) -> i128 {
let wide = D57::<SCALE>::from_bits(raw_wide);
let r: D38<SCALE> = wide.try_into().unwrap_or_else(|_| panic!(
"{op}: result out of range — produced {wide}, D38<{SCALE}> represents only |x| < 1.7e{}",
38_i32 - SCALE as i32,
));
r.0
}
#[inline]
#[must_use]
pub(crate) fn sin_strict<const SCALE: u32>(raw: i128, mode: RoundingMode) -> i128 {
let widened: D57<SCALE> = D38::<SCALE>::from_bits(raw).into();
let raw_wide = super::wide_kernel::sin_strict_d57(widened.0, mode, SCALE);
narrow::<SCALE>(raw_wide, "sin_strict")
}
#[inline]
#[must_use]
pub(crate) fn cos_strict<const SCALE: u32>(raw: i128, mode: RoundingMode) -> i128 {
let widened: D57<SCALE> = D38::<SCALE>::from_bits(raw).into();
let raw_wide = super::wide_kernel::cos_strict_d57(widened.0, mode, SCALE);
narrow::<SCALE>(raw_wide, "cos_strict")
}
#[inline]
#[must_use]
pub(crate) fn tan_strict<const SCALE: u32>(raw: i128, mode: RoundingMode) -> i128 {
let widened: D57<SCALE> = D38::<SCALE>::from_bits(raw).into();
let raw_wide = super::wide_kernel::tan_strict_d57(widened.0, mode, SCALE);
narrow::<SCALE>(raw_wide, "tan_strict")
}
#[inline]
#[must_use]
pub(crate) fn atan_strict<const SCALE: u32>(raw: i128, mode: RoundingMode) -> i128 {
let widened: D57<SCALE> = D38::<SCALE>::from_bits(raw).into();
let raw_wide = super::wide_kernel::atan_strict_d57(widened.0, mode, SCALE);
narrow::<SCALE>(raw_wide, "atan_strict")
}
#[inline]
#[must_use]
pub(crate) fn asin_strict<const SCALE: u32>(raw: i128, mode: RoundingMode) -> i128 {
let widened: D57<SCALE> = D38::<SCALE>::from_bits(raw).into();
let result = widened.asin_strict_with(mode);
narrow::<SCALE>(result.0, "asin_strict")
}
#[inline]
#[must_use]
pub(crate) fn acos_strict<const SCALE: u32>(raw: i128, mode: RoundingMode) -> i128 {
let widened: D57<SCALE> = D38::<SCALE>::from_bits(raw).into();
let result = widened.acos_strict_with(mode);
narrow::<SCALE>(result.0, "acos_strict")
}
#[inline]
#[must_use]
pub(crate) fn atan2_strict<const SCALE: u32>(y_raw: i128, x_raw: i128, mode: RoundingMode) -> i128 {
let y_wide: D57<SCALE> = D38::<SCALE>::from_bits(y_raw).into();
let x_wide: D57<SCALE> = D38::<SCALE>::from_bits(x_raw).into();
let result = y_wide.atan2_strict_with(x_wide, mode);
narrow::<SCALE>(result.0, "atan2_strict")
}