~ubuntu-branches/ubuntu/precise/kompozer/precise

« back to all changes in this revision

Viewing changes to mozilla/js/src/jsmath.c

  • Committer: Bazaar Package Importer
  • Author(s): Anthony Yarusso
  • Date: 2007-08-27 01:11:03 UTC
  • Revision ID: james.westby@ubuntu.com-20070827011103-2jgf4s6532gqu2ka
Tags: upstream-0.7.10
ImportĀ upstreamĀ versionĀ 0.7.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 
2
 *
 
3
 * ***** BEGIN LICENSE BLOCK *****
 
4
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 
5
 *
 
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/
 
10
 *
 
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
 
14
 * License.
 
15
 *
 
16
 * The Original Code is Mozilla Communicator client code, released
 
17
 * March 31, 1998.
 
18
 *
 
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.
 
23
 *
 
24
 * Contributor(s):
 
25
 *
 
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.
 
37
 *
 
38
 * ***** END LICENSE BLOCK ***** */
 
39
 
 
40
/*
 
41
 * JS math package.
 
42
 */
 
43
#include "jsstddef.h"
 
44
#include "jslibmath.h"
 
45
#include <stdlib.h>
 
46
#include "jstypes.h"
 
47
#include "jslong.h"
 
48
#include "prmjtime.h"
 
49
#include "jsapi.h"
 
50
#include "jsatom.h"
 
51
#include "jscntxt.h"
 
52
#include "jsconfig.h"
 
53
#include "jslock.h"
 
54
#include "jsmath.h"
 
55
#include "jsnum.h"
 
56
#include "jsobj.h"
 
57
 
 
58
#ifndef M_E
 
59
#define M_E             2.7182818284590452354
 
60
#endif
 
61
#ifndef M_LOG2E
 
62
#define M_LOG2E         1.4426950408889634074
 
63
#endif
 
64
#ifndef M_LOG10E
 
65
#define M_LOG10E        0.43429448190325182765
 
66
#endif
 
67
#ifndef M_LN2
 
68
#define M_LN2           0.69314718055994530942
 
69
#endif
 
70
#ifndef M_LN10
 
71
#define M_LN10          2.30258509299404568402
 
72
#endif
 
73
#ifndef M_PI
 
74
#define M_PI            3.14159265358979323846
 
75
#endif
 
76
#ifndef M_SQRT2
 
77
#define M_SQRT2         1.41421356237309504880
 
78
#endif
 
79
#ifndef M_SQRT1_2
 
80
#define M_SQRT1_2       0.70710678118654752440
 
81
#endif
 
82
 
 
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}},
 
92
    {0,0,0,{0,0,0}}
 
93
};
 
94
 
 
95
static JSClass math_class = {
 
96
    "Math",
 
97
    0,
 
98
    JS_PropertyStub,  JS_PropertyStub,  JS_PropertyStub,  JS_PropertyStub,
 
99
    JS_EnumerateStub, JS_ResolveStub,   JS_ConvertStub,   JS_FinalizeStub,
 
100
    JSCLASS_NO_OPTIONAL_MEMBERS
 
101
};
 
102
 
 
103
static JSBool
 
