diff options
Diffstat (limited to 'libgo/go/strconv')
-rw-r--r-- | libgo/go/strconv/atob_test.go | 2 | ||||
-rw-r--r-- | libgo/go/strconv/atof.go | 57 | ||||
-rw-r--r-- | libgo/go/strconv/atof_test.go | 36 | ||||
-rw-r--r-- | libgo/go/strconv/ftoa.go | 34 | ||||
-rw-r--r-- | libgo/go/strconv/ftoa_test.go | 4 |
5 files changed, 71 insertions, 62 deletions
diff --git a/libgo/go/strconv/atob_test.go b/libgo/go/strconv/atob_test.go index 7a95456214d..497df5b18d8 100644 --- a/libgo/go/strconv/atob_test.go +++ b/libgo/go/strconv/atob_test.go @@ -46,7 +46,7 @@ func TestAtob(t *testing.T) { } } else { if e != nil { - t.Errorf("%s: expected no error but got %s", test.in, test.err, e) + t.Errorf("%s: expected no error but got %s", test.in, e) } if b != test.out { t.Errorf("%s: expected %t but got %t", test.in, test.out, b) diff --git a/libgo/go/strconv/atof.go b/libgo/go/strconv/atof.go index 262a8b53c72..72f162c5134 100644 --- a/libgo/go/strconv/atof.go +++ b/libgo/go/strconv/atof.go @@ -19,6 +19,40 @@ import ( var optimize = true // can change for testing +func equalIgnoreCase(s1, s2 string) bool { + if len(s1) != len(s2) { + return false + } + for i := 0; i < len(s1); i++ { + c1 := s1[i] + if 'A' <= c1 && c1 <= 'Z' { + c1 += 'a' - 'A' + } + c2 := s2[i] + if 'A' <= c2 && c2 <= 'Z' { + c2 += 'a' - 'A' + } + if c1 != c2 { + return false + } + } + return true +} + +func special(s string) (f float64, ok bool) { + switch { + case equalIgnoreCase(s, "nan"): + return math.NaN(), true + case equalIgnoreCase(s, "-inf"): + return math.Inf(-1), true + case equalIgnoreCase(s, "+inf"): + return math.Inf(1), true + case equalIgnoreCase(s, "inf"): + return math.Inf(1), true + } + return +} + // TODO(rsc): Better truncation handling. func stringToDecimal(s string) (neg bool, d *decimal, trunc bool, ok bool) { i := 0 @@ -73,7 +107,7 @@ func stringToDecimal(s string) (neg bool, d *decimal, trunc bool, ok bool) { // just be sure to move the decimal point by // a lot (say, 100000). it doesn't matter if it's // not the exact number. - if i < len(s) && s[i] == 'e' { + if i < len(s) && (s[i] == 'e' || s[i] == 'E') { i++ if i >= len(s) { return @@ -209,7 +243,7 @@ out: // Compute exact floating-point integer from d's digits. // Caller is responsible for avoiding overflow. func decimalAtof64Int(neg bool, d *decimal) float64 { - f := float64(0) + f := 0.0 for i := 0; i < d.nd; i++ { f = f*10 + float64(d.d[i]-'0') } @@ -320,6 +354,10 @@ func decimalAtof32(neg bool, d *decimal, trunc bool) (f float32, ok bool) { // away from the largest floating point number of the given size, // Atof32 returns f = ±Inf, err.Error = os.ERANGE. func Atof32(s string) (f float32, err os.Error) { + if val, ok := special(s); ok { + return float32(val), nil + } + neg, d, trunc, ok := stringToDecimal(s) if !ok { return 0, &NumError{s, os.EINVAL} @@ -341,6 +379,10 @@ func Atof32(s string) (f float32, err os.Error) { // Except for the type of its result, its definition is the same as that // of Atof32. func Atof64(s string) (f float64, err os.Error) { + if val, ok := special(s); ok { + return val, nil + } + neg, d, trunc, ok := stringToDecimal(s) if !ok { return 0, &NumError{s, os.EINVAL} @@ -358,17 +400,6 @@ func Atof64(s string) (f float64, err os.Error) { return f, err } -// Atof is like Atof32 or Atof64, depending on the size of float. -func Atof(s string) (f float, err os.Error) { - if FloatSize == 32 { - f1, err1 := Atof32(s) - return float(f1), err1 - } - f1, err1 := Atof64(s) - return float(f1), err1 -} - - // AtofN converts the string s to a 64-bit floating-point number, // but it rounds the result assuming that it will be stored in a value // of n bits (32 or 64). diff --git a/libgo/go/strconv/atof_test.go b/libgo/go/strconv/atof_test.go index 1f7543891f9..6cc60e549da 100644 --- a/libgo/go/strconv/atof_test.go +++ b/libgo/go/strconv/atof_test.go @@ -24,6 +24,7 @@ var atoftests = []atofTest{ {"1x", "0", os.EINVAL}, {"1.1.", "0", os.EINVAL}, {"1e23", "1e+23", nil}, + {"1E23", "1e+23", nil}, {"100000000000000000000000", "1e+23", nil}, {"1e-100", "1e-100", nil}, {"123456700", "1.234567e+08", nil}, @@ -37,6 +38,16 @@ var atoftests = []atofTest{ {"1e-20", "1e-20", nil}, {"625e-3", "0.625", nil}, + // NaNs + {"nan", "NaN", nil}, + {"NaN", "NaN", nil}, + {"NAN", "NaN", nil}, + + // Infs + {"inf", "+Inf", nil}, + {"-Inf", "-Inf", nil}, + {"+INF", "+Inf", nil}, + // largest float64 {"1.7976931348623157e308", "1.7976931348623157e+308", nil}, {"-1.7976931348623157e308", "-1.7976931348623157e+308", nil}, @@ -139,15 +150,6 @@ func testAtof(t *testing.T, opt bool) { test.in, out32, err, test.out, test.err, out) } } - - if FloatSize == 64 || float64(float32(out)) == out { - outf, err := Atof(test.in) - outs := Ftoa(outf, 'g', -1) - if outs != test.out || !reflect.DeepEqual(err, test.err) { - t.Errorf("Ftoa(%v) = %v, %v want %v, %v # %v", - test.in, outf, err, test.out, test.err, out) - } - } } SetOptimize(oldopt) } @@ -156,26 +158,26 @@ func TestAtof(t *testing.T) { testAtof(t, true) } func TestAtofSlow(t *testing.T) { testAtof(t, false) } -func BenchmarkAtofDecimal(b *testing.B) { +func BenchmarkAtof64Decimal(b *testing.B) { for i := 0; i < b.N; i++ { - Atof("33909") + Atof64("33909") } } -func BenchmarkAtofFloat(b *testing.B) { +func BenchmarkAtof64Float(b *testing.B) { for i := 0; i < b.N; i++ { - Atof("339.7784") + Atof64("339.7784") } } -func BenchmarkAtofFloatExp(b *testing.B) { +func BenchmarkAtof64FloatExp(b *testing.B) { for i := 0; i < b.N; i++ { - Atof("-5.09e75") + Atof64("-5.09e75") } } -func BenchmarkAtofBig(b *testing.B) { +func BenchmarkAtof64Big(b *testing.B) { for i := 0; i < b.N; i++ { - Atof("123456789123456789123456789") + Atof64("123456789123456789123456789") } } diff --git a/libgo/go/strconv/ftoa.go b/libgo/go/strconv/ftoa.go index 3659243c790..4ec3cdbb974 100644 --- a/libgo/go/strconv/ftoa.go +++ b/libgo/go/strconv/ftoa.go @@ -22,33 +22,21 @@ type floatInfo struct { var float32info = floatInfo{23, 8, -127} var float64info = floatInfo{52, 11, -1023} -func floatsize() int { - // Figure out whether float is float32 or float64. - // 1e-35 is representable in both, but 1e-70 - // is too small for a float32. - var f float = 1e-35 - if f*f == 0 { - return 32 - } - return 64 -} - -// Floatsize gives the size of the float type, either 32 or 64. -var FloatSize = floatsize() - // Ftoa32 converts the 32-bit floating-point number f to a string, // according to the format fmt and precision prec. // // The format fmt is one of // 'b' (-ddddp±ddd, a binary exponent), // 'e' (-d.dddde±dd, a decimal exponent), -// 'f' (-ddd.dddd, no exponent), or -// 'g' ('e' for large exponents, 'f' otherwise). +// 'E' (-d.ddddE±dd, a decimal exponent), +// 'f' (-ddd.dddd, no exponent), +// 'g' ('e' for large exponents, 'f' otherwise), or +// 'G' ('E' for large exponents, 'f' otherwise). // // The precision prec controls the number of digits -// (excluding the exponent) printed by the 'e', 'f', and 'g' formats. -// For 'e' and 'f' it is the number of digits after the decimal point. -// For 'g' it is the total number of digits. +// (excluding the exponent) printed by the 'e', 'E', 'f', 'g', and 'G' formats. +// For 'e', 'E', and 'f' it is the number of digits after the decimal point. +// For 'g' and 'G' it is the total number of digits. // The special precision -1 uses the smallest number of digits // necessary such that Atof32 will return f exactly. // @@ -75,14 +63,6 @@ func FtoaN(f float64, fmt byte, prec int, n int) string { return Ftoa64(f, fmt, prec) } -// Ftoa behaves as Ftoa32 or Ftoa64, depending on the size of the float type. -func Ftoa(f float, fmt byte, prec int) string { - if FloatSize == 32 { - return Ftoa32(float32(f), fmt, prec) - } - return Ftoa64(float64(f), fmt, prec) -} - func genericFtoa(bits uint64, fmt byte, prec int, flt *floatInfo) string { neg := bits>>flt.expbits>>flt.mantbits != 0 exp := int(bits>>flt.mantbits) & (1<<flt.expbits - 1) diff --git a/libgo/go/strconv/ftoa_test.go b/libgo/go/strconv/ftoa_test.go index 6044afdae6d..3a862a2beeb 100644 --- a/libgo/go/strconv/ftoa_test.go +++ b/libgo/go/strconv/ftoa_test.go @@ -121,10 +121,6 @@ var ftoatests = []ftoaTest{ } func TestFtoa(t *testing.T) { - if FloatSize != 32 { - println("floatsize: ", FloatSize) - panic("floatsize") - } for i := 0; i < len(ftoatests); i++ { test := &ftoatests[i] s := Ftoa64(test.f, test.fmt, test.prec) |