1 module zua.vm.std.math;
2 import zua.vm.engine;
3 import zua.vm.reflection;
4 import std.typecons;
5 import std.random;
6 import std.math;
7 
8 private double lmath_abs(double x) {
9 	if (x < 0) return -x;
10 	else return x;
11 }
12 
13 private double lmath_acos(double x) {
14 	return acos(x);
15 }
16 
17 private double lmath_asin(double x) {
18 	return asin(x);
19 }
20 
21 private double lmath_atan(double x) {
22 	return atan(x);
23 }
24 
25 private double lmath_atan2(double y, double x) {
26 	return atan2(y, x);
27 }
28 
29 private double lmath_ceil(double x) {
30 	return ceil(x);
31 }
32 
33 private double lmath_cos(double x) {
34 	return cos(x);
35 }
36 
37 private double lmath_cosh(double x) {
38 	return cosh(x);
39 }
40 
41 private double lmath_deg(double x) {
42 	return x * 180 / PI;
43 }
44 
45 private double lmath_exp(double x) {
46 	return exp(x);
47 }
48 
49 private double lmath_floor(double x) {
50 	return floor(x);
51 }
52 
53 private double lmath_fmod(double x, double y) {
54 	return fmod(x, y);
55 }
56 
57 private double lmath_mod(double x, double y) {
58 	return fmod(x, y);
59 }
60 
61 private Tuple!(double, int) lmath_frexp(double x) {
62 	int exp;
63 	double res = frexp(x, exp);
64 	return tuple(res, exp);
65 }
66 
67 private double lmath_ldexp(double m, int e) {
68 	return m * pow(2.0, e);
69 }
70 
71 private double lmath_log(double x) {
72 	return log(x);
73 }
74 
75 private double lmath_log10(double x) {
76 	return log10(x);
77 }
78 
79 private double lmath_max(double x, double y) {
80 	if (x > y) return x;
81 	else return y;
82 }
83 
84 private double lmath_min(double x, double y) {
85 	if (x < y) return x;
86 	else return y;
87 }
88 
89 private Tuple!(double, double) lmath_modf(double x) {
90 	if (isNaN(x)) return tuple(x, x);
91 	long i = cast(long)x;
92 	return tuple(cast(double)i, x - i);
93 }
94 
95 private double lmath_pow(double x, double y) {
96 	return pow(x, y);
97 }
98 
99 private double lmath_rad(double x) {
100 	return x * PI / 180;
101 }
102 
103 private Random rand;
104 
105 static this() {
106 	rand = Random(unpredictableSeed);
107 }
108 
109 private double lmath_random(Nullable!long m, Nullable!long n) {
110 	if (m.isNull && n.isNull) {
111 		return uniform!"[)"(0.0, 1.0, rand);
112 	}
113 	else if (m.isNull && !n.isNull) {
114 		throw new Exception("bad argument #1 to 'random' (number expected, got nil)");
115 	}
116 	else if (!m.isNull && n.isNull) {
117 		return uniform!"[]"(1L, m.get, rand);
118 	}
119 	else if (!m.isNull && !n.isNull) {
120 		return uniform!"[]"(m.get, n.get, rand);
121 	}
122 	else assert(0);
123 }
124 
125 private void lmath_randomseed(long x) {
126 	rand.seed(cast(uint)x);
127 }
128 
129 private double lmath_sin(double x) {
130 	return sin(x);
131 }
132 
133 private double lmath_sinh(double x) {
134 	return sinh(x);
135 }
136 
137 private double lmath_sqrt(double x) {
138 	return sqrt(x);
139 }
140 
141 private double lmath_tan(double x) {
142 	return tan(x);
143 }
144 
145 private double lmath_tanh(double x) {
146 	return tanh(x);
147 }
148 
149 /** Get math library */
150 Value mathlib() {
151 	TableValue res = new TableValue;
152 	res.set(Value("abs"), exposeFunction!(lmath_abs, "abs"));
153 	res.set(Value("acos"), exposeFunction!(lmath_acos, "acos"));
154 	res.set(Value("asin"), exposeFunction!(lmath_asin, "asin"));
155 	res.set(Value("atan"), exposeFunction!(lmath_atan, "atan"));
156 	res.set(Value("atan2"), exposeFunction!(lmath_atan2, "atan2"));
157 	res.set(Value("ceil"), exposeFunction!(lmath_ceil, "ceil"));
158 	res.set(Value("cos"), exposeFunction!(lmath_cos, "cos"));
159 	res.set(Value("cosh"), exposeFunction!(lmath_cosh, "cosh"));
160 	res.set(Value("deg"), exposeFunction!(lmath_deg, "deg"));
161 	res.set(Value("exp"), exposeFunction!(lmath_exp, "exp"));
162 	res.set(Value("floor"), exposeFunction!(lmath_floor, "floor"));
163 	res.set(Value("fmod"), exposeFunction!(lmath_fmod, "fmod"));
164 	res.set(Value("mod"), exposeFunction!(lmath_mod, "mod"));
165 	res.set(Value("frexp"), exposeFunction!(lmath_frexp, "frexp"));
166 	res.set(Value("huge"), Value(double.infinity));
167 	res.set(Value("ldexp"), exposeFunction!(lmath_ldexp, "ldexp"));
168 	res.set(Value("log"), exposeFunction!(lmath_log, "log"));
169 	res.set(Value("log10"), exposeFunction!(lmath_log10, "log10"));
170 	res.set(Value("max"), exposeFunction!(lmath_max, "max"));
171 	res.set(Value("min"), exposeFunction!(lmath_min, "min"));
172 	res.set(Value("modf"), exposeFunction!(lmath_modf, "modf"));
173 	res.set(Value("pi"), Value(PI));
174 	res.set(Value("pow"), exposeFunction!(lmath_pow, "pow"));
175 	res.set(Value("rad"), exposeFunction!(lmath_rad, "rad"));
176 	res.set(Value("random"), exposeFunction!(lmath_random, "random"));
177 	res.set(Value("randomseed"), exposeFunction!(lmath_randomseed, "randomseed"));
178 	res.set(Value("sin"), exposeFunction!(lmath_sin, "sin"));
179 	res.set(Value("sinh"), exposeFunction!(lmath_sinh, "sinh"));
180 	res.set(Value("sqrt"), exposeFunction!(lmath_sqrt, "sqrt"));
181 	res.set(Value("tan"), exposeFunction!(lmath_tan, "tan"));
182 	res.set(Value("tanh"), exposeFunction!(lmath_tanh, "tanh"));
183 	return Value(res);
184 }