104
math_abs(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 
105
{
 
106
    jsdouble x, z;
 
107
 
 
108
    if (!js_ValueToNumber(cx, argv[0], &x))
 
109
        return JS_FALSE;
 
110
    z = fd_fabs(x);
 
111
    return js_NewNumberValue(cx, z, rval);
 
112
}
 
113
 
 
114
static JSBool
 
115
math_acos(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 
116
{
 
117
    jsdouble x, z;
 
118
 
 
119
    if (!js_ValueToNumber(cx, argv[0], &x))
 
120
        return JS_FALSE;
 
121
    z = fd_acos(x);
 
122
    return js_NewNumberValue(cx, z, rval);
 
123
}
 
124
 
 
125
static JSBool
 
126
math_asin(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 
127
{
 
128
    jsdouble x, z;
 
129
 
 
130
    if (!js_ValueToNumber(cx, argv[0], &x))
 
131
        return JS_FALSE;
 
132
#ifdef XP_MAC
 
133
    if (x == 0)
 
134
        return js_NewNumberValue(cx, x, rval);
 
135
#endif    
 
136
    z = fd_asin(x);
 
137
    return js_NewNumberValue(cx, z, rval);
 
138
}
 
139
 
 
140
static JSBool
 
141
math_atan(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 
142
{
 
143
    jsdouble x, z;
 
144
 
 
145
    if (!js_ValueToNumber(cx, argv[0], &x))
 
146
        return JS_FALSE;
 
147
#ifdef XP_MAC
 
148
    if (x == 0)
 
149
        return js_NewNumberValue(cx, x, rval);
 
150
#endif    
 
151
    z = fd_atan(x);
 
152
    return js_NewNumberValue(cx, z, rval);
 
153
}
 
154
 
 
155
static JSBool
 
156
math_atan2(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 
157
{
 
158
    jsdouble x, y, z;
 
159
 
 
160
    if (!js_ValueToNumber(cx, argv[0], &x))
 
161
        return JS_FALSE;
 
162
    if (!js_ValueToNumber(cx, argv[1], &y))
 
163
        return JS_FALSE;
 
164
    z = fd_atan2(x, y);
 
165
    return js_NewNumberValue(cx, z, rval);
 
166
}
 
167
 
 
168
static JSBool
 
169
math_ceil(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 
170
{
 
171
    jsdouble x, z;
 
172
 
 
173
    if (!js_ValueToNumber(cx, argv[0], &x))
 
174
        return JS_FALSE;
 
175
    z = fd_ceil(x);
 
176
    return js_NewNumberValue(cx, z, rval);
 
177
}
 
178
 
 
179
static JSBool
 
180
math_cos(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 
181
{
 
182
    jsdouble x, z;
 
183
 
 
184
    if (!js_ValueToNumber(cx, argv[0], &x))
 
185
        return JS_FALSE;
 
186
    z = fd_cos(x);
 
187
    return js_NewNumberValue(cx, z, rval);
 
188
}
 
189
 
 
190
static JSBool
 
191
math_exp(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 
192
{
 
193
    jsdouble x, z;
 
194
 
 
195
    if (!js_ValueToNumber(cx, argv[0], &x))
 
196
        return JS_FALSE;
 
197
#ifdef _WIN32
 
198
    if (!JSDOUBLE_IS_NaN(x)) {
 
199
        if (x == *cx->runtime->jsPositiveInfinity) {
 
200
            *rval = DOUBLE_TO_JSVAL(cx->runtime->jsPositiveInfinity);
 
201
            return JS_TRUE;
 
202
        }
 
203
        if (x == *cx->runtime->jsNegativeInfinity) {
 
204
            *rval = JSVAL_ZERO;
 
205
            return JS_TRUE;
 
206
        }
 
207
    }
 
208
#endif
 
209
    z = fd_exp(x);
 
210
    return js_NewNumberValue(cx, z, rval);
 
211
}
 
212
 
 
213
static JSBool
 
214
math_floor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 
215
{
 
216
    jsdouble x, z;
 
217
 
 
218
    if (!js_ValueToNumber(cx, argv[0], &x))
 
219
        return JS_FALSE;
 
220
    z = fd_floor(x);
 
221
    return js_NewNumberValue(cx, z, rval);
 
222
}
 
223
 
 
224
static JSBool
 
225
math_log(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 
226
{
 
227
    jsdouble x, z;
 
228
 
 
229
    if (!js_ValueToNumber(cx, argv[0], &x))
 
230
        return JS_FALSE;
 
231
    z = fd_log(x);
 
232
    return js_NewNumberValue(cx, z, rval);
 
233
}
 
234
 
 
235
static JSBool
 
236
math_max(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 
237
{
 
238
    jsdouble x, z = *cx->runtime->jsNegativeInfinity;
 
239
    uintN i;
 
240
 
 
241
    if (argc == 0) {
 
242
        *rval = DOUBLE_TO_JSVAL(cx->runtime->jsNegativeInfinity);
 
243
        return JS_TRUE;
 
244
    }
 
245
    for (i = 0; i < argc; i++) {
 
246
        if (!js_ValueToNumber(cx, argv[i], &x))
 
247
            return JS_FALSE;
 
248
        if (JSDOUBLE_IS_NaN(x)) {
 
249
            *rval = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
 
250
            return JS_TRUE;
 
251
        }
 
252
        if ((x==0)&&(x==z)&&(fd_copysign(1.0,z)==-1))
 
253
            z = x;
 
254
        else
 
255
            z = (x > z) ? x : z;
 
256
    }
 
257
    return js_NewNumberValue(cx, z, rval);
 
258
}
 
259
 
 
260
static JSBool
 
261
math_min(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 
262
{
 
263
    jsdouble x, z = *cx->runtime->jsPositiveInfinity;
 
264
    uintN i;
 
265
 
 
266
    if (argc == 0) {
 
267
        *rval = DOUBLE_TO_JSVAL(cx->runtime->jsPositiveInfinity);
 
268
        return JS_TRUE;
 
269
    }
 
270
    for (i = 0; i < argc; i++) {
 
271
        if (!js_ValueToNumber(cx, argv[i], &x))
 
272
            return JS_FALSE;
 
273
        if (JSDOUBLE_IS_NaN(x)) {
 
274
            *rval = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
 
275
            return JS_TRUE;
 
276
        }
 
277
        if ((x==0)&&(x==z)&&(fd_copysign(1.0,x)==-1))
 
278
            z = x;
 
279
        else
 
280
            z = (x < z) ? x : z;
 
281
    }
 
282
    return js_NewNumberValue(cx, z, rval);
 
283
}
 
284
 
 
285
static JSBool
 
286
math_pow(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 
287
{
 
288
    jsdouble x, y, z;
 
289
 
 
290
    if (!js_ValueToNumber(cx, argv[0], &x))
 
291
        return JS_FALSE;
 
292
    if (!js_ValueToNumber(cx, argv[1], &y))
 
293
        return JS_FALSE;
 
294
    z = fd_pow(x, y);
 
295
    return js_NewNumberValue(cx, z, rval);
 
296
}
 
297
 
 
298
/*
 
299
 * Math.random() support, lifted from java.util.Random.java.
 
300
 */
 
301
static void
 
302
random_setSeed(JSRuntime *rt, int64 seed)
 
303
{
 
304
    int64 tmp;
 
305
 
 
306
    JSLL_I2L(tmp, 1000);
 
307
    JSLL_DIV(seed, seed, tmp);
 
308
    JSLL_XOR(tmp, seed, rt->rngMultiplier);
 
309
    JSLL_AND(rt->rngSeed, tmp, rt->rngMask);
 
310
}
 
311
 
 
312
static void
 
313
random_init(JSRuntime *rt)
 
314
{
 
315
    int64 tmp, tmp2;
 
316
 
 
317
    /* Do at most once. */
 
318
    if (rt->rngInitialized)
 
319
        return;
 
320
    rt->rngInitialized = JS_TRUE;
 
321
 
 
322
    /* rt->rngMultiplier = 0x5DEECE66DL */
 
323
    JSLL_ISHL(tmp, 0x5, 32);
 
324
    JSLL_UI2L(tmp2, 0xDEECE66DL);
 
325
    JSLL_OR(rt->rngMultiplier, tmp, tmp2);
 
326
 
 
327
    /* rt->rngAddend = 0xBL */
 
328
    JSLL_I2L(rt->rngAddend, 0xBL);
 
329
 
 
330
    /* rt->rngMask = (1L << 48) - 1 */
 
331
    JSLL_I2L(tmp, 1);
 
332
    JSLL_SHL(tmp2, tmp, 48);
 
333
    JSLL_SUB(rt->rngMask, tmp2, tmp);
 
334
 
 
335
    /* rt->rngDscale = (jsdouble)(1L << 53) */
 
336
    JSLL_SHL(tmp2, tmp, 53);
 
337
    JSLL_L2D(rt->rngDscale, tmp2);
 
338
 
 
339
    /* Finally, set the seed from current time. */
 
340
    random_setSeed(rt, PRMJ_Now());
 
341
}
 
342
 
 
343
static uint32
 
344
random_next(JSRuntime *rt, int bits)
 
345
{
 
346
    int64 nextseed, tmp;
 
347
    uint32 retval;
 
348
 
 
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);
 
355
    return retval;
 
356
}
 
357
 
 
358
static jsdouble
 
359
random_nextDouble(JSRuntime *rt)
 
360
{
 
361
    int64 tmp, tmp2;
 
362
    jsdouble d;
 
363
 
 
364
    JSLL_ISHL(tmp, random_next(rt, 26), 27);
 
365
    JSLL_UI2L(tmp2, random_next(rt, 27));
 
366
    JSLL_ADD(tmp, tmp, tmp2);
 
367
    JSLL_L2D(d, tmp);
 
368
    return d / rt->rngDscale;
 
369
}
 
370
 
 
371
static JSBool
 
372
math_random(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 
373
{
 
374
    JSRuntime *rt;
 
375
    jsdouble z;
 
376
 
 
377
    rt = cx->runtime;
 
378
    JS_LOCK_RUNTIME(rt);
 
379
    random_init(rt);
 
380
    z = random_nextDouble(rt);
 
381
    JS_UNLOCK_RUNTIME(rt);
 
382
    return js_NewNumberValue(cx, z, rval);
 
383
}
 
384
 
 
385
static JSBool
 
386
math_round(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 
387
{
 
388
    jsdouble x, z;
 
389
 
 
390
    if (!js_ValueToNumber(cx, argv[0], &x))
 
391
        return JS_FALSE;
 
392
    z = fd_copysign(fd_floor(x + 0.5), x);
 
393
    return js_NewNumberValue(cx, z, rval);
 
394
}
 
395
 
 
396
static JSBool
 
397
math_sin(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 
398
{
 
399
    jsdouble x, z;
 
400
 
 
401
    if (!js_ValueToNumber(cx, argv[0], &x))
 
402
        return JS_FALSE;
 
403
    z = fd_sin(x);
 
404
    return js_NewNumberValue(cx, z, rval);
 
405
}
 
406
 
 
407
static JSBool
 
408
math_sqrt(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 
409
{
 
410
    jsdouble x, z;
 
411
 
 
412
    if (!js_ValueToNumber(cx, argv[0], &x))
 
413
        return JS_FALSE;
 
414
    z = fd_sqrt(x);
 
415
    return js_NewNumberValue(cx, z, rval);
 
416
}
 
417
 
 
418
static JSBool
 
419
math_tan(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 
420
{
 
421
    jsdouble x, z;
 
422
 
 
423
    if (!js_ValueToNumber(cx, argv[0], &x))
 
424
        return JS_FALSE;
 
425
    z = fd_tan(x);
 
426
    return js_NewNumberValue(cx, z, rval);
 
427
}
 
428
 
 
429
#if JS_HAS_TOSOURCE
 
430
static JSBool
 
431
math_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
 
432
              jsval *rval)
 
433
{
 
434
    *rval = ATOM_KEY(cx->runtime->atomState.MathAtom);
 
435
    return JS_TRUE;
 
436
}
 
437
#endif
 
438
 
 
439
static JSFunctionSpec math_static_methods[] = {
 
440
#if JS_HAS_TOSOURCE
 
441
    {js_toSource_str,   math_toSource,          0, 0, 0},
 
442
#endif
 
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},
 
461
    {0,0,0,0,0}
 
462
};
 
463
 
 
464
JSObject *
 
465
js_InitMathClass(JSContext *cx, JSObject *obj)
 
466
{
 
467
    JSObject *Math;
 
468
    
 
469
    Math = JS_DefineObject(cx, obj, "Math", &math_class, NULL, 0);
 
470
    if (!Math)
 
471
        return NULL;
 
472
    if (!JS_DefineFunctions(cx, Math, math_static_methods))
 
473
        return NULL;
 
474
    if (!JS_DefineConstDoubles(cx, Math, math_constants))
 
475
        return NULL;
 
476
    return Math;
 
477
}