1package lua
2
3import (
4	"math"
5	"math/rand"
6)
7
8func OpenMath(L *LState) int {
9	mod := L.RegisterModule(MathLibName, mathFuncs).(*LTable)
10	mod.RawSetString("pi", LNumber(math.Pi))
11	mod.RawSetString("huge", LNumber(math.MaxFloat64))
12	L.Push(mod)
13	return 1
14}
15
16var mathFuncs = map[string]LGFunction{
17	"abs":        mathAbs,
18	"acos":       mathAcos,
19	"asin":       mathAsin,
20	"atan":       mathAtan,
21	"atan2":      mathAtan2,
22	"ceil":       mathCeil,
23	"cos":        mathCos,
24	"cosh":       mathCosh,
25	"deg":        mathDeg,
26	"exp":        mathExp,
27	"floor":      mathFloor,
28	"fmod":       mathFmod,
29	"frexp":      mathFrexp,
30	"ldexp":      mathLdexp,
31	"log":        mathLog,
32	"log10":      mathLog10,
33	"max":        mathMax,
34	"min":        mathMin,
35	"mod":        mathMod,
36	"modf":       mathModf,
37	"pow":        mathPow,
38	"rad":        mathRad,
39	"random":     mathRandom,
40	"randomseed": mathRandomseed,
41	"sin":        mathSin,
42	"sinh":       mathSinh,
43	"sqrt":       mathSqrt,
44	"tan":        mathTan,
45	"tanh":       mathTanh,
46}
47
48func mathAbs(L *LState) int {
49	L.Push(LNumber(math.Abs(float64(L.CheckNumber(1)))))
50	return 1
51}
52
53func mathAcos(L *LState) int {
54	L.Push(LNumber(math.Acos(float64(L.CheckNumber(1)))))
55	return 1
56}
57
58func mathAsin(L *LState) int {
59	L.Push(LNumber(math.Asin(float64(L.CheckNumber(1)))))
60	return 1
61}
62
63func mathAtan(L *LState) int {
64	L.Push(LNumber(math.Atan(float64(L.CheckNumber(1)))))
65	return 1
66}
67
68func mathAtan2(L *LState) int {
69	L.Push(LNumber(math.Atan2(float64(L.CheckNumber(1)), float64(L.CheckNumber(2)))))
70	return 1
71}
72
73func mathCeil(L *LState) int {
74	L.Push(LNumber(math.Ceil(float64(L.CheckNumber(1)))))
75	return 1
76}
77
78func mathCos(L *LState) int {
79	L.Push(LNumber(math.Cos(float64(L.CheckNumber(1)))))
80	return 1
81}
82
83func mathCosh(L *LState) int {
84	L.Push(LNumber(math.Cosh(float64(L.CheckNumber(1)))))
85	return 1
86}
87
88func mathDeg(L *LState) int {
89	L.Push(LNumber(float64(L.CheckNumber(1)) * 180 / math.Pi))
90	return 1
91}
92
93func mathExp(L *LState) int {
94	L.Push(LNumber(math.Exp(float64(L.CheckNumber(1)))))
95	return 1
96}
97
98func mathFloor(L *LState) int {
99	L.Push(LNumber(math.Floor(float64(L.CheckNumber(1)))))
100	return 1
101}
102
103func mathFmod(L *LState) int {
104	L.Push(LNumber(math.Mod(float64(L.CheckNumber(1)), float64(L.CheckNumber(2)))))
105	return 1
106}
107
108func mathFrexp(L *LState) int {
109	v1, v2 := math.Frexp(float64(L.CheckNumber(1)))
110	L.Push(LNumber(v1))
111	L.Push(LNumber(v2))
112	return 2
113}
114
115func mathLdexp(L *LState) int {
116	L.Push(LNumber(math.Ldexp(float64(L.CheckNumber(1)), L.CheckInt(2))))
117	return 1
118}
119
120func mathLog(L *LState) int {
121	L.Push(LNumber(math.Log(float64(L.CheckNumber(1)))))
122	return 1
123}
124
125func mathLog10(L *LState) int {
126	L.Push(LNumber(math.Log10(float64(L.CheckNumber(1)))))
127	return 1
128}
129
130func mathMax(L *LState) int {
131	if L.GetTop() == 0 {
132		L.RaiseError("wrong number of arguments")
133	}
134	max := L.CheckNumber(1)
135	top := L.GetTop()
136	for i := 2; i <= top; i++ {
137		v := L.CheckNumber(i)
138		if v > max {
139			max = v
140		}
141	}
142	L.Push(max)
143	return 1
144}
145
146func mathMin(L *LState) int {
147	if L.GetTop() == 0 {
148		L.RaiseError("wrong number of arguments")
149	}
150	min := L.CheckNumber(1)
151	top := L.GetTop()
152	for i := 2; i <= top; i++ {
153		v := L.CheckNumber(i)
154		if v < min {
155			min = v
156		}
157	}
158	L.Push(min)
159	return 1
160}
161
162func mathMod(L *LState) int {
163	lhs := L.CheckNumber(1)
164	rhs := L.CheckNumber(2)
165	L.Push(luaModulo(lhs, rhs))
166	return 1
167}
168
169func mathModf(L *LState) int {
170	v1, v2 := math.Modf(float64(L.CheckNumber(1)))
171	L.Push(LNumber(v1))
172	L.Push(LNumber(v2))
173	return 2
174}
175
176func mathPow(L *LState) int {
177	L.Push(LNumber(math.Pow(float64(L.CheckNumber(1)), float64(L.CheckNumber(2)))))
178	return 1
179}
180
181func mathRad(L *LState) int {
182	L.Push(LNumber(float64(L.CheckNumber(1)) * math.Pi / 180))
183	return 1
184}
185
186func mathRandom(L *LState) int {
187	switch L.GetTop() {
188	case 0:
189		L.Push(LNumber(rand.Float64()))
190	case 1:
191		n := L.CheckInt(1)
192		L.Push(LNumber(rand.Intn(n) + 1))
193	default:
194		min := L.CheckInt(1)
195		max := L.CheckInt(2) + 1
196		L.Push(LNumber(rand.Intn(max-min) + min))
197	}
198	return 1
199}
200
201func mathRandomseed(L *LState) int {
202	rand.Seed(L.CheckInt64(1))
203	return 0
204}
205
206func mathSin(L *LState) int {
207	L.Push(LNumber(math.Sin(float64(L.CheckNumber(1)))))
208	return 1
209}
210
211func mathSinh(L *LState) int {
212	L.Push(LNumber(math.Sinh(float64(L.CheckNumber(1)))))
213	return 1
214}
215
216func mathSqrt(L *LState) int {
217	L.Push(LNumber(math.Sqrt(float64(L.CheckNumber(1)))))
218	return 1
219}
220
221func mathTan(L *LState) int {
222	L.Push(LNumber(math.Tan(float64(L.CheckNumber(1)))))
223	return 1
224}
225
226func mathTanh(L *LState) int {
227	L.Push(LNumber(math.Tanh(float64(L.CheckNumber(1)))))
228	return 1
229}
230
231//
232