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 <stdlib.h>
44 : #include "jstypes.h"
45 : #include "prmjtime.h"
46 : #include "jsapi.h"
47 : #include "jsatom.h"
48 : #include "jscntxt.h"
49 : #include "jsversion.h"
50 : #include "jslock.h"
51 : #include "jsmath.h"
52 : #include "jsnum.h"
53 : #include "jslibmath.h"
54 : #include "jscompartment.h"
55 :
56 : #include "jsinferinlines.h"
57 : #include "jsobjinlines.h"
58 :
59 : using namespace js;
60 :
61 : #ifndef M_E
62 : #define M_E 2.7182818284590452354
63 : #endif
64 : #ifndef M_LOG2E
65 : #define M_LOG2E 1.4426950408889634074
66 : #endif
67 : #ifndef M_LOG10E
68 : #define M_LOG10E 0.43429448190325182765
69 : #endif
70 : #ifndef M_LN2
71 : #define M_LN2 0.69314718055994530942
72 : #endif
73 : #ifndef M_LN10
74 : #define M_LN10 2.30258509299404568402
75 : #endif
76 : #ifndef M_PI
77 : #define M_PI 3.14159265358979323846
78 : #endif
79 : #ifndef M_SQRT2
80 : #define M_SQRT2 1.41421356237309504880
81 : #endif
82 : #ifndef M_SQRT1_2
83 : #define M_SQRT1_2 0.70710678118654752440
84 : #endif
85 :
86 : static JSConstDoubleSpec math_constants[] = {
87 : {M_E, "E", 0, {0,0,0}},
88 : {M_LOG2E, "LOG2E", 0, {0,0,0}},
89 : {M_LOG10E, "LOG10E", 0, {0,0,0}},
90 : {M_LN2, "LN2", 0, {0,0,0}},
91 : {M_LN10, "LN10", 0, {0,0,0}},
92 : {M_PI, "PI", 0, {0,0,0}},
93 : {M_SQRT2, "SQRT2", 0, {0,0,0}},
94 : {M_SQRT1_2, "SQRT1_2", 0, {0,0,0}},
95 : {0,0,0,{0,0,0}}
96 : };
97 :
98 174 : MathCache::MathCache() {
99 174 : memset(table, 0, sizeof(table));
100 :
101 : /* See comments in lookup(). */
102 174 : JS_ASSERT(JSDOUBLE_IS_NEGZERO(-0.0));
103 174 : JS_ASSERT(!JSDOUBLE_IS_NEGZERO(+0.0));
104 174 : JS_ASSERT(hash(-0.0) != hash(+0.0));
105 174 : }
106 :
107 : Class js::MathClass = {
108 : js_Math_str,
109 : JSCLASS_HAS_CACHED_PROTO(JSProto_Math),
110 : JS_PropertyStub, /* addProperty */
111 : JS_PropertyStub, /* delProperty */
112 : JS_PropertyStub, /* getProperty */
113 : JS_StrictPropertyStub, /* setProperty */
114 : JS_EnumerateStub,
115 : JS_ResolveStub,
116 : JS_ConvertStub
117 : };
118 :
119 : JSBool
120 22442 : js_math_abs(JSContext *cx, unsigned argc, Value *vp)
121 : {
122 : double x, z;
123 :
124 22442 : if (argc == 0) {
125 108 : vp->setDouble(js_NaN);
126 108 : return JS_TRUE;
127 : }
128 22334 : if (!ToNumber(cx, vp[2], &x))
129 0 : return JS_FALSE;
130 22334 : z = fabs(x);
131 22334 : vp->setNumber(z);
132 22334 : return JS_TRUE;
133 : }
134 :
135 : static JSBool
136 1530 : math_acos(JSContext *cx, unsigned argc, Value *vp)
137 : {
138 : double x, z;
139 :
140 1530 : if (argc == 0) {
141 0 : vp->setDouble(js_NaN);
142 0 : return JS_TRUE;
143 : }
144 1530 : if (!ToNumber(cx, vp[2], &x))
145 0 : return JS_FALSE;
146 : #if defined(SOLARIS) && defined(__GNUC__)
147 : if (x < -1 || 1 < x) {
148 : vp->setDouble(js_NaN);
149 : return JS_TRUE;
150 : }
151 : #endif
152 1530 : MathCache *mathCache = GetMathCache(cx);
153 1530 : if (!mathCache)
154 0 : return JS_FALSE;
155 1530 : z = mathCache->lookup(acos, x);
156 1530 : vp->setDouble(z);
157 1530 : return JS_TRUE;
158 : }
159 :
160 : static JSBool
161 1638 : math_asin(JSContext *cx, unsigned argc, Value *vp)
162 : {
163 : double x, z;
164 :
165 1638 : if (argc == 0) {
166 0 : vp->setDouble(js_NaN);
167 0 : return JS_TRUE;
168 : }
169 1638 : if (!ToNumber(cx, vp[2], &x))
170 0 : return JS_FALSE;
171 : #if defined(SOLARIS) && defined(__GNUC__)
172 : if (x < -1 || 1 < x) {
173 : vp->setDouble(js_NaN);
174 : return JS_TRUE;
175 : }
176 : #endif
177 1638 : MathCache *mathCache = GetMathCache(cx);
178 1638 : if (!mathCache)
179 0 : return JS_FALSE;
180 1638 : z = mathCache->lookup(asin, x);
181 1638 : vp->setDouble(z);
182 1638 : return JS_TRUE;
183 : }
184 :
185 : static JSBool
186 1440 : math_atan(JSContext *cx, unsigned argc, Value *vp)
187 : {
188 : double x, z;
189 :
190 1440 : if (argc == 0) {
191 0 : vp->setDouble(js_NaN);
192 0 : return JS_TRUE;
193 : }
194 1440 : if (!ToNumber(cx, vp[2], &x))
195 0 : return JS_FALSE;
196 1440 : MathCache *mathCache = GetMathCache(cx);
197 1440 : if (!mathCache)
198 0 : return JS_FALSE;
199 1440 : z = mathCache->lookup(atan, x);
200 1440 : vp->setDouble(z);
201 1440 : return JS_TRUE;
202 : }
203 :
204 : static inline double JS_FASTCALL
205 3186 : math_atan2_kernel(double x, double y)
206 : {
207 : #if defined(_MSC_VER)
208 : /*
209 : * MSVC's atan2 does not yield the result demanded by ECMA when both x
210 : * and y are infinite.
211 : * - The result is a multiple of pi/4.
212 : * - The sign of x determines the sign of the result.
213 : * - The sign of y determines the multiplicator, 1 or 3.
214 : */
215 : if (JSDOUBLE_IS_INFINITE(x) && JSDOUBLE_IS_INFINITE(y)) {
216 : double z = js_copysign(M_PI / 4, x);
217 : if (y < 0)
218 : z *= 3;
219 : return z;
220 : }
221 : #endif
222 :
223 : #if defined(SOLARIS) && defined(__GNUC__)
224 : if (x == 0) {
225 : if (JSDOUBLE_IS_NEGZERO(y))
226 : return js_copysign(M_PI, x);
227 : if (y == 0)
228 : return x;
229 : }
230 : #endif
231 3186 : return atan2(x, y);
232 : }
233 :
234 : static JSBool
235 3186 : math_atan2(JSContext *cx, unsigned argc, Value *vp)
236 : {
237 : double x, y, z;
238 :
239 3186 : if (argc <= 1) {
240 0 : vp->setDouble(js_NaN);
241 0 : return JS_TRUE;
242 : }
243 3186 : if (!ToNumber(cx, vp[2], &x) || !ToNumber(cx, vp[3], &y))
244 0 : return JS_FALSE;
245 3186 : z = math_atan2_kernel(x, y);
246 3186 : vp->setDouble(z);
247 3186 : return JS_TRUE;
248 : }
249 :
250 : double
251 3902 : js_math_ceil_impl(double x)
252 : {
253 : #ifdef __APPLE__
254 : if (x < 0 && x > -1.0)
255 : return js_copysign(0, -1);
256 : #endif
257 3902 : return ceil(x);
258 : }
259 :
260 : JSBool
261 3911 : js_math_ceil(JSContext *cx, unsigned argc, Value *vp)
262 : {
263 : double x, z;
264 :
265 3911 : if (argc == 0) {
266 9 : vp->setDouble(js_NaN);
267 9 : return JS_TRUE;
268 : }
269 3902 : if (!ToNumber(cx, vp[2], &x))
270 0 : return JS_FALSE;
271 3902 : z = js_math_ceil_impl(x);
272 3902 : vp->setNumber(z);
273 3902 : return JS_TRUE;
274 : }
275 :
276 : static JSBool
277 296883 : math_cos(JSContext *cx, unsigned argc, Value *vp)
278 : {
279 : double x, z;
280 :
281 296883 : if (argc == 0) {
282 0 : vp->setDouble(js_NaN);
283 0 : return JS_TRUE;
284 : }
285 296883 : if (!ToNumber(cx, vp[2], &x))
286 0 : return JS_FALSE;
287 296883 : MathCache *mathCache = GetMathCache(cx);
288 296883 : if (!mathCache)
289 0 : return JS_FALSE;
290 296883 : z = mathCache->lookup(cos, x);
291 296883 : vp->setDouble(z);
292 296883 : return JS_TRUE;
293 : }
294 :
295 : static double
296 135 : math_exp_body(double d)
297 : {
298 : #ifdef _WIN32
299 : if (!JSDOUBLE_IS_NaN(d)) {
300 : if (d == js_PositiveInfinity)
301 : return js_PositiveInfinity;
302 : if (d == js_NegativeInfinity)
303 : return 0.0;
304 : }
305 : #endif
306 135 : return exp(d);
307 : }
308 :
309 : static JSBool
310 1080 : math_exp(JSContext *cx, unsigned argc, Value *vp)
311 : {
312 : double x, z;
313 :
314 1080 : if (argc == 0) {
315 0 : vp->setDouble(js_NaN);
316 0 : return JS_TRUE;
317 : }
318 1080 : if (!ToNumber(cx, vp[2], &x))
319 0 : return JS_FALSE;
320 1080 : MathCache *mathCache = GetMathCache(cx);
321 1080 : if (!mathCache)
322 0 : return JS_FALSE;
323 1080 : z = mathCache->lookup(math_exp_body, x);
324 1080 : vp->setNumber(z);
325 1080 : return JS_TRUE;
326 : }
327 :
328 : double
329 52654 : js_math_floor_impl(double x)
330 : {
331 52654 : return floor(x);
332 : }
333 :
334 : JSBool
335 52654 : js_math_floor(JSContext *cx, unsigned argc, Value *vp)
336 : {
337 : double x, z;
338 :
339 52654 : if (argc == 0) {
340 0 : vp->setDouble(js_NaN);
341 0 : return JS_TRUE;
342 : }
343 52654 : if (!ToNumber(cx, vp[2], &x))
344 0 : return JS_FALSE;
345 52654 : z = js_math_floor_impl(x);
346 52654 : vp->setNumber(z);
347 52654 : return JS_TRUE;
348 : }
349 :
350 : static JSBool
351 23904 : math_log(JSContext *cx, unsigned argc, Value *vp)
352 : {
353 : double x, z;
354 :
355 23904 : if (argc == 0) {
356 0 : vp->setDouble(js_NaN);
357 0 : return JS_TRUE;
358 : }
359 23904 : if (!ToNumber(cx, vp[2], &x))
360 0 : return JS_FALSE;
361 : #if defined(SOLARIS) && defined(__GNUC__)
362 : if (x < 0) {
363 : vp->setDouble(js_NaN);
364 : return JS_TRUE;
365 : }
366 : #endif
367 23904 : MathCache *mathCache = GetMathCache(cx);
368 23904 : if (!mathCache)
369 0 : return JS_FALSE;
370 23904 : z = mathCache->lookup(log, x);
371 23904 : vp->setNumber(z);
372 23904 : return JS_TRUE;
373 : }
374 :
375 : JSBool
376 37661 : js_math_max(JSContext *cx, unsigned argc, Value *vp)
377 : {
378 37661 : double x, z = js_NegativeInfinity;
379 : Value *argv;
380 : unsigned i;
381 :
382 37661 : if (argc == 0) {
383 18 : vp->setDouble(js_NegativeInfinity);
384 18 : return JS_TRUE;
385 : }
386 37643 : argv = vp + 2;
387 117256 : for (i = 0; i < argc; i++) {
388 79946 : if (!ToNumber(cx, argv[i], &x))
389 0 : return JS_FALSE;
390 79946 : if (JSDOUBLE_IS_NaN(x)) {
391 333 : vp->setDouble(js_NaN);
392 333 : return JS_TRUE;
393 : }
394 79613 : if (x == 0 && x == z) {
395 904 : if (js_copysign(1.0, z) == -1)
396 117 : z = x;
397 : } else {
398 79161 : z = (x > z) ? x : z;
399 : }
400 : }
401 37310 : vp->setNumber(z);
402 37310 : return JS_TRUE;
403 : }
404 :
405 : JSBool
406 38283 : js_math_min(JSContext *cx, unsigned argc, Value *vp)
407 : {
408 38283 : double x, z = js_PositiveInfinity;
409 : Value *argv;
410 : unsigned i;
411 :
412 38283 : if (argc == 0) {
413 9 : vp->setDouble(js_PositiveInfinity);
414 9 : return JS_TRUE;
415 : }
416 38274 : argv = vp + 2;
417 114578 : for (i = 0; i < argc; i++) {
418 76565 : if (!ToNumber(cx, argv[i], &x))
419 0 : return JS_FALSE;
420 76565 : if (JSDOUBLE_IS_NaN(x)) {
421 261 : vp->setDouble(js_NaN);
422 261 : return JS_TRUE;
423 : }
424 76304 : if (x == 0 && x == z) {
425 360 : if (js_copysign(1.0, x) == -1)
426 126 : z = x;
427 : } else {
428 76124 : z = (x < z) ? x : z;
429 : }
430 : }
431 38013 : vp->setNumber(z);
432 38013 : return JS_TRUE;
433 : }
434 :
435 : static double
436 303558 : powi(double x, int y)
437 : {
438 303558 : unsigned n = (y < 0) ? -y : y;
439 303558 : double m = x;
440 303558 : double p = 1;
441 3269810 : while (true) {
442 3573368 : if ((n & 1) != 0) p *= m;
443 3573368 : n >>= 1;
444 3573368 : if (n == 0) {
445 303558 : if (y < 0) {
446 : // Unfortunately, we have to be careful when p has reached
447 : // infinity in the computation, because sometimes the higher
448 : // internal precision in the pow() implementation would have
449 : // given us a finite p. This happens very rarely.
450 :
451 90 : double result = 1.0 / p;
452 45 : return (result == 0 && JSDOUBLE_IS_INFINITE(p))
453 45 : ? pow(x, static_cast<double>(y)) // Avoid pow(double, int).
454 180 : : result;
455 : }
456 :
457 303468 : return p;
458 : }
459 3269810 : m *= m;
460 : }
461 : }
462 :
463 : JSBool
464 539921 : js_math_pow(JSContext *cx, unsigned argc, Value *vp)
465 : {
466 : double x, y, z;
467 :
468 539921 : if (argc <= 1) {
469 0 : vp->setDouble(js_NaN);
470 0 : return JS_TRUE;
471 : }
472 539921 : if (!ToNumber(cx, vp[2], &x) || !ToNumber(cx, vp[3], &y))
473 0 : return JS_FALSE;
474 : /*
475 : * Special case for square roots. Note that pow(x, 0.5) != sqrt(x)
476 : * when x = -0.0, so we have to guard for this.
477 : */
478 539921 : if (JSDOUBLE_IS_FINITE(x) && x != 0.0) {
479 535945 : if (y == 0.5) {
480 81 : vp->setNumber(sqrt(x));
481 81 : return JS_TRUE;
482 : }
483 535864 : if (y == -0.5) {
484 222418 : vp->setNumber(1.0/sqrt(x));
485 222418 : return JS_TRUE;
486 : }
487 : }
488 : /*
489 : * Because C99 and ECMA specify different behavior for pow(),
490 : * we need to wrap the libm call to make it ECMA compliant.
491 : */
492 317422 : if (!JSDOUBLE_IS_FINITE(y) && (x == 1.0 || x == -1.0)) {
493 99 : vp->setDouble(js_NaN);
494 99 : return JS_TRUE;
495 : }
496 : /* pow(x, +-0) is always 1, even for x = NaN. */
497 317323 : if (y == 0) {
498 147 : vp->setInt32(1);
499 147 : return JS_TRUE;
500 : }
501 :
502 317176 : if (vp[3].isInt32())
503 303558 : z = powi(x, vp[3].toInt32());
504 : else
505 13618 : z = pow(x, y);
506 :
507 317176 : vp->setNumber(z);
508 317176 : return JS_TRUE;
509 : }
510 :
511 : static const int64_t RNG_MULTIPLIER = 0x5DEECE66DLL;
512 : static const int64_t RNG_ADDEND = 0xBLL;
513 : static const int64_t RNG_MASK = (1LL << 48) - 1;
514 : static const double RNG_DSCALE = double(1LL << 53);
515 :
516 : /*
517 : * Math.random() support, lifted from java.util.Random.java.
518 : */
519 : extern void
520 39449 : random_setSeed(int64_t *rngSeed, int64_t seed)
521 : {
522 39449 : *rngSeed = (seed ^ RNG_MULTIPLIER) & RNG_MASK;
523 39449 : }
524 :
525 : void
526 39449 : js_InitRandom(JSContext *cx)
527 : {
528 : /*
529 : * Set the seed from current time. Since we have a RNG per context and we often bring
530 : * up several contexts at the same time, we xor in some additional values, namely
531 : * the context and its successor. We don't just use the context because it might be
532 : * possible to reverse engineer the context pointer if one guesses the time right.
533 : */
534 39449 : random_setSeed(&cx->rngSeed, (PRMJ_Now() / 1000) ^ int64_t(cx) ^ int64_t(cx->link.next));
535 39449 : }
536 :
537 : extern uint64_t
538 7848 : random_next(int64_t *rngSeed, int bits)
539 : {
540 7848 : uint64_t nextseed = *rngSeed * RNG_MULTIPLIER;
541 7848 : nextseed += RNG_ADDEND;
542 7848 : nextseed &= RNG_MASK;
543 7848 : *rngSeed = nextseed;
544 7848 : return nextseed >> (48 - bits);
545 : }
546 :
547 : static inline double
548 3924 : random_nextDouble(JSContext *cx)
549 : {
550 7848 : return double((random_next(&cx->rngSeed, 26) << 27) + random_next(&cx->rngSeed, 27)) /
551 7848 : RNG_DSCALE;
552 : }
553 :
554 : static JSBool
555 3924 : math_random(JSContext *cx, unsigned argc, Value *vp)
556 : {
557 3924 : double z = random_nextDouble(cx);
558 3924 : vp->setDouble(z);
559 3924 : return JS_TRUE;
560 : }
561 :
562 : #if defined _WIN32 && _MSC_VER < 1400
563 : /* Try to work around apparent _copysign bustage in VC7.x. */
564 : double
565 : js_copysign(double x, double y)
566 : {
567 : jsdpun xu, yu;
568 :
569 : xu.d = x;
570 : yu.d = y;
571 : xu.s.hi &= ~JSDOUBLE_HI32_SIGNBIT;
572 : xu.s.hi |= yu.s.hi & JSDOUBLE_HI32_SIGNBIT;
573 : return xu.d;
574 : }
575 : #endif
576 :
577 :
578 : JSBool /* ES5 15.8.2.15. */
579 15252 : js_math_round(JSContext *cx, unsigned argc, Value *vp)
580 : {
581 15252 : CallArgs args = CallArgsFromVp(argc, vp);
582 :
583 15252 : if (args.length() == 0) {
584 0 : args.rval().setDouble(js_NaN);
585 0 : return true;
586 : }
587 :
588 : double x;
589 15252 : if (!ToNumber(cx, args[0], &x))
590 0 : return false;
591 :
592 : int32_t i;
593 15252 : if (JSDOUBLE_IS_INT32(x, &i)) {
594 545 : args.rval().setInt32(i);
595 545 : return true;
596 : }
597 :
598 : jsdpun u;
599 14707 : u.d = x;
600 :
601 : /* Some numbers are so big that adding 0.5 would give the wrong number */
602 14707 : int exponent = ((u.s.hi & JSDOUBLE_HI32_EXPMASK) >> JSDOUBLE_HI32_EXPSHIFT) - JSDOUBLE_EXPBIAS;
603 14707 : if (exponent >= 52) {
604 81 : args.rval().setNumber(x);
605 81 : return true;
606 : }
607 :
608 14626 : args.rval().setNumber(js_copysign(floor(x + 0.5), x));
609 14626 : return true;
610 : }
611 :
612 : static JSBool
613 2238427 : math_sin(JSContext *cx, unsigned argc, Value *vp)
614 : {
615 : double x, z;
616 :
617 2238427 : if (argc == 0) {
618 0 : vp->setDouble(js_NaN);
619 0 : return JS_TRUE;
620 : }
621 2238427 : if (!ToNumber(cx, vp[2], &x))
622 0 : return JS_FALSE;
623 2238427 : MathCache *mathCache = GetMathCache(cx);
624 2238427 : if (!mathCache)
625 0 : return JS_FALSE;
626 2238427 : z = mathCache->lookup(sin, x);
627 2238427 : vp->setDouble(z);
628 2238427 : return JS_TRUE;
629 : }
630 :
631 : JSBool
632 284705 : js_math_sqrt(JSContext *cx, unsigned argc, Value *vp)
633 : {
634 : double x, z;
635 :
636 284705 : if (argc == 0) {
637 0 : vp->setDouble(js_NaN);
638 0 : return JS_TRUE;
639 : }
640 284705 : if (!ToNumber(cx, vp[2], &x))
641 0 : return JS_FALSE;
642 284705 : MathCache *mathCache = GetMathCache(cx);
643 284705 : if (!mathCache)
644 0 : return JS_FALSE;
645 284705 : z = mathCache->lookup(sqrt, x);
646 284705 : vp->setDouble(z);
647 284705 : return JS_TRUE;
648 : }
649 :
650 : static JSBool
651 1260 : math_tan(JSContext *cx, unsigned argc, Value *vp)
652 : {
653 : double x, z;
654 :
655 1260 : if (argc == 0) {
656 0 : vp->setDouble(js_NaN);
657 0 : return JS_TRUE;
658 : }
659 1260 : if (!ToNumber(cx, vp[2], &x))
660 0 : return JS_FALSE;
661 1260 : MathCache *mathCache = GetMathCache(cx);
662 1260 : if (!mathCache)
663 0 : return JS_FALSE;
664 1260 : z = mathCache->lookup(tan, x);
665 1260 : vp->setDouble(z);
666 1260 : return JS_TRUE;
667 : }
668 :
669 : #if JS_HAS_TOSOURCE
670 : static JSBool
671 0 : math_toSource(JSContext *cx, unsigned argc, Value *vp)
672 : {
673 0 : vp->setString(CLASS_ATOM(cx, Math));
674 0 : return JS_TRUE;
675 : }
676 : #endif
677 :
678 : static JSFunctionSpec math_static_methods[] = {
679 : #if JS_HAS_TOSOURCE
680 : JS_FN(js_toSource_str, math_toSource, 0, 0),
681 : #endif
682 : JS_FN("abs", js_math_abs, 1, 0),
683 : JS_FN("acos", math_acos, 1, 0),
684 : JS_FN("asin", math_asin, 1, 0),
685 : JS_FN("atan", math_atan, 1, 0),
686 : JS_FN("atan2", math_atan2, 2, 0),
687 : JS_FN("ceil", js_math_ceil, 1, 0),
688 : JS_FN("cos", math_cos, 1, 0),
689 : JS_FN("exp", math_exp, 1, 0),
690 : JS_FN("floor", js_math_floor, 1, 0),
691 : JS_FN("log", math_log, 1, 0),
692 : JS_FN("max", js_math_max, 2, 0),
693 : JS_FN("min", js_math_min, 2, 0),
694 : JS_FN("pow", js_math_pow, 2, 0),
695 : JS_FN("random", math_random, 0, 0),
696 : JS_FN("round", js_math_round, 1, 0),
697 : JS_FN("sin", math_sin, 1, 0),
698 : JS_FN("sqrt", js_math_sqrt, 1, 0),
699 : JS_FN("tan", math_tan, 1, 0),
700 : JS_FS_END
701 : };
702 :
703 : bool
704 0 : js_IsMathFunction(Native native)
705 : {
706 0 : for (size_t i=0; math_static_methods[i].name != NULL; i++) {
707 0 : if (native == math_static_methods[i].call)
708 0 : return true;
709 : }
710 0 : return false;
711 : }
712 :
713 : JSObject *
714 3925 : js_InitMathClass(JSContext *cx, JSObject *obj)
715 : {
716 3925 : JSObject *Math = NewObjectWithClassProto(cx, &MathClass, NULL, obj);
717 3925 : if (!Math || !Math->setSingletonType(cx))
718 0 : return NULL;
719 :
720 3925 : if (!JS_DefineProperty(cx, obj, js_Math_str, OBJECT_TO_JSVAL(Math),
721 3925 : JS_PropertyStub, JS_StrictPropertyStub, 0)) {
722 0 : return NULL;
723 : }
724 :
725 3925 : if (!JS_DefineFunctions(cx, Math, math_static_methods))
726 0 : return NULL;
727 3925 : if (!JS_DefineConstDoubles(cx, Math, math_constants))
728 0 : return NULL;
729 :
730 3925 : MarkStandardClassInitializedNoProto(obj, &MathClass);
731 :
732 3925 : return Math;
733 : }
|