blob: ebcdf2992a1edd2f71dfd9692f24c26099bf2521 [file] [log] [blame]
kocienda66a6d362001-08-24 14:24:45 +00001/*
kocienda66a6d362001-08-24 14:24:45 +00002 * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
oliver@apple.com524161e2013-07-25 04:02:47 +00003 * Copyright (C) 2007, 2008, 2013 Apple Inc. All Rights Reserved.
kocienda66a6d362001-08-24 14:24:45 +00004 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
mjscdff33b2006-01-23 21:41:36 +000017 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
mjs6f821c82002-03-22 00:31:57 +000018 *
kocienda66a6d362001-08-24 14:24:45 +000019 */
20
mjsb64c50a2005-10-03 21:13:12 +000021#include "config.h"
darin@apple.com5c0863d2008-06-16 04:17:44 +000022#include "MathObject.h"
kocienda66a6d362001-08-24 14:24:45 +000023
eric@webkit.org66cf5782010-04-21 14:09:49 +000024#include "Lookup.h"
weinig@apple.comee8c7802008-06-28 21:40:47 +000025#include "ObjectPrototype.h"
cwzwarich@webkit.org0b51a732008-11-05 23:21:32 +000026#include "Operations.h"
darin36d11362006-04-11 16:30:21 +000027#include <time.h>
ggaren7213ee02007-10-16 23:25:33 +000028#include <wtf/Assertions.h>
darindeaf0592007-10-27 19:10:40 +000029#include <wtf/MathExtras.h>
zimmermann@webkit.org1604d702008-12-16 21:15:22 +000030#include <wtf/RandomNumber.h>
oliver@apple.comf5e59da2009-02-13 09:18:43 +000031#include <wtf/RandomNumberSeed.h>
darin36d11362006-04-11 16:30:21 +000032
cwzwarich@webkit.org3f782f62008-09-08 01:28:33 +000033namespace JSC {
kocienda66a6d362001-08-24 14:24:45 +000034
andersca@apple.com7de5aae2013-09-05 20:12:23 +000035STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(MathObject);
ggaren@apple.comfea43532008-08-17 20:23:49 +000036
barraclough@apple.com99ff3432010-06-03 20:00:18 +000037static EncodedJSValue JSC_HOST_CALL mathProtoFuncAbs(ExecState*);
38static EncodedJSValue JSC_HOST_CALL mathProtoFuncACos(ExecState*);
39static EncodedJSValue JSC_HOST_CALL mathProtoFuncASin(ExecState*);
40static EncodedJSValue JSC_HOST_CALL mathProtoFuncATan(ExecState*);
41static EncodedJSValue JSC_HOST_CALL mathProtoFuncATan2(ExecState*);
42static EncodedJSValue JSC_HOST_CALL mathProtoFuncCeil(ExecState*);
43static EncodedJSValue JSC_HOST_CALL mathProtoFuncCos(ExecState*);
44static EncodedJSValue JSC_HOST_CALL mathProtoFuncExp(ExecState*);
45static EncodedJSValue JSC_HOST_CALL mathProtoFuncFloor(ExecState*);
46static EncodedJSValue JSC_HOST_CALL mathProtoFuncLog(ExecState*);
47static EncodedJSValue JSC_HOST_CALL mathProtoFuncMax(ExecState*);
48static EncodedJSValue JSC_HOST_CALL mathProtoFuncMin(ExecState*);
49static EncodedJSValue JSC_HOST_CALL mathProtoFuncPow(ExecState*);
50static EncodedJSValue JSC_HOST_CALL mathProtoFuncRandom(ExecState*);
51static EncodedJSValue JSC_HOST_CALL mathProtoFuncRound(ExecState*);
52static EncodedJSValue JSC_HOST_CALL mathProtoFuncSin(ExecState*);
53static EncodedJSValue JSC_HOST_CALL mathProtoFuncSqrt(ExecState*);
54static EncodedJSValue JSC_HOST_CALL mathProtoFuncTan(ExecState*);
oliver@apple.com64367322013-04-26 00:41:38 +000055static EncodedJSValue JSC_HOST_CALL mathProtoFuncIMul(ExecState*);
darin@apple.com1edff432008-06-24 05:23:17 +000056
57}
58
cwzwarich@webkit.org3f782f62008-09-08 01:28:33 +000059namespace JSC {
darin@apple.com1edff432008-06-24 05:23:17 +000060
oliver@apple.com524161e2013-07-25 04:02:47 +000061const ClassInfo MathObject::s_info = { "Math", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(MathObject) };
mjs6f821c82002-03-22 00:31:57 +000062
akling@apple.com3828a862013-09-30 21:41:04 +000063MathObject::MathObject(VM& vm, Structure* structure)
64 : JSNonFinalObject(vm, structure)
kocienda66a6d362001-08-24 14:24:45 +000065{
commit-queue@webkit.org6e5671b2011-09-01 23:49:23 +000066}
67
akling@apple.com3828a862013-09-30 21:41:04 +000068void MathObject::finishCreation(VM& vm, JSGlobalObject* globalObject)
commit-queue@webkit.org6e5671b2011-09-01 23:49:23 +000069{
akling@apple.com3828a862013-09-30 21:41:04 +000070 Base::finishCreation(vm);
fpizlo@apple.com10ae2d02013-08-14 02:41:47 +000071 ASSERT(inherits(info()));
barraclough@apple.com737a1582011-02-21 19:31:42 +000072
akling@apple.com3828a862013-09-30 21:41:04 +000073 putDirectWithoutTransition(vm, Identifier(&vm, "E"), jsNumber(exp(1.0)), DontDelete | DontEnum | ReadOnly);
74 putDirectWithoutTransition(vm, Identifier(&vm, "LN2"), jsNumber(log(2.0)), DontDelete | DontEnum | ReadOnly);
75 putDirectWithoutTransition(vm, Identifier(&vm, "LN10"), jsNumber(log(10.0)), DontDelete | DontEnum | ReadOnly);
76 putDirectWithoutTransition(vm, Identifier(&vm, "LOG2E"), jsNumber(1.0 / log(2.0)), DontDelete | DontEnum | ReadOnly);
77 putDirectWithoutTransition(vm, Identifier(&vm, "LOG10E"), jsNumber(0.4342944819032518), DontDelete | DontEnum | ReadOnly);
78 putDirectWithoutTransition(vm, Identifier(&vm, "PI"), jsNumber(piDouble), DontDelete | DontEnum | ReadOnly);
79 putDirectWithoutTransition(vm, Identifier(&vm, "SQRT1_2"), jsNumber(sqrt(0.5)), DontDelete | DontEnum | ReadOnly);
80 putDirectWithoutTransition(vm, Identifier(&vm, "SQRT2"), jsNumber(sqrt(2.0)), DontDelete | DontEnum | ReadOnly);
kocienda66a6d362001-08-24 14:24:45 +000081
akling@apple.com3828a862013-09-30 21:41:04 +000082 putDirectNativeFunctionWithoutTransition(vm, globalObject, Identifier(&vm, "abs"), 1, mathProtoFuncAbs, AbsIntrinsic, DontEnum | Function);
83 putDirectNativeFunctionWithoutTransition(vm, globalObject, Identifier(&vm, "acos"), 1, mathProtoFuncACos, NoIntrinsic, DontEnum | Function);
84 putDirectNativeFunctionWithoutTransition(vm, globalObject, Identifier(&vm, "asin"), 1, mathProtoFuncASin, NoIntrinsic, DontEnum | Function);
85 putDirectNativeFunctionWithoutTransition(vm, globalObject, Identifier(&vm, "atan"), 1, mathProtoFuncATan, NoIntrinsic, DontEnum | Function);
86 putDirectNativeFunctionWithoutTransition(vm, globalObject, Identifier(&vm, "atan2"), 2, mathProtoFuncATan2, NoIntrinsic, DontEnum | Function);
87 putDirectNativeFunctionWithoutTransition(vm, globalObject, Identifier(&vm, "ceil"), 1, mathProtoFuncCeil, CeilIntrinsic, DontEnum | Function);
88 putDirectNativeFunctionWithoutTransition(vm, globalObject, Identifier(&vm, "cos"), 1, mathProtoFuncCos, NoIntrinsic, DontEnum | Function);
89 putDirectNativeFunctionWithoutTransition(vm, globalObject, Identifier(&vm, "exp"), 1, mathProtoFuncExp, ExpIntrinsic, DontEnum | Function);
90 putDirectNativeFunctionWithoutTransition(vm, globalObject, Identifier(&vm, "floor"), 1, mathProtoFuncFloor, FloorIntrinsic, DontEnum | Function);
91 putDirectNativeFunctionWithoutTransition(vm, globalObject, Identifier(&vm, "log"), 1, mathProtoFuncLog, LogIntrinsic, DontEnum | Function);
92 putDirectNativeFunctionWithoutTransition(vm, globalObject, Identifier(&vm, "max"), 2, mathProtoFuncMax, MaxIntrinsic, DontEnum | Function);
93 putDirectNativeFunctionWithoutTransition(vm, globalObject, Identifier(&vm, "min"), 2, mathProtoFuncMin, MinIntrinsic, DontEnum | Function);
94 putDirectNativeFunctionWithoutTransition(vm, globalObject, Identifier(&vm, "pow"), 2, mathProtoFuncPow, PowIntrinsic, DontEnum | Function);
95 putDirectNativeFunctionWithoutTransition(vm, globalObject, Identifier(&vm, "random"), 0, mathProtoFuncRandom, NoIntrinsic, DontEnum | Function);
96 putDirectNativeFunctionWithoutTransition(vm, globalObject, Identifier(&vm, "round"), 1, mathProtoFuncRound, RoundIntrinsic, DontEnum | Function);
97 putDirectNativeFunctionWithoutTransition(vm, globalObject, Identifier(&vm, "sin"), 1, mathProtoFuncSin, NoIntrinsic, DontEnum | Function);
98 putDirectNativeFunctionWithoutTransition(vm, globalObject, Identifier(&vm, "sqrt"), 1, mathProtoFuncSqrt, SqrtIntrinsic, DontEnum | Function);
99 putDirectNativeFunctionWithoutTransition(vm, globalObject, Identifier(&vm, "tan"), 1, mathProtoFuncTan, NoIntrinsic, DontEnum | Function);
100 putDirectNativeFunctionWithoutTransition(vm, globalObject, Identifier(&vm, "imul"), 1, mathProtoFuncIMul, IMulIntrinsic, DontEnum | Function);
kocienda66a6d362001-08-24 14:24:45 +0000101}
102
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000103// ------------------------------ Functions --------------------------------
104
barraclough@apple.com99ff3432010-06-03 20:00:18 +0000105EncodedJSValue JSC_HOST_CALL mathProtoFuncAbs(ExecState* exec)
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000106{
oliver@apple.com5b67d9e2010-10-25 22:40:53 +0000107 return JSValue::encode(jsNumber(fabs(exec->argument(0).toNumber(exec))));
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000108}
109
barraclough@apple.com99ff3432010-06-03 20:00:18 +0000110EncodedJSValue JSC_HOST_CALL mathProtoFuncACos(ExecState* exec)
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000111{
oliver@apple.com5b67d9e2010-10-25 22:40:53 +0000112 return JSValue::encode(jsDoubleNumber(acos(exec->argument(0).toNumber(exec))));
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000113}
114
barraclough@apple.com99ff3432010-06-03 20:00:18 +0000115EncodedJSValue JSC_HOST_CALL mathProtoFuncASin(ExecState* exec)
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000116{
oliver@apple.com5b67d9e2010-10-25 22:40:53 +0000117 return JSValue::encode(jsDoubleNumber(asin(exec->argument(0).toNumber(exec))));
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000118}
119
barraclough@apple.com99ff3432010-06-03 20:00:18 +0000120EncodedJSValue JSC_HOST_CALL mathProtoFuncATan(ExecState* exec)
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000121{
oliver@apple.com5b67d9e2010-10-25 22:40:53 +0000122 return JSValue::encode(jsDoubleNumber(atan(exec->argument(0).toNumber(exec))));
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000123}
124
barraclough@apple.com99ff3432010-06-03 20:00:18 +0000125EncodedJSValue JSC_HOST_CALL mathProtoFuncATan2(ExecState* exec)
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000126{
commit-queue@webkit.org4bf477e2010-09-26 21:38:31 +0000127 double arg0 = exec->argument(0).toNumber(exec);
128 double arg1 = exec->argument(1).toNumber(exec);
oliver@apple.com5b67d9e2010-10-25 22:40:53 +0000129 return JSValue::encode(jsDoubleNumber(atan2(arg0, arg1)));
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000130}
131
barraclough@apple.com99ff3432010-06-03 20:00:18 +0000132EncodedJSValue JSC_HOST_CALL mathProtoFuncCeil(ExecState* exec)
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000133{
oliver@apple.com5b67d9e2010-10-25 22:40:53 +0000134 return JSValue::encode(jsNumber(ceil(exec->argument(0).toNumber(exec))));
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000135}
136
barraclough@apple.com99ff3432010-06-03 20:00:18 +0000137EncodedJSValue JSC_HOST_CALL mathProtoFuncCos(ExecState* exec)
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000138{
commit-queue@webkit.orgeca54fb2013-10-30 17:47:32 +0000139 return JSValue::encode(exec->vm().cachedCos(exec->argument(0).toNumber(exec)));
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000140}
141
barraclough@apple.com99ff3432010-06-03 20:00:18 +0000142EncodedJSValue JSC_HOST_CALL mathProtoFuncExp(ExecState* exec)
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000143{
oliver@apple.com5b67d9e2010-10-25 22:40:53 +0000144 return JSValue::encode(jsDoubleNumber(exp(exec->argument(0).toNumber(exec))));
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000145}
146
barraclough@apple.com99ff3432010-06-03 20:00:18 +0000147EncodedJSValue JSC_HOST_CALL mathProtoFuncFloor(ExecState* exec)
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000148{
oliver@apple.com5b67d9e2010-10-25 22:40:53 +0000149 return JSValue::encode(jsNumber(floor(exec->argument(0).toNumber(exec))));
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000150}
151
barraclough@apple.com99ff3432010-06-03 20:00:18 +0000152EncodedJSValue JSC_HOST_CALL mathProtoFuncLog(ExecState* exec)
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000153{
oliver@apple.com5b67d9e2010-10-25 22:40:53 +0000154 return JSValue::encode(jsDoubleNumber(log(exec->argument(0).toNumber(exec))));
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000155}
156
barraclough@apple.com99ff3432010-06-03 20:00:18 +0000157EncodedJSValue JSC_HOST_CALL mathProtoFuncMax(ExecState* exec)
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000158{
ggaren@apple.comfea29f12010-05-29 06:33:05 +0000159 unsigned argsCount = exec->argumentCount();
barraclough@apple.comf1fa5792011-06-11 02:03:00 +0000160 double result = -std::numeric_limits<double>::infinity();
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000161 for (unsigned k = 0; k < argsCount; ++k) {
darin@apple.comd9b22132013-09-22 04:02:59 +0000162 double val = exec->uncheckedArgument(k).toNumber(exec);
zandobersek@gmail.com9182d472013-02-13 23:01:21 +0000163 if (std::isnan(val)) {
fpizlo@apple.com3494d022012-11-05 18:15:23 +0000164 result = QNaN;
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000165 break;
166 }
zandobersek@gmail.com8c24b7a2013-02-18 17:13:23 +0000167 if (val > result || (!val && !result && !std::signbit(val)))
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000168 result = val;
169 }
oliver@apple.com5b67d9e2010-10-25 22:40:53 +0000170 return JSValue::encode(jsNumber(result));
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000171}
172
barraclough@apple.com99ff3432010-06-03 20:00:18 +0000173EncodedJSValue JSC_HOST_CALL mathProtoFuncMin(ExecState* exec)
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000174{
ggaren@apple.comfea29f12010-05-29 06:33:05 +0000175 unsigned argsCount = exec->argumentCount();
barraclough@apple.comf1fa5792011-06-11 02:03:00 +0000176 double result = +std::numeric_limits<double>::infinity();
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000177 for (unsigned k = 0; k < argsCount; ++k) {
darin@apple.comd9b22132013-09-22 04:02:59 +0000178 double val = exec->uncheckedArgument(k).toNumber(exec);
zandobersek@gmail.com9182d472013-02-13 23:01:21 +0000179 if (std::isnan(val)) {
fpizlo@apple.com3494d022012-11-05 18:15:23 +0000180 result = QNaN;
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000181 break;
182 }
zandobersek@gmail.com8c24b7a2013-02-18 17:13:23 +0000183 if (val < result || (!val && !result && std::signbit(val)))
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000184 result = val;
185 }
oliver@apple.com5b67d9e2010-10-25 22:40:53 +0000186 return JSValue::encode(jsNumber(result));
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000187}
188
barraclough@apple.com48386932012-06-08 00:29:27 +0000189#if PLATFORM(IOS) && CPU(ARM_THUMB2)
190
191static double fdlibmPow(double x, double y);
192
193static ALWAYS_INLINE bool isDenormal(double x)
194{
195 static const uint64_t signbit = 0x8000000000000000ULL;
196 static const uint64_t minNormal = 0x0001000000000000ULL;
197 return (bitwise_cast<uint64_t>(x) & ~signbit) - 1 < minNormal - 1;
198}
199
200static ALWAYS_INLINE bool isEdgeCase(double x)
201{
202 static const uint64_t signbit = 0x8000000000000000ULL;
203 static const uint64_t infinity = 0x7fffffffffffffffULL;
204 return (bitwise_cast<uint64_t>(x) & ~signbit) - 1 >= infinity - 1;
205}
206
207static ALWAYS_INLINE double mathPow(double x, double y)
208{
209 if (!isDenormal(x) && !isDenormal(y)) {
210 double libmResult = pow(x,y);
211 if (libmResult || isEdgeCase(x) || isEdgeCase(y))
212 return libmResult;
213 }
214 return fdlibmPow(x,y);
215}
216
217#else
218
219ALWAYS_INLINE double mathPow(double x, double y)
220{
221 return pow(x, y);
222}
223
224#endif
225
barraclough@apple.com99ff3432010-06-03 20:00:18 +0000226EncodedJSValue JSC_HOST_CALL mathProtoFuncPow(ExecState* exec)
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000227{
228 // ECMA 15.8.2.1.13
229
ggaren@apple.comfea29f12010-05-29 06:33:05 +0000230 double arg = exec->argument(0).toNumber(exec);
231 double arg2 = exec->argument(1).toNumber(exec);
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000232
zandobersek@gmail.com9182d472013-02-13 23:01:21 +0000233 if (std::isnan(arg2))
oliver@apple.com5b67d9e2010-10-25 22:40:53 +0000234 return JSValue::encode(jsNaN());
zandobersek@gmail.com9182d472013-02-13 23:01:21 +0000235 if (std::isinf(arg2) && fabs(arg) == 1)
oliver@apple.com5b67d9e2010-10-25 22:40:53 +0000236 return JSValue::encode(jsNaN());
barraclough@apple.com48386932012-06-08 00:29:27 +0000237 return JSValue::encode(jsNumber(mathPow(arg, arg2)));
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000238}
mjs6f821c82002-03-22 00:31:57 +0000239
barraclough@apple.com99ff3432010-06-03 20:00:18 +0000240EncodedJSValue JSC_HOST_CALL mathProtoFuncRandom(ExecState* exec)
kocienda66a6d362001-08-24 14:24:45 +0000241{
oliver@apple.com5b67d9e2010-10-25 22:40:53 +0000242 return JSValue::encode(jsDoubleNumber(exec->lexicalGlobalObject()->weakRandomNumber()));
kocienda66a6d362001-08-24 14:24:45 +0000243}
244
barraclough@apple.com99ff3432010-06-03 20:00:18 +0000245EncodedJSValue JSC_HOST_CALL mathProtoFuncRound(ExecState* exec)
mjs6f821c82002-03-22 00:31:57 +0000246{
ggaren@apple.comfea29f12010-05-29 06:33:05 +0000247 double arg = exec->argument(0).toNumber(exec);
tkent@chromium.org5dc0b632010-02-02 04:42:43 +0000248 double integer = ceil(arg);
oliver@apple.com5b67d9e2010-10-25 22:40:53 +0000249 return JSValue::encode(jsNumber(integer - (integer - arg > 0.5)));
kocienda66a6d362001-08-24 14:24:45 +0000250}
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000251
barraclough@apple.com99ff3432010-06-03 20:00:18 +0000252EncodedJSValue JSC_HOST_CALL mathProtoFuncSin(ExecState* exec)
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000253{
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000254 return JSValue::encode(exec->vm().cachedSin(exec->argument(0).toNumber(exec)));
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000255}
256
barraclough@apple.com99ff3432010-06-03 20:00:18 +0000257EncodedJSValue JSC_HOST_CALL mathProtoFuncSqrt(ExecState* exec)
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000258{
oliver@apple.com5b67d9e2010-10-25 22:40:53 +0000259 return JSValue::encode(jsDoubleNumber(sqrt(exec->argument(0).toNumber(exec))));
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000260}
261
barraclough@apple.com99ff3432010-06-03 20:00:18 +0000262EncodedJSValue JSC_HOST_CALL mathProtoFuncTan(ExecState* exec)
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000263{
oliver@apple.com5b67d9e2010-10-25 22:40:53 +0000264 return JSValue::encode(jsDoubleNumber(tan(exec->argument(0).toNumber(exec))));
weinig@apple.coma73c15f2007-11-08 20:31:26 +0000265}
266
oliver@apple.com64367322013-04-26 00:41:38 +0000267EncodedJSValue JSC_HOST_CALL mathProtoFuncIMul(ExecState* exec)
268{
269 int32_t left = exec->argument(0).toInt32(exec);
270 if (exec->hadException())
271 return JSValue::encode(jsNull());
272 int32_t right = exec->argument(1).toInt32(exec);
273 return JSValue::encode(jsNumber(left * right));
274}
275
barraclough@apple.com48386932012-06-08 00:29:27 +0000276#if PLATFORM(IOS) && CPU(ARM_THUMB2)
277
278// The following code is taken from netlib.org:
279// http://www.netlib.org/fdlibm/fdlibm.h
280// http://www.netlib.org/fdlibm/e_pow.c
281// http://www.netlib.org/fdlibm/s_scalbn.c
282//
283// And was originally distributed under the following license:
284
285/*
286 * ====================================================
287 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
288 *
289 * Developed at SunSoft, a Sun Microsystems, Inc. business.
290 * Permission to use, copy, modify, and distribute this
291 * software is freely granted, provided that this notice
292 * is preserved.
293 * ====================================================
294 */
295/*
296 * ====================================================
297 * Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved.
298 *
299 * Permission to use, copy, modify, and distribute this
300 * software is freely granted, provided that this notice
301 * is preserved.
302 * ====================================================
303 */
304
305/* __ieee754_pow(x,y) return x**y
306 *
307 * n
308 * Method: Let x = 2 * (1+f)
309 * 1. Compute and return log2(x) in two pieces:
310 * log2(x) = w1 + w2,
311 * where w1 has 53-24 = 29 bit trailing zeros.
312 * 2. Perform y*log2(x) = n+y' by simulating muti-precision
313 * arithmetic, where |y'|<=0.5.
314 * 3. Return x**y = 2**n*exp(y'*log2)
315 *
316 * Special cases:
317 * 1. (anything) ** 0 is 1
318 * 2. (anything) ** 1 is itself
319 * 3. (anything) ** NAN is NAN
320 * 4. NAN ** (anything except 0) is NAN
321 * 5. +-(|x| > 1) ** +INF is +INF
322 * 6. +-(|x| > 1) ** -INF is +0
323 * 7. +-(|x| < 1) ** +INF is +0
324 * 8. +-(|x| < 1) ** -INF is +INF
325 * 9. +-1 ** +-INF is NAN
326 * 10. +0 ** (+anything except 0, NAN) is +0
327 * 11. -0 ** (+anything except 0, NAN, odd integer) is +0
328 * 12. +0 ** (-anything except 0, NAN) is +INF
329 * 13. -0 ** (-anything except 0, NAN, odd integer) is +INF
330 * 14. -0 ** (odd integer) = -( +0 ** (odd integer) )
331 * 15. +INF ** (+anything except 0,NAN) is +INF
332 * 16. +INF ** (-anything except 0,NAN) is +0
333 * 17. -INF ** (anything) = -0 ** (-anything)
334 * 18. (-anything) ** (integer) is (-1)**(integer)*(+anything**integer)
335 * 19. (-anything except 0 and inf) ** (non-integer) is NAN
336 *
337 * Accuracy:
338 * pow(x,y) returns x**y nearly rounded. In particular
339 * pow(integer,integer)
340 * always returns the correct integer provided it is
341 * representable.
342 *
343 * Constants :
344 * The hexadecimal values are the intended ones for the following
345 * constants. The decimal values may be used, provided that the
346 * compiler will convert from decimal to binary accurately enough
347 * to produce the hexadecimal values shown.
348 */
349
350#define __HI(x) *(1+(int*)&x)
351#define __LO(x) *(int*)&x
352
353static const double
354bp[] = {1.0, 1.5,},
355dp_h[] = { 0.0, 5.84962487220764160156e-01,}, /* 0x3FE2B803, 0x40000000 */
356dp_l[] = { 0.0, 1.35003920212974897128e-08,}, /* 0x3E4CFDEB, 0x43CFD006 */
357zero = 0.0,
358one = 1.0,
359two = 2.0,
360two53 = 9007199254740992.0, /* 0x43400000, 0x00000000 */
361huge = 1.0e300,
362tiny = 1.0e-300,
363 /* for scalbn */
364two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */
365twom54 = 5.55111512312578270212e-17, /* 0x3C900000, 0x00000000 */
366 /* poly coefs for (3/2)*(log(x)-2s-2/3*s**3 */
367L1 = 5.99999999999994648725e-01, /* 0x3FE33333, 0x33333303 */
368L2 = 4.28571428578550184252e-01, /* 0x3FDB6DB6, 0xDB6FABFF */
369L3 = 3.33333329818377432918e-01, /* 0x3FD55555, 0x518F264D */
370L4 = 2.72728123808534006489e-01, /* 0x3FD17460, 0xA91D4101 */
371L5 = 2.30660745775561754067e-01, /* 0x3FCD864A, 0x93C9DB65 */
372L6 = 2.06975017800338417784e-01, /* 0x3FCA7E28, 0x4A454EEF */
373P1 = 1.66666666666666019037e-01, /* 0x3FC55555, 0x5555553E */
374P2 = -2.77777777770155933842e-03, /* 0xBF66C16C, 0x16BEBD93 */
375P3 = 6.61375632143793436117e-05, /* 0x3F11566A, 0xAF25DE2C */
376P4 = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */
377P5 = 4.13813679705723846039e-08, /* 0x3E663769, 0x72BEA4D0 */
378lg2 = 6.93147180559945286227e-01, /* 0x3FE62E42, 0xFEFA39EF */
379lg2_h = 6.93147182464599609375e-01, /* 0x3FE62E43, 0x00000000 */
380lg2_l = -1.90465429995776804525e-09, /* 0xBE205C61, 0x0CA86C39 */
381ovt = 8.0085662595372944372e-0017, /* -(1024-log2(ovfl+.5ulp)) */
382cp = 9.61796693925975554329e-01, /* 0x3FEEC709, 0xDC3A03FD =2/(3ln2) */
383cp_h = 9.61796700954437255859e-01, /* 0x3FEEC709, 0xE0000000 =(float)cp */
384cp_l = -7.02846165095275826516e-09, /* 0xBE3E2FE0, 0x145B01F5 =tail of cp_h*/
385ivln2 = 1.44269504088896338700e+00, /* 0x3FF71547, 0x652B82FE =1/ln2 */
386ivln2_h = 1.44269502162933349609e+00, /* 0x3FF71547, 0x60000000 =24b 1/ln2*/
387ivln2_l = 1.92596299112661746887e-08; /* 0x3E54AE0B, 0xF85DDF44 =1/ln2 tail*/
388
389inline double fdlibmScalbn (double x, int n)
390{
391 int k,hx,lx;
392 hx = __HI(x);
393 lx = __LO(x);
394 k = (hx&0x7ff00000)>>20; /* extract exponent */
395 if (k==0) { /* 0 or subnormal x */
396 if ((lx|(hx&0x7fffffff))==0) return x; /* +-0 */
397 x *= two54;
398 hx = __HI(x);
399 k = ((hx&0x7ff00000)>>20) - 54;
400 if (n< -50000) return tiny*x; /*underflow*/
401 }
402 if (k==0x7ff) return x+x; /* NaN or Inf */
403 k = k+n;
404 if (k > 0x7fe) return huge*copysign(huge,x); /* overflow */
405 if (k > 0) /* normal result */
406 {__HI(x) = (hx&0x800fffff)|(k<<20); return x;}
407 if (k <= -54) {
408 if (n > 50000) /* in case integer overflow in n+k */
409 return huge*copysign(huge,x); /*overflow*/
410 else return tiny*copysign(tiny,x); /*underflow*/
411 }
412 k += 54; /* subnormal result */
413 __HI(x) = (hx&0x800fffff)|(k<<20);
414 return x*twom54;
415}
416
417double fdlibmPow(double x, double y)
418{
419 double z,ax,z_h,z_l,p_h,p_l;
420 double y1,t1,t2,r,s,t,u,v,w;
421 int i0,i1,i,j,k,yisint,n;
422 int hx,hy,ix,iy;
423 unsigned lx,ly;
424
425 i0 = ((*(int*)&one)>>29)^1; i1=1-i0;
426 hx = __HI(x); lx = __LO(x);
427 hy = __HI(y); ly = __LO(y);
428 ix = hx&0x7fffffff; iy = hy&0x7fffffff;
429
430 /* y==zero: x**0 = 1 */
431 if((iy|ly)==0) return one;
432
433 /* +-NaN return x+y */
434 if(ix > 0x7ff00000 || ((ix==0x7ff00000)&&(lx!=0)) ||
435 iy > 0x7ff00000 || ((iy==0x7ff00000)&&(ly!=0)))
436 return x+y;
437
438 /* determine if y is an odd int when x < 0
439 * yisint = 0 ... y is not an integer
440 * yisint = 1 ... y is an odd int
441 * yisint = 2 ... y is an even int
442 */
443 yisint = 0;
444 if(hx<0) {
445 if(iy>=0x43400000) yisint = 2; /* even integer y */
446 else if(iy>=0x3ff00000) {
447 k = (iy>>20)-0x3ff; /* exponent */
448 if(k>20) {
449 j = ly>>(52-k);
450 if(static_cast<unsigned>(j<<(52-k))==ly) yisint = 2-(j&1);
451 } else if(ly==0) {
452 j = iy>>(20-k);
453 if((j<<(20-k))==iy) yisint = 2-(j&1);
454 }
455 }
456 }
457
458 /* special value of y */
459 if(ly==0) {
460 if (iy==0x7ff00000) { /* y is +-inf */
461 if(((ix-0x3ff00000)|lx)==0)
462 return y - y; /* inf**+-1 is NaN */
463 else if (ix >= 0x3ff00000)/* (|x|>1)**+-inf = inf,0 */
464 return (hy>=0)? y: zero;
465 else /* (|x|<1)**-,+inf = inf,0 */
466 return (hy<0)?-y: zero;
467 }
468 if(iy==0x3ff00000) { /* y is +-1 */
469 if(hy<0) return one/x; else return x;
470 }
471 if(hy==0x40000000) return x*x; /* y is 2 */
472 if(hy==0x3fe00000) { /* y is 0.5 */
473 if(hx>=0) /* x >= +0 */
474 return sqrt(x);
475 }
476 }
477
478 ax = fabs(x);
479 /* special value of x */
480 if(lx==0) {
481 if(ix==0x7ff00000||ix==0||ix==0x3ff00000){
482 z = ax; /*x is +-0,+-inf,+-1*/
483 if(hy<0) z = one/z; /* z = (1/|x|) */
484 if(hx<0) {
485 if(((ix-0x3ff00000)|yisint)==0) {
486 z = (z-z)/(z-z); /* (-1)**non-int is NaN */
487 } else if(yisint==1)
488 z = -z; /* (x<0)**odd = -(|x|**odd) */
489 }
490 return z;
491 }
492 }
493
494 n = (hx>>31)+1;
495
496 /* (x<0)**(non-int) is NaN */
497 if((n|yisint)==0) return (x-x)/(x-x);
498
499 s = one; /* s (sign of result -ve**odd) = -1 else = 1 */
500 if((n|(yisint-1))==0) s = -one;/* (-ve)**(odd int) */
501
502 /* |y| is huge */
503 if(iy>0x41e00000) { /* if |y| > 2**31 */
504 if(iy>0x43f00000){ /* if |y| > 2**64, must o/uflow */
505 if(ix<=0x3fefffff) return (hy<0)? huge*huge:tiny*tiny;
506 if(ix>=0x3ff00000) return (hy>0)? huge*huge:tiny*tiny;
507 }
508 /* over/underflow if x is not close to one */
509 if(ix<0x3fefffff) return (hy<0)? s*huge*huge:s*tiny*tiny;
510 if(ix>0x3ff00000) return (hy>0)? s*huge*huge:s*tiny*tiny;
511 /* now |1-x| is tiny <= 2**-20, suffice to compute
512 log(x) by x-x^2/2+x^3/3-x^4/4 */
513 t = ax-one; /* t has 20 trailing zeros */
514 w = (t*t)*(0.5-t*(0.3333333333333333333333-t*0.25));
515 u = ivln2_h*t; /* ivln2_h has 21 sig. bits */
516 v = t*ivln2_l-w*ivln2;
517 t1 = u+v;
518 __LO(t1) = 0;
519 t2 = v-(t1-u);
520 } else {
521 double ss,s2,s_h,s_l,t_h,t_l;
522 n = 0;
523 /* take care subnormal number */
524 if(ix<0x00100000)
525 {ax *= two53; n -= 53; ix = __HI(ax); }
526 n += ((ix)>>20)-0x3ff;
527 j = ix&0x000fffff;
528 /* determine interval */
529 ix = j|0x3ff00000; /* normalize ix */
530 if(j<=0x3988E) k=0; /* |x|<sqrt(3/2) */
531 else if(j<0xBB67A) k=1; /* |x|<sqrt(3) */
532 else {k=0;n+=1;ix -= 0x00100000;}
533 __HI(ax) = ix;
534
535 /* compute ss = s_h+s_l = (x-1)/(x+1) or (x-1.5)/(x+1.5) */
536 u = ax-bp[k]; /* bp[0]=1.0, bp[1]=1.5 */
537 v = one/(ax+bp[k]);
538 ss = u*v;
539 s_h = ss;
540 __LO(s_h) = 0;
541 /* t_h=ax+bp[k] High */
542 t_h = zero;
543 __HI(t_h)=((ix>>1)|0x20000000)+0x00080000+(k<<18);
544 t_l = ax - (t_h-bp[k]);
545 s_l = v*((u-s_h*t_h)-s_h*t_l);
546 /* compute log(ax) */
547 s2 = ss*ss;
548 r = s2*s2*(L1+s2*(L2+s2*(L3+s2*(L4+s2*(L5+s2*L6)))));
549 r += s_l*(s_h+ss);
550 s2 = s_h*s_h;
551 t_h = 3.0+s2+r;
552 __LO(t_h) = 0;
553 t_l = r-((t_h-3.0)-s2);
554 /* u+v = ss*(1+...) */
555 u = s_h*t_h;
556 v = s_l*t_h+t_l*ss;
557 /* 2/(3log2)*(ss+...) */
558 p_h = u+v;
559 __LO(p_h) = 0;
560 p_l = v-(p_h-u);
561 z_h = cp_h*p_h; /* cp_h+cp_l = 2/(3*log2) */
562 z_l = cp_l*p_h+p_l*cp+dp_l[k];
563 /* log2(ax) = (ss+..)*2/(3*log2) = n + dp_h + z_h + z_l */
564 t = (double)n;
565 t1 = (((z_h+z_l)+dp_h[k])+t);
566 __LO(t1) = 0;
567 t2 = z_l-(((t1-t)-dp_h[k])-z_h);
568 }
569
570 /* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */
571 y1 = y;
572 __LO(y1) = 0;
573 p_l = (y-y1)*t1+y*t2;
574 p_h = y1*t1;
575 z = p_l+p_h;
576 j = __HI(z);
577 i = __LO(z);
578 if (j>=0x40900000) { /* z >= 1024 */
579 if(((j-0x40900000)|i)!=0) /* if z > 1024 */
580 return s*huge*huge; /* overflow */
581 else {
582 if(p_l+ovt>z-p_h) return s*huge*huge; /* overflow */
583 }
584 } else if((j&0x7fffffff)>=0x4090cc00 ) { /* z <= -1075 */
585 if(((j-0xc090cc00)|i)!=0) /* z < -1075 */
586 return s*tiny*tiny; /* underflow */
587 else {
588 if(p_l<=z-p_h) return s*tiny*tiny; /* underflow */
589 }
590 }
591 /*
592 * compute 2**(p_h+p_l)
593 */
594 i = j&0x7fffffff;
595 k = (i>>20)-0x3ff;
596 n = 0;
597 if(i>0x3fe00000) { /* if |z| > 0.5, set n = [z+0.5] */
598 n = j+(0x00100000>>(k+1));
599 k = ((n&0x7fffffff)>>20)-0x3ff; /* new k for n */
600 t = zero;
601 __HI(t) = (n&~(0x000fffff>>k));
602 n = ((n&0x000fffff)|0x00100000)>>(20-k);
603 if(j<0) n = -n;
604 p_h -= t;
605 }
606 t = p_l+p_h;
607 __LO(t) = 0;
608 u = t*lg2_h;
609 v = (p_l-(t-p_h))*lg2+t*lg2_l;
610 z = u+v;
611 w = v-(z-u);
612 t = z*z;
613 t1 = z - t*(P1+t*(P2+t*(P3+t*(P4+t*P5))));
614 r = (z*t1)/(t1-two)-(w+z*w);
615 z = one-(r-z);
616 j = __HI(z);
617 j += (n<<20);
618 if((j>>20)<=0) z = fdlibmScalbn(z,n); /* subnormal output */
619 else __HI(z) += (n<<20);
620 return s*z;
621}
622
623#endif
624
cwzwarich@webkit.org3f782f62008-09-08 01:28:33 +0000625} // namespace JSC