Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit bbdaad0

Browse files
committedApr 14, 2017
Auto merge of #41302 - rkruppe:dec2flt-assoc-consts, r=BurntSushi
Use associated constants in core::num::dec2flt
2 parents ba37798 + e9c74bc commit bbdaad0

File tree

4 files changed

+99
-152
lines changed

4 files changed

+99
-152
lines changed
 

‎src/libcore/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
#![feature(allow_internal_unstable)]
7171
#![feature(asm)]
7272
#![feature(associated_type_defaults)]
73+
#![feature(associated_consts)]
7374
#![feature(cfg_target_feature)]
7475
#![feature(cfg_target_has_atomic)]
7576
#![feature(concat_idents)]

‎src/libcore/num/dec2flt/algorithm.rs

+19-19
Original file line numberDiff line numberDiff line change
@@ -106,17 +106,17 @@ mod fpu_precision {
106106
/// a bignum.
107107
pub fn fast_path<T: RawFloat>(integral: &[u8], fractional: &[u8], e: i64) -> Option<T> {
108108
let num_digits = integral.len() + fractional.len();
109-
// log_10(f64::max_sig) ~ 15.95. We compare the exact value to max_sig near the end,
109+
// log_10(f64::MAX_SIG) ~ 15.95. We compare the exact value to MAX_SIG near the end,
110110
// this is just a quick, cheap rejection (and also frees the rest of the code from
111111
// worrying about underflow).
112112
if num_digits > 16 {
113113
return None;
114114
}
115-
if e.abs() >= T::ceil_log5_of_max_sig() as i64 {
115+
if e.abs() >= T::CEIL_LOG5_OF_MAX_SIG as i64 {
116116
return None;
117117
}
118118
let f = num::from_str_unchecked(integral.iter().chain(fractional.iter()));
119-
if f > T::max_sig() {
119+
if f > T::MAX_SIG {
120120
return None;
121121
}
122122

@@ -154,14 +154,14 @@ pub fn fast_path<T: RawFloat>(integral: &[u8], fractional: &[u8], e: i64) -> Opt
154154
/// > the best possible approximation that uses p bits of significand.)
155155
pub fn bellerophon<T: RawFloat>(f: &Big, e: i16) -> T {
156156
let slop;
157-
if f <= &Big::from_u64(T::max_sig()) {
157+
if f <= &Big::from_u64(T::MAX_SIG) {
158158
// The cases abs(e) < log5(2^N) are in fast_path()
159159
slop = if e >= 0 { 0 } else { 3 };
160160
} else {
161161
slop = if e >= 0 { 1 } else { 4 };
162162
}
163163
let z = rawfp::big_to_fp(f).mul(&power_of_ten(e)).normalize();
164-
let exp_p_n = 1 << (P - T::sig_bits() as u32);
164+
let exp_p_n = 1 << (P - T::SIG_BITS as u32);
165165
let lowbits: i64 = (z.f % exp_p_n) as i64;
166166
// Is the slop large enough to make a difference when
167167
// rounding to n bits?
@@ -210,14 +210,14 @@ fn algorithm_r<T: RawFloat>(f: &Big, e: i16, z0: T) -> T {
210210
if d2 < y {
211211
let mut d2_double = d2;
212212
d2_double.mul_pow2(1);
213-
if m == T::min_sig() && d_negative && d2_double > y {
213+
if m == T::MIN_SIG && d_negative && d2_double > y {
214214
z = prev_float(z);
215215
} else {
216216
return z;
217217
}
218218
} else if d2 == y {
219219
if m % 2 == 0 {
220-
if m == T::min_sig() && d_negative {
220+
if m == T::MIN_SIG && d_negative {
221221
z = prev_float(z);
222222
} else {
223223
return z;
@@ -303,12 +303,12 @@ pub fn algorithm_m<T: RawFloat>(f: &Big, e: i16) -> T {
303303
quick_start::<T>(&mut u, &mut v, &mut k);
304304
let mut rem = Big::from_small(0);
305305
let mut x = Big::from_small(0);
306-
let min_sig = Big::from_u64(T::min_sig());
307-
let max_sig = Big::from_u64(T::max_sig());
306+
let min_sig = Big::from_u64(T::MIN_SIG);
307+
let max_sig = Big::from_u64(T::MAX_SIG);
308308
loop {
309309
u.div_rem(&v, &mut x, &mut rem);
310-
if k == T::min_exp_int() {
311-
// We have to stop at the minimum exponent, if we wait until `k < T::min_exp_int()`,
310+
if k == T::MIN_EXP_INT {
311+
// We have to stop at the minimum exponent, if we wait until `k < T::MIN_EXP_INT`,
312312
// then we'd be off by a factor of two. Unfortunately this means we have to special-
313313
// case normal numbers with the minimum exponent.
314314
// FIXME find a more elegant formulation, but run the `tiny-pow10` test to make sure
@@ -318,8 +318,8 @@ pub fn algorithm_m<T: RawFloat>(f: &Big, e: i16) -> T {
318318
}
319319
return underflow(x, v, rem);
320320
}
321-
if k > T::max_exp_int() {
322-
return T::infinity2();
321+
if k > T::MAX_EXP_INT {
322+
return T::INFINITY;
323323
}
324324
if x < min_sig {
325325
u.mul_pow2(1);
@@ -345,18 +345,18 @@ fn quick_start<T: RawFloat>(u: &mut Big, v: &mut Big, k: &mut i16) {
345345
// The target ratio is one where u/v is in an in-range significand. Thus our termination
346346
// condition is log2(u / v) being the significand bits, plus/minus one.
347347
// FIXME Looking at the second bit could improve the estimate and avoid some more divisions.
348-
let target_ratio = T::sig_bits() as i16;
348+
let target_ratio = T::SIG_BITS as i16;
349349
let log2_u = u.bit_length() as i16;
350350
let log2_v = v.bit_length() as i16;
351351
let mut u_shift: i16 = 0;
352352
let mut v_shift: i16 = 0;
353353
assert!(*k == 0);
354354
loop {
355-
if *k == T::min_exp_int() {
355+
if *k == T::MIN_EXP_INT {
356356
// Underflow or subnormal. Leave it to the main function.
357357
break;
358358
}
359-
if *k == T::max_exp_int() {
359+
if *k == T::MAX_EXP_INT {
360360
// Overflow. Leave it to the main function.
361361
break;
362362
}
@@ -376,7 +376,7 @@ fn quick_start<T: RawFloat>(u: &mut Big, v: &mut Big, k: &mut i16) {
376376
}
377377

378378
fn underflow<T: RawFloat>(x: Big, v: Big, rem: Big) -> T {
379-
if x < Big::from_u64(T::min_sig()) {
379+
if x < Big::from_u64(T::MIN_SIG) {
380380
let q = num::to_u64(&x);
381381
let z = rawfp::encode_subnormal(q);
382382
return round_by_remainder(v, rem, q, z);
@@ -395,9 +395,9 @@ fn underflow<T: RawFloat>(x: Big, v: Big, rem: Big) -> T {
395395
// needs to be rounded up. Only when the rounded off bits are 1/2 and the remainder
396396
// is zero, we have a half-to-even situation.
397397
let bits = x.bit_length();
398-
let lsb = bits - T::sig_bits() as usize;
398+
let lsb = bits - T::SIG_BITS as usize;
399399
let q = num::get_bits(&x, lsb, bits);
400-
let k = T::min_exp_int() + lsb as i16;
400+
let k = T::MIN_EXP_INT + lsb as i16;
401401
let z = rawfp::encode_normal(Unpacked::new(q, k));
402402
let q_even = q % 2 == 0;
403403
match num::compare_with_half_ulp(&x, lsb) {

‎src/libcore/num/dec2flt/mod.rs

+10-10
Original file line numberDiff line numberDiff line change
@@ -214,11 +214,11 @@ fn dec2flt<T: RawFloat>(s: &str) -> Result<T, ParseFloatError> {
214214
let (sign, s) = extract_sign(s);
215215
let flt = match parse_decimal(s) {
216216
ParseResult::Valid(decimal) => convert(decimal)?,
217-
ParseResult::ShortcutToInf => T::infinity2(),
218-
ParseResult::ShortcutToZero => T::zero2(),
217+
ParseResult::ShortcutToInf => T::INFINITY,
218+
ParseResult::ShortcutToZero => T::ZERO,
219219
ParseResult::Invalid => match s {
220-
"inf" => T::infinity2(),
221-
"NaN" => T::nan2(),
220+
"inf" => T::INFINITY,
221+
"NaN" => T::NAN,
222222
_ => { return Err(pfe_invalid()); }
223223
}
224224
};
@@ -254,7 +254,7 @@ fn convert<T: RawFloat>(mut decimal: Decimal) -> Result<T, ParseFloatError> {
254254
// FIXME These bounds are rather conservative. A more careful analysis of the failure modes
255255
// of Bellerophon could allow using it in more cases for a massive speed up.
256256
let exponent_in_range = table::MIN_E <= e && e <= table::MAX_E;
257-
let value_in_range = upper_bound <= T::max_normal_digits() as u64;
257+
let value_in_range = upper_bound <= T::MAX_NORMAL_DIGITS as u64;
258258
if exponent_in_range && value_in_range {
259259
Ok(algorithm::bellerophon(&f, e))
260260
} else {
@@ -315,17 +315,17 @@ fn bound_intermediate_digits(decimal: &Decimal, e: i64) -> u64 {
315315
fn trivial_cases<T: RawFloat>(decimal: &Decimal) -> Option<T> {
316316
// There were zeros but they were stripped by simplify()
317317
if decimal.integral.is_empty() && decimal.fractional.is_empty() {
318-
return Some(T::zero2());
318+
return Some(T::ZERO);
319319
}
320320
// This is a crude approximation of ceil(log10(the real value)). We don't need to worry too
321321
// much about overflow here because the input length is tiny (at least compared to 2^64) and
322322
// the parser already handles exponents whose absolute value is greater than 10^18
323323
// (which is still 10^19 short of 2^64).
324324
let max_place = decimal.exp + decimal.integral.len() as i64;
325-
if max_place > T::inf_cutoff() {
326-
return Some(T::infinity2());
327-
} else if max_place < T::zero_cutoff() {
328-
return Some(T::zero2());
325+
if max_place > T::INF_CUTOFF {
326+
return Some(T::INFINITY);
327+
} else if max_place < T::ZERO_CUTOFF {
328+
return Some(T::ZERO);
329329
}
330330
None
331331
}

‎src/libcore/num/dec2flt/rawfp.rs

+69-123
Original file line numberDiff line numberDiff line change
@@ -56,24 +56,12 @@ impl Unpacked {
5656
///
5757
/// Should **never ever** be implemented for other types or be used outside the dec2flt module.
5858
/// Inherits from `Float` because there is some overlap, but all the reused methods are trivial.
59-
/// The "methods" (pseudo-constants) with default implementation should not be overriden.
6059
pub trait RawFloat : Float + Copy + Debug + LowerExp
6160
+ Mul<Output=Self> + Div<Output=Self> + Neg<Output=Self>
6261
{
63-
// suffix of "2" because Float::infinity is deprecated
64-
#[allow(deprecated)]
65-
fn infinity2() -> Self {
66-
Float::infinity()
67-
}
68-
69-
// suffix of "2" because Float::nan is deprecated
70-
#[allow(deprecated)]
71-
fn nan2() -> Self {
72-
Float::nan()
73-
}
74-
75-
// suffix of "2" because Float::zero is deprecated
76-
fn zero2() -> Self;
62+
const INFINITY: Self;
63+
const NAN: Self;
64+
const ZERO: Self;
7765

7866
// suffix of "2" because Float::integer_decode is deprecated
7967
#[allow(deprecated)]
@@ -94,94 +82,83 @@ pub trait RawFloat : Float + Copy + Debug + LowerExp
9482
/// represented, the other code in this module makes sure to never let that happen.
9583
fn from_int(x: u64) -> Self;
9684

97-
/// Get the value 10<sup>e</sup> from a pre-computed table. Panics for e >=
98-
/// ceil_log5_of_max_sig().
85+
/// Get the value 10<sup>e</sup> from a pre-computed table.
86+
/// Panics for `e >= CEIL_LOG5_OF_MAX_SIG`.
9987
fn short_fast_pow10(e: usize) -> Self;
10088

101-
// FIXME Everything that follows should be associated constants, but taking the value of an
102-
// associated constant from a type parameter does not work (yet?)
103-
// A possible workaround is having a `FloatInfo` struct for all the constants, but so far
104-
// the methods aren't painful enough to rewrite.
105-
10689
/// What the name says. It's easier to hard code than juggling intrinsics and
10790
/// hoping LLVM constant folds it.
108-
fn ceil_log5_of_max_sig() -> i16;
91+
const CEIL_LOG5_OF_MAX_SIG: i16;
10992

11093
// A conservative bound on the decimal digits of inputs that can't produce overflow or zero or
11194
/// subnormals. Probably the decimal exponent of the maximum normal value, hence the name.
112-
fn max_normal_digits() -> usize;
95+
const MAX_NORMAL_DIGITS: usize;
11396

11497
/// When the most significant decimal digit has a place value greater than this, the number
11598
/// is certainly rounded to infinity.
116-
fn inf_cutoff() -> i64;
99+
const INF_CUTOFF: i64;
117100

118101
/// When the most significant decimal digit has a place value less than this, the number
119102
/// is certainly rounded to zero.
120-
fn zero_cutoff() -> i64;
103+
const ZERO_CUTOFF: i64;
121104

122105
/// The number of bits in the exponent.
123-
fn exp_bits() -> u8;
106+
const EXP_BITS: u8;
124107

125108
/// The number of bits in the singificand, *including* the hidden bit.
126-
fn sig_bits() -> u8;
109+
const SIG_BITS: u8;
127110

128111
/// The number of bits in the singificand, *excluding* the hidden bit.
129-
fn explicit_sig_bits() -> u8 {
130-
Self::sig_bits() - 1
131-
}
112+
const EXPLICIT_SIG_BITS: u8;
132113

133114
/// The maximum legal exponent in fractional representation.
134-
fn max_exp() -> i16 {
135-
(1 << (Self::exp_bits() - 1)) - 1
136-
}
115+
const MAX_EXP: i16;
137116

138117
/// The minimum legal exponent in fractional representation, excluding subnormals.
139-
fn min_exp() -> i16 {
140-
-Self::max_exp() + 1
141-
}
118+
const MIN_EXP: i16;
142119

143120
/// `MAX_EXP` for integral representation, i.e., with the shift applied.
144-
fn max_exp_int() -> i16 {
145-
Self::max_exp() - (Self::sig_bits() as i16 - 1)
146-
}
121+
const MAX_EXP_INT: i16;
147122

148123
/// `MAX_EXP` encoded (i.e., with offset bias)
149-
fn max_encoded_exp() -> i16 {
150-
(1 << Self::exp_bits()) - 1
151-
}
124+
const MAX_ENCODED_EXP: i16;
152125

153126
/// `MIN_EXP` for integral representation, i.e., with the shift applied.
154-
fn min_exp_int() -> i16 {
155-
Self::min_exp() - (Self::sig_bits() as i16 - 1)
156-
}
127+
const MIN_EXP_INT: i16;
157128

158129
/// The maximum normalized singificand in integral representation.
159-
fn max_sig() -> u64 {
160-
(1 << Self::sig_bits()) - 1
161-
}
130+
const MAX_SIG: u64;
162131

163132
/// The minimal normalized significand in integral representation.
164-
fn min_sig() -> u64 {
165-
1 << (Self::sig_bits() - 1)
166-
}
133+
const MIN_SIG: u64;
167134
}
168135

169-
impl RawFloat for f32 {
170-
fn zero2() -> Self {
171-
0.0
172-
}
173-
174-
fn sig_bits() -> u8 {
175-
24
176-
}
177-
178-
fn exp_bits() -> u8 {
179-
8
136+
// Mostly a workaround for #34344.
137+
macro_rules! other_constants {
138+
($type: ident) => {
139+
const EXPLICIT_SIG_BITS: u8 = Self::SIG_BITS - 1;
140+
const MAX_EXP: i16 = (1 << (Self::EXP_BITS - 1)) - 1;
141+
const MIN_EXP: i16 = -Self::MAX_EXP + 1;
142+
const MAX_EXP_INT: i16 = Self::MAX_EXP - (Self::SIG_BITS as i16 - 1);
143+
const MAX_ENCODED_EXP: i16 = (1 << Self::EXP_BITS) - 1;
144+
const MIN_EXP_INT: i16 = Self::MIN_EXP - (Self::SIG_BITS as i16 - 1);
145+
const MAX_SIG: u64 = (1 << Self::SIG_BITS) - 1;
146+
const MIN_SIG: u64 = 1 << (Self::SIG_BITS - 1);
147+
148+
const INFINITY: Self = $crate::$type::INFINITY;
149+
const NAN: Self = $crate::$type::NAN;
150+
const ZERO: Self = 0.0;
180151
}
152+
}
181153

182-
fn ceil_log5_of_max_sig() -> i16 {
183-
11
184-
}
154+
impl RawFloat for f32 {
155+
const SIG_BITS: u8 = 24;
156+
const EXP_BITS: u8 = 8;
157+
const CEIL_LOG5_OF_MAX_SIG: i16 = 11;
158+
const MAX_NORMAL_DIGITS: usize = 35;
159+
const INF_CUTOFF: i64 = 40;
160+
const ZERO_CUTOFF: i64 = -48;
161+
other_constants!(f32);
185162

186163
fn transmute(self) -> u64 {
187164
let bits: u32 = unsafe { transmute(self) };
@@ -207,37 +184,17 @@ impl RawFloat for f32 {
207184
fn short_fast_pow10(e: usize) -> Self {
208185
table::F32_SHORT_POWERS[e]
209186
}
210-
211-
fn max_normal_digits() -> usize {
212-
35
213-
}
214-
215-
fn inf_cutoff() -> i64 {
216-
40
217-
}
218-
219-
fn zero_cutoff() -> i64 {
220-
-48
221-
}
222187
}
223188

224189

225190
impl RawFloat for f64 {
226-
fn zero2() -> Self {
227-
0.0
228-
}
229-
230-
fn sig_bits() -> u8 {
231-
53
232-
}
233-
234-
fn exp_bits() -> u8 {
235-
11
236-
}
237-
238-
fn ceil_log5_of_max_sig() -> i16 {
239-
23
240-
}
191+
const SIG_BITS: u8 = 53;
192+
const EXP_BITS: u8 = 11;
193+
const CEIL_LOG5_OF_MAX_SIG: i16 = 23;
194+
const MAX_NORMAL_DIGITS: usize = 305;
195+
const INF_CUTOFF: i64 = 310;
196+
const ZERO_CUTOFF: i64 = -326;
197+
other_constants!(f64);
241198

242199
fn transmute(self) -> u64 {
243200
let bits: u64 = unsafe { transmute(self) };
@@ -262,38 +219,27 @@ impl RawFloat for f64 {
262219
fn short_fast_pow10(e: usize) -> Self {
263220
table::F64_SHORT_POWERS[e]
264221
}
265-
266-
fn max_normal_digits() -> usize {
267-
305
268-
}
269-
270-
fn inf_cutoff() -> i64 {
271-
310
272-
}
273-
274-
fn zero_cutoff() -> i64 {
275-
-326
276-
}
277-
278222
}
279223

280-
/// Convert an Fp to the closest f64. Only handles number that fit into a normalized f64.
224+
/// Convert an Fp to the closest machine float type.
225+
/// Does not handle subnormal results.
281226
pub fn fp_to_float<T: RawFloat>(x: Fp) -> T {
282227
let x = x.normalize();
283228
// x.f is 64 bit, so x.e has a mantissa shift of 63
284229
let e = x.e + 63;
285-
if e > T::max_exp() {
230+
if e > T::MAX_EXP {
286231
panic!("fp_to_float: exponent {} too large", e)
287-
} else if e > T::min_exp() {
232+
} else if e > T::MIN_EXP {
288233
encode_normal(round_normal::<T>(x))
289234
} else {
290235
panic!("fp_to_float: exponent {} too small", e)
291236
}
292237
}
293238

294-
/// Round the 64-bit significand to 53 bit with half-to-even. Does not handle exponent overflow.
239+
/// Round the 64-bit significand to T::SIG_BITS bits with half-to-even.
240+
/// Does not handle exponent overflow.
295241
pub fn round_normal<T: RawFloat>(x: Fp) -> Unpacked {
296-
let excess = 64 - T::sig_bits() as i16;
242+
let excess = 64 - T::SIG_BITS as i16;
297243
let half: u64 = 1 << (excess - 1);
298244
let (q, rem) = (x.f >> excess, x.f & ((1 << excess) - 1));
299245
assert_eq!(q << excess | rem, x.f);
@@ -303,8 +249,8 @@ pub fn round_normal<T: RawFloat>(x: Fp) -> Unpacked {
303249
Unpacked::new(q, k)
304250
} else if rem == half && (q % 2) == 0 {
305251
Unpacked::new(q, k)
306-
} else if q == T::max_sig() {
307-
Unpacked::new(T::min_sig(), k + 1)
252+
} else if q == T::MAX_SIG {
253+
Unpacked::new(T::MIN_SIG, k + 1)
308254
} else {
309255
Unpacked::new(q + 1, k)
310256
}
@@ -313,22 +259,22 @@ pub fn round_normal<T: RawFloat>(x: Fp) -> Unpacked {
313259
/// Inverse of `RawFloat::unpack()` for normalized numbers.
314260
/// Panics if the significand or exponent are not valid for normalized numbers.
315261
pub fn encode_normal<T: RawFloat>(x: Unpacked) -> T {
316-
debug_assert!(T::min_sig() <= x.sig && x.sig <= T::max_sig(),
262+
debug_assert!(T::MIN_SIG <= x.sig && x.sig <= T::MAX_SIG,
317263
"encode_normal: significand not normalized");
318264
// Remove the hidden bit
319-
let sig_enc = x.sig & !(1 << T::explicit_sig_bits());
265+
let sig_enc = x.sig & !(1 << T::EXPLICIT_SIG_BITS);
320266
// Adjust the exponent for exponent bias and mantissa shift
321-
let k_enc = x.k + T::max_exp() + T::explicit_sig_bits() as i16;
322-
debug_assert!(k_enc != 0 && k_enc < T::max_encoded_exp(),
267+
let k_enc = x.k + T::MAX_EXP + T::EXPLICIT_SIG_BITS as i16;
268+
debug_assert!(k_enc != 0 && k_enc < T::MAX_ENCODED_EXP,
323269
"encode_normal: exponent out of range");
324270
// Leave sign bit at 0 ("+"), our numbers are all positive
325-
let bits = (k_enc as u64) << T::explicit_sig_bits() | sig_enc;
271+
let bits = (k_enc as u64) << T::EXPLICIT_SIG_BITS | sig_enc;
326272
T::from_bits(bits)
327273
}
328274

329-
/// Construct the subnormal. A mantissa of 0 is allowed and constructs zero.
275+
/// Construct a subnormal. A mantissa of 0 is allowed and constructs zero.
330276
pub fn encode_subnormal<T: RawFloat>(significand: u64) -> T {
331-
assert!(significand < T::min_sig(), "encode_subnormal: not actually subnormal");
277+
assert!(significand < T::MIN_SIG, "encode_subnormal: not actually subnormal");
332278
// Encoded exponent is 0, the sign bit is 0, so we just have to reinterpret the bits.
333279
T::from_bits(significand)
334280
}
@@ -364,8 +310,8 @@ pub fn prev_float<T: RawFloat>(x: T) -> T {
364310
Zero => panic!("prev_float: argument is zero"),
365311
Normal => {
366312
let Unpacked { sig, k } = x.unpack();
367-
if sig == T::min_sig() {
368-
encode_normal(Unpacked::new(T::max_sig(), k - 1))
313+
if sig == T::MIN_SIG {
314+
encode_normal(Unpacked::new(T::MAX_SIG, k - 1))
369315
} else {
370316
encode_normal(Unpacked::new(sig - 1, k))
371317
}
@@ -380,7 +326,7 @@ pub fn prev_float<T: RawFloat>(x: T) -> T {
380326
pub fn next_float<T: RawFloat>(x: T) -> T {
381327
match x.classify() {
382328
Nan => panic!("next_float: argument is NaN"),
383-
Infinite => T::infinity2(),
329+
Infinite => T::INFINITY,
384330
// This seems too good to be true, but it works.
385331
// 0.0 is encoded as the all-zero word. Subnormals are 0x000m...m where m is the mantissa.
386332
// In particular, the smallest subnormal is 0x0...01 and the largest is 0x000F...F.

0 commit comments

Comments
 (0)
Please sign in to comment.