1 // Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 // ignore-lexer-test FIXME #15679
13 #![allow(missing_doc)]
17 use collections::{Collection, MutableSeq};
18 use num::{NumCast, Zero, One, cast, Int};
19 use num::{Float, FPNaN, FPInfinite, ToPrimitive};
21 use ops::{Add, Sub, Mul, Div, Rem, Neg};
22 use option::{None, Option, Some};
23 use slice::{ImmutableVector, MutableVector};
24 use std::cmp::{PartialOrd, PartialEq};
29 /// A flag that specifies whether to use exponential (scientific) notation.
30 pub enum ExponentFormat {
31 /// Do not use exponential notation.
33 /// Use exponential notation with the exponent having a base of 10 and the
34 /// exponent sign being `e` or `E`. For example, 1000 would be printed
37 /// Use exponential notation with the exponent having a base of 2 and the
38 /// exponent sign being `p` or `P`. For example, 8 would be printed 1p3.
42 /// The number of digits used for emitting the fractional part of a number, if
44 pub enum SignificantDigits {
45 /// All calculable digits will be printed.
47 /// Note that bignums or fractions may cause a surprisingly large number
48 /// of digits to be printed.
51 /// At most the given number of digits will be printed, truncating any
55 /// Precisely the given number of digits will be printed.
59 /// How to emit the sign of a number.
61 /// No sign will be printed. The exponent sign will also be emitted.
63 /// `-` will be printed for negative values, but no sign will be emitted
64 /// for positive numbers.
66 /// `+` will be printed for positive values, and `-` will be printed for
71 /// Encompasses functions used by the string converter.
72 pub trait NumStrConv {
73 /// Returns the NaN value.
74 fn nan() -> Option<Self>;
76 /// Returns the infinite value.
77 fn inf() -> Option<Self>;
79 /// Returns the negative infinite value.
80 fn neg_inf() -> Option<Self>;
83 fn neg_zero() -> Option<Self>;
85 /// Rounds the number toward zero.
86 fn round_to_zero(&self) -> Self;
88 /// Returns the fractional part of the number.
89 fn fractional_part(&self) -> Self;
92 macro_rules! impl_NumStrConv_Floating (($t:ty) => (
93 impl NumStrConv for $t {
95 fn nan() -> Option<$t> { Some( 0.0 / 0.0) }
97 fn inf() -> Option<$t> { Some( 1.0 / 0.0) }
99 fn neg_inf() -> Option<$t> { Some(-1.0 / 0.0) }
101 fn neg_zero() -> Option<$t> { Some(-0.0 ) }
104 fn round_to_zero(&self) -> $t { self.trunc() }
106 fn fractional_part(&self) -> $t { self.fract() }
110 macro_rules! impl_NumStrConv_Integer (($t:ty) => (
111 impl NumStrConv for $t {
112 #[inline] fn nan() -> Option<$t> { None }
113 #[inline] fn inf() -> Option<$t> { None }
114 #[inline] fn neg_inf() -> Option<$t> { None }
115 #[inline] fn neg_zero() -> Option<$t> { None }
117 #[inline] fn round_to_zero(&self) -> $t { *self }
118 #[inline] fn fractional_part(&self) -> $t { 0 }
123 // Replace by two generic impls for traits 'Integral' and 'Floating'
124 impl_NumStrConv_Floating!(f32)
125 impl_NumStrConv_Floating!(f64)
127 impl_NumStrConv_Integer!(int)
128 impl_NumStrConv_Integer!(i8)
129 impl_NumStrConv_Integer!(i16)
130 impl_NumStrConv_Integer!(i32)
131 impl_NumStrConv_Integer!(i64)
133 impl_NumStrConv_Integer!(uint)
134 impl_NumStrConv_Integer!(u8)
135 impl_NumStrConv_Integer!(u16)
136 impl_NumStrConv_Integer!(u32)
137 impl_NumStrConv_Integer!(u64)
140 // Special value strings as [u8] consts.
141 static INF_BUF: [u8, ..3] = ['i' as u8, 'n' as u8, 'f' as u8];
142 static POS_INF_BUF: [u8, ..4] = ['+' as u8, 'i' as u8, 'n' as u8,
144 static NEG_INF_BUF: [u8, ..4] = ['-' as u8, 'i' as u8, 'n' as u8,
146 static NAN_BUF: [u8, ..3] = ['N' as u8, 'a' as u8, 'N' as u8];
149 * Converts an integral number to its string representation as a byte vector.
150 * This is meant to be a common base implementation for all integral string
151 * conversion functions like `to_string()` or `to_str_radix()`.
154 * - `num` - The number to convert. Accepts any number that
155 * implements the numeric traits.
156 * - `radix` - Base to use. Accepts only the values 2-36.
157 * - `sign` - How to emit the sign. Options are:
158 * - `SignNone`: No sign at all. Basically emits `abs(num)`.
159 * - `SignNeg`: Only `-` on negative values.
160 * - `SignAll`: Both `+` on positive, and `-` on negative numbers.
161 * - `f` - a callback which will be invoked for each ascii character
162 * which composes the string representation of this integer
165 * A tuple containing the byte vector, and a boolean flag indicating
166 * whether it represents a special value like `inf`, `-inf`, `NaN` or not.
167 * It returns a tuple because there can be ambiguity between a special value
168 * and a number representation at higher bases.
171 * - Fails if `radix` < 2 or `radix` > 36.
173 #[deprecated = "format!() and friends should be favored instead"]
174 pub fn int_to_str_bytes_common<T: Int>(num: T, radix: uint, sign: SignFormat, f: |u8|) {
175 assert!(2 <= radix && radix <= 36);
177 let _0: T = Zero::zero();
180 let radix_gen: T = cast(radix).unwrap();
182 let mut deccum = num;
183 // This is just for integral types, the largest of which is a u64. The
184 // smallest base that we can have is 2, so the most number of digits we're
185 // ever going to have is 64
186 let mut buf = [0u8, ..64];
189 // Loop at least once to make sure at least a `0` gets emitted.
191 // Calculate the absolute value of each digit instead of only
192 // doing it once for the whole number because a
193 // representable negative number doesn't necessary have an
194 // representable additive inverse of the same type
195 // (See twos complement). But we assume that for the
196 // numbers [-35 .. 0] we always have [0 .. 35].
197 let current_digit_signed = deccum % radix_gen;
198 let current_digit = if current_digit_signed < _0 {
199 -current_digit_signed
203 buf[cur] = match current_digit.to_u8().unwrap() {
204 i @ 0..9 => '0' as u8 + i,
205 i => 'a' as u8 + (i - 10),
209 deccum = deccum / radix_gen;
210 // No more digits to calculate for the non-fractional part -> break
211 if deccum == _0 { break; }
214 // Decide what sign to put in front
216 SignNeg | SignAll if neg => { f('-' as u8); }
217 SignAll => { f('+' as u8); }
221 // We built the number in reverse order, so un-reverse it here
229 * Converts a number to its string representation as a byte vector.
230 * This is meant to be a common base implementation for all numeric string
231 * conversion functions like `to_string()` or `to_str_radix()`.
234 * - `num` - The number to convert. Accepts any number that
235 * implements the numeric traits.
236 * - `radix` - Base to use. Accepts only the values 2-36. If the exponential notation
237 * is used, then this base is only used for the significand. The exponent
238 * itself always printed using a base of 10.
239 * - `negative_zero` - Whether to treat the special value `-0` as
241 * - `sign` - How to emit the sign. See `SignFormat`.
242 * - `digits` - The amount of digits to use for emitting the fractional
243 * part, if any. See `SignificantDigits`.
244 * - `exp_format` - Whether or not to use the exponential (scientific) notation.
245 * See `ExponentFormat`.
246 * - `exp_capital` - Whether or not to use a capital letter for the exponent sign, if
247 * exponential notation is desired.
250 * A tuple containing the byte vector, and a boolean flag indicating
251 * whether it represents a special value like `inf`, `-inf`, `NaN` or not.
252 * It returns a tuple because there can be ambiguity between a special value
253 * and a number representation at higher bases.
256 * - Fails if `radix` < 2 or `radix` > 36.
257 * - Fails if `radix` > 14 and `exp_format` is `ExpDec` due to conflict
258 * between digit and exponent sign `'e'`.
259 * - Fails if `radix` > 25 and `exp_format` is `ExpBin` due to conflict
260 * between digit and exponent sign `'p'`.
263 pub fn float_to_str_bytes_common<T:NumCast+Zero+One+PartialEq+PartialOrd+Float+
264 Div<T,T>+Neg<T>+Rem<T,T>+Mul<T,T>>(
265 num: T, radix: uint, negative_zero: bool,
266 sign: SignFormat, digits: SignificantDigits, exp_format: ExponentFormat, exp_upper: bool
267 ) -> (Vec<u8>, bool) {
268 assert!(2 <= radix && radix <= 36);
270 ExpDec if radix >= DIGIT_E_RADIX // decimal exponent 'e'
271 => fail!("float_to_str_bytes_common: radix {} incompatible with \
272 use of 'e' as decimal exponent", radix),
273 ExpBin if radix >= DIGIT_P_RADIX // binary exponent 'p'
274 => fail!("float_to_str_bytes_common: radix {} incompatible with \
275 use of 'p' as binary exponent", radix),
279 let _0: T = Zero::zero();
280 let _1: T = One::one();
282 match num.classify() {
283 FPNaN => { return (Vec::from_slice("NaN".as_bytes()), true); }
284 FPInfinite if num > _0 => {
286 SignAll => (Vec::from_slice("+inf".as_bytes()), true),
287 _ => (Vec::from_slice("inf".as_bytes()), true)
290 FPInfinite if num < _0 => {
292 SignNone => (Vec::from_slice("inf".as_bytes()), true),
293 _ => (Vec::from_slice("-inf".as_bytes()), true),
299 let neg = num < _0 || (negative_zero && _1 / num == Float::neg_infinity());
300 let mut buf = Vec::new();
301 let radix_gen: T = cast(radix as int).unwrap();
303 let (num, exp) = match exp_format {
304 ExpNone => (num, 0i32),
309 let (exp, exp_base) = match exp_format {
310 ExpDec => (num.abs().log10().floor(), cast::<f64, T>(10.0f64).unwrap()),
311 ExpBin => (num.abs().log2().floor(), cast::<f64, T>(2.0f64).unwrap()),
312 ExpNone => unreachable!()
315 (num / exp_base.powf(exp), cast::<T, i32>(exp).unwrap())
320 // First emit the non-fractional part, looping at least once to make
321 // sure at least a `0` gets emitted.
322 let mut deccum = num.trunc();
324 // Calculate the absolute value of each digit instead of only
325 // doing it once for the whole number because a
326 // representable negative number doesn't necessary have an
327 // representable additive inverse of the same type
328 // (See twos complement). But we assume that for the
329 // numbers [-35 .. 0] we always have [0 .. 35].
330 let current_digit = (deccum % radix_gen).abs();
332 // Decrease the deccumulator one digit at a time
333 deccum = deccum / radix_gen;
334 deccum = deccum.trunc();
336 buf.push(char::from_digit(current_digit.to_int().unwrap() as uint, radix)
339 // No more digits to calculate for the non-fractional part -> break
340 if deccum == _0 { break; }
343 // If limited digits, calculate one digit more for rounding.
344 let (limit_digits, digit_count, exact) = match digits {
345 DigAll => (false, 0u, false),
346 DigMax(count) => (true, count+1, false),
347 DigExact(count) => (true, count+1, true)
350 // Decide what sign to put in front
352 SignNeg | SignAll if neg => {
363 // Remember start of the fractional digits.
364 // Points one beyond end of buf if none get generated,
365 // or at the '.' otherwise.
366 let start_fractional_digits = buf.len();
368 // Now emit the fractional part, if any
369 deccum = num.fract();
370 if deccum != _0 || (limit_digits && exact && digit_count > 0) {
374 // calculate new digits while
375 // - there is no limit and there are digits left
376 // - or there is a limit, it's not reached yet and
378 // - or it's a maximum, and there are still digits left
379 while (!limit_digits && deccum != _0)
380 || (limit_digits && dig < digit_count && (
382 || (!exact && deccum != _0)
385 // Shift first fractional digit into the integer part
386 deccum = deccum * radix_gen;
388 // Calculate the absolute value of each digit.
389 // See note in first loop.
390 let current_digit = deccum.trunc().abs();
392 buf.push(char::from_digit(
393 current_digit.to_int().unwrap() as uint, radix).unwrap() as u8);
395 // Decrease the deccumulator one fractional digit at a time
396 deccum = deccum.fract();
400 // If digits are limited, and that limit has been reached,
401 // cut off the one extra digit, and depending on its value
402 // round the remaining ones.
403 if limit_digits && dig == digit_count {
404 let ascii2value = |chr: u8| {
405 char::to_digit(chr as char, radix).unwrap()
407 let value2ascii = |val: uint| {
408 char::from_digit(val, radix).unwrap() as u8
411 let extra_digit = ascii2value(buf.pop().unwrap());
412 if extra_digit >= radix / 2 { // -> need to round
413 let mut i: int = buf.len() as int - 1;
415 // If reached left end of number, have to
416 // insert additional digit:
418 || *buf.get(i as uint) == '-' as u8
419 || *buf.get(i as uint) == '+' as u8 {
420 buf.insert((i + 1) as uint, value2ascii(1));
425 if *buf.get(i as uint) == '.' as u8 { i -= 1; continue; }
427 // Either increment the digit,
428 // or set to 0 if max and carry the 1.
429 let current_digit = ascii2value(*buf.get(i as uint));
430 if current_digit < (radix - 1) {
431 *buf.get_mut(i as uint) = value2ascii(current_digit+1);
434 *buf.get_mut(i as uint) = value2ascii(0);
442 // if number of digits is not exact, remove all trailing '0's up to
443 // and including the '.'
445 let buf_max_i = buf.len() - 1;
447 // index to truncate from
448 let mut i = buf_max_i;
450 // discover trailing zeros of fractional part
451 while i > start_fractional_digits && *buf.get(i) == '0' as u8 {
455 // Only attempt to truncate digits if buf has fractional digits
456 if i >= start_fractional_digits {
457 // If buf ends with '.', cut that too.
458 if *buf.get(i) == '.' as u8 { i -= 1 }
460 // only resize buf if we actually remove digits
462 buf = Vec::from_slice(buf.slice(0, i + 1));
465 } // If exact and trailing '.', just cut that
467 let max_i = buf.len() - 1;
468 if *buf.get(max_i) == '.' as u8 {
469 buf = Vec::from_slice(buf.slice(0, max_i));
476 buf.push(match exp_format {
477 ExpDec if exp_upper => 'E',
478 ExpDec if !exp_upper => 'e',
479 ExpBin if exp_upper => 'P',
480 ExpBin if !exp_upper => 'p',
484 int_to_str_bytes_common(exp, 10, sign, |c| buf.push(c));
492 * Converts a number to its string representation. This is a wrapper for
493 * `to_str_bytes_common()`, for details see there.
496 pub fn float_to_str_common<T:NumCast+Zero+One+PartialEq+PartialOrd+NumStrConv+Float+
497 Div<T,T>+Neg<T>+Rem<T,T>+Mul<T,T>>(
498 num: T, radix: uint, negative_zero: bool,
499 sign: SignFormat, digits: SignificantDigits, exp_format: ExponentFormat, exp_capital: bool
500 ) -> (String, bool) {
501 let (bytes, special) = float_to_str_bytes_common(num, radix,
502 negative_zero, sign, digits, exp_format, exp_capital);
503 (String::from_utf8(bytes).unwrap(), special)
506 // Some constants for from_str_bytes_common's input validation,
507 // they define minimum radix values for which the character is a valid digit.
508 static DIGIT_P_RADIX: uint = ('p' as uint) - ('a' as uint) + 11u;
509 static DIGIT_I_RADIX: uint = ('i' as uint) - ('a' as uint) + 11u;
510 static DIGIT_E_RADIX: uint = ('e' as uint) - ('a' as uint) + 11u;
513 * Parses a byte slice as a number. This is meant to
514 * be a common base implementation for all numeric string conversion
515 * functions like `from_str()` or `from_str_radix()`.
518 * - `buf` - The byte slice to parse.
519 * - `radix` - Which base to parse the number as. Accepts 2-36.
520 * - `negative` - Whether to accept negative numbers.
521 * - `fractional` - Whether to accept numbers with fractional parts.
522 * - `special` - Whether to accept special values like `inf`
523 * and `NaN`. Can conflict with `radix`, see Failure.
524 * - `exponent` - Which exponent format to accept. Options are:
525 * - `ExpNone`: No Exponent, accepts just plain numbers like `42` or
527 * - `ExpDec`: Accepts numbers with a decimal exponent like `42e5` or
528 * `8.2E-2`. The exponent string itself is always base 10.
529 * Can conflict with `radix`, see Failure.
530 * - `ExpBin`: Accepts numbers with a binary exponent like `42P-8` or
531 * `FFp128`. The exponent string itself is always base 10.
532 * Can conflict with `radix`, see Failure.
533 * - `empty_zero` - Whether to accept an empty `buf` as a 0 or not.
534 * - `ignore_underscores` - Whether all underscores within the string should
538 * Returns `Some(n)` if `buf` parses to a number n without overflowing, and
539 * `None` otherwise, depending on the constraints set by the remaining
543 * - Fails if `radix` < 2 or `radix` > 36.
544 * - Fails if `radix` > 14 and `exponent` is `ExpDec` due to conflict
545 * between digit and exponent sign `'e'`.
546 * - Fails if `radix` > 25 and `exponent` is `ExpBin` due to conflict
547 * between digit and exponent sign `'p'`.
548 * - Fails if `radix` > 18 and `special == true` due to conflict
549 * between digit and lowest first character in `inf` and `NaN`, the `'i'`.
551 pub fn from_str_bytes_common<T:NumCast+Zero+One+PartialEq+PartialOrd+Div<T,T>+
552 Mul<T,T>+Sub<T,T>+Neg<T>+Add<T,T>+
554 buf: &[u8], radix: uint, negative: bool, fractional: bool,
555 special: bool, exponent: ExponentFormat, empty_zero: bool,
556 ignore_underscores: bool
559 ExpDec if radix >= DIGIT_E_RADIX // decimal exponent 'e'
560 => fail!("from_str_bytes_common: radix {} incompatible with \
561 use of 'e' as decimal exponent", radix),
562 ExpBin if radix >= DIGIT_P_RADIX // binary exponent 'p'
563 => fail!("from_str_bytes_common: radix {} incompatible with \
564 use of 'p' as binary exponent", radix),
565 _ if special && radix >= DIGIT_I_RADIX // first digit of 'inf'
566 => fail!("from_str_bytes_common: radix {} incompatible with \
567 special values 'inf' and 'NaN'", radix),
568 _ if (radix as int) < 2
569 => fail!("from_str_bytes_common: radix {} to low, \
570 must lie in the range [2, 36]", radix),
571 _ if (radix as int) > 36
572 => fail!("from_str_bytes_common: radix {} to high, \
573 must lie in the range [2, 36]", radix),
577 let _0: T = Zero::zero();
578 let _1: T = One::one();
579 let radix_gen: T = cast(radix as int).unwrap();
592 if buf == INF_BUF || buf == POS_INF_BUF {
593 return NumStrConv::inf();
594 } else if buf == NEG_INF_BUF {
596 return NumStrConv::neg_inf();
600 } else if buf == NAN_BUF {
601 return NumStrConv::nan();
605 let (start, accum_positive) = match buf[0] as char {
606 '-' if !negative => return None,
612 // Initialize accumulator with signed zero for floating point parsing to
614 let mut accum = if accum_positive { _0.clone() } else { -_1 * _0};
615 let mut last_accum = accum.clone(); // Necessary to detect overflow
617 let mut exp_found = false;
619 // Parse integer part of number
621 let c = buf[i] as char;
623 match char::to_digit(c, radix) {
625 // shift accum one digit left
626 accum = accum * radix_gen.clone();
628 // add/subtract current digit depending on sign
630 accum = accum + cast(digit as int).unwrap();
632 accum = accum - cast(digit as int).unwrap();
635 // Detect overflow by comparing to last value, except
636 // if we've not seen any non-zero digits.
637 if last_accum != _0 {
638 if accum_positive && accum <= last_accum { return NumStrConv::inf(); }
639 if !accum_positive && accum >= last_accum { return NumStrConv::neg_inf(); }
641 // Detect overflow by reversing the shift-and-add process
643 (last_accum != ((accum - cast(digit as int).unwrap())/radix_gen.clone())) {
644 return NumStrConv::inf();
646 if !accum_positive &&
647 (last_accum != ((accum + cast(digit as int).unwrap())/radix_gen.clone())) {
648 return NumStrConv::neg_inf();
651 last_accum = accum.clone();
654 '_' if ignore_underscores => {}
655 'e' | 'E' | 'p' | 'P' => {
657 break; // start of exponent
659 '.' if fractional => {
660 i += 1u; // skip the '.'
661 break; // start of fractional part
663 _ => return None // invalid number
670 // Parse fractional part of number
671 // Skip if already reached start of exponent
673 let mut power = _1.clone();
676 let c = buf[i] as char;
678 match char::to_digit(c, radix) {
680 // Decrease power one order of magnitude
681 power = power / radix_gen;
683 let digit_t: T = cast(digit).unwrap();
685 // add/subtract current digit depending on sign
687 accum = accum + digit_t * power;
689 accum = accum - digit_t * power;
692 // Detect overflow by comparing to last value
693 if accum_positive && accum < last_accum { return NumStrConv::inf(); }
694 if !accum_positive && accum > last_accum { return NumStrConv::neg_inf(); }
695 last_accum = accum.clone();
698 '_' if ignore_underscores => {}
699 'e' | 'E' | 'p' | 'P' => {
701 break; // start of exponent
703 _ => return None // invalid number
711 // Special case: buf not empty, but does not contain any digit in front
712 // of the exponent sign -> number is empty string
721 let mut multiplier = _1.clone();
724 let c = buf[i] as char;
725 let base: T = match (c, exponent) {
726 // c is never _ so don't need to handle specially
727 ('e', ExpDec) | ('E', ExpDec) => cast(10u).unwrap(),
728 ('p', ExpBin) | ('P', ExpBin) => cast(2u).unwrap(),
729 _ => return None // char doesn't fit given exponent format
732 // parse remaining bytes as decimal integer,
733 // skipping the exponent char
734 let exp: Option<int> = from_str_bytes_common(
735 buf.slice(i+1, len), 10, true, false, false, ExpNone, false,
740 multiplier = if exp_pow < 0 {
741 _1 / num::pow(base, (-exp_pow.to_int().unwrap()) as uint)
743 num::pow(base, exp_pow.to_int().unwrap() as uint)
746 None => return None // invalid exponent -> invalid number
750 Some(accum * multiplier)
754 * Parses a string as a number. This is a wrapper for
755 * `from_str_bytes_common()`, for details see there.
758 pub fn from_str_common<T:NumCast+Zero+One+PartialEq+PartialOrd+Div<T,T>+Mul<T,T>+
759 Sub<T,T>+Neg<T>+Add<T,T>+NumStrConv+Clone>(
760 buf: &str, radix: uint, negative: bool, fractional: bool,
761 special: bool, exponent: ExponentFormat, empty_zero: bool,
762 ignore_underscores: bool
764 from_str_bytes_common(buf.as_bytes(), radix, negative,
765 fractional, special, exponent, empty_zero,
775 fn from_str_ignore_underscores() {
776 let s : Option<u8> = from_str_common("__1__", 2, false, false, false,
777 ExpNone, false, true);
778 assert_eq!(s, Some(1u8));
780 let n : Option<u8> = from_str_common("__1__", 2, false, false, false,
781 ExpNone, false, false);
784 let f : Option<f32> = from_str_common("_1_._5_e_1_", 10, false, true, false,
785 ExpDec, false, true);
786 assert_eq!(f, Some(1.5e1f32));
790 fn from_str_issue5770() {
791 // try to parse 0b1_1111_1111 = 511 as a u8. Caused problems
792 // since 255*2+1 == 255 (mod 256) so the overflow wasn't
794 let n : Option<u8> = from_str_common("111111111", 2, false, false, false,
795 ExpNone, false, false);
800 fn from_str_issue7588() {
801 let u : Option<u8> = from_str_common("1000", 10, false, false, false,
802 ExpNone, false, false);
804 let s : Option<i16> = from_str_common("80000", 10, false, false, false,
805 ExpNone, false, false);
807 let f : Option<f32> = from_str_common(
808 "10000000000000000000000000000000000000000", 10, false, false, false,
809 ExpNone, false, false);
810 assert_eq!(f, NumStrConv::inf())
811 let fe : Option<f32> = from_str_common("1e40", 10, false, false, false,
812 ExpDec, false, false);
813 assert_eq!(fe, NumStrConv::inf())
822 use super::test::Bencher;
823 use rand::{weak_rng, Rng};
827 fn to_str_bin(b: &mut Bencher) {
828 let mut rng = weak_rng();
829 b.iter(|| { rng.gen::<uint>().to_str_radix(2); })
833 fn to_str_oct(b: &mut Bencher) {
834 let mut rng = weak_rng();
835 b.iter(|| { rng.gen::<uint>().to_str_radix(8); })
839 fn to_str_dec(b: &mut Bencher) {
840 let mut rng = weak_rng();
841 b.iter(|| { rng.gen::<uint>().to_str_radix(10); })
845 fn to_str_hex(b: &mut Bencher) {
846 let mut rng = weak_rng();
847 b.iter(|| { rng.gen::<uint>().to_str_radix(16); })
851 fn to_str_base_36(b: &mut Bencher) {
852 let mut rng = weak_rng();
853 b.iter(|| { rng.gen::<uint>().to_str_radix(36); })
858 use super::test::Bencher;
859 use rand::{weak_rng, Rng};
863 fn to_str_bin(b: &mut Bencher) {
864 let mut rng = weak_rng();
865 b.iter(|| { rng.gen::<int>().to_str_radix(2); })
869 fn to_str_oct(b: &mut Bencher) {
870 let mut rng = weak_rng();
871 b.iter(|| { rng.gen::<int>().to_str_radix(8); })
875 fn to_str_dec(b: &mut Bencher) {
876 let mut rng = weak_rng();
877 b.iter(|| { rng.gen::<int>().to_str_radix(10); })
881 fn to_str_hex(b: &mut Bencher) {
882 let mut rng = weak_rng();
883 b.iter(|| { rng.gen::<int>().to_str_radix(16); })
887 fn to_str_base_36(b: &mut Bencher) {
888 let mut rng = weak_rng();
889 b.iter(|| { rng.gen::<int>().to_str_radix(36); })
894 use super::test::Bencher;
895 use rand::{weak_rng, Rng};
899 fn float_to_string(b: &mut Bencher) {
900 let mut rng = weak_rng();
901 b.iter(|| { f64::to_string(rng.gen()); })