about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorSiegeLord <slabode@aim.com>2014-01-16 18:24:03 -0500
committerSiegeLord <slabode@aim.com>2014-01-22 20:32:40 -0500
commit2b4bd0780bb98f4171dd6464a4f01065b8d85ffd (patch)
tree85887b4fd5a178eda845b44343fa84cb46745fad /src/libstd
parentfce792249e72a181f2ad52413b25b1db643c371f (diff)
downloadrust-2b4bd0780bb98f4171dd6464a4f01065b8d85ffd.tar.gz
rust-2b4bd0780bb98f4171dd6464a4f01065b8d85ffd.zip
float_to_str_bytes_common can now handle exponential notation
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/num/f32.rs12
-rw-r--r--src/libstd/num/f64.rs12
-rw-r--r--src/libstd/num/strconv.rs70
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 @@ impl Float for f32 {
 #[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 @@ impl Float for f64 {
 #[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<T:NumCast
  * # Arguments
  * - `num`           - The number to convert. Accepts any number that
  *                     implements the numeric traits.
- * - `radix`         - Base to use. Accepts only the values 2-36.
+ * - `radix`         - Base to use. Accepts only the values 2-36. If the exponential notation
+ *                     is used, then this base is only used for the significand. The exponent
+ *                     itself always printed using a base of 10.
  * - `negative_zero` - Whether to treat the special value `-0` as
  *                     `-0` or as `+0`.
  * - `sign`          - How to emit the sign. Options are:
- *     - `SignNone`: No sign at all. Basically emits `abs(num)`.
+ *     - `SignNone`: No sign at all. The exponent sign is also omitted.
  *     - `SignNeg`:  Only `-` on negative values.
  *     - `SignAll`:  Both `+` on positive, and `-` on negative numbers.
  * - `digits`        - The amount of digits to use for emitting the
@@ -220,6 +222,17 @@ pub fn int_to_str_bytes_common<T:NumCast
  *                         fractions!
  *     - `DigMax(uint)`:   Maximum N digits, truncating any trailing zeros.
  *     - `DigExact(uint)`: Exactly N digits.
+ * - `exp_format`   - Whether or not to use the exponential (scientific) notation.
+ *                    Options are:
+ *     - `ExpNone`: Do not use the exponential notation.
+ *     - `ExpDec`:  Use the exponential notation with the exponent having a base of 10,
+ *                  and exponent sign being `'e'` or `'E'` depending on the value of
+ *                  the `exp_upper` argument. E.g. the number 1000 would be printed as 1e3.
+ *     - `ExpBin`:  Use the exponential notation with the exponent having a base of 2,
+ *                  and exponent sign being `'p'` or `'P'` depending on the value of
+ *                  the `exp_upper` argument. E.g. the number 8 would be printed as 1p3.
+ * - `exp_capital`   - Whether or not to use a capital letter for the exponent sign, if
+ *                     exponential notation is desired.
  *
  * # Return value
  * A tuple containing the byte vector, and a boolean flag indicating
@@ -229,12 +242,26 @@ pub fn int_to_str_bytes_common<T:NumCast
  *
  * # Failure
  * - Fails if `radix` < 2 or `radix` > 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<T:NumCast+Zero+One+Eq+Ord+Float+Round+
                                   Div<T,T>+Neg<T>+Rem<T,T>+Mul<T,T>>(
         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<T:NumCast+Zero+One+Eq+Ord+Float+Round+
     let mut buf: ~[u8] = ~[];
     let radix_gen: T   = cast(radix as int).unwrap();
 
+    let (num, exp) = match exp_format {
+        ExpNone => (num, 0i32),
+        ExpDec | ExpBin => {
+            if num == _0 {
+                (num, 0i32)
+            } else {
+                let (exp, exp_base) = match exp_format {
+                    ExpDec => (num.abs().log10().floor(), cast::<f64, T>(10.0f64).unwrap()),
+                    ExpBin => (num.abs().log2().floor(), cast::<f64, T>(2.0f64).unwrap()),
+                    ExpNone => unreachable!()
+                };
+
+                (num / exp_base.powf(&exp), cast::<T, i32>(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<T:NumCast+Zero+One+Eq+Ord+Float+Round+
         }
     }
 
+    match exp_format {
+        ExpNone => (),
+        _ => {
+            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<T:NumCast+Zero+One+Eq+Ord+Float+Round+
 pub fn float_to_str_common<T:NumCast+Zero+One+Eq+Ord+NumStrConv+Float+Round+
                              Div<T,T>+Neg<T>+Rem<T,T>+Mul<T,T>>(
         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)
 }