// fnorm normalizes mantissa m by shifting it to the left
// such that the msb of the most-significant word (msw) is 1.
// It returns the shift amount. It assumes that len(m) != 0.
-func fnorm(m nat) uint {
+func fnorm(m nat) int64 {
if debugFloat && (len(m) == 0 || m[len(m)-1] == 0) {
panic("msw of mantissa is 0")
}
panic("nlz or shlVU incorrect")
}
}
- return s
+ return int64(s)
}
// SetInt sets z to the (possibly rounded) value of x and returns z.
}
// len(z.mant) > 0
- z.setExp(ex + int64(len(z.mant))*_W - int64(fnorm(z.mant)))
+ z.setExp(ex + int64(len(z.mant))*_W - fnorm(z.mant))
z.round(0)
}
}
// len(z.mant) > 0
- z.setExp(ex + int64(len(z.mant))*_W - int64(fnorm(z.mant)))
+ z.setExp(ex + int64(len(z.mant))*_W - fnorm(z.mant))
z.round(0)
}
z.mant = z.mant.mul(x.mant, y.mant)
// normalize mantissa
- z.setExp(e - int64(fnorm(z.mant)))
+ z.setExp(e - fnorm(z.mant))
z.round(0)
}
e := int64(x.exp) - int64(y.exp) - int64(d-len(z.mant))*_W
// normalize mantissa
- z.setExp(e - int64(fnorm(z.mant)))
+ z.setExp(e - fnorm(z.mant))
// The result is long enough to include (at least) the rounding bit.
// If there's a non-zero remainder, the corresponding fractional part
}
// there should be no unread characters left
- if _, _, err = r.ReadRune(); err != io.EOF {
+ if _, err = r.ReadByte(); err != io.EOF {
return nil, false
}
// 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:
+// It sets z to the (possibly rounded) value of the corresponding
+// floating-point number, and returns z, the actual base b, and an
+// error err, if any. If z's precision is 0, it is changed to 64
+// before rounding takes effect. The number must be of the form:
//
// number = [ sign ] [ prefix ] mantissa [ exponent ] .
// sign = "+" | "-" .
// argument will lead to a run-time panic.
//
// 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
+// "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 accepted.
-// The octal prefix ``0'' is not supported.
+// The octal prefix "0" is not supported (a leading "0" is simply
+// considered a "0").
//
-// 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.
+// A "p" exponent indicates a binary (rather then decimal) exponent;
+// for instance "0x1.fffffffffffffp1023" (using base 0) represents the
+// maximum float64 value. For hexadecimal mantissae, the exponent must
+// be binary, if present (an "e" or "E" exponent indicator cannot be
+// distinguished from a mantissa digit).
//
// BUG(gri) This signature conflicts with Scan(s fmt.ScanState, ch rune) error.
-// TODO(gri) What should the default precision be?
func (z *Float) Scan(r io.ByteScanner, base int) (f *Float, b int, err error) {
+ if z.prec == 0 {
+ z.prec = 64
+ }
+
// sign
z.neg, err = scanSign(r)
if err != nil {
}
// mantissa
- var ecorr int // decimal exponent correction; valid if <= 0
- z.mant, b, ecorr, err = z.mant.scan(r, base, true)
+ var fcount int // fractional digit count; valid if <= 0
+ z.mant, b, fcount, err = z.mant.scan(r, base, true)
if err != nil {
return
}
if err != nil {
return
}
+
+ // set result
+ f = z
+
// special-case 0
if len(z.mant) == 0 {
+ z.acc = Exact
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)))
+ // The mantissa may have a decimal point (fcount <= 0) and there
+ // may be a nonzero exponent exp. The decimal point amounts to a
+ // division by b**(-fcount). An exponent means multiplication by
+ // ebase**exp. Finally, mantissa normalization (shift left) requires
+ // a correcting multiplication by 2**(-shiftcount). Multiplications
+ // are commutative, so we can apply them in any order as long as there
+ // is no loss of precision. We only have powers of 2 and 10; keep
+ // track via separate exponents exp2 and exp10.
+
+ // normalize mantissa and get initial binary exponent
+ var exp2 = int64(len(z.mant))*_W - fnorm(z.mant)
+
+ // determine binary or decimal exponent contribution of decimal point
+ var exp10 int64
+ if fcount < 0 {
+ // The mantissa has a "decimal" point ddd.dddd; and
+ // -fcount is the number of digits to the right of '.'.
+ // Adjust relevant exponent accodingly.
+ switch b {
+ case 16:
+ fcount *= 4 // hexadecimal digits are 4 bits each
+ fallthrough
+ case 2:
+ exp2 += int64(fcount)
+ default: // b == 10
+ exp10 = int64(fcount)
+ }
+ // we don't need fcount anymore
+ }
+
+ // take actual exponent into account
if ebase == 2 {
exp2 += exp
- exp = 0
- }
- if ecorr < 0 {
- exp += int64(ecorr)
+ } else { // ebase == 10
+ exp10 += exp
}
+ // we don't need exp anymore
+ // apply 2**exp2
z.setExp(exp2)
- if exp == 0 {
- // no decimal exponent
+
+ if exp10 == 0 {
+ // no decimal exponent to consider
z.round(0)
- f = z
return
}
- // exp != 0
+ // exp10 != 0
// compute decimal exponent power
- expabs := exp
+ expabs := exp10
if expabs < 0 {
expabs = -expabs
}
- powTen := new(Float).SetInt(new(Int).SetBits(nat(nil).expNN(natTen, nat(nil).setWord(Word(expabs)), nil)))
+ powTen := nat(nil).expNN(natTen, nat(nil).setUint64(uint64(expabs)), nil)
+ fpowTen := new(Float).SetInt(new(Int).SetBits(powTen))
- // correct result
- if exp < 0 {
- z.uquo(z, powTen)
+ // apply 10**exp10
+ // (uquo and umul do the rounding)
+ if exp10 < 0 {
+ z.uquo(z, fpowTen)
} else {
- z.umul(z, powTen)
+ z.umul(z, fpowTen)
}
- f = z
return
}
s string
x float64
}{
+ // basics
{"0", 0},
{"-0", -0},
{"+0", 0},
{"1.", 1},
{"+1.", 1},
+ // various zeros
{"0e100", 0},
{"-0e+100", 0},
{"+0e-100", 0},
{"0E100", 0},
{"-0E+100", 0},
{"+0E-100", 0},
- {"0p100", 0},
- {"-0p+100", 0},
- {"+0p-100", 0},
+ // various decimal exponent formats
{"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)},
+ // misc decimal values
+ {"3.14159265", 3.14159265},
{"-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},
+
+ // decimal mantissa, binary exponent
+ {"0p0", 0},
+ {"-0p0", -0},
+ {"1p10", 1 << 10},
+ {"1p+10", 1 << 10},
+ {"+1p-10", 1.0 / (1 << 10)},
+ {"1024p-12", 0.25},
+ {"-1p10", -1024},
+ {"1.5p1", 3},
+
+ // binary mantissa, decimal exponent
+ {"0b0", 0},
+ {"-0b0", -0},
+ {"0b0e+10", 0},
+ {"-0b0e-10", -0},
+ {"0b1010", 10},
+ {"0B1010E2", 1000},
+ {"0b.1", 0.5},
+ {"0b.001", 0.125},
+ {"0b.001e3", 125},
+
+ // binary mantissa, binary exponent
+ {"0b0p+10", 0},
+ {"-0b0p-10", -0},
+ {"0b.1010p4", 10},
+ {"0b1p-1", 0.5},
+ {"0b001p-3", 0.125},
+ {"0b.001p3", 1},
+ {"0b0.01p2", 1},
+
+ // hexadecimal mantissa and exponent
+ {"0x0", 0},
+ {"-0x0", -0},
+ {"0x0p+10", 0},
+ {"-0x0p-10", -0},
+ {"0xff", 255},
+ {"0X.8p1", 1},
+ {"-0X0.00008p16", -0.5},
+ {"0x0.0000000000001p-1022", math.SmallestNonzeroFloat64},
+ {"0x1.fffffffffffffp1023", math.MaxFloat64},
} {
var x Float
x.SetPrec(53)
// and its output for 0.0 prints a biased exponent value
// as in 0p-1074 which makes no sense to emulate here)
if test.prec == 53 && test.format != 'p' && f.Sign() != 0 {
- f64, _ := f.Float64()
+ f64, acc := f.Float64()
+ if acc != Exact {
+ t.Errorf("%v: expected exact conversion to float64", test)
+ continue
+ }
got := strconv.FormatFloat(f64, test.format, test.digits, 64)
if got != test.want {
t.Errorf("%v: got %s; want %s", test, got, test.want)