11#![ feature( stmt_expr_attributes) ]
22#![ feature( round_ties_even) ]
3+ #![ feature( float_gamma) ]
34#![ allow( arithmetic_overflow) ]
5+
46use std:: fmt:: Debug ;
57use std:: hint:: black_box;
8+ use std:: { f32, f64} ;
9+
10+ macro_rules! assert_approx_eq {
11+ ( $a: expr, $b: expr) => { {
12+ let ( a, b) = ( & $a, & $b) ;
13+ assert!( ( * a - * b) . abs( ) < 1.0e-6 , "{} is not approximately equal to {}" , * a, * b) ;
14+ } } ;
15+ }
616
717fn main ( ) {
818 basic ( ) ;
@@ -11,6 +21,8 @@ fn main() {
1121 ops ( ) ;
1222 nan_casts ( ) ;
1323 rounding ( ) ;
24+ mul_add ( ) ;
25+ libm ( ) ;
1426}
1527
1628// Helper function to avoid promotion so that this tests "run-time" casts, not CTFE.
@@ -148,8 +160,6 @@ fn basic() {
148160 assert_ne ! ( { 5.0_f32 / 0.0 } , { -5.0_f32 / 0.0 } ) ;
149161 assert ! ( ( 5.0_f64 / 0.0 ) . is_infinite( ) ) ;
150162 assert_ne ! ( { 5.0_f64 / 0.0 } , { 5.0_f64 / -0.0 } ) ;
151- assert ! ( ( -5.0_f32 ) . sqrt( ) . is_nan( ) ) ;
152- assert ! ( ( -5.0_f64 ) . sqrt( ) . is_nan( ) ) ;
153163 assert_ne ! ( f32 :: NAN , f32 :: NAN ) ;
154164 assert_ne ! ( f64 :: NAN , f64 :: NAN ) ;
155165 // negative zero
@@ -178,6 +188,9 @@ fn basic() {
178188 assert ! ( ( black_box( 1.0f64 ) % -1.0 ) . is_sign_positive( ) ) ;
179189 assert ! ( ( black_box( -1.0f64 ) % 1.0 ) . is_sign_negative( ) ) ;
180190 assert ! ( ( black_box( -1.0f64 ) % -1.0 ) . is_sign_negative( ) ) ;
191+
192+ assert_eq ! ( ( -1.0f32 ) . abs( ) , 1.0f32 ) ;
193+ assert_eq ! ( 34.2f64 . abs( ) , 34.2f64 ) ;
181194}
182195
183196/// Many of these test values are taken from
@@ -592,4 +605,150 @@ fn rounding() {
592605 assert_eq ( ( -1.3f64 ) . round_ties_even ( ) , -1.0f64 ) ;
593606 assert_eq ( ( -1.5f64 ) . round_ties_even ( ) , -2.0f64 ) ;
594607 assert_eq ( ( -1.7f64 ) . round_ties_even ( ) , -2.0f64 ) ;
608+
609+ assert_approx_eq ! ( 3.8f32 . floor( ) , 3.0f32 ) ;
610+ assert_approx_eq ! ( ( -1.1f64 ) . floor( ) , -2.0f64 ) ;
611+
612+ assert_approx_eq ! ( ( -2.3f32 ) . ceil( ) , -2.0f32 ) ;
613+ assert_approx_eq ! ( 3.8f64 . ceil( ) , 4.0f64 ) ;
614+
615+ assert_approx_eq ! ( 0.1f32 . trunc( ) , 0.0f32 ) ;
616+ assert_approx_eq ! ( ( -0.1f64 ) . trunc( ) , 0.0f64 ) ;
617+
618+ assert_eq ! ( 3.3_f32 . round( ) , 3.0 ) ;
619+ assert_eq ! ( 2.5_f32 . round( ) , 3.0 ) ;
620+ assert_eq ! ( 3.9_f64 . round( ) , 4.0 ) ;
621+ assert_eq ! ( 2.5_f64 . round( ) , 3.0 ) ;
622+ }
623+
624+ fn mul_add ( ) {
625+ assert_approx_eq ! ( 3.0f32 . mul_add( 2.0f32 , 5.0f32 ) , 11.0 ) ;
626+ assert_eq ! ( 0.0f32 . mul_add( -2.0 , f32 :: consts:: E ) , f32 :: consts:: E ) ;
627+ assert_approx_eq ! ( 3.0f64 . mul_add( 2.0 , 5.0 ) , 11.0 ) ;
628+ assert_eq ! ( 0.0f64 . mul_add( -2.0f64 , f64 :: consts:: E ) , f64 :: consts:: E ) ;
629+ assert_eq ! ( ( -3.2f32 ) . mul_add( 2.4 , f32 :: NEG_INFINITY ) , f32 :: NEG_INFINITY ) ;
630+ assert_eq ! ( ( -3.2f64 ) . mul_add( 2.4 , f64 :: NEG_INFINITY ) , f64 :: NEG_INFINITY ) ;
631+
632+ let f = f32:: mul_add (
633+ -0.000000000000000000000000000000000000014728589 ,
634+ 0.0000037105144 ,
635+ 0.000000000000000000000000000000000000000000055 ,
636+ ) ;
637+ assert_eq ! ( f. to_bits( ) , f32 :: to_bits( -0.0 ) ) ;
638+ }
639+
640+ pub fn libm ( ) {
641+ fn ldexp ( a : f64 , b : i32 ) -> f64 {
642+ extern "C" {
643+ fn ldexp ( x : f64 , n : i32 ) -> f64 ;
644+ }
645+ unsafe { ldexp ( a, b) }
646+ }
647+
648+ assert_approx_eq ! ( 64f32 . sqrt( ) , 8f32 ) ;
649+ assert_approx_eq ! ( 64f64 . sqrt( ) , 8f64 ) ;
650+ assert ! ( ( -5.0_f32 ) . sqrt( ) . is_nan( ) ) ;
651+ assert ! ( ( -5.0_f64 ) . sqrt( ) . is_nan( ) ) ;
652+
653+ assert_approx_eq ! ( 25f32 . powi( -2 ) , 0.0016f32 ) ;
654+ assert_approx_eq ! ( 23.2f64 . powi( 2 ) , 538.24f64 ) ;
655+
656+ assert_approx_eq ! ( 25f32 . powf( -2f32 ) , 0.0016f32 ) ;
657+ assert_approx_eq ! ( 400f64 . powf( 0.5f64 ) , 20f64 ) ;
658+
659+ assert_approx_eq ! ( 1f32 . exp( ) , f32 :: consts:: E ) ;
660+ assert_approx_eq ! ( 1f64 . exp( ) , f64 :: consts:: E ) ;
661+
662+ assert_approx_eq ! ( 1f32 . exp_m1( ) , f32 :: consts:: E - 1.0 ) ;
663+ assert_approx_eq ! ( 1f64 . exp_m1( ) , f64 :: consts:: E - 1.0 ) ;
664+
665+ assert_approx_eq ! ( 10f32 . exp2( ) , 1024f32 ) ;
666+ assert_approx_eq ! ( 50f64 . exp2( ) , 1125899906842624f64 ) ;
667+
668+ assert_approx_eq ! ( f32 :: consts:: E . ln( ) , 1f32 ) ;
669+ assert_approx_eq ! ( 1f64 . ln( ) , 0f64 ) ;
670+
671+ assert_approx_eq ! ( 0f32 . ln_1p( ) , 0f32 ) ;
672+ assert_approx_eq ! ( 0f64 . ln_1p( ) , 0f64 ) ;
673+
674+ assert_approx_eq ! ( 10f32 . log10( ) , 1f32 ) ;
675+ assert_approx_eq ! ( f64 :: consts:: E . log10( ) , f64 :: consts:: LOG10_E ) ;
676+
677+ assert_approx_eq ! ( 8f32 . log2( ) , 3f32 ) ;
678+ assert_approx_eq ! ( f64 :: consts:: E . log2( ) , f64 :: consts:: LOG2_E ) ;
679+
680+ #[ allow( deprecated) ]
681+ {
682+ assert_approx_eq ! ( 5.0f32 . abs_sub( 3.0 ) , 2.0 ) ;
683+ assert_approx_eq ! ( 3.0f64 . abs_sub( 5.0 ) , 0.0 ) ;
684+ }
685+
686+ assert_approx_eq ! ( 27.0f32 . cbrt( ) , 3.0f32 ) ;
687+ assert_approx_eq ! ( 27.0f64 . cbrt( ) , 3.0f64 ) ;
688+
689+ assert_approx_eq ! ( 3.0f32 . hypot( 4.0f32 ) , 5.0f32 ) ;
690+ assert_approx_eq ! ( 3.0f64 . hypot( 4.0f64 ) , 5.0f64 ) ;
691+
692+ assert_eq ! ( ldexp( 0.65f64 , 3i32 ) , 5.2f64 ) ;
693+ assert_eq ! ( ldexp( 1.42 , 0xFFFF ) , f64 :: INFINITY ) ;
694+ assert_eq ! ( ldexp( 1.42 , -0xFFFF ) , 0f64 ) ;
695+
696+ // Trigonometric functions.
697+
698+ assert_approx_eq ! ( 0f32 . sin( ) , 0f32 ) ;
699+ assert_approx_eq ! ( ( f64 :: consts:: PI / 2f64 ) . sin( ) , 1f64 ) ;
700+ assert_approx_eq ! ( f32 :: consts:: FRAC_PI_6 . sin( ) , 0.5 ) ;
701+ assert_approx_eq ! ( f64 :: consts:: FRAC_PI_6 . sin( ) , 0.5 ) ;
702+ assert_approx_eq ! ( f32 :: consts:: FRAC_PI_4 . sin( ) . asin( ) , f32 :: consts:: FRAC_PI_4 ) ;
703+ assert_approx_eq ! ( f64 :: consts:: FRAC_PI_4 . sin( ) . asin( ) , f64 :: consts:: FRAC_PI_4 ) ;
704+
705+ assert_approx_eq ! ( 1.0f32 . sinh( ) , 1.1752012f32 ) ;
706+ assert_approx_eq ! ( 1.0f64 . sinh( ) , 1.1752012f64 ) ;
707+ assert_approx_eq ! ( 2.0f32 . asinh( ) , 1.443635475178810342493276740273105f32 ) ;
708+ assert_approx_eq ! ( ( -2.0f64 ) . asinh( ) , -1.443635475178810342493276740273105f64 ) ;
709+
710+ assert_approx_eq ! ( 0f32 . cos( ) , 1f32 ) ;
711+ assert_approx_eq ! ( ( f64 :: consts:: PI * 2f64 ) . cos( ) , 1f64 ) ;
712+ assert_approx_eq ! ( f32 :: consts:: FRAC_PI_3 . cos( ) , 0.5 ) ;
713+ assert_approx_eq ! ( f64 :: consts:: FRAC_PI_3 . cos( ) , 0.5 ) ;
714+ assert_approx_eq ! ( f32 :: consts:: FRAC_PI_4 . cos( ) . acos( ) , f32 :: consts:: FRAC_PI_4 ) ;
715+ assert_approx_eq ! ( f64 :: consts:: FRAC_PI_4 . cos( ) . acos( ) , f64 :: consts:: FRAC_PI_4 ) ;
716+
717+ assert_approx_eq ! ( 1.0f32 . cosh( ) , 1.54308f32 ) ;
718+ assert_approx_eq ! ( 1.0f64 . cosh( ) , 1.54308f64 ) ;
719+ assert_approx_eq ! ( 2.0f32 . acosh( ) , 1.31695789692481670862504634730796844f32 ) ;
720+ assert_approx_eq ! ( 3.0f64 . acosh( ) , 1.76274717403908605046521864995958461f64 ) ;
721+
722+ assert_approx_eq ! ( 1.0f32 . tan( ) , 1.557408f32 ) ;
723+ assert_approx_eq ! ( 1.0f64 . tan( ) , 1.557408f64 ) ;
724+ assert_approx_eq ! ( 1.0_f32 , 1.0_f32 . tan( ) . atan( ) ) ;
725+ assert_approx_eq ! ( 1.0_f64 , 1.0_f64 . tan( ) . atan( ) ) ;
726+ assert_approx_eq ! ( 1.0f32 . atan2( 2.0f32 ) , 0.46364761f32 ) ;
727+ assert_approx_eq ! ( 1.0f32 . atan2( 2.0f32 ) , 0.46364761f32 ) ;
728+
729+ assert_approx_eq ! (
730+ 1.0f32 . tanh( ) ,
731+ ( 1.0 - f32 :: consts:: E . powi( -2 ) ) / ( 1.0 + f32 :: consts:: E . powi( -2 ) )
732+ ) ;
733+ assert_approx_eq ! (
734+ 1.0f64 . tanh( ) ,
735+ ( 1.0 - f64 :: consts:: E . powi( -2 ) ) / ( 1.0 + f64 :: consts:: E . powi( -2 ) )
736+ ) ;
737+ assert_approx_eq ! ( 0.5f32 . atanh( ) , 0.54930614433405484569762261846126285f32 ) ;
738+ assert_approx_eq ! ( 0.5f64 . atanh( ) , 0.54930614433405484569762261846126285f64 ) ;
739+
740+ assert_approx_eq ! ( 5.0f32 . gamma( ) , 24.0 ) ;
741+ assert_approx_eq ! ( 5.0f64 . gamma( ) , 24.0 ) ;
742+ assert_approx_eq ! ( ( -0.5f32 ) . gamma( ) , ( -2.0 ) * f32 :: consts:: PI . sqrt( ) ) ;
743+ assert_approx_eq ! ( ( -0.5f64 ) . gamma( ) , ( -2.0 ) * f64 :: consts:: PI . sqrt( ) ) ;
744+
745+ assert_eq ! ( 2.0f32 . ln_gamma( ) , ( 0.0 , 1 ) ) ;
746+ assert_eq ! ( 2.0f64 . ln_gamma( ) , ( 0.0 , 1 ) ) ;
747+ // Gamma(-0.5) = -2*sqrt(π)
748+ let ( val, sign) = ( -0.5f32 ) . ln_gamma ( ) ;
749+ assert_approx_eq ! ( val, ( 2.0 * f32 :: consts:: PI . sqrt( ) ) . ln( ) ) ;
750+ assert_eq ! ( sign, -1 ) ;
751+ let ( val, sign) = ( -0.5f64 ) . ln_gamma ( ) ;
752+ assert_approx_eq ! ( val, ( 2.0 * f64 :: consts:: PI . sqrt( ) ) . ln( ) ) ;
753+ assert_eq ! ( sign, -1 ) ;
595754}
0 commit comments