|  | 
| 5 | 5 | #[path = "../libm/src/math/mod.rs"] | 
| 6 | 6 | pub(crate) mod libm; | 
| 7 | 7 | 
 | 
| 8 |  | -#[allow(unused_macros)] | 
| 9 |  | -macro_rules! no_mangle { | 
|  | 8 | +macro_rules! libm_intrinsics { | 
| 10 | 9 |     ($(fn $fun:ident($($iid:ident : $ity:ty),+) -> $oty:ty;)+) => { | 
| 11 | 10 |         intrinsics! { | 
| 12 | 11 |             $( | 
| 13 | 12 |                 pub extern "C" fn $fun($($iid: $ity),+) -> $oty { | 
| 14 |  | -                    self::libm::$fun($($iid),+) | 
|  | 13 | +                    $crate::math::libm::$fun($($iid),+) | 
| 15 | 14 |                 } | 
| 16 | 15 |             )+ | 
| 17 | 16 |         } | 
| 18 | 17 |     } | 
| 19 | 18 | } | 
| 20 | 19 | 
 | 
| 21 |  | -#[cfg(not(windows))] | 
| 22 |  | -no_mangle! { | 
| 23 |  | -    fn acos(x: f64) -> f64; | 
| 24 |  | -    fn asin(x: f64) -> f64; | 
| 25 |  | -    fn cbrt(x: f64) -> f64; | 
| 26 |  | -    fn expm1(x: f64) -> f64; | 
| 27 |  | -    fn hypot(x: f64, y: f64) -> f64; | 
| 28 |  | -    fn tan(x: f64) -> f64; | 
| 29 |  | -    fn cos(x: f64) -> f64; | 
| 30 |  | -    fn expf(x: f32) -> f32; | 
| 31 |  | -    fn log2(x: f64) -> f64; | 
| 32 |  | -    fn log2f(x: f32) -> f32; | 
| 33 |  | -    fn log10(x: f64) -> f64; | 
| 34 |  | -    fn log10f(x: f32) -> f32; | 
| 35 |  | -    fn log(x: f64) -> f64; | 
| 36 |  | -    fn logf(x: f32) -> f32; | 
| 37 |  | -    fn round(x: f64) -> f64; | 
| 38 |  | -    fn roundf(x: f32) -> f32; | 
| 39 |  | -    fn rint(x: f64) -> f64; | 
| 40 |  | -    fn rintf(x: f32) -> f32; | 
| 41 |  | -    fn sin(x: f64) -> f64; | 
| 42 |  | -    fn pow(x: f64, y: f64) -> f64; | 
| 43 |  | -    fn powf(x: f32, y: f32) -> f32; | 
| 44 |  | -    fn acosf(n: f32) -> f32; | 
| 45 |  | -    fn atan2f(a: f32, b: f32) -> f32; | 
| 46 |  | -    fn atanf(n: f32) -> f32; | 
| 47 |  | -    fn coshf(n: f32) -> f32; | 
| 48 |  | -    fn expm1f(n: f32) -> f32; | 
| 49 |  | -    fn fdim(a: f64, b: f64) -> f64; | 
| 50 |  | -    fn fdimf(a: f32, b: f32) -> f32; | 
| 51 |  | -    fn log1pf(n: f32) -> f32; | 
| 52 |  | -    fn sinhf(n: f32) -> f32; | 
| 53 |  | -    fn tanhf(n: f32) -> f32; | 
| 54 |  | -    fn ldexp(f: f64, n: i32) -> f64; | 
| 55 |  | -    fn ldexpf(f: f32, n: i32) -> f32; | 
| 56 |  | -    fn tgamma(x: f64) -> f64; | 
| 57 |  | -    fn tgammaf(x: f32) -> f32; | 
| 58 |  | -    fn atan(x: f64) -> f64; | 
| 59 |  | -    fn atan2(x: f64, y: f64) -> f64; | 
| 60 |  | -    fn cosh(x: f64) -> f64; | 
| 61 |  | -    fn log1p(x: f64) -> f64; | 
| 62 |  | -    fn sinh(x: f64) -> f64; | 
| 63 |  | -    fn tanh(x: f64) -> f64; | 
| 64 |  | -    fn cosf(x: f32) -> f32; | 
| 65 |  | -    fn exp(x: f64) -> f64; | 
| 66 |  | -    fn sinf(x: f32) -> f32; | 
| 67 |  | -    fn exp2(x: f64) -> f64; | 
| 68 |  | -    fn exp2f(x: f32) -> f32; | 
| 69 |  | -    fn fma(x: f64, y: f64, z: f64) -> f64; | 
| 70 |  | -    fn fmaf(x: f32, y: f32, z: f32) -> f32; | 
| 71 |  | -    fn asinf(n: f32) -> f32; | 
| 72 |  | -    fn cbrtf(n: f32) -> f32; | 
| 73 |  | -    fn hypotf(x: f32, y: f32) -> f32; | 
| 74 |  | -    fn tanf(n: f32) -> f32; | 
|  | 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. */ | 
| 75 | 44 | 
 | 
| 76 |  | -    fn sqrtf(x: f32) -> f32; | 
| 77 |  | -    fn sqrt(x: f64) -> f64; | 
|  | 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; | 
| 78 | 62 | 
 | 
| 79 |  | -    fn ceil(x: f64) -> f64; | 
| 80 |  | -    fn ceilf(x: f32) -> f32; | 
| 81 |  | -    fn floor(x: f64) -> f64; | 
| 82 |  | -    fn floorf(x: f32) -> f32; | 
| 83 |  | -    fn trunc(x: f64) -> f64; | 
| 84 |  | -    fn truncf(x: f32) -> f32; | 
|  | 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 | +    } | 
| 85 | 79 | 
 | 
| 86 |  | -    fn fmin(x: f64, y: f64) -> f64; | 
| 87 |  | -    fn fminf(x: f32, y: f32) -> f32; | 
| 88 |  | -    fn fmax(x: f64, y: f64) -> f64; | 
| 89 |  | -    fn fmaxf(x: f32, y: f32) -> f32; | 
| 90 |  | -    // `f64 % f64` | 
| 91 |  | -    fn fmod(x: f64, y: f64) -> f64; | 
| 92 |  | -    // `f32 % f32` | 
| 93 |  | -    fn fmodf(x: f32, y: f32) -> f32; | 
|  | 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 | +    } | 
| 94 | 90 | 
 | 
| 95 |  | -    fn erf(x: f64) -> f64; | 
| 96 |  | -    fn erff(x: f32) -> f32; | 
| 97 |  | -    fn erfc(x: f64) -> f64; | 
| 98 |  | -    fn erfcf(x: f32) -> f32; | 
|  | 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 | +    } | 
| 99 | 110 | } | 
| 100 | 111 | 
 | 
| 101 |  | -// allow for windows (and other targets) | 
| 102 |  | -intrinsics! { | 
| 103 |  | -    pub extern "C" fn lgamma_r(x: f64, s: &mut i32) -> f64 { | 
| 104 |  | -        let r = self::libm::lgamma_r(x); | 
| 105 |  | -        *s = r.1; | 
| 106 |  | -        r.0 | 
|  | 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; | 
| 107 | 183 |     } | 
| 108 | 184 | 
 | 
| 109 |  | -    pub extern "C" fn lgammaf_r(x: f32, s: &mut i32) -> f32 { | 
| 110 |  | -        let r = self::libm::lgammaf_r(x); | 
| 111 |  | -        *s = r.1; | 
| 112 |  | -        r.0 | 
|  | 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 | +        } | 
| 113 | 198 |     } | 
| 114 | 199 | } | 
0 commit comments