PageRenderTime 52ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/js/lib/Socket.IO-node/support/expresso/deps/jscoverage/js/jsmath.cpp

http://github.com/onedayitwillmake/RealtimeMultiplayerNodeJs
C++ | 721 lines | 584 code | 74 blank | 63 comment | 122 complexity | 874c54a9f3986f5c33d8559d8bf47911 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, MPL-2.0-no-copyleft-exception, BSD-3-Clause
  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. * JS math package.
  41. */
  42. #include "jsstddef.h"
  43. #include "jslibmath.h"
  44. #include <stdlib.h>
  45. #include "jstypes.h"
  46. #include "jslong.h"
  47. #include "prmjtime.h"
  48. #include "jsapi.h"
  49. #include "jsatom.h"
  50. #include "jsbuiltins.h"
  51. #include "jscntxt.h"
  52. #include "jsversion.h"
  53. #include "jslock.h"
  54. #include "jsmath.h"
  55. #include "jsnum.h"
  56. #include "jsobj.h"
  57. extern jsdouble js_NaN;
  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. static JSConstDoubleSpec math_constants[] = {
  83. {M_E, "E", 0, {0,0,0}},
  84. {M_LOG2E, "LOG2E", 0, {0,0,0}},
  85. {M_LOG10E, "LOG10E", 0, {0,0,0}},
  86. {M_LN2, "LN2", 0, {0,0,0}},
  87. {M_LN10, "LN10", 0, {0,0,0}},
  88. {M_PI, "PI", 0, {0,0,0}},
  89. {M_SQRT2, "SQRT2", 0, {0,0,0}},
  90. {M_SQRT1_2, "SQRT1_2", 0, {0,0,0}},
  91. {0,0,0,{0,0,0}}
  92. };
  93. JSClass js_MathClass = {
  94. js_Math_str,
  95. JSCLASS_HAS_CACHED_PROTO(JSProto_Math),
  96. JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
  97. JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
  98. JSCLASS_NO_OPTIONAL_MEMBERS
  99. };
  100. static JSBool
  101. math_abs(JSContext *cx, uintN argc, jsval *vp)
  102. {
  103. jsdouble x, z;
  104. if (argc == 0) {
  105. *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
  106. return JS_TRUE;
  107. }
  108. x = js_ValueToNumber(cx, &vp[2]);
  109. if (JSVAL_IS_NULL(vp[2]))
  110. return JS_FALSE;
  111. z = fabs(x);
  112. return js_NewNumberInRootedValue(cx, z, vp);
  113. }
  114. static JSBool
  115. math_acos(JSContext *cx, uintN argc, jsval *vp)
  116. {
  117. jsdouble x, z;
  118. if (argc == 0) {
  119. *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
  120. return JS_TRUE;
  121. }
  122. x = js_ValueToNumber(cx, &vp[2]);
  123. if (JSVAL_IS_NULL(vp[2]))
  124. return JS_FALSE;
  125. #if defined(SOLARIS) && defined(__GNUC__)
  126. if (x < -1 || 1 < x) {
  127. *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
  128. return JS_TRUE;
  129. }
  130. #endif
  131. z = acos(x);
  132. return js_NewNumberInRootedValue(cx, z, vp);
  133. }
  134. static JSBool
  135. math_asin(JSContext *cx, uintN argc, jsval *vp)
  136. {
  137. jsdouble x, z;
  138. if (argc == 0) {
  139. *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
  140. return JS_TRUE;
  141. }
  142. x = js_ValueToNumber(cx, &vp[2]);
  143. if (JSVAL_IS_NULL(vp[2]))
  144. return JS_FALSE;
  145. #if defined(SOLARIS) && defined(__GNUC__)
  146. if (x < -1 || 1 < x) {
  147. *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
  148. return JS_TRUE;
  149. }
  150. #endif
  151. z = asin(x);
  152. return js_NewNumberInRootedValue(cx, z, vp);
  153. }
  154. static JSBool
  155. math_atan(JSContext *cx, uintN argc, jsval *vp)
  156. {
  157. jsdouble x, z;
  158. if (argc == 0) {
  159. *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
  160. return JS_TRUE;
  161. }
  162. x = js_ValueToNumber(cx, &vp[2]);
  163. if (JSVAL_IS_NULL(vp[2]))
  164. return JS_FALSE;
  165. z = atan(x);
  166. return js_NewNumberInRootedValue(cx, z, vp);
  167. }
  168. static JSBool
  169. math_atan2(JSContext *cx, uintN argc, jsval *vp)
  170. {
  171. jsdouble x, y, z;
  172. if (argc <= 1) {
  173. *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
  174. return JS_TRUE;
  175. }
  176. x = js_ValueToNumber(cx, &vp[2]);
  177. if (JSVAL_IS_NULL(vp[2]))
  178. return JS_FALSE;
  179. y = js_ValueToNumber(cx, &vp[3]);
  180. if (JSVAL_IS_NULL(vp[3]))
  181. return JS_FALSE;
  182. #if defined(_MSC_VER)
  183. /*
  184. * MSVC's atan2 does not yield the result demanded by ECMA when both x
  185. * and y are infinite.
  186. * - The result is a multiple of pi/4.
  187. * - The sign of x determines the sign of the result.
  188. * - The sign of y determines the multiplicator, 1 or 3.
  189. */
  190. if (JSDOUBLE_IS_INFINITE(x) && JSDOUBLE_IS_INFINITE(y)) {
  191. z = js_copysign(M_PI / 4, x);
  192. if (y < 0)
  193. z *= 3;
  194. return js_NewDoubleInRootedValue(cx, z, vp);
  195. }
  196. #endif
  197. #if defined(SOLARIS) && defined(__GNUC__)
  198. if (x == 0) {
  199. if (JSDOUBLE_IS_NEGZERO(y)) {
  200. z = js_copysign(M_PI, x);
  201. return js_NewDoubleInRootedValue(cx, z, vp);
  202. }
  203. if (y == 0) {
  204. z = x;
  205. return js_NewDoubleInRootedValue(cx, z, vp);
  206. }
  207. }
  208. #endif
  209. z = atan2(x, y);
  210. return js_NewNumberInRootedValue(cx, z, vp);
  211. }
  212. static JSBool
  213. math_ceil(JSContext *cx, uintN argc, jsval *vp)
  214. {
  215. jsdouble x, z;
  216. if (argc == 0) {
  217. *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
  218. return JS_TRUE;
  219. }
  220. x = js_ValueToNumber(cx, &vp[2]);
  221. if (JSVAL_IS_NULL(vp[2]))
  222. return JS_FALSE;
  223. z = ceil(x);
  224. return js_NewNumberInRootedValue(cx, z, vp);
  225. }
  226. static JSBool
  227. math_cos(JSContext *cx, uintN argc, jsval *vp)
  228. {
  229. jsdouble x, z;
  230. if (argc == 0) {
  231. *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
  232. return JS_TRUE;
  233. }
  234. x = js_ValueToNumber(cx, &vp[2]);
  235. if (JSVAL_IS_NULL(vp[2]))
  236. return JS_FALSE;
  237. z = cos(x);
  238. return js_NewNumberInRootedValue(cx, z, vp);
  239. }
  240. static JSBool
  241. math_exp(JSContext *cx, uintN argc, jsval *vp)
  242. {
  243. jsdouble x, z;
  244. if (argc == 0) {
  245. *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
  246. return JS_TRUE;
  247. }
  248. x = js_ValueToNumber(cx, &vp[2]);
  249. if (JSVAL_IS_NULL(vp[2]))
  250. return JS_FALSE;
  251. #ifdef _WIN32
  252. if (!JSDOUBLE_IS_NaN(x)) {
  253. if (x == *cx->runtime->jsPositiveInfinity) {
  254. *vp = DOUBLE_TO_JSVAL(cx->runtime->jsPositiveInfinity);
  255. return JS_TRUE;
  256. }
  257. if (x == *cx->runtime->jsNegativeInfinity) {
  258. *vp = JSVAL_ZERO;
  259. return JS_TRUE;
  260. }
  261. }
  262. #endif
  263. z = exp(x);
  264. return js_NewNumberInRootedValue(cx, z, vp);
  265. }
  266. static JSBool
  267. math_floor(JSContext *cx, uintN argc, jsval *vp)
  268. {
  269. jsdouble x, z;
  270. if (argc == 0) {
  271. *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
  272. return JS_TRUE;
  273. }
  274. x = js_ValueToNumber(cx, &vp[2]);
  275. if (JSVAL_IS_NULL(vp[2]))
  276. return JS_FALSE;
  277. z = floor(x);
  278. return js_NewNumberInRootedValue(cx, z, vp);
  279. }
  280. static JSBool
  281. math_log(JSContext *cx, uintN argc, jsval *vp)
  282. {
  283. jsdouble x, z;
  284. if (argc == 0) {
  285. *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
  286. return JS_TRUE;
  287. }
  288. x = js_ValueToNumber(cx, &vp[2]);
  289. if (JSVAL_IS_NULL(vp[2]))
  290. return JS_FALSE;
  291. #if defined(SOLARIS) && defined(__GNUC__)
  292. if (x < 0) {
  293. *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
  294. return JS_TRUE;
  295. }
  296. #endif
  297. z = log(x);
  298. return js_NewNumberInRootedValue(cx, z, vp);
  299. }
  300. static JSBool
  301. math_max(JSContext *cx, uintN argc, jsval *vp)
  302. {
  303. jsdouble x, z = *cx->runtime->jsNegativeInfinity;
  304. jsval *argv;
  305. uintN i;
  306. if (argc == 0) {
  307. *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNegativeInfinity);
  308. return JS_TRUE;
  309. }
  310. argv = vp + 2;
  311. for (i = 0; i < argc; i++) {
  312. x = js_ValueToNumber(cx, &argv[i]);
  313. if (JSVAL_IS_NULL(argv[i]))
  314. return JS_FALSE;
  315. if (JSDOUBLE_IS_NaN(x)) {
  316. *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
  317. return JS_TRUE;
  318. }
  319. if (x == 0 && x == z) {
  320. if (js_copysign(1.0, z) == -1)
  321. z = x;
  322. } else {
  323. z = (x > z) ? x : z;
  324. }
  325. }
  326. return js_NewNumberInRootedValue(cx, z, vp);
  327. }
  328. static JSBool
  329. math_min(JSContext *cx, uintN argc, jsval *vp)
  330. {
  331. jsdouble x, z = *cx->runtime->jsPositiveInfinity;
  332. jsval *argv;
  333. uintN i;
  334. if (argc == 0) {
  335. *vp = DOUBLE_TO_JSVAL(cx->runtime->jsPositiveInfinity);
  336. return JS_TRUE;
  337. }
  338. argv = vp + 2;
  339. for (i = 0; i < argc; i++) {
  340. x = js_ValueToNumber(cx, &argv[i]);
  341. if (JSVAL_IS_NULL(argv[i]))
  342. return JS_FALSE;
  343. if (JSDOUBLE_IS_NaN(x)) {
  344. *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
  345. return JS_TRUE;
  346. }
  347. if (x == 0 && x == z) {
  348. if (js_copysign(1.0, x) == -1)
  349. z = x;
  350. } else {
  351. z = (x < z) ? x : z;
  352. }
  353. }
  354. return js_NewNumberInRootedValue(cx, z, vp);
  355. }
  356. static JSBool
  357. math_pow(JSContext *cx, uintN argc, jsval *vp)
  358. {
  359. jsdouble x, y, z;
  360. if (argc <= 1) {
  361. *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
  362. return JS_TRUE;
  363. }
  364. x = js_ValueToNumber(cx, &vp[2]);
  365. if (JSVAL_IS_NULL(vp[2]))
  366. return JS_FALSE;
  367. y = js_ValueToNumber(cx, &vp[3]);
  368. if (JSVAL_IS_NULL(vp[3]))
  369. return JS_FALSE;
  370. /*
  371. * Because C99 and ECMA specify different behavior for pow(),
  372. * we need to wrap the libm call to make it ECMA compliant.
  373. */
  374. if (!JSDOUBLE_IS_FINITE(y) && (x == 1.0 || x == -1.0)) {
  375. *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
  376. return JS_TRUE;
  377. }
  378. /* pow(x, +-0) is always 1, even for x = NaN. */
  379. if (y == 0) {
  380. *vp = JSVAL_ONE;
  381. return JS_TRUE;
  382. }
  383. z = pow(x, y);
  384. return js_NewNumberInRootedValue(cx, z, vp);
  385. }
  386. /*
  387. * Math.random() support, lifted from java.util.Random.java.
  388. */
  389. static void
  390. random_setSeed(JSRuntime *rt, int64 seed)
  391. {
  392. int64 tmp;
  393. JSLL_I2L(tmp, 1000);
  394. JSLL_DIV(seed, seed, tmp);
  395. JSLL_XOR(tmp, seed, rt->rngMultiplier);
  396. JSLL_AND(rt->rngSeed, tmp, rt->rngMask);
  397. }
  398. void
  399. js_random_init(JSRuntime *rt)
  400. {
  401. int64 tmp, tmp2;
  402. /* Do at most once. */
  403. if (rt->rngInitialized)
  404. return;
  405. rt->rngInitialized = JS_TRUE;
  406. /* rt->rngMultiplier = 0x5DEECE66DL */
  407. JSLL_ISHL(tmp, 0x5, 32);
  408. JSLL_UI2L(tmp2, 0xDEECE66DL);
  409. JSLL_OR(rt->rngMultiplier, tmp, tmp2);
  410. /* rt->rngAddend = 0xBL */
  411. JSLL_I2L(rt->rngAddend, 0xBL);
  412. /* rt->rngMask = (1L << 48) - 1 */
  413. JSLL_I2L(tmp, 1);
  414. JSLL_SHL(tmp2, tmp, 48);
  415. JSLL_SUB(rt->rngMask, tmp2, tmp);
  416. /* rt->rngDscale = (jsdouble)(1L << 53) */
  417. JSLL_SHL(tmp2, tmp, 53);
  418. JSLL_L2D(rt->rngDscale, tmp2);
  419. /* Finally, set the seed from current time. */
  420. random_setSeed(rt, PRMJ_Now());
  421. }
  422. static uint32
  423. random_next(JSRuntime *rt, int bits)
  424. {
  425. int64 nextseed, tmp;
  426. uint32 retval;
  427. JSLL_MUL(nextseed, rt->rngSeed, rt->rngMultiplier);
  428. JSLL_ADD(nextseed, nextseed, rt->rngAddend);
  429. JSLL_AND(nextseed, nextseed, rt->rngMask);
  430. rt->rngSeed = nextseed;
  431. JSLL_USHR(tmp, nextseed, 48 - bits);
  432. JSLL_L2I(retval, tmp);
  433. return retval;
  434. }
  435. jsdouble
  436. js_random_nextDouble(JSRuntime *rt)
  437. {
  438. int64 tmp, tmp2;
  439. jsdouble d;
  440. JSLL_ISHL(tmp, random_next(rt, 26), 27);
  441. JSLL_UI2L(tmp2, random_next(rt, 27));
  442. JSLL_ADD(tmp, tmp, tmp2);
  443. JSLL_L2D(d, tmp);
  444. return d / rt->rngDscale;
  445. }
  446. static JSBool
  447. math_random(JSContext *cx, uintN argc, jsval *vp)
  448. {
  449. JSRuntime *rt;
  450. jsdouble z;
  451. rt = cx->runtime;
  452. JS_LOCK_RUNTIME(rt);
  453. js_random_init(rt);
  454. z = js_random_nextDouble(rt);
  455. JS_UNLOCK_RUNTIME(rt);
  456. return js_NewNumberInRootedValue(cx, z, vp);
  457. }
  458. #if defined _WIN32 && !defined WINCE && _MSC_VER < 1400
  459. /* Try to work around apparent _copysign bustage in VC6 and VC7. */
  460. double
  461. js_copysign(double x, double y)
  462. {
  463. jsdpun xu, yu;
  464. xu.d = x;
  465. yu.d = y;
  466. xu.s.hi &= ~JSDOUBLE_HI32_SIGNBIT;
  467. xu.s.hi |= yu.s.hi & JSDOUBLE_HI32_SIGNBIT;
  468. return xu.d;
  469. }
  470. #endif
  471. static JSBool
  472. math_round(JSContext *cx, uintN argc, jsval *vp)
  473. {
  474. jsdouble x, z;
  475. if (argc == 0) {
  476. *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
  477. return JS_TRUE;
  478. }
  479. x = js_ValueToNumber(cx, &vp[2]);
  480. if (JSVAL_IS_NULL(vp[2]))
  481. return JS_FALSE;
  482. z = js_copysign(floor(x + 0.5), x);
  483. return js_NewNumberInRootedValue(cx, z, vp);
  484. }
  485. static JSBool
  486. math_sin(JSContext *cx, uintN argc, jsval *vp)
  487. {
  488. jsdouble x, z;
  489. if (argc == 0) {
  490. *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
  491. return JS_TRUE;
  492. }
  493. x = js_ValueToNumber(cx, &vp[2]);
  494. if (JSVAL_IS_NULL(vp[2]))
  495. return JS_FALSE;
  496. z = sin(x);
  497. return js_NewNumberInRootedValue(cx, z, vp);
  498. }
  499. static JSBool
  500. math_sqrt(JSContext *cx, uintN argc, jsval *vp)
  501. {
  502. jsdouble x, z;
  503. if (argc == 0) {
  504. *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
  505. return JS_TRUE;
  506. }
  507. x = js_ValueToNumber(cx, &vp[2]);
  508. if (JSVAL_IS_NULL(vp[2]))
  509. return JS_FALSE;
  510. z = sqrt(x);
  511. return js_NewNumberInRootedValue(cx, z, vp);
  512. }
  513. static JSBool
  514. math_tan(JSContext *cx, uintN argc, jsval *vp)
  515. {
  516. jsdouble x, z;
  517. if (argc == 0) {
  518. *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
  519. return JS_TRUE;
  520. }
  521. x = js_ValueToNumber(cx, &vp[2]);
  522. if (JSVAL_IS_NULL(vp[2]))
  523. return JS_FALSE;
  524. z = tan(x);
  525. return js_NewNumberInRootedValue(cx, z, vp);
  526. }
  527. #if JS_HAS_TOSOURCE
  528. static JSBool
  529. math_toSource(JSContext *cx, uintN argc, jsval *vp)
  530. {
  531. *vp = ATOM_KEY(CLASS_ATOM(cx, Math));
  532. return JS_TRUE;
  533. }
  534. #endif
  535. #ifdef JS_TRACER
  536. #define MATH_BUILTIN_1(name) \
  537. static jsdouble FASTCALL math_##name##_tn(jsdouble d) { return name(d); } \
  538. JS_DEFINE_TRCINFO_1(math_##name, \
  539. (1, (static, DOUBLE, math_##name##_tn, DOUBLE, 1, 1)))
  540. MATH_BUILTIN_1(sin)
  541. MATH_BUILTIN_1(cos)
  542. MATH_BUILTIN_1(sqrt)
  543. MATH_BUILTIN_1(floor)
  544. MATH_BUILTIN_1(ceil)
  545. static jsdouble FASTCALL
  546. math_abs_tn(jsdouble d)
  547. {
  548. return fabs(d);
  549. }
  550. static jsdouble FASTCALL
  551. math_log_tn(jsdouble d)
  552. {
  553. #if defined(SOLARIS) && defined(__GNUC__)
  554. if (d < 0)
  555. return js_NaN;
  556. #endif
  557. return log(d);
  558. }
  559. static jsdouble FASTCALL
  560. math_max_tn(jsdouble d, jsdouble p)
  561. {
  562. if (JSDOUBLE_IS_NaN(d) || JSDOUBLE_IS_NaN(p))
  563. return js_NaN;
  564. if (p == 0 && p == d) {
  565. if (js_copysign(1.0, d) == -1)
  566. return p;
  567. return d;
  568. }
  569. return (p > d) ? p : d;
  570. }
  571. static jsdouble FASTCALL
  572. math_pow_tn(jsdouble d, jsdouble p)
  573. {
  574. if (!JSDOUBLE_IS_FINITE(p) && (d == 1.0 || d == -1.0))
  575. return js_NaN;
  576. if (p == 0)
  577. return 1.0;
  578. return pow(d, p);
  579. }
  580. static jsdouble FASTCALL
  581. math_random_tn(JSRuntime* rt)
  582. {
  583. JS_LOCK_RUNTIME(rt);
  584. js_random_init(rt);
  585. jsdouble z = js_random_nextDouble(rt);
  586. JS_UNLOCK_RUNTIME(rt);
  587. return z;
  588. }
  589. static jsdouble FASTCALL
  590. math_round_tn(jsdouble x)
  591. {
  592. return js_copysign(floor(x + 0.5), x);
  593. }
  594. JS_DEFINE_TRCINFO_1(math_abs,
  595. (1, (static, DOUBLE, math_abs_tn, DOUBLE, 1, 1)))
  596. JS_DEFINE_TRCINFO_1(math_log,
  597. (1, (static, DOUBLE, math_log_tn, DOUBLE, 1, 1)))
  598. JS_DEFINE_TRCINFO_1(math_max,
  599. (2, (static, DOUBLE, math_max_tn, DOUBLE, DOUBLE, 1, 1)))
  600. JS_DEFINE_TRCINFO_1(math_pow,
  601. (2, (static, DOUBLE, math_pow_tn, DOUBLE, DOUBLE, 1, 1)))
  602. JS_DEFINE_TRCINFO_1(math_random,
  603. (1, (static, DOUBLE, math_random_tn, RUNTIME, 0, 0)))
  604. JS_DEFINE_TRCINFO_1(math_round,
  605. (1, (static, DOUBLE, math_round_tn, DOUBLE, 1, 1)))
  606. #endif /* JS_TRACER */
  607. static JSFunctionSpec math_static_methods[] = {
  608. #if JS_HAS_TOSOURCE
  609. JS_FN(js_toSource_str, math_toSource, 0, 0),
  610. #endif
  611. JS_TN("abs", math_abs, 1, 0, math_abs_trcinfo),
  612. JS_FN("acos", math_acos, 1, 0),
  613. JS_FN("asin", math_asin, 1, 0),
  614. JS_FN("atan", math_atan, 1, 0),
  615. JS_FN("atan2", math_atan2, 2, 0),
  616. JS_TN("ceil", math_ceil, 1, 0, math_ceil_trcinfo),
  617. JS_TN("cos", math_cos, 1, 0, math_cos_trcinfo),
  618. JS_FN("exp", math_exp, 1, 0),
  619. JS_TN("floor", math_floor, 1, 0, math_floor_trcinfo),
  620. JS_TN("log", math_log, 1, 0, math_log_trcinfo),
  621. JS_TN("max", math_max, 2, 0, math_max_trcinfo),
  622. JS_FN("min", math_min, 2, 0),
  623. JS_TN("pow", math_pow, 2, 0, math_pow_trcinfo),
  624. JS_TN("random", math_random, 0, 0, math_random_trcinfo),
  625. JS_TN("round", math_round, 1, 0, math_round_trcinfo),
  626. JS_TN("sin", math_sin, 1, 0, math_sin_trcinfo),
  627. JS_TN("sqrt", math_sqrt, 1, 0, math_sqrt_trcinfo),
  628. JS_FN("tan", math_tan, 1, 0),
  629. JS_FS_END
  630. };
  631. JSObject *
  632. js_InitMathClass(JSContext *cx, JSObject *obj)
  633. {
  634. JSObject *Math;
  635. Math = JS_NewObject(cx, &js_MathClass, NULL, obj);
  636. if (!Math)
  637. return NULL;
  638. if (!JS_DefineProperty(cx, obj, js_Math_str, OBJECT_TO_JSVAL(Math),
  639. JS_PropertyStub, JS_PropertyStub,
  640. JSPROP_READONLY | JSPROP_PERMANENT))
  641. return NULL;
  642. if (!JS_DefineFunctions(cx, Math, math_static_methods))
  643. return NULL;
  644. if (!JS_DefineConstDoubles(cx, Math, math_constants))
  645. return NULL;
  646. return Math;
  647. }