1 |
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- |
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- |
2 |
* |
* |
3 |
* ***** BEGIN LICENSE BLOCK ***** |
* ***** BEGIN LICENSE BLOCK ***** |
4 |
* Version: MPL 1.1/GPL 2.0/LGPL 2.1 |
* Version: MPL 1.1/GPL 2.0/LGPL 2.1 |
40 |
/* |
/* |
41 |
* JS math package. |
* JS math package. |
42 |
*/ |
*/ |
|
#include "jsstddef.h" |
|
|
#include "jslibmath.h" |
|
43 |
#include <stdlib.h> |
#include <stdlib.h> |
44 |
#include "jstypes.h" |
#include "jstypes.h" |
45 |
|
#include "jsstdint.h" |
46 |
#include "jslong.h" |
#include "jslong.h" |
47 |
#include "prmjtime.h" |
#include "prmjtime.h" |
48 |
#include "jsapi.h" |
#include "jsapi.h" |
53 |
#include "jslock.h" |
#include "jslock.h" |
54 |
#include "jsmath.h" |
#include "jsmath.h" |
55 |
#include "jsnum.h" |
#include "jsnum.h" |
56 |
|
#include "jslibmath.h" |
57 |
#include "jsobj.h" |
#include "jsobj.h" |
58 |
|
|
59 |
extern jsdouble js_NaN; |
extern jsdouble js_NaN; |
99 |
js_Math_str, |
js_Math_str, |
100 |
JSCLASS_HAS_CACHED_PROTO(JSProto_Math), |
JSCLASS_HAS_CACHED_PROTO(JSProto_Math), |
101 |
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, |
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, |
102 |
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub, |
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, NULL, |
103 |
JSCLASS_NO_OPTIONAL_MEMBERS |
JSCLASS_NO_OPTIONAL_MEMBERS |
104 |
}; |
}; |
105 |
|
|
231 |
math_ceil_kernel(jsdouble x) |
math_ceil_kernel(jsdouble x) |
232 |
{ |
{ |
233 |
#ifdef __APPLE__ |
#ifdef __APPLE__ |
234 |
if (x < 0 && x > -1.0) |
if (x < 0 && x > -1.0) |
235 |
return js_copysign(0, -1); |
return js_copysign(0, -1); |
236 |
#endif |
#endif |
237 |
return ceil(x); |
return ceil(x); |
238 |
} |
} |
239 |
|
|
240 |
static JSBool |
JSBool |
241 |
math_ceil(JSContext *cx, uintN argc, jsval *vp) |
js_math_ceil(JSContext *cx, uintN argc, jsval *vp) |
242 |
{ |
{ |
243 |
jsdouble x, z; |
jsdouble x, z; |
244 |
|
|
297 |
return js_NewNumberInRootedValue(cx, z, vp); |
return js_NewNumberInRootedValue(cx, z, vp); |
298 |
} |
} |
299 |
|
|
300 |
static JSBool |
JSBool |
301 |
math_floor(JSContext *cx, uintN argc, jsval *vp) |
js_math_floor(JSContext *cx, uintN argc, jsval *vp) |
302 |
{ |
{ |
303 |
jsdouble x, z; |
jsdouble x, z; |
304 |
|
|
335 |
return js_NewNumberInRootedValue(cx, z, vp); |
return js_NewNumberInRootedValue(cx, z, vp); |
336 |
} |
} |
337 |
|
|
338 |
static JSBool |
JSBool |
339 |
math_max(JSContext *cx, uintN argc, jsval *vp) |
js_math_max(JSContext *cx, uintN argc, jsval *vp) |
340 |
{ |
{ |
341 |
jsdouble x, z = *cx->runtime->jsNegativeInfinity; |
jsdouble x, z = *cx->runtime->jsNegativeInfinity; |
342 |
jsval *argv; |
jsval *argv; |
365 |
return js_NewNumberInRootedValue(cx, z, vp); |
return js_NewNumberInRootedValue(cx, z, vp); |
366 |
} |
} |
367 |
|
|
368 |
static JSBool |
JSBool |
369 |
math_min(JSContext *cx, uintN argc, jsval *vp) |
js_math_min(JSContext *cx, uintN argc, jsval *vp) |
370 |
{ |
{ |
371 |
jsdouble x, z = *cx->runtime->jsPositiveInfinity; |
jsdouble x, z = *cx->runtime->jsPositiveInfinity; |
372 |
jsval *argv; |
jsval *argv; |
427 |
return js_NewNumberInRootedValue(cx, z, vp); |
return js_NewNumberInRootedValue(cx, z, vp); |
428 |
} |
} |
429 |
|
|
430 |
|
static const int64 RNG_MULTIPLIER = 0x5DEECE66DLL; |
431 |
|
static const int64 RNG_ADDEND = 0xBLL; |
432 |
|
static const int64 RNG_MASK = (1LL << 48) - 1; |
433 |
|
static const jsdouble RNG_DSCALE = jsdouble(1LL << 53); |
434 |
|
|
435 |
/* |
/* |
436 |
* Math.random() support, lifted from java.util.Random.java. |
* Math.random() support, lifted from java.util.Random.java. |
437 |
*/ |
*/ |
438 |
static void |
static inline void |
439 |
random_setSeed(JSRuntime *rt, int64 seed) |
random_setSeed(JSThreadData *data, int64 seed) |
440 |
{ |
{ |
441 |
int64 tmp; |
data->rngSeed = (seed ^ RNG_MULTIPLIER) & RNG_MASK; |
|
|
|
|
JSLL_I2L(tmp, 1000); |
|
|
JSLL_DIV(seed, seed, tmp); |
|
|
JSLL_XOR(tmp, seed, rt->rngMultiplier); |
|
|
JSLL_AND(rt->rngSeed, tmp, rt->rngMask); |
|
442 |
} |
} |
443 |
|
|
444 |
void |
void |
445 |
js_random_init(JSRuntime *rt) |
js_InitRandom(JSThreadData *data) |
446 |
{ |
{ |
|
int64 tmp, tmp2; |
|
|
|
|
|
/* Do at most once. */ |
|
|
if (rt->rngInitialized) |
|
|
return; |
|
|
rt->rngInitialized = JS_TRUE; |
|
|
|
|
|
/* rt->rngMultiplier = 0x5DEECE66DL */ |
|
|
JSLL_ISHL(tmp, 0x5, 32); |
|
|
JSLL_UI2L(tmp2, 0xDEECE66DL); |
|
|
JSLL_OR(rt->rngMultiplier, tmp, tmp2); |
|
|
|
|
|
/* rt->rngAddend = 0xBL */ |
|
|
JSLL_I2L(rt->rngAddend, 0xBL); |
|
|
|
|
|
/* rt->rngMask = (1L << 48) - 1 */ |
|
|
JSLL_I2L(tmp, 1); |
|
|
JSLL_SHL(tmp2, tmp, 48); |
|
|
JSLL_SUB(rt->rngMask, tmp2, tmp); |
|
|
|
|
|
/* rt->rngDscale = (jsdouble)(1L << 53) */ |
|
|
JSLL_SHL(tmp2, tmp, 53); |
|
|
JSLL_L2D(rt->rngDscale, tmp2); |
|
|
|
|
447 |
/* Finally, set the seed from current time. */ |
/* Finally, set the seed from current time. */ |
448 |
random_setSeed(rt, PRMJ_Now()); |
random_setSeed(data, PRMJ_Now() / 1000); |
449 |
} |
} |
450 |
|
|
451 |
static uint32 |
static inline uint64 |
452 |
random_next(JSRuntime *rt, int bits) |
random_next(JSThreadData *data, int bits) |
453 |
{ |
{ |
454 |
int64 nextseed, tmp; |
uint64 nextseed = data->rngSeed * RNG_MULTIPLIER; |
455 |
uint32 retval; |
nextseed += RNG_ADDEND; |
456 |
|
nextseed &= RNG_MASK; |
457 |
JSLL_MUL(nextseed, rt->rngSeed, rt->rngMultiplier); |
data->rngSeed = nextseed; |
458 |
JSLL_ADD(nextseed, nextseed, rt->rngAddend); |
return nextseed >> (48 - bits); |
|
JSLL_AND(nextseed, nextseed, rt->rngMask); |
|
|
rt->rngSeed = nextseed; |
|
|
JSLL_USHR(tmp, nextseed, 48 - bits); |
|
|
JSLL_L2I(retval, tmp); |
|
|
return retval; |
|
459 |
} |
} |
460 |
|
|
461 |
jsdouble |
static inline jsdouble |
462 |
js_random_nextDouble(JSRuntime *rt) |
random_nextDouble(JSThreadData *data) |
463 |
{ |
{ |
464 |
int64 tmp, tmp2; |
return jsdouble((random_next(data, 26) << 27) + random_next(data, 27)) / RNG_DSCALE; |
|
jsdouble d; |
|
|
|
|
|
JSLL_ISHL(tmp, random_next(rt, 26), 27); |
|
|
JSLL_UI2L(tmp2, random_next(rt, 27)); |
|
|
JSLL_ADD(tmp, tmp, tmp2); |
|
|
JSLL_L2D(d, tmp); |
|
|
return d / rt->rngDscale; |
|
465 |
} |
} |
466 |
|
|
467 |
static JSBool |
static JSBool |
468 |
math_random(JSContext *cx, uintN argc, jsval *vp) |
math_random(JSContext *cx, uintN argc, jsval *vp) |
469 |
{ |
{ |
470 |
JSRuntime *rt; |
jsdouble z = random_nextDouble(JS_THREAD_DATA(cx)); |
|
jsdouble z; |
|
|
|
|
|
rt = cx->runtime; |
|
|
JS_LOCK_RUNTIME(rt); |
|
|
js_random_init(rt); |
|
|
z = js_random_nextDouble(rt); |
|
|
JS_UNLOCK_RUNTIME(rt); |
|
471 |
return js_NewNumberInRootedValue(cx, z, vp); |
return js_NewNumberInRootedValue(cx, z, vp); |
472 |
} |
} |
473 |
|
|
486 |
} |
} |
487 |
#endif |
#endif |
488 |
|
|
489 |
static JSBool |
JSBool |
490 |
math_round(JSContext *cx, uintN argc, jsval *vp) |
js_math_round(JSContext *cx, uintN argc, jsval *vp) |
491 |
{ |
{ |
492 |
jsdouble x, z; |
jsdouble x, z; |
493 |
|
|
572 |
MATH_BUILTIN_1(sin) |
MATH_BUILTIN_1(sin) |
573 |
MATH_BUILTIN_1(cos) |
MATH_BUILTIN_1(cos) |
574 |
MATH_BUILTIN_1(sqrt) |
MATH_BUILTIN_1(sqrt) |
|
MATH_BUILTIN_1(floor) |
|
575 |
MATH_BUILTIN_1(tan) |
MATH_BUILTIN_1(tan) |
576 |
|
|
577 |
static jsdouble FASTCALL |
static jsdouble FASTCALL |
672 |
} |
} |
673 |
|
|
674 |
static jsdouble FASTCALL |
static jsdouble FASTCALL |
675 |
math_random_tn(JSRuntime* rt) |
math_random_tn(JSContext *cx) |
676 |
{ |
{ |
677 |
JS_LOCK_RUNTIME(rt); |
return random_nextDouble(JS_THREAD_DATA(cx)); |
|
js_random_init(rt); |
|
|
jsdouble z = js_random_nextDouble(rt); |
|
|
JS_UNLOCK_RUNTIME(rt); |
|
|
return z; |
|
678 |
} |
} |
679 |
|
|
680 |
static jsdouble FASTCALL |
static jsdouble FASTCALL |
689 |
return math_ceil_kernel(x); |
return math_ceil_kernel(x); |
690 |
} |
} |
691 |
|
|
692 |
|
static jsdouble FASTCALL |
693 |
|
math_floor_tn(jsdouble x) |
694 |
|
{ |
695 |
|
return floor(x); |
696 |
|
} |
697 |
|
|
698 |
JS_DEFINE_TRCINFO_1(math_acos, |
JS_DEFINE_TRCINFO_1(math_acos, |
699 |
(1, (static, DOUBLE, math_acos_tn, DOUBLE, 1, 1))) |
(1, (static, DOUBLE, math_acos_tn, DOUBLE, 1, 1))) |
700 |
JS_DEFINE_TRCINFO_1(math_asin, |
JS_DEFINE_TRCINFO_1(math_asin, |
701 |
(1, (static, DOUBLE, math_asin_tn, DOUBLE, 1, 1))) |
(1, (static, DOUBLE, math_asin_tn, DOUBLE, 1, 1))) |
702 |
JS_DEFINE_TRCINFO_1(math_atan2, |
JS_DEFINE_TRCINFO_1(math_atan2, |
703 |
(2, (static, DOUBLE, math_atan2_kernel, DOUBLE, DOUBLE, 1, 1))) |
(2, (static, DOUBLE, math_atan2_kernel, DOUBLE, DOUBLE, 1, 1))) |
704 |
|
JS_DEFINE_TRCINFO_1(js_math_floor, |
705 |
|
(1, (static, DOUBLE, math_floor_tn, DOUBLE, 1, 1))) |
706 |
JS_DEFINE_TRCINFO_1(math_log, |
JS_DEFINE_TRCINFO_1(math_log, |
707 |
(1, (static, DOUBLE, math_log_tn, DOUBLE, 1, 1))) |
(1, (static, DOUBLE, math_log_tn, DOUBLE, 1, 1))) |
708 |
JS_DEFINE_TRCINFO_1(math_max, |
JS_DEFINE_TRCINFO_1(js_math_max, |
709 |
(2, (static, DOUBLE, math_max_tn, DOUBLE, DOUBLE, 1, 1))) |
(2, (static, DOUBLE, math_max_tn, DOUBLE, DOUBLE, 1, 1))) |
710 |
JS_DEFINE_TRCINFO_1(math_min, |
JS_DEFINE_TRCINFO_1(js_math_min, |
711 |
(2, (static, DOUBLE, math_min_tn, DOUBLE, DOUBLE, 1, 1))) |
(2, (static, DOUBLE, math_min_tn, DOUBLE, DOUBLE, 1, 1))) |
712 |
JS_DEFINE_TRCINFO_1(math_pow, |
JS_DEFINE_TRCINFO_1(math_pow, |
713 |
(2, (static, DOUBLE, math_pow_tn, DOUBLE, DOUBLE, 1, 1))) |
(2, (static, DOUBLE, math_pow_tn, DOUBLE, DOUBLE, 1, 1))) |
714 |
JS_DEFINE_TRCINFO_1(math_random, |
JS_DEFINE_TRCINFO_1(math_random, |
715 |
(1, (static, DOUBLE, math_random_tn, RUNTIME, 0, 0))) |
(1, (static, DOUBLE, math_random_tn, CONTEXT, 0, 0))) |
716 |
JS_DEFINE_TRCINFO_1(math_round, |
JS_DEFINE_TRCINFO_1(js_math_round, |
717 |
(1, (static, DOUBLE, math_round_tn, DOUBLE, 1, 1))) |
(1, (static, DOUBLE, math_round_tn, DOUBLE, 1, 1))) |
718 |
JS_DEFINE_TRCINFO_1(math_ceil, |
JS_DEFINE_TRCINFO_1(js_math_ceil, |
719 |
(1, (static, DOUBLE, math_ceil_tn, DOUBLE, 1, 1))) |
(1, (static, DOUBLE, math_ceil_tn, DOUBLE, 1, 1))) |
720 |
|
|
721 |
#endif /* JS_TRACER */ |
#endif /* JS_TRACER */ |
724 |
#if JS_HAS_TOSOURCE |
#if JS_HAS_TOSOURCE |
725 |
JS_FN(js_toSource_str, math_toSource, 0, 0), |
JS_FN(js_toSource_str, math_toSource, 0, 0), |
726 |
#endif |
#endif |
727 |
JS_TN("abs", math_abs, 1, 0, math_abs_trcinfo), |
JS_TN("abs", math_abs, 1, 0, &math_abs_trcinfo), |
728 |
JS_TN("acos", math_acos, 1, 0, math_acos_trcinfo), |
JS_TN("acos", math_acos, 1, 0, &math_acos_trcinfo), |
729 |
JS_TN("asin", math_asin, 1, 0, math_asin_trcinfo), |
JS_TN("asin", math_asin, 1, 0, &math_asin_trcinfo), |
730 |
JS_TN("atan", math_atan, 1, 0, math_atan_trcinfo), |
JS_TN("atan", math_atan, 1, 0, &math_atan_trcinfo), |
731 |
JS_TN("atan2", math_atan2, 2, 0, math_atan2_trcinfo), |
JS_TN("atan2", math_atan2, 2, 0, &math_atan2_trcinfo), |
732 |
JS_TN("ceil", math_ceil, 1, 0, math_ceil_trcinfo), |
JS_TN("ceil", js_math_ceil, 1, 0, &js_math_ceil_trcinfo), |
733 |
JS_TN("cos", math_cos, 1, 0, math_cos_trcinfo), |
JS_TN("cos", math_cos, 1, 0, &math_cos_trcinfo), |
734 |
JS_TN("exp", math_exp, 1, 0, math_exp_trcinfo), |
JS_TN("exp", math_exp, 1, 0, &math_exp_trcinfo), |
735 |
JS_TN("floor", math_floor, 1, 0, math_floor_trcinfo), |
JS_TN("floor", js_math_floor, 1, 0, &js_math_floor_trcinfo), |
736 |
JS_TN("log", math_log, 1, 0, math_log_trcinfo), |
JS_TN("log", math_log, 1, 0, &math_log_trcinfo), |
737 |
JS_TN("max", math_max, 2, 0, math_max_trcinfo), |
JS_TN("max", js_math_max, 2, 0, &js_math_max_trcinfo), |
738 |
JS_TN("min", math_min, 2, 0, math_min_trcinfo), |
JS_TN("min", js_math_min, 2, 0, &js_math_min_trcinfo), |
739 |
JS_TN("pow", math_pow, 2, 0, math_pow_trcinfo), |
JS_TN("pow", math_pow, 2, 0, &math_pow_trcinfo), |
740 |
JS_TN("random", math_random, 0, 0, math_random_trcinfo), |
JS_TN("random", math_random, 0, 0, &math_random_trcinfo), |
741 |
JS_TN("round", math_round, 1, 0, math_round_trcinfo), |
JS_TN("round", js_math_round, 1, 0, &js_math_round_trcinfo), |
742 |
JS_TN("sin", math_sin, 1, 0, math_sin_trcinfo), |
JS_TN("sin", math_sin, 1, 0, &math_sin_trcinfo), |
743 |
JS_TN("sqrt", math_sqrt, 1, 0, math_sqrt_trcinfo), |
JS_TN("sqrt", math_sqrt, 1, 0, &math_sqrt_trcinfo), |
744 |
JS_TN("tan", math_tan, 1, 0, math_tan_trcinfo), |
JS_TN("tan", math_tan, 1, 0, &math_tan_trcinfo), |
745 |
JS_FS_END |
JS_FS_END |
746 |
}; |
}; |
747 |
|
|