Skip to content

Commit

Permalink
math/big: removed TODO, cleanups
Browse files Browse the repository at this point in the history
- factor out handling of sign
- rename bstring, pstring to fmtB, fmtP consistent with fmtE, fmtF
- move all float-to-string conversion functions into ftoa.go
- no functional changes

Change-Id: I5970ecb874dc9c387630b59147d90bda16a5d8e6
Reviewed-on: https://go-review.googlesource.com/10387
Reviewed-by: Alan Donovan <[email protected]>
  • Loading branch information
griesemer committed May 27, 2015
1 parent acd82d5 commit 0858d88
Show file tree
Hide file tree
Showing 3 changed files with 152 additions and 170 deletions.
136 changes: 1 addition & 135 deletions src/math/big/floatconv.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,13 @@
// 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.
// This file implements string-to-Float conversion functions.

package big

import (
"fmt"
"io"
"strconv"
"strings"
)

Expand Down Expand Up @@ -244,136 +243,3 @@ func ScanFloat(r io.ByteScanner, base int, prec uint, mode RoundingMode) (f *Flo
func ParseFloat(s string, base int, prec uint, mode RoundingMode) (f *Float, b int, err error) {
return new(Float).SetPrec(prec).SetMode(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, at least two (possibly 0) exponent digits
// 'E' -d.ddddE±dd, decimal exponent, at least two (possibly 0) exponent digits
// '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.Prec() 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) Float.Format does not accept negative precisions.
// BUG(gri) The Float.Format signature conflicts with Format(f fmt.State, c rune).
// (https://github.com/golang/go/issues/10938)
func (x *Float) Format(format byte, prec int) string {
const extra = 10 // TODO(gri) determine a good/better value 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 {
// TODO(gri) factor out handling of sign?

// Inf
if x.IsInf() {
var ch byte = '+'
if x.neg {
ch = '-'
}
buf = append(buf, ch)
return append(buf, "Inf"...)
}

// easy formats
switch format {
case 'b':
return x.bstring(buf)
case 'p':
return x.pstring(buf)
}

return x.bigFtoa(buf, format, prec)
}

// BUG(gri): Float.String uses x.Format('g', 10) rather than x.Format('g', -1).
func (x *Float) String() string {
return x.Format('g', 10)
}

// 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.Prec() bits in binary
// representation.
func (x *Float) bstring(buf []byte) []byte {
if x.neg {
buf = append(buf, '-')
}
if x.form == zero {
return append(buf, '0')
}

if debugFloat && x.form != finite {
panic("non-finite float")
}
// x != 0

// adjust mantissa to use exactly x.prec bits
m := x.mant
switch w := uint32(len(x.mant)) * _W; {
case w < x.prec:
m = nat(nil).shl(m, uint(x.prec-w))
case w > x.prec:
m = nat(nil).shr(m, uint(w-x.prec))
}

buf = append(buf, m.decimalString()...)
buf = append(buf, 'p')
e := int64(x.exp) - int64(x.prec)
if e >= 0 {
buf = append(buf, '+')
}
return strconv.AppendInt(buf, e, 10)
}

// 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(buf []byte) []byte {
if x.neg {
buf = append(buf, '-')
}
if x.form == zero {
return append(buf, '0')
}

if debugFloat && x.form != finite {
panic("non-finite float")
}
// x != 0

// remove trailing 0 words early
// (no need to convert to hex 0's and trim later)
m := x.mant
i := 0
for i < len(m) && m[i] == 0 {
i++
}
m = m[i:]

buf = append(buf, "0x."...)
buf = append(buf, strings.TrimRight(x.mant.hexString(), "0")...)
buf = append(buf, 'p')
if x.exp >= 0 {
buf = append(buf, '+')
}
return strconv.AppendInt(buf, int64(x.exp), 10)
}
1 change: 1 addition & 0 deletions src/math/big/floatconv_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,7 @@ func TestFloatFormat(t *testing.T) {

// unsupported format
{"3.14", 64, 'x', 0, "%x"},
{"-3.14", 64, 'x', 0, "%x"},
} {
f, _, err := ParseFloat(test.x, 0, test.prec, ToNearestEven)
if err != nil {
Expand Down
Loading

0 comments on commit 0858d88

Please sign in to comment.