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 #![allow(missing_doc)]
15 use container::Container;
17 use num::{NumCast, Zero, One, cast, Int};
18 use num::{Float, FPNaN, FPInfinite, ToPrimitive};
20 use ops::{Add, Sub, Mul, Div, Rem, Neg};
21 use option::{None, Option, Some};
22 use slice::OwnedVector;
23 use slice::{CloneableVector, ImmutableVector, MutableVector};
24 use std::cmp::{Ord, Eq};
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_str()` 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 pub fn int_to_str_bytes_common<T: Int>(num: T, radix: uint, sign: SignFormat, f: |u8|) {
174 assert!(2 <= radix && radix <= 36);
176 let _0: T = Zero::zero();
179 let radix_gen: T = cast(radix).unwrap();
181 let mut deccum = num;
182 // This is just for integral types, the largest of which is a u64. The
183 // smallest base that we can have is 2, so the most number of digits we're
184 // ever going to have is 64
185 let mut buf = [0u8, ..64];
188 // Loop at least once to make sure at least a `0` gets emitted.
190 // Calculate the absolute value of each digit instead of only
191 // doing it once for the whole number because a
192 // representable negative number doesn't necessary have an
193 // representable additive inverse of the same type
194 // (See twos complement). But we assume that for the
195 // numbers [-35 .. 0] we always have [0 .. 35].
196 let current_digit_signed = deccum % radix_gen;
197 let current_digit = if current_digit_signed < _0 {
198 -current_digit_signed
202 buf[cur] = match current_digit.to_u8().unwrap() {
203 i @ 0..9 => '0' as u8 + i,
204 i => 'a' as u8 + (i - 10),
208 deccum = deccum / radix_gen;
209 // No more digits to calculate for the non-fractional part -> break
210 if deccum == _0 { break; }
213 // Decide what sign to put in front
215 SignNeg | SignAll if neg => { f('-' as u8); }
216 SignAll => { f('+' as u8); }
220 // We built the number in reverse order, so un-reverse it here
228 * Converts a number to its string representation as a byte vector.
229 * This is meant to be a common base implementation for all numeric string
230 * conversion functions like `to_str()` or `to_str_radix()`.
233 * - `num` - The number to convert. Accepts any number that
234 * implements the numeric traits.
235 * - `radix` - Base to use. Accepts only the values 2-36. If the exponential notation
236 * is used, then this base is only used for the significand. The exponent
237 * itself always printed using a base of 10.
238 * - `negative_zero` - Whether to treat the special value `-0` as
240 * - `sign` - How to emit the sign. See `SignFormat`.
241 * - `digits` - The amount of digits to use for emitting the fractional
242 * part, if any. See `SignificantDigits`.
243 * - `exp_format` - Whether or not to use the exponential (scientific) notation.
244 * See `ExponentFormat`.
245 * - `exp_capital` - Whether or not to use a capital letter for the exponent sign, if
246 * exponential notation is desired.
249 * A tuple containing the byte vector, and a boolean flag indicating
250 * whether it represents a special value like `inf`, `-inf`, `NaN` or not.
251 * It returns a tuple because there can be ambiguity between a special value
252 * and a number representation at higher bases.
255 * - Fails if `radix` < 2 or `radix` > 36.
256 * - Fails if `radix` > 14 and `exp_format` is `ExpDec` due to conflict
257 * between digit and exponent sign `'e'`.
258 * - Fails if `radix` > 25 and `exp_format` is `ExpBin` due to conflict
259 * between digit and exponent sign `'p'`.
261 pub fn float_to_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Float+
262 Div<T,T>+Neg<T>+Rem<T,T>+Mul<T,T>>(
263 num: T, radix: uint, negative_zero: bool,
264 sign: SignFormat, digits: SignificantDigits, exp_format: ExponentFormat, exp_upper: bool
266 assert!(2 <= radix && radix <= 36);
268 ExpDec if radix >= DIGIT_E_RADIX // decimal exponent 'e'
269 => fail!("float_to_str_bytes_common: radix {} incompatible with \
270 use of 'e' as decimal exponent", radix),
271 ExpBin if radix >= DIGIT_P_RADIX // binary exponent 'p'
272 => fail!("float_to_str_bytes_common: radix {} incompatible with \
273 use of 'p' as binary exponent", radix),
277 let _0: T = Zero::zero();
278 let _1: T = One::one();
280 match num.classify() {
281 FPNaN => { return ("NaN".as_bytes().to_owned(), true); }
282 FPInfinite if num > _0 => {
284 SignAll => ("+inf".as_bytes().to_owned(), true),
285 _ => ("inf".as_bytes().to_owned(), true)
288 FPInfinite if num < _0 => {
290 SignNone => ("inf".as_bytes().to_owned(), true),
291 _ => ("-inf".as_bytes().to_owned(), true),
297 let neg = num < _0 || (negative_zero && _1 / num == Float::neg_infinity());
298 let mut buf = Vec::new();
299 let radix_gen: T = cast(radix as int).unwrap();
301 let (num, exp) = match exp_format {
302 ExpNone => (num, 0i32),
307 let (exp, exp_base) = match exp_format {
308 ExpDec => (num.abs().log10().floor(), cast::<f64, T>(10.0f64).unwrap()),
309 ExpBin => (num.abs().log2().floor(), cast::<f64, T>(2.0f64).unwrap()),
310 ExpNone => unreachable!()
313 (num / exp_base.powf(&exp), cast::<T, i32>(exp).unwrap())
318 // First emit the non-fractional part, looping at least once to make
319 // sure at least a `0` gets emitted.
320 let mut deccum = num.trunc();
322 // Calculate the absolute value of each digit instead of only
323 // doing it once for the whole number because a
324 // representable negative number doesn't necessary have an
325 // representable additive inverse of the same type
326 // (See twos complement). But we assume that for the
327 // numbers [-35 .. 0] we always have [0 .. 35].
328 let current_digit = (deccum % radix_gen).abs();
330 // Decrease the deccumulator one digit at a time
331 deccum = deccum / radix_gen;
332 deccum = deccum.trunc();
334 buf.push(char::from_digit(current_digit.to_int().unwrap() as uint, radix)
337 // No more digits to calculate for the non-fractional part -> break
338 if deccum == _0 { break; }
341 // If limited digits, calculate one digit more for rounding.
342 let (limit_digits, digit_count, exact) = match digits {
343 DigAll => (false, 0u, false),
344 DigMax(count) => (true, count+1, false),
345 DigExact(count) => (true, count+1, true)
348 // Decide what sign to put in front
350 SignNeg | SignAll if neg => {
361 // Remember start of the fractional digits.
362 // Points one beyond end of buf if none get generated,
363 // or at the '.' otherwise.
364 let start_fractional_digits = buf.len();
366 // Now emit the fractional part, if any
367 deccum = num.fract();
368 if deccum != _0 || (limit_digits && exact && digit_count > 0) {
372 // calculate new digits while
373 // - there is no limit and there are digits left
374 // - or there is a limit, it's not reached yet and
376 // - or it's a maximum, and there are still digits left
377 while (!limit_digits && deccum != _0)
378 || (limit_digits && dig < digit_count && (
380 || (!exact && deccum != _0)
383 // Shift first fractional digit into the integer part
384 deccum = deccum * radix_gen;
386 // Calculate the absolute value of each digit.
387 // See note in first loop.
388 let current_digit = deccum.trunc().abs();
390 buf.push(char::from_digit(
391 current_digit.to_int().unwrap() as uint, radix).unwrap() as u8);
393 // Decrease the deccumulator one fractional digit at a time
394 deccum = deccum.fract();
398 // If digits are limited, and that limit has been reached,
399 // cut off the one extra digit, and depending on its value
400 // round the remaining ones.
401 if limit_digits && dig == digit_count {
402 let ascii2value = |chr: u8| {
403 char::to_digit(chr as char, radix).unwrap()
405 let value2ascii = |val: uint| {
406 char::from_digit(val, radix).unwrap() as u8
409 let extra_digit = ascii2value(buf.pop().unwrap());
410 if extra_digit >= radix / 2 { // -> need to round
411 let mut i: int = buf.len() as int - 1;
413 // If reached left end of number, have to
414 // insert additional digit:
416 || *buf.get(i as uint) == '-' as u8
417 || *buf.get(i as uint) == '+' as u8 {
418 buf.insert((i + 1) as uint, value2ascii(1));
423 if *buf.get(i as uint) == '.' as u8 { i -= 1; continue; }
425 // Either increment the digit,
426 // or set to 0 if max and carry the 1.
427 let current_digit = ascii2value(*buf.get(i as uint));
428 if current_digit < (radix - 1) {
429 *buf.get_mut(i as uint) = value2ascii(current_digit+1);
432 *buf.get_mut(i as uint) = value2ascii(0);
440 // if number of digits is not exact, remove all trailing '0's up to
441 // and including the '.'
443 let buf_max_i = buf.len() - 1;
445 // index to truncate from
446 let mut i = buf_max_i;
448 // discover trailing zeros of fractional part
449 while i > start_fractional_digits && *buf.get(i) == '0' as u8 {
453 // Only attempt to truncate digits if buf has fractional digits
454 if i >= start_fractional_digits {
455 // If buf ends with '.', cut that too.
456 if *buf.get(i) == '.' as u8 { i -= 1 }
458 // only resize buf if we actually remove digits
460 buf = Vec::from_slice(buf.slice(0, i + 1));
463 } // If exact and trailing '.', just cut that
465 let max_i = buf.len() - 1;
466 if *buf.get(max_i) == '.' as u8 {
467 buf = Vec::from_slice(buf.slice(0, max_i));
474 buf.push(match exp_format {
475 ExpDec if exp_upper => 'E',
476 ExpDec if !exp_upper => 'e',
477 ExpBin if exp_upper => 'P',
478 ExpBin if !exp_upper => 'p',
482 int_to_str_bytes_common(exp, 10, sign, |c| buf.push(c));
486 (buf.move_iter().collect(), false)
490 * Converts a number to its string representation. This is a wrapper for
491 * `to_str_bytes_common()`, for details see there.
494 pub fn float_to_str_common<T:NumCast+Zero+One+Eq+Ord+NumStrConv+Float+
495 Div<T,T>+Neg<T>+Rem<T,T>+Mul<T,T>>(
496 num: T, radix: uint, negative_zero: bool,
497 sign: SignFormat, digits: SignificantDigits, exp_format: ExponentFormat, exp_capital: bool
499 let (bytes, special) = float_to_str_bytes_common(num, radix,
500 negative_zero, sign, digits, exp_format, exp_capital);
501 (str::from_utf8_owned(bytes).unwrap(), special)
504 // Some constants for from_str_bytes_common's input validation,
505 // they define minimum radix values for which the character is a valid digit.
506 static DIGIT_P_RADIX: uint = ('p' as uint) - ('a' as uint) + 11u;
507 static DIGIT_I_RADIX: uint = ('i' as uint) - ('a' as uint) + 11u;
508 static DIGIT_E_RADIX: uint = ('e' as uint) - ('a' as uint) + 11u;
511 * Parses a byte slice as a number. This is meant to
512 * be a common base implementation for all numeric string conversion
513 * functions like `from_str()` or `from_str_radix()`.
516 * - `buf` - The byte slice to parse.
517 * - `radix` - Which base to parse the number as. Accepts 2-36.
518 * - `negative` - Whether to accept negative numbers.
519 * - `fractional` - Whether to accept numbers with fractional parts.
520 * - `special` - Whether to accept special values like `inf`
521 * and `NaN`. Can conflict with `radix`, see Failure.
522 * - `exponent` - Which exponent format to accept. Options are:
523 * - `ExpNone`: No Exponent, accepts just plain numbers like `42` or
525 * - `ExpDec`: Accepts numbers with a decimal exponent like `42e5` or
526 * `8.2E-2`. The exponent string itself is always base 10.
527 * Can conflict with `radix`, see Failure.
528 * - `ExpBin`: Accepts numbers with a binary exponent like `42P-8` or
529 * `FFp128`. The exponent string itself is always base 10.
530 * Can conflict with `radix`, see Failure.
531 * - `empty_zero` - Whether to accept an empty `buf` as a 0 or not.
532 * - `ignore_underscores` - Whether all underscores within the string should
536 * Returns `Some(n)` if `buf` parses to a number n without overflowing, and
537 * `None` otherwise, depending on the constraints set by the remaining
541 * - Fails if `radix` < 2 or `radix` > 36.
542 * - Fails if `radix` > 14 and `exponent` is `ExpDec` due to conflict
543 * between digit and exponent sign `'e'`.
544 * - Fails if `radix` > 25 and `exponent` is `ExpBin` due to conflict
545 * between digit and exponent sign `'p'`.
546 * - Fails if `radix` > 18 and `special == true` due to conflict
547 * between digit and lowest first character in `inf` and `NaN`, the `'i'`.
549 pub fn from_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Div<T,T>+
550 Mul<T,T>+Sub<T,T>+Neg<T>+Add<T,T>+
552 buf: &[u8], radix: uint, negative: bool, fractional: bool,
553 special: bool, exponent: ExponentFormat, empty_zero: bool,
554 ignore_underscores: bool
557 ExpDec if radix >= DIGIT_E_RADIX // decimal exponent 'e'
558 => fail!("from_str_bytes_common: radix {} incompatible with \
559 use of 'e' as decimal exponent", radix),
560 ExpBin if radix >= DIGIT_P_RADIX // binary exponent 'p'
561 => fail!("from_str_bytes_common: radix {} incompatible with \
562 use of 'p' as binary exponent", radix),
563 _ if special && radix >= DIGIT_I_RADIX // first digit of 'inf'
564 => fail!("from_str_bytes_common: radix {} incompatible with \
565 special values 'inf' and 'NaN'", radix),
566 _ if (radix as int) < 2
567 => fail!("from_str_bytes_common: radix {} to low, \
568 must lie in the range [2, 36]", radix),
569 _ if (radix as int) > 36
570 => fail!("from_str_bytes_common: radix {} to high, \
571 must lie in the range [2, 36]", radix),
575 let _0: T = Zero::zero();
576 let _1: T = One::one();
577 let radix_gen: T = cast(radix as int).unwrap();
590 if buf == INF_BUF || buf == POS_INF_BUF {
591 return NumStrConv::inf();
592 } else if buf == NEG_INF_BUF {
594 return NumStrConv::neg_inf();
598 } else if buf == NAN_BUF {
599 return NumStrConv::nan();
603 let (start, accum_positive) = match buf[0] as char {
604 '-' if !negative => return None,
610 // Initialize accumulator with signed zero for floating point parsing to
612 let mut accum = if accum_positive { _0.clone() } else { -_1 * _0};
613 let mut last_accum = accum.clone(); // Necessary to detect overflow
615 let mut exp_found = false;
617 // Parse integer part of number
619 let c = buf[i] as char;
621 match char::to_digit(c, radix) {
623 // shift accum one digit left
624 accum = accum * radix_gen.clone();
626 // add/subtract current digit depending on sign
628 accum = accum + cast(digit as int).unwrap();
630 accum = accum - cast(digit as int).unwrap();
633 // Detect overflow by comparing to last value, except
634 // if we've not seen any non-zero digits.
635 if last_accum != _0 {
636 if accum_positive && accum <= last_accum { return NumStrConv::inf(); }
637 if !accum_positive && accum >= last_accum { return NumStrConv::neg_inf(); }
639 // Detect overflow by reversing the shift-and-add proccess
641 (last_accum != ((accum - cast(digit as int).unwrap())/radix_gen.clone())) {
642 return NumStrConv::inf();
644 if !accum_positive &&
645 (last_accum != ((accum + cast(digit as int).unwrap())/radix_gen.clone())) {
646 return NumStrConv::neg_inf();
649 last_accum = accum.clone();
652 '_' if ignore_underscores => {}
653 'e' | 'E' | 'p' | 'P' => {
655 break; // start of exponent
657 '.' if fractional => {
658 i += 1u; // skip the '.'
659 break; // start of fractional part
661 _ => return None // invalid number
668 // Parse fractional part of number
669 // Skip if already reached start of exponent
671 let mut power = _1.clone();
674 let c = buf[i] as char;
676 match char::to_digit(c, radix) {
678 // Decrease power one order of magnitude
679 power = power / radix_gen;
681 let digit_t: T = cast(digit).unwrap();
683 // add/subtract current digit depending on sign
685 accum = accum + digit_t * power;
687 accum = accum - digit_t * power;
690 // Detect overflow by comparing to last value
691 if accum_positive && accum < last_accum { return NumStrConv::inf(); }
692 if !accum_positive && accum > last_accum { return NumStrConv::neg_inf(); }
693 last_accum = accum.clone();
696 '_' if ignore_underscores => {}
697 'e' | 'E' | 'p' | 'P' => {
699 break; // start of exponent
701 _ => return None // invalid number
709 // Special case: buf not empty, but does not contain any digit in front
710 // of the exponent sign -> number is empty string
719 let mut multiplier = _1.clone();
722 let c = buf[i] as char;
723 let base: T = match (c, exponent) {
724 // c is never _ so don't need to handle specially
725 ('e', ExpDec) | ('E', ExpDec) => cast(10u).unwrap(),
726 ('p', ExpBin) | ('P', ExpBin) => cast(2u).unwrap(),
727 _ => return None // char doesn't fit given exponent format
730 // parse remaining bytes as decimal integer,
731 // skipping the exponent char
732 let exp: Option<int> = from_str_bytes_common(
733 buf.slice(i+1, len), 10, true, false, false, ExpNone, false,
738 multiplier = if exp_pow < 0 {
739 _1 / num::pow(base, (-exp_pow.to_int().unwrap()) as uint)
741 num::pow(base, exp_pow.to_int().unwrap() as uint)
744 None => return None // invalid exponent -> invalid number
748 Some(accum * multiplier)
752 * Parses a string as a number. This is a wrapper for
753 * `from_str_bytes_common()`, for details see there.
756 pub fn from_str_common<T:NumCast+Zero+One+Eq+Ord+Div<T,T>+Mul<T,T>+
757 Sub<T,T>+Neg<T>+Add<T,T>+NumStrConv+Clone>(
758 buf: &str, radix: uint, negative: bool, fractional: bool,
759 special: bool, exponent: ExponentFormat, empty_zero: bool,
760 ignore_underscores: bool
762 from_str_bytes_common(buf.as_bytes(), radix, negative,
763 fractional, special, exponent, empty_zero,
773 fn from_str_ignore_underscores() {
774 let s : Option<u8> = from_str_common("__1__", 2, false, false, false,
775 ExpNone, false, true);
776 assert_eq!(s, Some(1u8));
778 let n : Option<u8> = from_str_common("__1__", 2, false, false, false,
779 ExpNone, false, false);
782 let f : Option<f32> = from_str_common("_1_._5_e_1_", 10, false, true, false,
783 ExpDec, false, true);
784 assert_eq!(f, Some(1.5e1f32));
788 fn from_str_issue5770() {
789 // try to parse 0b1_1111_1111 = 511 as a u8. Caused problems
790 // since 255*2+1 == 255 (mod 256) so the overflow wasn't
792 let n : Option<u8> = from_str_common("111111111", 2, false, false, false,
793 ExpNone, false, false);
798 fn from_str_issue7588() {
799 let u : Option<u8> = from_str_common("1000", 10, false, false, false,
800 ExpNone, false, false);
802 let s : Option<i16> = from_str_common("80000", 10, false, false, false,
803 ExpNone, false, false);
805 let f : Option<f32> = from_str_common(
806 "10000000000000000000000000000000000000000", 10, false, false, false,
807 ExpNone, false, false);
808 assert_eq!(f, NumStrConv::inf())
809 let fe : Option<f32> = from_str_common("1e40", 10, false, false, false,
810 ExpDec, false, false);
811 assert_eq!(fe, NumStrConv::inf())
820 use super::test::Bencher;
821 use rand::{XorShiftRng, Rng};
825 fn to_str_bin(b: &mut Bencher) {
826 let mut rng = XorShiftRng::new().unwrap();
827 b.iter(|| { rng.gen::<uint>().to_str_radix(2); })
831 fn to_str_oct(b: &mut Bencher) {
832 let mut rng = XorShiftRng::new().unwrap();
833 b.iter(|| { rng.gen::<uint>().to_str_radix(8); })
837 fn to_str_dec(b: &mut Bencher) {
838 let mut rng = XorShiftRng::new().unwrap();
839 b.iter(|| { rng.gen::<uint>().to_str_radix(10); })
843 fn to_str_hex(b: &mut Bencher) {
844 let mut rng = XorShiftRng::new().unwrap();
845 b.iter(|| { rng.gen::<uint>().to_str_radix(16); })
849 fn to_str_base_36(b: &mut Bencher) {
850 let mut rng = XorShiftRng::new().unwrap();
851 b.iter(|| { rng.gen::<uint>().to_str_radix(36); })
856 use super::test::Bencher;
857 use rand::{XorShiftRng, Rng};
861 fn to_str_bin(b: &mut Bencher) {
862 let mut rng = XorShiftRng::new().unwrap();
863 b.iter(|| { rng.gen::<int>().to_str_radix(2); })
867 fn to_str_oct(b: &mut Bencher) {
868 let mut rng = XorShiftRng::new().unwrap();
869 b.iter(|| { rng.gen::<int>().to_str_radix(8); })
873 fn to_str_dec(b: &mut Bencher) {
874 let mut rng = XorShiftRng::new().unwrap();
875 b.iter(|| { rng.gen::<int>().to_str_radix(10); })
879 fn to_str_hex(b: &mut Bencher) {
880 let mut rng = XorShiftRng::new().unwrap();
881 b.iter(|| { rng.gen::<int>().to_str_radix(16); })
885 fn to_str_base_36(b: &mut Bencher) {
886 let mut rng = XorShiftRng::new().unwrap();
887 b.iter(|| { rng.gen::<int>().to_str_radix(36); })
892 use super::test::Bencher;
893 use rand::{XorShiftRng, Rng};
897 fn float_to_str(b: &mut Bencher) {
898 let mut rng = XorShiftRng::new().unwrap();
899 b.iter(|| { f64::to_str(rng.gen()); })