-
Notifications
You must be signed in to change notification settings - Fork 10
/
log_test.go
114 lines (95 loc) · 4.89 KB
/
log_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
package bigfloat_test
import (
"fmt"
"math"
"math/big"
"math/rand"
"testing"
"github.com/ALTree/bigfloat"
)
// See note in sqrt_test.go about which numbers
// can we safely test this way.
func TestLog(t *testing.T) {
for _, test := range []struct {
z string
want string
}{
// 350 decimal digits are enough to give us up to 1000 binary digits
{"0.5", "-0.69314718055994530941723212145817656807550013436025525412068000949339362196969471560586332699641868754200148102057068573368552023575813055703267075163507596193072757082837143519030703862389167347112335011536449795523912047517268157493206515552473413952588295045300709532636664265410423915781495204374043038550080194417064167151864471283996817178454696"},
{"0.25", "-1.3862943611198906188344642429163531361510002687205105082413600189867872439393894312117266539928373750840029620411413714673710404715162611140653415032701519238614551416567428703806140772477833469422467002307289959104782409503453631498641303110494682790517659009060141906527332853082084783156299040874808607710016038883412833430372894256799363435690939"},
{"0.0125", "-4.3820266346738816122696878190588939118276018917095387383953679294477534755864366270535871860788543609679722271039983058344660861723571984277642996240040095752750899208106689864147210106979082189417635556550588715983462075888842670124944153533207460860520530946333864410280342429017041970928492563533263928706772062013203262792640026952942261381891629"},
{"1", "0.0"},
{"2", "0.69314718055994530941723212145817656807550013436025525412068000949339362196969471560586332699641868754200148102057068573368552023575813055703267075163507596193072757082837143519030703862389167347112335011536449795523912047517268157493206515552473413952588295045300709532636664265410423915781495204374043038550080194417064167151864471283996817178454696"},
{"10", "2.3025850929940456840179914546843642076011014886287729760333279009675726096773524802359972050895982983419677840422862486334095254650828067566662873690987816894829072083255546808437998948262331985283935053089653777326288461633662222876982198867465436674744042432743651550489343149393914796194044002221051017141748003688084012647080685567743216228355220"},
{"4096", "8.3177661667193437130067854574981188169060016123230630494481601139207234636363365872703599239570242505040177722468482288042262428290975666843920490196209115431687308499404572222836844634867000816534802013843739754628694457020721788991847818662968096743105954054360851439163997118492508698937794245248851646260096233300477000582237365540796180614145634"},
{"1e5", "11.512925464970228420089957273421821038005507443143864880166639504837863048386762401179986025447991491709838920211431243167047627325414033783331436845493908447414536041627773404218999474131165992641967526544826888663144230816831111438491099433732718337372021216371825775244671574696957398097022001110525508570874001844042006323540342783871608114177610"},
} {
for _, prec := range []uint{24, 53, 64, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000} {
want := new(big.Float).SetPrec(prec)
want.Parse(test.want, 10)
z := new(big.Float).SetPrec(prec)
z.Parse(test.z, 10)
x := bigfloat.Log(z)
if x.Cmp(want) != 0 {
t.Errorf("prec = %d, Log(%v) =\ngot %g;\n want %g", prec, test.z, x, want)
}
}
}
}
func testLogFloat64(scale float64, nTests int, t *testing.T) {
for i := 0; i < nTests; i++ {
r := rand.Float64() * scale
z := big.NewFloat(r)
x64, acc := bigfloat.Log(z).Float64()
want := math.Log(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(x64-want)/want > 1e-14 || acc != big.Exact {
t.Errorf("Log(%g) =\n got %g (%s);\nwant %g (Exact)", z, x64, acc, want)
}
}
}
func TestLogFloat64Small(t *testing.T) {
testLogFloat64(1e-100, 1e4, t)
testLogFloat64(1e-10, 1e4, t)
}
func TestLogFloat64Medium(t *testing.T) {
testLogFloat64(1, 1e4, t)
testLogFloat64(100, 1e4, t)
}
func TestLogFloat64Big(t *testing.T) {
testLogFloat64(1e10, 1e4, t)
testLogFloat64(1e100, 1e4, t)
}
func TestLogSpecialValues(t *testing.T) {
for _, f := range []float64{
+0.0,
-0.0,
math.Inf(+1),
} {
z := big.NewFloat(f)
x64, acc := bigfloat.Log(z).Float64()
want := math.Log(f)
if x64 != want || acc != big.Exact {
t.Errorf("Log(%f) =\n got %g (%s);\nwant %g (Exact)", f, x64, acc, want)
}
}
}
// ---------- Benchmarks ----------
func BenchmarkLog(b *testing.B) {
z := big.NewFloat(2).SetPrec(1e5)
_ = bigfloat.Log(z) // fill pi cache before benchmarking
for _, prec := range []uint{1e2, 1e3, 1e4, 1e5} {
z = big.NewFloat(2).SetPrec(prec)
b.Run(fmt.Sprintf("%v", prec), func(b *testing.B) {
b.ReportAllocs()
for n := 0; n < b.N; n++ {
bigfloat.Log(z)
}
})
}
}