diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index 3c5de1b703b7e..79623402c4d30 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -378,7 +378,7 @@ impl num::Round for f32 { #[inline(always)] pub pure fn to_str(num: f32) -> ~str { let (r, _) = strconv::to_str_common( - &num, 10u, true, true, strconv::SignNeg, strconv::DigAll); + &num, 10u, true, strconv::SignNeg, strconv::DigAll); r } @@ -392,7 +392,7 @@ pub pure fn to_str(num: f32) -> ~str { #[inline(always)] pub pure fn to_str_hex(num: f32) -> ~str { let (r, _) = strconv::to_str_common( - &num, 16u, true, true, strconv::SignNeg, strconv::DigAll); + &num, 16u, true, strconv::SignNeg, strconv::DigAll); r } @@ -413,7 +413,7 @@ pub pure fn to_str_hex(num: f32) -> ~str { #[inline(always)] pub pure fn to_str_radix(num: f32, rdx: uint) -> ~str { let (r, special) = strconv::to_str_common( - &num, rdx, true, true, strconv::SignNeg, strconv::DigAll); + &num, rdx, true, strconv::SignNeg, strconv::DigAll); if special { fail!(~"number has a special value, \ try to_str_radix_special() if those are expected") } r @@ -430,7 +430,7 @@ pub pure fn to_str_radix(num: f32, rdx: uint) -> ~str { */ #[inline(always)] pub pure fn to_str_radix_special(num: f32, rdx: uint) -> (~str, bool) { - strconv::to_str_common(&num, rdx, true, true, + strconv::to_str_common(&num, rdx, true, strconv::SignNeg, strconv::DigAll) } @@ -446,7 +446,7 @@ pub pure fn to_str_radix_special(num: f32, rdx: uint) -> (~str, bool) { #[inline(always)] pub pure fn to_str_exact(num: f32, dig: uint) -> ~str { let (r, _) = strconv::to_str_common( - &num, 10u, true, true, strconv::SignNeg, strconv::DigExact(dig)); + &num, 10u, true, strconv::SignNeg, strconv::DigExact(dig)); r } @@ -462,7 +462,7 @@ pub pure fn to_str_exact(num: f32, dig: uint) -> ~str { #[inline(always)] pub pure fn to_str_digits(num: f32, dig: uint) -> ~str { let (r, _) = strconv::to_str_common( - &num, 10u, true, true, strconv::SignNeg, strconv::DigMax(dig)); + &num, 10u, true, strconv::SignNeg, strconv::DigMax(dig)); r } diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index 0bd6e0e9d7718..51ee8eeba919d 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -403,7 +403,7 @@ impl num::Round for f64 { #[inline(always)] pub pure fn to_str(num: f64) -> ~str { let (r, _) = strconv::to_str_common( - &num, 10u, true, true, strconv::SignNeg, strconv::DigAll); + &num, 10u, true, strconv::SignNeg, strconv::DigAll); r } @@ -417,7 +417,7 @@ pub pure fn to_str(num: f64) -> ~str { #[inline(always)] pub pure fn to_str_hex(num: f64) -> ~str { let (r, _) = strconv::to_str_common( - &num, 16u, true, true, strconv::SignNeg, strconv::DigAll); + &num, 16u, true, strconv::SignNeg, strconv::DigAll); r } @@ -438,7 +438,7 @@ pub pure fn to_str_hex(num: f64) -> ~str { #[inline(always)] pub pure fn to_str_radix(num: f64, rdx: uint) -> ~str { let (r, special) = strconv::to_str_common( - &num, rdx, true, true, strconv::SignNeg, strconv::DigAll); + &num, rdx, true, strconv::SignNeg, strconv::DigAll); if special { fail!(~"number has a special value, \ try to_str_radix_special() if those are expected") } r @@ -455,7 +455,7 @@ pub pure fn to_str_radix(num: f64, rdx: uint) -> ~str { */ #[inline(always)] pub pure fn to_str_radix_special(num: f64, rdx: uint) -> (~str, bool) { - strconv::to_str_common(&num, rdx, true, true, + strconv::to_str_common(&num, rdx, true, strconv::SignNeg, strconv::DigAll) } @@ -471,7 +471,7 @@ pub pure fn to_str_radix_special(num: f64, rdx: uint) -> (~str, bool) { #[inline(always)] pub pure fn to_str_exact(num: f64, dig: uint) -> ~str { let (r, _) = strconv::to_str_common( - &num, 10u, true, true, strconv::SignNeg, strconv::DigExact(dig)); + &num, 10u, true, strconv::SignNeg, strconv::DigExact(dig)); r } @@ -487,7 +487,7 @@ pub pure fn to_str_exact(num: f64, dig: uint) -> ~str { #[inline(always)] pub pure fn to_str_digits(num: f64, dig: uint) -> ~str { let (r, _) = strconv::to_str_common( - &num, 10u, true, true, strconv::SignNeg, strconv::DigMax(dig)); + &num, 10u, true, strconv::SignNeg, strconv::DigMax(dig)); r } diff --git a/src/libcore/num/float.rs b/src/libcore/num/float.rs index 87879f6d7ad5d..31bd08b12418e 100644 --- a/src/libcore/num/float.rs +++ b/src/libcore/num/float.rs @@ -109,7 +109,7 @@ pub mod consts { #[inline(always)] pub pure fn to_str(num: float) -> ~str { let (r, _) = strconv::to_str_common( - &num, 10u, true, true, strconv::SignNeg, strconv::DigAll); + &num, 10u, true, strconv::SignNeg, strconv::DigAll); r } @@ -123,7 +123,7 @@ pub pure fn to_str(num: float) -> ~str { #[inline(always)] pub pure fn to_str_hex(num: float) -> ~str { let (r, _) = strconv::to_str_common( - &num, 16u, true, true, strconv::SignNeg, strconv::DigAll); + &num, 16u, true, strconv::SignNeg, strconv::DigAll); r } @@ -144,7 +144,7 @@ pub pure fn to_str_hex(num: float) -> ~str { #[inline(always)] pub pure fn to_str_radix(num: float, radix: uint) -> ~str { let (r, special) = strconv::to_str_common( - &num, radix, true, true, strconv::SignNeg, strconv::DigAll); + &num, radix, true, strconv::SignNeg, strconv::DigAll); if special { fail!(~"number has a special value, \ try to_str_radix_special() if those are expected") } r @@ -161,7 +161,7 @@ pub pure fn to_str_radix(num: float, radix: uint) -> ~str { */ #[inline(always)] pub pure fn to_str_radix_special(num: float, radix: uint) -> (~str, bool) { - strconv::to_str_common(&num, radix, true, true, + strconv::to_str_common(&num, radix, true, strconv::SignNeg, strconv::DigAll) } @@ -177,7 +177,7 @@ pub pure fn to_str_radix_special(num: float, radix: uint) -> (~str, bool) { #[inline(always)] pub pure fn to_str_exact(num: float, digits: uint) -> ~str { let (r, _) = strconv::to_str_common( - &num, 10u, true, true, strconv::SignNeg, strconv::DigExact(digits)); + &num, 10u, true, strconv::SignNeg, strconv::DigExact(digits)); r } @@ -199,7 +199,7 @@ pub fn test_to_str_exact_do_decimal() { #[inline(always)] pub pure fn to_str_digits(num: float, digits: uint) -> ~str { let (r, _) = strconv::to_str_common( - &num, 10u, true, true, strconv::SignNeg, strconv::DigMax(digits)); + &num, 10u, true, strconv::SignNeg, strconv::DigMax(digits)); r } diff --git a/src/libcore/num/int-template.rs b/src/libcore/num/int-template.rs index df9756423ef7f..c0624608a15f5 100644 --- a/src/libcore/num/int-template.rs +++ b/src/libcore/num/int-template.rs @@ -256,7 +256,7 @@ impl FromStrRadix for T { /// Convert to a string as a byte slice in a given base. #[inline(always)] pub pure fn to_str_bytes(n: T, radix: uint, f: fn(v: &[u8]) -> U) -> U { - let (buf, _) = strconv::to_str_bytes_common(&n, radix, false, false, + let (buf, _) = strconv::to_str_bytes_common(&n, radix, false, strconv::SignNeg, strconv::DigAll); f(buf) } @@ -264,7 +264,7 @@ pub pure fn to_str_bytes(n: T, radix: uint, f: fn(v: &[u8]) -> U) -> U { /// Convert to a string in base 10. #[inline(always)] pub pure fn to_str(num: T) -> ~str { - let (buf, _) = strconv::to_str_common(&num, 10u, false, false, + let (buf, _) = strconv::to_str_common(&num, 10u, false, strconv::SignNeg, strconv::DigAll); buf } @@ -272,7 +272,7 @@ pub pure fn to_str(num: T) -> ~str { /// Convert to a string in a given base. #[inline(always)] pub pure fn to_str_radix(num: T, radix: uint) -> ~str { - let (buf, _) = strconv::to_str_common(&num, radix, false, false, + let (buf, _) = strconv::to_str_common(&num, radix, false, strconv::SignNeg, strconv::DigAll); buf } diff --git a/src/libcore/num/strconv.rs b/src/libcore/num/strconv.rs index d5a76ef89d56e..7d6b62542621b 100644 --- a/src/libcore/num/strconv.rs +++ b/src/libcore/num/strconv.rs @@ -16,9 +16,9 @@ use str; use kinds::Copy; use vec; use num::{NumCast, Zero, One, cast, pow_with_uint}; -use num::{Round, RoundToZero, +/*use num::{Round, RoundToZero, is_NaN, is_infinity, is_neg_infinity, is_neg_zero, - infinity, neg_infinity, NaN}; + infinity, neg_infinity, NaN};*/ use float; use f32; use f64; @@ -42,59 +42,61 @@ pub enum SignFormat { } pub trait NumStrConv { - static fn has_NaN() -> bool; - static fn has_inf() -> bool; - static fn has_neg_inf() -> bool; - static fn has_neg_zero() -> bool; + static pure fn has_NaN() -> bool; + static pure fn has_inf() -> bool; + static pure fn has_neg_inf() -> bool; + static pure fn has_neg_zero() -> bool; - static fn NaN() -> Option; - static fn inf() -> Option; - static fn neg_inf() -> Option; - static fn neg_zero() -> Option; + static pure fn NaN() -> Option; + static pure fn inf() -> Option; + static pure fn neg_inf() -> Option; + static pure fn neg_zero() -> Option; - fn is_NaN(&self) -> bool; - fn is_inf(&self) -> bool; - fn is_neg_inf(&self) -> bool; - fn is_neg_zero(&self) -> bool; + pure fn is_NaN(&self) -> bool; + pure fn is_inf(&self) -> bool; + pure fn is_neg_inf(&self) -> bool; + pure fn is_neg_zero(&self) -> bool; - fn round_to_zero(&self) -> Self; - fn split_at_dot(&self) -> (Self, Self); + pure fn round_to_zero(&self) -> Self; + pure fn fractional_part(&self) -> Self; } macro_rules! impl_NumStrConv_Floating ( ($t:ty) => ( impl NumStrConv for $t { - static fn has_NaN() -> bool { true } - static fn has_inf() -> bool { true } - static fn has_neg_inf() -> bool { true } - static fn has_neg_zero() -> bool { true } - - static fn NaN() -> Option<$t> { Some( 0.0 / 0.0) } - static fn inf() -> Option<$t> { Some( 1.0 / 0.0) } - static fn neg_inf() -> Option<$t> { Some(-1.0 / 0.0) } - static fn neg_zero() -> Option<$t> { Some(-0.0 ) } - - fn is_NaN(&self) -> bool { *self != *self } - fn is_inf(&self) -> bool { + static pure fn has_NaN() -> bool { true } + static pure fn has_inf() -> bool { true } + static pure fn has_neg_inf() -> bool { true } + static pure fn has_neg_zero() -> bool { true } + + static pure fn NaN() -> Option<$t> { Some( 0.0 / 0.0) } + static pure fn inf() -> Option<$t> { Some( 1.0 / 0.0) } + static pure fn neg_inf() -> Option<$t> { Some(-1.0 / 0.0) } + static pure fn neg_zero() -> Option<$t> { Some(-0.0 ) } + + pure fn is_NaN(&self) -> bool { *self != *self } + + pure fn is_inf(&self) -> bool { *self == NumStrConv::inf().unwrap() } - fn is_neg_inf(&self) -> bool { + + pure fn is_neg_inf(&self) -> bool { *self == NumStrConv::neg_inf().unwrap() } - fn is_neg_zero(&self) -> bool { + + pure fn is_neg_zero(&self) -> bool { *self == 0.0 && (1.0 / *self).is_neg_inf() } - fn round_to_zero(&self) -> $t { + pure fn round_to_zero(&self) -> $t { ( if *self < 0.0 { f64::ceil(*self as f64) } else { f64::floor(*self as f64) } ) as $t } - fn split_at_dot(&self) -> ($t, $t) { - let r = self.round_to_zero(); - (r, *self - r) + pure fn fractional_part(&self) -> $t { + *self - self.round_to_zero() } } ) @@ -103,24 +105,23 @@ macro_rules! impl_NumStrConv_Floating ( macro_rules! impl_NumStrConv_Integer ( ($t:ty) => ( impl NumStrConv for $t { - static fn has_NaN() -> bool { false } - static fn has_inf() -> bool { false } - static fn has_neg_inf() -> bool { false } - static fn has_neg_zero() -> bool { false } - - static fn NaN() -> Option<$t> { None } - static fn inf() -> Option<$t> { None } - static fn neg_inf() -> Option<$t> { None } - static fn neg_zero() -> Option<$t> { None } - - fn is_NaN(&self) -> bool { false } - fn is_inf(&self) -> bool { false } - fn is_neg_inf(&self) -> bool { false } - fn is_neg_zero(&self) -> bool { false } - - fn round_to_zero(&self) -> $t { *self } - - fn split_at_dot(&self) -> ($t, $t) { (*self, 0) } + static pure fn has_NaN() -> bool { false } + static pure fn has_inf() -> bool { false } + static pure fn has_neg_inf() -> bool { false } + static pure fn has_neg_zero() -> bool { false } + + static pure fn NaN() -> Option<$t> { None } + static pure fn inf() -> Option<$t> { None } + static pure fn neg_inf() -> Option<$t> { None } + static pure fn neg_zero() -> Option<$t> { None } + + pure fn is_NaN(&self) -> bool { false } + pure fn is_inf(&self) -> bool { false } + pure fn is_neg_inf(&self) -> bool { false } + pure fn is_neg_zero(&self) -> bool { false } + + pure fn round_to_zero(&self) -> $t { *self } + pure fn fractional_part(&self) -> $t { 0 } } ) ) @@ -142,6 +143,8 @@ impl_NumStrConv_Integer!(u16) impl_NumStrConv_Integer!(u32) impl_NumStrConv_Integer!(u64) +// NOTE: inline the methods + /** * Converts a number to its string representation as a byte vector. * This is meant to be a common base implementation for all numeric string @@ -151,10 +154,6 @@ impl_NumStrConv_Integer!(u64) * - `num` - The number to convert. Accepts any number that * implements the numeric traits. * - `radix` - Base to use. Accepts only the values 2-36. - * - `special` - Whether to attempt to compare to special values like - * `inf` or `NaN`. Also needed to detect negative 0. - * Can fail if it doesn't match `num`s type - * (see safety note). * - `negative_zero` - Whether to treat the special value `-0` as * `-0` or as `+0`. * - `sign` - How to emit the sign. Options are: @@ -176,19 +175,10 @@ impl_NumStrConv_Integer!(u64) * * # Failure * - Fails if `radix` < 2 or `radix` > 36. - * - Fails on wrong value for `special` (see safety note). - * - * # Safety note - * The function detects the special values `inf`, `-inf` and `NaN` by - * dynamically comparing `num` to `1 / 0`, `-1 / 0` and `0 / 0` - * (each of type T) if `special` is `true`. This will fail on integer types - * with a 'divide by zero'. Likewise, it will fail if `num` **is** one of - * those special values, and `special` is `false`, because then the - * algorithm just does normal calculations on them. */ -pub pure fn to_str_bytes_common+ +pub pure fn to_str_bytes_common+ Neg+Modulo+Mul>( - num: &T, radix: uint, special: bool, negative_zero: bool, + num: &T, radix: uint, negative_zero: bool, sign: SignFormat, digits: SignificantDigits) -> (~[u8], bool) { if radix as int < 2 { fail!(fmt!("to_str_bytes_common: radix %? to low, \ @@ -201,24 +191,25 @@ pub pure fn to_str_bytes_common+ let _0: T = Zero::zero(); let _1: T = One::one(); - if special { - if is_NaN(num) { - return (str::to_bytes("NaN"), true); - } else if is_infinity(num){ - return match sign { - SignAll => (str::to_bytes("+inf"), true), - _ => (str::to_bytes("inf"), true) - } - } else if is_neg_infinity(num) { - return match sign { - SignNone => (str::to_bytes("inf"), true), - _ => (str::to_bytes("-inf"), true), - } + if NumStrConv::has_NaN::() && num.is_NaN() { + return (str::to_bytes("NaN"), true); + } + if NumStrConv::has_inf::() && num.is_inf(){ + return match sign { + SignAll => (str::to_bytes("+inf"), true), + _ => (str::to_bytes("inf"), true) + } + } + if NumStrConv::has_neg_inf::() && num.is_neg_inf() { + return match sign { + SignNone => (str::to_bytes("inf"), true), + _ => (str::to_bytes("-inf"), true), } } - let neg = *num < _0 || (negative_zero && *num == _0 - && special && is_neg_zero(num)); + let neg = *num < _0 || (negative_zero + && NumStrConv::has_neg_zero::() + && num.is_neg_zero()); let mut buf: ~[u8] = ~[]; let radix_gen: T = cast(radix as int); @@ -226,7 +217,7 @@ pub pure fn to_str_bytes_common+ // First emit the non-fractional part, looping at least once to make // sure at least a `0` gets emitted. - deccum = num.round(RoundToZero); + deccum = num.round_to_zero(); loop { // Calculate the absolute value of each digit instead of only // doing it once for the whole number because a @@ -243,7 +234,7 @@ pub pure fn to_str_bytes_common+ // Decrease the deccumulator one digit at a time deccum /= radix_gen; - deccum = deccum.round(RoundToZero); + deccum = deccum.round_to_zero(); unsafe { // FIXME: Pureness workaround (#4568) buf.push(char::from_digit(current_digit.to_int() as uint, radix) @@ -286,7 +277,7 @@ pub pure fn to_str_bytes_common+ let start_fractional_digits = buf.len(); // Now emit the fractional part, if any - deccum = num.fract(); + deccum = num.fractional_part(); if deccum != _0 || (limit_digits && exact && digit_count > 0) { unsafe { // FIXME: Pureness workaround (#4568) buf.push('.' as u8); @@ -309,7 +300,7 @@ pub pure fn to_str_bytes_common+ // Calculate the absolute value of each digit. // See note in first loop. - let current_digit_signed = deccum.round(RoundToZero); + let current_digit_signed = deccum.round_to_zero(); let current_digit = if current_digit_signed < _0 { -current_digit_signed } else { @@ -322,7 +313,7 @@ pub pure fn to_str_bytes_common+ } // Decrease the deccumulator one fractional digit at a time - deccum = deccum.fract(); + deccum = deccum.fractional_part(); dig += 1u; } @@ -409,11 +400,11 @@ pub pure fn to_str_bytes_common+ * `to_str_bytes_common()`, for details see there. */ #[inline(always)] -pub pure fn to_str_common+Neg +pub pure fn to_str_common+Neg +Modulo+Mul>( - num: &T, radix: uint, special: bool, negative_zero: bool, + num: &T, radix: uint, negative_zero: bool, sign: SignFormat, digits: SignificantDigits) -> (~str, bool) { - let (bytes, special) = to_str_bytes_common(num, radix, special, + let (bytes, special) = to_str_bytes_common(num, radix, negative_zero, sign, digits); (str::from_bytes(bytes), special) } @@ -466,7 +457,7 @@ priv const DIGIT_E_RADIX: uint = ('e' as uint) - ('a' as uint) + 11u; * formated like `FF_AE_FF_FF`. */ pub pure fn from_str_bytes_common+ - Mul+Sub+Neg+Add>( + Mul+Sub+Neg+Add+NumStrConv>( buf: &[u8], radix: uint, negative: bool, fractional: bool, special: bool, exponent: ExponentFormat, empty_zero: bool ) -> Option { @@ -503,17 +494,18 @@ pub pure fn from_str_bytes_common+ } } + // XXX: Bytevector constant from str if special { if buf == str::to_bytes("inf") || buf == str::to_bytes("+inf") { - return Some(infinity()); + return NumStrConv::inf(); } else if buf == str::to_bytes("-inf") { if negative { - return Some(neg_infinity()); + return NumStrConv::neg_inf(); } else { return None; } } else if buf == str::to_bytes("NaN") { - return Some(NaN()); + return NumStrConv::NaN(); } } @@ -654,7 +646,7 @@ pub pure fn from_str_bytes_common+ */ #[inline(always)] pub pure fn from_str_common+Mul+ - Sub+Neg+Add>( + Sub+Neg+Add+NumStrConv>( buf: &str, radix: uint, negative: bool, fractional: bool, special: bool, exponent: ExponentFormat, empty_zero: bool ) -> Option { diff --git a/src/libcore/num/uint-template.rs b/src/libcore/num/uint-template.rs index 9829bf9d9e086..c5743b40a89e4 100644 --- a/src/libcore/num/uint-template.rs +++ b/src/libcore/num/uint-template.rs @@ -220,7 +220,7 @@ impl FromStrRadix for T { /// Convert to a string as a byte slice in a given base. #[inline(always)] pub pure fn to_str_bytes(n: T, radix: uint, f: fn(v: &[u8]) -> U) -> U { - let (buf, _) = strconv::to_str_bytes_common(&n, radix, false, false, + let (buf, _) = strconv::to_str_bytes_common(&n, radix, false, strconv::SignNeg, strconv::DigAll); f(buf) } @@ -228,7 +228,7 @@ pub pure fn to_str_bytes(n: T, radix: uint, f: fn(v: &[u8]) -> U) -> U { /// Convert to a string in base 10. #[inline(always)] pub pure fn to_str(num: T) -> ~str { - let (buf, _) = strconv::to_str_common(&num, 10u, false, false, + let (buf, _) = strconv::to_str_common(&num, 10u, false, strconv::SignNeg, strconv::DigAll); buf } @@ -236,7 +236,7 @@ pub pure fn to_str(num: T) -> ~str { /// Convert to a string in a given base. #[inline(always)] pub pure fn to_str_radix(num: T, radix: uint) -> ~str { - let (buf, _) = strconv::to_str_common(&num, radix, false, false, + let (buf, _) = strconv::to_str_common(&num, radix, false, strconv::SignNeg, strconv::DigAll); buf }