// origin: FreeBSD /usr/src/lib/msun/src/e_rem_pio2.c // // ==================================================== // Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. // // Developed at SunPro, a Sun Microsystems, Inc. business. // Permission to use, copy, modify, and distribute this // software is freely granted, provided that this notice // is preserved. // ==================================================== // // Optimized by Bruce D. Evans. */ usesuper::rem_pio2_large;
// return the remainder of x rem pi/2 in y[0]+y[1] // use rem_pio2_large() for large x // // caller must handle the case when reduction is not needed: |x| ~<= pi/4 */ #[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] pub(crate) fn rem_pio2(x: f64) -> (i32, f64, f64) { let x1p24 = f64::from_bits(0x4170000000000000);
let sign = (f64::to_bits(x) >> 63) as i32; let ix = (f64::to_bits(x) >> 32) as u32 & 0x7fffffff;
fn medium(x: f64, ix: u32) -> (i32, f64, f64) { /* rint(x/(pi/2)), Assume round-to-nearest. */ let tmp = x as f64 * INV_PIO2 + TO_INT; // force rounding of tmp to it's storage format on x87 to avoid // excess precision issues. #[cfg(all(target_arch = "x86", not(target_feature = "sse2")))] let tmp = force_eval!(tmp); let f_n = tmp - TO_INT; let n = f_n as i32; letmut r = x - f_n * PIO2_1; letmut w = f_n * PIO2_1T; /* 1st round, good to 85 bits */ letmut y0 = r - w; let ui = f64::to_bits(y0); let ey = (ui >> 52) as i32 & 0x7ff; let ex = (ix >> 20) as i32; if ex - ey > 16 { /* 2nd round, good to 118 bits */ let t = r;
w = f_n * PIO2_2;
r = t - w;
w = f_n * PIO2_2T - ((t - r) - w);
y0 = r - w; let ey = (f64::to_bits(y0) >> 52) as i32 & 0x7ff; if ex - ey > 49 { /* 3rd round, good to 151 bits, covers all cases */ let t = r;
w = f_n * PIO2_3;
r = t - w;
w = f_n * PIO2_3T - ((t - r) - w);
y0 = r - w;
}
} let y1 = (r - y0) - w;
(n, y0, y1)
}
if ix <= 0x400f6a7a { /* |x| ~<= 5pi/4 */ if (ix & 0xfffff) == 0x921fb { /* |x| ~= pi/2 or 2pi/2 */ return medium(x, ix); /* cancellation -- use medium case */
} if ix <= 0x4002d97c { /* |x| ~<= 3pi/4 */ if sign == 0 { let z = x - PIO2_1; /* one round good to 85 bits */ let y0 = z - PIO2_1T; let y1 = (z - y0) - PIO2_1T; return (1, y0, y1);
} else { let z = x + PIO2_1; let y0 = z + PIO2_1T; let y1 = (z - y0) + PIO2_1T; return (-1, y0, y1);
}
} elseif sign == 0 { let z = x - 2.0 * PIO2_1; let y0 = z - 2.0 * PIO2_1T; let y1 = (z - y0) - 2.0 * PIO2_1T; return (2, y0, y1);
} else { let z = x + 2.0 * PIO2_1; let y0 = z + 2.0 * PIO2_1T; let y1 = (z - y0) + 2.0 * PIO2_1T; return (-2, y0, y1);
}
} if ix <= 0x401c463b { /* |x| ~<= 9pi/4 */ if ix <= 0x4015fdbc { /* |x| ~<= 7pi/4 */ if ix == 0x4012d97c { /* |x| ~= 3pi/2 */ return medium(x, ix);
} if sign == 0 { let z = x - 3.0 * PIO2_1; let y0 = z - 3.0 * PIO2_1T; let y1 = (z - y0) - 3.0 * PIO2_1T; return (3, y0, y1);
} else { let z = x + 3.0 * PIO2_1; let y0 = z + 3.0 * PIO2_1T; let y1 = (z - y0) + 3.0 * PIO2_1T; return (-3, y0, y1);
}
} else { if ix == 0x401921fb { /* |x| ~= 4pi/2 */ return medium(x, ix);
} if sign == 0 { let z = x - 4.0 * PIO2_1; let y0 = z - 4.0 * PIO2_1T; let y1 = (z - y0) - 4.0 * PIO2_1T; return (4, y0, y1);
} else { let z = x + 4.0 * PIO2_1; let y0 = z + 4.0 * PIO2_1T; let y1 = (z - y0) + 4.0 * PIO2_1T; return (-4, y0, y1);
}
}
} if ix < 0x413921fb { /* |x| ~< 2^20*(pi/2), medium size */ return medium(x, ix);
} /* *allother(large)arguments
*/ if ix >= 0x7ff00000 { /* x is inf or NaN */ let y0 = x - x; let y1 = y0; return (0, y0, y1);
} /* set z = scalbn(|x|,-ilogb(x)+23) */ letmut ui = f64::to_bits(x);
ui &= (!1) >> 12;
ui |= (0x3ff + 23) << 52; letmut z = f64::from_bits(ui); letmut tx = [0.0; 3]; for i in0..2 {
i!(tx,i, =, z as i32 as f64);
z = (z - i!(tx, i)) * x1p24;
}
i!(tx,2, =, z); /* skip zero terms, first term is non-zero */ letmut i = 2; while i != 0 && i!(tx, i) == 0.0 {
i -= 1;
} letmut ty = [0.0; 3]; let n = rem_pio2_large(&tx[..=i], &mut ty, ((ix as i32) >> 20) - (0x3ff + 23), 1); if sign != 0 { return (-n, -i!(ty, 0), -i!(ty, 1));
}
(n, i!(ty, 0), i!(ty, 1))
}
#[cfg(test)] mod tests { usesuper::rem_pio2;
#[test] fn test_near_pi() { let arg = 3.141592025756836; let arg = force_eval!(arg);
assert_eq!(
rem_pio2(arg),
(2, -6.278329573009626e-7, -2.1125998133974653e-23)
); let arg = 3.141592033207416; let arg = force_eval!(arg);
assert_eq!(
rem_pio2(arg),
(2, -6.20382377148128e-7, -2.1125998133974653e-23)
); let arg = 3.141592144966125; let arg = force_eval!(arg);
assert_eq!(
rem_pio2(arg),
(2, -5.086236681942706e-7, -2.1125998133974653e-23)
); let arg = 3.141592979431152; let arg = force_eval!(arg);
assert_eq!(
rem_pio2(arg),
(2, 3.2584135866119817e-7, -2.1125998133974653e-23)
);
}
#[test] fn test_overflow_b9b847() { let _ = rem_pio2(-3054214.5490637687);
}
#[test] fn test_overflow_4747b9() { let _ = rem_pio2(917340800458.2274);
}
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.19 Sekunden
(vorverarbeitet am 2026-06-21)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.