@@ -719,7 +719,7 @@ assume_usize_width! {
719719}
720720
721721macro_rules! test_float {
722- ( $modname: ident, $fty: ty, $inf: expr, $neginf: expr, $nan: expr, $min: expr, $max: expr, $min_pos: expr) => {
722+ ( $modname: ident, $fty: ty, $inf: expr, $neginf: expr, $nan: expr, $min: expr, $max: expr, $min_pos: expr, $max_exp : expr ) => {
723723 mod $modname {
724724 #[ test]
725725 fn min( ) {
@@ -874,11 +874,21 @@ macro_rules! test_float {
874874 // test if large differences in magnitude are still correctly computed.
875875 // NOTE: that because of how small x and y are, x + y can never overflow
876876 // so (x + y) / 2.0 is always correct
877- for i in 64 ..128 {
877+ // in particular, `2.pow(i)` will never be at the max exponent, so it could
878+ // be safely doubled, while j is significantly smaller.
879+ for i in $max_exp. saturating_sub( 64 ) ..$max_exp {
878880 for j in 0 ..64u8 {
879- let x = ( 2.0f32 . powi( i) + f32 :: from( j) ) / 2.0 ;
880- let y = 2.0f32 . powi( i) . midpoint( f32 :: from( j) ) ;
881- assert_eq!( x, y) ;
881+ let large = <$fty>:: from( 2.0f32 ) . powi( i) ;
882+ // a much smaller number, such that there is no chance of overflow to test
883+ // potential double rounding in midpoint's implementation.
884+ let small = <$fty>:: from( 2.0f32 ) . powi( $max_exp - 1 )
885+ * <$fty>:: EPSILON
886+ * <$fty>:: from( j) ;
887+
888+ let naive = ( large + small) / 2.0 ;
889+ let midpoint = large. midpoint( small) ;
890+
891+ assert_eq!( naive, midpoint) ;
882892 }
883893 }
884894 }
@@ -913,7 +923,8 @@ test_float!(
913923 f32 :: NAN ,
914924 f32 :: MIN ,
915925 f32 :: MAX ,
916- f32 :: MIN_POSITIVE
926+ f32 :: MIN_POSITIVE ,
927+ f32 :: MAX_EXP
917928) ;
918929test_float ! (
919930 f64 ,
@@ -923,5 +934,6 @@ test_float!(
923934 f64 :: NAN ,
924935 f64 :: MIN ,
925936 f64 :: MAX ,
926- f64 :: MIN_POSITIVE
937+ f64 :: MIN_POSITIVE ,
938+ f64 :: MAX_EXP
927939) ;
0 commit comments