1 /* 2 * Copyright 2008 Jacek Caban for CodeWeavers 3 * Copyright 2009 Piotr Caban 4 * 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.1 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 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 18 */ 19 20 #ifdef __REACTOS__ 21 #include <wine/config.h> 22 #include <wine/port.h> 23 #endif 24 25 #include <math.h> 26 #include <limits.h> 27 28 #include "jscript.h" 29 #include "ntsecapi.h" 30 31 #include "wine/debug.h" 32 33 WINE_DEFAULT_DEBUG_CHANNEL(jscript); 34 35 static const WCHAR EW[] = {'E',0}; 36 static const WCHAR LOG2EW[] = {'L','O','G','2','E',0}; 37 static const WCHAR LOG10EW[] = {'L','O','G','1','0','E',0}; 38 static const WCHAR LN2W[] = {'L','N','2',0}; 39 static const WCHAR LN10W[] = {'L','N','1','0',0}; 40 static const WCHAR PIW[] = {'P','I',0}; 41 static const WCHAR SQRT2W[] = {'S','Q','R','T','2',0}; 42 static const WCHAR SQRT1_2W[] = {'S','Q','R','T','1','_','2',0}; 43 static const WCHAR absW[] = {'a','b','s',0}; 44 static const WCHAR acosW[] = {'a','c','o','s',0}; 45 static const WCHAR asinW[] = {'a','s','i','n',0}; 46 static const WCHAR atanW[] = {'a','t','a','n',0}; 47 static const WCHAR atan2W[] = {'a','t','a','n','2',0}; 48 static const WCHAR ceilW[] = {'c','e','i','l',0}; 49 static const WCHAR cosW[] = {'c','o','s',0}; 50 static const WCHAR expW[] = {'e','x','p',0}; 51 static const WCHAR floorW[] = {'f','l','o','o','r',0}; 52 static const WCHAR logW[] = {'l','o','g',0}; 53 static const WCHAR maxW[] = {'m','a','x',0}; 54 static const WCHAR minW[] = {'m','i','n',0}; 55 static const WCHAR powW[] = {'p','o','w',0}; 56 static const WCHAR randomW[] = {'r','a','n','d','o','m',0}; 57 static const WCHAR roundW[] = {'r','o','u','n','d',0}; 58 static const WCHAR sinW[] = {'s','i','n',0}; 59 static const WCHAR sqrtW[] = {'s','q','r','t',0}; 60 static const WCHAR tanW[] = {'t','a','n',0}; 61 62 /* ECMA-262 3rd Edition 15.8.2.12 */ 63 static HRESULT Math_abs(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, 64 jsval_t *r) 65 { 66 double d; 67 HRESULT hres; 68 69 TRACE("\n"); 70 71 if(!argc) { 72 if(r) 73 *r = jsval_number(NAN); 74 return S_OK; 75 } 76 77 hres = to_number(ctx, argv[0], &d); 78 if(FAILED(hres)) 79 return hres; 80 81 if(r) 82 *r = jsval_number(d < 0.0 ? -d : d); 83 return S_OK; 84 } 85 86 static HRESULT Math_acos(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, 87 jsval_t *r) 88 { 89 double x; 90 HRESULT hres; 91 92 TRACE("\n"); 93 94 if(!argc) { 95 if(r) 96 *r = jsval_number(NAN); 97 return S_OK; 98 } 99 100 hres = to_number(ctx, argv[0], &x); 101 if(FAILED(hres)) 102 return hres; 103 104 if(r) 105 *r = jsval_number(x < -1.0 || x > 1.0 ? NAN : acos(x)); 106 return S_OK; 107 } 108 109 static HRESULT Math_asin(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, 110 jsval_t *r) 111 { 112 double x; 113 HRESULT hres; 114 115 TRACE("\n"); 116 117 if(!argc) { 118 if(r) 119 *r = jsval_number(NAN); 120 return S_OK; 121 } 122 123 hres = to_number(ctx, argv[0], &x); 124 if(FAILED(hres)) 125 return hres; 126 127 if(r) 128 *r = jsval_number(x < -1.0 || x > 1.0 ? NAN : asin(x)); 129 return S_OK; 130 } 131 132 static HRESULT Math_atan(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, 133 jsval_t *r) 134 { 135 double x; 136 HRESULT hres; 137 138 TRACE("\n"); 139 140 if(!argc) { 141 if(r) 142 *r = jsval_number(NAN); 143 return S_OK; 144 } 145 146 hres = to_number(ctx, argv[0], &x); 147 if(FAILED(hres)) 148 return hres; 149 150 if(r) 151 *r = jsval_number(atan(x)); 152 return S_OK; 153 } 154 155 static HRESULT Math_atan2(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, 156 jsval_t *r) 157 { 158 double x, y; 159 HRESULT hres; 160 161 TRACE("\n"); 162 163 if(argc<2) { 164 if(r) 165 *r = jsval_number(NAN); 166 return S_OK; 167 } 168 169 hres = to_number(ctx, argv[0], &y); 170 if(FAILED(hres)) 171 return hres; 172 173 hres = to_number(ctx, argv[1], &x); 174 if(FAILED(hres)) 175 return hres; 176 177 if(r) 178 *r = jsval_number(atan2(y, x)); 179 return S_OK; 180 } 181 182 /* ECMA-262 3rd Edition 15.8.2.6 */ 183 static HRESULT Math_ceil(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, 184 jsval_t *r) 185 { 186 double x; 187 HRESULT hres; 188 189 TRACE("\n"); 190 191 if(!argc) { 192 if(r) 193 *r = jsval_number(NAN); 194 return S_OK; 195 } 196 197 hres = to_number(ctx, argv[0], &x); 198 if(FAILED(hres)) 199 return hres; 200 201 if(r) 202 *r = jsval_number(ceil(x)); 203 return S_OK; 204 } 205 206 static HRESULT Math_cos(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, 207 jsval_t *r) 208 { 209 double x; 210 HRESULT hres; 211 212 TRACE("\n"); 213 214 if(!argc) { 215 if(r) 216 *r = jsval_number(NAN); 217 return S_OK; 218 } 219 220 hres = to_number(ctx, argv[0], &x); 221 if(FAILED(hres)) 222 return hres; 223 224 if(r) 225 *r = jsval_number(cos(x)); 226 return S_OK; 227 } 228 229 static HRESULT Math_exp(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, 230 jsval_t *r) 231 { 232 double x; 233 HRESULT hres; 234 235 TRACE("\n"); 236 237 if(!argc) { 238 if(r) 239 *r = jsval_number(NAN); 240 return S_OK; 241 } 242 243 hres = to_number(ctx, argv[0], &x); 244 if(FAILED(hres)) 245 return hres; 246 247 if(r) 248 *r = jsval_number(exp(x)); 249 return S_OK; 250 } 251 252 static HRESULT Math_floor(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, 253 jsval_t *r) 254 { 255 double x; 256 HRESULT hres; 257 258 TRACE("\n"); 259 260 if(!argc) { 261 if(r) 262 *r = jsval_number(NAN); 263 return S_OK; 264 } 265 266 hres = to_number(ctx, argv[0], &x); 267 if(FAILED(hres)) 268 return hres; 269 270 if(r) 271 *r = jsval_number(floor(x)); 272 return S_OK; 273 } 274 275 static HRESULT Math_log(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, 276 jsval_t *r) 277 { 278 double x; 279 HRESULT hres; 280 281 TRACE("\n"); 282 283 if(!argc) { 284 if(r) 285 *r = jsval_number(NAN); 286 return S_OK; 287 } 288 289 hres = to_number(ctx, argv[0], &x); 290 if(FAILED(hres)) 291 return hres; 292 293 if(r) 294 *r = jsval_number(x < -0.0 ? NAN : log(x)); 295 return S_OK; 296 } 297 298 /* ECMA-262 3rd Edition 15.8.2.11 */ 299 static HRESULT Math_max(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, 300 jsval_t *r) 301 { 302 DOUBLE max, d; 303 DWORD i; 304 HRESULT hres; 305 306 TRACE("\n"); 307 308 if(!argc) { 309 if(r) 310 *r = jsval_number(-INFINITY); 311 return S_OK; 312 } 313 314 hres = to_number(ctx, argv[0], &max); 315 if(FAILED(hres)) 316 return hres; 317 318 for(i=1; i < argc; i++) { 319 hres = to_number(ctx, argv[i], &d); 320 if(FAILED(hres)) 321 return hres; 322 323 if(d > max || isnan(d)) 324 max = d; 325 } 326 327 if(r) 328 *r = jsval_number(max); 329 return S_OK; 330 } 331 332 /* ECMA-262 3rd Edition 15.8.2.12 */ 333 static HRESULT Math_min(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, 334 jsval_t *r) 335 { 336 DOUBLE min, d; 337 DWORD i; 338 HRESULT hres; 339 340 TRACE("\n"); 341 342 if(!argc) { 343 if(r) 344 *r = jsval_number(INFINITY); 345 return S_OK; 346 } 347 348 hres = to_number(ctx, argv[0], &min); 349 if(FAILED(hres)) 350 return hres; 351 352 for(i=1; i < argc; i++) { 353 hres = to_number(ctx, argv[i], &d); 354 if(FAILED(hres)) 355 return hres; 356 357 if(d < min || isnan(d)) 358 min = d; 359 } 360 361 if(r) 362 *r = jsval_number(min); 363 return S_OK; 364 } 365 366 /* ECMA-262 3rd Edition 15.8.2.13 */ 367 static HRESULT Math_pow(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, 368 jsval_t *r) 369 { 370 double x, y; 371 HRESULT hres; 372 373 TRACE("\n"); 374 375 if(argc < 2) { 376 if(r) 377 *r = jsval_number(NAN); 378 return S_OK; 379 } 380 381 hres = to_number(ctx, argv[0], &x); 382 if(FAILED(hres)) 383 return hres; 384 385 hres = to_number(ctx, argv[1], &y); 386 if(FAILED(hres)) 387 return hres; 388 389 if(r) 390 *r = jsval_number(pow(x, y)); 391 return S_OK; 392 } 393 394 /* ECMA-262 3rd Edition 15.8.2.14 */ 395 static HRESULT Math_random(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, 396 jsval_t *r) 397 { 398 UINT x; 399 400 TRACE("\n"); 401 402 if(!RtlGenRandom(&x, sizeof(x))) 403 return E_UNEXPECTED; 404 405 if(r) 406 *r = jsval_number((double)x/(double)UINT_MAX); 407 return S_OK; 408 } 409 410 /* ECMA-262 3rd Edition 15.8.2.15 */ 411 static HRESULT Math_round(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, 412 jsval_t *r) 413 { 414 double x; 415 HRESULT hres; 416 417 TRACE("\n"); 418 419 if(!argc) { 420 if(r) 421 *r = jsval_number(NAN); 422 return S_OK; 423 } 424 425 hres = to_number(ctx, argv[0], &x); 426 if(FAILED(hres)) 427 return hres; 428 429 if(r) 430 *r = jsval_number(floor(x+0.5)); 431 return S_OK; 432 } 433 434 static HRESULT Math_sin(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, 435 jsval_t *r) 436 { 437 double x; 438 HRESULT hres; 439 440 TRACE("\n"); 441 442 if(!argc) { 443 if(r) 444 *r = jsval_number(NAN); 445 return S_OK; 446 } 447 448 hres = to_number(ctx, argv[0], &x); 449 if(FAILED(hres)) 450 return hres; 451 452 if(r) 453 *r = jsval_number(sin(x)); 454 return S_OK; 455 } 456 457 static HRESULT Math_sqrt(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, 458 jsval_t *r) 459 { 460 double x; 461 HRESULT hres; 462 463 TRACE("\n"); 464 465 if(!argc) { 466 if(r) 467 *r = jsval_number(NAN); 468 return S_OK; 469 } 470 471 hres = to_number(ctx, argv[0], &x); 472 if(FAILED(hres)) 473 return hres; 474 475 if(r) 476 *r = jsval_number(sqrt(x)); 477 return S_OK; 478 } 479 480 static HRESULT Math_tan(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, 481 jsval_t *r) 482 { 483 double x; 484 HRESULT hres; 485 486 TRACE("\n"); 487 488 if(!argc) { 489 if(r) 490 *r = jsval_number(NAN); 491 return S_OK; 492 } 493 494 hres = to_number(ctx, argv[0], &x); 495 if(FAILED(hres)) 496 return hres; 497 498 if(r) 499 *r = jsval_number(tan(x)); 500 return S_OK; 501 } 502 503 static const builtin_prop_t Math_props[] = { 504 {absW, Math_abs, PROPF_METHOD|1}, 505 {acosW, Math_acos, PROPF_METHOD|1}, 506 {asinW, Math_asin, PROPF_METHOD|1}, 507 {atanW, Math_atan, PROPF_METHOD|1}, 508 {atan2W, Math_atan2, PROPF_METHOD|2}, 509 {ceilW, Math_ceil, PROPF_METHOD|1}, 510 {cosW, Math_cos, PROPF_METHOD|1}, 511 {expW, Math_exp, PROPF_METHOD|1}, 512 {floorW, Math_floor, PROPF_METHOD|1}, 513 {logW, Math_log, PROPF_METHOD|1}, 514 {maxW, Math_max, PROPF_METHOD|2}, 515 {minW, Math_min, PROPF_METHOD|2}, 516 {powW, Math_pow, PROPF_METHOD|2}, 517 {randomW, Math_random, PROPF_METHOD}, 518 {roundW, Math_round, PROPF_METHOD|1}, 519 {sinW, Math_sin, PROPF_METHOD|1}, 520 {sqrtW, Math_sqrt, PROPF_METHOD|1}, 521 {tanW, Math_tan, PROPF_METHOD|1} 522 }; 523 524 static const builtin_info_t Math_info = { 525 JSCLASS_MATH, 526 {NULL, NULL, 0}, 527 ARRAY_SIZE(Math_props), 528 Math_props, 529 NULL, 530 NULL 531 }; 532 533 HRESULT create_math(script_ctx_t *ctx, jsdisp_t **ret) 534 { 535 jsdisp_t *math; 536 unsigned i; 537 HRESULT hres; 538 539 struct { 540 const WCHAR *name; 541 DOUBLE val; 542 }constants[] = { 543 {EW, M_E}, /* ECMA-262 3rd Edition 15.8.1.1 */ 544 {LN10W, M_LN10}, /* ECMA-262 3rd Edition 15.8.1.2 */ 545 {LN2W, M_LN2}, /* ECMA-262 3rd Edition 15.8.1.3 */ 546 {LOG2EW, M_LOG2E}, /* ECMA-262 3rd Edition 15.8.1.4 */ 547 {LOG10EW, M_LOG10E}, /* ECMA-262 3rd Edition 15.8.1.5 */ 548 {PIW, M_PI}, /* ECMA-262 3rd Edition 15.8.1.6 */ 549 {SQRT1_2W, M_SQRT1_2}, /* ECMA-262 3rd Edition 15.8.1.7 */ 550 {SQRT2W, M_SQRT2}, /* ECMA-262 3rd Edition 15.8.1.8 */ 551 }; 552 553 math = heap_alloc_zero(sizeof(jsdisp_t)); 554 if(!math) 555 return E_OUTOFMEMORY; 556 557 hres = init_dispex_from_constr(math, ctx, &Math_info, ctx->object_constr); 558 if(FAILED(hres)) { 559 heap_free(math); 560 return hres; 561 } 562 563 for(i=0; i < ARRAY_SIZE(constants); i++) { 564 hres = jsdisp_define_data_property(math, constants[i].name, 0, 565 jsval_number(constants[i].val)); 566 if(FAILED(hres)) { 567 jsdisp_release(math); 568 return hres; 569 } 570 } 571 572 *ret = math; 573 return S_OK; 574 } 575