home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / js / src / jsmath.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  9.4 KB  |  399 lines

  1. /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. /*
  20.  * JS math package.
  21.  */
  22. #include <math.h>
  23. #include <stdlib.h>
  24. #include "prtypes.h"
  25. #include "prlong.h"
  26. #include "prmjtime.h"
  27. #include "jsapi.h"
  28. #include "jsatom.h"
  29. #include "jscntxt.h"
  30. #include "jsmath.h"
  31. #include "jsnum.h"
  32. #include "jsobj.h"
  33.  
  34. #ifndef M_E
  35. #define M_E        2.7182818284590452354
  36. #endif
  37. #ifndef M_LOG2E
  38. #define M_LOG2E        1.4426950408889634074
  39. #endif
  40. #ifndef M_LOG10E
  41. #define M_LOG10E    0.43429448190325182765
  42. #endif
  43. #ifndef M_LN2
  44. #define M_LN2        0.69314718055994530942
  45. #endif
  46. #ifndef M_LN10
  47. #define M_LN10        2.30258509299404568402
  48. #endif
  49. #ifndef M_PI
  50. #define M_PI        3.14159265358979323846
  51. #endif
  52. #ifndef M_SQRT2
  53. #define M_SQRT2        1.41421356237309504880
  54. #endif
  55. #ifndef M_SQRT1_2
  56. #define M_SQRT1_2    0.70710678118654752440
  57. #endif
  58.  
  59. static JSConstDoubleSpec math_constants[] = {
  60.     {M_E,       "E"},
  61.     {M_LOG2E,   "LOG2E"},
  62.     {M_LOG10E,  "LOG10E"},
  63.     {M_LN2,     "LN2"},
  64.     {M_LN10,    "LN10"},
  65.     {M_PI,      "PI"},
  66.     {M_SQRT2,   "SQRT2"},
  67.     {M_SQRT1_2, "SQRT1_2"},
  68.     {0}
  69. };
  70.  
  71. static JSClass math_class = {
  72.     "Math",
  73.     0,
  74.     JS_PropertyStub,  JS_PropertyStub,  JS_PropertyStub,  JS_PropertyStub,
  75.     JS_EnumerateStub, JS_ResolveStub,   JS_ConvertStub,   JS_FinalizeStub
  76. };
  77.  
  78. static JSBool
  79. math_abs(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
  80. {
  81.     jsdouble x, z;
  82.  
  83.     if (!JS_ValueToNumber(cx, argv[0], &x))
  84.     return JS_FALSE;
  85.     z = (x < 0) ? -x : x;
  86.     return js_NewNumberValue(cx, z, rval);
  87. }
  88.  
  89. static JSBool
  90. math_acos(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
  91. {
  92.     jsdouble x, z;
  93.  
  94.     if (!JS_ValueToNumber(cx, argv[0], &x))
  95.     return JS_FALSE;
  96.     z = acos(x);
  97.     return js_NewNumberValue(cx, z, rval);
  98. }
  99.  
  100. static JSBool
  101. math_asin(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
  102. {
  103.     jsdouble x, z;
  104.  
  105.     if (!JS_ValueToNumber(cx, argv[0], &x))
  106.     return JS_FALSE;
  107.     z = asin(x);
  108.     return js_NewNumberValue(cx, z, rval);
  109. }
  110.  
  111. static JSBool
  112. math_atan(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
  113. {
  114.     jsdouble x, z;
  115.  
  116.     if (!JS_ValueToNumber(cx, argv[0], &x))
  117.     return JS_FALSE;
  118.     z = atan(x);
  119.     return js_NewNumberValue(cx, z, rval);
  120. }
  121.  
  122. static JSBool
  123. math_atan2(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
  124. {
  125.     jsdouble x, y, z;
  126.  
  127.     if (!JS_ValueToNumber(cx, argv[0], &x))
  128.     return JS_FALSE;
  129.     if (!JS_ValueToNumber(cx, argv[1], &y))
  130.     return JS_FALSE;
  131.     z = atan2(x, y);
  132.     return js_NewNumberValue(cx, z, rval);
  133. }
  134.  
  135. static JSBool
  136. math_ceil(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
  137. {
  138.     jsdouble x, z;
  139.  
  140.     if (!JS_ValueToNumber(cx, argv[0], &x))
  141.     return JS_FALSE;
  142.     z = ceil(x);
  143.     return js_NewNumberValue(cx, z, rval);
  144. }
  145.  
  146. static JSBool
  147. math_cos(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
  148. {
  149.     jsdouble x, z;
  150.  
  151.     if (!JS_ValueToNumber(cx, argv[0], &x))
  152.     return JS_FALSE;
  153.     z = cos(x);
  154.     return js_NewNumberValue(cx, z, rval);
  155. }
  156.  
  157. static JSBool
  158. math_exp(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
  159. {
  160.     jsdouble x, z;
  161.  
  162.     if (!JS_ValueToNumber(cx, argv[0], &x))
  163.     return JS_FALSE;
  164.     z = exp(x);
  165.     return js_NewNumberValue(cx, z, rval);
  166. }
  167.  
  168. static JSBool
  169. math_floor(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 = floor(x);
  176.     return js_NewNumberValue(cx, z, rval);
  177. }
  178.  
  179. static JSBool
  180. math_log(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 = log(x);
  187.     return js_NewNumberValue(cx, z, rval);
  188. }
  189.  
  190. static JSBool
  191. math_max(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
  192. {
  193.     jsdouble x, y, z;
  194.  
  195.     if (!JS_ValueToNumber(cx, argv[0], &x))
  196.     return JS_FALSE;
  197.     if (!JS_ValueToNumber(cx, argv[1], &y))
  198.     return JS_FALSE;
  199.     z = (x > y) ? x : y;
  200.     return js_NewNumberValue(cx, z, rval);
  201. }
  202.  
  203. static JSBool
  204. math_min(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
  205. {
  206.     jsdouble x, y, z;
  207.  
  208.     if (!JS_ValueToNumber(cx, argv[0], &x))
  209.     return JS_FALSE;
  210.     if (!JS_ValueToNumber(cx, argv[1], &y))
  211.     return JS_FALSE;
  212.     z = (x < y) ? x : y;
  213.     return js_NewNumberValue(cx, z, rval);
  214. }
  215.  
  216. static JSBool
  217. math_pow(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
  218. {
  219.     jsdouble x, y, z;
  220.  
  221.     if (!JS_ValueToNumber(cx, argv[0], &x))
  222.     return JS_FALSE;
  223.     if (!JS_ValueToNumber(cx, argv[1], &y))
  224.     return JS_FALSE;
  225.     z = pow(x, y);
  226.     return js_NewNumberValue(cx, z, rval);
  227. }
  228.  
  229. /*
  230.  * Math.random() support, lifted from java.util.Random.java.
  231.  */
  232. static void
  233. random_setSeed(JSRuntime *rt, int64 seed)
  234. {
  235.     int64 tmp;
  236.  
  237.     LL_I2L(tmp, 1000);
  238.     LL_DIV(seed, seed, tmp);
  239.     LL_XOR(tmp, seed, rt->rngMultiplier);
  240.     LL_AND(rt->rngSeed, tmp, rt->rngMask);
  241. }
  242.  
  243. static void
  244. random_init(JSRuntime *rt)
  245. {
  246.     int64 tmp, tmp2;
  247.  
  248.     /* Do at most once. */
  249.     if (rt->rngInitialized)
  250.     return;
  251.     rt->rngInitialized = JS_TRUE;
  252.  
  253.     /* rt->rngMultiplier = 0x5DEECE66DL */
  254.     LL_ISHL(tmp, 0x5D, 32);
  255.     LL_UI2L(tmp2, 0xEECE66DL);
  256.     LL_OR(rt->rngMultiplier, tmp, tmp2);
  257.  
  258.     /* rt->rngAddend = 0xBL */
  259.     LL_I2L(rt->rngAddend, 0xBL);
  260.  
  261.     /* rt->rngMask = (1L << 48) - 1 */
  262.     LL_I2L(tmp, 1);
  263.     LL_SHL(tmp2, tmp, 48);
  264.     LL_SUB(rt->rngMask, tmp2, tmp);
  265.  
  266.     /* rt->rngDscale = (jsdouble)(1L << 54) */
  267.     LL_SHL(tmp2, tmp, 54);
  268.     LL_L2D(rt->rngDscale, tmp2);
  269.  
  270.     /* Finally, set the seed from current time. */
  271.     random_setSeed(rt, PRMJ_Now());
  272. }
  273.  
  274. static uint32
  275. random_next(JSRuntime *rt, int bits)
  276. {
  277.     int64 nextseed, tmp;
  278.     uint32 retval;
  279.  
  280.     LL_MUL(nextseed, rt->rngSeed, rt->rngMultiplier);
  281.     LL_ADD(nextseed, nextseed, rt->rngAddend);
  282.     LL_AND(nextseed, nextseed, rt->rngMask);
  283.     rt->rngSeed = nextseed;
  284.     LL_USHR(tmp, nextseed, 48 - bits);
  285.     LL_L2I(retval, tmp);
  286.     return retval;
  287. }
  288.  
  289. static jsdouble
  290. random_nextDouble(JSRuntime *rt)
  291. {
  292.     int64 tmp, tmp2;
  293.     jsdouble d;
  294.  
  295.     LL_ISHL(tmp, random_next(rt, 27), 27);
  296.     LL_UI2L(tmp2, random_next(rt, 27));
  297.     LL_ADD(tmp, tmp, tmp2);
  298.     LL_L2D(d, tmp);
  299.     return d / rt->rngDscale;
  300. }
  301.  
  302. static JSBool
  303. math_random(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
  304. {
  305.     JSRuntime *rt;
  306.     jsdouble z;
  307.  
  308.     rt = cx->runtime;
  309.     random_init(rt);
  310.     z = random_nextDouble(rt);
  311.     return js_NewNumberValue(cx, z, rval);
  312. }
  313.  
  314. static JSBool
  315. math_round(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
  316. {
  317.     jsdouble x, z;
  318.  
  319.     if (!JS_ValueToNumber(cx, argv[0], &x))
  320.     return JS_FALSE;
  321.     z = floor(x + 0.5);
  322.     return js_NewNumberValue(cx, z, rval);
  323. }
  324.  
  325. static JSBool
  326. math_sin(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
  327. {
  328.     jsdouble x, z;
  329.  
  330.     if (!JS_ValueToNumber(cx, argv[0], &x))
  331.     return JS_FALSE;
  332.     z = sin(x);
  333.     return js_NewNumberValue(cx, z, rval);
  334. }
  335.  
  336. static JSBool
  337. math_sqrt(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
  338. {
  339.     jsdouble x, z;
  340.  
  341.     if (!JS_ValueToNumber(cx, argv[0], &x))
  342.     return JS_FALSE;
  343.     z = sqrt(x);
  344.     return js_NewNumberValue(cx, z, rval);
  345. }
  346.  
  347. static JSBool
  348. math_tan(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
  349. {
  350.     jsdouble x, z;
  351.  
  352.     if (!JS_ValueToNumber(cx, argv[0], &x))
  353.     return JS_FALSE;
  354.     z = tan(x);
  355.     return js_NewNumberValue(cx, z, rval);
  356. }
  357.  
  358. static JSFunctionSpec math_static_methods[] = {
  359.     {"abs",        math_abs,        1},
  360.     {"acos",        math_acos,        1},
  361.     {"asin",        math_asin,        1},
  362.     {"atan",        math_atan,        1},
  363.     {"atan2",        math_atan2,        2},
  364.     {"ceil",        math_ceil,        1},
  365.     {"cos",        math_cos,        1},
  366.     {"exp",        math_exp,        1},
  367.     {"floor",        math_floor,        1},
  368.     {"log",        math_log,        1},
  369.     {"max",        math_max,        2},
  370.     {"min",        math_min,        2},
  371.     {"pow",        math_pow,        2},
  372.     {"random",        math_random,        0},
  373.     {"round",        math_round,        1},
  374.     {"sin",        math_sin,        1},
  375.     {"sqrt",        math_sqrt,        1},
  376.     {"tan",        math_tan,        1},
  377.     {0}
  378. };
  379.  
  380. static JSBool
  381. Math(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
  382. {
  383.     return JS_TRUE;
  384. }
  385.  
  386. JSObject *
  387. js_InitMathClass(JSContext *cx, JSObject *obj)
  388. {
  389.     JSObject *proto, *ctor;
  390.  
  391.     proto = JS_InitClass(cx, obj, NULL, &math_class, Math, 0,
  392.                  NULL, NULL, NULL, math_static_methods);
  393.     if (!proto || !(ctor = JS_GetConstructor(cx, proto)))
  394.     return NULL;
  395.     if (!JS_DefineConstDoubles(cx, ctor, math_constants))
  396.     return NULL;
  397.     return proto;
  398. }
  399.