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/. */
10 #include "mozilla/MemoryReporting.h"
12 #include "NamespaceImports.h"
15 # define M_PI 3.14159265358979323846
18 # define M_E 2.7182818284590452354
21 # define M_LOG2E 1.4426950408889634074
24 # define M_LOG10E 0.43429448190325182765
27 # define M_LN2 0.69314718055994530942
30 # define M_LN10 2.30258509299404568402
33 # define M_SQRT2 1.41421356237309504880
36 # define M_SQRT1_2 0.70710678118654752440
41 typedef double (*UnaryFunType
)(double);
48 Sin
, Cos
, Tan
, Sinh
, Cosh
, Tanh
, Asin
, Acos
, Atan
, Asinh
, Acosh
, Atanh
,
49 Sqrt
, Log
, Log10
, Log2
, Log1p
, Exp
, Expm1
, Cbrt
, Trunc
, Sign
53 static const unsigned SizeLog2
= 12;
54 static const unsigned Size
= 1 << SizeLog2
;
55 struct Entry
{ double in
; MathFuncId id
; double out
; };
61 unsigned hash(double x
, MathFuncId id
) {
62 union { double d
; struct { uint32_t one
, two
; } s
; } u
= { x
};
63 uint32_t hash32
= u
.s
.one
^ u
.s
.two
;
64 hash32
+= uint32_t(id
) << 8;
65 uint16_t hash16
= uint16_t(hash32
^ (hash32
>> 16));
66 return (hash16
& (Size
- 1)) ^ (hash16
>> (16 - SizeLog2
));
70 * N.B. lookup uses double-equality. This is only safe if hash() maps +0
71 * and -0 to different table entries, which is asserted in MathCache().
73 double lookup(UnaryFunType f
, double x
, MathFuncId id
) {
74 unsigned index
= hash(x
, id
);
75 Entry
& e
= table
[index
];
76 if (e
.in
== x
&& e
.id
== id
)
83 size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf
);
93 js_InitMathClass(JSContext
* cx
, js::HandleObject obj
);
98 random_initState(uint64_t* rngState
);
101 random_next(uint64_t* rngState
, int bits
);
103 static const double RNG_DSCALE
= double(1LL << 53);
106 random_nextDouble(uint64_t* rng
)
108 return double((random_next(rng
, 26) << 27) + random_next(rng
, 27)) / RNG_DSCALE
;
112 math_random_no_outparam(JSContext
* cx
);
115 math_random(JSContext
* cx
, unsigned argc
, js::Value
* vp
);
118 math_abs_handle(JSContext
* cx
, js::HandleValue v
, js::MutableHandleValue r
);
121 math_abs(JSContext
* cx
, unsigned argc
, js::Value
* vp
);
124 math_max_impl(double x
, double y
);
127 math_max(JSContext
* cx
, unsigned argc
, js::Value
* vp
);
130 math_min_impl(double x
, double y
);
133 math_min(JSContext
* cx
, unsigned argc
, js::Value
* vp
);
136 math_sqrt(JSContext
* cx
, unsigned argc
, js::Value
* vp
);
139 math_pow_handle(JSContext
* cx
, js::HandleValue base
, js::HandleValue power
,
140 js::MutableHandleValue result
);
143 math_pow(JSContext
* cx
, unsigned argc
, js::Value
* vp
);
146 minmax_impl(JSContext
* cx
, bool max
, js::HandleValue a
, js::HandleValue b
,
147 js::MutableHandleValue res
);
150 math_sqrt_handle(JSContext
* cx
, js::HandleValue number
, js::MutableHandleValue result
);
153 math_imul(JSContext
* cx
, unsigned argc
, js::Value
* vp
);
156 RoundFloat32(JSContext
* cx
, HandleValue v
, float* out
);
159 RoundFloat32(JSContext
* cx
, HandleValue arg
, MutableHandleValue res
);
162 math_fround(JSContext
* cx
, unsigned argc
, js::Value
* vp
);
165 math_log(JSContext
* cx
, unsigned argc
, js::Value
* vp
);
168 math_log_impl(MathCache
* cache
, double x
);
171 math_log_uncached(double x
);
174 math_sin(JSContext
* cx
, unsigned argc
, js::Value
* vp
);
177 math_sin_impl(MathCache
* cache
, double x
);
180 math_sin_uncached(double x
);
183 math_sin_handle(JSContext
* cx
, HandleValue val
, MutableHandleValue res
);
186 math_cos(JSContext
* cx
, unsigned argc
, js::Value
* vp
);
189 math_cos_impl(MathCache
* cache
, double x
);
192 math_cos_uncached(double x
);
195 math_exp(JSContext
* cx
, unsigned argc
, js::Value
* vp
);
198 math_exp_impl(MathCache
* cache
, double x
);
201 math_exp_uncached(double x
);
204 math_tan(JSContext
* cx
, unsigned argc
, js::Value
* vp
);
207 math_tan_impl(MathCache
* cache
, double x
);
210 math_tan_uncached(double x
);
213 math_log10(JSContext
* cx
, unsigned argc
, js::Value
* vp
);
216 math_log2(JSContext
* cx
, unsigned argc
, js::Value
* vp
);
219 math_log1p(JSContext
* cx
, unsigned argc
, js::Value
* vp
);
222 math_expm1(JSContext
* cx
, unsigned argc
, js::Value
* vp
);
225 math_cosh(JSContext
* cx
, unsigned argc
, js::Value
* vp
);
228 math_sinh(JSContext
* cx
, unsigned argc
, js::Value
* vp
);
231 math_tanh(JSContext
* cx
, unsigned argc
, js::Value
* vp
);
234 math_acosh(JSContext
* cx
, unsigned argc
, js::Value
* vp
);
237 math_asinh(JSContext
* cx
, unsigned argc
, js::Value
* vp
);
240 math_atanh(JSContext
* cx
, unsigned argc
, js::Value
* vp
);
243 ecmaHypot(double x
, double y
);
246 math_hypot(JSContext
* cx
, unsigned argc
, Value
* vp
);
249 math_hypot_handle(JSContext
* cx
, HandleValueArray args
, MutableHandleValue res
);
252 math_trunc(JSContext
* cx
, unsigned argc
, Value
* vp
);
255 math_sign(JSContext
* cx
, unsigned argc
, Value
* vp
);
258 math_cbrt(JSContext
* cx
, unsigned argc
, Value
* vp
);
261 math_asin(JSContext
* cx
, unsigned argc
, Value
* vp
);
264 math_acos(JSContext
* cx
, unsigned argc
, Value
* vp
);
267 math_atan(JSContext
* cx
, unsigned argc
, Value
* vp
);
270 math_atan2_handle(JSContext
* cx
, HandleValue y
, HandleValue x
, MutableHandleValue res
);
273 math_atan2(JSContext
* cx
, unsigned argc
, Value
* vp
);
276 ecmaAtan2(double x
, double y
);
279 math_atan_impl(MathCache
* cache
, double x
);
282 math_atan_uncached(double x
);
285 math_atan(JSContext
* cx
, unsigned argc
, js::Value
* vp
);
288 math_asin_impl(MathCache
* cache
, double x
);
291 math_asin_uncached(double x
);
294 math_asin(JSContext
* cx
, unsigned argc
, js::Value
* vp
);
297 math_acos_impl(MathCache
* cache
, double x
);
300 math_acos_uncached(double x
);
303 math_acos(JSContext
* cx
, unsigned argc
, js::Value
* vp
);
306 math_ceil(JSContext
* cx
, unsigned argc
, Value
* vp
);
309 math_ceil_impl(double x
);
312 math_clz32(JSContext
* cx
, unsigned argc
, Value
* vp
);
315 math_floor_handle(JSContext
* cx
, HandleValue v
, MutableHandleValue r
);
318 math_floor(JSContext
* cx
, unsigned argc
, Value
* vp
);
321 math_floor_impl(double x
);
324 extern T
GetBiggestNumberLessThan(T x
);
327 math_round_handle(JSContext
* cx
, HandleValue arg
, MutableHandleValue res
);
330 math_round(JSContext
* cx
, unsigned argc
, Value
* vp
);
333 math_round_impl(double x
);
336 math_roundf_impl(float x
);
339 powi(double x
, int y
);
342 ecmaPow(double x
, double y
);
345 math_imul(JSContext
* cx
, unsigned argc
, Value
* vp
);
348 math_log10_impl(MathCache
* cache
, double x
);
351 math_log10_uncached(double x
);
354 math_log2_impl(MathCache
* cache
, double x
);
357 math_log2_uncached(double x
);
360 math_log1p_impl(MathCache
* cache
, double x
);
363 math_log1p_uncached(double x
);
366 math_expm1_impl(MathCache
* cache
, double x
);
369 math_expm1_uncached(double x
);
372 math_cosh_impl(MathCache
* cache
, double x
);
375 math_cosh_uncached(double x
);
378 math_sinh_impl(MathCache
* cache
, double x
);
381 math_sinh_uncached(double x
);
384 math_tanh_impl(MathCache
* cache
, double x
);
387 math_tanh_uncached(double x
);
390 math_acosh_impl(MathCache
* cache
, double x
);
393 math_acosh_uncached(double x
);
396 math_asinh_impl(MathCache
* cache
, double x
);
399 math_asinh_uncached(double x
);
402 math_atanh_impl(MathCache
* cache
, double x
);
405 math_atanh_uncached(double x
);
408 math_trunc_impl(MathCache
* cache
, double x
);
411 math_trunc_uncached(double x
);
414 math_sign_impl(MathCache
* cache
, double x
);
417 math_sign_uncached(double x
);
420 math_cbrt_impl(MathCache
* cache
, double x
);
423 math_cbrt_uncached(double x
);
427 #endif /* jsmath_h */