-
Notifications
You must be signed in to change notification settings - Fork 1
/
arithmetic.go
65 lines (51 loc) · 1.24 KB
/
arithmetic.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
package bettersine
import (
//"fmt"
"math"
"math/big"
)
// NewFloat creates a new big.Float element with 1000 bits of precision
func NewFloat(x float64) (y *big.Float) {
y = new(big.Float)
y.SetPrec(1000) // log2 precision
y.SetFloat64(x)
return
}
// Cos is an iterative arbitrary precision computation of Cos(x)
// Iterative process with an error of ~10^{−0.60206*k} after k iterations.
// ref : Johansson, B. Tomas, An elementary algorithm to evaluate trigonometric functions to high precision, 2018
func Cos(x *big.Float) (cosx *big.Float) {
tmp := new(big.Float)
k := 1000 // number of iterations
t := NewFloat(0.5)
half := new(big.Float).Copy(t)
for i := 1; i < k-1; i++ {
t.Mul(t, half)
}
s := new(big.Float).Mul(x, t)
s.Mul(s, x)
s.Mul(s, t)
four := NewFloat(4.0)
for i := 1; i < k; i++ {
tmp.Sub(four, s)
s.Mul(s, tmp)
}
cosx = new(big.Float).Quo(s, NewFloat(2.0))
cosx.Sub(NewFloat(1.0), cosx)
return
}
// Sin is an iterative arbitrary precision computation of Sin(x)
func Sin(x *big.Float) (sinx *big.Float) {
sinx = NewFloat(1)
tmp := Cos(x)
tmp.Mul(tmp, tmp)
sinx.Sub(sinx, tmp)
sinx.Sqrt(sinx)
return
}
func log2(x float64) float64 {
return math.Log2(x)
}
func abs(x float64) float64 {
return math.Abs(x)
}