1
1
use core:: num:: dec2flt:: float:: RawFloat ;
2
2
use core:: num:: dec2flt:: lemire:: compute_float;
3
3
4
+ #[ cfg( any( target_arch = "x86" , all( target_arch = "aarch64" , target_feature = "neon" ) ) ) ]
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
+
4
10
fn compute_float32 ( q : i64 , w : u64 ) -> ( i32 , u64 ) {
5
11
let fp = compute_float :: < f32 > ( q, w) ;
6
12
( fp. p_biased , fp. m )
@@ -11,23 +17,73 @@ fn compute_float64(q: i64, w: u64) -> (i32, u64) {
11
17
( fp. p_biased , fp. m )
12
18
}
13
19
20
+ // FIXME(f16_f128): enable on all targets once possible.
21
+ #[ test]
22
+ #[ cfg( any( target_arch = "x86" , all( target_arch = "aarch64" , target_feature = "neon" ) ) ) ]
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
+
14
58
#[ test]
15
59
fn 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
+
16
64
// 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 ) ) ;
28
84
// 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 ) ) ;
31
87
32
88
// Check the rounding point between infinity and the next representable number down
33
89
assert_eq ! ( compute_float32( 38 , 3 ) , ( f32 :: INFINITE_POWER - 1 , 6402534 ) ) ;
@@ -37,23 +93,38 @@ fn compute_float_f32_rounding() {
37
93
38
94
#[ test]
39
95
fn 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
+
40
100
// 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
+ ) ;
59
130
}
0 commit comments