diff options
Diffstat (limited to 'src/math/big/float_test.go')
| -rw-r--r-- | src/math/big/float_test.go | 212 |
1 files changed, 126 insertions, 86 deletions
diff --git a/src/math/big/float_test.go b/src/math/big/float_test.go index 5b5a0247b1..7df9fc74bc 100644 --- a/src/math/big/float_test.go +++ b/src/math/big/float_test.go @@ -203,6 +203,18 @@ func alike(x, y *Float) bool { return x.Cmp(y) == 0 && x.Signbit() == y.Signbit() } +func alike32(x, y float32) bool { + // we can ignore NaNs + return x == y && math.Signbit(float64(x)) == math.Signbit(float64(y)) + +} + +func alike64(x, y float64) bool { + // we can ignore NaNs + return x == y && math.Signbit(x) == math.Signbit(y) + +} + func TestFloatMantExp(t *testing.T) { for _, test := range []struct { x string @@ -828,52 +840,69 @@ func TestFloatFloat32(t *testing.T) { out float32 acc Accuracy }{ - {"-Inf", float32(math.Inf(-1)), Exact}, - {"-0x1.ffffff0p2147483646", float32(-math.Inf(+1)), Below}, // overflow in rounding - {"-1e10000", float32(math.Inf(-1)), Below}, // overflow - {"-0x1p128", float32(math.Inf(-1)), Below}, // overflow - {"-0x1.ffffff0p127", float32(-math.Inf(+1)), Below}, // overflow - {"-0x1.fffffe8p127", -math.MaxFloat32, Above}, - {"-0x1.fffffe0p127", -math.MaxFloat32, Exact}, - {"-12345.000000000000000000001", -12345, Above}, - {"-12345.0", -12345, Exact}, - {"-1.000000000000000000001", -1, Above}, - {"-1", -1, Exact}, - {"-0x0.000002p-126", -math.SmallestNonzeroFloat32, Exact}, - {"-0x0.000002p-127", -0, Above}, // underflow - {"-1e-1000", -0, Above}, // underflow {"0", 0, Exact}, - {"1e-1000", 0, Below}, // underflow - {"0x0.000002p-127", 0, Below}, // underflow - {"0x0.000002p-126", math.SmallestNonzeroFloat32, Exact}, + + // underflow + {"1e-1000", 0, Below}, + {"0x0.000002p-127", 0, Below}, + {"0x.0000010p-126", 0, Below}, + + // denormals + {"1.401298464e-45", math.SmallestNonzeroFloat32, Above}, // rounded up to smallest denormal + {"0x.ffffff8p-149", math.SmallestNonzeroFloat32, Above}, // rounded up to smallest denormal + {"0x.0000018p-126", math.SmallestNonzeroFloat32, Above}, // rounded up to smallest denormal + {"0x.0000020p-126", math.SmallestNonzeroFloat32, Exact}, + {"0x.8p-148", math.SmallestNonzeroFloat32, Exact}, + {"1p-149", math.SmallestNonzeroFloat32, Exact}, + {"0x.fffffep-126", math.Float32frombits(0x7fffff), Exact}, // largest denormal + + // normals + {"0x.ffffffp-126", math.Float32frombits(0x00800000), Above}, // rounded up to smallest normal + {"1p-126", math.Float32frombits(0x00800000), Exact}, // smallest normal + {"0x1.fffffep-126", math.Float32frombits(0x00ffffff), Exact}, + {"0x1.ffffffp-126", math.Float32frombits(0x01000000), Above}, // rounded up {"1", 1, Exact}, {"1.000000000000000000001", 1, Below}, {"12345.0", 12345, Exact}, {"12345.000000000000000000001", 12345, Below}, {"0x1.fffffe0p127", math.MaxFloat32, Exact}, {"0x1.fffffe8p127", math.MaxFloat32, Below}, - {"0x1.ffffff0p127", float32(math.Inf(+1)), Above}, // overflow - {"0x1p128", float32(math.Inf(+1)), Above}, // overflow - {"1e10000", float32(math.Inf(+1)), Above}, // overflow + + // overflow + {"0x1.ffffff0p127", float32(math.Inf(+1)), Above}, + {"0x1p128", float32(math.Inf(+1)), Above}, + {"1e10000", float32(math.Inf(+1)), Above}, {"0x1.ffffff0p2147483646", float32(math.Inf(+1)), Above}, // overflow in rounding - {"+Inf", float32(math.Inf(+1)), Exact}, + + // inf + {"Inf", float32(math.Inf(+1)), Exact}, } { - // conversion should match strconv where syntax is agreeable - if f, err := strconv.ParseFloat(test.x, 32); err == nil && float32(f) != test.out { - t.Errorf("%s: got %g; want %g (incorrect test data)", test.x, f, test.out) - } + for i := 0; i < 2; i++ { + // test both signs + tx, tout, tacc := test.x, test.out, test.acc + if i != 0 { + tx = "-" + tx + tout = -tout + tacc = -tacc + } - x := makeFloat(test.x) - out, acc := x.Float32() - if out != test.out || acc != test.acc { - t.Errorf("%s: got %g (%#x, %s); want %g (%#x, %s)", test.x, out, math.Float32bits(out), acc, test.out, math.Float32bits(test.out), test.acc) - } + // conversion should match strconv where syntax is agreeable + if f, err := strconv.ParseFloat(tx, 32); err == nil && !alike32(float32(f), tout) { + t.Errorf("%s: got %g; want %g (incorrect test data)", tx, f, tout) + } - // test that x.SetFloat64(float64(f)).Float32() == f - var x2 Float - out2, acc2 := x2.SetFloat64(float64(out)).Float32() - if out2 != out || acc2 != Exact { - t.Errorf("idempotency test: got %g (%s); want %g (Exact)", out2, acc2, out) + x := makeFloat(tx) + out, acc := x.Float32() + if !alike32(out, tout) || acc != tacc { + t.Errorf("%s: got %g (%#x, %s); want %g (%#x, %s)", tx, out, math.Float32bits(out), acc, test.out, math.Float32bits(test.out), tacc) + } + + // test that x.SetFloat64(float64(f)).Float32() == f + var x2 Float + out2, acc2 := x2.SetFloat64(float64(out)).Float32() + if !alike32(out2, out) || acc2 != Exact { + t.Errorf("idempotency test: got %g (%s); want %g (Exact)", out2, acc2, out) + } } } } @@ -885,35 +914,36 @@ func TestFloatFloat64(t *testing.T) { out float64 acc Accuracy }{ - {"-Inf", math.Inf(-1), Exact}, - {"-0x1.fffffffffffff8p2147483646", -math.Inf(+1), Below}, // overflow in rounding - {"-1e10000", math.Inf(-1), Below}, // overflow - {"-0x1p1024", math.Inf(-1), Below}, // overflow - {"-0x1.fffffffffffff8p1023", -math.Inf(+1), Below}, // overflow - {"-0x1.fffffffffffff4p1023", -math.MaxFloat64, Above}, - {"-0x1.fffffffffffff0p1023", -math.MaxFloat64, Exact}, - {"-12345.000000000000000000001", -12345, Above}, - {"-12345.0", -12345, Exact}, - {"-1.000000000000000000001", -1, Above}, - {"-1", -1, Exact}, - {"-0x0.0000000000001p-1022", -math.SmallestNonzeroFloat64, Exact}, - {"-0x0.0000000000001p-1023", -0, Above}, // underflow - {"-1e-1000", -0, Above}, // underflow {"0", 0, Exact}, - {"1e-1000", 0, Below}, // underflow - {"0x0.0000000000001p-1023", 0, Below}, // underflow - {"0x0.0000000000001p-1022", math.SmallestNonzeroFloat64, Exact}, + + // underflow + {"1e-1000", 0, Below}, + {"0x0.0000000000001p-1023", 0, Below}, + {"0x0.00000000000008p-1022", 0, Below}, + + // denormals + {"0x0.0000000000000cp-1022", math.SmallestNonzeroFloat64, Above}, // rounded up to smallest denormal + {"0x0.0000000000001p-1022", math.SmallestNonzeroFloat64, Exact}, // smallest denormal + {"0x.8p-1073", math.SmallestNonzeroFloat64, Exact}, + {"1p-1074", math.SmallestNonzeroFloat64, Exact}, + {"0x.fffffffffffffp-1022", math.Float64frombits(0x000fffffffffffff), Exact}, // largest denormal + + // normals + {"0x.fffffffffffff8p-1022", math.Float64frombits(0x0010000000000000), Above}, // rounded up to smallest normal + {"1p-1022", math.Float64frombits(0x0010000000000000), Exact}, // smallest normal {"1", 1, Exact}, {"1.000000000000000000001", 1, Below}, {"12345.0", 12345, Exact}, {"12345.000000000000000000001", 12345, Below}, {"0x1.fffffffffffff0p1023", math.MaxFloat64, Exact}, {"0x1.fffffffffffff4p1023", math.MaxFloat64, Below}, - {"0x1.fffffffffffff8p1023", math.Inf(+1), Above}, // overflow - {"0x1p1024", math.Inf(+1), Above}, // overflow - {"1e10000", math.Inf(+1), Above}, // overflow + + // overflow + {"0x1.fffffffffffff8p1023", math.Inf(+1), Above}, + {"0x1p1024", math.Inf(+1), Above}, + {"1e10000", math.Inf(+1), Above}, {"0x1.fffffffffffff8p2147483646", math.Inf(+1), Above}, // overflow in rounding - {"+Inf", math.Inf(+1), Exact}, + {"Inf", math.Inf(+1), Exact}, // selected denormalized values that were handled incorrectly in the past {"0x.fffffffffffffp-1022", smallestNormalFloat64 - math.SmallestNonzeroFloat64, Exact}, @@ -924,22 +954,32 @@ func TestFloatFloat64(t *testing.T) { // http://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308/ {"2.2250738585072012e-308", 2.2250738585072014e-308, Above}, } { - // conversion should match strconv where syntax is agreeable - if f, err := strconv.ParseFloat(test.x, 64); err == nil && f != test.out { - t.Errorf("%s: got %g; want %g (incorrect test data)", test.x, f, test.out) - } + for i := 0; i < 2; i++ { + // test both signs + tx, tout, tacc := test.x, test.out, test.acc + if i != 0 { + tx = "-" + tx + tout = -tout + tacc = -tacc + } - x := makeFloat(test.x) - out, acc := x.Float64() - if out != test.out || acc != test.acc { - t.Errorf("%s: got %g (%#x, %s); want %g (%#x, %s)", test.x, out, math.Float64bits(out), acc, test.out, math.Float64bits(test.out), test.acc) - } + // conversion should match strconv where syntax is agreeable + if f, err := strconv.ParseFloat(tx, 64); err == nil && !alike64(f, tout) { + t.Errorf("%s: got %g; want %g (incorrect test data)", tx, f, tout) + } - // test that x.SetFloat64(f).Float64() == f - var x2 Float - out2, acc2 := x2.SetFloat64(out).Float64() - if out2 != out || acc2 != Exact { - t.Errorf("idempotency test: got %g (%s); want %g (Exact)", out2, acc2, out) + x := makeFloat(tx) + out, acc := x.Float64() + if !alike64(out, tout) || acc != tacc { + t.Errorf("%s: got %g (%#x, %s); want %g (%#x, %s)", tx, out, math.Float64bits(out), acc, test.out, math.Float64bits(test.out), tacc) + } + + // test that x.SetFloat64(f).Float64() == f + var x2 Float + out2, acc2 := x2.SetFloat64(out).Float64() + if !alike64(out2, out) || acc2 != Exact { + t.Errorf("idempotency test: got %g (%s); want %g (Exact)", out2, acc2, out) + } } } } @@ -1523,32 +1563,32 @@ func TestFloatArithmeticOverflow(t *testing.T) { x, y, want string acc Accuracy }{ - {4, ToNearestEven, '+', "0", "0", "0", Exact}, // smoke test - {4, ToNearestEven, '+', "0x.8p0", "0x.8p0", "0x.8p1", Exact}, // smoke test + {4, ToNearestEven, '+', "0", "0", "0", Exact}, // smoke test + {4, ToNearestEven, '+', "0x.8p+0", "0x.8p+0", "0x.8p+1", Exact}, // smoke test - {4, ToNearestEven, '+', "0", "0x.8p2147483647", "0x.8p2147483647", Exact}, - {4, ToNearestEven, '+', "0x.8p2147483500", "0x.8p2147483647", "0x.8p2147483647", Below}, // rounded to zero - {4, ToNearestEven, '+', "0x.8p2147483647", "0x.8p2147483647", "+Inf", Above}, // exponent overflow in + - {4, ToNearestEven, '+', "-0x.8p2147483647", "-0x.8p2147483647", "-Inf", Below}, // exponent overflow in + - {4, ToNearestEven, '-', "-0x.8p2147483647", "0x.8p2147483647", "-Inf", Below}, // exponent overflow in - + {4, ToNearestEven, '+', "0", "0x.8p2147483647", "0x.8p+2147483647", Exact}, + {4, ToNearestEven, '+', "0x.8p2147483500", "0x.8p2147483647", "0x.8p+2147483647", Below}, // rounded to zero + {4, ToNearestEven, '+', "0x.8p2147483647", "0x.8p2147483647", "+Inf", Above}, // exponent overflow in + + {4, ToNearestEven, '+', "-0x.8p2147483647", "-0x.8p2147483647", "-Inf", Below}, // exponent overflow in + + {4, ToNearestEven, '-', "-0x.8p2147483647", "0x.8p2147483647", "-Inf", Below}, // exponent overflow in - - {4, ToZero, '+', "0x.fp2147483647", "0x.8p2147483643", "0x.fp2147483647", Below}, // rounded to zero - {4, ToNearestEven, '+', "0x.fp2147483647", "0x.8p2147483643", "+Inf", Above}, // exponent overflow in rounding - {4, AwayFromZero, '+', "0x.fp2147483647", "0x.8p2147483643", "+Inf", Above}, // exponent overflow in rounding + {4, ToZero, '+', "0x.fp2147483647", "0x.8p2147483643", "0x.fp+2147483647", Below}, // rounded to zero + {4, ToNearestEven, '+', "0x.fp2147483647", "0x.8p2147483643", "+Inf", Above}, // exponent overflow in rounding + {4, AwayFromZero, '+', "0x.fp2147483647", "0x.8p2147483643", "+Inf", Above}, // exponent overflow in rounding - {4, AwayFromZero, '-', "-0x.fp2147483647", "0x.8p2147483644", "-Inf", Below}, // exponent overflow in rounding - {4, ToNearestEven, '-', "-0x.fp2147483647", "0x.8p2147483643", "-Inf", Below}, // exponent overflow in rounding - {4, ToZero, '-', "-0x.fp2147483647", "0x.8p2147483643", "-0x.fp2147483647", Above}, // rounded to zero + {4, AwayFromZero, '-', "-0x.fp2147483647", "0x.8p2147483644", "-Inf", Below}, // exponent overflow in rounding + {4, ToNearestEven, '-', "-0x.fp2147483647", "0x.8p2147483643", "-Inf", Below}, // exponent overflow in rounding + {4, ToZero, '-', "-0x.fp2147483647", "0x.8p2147483643", "-0x.fp+2147483647", Above}, // rounded to zero {4, ToNearestEven, '+', "0", "0x.8p-2147483648", "0x.8p-2147483648", Exact}, {4, ToNearestEven, '+', "0x.8p-2147483648", "0x.8p-2147483648", "0x.8p-2147483647", Exact}, - {4, ToNearestEven, '*', "1", "0x.8p2147483647", "0x.8p2147483647", Exact}, + {4, ToNearestEven, '*', "1", "0x.8p2147483647", "0x.8p+2147483647", Exact}, {4, ToNearestEven, '*', "2", "0x.8p2147483647", "+Inf", Above}, // exponent overflow in * {4, ToNearestEven, '*', "-2", "0x.8p2147483647", "-Inf", Below}, // exponent overflow in * {4, ToNearestEven, '/', "0.5", "0x.8p2147483647", "0x.8p-2147483646", Exact}, - {4, ToNearestEven, '/', "0x.8p0", "0x.8p2147483647", "0x.8p-2147483646", Exact}, + {4, ToNearestEven, '/', "0x.8p+0", "0x.8p2147483647", "0x.8p-2147483646", Exact}, {4, ToNearestEven, '/', "0x.8p-1", "0x.8p2147483647", "0x.8p-2147483647", Exact}, {4, ToNearestEven, '/', "0x.8p-2", "0x.8p2147483647", "0x.8p-2147483648", Exact}, {4, ToNearestEven, '/', "0x.8p-3", "0x.8p2147483647", "0", Below}, // exponent underflow in / @@ -1659,7 +1699,7 @@ func TestFloatCmpSpecialValues(t *testing.T) { want = +1 } if got != want { - t.Errorf("(%g).Cmp(%g) = %s; want %s", x, y, got, want) + t.Errorf("(%g).Cmp(%g) = %v; want %v", x, y, got, want) } } } |
