1
1
#![ feature( stmt_expr_attributes) ]
2
2
#![ feature( round_ties_even) ]
3
+ #![ feature( float_gamma) ]
3
4
#![ allow( arithmetic_overflow) ]
5
+
4
6
use std:: fmt:: Debug ;
5
7
use 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
+ }
6
16
7
17
fn main ( ) {
8
18
basic ( ) ;
@@ -11,6 +21,8 @@ fn main() {
11
21
ops ( ) ;
12
22
nan_casts ( ) ;
13
23
rounding ( ) ;
24
+ mul_add ( ) ;
25
+ libm ( ) ;
14
26
}
15
27
16
28
// Helper function to avoid promotion so that this tests "run-time" casts, not CTFE.
@@ -148,8 +160,6 @@ fn basic() {
148
160
assert_ne ! ( { 5.0_f32 / 0.0 } , { -5.0_f32 / 0.0 } ) ;
149
161
assert ! ( ( 5.0_f64 / 0.0 ) . is_infinite( ) ) ;
150
162
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( ) ) ;
153
163
assert_ne ! ( f32 :: NAN , f32 :: NAN ) ;
154
164
assert_ne ! ( f64 :: NAN , f64 :: NAN ) ;
155
165
// negative zero
@@ -178,6 +188,9 @@ fn basic() {
178
188
assert ! ( ( black_box( 1.0f64 ) % -1.0 ) . is_sign_positive( ) ) ;
179
189
assert ! ( ( black_box( -1.0f64 ) % 1.0 ) . is_sign_negative( ) ) ;
180
190
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 ) ;
181
194
}
182
195
183
196
/// Many of these test values are taken from
@@ -592,4 +605,150 @@ fn rounding() {
592
605
assert_eq ( ( -1.3f64 ) . round_ties_even ( ) , -1.0f64 ) ;
593
606
assert_eq ( ( -1.5f64 ) . round_ties_even ( ) , -2.0f64 ) ;
594
607
assert_eq ( ( -1.7f64 ) . round_ties_even ( ) , -2.0f64 ) ;
608
+
609
+ assert_eq ! ( 3.8f32 . floor( ) , 3.0f32 ) ;
610
+ assert_eq ! ( ( -1.1f64 ) . floor( ) , -2.0f64 ) ;
611
+
612
+ assert_eq ! ( ( -2.3f32 ) . ceil( ) , -2.0f32 ) ;
613
+ assert_eq ! ( 3.8f64 . ceil( ) , 4.0f64 ) ;
614
+
615
+ assert_eq ! ( 0.1f32 . trunc( ) , 0.0f32 ) ;
616
+ assert_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_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_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 ) ;
595
754
}
0 commit comments