1
0
mirror of https://github.com/golang/go synced 2024-11-18 14:54:40 -07:00

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 <adonovan@google.com>
This commit is contained in:
Robert Griesemer 2015-01-30 15:57:38 -08:00
parent 2e5b065ac2
commit 4c91c0d07b
3 changed files with 39 additions and 38 deletions

View File

@ -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))

View File

@ -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)
}
}

View File

@ -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)
}