11
11
//! Operations and constants for `f32`
12
12
13
13
use num:: { Zero , One , strconv} ;
14
+ use num:: { FPCategory , FPNaN , FPInfinite , FPZero , FPSubnormal , FPNormal } ;
14
15
use prelude:: * ;
15
16
16
17
pub use cmath:: c_float_targ_consts:: * ;
@@ -82,7 +83,7 @@ delegate!(
82
83
fn cosh( n: c_float) -> c_float = c_float_utils:: cosh,
83
84
fn erf( n: c_float) -> c_float = c_float_utils:: erf,
84
85
fn erfc( n: c_float) -> c_float = c_float_utils:: erfc,
85
- fn expm1 ( n: c_float) -> c_float = c_float_utils:: expm1 ,
86
+ fn exp_m1 ( n: c_float) -> c_float = c_float_utils:: exp_m1 ,
86
87
fn abs_sub( a: c_float, b: c_float) -> c_float = c_float_utils:: abs_sub,
87
88
fn fmax( a: c_float, b: c_float) -> c_float = c_float_utils:: fmax,
88
89
fn fmin( a: c_float, b: c_float) -> c_float = c_float_utils:: fmin,
@@ -92,7 +93,7 @@ delegate!(
92
93
fn ldexp( x: c_float, n: c_int) -> c_float = c_float_utils:: ldexp,
93
94
fn lgamma( n: c_float, sign: & mut c_int) -> c_float = c_float_utils:: lgamma,
94
95
fn log_radix( n: c_float) -> c_float = c_float_utils:: log_radix,
95
- fn ln1p ( n: c_float) -> c_float = c_float_utils:: ln1p ,
96
+ fn ln_1p ( n: c_float) -> c_float = c_float_utils:: ln_1p ,
96
97
fn ilog_radix( n: c_float) -> c_int = c_float_utils:: ilog_radix,
97
98
fn modf( n: c_float, iptr: & mut c_float) -> c_float = c_float_utils:: modf,
98
99
fn round( n: c_float) -> c_float = c_float_utils:: round,
@@ -195,11 +196,6 @@ pub mod consts {
195
196
pub static ln_10: f32 = 2.30258509299404568401799145468436421_f32 ;
196
197
}
197
198
198
- #[ inline( always) ]
199
- pub fn logarithm ( n : f32 , b : f32 ) -> f32 {
200
- return log2 ( n) / log2 ( b) ;
201
- }
202
-
203
199
impl Num for f32 { }
204
200
205
201
#[ cfg( notest) ]
@@ -317,6 +313,13 @@ impl Signed for f32 {
317
313
#[ inline( always) ]
318
314
fn abs ( & self ) -> f32 { abs ( * self ) }
319
315
316
+ ///
317
+ /// The positive difference of two numbers. Returns `0.0` if the number is less than or
318
+ /// equal to `other`, otherwise the difference between`self` and `other` is returned.
319
+ ///
320
+ #[ inline( always) ]
321
+ fn abs_sub ( & self , other : & f32 ) -> f32 { abs_sub ( * self , * other) }
322
+
320
323
///
321
324
/// # Returns
322
325
///
@@ -413,21 +416,27 @@ impl Trigonometric for f32 {
413
416
}
414
417
415
418
impl Exponential for f32 {
419
+ /// Returns the exponential of the number
416
420
#[ inline( always) ]
417
421
fn exp ( & self ) -> f32 { exp ( * self ) }
418
422
423
+ /// Returns 2 raised to the power of the number
419
424
#[ inline( always) ]
420
425
fn exp2 ( & self ) -> f32 { exp2 ( * self ) }
421
426
427
+ /// Returns the natural logarithm of the number
422
428
#[ inline( always) ]
423
- fn expm1 ( & self ) -> f32 { expm1 ( * self ) }
429
+ fn ln ( & self ) -> f32 { ln ( * self ) }
424
430
431
+ /// Returns the logarithm of the number with respect to an arbitrary base
425
432
#[ inline( always) ]
426
- fn log ( & self ) -> f32 { ln ( * self ) }
433
+ fn log ( & self , base : f32 ) -> f32 { self . ln ( ) / base . ln ( ) }
427
434
435
+ /// Returns the base 2 logarithm of the number
428
436
#[ inline( always) ]
429
437
fn log2 ( & self ) -> f32 { log2 ( * self ) }
430
438
439
+ /// Returns the base 10 logarithm of the number
431
440
#[ inline( always) ]
432
441
fn log10 ( & self ) -> f32 { log10 ( * self ) }
433
442
}
@@ -504,13 +513,13 @@ impl Real for f32 {
504
513
#[ inline( always) ]
505
514
fn log10_e ( ) -> f32 { 0.434294481903251827651128918916605082 }
506
515
507
- /// log (2.0)
516
+ /// ln (2.0)
508
517
#[ inline( always) ]
509
- fn log_2 ( ) -> f32 { 0.693147180559945309417232121458176568 }
518
+ fn ln_2 ( ) -> f32 { 0.693147180559945309417232121458176568 }
510
519
511
- /// log (10.0)
520
+ /// ln (10.0)
512
521
#[ inline( always) ]
513
- fn log_10 ( ) -> f32 { 2.30258509299404568401799145468436421 }
522
+ fn ln_10 ( ) -> f32 { 2.30258509299404568401799145468436421 }
514
523
515
524
/// Converts to degrees, assuming the number is in radians
516
525
#[ inline( always) ]
@@ -550,9 +559,49 @@ impl Float for f32 {
550
559
#[ inline( always) ]
551
560
fn neg_zero ( ) -> f32 { -0.0 }
552
561
562
+ /// Returns `true` if the number is NaN
553
563
#[ inline( always) ]
554
564
fn is_NaN ( & self ) -> bool { * self != * self }
555
565
566
+ /// Returns `true` if the number is infinite
567
+ #[ inline( always) ]
568
+ fn is_infinite ( & self ) -> bool {
569
+ * self == Float :: infinity ( ) || * self == Float :: neg_infinity ( )
570
+ }
571
+
572
+ /// Returns `true` if the number is neither infinite or NaN
573
+ #[ inline( always) ]
574
+ fn is_finite ( & self ) -> bool {
575
+ !( self . is_NaN ( ) || self . is_infinite ( ) )
576
+ }
577
+
578
+ /// Returns `true` if the number is neither zero, infinite, subnormal or NaN
579
+ #[ inline( always) ]
580
+ fn is_normal ( & self ) -> bool {
581
+ match self . classify ( ) {
582
+ FPNormal => true ,
583
+ _ => false ,
584
+ }
585
+ }
586
+
587
+ /// Returns the floating point category of the number. If only one property is going to
588
+ /// be tested, it is generally faster to use the specific predicate instead.
589
+ fn classify ( & self ) -> FPCategory {
590
+ static EXP_MASK : u32 = 0x7f800000 ;
591
+ static MAN_MASK : u32 = 0x007fffff ;
592
+
593
+ match (
594
+ unsafe { :: cast:: transmute :: < f32 , u32 > ( * self ) } & EXP_MASK ,
595
+ unsafe { :: cast:: transmute :: < f32 , u32 > ( * self ) } & MAN_MASK
596
+ ) {
597
+ ( EXP_MASK , 0 ) => FPInfinite ,
598
+ ( EXP_MASK , _) => FPNaN ,
599
+ ( exp, _) if exp != 0 => FPNormal ,
600
+ _ if self . is_zero ( ) => FPZero ,
601
+ _ => FPSubnormal ,
602
+ }
603
+ }
604
+
556
605
#[ inline( always) ]
557
606
fn mantissa_digits ( ) -> uint { 24 }
558
607
@@ -574,17 +623,19 @@ impl Float for f32 {
574
623
#[ inline( always) ]
575
624
fn max_10_exp ( ) -> int { 38 }
576
625
577
- /// Returns `true` if the number is infinite
626
+ ///
627
+ /// Returns the exponential of the number, minus `1`, in a way that is accurate
628
+ /// even if the number is close to zero
629
+ ///
578
630
#[ inline( always) ]
579
- fn is_infinite ( & self ) -> bool {
580
- * self == Float :: infinity ( ) || * self == Float :: neg_infinity ( )
581
- }
631
+ fn exp_m1 ( & self ) -> f32 { exp_m1 ( * self ) }
582
632
583
- /// Returns `true` if the number is finite
633
+ ///
634
+ /// Returns the natural logarithm of the number plus `1` (`ln(1+n)`) more accurately
635
+ /// than if the operations were performed separately
636
+ ///
584
637
#[ inline( always) ]
585
- fn is_finite ( & self ) -> bool {
586
- !( self . is_NaN ( ) || self . is_infinite ( ) )
587
- }
638
+ fn ln_1p ( & self ) -> f32 { ln_1p ( * self ) }
588
639
589
640
///
590
641
/// Fused multiply-add. Computes `(self * a) + b` with only one rounding error. This
@@ -823,6 +874,7 @@ impl num::FromStrRadix for f32 {
823
874
#[ cfg( test) ]
824
875
mod tests {
825
876
use f32:: * ;
877
+ use num:: * ;
826
878
use super :: * ;
827
879
use prelude:: * ;
828
880
@@ -938,12 +990,12 @@ mod tests {
938
990
assert_approx_eq ! ( Real :: frac_1_sqrt2:: <f32 >( ) , 1f32 / 2f32 . sqrt( ) ) ;
939
991
assert_approx_eq ! ( Real :: log2_e:: <f32 >( ) , Real :: e:: <f32 >( ) . log2( ) ) ;
940
992
assert_approx_eq ! ( Real :: log10_e:: <f32 >( ) , Real :: e:: <f32 >( ) . log10( ) ) ;
941
- assert_approx_eq ! ( Real :: log_2 :: <f32 >( ) , 2f32 . log ( ) ) ;
942
- assert_approx_eq ! ( Real :: log_10 :: <f32 >( ) , 10f32 . log ( ) ) ;
993
+ assert_approx_eq ! ( Real :: ln_2 :: <f32 >( ) , 2f32 . ln ( ) ) ;
994
+ assert_approx_eq ! ( Real :: ln_10 :: <f32 >( ) , 10f32 . ln ( ) ) ;
943
995
}
944
996
945
997
#[ test]
946
- pub fn test_signed ( ) {
998
+ pub fn test_abs ( ) {
947
999
assert_eq ! ( infinity. abs( ) , infinity) ;
948
1000
assert_eq ! ( 1f32 . abs( ) , 1f32 ) ;
949
1001
assert_eq ! ( 0f32 . abs( ) , 0f32 ) ;
@@ -952,7 +1004,24 @@ mod tests {
952
1004
assert_eq ! ( neg_infinity. abs( ) , infinity) ;
953
1005
assert_eq ! ( ( 1f32 /neg_infinity) . abs( ) , 0f32 ) ;
954
1006
assert ! ( NaN . abs( ) . is_NaN( ) ) ;
1007
+ }
1008
+
1009
+ #[ test]
1010
+ fn test_abs_sub ( ) {
1011
+ assert_eq ! ( ( -1f32 ) . abs_sub( & 1f32 ) , 0f32 ) ;
1012
+ assert_eq ! ( 1f32 . abs_sub( & 1f32 ) , 0f32 ) ;
1013
+ assert_eq ! ( 1f32 . abs_sub( & 0f32 ) , 1f32 ) ;
1014
+ assert_eq ! ( 1f32 . abs_sub( & -1f32 ) , 2f32 ) ;
1015
+ assert_eq ! ( neg_infinity. abs_sub( & 0f32 ) , 0f32 ) ;
1016
+ assert_eq ! ( infinity. abs_sub( & 1f32 ) , infinity) ;
1017
+ assert_eq ! ( 0f32 . abs_sub( & neg_infinity) , infinity) ;
1018
+ assert_eq ! ( 0f32 . abs_sub( & infinity) , 0f32 ) ;
1019
+ assert ! ( NaN . abs_sub( & -1f32 ) . is_NaN( ) ) ;
1020
+ assert ! ( 1f32 . abs_sub( & NaN ) . is_NaN( ) ) ;
1021
+ }
955
1022
1023
+ #[ test]
1024
+ fn test_signum ( ) {
956
1025
assert_eq ! ( infinity. signum( ) , 1f32 ) ;
957
1026
assert_eq ! ( 1f32 . signum( ) , 1f32 ) ;
958
1027
assert_eq ! ( 0f32 . signum( ) , 1f32 ) ;
@@ -961,7 +1030,10 @@ mod tests {
961
1030
assert_eq ! ( neg_infinity. signum( ) , -1f32 ) ;
962
1031
assert_eq ! ( ( 1f32 /neg_infinity) . signum( ) , -1f32 ) ;
963
1032
assert ! ( NaN . signum( ) . is_NaN( ) ) ;
1033
+ }
964
1034
1035
+ #[ test]
1036
+ fn test_is_positive ( ) {
965
1037
assert ! ( infinity. is_positive( ) ) ;
966
1038
assert ! ( 1f32 . is_positive( ) ) ;
967
1039
assert ! ( 0f32 . is_positive( ) ) ;
@@ -970,7 +1042,10 @@ mod tests {
970
1042
assert ! ( !neg_infinity. is_positive( ) ) ;
971
1043
assert ! ( !( 1f32 /neg_infinity) . is_positive( ) ) ;
972
1044
assert ! ( !NaN . is_positive( ) ) ;
1045
+ }
973
1046
1047
+ #[ test]
1048
+ fn test_is_negative ( ) {
974
1049
assert ! ( !infinity. is_negative( ) ) ;
975
1050
assert ! ( !1f32 . is_negative( ) ) ;
976
1051
assert ! ( !0f32 . is_negative( ) ) ;
@@ -995,4 +1070,28 @@ mod tests {
995
1070
assert_eq ! ( Primitive :: bits:: <f32 >( ) , sys:: size_of:: <f32 >( ) * 8 ) ;
996
1071
assert_eq ! ( Primitive :: bytes:: <f32 >( ) , sys:: size_of:: <f32 >( ) ) ;
997
1072
}
1073
+
1074
+ #[ test]
1075
+ fn test_is_normal ( ) {
1076
+ assert ! ( !Float :: NaN :: <f32 >( ) . is_normal( ) ) ;
1077
+ assert ! ( !Float :: infinity:: <f32 >( ) . is_normal( ) ) ;
1078
+ assert ! ( !Float :: neg_infinity:: <f32 >( ) . is_normal( ) ) ;
1079
+ assert ! ( !Zero :: zero:: <f32 >( ) . is_normal( ) ) ;
1080
+ assert ! ( !Float :: neg_zero:: <f32 >( ) . is_normal( ) ) ;
1081
+ assert ! ( 1f32 . is_normal( ) ) ;
1082
+ assert ! ( 1e-37f32 . is_normal( ) ) ;
1083
+ assert ! ( !1e-38f32 . is_normal( ) ) ;
1084
+ }
1085
+
1086
+ #[ test]
1087
+ fn test_classify ( ) {
1088
+ assert_eq ! ( Float :: NaN :: <f32 >( ) . classify( ) , FPNaN ) ;
1089
+ assert_eq ! ( Float :: infinity:: <f32 >( ) . classify( ) , FPInfinite ) ;
1090
+ assert_eq ! ( Float :: neg_infinity:: <f32 >( ) . classify( ) , FPInfinite ) ;
1091
+ assert_eq ! ( Zero :: zero:: <f32 >( ) . classify( ) , FPZero ) ;
1092
+ assert_eq ! ( Float :: neg_zero:: <f32 >( ) . classify( ) , FPZero ) ;
1093
+ assert_eq ! ( 1f32 . classify( ) , FPNormal ) ;
1094
+ assert_eq ! ( 1e-37f32 . classify( ) , FPNormal ) ;
1095
+ assert_eq ! ( 1e-38f32 . classify( ) , FPSubnormal ) ;
1096
+ }
998
1097
}
0 commit comments