about summary refs log tree commit diff
path: root/library/compiler-builtins/builtins-test/tests/float_pow.rs
blob: a17dff27c105a0e880b4e59a830ad0a5fcaf19b2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#![allow(unused_macros)]
#![cfg_attr(f128_enabled, feature(f128))]

#[cfg_attr(x86_no_sse, allow(unused))]
use builtins_test::*;

// This is approximate because of issues related to
// https://github.com/rust-lang/rust/issues/73920.
// TODO how do we resolve this indeterminacy?
macro_rules! pow {
    ($($f:ty, $tolerance:expr, $fn:ident, $sys_available:meta);*;) => {
        $(
            #[test]
            // FIXME(apfloat): We skip tests if system symbols aren't available rather
            // than providing a fallback, since `rustc_apfloat` does not provide `pow`.
            #[cfg($sys_available)]
            fn $fn() {
                use compiler_builtins::float::pow::$fn;
                use compiler_builtins::float::Float;
                fuzz_float_2(N, |x: $f, y: $f| {
                    if !(Float::is_subnormal(x) || Float::is_subnormal(y) || x.is_nan()) {
                        let n = y.to_bits() & !<$f as Float>::SIG_MASK;
                        let n = (n as <$f as Float>::SignedInt) >> <$f as Float>::SIG_BITS;
                        let n = n as i32;
                        let tmp0: $f = x.powi(n);
                        let tmp1: $f = $fn(x, n);
                        let (a, b) = if tmp0 < tmp1 {
                            (tmp0, tmp1)
                        } else {
                            (tmp1, tmp0)
                        };

                        let good = if a == b {
                            // handles infinity equality
                            true
                        } else if a < $tolerance {
                            b < $tolerance
                        } else {
                            let quo = b / a;
                            (quo < (1. + $tolerance)) && (quo > (1. - $tolerance))
                        };

                        assert!(
                            good,
                            "{}({:?}, {:?}): std: {:?}, builtins: {:?}",
                            stringify!($fn), x, n, tmp0, tmp1
                        );
                    }
                });
            }
        )*
    };
}

#[cfg(not(x86_no_sse))] // FIXME(i586): failure for powidf2
pow! {
    f32, 1e-4, __powisf2, all();
    f64, 1e-12, __powidf2, all();
}

#[cfg(f128_enabled)]
#[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))]
pow! {
    f128, 1e-36, __powitf2, not(feature = "no-sys-f128");
}

#[cfg(f128_enabled)]
#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
pow! {
    f128, 1e-36, __powikf2, not(feature = "no-sys-f128");
}