mirror of https://github.com/golang/go.git
cmd/internal/gc/big: updated vendored version of math/big (fix build)
Change-Id: I04c2bd18a47cc775c78d074fe521cef2b0d6e7f0 Reviewed-on: https://go-review.googlesource.com/8426 Run-TryBot: Robert Griesemer <gri@golang.org> Reviewed-by: David Crawshaw <crawshaw@golang.org>
This commit is contained in:
parent
398bf9d5a0
commit
dec685921d
|
|
@ -4,13 +4,14 @@ package big
|
|||
|
||||
import "fmt"
|
||||
|
||||
const _Accuracy_name = "ExactBelowAboveUndef"
|
||||
const _Accuracy_name = "BelowExactAbove"
|
||||
|
||||
var _Accuracy_index = [...]uint8{0, 5, 10, 15, 20}
|
||||
var _Accuracy_index = [...]uint8{0, 5, 10, 15}
|
||||
|
||||
func (i Accuracy) String() string {
|
||||
i -= -1
|
||||
if i < 0 || i+1 >= Accuracy(len(_Accuracy_index)) {
|
||||
return fmt.Sprintf("Accuracy(%d)", i)
|
||||
return fmt.Sprintf("Accuracy(%d)", i+-1)
|
||||
}
|
||||
return _Accuracy_name[_Accuracy_index[i]:_Accuracy_index[i+1]]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,10 +23,9 @@ const debugFloat = true // enable for debugging
|
|||
// sign × mantissa × 2**exponent
|
||||
//
|
||||
// with 0.5 <= mantissa < 1.0, and MinExp <= exponent <= MaxExp.
|
||||
// A Float may also be zero (+0, -0), infinite (+Inf, -Inf) or
|
||||
// not-a-number (NaN). Except for NaNs, all Floats are ordered,
|
||||
// and the ordering of two Floats x and y is defined by x.Cmp(y).
|
||||
// NaNs are always different from any other Float value.
|
||||
// A Float may also be zero (+0, -0) or infinite (+Inf, -Inf).
|
||||
// All Floats are ordered, and the ordering of two Floats x and y
|
||||
// is defined by x.Cmp(y).
|
||||
//
|
||||
// Each Float value also has a precision, rounding mode, and accuracy.
|
||||
// The precision is the maximum number of mantissa bits available to
|
||||
|
|
@ -34,10 +33,10 @@ const debugFloat = true // enable for debugging
|
|||
// be rounded to fit into the mantissa bits, and accuracy describes the
|
||||
// rounding error with respect to the exact result.
|
||||
//
|
||||
// All operations, including setters, that specify a *Float variable for
|
||||
// the result (usually via the receiver with the exception of MantExp),
|
||||
// round the numeric result according to the precision and rounding mode
|
||||
// of the result variable, unless specified otherwise.
|
||||
// Unless specified otherwise, all operations (including setters) that
|
||||
// specify a *Float variable for the result (usually via the receiver
|
||||
// with the exception of MantExp), round the numeric result according
|
||||
// to the precision and rounding mode of the result variable.
|
||||
//
|
||||
// If the provided result precision is 0 (see below), it is set to the
|
||||
// precision of the argument with the largest precision value before any
|
||||
|
|
@ -48,9 +47,10 @@ const debugFloat = true // enable for debugging
|
|||
//
|
||||
// By setting the desired precision to 24 or 53 and using matching rounding
|
||||
// mode (typically ToNearestEven), Float operations produce the same results
|
||||
// as the corresponding float32 or float64 IEEE-754 arithmetic. Exponent
|
||||
// underflow and overflow lead to a 0 or an Infinity for different values
|
||||
// than IEEE-754 because Float exponents have a much larger range.
|
||||
// as the corresponding float32 or float64 IEEE-754 arithmetic for operands
|
||||
// that correspond to normal (i.e., not denormal) float32 or float64 numbers.
|
||||
// Exponent underflow and overflow lead to a 0 or an Infinity for different
|
||||
// values than IEEE-754 because Float exponents have a much larger range.
|
||||
//
|
||||
// The zero (uninitialized) value for a Float is ready to use and represents
|
||||
// the number +0.0 exactly, with precision 0 and rounding mode ToNearestEven.
|
||||
|
|
@ -65,9 +65,19 @@ type Float struct {
|
|||
exp int32
|
||||
}
|
||||
|
||||
// Float operations that would lead to a NaN under IEEE-754 rules cause
|
||||
// a run-time panic of ErrNaN type.
|
||||
type ErrNaN struct {
|
||||
msg string
|
||||
}
|
||||
|
||||
// NewFloat allocates and returns a new Float set to x,
|
||||
// with precision 53 and rounding mode ToNearestEven.
|
||||
// NewFloat panics with ErrNaN if x is a NaN.
|
||||
func NewFloat(x float64) *Float {
|
||||
if math.IsNaN(x) {
|
||||
panic(ErrNaN{"NewFloat(NaN)"})
|
||||
}
|
||||
return new(Float).SetFloat64(x)
|
||||
}
|
||||
|
||||
|
|
@ -87,15 +97,13 @@ const (
|
|||
// x.mant[0] has trailing zero bits. The msb of the mantissa corresponds
|
||||
// to the value 0.5; the exponent x.exp shifts the binary point as needed.
|
||||
//
|
||||
// A zero or non-finite Float x ignores x.mant and x.exp. A NaN x ignores
|
||||
// the sign x.neg.
|
||||
// A zero or non-finite Float x ignores x.mant and x.exp.
|
||||
//
|
||||
// x form neg mant exp
|
||||
// ----------------------------------------------------------
|
||||
// ±0 zero sign - -
|
||||
// 0 < |x| < +Inf finite sign mantissa exponent
|
||||
// ±Inf inf sign - -
|
||||
// NaN nan - - -
|
||||
|
||||
// A form value describes the internal representation.
|
||||
type form byte
|
||||
|
|
@ -105,7 +113,6 @@ const (
|
|||
zero form = iota
|
||||
finite
|
||||
inf
|
||||
nan
|
||||
)
|
||||
|
||||
// RoundingMode determines how a Float value is rounded to the
|
||||
|
|
@ -127,16 +134,13 @@ const (
|
|||
|
||||
// Accuracy describes the rounding error produced by the most recent
|
||||
// operation that generated a Float value, relative to the exact value.
|
||||
// The accuracy is Undef for operations on and resulting in NaNs since
|
||||
// they are neither Below nor Above any other value.
|
||||
type Accuracy byte
|
||||
type Accuracy int8
|
||||
|
||||
// Constants describing the Accuracy of a Float.
|
||||
const (
|
||||
Below Accuracy = -1
|
||||
Exact Accuracy = 0
|
||||
Below Accuracy = 1 << 0
|
||||
Above Accuracy = 1 << 1
|
||||
Undef Accuracy = Below | Above
|
||||
Above Accuracy = +1
|
||||
)
|
||||
|
||||
//go:generate stringer -type=Accuracy
|
||||
|
|
@ -144,8 +148,8 @@ const (
|
|||
// SetPrec sets z's precision to prec and returns the (possibly) rounded
|
||||
// value of z. Rounding occurs according to z's rounding mode if the mantissa
|
||||
// cannot be represented in prec bits without loss of precision.
|
||||
// SetPrec(0) maps all finite values to ±0; infinite and NaN values remain
|
||||
// unchanged. If prec > MaxPrec, it is set to MaxPrec.
|
||||
// SetPrec(0) maps all finite values to ±0; infinite values remain unchanged.
|
||||
// If prec > MaxPrec, it is set to MaxPrec.
|
||||
func (z *Float) SetPrec(prec uint) *Float {
|
||||
z.acc = Exact // optimistically assume no rounding is needed
|
||||
|
||||
|
|
@ -189,14 +193,14 @@ func (z *Float) SetMode(mode RoundingMode) *Float {
|
|||
}
|
||||
|
||||
// Prec returns the mantissa precision of x in bits.
|
||||
// The result may be 0 for |x| == 0, |x| == Inf, or NaN.
|
||||
// The result may be 0 for |x| == 0 and |x| == Inf.
|
||||
func (x *Float) Prec() uint {
|
||||
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 if x is 0 or not finite.
|
||||
// The result is 0 for |x| == 0 and |x| == Inf.
|
||||
func (x *Float) MinPrec() uint {
|
||||
if x.form != finite {
|
||||
return 0
|
||||
|
|
@ -217,14 +221,14 @@ func (x *Float) Acc() Accuracy {
|
|||
// Sign returns:
|
||||
//
|
||||
// -1 if x < 0
|
||||
// 0 if x is ±0 or NaN
|
||||
// 0 if x is ±0
|
||||
// +1 if x > 0
|
||||
//
|
||||
func (x *Float) Sign() int {
|
||||
if debugFloat {
|
||||
x.validate()
|
||||
}
|
||||
if x.form == zero || x.form == nan {
|
||||
if x.form == zero {
|
||||
return 0
|
||||
}
|
||||
if x.neg {
|
||||
|
|
@ -245,7 +249,6 @@ func (x *Float) Sign() int {
|
|||
//
|
||||
// ( ±0).MantExp(mant) = 0, with mant set to ±0
|
||||
// (±Inf).MantExp(mant) = 0, with mant set to ±Inf
|
||||
// ( NaN).MantExp(mant) = 0, with mant set to NaN
|
||||
//
|
||||
// x and mant may be the same in which case x is set to its
|
||||
// mantissa value.
|
||||
|
|
@ -297,7 +300,6 @@ func (z *Float) setExpAndRound(exp int64, sbit uint) {
|
|||
//
|
||||
// z.SetMantExp( ±0, exp) = ±0
|
||||
// z.SetMantExp(±Inf, exp) = ±Inf
|
||||
// z.SetMantExp( NaN, exp) = NaN
|
||||
//
|
||||
// z and mant may be the same in which case z's exponent
|
||||
// is set to exp.
|
||||
|
|
@ -314,21 +316,9 @@ func (z *Float) SetMantExp(mant *Float, exp int) *Float {
|
|||
return z
|
||||
}
|
||||
|
||||
// IsNeg reports whether x is negative.
|
||||
// A NaN value is not negative.
|
||||
func (x *Float) IsNeg() bool {
|
||||
return x.neg && x.form != nan
|
||||
}
|
||||
|
||||
// IsZero reports whether x is +0 or -0.
|
||||
func (x *Float) IsZero() bool {
|
||||
return x.form == zero
|
||||
}
|
||||
|
||||
// IsFinite reports whether -Inf < x < Inf.
|
||||
// A NaN value is not finite.
|
||||
func (x *Float) IsFinite() bool {
|
||||
return x.form <= finite
|
||||
// Signbit returns true if x is negative or negative zero.
|
||||
func (x *Float) Signbit() bool {
|
||||
return x.neg
|
||||
}
|
||||
|
||||
// IsInf reports whether x is +Inf or -Inf.
|
||||
|
|
@ -336,13 +326,8 @@ func (x *Float) IsInf() bool {
|
|||
return x.form == inf
|
||||
}
|
||||
|
||||
// IsNaN reports whether x is a NaN value.
|
||||
func (x *Float) IsNaN() bool {
|
||||
return x.form == nan
|
||||
}
|
||||
|
||||
// IsInt reports whether x is an integer.
|
||||
// ±Inf and NaN values are not integers.
|
||||
// ±Inf values are not integers.
|
||||
func (x *Float) IsInt() bool {
|
||||
if debugFloat {
|
||||
x.validate()
|
||||
|
|
@ -526,7 +511,7 @@ func (z *Float) round(sbit uint) {
|
|||
|
||||
// update accuracy
|
||||
if z.acc != Exact && z.neg {
|
||||
z.acc ^= Below | Above
|
||||
z.acc = -z.acc
|
||||
}
|
||||
|
||||
if debugFloat {
|
||||
|
|
@ -598,13 +583,13 @@ func (z *Float) SetInt64(x int64) *Float {
|
|||
|
||||
// SetFloat64 sets z to the (possibly rounded) value of x and returns z.
|
||||
// If z's precision is 0, it is changed to 53 (and rounding will have
|
||||
// no effect).
|
||||
// no effect). SetFloat64 panics with ErrNaN if x is a NaN.
|
||||
func (z *Float) SetFloat64(x float64) *Float {
|
||||
if z.prec == 0 {
|
||||
z.prec = 53
|
||||
}
|
||||
if math.IsNaN(x) {
|
||||
return z.SetNaN()
|
||||
panic(ErrNaN{"Float.SetFloat64(NaN)"})
|
||||
}
|
||||
z.acc = Exact
|
||||
z.neg = math.Signbit(x) // handle -0, -Inf correctly
|
||||
|
|
@ -684,21 +669,14 @@ func (z *Float) SetRat(x *Rat) *Float {
|
|||
return z.Quo(&a, &b)
|
||||
}
|
||||
|
||||
// SetInf sets z to the infinite Float +Inf for sign >= 0,
|
||||
// or -Inf for sign < 0, and returns z. The precision of
|
||||
// z is unchanged and the result is always Exact.
|
||||
func (z *Float) SetInf(sign int) *Float {
|
||||
// SetInf sets z to the infinite Float -Inf if signbit is
|
||||
// set, or +Inf if signbit is not set, and returns z. The
|
||||
// precision of z is unchanged and the result is always
|
||||
// Exact.
|
||||
func (z *Float) SetInf(signbit bool) *Float {
|
||||
z.acc = Exact
|
||||
z.form = inf
|
||||
z.neg = sign < 0
|
||||
return z
|
||||
}
|
||||
|
||||
// SetNaN sets z to a NaN value, and returns z.
|
||||
// The precision of z is unchanged and the result accuracy is always Undef.
|
||||
func (z *Float) SetNaN() *Float {
|
||||
z.acc = Undef
|
||||
z.form = nan
|
||||
z.neg = signbit
|
||||
return z
|
||||
}
|
||||
|
||||
|
|
@ -774,8 +752,8 @@ func high64(x nat) uint64 {
|
|||
// 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.
|
||||
// The result is (0, Above) for x < 0, (math.MaxUint64, Below)
|
||||
// for x > math.MaxUint64, and (0, Undef) for NaNs.
|
||||
// The result is (0, Above) for x < 0, and (math.MaxUint64, Below)
|
||||
// for x > math.MaxUint64.
|
||||
func (x *Float) Uint64() (uint64, Accuracy) {
|
||||
if debugFloat {
|
||||
x.validate()
|
||||
|
|
@ -811,9 +789,6 @@ func (x *Float) Uint64() (uint64, Accuracy) {
|
|||
return 0, Above
|
||||
}
|
||||
return math.MaxUint64, Below
|
||||
|
||||
case nan:
|
||||
return 0, Undef
|
||||
}
|
||||
|
||||
panic("unreachable")
|
||||
|
|
@ -823,7 +798,7 @@ func (x *Float) Uint64() (uint64, Accuracy) {
|
|||
// If math.MinInt64 <= x <= math.MaxInt64, the result is Exact if x is
|
||||
// an integer, and Above (x < 0) or Below (x > 0) otherwise.
|
||||
// The result is (math.MinInt64, Above) for x < math.MinInt64,
|
||||
// (math.MaxInt64, Below) for x > math.MaxInt64, and (0, Undef) for NaNs.
|
||||
// and (math.MaxInt64, Below) for x > math.MaxInt64.
|
||||
func (x *Float) Int64() (int64, Accuracy) {
|
||||
if debugFloat {
|
||||
x.validate()
|
||||
|
|
@ -869,9 +844,6 @@ func (x *Float) Int64() (int64, Accuracy) {
|
|||
return math.MinInt64, Above
|
||||
}
|
||||
return math.MaxInt64, Below
|
||||
|
||||
case nan:
|
||||
return 0, Undef
|
||||
}
|
||||
|
||||
panic("unreachable")
|
||||
|
|
@ -885,7 +857,6 @@ func (x *Float) Int64() (int64, Accuracy) {
|
|||
// is (0, Below) or (-0, Above), respectively, depending on the sign of x.
|
||||
// If x is too large to be represented by a float32 (|x| > math.MaxFloat32),
|
||||
// the result is (+Inf, Above) or (-Inf, Below), depending on the sign of x.
|
||||
// The result is (NaN, Undef) for NaNs.
|
||||
func (x *Float) Float32() (float32, Accuracy) {
|
||||
if debugFloat {
|
||||
x.validate()
|
||||
|
|
@ -976,9 +947,6 @@ func (x *Float) Float32() (float32, Accuracy) {
|
|||
return float32(math.Inf(-1)), Exact
|
||||
}
|
||||
return float32(math.Inf(+1)), Exact
|
||||
|
||||
case nan:
|
||||
return float32(math.NaN()), Undef
|
||||
}
|
||||
|
||||
panic("unreachable")
|
||||
|
|
@ -989,7 +957,6 @@ func (x *Float) Float32() (float32, Accuracy) {
|
|||
// is (0, Below) or (-0, Above), respectively, depending on the sign of x.
|
||||
// If x is too large to be represented by a float64 (|x| > math.MaxFloat64),
|
||||
// the result is (+Inf, Above) or (-Inf, Below), depending on the sign of x.
|
||||
// The result is (NaN, Undef) for NaNs.
|
||||
func (x *Float) Float64() (float64, Accuracy) {
|
||||
if debugFloat {
|
||||
x.validate()
|
||||
|
|
@ -1080,16 +1047,13 @@ func (x *Float) Float64() (float64, Accuracy) {
|
|||
return math.Inf(-1), Exact
|
||||
}
|
||||
return math.Inf(+1), Exact
|
||||
|
||||
case nan:
|
||||
return math.NaN(), Undef
|
||||
}
|
||||
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
// Int returns the result of truncating x towards zero;
|
||||
// or nil if x is an infinity or NaN.
|
||||
// or nil if x is an infinity.
|
||||
// The result is Exact if x.IsInt(); otherwise it is Below
|
||||
// for x > 0, and Above for x < 0.
|
||||
// If a non-nil *Int argument z is provided, Int stores
|
||||
|
|
@ -1140,17 +1104,14 @@ func (x *Float) Int(z *Int) (*Int, Accuracy) {
|
|||
|
||||
case inf:
|
||||
return nil, makeAcc(x.neg)
|
||||
|
||||
case nan:
|
||||
return nil, Undef
|
||||
}
|
||||
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
// Rat returns the rational number corresponding to x;
|
||||
// or nil if x is an infinity or NaN.
|
||||
// The result is Exact is x is not an Inf or NaN.
|
||||
// or nil if x is an infinity.
|
||||
// The result is Exact is x is not an Inf.
|
||||
// If a non-nil *Rat argument z is provided, Rat stores
|
||||
// the result in z instead of allocating a new Rat.
|
||||
func (x *Float) Rat(z *Rat) (*Rat, Accuracy) {
|
||||
|
|
@ -1190,9 +1151,6 @@ func (x *Float) Rat(z *Rat) (*Rat, Accuracy) {
|
|||
|
||||
case inf:
|
||||
return nil, makeAcc(x.neg)
|
||||
|
||||
case nan:
|
||||
return nil, Undef
|
||||
}
|
||||
|
||||
panic("unreachable")
|
||||
|
|
@ -1379,19 +1337,19 @@ func (z *Float) uquo(x, y *Float) {
|
|||
z.setExpAndRound(e-fnorm(z.mant), sbit)
|
||||
}
|
||||
|
||||
// ucmp returns Below, Exact, or Above, depending
|
||||
// on whether |x| < |y|, |x| == |y|, or |x| > |y|.
|
||||
// ucmp returns -1, 0, or +1, depending on whether
|
||||
// |x| < |y|, |x| == |y|, or |x| > |y|.
|
||||
// x and y must have a non-empty mantissa and valid exponent.
|
||||
func (x *Float) ucmp(y *Float) Accuracy {
|
||||
func (x *Float) ucmp(y *Float) int {
|
||||
if debugFloat {
|
||||
validateBinaryOperands(x, y)
|
||||
}
|
||||
|
||||
switch {
|
||||
case x.exp < y.exp:
|
||||
return Below
|
||||
return -1
|
||||
case x.exp > y.exp:
|
||||
return Above
|
||||
return +1
|
||||
}
|
||||
// x.exp == y.exp
|
||||
|
||||
|
|
@ -1410,13 +1368,13 @@ func (x *Float) ucmp(y *Float) Accuracy {
|
|||
}
|
||||
switch {
|
||||
case xm < ym:
|
||||
return Below
|
||||
return -1
|
||||
case xm > ym:
|
||||
return Above
|
||||
return +1
|
||||
}
|
||||
}
|
||||
|
||||
return Exact
|
||||
return 0
|
||||
}
|
||||
|
||||
// Handling of sign bit as defined by IEEE 754-2008, section 6.3:
|
||||
|
|
@ -1442,8 +1400,9 @@ func (x *Float) ucmp(y *Float) Accuracy {
|
|||
// it is changed to the larger of x's or y's precision before the operation.
|
||||
// Rounding is performed according to z's precision and rounding mode; and
|
||||
// z's accuracy reports the result error relative to the exact (not rounded)
|
||||
// result.
|
||||
// BUG(gri) Float.Add returns NaN if an operand is Inf.
|
||||
// result. Add panics with ErrNaN if x and y are infinities with opposite
|
||||
// signs. The value of z is undefined in that case.
|
||||
//
|
||||
// BUG(gri) When rounding ToNegativeInf, the sign of Float values rounded to 0 is incorrect.
|
||||
func (z *Float) Add(x, y *Float) *Float {
|
||||
if debugFloat {
|
||||
|
|
@ -1455,46 +1414,59 @@ func (z *Float) Add(x, y *Float) *Float {
|
|||
z.prec = umax32(x.prec, y.prec)
|
||||
}
|
||||
|
||||
// special cases
|
||||
if x.form != finite || y.form != finite {
|
||||
if x.form > finite || y.form > finite {
|
||||
// TODO(gri) handle Inf separately
|
||||
return z.SetNaN()
|
||||
}
|
||||
if x.form == zero {
|
||||
z.Set(y)
|
||||
if z.form == zero {
|
||||
z.neg = x.neg && y.neg // -0 + -0 == -0
|
||||
if x.form == finite && y.form == finite {
|
||||
// x + y (commom case)
|
||||
z.neg = x.neg
|
||||
if x.neg == y.neg {
|
||||
// x + y == x + y
|
||||
// (-x) + (-y) == -(x + y)
|
||||
z.uadd(x, y)
|
||||
} else {
|
||||
// x + (-y) == x - y == -(y - x)
|
||||
// (-x) + y == y - x == -(x - y)
|
||||
if x.ucmp(y) > 0 {
|
||||
z.usub(x, y)
|
||||
} else {
|
||||
z.neg = !z.neg
|
||||
z.usub(y, x)
|
||||
}
|
||||
return z
|
||||
}
|
||||
// y == ±0
|
||||
return z
|
||||
}
|
||||
|
||||
if x.form == inf && y.form == inf && x.neg != y.neg {
|
||||
// +Inf + -Inf
|
||||
// -Inf + +Inf
|
||||
// value of z is undefined but make sure it's valid
|
||||
z.acc = Exact
|
||||
z.form = zero
|
||||
z.neg = false
|
||||
panic(ErrNaN{"addition of infinities with opposite signs"})
|
||||
}
|
||||
|
||||
if x.form == zero && y.form == zero {
|
||||
// ±0 + ±0
|
||||
z.acc = Exact
|
||||
z.form = zero
|
||||
z.neg = x.neg && y.neg // -0 + -0 == -0
|
||||
return z
|
||||
}
|
||||
|
||||
if x.form == inf || y.form == zero {
|
||||
// ±Inf + y
|
||||
// x + ±0
|
||||
return z.Set(x)
|
||||
}
|
||||
|
||||
// x, y != 0
|
||||
z.neg = x.neg
|
||||
if x.neg == y.neg {
|
||||
// x + y == x + y
|
||||
// (-x) + (-y) == -(x + y)
|
||||
z.uadd(x, y)
|
||||
} else {
|
||||
// x + (-y) == x - y == -(y - x)
|
||||
// (-x) + y == y - x == -(x - y)
|
||||
if x.ucmp(y) == Above {
|
||||
z.usub(x, y)
|
||||
} else {
|
||||
z.neg = !z.neg
|
||||
z.usub(y, x)
|
||||
}
|
||||
}
|
||||
|
||||
return z
|
||||
// ±0 + y
|
||||
// x + ±Inf
|
||||
return z.Set(y)
|
||||
}
|
||||
|
||||
// Sub sets z to the rounded difference x-y and returns z.
|
||||
// Precision, rounding, and accuracy reporting are as for Add.
|
||||
// BUG(gri) Float.Sub returns NaN if an operand is Inf.
|
||||
// Sub panics with ErrNaN if x and y are infinities with equal
|
||||
// signs. The value of z is undefined in that case.
|
||||
func (z *Float) Sub(x, y *Float) *Float {
|
||||
if debugFloat {
|
||||
x.validate()
|
||||
|
|
@ -1505,46 +1477,59 @@ func (z *Float) Sub(x, y *Float) *Float {
|
|||
z.prec = umax32(x.prec, y.prec)
|
||||
}
|
||||
|
||||
// special cases
|
||||
if x.form != finite || y.form != finite {
|
||||
if x.form > finite || y.form > finite {
|
||||
// TODO(gri) handle Inf separately
|
||||
return z.SetNaN()
|
||||
}
|
||||
if x.form == zero {
|
||||
z.Neg(y)
|
||||
if z.form == zero {
|
||||
z.neg = x.neg && !y.neg // -0 - 0 == -0
|
||||
if x.form == finite && y.form == finite {
|
||||
// x - y (common case)
|
||||
z.neg = x.neg
|
||||
if x.neg != y.neg {
|
||||
// x - (-y) == x + y
|
||||
// (-x) - y == -(x + y)
|
||||
z.uadd(x, y)
|
||||
} else {
|
||||
// x - y == x - y == -(y - x)
|
||||
// (-x) - (-y) == y - x == -(x - y)
|
||||
if x.ucmp(y) > 0 {
|
||||
z.usub(x, y)
|
||||
} else {
|
||||
z.neg = !z.neg
|
||||
z.usub(y, x)
|
||||
}
|
||||
return z
|
||||
}
|
||||
// y == ±0
|
||||
return z
|
||||
}
|
||||
|
||||
if x.form == inf && y.form == inf && x.neg == y.neg {
|
||||
// +Inf - +Inf
|
||||
// -Inf - -Inf
|
||||
// value of z is undefined but make sure it's valid
|
||||
z.acc = Exact
|
||||
z.form = zero
|
||||
z.neg = false
|
||||
panic(ErrNaN{"subtraction of infinities with equal signs"})
|
||||
}
|
||||
|
||||
if x.form == zero && y.form == zero {
|
||||
// ±0 - ±0
|
||||
z.acc = Exact
|
||||
z.form = zero
|
||||
z.neg = x.neg && !y.neg // -0 - +0 == -0
|
||||
return z
|
||||
}
|
||||
|
||||
if x.form == inf || y.form == zero {
|
||||
// ±Inf - y
|
||||
// x - ±0
|
||||
return z.Set(x)
|
||||
}
|
||||
|
||||
// x, y != 0
|
||||
z.neg = x.neg
|
||||
if x.neg != y.neg {
|
||||
// x - (-y) == x + y
|
||||
// (-x) - y == -(x + y)
|
||||
z.uadd(x, y)
|
||||
} else {
|
||||
// x - y == x - y == -(y - x)
|
||||
// (-x) - (-y) == y - x == -(x - y)
|
||||
if x.ucmp(y) == Above {
|
||||
z.usub(x, y)
|
||||
} else {
|
||||
z.neg = !z.neg
|
||||
z.usub(y, x)
|
||||
}
|
||||
}
|
||||
|
||||
return z
|
||||
// ±0 - y
|
||||
// x - ±Inf
|
||||
return z.Neg(y)
|
||||
}
|
||||
|
||||
// Mul sets z to the rounded product x*y and returns z.
|
||||
// Precision, rounding, and accuracy reporting are as for Add.
|
||||
// BUG(gri) Float.Mul returns NaN if an operand is Inf.
|
||||
// Mul panics with ErrNaN if one operand is zero and the other
|
||||
// operand an infinity. The value of z is undefined in that case.
|
||||
func (z *Float) Mul(x, y *Float) *Float {
|
||||
if debugFloat {
|
||||
x.validate()
|
||||
|
|
@ -1557,27 +1542,39 @@ func (z *Float) Mul(x, y *Float) *Float {
|
|||
|
||||
z.neg = x.neg != y.neg
|
||||
|
||||
// special cases
|
||||
if x.form != finite || y.form != finite {
|
||||
if x.form > finite || y.form > finite {
|
||||
// TODO(gri) handle Inf separately
|
||||
return z.SetNaN()
|
||||
}
|
||||
// x == ±0 || y == ±0
|
||||
z.acc = Exact
|
||||
z.form = zero
|
||||
if x.form == finite && y.form == finite {
|
||||
// x * y (common case)
|
||||
z.umul(x, y)
|
||||
return z
|
||||
}
|
||||
|
||||
// x, y != 0
|
||||
z.umul(x, y)
|
||||
z.acc = Exact
|
||||
if x.form == zero && y.form == inf || x.form == inf && y.form == zero {
|
||||
// ±0 * ±Inf
|
||||
// ±Inf * ±0
|
||||
// value of z is undefined but make sure it's valid
|
||||
z.form = zero
|
||||
z.neg = false
|
||||
panic(ErrNaN{"multiplication of zero with infinity"})
|
||||
}
|
||||
|
||||
if x.form == inf || y.form == inf {
|
||||
// ±Inf * y
|
||||
// x * ±Inf
|
||||
z.form = inf
|
||||
return z
|
||||
}
|
||||
|
||||
// ±0 * y
|
||||
// x * ±0
|
||||
z.form = zero
|
||||
return z
|
||||
}
|
||||
|
||||
// Quo sets z to the rounded quotient x/y and returns z.
|
||||
// Precision, rounding, and accuracy reporting are as for Add.
|
||||
// BUG(gri) Float.Quo returns NaN if an operand is Inf.
|
||||
// Quo panics with ErrNaN if both operands are zero or infinities.
|
||||
// The value of z is undefined in that case.
|
||||
func (z *Float) Quo(x, y *Float) *Float {
|
||||
if debugFloat {
|
||||
x.validate()
|
||||
|
|
@ -1590,83 +1587,68 @@ func (z *Float) Quo(x, y *Float) *Float {
|
|||
|
||||
z.neg = x.neg != y.neg
|
||||
|
||||
// special cases
|
||||
z.acc = Exact
|
||||
if x.form != finite || y.form != finite {
|
||||
if x.form > finite || y.form > finite {
|
||||
// TODO(gri) handle Inf separately
|
||||
return z.SetNaN()
|
||||
}
|
||||
// x == ±0 || y == ±0
|
||||
if x.form == zero {
|
||||
if y.form == zero {
|
||||
return z.SetNaN()
|
||||
}
|
||||
z.form = zero
|
||||
return z
|
||||
}
|
||||
// y == ±0
|
||||
z.form = inf
|
||||
if x.form == finite && y.form == finite {
|
||||
// x / y (common case)
|
||||
z.uquo(x, y)
|
||||
return z
|
||||
}
|
||||
|
||||
// x, y != 0
|
||||
z.uquo(x, y)
|
||||
z.acc = Exact
|
||||
if x.form == zero && y.form == zero || x.form == inf && y.form == inf {
|
||||
// ±0 / ±0
|
||||
// ±Inf / ±Inf
|
||||
// value of z is undefined but make sure it's valid
|
||||
z.form = zero
|
||||
z.neg = false
|
||||
panic(ErrNaN{"division of zero by zero or infinity by infinity"})
|
||||
}
|
||||
|
||||
if x.form == zero || y.form == inf {
|
||||
// ±0 / y
|
||||
// x / ±Inf
|
||||
z.form = zero
|
||||
return z
|
||||
}
|
||||
|
||||
// x / ±0
|
||||
// ±Inf / y
|
||||
z.form = inf
|
||||
return z
|
||||
}
|
||||
|
||||
type cmpResult struct {
|
||||
acc Accuracy
|
||||
}
|
||||
|
||||
// Cmp compares x and y and returns:
|
||||
//
|
||||
// Below if x < y
|
||||
// Exact if x == y (incl. -0 == 0, -Inf == -Inf, and +Inf == +Inf)
|
||||
// Above if x > y
|
||||
// Undef if any of x, y is NaN
|
||||
// -1 if x < y
|
||||
// 0 if x == y (incl. -0 == 0, -Inf == -Inf, and +Inf == +Inf)
|
||||
// +1 if x > y
|
||||
//
|
||||
func (x *Float) Cmp(y *Float) cmpResult {
|
||||
func (x *Float) Cmp(y *Float) int {
|
||||
if debugFloat {
|
||||
x.validate()
|
||||
y.validate()
|
||||
}
|
||||
|
||||
if x.form == nan || y.form == nan {
|
||||
return cmpResult{Undef}
|
||||
}
|
||||
|
||||
mx := x.ord()
|
||||
my := y.ord()
|
||||
switch {
|
||||
case mx < my:
|
||||
return cmpResult{Below}
|
||||
return -1
|
||||
case mx > my:
|
||||
return cmpResult{Above}
|
||||
return +1
|
||||
}
|
||||
// mx == my
|
||||
|
||||
// only if |mx| == 1 we have to compare the mantissae
|
||||
switch mx {
|
||||
case -1:
|
||||
return cmpResult{y.ucmp(x)}
|
||||
return y.ucmp(x)
|
||||
case +1:
|
||||
return cmpResult{x.ucmp(y)}
|
||||
return x.ucmp(y)
|
||||
}
|
||||
|
||||
return cmpResult{Exact}
|
||||
return 0
|
||||
}
|
||||
|
||||
// The following accessors simplify testing of Cmp results.
|
||||
func (res cmpResult) Acc() Accuracy { return res.acc }
|
||||
func (res cmpResult) Eql() bool { return res.acc == Exact }
|
||||
func (res cmpResult) Neq() bool { return res.acc != Exact }
|
||||
func (res cmpResult) Lss() bool { return res.acc == Below }
|
||||
func (res cmpResult) Leq() bool { return res.acc&Above == 0 }
|
||||
func (res cmpResult) Gtr() bool { return res.acc == Above }
|
||||
func (res cmpResult) Geq() bool { return res.acc&Below == 0 }
|
||||
|
||||
// ord classifies x and returns:
|
||||
//
|
||||
// -2 if -Inf == x
|
||||
|
|
@ -1675,7 +1657,6 @@ func (res cmpResult) Geq() bool { return res.acc&Below == 0 }
|
|||
// +1 if 0 < x < +Inf
|
||||
// +2 if x == +Inf
|
||||
//
|
||||
// x must not be NaN.
|
||||
func (x *Float) ord() int {
|
||||
var m int
|
||||
switch x.form {
|
||||
|
|
@ -1685,8 +1666,6 @@ func (x *Float) ord() int {
|
|||
return 0
|
||||
case inf:
|
||||
m = 2
|
||||
default:
|
||||
panic("unreachable")
|
||||
}
|
||||
if x.neg {
|
||||
m = -m
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ func TestFloatZeroValue(t *testing.T) {
|
|||
{1, 2, 0, 0, '*', (*Float).Mul},
|
||||
{2, 0, 1, 0, '*', (*Float).Mul},
|
||||
|
||||
{0, 0, 0, 0, '/', (*Float).Quo}, // = Nan
|
||||
// {0, 0, 0, 0, '/', (*Float).Quo}, // panics
|
||||
{0, 2, 1, 2, '/', (*Float).Quo},
|
||||
{1, 2, 0, 0, '/', (*Float).Quo}, // = +Inf
|
||||
{2, 0, 1, 0, '/', (*Float).Quo},
|
||||
|
|
@ -77,7 +77,7 @@ func TestFloatZeroValue(t *testing.T) {
|
|||
z := make(test.z)
|
||||
test.op(z, make(test.x), make(test.y))
|
||||
got := 0
|
||||
if z.IsFinite() {
|
||||
if !z.IsInf() {
|
||||
got = int(z.int64())
|
||||
}
|
||||
if got != test.want {
|
||||
|
|
@ -97,11 +97,9 @@ func makeFloat(s string) *Float {
|
|||
case "-0":
|
||||
return x.Neg(&x)
|
||||
case "Inf", "+Inf":
|
||||
return x.SetInf(+1)
|
||||
return x.SetInf(false)
|
||||
case "-Inf":
|
||||
return x.SetInf(-1)
|
||||
case "NaN", "-NaN":
|
||||
return x.SetNaN()
|
||||
return x.SetInf(true)
|
||||
}
|
||||
|
||||
x.SetPrec(1000)
|
||||
|
|
@ -123,7 +121,6 @@ func TestFloatSetPrec(t *testing.T) {
|
|||
{"-0", 0, "-0", Exact},
|
||||
{"-Inf", 0, "-Inf", Exact},
|
||||
{"+Inf", 0, "+Inf", Exact},
|
||||
{"NaN", 0, "NaN", Exact},
|
||||
{"123", 0, "0", Below},
|
||||
{"-123", 0, "-0", Above},
|
||||
|
||||
|
|
@ -132,7 +129,6 @@ func TestFloatSetPrec(t *testing.T) {
|
|||
{"-0", MaxPrec, "-0", Exact},
|
||||
{"-Inf", MaxPrec, "-Inf", Exact},
|
||||
{"+Inf", MaxPrec, "+Inf", Exact},
|
||||
{"NaN", MaxPrec, "NaN", Exact},
|
||||
|
||||
// just a few regular cases - general rounding is tested elsewhere
|
||||
{"1.5", 1, "2", Above},
|
||||
|
|
@ -164,7 +160,6 @@ func TestFloatMinPrec(t *testing.T) {
|
|||
{"-0", 0},
|
||||
{"+Inf", 0},
|
||||
{"-Inf", 0},
|
||||
{"NaN", 0},
|
||||
{"1", 1},
|
||||
{"2", 1},
|
||||
{"3", 2},
|
||||
|
|
@ -191,7 +186,6 @@ func TestFloatSign(t *testing.T) {
|
|||
{"+0", 0},
|
||||
{"+1", +1},
|
||||
{"+Inf", +1},
|
||||
{"NaN", 0},
|
||||
} {
|
||||
x := makeFloat(test.x)
|
||||
s := x.Sign()
|
||||
|
|
@ -201,13 +195,9 @@ func TestFloatSign(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// feq(x, y) is like x.Cmp(y) == 0 but it also considers the sign of 0 (0 != -0).
|
||||
// Caution: Two NaN's are equal with this function!
|
||||
func feq(x, y *Float) bool {
|
||||
if x.IsNaN() || y.IsNaN() {
|
||||
return x.IsNaN() && y.IsNaN()
|
||||
}
|
||||
return x.Cmp(y).Eql() && x.IsNeg() == y.IsNeg()
|
||||
// alike(x, y) is like x.Cmp(y) == 0 but also considers the sign of 0 (0 != -0).
|
||||
func alike(x, y *Float) bool {
|
||||
return x.Cmp(y) == 0 && x.Signbit() == y.Signbit()
|
||||
}
|
||||
|
||||
func TestFloatMantExp(t *testing.T) {
|
||||
|
|
@ -222,7 +212,6 @@ func TestFloatMantExp(t *testing.T) {
|
|||
{"Inf", "+Inf", 0},
|
||||
{"+Inf", "+Inf", 0},
|
||||
{"-Inf", "-Inf", 0},
|
||||
{"NaN", "NaN", 0},
|
||||
{"1.5", "0.75", 1},
|
||||
{"1.024e3", "0.5", 11},
|
||||
{"-0.125", "-0.5", -2},
|
||||
|
|
@ -231,7 +220,7 @@ func TestFloatMantExp(t *testing.T) {
|
|||
mant := makeFloat(test.mant)
|
||||
m := new(Float)
|
||||
e := x.MantExp(m)
|
||||
if !feq(m, mant) || e != test.exp {
|
||||
if !alike(m, mant) || e != test.exp {
|
||||
t.Errorf("%s.MantExp() = %s, %d; want %s, %d", test.x, m.Format('g', 10), e, test.mant, test.exp)
|
||||
}
|
||||
}
|
||||
|
|
@ -242,7 +231,7 @@ func TestFloatMantExpAliasing(t *testing.T) {
|
|||
if e := x.MantExp(x); e != 10 {
|
||||
t.Fatalf("Float.MantExp aliasing error: got %d; want 10", e)
|
||||
}
|
||||
if want := makeFloat("0.5"); !feq(x, want) {
|
||||
if want := makeFloat("0.5"); !alike(x, want) {
|
||||
t.Fatalf("Float.MantExp aliasing error: got %s; want %s", x.Format('g', 10), want.Format('g', 10))
|
||||
}
|
||||
}
|
||||
|
|
@ -274,12 +263,12 @@ func TestFloatSetMantExp(t *testing.T) {
|
|||
want := makeFloat(test.z)
|
||||
var z Float
|
||||
z.SetMantExp(frac, test.exp)
|
||||
if !feq(&z, want) {
|
||||
if !alike(&z, want) {
|
||||
t.Errorf("SetMantExp(%s, %d) = %s; want %s", test.frac, test.exp, z.Format('g', 10), test.z)
|
||||
}
|
||||
// test inverse property
|
||||
mant := new(Float)
|
||||
if z.SetMantExp(mant, want.MantExp(mant)).Cmp(want).Neq() {
|
||||
if z.SetMantExp(mant, want.MantExp(mant)).Cmp(want) != 0 {
|
||||
t.Errorf("Inverse property not satisfied: got %s; want %s", z.Format('g', 10), test.z)
|
||||
}
|
||||
}
|
||||
|
|
@ -287,33 +276,27 @@ func TestFloatSetMantExp(t *testing.T) {
|
|||
|
||||
func TestFloatPredicates(t *testing.T) {
|
||||
for _, test := range []struct {
|
||||
x string
|
||||
neg, zero, finite, inf, nan bool
|
||||
x string
|
||||
sign int
|
||||
signbit, inf bool
|
||||
}{
|
||||
{x: "-Inf", neg: true, inf: true},
|
||||
{x: "-1", neg: true, finite: true},
|
||||
{x: "-0", neg: true, zero: true, finite: true},
|
||||
{x: "0", zero: true, finite: true},
|
||||
{x: "1", finite: true},
|
||||
{x: "+Inf", inf: true},
|
||||
{x: "NaN", nan: true},
|
||||
{x: "-Inf", sign: -1, signbit: true, inf: true},
|
||||
{x: "-1", sign: -1, signbit: true},
|
||||
{x: "-0", signbit: true},
|
||||
{x: "0"},
|
||||
{x: "1", sign: 1},
|
||||
{x: "+Inf", sign: 1, inf: true},
|
||||
} {
|
||||
x := makeFloat(test.x)
|
||||
if got := x.IsNeg(); got != test.neg {
|
||||
t.Errorf("(%s).IsNeg() = %v; want %v", test.x, got, test.neg)
|
||||
if got := x.Signbit(); got != test.signbit {
|
||||
t.Errorf("(%s).Signbit() = %v; want %v", test.x, got, test.signbit)
|
||||
}
|
||||
if got := x.IsZero(); got != test.zero {
|
||||
t.Errorf("(%s).IsZero() = %v; want %v", test.x, got, test.zero)
|
||||
}
|
||||
if got := x.IsFinite(); got != test.finite {
|
||||
t.Errorf("(%s).IsFinite() = %v; want %v", test.x, got, test.finite)
|
||||
if got := x.Sign(); got != test.sign {
|
||||
t.Errorf("(%s).Sign() = %d; want %d", test.x, got, test.sign)
|
||||
}
|
||||
if got := x.IsInf(); got != test.inf {
|
||||
t.Errorf("(%s).IsInf() = %v; want %v", test.x, got, test.inf)
|
||||
}
|
||||
if got := x.IsNaN(); got != test.nan {
|
||||
t.Errorf("(%s).IsNaN() = %v; want %v", test.x, got, test.nan)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -333,7 +316,6 @@ func TestFloatIsInt(t *testing.T) {
|
|||
"Inf",
|
||||
"+Inf",
|
||||
"-Inf",
|
||||
"NaN",
|
||||
} {
|
||||
s := strings.TrimSuffix(test, " int")
|
||||
want := s != test
|
||||
|
|
@ -413,7 +395,7 @@ func testFloatRound(t *testing.T, x, r int64, prec uint, mode RoundingMode) {
|
|||
// should be the same as rounding by SetInt64 after setting the
|
||||
// precision)
|
||||
g := new(Float).SetMode(mode).SetPrec(prec).SetInt64(x)
|
||||
if !feq(g, f) {
|
||||
if !alike(g, f) {
|
||||
t.Errorf("round %s (%d bits, %s) not symmetric: got %s and %s; want %s",
|
||||
toBinary(x), prec, mode,
|
||||
toBinary(g.int64()),
|
||||
|
|
@ -426,7 +408,7 @@ func testFloatRound(t *testing.T, x, r int64, prec uint, mode RoundingMode) {
|
|||
// h and f should be the same
|
||||
// (repeated rounding should be idempotent)
|
||||
h := new(Float).SetMode(mode).SetPrec(prec).Set(f)
|
||||
if !feq(h, f) {
|
||||
if !alike(h, f) {
|
||||
t.Errorf("round %s (%d bits, %s) not idempotent: got %s and %s; want %s",
|
||||
toBinary(x), prec, mode,
|
||||
toBinary(h.int64()),
|
||||
|
|
@ -647,13 +629,6 @@ func TestFloatSetFloat64(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// test NaN
|
||||
var f Float
|
||||
f.SetFloat64(math.NaN())
|
||||
if got, acc := f.Float64(); !math.IsNaN(got) || acc != Undef {
|
||||
t.Errorf("got %g (%s, %s); want %g (undef)", got, f.Format('p', 0), acc, math.NaN())
|
||||
}
|
||||
|
||||
// test basic rounding behavior (exhaustive rounding testing is done elsewhere)
|
||||
const x uint64 = 0x8765432143218 // 53 bits needed
|
||||
for prec := uint(1); prec <= 52; prec++ {
|
||||
|
|
@ -664,6 +639,17 @@ func TestFloatSetFloat64(t *testing.T) {
|
|||
t.Errorf("got %g (%s); want %g", got, f.Format('p', 0), want)
|
||||
}
|
||||
}
|
||||
|
||||
// test NaN
|
||||
defer func() {
|
||||
if p, ok := recover().(ErrNaN); !ok {
|
||||
t.Errorf("got %v; want ErrNaN panic", p)
|
||||
}
|
||||
}()
|
||||
var f Float
|
||||
f.SetFloat64(math.NaN())
|
||||
// should not reach here
|
||||
t.Errorf("got %s; want ErrNaN panic", f.Format('p', 0))
|
||||
}
|
||||
|
||||
func TestFloatSetInt(t *testing.T) {
|
||||
|
|
@ -747,20 +733,18 @@ func TestFloatSetRat(t *testing.T) {
|
|||
func TestFloatSetInf(t *testing.T) {
|
||||
var f Float
|
||||
for _, test := range []struct {
|
||||
sign int
|
||||
prec uint
|
||||
want string
|
||||
signbit bool
|
||||
prec uint
|
||||
want string
|
||||
}{
|
||||
{0, 0, "+Inf"},
|
||||
{100, 0, "+Inf"},
|
||||
{-1, 0, "-Inf"},
|
||||
{0, 10, "+Inf"},
|
||||
{100, 20, "+Inf"},
|
||||
{-1, 30, "-Inf"},
|
||||
{false, 0, "+Inf"},
|
||||
{true, 0, "-Inf"},
|
||||
{false, 10, "+Inf"},
|
||||
{true, 30, "-Inf"},
|
||||
} {
|
||||
x := f.SetPrec(test.prec).SetInf(test.sign)
|
||||
x := f.SetPrec(test.prec).SetInf(test.signbit)
|
||||
if got := x.String(); got != test.want || x.Prec() != test.prec {
|
||||
t.Errorf("SetInf(%d) = %s (prec = %d); want %s (prec = %d)", test.sign, got, x.Prec(), test.want, test.prec)
|
||||
t.Errorf("SetInf(%v) = %s (prec = %d); want %s (prec = %d)", test.signbit, got, x.Prec(), test.want, test.prec)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -786,7 +770,6 @@ func TestFloatUint64(t *testing.T) {
|
|||
{"18446744073709551616", math.MaxUint64, Below},
|
||||
{"1e10000", math.MaxUint64, Below},
|
||||
{"+Inf", math.MaxUint64, Below},
|
||||
{"NaN", 0, Undef},
|
||||
} {
|
||||
x := makeFloat(test.x)
|
||||
out, acc := x.Uint64()
|
||||
|
|
@ -827,7 +810,6 @@ func TestFloatInt64(t *testing.T) {
|
|||
{"9223372036854775808", math.MaxInt64, Below},
|
||||
{"1e10000", math.MaxInt64, Below},
|
||||
{"+Inf", math.MaxInt64, Below},
|
||||
{"NaN", 0, Undef},
|
||||
} {
|
||||
x := makeFloat(test.x)
|
||||
out, acc := x.Int64()
|
||||
|
|
@ -891,12 +873,6 @@ func TestFloatFloat32(t *testing.T) {
|
|||
t.Errorf("idempotency test: got %g (%s); want %g (Exact)", out2, acc2, out)
|
||||
}
|
||||
}
|
||||
|
||||
// test NaN
|
||||
x := makeFloat("NaN")
|
||||
if out, acc := x.Float32(); out == out || acc != Undef {
|
||||
t.Errorf("NaN: got %g (%s); want NaN (Undef)", out, acc)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFloatFloat64(t *testing.T) {
|
||||
|
|
@ -963,12 +939,6 @@ func TestFloatFloat64(t *testing.T) {
|
|||
t.Errorf("idempotency test: got %g (%s); want %g (Exact)", out2, acc2, out)
|
||||
}
|
||||
}
|
||||
|
||||
// test NaN
|
||||
x := makeFloat("NaN")
|
||||
if out, acc := x.Float64(); out == out || acc != Undef {
|
||||
t.Errorf("NaN: got %g (%s); want NaN (Undef)", out, acc)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFloatInt(t *testing.T) {
|
||||
|
|
@ -983,7 +953,6 @@ func TestFloatInt(t *testing.T) {
|
|||
{"Inf", "nil", Below},
|
||||
{"+Inf", "nil", Below},
|
||||
{"-Inf", "nil", Above},
|
||||
{"NaN", "nil", Undef},
|
||||
{"1", "1", Exact},
|
||||
{"-1", "-1", Exact},
|
||||
{"1.23", "1", Below},
|
||||
|
|
@ -1028,7 +997,6 @@ func TestFloatRat(t *testing.T) {
|
|||
{"Inf", "nil", Below},
|
||||
{"+Inf", "nil", Below},
|
||||
{"-Inf", "nil", Above},
|
||||
{"NaN", "nil", Undef},
|
||||
{"1", "1/1", Exact},
|
||||
{"-1", "-1/1", Exact},
|
||||
{"1.25", "5/4", Exact},
|
||||
|
|
@ -1056,7 +1024,7 @@ func TestFloatRat(t *testing.T) {
|
|||
// inverse conversion
|
||||
if res != nil {
|
||||
got := new(Float).SetPrec(64).SetRat(res)
|
||||
if got.Cmp(x).Neq() {
|
||||
if got.Cmp(x) != 0 {
|
||||
t.Errorf("%s: got %s; want %s", test.x, got, x)
|
||||
}
|
||||
}
|
||||
|
|
@ -1081,17 +1049,16 @@ func TestFloatAbs(t *testing.T) {
|
|||
"1e-1000",
|
||||
"1e1000",
|
||||
"Inf",
|
||||
"NaN",
|
||||
} {
|
||||
p := makeFloat(test)
|
||||
a := new(Float).Abs(p)
|
||||
if !feq(a, p) {
|
||||
if !alike(a, p) {
|
||||
t.Errorf("%s: got %s; want %s", test, a.Format('g', 10), test)
|
||||
}
|
||||
|
||||
n := makeFloat("-" + test)
|
||||
a.Abs(n)
|
||||
if !feq(a, p) {
|
||||
if !alike(a, p) {
|
||||
t.Errorf("-%s: got %s; want %s", test, a.Format('g', 10), test)
|
||||
}
|
||||
}
|
||||
|
|
@ -1106,16 +1073,15 @@ func TestFloatNeg(t *testing.T) {
|
|||
"1e-1000",
|
||||
"1e1000",
|
||||
"Inf",
|
||||
"NaN",
|
||||
} {
|
||||
p1 := makeFloat(test)
|
||||
n1 := makeFloat("-" + test)
|
||||
n2 := new(Float).Neg(p1)
|
||||
p2 := new(Float).Neg(n2)
|
||||
if !feq(n2, n1) {
|
||||
if !alike(n2, n1) {
|
||||
t.Errorf("%s: got %s; want %s", test, n2.Format('g', 10), n1.Format('g', 10))
|
||||
}
|
||||
if !feq(p2, p1) {
|
||||
if !alike(p2, p1) {
|
||||
t.Errorf("%s: got %s; want %s", test, p2.Format('g', 10), p1.Format('g', 10))
|
||||
}
|
||||
}
|
||||
|
|
@ -1133,7 +1099,7 @@ func TestFloatInc(t *testing.T) {
|
|||
for i := 0; i < n; i++ {
|
||||
x.Add(&x, &one)
|
||||
}
|
||||
if x.Cmp(new(Float).SetInt64(n)).Neq() {
|
||||
if x.Cmp(new(Float).SetInt64(n)) != 0 {
|
||||
t.Errorf("prec = %d: got %s; want %d", prec, &x, n)
|
||||
}
|
||||
}
|
||||
|
|
@ -1174,14 +1140,14 @@ func TestFloatAdd(t *testing.T) {
|
|||
got := new(Float).SetPrec(prec).SetMode(mode)
|
||||
got.Add(x, y)
|
||||
want := zbits.round(prec, mode)
|
||||
if got.Cmp(want).Neq() {
|
||||
if got.Cmp(want) != 0 {
|
||||
t.Errorf("i = %d, prec = %d, %s:\n\t %s %v\n\t+ %s %v\n\t= %s\n\twant %s",
|
||||
i, prec, mode, x, xbits, y, ybits, got, want)
|
||||
}
|
||||
|
||||
got.Sub(z, x)
|
||||
want = ybits.round(prec, mode)
|
||||
if got.Cmp(want).Neq() {
|
||||
if got.Cmp(want) != 0 {
|
||||
t.Errorf("i = %d, prec = %d, %s:\n\t %s %v\n\t- %s %v\n\t= %s\n\twant %s",
|
||||
i, prec, mode, z, zbits, x, xbits, got, want)
|
||||
}
|
||||
|
|
@ -1276,17 +1242,17 @@ func TestFloatMul(t *testing.T) {
|
|||
got := new(Float).SetPrec(prec).SetMode(mode)
|
||||
got.Mul(x, y)
|
||||
want := zbits.round(prec, mode)
|
||||
if got.Cmp(want).Neq() {
|
||||
if got.Cmp(want) != 0 {
|
||||
t.Errorf("i = %d, prec = %d, %s:\n\t %s %v\n\t* %s %v\n\t= %s\n\twant %s",
|
||||
i, prec, mode, x, xbits, y, ybits, got, want)
|
||||
}
|
||||
|
||||
if x.IsZero() {
|
||||
if x.Sign() == 0 {
|
||||
continue // ignore div-0 case (not invertable)
|
||||
}
|
||||
got.Quo(z, x)
|
||||
want = ybits.round(prec, mode)
|
||||
if got.Cmp(want).Neq() {
|
||||
if got.Cmp(want) != 0 {
|
||||
t.Errorf("i = %d, prec = %d, %s:\n\t %s %v\n\t/ %s %v\n\t= %s\n\twant %s",
|
||||
i, prec, mode, z, zbits, x, xbits, got, want)
|
||||
}
|
||||
|
|
@ -1369,7 +1335,7 @@ func TestIssue6866(t *testing.T) {
|
|||
p.Mul(p, psix)
|
||||
z2.Sub(two, p)
|
||||
|
||||
if z1.Cmp(z2).Neq() {
|
||||
if z1.Cmp(z2) != 0 {
|
||||
t.Fatalf("prec %d: got z1 = %s != z2 = %s; want z1 == z2\n", prec, z1, z2)
|
||||
}
|
||||
if z1.Sign() != 0 {
|
||||
|
|
@ -1420,7 +1386,7 @@ func TestFloatQuo(t *testing.T) {
|
|||
prec := uint(preci + d)
|
||||
got := new(Float).SetPrec(prec).SetMode(mode).Quo(x, y)
|
||||
want := bits.round(prec, mode)
|
||||
if got.Cmp(want).Neq() {
|
||||
if got.Cmp(want) != 0 {
|
||||
t.Errorf("i = %d, prec = %d, %s:\n\t %s\n\t/ %s\n\t= %s\n\twant %s",
|
||||
i, prec, mode, x, y, got, want)
|
||||
}
|
||||
|
|
@ -1472,10 +1438,10 @@ func TestFloatQuoSmoke(t *testing.T) {
|
|||
|
||||
// TestFloatArithmeticSpecialValues tests that Float operations produce the
|
||||
// correct results for combinations of zero (±0), finite (±1 and ±2.71828),
|
||||
// and non-finite (±Inf, NaN) operands.
|
||||
// and infinite (±Inf) operands.
|
||||
func TestFloatArithmeticSpecialValues(t *testing.T) {
|
||||
zero := 0.0
|
||||
args := []float64{math.Inf(-1), -2.71828, -1, -zero, zero, 1, 2.71828, math.Inf(1), math.NaN()}
|
||||
args := []float64{math.Inf(-1), -2.71828, -1, -zero, zero, 1, 2.71828, math.Inf(1)}
|
||||
xx := new(Float)
|
||||
yy := new(Float)
|
||||
got := new(Float)
|
||||
|
|
@ -1486,41 +1452,59 @@ func TestFloatArithmeticSpecialValues(t *testing.T) {
|
|||
// check conversion is correct
|
||||
// (no need to do this for y, since we see exactly the
|
||||
// same values there)
|
||||
if got, acc := xx.Float64(); !math.IsNaN(x) && (got != x || acc != Exact) {
|
||||
if got, acc := xx.Float64(); got != x || acc != Exact {
|
||||
t.Errorf("Float(%g) == %g (%s)", x, got, acc)
|
||||
}
|
||||
for _, y := range args {
|
||||
yy.SetFloat64(y)
|
||||
var op string
|
||||
var z float64
|
||||
var (
|
||||
op string
|
||||
z float64
|
||||
f func(z, x, y *Float) *Float
|
||||
)
|
||||
switch i {
|
||||
case 0:
|
||||
op = "+"
|
||||
z = x + y
|
||||
got.Add(xx, yy)
|
||||
f = (*Float).Add
|
||||
case 1:
|
||||
op = "-"
|
||||
z = x - y
|
||||
got.Sub(xx, yy)
|
||||
f = (*Float).Sub
|
||||
case 2:
|
||||
op = "*"
|
||||
z = x * y
|
||||
got.Mul(xx, yy)
|
||||
f = (*Float).Mul
|
||||
case 3:
|
||||
op = "/"
|
||||
z = x / y
|
||||
got.Quo(xx, yy)
|
||||
f = (*Float).Quo
|
||||
default:
|
||||
panic("unreachable")
|
||||
}
|
||||
// At the moment an Inf operand always leads to a NaN result (known bug).
|
||||
// TODO(gri) remove this once the bug is fixed.
|
||||
if math.IsInf(x, 0) || math.IsInf(y, 0) {
|
||||
want.SetNaN()
|
||||
} else {
|
||||
want.SetFloat64(z)
|
||||
var errnan bool // set if execution of f panicked with ErrNaN
|
||||
// protect execution of f
|
||||
func() {
|
||||
defer func() {
|
||||
if p := recover(); p != nil {
|
||||
_ = p.(ErrNaN) // re-panic if not ErrNaN
|
||||
errnan = true
|
||||
}
|
||||
}()
|
||||
f(got, xx, yy)
|
||||
}()
|
||||
if math.IsNaN(z) {
|
||||
if !errnan {
|
||||
t.Errorf("%5g %s %5g = %5s; want ErrNaN panic", x, op, y, got)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if !feq(got, want) {
|
||||
if errnan {
|
||||
t.Errorf("%5g %s %5g panicked with ErrNan; want %5s", x, op, y, want)
|
||||
continue
|
||||
}
|
||||
want.SetFloat64(z)
|
||||
if !alike(got, want) {
|
||||
t.Errorf("%5g %s %5g = %5s; want %5s", x, op, y, got, want)
|
||||
}
|
||||
}
|
||||
|
|
@ -1645,11 +1629,11 @@ func TestFloatArithmeticRounding(t *testing.T) {
|
|||
}
|
||||
|
||||
// TestFloatCmpSpecialValues tests that Cmp produces the correct results for
|
||||
// combinations of zero (±0), finite (±1 and ±2.71828), and non-finite (±Inf,
|
||||
// NaN) operands.
|
||||
// combinations of zero (±0), finite (±1 and ±2.71828), and infinite (±Inf)
|
||||
// operands.
|
||||
func TestFloatCmpSpecialValues(t *testing.T) {
|
||||
zero := 0.0
|
||||
args := []float64{math.Inf(-1), -2.71828, -1, -zero, zero, 1, 2.71828, math.Inf(1), math.NaN()}
|
||||
args := []float64{math.Inf(-1), -2.71828, -1, -zero, zero, 1, 2.71828, math.Inf(1)}
|
||||
xx := new(Float)
|
||||
yy := new(Float)
|
||||
for i := 0; i < 4; i++ {
|
||||
|
|
@ -1658,20 +1642,18 @@ func TestFloatCmpSpecialValues(t *testing.T) {
|
|||
// check conversion is correct
|
||||
// (no need to do this for y, since we see exactly the
|
||||
// same values there)
|
||||
if got, acc := xx.Float64(); !math.IsNaN(x) && (got != x || acc != Exact) {
|
||||
if got, acc := xx.Float64(); got != x || acc != Exact {
|
||||
t.Errorf("Float(%g) == %g (%s)", x, got, acc)
|
||||
}
|
||||
for _, y := range args {
|
||||
yy.SetFloat64(y)
|
||||
got := xx.Cmp(yy).Acc()
|
||||
want := Undef
|
||||
got := xx.Cmp(yy)
|
||||
want := 0
|
||||
switch {
|
||||
case x < y:
|
||||
want = Below
|
||||
case x == y:
|
||||
want = Exact
|
||||
want = -1
|
||||
case x > y:
|
||||
want = Above
|
||||
want = +1
|
||||
}
|
||||
if got != want {
|
||||
t.Errorf("(%g).Cmp(%g) = %s; want %s", x, y, got, want)
|
||||
|
|
|
|||
|
|
@ -73,10 +73,8 @@ func (z *Float) Scan(r io.ByteScanner, base int) (f *Float, b int, err error) {
|
|||
prec = 64
|
||||
}
|
||||
|
||||
// NaNs ignore sign, mantissa, and exponent so we can set
|
||||
// them below while having a valid value for z in case of
|
||||
// errors.
|
||||
z.SetNaN()
|
||||
// A reasonable value in case of an error.
|
||||
z.form = zero
|
||||
|
||||
// sign
|
||||
z.neg, err = scanSign(r)
|
||||
|
|
@ -260,11 +258,6 @@ func (x *Float) Append(buf []byte, format byte, prec int) []byte {
|
|||
return append(buf, "Inf"...)
|
||||
}
|
||||
|
||||
// NaN
|
||||
if x.IsNaN() {
|
||||
return append(buf, "NaN"...)
|
||||
}
|
||||
|
||||
// easy formats
|
||||
switch format {
|
||||
case 'b':
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ func TestFloatSetFloat64String(t *testing.T) {
|
|||
}
|
||||
f, _ := x.Float64()
|
||||
want := new(Float).SetFloat64(test.x)
|
||||
if x.Cmp(want).Neq() {
|
||||
if x.Cmp(want) != 0 {
|
||||
t.Errorf("%s: got %s (%v); want %v", test.s, &x, f, test.x)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,88 +50,62 @@ func Example_Shift() {
|
|||
func ExampleFloat_Cmp() {
|
||||
inf := math.Inf(1)
|
||||
zero := 0.0
|
||||
nan := math.NaN()
|
||||
|
||||
operands := []float64{-inf, -1.2, -zero, 0, +1.2, +inf, nan}
|
||||
operands := []float64{-inf, -1.2, -zero, 0, +1.2, +inf}
|
||||
|
||||
fmt.Println(" x y cmp eql neq lss leq gtr geq")
|
||||
fmt.Println("-----------------------------------------------")
|
||||
fmt.Println(" x y cmp")
|
||||
fmt.Println("---------------")
|
||||
for _, x64 := range operands {
|
||||
x := big.NewFloat(x64)
|
||||
for _, y64 := range operands {
|
||||
y := big.NewFloat(y64)
|
||||
t := x.Cmp(y)
|
||||
fmt.Printf(
|
||||
"%4s %4s %5s %c %c %c %c %c %c\n",
|
||||
x, y, t.Acc(),
|
||||
mark(t.Eql()), mark(t.Neq()), mark(t.Lss()), mark(t.Leq()), mark(t.Gtr()), mark(t.Geq()))
|
||||
fmt.Printf("%4s %4s %3d\n", x, y, x.Cmp(y))
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
// Output:
|
||||
// x y cmp eql neq lss leq gtr geq
|
||||
// -----------------------------------------------
|
||||
// -Inf -Inf Exact ● ○ ○ ● ○ ●
|
||||
// -Inf -1.2 Below ○ ● ● ● ○ ○
|
||||
// -Inf -0 Below ○ ● ● ● ○ ○
|
||||
// -Inf 0 Below ○ ● ● ● ○ ○
|
||||
// -Inf 1.2 Below ○ ● ● ● ○ ○
|
||||
// -Inf +Inf Below ○ ● ● ● ○ ○
|
||||
// -Inf NaN Undef ○ ● ○ ○ ○ ○
|
||||
// x y cmp
|
||||
// ---------------
|
||||
// -Inf -Inf 0
|
||||
// -Inf -1.2 -1
|
||||
// -Inf -0 -1
|
||||
// -Inf 0 -1
|
||||
// -Inf 1.2 -1
|
||||
// -Inf +Inf -1
|
||||
//
|
||||
// -1.2 -Inf Above ○ ● ○ ○ ● ●
|
||||
// -1.2 -1.2 Exact ● ○ ○ ● ○ ●
|
||||
// -1.2 -0 Below ○ ● ● ● ○ ○
|
||||
// -1.2 0 Below ○ ● ● ● ○ ○
|
||||
// -1.2 1.2 Below ○ ● ● ● ○ ○
|
||||
// -1.2 +Inf Below ○ ● ● ● ○ ○
|
||||
// -1.2 NaN Undef ○ ● ○ ○ ○ ○
|
||||
// -1.2 -Inf 1
|
||||
// -1.2 -1.2 0
|
||||
// -1.2 -0 -1
|
||||
// -1.2 0 -1
|
||||
// -1.2 1.2 -1
|
||||
// -1.2 +Inf -1
|
||||
//
|
||||
// -0 -Inf Above ○ ● ○ ○ ● ●
|
||||
// -0 -1.2 Above ○ ● ○ ○ ● ●
|
||||
// -0 -0 Exact ● ○ ○ ● ○ ●
|
||||
// -0 0 Exact ● ○ ○ ● ○ ●
|
||||
// -0 1.2 Below ○ ● ● ● ○ ○
|
||||
// -0 +Inf Below ○ ● ● ● ○ ○
|
||||
// -0 NaN Undef ○ ● ○ ○ ○ ○
|
||||
// -0 -Inf 1
|
||||
// -0 -1.2 1
|
||||
// -0 -0 0
|
||||
// -0 0 0
|
||||
// -0 1.2 -1
|
||||
// -0 +Inf -1
|
||||
//
|
||||
// 0 -Inf Above ○ ● ○ ○ ● ●
|
||||
// 0 -1.2 Above ○ ● ○ ○ ● ●
|
||||
// 0 -0 Exact ● ○ ○ ● ○ ●
|
||||
// 0 0 Exact ● ○ ○ ● ○ ●
|
||||
// 0 1.2 Below ○ ● ● ● ○ ○
|
||||
// 0 +Inf Below ○ ● ● ● ○ ○
|
||||
// 0 NaN Undef ○ ● ○ ○ ○ ○
|
||||
// 0 -Inf 1
|
||||
// 0 -1.2 1
|
||||
// 0 -0 0
|
||||
// 0 0 0
|
||||
// 0 1.2 -1
|
||||
// 0 +Inf -1
|
||||
//
|
||||
// 1.2 -Inf Above ○ ● ○ ○ ● ●
|
||||
// 1.2 -1.2 Above ○ ● ○ ○ ● ●
|
||||
// 1.2 -0 Above ○ ● ○ ○ ● ●
|
||||
// 1.2 0 Above ○ ● ○ ○ ● ●
|
||||
// 1.2 1.2 Exact ● ○ ○ ● ○ ●
|
||||
// 1.2 +Inf Below ○ ● ● ● ○ ○
|
||||
// 1.2 NaN Undef ○ ● ○ ○ ○ ○
|
||||
// 1.2 -Inf 1
|
||||
// 1.2 -1.2 1
|
||||
// 1.2 -0 1
|
||||
// 1.2 0 1
|
||||
// 1.2 1.2 0
|
||||
// 1.2 +Inf -1
|
||||
//
|
||||
// +Inf -Inf Above ○ ● ○ ○ ● ●
|
||||
// +Inf -1.2 Above ○ ● ○ ○ ● ●
|
||||
// +Inf -0 Above ○ ● ○ ○ ● ●
|
||||
// +Inf 0 Above ○ ● ○ ○ ● ●
|
||||
// +Inf 1.2 Above ○ ● ○ ○ ● ●
|
||||
// +Inf +Inf Exact ● ○ ○ ● ○ ●
|
||||
// +Inf NaN Undef ○ ● ○ ○ ○ ○
|
||||
//
|
||||
// NaN -Inf Undef ○ ● ○ ○ ○ ○
|
||||
// NaN -1.2 Undef ○ ● ○ ○ ○ ○
|
||||
// NaN -0 Undef ○ ● ○ ○ ○ ○
|
||||
// NaN 0 Undef ○ ● ○ ○ ○ ○
|
||||
// NaN 1.2 Undef ○ ● ○ ○ ○ ○
|
||||
// NaN +Inf Undef ○ ● ○ ○ ○ ○
|
||||
// NaN NaN Undef ○ ● ○ ○ ○ ○
|
||||
}
|
||||
|
||||
func mark(p bool) rune {
|
||||
if p {
|
||||
return '●'
|
||||
}
|
||||
return '○'
|
||||
// +Inf -Inf 1
|
||||
// +Inf -1.2 1
|
||||
// +Inf -0 1
|
||||
// +Inf 0 1
|
||||
// +Inf 1.2 1
|
||||
// +Inf +Inf 0
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import "strconv"
|
|||
|
||||
// bigFtoa formats a float for the %e, %E, %f, %g, and %G formats.
|
||||
func (f *Float) bigFtoa(buf []byte, fmt byte, prec int) []byte {
|
||||
if debugFloat && !f.IsFinite() {
|
||||
if debugFloat && f.IsInf() {
|
||||
panic("non-finite float")
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -184,6 +184,10 @@ func (z *Int) MulRange(a, b int64) *Int {
|
|||
|
||||
// Binomial sets z to the binomial coefficient of (n, k) and returns z.
|
||||
func (z *Int) Binomial(n, k int64) *Int {
|
||||
// reduce the number of multiplications by reducing k
|
||||
if n/2 < k && k <= n {
|
||||
k = n - k // Binomial(n, k) == Binomial(n, n-k)
|
||||
}
|
||||
var a, b Int
|
||||
a.MulRange(n-k+1, n)
|
||||
b.MulRange(1, k)
|
||||
|
|
|
|||
|
|
@ -219,6 +219,45 @@ func TestMulRangeZ(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestBinomial(t *testing.T) {
|
||||
var z Int
|
||||
for _, test := range []struct {
|
||||
n, k int64
|
||||
want string
|
||||
}{
|
||||
{0, 0, "1"},
|
||||
{0, 1, "0"},
|
||||
{1, 0, "1"},
|
||||
{1, 1, "1"},
|
||||
{1, 10, "0"},
|
||||
{4, 0, "1"},
|
||||
{4, 1, "4"},
|
||||
{4, 2, "6"},
|
||||
{4, 3, "4"},
|
||||
{4, 4, "1"},
|
||||
{10, 1, "10"},
|
||||
{10, 9, "10"},
|
||||
{10, 5, "252"},
|
||||
{11, 5, "462"},
|
||||
{11, 6, "462"},
|
||||
{100, 10, "17310309456440"},
|
||||
{100, 90, "17310309456440"},
|
||||
{1000, 10, "263409560461970212832400"},
|
||||
{1000, 990, "263409560461970212832400"},
|
||||
} {
|
||||
if got := z.Binomial(test.n, test.k).String(); got != test.want {
|
||||
t.Errorf("Binomial(%d, %d) = %s; want %s", test.n, test.k, got, test.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkBinomial(b *testing.B) {
|
||||
var z Int
|
||||
for i := b.N - 1; i >= 0; i-- {
|
||||
z.Binomial(1000, 990)
|
||||
}
|
||||
}
|
||||
|
||||
// Examples from the Go Language Spec, section "Arithmetic operators"
|
||||
var divisionSignsTests = []struct {
|
||||
x, y int64
|
||||
|
|
@ -353,7 +392,7 @@ func checkBytes(b []byte) bool {
|
|||
}
|
||||
|
||||
func TestBytes(t *testing.T) {
|
||||
if err := quick.Check(checkSetBytes, nil); err != nil {
|
||||
if err := quick.Check(checkBytes, nil); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue