From b1316eca922655f5d81559c1c26f457693aa5c2b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 6 Aug 2022 09:33:08 -0400 Subject: [PATCH] support and test some more math functions --- src/shims/foreign_items.rs | 20 +++++++- tests/pass/intrinsics-math.rs | 87 +++++++++++++++++++++++------------ 2 files changed, 77 insertions(+), 30 deletions(-) diff --git a/src/shims/foreign_items.rs b/src/shims/foreign_items.rs index 9a985b24503..e7cfd43f1b1 100644 --- a/src/shims/foreign_items.rs +++ b/src/shims/foreign_items.rs @@ -575,15 +575,18 @@ fn emulate_foreign_item_by_name( this.write_scalar(Scalar::from_machine_usize(u64::try_from(n).unwrap(), this), dest)?; } - // math functions + // math functions (note that there are also intrinsics for some other functions) #[rustfmt::skip] | "cbrtf" | "coshf" | "sinhf" | "tanf" + | "tanhf" | "acosf" | "asinf" | "atanf" + | "log1pf" + | "expm1f" => { let [f] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; // FIXME: Using host floats. @@ -593,9 +596,12 @@ fn emulate_foreign_item_by_name( "coshf" => f.cosh(), "sinhf" => f.sinh(), "tanf" => f.tan(), + "tanhf" => f.tanh(), "acosf" => f.acos(), "asinf" => f.asin(), "atanf" => f.atan(), + "log1pf" => f.ln_1p(), + "expm1f" => f.exp_m1(), _ => bug!(), }; this.write_scalar(Scalar::from_u32(res.to_bits()), dest)?; @@ -604,6 +610,7 @@ fn emulate_foreign_item_by_name( | "_hypotf" | "hypotf" | "atan2f" + | "fdimf" => { let [f1, f2] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; // underscore case for windows, here and below @@ -614,6 +621,8 @@ fn emulate_foreign_item_by_name( let res = match link_name.as_str() { "_hypotf" | "hypotf" => f1.hypot(f2), "atan2f" => f1.atan2(f2), + #[allow(deprecated)] + "fdimf" => f1.abs_sub(f2), _ => bug!(), }; this.write_scalar(Scalar::from_u32(res.to_bits()), dest)?; @@ -623,9 +632,12 @@ fn emulate_foreign_item_by_name( | "cosh" | "sinh" | "tan" + | "tanh" | "acos" | "asin" | "atan" + | "log1p" + | "expm1" => { let [f] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; // FIXME: Using host floats. @@ -635,9 +647,12 @@ fn emulate_foreign_item_by_name( "cosh" => f.cosh(), "sinh" => f.sinh(), "tan" => f.tan(), + "tanh" => f.tanh(), "acos" => f.acos(), "asin" => f.asin(), "atan" => f.atan(), + "log1p" => f.ln_1p(), + "expm1" => f.exp_m1(), _ => bug!(), }; this.write_scalar(Scalar::from_u64(res.to_bits()), dest)?; @@ -646,6 +661,7 @@ fn emulate_foreign_item_by_name( | "_hypot" | "hypot" | "atan2" + | "fdim" => { let [f1, f2] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; // FIXME: Using host floats. @@ -654,6 +670,8 @@ fn emulate_foreign_item_by_name( let res = match link_name.as_str() { "_hypot" | "hypot" => f1.hypot(f2), "atan2" => f1.atan2(f2), + #[allow(deprecated)] + "fdim" => f1.abs_sub(f2), _ => bug!(), }; this.write_scalar(Scalar::from_u64(res.to_bits()), dest)?; diff --git a/tests/pass/intrinsics-math.rs b/tests/pass/intrinsics-math.rs index fad01047b9c..5973f4cd197 100644 --- a/tests/pass/intrinsics-math.rs +++ b/tests/pass/intrinsics-math.rs @@ -32,24 +32,24 @@ pub fn main() { assert_approx_eq!(25f32.powi(-2), 0.0016f32); assert_approx_eq!(23.2f64.powi(2), 538.24f64); - assert_approx_eq!(0f32.sin(), 0f32); - assert_approx_eq!((f64::consts::PI / 2f64).sin(), 1f64); - - assert_approx_eq!(0f32.cos(), 1f32); - assert_approx_eq!((f64::consts::PI * 2f64).cos(), 1f64); - assert_approx_eq!(25f32.powf(-2f32), 0.0016f32); assert_approx_eq!(400f64.powf(0.5f64), 20f64); - assert_approx_eq!((1f32.exp() - f32::consts::E).abs(), 0f32); + assert_approx_eq!(1f32.exp(), f32::consts::E); assert_approx_eq!(1f64.exp(), f64::consts::E); + assert_approx_eq!(1f32.exp_m1(), f32::consts::E - 1.0); + assert_approx_eq!(1f64.exp_m1(), f64::consts::E - 1.0); + assert_approx_eq!(10f32.exp2(), 1024f32); assert_approx_eq!(50f64.exp2(), 1125899906842624f64); - assert_approx_eq!((f32::consts::E.ln() - 1f32).abs(), 0f32); + assert_approx_eq!(f32::consts::E.ln(), 1f32); assert_approx_eq!(1f64.ln(), 0f64); + assert_approx_eq!(0f32.ln_1p(), 0f32); + assert_approx_eq!(0f64.ln_1p(), 0f64); + assert_approx_eq!(10f32.log10(), 1f32); assert_approx_eq!(f64::consts::E.log10(), f64::consts::LOG10_E); @@ -66,6 +66,12 @@ pub fn main() { assert_approx_eq!((-1.0f32).abs(), 1.0f32); assert_approx_eq!(34.2f64.abs(), 34.2f64); + #[allow(deprecated)] + { + assert_approx_eq!(5.0f32.abs_sub(3.0), 2.0); + assert_approx_eq!(3.0f64.abs_sub(5.0), 0.0); + } + assert_approx_eq!(3.8f32.floor(), 3.0f32); assert_approx_eq!((-1.1f64).floor(), -2.0f64); @@ -81,31 +87,54 @@ pub fn main() { assert_approx_eq!(3.0f32.hypot(4.0f32), 5.0f32); assert_approx_eq!(3.0f64.hypot(4.0f64), 5.0f64); - assert_approx_eq!(1.0f32.atan2(2.0f32), 0.46364761f32); - assert_approx_eq!(1.0f32.atan2(2.0f32), 0.46364761f32); - - assert_approx_eq!(1.0f32.cosh(), 1.54308f32); - assert_approx_eq!(1.0f64.cosh(), 1.54308f64); - - assert_approx_eq!(1.0f32.sinh(), 1.1752012f32); - assert_approx_eq!(1.0f64.sinh(), 1.1752012f64); - - assert_approx_eq!(1.0f32.tan(), 1.557408f32); - assert_approx_eq!(1.0f64.tan(), 1.557408f64); - - assert_approx_eq!(f32::consts::FRAC_PI_4.cos().acos(), f32::consts::FRAC_PI_4); - assert_approx_eq!(f64::consts::FRAC_PI_4.cos().acos(), f64::consts::FRAC_PI_4); - - assert_approx_eq!(f32::consts::FRAC_PI_4.sin().asin(), f32::consts::FRAC_PI_4); - assert_approx_eq!(f64::consts::FRAC_PI_4.sin().asin(), f64::consts::FRAC_PI_4); - - assert_approx_eq!(1.0_f32, 1.0_f32.tan().atan()); - assert_approx_eq!(1.0_f64, 1.0_f64.tan().atan()); - assert_eq!(3.3_f32.round(), 3.0); assert_eq!(3.3_f64.round(), 3.0); assert_eq!(ldexp(0.65f64, 3i32), 5.2f64); assert_eq!(ldexp(1.42, 0xFFFF), f64::INFINITY); assert_eq!(ldexp(1.42, -0xFFFF), 0f64); + + // Trigonometric functions. + + assert_approx_eq!(0f32.sin(), 0f32); + assert_approx_eq!((f64::consts::PI / 2f64).sin(), 1f64); + assert_approx_eq!(f32::consts::FRAC_PI_6.sin(), 0.5); + assert_approx_eq!(f64::consts::FRAC_PI_6.sin(), 0.5); + assert_approx_eq!(f32::consts::FRAC_PI_4.sin().asin(), f32::consts::FRAC_PI_4); + assert_approx_eq!(f64::consts::FRAC_PI_4.sin().asin(), f64::consts::FRAC_PI_4); + + assert_approx_eq!(1.0f32.sinh(), 1.1752012f32); + assert_approx_eq!(1.0f64.sinh(), 1.1752012f64); + assert_approx_eq!(2.0f32.asinh(), 1.443635475178810342493276740273105f32); + assert_approx_eq!((-2.0f64).asinh(), -1.443635475178810342493276740273105f64); + + assert_approx_eq!(0f32.cos(), 1f32); + assert_approx_eq!((f64::consts::PI * 2f64).cos(), 1f64); + assert_approx_eq!(f32::consts::FRAC_PI_3.cos(), 0.5); + assert_approx_eq!(f64::consts::FRAC_PI_3.cos(), 0.5); + assert_approx_eq!(f32::consts::FRAC_PI_4.cos().acos(), f32::consts::FRAC_PI_4); + assert_approx_eq!(f64::consts::FRAC_PI_4.cos().acos(), f64::consts::FRAC_PI_4); + + assert_approx_eq!(1.0f32.cosh(), 1.54308f32); + assert_approx_eq!(1.0f64.cosh(), 1.54308f64); + assert_approx_eq!(2.0f32.acosh(), 1.31695789692481670862504634730796844f32); + assert_approx_eq!(3.0f64.acosh(), 1.76274717403908605046521864995958461f64); + + assert_approx_eq!(1.0f32.tan(), 1.557408f32); + assert_approx_eq!(1.0f64.tan(), 1.557408f64); + assert_approx_eq!(1.0_f32, 1.0_f32.tan().atan()); + assert_approx_eq!(1.0_f64, 1.0_f64.tan().atan()); + assert_approx_eq!(1.0f32.atan2(2.0f32), 0.46364761f32); + assert_approx_eq!(1.0f32.atan2(2.0f32), 0.46364761f32); + + assert_approx_eq!( + 1.0f32.tanh(), + (1.0 - f32::consts::E.powi(-2)) / (1.0 + f32::consts::E.powi(-2)) + ); + assert_approx_eq!( + 1.0f64.tanh(), + (1.0 - f64::consts::E.powi(-2)) / (1.0 + f64::consts::E.powi(-2)) + ); + assert_approx_eq!(0.5f32.atanh(), 0.54930614433405484569762261846126285f32); + assert_approx_eq!(0.5f64.atanh(), 0.54930614433405484569762261846126285f64); }