No other functional changes.
Change-Id: I7e0bb7452c6a265535297ec7ce6a629f1aff695c
Reviewed-on: https://go-review.googlesource.com/3674
Reviewed-by: Alan Donovan <adonovan@google.com>
package big
import (
- "bytes"
"fmt"
- "io"
"math"
- "strings"
)
// TODO(gri): Determine if there's a more natural way to set the precision.
}
return 1
}
-
-// SetString sets z to the value of s and returns z and a boolean indicating
-// success. s must be a floating-point number of the same format as accepted
-// by Scan, with number prefixes permitted.
-func (z *Float) SetString(s string) (*Float, bool) {
- r := strings.NewReader(s)
-
- f, _, err := z.Scan(r, 0)
- if err != nil {
- return nil, false
- }
-
- // there should be no unread characters left
- if _, _, err = r.ReadRune(); err != io.EOF {
- return nil, false
- }
-
- return f, true
-}
-
-// Scan scans the number corresponding to the longest possible prefix
-// of r representing a floating-point number with a mantissa in the
-// given conversion base (the exponent is always a decimal number).
-// It returns the corresponding Float f, the actual base b, and an
-// error err, if any. The number must be of the form:
-//
-// number = [ sign ] [ prefix ] mantissa [ exponent ] .
-// sign = "+" | "-" .
-// prefix = "0" ( "x" | "X" | "b" | "B" ) .
-// mantissa = digits | digits "." [ digits ] | "." digits .
-// exponent = ( "E" | "e" | "p" ) [ sign ] digits .
-// digits = digit { digit } .
-// digit = "0" ... "9" | "a" ... "z" | "A" ... "Z" .
-//
-// The base argument must be 0 or a value between 2 through MaxBase.
-//
-// For base 0, the number prefix determines the actual base: A prefix of
-// ``0x'' or ``0X'' selects base 16, and a ``0b'' or ``0B'' prefix selects
-// base 2; otherwise, the actual base is 10 and no prefix is permitted.
-// The octal prefix ``0'' is not supported.
-//
-// A "p" exponent indicates power of 2 for the exponent; for instance "1.2p3"
-// with base 0 or 10 corresponds to the value 1.2 * 2**3.
-//
-// BUG(gri) This signature conflicts with Scan(s fmt.ScanState, ch rune) error.
-func (z *Float) Scan(r io.ByteScanner, base int) (f *Float, b int, err error) {
- // sign
- z.neg, err = scanSign(r)
- if err != nil {
- return
- }
-
- // mantissa
- var ecorr int // decimal exponent correction; valid if <= 0
- z.mant, b, ecorr, err = z.mant.scan(r, base, true)
- if err != nil {
- return
- }
-
- // exponent
- var exp int64
- var ebase int
- exp, ebase, err = scanExponent(r)
- if err != nil {
- return
- }
- // special-case 0
- if len(z.mant) == 0 {
- z.exp = 0
- f = z
- return
- }
- // len(z.mant) > 0
-
- // determine binary (exp2) and decimal (exp) exponent
- exp2 := int64(len(z.mant)*_W - int(fnorm(z.mant)))
- if ebase == 2 {
- exp2 += exp
- exp = 0
- }
- if ecorr < 0 {
- exp += int64(ecorr)
- }
-
- z.setExp(exp2)
- if exp == 0 {
- // no decimal exponent
- z.round(0)
- f = z
- return
- }
- // exp != 0
-
- // compute decimal exponent power
- expabs := exp
- if expabs < 0 {
- expabs = -expabs
- }
- powTen := new(Float).SetInt(new(Int).SetBits(nat(nil).expNN(natTen, nat(nil).setWord(Word(expabs)), nil)))
-
- // correct result
- if exp < 0 {
- z.uquo(z, powTen)
- } else {
- z.umul(z, powTen)
- }
-
- f = z
- return
-}
-
-// Parse is like z.Scan(r, base), but instead of reading from an
-// io.ByteScanner, it parses the string s. An error is returned if the
-// string contains invalid or trailing characters not belonging to the
-// number.
-//
-// TODO(gri) define possible errors more precisely
-func (z *Float) Parse(s string, base int) (f *Float, b int, err error) {
- r := strings.NewReader(s)
-
- if f, b, err = z.Scan(r, base); err != nil {
- return
- }
-
- // entire string must have been consumed
- var ch byte
- if ch, err = r.ReadByte(); err != io.EOF {
- if err == nil {
- err = fmt.Errorf("expected end of string, found %q", ch)
- }
- }
-
- return
-}
-
-// ScanFloat is like f.Scan(r, base) with f set to the given precision
-// and rounding mode.
-func ScanFloat(r io.ByteScanner, base int, prec uint, mode RoundingMode) (f *Float, b int, err error) {
- return NewFloat(0, prec, mode).Scan(r, base)
-}
-
-// ParseFloat is like f.Parse(s, base) with f set to the given precision
-// and rounding mode.
-func ParseFloat(s string, base int, prec uint, mode RoundingMode) (f *Float, b int, err error) {
- return NewFloat(0, prec, mode).Parse(s, base)
-}
-
-// Format converts the floating-point number x to a string according
-// to the given format and precision prec. The format is one of:
-//
-// 'e' -d.dddde±dd, decimal exponent
-// 'E' -d.ddddE±dd, decimal exponent
-// 'f' -ddddd.dddd, no exponent
-// 'g' like 'e' for large exponents, like 'f' otherwise
-// 'G' like 'E' for large exponents, like 'f' otherwise
-// 'b' -ddddddp±dd, binary exponent
-// 'p' -0x.dddp±dd, binary exponent, hexadecimal mantissa
-//
-// For the binary exponent formats, the mantissa is printed in normalized form:
-//
-// 'b' decimal integer mantissa using x.Precision() bits, or -0
-// 'p' hexadecimal fraction with 0.5 <= 0.mantissa < 1.0, or -0
-//
-// The precision prec controls the number of digits (excluding the exponent)
-// printed by the 'e', 'E', 'f', 'g', and 'G' formats. For 'e', 'E', and 'f'
-// it is the number of digits after the decimal point. For 'g' and 'G' it is
-// the total number of digits. A negative precision selects the smallest
-// number of digits necessary such that ParseFloat will return f exactly.
-// The prec value is ignored for the 'b' or 'p' format.
-//
-// BUG(gri) Currently, Format only accepts the 'b' and 'p' format.
-func (x *Float) Format(format byte, prec int) string {
- switch format {
- case 'b':
- return x.bstring()
- case 'p':
- return x.pstring()
- }
- return fmt.Sprintf(`%%!c(%s)`, format, x.pstring())
-}
-
-// BUG(gri): Currently, String uses the 'p' (rather than 'g') format.
-func (x *Float) String() string {
- return x.Format('p', 0)
-}
-
-// TODO(gri) The 'b' and 'p' formats have different meanings here than
-// in strconv: in strconv, the printed exponent is the biased (hardware)
-// exponent; here it is the unbiased exponent. Decide what to do.
-// (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.
-// The mantissa is normalized such that is uses x.Precision() bits in binary
-// representation.
-func (x *Float) bstring() string {
- // TODO(gri) handle Inf
- if len(x.mant) == 0 {
- if x.neg {
- return "-0"
- }
- return "0"
- }
- // x != 0
- // normalize mantissa
- m := x.mant
- t := uint(len(x.mant)*_W) - x.prec // 0 <= t < _W
- 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()
-}
-
-// 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.
-// The mantissa is normalized such that 0.5 <= 0.mantissa < 1.0.
-func (x *Float) pstring() string {
- // TODO(gri) handle Inf
- if len(x.mant) == 0 {
- if x.neg {
- return "-0"
- }
- return "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()
-}
}
}
}
-
-var floatSetFloat64StringTests = []struct {
- s string
- x float64
-}{
- {"0", 0},
- {"-0", -0},
- {"+0", 0},
- {"1", 1},
- {"-1", -1},
- {"+1", 1},
- {"1.234", 1.234},
- {"-1.234", -1.234},
- {"+1.234", 1.234},
- {".1", 0.1},
- {"1.", 1},
- {"+1.", 1},
-
- {"0e100", 0},
- {"-0e+100", 0},
- {"+0e-100", 0},
- {"0E100", 0},
- {"-0E+100", 0},
- {"+0E-100", 0},
- {"0p100", 0},
- {"-0p+100", 0},
- {"+0p-100", 0},
-
- {"1.e10", 1e10},
- {"1e+10", 1e10},
- {"+1e-10", 1e-10},
- {"1E10", 1e10},
- {"1.E+10", 1e10},
- {"+1E-10", 1e-10},
- {"1p10", 1 << 10},
- {"1p+10", 1 << 10},
- {"+1.p-10", 1.0 / (1 << 10)},
-
- {"-687436.79457e-245", -687436.79457e-245},
- {"-687436.79457E245", -687436.79457e245},
- {"1024.p-12", 0.25},
- {"-1.p10", -1024},
- {"0.25p2", 1},
-
- {".0000000000000000000000000000000000000001", 1e-40},
- {"+10000000000000000000000000000000000000000e-0", 1e40},
-}
-
-func TestFloatSetFloat64String(t *testing.T) {
- for _, test := range floatSetFloat64StringTests {
- var x Float
- x.prec = 53 // TODO(gri) find better solution
- _, ok := x.SetString(test.s)
- if !ok {
- t.Errorf("%s: parse error", test.s)
- continue
- }
- f, _ := x.Float64()
- want := new(Float).SetFloat64(test.x)
- if x.Cmp(want) != 0 {
- t.Errorf("%s: got %s (%v); want %v", test.s, &x, f, test.x)
- }
- }
-}
-
-func TestFloatFormat(t *testing.T) {
- for _, test := range []struct {
- x string
- format byte
- prec int
- want string
- }{
- {"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)
- }
- }
-}
--- /dev/null
+// Copyright 2015 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.
+
+// This file implements float-to-string conversion functions.
+
+package big
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "strings"
+)
+
+// SetString sets z to the value of s and returns z and a boolean indicating
+// success. s must be a floating-point number of the same format as accepted
+// by Scan, with number prefixes permitted.
+func (z *Float) SetString(s string) (*Float, bool) {
+ r := strings.NewReader(s)
+
+ f, _, err := z.Scan(r, 0)
+ if err != nil {
+ return nil, false
+ }
+
+ // there should be no unread characters left
+ if _, _, err = r.ReadRune(); err != io.EOF {
+ return nil, false
+ }
+
+ return f, true
+}
+
+// Scan scans the number corresponding to the longest possible prefix
+// of r representing a floating-point number with a mantissa in the
+// given conversion base (the exponent is always a decimal number).
+// It returns the corresponding Float f, the actual base b, and an
+// error err, if any. The number must be of the form:
+//
+// number = [ sign ] [ prefix ] mantissa [ exponent ] .
+// sign = "+" | "-" .
+// prefix = "0" ( "x" | "X" | "b" | "B" ) .
+// mantissa = digits | digits "." [ digits ] | "." digits .
+// exponent = ( "E" | "e" | "p" ) [ sign ] digits .
+// digits = digit { digit } .
+// digit = "0" ... "9" | "a" ... "z" | "A" ... "Z" .
+//
+// The base argument must be 0 or a value between 2 through MaxBase.
+//
+// For base 0, the number prefix determines the actual base: A prefix of
+// ``0x'' or ``0X'' selects base 16, and a ``0b'' or ``0B'' prefix selects
+// base 2; otherwise, the actual base is 10 and no prefix is permitted.
+// The octal prefix ``0'' is not supported.
+//
+// A "p" exponent indicates power of 2 for the exponent; for instance "1.2p3"
+// with base 0 or 10 corresponds to the value 1.2 * 2**3.
+//
+// BUG(gri) This signature conflicts with Scan(s fmt.ScanState, ch rune) error.
+func (z *Float) Scan(r io.ByteScanner, base int) (f *Float, b int, err error) {
+ // sign
+ z.neg, err = scanSign(r)
+ if err != nil {
+ return
+ }
+
+ // mantissa
+ var ecorr int // decimal exponent correction; valid if <= 0
+ z.mant, b, ecorr, err = z.mant.scan(r, base, true)
+ if err != nil {
+ return
+ }
+
+ // exponent
+ var exp int64
+ var ebase int
+ exp, ebase, err = scanExponent(r)
+ if err != nil {
+ return
+ }
+ // special-case 0
+ if len(z.mant) == 0 {
+ z.exp = 0
+ f = z
+ return
+ }
+ // len(z.mant) > 0
+
+ // determine binary (exp2) and decimal (exp) exponent
+ exp2 := int64(len(z.mant)*_W - int(fnorm(z.mant)))
+ if ebase == 2 {
+ exp2 += exp
+ exp = 0
+ }
+ if ecorr < 0 {
+ exp += int64(ecorr)
+ }
+
+ z.setExp(exp2)
+ if exp == 0 {
+ // no decimal exponent
+ z.round(0)
+ f = z
+ return
+ }
+ // exp != 0
+
+ // compute decimal exponent power
+ expabs := exp
+ if expabs < 0 {
+ expabs = -expabs
+ }
+ powTen := new(Float).SetInt(new(Int).SetBits(nat(nil).expNN(natTen, nat(nil).setWord(Word(expabs)), nil)))
+
+ // correct result
+ if exp < 0 {
+ z.uquo(z, powTen)
+ } else {
+ z.umul(z, powTen)
+ }
+
+ f = z
+ return
+}
+
+// Parse is like z.Scan(r, base), but instead of reading from an
+// io.ByteScanner, it parses the string s. An error is returned if the
+// string contains invalid or trailing characters not belonging to the
+// number.
+//
+// TODO(gri) define possible errors more precisely
+func (z *Float) Parse(s string, base int) (f *Float, b int, err error) {
+ r := strings.NewReader(s)
+
+ if f, b, err = z.Scan(r, base); err != nil {
+ return
+ }
+
+ // entire string must have been consumed
+ var ch byte
+ if ch, err = r.ReadByte(); err != io.EOF {
+ if err == nil {
+ err = fmt.Errorf("expected end of string, found %q", ch)
+ }
+ }
+
+ return
+}
+
+// ScanFloat is like f.Scan(r, base) with f set to the given precision
+// and rounding mode.
+func ScanFloat(r io.ByteScanner, base int, prec uint, mode RoundingMode) (f *Float, b int, err error) {
+ return NewFloat(0, prec, mode).Scan(r, base)
+}
+
+// ParseFloat is like f.Parse(s, base) with f set to the given precision
+// and rounding mode.
+func ParseFloat(s string, base int, prec uint, mode RoundingMode) (f *Float, b int, err error) {
+ return NewFloat(0, prec, mode).Parse(s, base)
+}
+
+// Format converts the floating-point number x to a string according
+// to the given format and precision prec. The format is one of:
+//
+// 'e' -d.dddde±dd, decimal exponent
+// 'E' -d.ddddE±dd, decimal exponent
+// 'f' -ddddd.dddd, no exponent
+// 'g' like 'e' for large exponents, like 'f' otherwise
+// 'G' like 'E' for large exponents, like 'f' otherwise
+// 'b' -ddddddp±dd, binary exponent
+// 'p' -0x.dddp±dd, binary exponent, hexadecimal mantissa
+//
+// For the binary exponent formats, the mantissa is printed in normalized form:
+//
+// 'b' decimal integer mantissa using x.Precision() bits, or -0
+// 'p' hexadecimal fraction with 0.5 <= 0.mantissa < 1.0, or -0
+//
+// The precision prec controls the number of digits (excluding the exponent)
+// printed by the 'e', 'E', 'f', 'g', and 'G' formats. For 'e', 'E', and 'f'
+// it is the number of digits after the decimal point. For 'g' and 'G' it is
+// the total number of digits. A negative precision selects the smallest
+// number of digits necessary such that ParseFloat will return f exactly.
+// The prec value is ignored for the 'b' or 'p' format.
+//
+// BUG(gri) Currently, Format only accepts the 'b' and 'p' format.
+func (x *Float) Format(format byte, prec int) string {
+ switch format {
+ case 'b':
+ return x.bstring()
+ case 'p':
+ return x.pstring()
+ }
+ return fmt.Sprintf(`%%!c(%s)`, format, x.pstring())
+}
+
+// BUG(gri): Currently, String uses the 'p' (rather than 'g') format.
+func (x *Float) String() string {
+ return x.Format('p', 0)
+}
+
+// TODO(gri) The 'b' and 'p' formats have different meanings here than
+// in strconv: in strconv, the printed exponent is the biased (hardware)
+// exponent; here it is the unbiased exponent. Decide what to do.
+// (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.
+// The mantissa is normalized such that is uses x.Precision() bits in binary
+// representation.
+func (x *Float) bstring() string {
+ // TODO(gri) handle Inf
+ if len(x.mant) == 0 {
+ if x.neg {
+ return "-0"
+ }
+ return "0"
+ }
+ // x != 0
+ // normalize mantissa
+ m := x.mant
+ t := uint(len(x.mant)*_W) - x.prec // 0 <= t < _W
+ 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()
+}
+
+// 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.
+// The mantissa is normalized such that 0.5 <= 0.mantissa < 1.0.
+func (x *Float) pstring() string {
+ // TODO(gri) handle Inf
+ if len(x.mant) == 0 {
+ if x.neg {
+ return "-0"
+ }
+ return "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()
+}
--- /dev/null
+// Copyright 2015 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 big
+
+import (
+ "strconv"
+ "testing"
+)
+
+var floatSetFloat64StringTests = []struct {
+ s string
+ x float64
+}{
+ {"0", 0},
+ {"-0", -0},
+ {"+0", 0},
+ {"1", 1},
+ {"-1", -1},
+ {"+1", 1},
+ {"1.234", 1.234},
+ {"-1.234", -1.234},
+ {"+1.234", 1.234},
+ {".1", 0.1},
+ {"1.", 1},
+ {"+1.", 1},
+
+ {"0e100", 0},
+ {"-0e+100", 0},
+ {"+0e-100", 0},
+ {"0E100", 0},
+ {"-0E+100", 0},
+ {"+0E-100", 0},
+ {"0p100", 0},
+ {"-0p+100", 0},
+ {"+0p-100", 0},
+
+ {"1.e10", 1e10},
+ {"1e+10", 1e10},
+ {"+1e-10", 1e-10},
+ {"1E10", 1e10},
+ {"1.E+10", 1e10},
+ {"+1E-10", 1e-10},
+ {"1p10", 1 << 10},
+ {"1p+10", 1 << 10},
+ {"+1.p-10", 1.0 / (1 << 10)},
+
+ {"-687436.79457e-245", -687436.79457e-245},
+ {"-687436.79457E245", -687436.79457e245},
+ {"1024.p-12", 0.25},
+ {"-1.p10", -1024},
+ {"0.25p2", 1},
+
+ {".0000000000000000000000000000000000000001", 1e-40},
+ {"+10000000000000000000000000000000000000000e-0", 1e40},
+}
+
+func TestFloatSetFloat64String(t *testing.T) {
+ for _, test := range floatSetFloat64StringTests {
+ var x Float
+ x.prec = 53 // TODO(gri) find better solution
+ _, ok := x.SetString(test.s)
+ if !ok {
+ t.Errorf("%s: parse error", test.s)
+ continue
+ }
+ f, _ := x.Float64()
+ want := new(Float).SetFloat64(test.x)
+ if x.Cmp(want) != 0 {
+ t.Errorf("%s: got %s (%v); want %v", test.s, &x, f, test.x)
+ }
+ }
+}
+
+func TestFloatFormat(t *testing.T) {
+ for _, test := range []struct {
+ x string
+ format byte
+ prec int
+ want string
+ }{
+ {"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)
+ }
+ }
+}