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.pstring()))
}
if x.prec <= 0 {
panic(fmt.Sprintf("invalid precision %d", x.prec))
// z = x + y, ignoring signs of x and y.
// x and y must not be 0.
func (z *Float) uadd(x, y *Float) {
- if debugFloat && (len(x.mant) == 0 || len(y.mant) == 0) {
- panic("uadd called with 0 argument")
- }
-
// Note: This implementation requires 2 shifts most of the
// time. It is also inefficient if exponents or precisions
// differ by wide margins. The following article describes
// Point Addition With Exact Rounding (as in the MPFR Library)"
// http://www.vinc17.net/research/papers/rnc6.pdf
+ if debugFloat && (len(x.mant) == 0 || len(y.mant) == 0) {
+ panic("uadd called with 0 argument")
+ }
+
+ // compute exponents ex, ey for mantissa with "binary point"
+ // on the right (mantissa.0) - use int64 to avoid overflow
ex := int64(x.exp) - int64(len(x.mant))*_W
ey := int64(y.exp) - int64(len(y.mant))*_W
- var e int64
+ // TODO(gri) having a combined add-and-shift primitive
+ // could make this code significantly faster
switch {
case ex < ey:
t := z.mant.shl(y.mant, uint(ey-ex))
z.mant = t.add(x.mant, t)
- e = ex
default:
- // ex == ey
+ // ex == ey, no shift needed
z.mant = z.mant.add(x.mant, y.mant)
- e = ex
case ex > ey:
t := z.mant.shl(x.mant, uint(ex-ey))
z.mant = t.add(t, y.mant)
- e = ey
+ ex = ey
}
// len(z.mant) > 0
- z.setExp(e + int64(len(z.mant))*_W - int64(fnorm(z.mant)))
+ z.setExp(ex + int64(len(z.mant))*_W - int64(fnorm(z.mant)))
z.round(0)
}
// z = x - y for x >= y, ignoring signs of x and y.
// x and y must not be zero.
func (z *Float) usub(x, y *Float) {
+ // This code is symmetric to uadd.
+ // We have not factored the common code out because
+ // eventually uadd (and usub) should be optimized
+ // by special-casing, and the code will diverge.
+
if debugFloat && (len(x.mant) == 0 || len(y.mant) == 0) {
panic("usub called with 0 argument")
}
- if x.exp < y.exp {
- panic("underflow")
- }
-
- // This code is symmetric to uadd.
-
ex := int64(x.exp) - int64(len(x.mant))*_W
ey := int64(y.exp) - int64(len(y.mant))*_W
- var e int64
switch {
case ex < ey:
t := z.mant.shl(y.mant, uint(ey-ex))
z.mant = t.sub(x.mant, t)
- e = ex
default:
- // ex == ey
+ // ex == ey, no shift needed
z.mant = z.mant.sub(x.mant, y.mant)
- e = ex
case ex > ey:
t := z.mant.shl(x.mant, uint(ex-ey))
z.mant = t.sub(t, y.mant)
- e = ey
+ ex = ey
}
// operands may have cancelled each other out
}
// len(z.mant) > 0
- z.setExp(e + int64(len(z.mant))*_W - int64(fnorm(z.mant)))
+ z.setExp(ex + int64(len(z.mant))*_W - int64(fnorm(z.mant)))
z.round(0)
}
return 1
}
-func (x *Float) String() string {
- return x.PString() // TODO(gri) fix this
-}
-
-// PString returns x as a string in the format ["-"] "0." mantissa "p" exponent
+// pstring returns x as a string in the format ["-"] "0." mantissa "p" exponent
// with a hexadecimal mantissa and a decimal exponent, or ["-"] "0" if x is zero.
-func (x *Float) PString() string {
+func (x *Float) pstring() string {
// TODO(gri) handle Inf
var buf bytes.Buffer
if x.neg {
// is 1.2 * 2**3. If the operation failed, the value of z is undefined but
// the returned value is nil.
//
-func (z *Float) scan(r io.RuneScanner) (f *Float, err error) {
+func (z *Float) scan(r io.ByteScanner) (f *Float, err error) {
// sign
z.neg, err = scanSign(r)
if err != nil {
return z, nil
}
+
+// 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 = [ prefix ] [ sign ] mantissa [ exponent ] .
+// mantissa = digits | digits "." [ digits ] | "." digits .
+// prefix = prefix = "0" ( "x" | "X" | "b" | "B" ) .
+// sign = "+" | "-" .
+// exponent = ( "E" | "e" | "p" ) [ sign ] digits .
+// digits = digit { digit } .
+// digit = digit = "0" ... "9" | "a" ... "z" | "A" ... "Z" .
+//
+// The base argument must be 0 or a value between 2 and MaxBase, inclusive.
+//
+// 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.
+// Note that 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) Currently, Scan only accepts base 10.
+func (z *Float) Scan(r io.ByteScanner, base int) (f *Float, b int, err error) {
+ if base != 10 {
+ err = fmt.Errorf("base %d not supported yet", base)
+ return
+ }
+ b = 10
+ f, err = z.scan(r)
+ 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' ('e' for large exponents, 'f' otherwise),
+// 'G' ('E' for large exponents, 'f' otherwise),
+// 'b' (-ddddddp±dd, binary exponent), or
+// 'p' (-0.ddddp±dd, hexadecimal mantissa, binary exponent).
+//
+// 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 'p' format.
+func (x *Float) Format(format byte, prec int) string {
+ if format != 'p' {
+ return fmt.Sprintf(`%c`, format)
+ }
+ return x.pstring()
+}
+
+// BUG(gri): Currently, String uses the 'p' (rather than 'g') format.
+func (x *Float) String() string {
+ return x.Format('p', 0)
+}
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)
+ t.Errorf("got %d (%s); want %d", got, f.pstring(), want)
}
}
}
}
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.pstring(), want)
}
}
}
}
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.pstring(), want)
}
}
}
for _, test := range tests {
f := fromBits(test.bits...)
- if got := f.PString(); got != test.want {
+ if got := f.pstring(); got != test.want {
t.Errorf("setBits(%v) = %s; want %s", test.bits, got, test.want)
}
}
}
}
-func TestFloatPString(t *testing.T) {
+func TestFloatpstring(t *testing.T) {
var tests = []struct {
x Float
want string
{Float{mant: nat{0x87654321}, exp: -10}, "0.87654321p-10"},
}
for _, test := range tests {
- if got := test.x.PString(); got != test.want {
+ if got := test.x.pstring(); got != test.want {
t.Errorf("%v: got %s; want %s", test.x, got, test.want)
}
}
// ``0x'' or ``0X'' selects base 16; the ``0'' prefix selects base 8, and a
// ``0b'' or ``0B'' prefix selects base 2. Otherwise the selected base is 10.
//
-func (z *Int) scan(r io.RuneScanner, base int) (*Int, int, error) {
+func (z *Int) scan(r io.ByteScanner, base int) (*Int, int, error) {
// determine sign
neg, err := scanSign(r)
if err != nil {
return z, base, nil
}
-func scanSign(r io.RuneScanner) (neg bool, err error) {
- var ch rune
- if ch, _, err = r.ReadRune(); err != nil {
+func scanSign(r io.ByteScanner) (neg bool, err error) {
+ var ch byte
+ if ch, err = r.ReadByte(); err != nil {
return false, err
}
switch ch {
case '+':
// nothing to do
default:
- r.UnreadRune()
+ r.UnreadByte()
}
return
}
+// byteReader is a local wrapper around fmt.ScanState;
+// it implements the ByteReader interface.
+type byteReader struct {
+ fmt.ScanState
+}
+
+func (r byteReader) ReadByte() (byte, error) {
+ ch, size, err := r.ReadRune()
+ if size != 1 && err == nil {
+ err = fmt.Errorf("invalid rune %#U", ch)
+ }
+ return byte(ch), err
+}
+
+func (r byteReader) UnreadByte() error {
+ return r.UnreadRune()
+}
+
// Scan is a support routine for fmt.Scanner; it sets z to the value of
// the scanned number. It accepts the formats 'b' (binary), 'o' (octal),
// 'd' (decimal), 'x' (lowercase hexadecimal), and 'X' (uppercase hexadecimal).
default:
return errors.New("Int.Scan: invalid verb")
}
- _, _, err := z.scan(s, base)
+ _, _, err := z.scan(byteReader{s}, base)
return err
}
if err != nil {
return nil, false
}
- _, _, err = r.ReadRune()
+ _, err = r.ReadByte()
if err != io.EOF {
return nil, false
}
// base == 1, only), and the number of fractional digits is -count. In this
// case, the value of the scanned number is res * 10**count.
//
-func (z nat) scan(r io.RuneScanner, base int) (res nat, b, count int, err error) {
+func (z nat) scan(r io.ByteScanner, base int) (res nat, b, count int, err error) {
// reject illegal bases
if base < 0 || base > MaxBase {
err = errors.New("illegal number base")
}
// one char look-ahead
- ch, _, err := r.ReadRune()
+ ch, err := r.ReadByte()
if err != nil {
return
}
// actual base is 10 unless there's a base prefix
b = 10
if ch == '0' {
- switch ch, _, err = r.ReadRune(); err {
+ switch ch, err = r.ReadByte(); err {
case nil:
// possibly one of 0x, 0X, 0b, 0B
b = 8
b = 2
}
if b == 2 || b == 16 {
- if ch, _, err = r.ReadRune(); err != nil {
+ if ch, err = r.ReadByte(); err != nil {
// io.EOF is also an error in this case
return
}
base = 10 // no 2nd decimal point permitted
dp = count
// advance
- if ch, _, err = r.ReadRune(); err != nil {
+ if ch, err = r.ReadByte(); err != nil {
if err == io.EOF {
err = nil
break
d1 = MaxBase + 1
}
if d1 >= b1 {
- r.UnreadRune() // ch does not belong to number anymore
+ r.UnreadByte() // ch does not belong to number anymore
break
}
count++
}
// advance
- if ch, _, err = r.ReadRune(); err != nil {
+ if ch, err = r.ReadByte(); err != nil {
if err == io.EOF {
err = nil
break