use super::{F64Like, LikeF64};
use crate::generic::scalbn_medium;
use crate::traits::FloatConsts;
const FRAC_PI_2_HI: u64 = 0x3FF921FB54400000; const FRAC_PI_2_HIEX: u64 = 0x3DD0B4611A626331; const FRAC_PI_2_MI: u64 = 0x3DD0B4611A600000; const FRAC_PI_2_MIEX: u64 = 0x3BA3198A2E037073; const FRAC_PI_2_LO: u64 = 0x3BA3198A2E000000; const FRAC_PI_2_LOEX: u64 = 0x397B839A252049C1;
impl<F: F64Like + FloatConsts> crate::generic::ReducePi2<LikeF64> for F {
#[inline]
fn frac_pi_2_hi() -> Self {
Self::from_raw(FRAC_PI_2_HI)
}
#[inline]
fn frac_pi_2_hiex() -> Self {
Self::from_raw(FRAC_PI_2_HIEX)
}
#[inline]
fn frac_pi_2_mi() -> Self {
Self::from_raw(FRAC_PI_2_MI)
}
#[inline]
fn frac_pi_2_miex() -> Self {
Self::from_raw(FRAC_PI_2_MIEX)
}
#[inline]
fn frac_pi_2_lo() -> Self {
Self::from_raw(FRAC_PI_2_LO)
}
#[inline]
fn frac_pi_2_loex() -> Self {
Self::from_raw(FRAC_PI_2_LOEX)
}
fn max_reduce_pi_2_medium() -> Self {
Self::cast_from((1u64 << 20) - 1) * Self::frac_pi_2()
}
const REDUCE_PI_2_MEDIUM_TH1: i16 = 16;
const REDUCE_PI_2_MEDIUM_TH2: i16 = 49;
type SrcChunks = [u32; 3];
fn reduce_pi_2_prepare(x: Self) -> ([u32; 3], i16, usize) {
let mant = x.mant();
let x_chunks = [
((mant >> 29) as u32),
(((mant >> 5) & 0x00FF_FFFF) as u32),
(((mant << 19) & 0x00FF_FFFF) as u32),
];
let e0 = x.exponent() - 23;
let jk = 4;
(x_chunks, e0, jk)
}
fn reduce_pi_2_compress(qp: &[u64; 20], qe: i16, ih: u32, jz: usize) -> (Self, Self) {
let mut iw = 0;
for &qp_i in qp[0..=jz].iter().rev() {
iw = (iw >> 24) + (u128::from(qp_i) << 48);
}
let fw0 = Self::cast_from((iw as u64) & 0xFFFF_FFFF_FFFF);
let fw1 = Self::cast_from(((iw >> 48) as u64) & 0xFFFF_FFFF_FFFF) * Self::exp2i_fast(48);
let fw2 = Self::cast_from((iw >> 96) as u64) * Self::exp2i_fast(96);
let mut y0 = ((fw0 + fw1) + fw2).purify();
let mut y1 = ((fw2 - y0) + fw1) + fw0;
let scale = i32::from(qe) - 48;
y0 = scalbn_medium(y0, scale);
y1 = scalbn_medium(y1, scale);
if ih == 0 {
(y0, y1)
} else {
(-y0, -y1)
}
}
}