From 2b4bd0780bb98f4171dd6464a4f01065b8d85ffd Mon Sep 17 00:00:00 2001 From: SiegeLord Date: Thu, 16 Jan 2014 18:24:03 -0500 Subject: [PATCH] float_to_str_bytes_common can now handle exponential notation --- src/libstd/num/f32.rs | 12 +++---- src/libstd/num/f64.rs | 12 +++---- src/libstd/num/strconv.rs | 70 ++++++++++++++++++++++++++++++++++++--- 3 files changed, 77 insertions(+), 17 deletions(-) diff --git a/src/libstd/num/f32.rs b/src/libstd/num/f32.rs index 5b0c75ef174..e95ad7ca7f5 100644 --- a/src/libstd/num/f32.rs +++ b/src/libstd/num/f32.rs @@ -718,7 +718,7 @@ fn integer_decode(&self) -> (u64, i16, i8) { #[inline] pub fn to_str(num: f32) -> ~str { let (r, _) = strconv::float_to_str_common( - num, 10u, true, strconv::SignNeg, strconv::DigAll); + num, 10u, true, strconv::SignNeg, strconv::DigAll, strconv::ExpNone, false); r } @@ -732,7 +732,7 @@ pub fn to_str(num: f32) -> ~str { #[inline] pub fn to_str_hex(num: f32) -> ~str { let (r, _) = strconv::float_to_str_common( - num, 16u, true, strconv::SignNeg, strconv::DigAll); + num, 16u, true, strconv::SignNeg, strconv::DigAll, strconv::ExpNone, false); r } @@ -748,7 +748,7 @@ pub fn to_str_hex(num: f32) -> ~str { #[inline] pub fn to_str_radix_special(num: f32, rdx: uint) -> (~str, bool) { strconv::float_to_str_common(num, rdx, true, - strconv::SignNeg, strconv::DigAll) + strconv::SignNeg, strconv::DigAll, strconv::ExpNone, false) } /// @@ -763,7 +763,7 @@ pub fn to_str_radix_special(num: f32, rdx: uint) -> (~str, bool) { #[inline] pub fn to_str_exact(num: f32, dig: uint) -> ~str { let (r, _) = strconv::float_to_str_common( - num, 10u, true, strconv::SignNeg, strconv::DigExact(dig)); + num, 10u, true, strconv::SignNeg, strconv::DigExact(dig), strconv::ExpNone, false); r } @@ -779,7 +779,7 @@ pub fn to_str_exact(num: f32, dig: uint) -> ~str { #[inline] pub fn to_str_digits(num: f32, dig: uint) -> ~str { let (r, _) = strconv::float_to_str_common( - num, 10u, true, strconv::SignNeg, strconv::DigMax(dig)); + num, 10u, true, strconv::SignNeg, strconv::DigMax(dig), strconv::ExpNone, false); r } @@ -804,7 +804,7 @@ impl num::ToStrRadix for f32 { #[inline] fn to_str_radix(&self, rdx: uint) -> ~str { let (r, special) = strconv::float_to_str_common( - *self, rdx, true, strconv::SignNeg, strconv::DigAll); + *self, rdx, true, strconv::SignNeg, strconv::DigAll, strconv::ExpNone, false); if special { fail!("number has a special value, \ try to_str_radix_special() if those are expected") } r diff --git a/src/libstd/num/f64.rs b/src/libstd/num/f64.rs index 95e5797ae93..33ee4acf58b 100644 --- a/src/libstd/num/f64.rs +++ b/src/libstd/num/f64.rs @@ -720,7 +720,7 @@ fn integer_decode(&self) -> (u64, i16, i8) { #[inline] pub fn to_str(num: f64) -> ~str { let (r, _) = strconv::float_to_str_common( - num, 10u, true, strconv::SignNeg, strconv::DigAll); + num, 10u, true, strconv::SignNeg, strconv::DigAll, strconv::ExpNone, false); r } @@ -734,7 +734,7 @@ pub fn to_str(num: f64) -> ~str { #[inline] pub fn to_str_hex(num: f64) -> ~str { let (r, _) = strconv::float_to_str_common( - num, 16u, true, strconv::SignNeg, strconv::DigAll); + num, 16u, true, strconv::SignNeg, strconv::DigAll, strconv::ExpNone, false); r } @@ -750,7 +750,7 @@ pub fn to_str_hex(num: f64) -> ~str { #[inline] pub fn to_str_radix_special(num: f64, rdx: uint) -> (~str, bool) { strconv::float_to_str_common(num, rdx, true, - strconv::SignNeg, strconv::DigAll) + strconv::SignNeg, strconv::DigAll, strconv::ExpNone, false) } /// @@ -765,7 +765,7 @@ pub fn to_str_radix_special(num: f64, rdx: uint) -> (~str, bool) { #[inline] pub fn to_str_exact(num: f64, dig: uint) -> ~str { let (r, _) = strconv::float_to_str_common( - num, 10u, true, strconv::SignNeg, strconv::DigExact(dig)); + num, 10u, true, strconv::SignNeg, strconv::DigExact(dig), strconv::ExpNone, false); r } @@ -781,7 +781,7 @@ pub fn to_str_exact(num: f64, dig: uint) -> ~str { #[inline] pub fn to_str_digits(num: f64, dig: uint) -> ~str { let (r, _) = strconv::float_to_str_common( - num, 10u, true, strconv::SignNeg, strconv::DigMax(dig)); + num, 10u, true, strconv::SignNeg, strconv::DigMax(dig), strconv::ExpNone, false); r } @@ -806,7 +806,7 @@ impl num::ToStrRadix for f64 { #[inline] fn to_str_radix(&self, rdx: uint) -> ~str { let (r, special) = strconv::float_to_str_common( - *self, rdx, true, strconv::SignNeg, strconv::DigAll); + *self, rdx, true, strconv::SignNeg, strconv::DigAll, strconv::ExpNone, false); if special { fail!("number has a special value, \ try to_str_radix_special() if those are expected") } r diff --git a/src/libstd/num/strconv.rs b/src/libstd/num/strconv.rs index bf9e6b739f2..30abe86866e 100644 --- a/src/libstd/num/strconv.rs +++ b/src/libstd/num/strconv.rs @@ -207,11 +207,13 @@ pub fn int_to_str_bytes_common 36. + * - Fails if `radix` > 14 and `exp_format` is `ExpDec` due to conflict + * between digit and exponent sign `'e'`. + * - Fails if `radix` > 25 and `exp_format` is `ExpBin` due to conflict + * between digit and exponent sign `'p'`. */ pub fn float_to_str_bytes_common+Neg+Rem+Mul>( num: T, radix: uint, negative_zero: bool, - sign: SignFormat, digits: SignificantDigits) -> (~[u8], bool) { + sign: SignFormat, digits: SignificantDigits, exp_format: ExponentFormat, exp_upper: bool + ) -> (~[u8], bool) { assert!(2 <= radix && radix <= 36); + match exp_format { + ExpDec if radix >= DIGIT_E_RADIX // decimal exponent 'e' + => fail!("float_to_str_bytes_common: radix {} incompatible with \ + use of 'e' as decimal exponent", radix), + ExpBin if radix >= DIGIT_P_RADIX // binary exponent 'p' + => fail!("float_to_str_bytes_common: radix {} incompatible with \ + use of 'p' as binary exponent", radix), + _ => () + } let _0: T = Zero::zero(); let _1: T = One::one(); @@ -260,6 +287,23 @@ pub fn float_to_str_bytes_common (num, 0i32), + ExpDec | ExpBin => { + if num == _0 { + (num, 0i32) + } else { + let (exp, exp_base) = match exp_format { + ExpDec => (num.abs().log10().floor(), cast::(10.0f64).unwrap()), + ExpBin => (num.abs().log2().floor(), cast::(2.0f64).unwrap()), + ExpNone => unreachable!() + }; + + (num / exp_base.powf(&exp), cast::(exp).unwrap()) + } + } + }; + // First emit the non-fractional part, looping at least once to make // sure at least a `0` gets emitted. let mut deccum = num.trunc(); @@ -413,6 +457,21 @@ pub fn float_to_str_bytes_common (), + _ => { + buf.push(match exp_format { + ExpDec if exp_upper => 'E', + ExpDec if !exp_upper => 'e', + ExpBin if exp_upper => 'P', + ExpBin if !exp_upper => 'p', + _ => unreachable!() + } as u8); + + int_to_str_bytes_common(exp, 10, sign, |c| buf.push(c)); + } + } + (buf, false) } @@ -424,9 +483,10 @@ pub fn float_to_str_bytes_common+Neg+Rem+Mul>( num: T, radix: uint, negative_zero: bool, - sign: SignFormat, digits: SignificantDigits) -> (~str, bool) { + sign: SignFormat, digits: SignificantDigits, exp_format: ExponentFormat, exp_capital: bool + ) -> (~str, bool) { let (bytes, special) = float_to_str_bytes_common(num, radix, - negative_zero, sign, digits); + negative_zero, sign, digits, exp_format, exp_capital); (str::from_utf8_owned(bytes).unwrap(), special) }