1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 2 * vim: set ts=8 sts=4 et sw=4 tw=99: 3 * This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef jsmath_h 8 #define jsmath_h 9 10 #include "mozilla/MemoryReporting.h" 11 12 #include <cmath> 13 14 #include "NamespaceImports.h" 15 16 namespace js { 17 18 typedef double (*UnaryFunType)(double); 19 20 class MathCache 21 { 22 public: 23 enum MathFuncId { 24 Zero, 25 Sin, Cos, Tan, Sinh, Cosh, Tanh, Asin, Acos, Atan, Asinh, Acosh, Atanh, 26 Sqrt, Log, Log10, Log2, Log1p, Exp, Expm1, Cbrt, Trunc, Sign 27 }; 28 29 private: 30 static const unsigned SizeLog2 = 12; 31 static const unsigned Size = 1 << SizeLog2; 32 struct Entry { double in; MathFuncId id; double out; }; 33 Entry table[Size]; 34 35 public: 36 MathCache(); 37 hash(double x,MathFuncId id)38 unsigned hash(double x, MathFuncId id) { 39 union { double d; struct { uint32_t one, two; } s; } u = { x }; 40 uint32_t hash32 = u.s.one ^ u.s.two; 41 hash32 += uint32_t(id) << 8; 42 uint16_t hash16 = uint16_t(hash32 ^ (hash32 >> 16)); 43 return (hash16 & (Size - 1)) ^ (hash16 >> (16 - SizeLog2)); 44 } 45 46 /* 47 * N.B. lookup uses double-equality. This is only safe if hash() maps +0 48 * and -0 to different table entries, which is asserted in MathCache(). 49 */ lookup(UnaryFunType f,double x,MathFuncId id)50 double lookup(UnaryFunType f, double x, MathFuncId id) { 51 unsigned index = hash(x, id); 52 Entry& e = table[index]; 53 if (e.in == x && e.id == id) 54 return e.out; 55 e.in = x; 56 e.id = id; 57 return e.out = f(x); 58 } 59 isCached(double x,MathFuncId id,double * r,unsigned * index)60 bool isCached(double x, MathFuncId id, double *r, unsigned *index) { 61 *index = hash(x, id); 62 Entry& e = table[*index]; 63 if (e.in == x && e.id == id) { 64 *r = e.out; 65 return true; 66 } 67 return false; 68 } 69 store(MathFuncId id,double x,double v,unsigned index)70 void store(MathFuncId id, double x, double v, unsigned index) { 71 Entry &e = table[index]; 72 if (e.in == x && e.id == id) 73 return; 74 e.in = x; 75 e.id = id; 76 e.out = v; 77 } 78 79 size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf); 80 }; 81 82 /* 83 * JS math functions. 84 */ 85 86 extern JSObject* 87 InitMathClass(JSContext* cx, HandleObject obj); 88 89 extern uint64_t 90 GenerateRandomSeed(); 91 92 // Fill |seed[0]| and |seed[1]| with random bits, suitable for 93 // seeding a XorShift128+ random number generator. 94 extern void 95 GenerateXorShift128PlusSeed(mozilla::Array<uint64_t, 2>& seed); 96 97 extern uint64_t 98 random_next(uint64_t* rngState, int bits); 99 100 extern bool 101 math_random(JSContext* cx, unsigned argc, js::Value* vp); 102 103 extern bool 104 math_abs_handle(JSContext* cx, js::HandleValue v, js::MutableHandleValue r); 105 106 extern bool 107 math_abs(JSContext* cx, unsigned argc, js::Value* vp); 108 109 extern double 110 math_max_impl(double x, double y); 111 112 extern bool 113 math_max(JSContext* cx, unsigned argc, js::Value* vp); 114 115 extern double 116 math_min_impl(double x, double y); 117 118 extern bool 119 math_min(JSContext* cx, unsigned argc, js::Value* vp); 120 121 extern bool 122 math_sqrt(JSContext* cx, unsigned argc, js::Value* vp); 123 124 extern bool 125 math_pow_handle(JSContext* cx, js::HandleValue base, js::HandleValue power, 126 js::MutableHandleValue result); 127 128 extern bool 129 math_pow(JSContext* cx, unsigned argc, js::Value* vp); 130 131 extern bool 132 minmax_impl(JSContext* cx, bool max, js::HandleValue a, js::HandleValue b, 133 js::MutableHandleValue res); 134 135 extern void 136 math_sincos_uncached(double x, double *sin, double *cos); 137 138 extern void 139 math_sincos_impl(MathCache* mathCache, double x, double *sin, double *cos); 140 141 extern bool 142 math_sqrt_handle(JSContext* cx, js::HandleValue number, js::MutableHandleValue result); 143 144 extern bool 145 math_imul_handle(JSContext* cx, HandleValue lhs, HandleValue rhs, MutableHandleValue res); 146 147 extern bool 148 math_imul(JSContext* cx, unsigned argc, js::Value* vp); 149 150 extern bool 151 RoundFloat32(JSContext* cx, HandleValue v, float* out); 152 153 extern bool 154 RoundFloat32(JSContext* cx, HandleValue arg, MutableHandleValue res); 155 156 extern bool 157 math_fround(JSContext* cx, unsigned argc, js::Value* vp); 158 159 extern bool 160 math_log(JSContext* cx, unsigned argc, js::Value* vp); 161 162 extern double 163 math_log_impl(MathCache* cache, double x); 164 165 extern double 166 math_log_uncached(double x); 167 168 extern bool 169 math_log_handle(JSContext* cx, HandleValue val, MutableHandleValue res); 170 171 extern bool 172 math_sin(JSContext* cx, unsigned argc, js::Value* vp); 173 174 extern double 175 math_sin_impl(MathCache* cache, double x); 176 177 extern double 178 math_sin_uncached(double x); 179 180 extern bool 181 math_sin_handle(JSContext* cx, HandleValue val, MutableHandleValue res); 182 183 extern bool 184 math_cos(JSContext* cx, unsigned argc, js::Value* vp); 185 186 extern double 187 math_cos_impl(MathCache* cache, double x); 188 189 extern double 190 math_cos_uncached(double x); 191 192 extern bool 193 math_exp(JSContext* cx, unsigned argc, js::Value* vp); 194 195 extern double 196 math_exp_impl(MathCache* cache, double x); 197 198 extern double 199 math_exp_uncached(double x); 200 201 extern bool 202 math_tan(JSContext* cx, unsigned argc, js::Value* vp); 203 204 extern double 205 math_tan_impl(MathCache* cache, double x); 206 207 extern double 208 math_tan_uncached(double x); 209 210 extern bool 211 math_log10(JSContext* cx, unsigned argc, js::Value* vp); 212 213 extern bool 214 math_log2(JSContext* cx, unsigned argc, js::Value* vp); 215 216 extern bool 217 math_log1p(JSContext* cx, unsigned argc, js::Value* vp); 218 219 extern bool 220 math_expm1(JSContext* cx, unsigned argc, js::Value* vp); 221 222 extern bool 223 math_cosh(JSContext* cx, unsigned argc, js::Value* vp); 224 225 extern bool 226 math_sinh(JSContext* cx, unsigned argc, js::Value* vp); 227 228 extern bool 229 math_tanh(JSContext* cx, unsigned argc, js::Value* vp); 230 231 extern bool 232 math_acosh(JSContext* cx, unsigned argc, js::Value* vp); 233 234 extern bool 235 math_asinh(JSContext* cx, unsigned argc, js::Value* vp); 236 237 extern bool 238 math_atanh(JSContext* cx, unsigned argc, js::Value* vp); 239 240 extern double 241 ecmaHypot(double x, double y); 242 243 extern double 244 hypot3(double x, double y, double z); 245 246 extern double 247 hypot4(double x, double y, double z, double w); 248 249 extern bool 250 math_hypot(JSContext* cx, unsigned argc, Value* vp); 251 252 extern bool 253 math_hypot_handle(JSContext* cx, HandleValueArray args, MutableHandleValue res); 254 255 extern bool 256 math_trunc(JSContext* cx, unsigned argc, Value* vp); 257 258 extern bool 259 math_sign(JSContext* cx, unsigned argc, Value* vp); 260 261 extern bool 262 math_cbrt(JSContext* cx, unsigned argc, Value* vp); 263 264 extern bool 265 math_asin(JSContext* cx, unsigned argc, Value* vp); 266 267 extern bool 268 math_acos(JSContext* cx, unsigned argc, Value* vp); 269 270 extern bool 271 math_atan(JSContext* cx, unsigned argc, Value* vp); 272 273 extern bool 274 math_atan2_handle(JSContext* cx, HandleValue y, HandleValue x, MutableHandleValue res); 275 276 extern bool 277 math_atan2(JSContext* cx, unsigned argc, Value* vp); 278 279 extern double 280 ecmaAtan2(double x, double y); 281 282 extern double 283 math_atan_impl(MathCache* cache, double x); 284 285 extern double 286 math_atan_uncached(double x); 287 288 extern bool 289 math_atan(JSContext* cx, unsigned argc, js::Value* vp); 290 291 extern double 292 math_asin_impl(MathCache* cache, double x); 293 294 extern double 295 math_asin_uncached(double x); 296 297 extern bool 298 math_asin(JSContext* cx, unsigned argc, js::Value* vp); 299 300 extern double 301 math_acos_impl(MathCache* cache, double x); 302 303 extern double 304 math_acos_uncached(double x); 305 306 extern bool 307 math_acos(JSContext* cx, unsigned argc, js::Value* vp); 308 309 extern bool 310 math_ceil_handle(JSContext* cx, HandleValue value, MutableHandleValue res); 311 312 extern bool 313 math_ceil(JSContext* cx, unsigned argc, Value* vp); 314 315 extern double 316 math_ceil_impl(double x); 317 318 extern bool 319 math_clz32(JSContext* cx, unsigned argc, Value* vp); 320 321 extern bool 322 math_floor_handle(JSContext* cx, HandleValue v, MutableHandleValue r); 323 324 extern bool 325 math_floor(JSContext* cx, unsigned argc, Value* vp); 326 327 extern double 328 math_floor_impl(double x); 329 330 template<typename T> 331 extern T GetBiggestNumberLessThan(T x); 332 333 extern bool 334 math_round_handle(JSContext* cx, HandleValue arg, MutableHandleValue res); 335 336 extern bool 337 math_round(JSContext* cx, unsigned argc, Value* vp); 338 339 extern double 340 math_round_impl(double x); 341 342 extern float 343 math_roundf_impl(float x); 344 345 extern double 346 powi(double x, int y); 347 348 extern double 349 ecmaPow(double x, double y); 350 351 extern bool 352 math_imul(JSContext* cx, unsigned argc, Value* vp); 353 354 extern double 355 math_log10_impl(MathCache* cache, double x); 356 357 extern double 358 math_log10_uncached(double x); 359 360 extern double 361 math_log2_impl(MathCache* cache, double x); 362 363 extern double 364 math_log2_uncached(double x); 365 366 extern double 367 math_log1p_impl(MathCache* cache, double x); 368 369 extern double 370 math_log1p_uncached(double x); 371 372 extern double 373 math_expm1_impl(MathCache* cache, double x); 374 375 extern double 376 math_expm1_uncached(double x); 377 378 extern double 379 math_cosh_impl(MathCache* cache, double x); 380 381 extern double 382 math_cosh_uncached(double x); 383 384 extern double 385 math_sinh_impl(MathCache* cache, double x); 386 387 extern double 388 math_sinh_uncached(double x); 389 390 extern double 391 math_tanh_impl(MathCache* cache, double x); 392 393 extern double 394 math_tanh_uncached(double x); 395 396 extern double 397 math_acosh_impl(MathCache* cache, double x); 398 399 extern double 400 math_acosh_uncached(double x); 401 402 extern double 403 math_asinh_impl(MathCache* cache, double x); 404 405 extern double 406 math_asinh_uncached(double x); 407 408 extern double 409 math_atanh_impl(MathCache* cache, double x); 410 411 extern double 412 math_atanh_uncached(double x); 413 414 extern double 415 math_trunc_impl(MathCache* cache, double x); 416 417 extern double 418 math_trunc_uncached(double x); 419 420 extern double 421 math_sign_impl(MathCache* cache, double x); 422 423 extern double 424 math_sign_uncached(double x); 425 426 extern double 427 math_cbrt_impl(MathCache* cache, double x); 428 429 extern double 430 math_cbrt_uncached(double x); 431 432 } /* namespace js */ 433 434 #endif /* jsmath_h */ 435