diff options
| author | Rob Pike <r@golang.org> | 2009-06-09 09:53:44 -0700 |
|---|---|---|
| committer | Rob Pike <r@golang.org> | 2009-06-09 09:53:44 -0700 |
| commit | d90e7cbac65c5792ce312ee82fbe03a5dfc98c6f (patch) | |
| tree | 7032a11d0cac2ae4d3e90f7a189b575b5a50f848 /src/lib/strconv | |
| parent | bf5c0c957c3c3ea9add6cfd51b90c463cb4814b5 (diff) | |
| download | go-d90e7cbac65c5792ce312ee82fbe03a5dfc98c6f.tar.xz | |
mv src/lib to src/pkg
tests: all.bash passes, gobuild still works, godoc still works.
R=rsc
OCL=30096
CL=30102
Diffstat (limited to 'src/lib/strconv')
| -rw-r--r-- | src/lib/strconv/Makefile | 79 | ||||
| -rw-r--r-- | src/lib/strconv/atof.go | 372 | ||||
| -rw-r--r-- | src/lib/strconv/atof_test.go | 133 | ||||
| -rw-r--r-- | src/lib/strconv/atoi.go | 166 | ||||
| -rw-r--r-- | src/lib/strconv/atoi_test.go | 188 | ||||
| -rw-r--r-- | src/lib/strconv/decimal.go | 392 | ||||
| -rw-r--r-- | src/lib/strconv/decimal_test.go | 119 | ||||
| -rw-r--r-- | src/lib/strconv/fp_test.go | 149 | ||||
| -rw-r--r-- | src/lib/strconv/ftoa.go | 418 | ||||
| -rw-r--r-- | src/lib/strconv/ftoa_test.go | 119 | ||||
| -rw-r--r-- | src/lib/strconv/itoa.go | 49 | ||||
| -rw-r--r-- | src/lib/strconv/itoa_test.go | 111 | ||||
| -rw-r--r-- | src/lib/strconv/quote.go | 229 | ||||
| -rw-r--r-- | src/lib/strconv/quote_test.go | 170 | ||||
| -rw-r--r-- | src/lib/strconv/testfp.txt | 181 |
15 files changed, 0 insertions, 2875 deletions
diff --git a/src/lib/strconv/Makefile b/src/lib/strconv/Makefile deleted file mode 100644 index 499f8c1c14..0000000000 --- a/src/lib/strconv/Makefile +++ /dev/null @@ -1,79 +0,0 @@ -# Copyright 2009 The Go Authors. All rights reserved. -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file. - -# DO NOT EDIT. Automatically generated by gobuild. -# gobuild -m >Makefile - -D= - -include $(GOROOT)/src/Make.$(GOARCH) -AR=gopack - -default: packages - -clean: - rm -rf *.[$(OS)] *.a [$(OS)].out _obj - -test: packages - gotest - -coverage: packages - gotest - 6cov -g `pwd` | grep -v '_test\.go:' - -%.$O: %.go - $(GC) -I_obj $*.go - -%.$O: %.c - $(CC) $*.c - -%.$O: %.s - $(AS) $*.s - -O1=\ - atoi.$O\ - decimal.$O\ - itoa.$O\ - quote.$O\ - -O2=\ - ftoa.$O\ - -O3=\ - atof.$O\ - - -phases: a1 a2 a3 -_obj$D/strconv.a: phases - -a1: $(O1) - $(AR) grc _obj$D/strconv.a atoi.$O decimal.$O itoa.$O quote.$O - rm -f $(O1) - -a2: $(O2) - $(AR) grc _obj$D/strconv.a ftoa.$O - rm -f $(O2) - -a3: $(O3) - $(AR) grc _obj$D/strconv.a atof.$O - rm -f $(O3) - - -newpkg: clean - mkdir -p _obj$D - $(AR) grc _obj$D/strconv.a - -$(O1): newpkg -$(O2): a1 -$(O3): a2 -$(O4): a3 - -nuke: clean - rm -f $(GOROOT)/pkg/$(GOOS)_$(GOARCH)$D/strconv.a - -packages: _obj$D/strconv.a - -install: packages - test -d $(GOROOT)/pkg && mkdir -p $(GOROOT)/pkg/$(GOOS)_$(GOARCH)$D - cp _obj$D/strconv.a $(GOROOT)/pkg/$(GOOS)_$(GOARCH)$D/strconv.a diff --git a/src/lib/strconv/atof.go b/src/lib/strconv/atof.go deleted file mode 100644 index c257b2a33e..0000000000 --- a/src/lib/strconv/atof.go +++ /dev/null @@ -1,372 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// decimal to binary floating point conversion. -// Algorithm: -// 1) Store input in multiprecision decimal. -// 2) Multiply/divide decimal by powers of two until in range [0.5, 1) -// 3) Multiply by 2^precision and round to get mantissa. - -// The strconv package implements conversions to and from -// string representations of basic data types. -package strconv - -import ( - "math"; - "os"; - "strconv"; -) - -var optimize = true // can change for testing - -// TODO(rsc): Better truncation handling. -func stringToDecimal(s string) (neg bool, d *decimal, trunc bool, ok bool) { - i := 0; - - // optional sign - if i >= len(s) { - return; - } - switch { - case s[i] == '+': - i++; - case s[i] == '-': - neg = true; - i++; - } - - // digits - b := new(decimal); - sawdot := false; - sawdigits := false; - for ; i < len(s); i++ { - switch { - case s[i] == '.': - if sawdot { - return; - } - sawdot = true; - b.dp = b.nd; - continue; - - case '0' <= s[i] && s[i] <= '9': - sawdigits = true; - if s[i] == '0' && b.nd == 0 { // ignore leading zeros - b.dp--; - continue; - } - b.d[b.nd] = s[i]; - b.nd++; - continue; - } - break; - } - if !sawdigits { - return; - } - if !sawdot { - b.dp = b.nd; - } - - // optional exponent moves decimal point. - // if we read a very large, very long number, - // 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' { - i++; - if i >= len(s) { - return; - } - esign := 1; - if s[i] == '+' { - i++; - } else if s[i] == '-' { - i++; - esign = -1; - } - if i >= len(s) || s[i] < '0' || s[i] > '9' { - return; - } - e := 0; - for ; i < len(s) && '0' <= s[i] && s[i] <= '9'; i++ { - if e < 10000 { - e = e*10 + int(s[i]) - '0'; - } - } - b.dp += e*esign; - } - - if i != len(s) { - return; - } - - d = b; - ok = true; - return; -} - -// decimal power of ten to binary power of two. -var powtab = []int{ - 1, 3, 6, 9, 13, 16, 19, 23, 26 -} - -func decimalToFloatBits(neg bool, d *decimal, trunc bool, flt *floatInfo) (b uint64, overflow bool) { - var exp int; - var mant uint64; - - // Zero is always a special case. - if d.nd == 0 { - mant = 0; - exp = flt.bias; - goto out; - } - - // Obvious overflow/underflow. - // These bounds are for 64-bit floats. - // Will have to change if we want to support 80-bit floats in the future. - if d.dp > 310 { - goto overflow; - } - if d.dp < -330 { - // zero - mant = 0; - exp = flt.bias; - goto out; - } - - // Scale by powers of two until in range [0.5, 1.0) - exp = 0; - for d.dp > 0 { - var n int; - if d.dp >= len(powtab) { - n = 27; - } else { - n = powtab[d.dp]; - } - d.Shift(-n); - exp += n; - } - for d.dp < 0 || d.dp == 0 && d.d[0] < '5' { - var n int; - if -d.dp >= len(powtab) { - n = 27; - } else { - n = powtab[-d.dp]; - } - d.Shift(n); - exp -= n; - } - - // Our range is [0.5,1) but floating point range is [1,2). - exp--; - - // Minimum representable exponent is flt.bias+1. - // If the exponent is smaller, move it up and - // adjust d accordingly. - if exp < flt.bias+1 { - n := flt.bias+1 - exp; - d.Shift(-n); - exp += n; - } - - if exp-flt.bias >= 1<<flt.expbits - 1 { - goto overflow; - } - - // Extract 1+flt.mantbits bits. - mant = d.Shift(int(1+flt.mantbits)).RoundedInteger(); - - // Rounding might have added a bit; shift down. - if mant == 2<<flt.mantbits { - mant >>= 1; - exp++; - if exp-flt.bias >= 1<<flt.expbits - 1 { - goto overflow; - } - } - - // Denormalized? - if mant&(1<<flt.mantbits) == 0 { - exp = flt.bias; - } - goto out; - -overflow: - // ±Inf - mant = 0; - exp = 1<<flt.expbits - 1 + flt.bias; - overflow = true; - -out: - // Assemble bits. - bits := mant & (uint64(1)<<flt.mantbits - 1); - bits |= uint64((exp-flt.bias)&(1<<flt.expbits - 1)) << flt.mantbits; - if neg { - bits |= 1<<flt.mantbits<<flt.expbits; - } - return bits, overflow; -} - -// 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); - for i := 0; i < d.nd; i++ { - f = f*10 + float64(d.d[i] - '0'); - } - if neg { - f *= -1; // BUG work around 6g f = -f. - } - return f; -} - -func decimalAtof32Int(neg bool, d *decimal) float32 { - f := float32(0); - for i := 0; i < d.nd; i++ { - f = f*10 + float32(d.d[i] - '0'); - } - if neg { - f *= -1; // BUG work around 6g f = -f. - } - return f; -} - -// Exact powers of 10. -var float64pow10 = []float64 { - 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, - 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, - 1e20, 1e21, 1e22 -} -var float32pow10 = []float32 { - 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10 -} - -// If possible to convert decimal d to 64-bit float f exactly, -// entirely in floating-point math, do so, avoiding the expense of decimalToFloatBits. -// Three common cases: -// value is exact integer -// value is exact integer * exact power of ten -// value is exact integer / exact power of ten -// These all produce potentially inexact but correctly rounded answers. -func decimalAtof64(neg bool, d *decimal, trunc bool) (f float64, ok bool) { - // Exact integers are <= 10^15. - // Exact powers of ten are <= 10^22. - if d.nd > 15 { - return; - } - switch { - case d.dp == d.nd: // int - f := decimalAtof64Int(neg, d); - return f, true; - - case d.dp > d.nd && d.dp <= 15+22: // int * 10^k - f := decimalAtof64Int(neg, d); - k := d.dp - d.nd; - // If exponent is big but number of digits is not, - // can move a few zeros into the integer part. - if k > 22 { - f *= float64pow10[k-22]; - k = 22; - } - return f*float64pow10[k], true; - - case d.dp < d.nd && d.nd - d.dp <= 22: // int / 10^k - f := decimalAtof64Int(neg, d); - return f/float64pow10[d.nd - d.dp], true; - } - return; -} - -// If possible to convert decimal d to 32-bit float f exactly, -// entirely in floating-point math, do so, avoiding the machinery above. -func decimalAtof32(neg bool, d *decimal, trunc bool) (f float32, ok bool) { - // Exact integers are <= 10^7. - // Exact powers of ten are <= 10^10. - if d.nd > 7 { - return; - } - switch { - case d.dp == d.nd: // int - f := decimalAtof32Int(neg, d); - return f, true; - - case d.dp > d.nd && d.dp <= 7+10: // int * 10^k - f := decimalAtof32Int(neg, d); - k := d.dp - d.nd; - // If exponent is big but number of digits is not, - // can move a few zeros into the integer part. - if k > 10 { - f *= float32pow10[k-10]; - k = 10; - } - return f*float32pow10[k], true; - - case d.dp < d.nd && d.nd - d.dp <= 10: // int / 10^k - f := decimalAtof32Int(neg, d); - return f/float32pow10[d.nd - d.dp], true; - } - return; -} - -// Atof32 converts the string s to a 32-bit floating-point number. -// -// If s is well-formed and near a valid floating point number, -// Atof32 returns the nearest floating point number rounded -// using IEEE754 unbiased rounding. -// -// If s is not syntactically well-formed, Atof32 returns err = os.EINVAL. -// -// If s is syntactically well-formed but is more than 1/2 ULP -// away from the largest floating point number of the given size, -// Atof32 returns f = ±Inf, err = os.ERANGE. -func Atof32(s string) (f float32, err os.Error) { - neg, d, trunc, ok := stringToDecimal(s); - if !ok { - return 0, os.EINVAL; - } - if optimize { - if f, ok := decimalAtof32(neg, d, trunc); ok { - return f, nil; - } - } - b, ovf := decimalToFloatBits(neg, d, trunc, &float32info); - f = math.Float32frombits(uint32(b)); - if ovf { - err = os.ERANGE; - } - return f, err -} - -// Atof64 converts the string s to a 64-bit floating-point number. -// 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) { - neg, d, trunc, ok := stringToDecimal(s); - if !ok { - return 0, os.EINVAL; - } - if optimize { - if f, ok := decimalAtof64(neg, d, trunc); ok { - return f, nil; - } - } - b, ovf := decimalToFloatBits(neg, d, trunc, &float64info); - f = math.Float64frombits(b); - if ovf { - err = os.ERANGE; - } - 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; -} - diff --git a/src/lib/strconv/atof_test.go b/src/lib/strconv/atof_test.go deleted file mode 100644 index 6782f274a2..0000000000 --- a/src/lib/strconv/atof_test.go +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package strconv -import ( - "fmt"; - "os"; - "strconv"; - "testing" -) - -type atofTest struct { - in string; - out string; - err os.Error; -} - -var atoftests = []atofTest { - atofTest{ "", "0", os.EINVAL }, - atofTest{ "1", "1", nil }, - atofTest{ "+1", "1", nil }, - atofTest{ "1x", "0", os.EINVAL }, - atofTest{ "1.1.", "0", os.EINVAL }, - atofTest{ "1e23", "1e+23", nil }, - atofTest{ "100000000000000000000000", "1e+23", nil }, - atofTest{ "1e-100", "1e-100", nil }, - atofTest{ "123456700", "1.234567e+08", nil }, - atofTest{ "99999999999999974834176", "9.999999999999997e+22", nil }, - atofTest{ "100000000000000000000001", "1.0000000000000001e+23", nil }, - atofTest{ "100000000000000008388608", "1.0000000000000001e+23", nil }, - atofTest{ "100000000000000016777215", "1.0000000000000001e+23", nil }, - atofTest{ "100000000000000016777216", "1.0000000000000003e+23", nil }, - atofTest{ "-1", "-1", nil }, - atofTest{ "-0", "-0", nil }, - atofTest{ "1e-20", "1e-20", nil }, - atofTest{ "625e-3", "0.625", nil }, - - // largest float64 - atofTest{ "1.7976931348623157e308", "1.7976931348623157e+308", nil }, - atofTest{ "-1.7976931348623157e308", "-1.7976931348623157e+308", nil }, - // next float64 - too large - atofTest{ "1.7976931348623159e308", "+Inf", os.ERANGE }, - atofTest{ "-1.7976931348623159e308", "-Inf", os.ERANGE }, - // the border is ...158079 - // borderline - okay - atofTest{ "1.7976931348623158e308", "1.7976931348623157e+308", nil }, - atofTest{ "-1.7976931348623158e308", "-1.7976931348623157e+308", nil }, - // borderline - too large - atofTest{ "1.797693134862315808e308", "+Inf", os.ERANGE }, - atofTest{ "-1.797693134862315808e308", "-Inf", os.ERANGE }, - - // a little too large - atofTest{ "1e308", "1e+308", nil }, - atofTest{ "2e308", "+Inf", os.ERANGE }, - atofTest{ "1e309", "+Inf", os.ERANGE }, - - // way too large - atofTest{ "1e310", "+Inf", os.ERANGE }, - atofTest{ "-1e310", "-Inf", os.ERANGE }, - atofTest{ "1e400", "+Inf", os.ERANGE }, - atofTest{ "-1e400", "-Inf", os.ERANGE }, - atofTest{ "1e400000", "+Inf", os.ERANGE }, - atofTest{ "-1e400000", "-Inf", os.ERANGE }, - - // denormalized - atofTest{ "1e-305", "1e-305", nil }, - atofTest{ "1e-306", "1e-306", nil }, - atofTest{ "1e-307", "1e-307", nil }, - atofTest{ "1e-308", "1e-308", nil }, - atofTest{ "1e-309", "1e-309", nil }, - atofTest{ "1e-310", "1e-310", nil }, - atofTest{ "1e-322", "1e-322", nil }, - // smallest denormal - atofTest{ "5e-324", "5e-324", nil }, - // too small - atofTest{ "4e-324", "0", nil }, - // way too small - atofTest{ "1e-350", "0", nil }, - atofTest{ "1e-400000", "0", nil }, - - // try to overflow exponent - atofTest{ "1e-4294967296", "0", nil }, - atofTest{ "1e+4294967296", "+Inf", os.ERANGE }, - atofTest{ "1e-18446744073709551616", "0", nil }, - atofTest{ "1e+18446744073709551616", "+Inf", os.ERANGE }, - - // Parse errors - atofTest{ "1e", "0", os.EINVAL }, - atofTest{ "1e-", "0", os.EINVAL }, - atofTest{ ".e-1", "0", os.EINVAL }, -} - -func testAtof(t *testing.T, opt bool) { - oldopt := strconv.optimize; - strconv.optimize = opt; - for i := 0; i < len(atoftests); i++ { - test := &atoftests[i]; - out, err := strconv.Atof64(test.in); - outs := strconv.Ftoa64(out, 'g', -1); - if outs != test.out || err != test.err { - t.Errorf("strconv.Atof64(%v) = %v, %v want %v, %v\n", - test.in, out, err, test.out, test.err); - } - - if float64(float32(out)) == out { - out32, err := strconv.Atof32(test.in); - outs := strconv.Ftoa32(out32, 'g', -1); - if outs != test.out || err != test.err { - t.Errorf("strconv.Atof32(%v) = %v, %v want %v, %v # %v\n", - test.in, out32, err, test.out, test.err, out); - } - } - - if FloatSize == 64 || float64(float32(out)) == out { - outf, err := strconv.Atof(test.in); - outs := strconv.Ftoa(outf, 'g', -1); - if outs != test.out || err != test.err { - t.Errorf("strconv.Ftoa(%v) = %v, %v want %v, %v # %v\n", - test.in, outf, err, test.out, test.err, out); - } - } - } - strconv.optimize = oldopt; -} - -func TestAtof(t *testing.T) { - testAtof(t, true); -} - -func TestAtofSlow(t *testing.T) { - testAtof(t, false); -} diff --git a/src/lib/strconv/atoi.go b/src/lib/strconv/atoi.go deleted file mode 100644 index a5d896a05e..0000000000 --- a/src/lib/strconv/atoi.go +++ /dev/null @@ -1,166 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package strconv -import "os" - -func computeIntsize() uint { - siz := uint(8); - for 1<<siz != 0 { - siz *= 2 - } - return siz -} -var intsize = computeIntsize(); - -// Return the first number n such that n*base >= 1<<64. -func cutoff64(base int) uint64 { - if base < 2 { - return 0; - } - return (1<<64 - 1) / uint64(base) + 1; -} - -// Btoui64 interprets a string s in an arbitrary base b (2 to 36) -// and returns the corresponding value n. -// -// Btoui64 returns err == os.EINVAL if b is out of -// range or s is empty or contains invalid digits. -// It returns err == os.ERANGE if the value corresponding -// to s cannot be represented by a uint64. -func Btoui64(s string, b int) (n uint64, err os.Error) { - if b < 2 || b > 36 || len(s) < 1 { - return 0, os.EINVAL; - } - - n = 0; - cutoff := cutoff64(b); - - for i := 0; i < len(s); i++ { - var v byte; - switch { - case '0' <= s[i] && s[i] <= '9': - v = s[i] - '0'; - case 'a' <= s[i] && s[i] <= 'z': - v = s[i] - 'a' + 10; - case 'A' <= s[i] && s[i] <= 'Z': - v = s[i] - 'A' + 10; - default: - return 0, os.EINVAL; - } - if int(v) >= b { - return 0, os.EINVAL; - } - - if n >= cutoff { - // n*b overflows - return 1<<64-1, os.ERANGE; - } - n *= uint64(b); - - n1 := n+uint64(v); - if n1 < n { - // n+v overflows - return 1<<64-1, os.ERANGE; - } - n = n1; - } - - return n, nil; -} - -// Atoui64 interprets a string s as an unsigned decimal, octal, or -// hexadecimal number and returns the corresponding value n. -// The default base is decimal. Strings beginning with 0x are -// hexadecimal; strings beginning with 0 are octal. -// -// Atoui64 returns err == os.EINVAL if s is empty or contains invalid digits. -// It returns err == os.ERANGE if s cannot be represented by a uint64. -func Atoui64(s string) (n uint64, err os.Error) { - // Empty string bad. - if len(s) == 0 { - return 0, os.EINVAL - } - - // Look for octal, hex prefix. - if s[0] == '0' && len(s) > 1 { - if s[1] == 'x' || s[1] == 'X' { - // hex - return Btoui64(s[2:len(s)], 16); - } - // octal - return Btoui64(s[1:len(s)], 8); - } - // decimal - return Btoui64(s, 10); -} - - -// Atoi64 is like Atoui64 but allows signed numbers and -// returns its result in an int64. -func Atoi64(s string) (i int64, err os.Error) { - // Empty string bad. - if len(s) == 0 { - return 0, os.EINVAL - } - - // Pick off leading sign. - neg := false; - if s[0] == '+' { - s = s[1:len(s)] - } else if s[0] == '-' { - neg = true; - s = s[1:len(s)] - } - - // Convert unsigned and check range. - var un uint64; - un, err = Atoui64(s); - if err != nil && err != os.ERANGE { - return 0, err - } - if !neg && un >= 1<<63 { - return 1<<63-1, os.ERANGE - } - if neg && un > 1<<63 { - return -1<<63, os.ERANGE - } - n := int64(un); - if neg { - n = -n - } - return n, nil -} - -// Atoui is like Atoui64 but returns its result as a uint. -func Atoui(s string) (i uint, err os.Error) { - i1, e1 := Atoui64(s); - if e1 != nil && e1 != os.ERANGE { - return 0, e1 - } - i = uint(i1); - if uint64(i) != i1 { - // TODO: return uint(^0), os.ERANGE. - i1 = 1<<64-1; - return uint(i1), os.ERANGE - } - return i, nil -} - -// Atoi is like Atoi64 but returns its result as an int. -func Atoi(s string) (i int, err os.Error) { - i1, e1 := Atoi64(s); - if e1 != nil && e1 != os.ERANGE { - return 0, e1 - } - i = int(i1); - if int64(i) != i1 { - if i1 < 0 { - return -1<<(intsize-1), os.ERANGE - } - return 1<<(intsize-1) - 1, os.ERANGE - } - return i, nil -} - diff --git a/src/lib/strconv/atoi_test.go b/src/lib/strconv/atoi_test.go deleted file mode 100644 index e4a9f955d9..0000000000 --- a/src/lib/strconv/atoi_test.go +++ /dev/null @@ -1,188 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package strconv - -import ( - "fmt"; - "os"; - "strconv"; - "testing" -) - -type atoui64Test struct { - in string; - out uint64; - err os.Error; -} - -var atoui64tests = []atoui64Test { - atoui64Test{"", 0, os.EINVAL}, - atoui64Test{"0", 0, nil}, - atoui64Test{"1", 1, nil}, - atoui64Test{"12345", 12345, nil}, - atoui64Test{"012345", 012345, nil}, - atoui64Test{"0x12345", 0x12345, nil}, - atoui64Test{"0X12345", 0x12345, nil}, - atoui64Test{"12345x", 0, os.EINVAL}, - atoui64Test{"98765432100", 98765432100, nil}, - atoui64Test{"18446744073709551615", 1<<64-1, nil}, - atoui64Test{"18446744073709551616", 1<<64-1, os.ERANGE}, - atoui64Test{"18446744073709551620", 1<<64-1, os.ERANGE}, - atoui64Test{"0xFFFFFFFFFFFFFFFF", 1<<64-1, nil}, - atoui64Test{"0x10000000000000000", 1<<64-1, os.ERANGE}, - atoui64Test{"01777777777777777777777", 1<<64-1, nil}, - atoui64Test{"01777777777777777777778", 0, os.EINVAL}, - atoui64Test{"02000000000000000000000", 1<<64-1, os.ERANGE}, - atoui64Test{"0200000000000000000000", 1<<61, nil}, -} - -type atoi64Test struct { - in string; - out int64; - err os.Error; -} - -var atoi64test = []atoi64Test { - atoi64Test{"", 0, os.EINVAL}, - atoi64Test{"0", 0, nil}, - atoi64Test{"-0", 0, nil}, - atoi64Test{"1", 1, nil}, - atoi64Test{"-1", -1, nil}, - atoi64Test{"12345", 12345, nil}, - atoi64Test{"-12345", -12345, nil}, - atoi64Test{"012345", 012345, nil}, - atoi64Test{"-012345", -012345, nil}, - atoi64Test{"0x12345", 0x12345, nil}, - atoi64Test{"-0X12345", -0x12345, nil}, - atoi64Test{"12345x", 0, os.EINVAL}, - atoi64Test{"-12345x", 0, os.EINVAL}, - atoi64Test{"98765432100", 98765432100, nil}, - atoi64Test{"-98765432100", -98765432100, nil}, - atoi64Test{"9223372036854775807", 1<<63-1, nil}, - atoi64Test{"-9223372036854775807", -(1<<63-1), nil}, - atoi64Test{"9223372036854775808", 1<<63-1, os.ERANGE}, - atoi64Test{"-9223372036854775808", -1<<63, nil}, - atoi64Test{"9223372036854775809", 1<<63-1, os.ERANGE}, - atoi64Test{"-9223372036854775809", -1<<63, os.ERANGE}, -} - -type atoui32Test struct { - in string; - out uint32; - err os.Error; -} - -var atoui32tests = []atoui32Test { - atoui32Test{"", 0, os.EINVAL}, - atoui32Test{"0", 0, nil}, - atoui32Test{"1", 1, nil}, - atoui32Test{"12345", 12345, nil}, - atoui32Test{"012345", 012345, nil}, - atoui32Test{"0x12345", 0x12345, nil}, - atoui32Test{"0X12345", 0x12345, nil}, - atoui32Test{"12345x", 0, os.EINVAL}, - atoui32Test{"987654321", 987654321, nil}, - atoui32Test{"4294967295", 1<<32-1, nil}, - atoui32Test{"4294967296", 1<<32-1, os.ERANGE}, -} - -type atoi32Test struct { - in string; - out int32; - err os.Error; -} - -var atoi32tests = []atoi32Test { - atoi32Test{"", 0, os.EINVAL}, - atoi32Test{"0", 0, nil}, - atoi32Test{"-0", 0, nil}, - atoi32Test{"1", 1, nil}, - atoi32Test{"-1", -1, nil}, - atoi32Test{"12345", 12345, nil}, - atoi32Test{"-12345", -12345, nil}, - atoi32Test{"012345", 012345, nil}, - atoi32Test{"-012345", -012345, nil}, - atoi32Test{"0x12345", 0x12345, nil}, - atoi32Test{"-0X12345", -0x12345, nil}, - atoi32Test{"12345x", 0, os.EINVAL}, - atoi32Test{"-12345x", 0, os.EINVAL}, - atoi32Test{"987654321", 987654321, nil}, - atoi32Test{"-987654321", -987654321, nil}, - atoi32Test{"2147483647", 1<<31-1, nil}, - atoi32Test{"-2147483647", -(1<<31-1), nil}, - atoi32Test{"2147483648", 1<<31-1, os.ERANGE}, - atoi32Test{"-2147483648", -1<<31, nil}, - atoi32Test{"2147483649", 1<<31-1, os.ERANGE}, - atoi32Test{"-2147483649", -1<<31, os.ERANGE}, -} - -func TestAtoui64(t *testing.T) { - for i := 0; i < len(atoui64tests); i++ { - test := &atoui64tests[i]; - out, err := strconv.Atoui64(test.in); - if test.out != out || test.err != err { - t.Errorf("strconv.Atoui64(%v) = %v, %v want %v, %v\n", - test.in, out, err, test.out, test.err); - } - } -} - -func TestAtoi64(t *testing.T) { - for i := 0; i < len(atoi64test); i++ { - test := &atoi64test[i]; - out, err := strconv.Atoi64(test.in); - if test.out != out || test.err != err { - t.Errorf("strconv.Atoi64(%v) = %v, %v want %v, %v\n", - test.in, out, err, test.out, test.err); - } - } -} - -func TestAtoui(t *testing.T) { - switch intsize { - case 32: - for i := 0; i < len(atoui32tests); i++ { - test := &atoui32tests[i]; - out, err := strconv.Atoui(test.in); - if test.out != uint32(out) || test.err != err { - t.Errorf("strconv.Atoui(%v) = %v, %v want %v, %v\n", - test.in, out, err, test.out, test.err); - } - } - case 64: - for i := 0; i < len(atoui64tests); i++ { - test := &atoui64tests[i]; - out, err := strconv.Atoui(test.in); - if test.out != uint64(out) || test.err != err { - t.Errorf("strconv.Atoui(%v) = %v, %v want %v, %v\n", - test.in, out, err, test.out, test.err); - } - } - } -} - -func TestAtoi(t *testing.T) { - switch intsize { - case 32: - for i := 0; i < len(atoi32tests); i++ { - test := &atoi32tests[i]; - out, err := strconv.Atoi(test.in); - if test.out != int32(out) || test.err != err { - t.Errorf("strconv.Atoi(%v) = %v, %v want %v, %v\n", - test.in, out, err, test.out, test.err); - } - } - case 64: - for i := 0; i < len(atoi64test); i++ { - test := &atoi64test[i]; - out, err := strconv.Atoi(test.in); - if test.out != int64(out) || test.err != err { - t.Errorf("strconv.Atoi(%v) = %v, %v want %v, %v\n", - test.in, out, err, test.out, test.err); - } - } - } -} - diff --git a/src/lib/strconv/decimal.go b/src/lib/strconv/decimal.go deleted file mode 100644 index 38d9c47fb1..0000000000 --- a/src/lib/strconv/decimal.go +++ /dev/null @@ -1,392 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Multiprecision decimal numbers. -// For floating-point formatting only; not general purpose. -// Only operations are assign and (binary) left/right shift. -// Can do binary floating point in multiprecision decimal precisely -// because 2 divides 10; cannot do decimal floating point -// in multiprecision binary precisely. - -package strconv - -import "bytes" - -type decimal struct { - // TODO(rsc): Can make d[] a bit smaller and add - // truncated bool; - d [2000] byte; // digits - nd int; // number of digits used - dp int; // decimal point -}; -func (a *decimal) String() string; -func (a *decimal) Assign(v uint64); -func (a *decimal) Shift(k int) *decimal; -func (a *decimal) Round(nd int) *decimal; -func (a *decimal) RoundUp(nd int) *decimal; -func (a *decimal) RoundDown(nd int) *decimal; -func (a *decimal) RoundedInteger() uint64; - - -func digitZero(dst []byte) int; - -func (a *decimal) String() string { - n := 10 + a.nd; - if a.dp > 0 { - n += a.dp; - } - if a.dp < 0 { - n += -a.dp; - } - - buf := make([]byte, n); - w := 0; - switch { - case a.nd == 0: - return "0"; - - case a.dp <= 0: - // zeros fill space between decimal point and digits - buf[w] = '0'; - w++; - buf[w] = '.'; - w++; - w += digitZero(buf[w:w+-a.dp]); - w += bytes.Copy(buf[w:w+a.nd], a.d[0:a.nd]); - - case a.dp < a.nd: - // decimal point in middle of digits - w += bytes.Copy(buf[w:w+a.dp], a.d[0:a.dp]); - buf[w] = '.'; - w++; - w += bytes.Copy(buf[w:w+a.nd-a.dp], a.d[a.dp:a.nd]); - - default: - // zeros fill space between digits and decimal point - w += bytes.Copy(buf[w:w+a.nd], a.d[0:a.nd]); - w += digitZero(buf[w:w+a.dp-a.nd]); - } - return string(buf[0:w]); -} - -func copy(dst []byte, src []byte) int { - for i := 0; i < len(dst); i++ { - dst[i] = src[i]; - } - return len(dst); -} - -func digitZero(dst []byte) int { - for i := 0; i < len(dst); i++ { - dst[i] = '0'; - } - return len(dst); -} - -// trim trailing zeros from number. -// (They are meaningless; the decimal point is tracked -// independent of the number of digits.) -func trim(a *decimal) { - for a.nd > 0 && a.d[a.nd-1] == '0' { - a.nd--; - } - if a.nd == 0 { - a.dp = 0; - } -} - -// Assign v to a. -func (a *decimal) Assign(v uint64) { - var buf [50]byte; - - // Write reversed decimal in buf. - n := 0; - for v > 0 { - v1 := v/10; - v -= 10*v1; - buf[n] = byte(v + '0'); - n++; - v = v1; - } - - // Reverse again to produce forward decimal in a.d. - a.nd = 0; - for n--; n>=0; n-- { - a.d[a.nd] = buf[n]; - a.nd++; - } - a.dp = a.nd; - trim(a); -} - -func newDecimal(i uint64) *decimal { - a := new(decimal); - a.Assign(i); - return a; -} - -// Maximum shift that we can do in one pass without overflow. -// Signed int has 31 bits, and we have to be able to accomodate 9<<k. -const maxShift = 27 - -// Binary shift right (* 2) by k bits. k <= maxShift to avoid overflow. -func rightShift(a *decimal, k uint) { - r := 0; // read pointer - w := 0; // write pointer - - // Pick up enough leading digits to cover first shift. - n := 0; - for ; n>>k == 0; r++ { - if r >= a.nd { - if n == 0 { - // a == 0; shouldn't get here, but handle anyway. - a.nd = 0; - return; - } - for n>>k == 0 { - n = n*10; - r++; - } - break; - } - c := int(a.d[r]); - n = n*10 + c-'0'; - } - a.dp -= r-1; - - // Pick up a digit, put down a digit. - for ; r < a.nd; r++ { - c := int(a.d[r]); - dig := n>>k; - n -= dig<<k; - a.d[w] = byte(dig+'0'); - w++; - n = n*10 + c-'0'; - } - - // Put down extra digits. - for n > 0 { - dig := n>>k; - n -= dig<<k; - a.d[w] = byte(dig+'0'); - w++; - n = n*10; - } - - a.nd = w; - trim(a); -} - -// Cheat sheet for left shift: table indexed by shift count giving -// number of new digits that will be introduced by that shift. -// -// For example, leftcheats[4] = {2, "625"}. That means that -// if we are shifting by 4 (multiplying by 16), it will add 2 digits -// when the string prefix is "625" through "999", and one fewer digit -// if the string prefix is "000" through "624". -// -// Credit for this trick goes to Ken. - -type leftCheat struct { - delta int; // number of new digits - cutoff string; // minus one digit if original < a. -} - -var leftcheats = []leftCheat { - // Leading digits of 1/2^i = 5^i. - // 5^23 is not an exact 64-bit floating point number, - // so have to use bc for the math. - /* - seq 27 | sed 's/^/5^/' | bc | - awk 'BEGIN{ print "\tleftCheat{ 0, \"\" }," } - { - log2 = log(2)/log(10) - printf("\tleftCheat{ %d, \"%s\" },\t// * %d\n", - int(log2*NR+1), $0, 2**NR) - }' - */ - leftCheat{ 0, "" }, - leftCheat{ 1, "5" }, // * 2 - leftCheat{ 1, "25" }, // * 4 - leftCheat{ 1, "125" }, // * 8 - leftCheat{ 2, "625" }, // * 16 - leftCheat{ 2, "3125" }, // * 32 - leftCheat{ 2, "15625" }, // * 64 - leftCheat{ 3, "78125" }, // * 128 - leftCheat{ 3, "390625" }, // * 256 - leftCheat{ 3, "1953125" }, // * 512 - leftCheat{ 4, "9765625" }, // * 1024 - leftCheat{ 4, "48828125" }, // * 2048 - leftCheat{ 4, "244140625" }, // * 4096 - leftCheat{ 4, "1220703125" }, // * 8192 - leftCheat{ 5, "6103515625" }, // * 16384 - leftCheat{ 5, "30517578125" }, // * 32768 - leftCheat{ 5, "152587890625" }, // * 65536 - leftCheat{ 6, "762939453125" }, // * 131072 - leftCheat{ 6, "3814697265625" }, // * 262144 - leftCheat{ 6, "19073486328125" }, // * 524288 - leftCheat{ 7, "95367431640625" }, // * 1048576 - leftCheat{ 7, "476837158203125" }, // * 2097152 - leftCheat{ 7, "2384185791015625" }, // * 4194304 - leftCheat{ 7, "11920928955078125" }, // * 8388608 - leftCheat{ 8, "59604644775390625" }, // * 16777216 - leftCheat{ 8, "298023223876953125" }, // * 33554432 - leftCheat{ 8, "1490116119384765625" }, // * 67108864 - leftCheat{ 9, "7450580596923828125" }, // * 134217728 -} - -// Is the leading prefix of b lexicographically less than s? -func prefixIsLessThan(b []byte, s string) bool { - for i := 0; i < len(s); i++ { - if i >= len(b) { - return true; - } - if b[i] != s[i] { - return b[i] < s[i]; - } - } - return false; -} - -// Binary shift left (/ 2) by k bits. k <= maxShift to avoid overflow. -func leftShift(a *decimal, k uint) { - delta := leftcheats[k].delta; - if prefixIsLessThan(a.d[0:a.nd], leftcheats[k].cutoff) { - delta--; - } - - r := a.nd; // read index - w := a.nd + delta; // write index - n := 0; - - // Pick up a digit, put down a digit. - for r--; r >= 0; r-- { - n += (int(a.d[r])-'0') << k; - quo := n/10; - rem := n - 10*quo; - w--; - a.d[w] = byte(rem+'0'); - n = quo; - } - - // Put down extra digits. - for n > 0 { - quo := n/10; - rem := n - 10*quo; - w--; - a.d[w] = byte(rem+'0'); - n = quo; - } - - if w != 0 { - // TODO: Remove - has no business panicking. - panicln("strconv: bad leftShift", w); - } - a.nd += delta; - a.dp += delta; - trim(a); -} - -// Binary shift left (k > 0) or right (k < 0). -// Returns receiver for convenience. -func (a *decimal) Shift(k int) *decimal { - switch { - case a.nd == 0: - // nothing to do: a == 0 - case k > 0: - for k > maxShift { - leftShift(a, maxShift); - k -= maxShift; - } - leftShift(a, uint(k)); - case k < 0: - for k < -maxShift { - rightShift(a, maxShift); - k += maxShift; - } - rightShift(a, uint(-k)); - } - return a; -} - -// If we chop a at nd digits, should we round up? -func shouldRoundUp(a *decimal, nd int) bool { - if nd <= 0 || nd >= a.nd { - return false; - } - if a.d[nd] == '5' && nd+1 == a.nd { // exactly halfway - round to even - return (a.d[nd-1] - '0') % 2 != 0; - } - // not halfway - digit tells all - return a.d[nd] >= '5'; -} - -// Round a to nd digits (or fewer). -// Returns receiver for convenience. -func (a *decimal) Round(nd int) *decimal { - if nd <= 0 || nd >= a.nd { - return a; - } - if(shouldRoundUp(a, nd)) { - return a.RoundUp(nd); - } - return a.RoundDown(nd); -} - -// Round a down to nd digits (or fewer). -// Returns receiver for convenience. -func (a *decimal) RoundDown(nd int) *decimal { - if nd <= 0 || nd >= a.nd { - return a; - } - a.nd = nd; - trim(a); - return a; -} - -// Round a up to nd digits (or fewer). -// Returns receiver for convenience. -func (a *decimal) RoundUp(nd int) *decimal { - if nd <= 0 || nd >= a.nd { - return a; - } - - // round up - for i := nd-1; i >= 0; i-- { - c := a.d[i]; - if c < '9' { // can stop after this digit - a.d[i]++; - a.nd = i+1; - return a; - } - } - - // Number is all 9s. - // Change to single 1 with adjusted decimal point. - a.d[0] = '1'; - a.nd = 1; - a.dp++; - return a; -} - -// Extract integer part, rounded appropriately. -// No guarantees about overflow. -func (a *decimal) RoundedInteger() uint64 { - if a.dp > 20 { - return 0xFFFFFFFFFFFFFFFF; - } - var i int; - n := uint64(0); - for i = 0; i < a.dp && i < a.nd; i++ { - n = n*10 + uint64(a.d[i] - '0'); - } - for ; i < a.dp; i++ { - n *= 10; - } - if shouldRoundUp(a, a.dp) { - n++; - } - return n; -} - diff --git a/src/lib/strconv/decimal_test.go b/src/lib/strconv/decimal_test.go deleted file mode 100644 index bc82861bdd..0000000000 --- a/src/lib/strconv/decimal_test.go +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package strconv - -import ( - "fmt"; - "strconv"; - "testing"; -) - -type shiftTest struct { - i uint64; - shift int; - out string; -} - -var shifttests = []shiftTest { - shiftTest{ 0, -100, "0" }, - shiftTest{ 0, 100, "0" }, - shiftTest{ 1, 100, "1267650600228229401496703205376" }, - shiftTest{ 1, -100, - "0.00000000000000000000000000000078886090522101180541" - "17285652827862296732064351090230047702789306640625" }, - shiftTest{ 12345678, 8, "3160493568" }, - shiftTest{ 12345678, -8, "48225.3046875" }, - shiftTest{ 195312, 9, "99999744" }, - shiftTest{ 1953125, 9, "1000000000" }, -} - -func TestDecimalShift(t *testing.T) { - ok := true; - for i := 0; i < len(shifttests); i++ { - test := &shifttests[i]; - s := strconv.newDecimal(test.i).Shift(test.shift).String(); - if s != test.out { - t.Errorf("Decimal %v << %v = %v, want %v\n", - test.i, test.shift, s, test.out); - } - } -} - -type roundTest struct { - i uint64; - nd int; - down, round, up string; - int uint64; -} - -var roundtests = []roundTest { - roundTest{ 0, 4, "0", "0", "0", 0 }, - roundTest{ 12344999, 4, "12340000", "12340000", "12350000", 12340000 }, - roundTest{ 12345000, 4, "12340000", "12340000", "12350000", 12340000 }, - roundTest{ 12345001, 4, "12340000", "12350000", "12350000", 12350000 }, - roundTest{ 23454999, 4, "23450000", "23450000", "23460000", 23450000 }, - roundTest{ 23455000, 4, "23450000", "23460000", "23460000", 23460000 }, - roundTest{ 23455001, 4, "23450000", "23460000", "23460000", 23460000 }, - - roundTest{ 99994999, 4, "99990000", "99990000", "100000000", 99990000 }, - roundTest{ 99995000, 4, "99990000", "100000000", "100000000", 100000000 }, - roundTest{ 99999999, 4, "99990000", "100000000", "100000000", 100000000 }, - - roundTest{ 12994999, 4, "12990000", "12990000", "13000000", 12990000 }, - roundTest{ 12995000, 4, "12990000", "13000000", "13000000", 13000000 }, - roundTest{ 12999999, 4, "12990000", "13000000", "13000000", 13000000 }, -} - -func TestDecimalRound(t *testing.T) { - for i := 0; i < len(roundtests); i++ { - test := &roundtests[i]; - s := strconv.newDecimal(test.i).RoundDown(test.nd).String(); - if s != test.down { - t.Errorf("Decimal %v RoundDown %d = %v, want %v\n", - test.i, test.nd, s, test.down); - } - s = strconv.newDecimal(test.i).Round(test.nd).String(); - if s != test.round { - t.Errorf("Decimal %v Round %d = %v, want %v\n", - test.i, test.nd, s, test.down); - } - s = strconv.newDecimal(test.i).RoundUp(test.nd).String(); - if s != test.up { - t.Errorf("Decimal %v RoundUp %d = %v, want %v\n", - test.i, test.nd, s, test.up); - } - } -} - -type roundIntTest struct { - i uint64; - shift int; - int uint64; -} - -var roundinttests = []roundIntTest { - roundIntTest{ 0, 100, 0 }, - roundIntTest{ 512, -8, 2 }, - roundIntTest{ 513, -8, 2 }, - roundIntTest{ 640, -8, 2 }, - roundIntTest{ 641, -8, 3 }, - roundIntTest{ 384, -8, 2 }, - roundIntTest{ 385, -8, 2 }, - roundIntTest{ 383, -8, 1 }, - roundIntTest{ 1, 100, 1<<64-1 }, - roundIntTest{ 1000, 0, 1000 }, -} - -func TestDecimalRoundedInteger(t *testing.T) { - for i := 0; i < len(roundinttests); i++ { - test := roundinttests[i]; - // TODO: should be able to use int := here. - int1 := strconv.newDecimal(test.i).Shift(test.shift).RoundedInteger(); - if int1 != test.int { - t.Errorf("Decimal %v >> %v RoundedInteger = %v, want %v\n", - test.i, test.shift, int1, test.int); - } - } -} diff --git a/src/lib/strconv/fp_test.go b/src/lib/strconv/fp_test.go deleted file mode 100644 index 60d7ce6cfb..0000000000 --- a/src/lib/strconv/fp_test.go +++ /dev/null @@ -1,149 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package strconv -import ( - "bufio"; - "fmt"; - "io"; - "os"; - "strconv"; - "strings"; - "testing"; -) - -func pow2(i int) float64 { - switch { - case i < 0: - return 1 / pow2(-i); - case i == 0: - return 1; - case i == 1: - return 2; - } - return pow2(i/2) * pow2(i-i/2); -} - -// Wrapper around strconv.Atof64. Handles dddddp+ddd (binary exponent) -// itself, passes the rest on to strconv.Atof64. -func myatof64(s string) (f float64, ok bool) { - a := strings.Split(s, "p"); - if len(a) == 2 { - n, err := strconv.Atoi64(a[0]); - if err != nil { - return 0, false; - } - e, err1 := strconv.Atoi(a[1]); - if err1 != nil { - println("bad e", a[1]); - return 0, false; - } - v := float64(n); - // We expect that v*pow2(e) fits in a float64, - // but pow2(e) by itself may not. Be careful. - if e <= -1000 { - v *= pow2(-1000); - e += 1000; - for e < 0 { - v /= 2; - e++; - } - return v, true; - } - if e >= 1000 { - v *= pow2(1000); - e -= 1000; - for e > 0 { - v *= 2; - e--; - } - return v, true; - } - return v*pow2(e), true; - } - f1, err := strconv.Atof64(s); - if err != nil { - return 0, false; - } - return f1, true; -} - -// Wrapper around strconv.Atof32. Handles dddddp+ddd (binary exponent) -// itself, passes the rest on to strconv.Atof32. -func myatof32(s string) (f float32, ok bool) { - a := strings.Split(s, "p"); - if len(a) == 2 { - n, err := strconv.Atoi(a[0]); - if err != nil { - println("bad n", a[0]); - return 0, false; - } - e, err1 := strconv.Atoi(a[1]); - if err1 != nil { - println("bad p", a[1]); - return 0, false; - } - return float32(float64(n)*pow2(e)), true; - } - f1, err1 := strconv.Atof32(s); - if err1 != nil { - return 0, false; - } - return f1, true; -} - -func TestFp(t *testing.T) { - f, err := os.Open("testfp.txt", os.O_RDONLY, 0); - if err != nil { - panicln("testfp: open testfp.txt:", err.String()); - } - defer f.Close(); - - b := bufio.NewReader(f); - - lineno := 0; - for { - line, err2 := b.ReadLineString('\n', false); - if err2 == io.ErrEOF { - break; - } - if err2 != nil { - panicln("testfp: read testfp.txt:", err2.String()); - } - lineno++; - if len(line) == 0 || line[0] == '#' { - continue - } - a := strings.Split(line, " "); - if len(a) != 4 { - t.Error("testfp.txt:", lineno, ": wrong field count\n"); - continue; - } - var s string; - var v float64; - switch a[0] { - case "float64": - var ok bool; - v, ok = myatof64(a[2]); - if !ok { - t.Error("testfp.txt:", lineno, ": cannot atof64 ", a[2]); - continue; - } - s = fmt.Sprintf(a[1], v); - case "float32": - v1, ok := myatof32(a[2]); - if !ok { - t.Error("testfp.txt:", lineno, ": cannot atof32 ", a[2]); - continue; - } - s = fmt.Sprintf(a[1], v1); - v = float64(v1); - } - if s != a[3] { - t.Error("testfp.txt:", lineno, ": ", a[0], " ", a[1], " ", a[2], " (", v, ") ", - "want ", a[3], " got ", s); - } -//else print("testfp.txt:", lineno, ": worked! ", s, "\n"); - } -} diff --git a/src/lib/strconv/ftoa.go b/src/lib/strconv/ftoa.go deleted file mode 100644 index b171151758..0000000000 --- a/src/lib/strconv/ftoa.go +++ /dev/null @@ -1,418 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Binary to decimal floating point conversion. -// Algorithm: -// 1) store mantissa in multiprecision decimal -// 2) shift decimal by exponent -// 3) read digits out & format - -package strconv - -import ( - "math"; - "strconv"; -) - -// TODO: move elsewhere? -type floatInfo struct { - mantbits uint; - expbits uint; - bias int; -} -var float32info = floatInfo{ 23, 8, -127 } -var float64info = floatInfo{ 52, 11, -1023 } - -func fmtB(neg bool, mant uint64, exp int, flt *floatInfo) string -func fmtE(neg bool, d *decimal, prec int) string -func fmtF(neg bool, d *decimal, prec int) string -func genericFtoa(bits uint64, fmt byte, prec int, flt *floatInfo) string -func max(a, b int) int -func roundShortest(d *decimal, mant uint64, exp int, flt *floatInfo) - -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). -// -// 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. -// The special precision -1 uses the smallest number of digits -// necessary such that Atof32 will return f exactly. -// -// Ftoa32(f) is not the same as Ftoa64(float32(f)), -// because correct rounding and the number of digits -// needed to identify f depend on the precision of the representation. -func Ftoa32(f float32, fmt byte, prec int) string { - return genericFtoa(uint64(math.Float32bits(f)), fmt, prec, &float32info); -} - -// Ftoa64 is like Ftoa32 but converts a 64-bit floating-point number. -func Ftoa64(f float64, fmt byte, prec int) string { - return genericFtoa(math.Float64bits(f), fmt, prec, &float64info); -} - -// 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); - mant := bits & (uint64(1)<<flt.mantbits - 1); - - switch exp { - case 1<<flt.expbits - 1: - // Inf, NaN - if mant != 0 { - return "NaN"; - } - if neg { - return "-Inf"; - } - return "+Inf"; - - case 0: - // denormalized - exp++; - - default: - // add implicit top bit - mant |= uint64(1)<<flt.mantbits; - } - exp += flt.bias; - - // Pick off easy binary format. - if fmt == 'b' { - return fmtB(neg, mant, exp, flt); - } - - // Create exact decimal representation. - // The shift is exp - flt.mantbits because mant is a 1-bit integer - // followed by a flt.mantbits fraction, and we are treating it as - // a 1+flt.mantbits-bit integer. - d := newDecimal(mant).Shift(exp - int(flt.mantbits)); - - // Round appropriately. - // Negative precision means "only as much as needed to be exact." - shortest := false; - if prec < 0 { - shortest = true; - roundShortest(d, mant, exp, flt); - switch fmt { - case 'e': - prec = d.nd - 1; - case 'f': - prec = max(d.nd - d.dp, 0); - case 'g': - prec = d.nd; - } - } else { - switch fmt { - case 'e': - d.Round(prec+1); - case 'f': - d.Round(d.dp+prec); - case 'g': - if prec == 0 { - prec = 1; - } - d.Round(prec); - } - } - - switch fmt { - case 'e': - return fmtE(neg, d, prec); - case 'f': - return fmtF(neg, d, prec); - case 'g': - // trailing zeros are removed. - if prec > d.nd { - prec = d.nd; - } - // %e is used if the exponent from the conversion - // is less than -4 or greater than or equal to the precision. - // if precision was the shortest possible, use precision 6 for this decision. - eprec := prec; - if shortest { - eprec = 6 - } - exp := d.dp - 1; - if exp < -4 || exp >= eprec { - return fmtE(neg, d, prec - 1); - } - return fmtF(neg, d, max(prec - d.dp, 0)); - } - - return "%" + string(fmt); -} - -// Round d (= mant * 2^exp) to the shortest number of digits -// that will let the original floating point value be precisely -// reconstructed. Size is original floating point size (64 or 32). -func roundShortest(d *decimal, mant uint64, exp int, flt *floatInfo) { - // If mantissa is zero, the number is zero; stop now. - if mant == 0 { - d.nd = 0; - return; - } - - // TODO: Unless exp == minexp, if the number of digits in d - // is less than 17, it seems unlikely that it could not be - // the shortest possible number already. So maybe we can - // bail out without doing the extra multiprecision math here. - - // Compute upper and lower such that any decimal number - // between upper and lower (possibly inclusive) - // will round to the original floating point number. - - // d = mant << (exp - mantbits) - // Next highest floating point number is mant+1 << exp-mantbits. - // Our upper bound is halfway inbetween, mant*2+1 << exp-mantbits-1. - upper := newDecimal(mant*2+1).Shift(exp-int(flt.mantbits)-1); - - // d = mant << (exp - mantbits) - // Next lowest floating point number is mant-1 << exp-mantbits, - // unless mant-1 drops the significant bit and exp is not the minimum exp, - // in which case the next lowest is mant*2-1 << exp-mantbits-1. - // Either way, call it mantlo << explo-mantbits. - // Our lower bound is halfway inbetween, mantlo*2+1 << explo-mantbits-1. - minexp := flt.bias + 1; // minimum possible exponent - var mantlo uint64; - var explo int; - if mant > 1<<flt.mantbits || exp == minexp { - mantlo = mant - 1; - explo = exp; - } else { - mantlo = mant*2-1; - explo = exp-1; - } - lower := newDecimal(mantlo*2+1).Shift(explo-int(flt.mantbits)-1); - - // The upper and lower bounds are possible outputs only if - // the original mantissa is even, so that IEEE round-to-even - // would round to the original mantissa and not the neighbors. - inclusive := mant%2 == 0; - - // Now we can figure out the minimum number of digits required. - // Walk along until d has distinguished itself from upper and lower. - for i := 0; i < d.nd; i++ { - var l, m, u byte; // lower, middle, upper digits - if i < lower.nd { - l = lower.d[i]; - } else { - l = '0'; - } - m = d.d[i]; - if i < upper.nd { - u = upper.d[i]; - } else { - u = '0'; - } - - // Okay to round down (truncate) if lower has a different digit - // or if lower is inclusive and is exactly the result of rounding down. - okdown := l != m || (inclusive && l == m && i+1 == lower.nd); - - // Okay to round up if upper has a different digit and - // either upper is inclusive or upper is bigger than the result of rounding up. - okup := m != u && (inclusive || i+1 < upper.nd); - - // If it's okay to do either, then round to the nearest one. - // If it's okay to do only one, do it. - switch { - case okdown && okup: - d.Round(i+1); - return; - case okdown: - d.RoundDown(i+1); - return; - case okup: - d.RoundUp(i+1); - return; - } - } -} - -// %e: -d.ddddde±dd -func fmtE(neg bool, d *decimal, prec int) string { - buf := make([]byte, 3+max(prec, 0)+30); // "-0." + prec digits + exp - w := 0; // write index - - // sign - if neg { - buf[w] = '-'; - w++; - } - - // first digit - if d.nd == 0 { - buf[w] = '0'; - } else { - buf[w] = d.d[0]; - } - w++; - - // .moredigits - if prec > 0 { - buf[w] = '.'; - w++; - for i := 0; i < prec; i++ { - if 1+i < d.nd { - buf[w] = d.d[1+i]; - } else { - buf[w] = '0'; - } - w++; - } - } - - // e± - buf[w] = 'e'; - w++; - exp := d.dp - 1; - if d.nd == 0 { // special case: 0 has exponent 0 - exp = 0; - } - if exp < 0 { - buf[w] = '-'; - exp = -exp; - } else { - buf[w] = '+'; - } - w++; - - // dddd - // count digits - n := 0; - for e := exp; e > 0; e /= 10 { - n++; - } - // leading zeros - for i := n; i < 2; i++ { - buf[w] = '0'; - w++; - } - // digits - w += n; - n = 0; - for e := exp; e > 0; e /= 10 { - n++; - buf[w-n] = byte(e%10 + '0'); - } - - return string(buf[0:w]); -} - -// %f: -ddddddd.ddddd -func fmtF(neg bool, d *decimal, prec int) string { - buf := make([]byte, 1+max(d.dp, 1)+1+max(prec, 0)); - w := 0; - - // sign - if neg { - buf[w] = '-'; - w++; - } - - // integer, padded with zeros as needed. - if d.dp > 0 { - var i int; - for i = 0; i < d.dp && i < d.nd; i++ { - buf[w] = d.d[i]; - w++; - } - for ; i < d.dp; i++ { - buf[w] = '0'; - w++; - } - } else { - buf[w] = '0'; - w++; - } - - // fraction - if prec > 0 { - buf[w] = '.'; - w++; - for i := 0; i < prec; i++ { - if d.dp+i < 0 || d.dp+i >= d.nd { - buf[w] = '0'; - } else { - buf[w] = d.d[d.dp+i]; - } - w++; - } - } - - return string(buf[0:w]); -} - -// %b: -ddddddddp+ddd -func fmtB(neg bool, mant uint64, exp int, flt *floatInfo) string { - var buf [50]byte; - w := len(buf); - exp -= int(flt.mantbits); - esign := byte('+'); - if exp < 0 { - esign = '-'; - exp = -exp; - } - n := 0; - for exp > 0 || n < 1 { - n++; - w--; - buf[w] = byte(exp%10 + '0'); - exp /= 10 - } - w--; - buf[w] = esign; - w--; - buf[w] = 'p'; - n = 0; - for mant > 0 || n < 1 { - n++; - w--; - buf[w] = byte(mant%10 + '0'); - mant /= 10; - } - if neg { - w--; - buf[w] = '-'; - } - return string(buf[w:len(buf)]); -} - -func max(a, b int) int { - if a > b { - return a; - } - return b; -} - diff --git a/src/lib/strconv/ftoa_test.go b/src/lib/strconv/ftoa_test.go deleted file mode 100644 index 0f0baa5145..0000000000 --- a/src/lib/strconv/ftoa_test.go +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package strconv - -import ( - "math"; - "strconv"; - "testing" -) - -type ftoaTest struct { - f float64; - fmt byte; - prec int; - s string; -} - -func fdiv(a, b float64) float64 { return a / b } // keep compiler in the dark - -const ( - below1e23 = 99999999999999974834176; - above1e23 = 100000000000000008388608; -) - -var ftoatests = []ftoaTest { - ftoaTest{ 1, 'e', 5, "1.00000e+00" }, - ftoaTest{ 1, 'f', 5, "1.00000" }, - ftoaTest{ 1, 'g', 5, "1" }, - ftoaTest{ 1, 'g', -1, "1" }, - ftoaTest{ 20, 'g', -1, "20" }, - ftoaTest{ 1234567.8, 'g', -1, "1.2345678e+06" }, - ftoaTest{ 200000, 'g', -1, "200000" }, - ftoaTest{ 2000000, 'g', -1, "2e+06" }, - - ftoaTest{ 0, 'e', 5, "0.00000e+00" }, - ftoaTest{ 0, 'f', 5, "0.00000" }, - ftoaTest{ 0, 'g', 5, "0" }, - ftoaTest{ 0, 'g', -1, "0" }, - - ftoaTest{ -1, 'e', 5, "-1.00000e+00" }, - ftoaTest{ -1, 'f', 5, "-1.00000" }, - ftoaTest{ -1, 'g', 5, "-1" }, - ftoaTest{ -1, 'g', -1, "-1" }, - - ftoaTest{ 12, 'e', 5, "1.20000e+01" }, - ftoaTest{ 12, 'f', 5, "12.00000" }, - ftoaTest{ 12, 'g', 5, "12" }, - ftoaTest{ 12, 'g', -1, "12" }, - - ftoaTest{ 123456700, 'e', 5, "1.23457e+08" }, - ftoaTest{ 123456700, 'f', 5, "123456700.00000" }, - ftoaTest{ 123456700, 'g', 5, "1.2346e+08" }, - ftoaTest{ 123456700, 'g', -1, "1.234567e+08" }, - - ftoaTest{ 1.2345e6, 'e', 5, "1.23450e+06" }, - ftoaTest{ 1.2345e6, 'f', 5, "1234500.00000" }, - ftoaTest{ 1.2345e6, 'g', 5, "1.2345e+06" }, - - ftoaTest{ 1e23, 'e', 17, "9.99999999999999916e+22" }, - ftoaTest{ 1e23, 'f', 17, "99999999999999991611392.00000000000000000" }, - ftoaTest{ 1e23, 'g', 17, "9.9999999999999992e+22" }, - - ftoaTest{ 1e23, 'e', -1, "1e+23" }, - ftoaTest{ 1e23, 'f', -1, "100000000000000000000000" }, - ftoaTest{ 1e23, 'g', -1, "1e+23" }, - - ftoaTest{ below1e23, 'e', 17, "9.99999999999999748e+22" }, - ftoaTest{ below1e23, 'f', 17, "99999999999999974834176.00000000000000000" }, - ftoaTest{ below1e23, 'g', 17, "9.9999999999999975e+22" }, - - ftoaTest{ below1e23, 'e', -1, "9.999999999999997e+22" }, - ftoaTest{ below1e23, 'f', -1, "99999999999999970000000" }, - ftoaTest{ below1e23, 'g', -1, "9.999999999999997e+22" }, - - ftoaTest{ above1e23, 'e', 17, "1.00000000000000008e+23" }, - ftoaTest{ above1e23, 'f', 17, "100000000000000008388608.00000000000000000" }, - ftoaTest{ above1e23, 'g', 17, "1.0000000000000001e+23" }, - - ftoaTest{ above1e23, 'e', -1, "1.0000000000000001e+23" }, - ftoaTest{ above1e23, 'f', -1, "100000000000000010000000" }, - ftoaTest{ above1e23, 'g', -1, "1.0000000000000001e+23" }, - - ftoaTest{ fdiv(5e-304, 1e20), 'g', -1, "5e-324" }, - ftoaTest{ fdiv(-5e-304, 1e20), 'g', -1, "-5e-324" }, - - ftoaTest{ 32, 'g', -1, "32" }, - ftoaTest{ 32, 'g', 0, "3e+01" }, - - ftoaTest{ 100, 'x', -1, "%x" }, - - ftoaTest{ math.NaN(), 'g', -1, "NaN" }, - ftoaTest{ -math.NaN(), 'g', -1, "NaN" }, - ftoaTest{ math.Inf(0), 'g', -1, "+Inf" }, - ftoaTest{ math.Inf(-1), 'g', -1, "-Inf" }, - ftoaTest{ -math.Inf(0), 'g', -1, "-Inf" }, - - ftoaTest{ -1, 'b', -1, "-4503599627370496p-52" }, -} - -func TestFtoa(t *testing.T) { - if strconv.FloatSize != 32 { - panic("floatsize: ", strconv.FloatSize); - } - for i := 0; i < len(ftoatests); i++ { - test := &ftoatests[i]; - s := strconv.Ftoa64(test.f, test.fmt, test.prec); - if s != test.s { - t.Error("test", test.f, string(test.fmt), test.prec, "want", test.s, "got", s); - } - if float64(float32(test.f)) == test.f && test.fmt != 'b' { - s := strconv.Ftoa32(float32(test.f), test.fmt, test.prec); - if s != test.s { - t.Error("test32", test.f, string(test.fmt), test.prec, "want", test.s, "got", s); - } - } - } -} diff --git a/src/lib/strconv/itoa.go b/src/lib/strconv/itoa.go deleted file mode 100644 index 7f693ea8cf..0000000000 --- a/src/lib/strconv/itoa.go +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package strconv - -// Itob64 returns the string representation of i in the given base. -func Itob64(i int64, base uint) string { - if i == 0 { - return "0" - } - - u := uint64(i); - if i < 0 { - u = -u; - } - - // Assemble decimal in reverse order. - var buf [32]byte; - j := len(buf); - b := uint64(base); - for u > 0 { - j--; - buf[j] = "0123456789abcdefghijklmnopqrstuvwxyz"[u%b]; - u /= b; - } - - if i < 0 { // add sign - j--; - buf[j] = '-' - } - - return string(buf[j:len(buf)]) -} - -// Itoa64 returns the decimal string representation of i. -func Itoa64(i int64) string { - return Itob64(i, 10); -} - -// Itob returns the string representation of i in the given base. -func Itob(i int, base uint) string { - return Itob64(int64(i), base); -} - -// Itoa returns the decimal string representation of i. -func Itoa(i int) string { - return Itob64(int64(i), 10); -} diff --git a/src/lib/strconv/itoa_test.go b/src/lib/strconv/itoa_test.go deleted file mode 100644 index 34caf9a325..0000000000 --- a/src/lib/strconv/itoa_test.go +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package strconv - -import ( - "fmt"; - "os"; - "strconv"; - "testing"; -) - -type itob64Test struct { - in int64; - base uint; - out string; -} - -var itob64tests = []itob64Test { - itob64Test{ 0, 10, "0" }, - itob64Test{ 1, 10, "1" }, - itob64Test{ -1, 10, "-1" }, - itob64Test{ 12345678, 10, "12345678" }, - itob64Test{ -987654321, 10, "-987654321" }, - itob64Test{ 1<<31-1, 10, "2147483647" }, - itob64Test{ -1<<31+1, 10, "-2147483647" }, - itob64Test{ 1<<31, 10, "2147483648" }, - itob64Test{ -1<<31, 10, "-2147483648" }, - itob64Test{ 1<<31+1, 10, "2147483649" }, - itob64Test{ -1<<31-1, 10, "-2147483649" }, - itob64Test{ 1<<32-1, 10, "4294967295" }, - itob64Test{ -1<<32+1, 10, "-4294967295" }, - itob64Test{ 1<<32, 10, "4294967296" }, - itob64Test{ -1<<32, 10, "-4294967296" }, - itob64Test{ 1<<32+1, 10, "4294967297" }, - itob64Test{ -1<<32-1, 10, "-4294967297" }, - itob64Test{ 1<<50, 10, "1125899906842624" }, - itob64Test{ 1<<63-1, 10, "9223372036854775807" }, - itob64Test{ -1<<63+1, 10, "-9223372036854775807" }, - itob64Test{ -1<<63, 10, "-9223372036854775808" }, - - itob64Test{ 0, 2, "0" }, - itob64Test{ 10, 2, "1010" }, - itob64Test{ -1, 2, "-1" }, - itob64Test{ 1<<15, 2, "1000000000000000" }, - - itob64Test{ -8, 8, "-10" }, - itob64Test{ 057635436545, 8, "57635436545" }, - itob64Test{ 1<<24, 8, "100000000" }, - - itob64Test{ 16, 16, "10" }, - itob64Test{ -0x123456789abcdef, 16, "-123456789abcdef" }, - itob64Test{ 1<<63-1, 16, "7fffffffffffffff" }, - - itob64Test{ 16, 17, "g" }, - itob64Test{ 25, 25, "10" }, - itob64Test{ (((((17*35+24)*35+21)*35+34)*35+12)*35+24)*35+32, 35, "holycow" }, - itob64Test{ (((((17*36+24)*36+21)*36+34)*36+12)*36+24)*36+32, 36, "holycow" }, -} - -func TestItoa(t *testing.T) { - for i := 0; i < len(itob64tests); i++ { - test := itob64tests[i]; - - s := strconv.Itob64(test.in, test.base); - if s != test.out { - t.Errorf("strconv.Itob64(%v, %v) = %v want %v\n", - test.in, test.base, s, test.out); - } - - if int64(int(test.in)) == test.in { - s := strconv.Itob(int(test.in), test.base); - if s != test.out { - t.Errorf("strconv.Itob(%v, %v) = %v want %v\n", - test.in, test.base, s, test.out); - } - } - - if test.base == 10 { - s := strconv.Itoa64(test.in); - if s != test.out { - t.Errorf("strconv.Itoa64(%v) = %v want %v\n", - test.in, s, test.out); - } - - if int64(int(test.in)) == test.in { - s := strconv.Itoa(int(test.in)); - if s != test.out { - t.Errorf("strconv.Itoa(%v) = %v want %v\n", - test.in, s, test.out); - } - } - } - } -} - -// TODO: Use once there is a strconv.uitoa -type uitoa64Test struct { - in uint64; - out string; -} - -// TODO: should be able to call this atoui64tests. -var uitoa64tests = []uitoa64Test { - uitoa64Test{ 1<<63-1, "9223372036854775807" }, - uitoa64Test{ 1<<63, "9223372036854775808" }, - uitoa64Test{ 1<<63+1, "9223372036854775809" }, - uitoa64Test{ 1<<64-2, "18446744073709551614" }, - uitoa64Test{ 1<<64-1, "18446744073709551615" }, -} diff --git a/src/lib/strconv/quote.go b/src/lib/strconv/quote.go deleted file mode 100644 index 8d7900d1d7..0000000000 --- a/src/lib/strconv/quote.go +++ /dev/null @@ -1,229 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package strconv - -import ( - "os"; - "utf8"; -) - -const lowerhex = "0123456789abcdef" - -// Quote returns a double-quoted Go string literal -// representing s. The returned string s uses Go escape -// sequences (\t, \n, \xFF, \u0100) for control characters -// and non-ASCII characters. -func Quote(s string) string { - // TODO(rsc): String accumulation could be more efficient. - t := `"`; - for ; len(s) > 0; s = s[1:len(s)] { - switch c := s[0]; { - case c == '"': - t += `\"`; - case c == '\\': - t += `\\`; - case ' ' <= c && c <= '~': - t += string(c); - case c == '\a': - t += `\a`; - case c == '\b': - t += `\b`; - case c == '\f': - t += `\f`; - case c == '\n': - t += `\n`; - case c == '\r': - t += `\r`; - case c == '\t': - t += `\t`; - case c == '\v': - t += `\v`; - - case c < utf8.RuneSelf: - t += `\x` + string(lowerhex[c>>4]) + string(lowerhex[c&0xF]); - - case utf8.FullRuneInString(s): - r, size := utf8.DecodeRuneInString(s); - if r == utf8.RuneError && size == 1 { - goto EscX; - } - s = s[size-1:len(s)]; // next iteration will slice off 1 more - if r < 0x10000 { - t += `\u`; - for j:=uint(0); j<4; j++ { - t += string(lowerhex[(r>>(12-4*j))&0xF]); - } - } else { - t += `\U`; - for j:=uint(0); j<8; j++ { - t += string(lowerhex[(r>>(28-4*j))&0xF]); - } - } - - default: - EscX: - t += `\x`; - t += string(lowerhex[c>>4]); - t += string(lowerhex[c&0xF]); - } - } - t += `"`; - return t; -} - -// CanBackquote returns whether the string s would be -// a valid Go string literal if enclosed in backquotes. -func CanBackquote(s string) bool { - for i := 0; i < len(s); i++ { - if (s[i] < ' ' && s[i] != '\t') || s[i] == '`' { - return false; - } - } - return true; -} - -func unhex(b byte) (v int, ok bool) { - c := int(b); - switch { - case '0' <= c && c <= '9': - return c - '0', true; - case 'a' <= c && c <= 'f': - return c - 'a' + 10, true; - case 'A' <= c && c <= 'F': - return c - 'A' + 10, true; - } - return; -} - -func unquoteChar(s string, q byte) (t, ns string, err os.Error) { - err = os.EINVAL; // assume error for easy return - - // easy cases - switch c := s[0]; { - case c >= utf8.RuneSelf: - r, size := utf8.DecodeRuneInString(s); - return s[0:size], s[size:len(s)], nil; - case c == q: - return; - case c != '\\': - return s[0:1], s[1:len(s)], nil; - } - - // hard case: c is backslash - if len(s) <= 1 { - return; - } - c := s[1]; - s = s[2:len(s)]; - - switch c { - case 'a': - return "\a", s, nil; - case 'b': - return "\b", s, nil; - case 'f': - return "\f", s, nil; - case 'n': - return "\n", s, nil; - case 'r': - return "\r", s, nil; - case 't': - return "\t", s, nil; - case 'v': - return "\v", s, nil; - case 'x', 'u', 'U': - n := 0; - switch c { - case 'x': - n = 2; - case 'u': - n = 4; - case 'U': - n = 8; - } - v := 0; - if len(s) < n { - return; - } - for j := 0; j < n; j++ { - x, ok := unhex(s[j]); - if !ok { - return; - } - v = v<<4 | x; - } - s = s[n:len(s)]; - if c == 'x' { - // single-byte string, possibly not UTF-8 - return string([]byte{byte(v)}), s, nil; - } - if v > utf8.RuneMax { - return; - } - return string(v), s, nil; - case '0', '1', '2', '3', '4', '5', '6', '7': - v := int(c) - '0'; - if len(s) < 2 { - return; - } - for j := 0; j < 2; j++ { // one digit already; two more - x := int(s[j]) - '0'; - if x < 0 || x > 7 { - return; - } - v = (v<<3) | x; - } - s = s[2:len(s)]; - if v > 255 { - return; - } - return string(v), s, nil; - - case '\\', q: - return string(c), s, nil; - } - return; -} - -// Unquote interprets s as a single-quoted, double-quoted, -// or backquoted Go string literal, returning the string value -// that s quotes. (If s is single-quoted, it would be a Go -// character literal; Unquote returns the corresponding -// one-character string.) -func Unquote(s string) (t string, err os.Error) { - err = os.EINVAL; // assume error for easy return - n := len(s); - if n < 2 { - return; - } - quote := s[0]; - if quote != s[n-1] { - return; - } - s = s[1:n-1]; - - if quote == '`' { - return s, nil; - } - if quote != '"' && quote != '\'' { - return; - } - - // TODO(rsc): String accumulation could be more efficient. - var c, tt string; - var err1 os.Error; - for len(s) > 0 { - if c, s, err1 = unquoteChar(s, quote); err1 != nil { - err = err1; - return; - } - tt += c; - if quote == '\'' && len(s) != 0 { - // single-quoted must be single character - return; - } - } - return tt, nil -} diff --git a/src/lib/strconv/quote_test.go b/src/lib/strconv/quote_test.go deleted file mode 100644 index 0fc01ebae3..0000000000 --- a/src/lib/strconv/quote_test.go +++ /dev/null @@ -1,170 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package strconv - -import ( - "os"; - "strconv"; - "testing"; -) - -type quoteTest struct { - in string; - out string; -} - -var quotetests = []quoteTest { - quoteTest{ "\a\b\f\r\n\t\v", `"\a\b\f\r\n\t\v"` }, - quoteTest{ "\\", `"\\"` }, - quoteTest{ "abc\xffdef", `"abc\xffdef"` }, - quoteTest{ "\u263a", `"\u263a"` }, - quoteTest{ "\U0010ffff", `"\U0010ffff"` }, - quoteTest{ "\x04", `"\x04"` }, -} - -func TestQuote(t *testing.T) { - for i := 0; i < len(quotetests); i++ { - tt := quotetests[i]; - if out := Quote(tt.in); out != tt.out { - t.Errorf("Quote(%s) = %s, want %s", tt.in, out, tt.out); - } - } -} - -type canBackquoteTest struct { - in string; - out bool; -} - -var canbackquotetests = []canBackquoteTest { - canBackquoteTest{ "`", false }, - canBackquoteTest{ string(0), false }, - canBackquoteTest{ string(1), false }, - canBackquoteTest{ string(2), false }, - canBackquoteTest{ string(3), false }, - canBackquoteTest{ string(4), false }, - canBackquoteTest{ string(5), false }, - canBackquoteTest{ string(6), false }, - canBackquoteTest{ string(7), false }, - canBackquoteTest{ string(8), false }, - canBackquoteTest{ string(9), true }, // \t - canBackquoteTest{ string(10), false }, - canBackquoteTest{ string(11), false }, - canBackquoteTest{ string(12), false }, - canBackquoteTest{ string(13), false }, - canBackquoteTest{ string(14), false }, - canBackquoteTest{ string(15), false }, - canBackquoteTest{ string(16), false }, - canBackquoteTest{ string(17), false }, - canBackquoteTest{ string(18), false }, - canBackquoteTest{ string(19), false }, - canBackquoteTest{ string(20), false }, - canBackquoteTest{ string(21), false }, - canBackquoteTest{ string(22), false }, - canBackquoteTest{ string(23), false }, - canBackquoteTest{ string(24), false }, - canBackquoteTest{ string(25), false }, - canBackquoteTest{ string(26), false }, - canBackquoteTest{ string(27), false }, - canBackquoteTest{ string(28), false }, - canBackquoteTest{ string(29), false }, - canBackquoteTest{ string(30), false }, - canBackquoteTest{ string(31), false }, - canBackquoteTest{ `' !"#$%&'()*+,-./:;<=>?@[\]^_{|}~`, true }, - canBackquoteTest{ `0123456789`, true }, - canBackquoteTest{ `ABCDEFGHIJKLMNOPQRSTUVWXYZ`, true }, - canBackquoteTest{ `abcdefghijklmnopqrstuvwxyz`, true }, - canBackquoteTest{ `☺`, true }, -} - -func TestCanBackquote(t *testing.T) { - for i := 0; i < len(canbackquotetests); i++ { - tt := canbackquotetests[i]; - if out := CanBackquote(tt.in); out != tt.out { - t.Errorf("CanBackquote(%q) = %v, want %v", tt.in, out, tt.out); - } - } -} - -var unquotetests = []quoteTest { - quoteTest{ `""`, "" }, - quoteTest{ `"a"`, "a" }, - quoteTest{ `"abc"`, "abc" }, - quoteTest{ `"☺"`, "☺" }, - quoteTest{ `"hello world"`, "hello world" }, - quoteTest{ `"\xFF"`, "\xFF" }, - quoteTest{ `"\377"`, "\377" }, - quoteTest{ `"\u1234"`, "\u1234" }, - quoteTest{ `"\U00010111"`, "\U00010111" }, - quoteTest{ `"\U0001011111"`, "\U0001011111" }, - quoteTest{ `"\a\b\f\n\r\t\v\\\""`, "\a\b\f\n\r\t\v\\\"" }, - quoteTest{ `"'"`, "'" }, - - quoteTest{ `'a'`, "a" }, - quoteTest{ `'☹'`, "☹" }, - quoteTest{ `'\a'`, "\a" }, - quoteTest{ `'\x10'`, "\x10" }, - quoteTest{ `'\377'`, "\377" }, - quoteTest{ `'\u1234'`, "\u1234" }, - quoteTest{ `'\U00010111'`, "\U00010111" }, - quoteTest{ `'\t'`, "\t" }, - quoteTest{ `' '`, " " }, - quoteTest{ `'\''`, "'" }, - quoteTest{ `'"'`, "\"" }, - - quoteTest{ "``", `` }, - quoteTest{ "`a`", `a` }, - quoteTest{ "`abc`", `abc` }, - quoteTest{ "`☺`", `☺` }, - quoteTest{ "`hello world`", `hello world` }, - quoteTest{ "`\\xFF`", `\xFF` }, - quoteTest{ "`\\377`", `\377` }, - quoteTest{ "`\\`", `\` }, - quoteTest{ "` `", ` ` }, - quoteTest{ "` `", ` ` }, -} - -var misquoted = []string { - ``, - `"`, - `"a`, - `"'`, - `b"`, - `"\"`, - `'\'`, - `'ab'`, - `"\x1!"`, - `"\U12345678"`, - `"\z"`, - "`", - "`xxx", - "`\"", - `"\'"`, - `'\"'`, -} - -func TestUnquote(t *testing.T) { - for i := 0; i < len(unquotetests); i++ { - tt := unquotetests[i]; - if out, err := Unquote(tt.in); err != nil && out != tt.out { - t.Errorf("Unquote(%s) = %q, %s want %q, nil", tt.in, out, err, tt.out); - } - } - - // run the quote tests too, backward - for i := 0; i < len(quotetests); i++ { - tt := quotetests[i]; - if in, err := Unquote(tt.out); in != tt.in { - t.Errorf("Unquote(%s) = %q, %s, want %q, nil", tt.out, in, err, tt.in); - } - } - - for i := 0; i < len(misquoted); i++ { - s := misquoted[i]; - if out, err := Unquote(s); out != "" || err != os.EINVAL { - t.Errorf("Unquote(%q) = %q, %s want %q, %s", s, out, err, "", os.EINVAL); - } - } -} diff --git a/src/lib/strconv/testfp.txt b/src/lib/strconv/testfp.txt deleted file mode 100644 index 08d3c4ef09..0000000000 --- a/src/lib/strconv/testfp.txt +++ /dev/null @@ -1,181 +0,0 @@ -# Floating-point conversion test cases. -# Empty lines and lines beginning with # are ignored. -# The rest have four fields per line: type, format, input, and output. -# The input is given either in decimal or binary scientific notation. -# The output is the string that should be produced by formatting the -# input with the given format. -# -# The formats are as in C's printf, except that %b means print -# binary scientific notation: NpE = N x 2^E. - -# TODO: -# Powers of 10. -# Powers of 2. -# %.20g versions. -# random sources -# random targets -# random targets ± half a ULP - -# Difficult boundary cases, derived from tables given in -# Vern Paxson, A Program for Testing IEEE Decimal-Binary Conversion -# ftp://ftp.ee.lbl.gov/testbase-report.ps.Z - -# Table 1: Stress Inputs for Conversion to 53-bit Binary, < 1/2 ULP -float64 %b 5e+125 6653062250012735p+365 -float64 %b 69e+267 4705683757438170p+841 -float64 %b 999e-026 6798841691080350p-129 -float64 %b 7861e-034 8975675289889240p-153 -float64 %b 75569e-254 6091718967192243p-880 -float64 %b 928609e-261 7849264900213743p-900 -float64 %b 9210917e+080 8341110837370930p+236 -float64 %b 84863171e+114 4625202867375927p+353 -float64 %b 653777767e+273 5068902999763073p+884 -float64 %b 5232604057e-298 5741343011915040p-1010 -float64 %b 27235667517e-109 6707124626673586p-380 -float64 %b 653532977297e-123 7078246407265384p-422 -float64 %b 3142213164987e-294 8219991337640559p-988 -float64 %b 46202199371337e-072 5224462102115359p-246 -float64 %b 231010996856685e-073 5224462102115359p-247 -float64 %b 9324754620109615e+212 5539753864394442p+705 -float64 %b 78459735791271921e+049 8388176519442766p+166 -float64 %b 272104041512242479e+200 5554409530847367p+670 -float64 %b 6802601037806061975e+198 5554409530847367p+668 -float64 %b 20505426358836677347e-221 4524032052079546p-722 -float64 %b 836168422905420598437e-234 5070963299887562p-760 -float64 %b 4891559871276714924261e+222 6452687840519111p+757 - -# Table 2: Stress Inputs for Conversion to 53-bit Binary, > 1/2 ULP -float64 %b 9e-265 8168427841980010p-930 -float64 %b 85e-037 6360455125664090p-169 -float64 %b 623e+100 6263531988747231p+289 -float64 %b 3571e+263 6234526311072170p+833 -float64 %b 81661e+153 6696636728760206p+472 -float64 %b 920657e-023 5975405561110124p-109 -float64 %b 4603285e-024 5975405561110124p-110 -float64 %b 87575437e-309 8452160731874668p-1053 -float64 %b 245540327e+122 4985336549131723p+381 -float64 %b 6138508175e+120 4985336549131723p+379 -float64 %b 83356057653e+193 5986732817132056p+625 -float64 %b 619534293513e+124 4798406992060657p+399 -float64 %b 2335141086879e+218 5419088166961646p+713 -float64 %b 36167929443327e-159 8135819834632444p-536 -float64 %b 609610927149051e-255 4576664294594737p-850 -float64 %b 3743626360493413e-165 6898586531774201p-549 -float64 %b 94080055902682397e-242 6273271706052298p-800 -float64 %b 899810892172646163e+283 7563892574477827p+947 -float64 %b 7120190517612959703e+120 5385467232557565p+409 -float64 %b 25188282901709339043e-252 5635662608542340p-825 -float64 %b 308984926168550152811e-052 5644774693823803p-157 -float64 %b 6372891218502368041059e+064 4616868614322430p+233 - -# Table 3: Stress Inputs for Converting 53-bit Binary to Decimal, < 1/2 ULP -float64 %.0e 8511030020275656p-342 9e-88 -float64 %.1e 5201988407066741p-824 4.6e-233 -float64 %.2e 6406892948269899p+237 1.41e+87 -float64 %.3e 8431154198732492p+72 3.981e+37 -float64 %.4e 6475049196144587p+99 4.1040e+45 -float64 %.5e 8274307542972842p+726 2.92084e+234 -float64 %.6e 5381065484265332p-456 2.891946e-122 -float64 %.7e 6761728585499734p-1057 4.3787718e-303 -float64 %.8e 7976538478610756p+376 1.22770163e+129 -float64 %.9e 5982403858958067p+377 1.841552452e+129 -float64 %.10e 5536995190630837p+93 5.4835744350e+43 -float64 %.11e 7225450889282194p+710 3.89190181146e+229 -float64 %.12e 7225450889282194p+709 1.945950905732e+229 -float64 %.13e 8703372741147379p+117 1.4460958381605e+51 -float64 %.14e 8944262675275217p-1001 4.17367747458531e-286 -float64 %.15e 7459803696087692p-707 1.107950772878888e-197 -float64 %.16e 6080469016670379p-381 1.2345501366327440e-99 -float64 %.17e 8385515147034757p+721 9.25031711960365024e+232 -float64 %.18e 7514216811389786p-828 4.198047150284889840e-234 -float64 %.19e 8397297803260511p-345 1.1716315319786511046e-88 -float64 %.20e 6733459239310543p+202 4.32810072844612493629e+76 -float64 %.21e 8091450587292794p-473 3.317710118160031081518e-127 - -# Table 4: Stress Inputs for Converting 53-bit Binary to Decimal, > 1/2 ULP -float64 %.0e 6567258882077402p+952 3e+302 -float64 %.1e 6712731423444934p+535 7.6e+176 -float64 %.2e 6712731423444934p+534 3.78e+176 -float64 %.3e 5298405411573037p-957 4.350e-273 -float64 %.4e 5137311167659507p-144 2.3037e-28 -float64 %.5e 6722280709661868p+363 1.26301e+125 -float64 %.6e 5344436398034927p-169 7.142211e-36 -float64 %.7e 8369123604277281p-853 1.3934574e-241 -float64 %.8e 8995822108487663p-780 1.41463449e-219 -float64 %.9e 8942832835564782p-383 4.539277920e-100 -float64 %.10e 8942832835564782p-384 2.2696389598e-100 -float64 %.11e 8942832835564782p-385 1.13481947988e-100 -float64 %.12e 6965949469487146p-249 7.700366561890e-60 -float64 %.13e 6965949469487146p-250 3.8501832809448e-60 -float64 %.14e 6965949469487146p-251 1.92509164047238e-60 -float64 %.15e 7487252720986826p+548 6.898586531774201e+180 -float64 %.16e 5592117679628511p+164 1.3076622631878654e+65 -float64 %.17e 8887055249355788p+665 1.36052020756121240e+216 -float64 %.18e 6994187472632449p+690 3.592810217475959676e+223 -float64 %.19e 8797576579012143p+588 8.9125197712484551899e+192 -float64 %.20e 7363326733505337p+272 5.58769757362301140950e+97 -float64 %.21e 8549497411294502p-448 1.176257830728540379990e-119 - -# Table 14: Stress Inputs for Conversion to 24-bit Binary, <1/2 ULP -# NOTE: The lines with exponent p-149 have been changed from the -# paper. Those entries originally read p-150 and had a mantissa -# twice as large (and even), but IEEE single-precision has no p-150: -# that's the start of the denormals. -float32 %b 5e-20 15474250p-88 -float32 %b 67e+14 12479722p+29 -float32 %b 985e+15 14333636p+36 -# float32 %b 7693e-42 10979816p-150 -float32 %b 7693e-42 5489908p-149 -float32 %b 55895e-16 12888509p-61 -# float32 %b 996622e-44 14224264p-150 -float32 %b 996622e-44 7112132p-149 -float32 %b 7038531e-32 11420669p-107 -# float32 %b 60419369e-46 8623340p-150 -float32 %b 60419369e-46 4311670p-149 -float32 %b 702990899e-20 16209866p-61 -# float32 %b 6930161142e-48 9891056p-150 -float32 %b 6930161142e-48 4945528p-149 -float32 %b 25933168707e+13 14395800p+54 -float32 %b 596428896559e+20 12333860p+82 - -# Table 15: Stress Inputs for Conversion to 24-bit Binary, >1/2 ULP -float32 %b 3e-23 9507380p-98 -float32 %b 57e+18 12960300p+42 -float32 %b 789e-35 10739312p-130 -float32 %b 2539e-18 11990089p-72 -float32 %b 76173e+28 9845130p+86 -float32 %b 887745e-11 9760860p-40 -float32 %b 5382571e-37 11447463p-124 -float32 %b 82381273e-35 8554961p-113 -float32 %b 750486563e-38 9975678p-120 -float32 %b 3752432815e-39 9975678p-121 -float32 %b 75224575729e-45 13105970p-137 -float32 %b 459926601011e+15 12466336p+65 - -# Table 16: Stress Inputs for Converting 24-bit Binary to Decimal, < 1/2 ULP -float32 %.0e 12676506p-102 2e-24 -float32 %.1e 12676506p-103 1.2e-24 -float32 %.2e 15445013p+86 1.19e+33 -float32 %.3e 13734123p-138 3.941e-35 -float32 %.4e 12428269p-130 9.1308e-33 -float32 %.5e 15334037p-146 1.71900e-37 -float32 %.6e 11518287p-41 5.237910e-06 -float32 %.7e 12584953p-145 2.8216440e-37 -float32 %.8e 15961084p-125 3.75243281e-31 -float32 %.9e 14915817p-146 1.672120916e-37 -float32 %.10e 10845484p-102 2.1388945814e-24 -float32 %.11e 16431059p-61 7.12583594561e-12 - -# Table 17: Stress Inputs for Converting 24-bit Binary to Decimal, > 1/2 ULP -float32 %.0e 16093626p+69 1e+28 -float32 %.1e 9983778p+25 3.4e+14 -float32 %.2e 12745034p+104 2.59e+38 -float32 %.3e 12706553p+72 6.001e+28 -float32 %.4e 11005028p+45 3.8721e+20 -float32 %.5e 15059547p+71 3.55584e+28 -float32 %.6e 16015691p-99 2.526831e-23 -float32 %.7e 8667859p+56 6.2458507e+23 -float32 %.8e 14855922p-82 3.07213267e-18 -float32 %.9e 14855922p-83 1.536066333e-18 -float32 %.10e 10144164p-110 7.8147796834e-27 -float32 %.11e 13248074p+95 5.24810279937e+35 |
