| 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; |
| 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::$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::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::lgammaf_r(x); |
| 195 | *s = r.1; |
| 196 | r.0 |
| 197 | } |
| 198 | } |
| 199 | } |
| 200 | |