11use core:: num:: dec2flt:: float:: RawFloat ;
22use core:: num:: dec2flt:: lemire:: compute_float;
33
4+ #[ cfg( target_has_reliable_f16) ]
5+ fn compute_float16 ( q : i64 , w : u64 ) -> ( i32 , u64 ) {
6+ let fp = compute_float :: < f16 > ( q, w) ;
7+ ( fp. p_biased , fp. m )
8+ }
9+
410fn compute_float32 ( q : i64 , w : u64 ) -> ( i32 , u64 ) {
511 let fp = compute_float :: < f32 > ( q, w) ;
612 ( fp. p_biased , fp. m )
@@ -11,23 +17,73 @@ fn compute_float64(q: i64, w: u64) -> (i32, u64) {
1117 ( fp. p_biased , fp. m )
1218}
1319
20+ // FIXME(f16_f128): enable on all targets once possible.
21+ #[ test]
22+ #[ cfg( target_has_reliable_f16) ]
23+ fn compute_float_f16_rounding ( ) {
24+ // The maximum integer that cna be converted to a `f16` without lost precision.
25+ let val = 1 << 11 ;
26+ let scale = 10_u64 . pow ( 10 ) ;
27+
28+ // These test near-halfway cases for half-precision floats.
29+ assert_eq ! ( compute_float16( 0 , val) , ( 26 , 0 ) ) ;
30+ assert_eq ! ( compute_float16( 0 , val + 1 ) , ( 26 , 0 ) ) ;
31+ assert_eq ! ( compute_float16( 0 , val + 2 ) , ( 26 , 1 ) ) ;
32+ assert_eq ! ( compute_float16( 0 , val + 3 ) , ( 26 , 2 ) ) ;
33+ assert_eq ! ( compute_float16( 0 , val + 4 ) , ( 26 , 2 ) ) ;
34+
35+ // For the next power up, the two nearest representable numbers are twice as far apart.
36+ let val2 = 1 << 12 ;
37+ assert_eq ! ( compute_float16( 0 , val2) , ( 27 , 0 ) ) ;
38+ assert_eq ! ( compute_float16( 0 , val2 + 2 ) , ( 27 , 0 ) ) ;
39+ assert_eq ! ( compute_float16( 0 , val2 + 4 ) , ( 27 , 1 ) ) ;
40+ assert_eq ! ( compute_float16( 0 , val2 + 6 ) , ( 27 , 2 ) ) ;
41+ assert_eq ! ( compute_float16( 0 , val2 + 8 ) , ( 27 , 2 ) ) ;
42+
43+ // These are examples of the above tests, with digits from the exponent shifted
44+ // to the mantissa.
45+ assert_eq ! ( compute_float16( -10 , val * scale) , ( 26 , 0 ) ) ;
46+ assert_eq ! ( compute_float16( -10 , ( val + 1 ) * scale) , ( 26 , 0 ) ) ;
47+ assert_eq ! ( compute_float16( -10 , ( val + 2 ) * scale) , ( 26 , 1 ) ) ;
48+ // Let's check the lines to see if anything is different in table...
49+ assert_eq ! ( compute_float16( -10 , ( val + 3 ) * scale) , ( 26 , 2 ) ) ;
50+ assert_eq ! ( compute_float16( -10 , ( val + 4 ) * scale) , ( 26 , 2 ) ) ;
51+
52+ // Check the rounding point between infinity and the next representable number down
53+ assert_eq ! ( compute_float16( 4 , 6 ) , ( f16:: INFINITE_POWER - 1 , 851 ) ) ;
54+ assert_eq ! ( compute_float16( 4 , 7 ) , ( f16:: INFINITE_POWER , 0 ) ) ; // infinity
55+ assert_eq ! ( compute_float16( 2 , 655 ) , ( f16:: INFINITE_POWER - 1 , 1023 ) ) ;
56+ }
57+
1458#[ test]
1559fn compute_float_f32_rounding ( ) {
60+ // the maximum integer that cna be converted to a `f32` without lost precision.
61+ let val = 1 << 24 ;
62+ let scale = 10_u64 . pow ( 10 ) ;
63+
1664 // These test near-halfway cases for single-precision floats.
17- assert_eq ! ( compute_float32( 0 , 16777216 ) , ( 151 , 0 ) ) ;
18- assert_eq ! ( compute_float32( 0 , 16777217 ) , ( 151 , 0 ) ) ;
19- assert_eq ! ( compute_float32( 0 , 16777218 ) , ( 151 , 1 ) ) ;
20- assert_eq ! ( compute_float32( 0 , 16777219 ) , ( 151 , 2 ) ) ;
21- assert_eq ! ( compute_float32( 0 , 16777220 ) , ( 151 , 2 ) ) ;
22-
23- // These are examples of the above tests, with
24- // digits from the exponent shifted to the mantissa.
25- assert_eq ! ( compute_float32( -10 , 167772160000000000 ) , ( 151 , 0 ) ) ;
26- assert_eq ! ( compute_float32( -10 , 167772170000000000 ) , ( 151 , 0 ) ) ;
27- assert_eq ! ( compute_float32( -10 , 167772180000000000 ) , ( 151 , 1 ) ) ;
65+ assert_eq ! ( compute_float32( 0 , val) , ( 151 , 0 ) ) ;
66+ assert_eq ! ( compute_float32( 0 , val + 1 ) , ( 151 , 0 ) ) ;
67+ assert_eq ! ( compute_float32( 0 , val + 2 ) , ( 151 , 1 ) ) ;
68+ assert_eq ! ( compute_float32( 0 , val + 3 ) , ( 151 , 2 ) ) ;
69+ assert_eq ! ( compute_float32( 0 , val + 4 ) , ( 151 , 2 ) ) ;
70+
71+ // For the next power up, the two nearest representable numbers are twice as far apart.
72+ let val2 = 1 << 25 ;
73+ assert_eq ! ( compute_float32( 0 , val2) , ( 152 , 0 ) ) ;
74+ assert_eq ! ( compute_float32( 0 , val2 + 2 ) , ( 152 , 0 ) ) ;
75+ assert_eq ! ( compute_float32( 0 , val2 + 4 ) , ( 152 , 1 ) ) ;
76+ assert_eq ! ( compute_float32( 0 , val2 + 6 ) , ( 152 , 2 ) ) ;
77+ assert_eq ! ( compute_float32( 0 , val2 + 8 ) , ( 152 , 2 ) ) ;
78+
79+ // These are examples of the above tests, with digits from the exponent shifted
80+ // to the mantissa.
81+ assert_eq ! ( compute_float32( -10 , val * scale) , ( 151 , 0 ) ) ;
82+ assert_eq ! ( compute_float32( -10 , ( val + 1 ) * scale) , ( 151 , 0 ) ) ;
83+ assert_eq ! ( compute_float32( -10 , ( val + 2 ) * scale) , ( 151 , 1 ) ) ;
2884 // Let's check the lines to see if anything is different in table...
29- assert_eq ! ( compute_float32( -10 , 167772190000000000 ) , ( 151 , 2 ) ) ;
30- assert_eq ! ( compute_float32( -10 , 167772200000000000 ) , ( 151 , 2 ) ) ;
85+ assert_eq ! ( compute_float32( -10 , ( val + 3 ) * scale ) , ( 151 , 2 ) ) ;
86+ assert_eq ! ( compute_float32( -10 , ( val + 4 ) * scale ) , ( 151 , 2 ) ) ;
3187
3288 // Check the rounding point between infinity and the next representable number down
3389 assert_eq ! ( compute_float32( 38 , 3 ) , ( f32 :: INFINITE_POWER - 1 , 6402534 ) ) ;
@@ -37,23 +93,38 @@ fn compute_float_f32_rounding() {
3793
3894#[ test]
3995fn compute_float_f64_rounding ( ) {
96+ // The maximum integer that cna be converted to a `f64` without lost precision.
97+ let val = 1 << 53 ;
98+ let scale = 1000 ;
99+
40100 // These test near-halfway cases for double-precision floats.
41- assert_eq ! ( compute_float64( 0 , 9007199254740992 ) , ( 1076 , 0 ) ) ;
42- assert_eq ! ( compute_float64( 0 , 9007199254740993 ) , ( 1076 , 0 ) ) ;
43- assert_eq ! ( compute_float64( 0 , 9007199254740994 ) , ( 1076 , 1 ) ) ;
44- assert_eq ! ( compute_float64( 0 , 9007199254740995 ) , ( 1076 , 2 ) ) ;
45- assert_eq ! ( compute_float64( 0 , 9007199254740996 ) , ( 1076 , 2 ) ) ;
46- assert_eq ! ( compute_float64( 0 , 18014398509481984 ) , ( 1077 , 0 ) ) ;
47- assert_eq ! ( compute_float64( 0 , 18014398509481986 ) , ( 1077 , 0 ) ) ;
48- assert_eq ! ( compute_float64( 0 , 18014398509481988 ) , ( 1077 , 1 ) ) ;
49- assert_eq ! ( compute_float64( 0 , 18014398509481990 ) , ( 1077 , 2 ) ) ;
50- assert_eq ! ( compute_float64( 0 , 18014398509481992 ) , ( 1077 , 2 ) ) ;
51-
52- // These are examples of the above tests, with
53- // digits from the exponent shifted to the mantissa.
54- assert_eq ! ( compute_float64( -3 , 9007199254740992000 ) , ( 1076 , 0 ) ) ;
55- assert_eq ! ( compute_float64( -3 , 9007199254740993000 ) , ( 1076 , 0 ) ) ;
56- assert_eq ! ( compute_float64( -3 , 9007199254740994000 ) , ( 1076 , 1 ) ) ;
57- assert_eq ! ( compute_float64( -3 , 9007199254740995000 ) , ( 1076 , 2 ) ) ;
58- assert_eq ! ( compute_float64( -3 , 9007199254740996000 ) , ( 1076 , 2 ) ) ;
101+ assert_eq ! ( compute_float64( 0 , val) , ( 1076 , 0 ) ) ;
102+ assert_eq ! ( compute_float64( 0 , val + 1 ) , ( 1076 , 0 ) ) ;
103+ assert_eq ! ( compute_float64( 0 , val + 2 ) , ( 1076 , 1 ) ) ;
104+ assert_eq ! ( compute_float64( 0 , val + 3 ) , ( 1076 , 2 ) ) ;
105+ assert_eq ! ( compute_float64( 0 , val + 4 ) , ( 1076 , 2 ) ) ;
106+
107+ // For the next power up, the two nearest representable numbers are twice as far apart.
108+ let val2 = 1 << 54 ;
109+ assert_eq ! ( compute_float64( 0 , val2) , ( 1077 , 0 ) ) ;
110+ assert_eq ! ( compute_float64( 0 , val2 + 2 ) , ( 1077 , 0 ) ) ;
111+ assert_eq ! ( compute_float64( 0 , val2 + 4 ) , ( 1077 , 1 ) ) ;
112+ assert_eq ! ( compute_float64( 0 , val2 + 6 ) , ( 1077 , 2 ) ) ;
113+ assert_eq ! ( compute_float64( 0 , val2 + 8 ) , ( 1077 , 2 ) ) ;
114+
115+ // These are examples of the above tests, with digits from the exponent shifted
116+ // to the mantissa.
117+ assert_eq ! ( compute_float64( -3 , val * scale) , ( 1076 , 0 ) ) ;
118+ assert_eq ! ( compute_float64( -3 , ( val + 1 ) * scale) , ( 1076 , 0 ) ) ;
119+ assert_eq ! ( compute_float64( -3 , ( val + 2 ) * scale) , ( 1076 , 1 ) ) ;
120+ assert_eq ! ( compute_float64( -3 , ( val + 3 ) * scale) , ( 1076 , 2 ) ) ;
121+ assert_eq ! ( compute_float64( -3 , ( val + 4 ) * scale) , ( 1076 , 2 ) ) ;
122+
123+ // Check the rounding point between infinity and the next representable number down
124+ assert_eq ! ( compute_float64( 308 , 1 ) , ( f64 :: INFINITE_POWER - 1 , 506821272651936 ) ) ;
125+ assert_eq ! ( compute_float64( 308 , 2 ) , ( f64 :: INFINITE_POWER , 0 ) ) ; // infinity
126+ assert_eq ! (
127+ compute_float64( 292 , 17976931348623157 ) ,
128+ ( f64 :: INFINITE_POWER - 1 , 4503599627370495 )
129+ ) ;
59130}
0 commit comments