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