22
33use crate :: fmt:: { Debug , LowerExp } ;
44use crate :: num:: FpCategory ;
5- use crate :: ops:: { Add , Div , Mul , Neg } ;
5+ use crate :: ops:: { self , Add , Div , Mul , Neg } ;
66
77use core:: f64;
88
9+ pub trait CastInto < T : Copy > : Copy {
10+ fn cast ( self ) -> T ;
11+ }
12+
13+ pub trait Integer :
14+ Sized
15+ + Clone
16+ + Copy
17+ + Debug
18+ + ops:: Shr < u32 , Output = Self >
19+ + ops:: Shl < u32 , Output = Self >
20+ + ops:: BitAnd < Output = Self >
21+ + ops:: BitOr < Output = Self >
22+ + PartialEq
23+ + CastInto < i16 >
24+ {
25+ const ZERO : Self ;
26+ const ONE : Self ;
27+ }
28+
29+ macro_rules! int {
30+ ( $( $ty: ty) ,+) => {
31+ $(
32+ impl CastInto <i16 > for $ty {
33+ fn cast( self ) -> i16 {
34+ self as i16
35+ }
36+ }
37+
38+
39+ impl Integer for $ty {
40+ const ZERO : Self = 0 ;
41+ const ONE : Self = 1 ;
42+ }
43+ ) +
44+ }
45+ }
46+
47+ int ! ( u16 , u32 , u64 ) ;
48+
949/// A helper trait to avoid duplicating basically all the conversion code for IEEE floats.
1050///
1151/// See the parent module's doc comment for why this is necessary.
@@ -26,6 +66,9 @@ pub trait RawFloat:
2666 + Copy
2767 + Debug
2868{
69+ /// The unsigned integer with the same size as the float
70+ type Int : Integer + Into < u64 > ;
71+
2972 /* general constants */
3073
3174 const INFINITY : Self ;
@@ -39,6 +82,9 @@ pub trait RawFloat:
3982 /// Mantissa digits including the hidden bit (provided by core)
4083 const MANTISSA_BITS : u32 ;
4184
85+ const EXPONENT_MASK : Self :: Int ;
86+ const MANTISSA_MASK : Self :: Int ;
87+
4288 /// The number of bits in the significand, *excluding* the hidden bit.
4389 const MANTISSA_EXPLICIT_BITS : u32 = Self :: MANTISSA_BITS - 1 ;
4490
@@ -91,13 +137,14 @@ pub trait RawFloat:
91137 /// This is the max exponent in binary converted to the max exponent in decimal. Allows fast
92138 /// pathing anything larger than `10^LARGEST_POWER_OF_TEN`, which will round to infinity.
93139 // const LARGEST_POWER_OF_TEN: i32;
94- const LARGEST_POWER_OF_TEN : i32 = ( Self :: EXPONENT_BIAS as f64 / f64:: consts:: LOG2_10 ) as i32 ;
140+ const LARGEST_POWER_OF_TEN : i32 =
141+ ( ( Self :: EXPONENT_BIAS as f64 + 1.0 ) / f64:: consts:: LOG2_10 ) as i32 ;
95142
96143 /// Smallest decimal exponent for a non-zero value. This allows for fast pathing anything
97- /// smaller than `10^SMALLEST_POWER_OF_TEN`.
98- const SMALLEST_POWER_OF_TEN : i32 ;
99- // const SMALLEST_POWER_OF_TEN: i32 =
100- // -(((Self::EXPONENT_BIAS + Self::MANTISSA_BITS) as f64) / f64::consts::LOG2_10) as i32 - 2 ;
144+ // / smaller than `10^SMALLEST_POWER_OF_TEN`.
145+ // const SMALLEST_POWER_OF_TEN: i32;
146+ const SMALLEST_POWER_OF_TEN : i32 =
147+ -( ( ( Self :: EXPONENT_BIAS + Self :: MANTISSA_BITS + 64 ) as f64 ) / f64:: consts:: LOG2_10 ) as i32 ;
101148
102149 /// Maximum exponent that can be represented for a disguised-fast path case.
103150 /// This is `MAX_EXPONENT_FAST_PATH + ⌊(MANTISSA_EXPLICIT_BITS+1)/log2(10)⌋`
@@ -122,72 +169,83 @@ pub trait RawFloat:
122169 /// Returns the category that this number falls into.
123170 fn classify ( self ) -> FpCategory ;
124171
172+ /// Transmute to the integer representation
173+ fn to_bits ( self ) -> Self :: Int ;
174+
125175 /// Returns the mantissa, exponent and sign as integers.
126- fn integer_decode ( self ) -> ( u64 , i16 , i8 ) ;
176+ fn integer_decode ( self ) -> ( u64 , i16 , i8 ) {
177+ let bits = self . to_bits ( ) ;
178+ let sign: i8 = if bits >> ( Self :: BITS - 1 ) == Self :: Int :: ZERO { 1 } else { -1 } ;
179+ let mut exponent: i16 =
180+ ( ( bits & Self :: EXPONENT_MASK ) >> Self :: MANTISSA_EXPLICIT_BITS ) . cast ( ) ;
181+ let mantissa = if exponent == 0 {
182+ ( bits & Self :: MANTISSA_MASK ) << 1
183+ } else {
184+ ( bits & Self :: MANTISSA_MASK ) | ( Self :: Int :: ONE << Self :: MANTISSA_EXPLICIT_BITS )
185+ } ;
186+ // Exponent bias + mantissa shift
187+ exponent -= ( Self :: EXPONENT_BIAS + Self :: MANTISSA_EXPLICIT_BITS ) as i16 ;
188+ ( mantissa. into ( ) , exponent, sign)
189+ }
127190}
128191
129- // #[cfg(not(bootstrap))]
130- // impl RawFloat for f16 {
131- // const INFINITY: Self = Self::INFINITY;
132- // const NEG_INFINITY: Self = Self::NEG_INFINITY;
133- // const NAN: Self = Self::NAN;
134- // const NEG_NAN: Self = -Self::NAN;
135-
136- // const BITS: u32 = 16;
137- // const MANTISSA_DIGITS: u32 = Self::MANTISSA_DIGITS;
138-
139- // const MIN_EXPONENT_FAST_PATH: i64 = -4; // assuming FLT_EVAL_METHOD = 0
140- // const MAX_EXPONENT_FAST_PATH: i64 = 4;
141-
142- // const MIN_EXPONENT_ROUND_TO_EVEN: i32 = -17;
143- // const MAX_EXPONENT_ROUND_TO_EVEN: i32 = 10;
144- // const MAX_EXPONENT_DISGUISED_FAST_PATH: i64 = 17;
145- // const SMALLEST_POWER_OF_TEN: i32 = -65;
146- // const LARGEST_POWER_OF_TEN: i32 = Self::MAX_10_EXP;
147-
148- // #[inline]
149- // fn from_u64(v: u64) -> Self {
150- // debug_assert!(v <= Self::MAX_MANTISSA_FAST_PATH);
151- // v as _
152- // }
153-
154- // #[inline]
155- // fn from_u64_bits(v: u64) -> Self {
156- // Self::from_bits((v & 0xFFFF) as u16)
157- // }
158-
159- // fn pow10_fast_path(exponent: usize) -> Self {
160- // #[allow(clippy::use_self)]
161- // const TABLE: [f32; 16] =
162- // [1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 0., 0., 0., 0., 0.];
163- // TABLE[exponent & 15]
164- // }
165-
166- // /// Returns the mantissa, exponent and sign as integers.
167- // fn integer_decode(self) -> (u64, i16, i8) {
168- // let bits = self.to_bits();
169- // let sign: i8 = if bits >> 31 == 0 { 1 } else { -1 };
170- // let mut exponent: i16 = ((bits >> 23) & 0xff) as i16;
171- // let mantissa =
172- // if exponent == 0 { (bits & 0x7fffff) << 1 } else { (bits & 0x7fffff) | 0x800000 };
173- // // Exponent bias + mantissa shift
174- // exponent -= 127 + 23;
175- // (mantissa as u64, exponent, sign)
176- // }
177-
178- // fn classify(self) -> FpCategory {
179- // self.classify()
180- // }
181- // }
192+ #[ cfg( not( bootstrap) ) ]
193+ impl RawFloat for f16 {
194+ type Int = u16 ;
195+
196+ const INFINITY : Self = Self :: INFINITY ;
197+ const NEG_INFINITY : Self = Self :: NEG_INFINITY ;
198+ const NAN : Self = Self :: NAN ;
199+ const NEG_NAN : Self = -Self :: NAN ;
200+
201+ const BITS : u32 = 16 ;
202+ const MANTISSA_BITS : u32 = Self :: MANTISSA_DIGITS ;
203+ const EXPONENT_MASK : Self :: Int = Self :: EXP_MASK ;
204+ const MANTISSA_MASK : Self :: Int = Self :: MAN_MASK ;
205+
206+ const MIN_EXPONENT_ROUND_TO_EVEN : i32 = -17 ;
207+ const MAX_EXPONENT_ROUND_TO_EVEN : i32 = 10 ;
208+ // const SMALLEST_POWER_OF_TEN: i32 = -27;
209+ // const LARGEST_POWER_OF_TEN: i32 = Self::MAX_10_EXP;
210+
211+ #[ inline]
212+ fn from_u64 ( v : u64 ) -> Self {
213+ debug_assert ! ( v <= Self :: MAX_MANTISSA_FAST_PATH ) ;
214+ v as _
215+ }
216+
217+ #[ inline]
218+ fn from_u64_bits ( v : u64 ) -> Self {
219+ Self :: from_bits ( ( v & 0xFF ) as u16 )
220+ }
221+
222+ fn pow10_fast_path ( exponent : usize ) -> Self {
223+ #[ allow( clippy:: use_self) ]
224+ const TABLE : [ f16 ; 8 ] = [ 1e0 , 1e1 , 1e2 , 1e3 , 1e4 , 0.0 , 0.0 , 0. ] ;
225+ TABLE [ exponent & 15 ]
226+ }
227+
228+ fn to_bits ( self ) -> Self :: Int {
229+ self . to_bits ( )
230+ }
231+
232+ fn classify ( self ) -> FpCategory {
233+ todo ! ( )
234+ }
235+ }
182236
183237impl RawFloat for f32 {
238+ type Int = u32 ;
239+
184240 const INFINITY : Self = f32:: INFINITY ;
185241 const NEG_INFINITY : Self = f32:: NEG_INFINITY ;
186242 const NAN : Self = f32:: NAN ;
187243 const NEG_NAN : Self = -f32:: NAN ;
188244
189245 const BITS : u32 = 32 ;
190246 const MANTISSA_BITS : u32 = Self :: MANTISSA_DIGITS ;
247+ const EXPONENT_MASK : Self :: Int = Self :: EXP_MASK ;
248+ const MANTISSA_MASK : Self :: Int = Self :: MAN_MASK ;
191249
192250 // const MANTISSA_EXPLICIT_BITS: u32 = 23;
193251 const MIN_EXPONENT_ROUND_TO_EVEN : i32 = -17 ;
@@ -198,7 +256,7 @@ impl RawFloat for f32 {
198256 // const MINIMUM_EXPONENT: i32 = -127;
199257 // const INFINITE_POWER: i32 = 0xFF;
200258 // const SIGN_INDEX: u32 = 31;
201- const SMALLEST_POWER_OF_TEN : i32 = -65 ;
259+ // const SMALLEST_POWER_OF_TEN: i32 = -65;
202260 // const LARGEST_POWER_OF_TEN: i32 = 38;
203261
204262 #[ inline]
@@ -219,16 +277,8 @@ impl RawFloat for f32 {
219277 TABLE [ exponent & 15 ]
220278 }
221279
222- /// Returns the mantissa, exponent and sign as integers.
223- fn integer_decode ( self ) -> ( u64 , i16 , i8 ) {
224- let bits = self . to_bits ( ) ;
225- let sign: i8 = if bits >> 31 == 0 { 1 } else { -1 } ;
226- let mut exponent: i16 = ( ( bits >> 23 ) & 0xff ) as i16 ;
227- let mantissa =
228- if exponent == 0 { ( bits & 0x7fffff ) << 1 } else { ( bits & 0x7fffff ) | 0x800000 } ;
229- // Exponent bias + mantissa shift
230- exponent -= 127 + 23 ;
231- ( mantissa as u64 , exponent, sign)
280+ fn to_bits ( self ) -> Self :: Int {
281+ self . to_bits ( )
232282 }
233283
234284 fn classify ( self ) -> FpCategory {
@@ -237,13 +287,17 @@ impl RawFloat for f32 {
237287}
238288
239289impl RawFloat for f64 {
290+ type Int = u64 ;
291+
240292 const INFINITY : Self = Self :: INFINITY ;
241293 const NEG_INFINITY : Self = Self :: NEG_INFINITY ;
242294 const NAN : Self = Self :: NAN ;
243295 const NEG_NAN : Self = -Self :: NAN ;
244296
245297 const BITS : u32 = 64 ;
246298 const MANTISSA_BITS : u32 = Self :: MANTISSA_DIGITS ;
299+ const EXPONENT_MASK : Self :: Int = Self :: EXP_MASK ;
300+ const MANTISSA_MASK : Self :: Int = Self :: MAN_MASK ;
247301
248302 // const MANTISSA_EXPLICIT_BITS: u32 = 52;
249303 const MIN_EXPONENT_ROUND_TO_EVEN : i32 = -4 ;
@@ -254,7 +308,7 @@ impl RawFloat for f64 {
254308 // const MINIMUM_EXPONENT: i32 = -1023;
255309 // const INFINITE_POWER: i32 = 0x7FF;
256310 // const SIGN_INDEX: u32 = 63;
257- const SMALLEST_POWER_OF_TEN : i32 = -342 ;
311+ // const SMALLEST_POWER_OF_TEN: i32 = -342;
258312 // const LARGEST_POWER_OF_TEN: i32 = 308;
259313
260314 #[ inline]
@@ -276,19 +330,8 @@ impl RawFloat for f64 {
276330 TABLE [ exponent & 31 ]
277331 }
278332
279- /// Returns the mantissa, exponent and sign as integers.
280- fn integer_decode ( self ) -> ( u64 , i16 , i8 ) {
281- let bits = self . to_bits ( ) ;
282- let sign: i8 = if bits >> 63 == 0 { 1 } else { -1 } ;
283- let mut exponent: i16 = ( ( bits >> 52 ) & 0x7ff ) as i16 ;
284- let mantissa = if exponent == 0 {
285- ( bits & 0xfffffffffffff ) << 1
286- } else {
287- ( bits & 0xfffffffffffff ) | 0x10000000000000
288- } ;
289- // Exponent bias + mantissa shift
290- exponent -= 1023 + 52 ;
291- ( mantissa, exponent, sign)
333+ fn to_bits ( self ) -> Self :: Int {
334+ self . to_bits ( )
292335 }
293336
294337 fn classify ( self ) -> FpCategory {
0 commit comments