Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * vim: set ts=8 sts=4 et sw=4 tw=99:
3 : * This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #ifndef jsmath_h
8 : #define jsmath_h
9 :
10 : #include "mozilla/MemoryReporting.h"
11 :
12 : #include <cmath>
13 :
14 : #include "NamespaceImports.h"
15 :
16 : namespace js {
17 :
18 : typedef double (*UnaryFunType)(double);
19 :
20 : class MathCache
21 : {
22 : public:
23 : enum MathFuncId {
24 : Zero,
25 : Sin, Cos, Tan, Sinh, Cosh, Tanh, Asin, Acos, Atan, Asinh, Acosh, Atanh,
26 : Sqrt, Log, Log10, Log2, Log1p, Exp, Expm1, Cbrt, Trunc, Sign
27 : };
28 :
29 : private:
30 : static const unsigned SizeLog2 = 12;
31 : static const unsigned Size = 1 << SizeLog2;
32 : struct Entry { double in; MathFuncId id; double out; };
33 : Entry table[Size];
34 :
35 : public:
36 : MathCache();
37 :
38 0 : unsigned hash(double x, MathFuncId id) {
39 0 : union { double d; struct { uint32_t one, two; } s; } u = { x };
40 0 : uint32_t hash32 = u.s.one ^ u.s.two;
41 0 : hash32 += uint32_t(id) << 8;
42 0 : uint16_t hash16 = uint16_t(hash32 ^ (hash32 >> 16));
43 0 : return (hash16 & (Size - 1)) ^ (hash16 >> (16 - SizeLog2));
44 : }
45 :
46 : /*
47 : * N.B. lookup uses double-equality. This is only safe if hash() maps +0
48 : * and -0 to different table entries, which is asserted in MathCache().
49 : */
50 0 : double lookup(UnaryFunType f, double x, MathFuncId id) {
51 0 : unsigned index = hash(x, id);
52 0 : Entry& e = table[index];
53 0 : if (e.in == x && e.id == id)
54 0 : return e.out;
55 0 : e.in = x;
56 0 : e.id = id;
57 0 : return e.out = f(x);
58 : }
59 :
60 0 : bool isCached(double x, MathFuncId id, double *r, unsigned *index) {
61 0 : *index = hash(x, id);
62 0 : Entry& e = table[*index];
63 0 : if (e.in == x && e.id == id) {
64 0 : *r = e.out;
65 0 : return true;
66 : }
67 0 : return false;
68 : }
69 :
70 0 : void store(MathFuncId id, double x, double v, unsigned index) {
71 0 : Entry &e = table[index];
72 0 : if (e.in == x && e.id == id)
73 0 : return;
74 0 : e.in = x;
75 0 : e.id = id;
76 0 : e.out = v;
77 : }
78 :
79 : size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
80 : };
81 :
82 : /*
83 : * JS math functions.
84 : */
85 :
86 : extern JSObject*
87 : InitMathClass(JSContext* cx, HandleObject obj);
88 :
89 : extern uint64_t
90 : GenerateRandomSeed();
91 :
92 : // Fill |seed[0]| and |seed[1]| with random bits, suitable for
93 : // seeding a XorShift128+ random number generator.
94 : extern void
95 : GenerateXorShift128PlusSeed(mozilla::Array<uint64_t, 2>& seed);
96 :
97 : extern uint64_t
98 : random_next(uint64_t* rngState, int bits);
99 :
100 : extern double
101 : math_random_impl(JSContext* cx);
102 :
103 : extern bool
104 : math_random(JSContext* cx, unsigned argc, js::Value* vp);
105 :
106 : extern bool
107 : math_abs_handle(JSContext* cx, js::HandleValue v, js::MutableHandleValue r);
108 :
109 : extern bool
110 : math_abs(JSContext* cx, unsigned argc, js::Value* vp);
111 :
112 : extern double
113 : math_max_impl(double x, double y);
114 :
115 : extern bool
116 : math_max(JSContext* cx, unsigned argc, js::Value* vp);
117 :
118 : extern double
119 : math_min_impl(double x, double y);
120 :
121 : extern bool
122 : math_min(JSContext* cx, unsigned argc, js::Value* vp);
123 :
124 : extern bool
125 : math_sqrt(JSContext* cx, unsigned argc, js::Value* vp);
126 :
127 : extern bool
128 : math_pow_handle(JSContext* cx, js::HandleValue base, js::HandleValue power,
129 : js::MutableHandleValue result);
130 :
131 : extern bool
132 : math_pow(JSContext* cx, unsigned argc, js::Value* vp);
133 :
134 : extern bool
135 : minmax_impl(JSContext* cx, bool max, js::HandleValue a, js::HandleValue b,
136 : js::MutableHandleValue res);
137 :
138 : extern void
139 : math_sincos_uncached(double x, double *sin, double *cos);
140 :
141 : extern void
142 : math_sincos_impl(MathCache* mathCache, double x, double *sin, double *cos);
143 :
144 : extern bool
145 : math_sqrt_handle(JSContext* cx, js::HandleValue number, js::MutableHandleValue result);
146 :
147 : extern bool
148 : math_imul_handle(JSContext* cx, HandleValue lhs, HandleValue rhs, MutableHandleValue res);
149 :
150 : extern bool
151 : math_imul(JSContext* cx, unsigned argc, js::Value* vp);
152 :
153 : extern bool
154 : RoundFloat32(JSContext* cx, HandleValue v, float* out);
155 :
156 : extern bool
157 : RoundFloat32(JSContext* cx, HandleValue arg, MutableHandleValue res);
158 :
159 : extern bool
160 : math_fround(JSContext* cx, unsigned argc, js::Value* vp);
161 :
162 : extern bool
163 : math_log(JSContext* cx, unsigned argc, js::Value* vp);
164 :
165 : extern double
166 : math_log_impl(MathCache* cache, double x);
167 :
168 : extern double
169 : math_log_uncached(double x);
170 :
171 : extern bool
172 : math_log_handle(JSContext* cx, HandleValue val, MutableHandleValue res);
173 :
174 : extern bool
175 : math_sin(JSContext* cx, unsigned argc, js::Value* vp);
176 :
177 : extern double
178 : math_sin_impl(MathCache* cache, double x);
179 :
180 : extern double
181 : math_sin_uncached(double x);
182 :
183 : extern bool
184 : math_sin_handle(JSContext* cx, HandleValue val, MutableHandleValue res);
185 :
186 : extern bool
187 : math_cos(JSContext* cx, unsigned argc, js::Value* vp);
188 :
189 : extern double
190 : math_cos_impl(MathCache* cache, double x);
191 :
192 : extern double
193 : math_cos_uncached(double x);
194 :
195 : extern bool
196 : math_exp(JSContext* cx, unsigned argc, js::Value* vp);
197 :
198 : extern double
199 : math_exp_impl(MathCache* cache, double x);
200 :
201 : extern double
202 : math_exp_uncached(double x);
203 :
204 : extern bool
205 : math_tan(JSContext* cx, unsigned argc, js::Value* vp);
206 :
207 : extern double
208 : math_tan_impl(MathCache* cache, double x);
209 :
210 : extern double
211 : math_tan_uncached(double x);
212 :
213 : extern bool
214 : math_log10(JSContext* cx, unsigned argc, js::Value* vp);
215 :
216 : extern bool
217 : math_log2(JSContext* cx, unsigned argc, js::Value* vp);
218 :
219 : extern bool
220 : math_log1p(JSContext* cx, unsigned argc, js::Value* vp);
221 :
222 : extern bool
223 : math_expm1(JSContext* cx, unsigned argc, js::Value* vp);
224 :
225 : extern bool
226 : math_cosh(JSContext* cx, unsigned argc, js::Value* vp);
227 :
228 : extern bool
229 : math_sinh(JSContext* cx, unsigned argc, js::Value* vp);
230 :
231 : extern bool
232 : math_tanh(JSContext* cx, unsigned argc, js::Value* vp);
233 :
234 : extern bool
235 : math_acosh(JSContext* cx, unsigned argc, js::Value* vp);
236 :
237 : extern bool
238 : math_asinh(JSContext* cx, unsigned argc, js::Value* vp);
239 :
240 : extern bool
241 : math_atanh(JSContext* cx, unsigned argc, js::Value* vp);
242 :
243 : extern double
244 : ecmaHypot(double x, double y);
245 :
246 : extern double
247 : hypot3(double x, double y, double z);
248 :
249 : extern double
250 : hypot4(double x, double y, double z, double w);
251 :
252 : extern bool
253 : math_hypot(JSContext* cx, unsigned argc, Value* vp);
254 :
255 : extern bool
256 : math_hypot_handle(JSContext* cx, HandleValueArray args, MutableHandleValue res);
257 :
258 : extern bool
259 : math_trunc(JSContext* cx, unsigned argc, Value* vp);
260 :
261 : extern bool
262 : math_sign(JSContext* cx, unsigned argc, Value* vp);
263 :
264 : extern bool
265 : math_cbrt(JSContext* cx, unsigned argc, Value* vp);
266 :
267 : extern bool
268 : math_asin(JSContext* cx, unsigned argc, Value* vp);
269 :
270 : extern bool
271 : math_acos(JSContext* cx, unsigned argc, Value* vp);
272 :
273 : extern bool
274 : math_atan(JSContext* cx, unsigned argc, Value* vp);
275 :
276 : extern bool
277 : math_atan2_handle(JSContext* cx, HandleValue y, HandleValue x, MutableHandleValue res);
278 :
279 : extern bool
280 : math_atan2(JSContext* cx, unsigned argc, Value* vp);
281 :
282 : extern double
283 : ecmaAtan2(double x, double y);
284 :
285 : extern double
286 : math_atan_impl(MathCache* cache, double x);
287 :
288 : extern double
289 : math_atan_uncached(double x);
290 :
291 : extern bool
292 : math_atan(JSContext* cx, unsigned argc, js::Value* vp);
293 :
294 : extern double
295 : math_asin_impl(MathCache* cache, double x);
296 :
297 : extern double
298 : math_asin_uncached(double x);
299 :
300 : extern bool
301 : math_asin(JSContext* cx, unsigned argc, js::Value* vp);
302 :
303 : extern double
304 : math_acos_impl(MathCache* cache, double x);
305 :
306 : extern double
307 : math_acos_uncached(double x);
308 :
309 : extern bool
310 : math_acos(JSContext* cx, unsigned argc, js::Value* vp);
311 :
312 : extern bool
313 : math_ceil_handle(JSContext* cx, HandleValue value, MutableHandleValue res);
314 :
315 : extern bool
316 : math_ceil(JSContext* cx, unsigned argc, Value* vp);
317 :
318 : extern double
319 : math_ceil_impl(double x);
320 :
321 : extern bool
322 : math_clz32(JSContext* cx, unsigned argc, Value* vp);
323 :
324 : extern bool
325 : math_floor_handle(JSContext* cx, HandleValue v, MutableHandleValue r);
326 :
327 : extern bool
328 : math_floor(JSContext* cx, unsigned argc, Value* vp);
329 :
330 : extern double
331 : math_floor_impl(double x);
332 :
333 : template<typename T>
334 : extern T GetBiggestNumberLessThan(T x);
335 :
336 : extern bool
337 : math_round_handle(JSContext* cx, HandleValue arg, MutableHandleValue res);
338 :
339 : extern bool
340 : math_round(JSContext* cx, unsigned argc, Value* vp);
341 :
342 : extern double
343 : math_round_impl(double x);
344 :
345 : extern float
346 : math_roundf_impl(float x);
347 :
348 : extern double
349 : powi(double x, int y);
350 :
351 : extern double
352 : ecmaPow(double x, double y);
353 :
354 : extern bool
355 : math_imul(JSContext* cx, unsigned argc, Value* vp);
356 :
357 : extern double
358 : math_log10_impl(MathCache* cache, double x);
359 :
360 : extern double
361 : math_log10_uncached(double x);
362 :
363 : extern double
364 : math_log2_impl(MathCache* cache, double x);
365 :
366 : extern double
367 : math_log2_uncached(double x);
368 :
369 : extern double
370 : math_log1p_impl(MathCache* cache, double x);
371 :
372 : extern double
373 : math_log1p_uncached(double x);
374 :
375 : extern double
376 : math_expm1_impl(MathCache* cache, double x);
377 :
378 : extern double
379 : math_expm1_uncached(double x);
380 :
381 : extern double
382 : math_cosh_impl(MathCache* cache, double x);
383 :
384 : extern double
385 : math_cosh_uncached(double x);
386 :
387 : extern double
388 : math_sinh_impl(MathCache* cache, double x);
389 :
390 : extern double
391 : math_sinh_uncached(double x);
392 :
393 : extern double
394 : math_tanh_impl(MathCache* cache, double x);
395 :
396 : extern double
397 : math_tanh_uncached(double x);
398 :
399 : extern double
400 : math_acosh_impl(MathCache* cache, double x);
401 :
402 : extern double
403 : math_acosh_uncached(double x);
404 :
405 : extern double
406 : math_asinh_impl(MathCache* cache, double x);
407 :
408 : extern double
409 : math_asinh_uncached(double x);
410 :
411 : extern double
412 : math_atanh_impl(MathCache* cache, double x);
413 :
414 : extern double
415 : math_atanh_uncached(double x);
416 :
417 : extern double
418 : math_trunc_impl(MathCache* cache, double x);
419 :
420 : extern double
421 : math_trunc_uncached(double x);
422 :
423 : extern double
424 : math_sign_impl(MathCache* cache, double x);
425 :
426 : extern double
427 : math_sign_uncached(double x);
428 :
429 : extern double
430 : math_cbrt_impl(MathCache* cache, double x);
431 :
432 : extern double
433 : math_cbrt_uncached(double x);
434 :
435 : } /* namespace js */
436 :
437 : #endif /* jsmath_h */
|