14514f5e3Sopenharmony_ci/* 24514f5e3Sopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd. 34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License. 54514f5e3Sopenharmony_ci * You may obtain a copy of the License at 64514f5e3Sopenharmony_ci * 74514f5e3Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 84514f5e3Sopenharmony_ci * 94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and 134514f5e3Sopenharmony_ci * limitations under the License. 144514f5e3Sopenharmony_ci */ 154514f5e3Sopenharmony_ci 164514f5e3Sopenharmony_ci#include "ecmascript/builtins/builtins_math.h" 174514f5e3Sopenharmony_ci#include <random> 184514f5e3Sopenharmony_ci#include <sys/time.h> 194514f5e3Sopenharmony_ci#include "ecmascript/js_tagged_value-inl.h" 204514f5e3Sopenharmony_ci 214514f5e3Sopenharmony_cinamespace panda::ecmascript::builtins { 224514f5e3Sopenharmony_ciusing NumberHelper = base::NumberHelper; 234514f5e3Sopenharmony_ciusing RandomGenerator = base::RandomGenerator; 244514f5e3Sopenharmony_ci 254514f5e3Sopenharmony_ci// 20.2.2.1 264514f5e3Sopenharmony_ciJSTaggedValue BuiltinsMath::Abs(EcmaRuntimeCallInfo *argv) 274514f5e3Sopenharmony_ci{ 284514f5e3Sopenharmony_ci ASSERT(argv); 294514f5e3Sopenharmony_ci BUILTINS_API_TRACE(argv->GetThread(), Math, Abs); 304514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 314514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 324514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> msg = GetCallArg(argv, 0); 334514f5e3Sopenharmony_ci JSTaggedNumber numberValue = JSTaggedValue::ToNumber(thread, msg); 344514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 354514f5e3Sopenharmony_ci if (numberValue.IsDouble()) { 364514f5e3Sopenharmony_ci // if number_value is double,NaN,Undefine, deal in this case 374514f5e3Sopenharmony_ci // if number_value is a String ,which can change to double. e.g."100",deal in this case 384514f5e3Sopenharmony_ci return GetTaggedDouble(std::fabs(numberValue.GetDouble())); 394514f5e3Sopenharmony_ci } 404514f5e3Sopenharmony_ci // if number_value is int,boolean,null, deal in this case 414514f5e3Sopenharmony_ci int value = numberValue.GetInt(); 424514f5e3Sopenharmony_ci if (value == INT_MIN) { 434514f5e3Sopenharmony_ci return GetTaggedDouble(-static_cast<int64_t>(INT_MIN)); 444514f5e3Sopenharmony_ci } 454514f5e3Sopenharmony_ci return GetTaggedInt(std::abs(value)); 464514f5e3Sopenharmony_ci} 474514f5e3Sopenharmony_ci 484514f5e3Sopenharmony_ci// 20.2.2.2 494514f5e3Sopenharmony_ciJSTaggedValue BuiltinsMath::Acos(EcmaRuntimeCallInfo *argv) 504514f5e3Sopenharmony_ci{ 514514f5e3Sopenharmony_ci ASSERT(argv); 524514f5e3Sopenharmony_ci BUILTINS_API_TRACE(argv->GetThread(), Math, Acos); 534514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 544514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 554514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> msg = GetCallArg(argv, 0); 564514f5e3Sopenharmony_ci JSTaggedNumber numberValue = JSTaggedValue::ToNumber(thread, msg); 574514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 584514f5e3Sopenharmony_ci double value = numberValue.GetNumber(); 594514f5e3Sopenharmony_ci double result = base::NAN_VALUE; 604514f5e3Sopenharmony_ci // value == -NaN , <-1 or > 1,result is NaN 614514f5e3Sopenharmony_ci if (!std::isnan(std::abs(value)) && value <= 1 && value >= -1) { 624514f5e3Sopenharmony_ci result = std::acos(value); 634514f5e3Sopenharmony_ci } 644514f5e3Sopenharmony_ci return GetTaggedDouble(result); 654514f5e3Sopenharmony_ci} 664514f5e3Sopenharmony_ci 674514f5e3Sopenharmony_ci// 20.2.2.3 684514f5e3Sopenharmony_ciJSTaggedValue BuiltinsMath::Acosh(EcmaRuntimeCallInfo *argv) 694514f5e3Sopenharmony_ci{ 704514f5e3Sopenharmony_ci ASSERT(argv); 714514f5e3Sopenharmony_ci BUILTINS_API_TRACE(argv->GetThread(), Math, Acosh); 724514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 734514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 744514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> msg = GetCallArg(argv, 0); 754514f5e3Sopenharmony_ci JSTaggedNumber numberValue = JSTaggedValue::ToNumber(thread, msg); 764514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 774514f5e3Sopenharmony_ci double value = numberValue.GetNumber(); 784514f5e3Sopenharmony_ci double result = base::NAN_VALUE; 794514f5e3Sopenharmony_ci if (value >= 1) { 804514f5e3Sopenharmony_ci result = std::acosh(value); 814514f5e3Sopenharmony_ci } 824514f5e3Sopenharmony_ci return GetTaggedDouble(result); 834514f5e3Sopenharmony_ci} 844514f5e3Sopenharmony_ci 854514f5e3Sopenharmony_ci// 20.2.2.4 864514f5e3Sopenharmony_ciJSTaggedValue BuiltinsMath::Asin(EcmaRuntimeCallInfo *argv) 874514f5e3Sopenharmony_ci{ 884514f5e3Sopenharmony_ci ASSERT(argv); 894514f5e3Sopenharmony_ci BUILTINS_API_TRACE(argv->GetThread(), Math, Asin); 904514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 914514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 924514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> msg = GetCallArg(argv, 0); 934514f5e3Sopenharmony_ci JSTaggedNumber numberValue = JSTaggedValue::ToNumber(thread, msg); 944514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 954514f5e3Sopenharmony_ci double value = numberValue.GetNumber(); 964514f5e3Sopenharmony_ci double result = base::NAN_VALUE; 974514f5e3Sopenharmony_ci if (value >= -1 && value <= 1) { 984514f5e3Sopenharmony_ci result = std::asin(value); 994514f5e3Sopenharmony_ci } 1004514f5e3Sopenharmony_ci return GetTaggedDouble(result); 1014514f5e3Sopenharmony_ci} 1024514f5e3Sopenharmony_ci 1034514f5e3Sopenharmony_ci// 20.2.2.5 1044514f5e3Sopenharmony_ciJSTaggedValue BuiltinsMath::Asinh(EcmaRuntimeCallInfo *argv) 1054514f5e3Sopenharmony_ci{ 1064514f5e3Sopenharmony_ci ASSERT(argv); 1074514f5e3Sopenharmony_ci BUILTINS_API_TRACE(argv->GetThread(), Math, Asinh); 1084514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 1094514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 1104514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> msg = GetCallArg(argv, 0); 1114514f5e3Sopenharmony_ci JSTaggedNumber numberValue = JSTaggedValue::ToNumber(thread, msg); 1124514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1134514f5e3Sopenharmony_ci double value = numberValue.GetNumber(); 1144514f5e3Sopenharmony_ci double result = base::NAN_VALUE; 1154514f5e3Sopenharmony_ci // value == -NaN, NaN, result is NaN 1164514f5e3Sopenharmony_ci if (!std::isnan(std::abs(value))) { 1174514f5e3Sopenharmony_ci result = base::MathHelper::Asinh(value); 1184514f5e3Sopenharmony_ci } 1194514f5e3Sopenharmony_ci return GetTaggedDouble(result); 1204514f5e3Sopenharmony_ci} 1214514f5e3Sopenharmony_ci 1224514f5e3Sopenharmony_ci// 20.2.2.6 1234514f5e3Sopenharmony_ciJSTaggedValue BuiltinsMath::Atan(EcmaRuntimeCallInfo *argv) 1244514f5e3Sopenharmony_ci{ 1254514f5e3Sopenharmony_ci ASSERT(argv); 1264514f5e3Sopenharmony_ci BUILTINS_API_TRACE(argv->GetThread(), Math, Atan); 1274514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 1284514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 1294514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> msg = GetCallArg(argv, 0); 1304514f5e3Sopenharmony_ci JSTaggedNumber numberValue = JSTaggedValue::ToNumber(thread, msg); 1314514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1324514f5e3Sopenharmony_ci double value = numberValue.GetNumber(); 1334514f5e3Sopenharmony_ci double result = base::NAN_VALUE; 1344514f5e3Sopenharmony_ci // value == -NaN, NaN, result is NaN 1354514f5e3Sopenharmony_ci if (!std::isnan(std::abs(value))) { 1364514f5e3Sopenharmony_ci result = std::atan(value); 1374514f5e3Sopenharmony_ci } 1384514f5e3Sopenharmony_ci return GetTaggedDouble(result); 1394514f5e3Sopenharmony_ci} 1404514f5e3Sopenharmony_ci 1414514f5e3Sopenharmony_ci// 20.2.2.7 1424514f5e3Sopenharmony_ciJSTaggedValue BuiltinsMath::Atanh(EcmaRuntimeCallInfo *argv) 1434514f5e3Sopenharmony_ci{ 1444514f5e3Sopenharmony_ci ASSERT(argv); 1454514f5e3Sopenharmony_ci BUILTINS_API_TRACE(argv->GetThread(), Math, Atanh); 1464514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 1474514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 1484514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> msg = GetCallArg(argv, 0); 1494514f5e3Sopenharmony_ci JSTaggedNumber numberValue = JSTaggedValue::ToNumber(thread, msg); 1504514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1514514f5e3Sopenharmony_ci double value = numberValue.GetNumber(); 1524514f5e3Sopenharmony_ci double result = base::NAN_VALUE; 1534514f5e3Sopenharmony_ci if (value >= -1 && value <= 1) { 1544514f5e3Sopenharmony_ci result = base::MathHelper::Atanh(value); 1554514f5e3Sopenharmony_ci } 1564514f5e3Sopenharmony_ci return GetTaggedDouble(result); 1574514f5e3Sopenharmony_ci} 1584514f5e3Sopenharmony_ci 1594514f5e3Sopenharmony_ci// 20.2.2.8 1604514f5e3Sopenharmony_ciJSTaggedValue BuiltinsMath::Atan2(EcmaRuntimeCallInfo *argv) 1614514f5e3Sopenharmony_ci{ 1624514f5e3Sopenharmony_ci ASSERT(argv); 1634514f5e3Sopenharmony_ci BUILTINS_API_TRACE(argv->GetThread(), Math, Atan2); 1644514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 1654514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 1664514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> msgY = GetCallArg(argv, 0); 1674514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> msgX = GetCallArg(argv, 1); 1684514f5e3Sopenharmony_ci double result = base::NAN_VALUE; 1694514f5e3Sopenharmony_ci JSTaggedNumber numberValueY = JSTaggedValue::ToNumber(thread, msgY); 1704514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1714514f5e3Sopenharmony_ci JSTaggedNumber numberValueX = JSTaggedValue::ToNumber(thread, msgX); 1724514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 1734514f5e3Sopenharmony_ci double valueY = numberValueY.GetNumber(); 1744514f5e3Sopenharmony_ci double valueX = numberValueX.GetNumber(); 1754514f5e3Sopenharmony_ci // y = +0 and x > +0, return +0 1764514f5e3Sopenharmony_ci // y = -0 and x > +0, return -0 1774514f5e3Sopenharmony_ci if (valueY == 0 && valueX > 0) { 1784514f5e3Sopenharmony_ci result = valueY; 1794514f5e3Sopenharmony_ci } else if (std::isfinite(valueY) && valueX == std::numeric_limits<double>::infinity()) { 1804514f5e3Sopenharmony_ci // y < 0 and y is finite and x is POSITIVE_INFINITY,return -0 1814514f5e3Sopenharmony_ci // y >= 0 and y is finite and x is POSITIVE_INFINITY,return +0 1824514f5e3Sopenharmony_ci result = valueY >= 0 ? 0 : -0.0; 1834514f5e3Sopenharmony_ci } else if (!std::isnan(std::abs(valueY)) && !std::isnan(std::abs(valueX))) { 1844514f5e3Sopenharmony_ci // If either x or y is NaN, the result is NaN 1854514f5e3Sopenharmony_ci result = std::atan2(valueY, valueX); 1864514f5e3Sopenharmony_ci } 1874514f5e3Sopenharmony_ci return GetTaggedDouble(result); 1884514f5e3Sopenharmony_ci} 1894514f5e3Sopenharmony_ci 1904514f5e3Sopenharmony_ci// 20.2.2.9 1914514f5e3Sopenharmony_ciJSTaggedValue BuiltinsMath::Cbrt(EcmaRuntimeCallInfo *argv) 1924514f5e3Sopenharmony_ci{ 1934514f5e3Sopenharmony_ci ASSERT(argv); 1944514f5e3Sopenharmony_ci BUILTINS_API_TRACE(argv->GetThread(), Math, Cbrt); 1954514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 1964514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 1974514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> msg = GetCallArg(argv, 0); 1984514f5e3Sopenharmony_ci JSTaggedNumber numberValue = JSTaggedValue::ToNumber(thread, msg); 1994514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2004514f5e3Sopenharmony_ci double value = numberValue.GetNumber(); 2014514f5e3Sopenharmony_ci double result = base::NAN_VALUE; 2024514f5e3Sopenharmony_ci // if value == -NaN, NaN, result is NaN 2034514f5e3Sopenharmony_ci if (!std::isnan(std::abs(value))) { 2044514f5e3Sopenharmony_ci result = std::cbrt(value); 2054514f5e3Sopenharmony_ci } 2064514f5e3Sopenharmony_ci return GetTaggedDouble(result); 2074514f5e3Sopenharmony_ci} 2084514f5e3Sopenharmony_ci 2094514f5e3Sopenharmony_ci// 20.2.2.10 2104514f5e3Sopenharmony_ciJSTaggedValue BuiltinsMath::Ceil(EcmaRuntimeCallInfo *argv) 2114514f5e3Sopenharmony_ci{ 2124514f5e3Sopenharmony_ci ASSERT(argv); 2134514f5e3Sopenharmony_ci BUILTINS_API_TRACE(argv->GetThread(), Math, Ceil); 2144514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 2154514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 2164514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> msg = GetCallArg(argv, 0); 2174514f5e3Sopenharmony_ci JSTaggedNumber numberValue = JSTaggedValue::ToNumber(thread, msg); 2184514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2194514f5e3Sopenharmony_ci double value = numberValue.GetNumber(); 2204514f5e3Sopenharmony_ci double result = base::NAN_VALUE; 2214514f5e3Sopenharmony_ci // If value is NaN or -NaN, +infinite, -infinite,return value 2224514f5e3Sopenharmony_ci if (!std::isfinite(value)) { 2234514f5e3Sopenharmony_ci // if value is -NaN , return NaN, else return value 2244514f5e3Sopenharmony_ci if (!std::isnan(std::abs(value))) { 2254514f5e3Sopenharmony_ci result = value; 2264514f5e3Sopenharmony_ci } 2274514f5e3Sopenharmony_ci } else { 2284514f5e3Sopenharmony_ci result = std::ceil(value); 2294514f5e3Sopenharmony_ci } 2304514f5e3Sopenharmony_ci return GetTaggedDouble(result); 2314514f5e3Sopenharmony_ci} 2324514f5e3Sopenharmony_ci 2334514f5e3Sopenharmony_ci// 20.2.2.11 2344514f5e3Sopenharmony_ciJSTaggedValue BuiltinsMath::Clz32(EcmaRuntimeCallInfo *argv) 2354514f5e3Sopenharmony_ci{ 2364514f5e3Sopenharmony_ci ASSERT(argv); 2374514f5e3Sopenharmony_ci BUILTINS_API_TRACE(argv->GetThread(), Math, Clz32); 2384514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 2394514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 2404514f5e3Sopenharmony_ci constexpr int defaultValue = 32; 2414514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> msg = GetCallArg(argv, 0); 2424514f5e3Sopenharmony_ci JSTaggedNumber numberValue = JSTaggedValue::ToNumber(thread, msg); 2434514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2444514f5e3Sopenharmony_ci double value = numberValue.GetNumber(); 2454514f5e3Sopenharmony_ci auto tmpValue = std::abs(value); 2464514f5e3Sopenharmony_ci auto result = numberValue.ToUint32(); 2474514f5e3Sopenharmony_ci if (!std::isfinite(tmpValue) || tmpValue == 0 || result == 0) { 2484514f5e3Sopenharmony_ci // If value is NaN or -NaN, +infinite, -infinite, 0,return 32 2494514f5e3Sopenharmony_ci return GetTaggedInt(defaultValue); 2504514f5e3Sopenharmony_ci } 2514514f5e3Sopenharmony_ci return GetTaggedInt(__builtin_clz(result)); 2524514f5e3Sopenharmony_ci} 2534514f5e3Sopenharmony_ci 2544514f5e3Sopenharmony_ci// 20.2.2.12 2554514f5e3Sopenharmony_ciJSTaggedValue BuiltinsMath::Cos(EcmaRuntimeCallInfo *argv) 2564514f5e3Sopenharmony_ci{ 2574514f5e3Sopenharmony_ci ASSERT(argv); 2584514f5e3Sopenharmony_ci BUILTINS_API_TRACE(argv->GetThread(), Math, Cos); 2594514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 2604514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 2614514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> msg = GetCallArg(argv, 0); 2624514f5e3Sopenharmony_ci JSTaggedNumber numberValue = JSTaggedValue::ToNumber(thread, msg); 2634514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2644514f5e3Sopenharmony_ci double value = numberValue.GetNumber(); 2654514f5e3Sopenharmony_ci double result = base::NAN_VALUE; 2664514f5e3Sopenharmony_ci // If value is NaN or -NaN, +infinite, -infinite, result is NaN 2674514f5e3Sopenharmony_ci if (std::isfinite(std::abs(value))) { 2684514f5e3Sopenharmony_ci result = std::cos(value); 2694514f5e3Sopenharmony_ci } 2704514f5e3Sopenharmony_ci return GetTaggedDouble(result); 2714514f5e3Sopenharmony_ci} 2724514f5e3Sopenharmony_ci 2734514f5e3Sopenharmony_ci// 20.2.2.13 2744514f5e3Sopenharmony_ciJSTaggedValue BuiltinsMath::Cosh(EcmaRuntimeCallInfo *argv) 2754514f5e3Sopenharmony_ci{ 2764514f5e3Sopenharmony_ci ASSERT(argv); 2774514f5e3Sopenharmony_ci BUILTINS_API_TRACE(argv->GetThread(), Math, Cosh); 2784514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 2794514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 2804514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> msg = GetCallArg(argv, 0); 2814514f5e3Sopenharmony_ci JSTaggedNumber numberValue = JSTaggedValue::ToNumber(thread, msg); 2824514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 2834514f5e3Sopenharmony_ci double value = numberValue.GetNumber(); 2844514f5e3Sopenharmony_ci double result = base::NAN_VALUE; 2854514f5e3Sopenharmony_ci // if value is NaN or -NaN, result is NaN 2864514f5e3Sopenharmony_ci if (!std::isnan(std::abs(value))) { 2874514f5e3Sopenharmony_ci result = std::cosh(value); 2884514f5e3Sopenharmony_ci } 2894514f5e3Sopenharmony_ci return GetTaggedDouble(result); 2904514f5e3Sopenharmony_ci} 2914514f5e3Sopenharmony_ci 2924514f5e3Sopenharmony_ci// 20.2.2.14 2934514f5e3Sopenharmony_ciJSTaggedValue BuiltinsMath::Exp(EcmaRuntimeCallInfo *argv) 2944514f5e3Sopenharmony_ci{ 2954514f5e3Sopenharmony_ci ASSERT(argv); 2964514f5e3Sopenharmony_ci BUILTINS_API_TRACE(argv->GetThread(), Math, Exp); 2974514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 2984514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 2994514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> msg = GetCallArg(argv, 0); 3004514f5e3Sopenharmony_ci JSTaggedNumber numberValue = JSTaggedValue::ToNumber(thread, msg); 3014514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 3024514f5e3Sopenharmony_ci double value = numberValue.GetNumber(); 3034514f5e3Sopenharmony_ci double result = base::NAN_VALUE; 3044514f5e3Sopenharmony_ci // if value is NaN or -NaN, result is NaN 3054514f5e3Sopenharmony_ci if (!std::isnan(std::abs(value))) { 3064514f5e3Sopenharmony_ci result = std::exp(value); 3074514f5e3Sopenharmony_ci } 3084514f5e3Sopenharmony_ci return GetTaggedDouble(result); 3094514f5e3Sopenharmony_ci} 3104514f5e3Sopenharmony_ci 3114514f5e3Sopenharmony_ci// 20.2.2.15 3124514f5e3Sopenharmony_ciJSTaggedValue BuiltinsMath::Expm1(EcmaRuntimeCallInfo *argv) 3134514f5e3Sopenharmony_ci{ 3144514f5e3Sopenharmony_ci ASSERT(argv); 3154514f5e3Sopenharmony_ci BUILTINS_API_TRACE(argv->GetThread(), Math, Expm1); 3164514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 3174514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 3184514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> msg = GetCallArg(argv, 0); 3194514f5e3Sopenharmony_ci JSTaggedNumber numberValue = JSTaggedValue::ToNumber(thread, msg); 3204514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 3214514f5e3Sopenharmony_ci double value = numberValue.GetNumber(); 3224514f5e3Sopenharmony_ci double result = base::NAN_VALUE; 3234514f5e3Sopenharmony_ci // if value is NaN or -NaN, result is NaN 3244514f5e3Sopenharmony_ci if (!std::isnan(std::abs(value))) { 3254514f5e3Sopenharmony_ci result = std::expm1(value); 3264514f5e3Sopenharmony_ci } 3274514f5e3Sopenharmony_ci return GetTaggedDouble(result); 3284514f5e3Sopenharmony_ci} 3294514f5e3Sopenharmony_ci 3304514f5e3Sopenharmony_ci// 20.2.2.16 3314514f5e3Sopenharmony_ciJSTaggedValue BuiltinsMath::Floor(EcmaRuntimeCallInfo *argv) 3324514f5e3Sopenharmony_ci{ 3334514f5e3Sopenharmony_ci ASSERT(argv); 3344514f5e3Sopenharmony_ci BUILTINS_API_TRACE(argv->GetThread(), Math, Floor); 3354514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 3364514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 3374514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> msg = GetCallArg(argv, 0); 3384514f5e3Sopenharmony_ci JSTaggedNumber numberValue = JSTaggedValue::ToNumber(thread, msg); 3394514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 3404514f5e3Sopenharmony_ci double value = numberValue.GetNumber(); 3414514f5e3Sopenharmony_ci double result = base::NAN_VALUE; 3424514f5e3Sopenharmony_ci // If value is NaN or -NaN, +infinite, -infinite, +0, -0, return value 3434514f5e3Sopenharmony_ci if (!std::isfinite(value) || value == 0) { 3444514f5e3Sopenharmony_ci // If value is -NaN, return NaN, else return value 3454514f5e3Sopenharmony_ci if (!std::isnan(std::abs(value))) { 3464514f5e3Sopenharmony_ci result = value; 3474514f5e3Sopenharmony_ci } 3484514f5e3Sopenharmony_ci } else if (value > 0 && value < 1) { 3494514f5e3Sopenharmony_ci // If x is greater than 0 but less than 1, the result is +0 3504514f5e3Sopenharmony_ci result = 0; 3514514f5e3Sopenharmony_ci } else { 3524514f5e3Sopenharmony_ci result = std::floor(value); 3534514f5e3Sopenharmony_ci } 3544514f5e3Sopenharmony_ci return GetTaggedDouble(result); 3554514f5e3Sopenharmony_ci} 3564514f5e3Sopenharmony_ci 3574514f5e3Sopenharmony_ci// 20.2.2.17 3584514f5e3Sopenharmony_ciJSTaggedValue BuiltinsMath::Fround(EcmaRuntimeCallInfo *argv) 3594514f5e3Sopenharmony_ci{ 3604514f5e3Sopenharmony_ci ASSERT(argv); 3614514f5e3Sopenharmony_ci BUILTINS_API_TRACE(argv->GetThread(), Math, Fround); 3624514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 3634514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 3644514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> msg = GetCallArg(argv, 0); 3654514f5e3Sopenharmony_ci JSTaggedNumber numberValue = JSTaggedValue::ToNumber(thread, msg); 3664514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 3674514f5e3Sopenharmony_ci double value = numberValue.GetNumber(); 3684514f5e3Sopenharmony_ci double result; 3694514f5e3Sopenharmony_ci if (std::isnan(std::abs(value))) { 3704514f5e3Sopenharmony_ci // If result is NaN or -NaN, the result is NaN 3714514f5e3Sopenharmony_ci result = base::NAN_VALUE; 3724514f5e3Sopenharmony_ci } else { 3734514f5e3Sopenharmony_ci result = static_cast<float>(value); 3744514f5e3Sopenharmony_ci } 3754514f5e3Sopenharmony_ci return GetTaggedDouble(result); 3764514f5e3Sopenharmony_ci} 3774514f5e3Sopenharmony_ci 3784514f5e3Sopenharmony_ci// 20.2.2.18 3794514f5e3Sopenharmony_ciJSTaggedValue BuiltinsMath::Hypot(EcmaRuntimeCallInfo *argv) 3804514f5e3Sopenharmony_ci{ 3814514f5e3Sopenharmony_ci ASSERT(argv); 3824514f5e3Sopenharmony_ci BUILTINS_API_TRACE(argv->GetThread(), Math, Hypot); 3834514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 3844514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 3854514f5e3Sopenharmony_ci double result = 0; 3864514f5e3Sopenharmony_ci double value = 0; 3874514f5e3Sopenharmony_ci uint32_t argLen = argv->GetArgsNumber(); 3884514f5e3Sopenharmony_ci auto numberValue = JSTaggedNumber(0); 3894514f5e3Sopenharmony_ci for (uint32_t i = 0; i < argLen; i++) { 3904514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> msg = GetCallArg(argv, i); 3914514f5e3Sopenharmony_ci numberValue = JSTaggedValue::ToNumber(thread, msg); 3924514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 3934514f5e3Sopenharmony_ci value = numberValue.GetNumber(); 3944514f5e3Sopenharmony_ci result = std::hypot(result, value); 3954514f5e3Sopenharmony_ci } 3964514f5e3Sopenharmony_ci return GetTaggedDouble(result); 3974514f5e3Sopenharmony_ci} 3984514f5e3Sopenharmony_ci 3994514f5e3Sopenharmony_ci// 20.2.2.19 4004514f5e3Sopenharmony_ciJSTaggedValue BuiltinsMath::Imul(EcmaRuntimeCallInfo *argv) 4014514f5e3Sopenharmony_ci{ 4024514f5e3Sopenharmony_ci ASSERT(argv); 4034514f5e3Sopenharmony_ci BUILTINS_API_TRACE(argv->GetThread(), Math, Imul); 4044514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 4054514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 4064514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> msg1 = GetCallArg(argv, 0); 4074514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> msg2 = GetCallArg(argv, 1); 4084514f5e3Sopenharmony_ci JSTaggedNumber numberValue1 = JSTaggedValue::ToNumber(thread, msg1); 4094514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 4104514f5e3Sopenharmony_ci JSTaggedNumber numberValue2 = JSTaggedValue::ToNumber(thread, msg2); 4114514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 4124514f5e3Sopenharmony_ci auto value1 = numberValue1.GetNumber(); 4134514f5e3Sopenharmony_ci auto value2 = numberValue2.GetNumber(); 4144514f5e3Sopenharmony_ci if (!std::isfinite(value1) || !std::isfinite(value2)) { 4154514f5e3Sopenharmony_ci // If value is NaN or -NaN, +infinite, -infinite 4164514f5e3Sopenharmony_ci return GetTaggedInt(0); 4174514f5e3Sopenharmony_ci } 4184514f5e3Sopenharmony_ci value1 = numberValue1.ToInt32(); 4194514f5e3Sopenharmony_ci value2 = numberValue2.ToInt32(); 4204514f5e3Sopenharmony_ci // purposely ignoring overflow 4214514f5e3Sopenharmony_ci auto result = static_cast<int32_t>(static_cast<int64_t>(value1) * static_cast<int64_t>(value2)); 4224514f5e3Sopenharmony_ci return GetTaggedInt(result); 4234514f5e3Sopenharmony_ci} 4244514f5e3Sopenharmony_ci 4254514f5e3Sopenharmony_ci// 20.2.2.20 4264514f5e3Sopenharmony_ciJSTaggedValue BuiltinsMath::Log(EcmaRuntimeCallInfo *argv) 4274514f5e3Sopenharmony_ci{ 4284514f5e3Sopenharmony_ci ASSERT(argv); 4294514f5e3Sopenharmony_ci BUILTINS_API_TRACE(argv->GetThread(), Math, Log); 4304514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 4314514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 4324514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> msg = GetCallArg(argv, 0); 4334514f5e3Sopenharmony_ci JSTaggedNumber numberValue = JSTaggedValue::ToNumber(thread, msg); 4344514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 4354514f5e3Sopenharmony_ci double value = numberValue.GetNumber(); 4364514f5e3Sopenharmony_ci double result = base::NAN_VALUE; 4374514f5e3Sopenharmony_ci // If value is NaN , -NaN , or < 0,result is NaN 4384514f5e3Sopenharmony_ci if (!std::isnan(std::abs(value)) && value >= 0) { 4394514f5e3Sopenharmony_ci result = std::log(value); 4404514f5e3Sopenharmony_ci } 4414514f5e3Sopenharmony_ci return GetTaggedDouble(result); 4424514f5e3Sopenharmony_ci} 4434514f5e3Sopenharmony_ci 4444514f5e3Sopenharmony_ci// 20.2.2.21 4454514f5e3Sopenharmony_ciJSTaggedValue BuiltinsMath::Log1p(EcmaRuntimeCallInfo *argv) 4464514f5e3Sopenharmony_ci{ 4474514f5e3Sopenharmony_ci ASSERT(argv); 4484514f5e3Sopenharmony_ci BUILTINS_API_TRACE(argv->GetThread(), Math, Log1p); 4494514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 4504514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 4514514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> msg = GetCallArg(argv, 0); 4524514f5e3Sopenharmony_ci JSTaggedNumber numberValue = JSTaggedValue::ToNumber(thread, msg); 4534514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 4544514f5e3Sopenharmony_ci double value = numberValue.GetNumber(); 4554514f5e3Sopenharmony_ci double result = base::NAN_VALUE; 4564514f5e3Sopenharmony_ci // If value is NaN , -NaN , or < -1,result is NaN 4574514f5e3Sopenharmony_ci if (!std::isnan(std::abs(value)) && value >= -1) { 4584514f5e3Sopenharmony_ci result = std::log1p(value); 4594514f5e3Sopenharmony_ci } 4604514f5e3Sopenharmony_ci return GetTaggedDouble(result); 4614514f5e3Sopenharmony_ci} 4624514f5e3Sopenharmony_ci 4634514f5e3Sopenharmony_ci// 20.2.2.22 4644514f5e3Sopenharmony_ciJSTaggedValue BuiltinsMath::Log10(EcmaRuntimeCallInfo *argv) 4654514f5e3Sopenharmony_ci{ 4664514f5e3Sopenharmony_ci ASSERT(argv); 4674514f5e3Sopenharmony_ci BUILTINS_API_TRACE(argv->GetThread(), Math, Log10); 4684514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 4694514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 4704514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> msg = GetCallArg(argv, 0); 4714514f5e3Sopenharmony_ci JSTaggedNumber numberValue = JSTaggedValue::ToNumber(thread, msg); 4724514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 4734514f5e3Sopenharmony_ci double value = numberValue.GetNumber(); 4744514f5e3Sopenharmony_ci double result = base::NAN_VALUE; 4754514f5e3Sopenharmony_ci // If value is NaN , -NaN , or < 0,result is NaN 4764514f5e3Sopenharmony_ci if (!std::isnan(std::abs(value)) && value >= 0) { 4774514f5e3Sopenharmony_ci result = std::log10(value); 4784514f5e3Sopenharmony_ci } 4794514f5e3Sopenharmony_ci return GetTaggedDouble(result); 4804514f5e3Sopenharmony_ci} 4814514f5e3Sopenharmony_ci 4824514f5e3Sopenharmony_ci// 20.2.2.23 4834514f5e3Sopenharmony_ciJSTaggedValue BuiltinsMath::Log2(EcmaRuntimeCallInfo *argv) 4844514f5e3Sopenharmony_ci{ 4854514f5e3Sopenharmony_ci ASSERT(argv); 4864514f5e3Sopenharmony_ci BUILTINS_API_TRACE(argv->GetThread(), Math, Log2); 4874514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 4884514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 4894514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> msg = GetCallArg(argv, 0); 4904514f5e3Sopenharmony_ci JSTaggedNumber numberValue = JSTaggedValue::ToNumber(thread, msg); 4914514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 4924514f5e3Sopenharmony_ci double value = numberValue.GetNumber(); 4934514f5e3Sopenharmony_ci double result = base::NAN_VALUE; 4944514f5e3Sopenharmony_ci // If value is NaN , -NaN , or < 0,result is NaN 4954514f5e3Sopenharmony_ci if (!std::isnan(std::abs(value)) && value >= 0) { 4964514f5e3Sopenharmony_ci result = std::log2(value); 4974514f5e3Sopenharmony_ci } 4984514f5e3Sopenharmony_ci return GetTaggedDouble(result); 4994514f5e3Sopenharmony_ci} 5004514f5e3Sopenharmony_ci 5014514f5e3Sopenharmony_ciinline bool IsNegZero(double value) 5024514f5e3Sopenharmony_ci{ 5034514f5e3Sopenharmony_ci return (value == 0.0 && (base::bit_cast<uint64_t>(value) & base::DOUBLE_SIGN_MASK) == base::DOUBLE_SIGN_MASK); 5044514f5e3Sopenharmony_ci} 5054514f5e3Sopenharmony_ci 5064514f5e3Sopenharmony_ci// 20.2.2.24 5074514f5e3Sopenharmony_ciJSTaggedValue BuiltinsMath::Max(EcmaRuntimeCallInfo *argv) 5084514f5e3Sopenharmony_ci{ 5094514f5e3Sopenharmony_ci ASSERT(argv); 5104514f5e3Sopenharmony_ci BUILTINS_API_TRACE(argv->GetThread(), Math, Max); 5114514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 5124514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 5134514f5e3Sopenharmony_ci uint32_t argLen = argv->GetArgsNumber(); 5144514f5e3Sopenharmony_ci auto numberValue = JSTaggedNumber(-base::POSITIVE_INFINITY); 5154514f5e3Sopenharmony_ci // If no arguments are given, the result is -inf 5164514f5e3Sopenharmony_ci auto result = JSTaggedNumber(-base::POSITIVE_INFINITY); 5174514f5e3Sopenharmony_ci auto tmpMax = -base::POSITIVE_INFINITY; 5184514f5e3Sopenharmony_ci auto value = -base::POSITIVE_INFINITY; 5194514f5e3Sopenharmony_ci bool flag = false; 5204514f5e3Sopenharmony_ci uint32_t i = 0; 5214514f5e3Sopenharmony_ci for (; i < argLen; i++) { 5224514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> msg = GetCallArg(argv, i); 5234514f5e3Sopenharmony_ci numberValue = JSTaggedValue::ToNumber(thread, msg); 5244514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 5254514f5e3Sopenharmony_ci value = numberValue.GetNumber(); 5264514f5e3Sopenharmony_ci if (std::isnan(std::abs(value))) { 5274514f5e3Sopenharmony_ci // If any value is NaN, or -NaN, the max result is NaN 5284514f5e3Sopenharmony_ci result = numberValue; 5294514f5e3Sopenharmony_ci flag = true; 5304514f5e3Sopenharmony_ci i++; 5314514f5e3Sopenharmony_ci break; 5324514f5e3Sopenharmony_ci } 5334514f5e3Sopenharmony_ci if (value > tmpMax) { 5344514f5e3Sopenharmony_ci result = numberValue; 5354514f5e3Sopenharmony_ci tmpMax = value; 5364514f5e3Sopenharmony_ci } else if (value == 0 && tmpMax == 0 && IsNegZero(tmpMax) && !IsNegZero(value)) { 5374514f5e3Sopenharmony_ci // if tmp_max is -0, value is 0, max is 0 5384514f5e3Sopenharmony_ci result = numberValue; 5394514f5e3Sopenharmony_ci tmpMax = value; 5404514f5e3Sopenharmony_ci } 5414514f5e3Sopenharmony_ci } 5424514f5e3Sopenharmony_ci if (flag) { 5434514f5e3Sopenharmony_ci for (; i < argLen; i++) { 5444514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> msg = GetCallArg(argv, i); 5454514f5e3Sopenharmony_ci numberValue = JSTaggedValue::ToNumber(thread, msg); 5464514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 5474514f5e3Sopenharmony_ci } 5484514f5e3Sopenharmony_ci } 5494514f5e3Sopenharmony_ci return result; 5504514f5e3Sopenharmony_ci} 5514514f5e3Sopenharmony_ci 5524514f5e3Sopenharmony_ci// 20.2.2.25 5534514f5e3Sopenharmony_ciJSTaggedValue BuiltinsMath::Min(EcmaRuntimeCallInfo *argv) 5544514f5e3Sopenharmony_ci{ 5554514f5e3Sopenharmony_ci ASSERT(argv); 5564514f5e3Sopenharmony_ci BUILTINS_API_TRACE(argv->GetThread(), Math, Min); 5574514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 5584514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 5594514f5e3Sopenharmony_ci uint32_t argLen = argv->GetArgsNumber(); 5604514f5e3Sopenharmony_ci auto numberValue = JSTaggedNumber(base::POSITIVE_INFINITY); 5614514f5e3Sopenharmony_ci // If no arguments are given, the result is inf 5624514f5e3Sopenharmony_ci auto result = JSTaggedNumber(base::POSITIVE_INFINITY); 5634514f5e3Sopenharmony_ci auto tmpMin = base::POSITIVE_INFINITY; 5644514f5e3Sopenharmony_ci auto value = base::POSITIVE_INFINITY; 5654514f5e3Sopenharmony_ci bool flag = false; 5664514f5e3Sopenharmony_ci uint32_t i = 0; 5674514f5e3Sopenharmony_ci for (; i < argLen; i++) { 5684514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> msg = GetCallArg(argv, i); 5694514f5e3Sopenharmony_ci numberValue = JSTaggedValue::ToNumber(thread, msg); 5704514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 5714514f5e3Sopenharmony_ci value = numberValue.GetNumber(); 5724514f5e3Sopenharmony_ci if (std::isnan(std::abs(value))) { 5734514f5e3Sopenharmony_ci // If any value is NaN or -NaN, the min result is NaN 5744514f5e3Sopenharmony_ci result = numberValue; 5754514f5e3Sopenharmony_ci flag = true; 5764514f5e3Sopenharmony_ci i++; 5774514f5e3Sopenharmony_ci break; 5784514f5e3Sopenharmony_ci } 5794514f5e3Sopenharmony_ci if (value < tmpMin) { 5804514f5e3Sopenharmony_ci result = numberValue; 5814514f5e3Sopenharmony_ci tmpMin = value; 5824514f5e3Sopenharmony_ci } else if (value == 0 && tmpMin == 0 && !IsNegZero(tmpMin) && IsNegZero(value)) { 5834514f5e3Sopenharmony_ci // if tmp_min is 0, value is -0, min is -0 5844514f5e3Sopenharmony_ci result = numberValue; 5854514f5e3Sopenharmony_ci tmpMin = value; 5864514f5e3Sopenharmony_ci } 5874514f5e3Sopenharmony_ci } 5884514f5e3Sopenharmony_ci if (flag) { 5894514f5e3Sopenharmony_ci for (; i < argLen; i++) { 5904514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> msg = GetCallArg(argv, i); 5914514f5e3Sopenharmony_ci numberValue = JSTaggedValue::ToNumber(thread, msg); 5924514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 5934514f5e3Sopenharmony_ci } 5944514f5e3Sopenharmony_ci } 5954514f5e3Sopenharmony_ci return result; 5964514f5e3Sopenharmony_ci} 5974514f5e3Sopenharmony_ci 5984514f5e3Sopenharmony_ci// 20.2.2.26 5994514f5e3Sopenharmony_ciJSTaggedValue BuiltinsMath::Pow(EcmaRuntimeCallInfo *argv) 6004514f5e3Sopenharmony_ci{ 6014514f5e3Sopenharmony_ci ASSERT(argv); 6024514f5e3Sopenharmony_ci BUILTINS_API_TRACE(argv->GetThread(), Math, Pow); 6034514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 6044514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 6054514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> msgX = GetCallArg(argv, 0); 6064514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> msgY = GetCallArg(argv, 1); 6074514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> baseVale = JSTaggedValue::ToNumeric(thread, msgX); 6084514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 6094514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> exponentValue = JSTaggedValue::ToNumeric(thread, msgY); 6104514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 6114514f5e3Sopenharmony_ci if (baseVale->IsBigInt() || exponentValue->IsBigInt()) { 6124514f5e3Sopenharmony_ci if (baseVale->IsBigInt() && exponentValue->IsBigInt()) { 6134514f5e3Sopenharmony_ci JSHandle<BigInt> bigBaseVale(baseVale); 6144514f5e3Sopenharmony_ci JSHandle<BigInt> bigExponentValue(exponentValue); 6154514f5e3Sopenharmony_ci return BigInt::Exponentiate(thread, bigBaseVale, bigExponentValue).GetTaggedValue(); 6164514f5e3Sopenharmony_ci } 6174514f5e3Sopenharmony_ci THROW_TYPE_ERROR_AND_RETURN(thread, "Cannot mix BigInt and other types, use explicit conversions", 6184514f5e3Sopenharmony_ci JSTaggedValue::Exception()); 6194514f5e3Sopenharmony_ci } 6204514f5e3Sopenharmony_ci double valueX = baseVale->GetNumber(); 6214514f5e3Sopenharmony_ci double valueY = exponentValue->GetNumber(); 6224514f5e3Sopenharmony_ci // If abs(x) is 1 and y is inf or -inf, the result is NaN 6234514f5e3Sopenharmony_ci if (std::abs(valueX) == 1 && !std::isfinite(valueY)) { 6244514f5e3Sopenharmony_ci return GetTaggedDouble(base::NAN_VALUE); 6254514f5e3Sopenharmony_ci } 6264514f5e3Sopenharmony_ci double result = std::pow(valueX, valueY); 6274514f5e3Sopenharmony_ci if (std::isnan(std::abs(result))) { 6284514f5e3Sopenharmony_ci // If result is NaN or -NaN, the result is NaN 6294514f5e3Sopenharmony_ci result = base::NAN_VALUE; 6304514f5e3Sopenharmony_ci } 6314514f5e3Sopenharmony_ci return GetTaggedDouble(result); 6324514f5e3Sopenharmony_ci} 6334514f5e3Sopenharmony_ci 6344514f5e3Sopenharmony_ci// 20.2.2.27 6354514f5e3Sopenharmony_ciJSTaggedValue BuiltinsMath::Random(EcmaRuntimeCallInfo *argv) 6364514f5e3Sopenharmony_ci{ 6374514f5e3Sopenharmony_ci ASSERT(argv); 6384514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 6394514f5e3Sopenharmony_ci BUILTINS_API_TRACE(thread, Math, Random); 6404514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 6414514f5e3Sopenharmony_ci return GetTaggedDouble(RandomGenerator::NextDouble()); 6424514f5e3Sopenharmony_ci} 6434514f5e3Sopenharmony_ci 6444514f5e3Sopenharmony_ci// 20.2.2.28 6454514f5e3Sopenharmony_ciJSTaggedValue BuiltinsMath::Round(EcmaRuntimeCallInfo *argv) 6464514f5e3Sopenharmony_ci{ 6474514f5e3Sopenharmony_ci ASSERT(argv); 6484514f5e3Sopenharmony_ci BUILTINS_API_TRACE(argv->GetThread(), Math, Round); 6494514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 6504514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 6514514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> msg = GetCallArg(argv, 0); 6524514f5e3Sopenharmony_ci JSTaggedNumber numberValue = JSTaggedValue::ToNumber(thread, msg); 6534514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 6544514f5e3Sopenharmony_ci double value = numberValue.GetNumber(); 6554514f5e3Sopenharmony_ci auto result = base::NAN_VALUE; 6564514f5e3Sopenharmony_ci const double diff = 0.5; 6574514f5e3Sopenharmony_ci double absValue = std::abs(value); 6584514f5e3Sopenharmony_ci if (!std::isfinite(absValue) || absValue == 0) { 6594514f5e3Sopenharmony_ci // If value is NaN, +infinite, or -infinite, VRegisterTag is DOUBLE 6604514f5e3Sopenharmony_ci if (!std::isnan(absValue)) { 6614514f5e3Sopenharmony_ci // If value is NaN or -NaN, the result is default NaN, else is value 6624514f5e3Sopenharmony_ci result = value; 6634514f5e3Sopenharmony_ci } 6644514f5e3Sopenharmony_ci return GetTaggedDouble(result); 6654514f5e3Sopenharmony_ci } 6664514f5e3Sopenharmony_ci // If x is less than 0 but greater than or equal to -0.5, the result is -0 6674514f5e3Sopenharmony_ci if (value < 0 && value >= -diff) { 6684514f5e3Sopenharmony_ci return GetTaggedDouble(-0.0); 6694514f5e3Sopenharmony_ci } 6704514f5e3Sopenharmony_ci // If x is greater than 0 but less than 0.5, the result is +0 6714514f5e3Sopenharmony_ci if (value > 0 && value < diff) { 6724514f5e3Sopenharmony_ci return GetTaggedInt(0); 6734514f5e3Sopenharmony_ci } 6744514f5e3Sopenharmony_ci // For huge integers 6754514f5e3Sopenharmony_ci result = std::ceil(value); 6764514f5e3Sopenharmony_ci if (result - value > diff) { 6774514f5e3Sopenharmony_ci result -= 1; 6784514f5e3Sopenharmony_ci } 6794514f5e3Sopenharmony_ci return GetTaggedDouble(result); 6804514f5e3Sopenharmony_ci} 6814514f5e3Sopenharmony_ci 6824514f5e3Sopenharmony_ci// 20.2.2.29 6834514f5e3Sopenharmony_ciJSTaggedValue BuiltinsMath::Sign(EcmaRuntimeCallInfo *argv) 6844514f5e3Sopenharmony_ci{ 6854514f5e3Sopenharmony_ci ASSERT(argv); 6864514f5e3Sopenharmony_ci BUILTINS_API_TRACE(argv->GetThread(), Math, Sign); 6874514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 6884514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 6894514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> msg = GetCallArg(argv, 0); 6904514f5e3Sopenharmony_ci JSTaggedNumber numberValue = JSTaggedValue::ToNumber(thread, msg); 6914514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 6924514f5e3Sopenharmony_ci double value = numberValue.GetNumber(); 6934514f5e3Sopenharmony_ci if (std::isnan(std::abs(value))) { 6944514f5e3Sopenharmony_ci return GetTaggedDouble(std::abs(value)); 6954514f5e3Sopenharmony_ci } 6964514f5e3Sopenharmony_ci if (value == 0.0) { 6974514f5e3Sopenharmony_ci return GetTaggedDouble(value); 6984514f5e3Sopenharmony_ci } 6994514f5e3Sopenharmony_ci if (value < 0) { 7004514f5e3Sopenharmony_ci return GetTaggedInt(-1); 7014514f5e3Sopenharmony_ci } 7024514f5e3Sopenharmony_ci return GetTaggedInt(1); 7034514f5e3Sopenharmony_ci} 7044514f5e3Sopenharmony_ci 7054514f5e3Sopenharmony_ci// 20.2.2.30 7064514f5e3Sopenharmony_ciJSTaggedValue BuiltinsMath::Sin(EcmaRuntimeCallInfo *argv) 7074514f5e3Sopenharmony_ci{ 7084514f5e3Sopenharmony_ci ASSERT(argv); 7094514f5e3Sopenharmony_ci BUILTINS_API_TRACE(argv->GetThread(), Math, Sin); 7104514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 7114514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 7124514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> msg = GetCallArg(argv, 0); 7134514f5e3Sopenharmony_ci JSTaggedNumber numberValue = JSTaggedValue::ToNumber(thread, msg); 7144514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 7154514f5e3Sopenharmony_ci double value = numberValue.GetNumber(); 7164514f5e3Sopenharmony_ci double result = base::NAN_VALUE; 7174514f5e3Sopenharmony_ci // If value is NaN or -NaN, the result is NaN 7184514f5e3Sopenharmony_ci if (std::isfinite(std::abs(value))) { 7194514f5e3Sopenharmony_ci result = std::sin(value); 7204514f5e3Sopenharmony_ci } 7214514f5e3Sopenharmony_ci return GetTaggedDouble(result); 7224514f5e3Sopenharmony_ci} 7234514f5e3Sopenharmony_ci 7244514f5e3Sopenharmony_ci// 20.2.2.31 7254514f5e3Sopenharmony_ciJSTaggedValue BuiltinsMath::Sinh(EcmaRuntimeCallInfo *argv) 7264514f5e3Sopenharmony_ci{ 7274514f5e3Sopenharmony_ci ASSERT(argv); 7284514f5e3Sopenharmony_ci BUILTINS_API_TRACE(argv->GetThread(), Math, Sinh); 7294514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 7304514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 7314514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> msg = GetCallArg(argv, 0); 7324514f5e3Sopenharmony_ci JSTaggedNumber numberValue = JSTaggedValue::ToNumber(thread, msg); 7334514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 7344514f5e3Sopenharmony_ci double value = numberValue.GetNumber(); 7354514f5e3Sopenharmony_ci double result = base::NAN_VALUE; 7364514f5e3Sopenharmony_ci // If value is NaN or -NaN, the result is NaN 7374514f5e3Sopenharmony_ci if (!std::isnan(std::abs(value))) { 7384514f5e3Sopenharmony_ci result = std::sinh(value); 7394514f5e3Sopenharmony_ci } 7404514f5e3Sopenharmony_ci return GetTaggedDouble(result); 7414514f5e3Sopenharmony_ci} 7424514f5e3Sopenharmony_ci 7434514f5e3Sopenharmony_ci// 20.2.2.32 7444514f5e3Sopenharmony_ciJSTaggedValue BuiltinsMath::Sqrt(EcmaRuntimeCallInfo *argv) 7454514f5e3Sopenharmony_ci{ 7464514f5e3Sopenharmony_ci ASSERT(argv); 7474514f5e3Sopenharmony_ci BUILTINS_API_TRACE(argv->GetThread(), Math, Sqrt); 7484514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 7494514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 7504514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> msg = GetCallArg(argv, 0); 7514514f5e3Sopenharmony_ci JSTaggedNumber numberValue = JSTaggedValue::ToNumber(thread, msg); 7524514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 7534514f5e3Sopenharmony_ci double value = numberValue.GetNumber(); 7544514f5e3Sopenharmony_ci double result = base::NAN_VALUE; 7554514f5e3Sopenharmony_ci // If value is negative, include -NaN and -Infinity but not -0.0, the result is NaN 7564514f5e3Sopenharmony_ci if (std::signbit(value) && value != 0) { 7574514f5e3Sopenharmony_ci return GetTaggedDouble(result); 7584514f5e3Sopenharmony_ci } 7594514f5e3Sopenharmony_ci // If value is NaN, the result is NaN 7604514f5e3Sopenharmony_ci if (!std::isnan(value)) { 7614514f5e3Sopenharmony_ci result = std::sqrt(value); 7624514f5e3Sopenharmony_ci } 7634514f5e3Sopenharmony_ci return GetTaggedDouble(result); 7644514f5e3Sopenharmony_ci} 7654514f5e3Sopenharmony_ci 7664514f5e3Sopenharmony_ci// 20.2.2.33 7674514f5e3Sopenharmony_ciJSTaggedValue BuiltinsMath::Tan(EcmaRuntimeCallInfo *argv) 7684514f5e3Sopenharmony_ci{ 7694514f5e3Sopenharmony_ci ASSERT(argv); 7704514f5e3Sopenharmony_ci BUILTINS_API_TRACE(argv->GetThread(), Math, Tan); 7714514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 7724514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 7734514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> msg = GetCallArg(argv, 0); 7744514f5e3Sopenharmony_ci JSTaggedNumber numberValue = JSTaggedValue::ToNumber(thread, msg); 7754514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 7764514f5e3Sopenharmony_ci double value = numberValue.GetNumber(); 7774514f5e3Sopenharmony_ci double result = base::NAN_VALUE; 7784514f5e3Sopenharmony_ci // If value is NaN or -NaN, +infinite, -infinite, result is NaN 7794514f5e3Sopenharmony_ci if (std::isfinite(value)) { 7804514f5e3Sopenharmony_ci result = std::tan(value); 7814514f5e3Sopenharmony_ci } 7824514f5e3Sopenharmony_ci return GetTaggedDouble(result); 7834514f5e3Sopenharmony_ci} 7844514f5e3Sopenharmony_ci 7854514f5e3Sopenharmony_ci// 20.2.2.34 7864514f5e3Sopenharmony_ciJSTaggedValue BuiltinsMath::Tanh(EcmaRuntimeCallInfo *argv) 7874514f5e3Sopenharmony_ci{ 7884514f5e3Sopenharmony_ci ASSERT(argv); 7894514f5e3Sopenharmony_ci BUILTINS_API_TRACE(argv->GetThread(), Math, Tanh); 7904514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 7914514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 7924514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> msg = GetCallArg(argv, 0); 7934514f5e3Sopenharmony_ci JSTaggedNumber numberValue = JSTaggedValue::ToNumber(thread, msg); 7944514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 7954514f5e3Sopenharmony_ci double value = numberValue.GetNumber(); 7964514f5e3Sopenharmony_ci double result = base::NAN_VALUE; 7974514f5e3Sopenharmony_ci if (!std::isnan(std::abs(value))) { 7984514f5e3Sopenharmony_ci result = std::tanh(value); 7994514f5e3Sopenharmony_ci } 8004514f5e3Sopenharmony_ci return GetTaggedDouble(result); 8014514f5e3Sopenharmony_ci} 8024514f5e3Sopenharmony_ci 8034514f5e3Sopenharmony_ci// 20.2.2.35 8044514f5e3Sopenharmony_ciJSTaggedValue BuiltinsMath::Trunc(EcmaRuntimeCallInfo *argv) 8054514f5e3Sopenharmony_ci{ 8064514f5e3Sopenharmony_ci ASSERT(argv); 8074514f5e3Sopenharmony_ci BUILTINS_API_TRACE(argv->GetThread(), Math, Trunc); 8084514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 8094514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 8104514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> msg = GetCallArg(argv, 0); 8114514f5e3Sopenharmony_ci JSTaggedNumber numberValue = JSTaggedValue::ToNumber(thread, msg); 8124514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 8134514f5e3Sopenharmony_ci double value = numberValue.GetNumber(); 8144514f5e3Sopenharmony_ci double result = base::NAN_VALUE; 8154514f5e3Sopenharmony_ci if (!std::isfinite(value)) { 8164514f5e3Sopenharmony_ci // if value is +infinite, -infinite, NaN, -NaN, VRegisterTag is double 8174514f5e3Sopenharmony_ci if (!std::isnan(std::abs(value))) { 8184514f5e3Sopenharmony_ci // if value is +infinite, -infinite, result is value 8194514f5e3Sopenharmony_ci result = value; 8204514f5e3Sopenharmony_ci } 8214514f5e3Sopenharmony_ci } else { 8224514f5e3Sopenharmony_ci result = std::trunc(value); 8234514f5e3Sopenharmony_ci } 8244514f5e3Sopenharmony_ci return GetTaggedDouble(result); 8254514f5e3Sopenharmony_ci} 8264514f5e3Sopenharmony_ci} // namespace panda::ecmascript::builtins 827