include: Add missing enum XHR_PROP_ values.
[wine.git] / dlls / jscript / math.c
blob362b877cb5e1a6a3bcf562659dce6b10436ec92c
1 /*
2 * Copyright 2008 Jacek Caban for CodeWeavers
3 * Copyright 2009 Piotr Caban
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.
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.
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
21 #include <math.h>
22 #include <limits.h>
24 #include "jscript.h"
25 #include "ntsecapi.h"
27 #include "wine/debug.h"
29 WINE_DEFAULT_DEBUG_CHANNEL(jscript);
31 /* ECMA-262 3rd Edition 15.8.2.12 */
32 static HRESULT Math_abs(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv,
33 jsval_t *r)
35 double d;
36 HRESULT hres;
38 TRACE("\n");
40 if(!argc) {
41 if(r)
42 *r = jsval_number(NAN);
43 return S_OK;
46 hres = to_number(ctx, argv[0], &d);
47 if(FAILED(hres))
48 return hres;
50 if(r)
51 *r = jsval_number(d < 0.0 ? -d : d);
52 return S_OK;
55 static HRESULT Math_acos(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv,
56 jsval_t *r)
58 double x;
59 HRESULT hres;
61 TRACE("\n");
63 if(!argc) {
64 if(r)
65 *r = jsval_number(NAN);
66 return S_OK;
69 hres = to_number(ctx, argv[0], &x);
70 if(FAILED(hres))
71 return hres;
73 if(r)
74 *r = jsval_number(x < -1.0 || x > 1.0 ? NAN : acos(x));
75 return S_OK;
78 static HRESULT Math_asin(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv,
79 jsval_t *r)
81 double x;
82 HRESULT hres;
84 TRACE("\n");
86 if(!argc) {
87 if(r)
88 *r = jsval_number(NAN);
89 return S_OK;
92 hres = to_number(ctx, argv[0], &x);
93 if(FAILED(hres))
94 return hres;
96 if(r)
97 *r = jsval_number(x < -1.0 || x > 1.0 ? NAN : asin(x));
98 return S_OK;
101 static HRESULT Math_atan(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv,
102 jsval_t *r)
104 double x;
105 HRESULT hres;
107 TRACE("\n");
109 if(!argc) {
110 if(r)
111 *r = jsval_number(NAN);
112 return S_OK;
115 hres = to_number(ctx, argv[0], &x);
116 if(FAILED(hres))
117 return hres;
119 if(r)
120 *r = jsval_number(atan(x));
121 return S_OK;
124 static HRESULT Math_atan2(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv,
125 jsval_t *r)
127 double x, y;
128 HRESULT hres;
130 TRACE("\n");
132 if(argc<2) {
133 if(r)
134 *r = jsval_number(NAN);
135 return S_OK;
138 hres = to_number(ctx, argv[0], &y);
139 if(FAILED(hres))
140 return hres;
142 hres = to_number(ctx, argv[1], &x);
143 if(FAILED(hres))
144 return hres;
146 if(r)
147 *r = jsval_number(atan2(y, x));
148 return S_OK;
151 /* ECMA-262 3rd Edition 15.8.2.6 */
152 static HRESULT Math_ceil(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv,
153 jsval_t *r)
155 double x;
156 HRESULT hres;
158 TRACE("\n");
160 if(!argc) {
161 if(r)
162 *r = jsval_number(NAN);
163 return S_OK;
166 hres = to_number(ctx, argv[0], &x);
167 if(FAILED(hres))
168 return hres;
170 if(r)
171 *r = jsval_number(ceil(x));
172 return S_OK;
175 static HRESULT Math_cos(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv,
176 jsval_t *r)
178 double x;
179 HRESULT hres;
181 TRACE("\n");
183 if(!argc) {
184 if(r)
185 *r = jsval_number(NAN);
186 return S_OK;
189 hres = to_number(ctx, argv[0], &x);
190 if(FAILED(hres))
191 return hres;
193 if(r)
194 *r = jsval_number(cos(x));
195 return S_OK;
198 static HRESULT Math_exp(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv,
199 jsval_t *r)
201 double x;
202 HRESULT hres;
204 TRACE("\n");
206 if(!argc) {
207 if(r)
208 *r = jsval_number(NAN);
209 return S_OK;
212 hres = to_number(ctx, argv[0], &x);
213 if(FAILED(hres))
214 return hres;
216 if(r)
217 *r = jsval_number(exp(x));
218 return S_OK;
221 static HRESULT Math_floor(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv,
222 jsval_t *r)
224 double x;
225 HRESULT hres;
227 TRACE("\n");
229 if(!argc) {
230 if(r)
231 *r = jsval_number(NAN);
232 return S_OK;
235 hres = to_number(ctx, argv[0], &x);
236 if(FAILED(hres))
237 return hres;
239 if(r)
240 *r = jsval_number(floor(x));
241 return S_OK;
244 static HRESULT Math_log(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv,
245 jsval_t *r)
247 double x;
248 HRESULT hres;
250 TRACE("\n");
252 if(!argc) {
253 if(r)
254 *r = jsval_number(NAN);
255 return S_OK;
258 hres = to_number(ctx, argv[0], &x);
259 if(FAILED(hres))
260 return hres;
262 if(r)
263 *r = jsval_number(x < -0.0 ? NAN : log(x));
264 return S_OK;
267 /* ECMA-262 3rd Edition 15.8.2.11 */
268 static HRESULT Math_max(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv,
269 jsval_t *r)
271 DOUBLE max, d;
272 DWORD i;
273 HRESULT hres;
275 TRACE("\n");
277 if(!argc) {
278 if(r)
279 *r = jsval_number(-INFINITY);
280 return S_OK;
283 hres = to_number(ctx, argv[0], &max);
284 if(FAILED(hres))
285 return hres;
287 for(i=1; i < argc; i++) {
288 hres = to_number(ctx, argv[i], &d);
289 if(FAILED(hres))
290 return hres;
292 if(d > max || isnan(d))
293 max = d;
296 if(r)
297 *r = jsval_number(max);
298 return S_OK;
301 /* ECMA-262 3rd Edition 15.8.2.12 */
302 static HRESULT Math_min(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv,
303 jsval_t *r)
305 DOUBLE min, d;
306 DWORD i;
307 HRESULT hres;
309 TRACE("\n");
311 if(!argc) {
312 if(r)
313 *r = jsval_number(INFINITY);
314 return S_OK;
317 hres = to_number(ctx, argv[0], &min);
318 if(FAILED(hres))
319 return hres;
321 for(i=1; i < argc; i++) {
322 hres = to_number(ctx, argv[i], &d);
323 if(FAILED(hres))
324 return hres;
326 if(d < min || isnan(d))
327 min = d;
330 if(r)
331 *r = jsval_number(min);
332 return S_OK;
335 /* ECMA-262 3rd Edition 15.8.2.13 */
336 static HRESULT Math_pow(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv,
337 jsval_t *r)
339 double x, y;
340 HRESULT hres;
342 TRACE("\n");
344 if(argc < 2) {
345 if(r)
346 *r = jsval_number(NAN);
347 return S_OK;
350 hres = to_number(ctx, argv[0], &x);
351 if(FAILED(hres))
352 return hres;
354 hres = to_number(ctx, argv[1], &y);
355 if(FAILED(hres))
356 return hres;
358 if(r)
359 *r = jsval_number(pow(x, y));
360 return S_OK;
363 /* ECMA-262 3rd Edition 15.8.2.14 */
364 static HRESULT Math_random(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv,
365 jsval_t *r)
367 UINT x;
369 TRACE("\n");
371 if(!RtlGenRandom(&x, sizeof(x)))
372 return E_UNEXPECTED;
374 if(r)
375 *r = jsval_number((double)x/(double)UINT_MAX);
376 return S_OK;
379 /* ECMA-262 3rd Edition 15.8.2.15 */
380 static HRESULT Math_round(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv,
381 jsval_t *r)
383 double x;
384 HRESULT hres;
386 TRACE("\n");
388 if(!argc) {
389 if(r)
390 *r = jsval_number(NAN);
391 return S_OK;
394 hres = to_number(ctx, argv[0], &x);
395 if(FAILED(hres))
396 return hres;
398 if(r)
399 *r = jsval_number(floor(x+0.5));
400 return S_OK;
403 static HRESULT Math_sin(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv,
404 jsval_t *r)
406 double x;
407 HRESULT hres;
409 TRACE("\n");
411 if(!argc) {
412 if(r)
413 *r = jsval_number(NAN);
414 return S_OK;
417 hres = to_number(ctx, argv[0], &x);
418 if(FAILED(hres))
419 return hres;
421 if(r)
422 *r = jsval_number(sin(x));
423 return S_OK;
426 static HRESULT Math_sqrt(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv,
427 jsval_t *r)
429 double x;
430 HRESULT hres;
432 TRACE("\n");
434 if(!argc) {
435 if(r)
436 *r = jsval_number(NAN);
437 return S_OK;
440 hres = to_number(ctx, argv[0], &x);
441 if(FAILED(hres))
442 return hres;
444 if(r)
445 *r = jsval_number(sqrt(x));
446 return S_OK;
449 static HRESULT Math_tan(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv,
450 jsval_t *r)
452 double x;
453 HRESULT hres;
455 TRACE("\n");
457 if(!argc) {
458 if(r)
459 *r = jsval_number(NAN);
460 return S_OK;
463 hres = to_number(ctx, argv[0], &x);
464 if(FAILED(hres))
465 return hres;
467 if(r)
468 *r = jsval_number(tan(x));
469 return S_OK;
472 static const builtin_prop_t Math_props[] = {
473 {L"abs", Math_abs, PROPF_METHOD|1},
474 {L"acos", Math_acos, PROPF_METHOD|1},
475 {L"asin", Math_asin, PROPF_METHOD|1},
476 {L"atan", Math_atan, PROPF_METHOD|1},
477 {L"atan2", Math_atan2, PROPF_METHOD|2},
478 {L"ceil", Math_ceil, PROPF_METHOD|1},
479 {L"cos", Math_cos, PROPF_METHOD|1},
480 {L"exp", Math_exp, PROPF_METHOD|1},
481 {L"floor", Math_floor, PROPF_METHOD|1},
482 {L"log", Math_log, PROPF_METHOD|1},
483 {L"max", Math_max, PROPF_METHOD|2},
484 {L"min", Math_min, PROPF_METHOD|2},
485 {L"pow", Math_pow, PROPF_METHOD|2},
486 {L"random", Math_random, PROPF_METHOD},
487 {L"round", Math_round, PROPF_METHOD|1},
488 {L"sin", Math_sin, PROPF_METHOD|1},
489 {L"sqrt", Math_sqrt, PROPF_METHOD|1},
490 {L"tan", Math_tan, PROPF_METHOD|1}
493 static const builtin_info_t Math_info = {
494 JSCLASS_MATH,
495 NULL,
496 ARRAY_SIZE(Math_props),
497 Math_props,
498 NULL,
499 NULL
502 HRESULT create_math(script_ctx_t *ctx, jsdisp_t **ret)
504 jsdisp_t *math;
505 unsigned i;
506 HRESULT hres;
508 struct {
509 const WCHAR *name;
510 DOUBLE val;
511 }constants[] = {
512 {L"E", M_E}, /* ECMA-262 3rd Edition 15.8.1.1 */
513 {L"LN10", M_LN10}, /* ECMA-262 3rd Edition 15.8.1.2 */
514 {L"LN2", M_LN2}, /* ECMA-262 3rd Edition 15.8.1.3 */
515 {L"LOG2E", M_LOG2E}, /* ECMA-262 3rd Edition 15.8.1.4 */
516 {L"LOG10E", M_LOG10E}, /* ECMA-262 3rd Edition 15.8.1.5 */
517 {L"PI", M_PI}, /* ECMA-262 3rd Edition 15.8.1.6 */
518 {L"SQRT1_2", M_SQRT1_2}, /* ECMA-262 3rd Edition 15.8.1.7 */
519 {L"SQRT2", M_SQRT2}, /* ECMA-262 3rd Edition 15.8.1.8 */
522 math = calloc(1, sizeof(jsdisp_t));
523 if(!math)
524 return E_OUTOFMEMORY;
526 hres = init_dispex_from_constr(math, ctx, &Math_info, ctx->object_constr);
527 if(FAILED(hres)) {
528 free(math);
529 return hres;
532 for(i=0; i < ARRAY_SIZE(constants); i++) {
533 hres = jsdisp_define_data_property(math, constants[i].name, 0,
534 jsval_number(constants[i].val));
535 if(FAILED(hres)) {
536 jsdisp_release(math);
537 return hres;
541 *ret = math;
542 return S_OK;