math/big: parsing of fractions and floats in mantissa bases other than 10

Change-Id: I1eaebf956a69e0958201cc5e0a9beefa062c71e1
Reviewed-on: https://go-review.googlesource.com/3454
Reviewed-by: Alan Donovan <adonovan@google.com>
diff --git a/src/math/big/float_test.go b/src/math/big/float_test.go
index e8a14bf..940cb6d 100644
--- a/src/math/big/float_test.go
+++ b/src/math/big/float_test.go
@@ -79,7 +79,7 @@
 
 // TestFloatRound tests basic rounding.
 func TestFloatRound(t *testing.T) {
-	var tests = []struct {
+	for _, test := range []struct {
 		prec                        uint
 		x, zero, neven, naway, away string // input, results rounded to prec bits
 	}{
@@ -154,9 +154,7 @@
 		{1, "1101001", "1000000", "10000000", "10000000", "10000000"},
 		{1, "1110001", "1000000", "10000000", "10000000", "10000000"},
 		{1, "1111001", "1000000", "10000000", "10000000", "10000000"},
-	}
-
-	for _, test := range tests {
+	} {
 		x := fromBinary(test.x)
 		z := fromBinary(test.zero)
 		e := fromBinary(test.neven)
@@ -195,7 +193,7 @@
 }
 
 func TestFloatSetUint64(t *testing.T) {
-	var tests = []uint64{
+	for _, want := range []uint64{
 		0,
 		1,
 		2,
@@ -204,8 +202,7 @@
 		1<<32 - 1,
 		1 << 32,
 		1<<64 - 1,
-	}
-	for _, want := range tests {
+	} {
 		f := new(Float).SetUint64(want)
 		if got := f.Uint64(); got != want {
 			t.Errorf("got %d (%s); want %d", got, f.pstring(), want)
@@ -214,7 +211,7 @@
 }
 
 func TestFloatSetInt64(t *testing.T) {
-	var tests = []int64{
+	for _, want := range []int64{
 		0,
 		1,
 		2,
@@ -223,8 +220,7 @@
 		1<<32 - 1,
 		1 << 32,
 		1<<63 - 1,
-	}
-	for _, want := range tests {
+	} {
 		for i := range [2]int{} {
 			if i&1 != 0 {
 				want = -want
@@ -238,7 +234,7 @@
 }
 
 func TestFloatSetFloat64(t *testing.T) {
-	var tests = []float64{
+	for _, want := range []float64{
 		0,
 		1,
 		2,
@@ -248,8 +244,7 @@
 		3.14159265e10,
 		2.718281828e-123,
 		1.0 / 3,
-	}
-	for _, want := range tests {
+	} {
 		for i := range [2]int{} {
 			if i&1 != 0 {
 				want = -want
@@ -396,7 +391,7 @@
 // TestFloatMul64 tests that Float.Mul/Quo of numbers with
 // 53bit mantissa behaves like float64 multiplication/division.
 func TestFloatMul64(t *testing.T) {
-	var tests = []struct {
+	for _, test := range []struct {
 		x, y float64
 	}{
 		{0, 0},
@@ -407,8 +402,7 @@
 		{2.718281828, 3.14159265358979},
 		{2.718281828e10, 3.14159265358979e-32},
 		{1.0 / 3, 1e200},
-	}
-	for _, test := range tests {
+	} {
 		for i := range [8]int{} {
 			x0, y0 := test.x, test.y
 			if i&1 != 0 {
@@ -552,7 +546,7 @@
 }
 
 func TestNormBits(t *testing.T) {
-	var tests = []struct {
+	for _, test := range []struct {
 		x, want []int
 	}{
 		{nil, nil},
@@ -561,9 +555,7 @@
 		{[]int{0, 0}, []int{1}},
 		{[]int{3, 1, 1}, []int{2, 3}},
 		{[]int{10, 9, 8, 7, 6, 6}, []int{11}},
-	}
-
-	for _, test := range tests {
+	} {
 		got := fmt.Sprintf("%v", normBits(test.x))
 		want := fmt.Sprintf("%v", test.want)
 		if got != want {
@@ -665,27 +657,25 @@
 }
 
 func TestFromBits(t *testing.T) {
-	var tests = []struct {
+	for _, test := range []struct {
 		bits []int
 		want string
 	}{
 		// all different bit numbers
 		{nil, "0"},
-		{[]int{0}, "0.8p1"},
-		{[]int{1}, "0.8p2"},
-		{[]int{-1}, "0.8p0"},
-		{[]int{63}, "0.8p64"},
-		{[]int{33, -30}, "0.8000000000000001p34"},
-		{[]int{255, 0}, "0.8000000000000000000000000000000000000000000000000000000000000001p256"},
+		{[]int{0}, "0x.8p1"},
+		{[]int{1}, "0x.8p2"},
+		{[]int{-1}, "0x.8p0"},
+		{[]int{63}, "0x.8p64"},
+		{[]int{33, -30}, "0x.8000000000000001p34"},
+		{[]int{255, 0}, "0x.8000000000000000000000000000000000000000000000000000000000000001p256"},
 
 		// multiple equal bit numbers
-		{[]int{0, 0}, "0.8p2"},
-		{[]int{0, 0, 0, 0}, "0.8p3"},
-		{[]int{0, 1, 0}, "0.8p3"},
-		{append([]int{2, 1, 0} /* 7 */, []int{3, 1} /* 10 */ ...), "0.88p5" /* 17 */},
-	}
-
-	for _, test := range tests {
+		{[]int{0, 0}, "0x.8p2"},
+		{[]int{0, 0, 0, 0}, "0x.8p3"},
+		{[]int{0, 1, 0}, "0x.8p3"},
+		{append([]int{2, 1, 0} /* 7 */, []int{3, 1} /* 10 */ ...), "0x.88p5" /* 17 */},
+	} {
 		f := fromBits(test.bits...)
 		if got := f.pstring(); got != test.want {
 			t.Errorf("setBits(%v) = %s; want %s", test.bits, got, test.want)
@@ -757,19 +747,39 @@
 	}
 }
 
-func TestFloatpstring(t *testing.T) {
-	var tests = []struct {
-		x    Float
-		want string
+func TestFloatFormat(t *testing.T) {
+	for _, test := range []struct {
+		x      string
+		format byte
+		prec   int
+		want   string
 	}{
-		{Float{}, "0"},
-		{Float{neg: true}, "-0"},
-		{Float{mant: nat{0x87654321}}, "0.87654321p0"},
-		{Float{mant: nat{0x87654321}, exp: -10}, "0.87654321p-10"},
-	}
-	for _, test := range tests {
-		if got := test.x.pstring(); got != test.want {
-			t.Errorf("%v: got %s; want %s", test.x, got, test.want)
+		{"0", 'b', 0, "0"},
+		{"-0", 'b', 0, "-0"},
+		{"1.0", 'b', 0, "4503599627370496p1"},
+		{"-1.0", 'b', 0, "-4503599627370496p1"},
+
+		{"0", 'p', 0, "0"},
+		{"-0", 'p', 0, "-0"},
+		{"1024.0", 'p', 0, "0x.8p11"},
+		{"-1024.0", 'p', 0, "-0x.8p11"},
+	} {
+		f64, err := strconv.ParseFloat(test.x, 64)
+		if err != nil {
+			t.Error(err)
+			continue
+		}
+		f := new(Float).SetFloat64(f64)
+		got := f.Format(test.format, test.prec)
+		if got != test.want {
+			t.Errorf("%v: got %s", test, got)
+		}
+		if test.format == 'b' || test.format == 'p' {
+			continue // 'b', 'p' format not supported or different in strconv.Format
+		}
+		want := strconv.FormatFloat(f64, test.format, test.prec, 64)
+		if got != want {
+			t.Errorf("%v: got %s; want %s", test, got, want)
 		}
 	}
 }