From 09a4df5e10645ecec96a01c1ca1eecdf93fc063b Mon Sep 17 00:00:00 2001 From: Michael Pankov Date: Sat, 17 Oct 2015 02:05:23 +0300 Subject: [PATCH 1/8] rustfmt the libcore/num --- src/libcore/num/dec2flt/algorithm.rs | 12 +- src/libcore/num/dec2flt/mod.rs | 11 +- src/libcore/num/dec2flt/num.rs | 4 +- src/libcore/num/dec2flt/parse.rs | 6 +- src/libcore/num/dec2flt/rawfp.rs | 16 +- src/libcore/num/diy_float.rs | 35 ++- src/libcore/num/flt2dec/decoder.rs | 36 ++- src/libcore/num/flt2dec/estimator.rs | 1 - src/libcore/num/flt2dec/mod.rs | 298 ++++++++++++++++----- src/libcore/num/flt2dec/strategy/dragon.rs | 129 ++++++--- src/libcore/num/flt2dec/strategy/grisu.rs | 132 +++++++-- src/libcore/num/mod.rs | 19 +- 12 files changed, 529 insertions(+), 170 deletions(-) diff --git a/src/libcore/num/dec2flt/algorithm.rs b/src/libcore/num/dec2flt/algorithm.rs index 1f0f06d746197..5382ca32f53bd 100644 --- a/src/libcore/num/dec2flt/algorithm.rs +++ b/src/libcore/num/dec2flt/algorithm.rs @@ -93,9 +93,17 @@ pub fn bellerophon(f: &Big, e: i16) -> T { let slop; if f <= &Big::from_u64(T::max_sig()) { // The cases abs(e) < log5(2^N) are in fast_path() - slop = if e >= 0 { 0 } else { 3 }; + slop = if e >= 0 { + 0 + } else { + 3 + }; } else { - slop = if e >= 0 { 1 } else { 4 }; + slop = if e >= 0 { + 1 + } else { + 4 + }; } let z = rawfp::big_to_fp(f).mul(&power_of_ten(e)).normalize(); let exp_p_n = 1 << (P - T::sig_bits() as u32); diff --git a/src/libcore/num/dec2flt/mod.rs b/src/libcore/num/dec2flt/mod.rs index 55be4cd31910b..02a2aee028562 100644 --- a/src/libcore/num/dec2flt/mod.rs +++ b/src/libcore/num/dec2flt/mod.rs @@ -153,7 +153,7 @@ from_str_float_impl!(f64, to_f64); #[derive(Debug, Clone, PartialEq)] #[stable(feature = "rust1", since = "1.0.0")] pub struct ParseFloatError { - kind: FloatErrorKind + kind: FloatErrorKind, } #[derive(Debug, Clone, PartialEq)] @@ -214,8 +214,10 @@ fn dec2flt(s: &str) -> Result { ParseResult::Invalid => match s { "inf" => T::infinity(), "NaN" => T::nan(), - _ => { return Err(pfe_invalid()); } - } + _ => { + return Err(pfe_invalid()); + } + }, }; match sign { @@ -232,8 +234,7 @@ fn convert(mut decimal: Decimal) -> Result { return Ok(x); } // AlgorithmM and AlgorithmR both compute approximately `f * 10^e`. - let max_digits = decimal.integral.len() + decimal.fractional.len() + - decimal.exp.abs() as usize; + let max_digits = decimal.integral.len() + decimal.fractional.len() + decimal.exp.abs() as usize; // Remove/shift out the decimal point. let e = decimal.exp - decimal.fractional.len() as i64; if let Some(x) = algorithm::fast_path(decimal.integral, decimal.fractional, e) { diff --git a/src/libcore/num/dec2flt/num.rs b/src/libcore/num/dec2flt/num.rs index 81e7856633b25..7febbdb242b89 100644 --- a/src/libcore/num/dec2flt/num.rs +++ b/src/libcore/num/dec2flt/num.rs @@ -47,7 +47,9 @@ pub fn compare_with_half_ulp(f: &Big, ones_place: usize) -> Ordering { /// 1. using `FromStr` on `&[u8]` requires `from_utf8_unchecked`, which is bad, and /// 2. piecing together the results of `integral.parse()` and `fractional.parse()` is /// more complicated than this entire function. -pub fn from_str_unchecked<'a, T>(bytes: T) -> u64 where T : IntoIterator { +pub fn from_str_unchecked<'a, T>(bytes: T) -> u64 + where T: IntoIterator +{ let mut result = 0; for &c in bytes { result = result * 10 + (c - b'0') as u64; diff --git a/src/libcore/num/dec2flt/parse.rs b/src/libcore/num/dec2flt/parse.rs index 58e2a6e9bba46..0d7a4c1509790 100644 --- a/src/libcore/num/dec2flt/parse.rs +++ b/src/libcore/num/dec2flt/parse.rs @@ -41,7 +41,11 @@ pub struct Decimal<'a> { impl<'a> Decimal<'a> { pub fn new(integral: &'a [u8], fractional: &'a [u8], exp: i64) -> Decimal<'a> { - Decimal { integral: integral, fractional: fractional, exp: exp } + Decimal { + integral: integral, + fractional: fractional, + exp: exp, + } } } diff --git a/src/libcore/num/dec2flt/rawfp.rs b/src/libcore/num/dec2flt/rawfp.rs index be61653c37937..0d00861447d2f 100644 --- a/src/libcore/num/dec2flt/rawfp.rs +++ b/src/libcore/num/dec2flt/rawfp.rs @@ -243,7 +243,7 @@ pub fn fp_to_float(x: Fp) -> T { let e = x.e + 63; if e > T::max_exp() { panic!("fp_to_float: exponent {} too large", e) - } else if e > T::min_exp() { + } else if e > T::min_exp() { encode_normal(round_normal::(x)) } else { panic!("fp_to_float: exponent {} too small", e) @@ -273,13 +273,13 @@ pub fn round_normal(x: Fp) -> Unpacked { /// Panics if the significand or exponent are not valid for normalized numbers. pub fn encode_normal(x: Unpacked) -> T { debug_assert!(T::min_sig() <= x.sig && x.sig <= T::max_sig(), - "encode_normal: significand not normalized"); + "encode_normal: significand not normalized"); // Remove the hidden bit let sig_enc = x.sig & !(1 << T::explicit_sig_bits()); // Adjust the exponent for exponent bias and mantissa shift let k_enc = x.k + T::max_exp() + T::explicit_sig_bits() as i16; debug_assert!(k_enc != 0 && k_enc < T::max_encoded_exp(), - "encode_normal: exponent out of range"); + "encode_normal: exponent out of range"); // Leave sign bit at 0 ("+"), our numbers are all positive let bits = (k_enc as u64) << T::explicit_sig_bits() | sig_enc; T::from_bits(bits) @@ -287,7 +287,8 @@ pub fn encode_normal(x: Unpacked) -> T { /// Construct the subnormal. A mantissa of 0 is allowed and constructs zero. pub fn encode_subnormal(significand: u64) -> T { - assert!(significand < T::min_sig(), "encode_subnormal: not actually subnormal"); + assert!(significand < T::min_sig(), + "encode_subnormal: not actually subnormal"); // Êncoded exponent is 0, the sign bit is 0, so we just have to reinterpret the bits. T::from_bits(significand) } @@ -308,8 +309,11 @@ pub fn big_to_fp(f: &Big) -> Fp { Equal if leading % 2 == 0 => rounded_down, Equal | Greater => match leading.checked_add(1) { Some(f) => Fp { f: f, e: e }.normalize(), - None => Fp { f: 1 << 63, e: e + 1 }, - } + None => Fp { + f: 1 << 63, + e: e + 1, + }, + }, } } diff --git a/src/libcore/num/diy_float.rs b/src/libcore/num/diy_float.rs index 7c369ee3b3bd7..11eea753f93f9 100644 --- a/src/libcore/num/diy_float.rs +++ b/src/libcore/num/diy_float.rs @@ -49,12 +49,30 @@ impl Fp { pub fn normalize(&self) -> Fp { let mut f = self.f; let mut e = self.e; - if f >> (64 - 32) == 0 { f <<= 32; e -= 32; } - if f >> (64 - 16) == 0 { f <<= 16; e -= 16; } - if f >> (64 - 8) == 0 { f <<= 8; e -= 8; } - if f >> (64 - 4) == 0 { f <<= 4; e -= 4; } - if f >> (64 - 2) == 0 { f <<= 2; e -= 2; } - if f >> (64 - 1) == 0 { f <<= 1; e -= 1; } + if f >> (64 - 32) == 0 { + f <<= 32; + e -= 32; + } + if f >> (64 - 16) == 0 { + f <<= 16; + e -= 16; + } + if f >> (64 - 8) == 0 { + f <<= 8; + e -= 8; + } + if f >> (64 - 4) == 0 { + f <<= 4; + e -= 4; + } + if f >> (64 - 2) == 0 { + f <<= 2; + e -= 2; + } + if f >> (64 - 1) == 0 { + f <<= 1; + e -= 1; + } debug_assert!(f >= (1 >> 63)); Fp { f: f, e: e } } @@ -66,6 +84,9 @@ impl Fp { assert!(edelta >= 0); let edelta = edelta as usize; assert_eq!(self.f << edelta >> edelta, self.f); - Fp { f: self.f << edelta, e: e } + Fp { + f: self.f << edelta, + e: e, + } } } diff --git a/src/libcore/num/flt2dec/decoder.rs b/src/libcore/num/flt2dec/decoder.rs index 6265691bde9e9..2b7f7604243a2 100644 --- a/src/libcore/num/flt2dec/decoder.rs +++ b/src/libcore/num/flt2dec/decoder.rs @@ -58,11 +58,15 @@ pub trait DecodableFloat: Float + Copy { } impl DecodableFloat for f32 { - fn min_pos_norm_value() -> Self { f32::MIN_POSITIVE } + fn min_pos_norm_value() -> Self { + f32::MIN_POSITIVE + } } impl DecodableFloat for f64 { - fn min_pos_norm_value() -> Self { f64::MIN_POSITIVE } + fn min_pos_norm_value() -> Self { + f64::MIN_POSITIVE + } } /// Returns a sign (true when negative) and `FullDecoded` value @@ -78,23 +82,37 @@ pub fn decode(v: T) -> (/*negative?*/ bool, FullDecoded) { // neighbors: (mant - 2, exp) -- (mant, exp) -- (mant + 2, exp) // Float::integer_decode always preserves the exponent, // so the mantissa is scaled for subnormals. - FullDecoded::Finite(Decoded { mant: mant, minus: 1, plus: 1, - exp: exp, inclusive: even }) + FullDecoded::Finite(Decoded { + mant: mant, + minus: 1, + plus: 1, + exp: exp, + inclusive: even, + }) } FpCategory::Normal => { let minnorm = ::min_pos_norm_value().integer_decode(); if mant == minnorm.0 { // neighbors: (maxmant, exp - 1) -- (minnormmant, exp) -- (minnormmant + 1, exp) // where maxmant = minnormmant * 2 - 1 - FullDecoded::Finite(Decoded { mant: mant << 2, minus: 1, plus: 2, - exp: exp - 2, inclusive: even }) + FullDecoded::Finite(Decoded { + mant: mant << 2, + minus: 1, + plus: 2, + exp: exp - 2, + inclusive: even, + }) } else { // neighbors: (mant - 1, exp) -- (mant, exp) -- (mant + 1, exp) - FullDecoded::Finite(Decoded { mant: mant << 1, minus: 1, plus: 1, - exp: exp - 1, inclusive: even }) + FullDecoded::Finite(Decoded { + mant: mant << 1, + minus: 1, + plus: 1, + exp: exp - 1, + inclusive: even, + }) } } }; (sign < 0, decoded) } - diff --git a/src/libcore/num/flt2dec/estimator.rs b/src/libcore/num/flt2dec/estimator.rs index d42e05a91f140..4e33fcfd76e61 100644 --- a/src/libcore/num/flt2dec/estimator.rs +++ b/src/libcore/num/flt2dec/estimator.rs @@ -22,4 +22,3 @@ pub fn estimate_scaling_factor(mant: u64, exp: i16) -> i16 { // therefore this always underestimates (or is exact), but not much. (((nbits + exp as i64) * 1292913986) >> 32) as i16 } - diff --git a/src/libcore/num/flt2dec/mod.rs b/src/libcore/num/flt2dec/mod.rs index 7f7c61938cb40..6666ef5e0ba3c 100644 --- a/src/libcore/num/flt2dec/mod.rs +++ b/src/libcore/num/flt2dec/mod.rs @@ -158,12 +158,16 @@ pub fn round_up(d: &mut [u8], n: usize) -> Option { match d[..n].iter().rposition(|&c| c != b'9') { Some(i) => { // d[i+1..n] is all nines d[i] += 1; - for j in i+1..n { d[j] = b'0'; } + for j in i + 1..n { + d[j] = b'0'; + } None } None if n > 0 => { // 999..999 rounds to 1000..000 with an increased exponent d[0] = b'1'; - for j in 1..n { d[j] = b'0'; } + for j in 1..n { + d[j] = b'0'; + } Some(b'0') } None => { // an empty buffer rounds up (a bit strange but reasonable) @@ -188,8 +192,21 @@ impl<'a> Part<'a> { pub fn len(&self) -> usize { match *self { Part::Zero(nzeroes) => nzeroes, - Part::Num(v) => if v < 1_000 { if v < 10 { 1 } else if v < 100 { 2 } else { 3 } } - else { if v < 10_000 { 4 } else { 5 } }, + Part::Num(v) => if v < 1_000 { + if v < 10 { + 1 + } else if v < 100 { + 2 + } else { + 3 + } + } else { + if v < 10_000 { + 4 + } else { + 5 + } + }, Part::Copy(buf) => buf.len(), } } @@ -202,7 +219,9 @@ impl<'a> Part<'a> { if out.len() >= len { match *self { Part::Zero(nzeroes) => { - for c in &mut out[..nzeroes] { *c = b'0'; } + for c in &mut out[..nzeroes] { + *c = b'0'; + } } Part::Num(mut v) => { for c in out[..len].iter_mut().rev() { @@ -245,14 +264,20 @@ impl<'a> Formatted<'a> { /// Returns the number of written bytes, or `None` if the buffer is not enough. /// (It may still leave partially written bytes in the buffer; do not rely on that.) pub fn write(&self, out: &mut [u8]) -> Option { - if out.len() < self.sign.len() { return None; } + if out.len() < self.sign.len() { + return None; + } bytes::copy_memory(self.sign, out); let mut written = self.sign.len(); for part in self.parts { match part.write(&mut out[written..]) { - Some(len) => { written += len; } - None => { return None; } + Some(len) => { + written += len; + } + None => { + return None; + } } } Some(written) @@ -267,8 +292,11 @@ impl<'a> Formatted<'a> { /// it will be ignored and full digits will be printed. It is only used to print /// additional zeroes after rendered digits. Thus `frac_digits` of 0 means that /// it will only print given digits and nothing else. -fn digits_to_dec_str<'a>(buf: &'a [u8], exp: i16, frac_digits: usize, - parts: &'a mut [Part<'a>]) -> &'a [Part<'a>] { +fn digits_to_dec_str<'a>(buf: &'a [u8], + exp: i16, + frac_digits: usize, + parts: &'a mut [Part<'a>]) + -> &'a [Part<'a>] { assert!(!buf.is_empty()); assert!(buf[0] > b'0'); assert!(parts.len() >= 4); @@ -335,8 +363,12 @@ fn digits_to_dec_str<'a>(buf: &'a [u8], exp: i16, frac_digits: usize, /// it will be ignored and full digits will be printed. It is only used to print /// additional zeroes after rendered digits. Thus `min_digits` of 0 means that /// it will only print given digits and nothing else. -fn digits_to_exp_str<'a>(buf: &'a [u8], exp: i16, min_ndigits: usize, upper: bool, - parts: &'a mut [Part<'a>]) -> &'a [Part<'a>] { +fn digits_to_exp_str<'a>(buf: &'a [u8], + exp: i16, + min_ndigits: usize, + upper: bool, + parts: &'a mut [Part<'a>]) + -> &'a [Part<'a>] { assert!(!buf.is_empty()); assert!(buf[0] > b'0'); assert!(parts.len() >= 6); @@ -359,10 +391,18 @@ fn digits_to_exp_str<'a>(buf: &'a [u8], exp: i16, min_ndigits: usize, upper: boo // 0.1234 x 10^exp = 1.234 x 10^(exp-1) let exp = exp as i32 - 1; // avoid underflow when exp is i16::MIN if exp < 0 { - parts[n] = Part::Copy(if upper { b"E-" } else { b"e-" }); + parts[n] = Part::Copy(if upper { + b"E-" + } else { + b"e-" + }); parts[n + 1] = Part::Num(-exp as u16); } else { - parts[n] = Part::Copy(if upper { b"E" } else { b"e" }); + parts[n] = Part::Copy(if upper { + b"E" + } else { + b"e" + }); parts[n + 1] = Part::Num(exp as u16); } &parts[..n + 2] @@ -387,11 +427,27 @@ fn determine_sign(sign: Sign, decoded: &FullDecoded, negative: bool) -> &'static match (*decoded, sign) { (FullDecoded::Nan, _) => b"", (FullDecoded::Zero, Sign::Minus) => b"", - (FullDecoded::Zero, Sign::MinusRaw) => if negative { b"-" } else { b"" }, + (FullDecoded::Zero, Sign::MinusRaw) => if negative { + b"-" + } else { + b"" + }, (FullDecoded::Zero, Sign::MinusPlus) => b"+", - (FullDecoded::Zero, Sign::MinusPlusRaw) => if negative { b"-" } else { b"+" }, - (_, Sign::Minus) | (_, Sign::MinusRaw) => if negative { b"-" } else { b"" }, - (_, Sign::MinusPlus) | (_, Sign::MinusPlusRaw) => if negative { b"-" } else { b"+" }, + (FullDecoded::Zero, Sign::MinusPlusRaw) => if negative { + b"-" + } else { + b"+" + }, + (_, Sign::Minus) | (_, Sign::MinusRaw) => if negative { + b"-" + } else { + b"" + }, + (_, Sign::MinusPlus) | (_, Sign::MinusPlusRaw) => if negative { + b"-" + } else { + b"+" + }, } } @@ -413,10 +469,17 @@ fn determine_sign(sign: Sign, decoded: &FullDecoded, negative: bool) -> &'static /// The byte buffer should be at least `MAX_SIG_DIGITS` bytes long. /// There should be at least 5 parts available, due to the worst case like /// `[+][0.][0000][45][0000]` with `frac_digits = 10`. -pub fn to_shortest_str<'a, T, F>(mut format_shortest: F, v: T, - sign: Sign, frac_digits: usize, _upper: bool, - buf: &'a mut [u8], parts: &'a mut [Part<'a>]) -> Formatted<'a> - where T: DecodableFloat, F: FnMut(&Decoded, &mut [u8]) -> (usize, i16) { +pub fn to_shortest_str<'a, T, F>(mut format_shortest: F, + v: T, + sign: Sign, + frac_digits: usize, + _upper: bool, + buf: &'a mut [u8], + parts: &'a mut [Part<'a>]) + -> Formatted<'a> + where T: DecodableFloat, + F: FnMut(&Decoded, &mut [u8]) -> (usize, i16) +{ assert!(parts.len() >= 4); assert!(buf.len() >= MAX_SIG_DIGITS); @@ -425,26 +488,40 @@ pub fn to_shortest_str<'a, T, F>(mut format_shortest: F, v: T, match full_decoded { FullDecoded::Nan => { parts[0] = Part::Copy(b"NaN"); - Formatted { sign: sign, parts: &parts[..1] } + Formatted { + sign: sign, + parts: &parts[..1], + } } FullDecoded::Infinite => { parts[0] = Part::Copy(b"inf"); - Formatted { sign: sign, parts: &parts[..1] } + Formatted { + sign: sign, + parts: &parts[..1], + } } FullDecoded::Zero => { if frac_digits > 0 { // [0.][0000] parts[0] = Part::Copy(b"0."); parts[1] = Part::Zero(frac_digits); - Formatted { sign: sign, parts: &parts[..2] } + Formatted { + sign: sign, + parts: &parts[..2], + } } else { parts[0] = Part::Copy(b"0"); - Formatted { sign: sign, parts: &parts[..1] } + Formatted { + sign: sign, + parts: &parts[..1], + } } } FullDecoded::Finite(ref decoded) => { let (len, exp) = format_shortest(decoded, buf); - Formatted { sign: sign, - parts: digits_to_dec_str(&buf[..len], exp, frac_digits, parts) } + Formatted { + sign: sign, + parts: digits_to_dec_str(&buf[..len], exp, frac_digits, parts), + } } } } @@ -468,10 +545,17 @@ pub fn to_shortest_str<'a, T, F>(mut format_shortest: F, v: T, /// The byte buffer should be at least `MAX_SIG_DIGITS` bytes long. /// There should be at least 7 parts available, due to the worst case like /// `[+][1][.][2345][e][-][67]`. -pub fn to_shortest_exp_str<'a, T, F>(mut format_shortest: F, v: T, - sign: Sign, dec_bounds: (i16, i16), upper: bool, - buf: &'a mut [u8], parts: &'a mut [Part<'a>]) -> Formatted<'a> - where T: DecodableFloat, F: FnMut(&Decoded, &mut [u8]) -> (usize, i16) { +pub fn to_shortest_exp_str<'a, T, F>(mut format_shortest: F, + v: T, + sign: Sign, + dec_bounds: (i16, i16), + upper: bool, + buf: &'a mut [u8], + parts: &'a mut [Part<'a>]) + -> Formatted<'a> + where T: DecodableFloat, + F: FnMut(&Decoded, &mut [u8]) -> (usize, i16) +{ assert!(parts.len() >= 6); assert!(buf.len() >= MAX_SIG_DIGITS); assert!(dec_bounds.0 <= dec_bounds.1); @@ -481,19 +565,32 @@ pub fn to_shortest_exp_str<'a, T, F>(mut format_shortest: F, v: T, match full_decoded { FullDecoded::Nan => { parts[0] = Part::Copy(b"NaN"); - Formatted { sign: sign, parts: &parts[..1] } + Formatted { + sign: sign, + parts: &parts[..1], + } } FullDecoded::Infinite => { parts[0] = Part::Copy(b"inf"); - Formatted { sign: sign, parts: &parts[..1] } + Formatted { + sign: sign, + parts: &parts[..1], + } } FullDecoded::Zero => { parts[0] = if dec_bounds.0 <= 0 && 0 < dec_bounds.1 { Part::Copy(b"0") } else { - Part::Copy(if upper { b"0E0" } else { b"0e0" }) + Part::Copy(if upper { + b"0E0" + } else { + b"0e0" + }) }; - Formatted { sign: sign, parts: &parts[..1] } + Formatted { + sign: sign, + parts: &parts[..1], + } } FullDecoded::Finite(ref decoded) => { let (len, exp) = format_shortest(decoded, buf); @@ -503,7 +600,10 @@ pub fn to_shortest_exp_str<'a, T, F>(mut format_shortest: F, v: T, } else { digits_to_exp_str(&buf[..len], exp, 0, upper, parts) }; - Formatted { sign: sign, parts: parts } + Formatted { + sign: sign, + parts: parts, + } } } } @@ -529,7 +629,12 @@ pub fn to_shortest_exp_str<'a, T, F>(mut format_shortest: F, v: T, /// 826 bytes of buffer should be sufficient for `f64`. Compare this with /// the actual number for the worst case: 770 bytes (when `exp = -1074`). fn estimate_max_buf_len(exp: i16) -> usize { - 21 + ((if exp < 0 { -12 } else { 5 } * exp as i32) as usize >> 4) + 21 + + ((if exp < 0 { + -12 + } else { + 5 + } * exp as i32) as usize >> 4) } /// Formats given floating point number into the exponential form with @@ -547,10 +652,17 @@ fn estimate_max_buf_len(exp: i16) -> usize { /// (The tipping point for `f64` is about 800, so 1000 bytes should be enough.) /// There should be at least 7 parts available, due to the worst case like /// `[+][1][.][2345][e][-][67]`. -pub fn to_exact_exp_str<'a, T, F>(mut format_exact: F, v: T, - sign: Sign, ndigits: usize, upper: bool, - buf: &'a mut [u8], parts: &'a mut [Part<'a>]) -> Formatted<'a> - where T: DecodableFloat, F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) { +pub fn to_exact_exp_str<'a, T, F>(mut format_exact: F, + v: T, + sign: Sign, + ndigits: usize, + upper: bool, + buf: &'a mut [u8], + parts: &'a mut [Part<'a>]) + -> Formatted<'a> + where T: DecodableFloat, + F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) +{ assert!(parts.len() >= 6); assert!(ndigits > 0); @@ -559,31 +671,57 @@ pub fn to_exact_exp_str<'a, T, F>(mut format_exact: F, v: T, match full_decoded { FullDecoded::Nan => { parts[0] = Part::Copy(b"NaN"); - Formatted { sign: sign, parts: &parts[..1] } + Formatted { + sign: sign, + parts: &parts[..1], + } } FullDecoded::Infinite => { parts[0] = Part::Copy(b"inf"); - Formatted { sign: sign, parts: &parts[..1] } + Formatted { + sign: sign, + parts: &parts[..1], + } } FullDecoded::Zero => { if ndigits > 1 { // [0.][0000][e0] parts[0] = Part::Copy(b"0."); parts[1] = Part::Zero(ndigits - 1); - parts[2] = Part::Copy(if upper { b"E0" } else { b"e0" }); - Formatted { sign: sign, parts: &parts[..3] } + parts[2] = Part::Copy(if upper { + b"E0" + } else { + b"e0" + }); + Formatted { + sign: sign, + parts: &parts[..3], + } } else { - parts[0] = Part::Copy(if upper { b"0E0" } else { b"0e0" }); - Formatted { sign: sign, parts: &parts[..1] } + parts[0] = Part::Copy(if upper { + b"0E0" + } else { + b"0e0" + }); + Formatted { + sign: sign, + parts: &parts[..1], + } } } FullDecoded::Finite(ref decoded) => { let maxlen = estimate_max_buf_len(decoded.exp); assert!(buf.len() >= ndigits || buf.len() >= maxlen); - let trunc = if ndigits < maxlen { ndigits } else { maxlen }; + let trunc = if ndigits < maxlen { + ndigits + } else { + maxlen + }; let (len, exp) = format_exact(decoded, &mut buf[..trunc], i16::MIN); - Formatted { sign: sign, - parts: digits_to_exp_str(&buf[..len], exp, ndigits, upper, parts) } + Formatted { + sign: sign, + parts: digits_to_exp_str(&buf[..len], exp, ndigits, upper, parts), + } } } } @@ -603,10 +741,17 @@ pub fn to_exact_exp_str<'a, T, F>(mut format_exact: F, v: T, /// (The tipping point for `f64` is about 800, and 1000 bytes should be enough.) /// There should be at least 5 parts available, due to the worst case like /// `[+][0.][0000][45][0000]` with `frac_digits = 10`. -pub fn to_exact_fixed_str<'a, T, F>(mut format_exact: F, v: T, - sign: Sign, frac_digits: usize, _upper: bool, - buf: &'a mut [u8], parts: &'a mut [Part<'a>]) -> Formatted<'a> - where T: DecodableFloat, F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) { +pub fn to_exact_fixed_str<'a, T, F>(mut format_exact: F, + v: T, + sign: Sign, + frac_digits: usize, + _upper: bool, + buf: &'a mut [u8], + parts: &'a mut [Part<'a>]) + -> Formatted<'a> + where T: DecodableFloat, + F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) +{ assert!(parts.len() >= 4); let (negative, full_decoded) = decode(v); @@ -614,20 +759,32 @@ pub fn to_exact_fixed_str<'a, T, F>(mut format_exact: F, v: T, match full_decoded { FullDecoded::Nan => { parts[0] = Part::Copy(b"NaN"); - Formatted { sign: sign, parts: &parts[..1] } + Formatted { + sign: sign, + parts: &parts[..1], + } } FullDecoded::Infinite => { parts[0] = Part::Copy(b"inf"); - Formatted { sign: sign, parts: &parts[..1] } + Formatted { + sign: sign, + parts: &parts[..1], + } } FullDecoded::Zero => { if frac_digits > 0 { // [0.][0000] parts[0] = Part::Copy(b"0."); parts[1] = Part::Zero(frac_digits); - Formatted { sign: sign, parts: &parts[..2] } + Formatted { + sign: sign, + parts: &parts[..2], + } } else { parts[0] = Part::Copy(b"0"); - Formatted { sign: sign, parts: &parts[..1] } + Formatted { + sign: sign, + parts: &parts[..1], + } } } FullDecoded::Finite(ref decoded) => { @@ -637,7 +794,11 @@ pub fn to_exact_fixed_str<'a, T, F>(mut format_exact: F, v: T, // it *is* possible that `frac_digits` is ridiculously large. // `format_exact` will end rendering digits much earlier in this case, // because we are strictly limited by `maxlen`. - let limit = if frac_digits < 0x8000 { -(frac_digits as i16) } else { i16::MIN }; + let limit = if frac_digits < 0x8000 { + -(frac_digits as i16) + } else { + i16::MIN + }; let (len, exp) = format_exact(decoded, &mut buf[..maxlen], limit); if exp <= limit { // the restriction couldn't been met, so this should render like zero no matter @@ -647,16 +808,23 @@ pub fn to_exact_fixed_str<'a, T, F>(mut format_exact: F, v: T, if frac_digits > 0 { // [0.][0000] parts[0] = Part::Copy(b"0."); parts[1] = Part::Zero(frac_digits); - Formatted { sign: sign, parts: &parts[..2] } + Formatted { + sign: sign, + parts: &parts[..2], + } } else { parts[0] = Part::Copy(b"0"); - Formatted { sign: sign, parts: &parts[..1] } + Formatted { + sign: sign, + parts: &parts[..1], + } } } else { - Formatted { sign: sign, - parts: digits_to_dec_str(&buf[..len], exp, frac_digits, parts) } + Formatted { + sign: sign, + parts: digits_to_dec_str(&buf[..len], exp, frac_digits, parts), + } } } } } - diff --git a/src/libcore/num/flt2dec/strategy/dragon.rs b/src/libcore/num/flt2dec/strategy/dragon.rs index 2d68c3a6d026e..6fcd208167628 100644 --- a/src/libcore/num/flt2dec/strategy/dragon.rs +++ b/src/libcore/num/flt2dec/strategy/dragon.rs @@ -24,33 +24,45 @@ use num::flt2dec::estimator::estimate_scaling_factor; use num::bignum::Digit32 as Digit; use num::bignum::Big32x40 as Big; -static POW10: [Digit; 10] = [1, 10, 100, 1000, 10000, 100000, - 1000000, 10000000, 100000000, 1000000000]; -static TWOPOW10: [Digit; 10] = [2, 20, 200, 2000, 20000, 200000, - 2000000, 20000000, 200000000, 2000000000]; +static POW10: [Digit; 10] = [1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000]; +static TWOPOW10: [Digit; 10] = [2, 20, 200, 2000, 20000, 200000, 2000000, 20000000, 200000000, 2000000000]; // precalculated arrays of `Digit`s for 10^(2^n) static POW10TO16: [Digit; 2] = [0x6fc10000, 0x2386f2]; static POW10TO32: [Digit; 4] = [0, 0x85acef81, 0x2d6d415b, 0x4ee]; static POW10TO64: [Digit; 7] = [0, 0, 0xbf6a1f01, 0x6e38ed64, 0xdaa797ed, 0xe93ff9f4, 0x184f03]; static POW10TO128: [Digit; 14] = - [0, 0, 0, 0, 0x2e953e01, 0x3df9909, 0xf1538fd, 0x2374e42f, 0xd3cff5ec, 0xc404dc08, - 0xbccdb0da, 0xa6337f19, 0xe91f2603, 0x24e]; + [0, 0, 0, 0, 0x2e953e01, 0x3df9909, 0xf1538fd, 0x2374e42f, 0xd3cff5ec, 0xc404dc08, 0xbccdb0da, + 0xa6337f19, 0xe91f2603, 0x24e]; static POW10TO256: [Digit; 27] = - [0, 0, 0, 0, 0, 0, 0, 0, 0x982e7c01, 0xbed3875b, 0xd8d99f72, 0x12152f87, 0x6bde50c6, - 0xcf4a6e70, 0xd595d80f, 0x26b2716e, 0xadc666b0, 0x1d153624, 0x3c42d35a, 0x63ff540e, - 0xcc5573c0, 0x65f9ef17, 0x55bc28f2, 0x80dcc7f7, 0xf46eeddc, 0x5fdcefce, 0x553f7]; + [0, 0, 0, 0, 0, 0, 0, 0, 0x982e7c01, 0xbed3875b, 0xd8d99f72, 0x12152f87, 0x6bde50c6, 0xcf4a6e70, + 0xd595d80f, 0x26b2716e, 0xadc666b0, 0x1d153624, 0x3c42d35a, 0x63ff540e, 0xcc5573c0, 0x65f9ef17, + 0x55bc28f2, 0x80dcc7f7, 0xf46eeddc, 0x5fdcefce, 0x553f7]; #[doc(hidden)] pub fn mul_pow10(x: &mut Big, n: usize) -> &mut Big { debug_assert!(n < 512); - if n & 7 != 0 { x.mul_small(POW10[n & 7]); } - if n & 8 != 0 { x.mul_small(POW10[8]); } - if n & 16 != 0 { x.mul_digits(&POW10TO16); } - if n & 32 != 0 { x.mul_digits(&POW10TO32); } - if n & 64 != 0 { x.mul_digits(&POW10TO64); } - if n & 128 != 0 { x.mul_digits(&POW10TO128); } - if n & 256 != 0 { x.mul_digits(&POW10TO256); } + if n & 7 != 0 { + x.mul_small(POW10[n & 7]); + } + if n & 8 != 0 { + x.mul_small(POW10[8]); + } + if n & 16 != 0 { + x.mul_digits(&POW10TO16); + } + if n & 32 != 0 { + x.mul_digits(&POW10TO32); + } + if n & 64 != 0 { + x.mul_digits(&POW10TO64); + } + if n & 128 != 0 { + x.mul_digits(&POW10TO128); + } + if n & 256 != 0 { + x.mul_digits(&POW10TO256); + } x } @@ -65,13 +77,29 @@ fn div_2pow10(x: &mut Big, mut n: usize) -> &mut Big { } // only usable when `x < 16 * scale`; `scaleN` should be `scale.mul_small(N)` -fn div_rem_upto_16<'a>(x: &'a mut Big, scale: &Big, - scale2: &Big, scale4: &Big, scale8: &Big) -> (u8, &'a mut Big) { +fn div_rem_upto_16<'a>(x: &'a mut Big, + scale: &Big, + scale2: &Big, + scale4: &Big, + scale8: &Big) + -> (u8, &'a mut Big) { let mut d = 0; - if *x >= *scale8 { x.sub(scale8); d += 8; } - if *x >= *scale4 { x.sub(scale4); d += 4; } - if *x >= *scale2 { x.sub(scale2); d += 2; } - if *x >= *scale { x.sub(scale); d += 1; } + if *x >= *scale8 { + x.sub(scale8); + d += 8; + } + if *x >= *scale4 { + x.sub(scale4); + d += 4; + } + if *x >= *scale2 { + x.sub(scale2); + d += 2; + } + if *x >= *scale { + x.sub(scale); + d += 1; + } debug_assert!(*x < *scale); (d, x) } @@ -98,7 +126,11 @@ pub fn format_shortest(d: &Decoded, buf: &mut [u8]) -> (/*#digits*/ usize, /*exp assert!(buf.len() >= MAX_SIG_DIGITS); // `a.cmp(&b) < rounding` is `if d.inclusive {a <= b} else {a < b}` - let rounding = if d.inclusive {Ordering::Greater} else {Ordering::Equal}; + let rounding = if d.inclusive { + Ordering::Greater + } else { + Ordering::Equal + }; // estimate `k_0` from original inputs satisfying `10^(k_0-1) < high <= 10^(k_0+1)`. // the tight bound `k` satisfying `10^(k-1) < high <= 10^k` is calculated later. @@ -145,9 +177,12 @@ pub fn format_shortest(d: &Decoded, buf: &mut [u8]) -> (/*#digits*/ usize, /*exp } // cache `(2, 4, 8) * scale` for digit generation. - let mut scale2 = scale.clone(); scale2.mul_pow2(1); - let mut scale4 = scale.clone(); scale4.mul_pow2(2); - let mut scale8 = scale.clone(); scale8.mul_pow2(3); + let mut scale2 = scale.clone(); + scale2.mul_pow2(1); + let mut scale4 = scale.clone(); + scale4.mul_pow2(2); + let mut scale8 = scale.clone(); + scale8.mul_pow2(3); let mut down; let mut up; @@ -199,7 +234,10 @@ pub fn format_shortest(d: &Decoded, buf: &mut [u8]) -> (/*#digits*/ usize, /*exp // - keep generating otherwise. down = mant.cmp(&minus) < rounding; up = scale.cmp(mant.clone().add(&plus)) < rounding; - if down || up { break; } // we have the shortest representation, proceed to the rounding + if down || up { + // we have the shortest representation, proceed to the rounding + break; + } // restore the invariants. // this makes the algorithm always terminating: `minus` and `plus` always increases, @@ -282,22 +320,39 @@ pub fn format_exact(d: &Decoded, buf: &mut [u8], limit: i16) -> (/*#digits*/ usi if len > 0 { // cache `(2, 4, 8) * scale` for digit generation. // (this can be expensive, so do not calculate them when the buffer is empty.) - let mut scale2 = scale.clone(); scale2.mul_pow2(1); - let mut scale4 = scale.clone(); scale4.mul_pow2(2); - let mut scale8 = scale.clone(); scale8.mul_pow2(3); + let mut scale2 = scale.clone(); + scale2.mul_pow2(1); + let mut scale4 = scale.clone(); + scale4.mul_pow2(2); + let mut scale8 = scale.clone(); + scale8.mul_pow2(3); for i in 0..len { if mant.is_zero() { // following digits are all zeroes, we stop here // do *not* try to perform rounding! rather, fill remaining digits. - for c in &mut buf[i..len] { *c = b'0'; } + for c in &mut buf[i..len] { + *c = b'0'; + } return (len, k); } let mut d = 0; - if mant >= scale8 { mant.sub(&scale8); d += 8; } - if mant >= scale4 { mant.sub(&scale4); d += 4; } - if mant >= scale2 { mant.sub(&scale2); d += 2; } - if mant >= scale { mant.sub(&scale); d += 1; } + if mant >= scale8 { + mant.sub(&scale8); + d += 8; + } + if mant >= scale4 { + mant.sub(&scale4); + d += 4; + } + if mant >= scale2 { + mant.sub(&scale2); + d += 2; + } + if mant >= scale { + mant.sub(&scale); + d += 1; + } debug_assert!(mant < scale); debug_assert!(d < 10); buf[i] = b'0' + d; @@ -309,8 +364,8 @@ pub fn format_exact(d: &Decoded, buf: &mut [u8], limit: i16) -> (/*#digits*/ usi // if the following digits are exactly 5000..., check the prior digit and try to // round to even (i.e. avoid rounding up when the prior digit is even). let order = mant.cmp(scale.mul_small(5)); - if order == Ordering::Greater || (order == Ordering::Equal && - (len == 0 || buf[len-1] & 1 == 1)) { + if order == Ordering::Greater || + (order == Ordering::Equal && (len == 0 || buf[len - 1] & 1 == 1)) { // if rounding up changes the length, the exponent should also change. // but we've been requested a fixed number of digits, so do not alter the buffer... if let Some(c) = round_up(buf, len) { diff --git a/src/libcore/num/flt2dec/strategy/grisu.rs b/src/libcore/num/flt2dec/strategy/grisu.rs index 5b4b2e46478d4..ebbd85234c6aa 100644 --- a/src/libcore/num/flt2dec/strategy/grisu.rs +++ b/src/libcore/num/flt2dec/strategy/grisu.rs @@ -151,20 +151,47 @@ pub fn max_pow10_no_more_than(x: u32) -> (u8, u32) { const X1: u32 = 10; if x < X4 { - if x < X2 { if x < X1 {(0, 1)} else {(1, X1)} } - else { if x < X3 {(2, X2)} else {(3, X3)} } + if x < X2 { + if x < X1 { + (0, 1) + } else { + (1, X1) + } + } else { + if x < X3 { + (2, X2) + } else { + (3, X3) + } + } } else { - if x < X6 { if x < X5 {(4, X4)} else {(5, X5)} } - else if x < X8 { if x < X7 {(6, X6)} else {(7, X7)} } - else { if x < X9 {(8, X8)} else {(9, X9)} } + if x < X6 { + if x < X5 { + (4, X4) + } else { + (5, X5) + } + } else if x < X8 { + if x < X7 { + (6, X6) + } else { + (7, X7) + } + } else { + if x < X9 { + (8, X8) + } else { + (9, X9) + } + } } } /// The shortest mode implementation for Grisu. /// /// It returns `None` when it would return an inexact representation otherwise. -pub fn format_shortest_opt(d: &Decoded, - buf: &mut [u8]) -> Option<(/*#digits*/ usize, /*exp*/ i16)> { +pub fn format_shortest_opt(d: &Decoded, buf: &mut [u8]) + -> Option<(/*#digits*/ usize, /*exp*/ i16)> { assert!(d.mant > 0); assert!(d.minus > 0); assert!(d.plus > 0); @@ -174,9 +201,18 @@ pub fn format_shortest_opt(d: &Decoded, assert!(d.mant + d.plus < (1 << 61)); // we need at least three bits of additional precision // start with the normalized values with the shared exponent - let plus = Fp { f: d.mant + d.plus, e: d.exp }.normalize(); - let minus = Fp { f: d.mant - d.minus, e: d.exp }.normalize_to(plus.e); - let v = Fp { f: d.mant, e: d.exp }.normalize_to(plus.e); + let plus = Fp { + f: d.mant + d.plus, + e: d.exp, + }.normalize(); + let minus = Fp { + f: d.mant - d.minus, + e: d.exp, + }.normalize_to(plus.e); + let v = Fp { + f: d.mant, + e: d.exp, + }.normalize_to(plus.e); // find any `cached = 10^minusk` such that `ALPHA <= minusk + plus.e + 64 <= GAMMA`. // since `plus` is normalized, this means `2^(62 + ALPHA) <= plus * cached < 2^(64 + GAMMA)`; @@ -272,7 +308,13 @@ pub fn format_shortest_opt(d: &Decoded, if plus1rem < delta1 { // `plus1 % 10^kappa < delta1 = plus1 - minus1`; we've found the correct `kappa`. let ten_kappa = (ten_kappa as u64) << e; // scale 10^kappa back to the shared exponent - return round_and_weed(&mut buf[..i], exp, plus1rem, delta1, plus1 - v.f, ten_kappa, 1); + return round_and_weed(&mut buf[..i], + exp, + plus1rem, + delta1, + plus1 - v.f, + ten_kappa, + 1); } // break the loop when we have rendered all integral digits. @@ -313,8 +355,13 @@ pub fn format_shortest_opt(d: &Decoded, if r < threshold { let ten_kappa = 1 << e; // implicit divisor - return round_and_weed(&mut buf[..i], exp, r, threshold, - (plus1 - v.f) * ulp, ten_kappa, ulp); + return round_and_weed(&mut buf[..i], + exp, + r, + threshold, + (plus1 - v.f) * ulp, + ten_kappa, + ulp); } // restore invariants @@ -338,8 +385,14 @@ pub fn format_shortest_opt(d: &Decoded, // - `plus1v = (plus1 - v) * k` (and also, `threshold > plus1v` from prior invariants) // - `ten_kappa = 10^kappa * k` // - `ulp = 2^-e * k` - fn round_and_weed(buf: &mut [u8], exp: i16, remainder: u64, threshold: u64, plus1v: u64, - ten_kappa: u64, ulp: u64) -> Option<(usize, i16)> { + fn round_and_weed(buf: &mut [u8], + exp: i16, + remainder: u64, + threshold: u64, + plus1v: u64, + ten_kappa: u64, + ulp: u64) + -> Option<(usize, i16)> { assert!(!buf.is_empty()); // produce two approximations to `v` (actually `plus1 - v`) within 1.5 ulps. @@ -394,8 +447,7 @@ pub fn format_shortest_opt(d: &Decoded, // // consequently, we should stop when `TC1 || TC2 || (TC3a && TC3b)`. the following is // equal to its inverse, `!TC1 && !TC2 && (!TC3a || !TC3b)`. - while plus1w < plus1v_up && - threshold - plus1w >= ten_kappa && + while plus1w < plus1v_up && threshold - plus1w >= ten_kappa && (plus1w + ten_kappa < plus1v_up || plus1v_up - plus1w >= plus1w + ten_kappa - plus1v_up) { *last -= 1; @@ -408,8 +460,7 @@ pub fn format_shortest_opt(d: &Decoded, // // this is simply same to the terminating conditions for `v + 1 ulp`, with all `plus1v_up` // replaced by `plus1v_down` instead. overflow analysis equally holds. - if plus1w < plus1v_down && - threshold - plus1w >= ten_kappa && + if plus1w < plus1v_down && threshold - plus1w >= ten_kappa && (plus1w + ten_kappa < plus1v_down || plus1v_down - plus1w >= plus1w + ten_kappa - plus1v_down) { return None; @@ -430,7 +481,7 @@ pub fn format_shortest_opt(d: &Decoded, /// The shortest mode implementation for Grisu with Dragon fallback. /// /// This should be used for most cases. -pub fn format_shortest(d: &Decoded, buf: &mut [u8]) -> (/*#digits*/ usize, /*exp*/ i16) { +pub fn format_shortest(d: &Decoded, buf: &mut [u8]) -> (usize, i16) { use num::flt2dec::strategy::dragon::format_shortest as fallback; match format_shortest_opt(d, buf) { Some(ret) => ret, @@ -442,13 +493,16 @@ pub fn format_shortest(d: &Decoded, buf: &mut [u8]) -> (/*#digits*/ usize, /*exp /// /// It returns `None` when it would return an inexact representation otherwise. pub fn format_exact_opt(d: &Decoded, buf: &mut [u8], limit: i16) - -> Option<(/*#digits*/ usize, /*exp*/ i16)> { + -> Option<(/*#digits*/ usize, /*exp*/ i16)> { assert!(d.mant > 0); assert!(d.mant < (1 << 61)); // we need at least three bits of additional precision assert!(!buf.is_empty()); // normalize and scale `v`. - let v = Fp { f: d.mant, e: d.exp }.normalize(); + let v = Fp { + f: d.mant, + e: d.exp, + }.normalize(); let (minusk, cached) = cached_power(ALPHA - v.e - 64, GAMMA - v.e - 64); let v = v.mul(&cached); @@ -489,7 +543,13 @@ pub fn format_exact_opt(d: &Decoded, buf: &mut [u8], limit: i16) // thus we are being sloppy here and widen the error range by a factor of 10. // this will increase the false negative rate, but only very, *very* slightly; // it can only matter noticably when the mantissa is bigger than 60 bits. - return possibly_round(buf, 0, exp, limit, v.f / 10, (max_ten_kappa as u64) << e, err << e); + return possibly_round(buf, + 0, + exp, + limit, + v.f / 10, + (max_ten_kappa as u64) << e, + err << e); } else if ((exp as i32 - limit as i32) as usize) < buf.len() { (exp - limit) as usize } else { @@ -518,7 +578,13 @@ pub fn format_exact_opt(d: &Decoded, buf: &mut [u8], limit: i16) // is the buffer full? run the rounding pass with the remainder. if i == len { let vrem = ((r as u64) << e) + vfrac; // == (v % 10^kappa) * 2^e - return possibly_round(buf, len, exp, limit, vrem, (ten_kappa as u64) << e, err << e); + return possibly_round(buf, + len, + exp, + limit, + vrem, + (ten_kappa as u64) << e, + err << e); } // break the loop when we have rendered all integral digits. @@ -588,8 +654,14 @@ pub fn format_exact_opt(d: &Decoded, buf: &mut [u8], limit: i16) // - `remainder = (v % 10^kappa) * k` // - `ten_kappa = 10^kappa * k` // - `ulp = 2^-e * k` - fn possibly_round(buf: &mut [u8], mut len: usize, mut exp: i16, limit: i16, - remainder: u64, ten_kappa: u64, ulp: u64) -> Option<(usize, i16)> { + fn possibly_round(buf: &mut [u8], + mut len: usize, + mut exp: i16, + limit: i16, + remainder: u64, + ten_kappa: u64, + ulp: u64) + -> Option<(usize, i16)> { debug_assert!(remainder < ten_kappa); // 10^kappa @@ -606,7 +678,9 @@ pub fn format_exact_opt(d: &Decoded, buf: &mut [u8], limit: i16) // // error is too large that there are at least three possible representations // between `v - 1 ulp` and `v + 1 ulp`. we cannot determine which one is correct. - if ulp >= ten_kappa { return None; } + if ulp >= ten_kappa { + return None; + } // 10^kappa // :<------->: @@ -620,7 +694,9 @@ pub fn format_exact_opt(d: &Decoded, buf: &mut [u8], limit: i16) // in fact, 1/2 ulp is enough to introduce two possible representations. // (remember that we need a unique representation for both `v - 1 ulp` and `v + 1 ulp`.) // this won't overflow, as `ulp < ten_kappa` from the first check. - if ten_kappa - ulp <= ulp { return None; } + if ten_kappa - ulp <= ulp { + return None; + } // remainder // :<->| : diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 6507bb7bf8c82..21b0226c93501 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -111,7 +111,9 @@ macro_rules! checked_op { /// Swapping a single byte is a no-op. This is marked as `unsafe` for /// consistency with the other `bswap` intrinsics. -unsafe fn bswap8(x: u8) -> u8 { x } +unsafe fn bswap8(x: u8) -> u8 { + x +} // `Int` + `SignedInt` implemented for signed integers macro_rules! int_impl { @@ -1366,14 +1368,13 @@ macro_rules! doit { } doit! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize } -fn from_str_radix(src: &str, radix: u32) - -> Result { +fn from_str_radix(src: &str, radix: u32) -> Result { use self::IntErrorKind::*; use self::ParseIntError as PIE; assert!(radix >= 2 && radix <= 36, - "from_str_radix_int: must lie in the range `[2, 36]` - found {}", - radix); + "from_str_radix_int: must lie in the range `[2, 36]` - found {}", + radix); if src.is_empty() { return Err(PIE { kind: Empty }); @@ -1387,7 +1388,7 @@ fn from_str_radix(src: &str, radix: u32) // of multi-byte sequences let src = src.as_bytes(); - match (src[0], &src[1..]) { + match (src[0], &src[1..]) { (b'-', digits) if digits.is_empty() => Err(PIE { kind: Empty }), (b'-', digits) if is_signed_ty => { // The number is negative @@ -1407,7 +1408,7 @@ fn from_str_radix(src: &str, radix: u32) }; } Ok(result) - }, + } (c, digits) => { // The number is signed let mut result = match (c as char).to_digit(radix) { @@ -1436,7 +1437,9 @@ fn from_str_radix(src: &str, radix: u32) /// An error which can be returned when parsing an integer. #[derive(Debug, Clone, PartialEq)] #[stable(feature = "rust1", since = "1.0.0")] -pub struct ParseIntError { kind: IntErrorKind } +pub struct ParseIntError { + kind: IntErrorKind, +} #[derive(Debug, Clone, PartialEq)] enum IntErrorKind { From 8233d7c99e05398f5bb5b3315628ce202746ab85 Mon Sep 17 00:00:00 2001 From: Michael Pankov Date: Sat, 17 Oct 2015 16:38:57 +0300 Subject: [PATCH 2/8] Rewrite a complex conditional --- src/libcore/num/flt2dec/mod.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/libcore/num/flt2dec/mod.rs b/src/libcore/num/flt2dec/mod.rs index e0f7dcdf3bc93..f75a677515d20 100644 --- a/src/libcore/num/flt2dec/mod.rs +++ b/src/libcore/num/flt2dec/mod.rs @@ -629,12 +629,13 @@ pub fn to_shortest_exp_str<'a, T, F>(mut format_shortest: F, /// 826 bytes of buffer should be sufficient for `f64`. Compare this with /// the actual number for the worst case: 770 bytes (when `exp = -1074`). fn estimate_max_buf_len(exp: i16) -> usize { - 21 + - ((if exp < 0 { + let multiplier = if exp < 0 { -12 } else { 5 - } * exp as i32) as usize >> 4) + }; + let exp_part_len = (multiplier * (exp as i32)) as usize >> 4; + 21 + exp_part_len } /// Formats given floating point number into the exponential form with From 21a8eef69b4b2260ac11d12ac5f7c18525f87e67 Mon Sep 17 00:00:00 2001 From: Michael Pankov Date: Sat, 17 Oct 2015 16:53:37 +0300 Subject: [PATCH 3/8] Manually wrap long arrays --- src/libcore/num/flt2dec/strategy/dragon.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/libcore/num/flt2dec/strategy/dragon.rs b/src/libcore/num/flt2dec/strategy/dragon.rs index 6fcd208167628..5a5d8b294b5e3 100644 --- a/src/libcore/num/flt2dec/strategy/dragon.rs +++ b/src/libcore/num/flt2dec/strategy/dragon.rs @@ -24,8 +24,10 @@ use num::flt2dec::estimator::estimate_scaling_factor; use num::bignum::Digit32 as Digit; use num::bignum::Big32x40 as Big; -static POW10: [Digit; 10] = [1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000]; -static TWOPOW10: [Digit; 10] = [2, 20, 200, 2000, 20000, 200000, 2000000, 20000000, 200000000, 2000000000]; +static POW10: [Digit; 10] = [ + 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000]; +static TWOPOW10: [Digit; 10] = [ + 2, 20, 200, 2000, 20000, 200000, 2000000, 20000000, 200000000, 2000000000]; // precalculated arrays of `Digit`s for 10^(2^n) static POW10TO16: [Digit; 2] = [0x6fc10000, 0x2386f2]; From 2bcf540df085c67df4433de215c3283c813372a5 Mon Sep 17 00:00:00 2001 From: Michael Pankov Date: Thu, 22 Oct 2015 02:12:09 +0300 Subject: [PATCH 4/8] Run the new version of rustfmt --- src/libcore/num/bignum.rs | 14 +- src/libcore/num/dec2flt/algorithm.rs | 72 ++-- src/libcore/num/dec2flt/mod.rs | 170 +++++--- src/libcore/num/dec2flt/num.rs | 9 +- src/libcore/num/dec2flt/parse.rs | 27 +- src/libcore/num/dec2flt/rawfp.rs | 51 ++- src/libcore/num/diy_float.rs | 3 +- src/libcore/num/flt2dec/decoder.rs | 5 +- src/libcore/num/flt2dec/mod.rs | 274 ++++++------ src/libcore/num/flt2dec/strategy/dragon.rs | 113 +++-- src/libcore/num/flt2dec/strategy/grisu.rs | 472 ++++++++++++--------- src/libcore/num/mod.rs | 10 +- src/libcore/num/wrapping.rs | 6 +- 13 files changed, 746 insertions(+), 480 deletions(-) diff --git a/src/libcore/num/bignum.rs b/src/libcore/num/bignum.rs index 18b34e24fcb30..dac7193047563 100644 --- a/src/libcore/num/bignum.rs +++ b/src/libcore/num/bignum.rs @@ -19,7 +19,8 @@ //! inputs, but we don't do so to avoid the code bloat. Each bignum is still //! tracked for the actual usages, so it normally doesn't matter. -// This module is only for dec2flt and flt2dec, and only public because of libcoretest. +// This module is only for dec2flt and flt2dec, and only public because of +// libcoretest. // It is not intended to ever be stabilized. #![doc(hidden)] #![unstable(feature = "core_private_bignum", @@ -36,19 +37,22 @@ use intrinsics; pub trait FullOps { /// Returns `(carry', v')` such that `carry' * 2^W + v' = self + other + carry`, /// where `W` is the number of bits in `Self`. - fn full_add(self, other: Self, carry: bool) -> (bool /*carry*/, Self); + fn full_add(self, other: Self, carry: bool) -> (bool /* carry */, Self); /// Returns `(carry', v')` such that `carry' * 2^W + v' = self * other + carry`, /// where `W` is the number of bits in `Self`. - fn full_mul(self, other: Self, carry: Self) -> (Self /*carry*/, Self); + fn full_mul(self, other: Self, carry: Self) -> (Self /* carry */, Self); /// Returns `(carry', v')` such that `carry' * 2^W + v' = self * other + other2 + carry`, /// where `W` is the number of bits in `Self`. - fn full_mul_add(self, other: Self, other2: Self, carry: Self) -> (Self /*carry*/, Self); + fn full_mul_add(self, other: Self, other2: Self, carry: Self) -> (Self /* carry */, Self); /// Returns `(quo, rem)` such that `borrow * 2^W + self = quo * other + rem` /// and `0 <= rem < other`, where `W` is the number of bits in `Self`. - fn full_div_rem(self, other: Self, borrow: Self) -> (Self /*quotient*/, Self /*remainder*/); + fn full_div_rem(self, + other: Self, + borrow: Self) + -> (Self /* quotient */, Self /* remainder */); } macro_rules! impl_full_ops { diff --git a/src/libcore/num/dec2flt/algorithm.rs b/src/libcore/num/dec2flt/algorithm.rs index 5382ca32f53bd..6c5d59b0aa36d 100644 --- a/src/libcore/num/dec2flt/algorithm.rs +++ b/src/libcore/num/dec2flt/algorithm.rs @@ -21,8 +21,10 @@ use num::dec2flt::num::{self, Big}; /// Number of significand bits in Fp const P: u32 = 64; -// We simply store the best approximation for *all* exponents, so the variable "h" and the -// associated conditions can be omitted. This trades performance for a couple kilobytes of space. +// We simply store the best approximation for *all* exponents, so the variable +// "h" and the +// associated conditions can be omitted. This trades performance for a couple +// kilobytes of space. fn power_of_ten(e: i16) -> Fp { assert!(e >= table::MIN_E); @@ -47,8 +49,10 @@ fn power_of_ten(e: i16) -> Fp { /// FIXME: It would nevertheless be nice if we had a good way to detect and deal with x87. pub fn fast_path(integral: &[u8], fractional: &[u8], e: i64) -> Option { let num_digits = integral.len() + fractional.len(); - // log_10(f64::max_sig) ~ 15.95. We compare the exact value to max_sig near the end, - // this is just a quick, cheap rejection (and also frees the rest of the code from + // log_10(f64::max_sig) ~ 15.95. We compare the exact value to max_sig near the + // end, + // this is just a quick, cheap rejection (and also frees the rest of the code + // from // worrying about underflow). if num_digits > 16 { return None; @@ -130,16 +134,20 @@ fn algorithm_r(f: &Big, e: i16, z0: T) -> T { let mut x = f.clone(); let mut y = Big::from_u64(m); - // Find positive integers `x`, `y` such that `x / y` is exactly `(f * 10^e) / (m * 2^k)`. - // This not only avoids dealing with the signs of `e` and `k`, we also eliminate the + // Find positive integers `x`, `y` such that `x / y` is exactly `(f * 10^e) / + // (m * 2^k)`. + // This not only avoids dealing with the signs of `e` and `k`, we also + // eliminate the // power of two common to `10^e` and `2^k` to make the numbers smaller. make_ratio(&mut x, &mut y, e, k); let m_digits = [(m & 0xFF_FF_FF_FF) as u32, (m >> 32) as u32]; // This is written a bit awkwardly because our bignums don't support // negative numbers, so we use the absolute value + sign information. - // The multiplication with m_digits can't overflow. If `x` or `y` are large enough that - // we need to worry about overflow, then they are also large enough that`make_ratio` has + // The multiplication with m_digits can't overflow. If `x` or `y` are large + // enough that + // we need to worry about overflow, then they are also large enough + // that`make_ratio` has // reduced the fraction by a factor of 2^64 or more. let (d2, d_negative) = if x >= y { // Don't need x any more, save a clone(). @@ -187,14 +195,17 @@ fn make_ratio(x: &mut Big, y: &mut Big, e: i16, k: i16) { let (e_abs, k_abs) = (e.abs() as usize, k.abs() as usize); if e >= 0 { if k >= 0 { - // x = f * 10^e, y = m * 2^k, except that we reduce the fraction by some power of two. + // x = f * 10^e, y = m * 2^k, except that we reduce the fraction by some power + // of two. let common = min(e_abs, k_abs); x.mul_pow5(e_abs).mul_pow2(e_abs - common); y.mul_pow2(k_abs - common); } else { // x = f * 10^e * 2^abs(k), y = m - // This can't overflow because it requires positive `e` and negative `k`, which can - // only happen for values extremely close to 1, which means that `e` and `k` will be + // This can't overflow because it requires positive `e` and negative `k`, which + // can + // only happen for values extremely close to 1, which means that `e` and `k` + // will be // comparatively tiny. x.mul_pow5(e_abs).mul_pow2(e_abs + k_abs); } @@ -239,7 +250,8 @@ pub fn algorithm_m(f: &Big, e: i16) -> T { v = Big::from_small(1); v.mul_pow5(e_abs).mul_pow2(e_abs); } else { - // FIXME possible optimization: generalize big_to_fp so that we can do the equivalent of + // FIXME possible optimization: generalize big_to_fp so that we can do the + // equivalent of // fp_to_float(big_to_fp(u)) here, only without the double rounding. u = f.clone(); u.mul_pow5(e_abs).mul_pow2(e_abs); @@ -253,10 +265,13 @@ pub fn algorithm_m(f: &Big, e: i16) -> T { loop { u.div_rem(&v, &mut x, &mut rem); if k == T::min_exp_int() { - // We have to stop at the minimum exponent, if we wait until `k < T::min_exp_int()`, - // then we'd be off by a factor of two. Unfortunately this means we have to special- + // We have to stop at the minimum exponent, if we wait until `k < + // T::min_exp_int()`, + // then we'd be off by a factor of two. Unfortunately this means we have to + // special- // case normal numbers with the minimum exponent. - // FIXME find a more elegant formulation, but run the `tiny-pow10` test to make sure + // FIXME find a more elegant formulation, but run the `tiny-pow10` test to make + // sure // that it's actually correct! if x >= min_sig && x <= max_sig { break; @@ -283,13 +298,18 @@ pub fn algorithm_m(f: &Big, e: i16) -> T { /// Skip over most AlgorithmM iterations by checking the bit length. fn quick_start(u: &mut Big, v: &mut Big, k: &mut i16) { - // The bit length is an estimate of the base two logarithm, and log(u / v) = log(u) - log(v). - // The estimate is off by at most 1, but always an under-estimate, so the error on log(u) - // and log(v) are of the same sign and cancel out (if both are large). Therefore the error + // The bit length is an estimate of the base two logarithm, and log(u / v) = + // log(u) - log(v). + // The estimate is off by at most 1, but always an under-estimate, so the error + // on log(u) + // and log(v) are of the same sign and cancel out (if both are large). + // Therefore the error // for log(u / v) is at most one as well. - // The target ratio is one where u/v is in an in-range significand. Thus our termination + // The target ratio is one where u/v is in an in-range significand. Thus our + // termination // condition is log2(u / v) being the significand bits, plus/minus one. - // FIXME Looking at the second bit could improve the estimate and avoid some more divisions. + // FIXME Looking at the second bit could improve the estimate and avoid some + // more divisions. let target_ratio = f64::sig_bits() as i16; let log2_u = u.bit_length() as i16; let log2_v = v.bit_length() as i16; @@ -326,8 +346,10 @@ fn underflow(x: Big, v: Big, rem: Big) -> T { let z = rawfp::encode_subnormal(q); return round_by_remainder(v, rem, q, z); } - // Ratio isn't an in-range significand with the minimum exponent, so we need to round off - // excess bits and adjust the exponent accordingly. The real value now looks like this: + // Ratio isn't an in-range significand with the minimum exponent, so we need to + // round off + // excess bits and adjust the exponent accordingly. The real value now looks + // like this: // // x lsb // /--------------\/ @@ -336,8 +358,10 @@ fn underflow(x: Big, v: Big, rem: Big) -> T { // q trunc. (represented by rem) // // Therefore, when the rounded-off bits are != 0.5 ULP, they decide the rounding - // on their own. When they are equal and the remainder is non-zero, the value still - // needs to be rounded up. Only when the rounded off bits are 1/2 and the remainer + // on their own. When they are equal and the remainder is non-zero, the value + // still + // needs to be rounded up. Only when the rounded off bits are 1/2 and the + // remainer // is zero, we have a half-to-even situation. let bits = x.bit_length(); let lsb = bits - T::sig_bits() as usize; diff --git a/src/libcore/num/dec2flt/mod.rs b/src/libcore/num/dec2flt/mod.rs index 02a2aee028562..c739d67174cb0 100644 --- a/src/libcore/num/dec2flt/mod.rs +++ b/src/libcore/num/dec2flt/mod.rs @@ -12,79 +12,124 @@ //! //! # Problem statement //! -//! We are given a decimal string such as `12.34e56`. This string consists of integral (`12`), -//! fractional (`45`), and exponent (`56`) parts. All parts are optional and interpreted as zero +//! We are given a decimal string such as `12.34e56`. This string consists of +//! integral (`12`), +//! fractional (`45`), and exponent (`56`) parts. All parts are optional and +//! interpreted as zero //! when missing. //! -//! We seek the IEEE 754 floating point number that is closest to the exact value of the decimal -//! string. It is well-known that many decimal strings do not have terminating representations in -//! base two, so we round to 0.5 units in the last place (in other words, as well as possible). -//! Ties, decimal values exactly half-way between two consecutive floats, are resolved with the +//! We seek the IEEE 754 floating point number that is closest to the exact +//! value of the decimal +//! string. It is well-known that many decimal strings do not have terminating +//! representations in +//! base two, so we round to 0.5 units in the last place (in other words, as +//! well as possible). +//! Ties, decimal values exactly half-way between two consecutive floats, are +//! resolved with the //! half-to-even strategy, also known as banker's rounding. //! -//! Needless to say, this is quite hard, both in terms of implementation complexity and in terms +//! Needless to say, this is quite hard, both in terms of implementation +//! complexity and in terms //! of CPU cycles taken. //! //! # Implementation //! -//! First, we ignore signs. Or rather, we remove it at the very beginning of the conversion -//! process and re-apply it at the very end. This is correct in all edge cases since IEEE +//! First, we ignore signs. Or rather, we remove it at the very beginning of +//! the conversion +//! process and re-apply it at the very end. This is correct in all edge cases +//! since IEEE //! floats are symmetric around zero, negating one simply flips the first bit. //! -//! Then we remove the decimal point by adjusting the exponent: Conceptually, `12.34e56` turns -//! into `1234e54`, which we describe with a positive integer `f = 1234` and an integer `e = 54`. -//! The `(f, e)` representation is used by almost all code past the parsing stage. +//! Then we remove the decimal point by adjusting the exponent: Conceptually, +//! `12.34e56` turns +//! into `1234e54`, which we describe with a positive integer `f = 1234` and an +//! integer `e = 54`. +//! The `(f, e)` representation is used by almost all code past the parsing +//! stage. //! -//! We then try a long chain of progressively more general and expensive special cases using -//! machine-sized integers and small, fixed-sized floating point numbers (first `f32`/`f64`, then -//! a type with 64 bit significand, `Fp`). When all these fail, we bite the bullet and resort to a -//! simple but very slow algorithm that involved computing `f * 10^e` fully and doing an iterative +//! We then try a long chain of progressively more general and expensive +//! special cases using +//! machine-sized integers and small, fixed-sized floating point numbers (first +//! `f32`/`f64`, then +//! a type with 64 bit significand, `Fp`). When all these fail, we bite the +//! bullet and resort to a +//! simple but very slow algorithm that involved computing `f * 10^e` fully and +//! doing an iterative //! search for the best approximation. //! -//! Primarily, this module and its children implement the algorithms described in: +//! Primarily, this module and its children implement the algorithms described +//! in: //! "How to Read Floating Point Numbers Accurately" by William D. Clinger, -//! available online: http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.45.4152 +//! available online: +//! http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.45.4152 //! -//! In addition, there are numerous helper functions that are used in the paper but not available -//! in Rust (or at least in core). Our version is additionally complicated by the need to handle -//! overflow and underflow and the desire to handle subnormal numbers. Bellerophon and -//! Algorithm R have trouble with overflow, subnormals, and underflow. We conservatively switch to -//! Algorithm M (with the modifications described in section 8 of the paper) well before the +//! In addition, there are numerous helper functions that are used in the paper +//! but not available +//! in Rust (or at least in core). Our version is additionally complicated by +//! the need to handle +//! overflow and underflow and the desire to handle subnormal numbers. +//! Bellerophon and +//! Algorithm R have trouble with overflow, subnormals, and underflow. We +//! conservatively switch to +//! Algorithm M (with the modifications described in section 8 of the paper) +//! well before the //! inputs get into the critical region. //! -//! Another aspect that needs attention is the ``RawFloat`` trait by which almost all functions -//! are parametrized. One might think that it's enough to parse to `f64` and cast the result to -//! `f32`. Unfortunately this is not the world we live in, and this has nothing to do with using +//! Another aspect that needs attention is the ``RawFloat`` trait by which +//! almost all functions +//! are parametrized. One might think that it's enough to parse to `f64` and +//! cast the result to +//! `f32`. Unfortunately this is not the world we live in, and this has nothing +//! to do with using //! base two or half-to-even rounding. //! -//! Consider for example two types `d2` and `d4` representing a decimal type with two decimal -//! digits and four decimal digits each and take "0.01499" as input. Let's use half-up rounding. -//! Going directly to two decimal digits gives `0.01`, but if we round to four digits first, -//! we get `0.0150`, which is then rounded up to `0.02`. The same principle applies to other -//! operations as well, if you want 0.5 ULP accuracy you need to do *everything* in full precision -//! and round *exactly once, at the end*, by considering all truncated bits at once. +//! Consider for example two types `d2` and `d4` representing a decimal type +//! with two decimal +//! digits and four decimal digits each and take "0.01499" as input. Let's use +//! half-up rounding. +//! Going directly to two decimal digits gives `0.01`, but if we round to four +//! digits first, +//! we get `0.0150`, which is then rounded up to `0.02`. The same principle +//! applies to other +//! operations as well, if you want 0.5 ULP accuracy you need to do +//! *everything* in full precision +//! and round *exactly once, at the end*, by considering all truncated bits at +//! once. //! -//! FIXME Although some code duplication is necessary, perhaps parts of the code could be shuffled -//! around such that less code is duplicated. Large parts of the algorithms are independent of the -//! float type to output, or only needs access to a few constants, which could be passed in as +//! FIXME Although some code duplication is necessary, perhaps parts of the +//! code could be shuffled +//! around such that less code is duplicated. Large parts of the algorithms are +//! independent of the +//! float type to output, or only needs access to a few constants, which could +//! be passed in as //! parameters. //! //! # Other //! -//! The conversion should *never* panic. There are assertions and explicit panics in the code, -//! but they should never be triggered and only serve as internal sanity checks. Any panics should +//! The conversion should *never* panic. There are assertions and explicit +//! panics in the code, +//! but they should never be triggered and only serve as internal sanity +//! checks. Any panics should //! be considered a bug. //! -//! There are unit tests but they are woefully inadequate at ensuring correctness, they only cover -//! a small percentage of possible errors. Far more extensive tests are located in the directory +//! There are unit tests but they are woefully inadequate at ensuring +//! correctness, they only cover +//! a small percentage of possible errors. Far more extensive tests are located +//! in the directory //! `src/etc/test-float-parse` as a Python script. //! -//! A note on integer overflow: Many parts of this file perform arithmetic with the decimal -//! exponent `e`. Primarily, we shift the decimal point around: Before the first decimal digit, -//! after the last decimal digit, and so on. This could overflow if done carelessly. We rely on -//! the parsing submodule to only hand out sufficiently small exponents, where "sufficient" means -//! "such that the exponent +/- the number of decimal digits fits into a 64 bit integer". -//! Larger exponents are accepted, but we don't do arithmetic with them, they are immediately +//! A note on integer overflow: Many parts of this file perform arithmetic with +//! the decimal +//! exponent `e`. Primarily, we shift the decimal point around: Before the +//! first decimal digit, +//! after the last decimal digit, and so on. This could overflow if done +//! carelessly. We rely on +//! the parsing submodule to only hand out sufficiently small exponents, where +//! "sufficient" means +//! "such that the exponent +/- the number of decimal digits fits into a 64 bit +//! integer". +//! Larger exponents are accepted, but we don't do arithmetic with them, they +//! are immediately //! turned into {positive,negative} {zero,infinity}. #![doc(hidden)] @@ -204,7 +249,7 @@ fn extract_sign(s: &str) -> (Sign, &str) { /// Convert a decimal string into a floating point number. fn dec2flt(s: &str) -> Result { if s.is_empty() { - return Err(pfe_empty()) + return Err(pfe_empty()); } let (sign, s) = extract_sign(s); let flt = match parse_decimal(s) { @@ -240,17 +285,22 @@ fn convert(mut decimal: Decimal) -> Result { if let Some(x) = algorithm::fast_path(decimal.integral, decimal.fractional, e) { return Ok(x); } - // Big32x40 is limited to 1280 bits, which translates to about 385 decimal digits. - // If we exceed this, perhaps while calculating `f * 10^e` in Algorithm R or Algorithm M, - // we'll crash. So we error out before getting too close, with a generous safety margin. + // Big32x40 is limited to 1280 bits, which translates to about 385 decimal + // digits. + // If we exceed this, perhaps while calculating `f * 10^e` in Algorithm R or + // Algorithm M, + // we'll crash. So we error out before getting too close, with a generous + // safety margin. if max_digits > 375 { return Err(pfe_invalid()); } let f = digits_to_big(decimal.integral, decimal.fractional); - // Now the exponent certainly fits in 16 bit, which is used throughout the main algorithms. + // Now the exponent certainly fits in 16 bit, which is used throughout the main + // algorithms. let e = e as i16; - // FIXME These bounds are rather conservative. A more careful analysis of the failure modes + // FIXME These bounds are rather conservative. A more careful analysis of the + // failure modes // of Bellerophon could allow using it in more cases for a massive speed up. let exponent_in_range = table::MIN_E <= e && e <= table::MAX_E; let value_in_range = max_digits <= T::max_normal_digits(); @@ -261,23 +311,29 @@ fn convert(mut decimal: Decimal) -> Result { } } -// As written, this optimizes badly (see #27130, though it refers to an old version of the code). -// `inline(always)` is a workaround for that. There are only two call sites overall and it doesn't +// As written, this optimizes badly (see #27130, though it refers to an old +// version of the code). +// `inline(always)` is a workaround for that. There are only two call sites +// overall and it doesn't // make code size worse. /// Strip zeros where possible, even when this requires changing the exponent #[inline(always)] fn simplify(decimal: &mut Decimal) { let is_zero = &|&&d: &&u8| -> bool { d == b'0' }; - // Trimming these zeros does not change anything but may enable the fast path (< 15 digits). + // Trimming these zeros does not change anything but may enable the fast path + // (< 15 digits). let leading_zeros = decimal.integral.iter().take_while(is_zero).count(); decimal.integral = &decimal.integral[leading_zeros..]; let trailing_zeros = decimal.fractional.iter().rev().take_while(is_zero).count(); let end = decimal.fractional.len() - trailing_zeros; decimal.fractional = &decimal.fractional[..end]; - // Simplify numbers of the form 0.0...x and x...0.0, adjusting the exponent accordingly. - // This may not always be a win (possibly pushes some numbers out of the fast path), but it - // simplifies other parts significantly (notably, approximating the magnitude of the value). + // Simplify numbers of the form 0.0...x and x...0.0, adjusting the exponent + // accordingly. + // This may not always be a win (possibly pushes some numbers out of the fast + // path), but it + // simplifies other parts significantly (notably, approximating the magnitude + // of the value). if decimal.integral.is_empty() { let leading_zeros = decimal.fractional.iter().take_while(is_zero).count(); decimal.fractional = &decimal.fractional[leading_zeros..]; diff --git a/src/libcore/num/dec2flt/num.rs b/src/libcore/num/dec2flt/num.rs index 7febbdb242b89..57d2d57081134 100644 --- a/src/libcore/num/dec2flt/num.rs +++ b/src/libcore/num/dec2flt/num.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Utility functions for bignums that don't make too much sense to turn into methods. +//! Utility functions for bignums that don't make too much sense to turn into +//! methods. -// FIXME This module's name is a bit unfortunate, since other modules also import `core::num`. +// FIXME This module's name is a bit unfortunate, since other modules also +// import `core::num`. use prelude::v1::*; use cmp::Ordering::{self, Less, Equal, Greater}; @@ -29,7 +31,8 @@ pub fn compare_with_half_ulp(f: &Big, ones_place: usize) -> Ordering { return Less; } // If all remaining bits are zero, it's = 0.5 ULP, otherwise > 0.5 - // If there are no more bits (half_bit == 0), the below also correctly returns Equal. + // If there are no more bits (half_bit == 0), the below also correctly returns + // Equal. for i in 0..half_bit { if f.get_bit(i) == 1 { return Greater; diff --git a/src/libcore/num/dec2flt/parse.rs b/src/libcore/num/dec2flt/parse.rs index 5b260428f47e3..7b0091669c015 100644 --- a/src/libcore/num/dec2flt/parse.rs +++ b/src/libcore/num/dec2flt/parse.rs @@ -12,14 +12,19 @@ //! //! `(digits | digits? '.'? digits?) (('e' | 'E') ('+' | '-')? digits)?` //! -//! In other words, standard floating-point syntax, with two exceptions: No sign, and no -//! handling of "inf" and "NaN". These are handled by the driver function (super::dec2flt). +//! In other words, standard floating-point syntax, with two exceptions: No +//! sign, and no +//! handling of "inf" and "NaN". These are handled by the driver function +//! (super::dec2flt). //! -//! Although recognizing valid inputs is relatively easy, this module also has to reject the -//! countless invalid variations, never panic, and perform numerous checks that the other +//! Although recognizing valid inputs is relatively easy, this module also has +//! to reject the +//! countless invalid variations, never panic, and perform numerous checks that +//! the other //! modules rely on to not panic (or overflow) in turn. //! To make matters worse, all that happens in a single pass over the input. -//! So, be careful when modifying anything, and double-check with the other modules. +//! So, be careful when modifying anything, and double-check with the other +//! modules. use prelude::v1::*; use super::num; use self::ParseResult::{Valid, ShortcutToInf, ShortcutToZero, Invalid}; @@ -114,10 +119,14 @@ fn parse_exp<'a>(integral: &'a [u8], fractional: &'a [u8], rest: &'a [u8]) -> Pa if number.is_empty() { return Invalid; // Empty exponent } - // At this point, we certainly have a valid string of digits. It may be too long to put into - // an `i64`, but if it's that huge, the input is certainly zero or infinity. Since each zero - // in the decimal digits only adjusts the exponent by +/- 1, at exp = 10^18 the input would - // have to be 17 exabyte (!) of zeros to get even remotely close to being finite. + // At this point, we certainly have a valid string of digits. It may be too + // long to put into + // an `i64`, but if it's that huge, the input is certainly zero or infinity. + // Since each zero + // in the decimal digits only adjusts the exponent by +/- 1, at exp = 10^18 the + // input would + // have to be 17 exabyte (!) of zeros to get even remotely close to being + // finite. // This is not exactly a use case we need to cater to. while number.first() == Some(&b'0') { number = &number[1..]; diff --git a/src/libcore/num/dec2flt/rawfp.rs b/src/libcore/num/dec2flt/rawfp.rs index 0d00861447d2f..fb5f5f72f1e3d 100644 --- a/src/libcore/num/dec2flt/rawfp.rs +++ b/src/libcore/num/dec2flt/rawfp.rs @@ -8,25 +8,35 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Bit fiddling on positive IEEE 754 floats. Negative numbers aren't and needn't be handled. -//! Normal floating point numbers have a canonical representation as (frac, exp) such that the -//! value is 2^exp * (1 + sum(frac[N-i] / 2^i)) where N is the number of bits. Subnormals are +//! Bit fiddling on positive IEEE 754 floats. Negative numbers aren't and +//! needn't be handled. +//! Normal floating point numbers have a canonical representation as (frac, +//! exp) such that the +//! value is 2^exp * (1 + sum(frac[N-i] / 2^i)) where N is the number of bits. +//! Subnormals are //! slightly different and weird, but the same principle applies. //! -//! Here, however, we represent them as (sig, k) with f positive, such that the value is f * 2^e. -//! Besides making the "hidden bit" explicit, this changes the exponent by the so-called +//! Here, however, we represent them as (sig, k) with f positive, such that the +//! value is f * 2^e. +//! Besides making the "hidden bit" explicit, this changes the exponent by the +//! so-called //! mantissa shift. //! -//! Put another way, normally floats are written as (1) but here they are written as (2): +//! Put another way, normally floats are written as (1) but here they are +//! written as (2): //! //! 1. `1.101100...11 * 2^m` //! 2. `1101100...11 * 2^n` //! -//! We call (1) the **fractional representation** and (2) the **integral representation**. +//! We call (1) the **fractional representation** and (2) the **integral +//! representation**. //! -//! Many functions in this module only handle normal numbers. The dec2flt routines conservatively -//! take the universally-correct slow path (Algorithm M) for very small and very large numbers. -//! That algorithm needs only next_float() which does handle subnormals and zeros. +//! Many functions in this module only handle normal numbers. The dec2flt +//! routines conservatively +//! take the universally-correct slow path (Algorithm M) for very small and +//! very large numbers. +//! That algorithm needs only next_float() which does handle subnormals and +//! zeros. use prelude::v1::*; use u32; use cmp::Ordering::{Less, Equal, Greater}; @@ -73,16 +83,19 @@ pub trait RawFloat : Float + Copy + Debug + LowerExp /// represented, the other code in this module makes sure to never let that happen. fn from_int(x: u64) -> Self; - // FIXME Everything that follows should be associated constants, but taking the value of an + // FIXME Everything that follows should be associated constants, but taking the + // value of an // associated constant from a type parameter does not work (yet?) - // A possible workaround is having a `FloatInfo` struct for all the constants, but so far + // A possible workaround is having a `FloatInfo` struct for all the constants, + // but so far // the methods aren't painful enough to rewrite. /// What the name says. It's easier to hard code than juggling intrinsics and /// hoping LLVM constant folds it. fn ceil_log5_of_max_sig() -> i16; - // A conservative bound on the decimal digits of inputs that can't produce overflow or zero or + // A conservative bound on the decimal digits of inputs that can't produce + // overflow or zero or /// subnormals. Probably the decimal exponent of the maximum normal value, hence the name. fn max_normal_digits() -> usize; @@ -289,7 +302,8 @@ pub fn encode_normal(x: Unpacked) -> T { pub fn encode_subnormal(significand: u64) -> T { assert!(significand < T::min_sig(), "encode_subnormal: not actually subnormal"); - // Êncoded exponent is 0, the sign bit is 0, so we just have to reinterpret the bits. + // Êncoded exponent is 0, the sign bit is 0, so we just have to reinterpret the + // bits. T::from_bits(significand) } @@ -299,7 +313,8 @@ pub fn big_to_fp(f: &Big) -> Fp { assert!(end != 0, "big_to_fp: unexpectedly, input is zero"); let start = end.saturating_sub(64); let leading = num::get_bits(f, start, end); - // We cut off all bits prior to the index `start`, i.e., we effectively right-shift by + // We cut off all bits prior to the index `start`, i.e., we effectively + // right-shift by // an amount of `start`, so this is also the exponent we need. let e = start as i16; let rounded_down = Fp { f: leading, e: e }.normalize(); @@ -338,8 +353,10 @@ pub fn prev_float(x: T) -> T { // Find the smallest floating point number strictly larger than the argument. // This operation is saturating, i.e. next_float(inf) == inf. -// Unlike most code in this module, this function does handle zero, subnormals, and infinities. -// However, like all other code here, it does not deal with NaN and negative numbers. +// Unlike most code in this module, this function does handle zero, subnormals, +// and infinities. +// However, like all other code here, it does not deal with NaN and negative +// numbers. pub fn next_float(x: T) -> T { match x.classify() { Nan => panic!("next_float: argument is NaN"), diff --git a/src/libcore/num/diy_float.rs b/src/libcore/num/diy_float.rs index 11eea753f93f9..4a8332bfab276 100644 --- a/src/libcore/num/diy_float.rs +++ b/src/libcore/num/diy_float.rs @@ -10,7 +10,8 @@ //! Extended precision "soft float", for internal use only. -// This module is only for dec2flt and flt2dec, and only public because of libcoretest. +// This module is only for dec2flt and flt2dec, and only public because of +// libcoretest. // It is not intended to ever be stabilized. #![doc(hidden)] #![unstable(feature = "core_private_diy_float", diff --git a/src/libcore/num/flt2dec/decoder.rs b/src/libcore/num/flt2dec/decoder.rs index 2b7f7604243a2..b67d16e351aa3 100644 --- a/src/libcore/num/flt2dec/decoder.rs +++ b/src/libcore/num/flt2dec/decoder.rs @@ -71,7 +71,10 @@ impl DecodableFloat for f64 { /// Returns a sign (true when negative) and `FullDecoded` value /// from given floating point number. -pub fn decode(v: T) -> (/*negative?*/ bool, FullDecoded) { +pub fn decode(v: T) + -> (// negative? + bool, + FullDecoded) { let (mant, exp, sign) = v.integer_decode(); let even = (mant & 1) == 0; let decoded = match v.classify() { diff --git a/src/libcore/num/flt2dec/mod.rs b/src/libcore/num/flt2dec/mod.rs index f75a677515d20..66041ffc32a70 100644 --- a/src/libcore/num/flt2dec/mod.rs +++ b/src/libcore/num/flt2dec/mod.rs @@ -8,120 +8,130 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - -Floating-point number to decimal conversion routines. - -# Problem statement - -We are given the floating-point number `v = f * 2^e` with an integer `f`, -and its bounds `minus` and `plus` such that any number between `v - minus` and -`v + plus` will be rounded to `v`. For the simplicity we assume that -this range is exclusive. Then we would like to get the unique decimal -representation `V = 0.d[0..n-1] * 10^k` such that: - -- `d[0]` is non-zero. - -- It's correctly rounded when parsed back: `v - minus < V < v + plus`. - Furthermore it is shortest such one, i.e. there is no representation - with less than `n` digits that is correctly rounded. - -- It's closest to the original value: `abs(V - v) <= 10^(k-n) / 2`. Note that - there might be two representations satisfying this uniqueness requirement, - in which case some tie-breaking mechanism is used. - -We will call this mode of operation as to the *shortest* mode. This mode is used -when there is no additional constraint, and can be thought as a "natural" mode -as it matches the ordinary intuition (it at least prints `0.1f32` as "0.1"). - -We have two more modes of operation closely related to each other. In these modes -we are given either the number of significant digits `n` or the last-digit -limitation `limit` (which determines the actual `n`), and we would like to get -the representation `V = 0.d[0..n-1] * 10^k` such that: - -- `d[0]` is non-zero, unless `n` was zero in which case only `k` is returned. - -- It's closest to the original value: `abs(V - v) <= 10^(k-n) / 2`. Again, - there might be some tie-breaking mechanism. - -When `limit` is given but not `n`, we set `n` such that `k - n = limit` -so that the last digit `d[n-1]` is scaled by `10^(k-n) = 10^limit`. -If such `n` is negative, we clip it to zero so that we will only get `k`. -We are also limited by the supplied buffer. This limitation is used to print -the number up to given number of fractional digits without knowing -the correct `k` beforehand. - -We will call the mode of operation requiring `n` as to the *exact* mode, -and one requiring `limit` as to the *fixed* mode. The exact mode is a subset of -the fixed mode: the sufficiently large last-digit limitation will eventually fill -the supplied buffer and let the algorithm to return. - -# Implementation overview - -It is easy to get the floating point printing correct but slow (Russ Cox has -[demonstrated](http://research.swtch.com/ftoa) how it's easy), or incorrect but -fast (naïve division and modulo). But it is surprisingly hard to print -floating point numbers correctly *and* efficiently. - -There are two classes of algorithms widely known to be correct. - -- The "Dragon" family of algorithm is first described by Guy L. Steele Jr. and - Jon L. White. They rely on the fixed-size big integer for their correctness. - A slight improvement was found later, which is posthumously described by - Robert G. Burger and R. Kent Dybvig. David Gay's `dtoa.c` routine is - a popular implementation of this strategy. - -- The "Grisu" family of algorithm is first described by Florian Loitsch. - They use very cheap integer-only procedure to determine the close-to-correct - representation which is at least guaranteed to be shortest. The variant, - Grisu3, actively detects if the resulting representation is incorrect. - -We implement both algorithms with necessary tweaks to suit our requirements. -In particular, published literatures are short of the actual implementation -difficulties like how to avoid arithmetic overflows. Each implementation, -available in `strategy::dragon` and `strategy::grisu` respectively, -extensively describes all necessary justifications and many proofs for them. -(It is still difficult to follow though. You have been warned.) - -Both implementations expose two public functions: - -- `format_shortest(decoded, buf)`, which always needs at least - `MAX_SIG_DIGITS` digits of buffer. Implements the shortest mode. - -- `format_exact(decoded, buf, limit)`, which accepts as small as - one digit of buffer. Implements exact and fixed modes. - -They try to fill the `u8` buffer with digits and returns the number of digits -written and the exponent `k`. They are total for all finite `f32` and `f64` -inputs (Grisu internally falls back to Dragon if necessary). - -The rendered digits are formatted into the actual string form with -four functions: - -- `to_shortest_str` prints the shortest representation, which can be padded by - zeroes to make *at least* given number of fractional digits. - -- `to_shortest_exp_str` prints the shortest representation, which can be - padded by zeroes when its exponent is in the specified ranges, - or can be printed in the exponential form such as `1.23e45`. - -- `to_exact_exp_str` prints the exact representation with given number of - digits in the exponential form. - -- `to_exact_fixed_str` prints the fixed representation with *exactly* - given number of fractional digits. - -They all return a slice of preallocated `Part` array, which corresponds to -the individual part of strings: a fixed string, a part of rendered digits, -a number of zeroes or a small (`u16`) number. The caller is expected to -provide a large enough buffer and `Part` array, and to assemble the final -string from resulting `Part`s itself. - -All algorithms and formatting functions are accompanied by extensive tests -in `coretest::num::flt2dec` module. It also shows how to use individual -functions. - -*/ +// ! +// +// Floating-point number to decimal conversion routines. +// +// # Problem statement +// +// We are given the floating-point number `v = f * 2^e` with an integer `f`, +// and its bounds `minus` and `plus` such that any number between `v - minus` +// and +// `v + plus` will be rounded to `v`. For the simplicity we assume that +// this range is exclusive. Then we would like to get the unique decimal +// representation `V = 0.d[0..n-1] * 10^k` such that: +// +// - `d[0]` is non-zero. +// +// - It's correctly rounded when parsed back: `v - minus < V < v + plus`. +// Furthermore it is shortest such one, i.e. there is no representation +// with less than `n` digits that is correctly rounded. +// +// - It's closest to the original value: `abs(V - v) <= 10^(k-n) / 2`. Note that +// there might be two representations satisfying this uniqueness requirement, +// in which case some tie-breaking mechanism is used. +// +// We will call this mode of operation as to the *shortest* mode. This mode is +// used +// when there is no additional constraint, and can be thought as a "natural" +// mode +// as it matches the ordinary intuition (it at least prints `0.1f32` as "0.1"). +// +// We have two more modes of operation closely related to each other. In these +// modes +// we are given either the number of significant digits `n` or the last-digit +// limitation `limit` (which determines the actual `n`), and we would like to +// get +// the representation `V = 0.d[0..n-1] * 10^k` such that: +// +// - `d[0]` is non-zero, unless `n` was zero in which case only `k` is returned. +// +// - It's closest to the original value: `abs(V - v) <= 10^(k-n) / 2`. Again, +// there might be some tie-breaking mechanism. +// +// When `limit` is given but not `n`, we set `n` such that `k - n = limit` +// so that the last digit `d[n-1]` is scaled by `10^(k-n) = 10^limit`. +// If such `n` is negative, we clip it to zero so that we will only get `k`. +// We are also limited by the supplied buffer. This limitation is used to print +// the number up to given number of fractional digits without knowing +// the correct `k` beforehand. +// +// We will call the mode of operation requiring `n` as to the *exact* mode, +// and one requiring `limit` as to the *fixed* mode. The exact mode is a subset +// of +// the fixed mode: the sufficiently large last-digit limitation will eventually +// fill +// the supplied buffer and let the algorithm to return. +// +// # Implementation overview +// +// It is easy to get the floating point printing correct but slow (Russ Cox has +// [demonstrated](http://research.swtch.com/ftoa) how it's easy), or incorrect +// but +// fast (naïve division and modulo). But it is surprisingly hard to print +// floating point numbers correctly *and* efficiently. +// +// There are two classes of algorithms widely known to be correct. +// +// - The "Dragon" family of algorithm is first described by Guy L. Steele Jr. +// and +// Jon L. White. They rely on the fixed-size big integer for their correctness. +// A slight improvement was found later, which is posthumously described by +// Robert G. Burger and R. Kent Dybvig. David Gay's `dtoa.c` routine is +// a popular implementation of this strategy. +// +// - The "Grisu" family of algorithm is first described by Florian Loitsch. +// They use very cheap integer-only procedure to determine the close-to-correct +// representation which is at least guaranteed to be shortest. The variant, +// Grisu3, actively detects if the resulting representation is incorrect. +// +// We implement both algorithms with necessary tweaks to suit our requirements. +// In particular, published literatures are short of the actual implementation +// difficulties like how to avoid arithmetic overflows. Each implementation, +// available in `strategy::dragon` and `strategy::grisu` respectively, +// extensively describes all necessary justifications and many proofs for them. +// (It is still difficult to follow though. You have been warned.) +// +// Both implementations expose two public functions: +// +// - `format_shortest(decoded, buf)`, which always needs at least +// `MAX_SIG_DIGITS` digits of buffer. Implements the shortest mode. +// +// - `format_exact(decoded, buf, limit)`, which accepts as small as +// one digit of buffer. Implements exact and fixed modes. +// +// They try to fill the `u8` buffer with digits and returns the number of digits +// written and the exponent `k`. They are total for all finite `f32` and `f64` +// inputs (Grisu internally falls back to Dragon if necessary). +// +// The rendered digits are formatted into the actual string form with +// four functions: +// +// - `to_shortest_str` prints the shortest representation, which can be padded +// by +// zeroes to make *at least* given number of fractional digits. +// +// - `to_shortest_exp_str` prints the shortest representation, which can be +// padded by zeroes when its exponent is in the specified ranges, +// or can be printed in the exponential form such as `1.23e45`. +// +// - `to_exact_exp_str` prints the exact representation with given number of +// digits in the exponential form. +// +// - `to_exact_fixed_str` prints the fixed representation with *exactly* +// given number of fractional digits. +// +// They all return a slice of preallocated `Part` array, which corresponds to +// the individual part of strings: a fixed string, a part of rendered digits, +// a number of zeroes or a small (`u16`) number. The caller is expected to +// provide a large enough buffer and `Part` array, and to assemble the final +// string from resulting `Part`s itself. +// +// All algorithms and formatting functions are accompanied by extensive tests +// in `coretest::num::flt2dec` module. It also shows how to use individual +// functions. +// +// // while this is extensively documented, this is in principle private which is // only made public for testing. do not expose us. @@ -156,21 +166,24 @@ pub const MAX_SIG_DIGITS: usize = 17; #[doc(hidden)] pub fn round_up(d: &mut [u8], n: usize) -> Option { match d[..n].iter().rposition(|&c| c != b'9') { - Some(i) => { // d[i+1..n] is all nines + Some(i) => { + // d[i+1..n] is all nines d[i] += 1; for j in i + 1..n { d[j] = b'0'; } None } - None if n > 0 => { // 999..999 rounds to 1000..000 with an increased exponent + None if n > 0 => { + // 999..999 rounds to 1000..000 with an increased exponent d[0] = b'1'; for j in 1..n { d[j] = b'0'; } Some(b'0') } - None => { // an empty buffer rounds up (a bit strange but reasonable) + None => { + // an empty buffer rounds up (a bit strange but reasonable) Some(b'1') } } @@ -301,7 +314,8 @@ fn digits_to_dec_str<'a>(buf: &'a [u8], assert!(buf[0] > b'0'); assert!(parts.len() >= 4); - // if there is the restriction on the last digit position, `buf` is assumed to be + // if there is the restriction on the last digit position, `buf` is assumed to + // be // left-padded with the virtual zeroes. the number of virtual zeroes, `nzeroes`, // equals to `max(0, exp + frac_digits - buf.len())`, so that the position of // the last digit `exp - buf.len() - nzeroes` is no more than `-frac_digits`: @@ -312,7 +326,8 @@ fn digits_to_dec_str<'a>(buf: &'a [u8], // | | | // 10^exp 10^(exp-buf.len()) 10^(exp-buf.len()-nzeroes) // - // `nzeroes` is individually calculated for each case in order to avoid overflow. + // `nzeroes` is individually calculated for each case in order to avoid + // overflow. if exp <= 0 { // the decimal point is before rendered digits: [0.][000...000][1234][____] @@ -340,7 +355,8 @@ fn digits_to_dec_str<'a>(buf: &'a [u8], &parts[..3] } } else { - // the decimal point is after rendered digits: [1234][____0000] or [1234][__][.][__]. + // the decimal point is after rendered digits: [1234][____0000] or + // [1234][__][.][__]. parts[0] = Part::Copy(buf); parts[1] = Part::Zero(exp - buf.len()); if frac_digits > 0 { @@ -412,11 +428,11 @@ fn digits_to_exp_str<'a>(buf: &'a [u8], #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum Sign { /// Prints `-` only for the negative non-zero values. - Minus, // -inf -1 0 0 1 inf nan + Minus, // -inf -1 0 0 1 inf nan /// Prints `-` only for any negative values (including the negative zero). - MinusRaw, // -inf -1 -0 0 1 inf nan + MinusRaw, // -inf -1 -0 0 1 inf nan /// Prints `-` for the negative non-zero values, or `+` otherwise. - MinusPlus, // -inf -1 +0 +0 +1 +inf nan + MinusPlus, // -inf -1 +0 +0 +1 +inf nan /// Prints `-` for any negative values (including the negative zero), or `+` otherwise. MinusPlusRaw, // -inf -1 -0 +0 +1 +inf nan } @@ -501,7 +517,8 @@ pub fn to_shortest_str<'a, T, F>(mut format_shortest: F, } } FullDecoded::Zero => { - if frac_digits > 0 { // [0.][0000] + if frac_digits > 0 { + // [0.][0000] parts[0] = Part::Copy(b"0."); parts[1] = Part::Zero(frac_digits); Formatted { @@ -685,7 +702,8 @@ pub fn to_exact_exp_str<'a, T, F>(mut format_exact: F, } } FullDecoded::Zero => { - if ndigits > 1 { // [0.][0000][e0] + if ndigits > 1 { + // [0.][0000][e0] parts[0] = Part::Copy(b"0."); parts[1] = Part::Zero(ndigits - 1); parts[2] = Part::Copy(if upper { @@ -773,7 +791,8 @@ pub fn to_exact_fixed_str<'a, T, F>(mut format_exact: F, } } FullDecoded::Zero => { - if frac_digits > 0 { // [0.][0000] + if frac_digits > 0 { + // [0.][0000] parts[0] = Part::Copy(b"0."); parts[1] = Part::Zero(frac_digits); Formatted { @@ -806,7 +825,8 @@ pub fn to_exact_fixed_str<'a, T, F>(mut format_exact: F, // `exp` was. this does not include the case that the restriction has been met // only after the final rounding-up; it's a regular case with `exp = limit + 1`. debug_assert_eq!(len, 0); - if frac_digits > 0 { // [0.][0000] + if frac_digits > 0 { + // [0.][0000] parts[0] = Part::Copy(b"0."); parts[1] = Part::Zero(frac_digits); Formatted { diff --git a/src/libcore/num/flt2dec/strategy/dragon.rs b/src/libcore/num/flt2dec/strategy/dragon.rs index 5a5d8b294b5e3..327c97d210983 100644 --- a/src/libcore/num/flt2dec/strategy/dragon.rs +++ b/src/libcore/num/flt2dec/strategy/dragon.rs @@ -8,12 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! -Almost direct (but slightly optimized) Rust translation of Figure 3 of [1]. - -[1] Burger, R. G. and Dybvig, R. K. 1996. Printing floating-point numbers - quickly and accurately. SIGPLAN Not. 31, 5 (May. 1996), 108-116. -*/ +// ! +// Almost direct (but slightly optimized) Rust translation of Figure 3 of [1]. +// +// [1] Burger, R. G. and Dybvig, R. K. 1996. Printing floating-point numbers +// quickly and accurately. SIGPLAN Not. 31, 5 (May. 1996), 108-116. +// use prelude::v1::*; @@ -24,22 +24,23 @@ use num::flt2dec::estimator::estimate_scaling_factor; use num::bignum::Digit32 as Digit; use num::bignum::Big32x40 as Big; -static POW10: [Digit; 10] = [ - 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000]; -static TWOPOW10: [Digit; 10] = [ - 2, 20, 200, 2000, 20000, 200000, 2000000, 20000000, 200000000, 2000000000]; +static POW10: [Digit; 10] = [1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, + 1000000000]; +static TWOPOW10: [Digit; 10] = [2, 20, 200, 2000, 20000, 200000, 2000000, 20000000, 200000000, + 2000000000]; // precalculated arrays of `Digit`s for 10^(2^n) static POW10TO16: [Digit; 2] = [0x6fc10000, 0x2386f2]; static POW10TO32: [Digit; 4] = [0, 0x85acef81, 0x2d6d415b, 0x4ee]; static POW10TO64: [Digit; 7] = [0, 0, 0xbf6a1f01, 0x6e38ed64, 0xdaa797ed, 0xe93ff9f4, 0x184f03]; -static POW10TO128: [Digit; 14] = - [0, 0, 0, 0, 0x2e953e01, 0x3df9909, 0xf1538fd, 0x2374e42f, 0xd3cff5ec, 0xc404dc08, 0xbccdb0da, - 0xa6337f19, 0xe91f2603, 0x24e]; -static POW10TO256: [Digit; 27] = - [0, 0, 0, 0, 0, 0, 0, 0, 0x982e7c01, 0xbed3875b, 0xd8d99f72, 0x12152f87, 0x6bde50c6, 0xcf4a6e70, - 0xd595d80f, 0x26b2716e, 0xadc666b0, 0x1d153624, 0x3c42d35a, 0x63ff540e, 0xcc5573c0, 0x65f9ef17, - 0x55bc28f2, 0x80dcc7f7, 0xf46eeddc, 0x5fdcefce, 0x553f7]; +static POW10TO128: [Digit; 14] = [0, 0, 0, 0, 0x2e953e01, 0x3df9909, 0xf1538fd, 0x2374e42f, + 0xd3cff5ec, 0xc404dc08, 0xbccdb0da, 0xa6337f19, 0xe91f2603, + 0x24e]; +static POW10TO256: [Digit; 27] = [0, 0, 0, 0, 0, 0, 0, 0, 0x982e7c01, 0xbed3875b, 0xd8d99f72, + 0x12152f87, 0x6bde50c6, 0xcf4a6e70, 0xd595d80f, 0x26b2716e, + 0xadc666b0, 0x1d153624, 0x3c42d35a, 0x63ff540e, 0xcc5573c0, + 0x65f9ef17, 0x55bc28f2, 0x80dcc7f7, 0xf46eeddc, 0x5fdcefce, + 0x553f7]; #[doc(hidden)] pub fn mul_pow10(x: &mut Big, n: usize) -> &mut Big { @@ -107,18 +108,26 @@ fn div_rem_upto_16<'a>(x: &'a mut Big, } /// The shortest mode implementation for Dragon. -pub fn format_shortest(d: &Decoded, buf: &mut [u8]) -> (/*#digits*/ usize, /*exp*/ i16) { +pub fn format_shortest(d: &Decoded, + buf: &mut [u8]) + -> (// #digits + usize, + // exp + i16) { // the number `v` to format is known to be: // - equal to `mant * 2^exp`; // - preceded by `(mant - 2 * minus) * 2^exp` in the original type; and // - followed by `(mant + 2 * plus) * 2^exp` in the original type. // - // obviously, `minus` and `plus` cannot be zero. (for infinities, we use out-of-range values.) - // also we assume that at least one digit is generated, i.e. `mant` cannot be zero too. + // obviously, `minus` and `plus` cannot be zero. (for infinities, we use + // out-of-range values.) + // also we assume that at least one digit is generated, i.e. `mant` cannot be + // zero too. // // this also means that any number between `low = (mant - minus) * 2^exp` and // `high = (mant + plus) * 2^exp` will map to this exact floating point number, - // with bounds included when the original mantissa was even (i.e. `!mant_was_odd`). + // with bounds included when the original mantissa was even (i.e. + // `!mant_was_odd`). assert!(d.mant > 0); assert!(d.minus > 0); @@ -134,7 +143,8 @@ pub fn format_shortest(d: &Decoded, buf: &mut [u8]) -> (/*#digits*/ usize, /*exp Ordering::Equal }; - // estimate `k_0` from original inputs satisfying `10^(k_0-1) < high <= 10^(k_0+1)`. + // estimate `k_0` from original inputs satisfying `10^(k_0-1) < high <= + // 10^(k_0+1)`. // the tight bound `k` satisfying `10^(k-1) < high <= 10^k` is calculated later. let mut k = estimate_scaling_factor(d.mant + d.plus, d.exp); @@ -164,11 +174,13 @@ pub fn format_shortest(d: &Decoded, buf: &mut [u8]) -> (/*#digits*/ usize, /*exp } // fixup when `mant + plus > scale` (or `>=`). - // we are not actually modifying `scale`, since we can skip the initial multiplication instead. + // we are not actually modifying `scale`, since we can skip the initial + // multiplication instead. // now `scale < mant + plus <= scale * 10` and we are ready to generate digits. // // note that `d[0]` *can* be zero, when `scale - plus < mant < scale`. - // in this case rounding-up condition (`up` below) will be triggered immediately. + // in this case rounding-up condition (`up` below) will be triggered + // immediately. if scale.cmp(mant.clone().add(&plus)) < rounding { // equivalent to scaling `scale` by 10 k += 1; @@ -195,7 +207,8 @@ pub fn format_shortest(d: &Decoded, buf: &mut [u8]) -> (/*#digits*/ usize, /*exp // - `v - low = minus / scale * 10^(k-n-1)` // - `high - v = plus / scale * 10^(k-n-1)` // - `(mant + plus) / scale <= 10` (thus `mant / scale < 10`) - // where `d[i..j]` is a shorthand for `d[i] * 10^(j-i) + ... + d[j-1] * 10 + d[j]`. + // where `d[i..j]` is a shorthand for `d[i] * 10^(j-i) + ... + d[j-1] * 10 + + // d[j]`. // generate one digit: `d[n] = floor(mant / scale) < 10`. let (d, _) = div_rem_upto_16(&mut mant, &scale, &scale2, &scale4, &scale8); @@ -204,14 +217,16 @@ pub fn format_shortest(d: &Decoded, buf: &mut [u8]) -> (/*#digits*/ usize, /*exp i += 1; // this is a simplified description of the modified Dragon algorithm. - // many intermediate derivations and completeness arguments are omitted for convenience. + // many intermediate derivations and completeness arguments are omitted for + // convenience. // // start with modified invariants, as we've updated `n`: // - `v = mant / scale * 10^(k-n) + d[0..n-1] * 10^(k-n)` // - `v - low = minus / scale * 10^(k-n)` // - `high - v = plus / scale * 10^(k-n)` // - // assume that `d[0..n-1]` is the shortest representation between `low` and `high`, + // assume that `d[0..n-1]` is the shortest representation between `low` and + // `high`, // i.e. `d[0..n-1]` satisfies both of the following but `d[0..n-2]` doesn't: // - `low < d[0..n-1] * 10^(k-n) < high` (bijectivity: digits round to `v`); and // - `abs(v / 10^(k-n) - d[0..n-1]) <= 1/2` (the last digit is correct). @@ -223,16 +238,19 @@ pub fn format_shortest(d: &Decoded, buf: &mut [u8]) -> (/*#digits*/ usize, /*exp // when `mant < minus` and `2 * mant <= scale`. // (the former becomes `mant <= minus` when the original mantissa is even.) // - // when the second doesn't hold (`2 * mant > scale`), we need to increase the last digit. + // when the second doesn't hold (`2 * mant > scale`), we need to increase the + // last digit. // this is enough for restoring that condition: we already know that // the digit generation guarantees `0 <= v / 10^(k-n) - d[0..n-1] < 1`. // in this case, the first condition becomes `-plus < mant - scale < minus`. // since `mant < scale` after the generation, we have `scale < mant + plus`. - // (again, this becomes `scale <= mant + plus` when the original mantissa is even.) + // (again, this becomes `scale <= mant + plus` when the original mantissa is + // even.) // // in short: // - stop and round `down` (keep digits as is) when `mant < minus` (or `<=`). - // - stop and round `up` (increase the last digit) when `scale < mant + plus` (or `<=`). + // - stop and round `up` (increase the last digit) when `scale < mant + plus` + // (or `<=`). // - keep generating otherwise. down = mant.cmp(&minus) < rounding; up = scale.cmp(mant.clone().add(&plus)) < rounding; @@ -242,7 +260,8 @@ pub fn format_shortest(d: &Decoded, buf: &mut [u8]) -> (/*#digits*/ usize, /*exp } // restore the invariants. - // this makes the algorithm always terminating: `minus` and `plus` always increases, + // this makes the algorithm always terminating: `minus` and `plus` always + // increases, // but `mant` is clipped modulo `scale` and `scale` is fixed. mant.mul_small(10); minus.mul_small(10); @@ -267,14 +286,21 @@ pub fn format_shortest(d: &Decoded, buf: &mut [u8]) -> (/*#digits*/ usize, /*exp } /// The exact and fixed mode implementation for Dragon. -pub fn format_exact(d: &Decoded, buf: &mut [u8], limit: i16) -> (/*#digits*/ usize, /*exp*/ i16) { +pub fn format_exact(d: &Decoded, + buf: &mut [u8], + limit: i16) + -> (// #digits + usize, + // exp + i16) { assert!(d.mant > 0); assert!(d.minus > 0); assert!(d.plus > 0); assert!(d.mant.checked_add(d.plus).is_some()); assert!(d.mant.checked_sub(d.minus).is_some()); - // estimate `k_0` from original inputs satisfying `10^(k_0-1) < v <= 10^(k_0+1)`. + // estimate `k_0` from original inputs satisfying `10^(k_0-1) < v <= + // 10^(k_0+1)`. let mut k = estimate_scaling_factor(d.mant, d.exp); // `v = mant / scale`. @@ -294,9 +320,12 @@ pub fn format_exact(d: &Decoded, buf: &mut [u8], limit: i16) -> (/*#digits*/ usi } // fixup when `mant + plus >= scale`, where `plus / scale = 10^-buf.len() / 2`. - // in order to keep the fixed-size bignum, we actually use `mant + floor(plus) >= scale`. - // we are not actually modifying `scale`, since we can skip the initial multiplication instead. - // again with the shortest algorithm, `d[0]` can be zero but will be eventually rounded up. + // in order to keep the fixed-size bignum, we actually use `mant + floor(plus) + // >= scale`. + // we are not actually modifying `scale`, since we can skip the initial + // multiplication instead. + // again with the shortest algorithm, `d[0]` can be zero but will be eventually + // rounded up. if *div_2pow10(&mut scale.clone(), buf.len()).add(&mant) >= scale { // equivalent to scaling `scale` by 10 k += 1; @@ -304,12 +333,14 @@ pub fn format_exact(d: &Decoded, buf: &mut [u8], limit: i16) -> (/*#digits*/ usi mant.mul_small(10); } - // if we are working with the last-digit limitation, we need to shorten the buffer + // if we are working with the last-digit limitation, we need to shorten the + // buffer // before the actual rendering in order to avoid double rounding. // note that we have to enlarge the buffer again when rounding up happens! let mut len = if k < limit { // oops, we cannot even produce *one* digit. - // this is possible when, say, we've got something like 9.5 and it's being rounded to 10. + // this is possible when, say, we've got something like 9.5 and it's being + // rounded to 10. // we return an empty buffer, with an exception of the later rounding-up case // which occurs when `k == limit` and has to produce exactly one digit. 0 @@ -330,7 +361,8 @@ pub fn format_exact(d: &Decoded, buf: &mut [u8], limit: i16) -> (/*#digits*/ usi scale8.mul_pow2(3); for i in 0..len { - if mant.is_zero() { // following digits are all zeroes, we stop here + if mant.is_zero() { + // following digits are all zeroes, we stop here // do *not* try to perform rounding! rather, fill remaining digits. for c in &mut buf[i..len] { *c = b'0'; @@ -369,7 +401,8 @@ pub fn format_exact(d: &Decoded, buf: &mut [u8], limit: i16) -> (/*#digits*/ usi if order == Ordering::Greater || (order == Ordering::Equal && (len == 0 || buf[len - 1] & 1 == 1)) { // if rounding up changes the length, the exponent should also change. - // but we've been requested a fixed number of digits, so do not alter the buffer... + // but we've been requested a fixed number of digits, so do not alter the + // buffer... if let Some(c) = round_up(buf, len) { // ...unless we've been requested the fixed precision instead. // we also need to check that, if the original buffer was empty, diff --git a/src/libcore/num/flt2dec/strategy/grisu.rs b/src/libcore/num/flt2dec/strategy/grisu.rs index ebbd85234c6aa..ca19b8400b0c7 100644 --- a/src/libcore/num/flt2dec/strategy/grisu.rs +++ b/src/libcore/num/flt2dec/strategy/grisu.rs @@ -8,13 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! -Rust adaptation of Grisu3 algorithm described in [1]. It uses about -1KB of precomputed table, and in turn, it's very quick for most inputs. - -[1] Florian Loitsch. 2010. Printing floating-point numbers quickly and - accurately with integers. SIGPLAN Not. 45, 6 (June 2010), 233-243. -*/ +// ! +// Rust adaptation of Grisu3 algorithm described in [1]. It uses about +// 1KB of precomputed table, and in turn, it's very quick for most inputs. +// +// [1] Florian Loitsch. 2010. Printing floating-point numbers quickly and +// accurately with integers. SIGPLAN Not. 45, 6 (June 2010), 233-243. +// use prelude::v1::*; @@ -23,106 +23,109 @@ use num::flt2dec::{Decoded, MAX_SIG_DIGITS, round_up}; // see the comments in `format_shortest_opt` for the rationale. -#[doc(hidden)] pub const ALPHA: i16 = -60; -#[doc(hidden)] pub const GAMMA: i16 = -32; - -/* -# the following Python code generates this table: -for i in xrange(-308, 333, 8): - if i >= 0: f = 10**i; e = 0 - else: f = 2**(80-4*i) // 10**-i; e = 4 * i - 80 - l = f.bit_length() - f = ((f << 64 >> (l-1)) + 1) >> 1; e += l - 64 - print ' (%#018x, %5d, %4d),' % (f, e, i) -*/ +#[doc(hidden)] +pub const ALPHA: i16 = -60; +#[doc(hidden)] +pub const GAMMA: i16 = -32; +// +// # the following Python code generates this table: +// for i in xrange(-308, 333, 8): +// if i >= 0: f = 10**i; e = 0 +// else: f = 2**(80-4*i) // 10**-i; e = 4 * i - 80 +// l = f.bit_length() +// f = ((f << 64 >> (l-1)) + 1) >> 1; e += l - 64 +// print ' (%#018x, %5d, %4d),' % (f, e, i) +// + +#[doc(hidden)] +pub static CACHED_POW10: [(u64, i16, i16); 81] = [// (f, e, k) + (0xe61acf033d1a45df, -1087, -308), + (0xab70fe17c79ac6ca, -1060, -300), + (0xff77b1fcbebcdc4f, -1034, -292), + (0xbe5691ef416bd60c, -1007, -284), + (0x8dd01fad907ffc3c, -980, -276), + (0xd3515c2831559a83, -954, -268), + (0x9d71ac8fada6c9b5, -927, -260), + (0xea9c227723ee8bcb, -901, -252), + (0xaecc49914078536d, -874, -244), + (0x823c12795db6ce57, -847, -236), + (0xc21094364dfb5637, -821, -228), + (0x9096ea6f3848984f, -794, -220), + (0xd77485cb25823ac7, -768, -212), + (0xa086cfcd97bf97f4, -741, -204), + (0xef340a98172aace5, -715, -196), + (0xb23867fb2a35b28e, -688, -188), + (0x84c8d4dfd2c63f3b, -661, -180), + (0xc5dd44271ad3cdba, -635, -172), + (0x936b9fcebb25c996, -608, -164), + (0xdbac6c247d62a584, -582, -156), + (0xa3ab66580d5fdaf6, -555, -148), + (0xf3e2f893dec3f126, -529, -140), + (0xb5b5ada8aaff80b8, -502, -132), + (0x87625f056c7c4a8b, -475, -124), + (0xc9bcff6034c13053, -449, -116), + (0x964e858c91ba2655, -422, -108), + (0xdff9772470297ebd, -396, -100), + (0xa6dfbd9fb8e5b88f, -369, -92), + (0xf8a95fcf88747d94, -343, -84), + (0xb94470938fa89bcf, -316, -76), + (0x8a08f0f8bf0f156b, -289, -68), + (0xcdb02555653131b6, -263, -60), + (0x993fe2c6d07b7fac, -236, -52), + (0xe45c10c42a2b3b06, -210, -44), + (0xaa242499697392d3, -183, -36), + (0xfd87b5f28300ca0e, -157, -28), + (0xbce5086492111aeb, -130, -20), + (0x8cbccc096f5088cc, -103, -12), + (0xd1b71758e219652c, -77, -4), + (0x9c40000000000000, -50, 4), + (0xe8d4a51000000000, -24, 12), + (0xad78ebc5ac620000, 3, 20), + (0x813f3978f8940984, 30, 28), + (0xc097ce7bc90715b3, 56, 36), + (0x8f7e32ce7bea5c70, 83, 44), + (0xd5d238a4abe98068, 109, 52), + (0x9f4f2726179a2245, 136, 60), + (0xed63a231d4c4fb27, 162, 68), + (0xb0de65388cc8ada8, 189, 76), + (0x83c7088e1aab65db, 216, 84), + (0xc45d1df942711d9a, 242, 92), + (0x924d692ca61be758, 269, 100), + (0xda01ee641a708dea, 295, 108), + (0xa26da3999aef774a, 322, 116), + (0xf209787bb47d6b85, 348, 124), + (0xb454e4a179dd1877, 375, 132), + (0x865b86925b9bc5c2, 402, 140), + (0xc83553c5c8965d3d, 428, 148), + (0x952ab45cfa97a0b3, 455, 156), + (0xde469fbd99a05fe3, 481, 164), + (0xa59bc234db398c25, 508, 172), + (0xf6c69a72a3989f5c, 534, 180), + (0xb7dcbf5354e9bece, 561, 188), + (0x88fcf317f22241e2, 588, 196), + (0xcc20ce9bd35c78a5, 614, 204), + (0x98165af37b2153df, 641, 212), + (0xe2a0b5dc971f303a, 667, 220), + (0xa8d9d1535ce3b396, 694, 228), + (0xfb9b7cd9a4a7443c, 720, 236), + (0xbb764c4ca7a44410, 747, 244), + (0x8bab8eefb6409c1a, 774, 252), + (0xd01fef10a657842c, 800, 260), + (0x9b10a4e5e9913129, 827, 268), + (0xe7109bfba19c0c9d, 853, 276), + (0xac2820d9623bf429, 880, 284), + (0x80444b5e7aa7cf85, 907, 292), + (0xbf21e44003acdd2d, 933, 300), + (0x8e679c2f5e44ff8f, 960, 308), + (0xd433179d9c8cb841, 986, 316), + (0x9e19db92b4e31ba9, 1013, 324), + (0xeb96bf6ebadf77d9, 1039, 332)]; + +#[doc(hidden)] +pub const CACHED_POW10_FIRST_E: i16 = -1087; #[doc(hidden)] -pub static CACHED_POW10: [(u64, i16, i16); 81] = [ // (f, e, k) - (0xe61acf033d1a45df, -1087, -308), - (0xab70fe17c79ac6ca, -1060, -300), - (0xff77b1fcbebcdc4f, -1034, -292), - (0xbe5691ef416bd60c, -1007, -284), - (0x8dd01fad907ffc3c, -980, -276), - (0xd3515c2831559a83, -954, -268), - (0x9d71ac8fada6c9b5, -927, -260), - (0xea9c227723ee8bcb, -901, -252), - (0xaecc49914078536d, -874, -244), - (0x823c12795db6ce57, -847, -236), - (0xc21094364dfb5637, -821, -228), - (0x9096ea6f3848984f, -794, -220), - (0xd77485cb25823ac7, -768, -212), - (0xa086cfcd97bf97f4, -741, -204), - (0xef340a98172aace5, -715, -196), - (0xb23867fb2a35b28e, -688, -188), - (0x84c8d4dfd2c63f3b, -661, -180), - (0xc5dd44271ad3cdba, -635, -172), - (0x936b9fcebb25c996, -608, -164), - (0xdbac6c247d62a584, -582, -156), - (0xa3ab66580d5fdaf6, -555, -148), - (0xf3e2f893dec3f126, -529, -140), - (0xb5b5ada8aaff80b8, -502, -132), - (0x87625f056c7c4a8b, -475, -124), - (0xc9bcff6034c13053, -449, -116), - (0x964e858c91ba2655, -422, -108), - (0xdff9772470297ebd, -396, -100), - (0xa6dfbd9fb8e5b88f, -369, -92), - (0xf8a95fcf88747d94, -343, -84), - (0xb94470938fa89bcf, -316, -76), - (0x8a08f0f8bf0f156b, -289, -68), - (0xcdb02555653131b6, -263, -60), - (0x993fe2c6d07b7fac, -236, -52), - (0xe45c10c42a2b3b06, -210, -44), - (0xaa242499697392d3, -183, -36), - (0xfd87b5f28300ca0e, -157, -28), - (0xbce5086492111aeb, -130, -20), - (0x8cbccc096f5088cc, -103, -12), - (0xd1b71758e219652c, -77, -4), - (0x9c40000000000000, -50, 4), - (0xe8d4a51000000000, -24, 12), - (0xad78ebc5ac620000, 3, 20), - (0x813f3978f8940984, 30, 28), - (0xc097ce7bc90715b3, 56, 36), - (0x8f7e32ce7bea5c70, 83, 44), - (0xd5d238a4abe98068, 109, 52), - (0x9f4f2726179a2245, 136, 60), - (0xed63a231d4c4fb27, 162, 68), - (0xb0de65388cc8ada8, 189, 76), - (0x83c7088e1aab65db, 216, 84), - (0xc45d1df942711d9a, 242, 92), - (0x924d692ca61be758, 269, 100), - (0xda01ee641a708dea, 295, 108), - (0xa26da3999aef774a, 322, 116), - (0xf209787bb47d6b85, 348, 124), - (0xb454e4a179dd1877, 375, 132), - (0x865b86925b9bc5c2, 402, 140), - (0xc83553c5c8965d3d, 428, 148), - (0x952ab45cfa97a0b3, 455, 156), - (0xde469fbd99a05fe3, 481, 164), - (0xa59bc234db398c25, 508, 172), - (0xf6c69a72a3989f5c, 534, 180), - (0xb7dcbf5354e9bece, 561, 188), - (0x88fcf317f22241e2, 588, 196), - (0xcc20ce9bd35c78a5, 614, 204), - (0x98165af37b2153df, 641, 212), - (0xe2a0b5dc971f303a, 667, 220), - (0xa8d9d1535ce3b396, 694, 228), - (0xfb9b7cd9a4a7443c, 720, 236), - (0xbb764c4ca7a44410, 747, 244), - (0x8bab8eefb6409c1a, 774, 252), - (0xd01fef10a657842c, 800, 260), - (0x9b10a4e5e9913129, 827, 268), - (0xe7109bfba19c0c9d, 853, 276), - (0xac2820d9623bf429, 880, 284), - (0x80444b5e7aa7cf85, 907, 292), - (0xbf21e44003acdd2d, 933, 300), - (0x8e679c2f5e44ff8f, 960, 308), - (0xd433179d9c8cb841, 986, 316), - (0x9e19db92b4e31ba9, 1013, 324), - (0xeb96bf6ebadf77d9, 1039, 332), -]; - -#[doc(hidden)] pub const CACHED_POW10_FIRST_E: i16 = -1087; -#[doc(hidden)] pub const CACHED_POW10_LAST_E: i16 = 1039; +pub const CACHED_POW10_LAST_E: i16 = 1039; #[doc(hidden)] pub fn cached_power(alpha: i16, gamma: i16) -> (i16, Fp) { @@ -190,8 +193,12 @@ pub fn max_pow10_no_more_than(x: u32) -> (u8, u32) { /// The shortest mode implementation for Grisu. /// /// It returns `None` when it would return an inexact representation otherwise. -pub fn format_shortest_opt(d: &Decoded, buf: &mut [u8]) - -> Option<(/*#digits*/ usize, /*exp*/ i16)> { +pub fn format_shortest_opt(d: &Decoded, + buf: &mut [u8]) + -> Option<(// #digits + usize, + // exp + i16)> { assert!(d.mant > 0); assert!(d.minus > 0); assert!(d.plus > 0); @@ -214,19 +221,26 @@ pub fn format_shortest_opt(d: &Decoded, buf: &mut [u8]) e: d.exp, }.normalize_to(plus.e); - // find any `cached = 10^minusk` such that `ALPHA <= minusk + plus.e + 64 <= GAMMA`. - // since `plus` is normalized, this means `2^(62 + ALPHA) <= plus * cached < 2^(64 + GAMMA)`; - // given our choices of `ALPHA` and `GAMMA`, this puts `plus * cached` into `[4, 2^32)`. + // find any `cached = 10^minusk` such that `ALPHA <= minusk + plus.e + 64 <= + // GAMMA`. + // since `plus` is normalized, this means `2^(62 + ALPHA) <= plus * cached < + // 2^(64 + GAMMA)`; + // given our choices of `ALPHA` and `GAMMA`, this puts `plus * cached` into + // `[4, 2^32)`. // // it is obviously desirable to maximize `GAMMA - ALPHA`, - // so that we don't need many cached powers of 10, but there are some considerations: + // so that we don't need many cached powers of 10, but there are some + // considerations: // - // 1. we want to keep `floor(plus * cached)` within `u32` since it needs a costly division. - // (this is not really avoidable, remainder is required for accuracy estimation.) + // 1. we want to keep `floor(plus * cached)` within `u32` since it needs a + // costly division. + // (this is not really avoidable, remainder is required for accuracy + // estimation.) // 2. the remainder of `floor(plus * cached)` repeatedly gets multiplied by 10, // and it should not overflow. // - // the first gives `64 + GAMMA <= 32`, while the second gives `10 * 2^-ALPHA <= 2^64`; + // the first gives `64 + GAMMA <= 32`, while the second gives `10 * 2^-ALPHA <= + // 2^64`; // -60 and -32 is the maximal range with this constraint, and V8 also uses them. let (minusk, cached) = cached_power(ALPHA - plus.e - 64, GAMMA - plus.e - 64); @@ -249,26 +263,31 @@ pub fn format_shortest_opt(d: &Decoded, buf: &mut [u8]) // minus1 minus0 v - 1 ulp v + 1 ulp plus0 plus1 // // above `minus`, `v` and `plus` are *quantized* approximations (error < 1 ulp). - // as we don't know the error is positive or negative, we use two approximations spaced equally + // as we don't know the error is positive or negative, we use two + // approximations spaced equally // and have the maximal error of 2 ulps. // // the "unsafe region" is a liberal interval which we initially generate. // the "safe region" is a conservative interval which we only accept. - // we start with the correct repr within the unsafe region, and try to find the closest repr + // we start with the correct repr within the unsafe region, and try to find the + // closest repr // to `v` which is also within the safe region. if we can't, we give up. let plus1 = plus.f + 1; -// let plus0 = plus.f - 1; // only for explanation -// let minus0 = minus.f + 1; // only for explanation + // let plus0 = plus.f - 1; // only for explanation + // let minus0 = minus.f + 1; // only for explanation let minus1 = minus.f - 1; let e = -plus.e as usize; // shared exponent // divide `plus1` into integral and fractional parts. - // integral parts are guaranteed to fit in u32, since cached power guarantees `plus < 2^32` - // and normalized `plus.f` is always less than `2^64 - 2^4` due to the precision requirement. + // integral parts are guaranteed to fit in u32, since cached power guarantees + // `plus < 2^32` + // and normalized `plus.f` is always less than `2^64 - 2^4` due to the + // precision requirement. let plus1int = (plus1 >> e) as u32; let plus1frac = plus1 & ((1 << e) - 1); - // calculate the largest `10^max_kappa` no more than `plus1` (thus `plus1 < 10^(max_kappa+1)`). + // calculate the largest `10^max_kappa` no more than `plus1` (thus `plus1 < + // 10^(max_kappa+1)`). // this is an upper bound of `kappa` below. let (max_kappa, max_ten_kappa) = max_pow10_no_more_than(plus1int); @@ -276,22 +295,27 @@ pub fn format_shortest_opt(d: &Decoded, buf: &mut [u8]) let exp = max_kappa as i16 - minusk + 1; // Theorem 6.2: if `k` is the greatest integer s.t. `0 <= y mod 10^k <= y - x`, - // then `V = floor(y / 10^k) * 10^k` is in `[x, y]` and one of the shortest - // representations (with the minimal number of significant digits) in that range. + // then `V = floor(y / 10^k) * 10^k` is in `[x, y]` and one of the + // shortest + // representations (with the minimal number of significant digits) + // in that range. // // find the digit length `kappa` between `(minus1, plus1)` as per Theorem 6.2. - // Theorem 6.2 can be adopted to exclude `x` by requiring `y mod 10^k < y - x` instead. - // (e.g. `x` = 32000, `y` = 32777; `kappa` = 2 since `y mod 10^3 = 777 < y - x = 777`.) + // Theorem 6.2 can be adopted to exclude `x` by requiring `y mod 10^k < y - x` + // instead. + // (e.g. `x` = 32000, `y` = 32777; `kappa` = 2 since `y mod 10^3 = 777 < y - x + // = 777`.) // the algorithm relies on the later verification phase to exclude `y`. let delta1 = plus1 - minus1; -// let delta1int = (delta1 >> e) as usize; // only for explanation + // let delta1int = (delta1 >> e) as usize; // only for explanation let delta1frac = delta1 & ((1 << e) - 1); // render integral parts, while checking for the accuracy at each step. let mut kappa = max_kappa as i16; let mut ten_kappa = max_ten_kappa; // 10^kappa let mut remainder = plus1int; // digits yet to be rendered - loop { // we always have at least one digit to render, as `plus1 >= 10^kappa` + loop { + // we always have at least one digit to render, as `plus1 >= 10^kappa` // invariants: // - `delta1int <= remainder < 10^(kappa+1)` // - `plus1int = d[0..n-1] * 10^(kappa+1) + remainder` @@ -306,7 +330,8 @@ pub fn format_shortest_opt(d: &Decoded, buf: &mut [u8]) let plus1rem = ((r as u64) << e) + plus1frac; // == (plus1 % 10^kappa) * 2^e if plus1rem < delta1 { - // `plus1 % 10^kappa < delta1 = plus1 - minus1`; we've found the correct `kappa`. + // `plus1 % 10^kappa < delta1 = plus1 - minus1`; we've found the correct + // `kappa`. let ten_kappa = (ten_kappa as u64) << e; // scale 10^kappa back to the shared exponent return round_and_weed(&mut buf[..i], exp, @@ -332,11 +357,13 @@ pub fn format_shortest_opt(d: &Decoded, buf: &mut [u8]) } // render fractional parts, while checking for the accuracy at each step. - // this time we rely on repeated multiplications, as division will lose the precision. + // this time we rely on repeated multiplications, as division will lose the + // precision. let mut remainder = plus1frac; let mut threshold = delta1frac; let mut ulp = 1; - loop { // the next digit should be significant as we've tested that before breaking out + loop { + // the next digit should be significant as we've tested that before breaking out // invariants, where `m = max_kappa + 1` (# of digits in the integral part): // - `remainder < 2^e` // - `plus1frac * 10^(n-m) = d[m..n-1] * 2^e + remainder` @@ -369,20 +396,29 @@ pub fn format_shortest_opt(d: &Decoded, buf: &mut [u8]) remainder = r; } - // we've generated all significant digits of `plus1`, but not sure if it's the optimal one. - // for example, if `minus1` is 3.14153... and `plus1` is 3.14158..., there are 5 different - // shortest representation from 3.14154 to 3.14158 but we only have the greatest one. - // we have to successively decrease the last digit and check if this is the optimal repr. - // there are at most 9 candidates (..1 to ..9), so this is fairly quick. ("rounding" phase) + // we've generated all significant digits of `plus1`, but not sure if it's the + // optimal one. + // for example, if `minus1` is 3.14153... and `plus1` is 3.14158..., there are + // 5 different + // shortest representation from 3.14154 to 3.14158 but we only have the + // greatest one. + // we have to successively decrease the last digit and check if this is the + // optimal repr. + // there are at most 9 candidates (..1 to ..9), so this is fairly quick. + // ("rounding" phase) // // the function checks if this "optimal" repr is actually within the ulp ranges, - // and also, it is possible that the "second-to-optimal" repr can actually be optimal - // due to the rounding error. in either cases this returns `None`. ("weeding" phase) + // and also, it is possible that the "second-to-optimal" repr can actually be + // optimal + // due to the rounding error. in either cases this returns `None`. ("weeding" + // phase) // - // all arguments here are scaled by the common (but implicit) value `k`, so that: + // all arguments here are scaled by the common (but implicit) value `k`, so + // that: // - `remainder = (plus1 % 10^kappa) * k` // - `threshold = (plus1 - minus1) * k` (and also, `remainder < threshold`) - // - `plus1v = (plus1 - v) * k` (and also, `threshold > plus1v` from prior invariants) + // - `plus1v = (plus1 - v) * k` (and also, `threshold > plus1v` from prior + // invariants) // - `ten_kappa = 10^kappa * k` // - `ulp = 2^-e * k` fn round_and_weed(buf: &mut [u8], @@ -403,24 +439,32 @@ pub fn format_shortest_opt(d: &Decoded, buf: &mut [u8]) let plus1v_down = plus1v + ulp; // plus1 - (v - 1 ulp) let plus1v_up = plus1v - ulp; // plus1 - (v + 1 ulp) - // decrease the last digit and stop at the closest representation to `v + 1 ulp`. + // decrease the last digit and stop at the closest representation to `v + 1 + // ulp`. let mut plus1w = remainder; // plus1w(n) = plus1 - w(n) { let last = buf.last_mut().unwrap(); - // we work with the approximated digits `w(n)`, which is initially equal to `plus1 - + // we work with the approximated digits `w(n)`, which is initially equal to + // `plus1 - // plus1 % 10^kappa`. after running the loop body `n` times, `w(n) = plus1 - // plus1 % 10^kappa - n * 10^kappa`. we set `plus1w(n) = plus1 - w(n) = - // plus1 % 10^kappa + n * 10^kappa` (thus `remainder = plus1w(0)`) to simplify checks. + // plus1 % 10^kappa + n * 10^kappa` (thus `remainder = plus1w(0)`) to simplify + // checks. // note that `plus1w(n)` is always increasing. // - // we have three conditions to terminate. any of them will make the loop unable to - // proceed, but we then have at least one valid representation known to be closest to + // we have three conditions to terminate. any of them will make the loop unable + // to + // proceed, but we then have at least one valid representation known to be + // closest to // `v + 1 ulp` anyway. we will denote them as TC1 through TC3 for brevity. // - // TC1: `w(n) <= v + 1 ulp`, i.e. this is the last repr that can be the closest one. - // this is equivalent to `plus1 - w(n) = plus1w(n) >= plus1 - (v + 1 ulp) = plus1v_up`. - // combined with TC2 (which checks if `w(n+1)` is valid), this prevents the possible + // TC1: `w(n) <= v + 1 ulp`, i.e. this is the last repr that can be the closest + // one. + // this is equivalent to `plus1 - w(n) = plus1w(n) >= plus1 - (v + 1 ulp) = + // plus1v_up`. + // combined with TC2 (which checks if `w(n+1)` is valid), this prevents the + // possible // overflow on the calculation of `plus1w(n)`. // // TC2: `w(n+1) < minus1`, i.e. the next repr definitely does not round to `v`. @@ -430,22 +474,29 @@ pub fn format_shortest_opt(d: &Decoded, buf: &mut [u8]) // threshold - (plus1v - 1 ulp) > 1 ulp` and we can safely test if // `threshold - plus1w(n) < 10^kappa` instead. // - // TC3: `abs(w(n) - (v + 1 ulp)) <= abs(w(n+1) - (v + 1 ulp))`, i.e. the next repr is - // no closer to `v + 1 ulp` than the current repr. given `z(n) = plus1v_up - plus1w(n)`, - // this becomes `abs(z(n)) <= abs(z(n+1))`. again assuming that TC1 is false, we have + // TC3: `abs(w(n) - (v + 1 ulp)) <= abs(w(n+1) - (v + 1 ulp))`, i.e. the next + // repr is + // no closer to `v + 1 ulp` than the current repr. given `z(n) = plus1v_up - + // plus1w(n)`, + // this becomes `abs(z(n)) <= abs(z(n+1))`. again assuming that TC1 is false, + // we have // `z(n) > 0`. we have two cases to consider: // - // - when `z(n+1) >= 0`: TC3 becomes `z(n) <= z(n+1)`. as `plus1w(n)` is increasing, + // - when `z(n+1) >= 0`: TC3 becomes `z(n) <= z(n+1)`. as `plus1w(n)` is + // increasing, // `z(n)` should be decreasing and this is clearly false. // - when `z(n+1) < 0`: - // - TC3a: the precondition is `plus1v_up < plus1w(n) + 10^kappa`. assuming TC2 is + // - TC3a: the precondition is `plus1v_up < plus1w(n) + 10^kappa`. assuming + // TC2 is // false, `threshold >= plus1w(n) + 10^kappa` so it cannot overflow. // - TC3b: TC3 becomes `z(n) <= -z(n+1)`, i.e. `plus1v_up - plus1w(n) >= - // plus1w(n+1) - plus1v_up = plus1w(n) + 10^kappa - plus1v_up`. the negated TC1 + // plus1w(n+1) - plus1v_up = plus1w(n) + 10^kappa - plus1v_up`. the negated + // TC1 // gives `plus1v_up > plus1w(n)`, so it cannot overflow or underflow when // combined with TC3a. // - // consequently, we should stop when `TC1 || TC2 || (TC3a && TC3b)`. the following is + // consequently, we should stop when `TC1 || TC2 || (TC3a && TC3b)`. the + // following is // equal to its inverse, `!TC1 && !TC2 && (!TC3a || !TC3b)`. while plus1w < plus1v_up && threshold - plus1w >= ten_kappa && (plus1w + ten_kappa < plus1v_up || @@ -456,9 +507,11 @@ pub fn format_shortest_opt(d: &Decoded, buf: &mut [u8]) } } - // check if this representation is also the closest representation to `v - 1 ulp`. + // check if this representation is also the closest representation to `v - 1 + // ulp`. // - // this is simply same to the terminating conditions for `v + 1 ulp`, with all `plus1v_up` + // this is simply same to the terminating conditions for `v + 1 ulp`, with all + // `plus1v_up` // replaced by `plus1v_down` instead. overflow analysis equally holds. if plus1w < plus1v_down && threshold - plus1w >= ten_kappa && (plus1w + ten_kappa < plus1v_down || @@ -467,9 +520,12 @@ pub fn format_shortest_opt(d: &Decoded, buf: &mut [u8]) } // now we have the closest representation to `v` between `plus1` and `minus1`. - // this is too liberal, though, so we reject any `w(n)` not between `plus0` and `minus0`, - // i.e. `plus1 - plus1w(n) <= minus0` or `plus1 - plus1w(n) >= plus0`. we utilize the facts - // that `threshold = plus1 - minus1` and `plus1 - plus0 = minus0 - minus1 = 2 ulp`. + // this is too liberal, though, so we reject any `w(n)` not between `plus0` and + // `minus0`, + // i.e. `plus1 - plus1w(n) <= minus0` or `plus1 - plus1w(n) >= plus0`. we + // utilize the facts + // that `threshold = plus1 - minus1` and `plus1 - plus0 = minus0 - minus1 = 2 + // ulp`. if 2 * ulp <= plus1w && plus1w <= threshold - 4 * ulp { Some((buf.len(), exp)) } else { @@ -492,8 +548,13 @@ pub fn format_shortest(d: &Decoded, buf: &mut [u8]) -> (usize, i16) { /// The exact and fixed mode implementation for Grisu. /// /// It returns `None` when it would return an inexact representation otherwise. -pub fn format_exact_opt(d: &Decoded, buf: &mut [u8], limit: i16) - -> Option<(/*#digits*/ usize, /*exp*/ i16)> { +pub fn format_exact_opt(d: &Decoded, + buf: &mut [u8], + limit: i16) + -> Option<(// #digits + usize, + // exp + i16)> { assert!(d.mant > 0); assert!(d.mant < (1 << 61)); // we need at least three bits of additional precision assert!(!buf.is_empty()); @@ -511,32 +572,38 @@ pub fn format_exact_opt(d: &Decoded, buf: &mut [u8], limit: i16) let vint = (v.f >> e) as u32; let vfrac = v.f & ((1 << e) - 1); - // both old `v` and new `v` (scaled by `10^-k`) has an error of < 1 ulp (Theorem 5.1). + // both old `v` and new `v` (scaled by `10^-k`) has an error of < 1 ulp + // (Theorem 5.1). // as we don't know the error is positive or negative, we use two approximations - // spaced equally and have the maximal error of 2 ulps (same to the shortest case). + // spaced equally and have the maximal error of 2 ulps (same to the shortest + // case). // // the goal is to find the exactly rounded series of digits that are common to // both `v - 1 ulp` and `v + 1 ulp`, so that we are maximally confident. - // if this is not possible, we don't know which one is the correct output for `v`, + // if this is not possible, we don't know which one is the correct output for + // `v`, // so we give up and fall back. // // `err` is defined as `1 ulp * 2^e` here (same to the ulp in `vfrac`), // and we will scale it whenever `v` gets scaled. let mut err = 1; - // calculate the largest `10^max_kappa` no more than `v` (thus `v < 10^(max_kappa+1)`). + // calculate the largest `10^max_kappa` no more than `v` (thus `v < + // 10^(max_kappa+1)`). // this is an upper bound of `kappa` below. let (max_kappa, max_ten_kappa) = max_pow10_no_more_than(vint); let mut i = 0; let exp = max_kappa as i16 - minusk + 1; - // if we are working with the last-digit limitation, we need to shorten the buffer + // if we are working with the last-digit limitation, we need to shorten the + // buffer // before the actual rendering in order to avoid double rounding. // note that we have to enlarge the buffer again when rounding up happens! let len = if exp <= limit { // oops, we cannot even produce *one* digit. - // this is possible when, say, we've got something like 9.5 and it's being rounded to 10. + // this is possible when, say, we've got something like 9.5 and it's being + // rounded to 10. // // in principle we can immediately call `possibly_round` with an empty buffer, // but scaling `max_ten_kappa << e` by 10 can result in overflow. @@ -562,7 +629,8 @@ pub fn format_exact_opt(d: &Decoded, buf: &mut [u8], limit: i16) let mut kappa = max_kappa as i16; let mut ten_kappa = max_ten_kappa; // 10^kappa let mut remainder = vint; // digits yet to be rendered - loop { // we always have at least one digit to render + loop { + // we always have at least one digit to render // invariants: // - `remainder < 10^(kappa+1)` // - `vint = d[0..n-1] * 10^(kappa+1) + remainder` @@ -603,15 +671,21 @@ pub fn format_exact_opt(d: &Decoded, buf: &mut [u8], limit: i16) // render fractional parts. // - // in principle we can continue to the last available digit and check for the accuracy. - // unfortunately we are working with the finite-sized integers, so we need some criterion + // in principle we can continue to the last available digit and check for the + // accuracy. + // unfortunately we are working with the finite-sized integers, so we need some + // criterion // to detect the overflow. V8 uses `remainder > err`, which becomes false when - // the first `i` significant digits of `v - 1 ulp` and `v` differ. however this rejects + // the first `i` significant digits of `v - 1 ulp` and `v` differ. however this + // rejects // too many otherwise valid input. // - // since the later phase has a correct overflow detection, we instead use tighter criterion: - // we continue til `err` exceeds `10^kappa / 2`, so that the range between `v - 1 ulp` and - // `v + 1 ulp` definitely contains two or more rounded representations. this is same to + // since the later phase has a correct overflow detection, we instead use + // tighter criterion: + // we continue til `err` exceeds `10^kappa / 2`, so that the range between `v - + // 1 ulp` and + // `v + 1 ulp` definitely contains two or more rounded representations. this is + // same to // the first two comparisons from `possibly_round`, for the reference. let mut remainder = vfrac; let maxerr = 1 << (e - 1); @@ -641,16 +715,22 @@ pub fn format_exact_opt(d: &Decoded, buf: &mut [u8], limit: i16) remainder = r; } - // further calculation is useless (`possibly_round` definitely fails), so we give up. + // further calculation is useless (`possibly_round` definitely fails), so we + // give up. return None; - // we've generated all requested digits of `v`, which should be also same to corresponding - // digits of `v - 1 ulp`. now we check if there is a unique representation shared by - // both `v - 1 ulp` and `v + 1 ulp`; this can be either same to generated digits, or - // to the rounded-up version of those digits. if the range contains multiple representations + // we've generated all requested digits of `v`, which should be also same to + // corresponding + // digits of `v - 1 ulp`. now we check if there is a unique representation + // shared by + // both `v - 1 ulp` and `v + 1 ulp`; this can be either same to generated + // digits, or + // to the rounded-up version of those digits. if the range contains multiple + // representations // of the same length, we cannot be sure and should return `None` instead. // - // all arguments here are scaled by the common (but implicit) value `k`, so that: + // all arguments here are scaled by the common (but implicit) value `k`, so + // that: // - `remainder = (v % 10^kappa) * k` // - `ten_kappa = 10^kappa * k` // - `ulp = 2^-e * k` @@ -677,7 +757,8 @@ pub fn format_exact_opt(d: &Decoded, buf: &mut [u8], limit: i16) // possible representations in given number of digits.) // // error is too large that there are at least three possible representations - // between `v - 1 ulp` and `v + 1 ulp`. we cannot determine which one is correct. + // between `v - 1 ulp` and `v + 1 ulp`. we cannot determine which one is + // correct. if ulp >= ten_kappa { return None; } @@ -692,7 +773,8 @@ pub fn format_exact_opt(d: &Decoded, buf: &mut [u8], limit: i16) // v - 1 ulp v + 1 ulp // // in fact, 1/2 ulp is enough to introduce two possible representations. - // (remember that we need a unique representation for both `v - 1 ulp` and `v + 1 ulp`.) + // (remember that we need a unique representation for both `v - 1 ulp` and `v + + // 1 ulp`.) // this won't overflow, as `ulp < ten_kappa` from the first check. if ten_kappa - ulp <= ulp { return None; @@ -709,8 +791,10 @@ pub fn format_exact_opt(d: &Decoded, buf: &mut [u8], limit: i16) // | v | // v - 1 ulp v + 1 ulp // - // if `v + 1 ulp` is closer to the rounded-down representation (which is already in `buf`), - // then we can safely return. note that `v - 1 ulp` *can* be less than the current + // if `v + 1 ulp` is closer to the rounded-down representation (which is + // already in `buf`), + // then we can safely return. note that `v - 1 ulp` *can* be less than the + // current // representation, but as `1 ulp < 10^kappa / 2`, this condition is enough: // the distance between `v - 1 ulp` and the current representation // cannot exceed `10^kappa / 2`. @@ -733,11 +817,14 @@ pub fn format_exact_opt(d: &Decoded, buf: &mut [u8], limit: i16) // | v | // v - 1 ulp v + 1 ulp // - // on the other hands, if `v - 1 ulp` is closer to the rounded-up representation, - // we should round up and return. for the same reason we don't need to check `v + 1 ulp`. + // on the other hands, if `v - 1 ulp` is closer to the rounded-up + // representation, + // we should round up and return. for the same reason we don't need to check `v + // + 1 ulp`. // // the condition equals to `remainder - ulp >= 10^kappa / 2`. - // again we first check if `remainder > ulp` (note that this is not `remainder >= ulp`, + // again we first check if `remainder > ulp` (note that this is not `remainder + // >= ulp`, // as `10^kappa` is never zero). also note that `remainder - ulp <= 10^kappa`, // so the second check does not overflow. if remainder > ulp && ten_kappa - (remainder - ulp) <= remainder - ulp { @@ -754,7 +841,8 @@ pub fn format_exact_opt(d: &Decoded, buf: &mut [u8], limit: i16) return Some((len, exp)); } - // otherwise we are doomed (i.e. some values between `v - 1 ulp` and `v + 1 ulp` are + // otherwise we are doomed (i.e. some values between `v - 1 ulp` and `v + 1 + // ulp` are // rounding down and others are rounding up) and give up. None } @@ -763,7 +851,13 @@ pub fn format_exact_opt(d: &Decoded, buf: &mut [u8], limit: i16) /// The exact and fixed mode implementation for Grisu with Dragon fallback. /// /// This should be used for most cases. -pub fn format_exact(d: &Decoded, buf: &mut [u8], limit: i16) -> (/*#digits*/ usize, /*exp*/ i16) { +pub fn format_exact(d: &Decoded, + buf: &mut [u8], + limit: i16) + -> (// #digits + usize, + // exp + i16) { use num::flt2dec::strategy::dragon::format_exact as fallback; match format_exact_opt(d, buf, limit) { Some(ret) => ret, diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index dd59e10763780..0bc51d1d918c0 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -41,7 +41,8 @@ use slice::SliceExt; /// intended to have wrapping semantics. #[stable(feature = "rust1", since = "1.0.0")] #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug, Default)] -pub struct Wrapping(#[stable(feature = "rust1", since = "1.0.0")] pub T); +pub struct Wrapping(#[stable(feature = "rust1", since = "1.0.0")] + pub T); pub mod wrapping; @@ -1249,7 +1250,7 @@ pub enum FpCategory { /// Positive or negative infinity #[stable(feature = "rust1", since = "1.0.0")] - Infinite , + Infinite, /// Positive or negative zero #[stable(feature = "rust1", since = "1.0.0")] @@ -1392,7 +1393,7 @@ fn from_str_radix(src: &str, radix: u32) -> Result (true, &src[1..]), b'-' if is_signed_ty => (false, &src[1..]), - _ => (true, src) + _ => (true, src), }; if digits.is_empty() { @@ -1478,7 +1479,8 @@ pub use num::dec2flt::ParseFloatError; // Conversion traits for primitive integer types // Conversions T -> T are covered by a blanket impl and therefore excluded -// Some conversions from and to usize/isize are not implemented due to portability concerns +// Some conversions from and to usize/isize are not implemented due to +// portability concerns macro_rules! impl_from { ($Small: ty, $Large: ty) => { #[stable(feature = "lossless_int_conv", since = "1.5.0")] diff --git a/src/libcore/num/wrapping.rs b/src/libcore/num/wrapping.rs index 0e8ced0aa1934..cb3867bb62dd4 100644 --- a/src/libcore/num/wrapping.rs +++ b/src/libcore/num/wrapping.rs @@ -29,7 +29,7 @@ use intrinsics::{i16_mul_with_overflow, u16_mul_with_overflow}; use intrinsics::{i32_mul_with_overflow, u32_mul_with_overflow}; use intrinsics::{i64_mul_with_overflow, u64_mul_with_overflow}; -use ::{i8,i16,i32,i64}; +use {i8, i16, i32, i64}; pub trait OverflowingOps { fn overflowing_add(self, rhs: Self) -> (Self, bool); @@ -176,12 +176,12 @@ wrapping_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 } mod shift_max { #![allow(non_upper_case_globals)] - pub const i8: u32 = (1 << 3) - 1; + pub const i8: u32 = (1 << 3) - 1; pub const i16: u32 = (1 << 4) - 1; pub const i32: u32 = (1 << 5) - 1; pub const i64: u32 = (1 << 6) - 1; - pub const u8: u32 = i8; + pub const u8: u32 = i8; pub const u16: u32 = i16; pub const u32: u32 = i32; pub const u64: u32 = i64; From 53f19af08b25af88d54c9aeea02a7e1083f4e62b Mon Sep 17 00:00:00 2001 From: Michael Pankov Date: Thu, 22 Oct 2015 02:18:22 +0300 Subject: [PATCH 5/8] Restore the lost comment --- src/libcore/num/flt2dec/strategy/grisu.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/num/flt2dec/strategy/grisu.rs b/src/libcore/num/flt2dec/strategy/grisu.rs index ca19b8400b0c7..e026f3c5bccc5 100644 --- a/src/libcore/num/flt2dec/strategy/grisu.rs +++ b/src/libcore/num/flt2dec/strategy/grisu.rs @@ -537,7 +537,7 @@ pub fn format_shortest_opt(d: &Decoded, /// The shortest mode implementation for Grisu with Dragon fallback. /// /// This should be used for most cases. -pub fn format_shortest(d: &Decoded, buf: &mut [u8]) -> (usize, i16) { +pub fn format_shortest(d: &Decoded, buf: &mut [u8]) -> (/* #digits */ usize, /* exp */ i16) { use num::flt2dec::strategy::dragon::format_shortest as fallback; match format_shortest_opt(d, buf) { Some(ret) => ret, From a6722ee613146329c731f2d69e1884edd91c3fac Mon Sep 17 00:00:00 2001 From: Michael Pankov Date: Thu, 22 Oct 2015 02:22:24 +0300 Subject: [PATCH 6/8] Skip the generated table --- src/libcore/num/dec2flt/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libcore/num/dec2flt/mod.rs b/src/libcore/num/dec2flt/mod.rs index c739d67174cb0..50d52f24e80c8 100644 --- a/src/libcore/num/dec2flt/mod.rs +++ b/src/libcore/num/dec2flt/mod.rs @@ -147,6 +147,7 @@ use self::num::digits_to_big; use self::rawfp::RawFloat; mod algorithm; +#[rustfmt_skip] mod table; mod num; // These two have their own tests. From 9bf980992b600babb82d4297290e2ea3df2c184e Mon Sep 17 00:00:00 2001 From: Michael Pankov Date: Thu, 22 Oct 2015 02:22:39 +0300 Subject: [PATCH 7/8] Reformat the signature with restored comments --- src/libcore/num/flt2dec/strategy/grisu.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/libcore/num/flt2dec/strategy/grisu.rs b/src/libcore/num/flt2dec/strategy/grisu.rs index e026f3c5bccc5..391d878333c48 100644 --- a/src/libcore/num/flt2dec/strategy/grisu.rs +++ b/src/libcore/num/flt2dec/strategy/grisu.rs @@ -537,7 +537,12 @@ pub fn format_shortest_opt(d: &Decoded, /// The shortest mode implementation for Grisu with Dragon fallback. /// /// This should be used for most cases. -pub fn format_shortest(d: &Decoded, buf: &mut [u8]) -> (/* #digits */ usize, /* exp */ i16) { +pub fn format_shortest(d: &Decoded, + buf: &mut [u8]) + -> (// #digits + usize, + // exp + i16) { use num::flt2dec::strategy::dragon::format_shortest as fallback; match format_shortest_opt(d, buf) { Some(ret) => ret, From 28327e4189066481239de755e7224514e805e9f5 Mon Sep 17 00:00:00 2001 From: Michael Pankov Date: Fri, 23 Oct 2015 00:32:59 +0300 Subject: [PATCH 8/8] Use the proper attributes --- src/libcore/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 94408072932ea..910fe80034f07 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -64,6 +64,7 @@ #![no_core] #![allow(raw_pointer_derive)] +#![allow(unused_attributes)] #![deny(missing_docs)] #![feature(allow_internal_unstable)] @@ -84,6 +85,7 @@ #![cfg_attr(not(stage0), feature(repr_simd, platform_intrinsics))] #![feature(staged_api)] #![feature(unboxed_closures)] +#![feature(custom_attribute)] #[macro_use] mod macros;