@@ -66,7 +66,7 @@ fn test_validate() {
66
66
}
67
67
68
68
#[ test]
69
- fn test_check ( ) {
69
+ fn test_validate_real ( ) {
70
70
// Most of the arbitrary values come from checking against <http://weitz.de/ieee/>.
71
71
let r = & BigRational :: from_float ( 10.0 ) . unwrap ( ) ;
72
72
FloatRes :: < f32 > :: validate_real ( r. clone ( ) , 10 , 0 ) . unwrap ( ) ;
@@ -88,6 +88,61 @@ fn test_check() {
88
88
FloatRes :: < f32 > :: validate_real ( r. clone ( ) , -0b100110100101001000101100 , -13 ) . unwrap_err ( ) ;
89
89
}
90
90
91
+ #[ test]
92
+ #[ allow( unused) ]
93
+ fn test_validate_real_rounding ( ) {
94
+ // Check that we catch when values don't round to even.
95
+
96
+ // For f32, the cutoff between 1.0 and the next value up (1.0000001) is
97
+ // 1.000000059604644775390625. Anything below it should round down, anything above it should
98
+ // round up, and the value itself should round _down_ because `1.0` has an even significand but
99
+ // 1.0000001 is odd.
100
+ let v1_low_down = Rational :: parse ( "1.00000005960464477539062499999" ) . expect_finite ( ) ;
101
+ let v1_mid_down = Rational :: parse ( "1.000000059604644775390625" ) . expect_finite ( ) ;
102
+ let v1_high_up = Rational :: parse ( "1.00000005960464477539062500001" ) . expect_finite ( ) ;
103
+
104
+ let exp = -( f32:: MAN_BITS as i32 ) ;
105
+ let v1_down_sig = 1 << f32:: MAN_BITS ;
106
+ let v1_up_sig = ( 1 << f32:: MAN_BITS ) | 0b1 ;
107
+
108
+ FloatRes :: < f32 > :: validate_real ( v1_low_down. clone ( ) , v1_down_sig, exp) . unwrap ( ) ;
109
+ FloatRes :: < f32 > :: validate_real ( v1_mid_down. clone ( ) , v1_down_sig, exp) . unwrap ( ) ;
110
+ FloatRes :: < f32 > :: validate_real ( v1_high_up. clone ( ) , v1_up_sig, exp) . unwrap ( ) ;
111
+ FloatRes :: < f32 > :: validate_real ( -v1_low_down. clone ( ) , -v1_down_sig, exp) . unwrap ( ) ;
112
+ FloatRes :: < f32 > :: validate_real ( -v1_mid_down. clone ( ) , -v1_down_sig, exp) . unwrap ( ) ;
113
+ FloatRes :: < f32 > :: validate_real ( -v1_high_up. clone ( ) , -v1_up_sig, exp) . unwrap ( ) ;
114
+
115
+ // 1.000000178813934326171875 is between 1.0000001 and the next value up, 1.0000002. The middle
116
+ // value here should round _up_ since 1.0000002 has an even mantissa.
117
+ let v2_low_down = Rational :: parse ( "1.00000017881393432617187499999" ) . expect_finite ( ) ;
118
+ let v2_mid_up = Rational :: parse ( "1.000000178813934326171875" ) . expect_finite ( ) ;
119
+ let v2_high_up = Rational :: parse ( "1.00000017881393432617187500001" ) . expect_finite ( ) ;
120
+
121
+ let v2_down_sig = v1_up_sig;
122
+ let v2_up_sig = ( 1 << f32:: MAN_BITS ) | 0b10 ;
123
+
124
+ FloatRes :: < f32 > :: validate_real ( v2_low_down. clone ( ) , v2_down_sig, exp) . unwrap ( ) ;
125
+ FloatRes :: < f32 > :: validate_real ( v2_mid_up. clone ( ) , v2_up_sig, exp) . unwrap ( ) ;
126
+ FloatRes :: < f32 > :: validate_real ( v2_high_up. clone ( ) , v2_up_sig, exp) . unwrap ( ) ;
127
+ FloatRes :: < f32 > :: validate_real ( -v2_low_down. clone ( ) , -v2_down_sig, exp) . unwrap ( ) ;
128
+ FloatRes :: < f32 > :: validate_real ( -v2_mid_up. clone ( ) , -v2_up_sig, exp) . unwrap ( ) ;
129
+ FloatRes :: < f32 > :: validate_real ( -v2_high_up. clone ( ) , -v2_up_sig, exp) . unwrap ( ) ;
130
+
131
+ // Rounding the wrong direction should error
132
+ for res in [
133
+ FloatRes :: < f32 > :: validate_real ( v1_mid_down. clone ( ) , v1_up_sig, exp) ,
134
+ FloatRes :: < f32 > :: validate_real ( v2_mid_up. clone ( ) , v2_down_sig, exp) ,
135
+ FloatRes :: < f32 > :: validate_real ( -v1_mid_down. clone ( ) , -v1_up_sig, exp) ,
136
+ FloatRes :: < f32 > :: validate_real ( -v2_mid_up. clone ( ) , -v2_down_sig, exp) ,
137
+ ] {
138
+ let e = res. unwrap_err ( ) ;
139
+ let CheckFailure :: InvalidReal { incorrect_midpoint_rounding : true , .. } = e else {
140
+ panic ! ( "{e:?}" ) ;
141
+ } ;
142
+ }
143
+ }
144
+
145
+ /// Just a quick check that the constants are what we expect.
91
146
#[ test]
92
147
fn check_constants ( ) {
93
148
assert_eq ! ( f32 :: constants( ) . max. to_f32( ) . unwrap( ) , f32 :: MAX ) ;
0 commit comments