1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
3
* ***** BEGIN LICENSE BLOCK *****
4
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
6
* The contents of this file are subject to the Mozilla Public License Version
7
* 1.1 (the "License"); you may not use this file except in compliance with
8
* the License. You may obtain a copy of the License at
9
* http://www.mozilla.org/MPL/
11
* Software distributed under the License is distributed on an "AS IS" basis,
12
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13
* for the specific language governing rights and limitations under the
16
* The Original Code is Mozilla Communicator client code, released
19
* The Initial Developer of the Original Code is
20
* Netscape Communications Corporation.
21
* Portions created by the Initial Developer are Copyright (C) 1998
22
* the Initial Developer. All Rights Reserved.
26
* Alternatively, the contents of this file may be used under the terms of
27
* either of the GNU General Public License Version 2 or later (the "GPL"),
28
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29
* in which case the provisions of the GPL or the LGPL are applicable instead
30
* of those above. If you wish to allow use of your version of this file only
31
* under the terms of either the GPL or the LGPL, and not to allow others to
32
* use your version of this file under the terms of the MPL, indicate your
33
* decision by deleting the provisions above and replace them with the notice
34
* and other provisions required by the GPL or the LGPL. If you do not delete
35
* the provisions above, a recipient may use your version of this file under
36
* the terms of any one of the MPL, the GPL or the LGPL.
38
* ***** END LICENSE BLOCK ***** */
44
#include "jslibmath.h"
59
#define M_E 2.7182818284590452354
62
#define M_LOG2E 1.4426950408889634074
65
#define M_LOG10E 0.43429448190325182765
68
#define M_LN2 0.69314718055994530942
71
#define M_LN10 2.30258509299404568402
74
#define M_PI 3.14159265358979323846
77
#define M_SQRT2 1.41421356237309504880
80
#define M_SQRT1_2 0.70710678118654752440
83
static JSConstDoubleSpec math_constants[] = {
84
{M_E, "E", 0, {0,0,0}},
85
{M_LOG2E, "LOG2E", 0, {0,0,0}},
86
{M_LOG10E, "LOG10E", 0, {0,0,0}},
87
{M_LN2, "LN2", 0, {0,0,0}},
88
{M_LN10, "LN10", 0, {0,0,0}},
89
{M_PI, "PI", 0, {0,0,0}},
90
{M_SQRT2, "SQRT2", 0, {0,0,0}},
91
{M_SQRT1_2, "SQRT1_2", 0, {0,0,0}},
95
static JSClass math_class = {
98
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
99
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
100
JSCLASS_NO_OPTIONAL_MEMBERS
104
math_abs(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
108
if (!js_ValueToNumber(cx, argv[0], &x))
111
return js_NewNumberValue(cx, z, rval);
115
math_acos(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
119
if (!js_ValueToNumber(cx, argv[0], &x))
122
return js_NewNumberValue(cx, z, rval);
126
math_asin(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
130
if (!js_ValueToNumber(cx, argv[0], &x))
134
return js_NewNumberValue(cx, x, rval);
137
return js_NewNumberValue(cx, z, rval);
141
math_atan(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
145
if (!js_ValueToNumber(cx, argv[0], &x))
149
return js_NewNumberValue(cx, x, rval);
152
return js_NewNumberValue(cx, z, rval);
156
math_atan2(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
160
if (!js_ValueToNumber(cx, argv[0], &x))
162
if (!js_ValueToNumber(cx, argv[1], &y))
165
return js_NewNumberValue(cx, z, rval);
169
math_ceil(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
173
if (!js_ValueToNumber(cx, argv[0], &x))
176
return js_NewNumberValue(cx, z, rval);
180
math_cos(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
184
if (!js_ValueToNumber(cx, argv[0], &x))
187
return js_NewNumberValue(cx, z, rval);
191
math_exp(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
195
if (!js_ValueToNumber(cx, argv[0], &x))
198
if (!JSDOUBLE_IS_NaN(x)) {
199
if (x == *cx->runtime->jsPositiveInfinity) {
200
*rval = DOUBLE_TO_JSVAL(cx->runtime->jsPositiveInfinity);
203
if (x == *cx->runtime->jsNegativeInfinity) {
210
return js_NewNumberValue(cx, z, rval);
214
math_floor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
218
if (!js_ValueToNumber(cx, argv[0], &x))
221
return js_NewNumberValue(cx, z, rval);
225
math_log(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
229
if (!js_ValueToNumber(cx, argv[0], &x))
232
return js_NewNumberValue(cx, z, rval);
236
math_max(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
238
jsdouble x, z = *cx->runtime->jsNegativeInfinity;
242
*rval = DOUBLE_TO_JSVAL(cx->runtime->jsNegativeInfinity);
245
for (i = 0; i < argc; i++) {
246
if (!js_ValueToNumber(cx, argv[i], &x))
248
if (JSDOUBLE_IS_NaN(x)) {
249
*rval = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
252
if ((x==0)&&(x==z)&&(fd_copysign(1.0,z)==-1))
257
return js_NewNumberValue(cx, z, rval);
261
math_min(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
263
jsdouble x, z = *cx->runtime->jsPositiveInfinity;
267
*rval = DOUBLE_TO_JSVAL(cx->runtime->jsPositiveInfinity);
270
for (i = 0; i < argc; i++) {
271
if (!js_ValueToNumber(cx, argv[i], &x))
273
if (JSDOUBLE_IS_NaN(x)) {
274
*rval = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
277
if ((x==0)&&(x==z)&&(fd_copysign(1.0,x)==-1))
282
return js_NewNumberValue(cx, z, rval);
286
math_pow(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
290
if (!js_ValueToNumber(cx, argv[0], &x))
292
if (!js_ValueToNumber(cx, argv[1], &y))
295
return js_NewNumberValue(cx, z, rval);
299
* Math.random() support, lifted from java.util.Random.java.
302
random_setSeed(JSRuntime *rt, int64 seed)
307
JSLL_DIV(seed, seed, tmp);
308
JSLL_XOR(tmp, seed, rt->rngMultiplier);
309
JSLL_AND(rt->rngSeed, tmp, rt->rngMask);
313
random_init(JSRuntime *rt)
317
/* Do at most once. */
318
if (rt->rngInitialized)
320
rt->rngInitialized = JS_TRUE;
322
/* rt->rngMultiplier = 0x5DEECE66DL */
323
JSLL_ISHL(tmp, 0x5, 32);
324
JSLL_UI2L(tmp2, 0xDEECE66DL);
325
JSLL_OR(rt->rngMultiplier, tmp, tmp2);
327
/* rt->rngAddend = 0xBL */
328
JSLL_I2L(rt->rngAddend, 0xBL);
330
/* rt->rngMask = (1L << 48) - 1 */
332
JSLL_SHL(tmp2, tmp, 48);
333
JSLL_SUB(rt->rngMask, tmp2, tmp);
335
/* rt->rngDscale = (jsdouble)(1L << 53) */
336
JSLL_SHL(tmp2, tmp, 53);
337
JSLL_L2D(rt->rngDscale, tmp2);
339
/* Finally, set the seed from current time. */
340
random_setSeed(rt, PRMJ_Now());
344
random_next(JSRuntime *rt, int bits)
349
JSLL_MUL(nextseed, rt->rngSeed, rt->rngMultiplier);
350
JSLL_ADD(nextseed, nextseed, rt->rngAddend);
351
JSLL_AND(nextseed, nextseed, rt->rngMask);
352
rt->rngSeed = nextseed;
353
JSLL_USHR(tmp, nextseed, 48 - bits);
354
JSLL_L2I(retval, tmp);
359
random_nextDouble(JSRuntime *rt)
364
JSLL_ISHL(tmp, random_next(rt, 26), 27);
365
JSLL_UI2L(tmp2, random_next(rt, 27));
366
JSLL_ADD(tmp, tmp, tmp2);
368
return d / rt->rngDscale;
372
math_random(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
380
z = random_nextDouble(rt);
381
JS_UNLOCK_RUNTIME(rt);
382
return js_NewNumberValue(cx, z, rval);
386
math_round(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
390
if (!js_ValueToNumber(cx, argv[0], &x))
392
z = fd_copysign(fd_floor(x + 0.5), x);
393
return js_NewNumberValue(cx, z, rval);
397
math_sin(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
401
if (!js_ValueToNumber(cx, argv[0], &x))
404
return js_NewNumberValue(cx, z, rval);
408
math_sqrt(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
412
if (!js_ValueToNumber(cx, argv[0], &x))
415
return js_NewNumberValue(cx, z, rval);
419
math_tan(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
423
if (!js_ValueToNumber(cx, argv[0], &x))
426
return js_NewNumberValue(cx, z, rval);
431
math_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
434
*rval = ATOM_KEY(cx->runtime->atomState.MathAtom);
439
static JSFunctionSpec math_static_methods[] = {
441
{js_toSource_str, math_toSource, 0, 0, 0},
443
{"abs", math_abs, 1, 0, 0},
444
{"acos", math_acos, 1, 0, 0},
445
{"asin", math_asin, 1, 0, 0},
446
{"atan", math_atan, 1, 0, 0},
447
{"atan2", math_atan2, 2, 0, 0},
448
{"ceil", math_ceil, 1, 0, 0},
449
{"cos", math_cos, 1, 0, 0},
450
{"exp", math_exp, 1, 0, 0},
451
{"floor", math_floor, 1, 0, 0},
452
{"log", math_log, 1, 0, 0},
453
{"max", math_max, 2, 0, 0},
454
{"min", math_min, 2, 0, 0},
455
{"pow", math_pow, 2, 0, 0},
456
{"random", math_random, 0, 0, 0},
457
{"round", math_round, 1, 0, 0},
458
{"sin", math_sin, 1, 0, 0},
459
{"sqrt", math_sqrt, 1, 0, 0},
460
{"tan", math_tan, 1, 0, 0},
465
js_InitMathClass(JSContext *cx, JSObject *obj)
469
Math = JS_DefineObject(cx, obj, "Math", &math_class, NULL, 0);
472
if (!JS_DefineFunctions(cx, Math, math_static_methods))
474
if (!JS_DefineConstDoubles(cx, Math, math_constants))