11use core:: num:: dec2flt:: float:: RawFloat ;
22use core:: num:: dec2flt:: lemire:: compute_float;
33
4+ #[ cfg( not( bootstrap) ) ]
5+ #[ cfg( target_has_reliable_f16) ]
6+ fn compute_float16 ( q : i64 , w : u64 ) -> ( i32 , u64 ) {
7+ let fp = compute_float :: < f16 > ( q, w) ;
8+ ( fp. p_biased , fp. m )
9+ }
10+
411fn compute_float32 ( q : i64 , w : u64 ) -> ( i32 , u64 ) {
512 let fp = compute_float :: < f32 > ( q, w) ;
613 ( fp. p_biased , fp. m )
@@ -11,23 +18,74 @@ fn compute_float64(q: i64, w: u64) -> (i32, u64) {
1118 ( fp. p_biased , fp. m )
1219}
1320
21+ // FIXME(f16_f128): enable on all targets once possible.
22+ #[ test]
23+ #[ cfg( not( bootstrap) ) ]
24+ #[ cfg( target_has_reliable_f16) ]
25+ fn compute_float_f16_rounding ( ) {
26+ // The maximum integer that cna be converted to a `f16` without lost precision.
27+ let val = 1 << 11 ;
28+ let scale = 10_u64 . pow ( 10 ) ;
29+
30+ // These test near-halfway cases for half-precision floats.
31+ assert_eq ! ( compute_float16( 0 , val) , ( 26 , 0 ) ) ;
32+ assert_eq ! ( compute_float16( 0 , val + 1 ) , ( 26 , 0 ) ) ;
33+ assert_eq ! ( compute_float16( 0 , val + 2 ) , ( 26 , 1 ) ) ;
34+ assert_eq ! ( compute_float16( 0 , val + 3 ) , ( 26 , 2 ) ) ;
35+ assert_eq ! ( compute_float16( 0 , val + 4 ) , ( 26 , 2 ) ) ;
36+
37+ // For the next power up, the two nearest representable numbers are twice as far apart.
38+ let val2 = 1 << 12 ;
39+ assert_eq ! ( compute_float16( 0 , val2) , ( 27 , 0 ) ) ;
40+ assert_eq ! ( compute_float16( 0 , val2 + 2 ) , ( 27 , 0 ) ) ;
41+ assert_eq ! ( compute_float16( 0 , val2 + 4 ) , ( 27 , 1 ) ) ;
42+ assert_eq ! ( compute_float16( 0 , val2 + 6 ) , ( 27 , 2 ) ) ;
43+ assert_eq ! ( compute_float16( 0 , val2 + 8 ) , ( 27 , 2 ) ) ;
44+
45+ // These are examples of the above tests, with digits from the exponent shifted
46+ // to the mantissa.
47+ assert_eq ! ( compute_float16( -10 , val * scale) , ( 26 , 0 ) ) ;
48+ assert_eq ! ( compute_float16( -10 , ( val + 1 ) * scale) , ( 26 , 0 ) ) ;
49+ assert_eq ! ( compute_float16( -10 , ( val + 2 ) * scale) , ( 26 , 1 ) ) ;
50+ // Let's check the lines to see if anything is different in table...
51+ assert_eq ! ( compute_float16( -10 , ( val + 3 ) * scale) , ( 26 , 2 ) ) ;
52+ assert_eq ! ( compute_float16( -10 , ( val + 4 ) * scale) , ( 26 , 2 ) ) ;
53+
54+ // Check the rounding point between infinity and the next representable number down
55+ assert_eq ! ( compute_float16( 4 , 6 ) , ( f16:: INFINITE_POWER - 1 , 851 ) ) ;
56+ assert_eq ! ( compute_float16( 4 , 7 ) , ( f16:: INFINITE_POWER , 0 ) ) ; // infinity
57+ assert_eq ! ( compute_float16( 2 , 655 ) , ( f16:: INFINITE_POWER - 1 , 1023 ) ) ;
58+ }
59+
1460#[ test]
1561fn compute_float_f32_rounding ( ) {
62+ // the maximum integer that cna be converted to a `f32` without lost precision.
63+ let val = 1 << 24 ;
64+ let scale = 10_u64 . pow ( 10 ) ;
65+
1666 // 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 ) ) ;
67+ assert_eq ! ( compute_float32( 0 , val) , ( 151 , 0 ) ) ;
68+ assert_eq ! ( compute_float32( 0 , val + 1 ) , ( 151 , 0 ) ) ;
69+ assert_eq ! ( compute_float32( 0 , val + 2 ) , ( 151 , 1 ) ) ;
70+ assert_eq ! ( compute_float32( 0 , val + 3 ) , ( 151 , 2 ) ) ;
71+ assert_eq ! ( compute_float32( 0 , val + 4 ) , ( 151 , 2 ) ) ;
72+
73+ // For the next power up, the two nearest representable numbers are twice as far apart.
74+ let val2 = 1 << 25 ;
75+ assert_eq ! ( compute_float32( 0 , val2) , ( 152 , 0 ) ) ;
76+ assert_eq ! ( compute_float32( 0 , val2 + 2 ) , ( 152 , 0 ) ) ;
77+ assert_eq ! ( compute_float32( 0 , val2 + 4 ) , ( 152 , 1 ) ) ;
78+ assert_eq ! ( compute_float32( 0 , val2 + 6 ) , ( 152 , 2 ) ) ;
79+ assert_eq ! ( compute_float32( 0 , val2 + 8 ) , ( 152 , 2 ) ) ;
80+
81+ // These are examples of the above tests, with digits from the exponent shifted
82+ // to the mantissa.
83+ assert_eq ! ( compute_float32( -10 , val * scale) , ( 151 , 0 ) ) ;
84+ assert_eq ! ( compute_float32( -10 , ( val + 1 ) * scale) , ( 151 , 0 ) ) ;
85+ assert_eq ! ( compute_float32( -10 , ( val + 2 ) * scale) , ( 151 , 1 ) ) ;
2886 // 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 ) ) ;
87+ assert_eq ! ( compute_float32( -10 , ( val + 3 ) * scale ) , ( 151 , 2 ) ) ;
88+ assert_eq ! ( compute_float32( -10 , ( val + 4 ) * scale ) , ( 151 , 2 ) ) ;
3189
3290 // Check the rounding point between infinity and the next representable number down
3391 assert_eq ! ( compute_float32( 38 , 3 ) , ( f32 :: INFINITE_POWER - 1 , 6402534 ) ) ;
@@ -37,23 +95,38 @@ fn compute_float_f32_rounding() {
3795
3896#[ test]
3997fn compute_float_f64_rounding ( ) {
98+ // The maximum integer that cna be converted to a `f64` without lost precision.
99+ let val = 1 << 53 ;
100+ let scale = 1000 ;
101+
40102 // 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 ) ) ;
103+ assert_eq ! ( compute_float64( 0 , val) , ( 1076 , 0 ) ) ;
104+ assert_eq ! ( compute_float64( 0 , val + 1 ) , ( 1076 , 0 ) ) ;
105+ assert_eq ! ( compute_float64( 0 , val + 2 ) , ( 1076 , 1 ) ) ;
106+ assert_eq ! ( compute_float64( 0 , val + 3 ) , ( 1076 , 2 ) ) ;
107+ assert_eq ! ( compute_float64( 0 , val + 4 ) , ( 1076 , 2 ) ) ;
108+
109+ // For the next power up, the two nearest representable numbers are twice as far apart.
110+ let val2 = 1 << 54 ;
111+ assert_eq ! ( compute_float64( 0 , val2) , ( 1077 , 0 ) ) ;
112+ assert_eq ! ( compute_float64( 0 , val2 + 2 ) , ( 1077 , 0 ) ) ;
113+ assert_eq ! ( compute_float64( 0 , val2 + 4 ) , ( 1077 , 1 ) ) ;
114+ assert_eq ! ( compute_float64( 0 , val2 + 6 ) , ( 1077 , 2 ) ) ;
115+ assert_eq ! ( compute_float64( 0 , val2 + 8 ) , ( 1077 , 2 ) ) ;
116+
117+ // These are examples of the above tests, with digits from the exponent shifted
118+ // to the mantissa.
119+ assert_eq ! ( compute_float64( -3 , val * scale) , ( 1076 , 0 ) ) ;
120+ assert_eq ! ( compute_float64( -3 , ( val + 1 ) * scale) , ( 1076 , 0 ) ) ;
121+ assert_eq ! ( compute_float64( -3 , ( val + 2 ) * scale) , ( 1076 , 1 ) ) ;
122+ assert_eq ! ( compute_float64( -3 , ( val + 3 ) * scale) , ( 1076 , 2 ) ) ;
123+ assert_eq ! ( compute_float64( -3 , ( val + 4 ) * scale) , ( 1076 , 2 ) ) ;
124+
125+ // Check the rounding point between infinity and the next representable number down
126+ assert_eq ! ( compute_float64( 308 , 1 ) , ( f64 :: INFINITE_POWER - 1 , 506821272651936 ) ) ;
127+ assert_eq ! ( compute_float64( 308 , 2 ) , ( f64 :: INFINITE_POWER , 0 ) ) ; // infinity
128+ assert_eq ! (
129+ compute_float64( 292 , 17976931348623157 ) ,
130+ ( f64 :: INFINITE_POWER - 1 , 4503599627370495 )
131+ ) ;
59132}
0 commit comments