Skip to content

Commit

Permalink
test_{exp, log}.go: uniform tests
Browse files Browse the repository at this point in the history
  • Loading branch information
ALTree committed May 2, 2016
1 parent dd2552d commit 8d97808
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 118 deletions.
65 changes: 27 additions & 38 deletions exp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,52 +48,41 @@ func TestExp(t *testing.T) {
}
}

func TestExp32(t *testing.T) {
for i := 0; i < 1e4; i++ {
r := rand.Float32() * 80
x := big.NewFloat(float64(r)).SetPrec(24)
z, acc := floats.Exp(x).Float32()
want := math.Exp(float64(r))
if z != float32(want) {
t.Errorf("Exp(%f) =\n got %b (%s);\nwant %b (Exact)", x, z, acc, float32(want))
func testExpFloat64(scale float64, nTests int, t *testing.T) {
for i := 0; i < nTests; i++ {
r := rand.Float64() * scale

x := big.NewFloat(r).SetPrec(53)
z64, acc := floats.Exp(x).Float64()

want := math.Exp(r)

// Unfortunately, the Go math.Log function is not completely
// accurate, so it doesn't make sense to require 100%
// compatibility with it, since it happens that math.Log
// returns a result with the last bit off (see Issue #9546).
//
// Just require a relative error smaller than 1e-14
if math.Abs(z64-want)/want > 1e-14 || acc != big.Exact {
t.Errorf("Exp(%g) =\n got %g (%s);\nwant %g (Exact)", x, z64, acc, want)
}
}
}

func TestExp32Small(t *testing.T) {
for i := 0; i < 1e4; i++ {
r := rand.Float32() * 1e-4
x := big.NewFloat(float64(r)).SetPrec(24)
z, acc := floats.Exp(x).Float32()
want := math.Exp(float64(r))
if z != float32(want) {
t.Errorf("Exp(%f) =\n got %b (%s);\nwant %b (Exact)", x, z, acc, float32(want))
}
}
func TestExpFloat64Small(t *testing.T) {
testExpFloat64(-100, 4e3, t)
testExpFloat64(-10, 4e3, t)
testExpFloat64(-1, 4e3, t)
}

func TestExp64(t *testing.T) {
for i := 0; i < 1e4; i++ {
r := rand.Float64() * 160
x := big.NewFloat(r).SetPrec(53)
z, acc := floats.Exp(x).Float64()
want := math.Exp(r)
if math.Abs(z-want)/want > 1e-14 {
t.Errorf("Exp(%g) =\n got %b (%s);\nwant %b (Exact)", x, z, acc, want)
}
}
func TestExpFloat64Medium(t *testing.T) {
testExpFloat64(0.1, 5e3, t)
testExpFloat64(1, 5e3, t)
}

func TestExp64Small(t *testing.T) {
for i := 0; i < 1e4; i++ {
r := rand.Float64() * 1e-8
x := big.NewFloat(r).SetPrec(53)
z, acc := floats.Exp(x).Float64()
want := math.Exp(r)
if math.Abs(z-want)/want > 1e-14 {
t.Errorf("Exp(%g) =\n got %b (%s);\nwant %b (Exact)", x, z, acc, want)
}
}
func TestExpFloat64Big(t *testing.T) {
testExpFloat64(10, 5e3, t)
testExpFloat64(100, 5e3, t)
}

// ---------- Benchmarks ----------
Expand Down
93 changes: 24 additions & 69 deletions log_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,85 +44,40 @@ func TestLog(t *testing.T) {
}
}

func TestLog32(t *testing.T) {
for i := 0; i < 1e4; i++ {
r := rand.Float32() * 1e3
x := big.NewFloat(float64(r)).SetPrec(24)
z, acc := floats.Log(x).Float32()
want := math.Log(float64(r))
if z != float32(want) || acc != big.Exact {
t.Errorf("Log(%f) =\n got %b (%s);\nwant %b (Exact)", x, z, acc, want)
}
}
}
func testLogFloat64(scale float64, nTests int, t *testing.T) {
for i := 0; i < nTests; i++ {
r := rand.Float64() * scale

func TestLog32Small(t *testing.T) {
for i := 0; i < 1e4; i++ {
r := rand.Float32() * 1e-30
x := big.NewFloat(float64(r)).SetPrec(24)
z, acc := floats.Log(x).Float32()
want := math.Log(float64(r))
if z != float32(want) || acc != big.Exact {
t.Errorf("Log(%f) =\n got %b (%s);\nwant %b (Exact)", x, z, acc, want)
}
}
}
x := big.NewFloat(r).SetPrec(53)
z64, acc := floats.Log(x).Float64()

want := math.Log(r)

func TestLog32Big(t *testing.T) {
for i := 0; i < 1e4; i++ {
r := rand.Float32() * 1e30
x := big.NewFloat(float64(r)).SetPrec(24)
z, acc := floats.Log(x).Float32()
want := math.Log(float64(r))
if z != float32(want) || acc != big.Exact {
t.Errorf("Log(%f) =\n got %b (%s);\nwant %b (Exact)", x, z, acc, want)
// Unfortunately, the Go math.Log function is not completely
// accurate, so it doesn't make sense to require 100%
// compatibility with it, since it happens that math.Log
// returns a result with the last bit off (see Issue #9546).
//
// Just require a relative error smaller than 1e-14
if math.Abs(z64-want)/want > 1e-14 || acc != big.Exact {
t.Errorf("Log(%g) =\n got %g (%s);\nwant %g (Exact)", x, z64, acc, want)
}
}
}

// Unfortunately, the Go math.Log function is not completely
// accurate, so it doesn't make sense to require 100%
// compatibility with it, since it happens that math.Log
// returns a result with the last bit off (see Issue #9546).
//
// For this reason, we just require that the result is
// within distance 1e-14 from what math.Log returns
// (1e-12 for very small values).
// TODO: figure out a good permitted error.
func TestLog64(t *testing.T) {
for i := 0; i < 1e4; i++ {
r := rand.Float64() * 1e3
x := big.NewFloat(r).SetPrec(53)
z, acc := floats.Log(x).Float64()
want := math.Log(r)
if math.Abs(z-want)/want > 1e-14 || acc != big.Exact {
t.Errorf("Log(%g) =\n got %g (%s);\nwant %g (Exact)", x, z, acc, want)
}
}
func TestLogFloat64Small(t *testing.T) {
testLogFloat64(1e-100, 1e4, t)
testLogFloat64(1e-10, 1e4, t)
}

func TestLog64Small(t *testing.T) {
for i := 0; i < 1e4; i++ {
r := rand.Float64() * 1e-300
x := big.NewFloat(r).SetPrec(53)
z, acc := floats.Log(x).Float64()
want := math.Log(r)
if math.Abs(z-want)/want > 1e-14 || acc != big.Exact { // 1e-12 for very small values
t.Errorf("Log(%g) =\n got %g (%s);\nwant %g (Exact)", x, z, acc, want)
}
}
func TestLogFloat64Medium(t *testing.T) {
testLogFloat64(1, 1e4, t)
testLogFloat64(100, 1e4, t)
}

func TestLog64Big(t *testing.T) {
for i := 0; i < 1e4; i++ {
r := rand.Float64() * 1e300
x := big.NewFloat(r).SetPrec(53)
z, acc := floats.Log(x).Float64()
want := math.Log(r)
if math.Abs(z-want)/want > 1e-14 || acc != big.Exact {
t.Errorf("Log(%g) =\n got %g (%s);\nwant %g (Exact)", x, z, acc, want)
}
}
func TestLogFloat64Big(t *testing.T) {
testLogFloat64(1e10, 1e4, t)
testLogFloat64(1e100, 1e4, t)
}

func TestLogSpecialValues(t *testing.T) {
Expand Down
22 changes: 11 additions & 11 deletions sqrt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ func TestSqrt(t *testing.T) {
}
}

func testSqrtIEEE(scale float64, nTests int, t *testing.T) {
func testSqrtFloat64(scale float64, nTests int, t *testing.T) {
for i := 0; i < nTests; i++ {
r := rand.Float64() * scale

Expand All @@ -79,24 +79,24 @@ func testSqrtIEEE(scale float64, nTests int, t *testing.T) {
want := math.Sqrt(r)

if z64 != want || acc != big.Exact {
t.Errorf("Sqrt(%g) =\n got %g;\nwant %g", x, z64, want)
t.Errorf("Sqrt(%g) =\n got %g (%s);\nwant %g (Exact)", x, z64, acc, want)
}
}
}

func TestSqrtIEEESmall(t *testing.T) {
testSqrtIEEE(1e-100, 1e5, t)
testSqrtIEEE(1e-10, 1e5, t)
func TestSqrtFloat64Small(t *testing.T) {
testSqrtFloat64(1e-100, 1e5, t)
testSqrtFloat64(1e-10, 1e5, t)
}

func TestSqrtIEEEMedium(t *testing.T) {
testSqrtIEEE(1, 1e5, t)
testSqrtIEEE(100, 1e5, t)
func TestSqrtFloa64Medium(t *testing.T) {
testSqrtFloat64(1, 1e5, t)
testSqrtFloat64(100, 1e5, t)
}

func TestSqrtIEEEBig(t *testing.T) {
testSqrtIEEE(1e10, 1e5, t)
testSqrtIEEE(1e100, 1e5, t)
func TestSqrtFloat64Big(t *testing.T) {
testSqrtFloat64(1e10, 1e5, t)
testSqrtFloat64(1e100, 1e5, t)
}

func TestSqrtSpecialValues(t *testing.T) {
Expand Down

0 comments on commit 8d97808

Please sign in to comment.