| //! Bindings to Musl math functions (these are built in `build.rs`). |
| |
| use std::ffi::{c_char, c_int, c_long}; |
| |
| /// Macro for creating bindings and exposing a safe function (since the implementations have no |
| /// preconditions). Included functions must have correct signatures, otherwise this will be |
| /// unsound. |
| macro_rules! functions { |
| ( $( |
| $( #[$meta:meta] )* |
| $pfx_name:ident: $name:ident( $($arg:ident: $aty:ty),+ ) -> $rty:ty; |
| )* ) => { |
| unsafe extern "C" { |
| $( fn $pfx_name( $($arg: $aty),+ ) -> $rty; )* |
| } |
| |
| $( |
| // Expose a safe version |
| $( #[$meta] )* |
| pub fn $name( $($arg: $aty),+ ) -> $rty { |
| // SAFETY: FFI calls with no preconditions |
| unsafe { $pfx_name( $($arg),+ ) } |
| } |
| )* |
| |
| #[cfg(test)] |
| mod tests { |
| use super::*; |
| use test_support::CallTest; |
| |
| $( functions!( |
| @single_test |
| $name($($arg: $aty),+) -> $rty |
| ); )* |
| } |
| }; |
| |
| (@single_test |
| $name:ident( $($arg:ident: $aty:ty),+ ) -> $rty:ty |
| ) => { |
| // Run a simple check to ensure we can link and call the function without crashing. |
| #[test] |
| fn $name() { |
| <fn($($aty),+) -> $rty>::check(super::$name); |
| } |
| }; |
| } |
| |
| #[cfg(test)] |
| mod test_support { |
| use core::ffi::c_char; |
| |
| /// Just verify that we are able to call the function. |
| pub trait CallTest { |
| fn check(f: Self); |
| } |
| |
| macro_rules! impl_calltest { |
| ($( ($($arg:ty),*) -> $ret:ty; )*) => { |
| $( |
| impl CallTest for fn($($arg),*) -> $ret { |
| fn check(f: Self) { |
| f($(1 as $arg),*); |
| } |
| } |
| )* |
| }; |
| } |
| |
| impl_calltest! { |
| (f32) -> f32; |
| (f64) -> f64; |
| (f32, f32) -> f32; |
| (f64, f64) -> f64; |
| (i32, f32) -> f32; |
| (i32, f64) -> f64; |
| (f32, f32, f32) -> f32; |
| (f64, f64, f64) -> f64; |
| (f32, i32) -> f32; |
| (f32, i64) -> f32; |
| (f32) -> i32; |
| (f64) -> i32; |
| (f64, i32) -> f64; |
| (f64, i64) -> f64; |
| } |
| |
| impl CallTest for fn(f32, &mut f32) -> f32 { |
| fn check(f: Self) { |
| let mut tmp = 0.0; |
| f(0.0, &mut tmp); |
| } |
| } |
| impl CallTest for fn(f64, &mut f64) -> f64 { |
| fn check(f: Self) { |
| let mut tmp = 0.0; |
| f(0.0, &mut tmp); |
| } |
| } |
| impl CallTest for fn(f32, &mut i32) -> f32 { |
| fn check(f: Self) { |
| let mut tmp = 1; |
| f(0.0, &mut tmp); |
| } |
| } |
| impl CallTest for fn(f64, &mut i32) -> f64 { |
| fn check(f: Self) { |
| let mut tmp = 1; |
| f(0.0, &mut tmp); |
| } |
| } |
| impl CallTest for fn(f32, f32, &mut i32) -> f32 { |
| fn check(f: Self) { |
| let mut tmp = 1; |
| f(0.0, 0.0, &mut tmp); |
| } |
| } |
| impl CallTest for fn(f64, f64, &mut i32) -> f64 { |
| fn check(f: Self) { |
| let mut tmp = 1; |
| f(0.0, 0.0, &mut tmp); |
| } |
| } |
| impl CallTest for fn(f32, &mut f32, &mut f32) { |
| fn check(f: Self) { |
| let mut tmp1 = 1.0; |
| let mut tmp2 = 1.0; |
| f(0.0, &mut tmp1, &mut tmp2); |
| } |
| } |
| impl CallTest for fn(f64, &mut f64, &mut f64) { |
| fn check(f: Self) { |
| let mut tmp1 = 1.0; |
| let mut tmp2 = 1.0; |
| f(0.0, &mut tmp1, &mut tmp2); |
| } |
| } |
| impl CallTest for fn(*const c_char) -> f32 { |
| fn check(f: Self) { |
| f(c"1".as_ptr()); |
| } |
| } |
| impl CallTest for fn(*const c_char) -> f64 { |
| fn check(f: Self) { |
| f(c"1".as_ptr()); |
| } |
| } |
| } |
| |
| functions! { |
| musl_acos: acos(a: f64) -> f64; |
| musl_acosf: acosf(a: f32) -> f32; |
| musl_acosh: acosh(a: f64) -> f64; |
| musl_acoshf: acoshf(a: f32) -> f32; |
| musl_asin: asin(a: f64) -> f64; |
| musl_asinf: asinf(a: f32) -> f32; |
| musl_asinh: asinh(a: f64) -> f64; |
| musl_asinhf: asinhf(a: f32) -> f32; |
| musl_atan2: atan2(a: f64, b: f64) -> f64; |
| musl_atan2f: atan2f(a: f32, b: f32) -> f32; |
| musl_atan: atan(a: f64) -> f64; |
| musl_atanf: atanf(a: f32) -> f32; |
| musl_atanh: atanh(a: f64) -> f64; |
| musl_atanhf: atanhf(a: f32) -> f32; |
| musl_cbrt: cbrt(a: f64) -> f64; |
| musl_cbrtf: cbrtf(a: f32) -> f32; |
| musl_ceil: ceil(a: f64) -> f64; |
| musl_ceilf: ceilf(a: f32) -> f32; |
| musl_copysign: copysign(a: f64, b: f64) -> f64; |
| musl_copysignf: copysignf(a: f32, b: f32) -> f32; |
| musl_cos: cos(a: f64) -> f64; |
| musl_cosf: cosf(a: f32) -> f32; |
| musl_cosh: cosh(a: f64) -> f64; |
| musl_coshf: coshf(a: f32) -> f32; |
| musl_drem: drem(a: f64, b: f64) -> f64; |
| musl_dremf: dremf(a: f32, b: f32) -> f32; |
| musl_erf: erf(a: f64) -> f64; |
| musl_erfc: erfc(a: f64) -> f64; |
| musl_erfcf: erfcf(a: f32) -> f32; |
| musl_erff: erff(a: f32) -> f32; |
| musl_exp10: exp10(a: f64) -> f64; |
| musl_exp10f: exp10f(a: f32) -> f32; |
| musl_exp2: exp2(a: f64) -> f64; |
| musl_exp2f: exp2f(a: f32) -> f32; |
| musl_exp: exp(a: f64) -> f64; |
| musl_expf: expf(a: f32) -> f32; |
| musl_expm1: expm1(a: f64) -> f64; |
| musl_expm1f: expm1f(a: f32) -> f32; |
| musl_fabs: fabs(a: f64) -> f64; |
| musl_fabsf: fabsf(a: f32) -> f32; |
| musl_fdim: fdim(a: f64, b: f64) -> f64; |
| musl_fdimf: fdimf(a: f32, b: f32) -> f32; |
| musl_finite: finite(a: f64) -> c_int; |
| musl_finitef: finitef(a: f32) -> c_int; |
| musl_floor: floor(a: f64) -> f64; |
| musl_floorf: floorf(a: f32) -> f32; |
| musl_fma: fma(a: f64, b: f64, c: f64) -> f64; |
| musl_fmaf: fmaf(a: f32, b: f32, c: f32) -> f32; |
| musl_fmax: fmax(a: f64, b: f64) -> f64; |
| musl_fmaxf: fmaxf(a: f32, b: f32) -> f32; |
| musl_fmin: fmin(a: f64, b: f64) -> f64; |
| musl_fminf: fminf(a: f32, b: f32) -> f32; |
| musl_fmod: fmod(a: f64, b: f64) -> f64; |
| musl_fmodf: fmodf(a: f32, b: f32) -> f32; |
| musl_frexp: frexp(a: f64, b: &mut c_int) -> f64; |
| musl_frexpf: frexpf(a: f32, b: &mut c_int) -> f32; |
| musl_hypot: hypot(a: f64, b: f64) -> f64; |
| musl_hypotf: hypotf(a: f32, b: f32) -> f32; |
| musl_ilogb: ilogb(a: f64) -> c_int; |
| musl_ilogbf: ilogbf(a: f32) -> c_int; |
| musl_j0: j0(a: f64) -> f64; |
| musl_j0f: j0f(a: f32) -> f32; |
| musl_j1: j1(a: f64) -> f64; |
| musl_j1f: j1f(a: f32) -> f32; |
| musl_jn: jn(a: c_int, b: f64) -> f64; |
| musl_jnf: jnf(a: c_int, b: f32) -> f32; |
| musl_ldexp: ldexp(a: f64, b: c_int) -> f64; |
| musl_ldexpf: ldexpf(a: f32, b: c_int) -> f32; |
| musl_lgamma: lgamma(a: f64) -> f64; |
| musl_lgamma_r: lgamma_r(a: f64, b: &mut c_int) -> f64; |
| musl_lgammaf: lgammaf(a: f32) -> f32; |
| musl_lgammaf_r: lgammaf_r(a: f32, b: &mut c_int) -> f32; |
| musl_log10: log10(a: f64) -> f64; |
| musl_log10f: log10f(a: f32) -> f32; |
| musl_log1p: log1p(a: f64) -> f64; |
| musl_log1pf: log1pf(a: f32) -> f32; |
| musl_log2: log2(a: f64) -> f64; |
| musl_log2f: log2f(a: f32) -> f32; |
| musl_log: log(a: f64) -> f64; |
| musl_logb: logb(a: f64) -> f64; |
| musl_logbf: logbf(a: f32) -> f32; |
| musl_logf: logf(a: f32) -> f32; |
| musl_modf: modf(a: f64, b: &mut f64) -> f64; |
| musl_modff: modff(a: f32, b: &mut f32) -> f32; |
| |
| // FIXME: these need to be unsafe |
| #[allow(clippy::not_unsafe_ptr_arg_deref)] |
| musl_nan: nan(a: *const c_char) -> f64; |
| #[allow(clippy::not_unsafe_ptr_arg_deref)] |
| musl_nanf: nanf(a: *const c_char) -> f32; |
| |
| musl_nearbyint: nearbyint(a: f64) -> f64; |
| musl_nearbyintf: nearbyintf(a: f32) -> f32; |
| musl_nextafter: nextafter(a: f64, b: f64) -> f64; |
| musl_nextafterf: nextafterf(a: f32, b: f32) -> f32; |
| musl_pow10: pow10(a: f64) -> f64; |
| musl_pow10f: pow10f(a: f32) -> f32; |
| musl_pow: pow(a: f64, b: f64) -> f64; |
| musl_powf: powf(a: f32, b: f32) -> f32; |
| musl_remainder: remainder(a: f64, b: f64) -> f64; |
| musl_remainderf: remainderf(a: f32, b: f32) -> f32; |
| musl_remquo: remquo(a: f64, b: f64, c: &mut c_int) -> f64; |
| musl_remquof: remquof(a: f32, b: f32, c: &mut c_int) -> f32; |
| musl_rint: rint(a: f64) -> f64; |
| musl_rintf: rintf(a: f32) -> f32; |
| musl_round: round(a: f64) -> f64; |
| musl_roundf: roundf(a: f32) -> f32; |
| musl_scalbln: scalbln(a: f64, b: c_long) -> f64; |
| musl_scalblnf: scalblnf(a: f32, b: c_long) -> f32; |
| musl_scalbn: scalbn(a: f64, b: c_int) -> f64; |
| musl_scalbnf: scalbnf(a: f32, b: c_int) -> f32; |
| musl_significand: significand(a: f64) -> f64; |
| musl_significandf: significandf(a: f32) -> f32; |
| musl_sin: sin(a: f64) -> f64; |
| musl_sincos: sincos(a: f64, b: &mut f64, c: &mut f64) -> (); |
| musl_sincosf: sincosf(a: f32, b: &mut f32, c: &mut f32) -> (); |
| musl_sinf: sinf(a: f32) -> f32; |
| musl_sinh: sinh(a: f64) -> f64; |
| musl_sinhf: sinhf(a: f32) -> f32; |
| musl_sqrt: sqrt(a: f64) -> f64; |
| musl_sqrtf: sqrtf(a: f32) -> f32; |
| musl_tan: tan(a: f64) -> f64; |
| musl_tanf: tanf(a: f32) -> f32; |
| musl_tanh: tanh(a: f64) -> f64; |
| musl_tanhf: tanhf(a: f32) -> f32; |
| musl_tgamma: tgamma(a: f64) -> f64; |
| musl_tgammaf: tgammaf(a: f32) -> f32; |
| musl_trunc: trunc(a: f64) -> f64; |
| musl_truncf: truncf(a: f32) -> f32; |
| musl_y0: y0(a: f64) -> f64; |
| musl_y0f: y0f(a: f32) -> f32; |
| musl_y1: y1(a: f64) -> f64; |
| musl_y1f: y1f(a: f32) -> f32; |
| musl_yn: yn(a: c_int, b: f64) -> f64; |
| musl_ynf: ynf(a: c_int, b: f32) -> f32; |
| } |