LCOV - app.info - js/src/jsmath.cpp

LCOV - code coverage report
| Current view: | directory - js/src - jsmath.cpp (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 290 | 226 | 77.9 %
| Date: | 2012-04-07 | Functions: | 31 | 29 | 93.5 %

           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             183 : MathCache::MathCache() {
          99             183 :     memset(table, 0, sizeof(table));
         100                 :
         101                 :     /* See comments in lookup(). */
         102             183 :     JS_ASSERT(JSDOUBLE_IS_NEGZERO(-0.0));
         103             183 :     JS_ASSERT(!JSDOUBLE_IS_NEGZERO(+0.0));
         104             183 :     JS_ASSERT(hash(-0.0) != hash(+0.0));
         105             183 : }
         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           22347 : js_math_abs(JSContext *cx, unsigned argc, Value *vp)
         121                 : {
         122                 :     double x, z;
         123                 :
         124           22347 :     if (argc == 0) {
         125             108 :         vp->setDouble(js_NaN);
         126             108 :         return JS_TRUE;
         127                 :     }
         128           22239 :     if (!ToNumber(cx, vp[2], &x))
         129               0 :         return JS_FALSE;
         130           22239 :     z = fabs(x);
         131           22239 :     vp->setNumber(z);
         132           22239 :     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            3438 : 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            3438 :     return ceil(x);
         258                 : }
         259                 :
         260                 : JSBool
         261            3447 : js_math_ceil(JSContext *cx, unsigned argc, Value *vp)
         262                 : {
         263                 :     double x, z;
         264                 :
         265            3447 :     if (argc == 0) {
         266               9 :         vp->setDouble(js_NaN);
         267               9 :         return JS_TRUE;
         268                 :     }
         269            3438 :     if (!ToNumber(cx, vp[2], &x))
         270               0 :         return JS_FALSE;
         271            3438 :     z = js_math_ceil_impl(x);
         272            3438 :     vp->setNumber(z);
         273            3438 :     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           48819 : js_math_floor_impl(double x)
         330                 : {
         331           48819 :     return floor(x);
         332                 : }
         333                 :
         334                 : JSBool
         335           48819 : js_math_floor(JSContext *cx, unsigned argc, Value *vp)
         336                 : {
         337                 :     double x, z;
         338                 :
         339           48819 :     if (argc == 0) {
         340               0 :         vp->setDouble(js_NaN);
         341               0 :         return JS_TRUE;
         342                 :     }
         343           48819 :     if (!ToNumber(cx, vp[2], &x))
         344               0 :         return JS_FALSE;
         345           48819 :     z = js_math_floor_impl(x);
         346           48819 :     vp->setNumber(z);
         347           48819 :     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           34082 : js_math_max(JSContext *cx, unsigned argc, Value *vp)
         377                 : {
         378           34082 :     double x, z = js_NegativeInfinity;
         379                 :     Value *argv;
         380                 :     unsigned i;
         381                 :
         382           34082 :     if (argc == 0) {
         383              18 :         vp->setDouble(js_NegativeInfinity);
         384              18 :         return JS_TRUE;
         385                 :     }
         386           34064 :     argv = vp + 2;
         387          101751 :     for (i = 0; i < argc; i++) {
         388           68020 :         if (!ToNumber(cx, argv[i], &x))
         389               0 :             return JS_FALSE;
         390           68020 :         if (JSDOUBLE_IS_NaN(x)) {
         391             333 :             vp->setDouble(js_NaN);
         392             333 :             return JS_TRUE;
         393                 :         }
         394           67687 :         if (x == 0 && x == z) {
         395             468 :             if (js_copysign(1.0, z) == -1)
         396             117 :                 z = x;
         397                 :         } else {
         398           67453 :             z = (x > z) ? x : z;
         399                 :         }
         400                 :     }
         401           33731 :     vp->setNumber(z);
         402           33731 :     return JS_TRUE;
         403                 : }
         404                 :
         405                 : JSBool
         406            3084 : js_math_min(JSContext *cx, unsigned argc, Value *vp)
         407                 : {
         408            3084 :     double x, z = js_PositiveInfinity;
         409                 :     Value *argv;
         410                 :     unsigned i;
         411                 :
         412            3084 :     if (argc == 0) {
         413               9 :         vp->setDouble(js_PositiveInfinity);
         414               9 :         return JS_TRUE;
         415                 :     }
         416            3075 :     argv = vp + 2;
         417            8802 :     for (i = 0; i < argc; i++) {
         418            5988 :         if (!ToNumber(cx, argv[i], &x))
         419               0 :             return JS_FALSE;
         420            5988 :         if (JSDOUBLE_IS_NaN(x)) {
         421             261 :             vp->setDouble(js_NaN);
         422             261 :             return JS_TRUE;
         423                 :         }
         424            5727 :         if (x == 0 && x == z) {
         425             360 :             if (js_copysign(1.0, x) == -1)
         426             126 :                 z = x;
         427                 :         } else {
         428            5547 :             z = (x < z) ? x : z;
         429                 :         }
         430                 :     }
         431            2814 :     vp->setNumber(z);
         432            2814 :     return JS_TRUE;
         433                 : }
         434                 :
         435                 : static double
         436          300300 : powi(double x, int y)
         437                 : {
         438          300300 :     unsigned n = (y < 0) ? -y : y;
         439          300300 :     double m = x;
         440          300300 :     double p = 1;
         441         3254073 :     while (true) {
         442         3554373 :         if ((n & 1) != 0) p *= m;
         443         3554373 :         n >>= 1;
         444         3554373 :         if (n == 0) {
         445          300300 :             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          300210 :             return p;
         458                 :         }
         459         3254073 :         m *= m;
         460                 :     }
         461                 : }
         462                 :
         463                 : JSBool
         464          536660 : js_math_pow(JSContext *cx, unsigned argc, Value *vp)
         465                 : {
         466                 :     double x, y, z;
         467                 :
         468          536660 :     if (argc <= 1) {
         469               0 :         vp->setDouble(js_NaN);
         470               0 :         return JS_TRUE;
         471                 :     }
         472          536660 :     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          536660 :     if (JSDOUBLE_IS_FINITE(x) && x != 0.0) {
         479          532684 :         if (y == 0.5) {
         480              81 :             vp->setNumber(sqrt(x));
         481              81 :             return JS_TRUE;
         482                 :         }
         483          532603 :         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          314161 :     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          314062 :     if (y == 0) {
         498             144 :         vp->setInt32(1);
         499             144 :         return JS_TRUE;
         500                 :     }
         501                 :
         502          313918 :     if (vp[3].isInt32())
         503          300300 :         z = powi(x, vp[3].toInt32());
         504                 :     else
         505           13618 :         z = pow(x, y);
         506                 :
         507          313918 :     vp->setNumber(z);
         508          313918 :     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           18771 : random_setSeed(int64_t *rngSeed, int64_t seed)
         521                 : {
         522           18771 :     *rngSeed = (seed ^ RNG_MULTIPLIER) & RNG_MASK;
         523           18771 : }
         524                 :
         525                 : void
         526           18771 : 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           18771 :     random_setSeed(&cx->rngSeed, (PRMJ_Now() / 1000) ^ int64_t(cx) ^ int64_t(cx->link.next));
         535           18771 : }
         536                 :
         537                 : extern uint64_t
         538              36 : random_next(int64_t *rngSeed, int bits)
         539                 : {
         540              36 :     uint64_t nextseed = *rngSeed * RNG_MULTIPLIER;
         541              36 :     nextseed += RNG_ADDEND;
         542              36 :     nextseed &= RNG_MASK;
         543              36 :     *rngSeed = nextseed;
         544              36 :     return nextseed >> (48 - bits);
         545                 : }
         546                 :
         547                 : static inline double
         548              18 : random_nextDouble(JSContext *cx)
         549                 : {
         550              36 :     return double((random_next(&cx->rngSeed, 26) << 27) + random_next(&cx->rngSeed, 27)) /
         551              36 :            RNG_DSCALE;
         552                 : }
         553                 :
         554                 : static JSBool
         555              18 : math_random(JSContext *cx, unsigned argc, Value *vp)
         556                 : {
         557              18 :     double z = random_nextDouble(cx);
         558              18 :     vp->setDouble(z);
         559              18 :     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           11149 : js_math_round(JSContext *cx, unsigned argc, Value *vp)
         580                 : {
         581           11149 :     CallArgs args = CallArgsFromVp(argc, vp);
         582                 :
         583           11149 :     if (args.length() == 0) {
         584               0 :         args.rval().setDouble(js_NaN);
         585               0 :         return true;
         586                 :     }
         587                 :
         588                 :     double x;
         589           11149 :     if (!ToNumber(cx, args[0], &x))
         590               0 :         return false;
         591                 :
         592                 :     int32_t i;
         593           11149 :     if (JSDOUBLE_IS_INT32(x, &i)) {
         594             393 :         args.rval().setInt32(i);
         595             393 :         return true;
         596                 :     }
         597                 :
         598                 :     jsdpun u;
         599           10756 :     u.d = x;
         600                 :
         601                 :     /* Some numbers are so big that adding 0.5 would give the wrong number */
         602           10756 :     int exponent = ((u.s.hi & JSDOUBLE_HI32_EXPMASK) >> JSDOUBLE_HI32_EXPSHIFT) - JSDOUBLE_EXPBIAS;
         603           10756 :     if (exponent >= 52) {
         604              81 :         args.rval().setNumber(x);
         605              81 :         return true;
         606                 :     }
         607                 :
         608           10675 :     args.rval().setNumber(js_copysign(floor(x + 0.5), x));
         609           10675 :     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          284714 : js_math_sqrt(JSContext *cx, unsigned argc, Value *vp)
         633                 : {
         634                 :     double x, z;
         635                 :
         636          284714 :     if (argc == 0) {
         637               0 :         vp->setDouble(js_NaN);
         638               0 :         return JS_TRUE;
         639                 :     }
         640          284714 :     if (!ToNumber(cx, vp[2], &x))
         641               0 :         return JS_FALSE;
         642          284714 :     MathCache *mathCache = GetMathCache(cx);
         643          284714 :     if (!mathCache)
         644               0 :         return JS_FALSE;
         645          284714 :     z = mathCache->lookup(sqrt, x);
         646          284714 :     vp->setDouble(z);
         647          284714 :     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            1770 : js_InitMathClass(JSContext *cx, JSObject *obj)
         715                 : {
         716            1770 :     JSObject *Math = NewObjectWithClassProto(cx, &MathClass, NULL, obj);
         717            1770 :     if (!Math || !Math->setSingletonType(cx))
         718               0 :         return NULL;
         719                 :
         720            1770 :     if (!JS_DefineProperty(cx, obj, js_Math_str, OBJECT_TO_JSVAL(Math),
         721            1770 :                            JS_PropertyStub, JS_StrictPropertyStub, 0)) {
         722               0 :         return NULL;
         723                 :     }
         724                 :
         725            1770 :     if (!JS_DefineFunctions(cx, Math, math_static_methods))
         726               0 :         return NULL;
         727            1770 :     if (!JS_DefineConstDoubles(cx, Math, math_constants))
         728               0 :         return NULL;
         729                 :
         730            1770 :     MarkStandardClassInitializedNoProto(obj, &MathClass);
         731                 :
         732            1770 :     return Math;
         733                 : }

Generated by: LCOV version 1.7