summaryrefslogtreecommitdiff
path: root/libgo/go/strconv
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/strconv')
-rw-r--r--libgo/go/strconv/atob_test.go2
-rw-r--r--libgo/go/strconv/atof.go57
-rw-r--r--libgo/go/strconv/atof_test.go36
-rw-r--r--libgo/go/strconv/ftoa.go34
-rw-r--r--libgo/go/strconv/ftoa_test.go4
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)