return uint(x.prec)
}
+// MinPrec returns the minimum precision required to represent x exactly
+// (i.e., the smallest prec before x.SetPrec(prec) would start rounding x).
+// The result is 0 for ±0 and ±Inf.
+func (x *Float) MinPrec() uint {
+ return uint(len(x.mant))*_W - x.mant.trailingZeroBits()
+}
+
// Acc returns the accuracy of x produced by the most recent operation.
func (x *Float) Acc() Accuracy {
return x.acc
return len(x.mant) == 0 && x.exp != infExp
}
// x.exp > 0
- return x.prec <= uint32(x.exp) || x.minPrec() <= uint(x.exp) // not enough bits for fractional mantissa
+ return x.prec <= uint32(x.exp) || x.MinPrec() <= uint(x.exp) // not enough bits for fractional mantissa
}
// IsInf reports whether x is an infinity, according to sign.
return v
}
-// minPrec returns the minimum precision required to represent
-// x without loss of accuracy.
-// TODO(gri) this might be useful to export, perhaps under a better name
-func (x *Float) minPrec() uint {
- return uint(len(x.mant))*_W - x.mant.trailingZeroBits()
-}
-
// Uint64 returns the unsigned integer resulting from truncating x
// towards zero. If 0 <= x <= math.MaxUint64, the result is Exact
// if x is an integer and Below otherwise.
if x.exp <= 64 {
// u = trunc(x) fits into a uint64
u := high64(x.mant) >> (64 - uint32(x.exp))
- if x.minPrec() <= 64 {
+ if x.MinPrec() <= 64 {
return u, Exact
}
return u, Below // x truncated
if x.neg {
i = -i
}
- if x.minPrec() <= 63 {
+ if x.MinPrec() <= 63 {
return i, Exact
}
return i, acc // x truncated
}
if x.neg {
// check for special case x == math.MinInt64 (i.e., x == -(0.5 << 64))
- if x.exp == 64 && x.minPrec() == 1 {
+ if x.exp == 64 && x.MinPrec() == 1 {
acc = Exact
}
return math.MinInt64, acc
// determine minimum required precision for x
allBits := uint(len(x.mant)) * _W
exp := uint(x.exp)
- if x.minPrec() <= exp {
+ if x.MinPrec() <= exp {
acc = Exact
}
// shift mantissa as needed
}
}
+func TestFloatMinPrec(t *testing.T) {
+ const max = 100
+ for _, test := range []struct {
+ x string
+ want uint
+ }{
+ {"0", 0},
+ {"-0", 0},
+ {"+Inf", 0},
+ {"-Inf", 0},
+ {"1", 1},
+ {"2", 1},
+ {"3", 2},
+ {"0x8001", 16},
+ {"0x8001p-1000", 16},
+ {"0x8001p+1000", 16},
+ {"0.1", max},
+ } {
+ x := makeFloat(test.x).SetPrec(max)
+ if got := x.MinPrec(); got != test.want {
+ t.Errorf("%s.MinPrec() = %d; want %d", test.x, got, test.want)
+ }
+ }
+}
+
func TestFloatSign(t *testing.T) {
for _, test := range []struct {
x string