@@ -241,6 +241,32 @@ pub trait FloatCore: Num + NumCast + Neg<Output = Self> + PartialOrd + Copy {
241241 self . classify ( ) == FpCategory :: Normal
242242 }
243243
244+ /// Returns `true` if the number is [subnormal].
245+ ///
246+ /// ```
247+ /// use num_traits::float::FloatCore;
248+ /// use std::f64;
249+ ///
250+ /// let min = f64::MIN_POSITIVE; // 2.2250738585072014e-308_f64
251+ /// let max = f64::MAX;
252+ /// let lower_than_min = 1.0e-308_f64;
253+ /// let zero = 0.0_f64;
254+ ///
255+ /// assert!(!min.is_subnormal());
256+ /// assert!(!max.is_subnormal());
257+ ///
258+ /// assert!(!zero.is_subnormal());
259+ /// assert!(!f64::NAN.is_subnormal());
260+ /// assert!(!f64::INFINITY.is_subnormal());
261+ /// // Values between `0` and `min` are Subnormal.
262+ /// assert!(lower_than_min.is_subnormal());
263+ /// ```
264+ /// [subnormal]: https://en.wikipedia.org/wiki/Subnormal_number
265+ #[ inline]
266+ fn is_subnormal ( self ) -> bool {
267+ self . classify ( ) == FpCategory :: Subnormal
268+ }
269+
244270 /// Returns the floating point category of the number. If only one property
245271 /// is going to be tested, it is generally faster to use the specific
246272 /// predicate instead.
@@ -918,6 +944,11 @@ impl FloatCore for f64 {
918944 Self :: to_radians( self ) -> Self ;
919945 }
920946
947+ #[ cfg( has_is_subnormal) ]
948+ forward ! {
949+ Self :: is_subnormal( self ) -> bool ;
950+ }
951+
921952 #[ cfg( all( not( feature = "std" ) , feature = "libm" ) ) ]
922953 forward ! {
923954 libm:: floor as floor( self ) -> Self ;
@@ -1123,9 +1154,35 @@ pub trait Float: Num + Copy + NumCast + PartialOrd + Neg<Output = Self> {
11231154 /// // Values between `0` and `min` are Subnormal.
11241155 /// assert!(!lower_than_min.is_normal());
11251156 /// ```
1126- /// [subnormal]: http://en.wikipedia.org/wiki/Denormal_number
1157+ /// [subnormal]: http://en.wikipedia.org/wiki/Subnormal_number
11271158 fn is_normal ( self ) -> bool ;
11281159
1160+ /// Returns `true` if the number is [subnormal].
1161+ ///
1162+ /// ```
1163+ /// use num_traits::Float;
1164+ /// use std::f64;
1165+ ///
1166+ /// let min = f64::MIN_POSITIVE; // 2.2250738585072014e-308_f64
1167+ /// let max = f64::MAX;
1168+ /// let lower_than_min = 1.0e-308_f64;
1169+ /// let zero = 0.0_f64;
1170+ ///
1171+ /// assert!(!min.is_subnormal());
1172+ /// assert!(!max.is_subnormal());
1173+ ///
1174+ /// assert!(!zero.is_subnormal());
1175+ /// assert!(!f64::NAN.is_subnormal());
1176+ /// assert!(!f64::INFINITY.is_subnormal());
1177+ /// // Values between `0` and `min` are Subnormal.
1178+ /// assert!(lower_than_min.is_subnormal());
1179+ /// ```
1180+ /// [subnormal]: https://en.wikipedia.org/wiki/Subnormal_number
1181+ #[ inline]
1182+ fn is_subnormal ( self ) -> bool {
1183+ self . classify ( ) == FpCategory :: Subnormal
1184+ }
1185+
11291186 /// Returns the floating point category of the number. If only one property
11301187 /// is going to be tested, it is generally faster to use the specific
11311188 /// predicate instead.
@@ -1959,9 +2016,13 @@ macro_rules! float_impl_std {
19592016 }
19602017
19612018 #[ cfg( has_copysign) ]
1962- #[ inline]
1963- fn copysign( self , sign: Self ) -> Self {
1964- Self :: copysign( self , sign)
2019+ forward! {
2020+ Self :: copysign( self , sign: Self ) -> Self ;
2021+ }
2022+
2023+ #[ cfg( has_is_subnormal) ]
2024+ forward! {
2025+ Self :: is_subnormal( self ) -> bool ;
19652026 }
19662027 }
19672028 } ;
@@ -2318,6 +2379,7 @@ mod tests {
23182379 assert ! ( p. is_sign_positive( ) ) ;
23192380 assert ! ( n. is_sign_negative( ) ) ;
23202381 assert ! ( nan. is_nan( ) ) ;
2382+ assert ! ( !nan. is_subnormal( ) ) ;
23212383
23222384 assert_eq ! ( p, p. copysign( p) ) ;
23232385 assert_eq ! ( p. neg( ) , p. copysign( n) ) ;
@@ -2328,4 +2390,19 @@ mod tests {
23282390 assert ! ( nan. copysign( p) . is_sign_positive( ) ) ;
23292391 assert ! ( nan. copysign( n) . is_sign_negative( ) ) ;
23302392 }
2393+
2394+ #[ cfg( any( feature = "std" , feature = "libm" ) ) ]
2395+ fn test_subnormal < F : crate :: float:: Float + :: core:: fmt:: Debug > ( ) {
2396+ let min_positive = F :: min_positive_value ( ) ;
2397+ let lower_than_min = min_positive / F :: from ( 2.0f32 ) . unwrap ( ) ;
2398+ assert ! ( !min_positive. is_subnormal( ) ) ;
2399+ assert ! ( lower_than_min. is_subnormal( ) ) ;
2400+ }
2401+
2402+ #[ test]
2403+ #[ cfg( any( feature = "std" , feature = "libm" ) ) ]
2404+ fn subnormal ( ) {
2405+ test_subnormal :: < f64 > ( ) ;
2406+ test_subnormal :: < f32 > ( ) ;
2407+ }
23312408}
0 commit comments