MathObject.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637
  1. /*
  2. * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
  3. * Copyright (c) 2020, Linus Groh <linusg@serenityos.org>
  4. * Copyright (c) 2021, Idan Horowitz <idan.horowitz@serenityos.org>
  5. *
  6. * SPDX-License-Identifier: BSD-2-Clause
  7. */
  8. #include <AK/Function.h>
  9. #include <AK/Random.h>
  10. #include <LibJS/Runtime/GlobalObject.h>
  11. #include <LibJS/Runtime/MathObject.h>
  12. #include <math.h>
  13. namespace JS {
  14. MathObject::MathObject(GlobalObject& global_object)
  15. : Object(*global_object.object_prototype())
  16. {
  17. }
  18. void MathObject::initialize(GlobalObject& global_object)
  19. {
  20. auto& vm = this->vm();
  21. Object::initialize(global_object);
  22. u8 attr = Attribute::Writable | Attribute::Configurable;
  23. define_native_function(vm.names.abs, abs, 1, attr);
  24. define_native_function(vm.names.random, random, 0, attr);
  25. define_native_function(vm.names.sqrt, sqrt, 1, attr);
  26. define_native_function(vm.names.floor, floor, 1, attr);
  27. define_native_function(vm.names.ceil, ceil, 1, attr);
  28. define_native_function(vm.names.round, round, 1, attr);
  29. define_native_function(vm.names.max, max, 2, attr);
  30. define_native_function(vm.names.min, min, 2, attr);
  31. define_native_function(vm.names.trunc, trunc, 1, attr);
  32. define_native_function(vm.names.sin, sin, 1, attr);
  33. define_native_function(vm.names.cos, cos, 1, attr);
  34. define_native_function(vm.names.tan, tan, 1, attr);
  35. define_native_function(vm.names.pow, pow, 2, attr);
  36. define_native_function(vm.names.exp, exp, 1, attr);
  37. define_native_function(vm.names.expm1, expm1, 1, attr);
  38. define_native_function(vm.names.sign, sign, 1, attr);
  39. define_native_function(vm.names.clz32, clz32, 1, attr);
  40. define_native_function(vm.names.acos, acos, 1, attr);
  41. define_native_function(vm.names.acosh, acosh, 1, attr);
  42. define_native_function(vm.names.asin, asin, 1, attr);
  43. define_native_function(vm.names.asinh, asinh, 1, attr);
  44. define_native_function(vm.names.atan, atan, 1, attr);
  45. define_native_function(vm.names.atanh, atanh, 1, attr);
  46. define_native_function(vm.names.log1p, log1p, 1, attr);
  47. define_native_function(vm.names.cbrt, cbrt, 1, attr);
  48. define_native_function(vm.names.atan2, atan2, 2, attr);
  49. define_native_function(vm.names.fround, fround, 1, attr);
  50. define_native_function(vm.names.hypot, hypot, 2, attr);
  51. define_native_function(vm.names.imul, imul, 2, attr);
  52. define_native_function(vm.names.log, log, 1, attr);
  53. define_native_function(vm.names.log2, log2, 1, attr);
  54. define_native_function(vm.names.log10, log10, 1, attr);
  55. define_native_function(vm.names.sinh, sinh, 1, attr);
  56. define_native_function(vm.names.cosh, cosh, 1, attr);
  57. define_native_function(vm.names.tanh, tanh, 1, attr);
  58. // 21.3.1 Value Properties of the Math Object, https://tc39.es/ecma262/#sec-value-properties-of-the-math-object
  59. define_property(vm.names.E, Value(M_E), 0);
  60. define_property(vm.names.LN2, Value(M_LN2), 0);
  61. define_property(vm.names.LN10, Value(M_LN10), 0);
  62. define_property(vm.names.LOG2E, Value(::log2(M_E)), 0);
  63. define_property(vm.names.LOG10E, Value(::log10(M_E)), 0);
  64. define_property(vm.names.PI, Value(M_PI), 0);
  65. define_property(vm.names.SQRT1_2, Value(M_SQRT1_2), 0);
  66. define_property(vm.names.SQRT2, Value(M_SQRT2), 0);
  67. // 21.3.1.9 Math [ @@toStringTag ], https://tc39.es/ecma262/#sec-math-@@tostringtag
  68. define_property(vm.well_known_symbol_to_string_tag(), js_string(vm.heap(), vm.names.Math.as_string()), Attribute::Configurable);
  69. }
  70. MathObject::~MathObject()
  71. {
  72. }
  73. // 21.3.2.1 Math.abs ( x ), https://tc39.es/ecma262/#sec-math.abs
  74. JS_DEFINE_NATIVE_FUNCTION(MathObject::abs)
  75. {
  76. auto number = vm.argument(0).to_number(global_object);
  77. if (vm.exception())
  78. return {};
  79. if (number.is_nan())
  80. return js_nan();
  81. if (number.is_negative_zero())
  82. return Value(0);
  83. if (number.is_negative_infinity())
  84. return js_infinity();
  85. return Value(number.as_double() < 0 ? -number.as_double() : number.as_double());
  86. }
  87. // 21.3.2.27 Math.random ( ), https://tc39.es/ecma262/#sec-math.random
  88. JS_DEFINE_NATIVE_FUNCTION(MathObject::random)
  89. {
  90. #ifdef __serenity__
  91. double r = (double)get_random<u32>() / (double)UINT32_MAX;
  92. #else
  93. double r = (double)rand() / (double)RAND_MAX;
  94. #endif
  95. return Value(r);
  96. }
  97. // 21.3.2.32 Math.sqrt ( x ), https://tc39.es/ecma262/#sec-math.sqrt
  98. JS_DEFINE_NATIVE_FUNCTION(MathObject::sqrt)
  99. {
  100. auto number = vm.argument(0).to_number(global_object);
  101. if (vm.exception())
  102. return {};
  103. if (number.is_nan())
  104. return js_nan();
  105. return Value(::sqrt(number.as_double()));
  106. }
  107. // 21.3.2.16 Math.floor ( x ), https://tc39.es/ecma262/#sec-math.floor
  108. JS_DEFINE_NATIVE_FUNCTION(MathObject::floor)
  109. {
  110. auto number = vm.argument(0).to_number(global_object);
  111. if (vm.exception())
  112. return {};
  113. if (number.is_nan())
  114. return js_nan();
  115. return Value(::floor(number.as_double()));
  116. }
  117. // 21.3.2.10 Math.ceil ( x ), https://tc39.es/ecma262/#sec-math.ceil
  118. JS_DEFINE_NATIVE_FUNCTION(MathObject::ceil)
  119. {
  120. auto number = vm.argument(0).to_number(global_object);
  121. if (vm.exception())
  122. return {};
  123. if (number.is_nan())
  124. return js_nan();
  125. auto number_double = number.as_double();
  126. if (number_double < 0 && number_double > -1)
  127. return Value(-0.f);
  128. return Value(::ceil(number.as_double()));
  129. }
  130. // 21.3.2.28 Math.round ( x ), https://tc39.es/ecma262/#sec-math.round
  131. JS_DEFINE_NATIVE_FUNCTION(MathObject::round)
  132. {
  133. auto number = vm.argument(0).to_number(global_object);
  134. if (vm.exception())
  135. return {};
  136. if (number.is_nan())
  137. return js_nan();
  138. double intpart = 0;
  139. double frac = modf(number.as_double(), &intpart);
  140. if (intpart >= 0) {
  141. if (frac >= 0.5)
  142. intpart += 1.0;
  143. } else {
  144. if (frac < -0.5)
  145. intpart -= 1.0;
  146. }
  147. return Value(intpart);
  148. }
  149. // 21.3.2.24 Math.max ( ...args ), https://tc39.es/ecma262/#sec-math.max
  150. JS_DEFINE_NATIVE_FUNCTION(MathObject::max)
  151. {
  152. Vector<Value> coerced;
  153. for (size_t i = 0; i < vm.argument_count(); ++i) {
  154. auto number = vm.argument(i).to_number(global_object);
  155. if (vm.exception())
  156. return {};
  157. coerced.append(number);
  158. }
  159. auto highest = js_negative_infinity();
  160. for (auto& number : coerced) {
  161. if (number.is_nan())
  162. return js_nan();
  163. if ((number.is_positive_zero() && highest.is_negative_zero()) || number.as_double() > highest.as_double())
  164. highest = number;
  165. }
  166. return highest;
  167. }
  168. // 21.3.2.25 Math.min ( ...args ), https://tc39.es/ecma262/#sec-math.min
  169. JS_DEFINE_NATIVE_FUNCTION(MathObject::min)
  170. {
  171. Vector<Value> coerced;
  172. for (size_t i = 0; i < vm.argument_count(); ++i) {
  173. auto number = vm.argument(i).to_number(global_object);
  174. if (vm.exception())
  175. return {};
  176. coerced.append(number);
  177. }
  178. auto lowest = js_infinity();
  179. for (auto& number : coerced) {
  180. if (number.is_nan())
  181. return js_nan();
  182. if ((number.is_negative_zero() && lowest.is_positive_zero()) || number.as_double() < lowest.as_double())
  183. lowest = number;
  184. }
  185. return lowest;
  186. }
  187. // 21.3.2.35 Math.trunc ( x ), https://tc39.es/ecma262/#sec-math.trunc
  188. JS_DEFINE_NATIVE_FUNCTION(MathObject::trunc)
  189. {
  190. auto number = vm.argument(0).to_number(global_object);
  191. if (vm.exception())
  192. return {};
  193. if (number.is_nan())
  194. return js_nan();
  195. if (number.as_double() < 0)
  196. return MathObject::ceil(vm, global_object);
  197. return MathObject::floor(vm, global_object);
  198. }
  199. // 21.3.2.30 Math.sin ( x ), https://tc39.es/ecma262/#sec-math.sin
  200. JS_DEFINE_NATIVE_FUNCTION(MathObject::sin)
  201. {
  202. auto number = vm.argument(0).to_number(global_object);
  203. if (vm.exception())
  204. return {};
  205. if (number.is_nan())
  206. return js_nan();
  207. return Value(::sin(number.as_double()));
  208. }
  209. // 21.3.2.12 Math.cos ( x ), https://tc39.es/ecma262/#sec-math.cos
  210. JS_DEFINE_NATIVE_FUNCTION(MathObject::cos)
  211. {
  212. auto number = vm.argument(0).to_number(global_object);
  213. if (vm.exception())
  214. return {};
  215. if (number.is_nan())
  216. return js_nan();
  217. return Value(::cos(number.as_double()));
  218. }
  219. // 21.3.2.33 Math.tan ( x ), https://tc39.es/ecma262/#sec-math.tan
  220. JS_DEFINE_NATIVE_FUNCTION(MathObject::tan)
  221. {
  222. auto number = vm.argument(0).to_number(global_object);
  223. if (vm.exception())
  224. return {};
  225. if (number.is_nan())
  226. return js_nan();
  227. return Value(::tan(number.as_double()));
  228. }
  229. // 21.3.2.26 Math.pow ( base, exponent ), https://tc39.es/ecma262/#sec-math.pow
  230. JS_DEFINE_NATIVE_FUNCTION(MathObject::pow)
  231. {
  232. auto base = vm.argument(0).to_number(global_object);
  233. if (vm.exception())
  234. return {};
  235. auto exponent = vm.argument(1).to_number(global_object);
  236. if (vm.exception())
  237. return {};
  238. if (exponent.is_nan())
  239. return js_nan();
  240. if (exponent.is_positive_zero() || exponent.is_negative_zero())
  241. return Value(1);
  242. if (base.is_nan())
  243. return js_nan();
  244. if (base.is_positive_infinity())
  245. return exponent.as_double() > 0 ? js_infinity() : Value(0);
  246. if (base.is_negative_infinity()) {
  247. auto is_odd_integral_number = exponent.is_integral_number() && (exponent.as_i32() % 2 != 0);
  248. if (exponent.as_double() > 0)
  249. return is_odd_integral_number ? js_negative_infinity() : js_infinity();
  250. else
  251. return is_odd_integral_number ? Value(-0.0) : Value(0);
  252. }
  253. if (base.is_positive_zero())
  254. return exponent.as_double() > 0 ? Value(0) : js_infinity();
  255. if (base.is_negative_zero()) {
  256. auto is_odd_integral_number = exponent.is_integral_number() && (exponent.as_i32() % 2 != 0);
  257. if (exponent.as_double() > 0)
  258. return is_odd_integral_number ? Value(-0.0) : Value(0);
  259. else
  260. return is_odd_integral_number ? js_negative_infinity() : js_infinity();
  261. }
  262. VERIFY(base.is_finite_number() && !base.is_positive_zero() && !base.is_negative_zero());
  263. if (exponent.is_positive_infinity()) {
  264. auto absolute_base = fabs(base.as_double());
  265. if (absolute_base > 1)
  266. return js_infinity();
  267. else if (absolute_base == 1)
  268. return js_nan();
  269. else if (absolute_base < 1)
  270. return Value(0);
  271. }
  272. if (exponent.is_negative_infinity()) {
  273. auto absolute_base = fabs(base.as_double());
  274. if (absolute_base > 1)
  275. return Value(0);
  276. else if (absolute_base == 1)
  277. return js_nan();
  278. else if (absolute_base < 1)
  279. return js_infinity();
  280. }
  281. VERIFY(exponent.is_finite_number() && !exponent.is_positive_zero() && !exponent.is_negative_zero());
  282. if (base.as_double() < 0 && !exponent.is_integral_number())
  283. return js_nan();
  284. return Value(::pow(base.as_double(), exponent.as_double()));
  285. }
  286. // 21.3.2.14 Math.exp ( x ), https://tc39.es/ecma262/#sec-math.exp
  287. JS_DEFINE_NATIVE_FUNCTION(MathObject::exp)
  288. {
  289. auto number = vm.argument(0).to_number(global_object);
  290. if (vm.exception())
  291. return {};
  292. if (number.is_nan())
  293. return js_nan();
  294. return Value(::exp(number.as_double()));
  295. }
  296. // 21.3.2.15 Math.expm1 ( x ), https://tc39.es/ecma262/#sec-math.expm1
  297. JS_DEFINE_NATIVE_FUNCTION(MathObject::expm1)
  298. {
  299. auto number = vm.argument(0).to_number(global_object);
  300. if (vm.exception())
  301. return {};
  302. if (number.is_nan())
  303. return js_nan();
  304. return Value(::expm1(number.as_double()));
  305. }
  306. // 21.3.2.29 Math.sign ( x ), https://tc39.es/ecma262/#sec-math.sign
  307. JS_DEFINE_NATIVE_FUNCTION(MathObject::sign)
  308. {
  309. auto number = vm.argument(0).to_number(global_object);
  310. if (vm.exception())
  311. return {};
  312. if (number.is_positive_zero())
  313. return Value(0);
  314. if (number.is_negative_zero())
  315. return Value(-0.0);
  316. if (number.as_double() > 0)
  317. return Value(1);
  318. if (number.as_double() < 0)
  319. return Value(-1);
  320. return js_nan();
  321. }
  322. // 21.3.2.11 Math.clz32 ( x ), https://tc39.es/ecma262/#sec-math.clz32
  323. JS_DEFINE_NATIVE_FUNCTION(MathObject::clz32)
  324. {
  325. auto number = vm.argument(0).to_number(global_object);
  326. if (vm.exception())
  327. return {};
  328. if (!number.is_finite_number() || (unsigned)number.as_double() == 0)
  329. return Value(32);
  330. return Value(__builtin_clz((unsigned)number.as_double()));
  331. }
  332. // 21.3.2.2 Math.acos ( x ), https://tc39.es/ecma262/#sec-math.acos
  333. JS_DEFINE_NATIVE_FUNCTION(MathObject::acos)
  334. {
  335. auto number = vm.argument(0).to_number(global_object);
  336. if (vm.exception())
  337. return {};
  338. if (number.is_nan() || number.as_double() > 1 || number.as_double() < -1)
  339. return js_nan();
  340. if (number.as_double() == 1)
  341. return Value(0);
  342. return Value(::acos(number.as_double()));
  343. }
  344. // 21.3.2.3 Math.acosh ( x ), https://tc39.es/ecma262/#sec-math.acosh
  345. JS_DEFINE_NATIVE_FUNCTION(MathObject::acosh)
  346. {
  347. auto number = vm.argument(0).to_number(global_object);
  348. if (vm.exception())
  349. return {};
  350. if (number.as_double() < 1)
  351. return js_nan();
  352. return Value(::acosh(number.as_double()));
  353. }
  354. // 21.3.2.4 Math.asin ( x ), https://tc39.es/ecma262/#sec-math.asin
  355. JS_DEFINE_NATIVE_FUNCTION(MathObject::asin)
  356. {
  357. auto number = vm.argument(0).to_number(global_object);
  358. if (vm.exception())
  359. return {};
  360. if (number.is_nan() || number.is_positive_zero() || number.is_negative_zero())
  361. return number;
  362. return Value(::asin(number.as_double()));
  363. }
  364. // 21.3.2.5 Math.asinh ( x ), https://tc39.es/ecma262/#sec-math.asinh
  365. JS_DEFINE_NATIVE_FUNCTION(MathObject::asinh)
  366. {
  367. auto number = vm.argument(0).to_number(global_object);
  368. if (vm.exception())
  369. return {};
  370. return Value(::asinh(number.as_double()));
  371. }
  372. // 21.3.2.6 Math.atan ( x ), https://tc39.es/ecma262/#sec-math.atan
  373. JS_DEFINE_NATIVE_FUNCTION(MathObject::atan)
  374. {
  375. auto number = vm.argument(0).to_number(global_object);
  376. if (vm.exception())
  377. return {};
  378. if (number.is_nan() || number.is_positive_zero() || number.is_negative_zero())
  379. return number;
  380. if (number.is_positive_infinity())
  381. return Value(M_PI_2);
  382. if (number.is_negative_infinity())
  383. return Value(-M_PI_2);
  384. return Value(::atan(number.as_double()));
  385. }
  386. // 21.3.2.7 Math.atanh ( x ), https://tc39.es/ecma262/#sec-math.atanh
  387. JS_DEFINE_NATIVE_FUNCTION(MathObject::atanh)
  388. {
  389. auto number = vm.argument(0).to_number(global_object);
  390. if (vm.exception())
  391. return {};
  392. if (number.as_double() > 1 || number.as_double() < -1)
  393. return js_nan();
  394. return Value(::atanh(number.as_double()));
  395. }
  396. // 21.3.2.21 Math.log1p ( x ), https://tc39.es/ecma262/#sec-math.log1p
  397. JS_DEFINE_NATIVE_FUNCTION(MathObject::log1p)
  398. {
  399. auto number = vm.argument(0).to_number(global_object);
  400. if (vm.exception())
  401. return {};
  402. if (number.as_double() < -1)
  403. return js_nan();
  404. return Value(::log1p(number.as_double()));
  405. }
  406. // 21.3.2.9 Math.cbrt ( x ), https://tc39.es/ecma262/#sec-math.cbrt
  407. JS_DEFINE_NATIVE_FUNCTION(MathObject::cbrt)
  408. {
  409. auto number = vm.argument(0).to_number(global_object);
  410. if (vm.exception())
  411. return {};
  412. return Value(::cbrt(number.as_double()));
  413. }
  414. // 21.3.2.8 Math.atan2 ( y, x ), https://tc39.es/ecma262/#sec-math.atan2
  415. JS_DEFINE_NATIVE_FUNCTION(MathObject::atan2)
  416. {
  417. auto constexpr three_quarters_pi = M_PI_4 + M_PI_2;
  418. auto y = vm.argument(0).to_number(global_object);
  419. if (vm.exception())
  420. return {};
  421. auto x = vm.argument(1).to_number(global_object);
  422. if (vm.exception())
  423. return {};
  424. if (y.is_nan() || x.is_nan())
  425. return js_nan();
  426. if (y.is_positive_infinity()) {
  427. if (x.is_positive_infinity())
  428. return Value(M_PI_4);
  429. else if (x.is_negative_infinity())
  430. return Value(three_quarters_pi);
  431. else
  432. return Value(M_PI_2);
  433. }
  434. if (y.is_negative_infinity()) {
  435. if (x.is_positive_infinity())
  436. return Value(-M_PI_4);
  437. else if (x.is_negative_infinity())
  438. return Value(-three_quarters_pi);
  439. else
  440. return Value(-M_PI_2);
  441. }
  442. if (y.is_positive_zero()) {
  443. if (x.as_double() > 0 || x.is_positive_zero())
  444. return Value(0.0);
  445. else
  446. return Value(M_PI);
  447. }
  448. if (y.is_negative_zero()) {
  449. if (x.as_double() > 0 || x.is_positive_zero())
  450. return Value(-0.0);
  451. else
  452. return Value(-M_PI);
  453. }
  454. VERIFY(y.is_finite_number() && !y.is_positive_zero() && !y.is_negative_zero());
  455. if (y.as_double() > 0) {
  456. if (x.is_positive_infinity())
  457. return Value(0);
  458. else if (x.is_negative_infinity())
  459. return Value(M_PI);
  460. else if (x.is_positive_zero() || x.is_negative_zero())
  461. return Value(M_PI_2);
  462. }
  463. if (y.as_double() < 0) {
  464. if (x.is_positive_infinity())
  465. return Value(-0.0);
  466. else if (x.is_negative_infinity())
  467. return Value(-M_PI);
  468. else if (x.is_positive_zero() || x.is_negative_zero())
  469. return Value(-M_PI_2);
  470. }
  471. VERIFY(x.is_finite_number() && !x.is_positive_zero() && !x.is_negative_zero());
  472. return Value(::atan2(y.as_double(), x.as_double()));
  473. }
  474. // 21.3.2.17 Math.fround ( x ), https://tc39.es/ecma262/#sec-math.fround
  475. JS_DEFINE_NATIVE_FUNCTION(MathObject::fround)
  476. {
  477. auto number = vm.argument(0).to_number(global_object);
  478. if (vm.exception())
  479. return {};
  480. if (number.is_nan())
  481. return js_nan();
  482. return Value((float)number.as_double());
  483. }
  484. // 21.3.2.18 Math.hypot ( ...args ), https://tc39.es/ecma262/#sec-math.hypot
  485. JS_DEFINE_NATIVE_FUNCTION(MathObject::hypot)
  486. {
  487. Vector<Value> coerced;
  488. for (size_t i = 0; i < vm.argument_count(); ++i) {
  489. auto number = vm.argument(i).to_number(global_object);
  490. if (vm.exception())
  491. return {};
  492. coerced.append(number);
  493. }
  494. for (auto& number : coerced) {
  495. if (number.is_positive_infinity() || number.is_negative_infinity())
  496. return js_infinity();
  497. }
  498. auto only_zero = true;
  499. double sum_of_squares = 0;
  500. for (auto& number : coerced) {
  501. if (number.is_nan() || number.is_positive_infinity())
  502. return number;
  503. if (number.is_negative_infinity())
  504. return js_infinity();
  505. if (!number.is_positive_zero() && !number.is_negative_zero())
  506. only_zero = false;
  507. sum_of_squares += number.as_double() * number.as_double();
  508. }
  509. if (only_zero)
  510. return Value(0);
  511. return Value(::sqrt(sum_of_squares));
  512. }
  513. // 21.3.2.19 Math.imul ( x, y ), https://tc39.es/ecma262/#sec-math.imul
  514. JS_DEFINE_NATIVE_FUNCTION(MathObject::imul)
  515. {
  516. auto a = vm.argument(0).to_u32(global_object);
  517. if (vm.exception())
  518. return {};
  519. auto b = vm.argument(1).to_u32(global_object);
  520. if (vm.exception())
  521. return {};
  522. return Value(static_cast<i32>(a * b));
  523. }
  524. // 21.3.2.20 Math.log ( x ), https://tc39.es/ecma262/#sec-math.log
  525. JS_DEFINE_NATIVE_FUNCTION(MathObject::log)
  526. {
  527. auto number = vm.argument(0).to_number(global_object);
  528. if (vm.exception())
  529. return {};
  530. if (number.as_double() < 0)
  531. return js_nan();
  532. return Value(::log(number.as_double()));
  533. }
  534. // 21.3.2.23 Math.log2 ( x ), https://tc39.es/ecma262/#sec-math.log2
  535. JS_DEFINE_NATIVE_FUNCTION(MathObject::log2)
  536. {
  537. auto number = vm.argument(0).to_number(global_object);
  538. if (vm.exception())
  539. return {};
  540. if (number.as_double() < 0)
  541. return js_nan();
  542. return Value(::log2(number.as_double()));
  543. }
  544. // 21.3.2.22 Math.log10 ( x ), https://tc39.es/ecma262/#sec-math.log10
  545. JS_DEFINE_NATIVE_FUNCTION(MathObject::log10)
  546. {
  547. auto number = vm.argument(0).to_number(global_object);
  548. if (vm.exception())
  549. return {};
  550. if (number.as_double() < 0)
  551. return js_nan();
  552. return Value(::log10(number.as_double()));
  553. }
  554. // 21.3.2.31 Math.sinh ( x ), https://tc39.es/ecma262/#sec-math.sinh
  555. JS_DEFINE_NATIVE_FUNCTION(MathObject::sinh)
  556. {
  557. auto number = vm.argument(0).to_number(global_object);
  558. if (vm.exception())
  559. return {};
  560. if (number.is_nan())
  561. return js_nan();
  562. return Value(::sinh(number.as_double()));
  563. }
  564. // 21.3.2.13 Math.cosh ( x ), https://tc39.es/ecma262/#sec-math.cosh
  565. JS_DEFINE_NATIVE_FUNCTION(MathObject::cosh)
  566. {
  567. auto number = vm.argument(0).to_number(global_object);
  568. if (vm.exception())
  569. return {};
  570. if (number.is_nan())
  571. return js_nan();
  572. return Value(::cosh(number.as_double()));
  573. }
  574. // 21.3.2.34 Math.tanh ( x ), https://tc39.es/ecma262/#sec-math.tanh
  575. JS_DEFINE_NATIVE_FUNCTION(MathObject::tanh)
  576. {
  577. auto number = vm.argument(0).to_number(global_object);
  578. if (vm.exception())
  579. return {};
  580. if (number.is_nan())
  581. return js_nan();
  582. if (number.is_positive_infinity())
  583. return Value(1);
  584. if (number.is_negative_infinity())
  585. return Value(-1);
  586. return Value(::tanh(number.as_double()));
  587. }
  588. }