MathObject.cpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. /*
  2. * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright notice, this
  9. * list of conditions and the following disclaimer.
  10. *
  11. * 2. Redistributions in binary form must reproduce the above copyright notice,
  12. * this list of conditions and the following disclaimer in the documentation
  13. * and/or other materials provided with the distribution.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  16. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  18. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  19. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  20. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  21. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  22. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  23. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  24. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. */
  26. #include <AK/FlyString.h>
  27. #include <AK/Function.h>
  28. #include <LibJS/Interpreter.h>
  29. #include <LibJS/Runtime/GlobalObject.h>
  30. #include <LibJS/Runtime/MathObject.h>
  31. #include <math.h>
  32. namespace JS {
  33. MathObject::MathObject()
  34. : Object(interpreter().global_object().object_prototype())
  35. {
  36. u8 attr = Attribute::Writable | Attribute::Configurable;
  37. put_native_function("abs", abs, 1, attr);
  38. put_native_function("random", random, 0, attr);
  39. put_native_function("sqrt", sqrt, 1, attr);
  40. put_native_function("floor", floor, 1, attr);
  41. put_native_function("ceil", ceil, 1, attr);
  42. put_native_function("round", round, 1, attr);
  43. put_native_function("max", max, 2, attr);
  44. put_native_function("min", min, 2, attr);
  45. put_native_function("trunc", trunc, 1, attr);
  46. put_native_function("sin", sin, 1, attr);
  47. put_native_function("cos", cos, 1, attr);
  48. put_native_function("tan", tan, 1, attr);
  49. put_native_function("pow", pow, 2, attr);
  50. put_native_function("exp", exp, 1, attr);
  51. put_native_function("sign", sign, 1, attr);
  52. put("E", Value(M_E), 0);
  53. put("LN2", Value(M_LN2), 0);
  54. put("LN10", Value(M_LN10), 0);
  55. put("LOG2E", Value(log2(M_E)), 0);
  56. put("LOG10E", Value(log10(M_E)), 0);
  57. put("PI", Value(M_PI), 0);
  58. put("SQRT1_2", Value(::sqrt(1.0 / 2.0)), 0);
  59. put("SQRT2", Value(::sqrt(2)), 0);
  60. }
  61. MathObject::~MathObject()
  62. {
  63. }
  64. Value MathObject::abs(Interpreter& interpreter)
  65. {
  66. auto number = interpreter.argument(0).to_number(interpreter);
  67. if (interpreter.exception())
  68. return {};
  69. if (number.is_nan())
  70. return js_nan();
  71. return Value(number.as_double() >= 0 ? number.as_double() : -number.as_double());
  72. }
  73. Value MathObject::random(Interpreter&)
  74. {
  75. #ifdef __serenity__
  76. double r = (double)arc4random() / (double)UINT32_MAX;
  77. #else
  78. double r = (double)rand() / (double)RAND_MAX;
  79. #endif
  80. return Value(r);
  81. }
  82. Value MathObject::sqrt(Interpreter& interpreter)
  83. {
  84. auto number = interpreter.argument(0).to_number(interpreter);
  85. if (interpreter.exception())
  86. return {};
  87. if (number.is_nan())
  88. return js_nan();
  89. return Value(::sqrt(number.as_double()));
  90. }
  91. Value MathObject::floor(Interpreter& interpreter)
  92. {
  93. auto number = interpreter.argument(0).to_number(interpreter);
  94. if (interpreter.exception())
  95. return {};
  96. if (number.is_nan())
  97. return js_nan();
  98. return Value(::floor(number.as_double()));
  99. }
  100. Value MathObject::ceil(Interpreter& interpreter)
  101. {
  102. auto number = interpreter.argument(0).to_number(interpreter);
  103. if (interpreter.exception())
  104. return {};
  105. if (number.is_nan())
  106. return js_nan();
  107. return Value(::ceil(number.as_double()));
  108. }
  109. Value MathObject::round(Interpreter& interpreter)
  110. {
  111. auto number = interpreter.argument(0).to_number(interpreter);
  112. if (interpreter.exception())
  113. return {};
  114. if (number.is_nan())
  115. return js_nan();
  116. return Value(::round(number.as_double()));
  117. }
  118. Value MathObject::max(Interpreter& interpreter)
  119. {
  120. if (!interpreter.argument_count())
  121. return js_negative_infinity();
  122. auto max = interpreter.argument(0).to_number(interpreter);
  123. if (interpreter.exception())
  124. return {};
  125. for (size_t i = 1; i < interpreter.argument_count(); ++i) {
  126. auto cur = interpreter.argument(i).to_number(interpreter);
  127. if (interpreter.exception())
  128. return {};
  129. max = Value(cur.as_double() > max.as_double() ? cur : max);
  130. }
  131. return max;
  132. }
  133. Value MathObject::min(Interpreter& interpreter)
  134. {
  135. if (!interpreter.argument_count())
  136. return js_infinity();
  137. auto min = interpreter.argument(0).to_number(interpreter);
  138. if (interpreter.exception())
  139. return {};
  140. for (size_t i = 1; i < interpreter.argument_count(); ++i) {
  141. auto cur = interpreter.argument(i).to_number(interpreter);
  142. if (interpreter.exception())
  143. return {};
  144. min = Value(cur.as_double() < min.as_double() ? cur : min);
  145. }
  146. return min;
  147. }
  148. Value MathObject::trunc(Interpreter& interpreter)
  149. {
  150. auto number = interpreter.argument(0).to_number(interpreter);
  151. if (interpreter.exception())
  152. return {};
  153. if (number.is_nan())
  154. return js_nan();
  155. if (number.as_double() < 0)
  156. return MathObject::ceil(interpreter);
  157. return MathObject::floor(interpreter);
  158. }
  159. Value MathObject::sin(Interpreter& interpreter)
  160. {
  161. auto number = interpreter.argument(0).to_number(interpreter);
  162. if (interpreter.exception())
  163. return {};
  164. if (number.is_nan())
  165. return js_nan();
  166. return Value(::sin(number.as_double()));
  167. }
  168. Value MathObject::cos(Interpreter& interpreter)
  169. {
  170. auto number = interpreter.argument(0).to_number(interpreter);
  171. if (interpreter.exception())
  172. return {};
  173. if (number.is_nan())
  174. return js_nan();
  175. return Value(::cos(number.as_double()));
  176. }
  177. Value MathObject::tan(Interpreter& interpreter)
  178. {
  179. auto number = interpreter.argument(0).to_number(interpreter);
  180. if (interpreter.exception())
  181. return {};
  182. if (number.is_nan())
  183. return js_nan();
  184. return Value(::tan(number.as_double()));
  185. }
  186. Value MathObject::pow(Interpreter& interpreter)
  187. {
  188. return JS::exp(interpreter, interpreter.argument(0), interpreter.argument(1));
  189. }
  190. Value MathObject::exp(Interpreter& interpreter)
  191. {
  192. auto number = interpreter.argument(0).to_number(interpreter);
  193. if (interpreter.exception())
  194. return {};
  195. if (number.is_nan())
  196. return js_nan();
  197. return Value(::pow(M_E, number.as_double()));
  198. }
  199. Value MathObject::sign(Interpreter& interpreter)
  200. {
  201. auto number = interpreter.argument(0).to_number(interpreter);
  202. if (interpreter.exception())
  203. return {};
  204. if (number.is_positive_zero())
  205. return Value(0);
  206. if (number.is_negative_zero())
  207. return Value(-0.0);
  208. if (number.as_double() > 0)
  209. return Value(1);
  210. if (number.as_double() < 0)
  211. return Value(-1);
  212. return js_nan();
  213. }
  214. }