blob: 42763c00b0fe72d1e54c355834506f48399ddcb6 (
plain) (
blame)
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
|
package main
import (
"fmt"
"math"
)
// parseFunction returns nil is fn is not a valid function.
func parseFunction(fn string) func(Calculator) {
switch fn {
case "sin", "cos", "tan":
return trig(fn)
case "asin", "acos", "atan":
return invTrig(fn)
case "deg":
return deg
case "rad":
return rad
case "fac":
return fac
}
return nil
}
// trig returns a closure that performs the trig function specified by fn.
// Panics if fn is not one of "sin", "cos" or "tan".
func trig(fn string) func(Calculator) {
return func(c Calculator) {
if len(c.stack) <= 0 {
return
}
v := &c.stack[len(c.stack)-1]
// The math package expects arguments to trig functions to be in radians.
if c.anglem == modeDeg {
*v = radians(*v)
}
switch fn {
case "sin":
*v = math.Sin(*v)
case "cos":
*v = math.Cos(*v)
case "tan":
*v = math.Tan(*v)
default:
panic(fmt.Sprintf("invalid trig function: '%s'", fn))
}
}
}
// invTrig returns a closure that performs the inverse trig function specified
// by fn. Panics if fn is not one of "asin", "acos" or "atan".
func invTrig(fn string) func(Calculator) {
return func(c Calculator) {
if len(c.stack) <= 0 {
return
}
v := &c.stack[len(c.stack)-1]
switch fn {
case "asin":
*v = math.Asin(*v)
case "acos":
*v = math.Acos(*v)
case "atan":
*v = math.Atan(*v)
default:
panic(fmt.Sprintf("invalid inverse trig function: '%s'", fn))
}
if c.anglem == modeDeg {
*v = degrees(*v)
}
}
}
// Convert radians to degrees.
func deg(c Calculator) {
if len(c.stack) > 0 {
c.stack[len(c.stack)-1] = degrees(c.stack[len(c.stack)-1])
}
}
// Convert degrees to radians.
func rad(c Calculator) {
if len(c.stack) > 0 {
c.stack[len(c.stack)-1] = radians(c.stack[len(c.stack)-1])
}
}
// Factorial (!).
func fac(c Calculator) {
if len(c.stack) > 0 {
a := &c.stack[len(c.stack)-1] // will replace with a!
if float64(int(*a)) != *a { // undefined on non-ints
return
} else if int(*a) == 0 { // 0! = 1
*a = 1.0
} else { // a! = a*(a-1)!
for i := int(*a) - 1; i > 1; i-- {
*a *= float64(i)
}
}
}
}
// radians converts degrees to radians.
func radians(deg float64) float64 {
return deg * math.Pi / 180.0
}
// degrees converts radians to degrees.
func degrees(rad float64) float64 {
return rad * 180 / math.Pi
}
|