|
| 1 | +#![allow(unused_macros)] |
| 2 | +#![cfg_attr(f128_enabled, feature(f128))] |
| 3 | +#![cfg(not(all(target_arch = "x86", not(target_feature = "sse"))))] |
| 4 | + |
| 5 | +use testcrate::*; |
| 6 | + |
| 7 | +// This is approximate because of issues related to |
| 8 | +// https://github.com/rust-lang/rust/issues/73920. |
| 9 | +// TODO how do we resolve this indeterminacy? |
| 10 | +macro_rules! pow { |
| 11 | + ($($f:ty, $tolerance:expr, $fn:ident, $sys_available:meta);*;) => { |
| 12 | + $( |
| 13 | + #[test] |
| 14 | + // FIXME(apfloat): We skip tests if system symbols aren't available rather |
| 15 | + // than providing a fallback, since `rustc_apfloat` does not provide `pow`. |
| 16 | + #[cfg($sys_available)] |
| 17 | + fn $fn() { |
| 18 | + use compiler_builtins::float::pow::$fn; |
| 19 | + use compiler_builtins::float::Float; |
| 20 | + fuzz_float_2(N, |x: $f, y: $f| { |
| 21 | + if !(Float::is_subnormal(x) || Float::is_subnormal(y) || x.is_nan()) { |
| 22 | + let n = y.to_bits() & !<$f as Float>::SIGNIFICAND_MASK; |
| 23 | + let n = (n as <$f as Float>::SignedInt) >> <$f as Float>::SIGNIFICAND_BITS; |
| 24 | + let n = n as i32; |
| 25 | + let tmp0: $f = x.powi(n); |
| 26 | + let tmp1: $f = $fn(x, n); |
| 27 | + let (a, b) = if tmp0 < tmp1 { |
| 28 | + (tmp0, tmp1) |
| 29 | + } else { |
| 30 | + (tmp1, tmp0) |
| 31 | + }; |
| 32 | + |
| 33 | + let good = if a == b { |
| 34 | + // handles infinity equality |
| 35 | + true |
| 36 | + } else if a < $tolerance { |
| 37 | + b < $tolerance |
| 38 | + } else { |
| 39 | + let quo = b / a; |
| 40 | + (quo < (1. + $tolerance)) && (quo > (1. - $tolerance)) |
| 41 | + }; |
| 42 | + |
| 43 | + assert!( |
| 44 | + good, |
| 45 | + "{}({:?}, {:?}): std: {:?}, builtins: {:?}", |
| 46 | + stringify!($fn), x, n, tmp0, tmp1 |
| 47 | + ); |
| 48 | + } |
| 49 | + }); |
| 50 | + } |
| 51 | + )* |
| 52 | + }; |
| 53 | +} |
| 54 | + |
| 55 | +pow! { |
| 56 | + f32, 1e-4, __powisf2, all(); |
| 57 | + f64, 1e-12, __powidf2, all(); |
| 58 | +} |
| 59 | + |
| 60 | +#[cfg(f128_enabled)] |
| 61 | +// FIXME(f16_f128): MSVC cannot build these until `__divtf3` is available in nightly. |
| 62 | +#[cfg(not(target_env = "msvc"))] |
| 63 | +#[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))] |
| 64 | +pow! { |
| 65 | + f128, 1e-36, __powitf2, not(feature = "no-sys-f128"); |
| 66 | +} |
| 67 | + |
| 68 | +#[cfg(f128_enabled)] |
| 69 | +#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))] |
| 70 | +pow! { |
| 71 | + f128, 1e-36, __powikf2, not(feature = "no-sys-f128"); |
| 72 | +} |
0 commit comments