math/big: remove NaN support - just not worth it

NaNs make the API more complicated for no real good reasons.
There are few operations that produce NaNs with IEEE arithmetic,
there's no need to copy the behavior. It's easy to test for these
scenarios and avoid them (on the other hand, it's not easy to test
for overflow or underflow, so we want to keep +/-Inf).

Also:
- renamed IsNeg -> Signbit (clearer, especially for x == -0)
- removed IsZero           (Sign() == 0 is sufficient and efficient)
- removed IsFinite         (now same as !IsInf)

Change-Id: I3f3b4445c325d9bbb1bf46ce2e298a6aeb498e07
Reviewed-on: https://go-review.googlesource.com/8280
Reviewed-by: Alan Donovan <adonovan@google.com>
diff --git a/src/math/big/accuracy_string.go b/src/math/big/accuracy_string.go
index 647a1fb..24ef7f1 100644
--- a/src/math/big/accuracy_string.go
+++ b/src/math/big/accuracy_string.go
@@ -4,13 +4,14 @@
 
 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]]
 }
diff --git a/src/math/big/float.go b/src/math/big/float.go
index 629510a..2e536e0 100644
--- a/src/math/big/float.go
+++ b/src/math/big/float.go
@@ -23,10 +23,9 @@
 //   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 @@
 // 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 @@
 //
 // 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 @@
 	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 @@
 // 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 @@
 	zero form = iota
 	finite
 	inf
-	nan
 )
 
 // RoundingMode determines how a Float value is rounded to the
@@ -127,16 +134,13 @@
 
 // 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 @@
 // 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 @@
 }
 
 // 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 @@
 // 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 @@
 //
 //	(  ±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 @@
 //
 //	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 @@
 	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 @@
 	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 @@
 
 	// update accuracy
 	if z.acc != Exact && z.neg {
-		z.acc ^= Below | Above
+		z.acc = -z.acc
 	}
 
 	if debugFloat {
@@ -598,13 +583,13 @@
 
 // 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 @@
 	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 @@
 // 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 @@
 			return 0, Above
 		}
 		return math.MaxUint64, Below
-
-	case nan:
-		return 0, Undef
 	}
 
 	panic("unreachable")
@@ -823,7 +798,7 @@
 // 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 @@
 			return math.MinInt64, Above
 		}
 		return math.MaxInt64, Below
-
-	case nan:
-		return 0, Undef
 	}
 
 	panic("unreachable")
@@ -885,7 +857,6 @@
 // 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 @@
 			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 @@
 // 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 @@
 			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 @@
 
 	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 @@
 
 	case inf:
 		return nil, makeAcc(x.neg)
-
-	case nan:
-		return nil, Undef
 	}
 
 	panic("unreachable")
@@ -1379,19 +1337,19 @@
 	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 @@
 		}
 		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:
@@ -1443,7 +1401,7 @@
 // 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.
+// BUG(gri) Float.Add panics if an operand is Inf.
 // 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 {
