Serenity Operating System
at hosted 182 lines 5.6 kB view raw
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 27#include <AK/FlyString.h> 28#include <AK/Function.h> 29#include <LibJS/Interpreter.h> 30#include <LibJS/Runtime/MathObject.h> 31#include <math.h> 32 33namespace JS { 34 35MathObject::MathObject() 36{ 37 put_native_function("abs", abs, 1); 38 put_native_function("random", random); 39 put_native_function("sqrt", sqrt, 1); 40 put_native_function("floor", floor, 1); 41 put_native_function("ceil", ceil, 1); 42 put_native_function("round", round, 1); 43 put_native_function("max", max, 2); 44 put_native_function("min", min, 2); 45 put_native_function("trunc", trunc, 1); 46 put_native_function("sin", sin, 1); 47 put_native_function("cos", cos, 1); 48 put_native_function("tan", tan, 1); 49 50 put("E", Value(M_E)); 51 put("LN2", Value(M_LN2)); 52 put("LN10", Value(M_LN10)); 53 put("LOG2E", Value(log2(M_E))); 54 put("LOG10E", Value(log10(M_E))); 55 put("PI", Value(M_PI)); 56 put("SQRT1_2", Value(::sqrt(1.0 / 2.0))); 57 put("SQRT2", Value(::sqrt(2))); 58} 59 60MathObject::~MathObject() 61{ 62} 63 64Value MathObject::abs(Interpreter& interpreter) 65{ 66 auto number = interpreter.argument(0).to_number(); 67 if (number.is_nan()) 68 return js_nan(); 69 return Value(number.as_double() >= 0 ? number.as_double() : -number.as_double()); 70} 71 72Value MathObject::random(Interpreter&) 73{ 74#ifdef __serenity__ 75 double r = (double)arc4random() / (double)UINT32_MAX; 76#else 77 double r = (double)rand() / (double)RAND_MAX; 78#endif 79 return Value(r); 80} 81 82Value MathObject::sqrt(Interpreter& interpreter) 83{ 84 auto number = interpreter.argument(0).to_number(); 85 if (number.is_nan()) 86 return js_nan(); 87 return Value(::sqrt(number.as_double())); 88} 89 90Value MathObject::floor(Interpreter& interpreter) 91{ 92 auto number = interpreter.argument(0).to_number(); 93 if (number.is_nan()) 94 return js_nan(); 95 return Value(::floor(number.as_double())); 96} 97 98Value MathObject::ceil(Interpreter& interpreter) 99{ 100 auto number = interpreter.argument(0).to_number(); 101 if (number.is_nan()) 102 return js_nan(); 103 return Value(::ceil(number.as_double())); 104} 105 106Value MathObject::round(Interpreter& interpreter) 107{ 108 auto number = interpreter.argument(0).to_number(); 109 if (number.is_nan()) 110 return js_nan(); 111 // FIXME: Use ::round() instead of ::roundf(). 112 return Value(::roundf(number.as_double())); 113} 114 115Value MathObject::max(Interpreter& interpreter) 116{ 117 if (!interpreter.argument_count()) { 118 return Value(-js_infinity().as_double()); 119 } else if (interpreter.argument_count() == 1) { 120 return interpreter.argument(0).to_number(); 121 } else { 122 Value max = interpreter.argument(0).to_number(); 123 for (size_t i = 1; i < interpreter.argument_count(); ++i) { 124 Value cur = interpreter.argument(i).to_number(); 125 max = Value(cur.as_double() > max.as_double() ? cur : max); 126 } 127 return max; 128 } 129} 130 131Value MathObject::min(Interpreter& interpreter) 132{ 133 if (!interpreter.argument_count()) 134 return js_infinity(); 135 136 if (interpreter.argument_count() == 1) 137 return interpreter.argument(0).to_number(); 138 139 Value min = interpreter.argument(0).to_number(); 140 for (size_t i = 1; i < interpreter.argument_count(); ++i) { 141 Value cur = interpreter.argument(i).to_number(); 142 min = Value(cur.as_double() < min.as_double() ? cur : min); 143 } 144 return min; 145} 146 147Value MathObject::trunc(Interpreter& interpreter) 148{ 149 auto number = interpreter.argument(0).to_number(); 150 if (number.is_nan()) 151 return js_nan(); 152 153 if (number.as_double() < 0) 154 return MathObject::ceil(interpreter); 155 return MathObject::floor(interpreter); 156} 157 158Value MathObject::sin(Interpreter& interpreter) 159{ 160 auto number = interpreter.argument(0).to_number(); 161 if (number.is_nan()) 162 return js_nan(); 163 return Value(::sin(number.as_double())); 164} 165 166Value MathObject::cos(Interpreter& interpreter) 167{ 168 auto number = interpreter.argument(0).to_number(); 169 if (number.is_nan()) 170 return js_nan(); 171 return Value(::cos(number.as_double())); 172} 173 174Value MathObject::tan(Interpreter& interpreter) 175{ 176 auto number = interpreter.argument(0).to_number(); 177 if (number.is_nan()) 178 return js_nan(); 179 return Value(::tan(number.as_double())); 180} 181 182}