Skip to content

Commit dccacbc

Browse files
committed
core: fixed more comments and slight bug.
The bug involves the incorrect logic for `core::num::flt2dec::decoder`. This makes some numbers in the form of 2^n inaccurate by one digit; the regression tests have been added.
1 parent c58785d commit dccacbc

File tree

4 files changed

+23
-7
lines changed

4 files changed

+23
-7
lines changed

src/libcore/num/flt2dec/bignum.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ macro_rules! define_bignum {
216216
self.base[i] = 0;
217217
}
218218

219-
// shift by `nbits` bits
219+
// shift by `bits` bits
220220
let mut sz = self.size + digits;
221221
if bits > 0 {
222222
let last = sz;

src/libcore/num/flt2dec/decoder.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -73,21 +73,21 @@ pub fn decode<T: DecodableFloat>(v: T) -> (/*negative?*/ bool, FullDecoded) {
7373
FpCategory::Infinite => FullDecoded::Infinite,
7474
FpCategory::Zero => FullDecoded::Zero,
7575
FpCategory::Subnormal => {
76-
// (mant - 2, exp) -- (mant, exp) -- (mant + 2, exp)
76+
// neighbors: (mant - 2, exp) -- (mant, exp) -- (mant + 2, exp)
7777
// Float::integer_decode always preserves the exponent,
7878
// so the mantissa is scaled for subnormals.
7979
FullDecoded::Finite(Decoded { mant: mant, minus: 1, plus: 1,
8080
exp: exp, inclusive: even })
8181
}
8282
FpCategory::Normal => {
8383
let minnorm = <T as DecodableFloat>::min_pos_norm_value().integer_decode();
84-
if mant == minnorm.0 && exp == minnorm.1 {
85-
// (maxmant, exp - 1) -- (minnormmant, exp) -- (minnormmant + 1, exp)
84+
if mant == minnorm.0 {
85+
// neighbors: (maxmant, exp - 1) -- (minnormmant, exp) -- (minnormmant + 1, exp)
8686
// where maxmant = minnormmant * 2 - 1
87-
FullDecoded::Finite(Decoded { mant: mant << 1, minus: 1, plus: 2,
88-
exp: exp - 1, inclusive: even })
87+
FullDecoded::Finite(Decoded { mant: mant << 2, minus: 1, plus: 2,
88+
exp: exp - 2, inclusive: even })
8989
} else {
90-
// (mant - 1, exp) -- (mant, exp) -- (mant + 1, exp)
90+
// neighbors: (mant - 1, exp) -- (mant, exp) -- (mant + 1, exp)
9191
FullDecoded::Finite(Decoded { mant: mant << 1, minus: 1, plus: 1,
9292
exp: exp - 1, inclusive: even })
9393
}

src/libcore/num/flt2dec/estimator.rs

+2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
pub fn estimate_scaling_factor(mant: u64, exp: i16) -> i16 {
1919
// 2^(nbits-1) < mant <= 2^nbits if mant > 0
2020
let nbits = 64 - (mant - 1).leading_zeros() as i64;
21+
// 1292913986 = floor(2^32 * log_10 2)
22+
// therefore this always underestimates (or is exact), but not much.
2123
(((nbits + exp as i64) * 1292913986) >> 32) as i16
2224
}
2325

src/libcoretest/num/flt2dec/mod.rs

+14
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,13 @@ pub fn f32_shortest_sanity_test<F>(mut f: F) where F: FnMut(&Decoded, &mut [u8])
216216
// 10^18 * 0.314159231156617216
217217
check_shortest!(f(3.141592e17f32) => b"3141592", 18);
218218

219+
// regression test for decoders
220+
// 33554430
221+
// 33554432
222+
// 33554436
223+
let twoto25: f32 = StdFloat::ldexp(1.0, 25);
224+
check_shortest!(f(twoto25) => b"33554432", 8);
225+
219226
// 10^39 * 0.340282326356119256160033759537265639424
220227
// 10^39 * 0.34028234663852885981170418348451692544
221228
// 10^39 * 0.340282366920938463463374607431768211456
@@ -308,6 +315,13 @@ pub fn f64_shortest_sanity_test<F>(mut f: F) where F: FnMut(&Decoded, &mut [u8])
308315
// 10^18 * 0.314159200000000064
309316
check_shortest!(f(3.141592e17f64) => b"3141592", 18);
310317

318+
// regression test for decoders
319+
// 18446744073709549568
320+
// 18446744073709551616
321+
// 18446744073709555712
322+
let twoto64: f64 = StdFloat::ldexp(1.0, 64);
323+
check_shortest!(f(twoto64) => b"18446744073709552", 20);
324+
311325
// pathological case: high = 10^23 (exact). tie breaking should always prefer that.
312326
// 10^24 * 0.099999999999999974834176
313327
// 10^24 * 0.099999999999999991611392

0 commit comments

Comments
 (0)