@@ -1459,7 +1417,7 @@
 	if x.form != finite || y.form != finite {
 		if x.form > finite || y.form > finite {
 			// TODO(gri) handle Inf separately
-			return z.SetNaN()
+			panic("Inf operand")
 		}
 		if x.form == zero {
 			z.Set(y)
@@ -1481,7 +1439,7 @@
 	} else {
 		// x + (-y) == x - y == -(y - x)
 		// (-x) + y == y - x == -(x - y)
-		if x.ucmp(y) == Above {
+		if x.ucmp(y) > 0 {
 			z.usub(x, y)
 		} else {
 			z.neg = !z.neg
@@ -1494,7 +1452,7 @@
 
 // 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.
+// BUG(gri) Float.Sub panics if an operand is Inf.
 func (z *Float) Sub(x, y *Float) *Float {
 	if debugFloat {
 		x.validate()
@@ -1509,7 +1467,7 @@
 	if x.form != finite || y.form != finite {
 		if x.form > finite || y.form > finite {
 			// TODO(gri) handle Inf separately
-			return z.SetNaN()
+			panic("Inf operand")
 		}
 		if x.form == zero {
 			z.Neg(y)
@@ -1531,7 +1489,7 @@
 	} else {
 		// x - y == x - y == -(y - x)
 		// (-x) - (-y) == y - x == -(x - y)
-		if x.ucmp(y) == Above {
+		if x.ucmp(y) > 0 {
 			z.usub(x, y)
 		} else {
 			z.neg = !z.neg
@@ -1544,7 +1502,7 @@
 
 // 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.
+// BUG(gri) Float.Mul panics if an operand is Inf.
 func (z *Float) Mul(x, y *Float) *Float {
 	if debugFloat {
 		x.validate()
@@ -1561,7 +1519,7 @@
 	if x.form != finite || y.form != finite {
 		if x.form > finite || y.form > finite {
 			// TODO(gri) handle Inf separately
-			return z.SetNaN()
+			panic("Inf operand")
 		}
 		// x == ±0 || y == ±0
 		z.acc = Exact
@@ -1577,7 +1535,8 @@
 
 // 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 is both operands are 0.
+// BUG(gri) Float.Quo panics if an operand is Inf.
 func (z *Float) Quo(x, y *Float) *Float {
 	if debugFloat {
 		x.validate()
@@ -1595,12 +1554,12 @@
 	if x.form != finite || y.form != finite {
 		if x.form > finite || y.form > finite {
 			// TODO(gri) handle Inf separately
-			return z.SetNaN()
+			panic("Inf operand")
 		}
 		// x == ±0 || y == ±0
 		if x.form == zero {
 			if y.form == zero {
-				return z.SetNaN()
+				panic("0/0")
 			}
 			z.form = zero
 			return z
@@ -1616,57 +1575,39 @@
 	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 +1616,6 @@
 //	+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 +1625,6 @@
 		return 0
 	case inf:
 		m = 2
-	default:
-		panic("unreachable")
 	}
 	if x.neg {
 		m = -m
diff --git a/src/math/big/float_test.go b/src/math/big/float_test.go
index 9d10153..b3f1a60 100644
--- a/src/math/big/float_test.go
+++ b/src/math/big/float_test.go
@@ -69,7 +69,7 @@
 		{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 @@
 		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 @@
 	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 @@
 		{"-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 @@
 		{"-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 @@
 		{"-0", 0},
 		{"+Inf", 0},
 		{"-Inf", 0},
-		{"NaN", 0},
 		{"1", 1},
 		{"2", 1},
 		{"3", 2},
@@ -191,7 +186,6 @@
 		{"+0", 0},
 		{"+1", +1},
 		{"+Inf", +1},
-		{"NaN", 0},
 	} {
 		x := makeFloat(test.x)
 		s := x.Sign()
@@ -201,13 +195,9 @@
 	}
 }
 
-// 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 @@
 		{"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 @@
 		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 @@
 	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 @@
 		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 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 @@
 		"Inf",
 		"+Inf",
 		"-Inf",
-		"NaN",
 	} {
 		s := strings.TrimSuffix(test, " int")
 		want := s != test
@@ -413,7 +395,7 @@
 	// 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 @@
 	// 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 @@
 		}
 	}
 
-	// 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 @@
 			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 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 @@
 		{"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 @@
 		{"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 @@
 			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 @@
 			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 @@
 		{"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 @@
 		{"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 @@
 		// 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 @@
 		"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 @@
 		"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 @@
 		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 @@
 					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 @@
 					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 @@
 		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 @@
 				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 @@
 
 // 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 non-finite (±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,10 +1452,15 @@
 			// 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 {
+				// At the moment an Inf operand always leads to a panic (known bug).
+				// TODO(gri) remove this once the bug is fixed.
+				if math.IsInf(x, 0) || math.IsInf(y, 0) {
+					continue
+				}
 				yy.SetFloat64(y)
 				var op string
 				var z float64
@@ -1507,20 +1478,18 @@
 					z = x * y
 					got.Mul(xx, yy)
 				case 3:
+					if x == 0 && y == 0 {
+						// TODO(gri) check for ErrNaN
+						continue // 0/0 panics with ErrNaN
+					}
 					op = "/"
 					z = x / y
 					got.Quo(xx, yy)
 				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)
-				}
-				if !feq(got, want) {
+				want.SetFloat64(z)
+				if !alike(got, want) {
 					t.Errorf("%5g %s %5g = %5s; want %5s", x, op, y, got, want)
 				}
 			}
@@ -1645,11 +1614,11 @@
 }
 
 // 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 non-finite (±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 +1627,18 @@
 			// 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)
diff --git a/src/math/big/floatconv.go b/src/math/big/floatconv.go
index 8905718..7dc9a28 100644
--- a/src/math/big/floatconv.go
+++ b/src/math/big/floatconv.go
@@ -73,10 +73,8 @@
 		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 @@
 		return append(buf, "Inf"...)
 	}
 
-	// NaN
-	if x.IsNaN() {
-		return append(buf, "NaN"...)
-	}
-
 	// easy formats
 	switch format {
 	case 'b':
diff --git a/src/math/big/floatconv_test.go b/src/math/big/floatconv_test.go
index 17c8b14..e7920d0 100644
--- a/src/math/big/floatconv_test.go
+++ b/src/math/big/floatconv_test.go
@@ -102,7 +102,7 @@
 		}
 		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)
 		}
 	}
diff --git a/src/math/big/floatexample_test.go b/src/math/big/floatexample_test.go
index 5e4a9cb..7db1023 100644
--- a/src/math/big/floatexample_test.go
+++ b/src/math/big/floatexample_test.go
@@ -50,88 +50,62 @@
 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
 }
diff --git a/src/math/big/ftoa.go b/src/math/big/ftoa.go
index 5502eda..0a9edfd 100644
--- a/src/math/big/ftoa.go
+++ b/src/math/big/ftoa.go
@@ -19,7 +19,7 @@
 
 // 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")
 	}