@@ -719,7 +719,7 @@ assume_usize_width! {
719
719
}
720
720
721
721
macro_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 ) => {
723
723
mod $modname {
724
724
#[ test]
725
725
fn min( ) {
@@ -874,11 +874,21 @@ macro_rules! test_float {
874
874
// test if large differences in magnitude are still correctly computed.
875
875
// NOTE: that because of how small x and y are, x + y can never overflow
876
876
// 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 {
878
880
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) ;
882
892
}
883
893
}
884
894
}
@@ -913,7 +923,8 @@ test_float!(
913
923
f32 :: NAN ,
914
924
f32 :: MIN ,
915
925
f32 :: MAX ,
916
- f32 :: MIN_POSITIVE
926
+ f32 :: MIN_POSITIVE ,
927
+ f32 :: MAX_EXP
917
928
) ;
918
929
test_float ! (
919
930
f64 ,
@@ -923,5 +934,6 @@ test_float!(
923
934
f64 :: NAN ,
924
935
f64 :: MIN ,
925
936
f64 :: MAX ,
926
- f64 :: MIN_POSITIVE
937
+ f64 :: MIN_POSITIVE ,
938
+ f64 :: MAX_EXP
927
939
) ;
0 commit comments