Commit fa85a720 authored by Robert Griesemer's avatar Robert Griesemer

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/8280Reviewed-by: 's avatarAlan Donovan <adonovan@google.com>
parent 67426a8a
......@@ -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]]
}
This diff is collapsed.
This diff is collapsed.
......@@ -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")
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment