Skip to content

Commit 7c3f9c1

Browse files
committed
Enable LARGEST_POWER_OF_TEN from expression to show failures
More generic work, tests passing flt2dec work Figured out the power of 10 magic numbers Fix off by one Update library/core/src/num/dec2flt/number.rs
1 parent b0561b5 commit 7c3f9c1

File tree

9 files changed

+259
-109
lines changed

9 files changed

+259
-109
lines changed

Diff for: library/core/src/num/dec2flt/float.rs

+128-85
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,50 @@
22
33
use crate::fmt::{Debug, LowerExp};
44
use crate::num::FpCategory;
5-
use crate::ops::{Add, Div, Mul, Neg};
5+
use crate::ops::{self, Add, Div, Mul, Neg};
66

77
use 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

183237
impl 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

239289
impl 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 {

Diff for: library/core/src/num/dec2flt/lemire.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ pub fn compute_float<F: RawFloat>(q: i64, mut w: u64) -> BiasedFp {
8989
if lo <= 1
9090
&& q >= F::MIN_EXPONENT_ROUND_TO_EVEN as i64
9191
&& q <= F::MAX_EXPONENT_ROUND_TO_EVEN as i64
92-
&& mantissa & 3 == 1
92+
&& mantissa & 0b11 == 1
9393
&& (mantissa << (upperbit + 64 - F::MANTISSA_EXPLICIT_BITS as i32 - 3)) == hi
9494
{
9595
// Zero the lowest bit, so we don't round up.

Diff for: library/core/src/num/dec2flt/number.rs

+1-5
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,6 @@ impl Number {
8282
F::from_u64(mantissa) * F::pow10_fast_path(F::MAX_EXPONENT_FAST_PATH as _)
8383
};
8484

85-
if self.negative {
86-
value = -value;
87-
}
88-
89-
Some(value)
85+
if self.negative { Some(-value) } else { Some(value) }
9086
}
9187
}

Diff for: library/core/src/num/f16.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -250,9 +250,10 @@ impl f16 {
250250
pub(crate) const SIGN_MASK: u16 = 0x8000;
251251

252252
/// Exponent mask
253+
#[cfg(not(bootstrap))]
253254
pub(crate) const EXP_MASK: u16 = 0x7c00;
254255

255-
/// Mantissa mask
256+
#[cfg(not(bootstrap))]
256257
pub(crate) const MAN_MASK: u16 = 0x03ff;
257258

258259
/// Minimum representable positive value (min subnormal)

Diff for: library/core/src/num/f32.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -491,13 +491,13 @@ impl f32 {
491491
pub const NEG_INFINITY: f32 = -1.0_f32 / 0.0_f32;
492492

493493
/// Sign bit
494-
const SIGN_MASK: u32 = 0x8000_0000;
494+
pub(crate) const SIGN_MASK: u32 = 0x8000_0000;
495495

496496
/// Exponent mask
497-
const EXP_MASK: u32 = 0x7f80_0000;
497+
pub(crate) const EXP_MASK: u32 = 0x7f80_0000;
498498

499499
/// Mantissa mask
500-
const MAN_MASK: u32 = 0x007f_ffff;
500+
pub(crate) const MAN_MASK: u32 = 0x007f_ffff;
501501

502502
/// Minimum representable positive value (min subnormal)
503503
const TINY_BITS: u32 = 0x1;

Diff for: library/core/src/num/f64.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -490,13 +490,13 @@ impl f64 {
490490
pub const NEG_INFINITY: f64 = -1.0_f64 / 0.0_f64;
491491

492492
/// Sign bit
493-
const SIGN_MASK: u64 = 0x8000_0000_0000_0000;
493+
pub(crate) const SIGN_MASK: u64 = 0x8000_0000_0000_0000;
494494

495495
/// Exponent mask
496-
const EXP_MASK: u64 = 0x7ff0_0000_0000_0000;
496+
pub(crate) const EXP_MASK: u64 = 0x7ff0_0000_0000_0000;
497497

498498
/// Mantissa mask
499-
const MAN_MASK: u64 = 0x000f_ffff_ffff_ffff;
499+
pub(crate) const MAN_MASK: u64 = 0x000f_ffff_ffff_ffff;
500500

501501
/// Minimum representable positive value (min subnormal)
502502
const TINY_BITS: u64 = 0x1;

Diff for: library/core/tests/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#![feature(duration_constructors)]
3636
#![feature(exact_size_is_empty)]
3737
#![feature(extern_types)]
38+
#![feature(f16)]
3839
#![feature(freeze)]
3940
#![feature(flt2dec)]
4041
#![feature(fmt_internals)]

0 commit comments

Comments
 (0)