From: Robert Griesemer Date: Fri, 30 Jan 2015 23:57:38 +0000 (-0800) Subject: math/big: build Float.Format on top of Float.Append X-Git-Tag: go1.5beta1~2158 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=4c91c0d07b7da552a57ec2b7a33b1d6b46d4889c;p=gostls13.git math/big: build Float.Format on top of Float.Append Change-Id: I444eec24467f827caa5c88a1c5ae5bce92508b98 Reviewed-on: https://go-review.googlesource.com/3750 Reviewed-by: Alan Donovan --- diff --git a/src/math/big/float.go b/src/math/big/float.go index 7047a6d996..1c3fcb5f74 100644 --- a/src/math/big/float.go +++ b/src/math/big/float.go @@ -176,7 +176,7 @@ func (x *Float) validate() { const msb = 1 << (_W - 1) m := len(x.mant) if x.mant[m-1]&msb == 0 { - panic(fmt.Sprintf("msb not set in last word %#x of %s", x.mant[m-1], x.pstring())) + panic(fmt.Sprintf("msb not set in last word %#x of %s", x.mant[m-1], x.Format('p', 0))) } if x.prec <= 0 { panic(fmt.Sprintf("invalid precision %d", x.prec)) diff --git a/src/math/big/float_test.go b/src/math/big/float_test.go index 3281f2745a..ec67a6d606 100644 --- a/src/math/big/float_test.go +++ b/src/math/big/float_test.go @@ -205,7 +205,7 @@ func TestFloatSetUint64(t *testing.T) { } { f := new(Float).SetUint64(want) if got := f.Uint64(); got != want { - t.Errorf("got %d (%s); want %d", got, f.pstring(), want) + t.Errorf("got %d (%s); want %d", got, f.Format('p', 0), want) } } } @@ -227,7 +227,7 @@ func TestFloatSetInt64(t *testing.T) { } f := new(Float).SetInt64(want) if got := f.Int64(); got != want { - t.Errorf("got %d (%s); want %d", got, f.pstring(), want) + t.Errorf("got %d (%s); want %d", got, f.Format('p', 0), want) } } } @@ -251,7 +251,7 @@ func TestFloatSetFloat64(t *testing.T) { } f := new(Float).SetFloat64(want) if got, _ := f.Float64(); got != want { - t.Errorf("got %g (%s); want %g", got, f.pstring(), want) + t.Errorf("got %g (%s); want %g", got, f.Format('p', 0), want) } } } @@ -677,7 +677,7 @@ func TestFromBits(t *testing.T) { {append([]int{2, 1, 0} /* 7 */, []int{3, 1} /* 10 */ ...), "0x.88p5" /* 17 */}, } { f := fromBits(test.bits...) - if got := f.pstring(); got != test.want { + if got := f.Format('p', 0); got != test.want { t.Errorf("setBits(%v) = %s; want %s", test.bits, got, test.want) } } diff --git a/src/math/big/floatconv.go b/src/math/big/floatconv.go index 06bbdbcb02..f50a3a5c72 100644 --- a/src/math/big/floatconv.go +++ b/src/math/big/floatconv.go @@ -7,9 +7,9 @@ package big import ( - "bytes" "fmt" "io" + "strconv" "strings" ) @@ -184,13 +184,20 @@ func ParseFloat(s string, base int, prec uint, mode RoundingMode) (f *Float, b i // // BUG(gri) Currently, Format only accepts the 'b' and 'p' format. func (x *Float) Format(format byte, prec int) string { + const extra = 10 // TODO(gri) determine a good/better vaue here + return string(x.Append(make([]byte, 0, prec+extra), format, prec)) +} + +// Append appends the string form of the floating-point number x, +// as generated by x.Format, to buf and returns the extended buffer. +func (x *Float) Append(buf []byte, format byte, prec int) []byte { switch format { case 'b': - return x.bstring() + return x.bstring(buf) case 'p': - return x.pstring() + return x.pstring(buf) } - return fmt.Sprintf(`%%!c(%s)`, format, x.pstring()) + return append(buf, fmt.Sprintf(`%%!c`, format)...) } // BUG(gri): Currently, String uses the 'p' (rather than 'g') format. @@ -204,17 +211,18 @@ func (x *Float) String() string { // (a strconv 'p' formatted float value can only be interpreted correctly // if the bias is known; i.e., we must know if it's a 32bit or 64bit number). -// bstring returns x as a string in the format ["-"] mantissa "p" exponent -// with a decimal mantissa and a binary exponent, or ["-"] "0" if x is zero. +// bstring appends the string of x in the format ["-"] mantissa "p" exponent +// with a decimal mantissa and a binary exponent, or ["-"] "0" if x is zero, +// and returns the extended buffer. // The mantissa is normalized such that is uses x.Precision() bits in binary // representation. -func (x *Float) bstring() string { +func (x *Float) bstring(buf []byte) []byte { // TODO(gri) handle Inf + if x.neg { + buf = append(buf, '-') + } if len(x.mant) == 0 { - if x.neg { - return "-0" - } - return "0" + return append(buf, '0') } // x != 0 // normalize mantissa @@ -223,34 +231,27 @@ func (x *Float) bstring() string { if t > 0 { m = nat(nil).shr(m, t) } - var buf bytes.Buffer - if x.neg { - buf.WriteByte('-') - } - buf.WriteString(m.decimalString()) - fmt.Fprintf(&buf, "p%d", x.exp) - return buf.String() + buf = append(buf, m.decimalString()...) + buf = append(buf, 'p') + return strconv.AppendInt(buf, int64(x.exp), 10) } -// pstring returns x as a string in the format ["-"] "0x." mantissa "p" exponent -// with a hexadecimal mantissa and a binary exponent, or ["-"] "0" if x is zero. +// pstring appends the string of x in the format ["-"] "0x." mantissa "p" exponent +// with a hexadecimal mantissa and a binary exponent, or ["-"] "0" if x is zero, +// ad returns the extended buffer. // The mantissa is normalized such that 0.5 <= 0.mantissa < 1.0. -func (x *Float) pstring() string { +func (x *Float) pstring(buf []byte) []byte { // TODO(gri) handle Inf + if x.neg { + buf = append(buf, '-') + } if len(x.mant) == 0 { - if x.neg { - return "-0" - } - return "0" + return append(buf, '0') } // x != 0 // mantissa is stored in normalized form - var buf bytes.Buffer - if x.neg { - buf.WriteByte('-') - } - buf.WriteString("0x.") - buf.WriteString(strings.TrimRight(x.mant.hexString(), "0")) - fmt.Fprintf(&buf, "p%d", x.exp) - return buf.String() + buf = append(buf, "0x."...) + buf = append(buf, strings.TrimRight(x.mant.hexString(), "0")...) + buf = append(buf, 'p') + return strconv.AppendInt(buf, int64(x.exp), 10) }