@@ -10,141 +10,149 @@ use super::Float;
10
10
/// which unfortunately isn't the easiest kind of code to read.
11
11
///
12
12
/// The algorithm is explained here: <https://blog.m-ou.se/floats/>
13
- mod int_to_float {
14
- pub fn u32_to_f32_bits ( i : u32 ) -> u32 {
15
- if i == 0 {
16
- return 0 ;
17
- }
18
- let n = i. leading_zeros ( ) ;
19
- let a = ( i << n) >> 8 ; // Significant bits, with bit 24 still in tact.
20
- let b = ( i << n) << 24 ; // Insignificant bits, only relevant for rounding.
21
- let m = a + ( ( b - ( b >> 31 & !a) ) >> 31 ) ; // Add one when we need to round up. Break ties to even.
22
- let e = 157 - n; // Exponent plus 127, minus one.
23
- ( e << 23 ) + m // + not |, so the mantissa can overflow into the exponent.
24
- }
25
-
26
- pub fn u32_to_f64_bits ( i : u32 ) -> u64 {
27
- if i == 0 {
28
- return 0 ;
29
- }
30
- let n = i. leading_zeros ( ) ;
31
- let m = ( i as u64 ) << ( 21 + n) ; // Significant bits, with bit 53 still in tact.
32
- let e = 1053 - n as u64 ; // Exponent plus 1023, minus one.
33
- ( e << 52 ) + m // Bit 53 of m will overflow into e.
34
- }
35
-
36
- pub fn u64_to_f32_bits ( i : u64 ) -> u32 {
37
- let n = i. leading_zeros ( ) ;
38
- let y = i. wrapping_shl ( n) ;
39
- let a = ( y >> 40 ) as u32 ; // Significant bits, with bit 24 still in tact.
40
- let b = ( y >> 8 | y & 0xFFFF ) as u32 ; // Insignificant bits, only relevant for rounding.
41
- let m = a + ( ( b - ( b >> 31 & !a) ) >> 31 ) ; // Add one when we need to round up. Break ties to even.
42
- let e = if i == 0 { 0 } else { 189 - n } ; // Exponent plus 127, minus one, except for zero.
43
- ( e << 23 ) + m // + not |, so the mantissa can overflow into the exponent.
44
- }
45
-
46
- pub fn u64_to_f64_bits ( i : u64 ) -> u64 {
47
- if i == 0 {
48
- return 0 ;
49
- }
50
- let n = i. leading_zeros ( ) ;
51
- let a = ( i << n) >> 11 ; // Significant bits, with bit 53 still in tact.
52
- let b = ( i << n) << 53 ; // Insignificant bits, only relevant for rounding.
53
- let m = a + ( ( b - ( b >> 63 & !a) ) >> 63 ) ; // Add one when we need to round up. Break ties to even.
54
- let e = 1085 - n as u64 ; // Exponent plus 1023, minus one.
55
- ( e << 52 ) + m // + not |, so the mantissa can overflow into the exponent.
56
- }
57
-
58
- pub fn u128_to_f32_bits ( i : u128 ) -> u32 {
59
- let n = i. leading_zeros ( ) ;
60
- let y = i. wrapping_shl ( n) ;
61
- let a = ( y >> 104 ) as u32 ; // Significant bits, with bit 24 still in tact.
62
- let b = ( y >> 72 ) as u32 | ( ( y << 32 ) >> 32 != 0 ) as u32 ; // Insignificant bits, only relevant for rounding.
63
- let m = a + ( ( b - ( b >> 31 & !a) ) >> 31 ) ; // Add one when we need to round up. Break ties to even.
64
- let e = if i == 0 { 0 } else { 253 - n } ; // Exponent plus 127, minus one, except for zero.
65
- ( e << 23 ) + m // + not |, so the mantissa can overflow into the exponent.
66
- }
67
-
68
- pub fn u128_to_f64_bits ( i : u128 ) -> u64 {
69
- let n = i. leading_zeros ( ) ;
70
- let y = i. wrapping_shl ( n) ;
71
- let a = ( y >> 75 ) as u64 ; // Significant bits, with bit 53 still in tact.
72
- let b = ( y >> 11 | y & 0xFFFF_FFFF ) as u64 ; // Insignificant bits, only relevant for rounding.
73
- let m = a + ( ( b - ( b >> 63 & !a) ) >> 63 ) ; // Add one when we need to round up. Break ties to even.
74
- let e = if i == 0 { 0 } else { 1149 - n as u64 } ; // Exponent plus 1023, minus one, except for zero.
75
- ( e << 52 ) + m // + not |, so the mantissa can overflow into the exponent.
13
+ fn int_to_float < I , F > ( i : I ) -> F
14
+ where
15
+ F : Float ,
16
+ I : Int < UnsignedInt : Int > ,
17
+ I :: UnsignedInt : CastInto < F :: Int > ,
18
+ F :: Int : CastFrom < u32 > ,
19
+ F :: Int : CastFrom < I > ,
20
+ F :: Int : From < bool > ,
21
+ F :: Int : CastInto < I :: UnsignedInt > ,
22
+ {
23
+ if i == I :: ZERO {
24
+ return F :: ZERO ;
76
25
}
26
+
27
+ let sign_bit: F :: Int = if I :: SIGNED {
28
+ F :: Int :: cast_from ( i >> ( I :: BITS - 1 ) ) << ( F :: BITS - 1 )
29
+ } else {
30
+ // Never used
31
+ F :: Int :: ZERO
32
+ } ;
33
+
34
+ let i = i. unsigned_abs ( ) ;
35
+ let n = i. leading_zeros ( ) ;
36
+
37
+ // Calculate the exponent from the integer's significant digits
38
+ let e = F :: Int :: cast_from ( I :: BITS + F :: EXPONENT_BIAS - 2 - n) ;
39
+
40
+ // The mantissa of `i`, still in `I`'s form (left shifted so the first bit is nonzero)
41
+ let i_m = i. wrapping_shl ( n) ;
42
+
43
+ let m: F :: Int = if F :: BITS > I :: BITS {
44
+ F :: Int :: cast_from ( i) << ( F :: SIGNIFICAND_BITS - I :: BITS + 1 + n)
45
+ } else {
46
+ // Shift the integer into the float's mantissa bits. Keep the lowest
47
+ // exponent bit intact.
48
+ let m_base = F :: Int :: cast_from ( i_m >> ( ( I :: BITS - F :: BITS ) + F :: EXPONENT_BITS ) ) ;
49
+
50
+ // Squash dropped bits into a single `F::Int` for comparison. The result will have
51
+ // no meaning outside of indicating rounding.
52
+ let dropped_bits: F :: Int = if F :: BITS == I :: BITS {
53
+ // Simple case
54
+
55
+ // Only the lowest `F::EXPONENT_BITS` bits will be truncated. Shift them
56
+ // to the highest position
57
+ ( i_m << ( F :: SIGNIFICAND_BITS + 1 ) ) . cast ( )
58
+ } else if F :: BITS * 2 == I :: BITS {
59
+ // Specialized case where the float is half the integer size
60
+
61
+ // The entire lower half of `i` will be truncated (masked portion), plus the
62
+ // next `EXPONENT_BITS` bits.
63
+ let mask: I :: UnsignedInt = ( F :: Int :: MAX >> ( F :: Int :: BITS / 2 ) ) . cast ( ) ;
64
+ ( i_m >> F :: EXPONENT_BITS | i_m & mask) . cast ( )
65
+ } else {
66
+ // Generic case
67
+
68
+ // Within the upper `F::BITS`, everything except for the signifcand
69
+ // gets truncated
70
+ let d1: F :: Int = ( i_m >> ( I :: BITS - F :: BITS - F :: SIGNIFICAND_BITS - 1 ) ) . cast ( ) ;
71
+
72
+ // The entire rest of `i_m` gets truncated. Zero the upper `F::BITS` then just
73
+ // check if it is nonzero.
74
+ let d2: F :: Int = ( i_m << F :: BITS >> F :: BITS != I :: UnsignedInt :: ZERO ) . into ( ) ;
75
+
76
+ d1 | d2
77
+ } ;
78
+
79
+ // Branchlessly extract a `1` if rounding up should happen
80
+ let m_adj = ( dropped_bits - ( dropped_bits >> ( F :: BITS - 1 ) & !m_base) ) >> ( F :: BITS - 1 ) ;
81
+
82
+ // Add one when we need to round up. Break ties to even.
83
+ m_base + m_adj
84
+ } ;
85
+
86
+ // + not |, so the mantissa can overflow into the exponent.
87
+ let urepr = ( e << F :: SIGNIFICAND_BITS ) + m;
88
+ let repr: F :: Int = if I :: SIGNED { urepr | sign_bit } else { urepr } ;
89
+
90
+ F :: from_repr ( repr)
77
91
}
78
92
79
93
// Conversions from unsigned integers to floats.
80
94
intrinsics ! {
81
95
#[ arm_aeabi_alias = __aeabi_ui2f]
82
96
pub extern "C" fn __floatunsisf( i: u32 ) -> f32 {
83
- f32 :: from_bits ( int_to_float:: u32_to_f32_bits ( i ) )
97
+ int_to_float( i )
84
98
}
85
99
86
100
#[ arm_aeabi_alias = __aeabi_ui2d]
87
101
pub extern "C" fn __floatunsidf( i: u32 ) -> f64 {
88
- f64 :: from_bits ( int_to_float:: u32_to_f64_bits ( i ) )
102
+ int_to_float( i )
89
103
}
90
104
91
105
#[ arm_aeabi_alias = __aeabi_ul2f]
92
106
pub extern "C" fn __floatundisf( i: u64 ) -> f32 {
93
- f32 :: from_bits ( int_to_float:: u64_to_f32_bits ( i ) )
107
+ int_to_float( i )
94
108
}
95
109
96
110
#[ arm_aeabi_alias = __aeabi_ul2d]
97
111
pub extern "C" fn __floatundidf( i: u64 ) -> f64 {
98
- f64 :: from_bits ( int_to_float:: u64_to_f64_bits ( i ) )
112
+ int_to_float( i )
99
113
}
100
114
101
115
#[ cfg_attr( target_os = "uefi" , unadjusted_on_win64) ]
102
116
pub extern "C" fn __floatuntisf( i: u128 ) -> f32 {
103
- f32 :: from_bits ( int_to_float:: u128_to_f32_bits ( i ) )
117
+ int_to_float( i )
104
118
}
105
119
106
120
#[ cfg_attr( target_os = "uefi" , unadjusted_on_win64) ]
107
121
pub extern "C" fn __floatuntidf( i: u128 ) -> f64 {
108
- f64 :: from_bits ( int_to_float:: u128_to_f64_bits ( i ) )
122
+ int_to_float( i )
109
123
}
110
124
}
111
125
112
126
// Conversions from signed integers to floats.
113
127
intrinsics ! {
114
128
#[ arm_aeabi_alias = __aeabi_i2f]
115
129
pub extern "C" fn __floatsisf( i: i32 ) -> f32 {
116
- let sign_bit = ( ( i >> 31 ) as u32 ) << 31 ;
117
- f32 :: from_bits( int_to_float:: u32_to_f32_bits( i. unsigned_abs( ) ) | sign_bit)
130
+ int_to_float( i)
118
131
}
119
132
120
133
#[ arm_aeabi_alias = __aeabi_i2d]
121
134
pub extern "C" fn __floatsidf( i: i32 ) -> f64 {
122
- let sign_bit = ( ( i >> 31 ) as u64 ) << 63 ;
123
- f64 :: from_bits( int_to_float:: u32_to_f64_bits( i. unsigned_abs( ) ) | sign_bit)
135
+ int_to_float( i)
124
136
}
125
137
126
138
#[ arm_aeabi_alias = __aeabi_l2f]
127
139
pub extern "C" fn __floatdisf( i: i64 ) -> f32 {
128
- let sign_bit = ( ( i >> 63 ) as u32 ) << 31 ;
129
- f32 :: from_bits( int_to_float:: u64_to_f32_bits( i. unsigned_abs( ) ) | sign_bit)
140
+ int_to_float( i)
130
141
}
131
142
132
143
#[ arm_aeabi_alias = __aeabi_l2d]
133
144
pub extern "C" fn __floatdidf( i: i64 ) -> f64 {
134
- let sign_bit = ( ( i >> 63 ) as u64 ) << 63 ;
135
- f64 :: from_bits( int_to_float:: u64_to_f64_bits( i. unsigned_abs( ) ) | sign_bit)
145
+ int_to_float( i)
136
146
}
137
147
138
148
#[ cfg_attr( target_os = "uefi" , unadjusted_on_win64) ]
139
149
pub extern "C" fn __floattisf( i: i128 ) -> f32 {
140
- let sign_bit = ( ( i >> 127 ) as u32 ) << 31 ;
141
- f32 :: from_bits( int_to_float:: u128_to_f32_bits( i. unsigned_abs( ) ) | sign_bit)
150
+ int_to_float( i)
142
151
}
143
152
144
153
#[ cfg_attr( target_os = "uefi" , unadjusted_on_win64) ]
145
154
pub extern "C" fn __floattidf( i: i128 ) -> f64 {
146
- let sign_bit = ( ( i >> 127 ) as u64 ) << 63 ;
147
- f64 :: from_bits( int_to_float:: u128_to_f64_bits( i. unsigned_abs( ) ) | sign_bit)
155
+ int_to_float( i)
148
156
}
149
157
}
150
158
0 commit comments