1 | #include "jsi.h" |
2 | #include "jsvalue.h" |
3 | #include "jsbuiltin.h" |
4 | |
5 | #include <time.h> |
6 | |
7 | #define JS_RAND_MAX (0x7fffffff) |
8 | |
9 | static unsigned int jsM_rand_temper(unsigned int x) |
10 | { |
11 | x ^= x>>11; |
12 | x ^= x<<7 & 0x9D2C5680; |
13 | x ^= x<<15 & 0xEFC60000; |
14 | x ^= x>>18; |
15 | return x; |
16 | } |
17 | |
18 | static int jsM_rand_r(unsigned int *seed) |
19 | { |
20 | return jsM_rand_temper(*seed = *seed * 1103515245 + 12345)/2; |
21 | } |
22 | |
23 | static double jsM_round(double x) |
24 | { |
25 | if (isnan(x)) return x; |
26 | if (isinf(x)) return x; |
27 | if (x == 0) return x; |
28 | if (x > 0 && x < 0.5) return 0; |
29 | if (x < 0 && x >= -0.5) return -0; |
30 | return floor(x + 0.5); |
31 | } |
32 | |
33 | static void Math_abs(js_State *J) |
34 | { |
35 | js_pushnumber(J, fabs(js_tonumber(J, 1))); |
36 | } |
37 | |
38 | static void Math_acos(js_State *J) |
39 | { |
40 | js_pushnumber(J, acos(js_tonumber(J, 1))); |
41 | } |
42 | |
43 | static void Math_asin(js_State *J) |
44 | { |
45 | js_pushnumber(J, asin(js_tonumber(J, 1))); |
46 | } |
47 | |
48 | static void Math_atan(js_State *J) |
49 | { |
50 | js_pushnumber(J, atan(js_tonumber(J, 1))); |
51 | } |
52 | |
53 | static void Math_atan2(js_State *J) |
54 | { |
55 | double y = js_tonumber(J, 1); |
56 | double x = js_tonumber(J, 2); |
57 | js_pushnumber(J, atan2(y, x)); |
58 | } |
59 | |
60 | static void Math_ceil(js_State *J) |
61 | { |
62 | js_pushnumber(J, ceil(js_tonumber(J, 1))); |
63 | } |
64 | |
65 | static void Math_cos(js_State *J) |
66 | { |
67 | js_pushnumber(J, cos(js_tonumber(J, 1))); |
68 | } |
69 | |
70 | static void Math_exp(js_State *J) |
71 | { |
72 | js_pushnumber(J, exp(js_tonumber(J, 1))); |
73 | } |
74 | |
75 | static void Math_floor(js_State *J) |
76 | { |
77 | js_pushnumber(J, floor(js_tonumber(J, 1))); |
78 | } |
79 | |
80 | static void Math_log(js_State *J) |
81 | { |
82 | js_pushnumber(J, log(js_tonumber(J, 1))); |
83 | } |
84 | |
85 | static void Math_pow(js_State *J) |
86 | { |
87 | double x = js_tonumber(J, 1); |
88 | double y = js_tonumber(J, 2); |
89 | if (!isfinite(y) && fabs(x) == 1) |
90 | js_pushnumber(J, NAN); |
91 | else |
92 | js_pushnumber(J, pow(x,y)); |
93 | } |
94 | |
95 | static void Math_random(js_State *J) |
96 | { |
97 | js_pushnumber(J, jsM_rand_r(&J->seed) / (JS_RAND_MAX + 1.0)); |
98 | } |
99 | |
100 | static void Math_round(js_State *J) |
101 | { |
102 | double x = js_tonumber(J, 1); |
103 | js_pushnumber(J, jsM_round(x)); |
104 | } |
105 | |
106 | static void Math_sin(js_State *J) |
107 | { |
108 | js_pushnumber(J, sin(js_tonumber(J, 1))); |
109 | } |
110 | |
111 | static void Math_sqrt(js_State *J) |
112 | { |
113 | js_pushnumber(J, sqrt(js_tonumber(J, 1))); |
114 | } |
115 | |
116 | static void Math_tan(js_State *J) |
117 | { |
118 | js_pushnumber(J, tan(js_tonumber(J, 1))); |
119 | } |
120 | |
121 | static void Math_max(js_State *J) |
122 | { |
123 | int i, n = js_gettop(J); |
124 | double x = -INFINITY; |
125 | for (i = 1; i < n; ++i) { |
126 | double y = js_tonumber(J, i); |
127 | if (isnan(y)) { |
128 | x = y; |
129 | break; |
130 | } |
131 | if (signbit(x) == signbit(y)) |
132 | x = x > y ? x : y; |
133 | else if (signbit(x)) |
134 | x = y; |
135 | } |
136 | js_pushnumber(J, x); |
137 | } |
138 | |
139 | static void Math_min(js_State *J) |
140 | { |
141 | int i, n = js_gettop(J); |
142 | double x = INFINITY; |
143 | for (i = 1; i < n; ++i) { |
144 | double y = js_tonumber(J, i); |
145 | if (isnan(y)) { |
146 | x = y; |
147 | break; |
148 | } |
149 | if (signbit(x) == signbit(y)) |
150 | x = x < y ? x : y; |
151 | else if (signbit(y)) |
152 | x = y; |
153 | } |
154 | js_pushnumber(J, x); |
155 | } |
156 | |
157 | void jsB_initmath(js_State *J) |
158 | { |
159 | J->seed = time(NULL); |
160 | |
161 | js_pushobject(J, jsV_newobject(J, JS_CMATH, J->Object_prototype)); |
162 | { |
163 | jsB_propn(J, "E" , 2.7182818284590452354); |
164 | jsB_propn(J, "LN10" , 2.302585092994046); |
165 | jsB_propn(J, "LN2" , 0.6931471805599453); |
166 | jsB_propn(J, "LOG2E" , 1.4426950408889634); |
167 | jsB_propn(J, "LOG10E" , 0.4342944819032518); |
168 | jsB_propn(J, "PI" , 3.1415926535897932); |
169 | jsB_propn(J, "SQRT1_2" , 0.7071067811865476); |
170 | jsB_propn(J, "SQRT2" , 1.4142135623730951); |
171 | |
172 | jsB_propf(J, "Math.abs" , Math_abs, 1); |
173 | jsB_propf(J, "Math.acos" , Math_acos, 1); |
174 | jsB_propf(J, "Math.asin" , Math_asin, 1); |
175 | jsB_propf(J, "Math.atan" , Math_atan, 1); |
176 | jsB_propf(J, "Math.atan2" , Math_atan2, 2); |
177 | jsB_propf(J, "Math.ceil" , Math_ceil, 1); |
178 | jsB_propf(J, "Math.cos" , Math_cos, 1); |
179 | jsB_propf(J, "Math.exp" , Math_exp, 1); |
180 | jsB_propf(J, "Math.floor" , Math_floor, 1); |
181 | jsB_propf(J, "Math.log" , Math_log, 1); |
182 | jsB_propf(J, "Math.max" , Math_max, 0); /* 2 */ |
183 | jsB_propf(J, "Math.min" , Math_min, 0); /* 2 */ |
184 | jsB_propf(J, "Math.pow" , Math_pow, 2); |
185 | jsB_propf(J, "Math.random" , Math_random, 0); |
186 | jsB_propf(J, "Math.round" , Math_round, 1); |
187 | jsB_propf(J, "Math.sin" , Math_sin, 1); |
188 | jsB_propf(J, "Math.sqrt" , Math_sqrt, 1); |
189 | jsB_propf(J, "Math.tan" , Math_tan, 1); |
190 | } |
191 | js_defglobal(J, "Math" , JS_DONTENUM); |
192 | } |
193 | |