diff --git a/src/libcore/extfmt.rs b/src/libcore/extfmt.rs index 4627c048015..ed0625624d8 100644 --- a/src/libcore/extfmt.rs +++ b/src/libcore/extfmt.rs @@ -563,7 +563,7 @@ pub mod rt { pub pure fn conv_float(cv: Conv, f: float) -> ~str { let (to_str, digits) = match cv.precision { CountIs(c) => (float::to_str_exact, c as uint), - CountImplied => (float::to_str, 6u) + CountImplied => (float::to_str_digits, 6u) }; let mut s = unsafe { to_str(f, digits) }; if 0.0 <= f { diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index 43b68c5fc4f..a33a46192fd 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -18,6 +18,9 @@ use cmath; use cmp; use libc::{c_float, c_int}; use num; +use option::Option; +use from_str; +use to_str; pub use cmath::c_float_targ_consts::*; @@ -333,6 +336,197 @@ impl f32: num::Round { } } +/** + * Section: String Conversions + */ + +/** + * Converts a float to a string + * + * # Arguments + * + * * num - The float value + */ +#[inline(always)] +pub pure fn to_str(num: f32) -> ~str { + let (r, _) = num::to_str_common( + &num, 10u, true, true, num::SignNeg, num::DigAll); + r +} + +/** + * Converts a float to a string in hexadecimal format + * + * # Arguments + * + * * num - The float value + */ +#[inline(always)] +pub pure fn to_str_hex(num: f32) -> ~str { + let (r, _) = num::to_str_common( + &num, 16u, true, true, num::SignNeg, num::DigAll); + r +} + +/** + * Converts a float to a string in a given radix + * + * # Arguments + * + * * num - The float value + * * radix - The base to use + */ +#[inline(always)] +pub pure fn to_str_radix(num: f32, rdx: uint) -> ~str { + let (r, _) = num::to_str_common( + &num, rdx, true, true, num::SignNeg, num::DigAll); + r +} + +/** + * Converts a float to a string with exactly the number of + * provided significant digits + * + * # Arguments + * + * * num - The float value + * * digits - The number of significant digits + */ +#[inline(always)] +pub pure fn to_str_exact(num: f32, dig: uint) -> ~str { + let (r, _) = num::to_str_common( + &num, 10u, true, true, num::SignNeg, num::DigExact(dig)); + r +} + +/** + * Converts a float to a string with a maximum number of + * significant digits + * + * # Arguments + * + * * num - The float value + * * digits - The number of significant digits + */ +#[inline(always)] +pub pure fn to_str_digits(num: f32, dig: uint) -> ~str { + let (r, _) = num::to_str_common( + &num, 10u, true, true, num::SignNeg, num::DigMax(dig)); + r +} + +impl f32: to_str::ToStr { + #[inline(always)] + pure fn to_str() -> ~str { to_str_digits(self, 8) } +} + +impl f32: num::ToStrRadix { + #[inline(always)] + pure fn to_str_radix(&self, rdx: uint) -> ~str { + to_str_radix(*self, rdx) + } +} + +/** + * Convert a string in base 10 to a float. + * Accepts a optional decimal exponent. + * + * This function accepts strings such as + * + * * '3.14' + * * '+3.14', equivalent to '3.14' + * * '-3.14' + * * '2.5E10', or equivalently, '2.5e10' + * * '2.5E-10' + * * '.' (understood as 0) + * * '5.' + * * '.5', or, equivalently, '0.5' + * * '+inf', 'inf', '-inf', 'NaN' + * + * Leading and trailing whitespace represent an error. + * + * # Arguments + * + * * num - A string + * + * # Return value + * + * `none` if the string did not represent a valid number. Otherwise, + * `Some(n)` where `n` is the floating-point number represented by `num`. + */ +#[inline(always)] +pub pure fn from_str(num: &str) -> Option { + num::from_str_common(num, 10u, true, true, true, num::ExpDec, false) +} + +/** + * Convert a string in base 16 to a float. + * Accepts a optional binary exponent. + * + * This function accepts strings such as + * + * * 'a4.fe' + * * '+a4.fe', equivalent to 'a4.fe' + * * '-a4.fe' + * * '2b.aP128', or equivalently, '2b.ap128' + * * '2b.aP-128' + * * '.' (understood as 0) + * * 'c.' + * * '.c', or, equivalently, '0.c' + * * '+inf', 'inf', '-inf', 'NaN' + * + * Leading and trailing whitespace represent an error. + * + * # Arguments + * + * * num - A string + * + * # Return value + * + * `none` if the string did not represent a valid number. Otherwise, + * `Some(n)` where `n` is the floating-point number represented by `[num]`. + */ +#[inline(always)] +pub pure fn from_str_hex(num: &str) -> Option { + num::from_str_common(num, 16u, true, true, true, num::ExpBin, false) +} + +/** + * Convert a string in an given base to a float. + * + * Due to possible conflicts, this function does **not** accept + * the special values `inf`, `-inf`, `+inf` and `NaN`, **nor** + * does it recognize exponents of any kind. + * + * Leading and trailing whitespace represent an error. + * + * # Arguments + * + * * num - A string + * * radix - The base to use. Must lie in the range [2 .. 36] + * + * # Return value + * + * `none` if the string did not represent a valid number. Otherwise, + * `Some(n)` where `n` is the floating-point number represented by `num`. + */ +#[inline(always)] +pub pure fn from_str_radix(num: &str, rdx: uint) -> Option { + num::from_str_common(num, rdx, true, true, false, num::ExpNone, false) +} + +impl f32: from_str::FromStr { + #[inline(always)] + static pure fn from_str(val: &str) -> Option { from_str(val) } +} + +impl f32: num::FromStrRadix { + #[inline(always)] + static pure fn from_str_radix(val: &str, rdx: uint) -> Option { + from_str_radix(val, rdx) + } +} + // // Local Variables: // mode: rust diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index 851697012fc..276aa13da71 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -19,6 +19,9 @@ use cmp; use libc::{c_double, c_int}; use libc; use num; +use option::Option; +use to_str; +use from_str; pub use cmath::c_double_targ_consts::*; @@ -357,6 +360,197 @@ impl f64: num::Round { } } +/** + * Section: String Conversions + */ + +/** + * Converts a float to a string + * + * # Arguments + * + * * num - The float value + */ +#[inline(always)] +pub pure fn to_str(num: f64) -> ~str { + let (r, _) = num::to_str_common( + &num, 10u, true, true, num::SignNeg, num::DigAll); + r +} + +/** + * Converts a float to a string in hexadecimal format + * + * # Arguments + * + * * num - The float value + */ +#[inline(always)] +pub pure fn to_str_hex(num: f64) -> ~str { + let (r, _) = num::to_str_common( + &num, 16u, true, true, num::SignNeg, num::DigAll); + r +} + +/** + * Converts a float to a string in a given radix + * + * # Arguments + * + * * num - The float value + * * radix - The base to use + */ +#[inline(always)] +pub pure fn to_str_radix(num: f64, rdx: uint) -> ~str { + let (r, _) = num::to_str_common( + &num, rdx, true, true, num::SignNeg, num::DigAll); + r +} + +/** + * Converts a float to a string with exactly the number of + * provided significant digits + * + * # Arguments + * + * * num - The float value + * * digits - The number of significant digits + */ +#[inline(always)] +pub pure fn to_str_exact(num: f64, dig: uint) -> ~str { + let (r, _) = num::to_str_common( + &num, 10u, true, true, num::SignNeg, num::DigExact(dig)); + r +} + +/** + * Converts a float to a string with a maximum number of + * significant digits + * + * # Arguments + * + * * num - The float value + * * digits - The number of significant digits + */ +#[inline(always)] +pub pure fn to_str_digits(num: f64, dig: uint) -> ~str { + let (r, _) = num::to_str_common( + &num, 10u, true, true, num::SignNeg, num::DigMax(dig)); + r +} + +impl f64: to_str::ToStr { + #[inline(always)] + pure fn to_str() -> ~str { to_str_digits(self, 8) } +} + +impl f64: num::ToStrRadix { + #[inline(always)] + pure fn to_str_radix(&self, rdx: uint) -> ~str { + to_str_radix(*self, rdx) + } +} + +/** + * Convert a string in base 10 to a float. + * Accepts a optional decimal exponent. + * + * This function accepts strings such as + * + * * '3.14' + * * '+3.14', equivalent to '3.14' + * * '-3.14' + * * '2.5E10', or equivalently, '2.5e10' + * * '2.5E-10' + * * '.' (understood as 0) + * * '5.' + * * '.5', or, equivalently, '0.5' + * * '+inf', 'inf', '-inf', 'NaN' + * + * Leading and trailing whitespace represent an error. + * + * # Arguments + * + * * num - A string + * + * # Return value + * + * `none` if the string did not represent a valid number. Otherwise, + * `Some(n)` where `n` is the floating-point number represented by `num`. + */ +#[inline(always)] +pub pure fn from_str(num: &str) -> Option { + num::from_str_common(num, 10u, true, true, true, num::ExpDec, false) +} + +/** + * Convert a string in base 16 to a float. + * Accepts a optional binary exponent. + * + * This function accepts strings such as + * + * * 'a4.fe' + * * '+a4.fe', equivalent to 'a4.fe' + * * '-a4.fe' + * * '2b.aP128', or equivalently, '2b.ap128' + * * '2b.aP-128' + * * '.' (understood as 0) + * * 'c.' + * * '.c', or, equivalently, '0.c' + * * '+inf', 'inf', '-inf', 'NaN' + * + * Leading and trailing whitespace represent an error. + * + * # Arguments + * + * * num - A string + * + * # Return value + * + * `none` if the string did not represent a valid number. Otherwise, + * `Some(n)` where `n` is the floating-point number represented by `[num]`. + */ +#[inline(always)] +pub pure fn from_str_hex(num: &str) -> Option { + num::from_str_common(num, 16u, true, true, true, num::ExpBin, false) +} + +/** + * Convert a string in an given base to a float. + * + * Due to possible conflicts, this function does **not** accept + * the special values `inf`, `-inf`, `+inf` and `NaN`, **nor** + * does it recognize exponents of any kind. + * + * Leading and trailing whitespace represent an error. + * + * # Arguments + * + * * num - A string + * * radix - The base to use. Must lie in the range [2 .. 36] + * + * # Return value + * + * `none` if the string did not represent a valid number. Otherwise, + * `Some(n)` where `n` is the floating-point number represented by `num`. + */ +#[inline(always)] +pub pure fn from_str_radix(num: &str, rdx: uint) -> Option { + num::from_str_common(num, rdx, true, true, false, num::ExpNone, false) +} + +impl f64: from_str::FromStr { + #[inline(always)] + static pure fn from_str(val: &str) -> Option { from_str(val) } +} + +impl f64: num::FromStrRadix { + #[inline(always)] + static pure fn from_str_radix(val: &str, rdx: uint) -> Option { + from_str_radix(val, rdx) + } +} + // // Local Variables: // mode: rust diff --git a/src/libcore/num/float.rs b/src/libcore/num/float.rs index 1d1be6df87a..4f683ed14f7 100644 --- a/src/libcore/num/float.rs +++ b/src/libcore/num/float.rs @@ -34,6 +34,8 @@ use num::Num::from_int; use option::{None, Option, Some}; use str; use uint; +use to_str; +use from_str; pub use f64::{add, sub, mul, div, rem, lt, le, eq, ne, ge, gt}; pub use f64::logarithm; @@ -95,7 +97,7 @@ pub mod consts { pub const ln_10: float = 2.30258509299404568401799145468436421; } -/** +/* * Section: String Conversions */ @@ -105,85 +107,41 @@ pub mod consts { * # Arguments * * * num - The float value - * * digits - The number of significant digits - * * exact - Whether to enforce the exact number of significant digits */ -pub pure fn to_str_common(num: float, digits: uint, exact: bool) -> ~str { - if is_NaN(num) { return ~"NaN"; } - if num == infinity { return ~"inf"; } - if num == neg_infinity { return ~"-inf"; } +#[inline(always)] +pub pure fn to_str(num: float) -> ~str { + let (r, _) = num::to_str_common( + &num, 10u, true, true, num::SignNeg, num::DigAll); + r +} - let mut (num, sign) = if num < 0.0 { (-num, ~"-") } else { (num, ~"") }; +/** + * Converts a float to a string in hexadecimal format + * + * # Arguments + * + * * num - The float value + */ +#[inline(always)] +pub pure fn to_str_hex(num: float) -> ~str { + let (r, _) = num::to_str_common( + &num, 16u, true, true, num::SignNeg, num::DigAll); + r +} - // truncated integer - let trunc = num as uint; - - // decimal remainder - let mut frac = num - (trunc as float); - - // stack of digits - let mut fractionalParts = ~[]; - - // FIXME: (#2608) - // This used to return right away without rounding, as "~[-]num", - // but given epsilon like in f64.rs, I don't see how the comparison - // to epsilon did much when only used there. - // if (frac < epsilon && !exact) || digits == 0u { return accum; } - // - // With something better, possibly weird results like this can be avoided: - // assert "3.14158999999999988262" == my_to_str_exact(3.14159, 20u); - - let mut ii = digits; - let mut epsilon_prime = 1.0 / pow_with_uint(10u, ii); - - // while we still need digits - // build stack of digits - while ii > 0 && (frac >= epsilon_prime || exact) { - // store the next digit - frac *= 10.0; - let digit = frac as uint; - // Bleh: not really unsafe. - unsafe { fractionalParts.push(digit); } - - // calculate the next frac - frac -= digit as float; - epsilon_prime *= 10.0; - ii -= 1u; - } - - let mut acc; - let mut racc = ~""; - let mut carry = if frac * 10.0 as uint >= 5 { 1 } else { 0 }; - - // turn digits into string - // using stack of digits - while !fractionalParts.is_empty() { - // Bleh; shouldn't need to be unsafe - let mut adjusted_digit = carry + unsafe { fractionalParts.pop() }; - - if adjusted_digit == 10 { - carry = 1; - adjusted_digit %= 10 - } else { - carry = 0; - }; - - racc = uint::str(adjusted_digit) + racc; - } - - // pad decimals with trailing zeroes - while racc.len() < digits && exact { - racc += ~"0" - } - - // combine ints and decimals - let mut ones = uint::str(trunc + carry); - if racc == ~"" { - acc = sign + ones; - } else { - acc = sign + ones + ~"." + racc; - } - move acc +/** + * Converts a float to a string in a given radix + * + * # Arguments + * + * * num - The float value + * * radix - The base to use + */ +#[inline(always)] +pub pure fn to_str_radix(num: float, radix: uint) -> ~str { + let (r, _) = num::to_str_common( + &num, radix, true, true, num::SignNeg, num::DigAll); + r } /** @@ -197,7 +155,9 @@ pub pure fn to_str_common(num: float, digits: uint, exact: bool) -> ~str { */ #[inline(always)] pub pure fn to_str_exact(num: float, digits: uint) -> ~str { - to_str_common(num, digits, true) + let (r, _) = num::to_str_common( + &num, 10u, true, true, num::SignNeg, num::DigExact(digits)); + r } #[test] @@ -206,7 +166,6 @@ pub fn test_to_str_exact_do_decimal() { assert s == ~"5.0000"; } - /** * Converts a float to a string with a maximum number of * significant digits @@ -217,12 +176,27 @@ pub fn test_to_str_exact_do_decimal() { * * digits - The number of significant digits */ #[inline(always)] -pub pure fn to_str(num: float, digits: uint) -> ~str { - to_str_common(num, digits, false) +pub pure fn to_str_digits(num: float, digits: uint) -> ~str { + let (r, _) = num::to_str_common( + &num, 10u, true, true, num::SignNeg, num::DigMax(digits)); + r +} + +impl float: to_str::ToStr { + #[inline(always)] + pure fn to_str() -> ~str { to_str_digits(self, 8) } +} + +impl float: num::ToStrRadix { + #[inline(always)] + pure fn to_str_radix(&self, radix: uint) -> ~str { + to_str_radix(*self, radix) + } } /** - * Convert a string to a float + * Convert a string in base 10 to a float. + * Accepts a optional decimal exponent. * * This function accepts strings such as * @@ -231,12 +205,44 @@ pub pure fn to_str(num: float, digits: uint) -> ~str { * * '-3.14' * * '2.5E10', or equivalently, '2.5e10' * * '2.5E-10' - * * '', or, equivalently, '.' (understood as 0) + * * '.' (understood as 0) * * '5.' * * '.5', or, equivalently, '0.5' - * * 'inf', '-inf', 'NaN' + * * '+inf', 'inf', '-inf', 'NaN' * - * Leading and trailing whitespace are ignored. + * Leading and trailing whitespace represent an error. + * + * # Arguments + * + * * num - A string + * + * # Return value + * + * `none` if the string did not represent a valid number. Otherwise, + * `Some(n)` where `n` is the floating-point number represented by `num`. + */ +#[inline(always)] +pub pure fn from_str(num: &str) -> Option { + num::from_str_common(num, 10u, true, true, true, num::ExpDec, false) +} + +/** + * Convert a string in base 16 to a float. + * Accepts a optional binary exponent. + * + * This function accepts strings such as + * + * * 'a4.fe' + * * '+a4.fe', equivalent to 'a4.fe' + * * '-a4.fe' + * * '2b.aP128', or equivalently, '2b.ap128' + * * '2b.aP-128' + * * '.' (understood as 0) + * * 'c.' + * * '.c', or, equivalently, '0.c' + * * '+inf', 'inf', '-inf', 'NaN' + * + * Leading and trailing whitespace represent an error. * * # Arguments * @@ -247,123 +253,45 @@ pub pure fn to_str(num: float, digits: uint) -> ~str { * `none` if the string did not represent a valid number. Otherwise, * `Some(n)` where `n` is the floating-point number represented by `[num]`. */ -pub pure fn from_str(num: &str) -> Option { - if num == "inf" { - return Some(infinity as float); - } else if num == "-inf" { - return Some(neg_infinity as float); - } else if num == "NaN" { - return Some(NaN as float); - } +#[inline(always)] +pub pure fn from_str_hex(num: &str) -> Option { + num::from_str_common(num, 16u, true, true, true, num::ExpBin, false) +} - let mut pos = 0u; //Current byte position in the string. - //Used to walk the string in O(n). - let len = str::len(num); //Length of the string, in bytes. +/** + * Convert a string in an given base to a float. + * + * Due to possible conflicts, this function does **not** accept + * the special values `inf`, `-inf`, `+inf` and `NaN`, **nor** + * does it recognize exponents of any kind. + * + * Leading and trailing whitespace represent an error. + * + * # Arguments + * + * * num - A string + * * radix - The base to use. Must lie in the range [2 .. 36] + * + * # Return value + * + * `none` if the string did not represent a valid number. Otherwise, + * `Some(n)` where `n` is the floating-point number represented by `num`. + */ +#[inline(always)] +pub pure fn from_str_radix(num: &str, radix: uint) -> Option { + num::from_str_common(num, radix, true, true, false, num::ExpNone, false) +} - if len == 0u { return None; } - let mut total = 0f; //Accumulated result - let mut c = 'z'; //Latest char. +impl float: from_str::FromStr { + #[inline(always)] + static pure fn from_str(val: &str) -> Option { from_str(val) } +} - //The string must start with one of the following characters. - match str::char_at(num, 0u) { - '-' | '+' | '0' .. '9' | '.' => (), - _ => return None - } - - //Determine if first char is '-'/'+'. Set [pos] and [neg] accordingly. - let mut neg = false; //Sign of the result - match str::char_at(num, 0u) { - '-' => { - neg = true; - pos = 1u; - } - '+' => { - pos = 1u; - } - _ => () - } - - //Examine the following chars until '.', 'e', 'E' - while(pos < len) { - let char_range = str::char_range_at(num, pos); - c = char_range.ch; - pos = char_range.next; - match c { - '0' .. '9' => { - total = total * 10f; - total += ((c as int) - ('0' as int)) as float; - } - '.' | 'e' | 'E' => break, - _ => return None - } - } - - if c == '.' {//Examine decimal part - let mut decimal = 1f; - while(pos < len) { - let char_range = str::char_range_at(num, pos); - c = char_range.ch; - pos = char_range.next; - match c { - '0' | '1' | '2' | '3' | '4' | '5' | '6'| '7' | '8' | '9' => { - decimal /= 10f; - total += (((c as int) - ('0' as int)) as float)*decimal; - } - 'e' | 'E' => break, - _ => return None - } - } - } - - if (c == 'e') || (c == 'E') { //Examine exponent - let mut exponent = 0u; - let mut neg_exponent = false; - if(pos < len) { - let char_range = str::char_range_at(num, pos); - c = char_range.ch; - match c { - '+' => { - pos = char_range.next; - } - '-' => { - pos = char_range.next; - neg_exponent = true; - } - _ => () - } - while(pos < len) { - let char_range = str::char_range_at(num, pos); - c = char_range.ch; - match c { - '0' | '1' | '2' | '3' | '4' | '5' | '6'| '7' | '8' | '9' => { - exponent *= 10u; - exponent += ((c as uint) - ('0' as uint)); - } - _ => break - } - pos = char_range.next; - } - let multiplier = pow_with_uint(10u, exponent); - //Note: not ~[int::pow], otherwise, we'll quickly - //end up with a nice overflow - if neg_exponent { - total = total / multiplier; - } else { - total = total * multiplier; - } - } else { - return None; - } - } - - if(pos < len) { - return None; - } else { - if(neg) { - total *= -1f; - } - return Some(total); - } +impl float: num::FromStrRadix { + #[inline(always)] + static pure fn from_str_radix(val: &str, radix: uint) -> Option { + from_str_radix(val, radix) + } } /** @@ -523,7 +451,6 @@ impl float: num::Round { #[test] pub fn test_from_str() { - assert from_str(~"3") == Some(3.); assert from_str(~"3") == Some(3.); assert from_str(~"3.14") == Some(3.14); assert from_str(~"+3.14") == Some(3.14); @@ -537,20 +464,25 @@ pub fn test_from_str() { assert from_str(~"5.") == Some(5.); assert from_str(~".5") == Some(0.5); assert from_str(~"0.5") == Some(0.5); - assert from_str(~"0.5") == Some(0.5); - assert from_str(~"0.5") == Some(0.5); - assert from_str(~"-.5") == Some(-0.5); assert from_str(~"-.5") == Some(-0.5); assert from_str(~"-5") == Some(-5.); - assert from_str(~"-0") == Some(-0.); - assert from_str(~"0") == Some(0.); assert from_str(~"inf") == Some(infinity); + assert from_str(~"+inf") == Some(infinity); assert from_str(~"-inf") == Some(neg_infinity); // note: NaN != NaN, hence this slightly complex test match from_str(~"NaN") { Some(f) => assert is_NaN(f), None => die!() } + // note: -0 == 0, hence these slightly more complex tests + match from_str(~"-0") { + Some(v) if is_zero(v) => assert is_negative(v), + _ => fail + } + match from_str(~"0") { + Some(v) if is_zero(v) => assert is_positive(v), + _ => fail + } assert from_str(~"").is_none(); assert from_str(~"x").is_none(); @@ -564,6 +496,89 @@ pub fn test_from_str() { assert from_str(~"1e1-1").is_none(); } +#[test] +pub fn test_from_str_hex() { + assert from_str_hex(~"a4") == Some(164.); + assert from_str_hex(~"a4.fe") == Some(164.9921875); + assert from_str_hex(~"-a4.fe") == Some(-164.9921875); + assert from_str_hex(~"+a4.fe") == Some(164.9921875); + assert from_str_hex(~"ff0P4") == Some(0xff00 as float); + assert from_str_hex(~"ff0p4") == Some(0xff00 as float); + assert from_str_hex(~"ff0p-4") == Some(0xff as float); + assert from_str_hex(~".") == Some(0.); + assert from_str_hex(~".p1") == Some(0.); + assert from_str_hex(~".p-1") == Some(0.); + assert from_str_hex(~"f.") == Some(15.); + assert from_str_hex(~".f") == Some(0.9375); + assert from_str_hex(~"0.f") == Some(0.9375); + assert from_str_hex(~"-.f") == Some(-0.9375); + assert from_str_hex(~"-f") == Some(-15.); + assert from_str_hex(~"inf") == Some(infinity); + assert from_str_hex(~"+inf") == Some(infinity); + assert from_str_hex(~"-inf") == Some(neg_infinity); + // note: NaN != NaN, hence this slightly complex test + match from_str_hex(~"NaN") { + Some(f) => assert is_NaN(f), + None => fail + } + // note: -0 == 0, hence these slightly more complex tests + match from_str_hex(~"-0") { + Some(v) if is_zero(v) => assert is_negative(v), + _ => fail + } + match from_str_hex(~"0") { + Some(v) if is_zero(v) => assert is_positive(v), + _ => fail + } + assert from_str_hex(~"e") == Some(14.); + assert from_str_hex(~"E") == Some(14.); + assert from_str_hex(~"E1") == Some(225.); + assert from_str_hex(~"1e1e1") == Some(123361.); + assert from_str_hex(~"1e1.1") == Some(481.0625); + + assert from_str_hex(~"").is_none(); + assert from_str_hex(~"x").is_none(); + assert from_str_hex(~" ").is_none(); + assert from_str_hex(~" ").is_none(); + assert from_str_hex(~"p").is_none(); + assert from_str_hex(~"P").is_none(); + assert from_str_hex(~"P1").is_none(); + assert from_str_hex(~"1p1p1").is_none(); + assert from_str_hex(~"1p1.1").is_none(); + assert from_str_hex(~"1p1-1").is_none(); +} + +#[test] +pub fn test_to_str_hex() { + assert to_str_hex(164.) == ~"a4"; + assert to_str_hex(164.9921875) == ~"a4.fe"; + assert to_str_hex(-164.9921875) == ~"-a4.fe"; + assert to_str_hex(0xff00 as float) == ~"ff00"; + assert to_str_hex(-(0xff00 as float)) == ~"-ff00"; + assert to_str_hex(0.) == ~"0"; + assert to_str_hex(15.) == ~"f"; + assert to_str_hex(-15.) == ~"-f"; + assert to_str_hex(0.9375) == ~"0.f"; + assert to_str_hex(-0.9375) == ~"-0.f"; + assert to_str_hex(infinity) == ~"inf"; + assert to_str_hex(neg_infinity) == ~"-inf"; + assert to_str_hex(NaN) == ~"NaN"; + assert to_str_hex(0.) == ~"0"; + assert to_str_hex(-0.) == ~"-0"; +} + +#[test] +pub fn test_to_str_radix() { + assert to_str_radix(36., 36u) == ~"10"; + assert to_str_radix(8.125, 2u) == ~"1000.001"; +} + +#[test] +pub fn test_from_str_radix() { + assert from_str_radix(~"10", 36u) == Some(36.); + assert from_str_radix(~"1000.001", 2u) == Some(8.125); +} + #[test] pub fn test_positive() { assert(is_positive(infinity)); @@ -610,8 +625,8 @@ pub fn test_nonnegative() { #[test] pub fn test_to_str_inf() { - assert to_str(infinity, 10u) == ~"inf"; - assert to_str(-infinity, 10u) == ~"-inf"; + assert to_str_digits(infinity, 10u) == ~"inf"; + assert to_str_digits(-infinity, 10u) == ~"-inf"; } #[test] diff --git a/src/libcore/repr.rs b/src/libcore/repr.rs index a5c3afcc87f..2f77e71bef0 100644 --- a/src/libcore/repr.rs +++ b/src/libcore/repr.rs @@ -893,7 +893,7 @@ fn test_repr() { exact_test(&10, "10"); exact_test(&true, "true"); exact_test(&false, "false"); - exact_test(&1.234, "1.2340"); + exact_test(&1.234, "1.234"); exact_test(&(&"hello"), "\"hello\""); exact_test(&(@"hello"), "@\"hello\""); exact_test(&(~"he\u10f3llo"), "~\"he\\u10f3llo\""); @@ -918,11 +918,11 @@ fn test_repr() { exact_test(&(&["hi", "there"]), "&[\"hi\", \"there\"]"); exact_test(&(P{a:10, b:1.234}), - "{a: 10, b: 1.2340}"); + "{a: 10, b: 1.234}"); exact_test(&(@P{a:10, b:1.234}), - "@{a: 10, b: 1.2340}"); + "@{a: 10, b: 1.234}"); exact_test(&(~P{a:10, b:1.234}), - "~{a: 10, b: 1.2340}"); + "~{a: 10, b: 1.234}"); exact_test(&(10_u8, ~"hello"), "(10, ~\"hello\")"); exact_test(&(10_u16, ~"hello"), diff --git a/src/libcore/to_str.rs b/src/libcore/to_str.rs index 13b09590b44..51205b0c647 100644 --- a/src/libcore/to_str.rs +++ b/src/libcore/to_str.rs @@ -24,18 +24,6 @@ use vec; pub trait ToStr { pub pure fn to_str() -> ~str; } -impl float: ToStr { - #[inline(always)] - pure fn to_str() -> ~str { ::float::to_str(self, 4u) } -} -impl f32: ToStr { - #[inline(always)] - pure fn to_str() -> ~str { ::float::to_str(self as float, 4u) } -} -impl f64: ToStr { - #[inline(always)] - pure fn to_str() -> ~str { ::float::to_str(self as float, 4u) } -} impl bool: ToStr { #[inline(always)] pure fn to_str() -> ~str { ::bool::to_str(self) } diff --git a/src/libstd/json.rs b/src/libstd/json.rs index f0929c3dba0..b1cdeef4e66 100644 --- a/src/libstd/json.rs +++ b/src/libstd/json.rs @@ -109,7 +109,7 @@ pub impl Encoder: serialize::Encoder { fn emit_f64(&self, v: f64) { self.emit_float(v as float); } fn emit_f32(&self, v: f32) { self.emit_float(v as float); } fn emit_float(&self, v: float) { - self.wr.write_str(float::to_str(v, 6u)); + self.wr.write_str(float::to_str_digits(v, 6u)); } fn emit_char(&self, v: char) { self.emit_borrowed_str(str::from_char(v)) } @@ -213,7 +213,7 @@ pub impl PrettyEncoder: serialize::Encoder { fn emit_f64(&self, v: f64) { self.emit_float(v as float); } fn emit_f32(&self, v: f32) { self.emit_float(v as float); } fn emit_float(&self, v: float) { - self.wr.write_str(float::to_str(v, 6u)); + self.wr.write_str(float::to_str_digits(v, 6u)); } fn emit_char(&self, v: char) { self.emit_borrowed_str(str::from_char(v)) }