compiler_builtins/math/
mod.rs

1#[rustfmt::skip]
2#[allow(dead_code)]
3#[allow(unused_imports)]
4#[allow(clippy::all)]
5pub(crate) mod libm_math;
6
7macro_rules! libm_intrinsics {
8    ($(fn $fun:ident($($iid:ident : $ity:ty),+) -> $oty:ty;)+) => {
9        intrinsics! {
10            $(
11                pub extern "C" fn $fun($($iid: $ity),+) -> $oty {
12                    $crate::math::libm_math::$fun($($iid),+)
13                }
14            )+
15        }
16    }
17}
18
19/// This set of functions is well tested in `libm` and known to provide similar performance to
20/// system `libm`, as well as the same or better accuracy.
21pub mod full_availability {
22    #[cfg(f16_enabled)]
23    libm_intrinsics! {
24        fn ceilf16(x: f16) -> f16;
25        fn copysignf16(x: f16, y: f16) -> f16;
26        fn fabsf16(x: f16) -> f16;
27        fn fdimf16(x: f16, y: f16) -> f16;
28        fn floorf16(x: f16) -> f16;
29        fn fmaxf16(x: f16, y: f16) -> f16;
30        fn fmaximumf16(x: f16, y: f16) -> f16;
31        fn fminf16(x: f16, y: f16) -> f16;
32        fn fminimumf16(x: f16, y: f16) -> f16;
33        fn fmodf16(x: f16, y: f16) -> f16;
34        fn rintf16(x: f16) -> f16;
35        fn roundevenf16(x: f16) -> f16;
36        fn roundf16(x: f16) -> f16;
37        fn sqrtf16(x: f16) -> f16;
38        fn truncf16(x: f16) -> f16;
39    }
40
41    /* Weak linkage is unreliable on Windows and Apple, so we don't expose symbols that we know
42     * the system libc provides in order to avoid conflicts. */
43
44    #[cfg(all(not(windows), not(target_vendor = "apple")))]
45    libm_intrinsics! {
46        /* f32 */
47        fn cbrtf(n: f32) -> f32;
48        fn ceilf(x: f32) -> f32;
49        fn copysignf(x: f32, y: f32) -> f32;
50        fn fabsf(x: f32) -> f32;
51        fn fdimf(a: f32, b: f32) -> f32;
52        fn floorf(x: f32) -> f32;
53        fn fmaf(x: f32, y: f32, z: f32) -> f32;
54        fn fmaxf(x: f32, y: f32) -> f32;
55        fn fminf(x: f32, y: f32) -> f32;
56        fn fmodf(x: f32, y: f32) -> f32;
57        fn rintf(x: f32) -> f32;
58        fn roundf(x: f32) -> f32;
59        fn sqrtf(x: f32) -> f32;
60        fn truncf(x: f32) -> f32;
61
62        /* f64 */
63        fn cbrt(x: f64) -> f64;
64        fn ceil(x: f64) -> f64;
65        fn copysign(x: f64, y: f64) -> f64;
66        fn fabs(x: f64) -> f64;
67        fn fdim(a: f64, b: f64) -> f64;
68        fn floor(x: f64) -> f64;
69        fn fma(x: f64, y: f64, z: f64) -> f64;
70        fn fmax(x: f64, y: f64) -> f64;
71        fn fmin(x: f64, y: f64) -> f64;
72        fn fmod(x: f64, y: f64) -> f64;
73        fn rint(x: f64) -> f64;
74        fn round(x: f64) -> f64;
75        fn sqrt(x: f64) -> f64;
76        fn trunc(x: f64) -> f64;
77    }
78
79    // Windows and MacOS do not yet expose roundeven and IEEE 754-2019 `maximum` / `minimum`,
80    // however, so we still provide a fallback.
81    libm_intrinsics! {
82        fn fmaximum(x: f64, y: f64) -> f64;
83        fn fmaximumf(x: f32, y: f32) -> f32;
84        fn fminimum(x: f64, y: f64) -> f64;
85        fn fminimumf(x: f32, y: f32) -> f32;
86        fn roundeven(x: f64) -> f64;
87        fn roundevenf(x: f32) -> f32;
88    }
89
90    #[cfg(f128_enabled)]
91    libm_intrinsics! {
92        fn ceilf128(x: f128) -> f128;
93        fn copysignf128(x: f128, y: f128) -> f128;
94        fn fabsf128(x: f128) -> f128;
95        fn fdimf128(x: f128, y: f128) -> f128;
96        fn floorf128(x: f128) -> f128;
97        fn fmaf128(x: f128, y: f128, z: f128) -> f128;
98        fn fmaxf128(x: f128, y: f128) -> f128;
99        fn fmaximumf128(x: f128, y: f128) -> f128;
100        fn fminf128(x: f128, y: f128) -> f128;
101        fn fminimumf128(x: f128, y: f128) -> f128;
102        fn fmodf128(x: f128, y: f128) -> f128;
103        fn rintf128(x: f128) -> f128;
104        fn roundevenf128(x: f128) -> f128;
105        fn roundf128(x: f128) -> f128;
106        fn sqrtf128(x: f128) -> f128;
107        fn truncf128(x: f128) -> f128;
108    }
109}
110
111/// This group of functions has more performance or precision issues than system versions, or
112/// are otherwise less well tested. Provide them only on platforms that have problems with the
113/// system `libm`.
114///
115/// As `libm` improves, more functions will be moved from this group to the first group.
116///
117/// Do not supply for any of the following:
118/// - x86 without sse2 due to ABI issues
119///   - <https://github.com/rust-lang/rust/issues/114479>
120///   - but exclude UEFI since it is a soft-float target
121///     - <https://github.com/rust-lang/rust/issues/128533>
122/// - All unix targets (linux, macos, freebsd, android, etc)
123/// - wasm with known target_os
124#[cfg(not(any(
125    all(
126        target_arch = "x86",
127        not(target_feature = "sse2"),
128        not(target_os = "uefi"),
129    ),
130    unix,
131    all(target_family = "wasm", not(target_os = "unknown"))
132)))]
133pub mod partial_availability {
134    #[cfg(not(windows))]
135    libm_intrinsics! {
136        fn acos(x: f64) -> f64;
137        fn acosf(n: f32) -> f32;
138        fn asin(x: f64) -> f64;
139        fn asinf(n: f32) -> f32;
140        fn atan(x: f64) -> f64;
141        fn atan2(x: f64, y: f64) -> f64;
142        fn atan2f(a: f32, b: f32) -> f32;
143        fn atanf(n: f32) -> f32;
144        fn cos(x: f64) -> f64;
145        fn cosf(x: f32) -> f32;
146        fn cosh(x: f64) -> f64;
147        fn coshf(n: f32) -> f32;
148        fn erf(x: f64) -> f64;
149        fn erfc(x: f64) -> f64;
150        fn erfcf(x: f32) -> f32;
151        fn erff(x: f32) -> f32;
152        fn exp(x: f64) -> f64;
153        fn exp2(x: f64) -> f64;
154        fn exp2f(x: f32) -> f32;
155        fn expf(x: f32) -> f32;
156        fn expm1(x: f64) -> f64;
157        fn expm1f(n: f32) -> f32;
158        fn hypot(x: f64, y: f64) -> f64;
159        fn hypotf(x: f32, y: f32) -> f32;
160        fn ldexp(f: f64, n: i32) -> f64;
161        fn ldexpf(f: f32, n: i32) -> f32;
162        fn log(x: f64) -> f64;
163        fn log10(x: f64) -> f64;
164        fn log10f(x: f32) -> f32;
165        fn log1p(x: f64) -> f64;
166        fn log1pf(n: f32) -> f32;
167        fn log2(x: f64) -> f64;
168        fn log2f(x: f32) -> f32;
169        fn logf(x: f32) -> f32;
170        fn pow(x: f64, y: f64) -> f64;
171        fn powf(x: f32, y: f32) -> f32;
172        fn sin(x: f64) -> f64;
173        fn sinf(x: f32) -> f32;
174        fn sinh(x: f64) -> f64;
175        fn sinhf(n: f32) -> f32;
176        fn tan(x: f64) -> f64;
177        fn tanf(n: f32) -> f32;
178        fn tanh(x: f64) -> f64;
179        fn tanhf(n: f32) -> f32;
180        fn tgamma(x: f64) -> f64;
181        fn tgammaf(x: f32) -> f32;
182    }
183
184    // allow for windows (and other targets)
185    intrinsics! {
186        pub extern "C" fn lgamma_r(x: f64, s: &mut i32) -> f64 {
187            let r = super::libm_math::lgamma_r(x);
188            *s = r.1;
189            r.0
190        }
191
192        pub extern "C" fn lgammaf_r(x: f32, s: &mut i32) -> f32 {
193            let r = super::libm_math::lgammaf_r(x);
194            *s = r.1;
195            r.0
196        }
197    }
198}