1
2
3
4
5
6 package math
7
8 import (
9 "errors"
10 "fmt"
11 "math"
12
13 "go.starlark.net/starlark"
14 "go.starlark.net/starlarkstruct"
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 var Module = &starlarkstruct.Module{
68 Name: "math",
69 Members: starlark.StringDict{
70 "ceil": starlark.NewBuiltin("ceil", ceil),
71 "copysign": newBinaryBuiltin("copysign", math.Copysign),
72 "fabs": newUnaryBuiltin("fabs", math.Abs),
73 "floor": starlark.NewBuiltin("floor", floor),
74 "mod": newBinaryBuiltin("round", math.Mod),
75 "pow": newBinaryBuiltin("pow", math.Pow),
76 "remainder": newBinaryBuiltin("remainder", math.Remainder),
77 "round": newUnaryBuiltin("round", math.Round),
78
79 "exp": newUnaryBuiltin("exp", math.Exp),
80 "sqrt": newUnaryBuiltin("sqrt", math.Sqrt),
81
82 "acos": newUnaryBuiltin("acos", math.Acos),
83 "asin": newUnaryBuiltin("asin", math.Asin),
84 "atan": newUnaryBuiltin("atan", math.Atan),
85 "atan2": newBinaryBuiltin("atan2", math.Atan2),
86 "cos": newUnaryBuiltin("cos", math.Cos),
87 "hypot": newBinaryBuiltin("hypot", math.Hypot),
88 "sin": newUnaryBuiltin("sin", math.Sin),
89 "tan": newUnaryBuiltin("tan", math.Tan),
90
91 "degrees": newUnaryBuiltin("degrees", degrees),
92 "radians": newUnaryBuiltin("radians", radians),
93
94 "acosh": newUnaryBuiltin("acosh", math.Acosh),
95 "asinh": newUnaryBuiltin("asinh", math.Asinh),
96 "atanh": newUnaryBuiltin("atanh", math.Atanh),
97 "cosh": newUnaryBuiltin("cosh", math.Cosh),
98 "sinh": newUnaryBuiltin("sinh", math.Sinh),
99 "tanh": newUnaryBuiltin("tanh", math.Tanh),
100
101 "log": starlark.NewBuiltin("log", log),
102
103 "gamma": newUnaryBuiltin("gamma", math.Gamma),
104
105 "e": starlark.Float(math.E),
106 "pi": starlark.Float(math.Pi),
107 },
108 }
109
110
111 type floatOrInt float64
112
113 func (p *floatOrInt) Unpack(v starlark.Value) error {
114 switch v := v.(type) {
115 case starlark.Int:
116 *p = floatOrInt(v.Float())
117 return nil
118 case starlark.Float:
119 *p = floatOrInt(v)
120 return nil
121 }
122 return fmt.Errorf("got %s, want float or int", v.Type())
123 }
124
125
126
127 func newUnaryBuiltin(name string, fn func(float64) float64) *starlark.Builtin {
128 return starlark.NewBuiltin(name, func(thread *starlark.Thread, b *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
129 var x floatOrInt
130 if err := starlark.UnpackPositionalArgs(name, args, kwargs, 1, &x); err != nil {
131 return nil, err
132 }
133 return starlark.Float(fn(float64(x))), nil
134 })
135 }
136
137
138
139 func newBinaryBuiltin(name string, fn func(float64, float64) float64) *starlark.Builtin {
140 return starlark.NewBuiltin(name, func(thread *starlark.Thread, b *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
141 var x, y floatOrInt
142 if err := starlark.UnpackPositionalArgs(name, args, kwargs, 2, &x, &y); err != nil {
143 return nil, err
144 }
145 return starlark.Float(fn(float64(x), float64(y))), nil
146 })
147 }
148
149
150
151 func log(thread *starlark.Thread, b *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
152 var (
153 x floatOrInt
154 base floatOrInt = math.E
155 )
156 if err := starlark.UnpackPositionalArgs("log", args, kwargs, 1, &x, &base); err != nil {
157 return nil, err
158 }
159 if base == 1 {
160 return nil, errors.New("division by zero")
161 }
162 return starlark.Float(math.Log(float64(x)) / math.Log(float64(base))), nil
163 }
164
165 func ceil(thread *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
166 var x starlark.Value
167
168 if err := starlark.UnpackPositionalArgs("ceil", args, kwargs, 1, &x); err != nil {
169 return nil, err
170 }
171
172 switch t := x.(type) {
173 case starlark.Int:
174 return t, nil
175 case starlark.Float:
176 return starlark.NumberToInt(starlark.Float(math.Ceil(float64(t))))
177 }
178
179 return nil, fmt.Errorf("got %s, want float or int", x.Type())
180 }
181
182 func floor(thread *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
183 var x starlark.Value
184
185 if err := starlark.UnpackPositionalArgs("floor", args, kwargs, 1, &x); err != nil {
186 return nil, err
187 }
188
189 switch t := x.(type) {
190 case starlark.Int:
191 return t, nil
192 case starlark.Float:
193 return starlark.NumberToInt(starlark.Float(math.Floor(float64(t))))
194 }
195
196 return nil, fmt.Errorf("got %s, want float or int", x.Type())
197 }
198
199 func degrees(x float64) float64 {
200 return 360 * x / (2 * math.Pi)
201 }
202
203 func radians(x float64) float64 {
204 return 2 * math.Pi * x / 360
205 }
206
View as plain text