~ubuntu-branches/ubuntu/karmic/rhino/karmic

« back to all changes in this revision

Viewing changes to src/org/mozilla/javascript/NativeMath.java

  • Committer: Bazaar Package Importer
  • Author(s): Jerry Haltom
  • Date: 2005-03-19 16:56:07 UTC
  • mto: (11.1.1 squeeze)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20050319165607-geu3j3fnqlkpqkh1
Tags: upstream-1.6.R1
ImportĀ upstreamĀ versionĀ 1.6.R1

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* -*- Mode: java; tab-width: 4; indent-tabs-mode: 1; c-basic-offset: 4 -*-
2
 
 *
3
 
 * The contents of this file are subject to the Netscape Public
4
 
 * License Version 1.1 (the "License"); you may not use this file
5
 
 * except in compliance with the License. You may obtain a copy of
6
 
 * the License at http://www.mozilla.org/NPL/
7
 
 *
8
 
 * Software distributed under the License is distributed on an "AS
9
 
 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
10
 
 * implied. See the License for the specific language governing
11
 
 * rights and limitations under the License.
12
 
 *
13
 
 * The Original Code is Rhino code, released
14
 
 * May 6, 1999.
15
 
 *
16
 
 * The Initial Developer of the Original Code is Netscape
17
 
 * Communications Corporation.  Portions created by Netscape are
18
 
 * Copyright (C) 1997-1999 Netscape Communications Corporation. All
19
 
 * Rights Reserved.
20
 
 *
21
 
 * Contributor(s):
22
 
 * Norris Boyd
23
 
 * Igor Bukanov
24
 
 *
25
 
 * Alternatively, the contents of this file may be used under the
26
 
 * terms of the GNU Public License (the "GPL"), in which case the
27
 
 * provisions of the GPL are applicable instead of those above.
28
 
 * If you wish to allow use of your version of this file only
29
 
 * under the terms of the GPL and not to allow others to use your
30
 
 * version of this file under the NPL, indicate your decision by
31
 
 * deleting the provisions above and replace them with the notice
32
 
 * and other provisions required by the GPL.  If you do not delete
33
 
 * the provisions above, a recipient may use your version of this
34
 
 * file under either the NPL or the GPL.
35
 
 */
36
 
 
37
 
package org.mozilla.javascript;
38
 
 
39
 
/**
40
 
 * This class implements the Math native object.
41
 
 * See ECMA 15.8.
42
 
 * @author Norris Boyd
43
 
 */
44
 
 
45
 
public class NativeMath extends IdScriptable
46
 
{
47
 
    public static void init(Context cx, Scriptable scope, boolean sealed) {
48
 
        NativeMath obj = new NativeMath();
49
 
        obj.setSealFunctionsFlag(sealed);
50
 
        obj.setFunctionParametrs(cx);
51
 
        obj.setPrototype(getObjectPrototype(scope));
52
 
        obj.setParentScope(scope);
53
 
        if (sealed) { obj.sealObject(); }
54
 
        ScriptableObject.defineProperty(scope, "Math", obj,
55
 
                                        ScriptableObject.DONTENUM);
56
 
    }
57
 
 
58
 
    public String getClassName() { return "Math"; }
59
 
 
60
 
    protected int getIdDefaultAttributes(int id) {
61
 
        if (id > LAST_METHOD_ID) {
62
 
            return DONTENUM | READONLY | PERMANENT;
63
 
        }
64
 
        return super.getIdDefaultAttributes(id);
65
 
    }
66
 
 
67
 
    protected Object getIdValue(int id) {
68
 
        if (id > LAST_METHOD_ID) {
69
 
            return cacheIdValue(id, wrap_double(getField(id)));
70
 
        }
71
 
        return super.getIdValue(id);
72
 
    }
73
 
 
74
 
    private double getField(int fieldId) {
75
 
        switch (fieldId) {
76
 
            case Id_E:       return E;
77
 
            case Id_PI:      return PI;
78
 
            case Id_LN10:    return LN10;
79
 
            case Id_LN2:     return LN2;
80
 
            case Id_LOG2E:   return LOG2E;
81
 
            case Id_LOG10E:  return LOG10E;
82
 
            case Id_SQRT1_2: return SQRT1_2;
83
 
            case Id_SQRT2:   return SQRT2;
84
 
        }
85
 
        return 0; // Unreachable
86
 
    }
87
 
 
88
 
    public int methodArity(int methodId) {
89
 
        switch (methodId) {
90
 
            case Id_abs:      return 1;
91
 
            case Id_acos:     return 1;
92
 
            case Id_asin:     return 1;
93
 
            case Id_atan:     return 1;
94
 
            case Id_atan2:    return 2;
95
 
            case Id_ceil:     return 1;
96
 
            case Id_cos:      return 1;
97
 
            case Id_exp:      return 1;
98
 
            case Id_floor:    return 1;
99
 
            case Id_log:      return 1;
100
 
            case Id_max:      return 2;
101
 
            case Id_min:      return 2;
102
 
            case Id_pow:      return 2;
103
 
            case Id_random:   return 0;
104
 
            case Id_round:    return 1;
105
 
            case Id_sin:      return 1;
106
 
            case Id_sqrt:     return 1;
107
 
            case Id_tan:      return 1;
108
 
        }
109
 
        return super.methodArity(methodId);
110
 
    }
111
 
 
112
 
    public Object execMethod
113
 
        (int methodId, IdFunction f,
114
 
         Context cx, Scriptable scope, Scriptable thisObj, Object[] args)
115
 
        throws JavaScriptException
116
 
    {
117
 
        switch (methodId) {
118
 
            case Id_abs: return wrap_double
119
 
                (js_abs(ScriptRuntime.toNumber(args, 0)));
120
 
 
121
 
            case Id_acos: return wrap_double
122
 
                (js_acos(ScriptRuntime.toNumber(args, 0)));
123
 
 
124
 
            case Id_asin: return wrap_double
125
 
                (js_asin(ScriptRuntime.toNumber(args, 0)));
126
 
 
127
 
            case Id_atan: return wrap_double
128
 
                (js_atan(ScriptRuntime.toNumber(args, 0)));
129
 
 
130
 
            case Id_atan2: return wrap_double
131
 
                (js_atan2(ScriptRuntime.toNumber(args, 0),
132
 
                          ScriptRuntime.toNumber(args, 1)));
133
 
 
134
 
            case Id_ceil: return wrap_double
135
 
                (js_ceil(ScriptRuntime.toNumber(args, 0)));
136
 
 
137
 
            case Id_cos: return wrap_double
138
 
                (js_cos(ScriptRuntime.toNumber(args, 0)));
139
 
 
140
 
            case Id_exp: return wrap_double
141
 
                (js_exp(ScriptRuntime.toNumber(args, 0)));
142
 
 
143
 
            case Id_floor: return wrap_double
144
 
                (js_floor(ScriptRuntime.toNumber(args, 0)));
145
 
 
146
 
            case Id_log: return wrap_double
147
 
                (js_log(ScriptRuntime.toNumber(args, 0)));
148
 
 
149
 
            case Id_max: return wrap_double
150
 
                (js_max(args));
151
 
 
152
 
            case Id_min: return wrap_double
153
 
                (js_min(args));
154
 
 
155
 
            case Id_pow: return wrap_double
156
 
                (js_pow(ScriptRuntime.toNumber(args, 0),
157
 
                        ScriptRuntime.toNumber(args, 1)));
158
 
 
159
 
            case Id_random: return wrap_double
160
 
                (js_random());
161
 
 
162
 
            case Id_round: return wrap_double
163
 
                (js_round(ScriptRuntime.toNumber(args, 0)));
164
 
 
165
 
            case Id_sin: return wrap_double
166
 
                (js_sin(ScriptRuntime.toNumber(args, 0)));
167
 
 
168
 
            case Id_sqrt: return wrap_double
169
 
                (js_sqrt(ScriptRuntime.toNumber(args, 0)));
170
 
 
171
 
            case Id_tan: return wrap_double
172
 
                (js_tan(ScriptRuntime.toNumber(args, 0)));
173
 
        }
174
 
        return super.execMethod(methodId, f, cx, scope, thisObj, args);
175
 
    }
176
 
 
177
 
    private double js_abs(double x) {
178
 
        // abs(-0.0) should be 0.0, but -0.0 < 0.0 == false
179
 
        return (x == 0.0) ? 0.0 : (x < 0.0) ? -x : x;
180
 
    }
181
 
 
182
 
    private double js_acos(double x) {
183
 
        return (x == x && -1.0 <= x && x <= 1.0) ? Math.acos(x) : Double.NaN;
184
 
    }
185
 
 
186
 
    private double js_asin(double x) {
187
 
        return (x == x && -1.0 <= x && x <= 1.0) ? Math.asin(x) : Double.NaN;
188
 
    }
189
 
 
190
 
    private double js_atan(double x) { return Math.atan(x); }
191
 
 
192
 
    private double js_atan2(double x, double y) { return Math.atan2(x, y); }
193
 
 
194
 
    private double js_ceil(double x) { return Math.ceil(x); }
195
 
 
196
 
    private double js_cos(double x) { return Math.cos(x); }
197
 
 
198
 
    private double js_exp(double x) {
199
 
        return (x == Double.POSITIVE_INFINITY) ? x
200
 
            : (x == Double.NEGATIVE_INFINITY) ? 0.0
201
 
            : Math.exp(x);
202
 
    }
203
 
 
204
 
    private double js_floor(double x) { return Math.floor(x); }
205
 
 
206
 
    private double js_log(double x) {
207
 
        // Java's log(<0) = -Infinity; we need NaN
208
 
        return (x < 0) ? Double.NaN : Math.log(x);
209
 
    }
210
 
 
211
 
    private double js_max(Object[] args) {
212
 
        double result = Double.NEGATIVE_INFINITY;
213
 
        if (args.length == 0)
214
 
            return result;
215
 
        for (int i = 0; i < args.length; i++) {
216
 
            double d = ScriptRuntime.toNumber(args[i]);
217
 
            if (d != d) return d;
218
 
            // if (result < d) result = d; does not work due to -0.0 >= +0.0
219
 
            result = Math.max(result, d);
220
 
        }
221
 
        return result;
222
 
    }
223
 
 
224
 
    private double js_min(Object[] args) {
225
 
        double result = Double.POSITIVE_INFINITY;
226
 
        if (args.length == 0)
227
 
            return result;
228
 
        for (int i = 0; i < args.length; i++) {
229
 
            double d = ScriptRuntime.toNumber(args[i]);
230
 
            if (d != d) return d;
231
 
            // if (result > d) result = d; does not work due to -0.0 >= +0.0
232
 
            result = Math.min(result, d);
233
 
        }
234
 
        return result;
235
 
    }
236
 
 
237
 
    private double js_pow(double x, double y) {
238
 
        if (y == 0) return 1.0;   // Java's pow(NaN, 0) = NaN; we need 1
239
 
        if ((x == 0) && (y < 0)) {
240
 
            if (1 / x > 0) {
241
 
                // x is +0, Java is -oo, we need +oo
242
 
                return Double.POSITIVE_INFINITY;
243
 
            }
244
 
            /* if x is -0 and y is an odd integer, -oo */
245
 
            int y_int = (int)y;
246
 
            if (y_int == y && (y_int & 0x1) != 0)
247
 
                return Double.NEGATIVE_INFINITY;
248
 
            return Double.POSITIVE_INFINITY;
249
 
        }
250
 
        return Math.pow(x, y);
251
 
    }
252
 
 
253
 
    private double js_random() { return Math.random(); }
254
 
 
255
 
    private double js_round(double d) {
256
 
        if (d != d)
257
 
            return d;   // NaN
258
 
        if (d == Double.POSITIVE_INFINITY || d == Double.NEGATIVE_INFINITY)
259
 
            return d;
260
 
        long l = Math.round(d);
261
 
        if (l == 0) {
262
 
            // We must propagate the sign of d into the result
263
 
            if (d < 0.0)
264
 
                return ScriptRuntime.negativeZero;
265
 
            return d == 0.0 ? d : 0.0;
266
 
        }
267
 
        return (double) l;
268
 
    }
269
 
 
270
 
    private double js_sin(double x) { return Math.sin(x); }
271
 
 
272
 
    private double js_sqrt(double x) { return Math.sqrt(x); }
273
 
 
274
 
    private double js_tan(double x) { return Math.tan(x); }
275
 
 
276
 
    protected int maxInstanceId() { return MAX_INSTANCE_ID; }
277
 
 
278
 
    protected String getIdName(int id) {
279
 
        switch (id) {
280
 
            case Id_abs:      return "abs";
281
 
            case Id_acos:     return "acos";
282
 
            case Id_asin:     return "asin";
283
 
            case Id_atan:     return "atan";
284
 
            case Id_atan2:    return "atan2";
285
 
            case Id_ceil:     return "ceil";
286
 
            case Id_cos:      return "cos";
287
 
            case Id_exp:      return "exp";
288
 
            case Id_floor:    return "floor";
289
 
            case Id_log:      return "log";
290
 
            case Id_max:      return "max";
291
 
            case Id_min:      return "min";
292
 
            case Id_pow:      return "pow";
293
 
            case Id_random:   return "random";
294
 
            case Id_round:    return "round";
295
 
            case Id_sin:      return "sin";
296
 
            case Id_sqrt:     return "sqrt";
297
 
            case Id_tan:      return "tan";
298
 
 
299
 
            case Id_E:        return "E";
300
 
            case Id_PI:       return "PI";
301
 
            case Id_LN10:     return "LN10";
302
 
            case Id_LN2:      return "LN2";
303
 
            case Id_LOG2E:    return "LOG2E";
304
 
            case Id_LOG10E:   return "LOG10E";
305
 
            case Id_SQRT1_2:  return "SQRT1_2";
306
 
            case Id_SQRT2:    return "SQRT2";
307
 
        }
308
 
        return null;
309
 
    }
310
 
 
311
 
// #string_id_map#
312
 
 
313
 
    protected int mapNameToId(String s) {
314
 
        int id;
315
 
// #generated# Last update: 2001-03-23 13:50:14 GMT+01:00
316
 
        L0: { id = 0; String X = null; int c;
317
 
            L: switch (s.length()) {
318
 
            case 1: if (s.charAt(0)=='E') {id=Id_E; break L0;} break L;
319
 
            case 2: if (s.charAt(0)=='P' && s.charAt(1)=='I') {id=Id_PI; break L0;} break L;
320
 
            case 3: switch (s.charAt(0)) {
321
 
                case 'L': if (s.charAt(2)=='2' && s.charAt(1)=='N') {id=Id_LN2; break L0;} break L;
322
 
                case 'a': if (s.charAt(2)=='s' && s.charAt(1)=='b') {id=Id_abs; break L0;} break L;
323
 
                case 'c': if (s.charAt(2)=='s' && s.charAt(1)=='o') {id=Id_cos; break L0;} break L;
324
 
                case 'e': if (s.charAt(2)=='p' && s.charAt(1)=='x') {id=Id_exp; break L0;} break L;
325
 
                case 'l': if (s.charAt(2)=='g' && s.charAt(1)=='o') {id=Id_log; break L0;} break L;
326
 
                case 'm': c=s.charAt(2);
327
 
                    if (c=='n') { if (s.charAt(1)=='i') {id=Id_min; break L0;} }
328
 
                    else if (c=='x') { if (s.charAt(1)=='a') {id=Id_max; break L0;} }
329
 
                    break L;
330
 
                case 'p': if (s.charAt(2)=='w' && s.charAt(1)=='o') {id=Id_pow; break L0;} break L;
331
 
                case 's': if (s.charAt(2)=='n' && s.charAt(1)=='i') {id=Id_sin; break L0;} break L;
332
 
                case 't': if (s.charAt(2)=='n' && s.charAt(1)=='a') {id=Id_tan; break L0;} break L;
333
 
                } break L;
334
 
            case 4: switch (s.charAt(1)) {
335
 
                case 'N': X="LN10";id=Id_LN10; break L;
336
 
                case 'c': X="acos";id=Id_acos; break L;
337
 
                case 'e': X="ceil";id=Id_ceil; break L;
338
 
                case 'q': X="sqrt";id=Id_sqrt; break L;
339
 
                case 's': X="asin";id=Id_asin; break L;
340
 
                case 't': X="atan";id=Id_atan; break L;
341
 
                } break L;
342
 
            case 5: switch (s.charAt(0)) {
343
 
                case 'L': X="LOG2E";id=Id_LOG2E; break L;
344
 
                case 'S': X="SQRT2";id=Id_SQRT2; break L;
345
 
                case 'a': X="atan2";id=Id_atan2; break L;
346
 
                case 'f': X="floor";id=Id_floor; break L;
347
 
                case 'r': X="round";id=Id_round; break L;
348
 
                } break L;
349
 
            case 6: c=s.charAt(0);
350
 
                if (c=='L') { X="LOG10E";id=Id_LOG10E; }
351
 
                else if (c=='r') { X="random";id=Id_random; }
352
 
                break L;
353
 
            case 7: X="SQRT1_2";id=Id_SQRT1_2; break L;
354
 
            }
355
 
            if (X!=null && X!=s && !X.equals(s)) id = 0;
356
 
        }
357
 
// #/generated#
358
 
        return id;
359
 
    }
360
 
 
361
 
    private static final int
362
 
        Id_abs          =  1,
363
 
        Id_acos         =  2,
364
 
        Id_asin         =  3,
365
 
        Id_atan         =  4,
366
 
        Id_atan2        =  5,
367
 
        Id_ceil         =  6,
368
 
        Id_cos          =  7,
369
 
        Id_exp          =  8,
370
 
        Id_floor        =  9,
371
 
        Id_log          = 10,
372
 
        Id_max          = 11,
373
 
        Id_min          = 12,
374
 
        Id_pow          = 13,
375
 
        Id_random       = 14,
376
 
        Id_round        = 15,
377
 
        Id_sin          = 16,
378
 
        Id_sqrt         = 17,
379
 
        Id_tan          = 18,
380
 
 
381
 
        LAST_METHOD_ID  = 18,
382
 
 
383
 
        Id_E            = 19,
384
 
        Id_PI           = 20,
385
 
        Id_LN10         = 21,
386
 
        Id_LN2          = 22,
387
 
        Id_LOG2E        = 23,
388
 
        Id_LOG10E       = 24,
389
 
        Id_SQRT1_2      = 25,
390
 
        Id_SQRT2        = 26,
391
 
 
392
 
        MAX_INSTANCE_ID = 26;
393
 
 
394
 
// #/string_id_map#
395
 
 
396
 
    private static final double
397
 
        E       = Math.E,
398
 
        PI      = Math.PI,
399
 
        LN10    = 2.302585092994046,
400
 
        LN2     = 0.6931471805599453,
401
 
        LOG2E   = 1.4426950408889634,
402
 
        LOG10E  = 0.4342944819032518,
403
 
        SQRT1_2 = 0.7071067811865476,
404
 
        SQRT2   = 1.4142135623730951;
405
 
}
 
1
/* -*- Mode: java; tab-width: 4; indent-tabs-mode: 1; c-basic-offset: 4 -*-
 
2
 *
 
3
 * The contents of this file are subject to the Netscape Public
 
4
 * License Version 1.1 (the "License"); you may not use this file
 
5
 * except in compliance with the License. You may obtain a copy of
 
6
 * the License at http://www.mozilla.org/NPL/
 
7
 *
 
8
 * Software distributed under the License is distributed on an "AS
 
9
 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
 
10
 * implied. See the License for the specific language governing
 
11
 * rights and limitations under the License.
 
12
 *
 
13
 * The Original Code is Rhino code, released
 
14
 * May 6, 1999.
 
15
 *
 
16
 * The Initial Developer of the Original Code is Netscape
 
17
 * Communications Corporation.  Portions created by Netscape are
 
18
 * Copyright (C) 1997-1999 Netscape Communications Corporation. All
 
19
 * Rights Reserved.
 
20
 *
 
21
 * Contributor(s):
 
22
 * Norris Boyd
 
23
 * Igor Bukanov
 
24
 *
 
25
 * Alternatively, the contents of this file may be used under the
 
26
 * terms of the GNU Public License (the "GPL"), in which case the
 
27
 * provisions of the GPL are applicable instead of those above.
 
28
 * If you wish to allow use of your version of this file only
 
29
 * under the terms of the GPL and not to allow others to use your
 
30
 * version of this file under the NPL, indicate your decision by
 
31
 * deleting the provisions above and replace them with the notice
 
32
 * and other provisions required by the GPL.  If you do not delete
 
33
 * the provisions above, a recipient may use your version of this
 
34
 * file under either the NPL or the GPL.
 
35
 */
 
36
 
 
37
package org.mozilla.javascript;
 
38
 
 
39
/**
 
40
 * This class implements the Math native object.
 
41
 * See ECMA 15.8.
 
42
 * @author Norris Boyd
 
43
 */
 
44
 
 
45
final class NativeMath extends IdScriptableObject
 
46
{
 
47
    private static final Object MATH_TAG = new Object();
 
48
 
 
49
    static void init(Context cx, Scriptable scope, boolean sealed)
 
50
    {
 
51
        NativeMath obj = new NativeMath();
 
52
        obj.activatePrototypeMap(MAX_ID);
 
53
        obj.setPrototype(getObjectPrototype(scope));
 
54
        obj.setParentScope(scope);
 
55
        if (sealed) { obj.sealObject(); }
 
56
        ScriptableObject.defineProperty(scope, "Math", obj,
 
57
                                        ScriptableObject.DONTENUM);
 
58
    }
 
59
 
 
60
    private NativeMath()
 
61
    {
 
62
    }
 
63
 
 
64
    public String getClassName() { return "Math"; }
 
65
 
 
66
    protected void initPrototypeId(int id)
 
67
    {
 
68
        if (id <= LAST_METHOD_ID) {
 
69
            String name;
 
70
            int arity;
 
71
            switch (id) {
 
72
              case Id_toSource: arity = 0; name = "toSource"; break;
 
73
              case Id_abs:      arity = 1; name = "abs";      break;
 
74
              case Id_acos:     arity = 1; name = "acos";     break;
 
75
              case Id_asin:     arity = 1; name = "asin";     break;
 
76
              case Id_atan:     arity = 1; name = "atan";     break;
 
77
              case Id_atan2:    arity = 2; name = "atan2";    break;
 
78
              case Id_ceil:     arity = 1; name = "ceil";     break;
 
79
              case Id_cos:      arity = 1; name = "cos";      break;
 
80
              case Id_exp:      arity = 1; name = "exp";      break;
 
81
              case Id_floor:    arity = 1; name = "floor";    break;
 
82
              case Id_log:      arity = 1; name = "log";      break;
 
83
              case Id_max:      arity = 2; name = "max";      break;
 
84
              case Id_min:      arity = 2; name = "min";      break;
 
85
              case Id_pow:      arity = 2; name = "pow";      break;
 
86
              case Id_random:   arity = 0; name = "random";   break;
 
87
              case Id_round:    arity = 1; name = "round";    break;
 
88
              case Id_sin:      arity = 1; name = "sin";      break;
 
89
              case Id_sqrt:     arity = 1; name = "sqrt";     break;
 
90
              case Id_tan:      arity = 1; name = "tan";      break;
 
91
              default: throw new IllegalStateException(String.valueOf(id));
 
92
            }
 
93
            initPrototypeMethod(MATH_TAG, id, name, arity);
 
94
        } else {
 
95
            String name;
 
96
            double x;
 
97
            switch (id) {
 
98
              case Id_E:       x = Math.E;             name = "E";       break;
 
99
              case Id_PI:      x = Math.PI;            name = "PI";      break;
 
100
              case Id_LN10:    x = 2.302585092994046;  name = "LN10";    break;
 
101
              case Id_LN2:     x = 0.6931471805599453; name = "LN2";     break;
 
102
              case Id_LOG2E:   x = 1.4426950408889634; name = "LOG2E";   break;
 
103
              case Id_LOG10E:  x = 0.4342944819032518; name = "LOG10E";  break;
 
104
              case Id_SQRT1_2: x = 0.7071067811865476; name = "SQRT1_2"; break;
 
105
              case Id_SQRT2:   x = 1.4142135623730951; name = "SQRT2";   break;
 
106
              default: throw new IllegalStateException(String.valueOf(id));
 
107
            }
 
108
            initPrototypeValue(id, name, ScriptRuntime.wrapNumber(x),
 
109
                               DONTENUM | READONLY | PERMANENT);
 
110
        }
 
111
    }
 
112
 
 
113
    public Object execIdCall(IdFunctionObject f, Context cx, Scriptable scope,
 
114
                             Scriptable thisObj, Object[] args)
 
115
    {
 
116
        if (!f.hasTag(MATH_TAG)) {
 
117
            return super.execIdCall(f, cx, scope, thisObj, args);
 
118
        }
 
119
        double x;
 
120
        int methodId = f.methodId();
 
121
        switch (methodId) {
 
122
            case Id_toSource:
 
123
                return "Math";
 
124
 
 
125
            case Id_abs:
 
126
                x = ScriptRuntime.toNumber(args, 0);
 
127
                // abs(-0.0) should be 0.0, but -0.0 < 0.0 == false
 
128
                x = (x == 0.0) ? 0.0 : (x < 0.0) ? -x : x;
 
129
                break;
 
130
 
 
131
            case Id_acos:
 
132
            case Id_asin:
 
133
                x = ScriptRuntime.toNumber(args, 0);
 
134
                if (x == x && -1.0 <= x && x <= 1.0) {
 
135
                    x = (methodId == Id_acos) ? Math.acos(x) : Math.asin(x);
 
136
                } else {
 
137
                    x = Double.NaN;
 
138
                }
 
139
                break;
 
140
 
 
141
            case Id_atan:
 
142
                x = ScriptRuntime.toNumber(args, 0);
 
143
                x = Math.atan(x);
 
144
                break;
 
145
 
 
146
            case Id_atan2:
 
147
                x = ScriptRuntime.toNumber(args, 0);
 
148
                x = Math.atan2(x, ScriptRuntime.toNumber(args, 1));
 
149
                break;
 
150
 
 
151
            case Id_ceil:
 
152
                x = ScriptRuntime.toNumber(args, 0);
 
153
                x = Math.ceil(x);
 
154
                break;
 
155
 
 
156
            case Id_cos:
 
157
                x = ScriptRuntime.toNumber(args, 0);
 
158
                x = (x == Double.POSITIVE_INFINITY
 
159
                     || x == Double.NEGATIVE_INFINITY)
 
160
                    ? Double.NaN : Math.cos(x);
 
161
                break;
 
162
 
 
163
            case Id_exp:
 
164
                x = ScriptRuntime.toNumber(args, 0);
 
165
                x = (x == Double.POSITIVE_INFINITY) ? x
 
166
                    : (x == Double.NEGATIVE_INFINITY) ? 0.0
 
167
                    : Math.exp(x);
 
168
                break;
 
169
 
 
170
            case Id_floor:
 
171
                x = ScriptRuntime.toNumber(args, 0);
 
172
                x = Math.floor(x);
 
173
                break;
 
174
 
 
175
            case Id_log:
 
176
                x = ScriptRuntime.toNumber(args, 0);
 
177
                // Java's log(<0) = -Infinity; we need NaN
 
178
                x = (x < 0) ? Double.NaN : Math.log(x);
 
179
                break;
 
180
 
 
181
            case Id_max:
 
182
            case Id_min:
 
183
                x = (methodId == Id_max)
 
184
                    ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
 
185
                for (int i = 0; i != args.length; ++i) {
 
186
                    double d = ScriptRuntime.toNumber(args[i]);
 
187
                    if (d != d) {
 
188
                        x = d; // NaN
 
189
                        break;
 
190
                    }
 
191
                    if (methodId == Id_max) {
 
192
                        // if (x < d) x = d; does not work due to -0.0 >= +0.0
 
193
                        x = Math.max(x, d);
 
194
                    } else {
 
195
                        x = Math.min(x, d);
 
196
                    }
 
197
                }
 
198
                break;
 
199
 
 
200
            case Id_pow:
 
201
                x = ScriptRuntime.toNumber(args, 0);
 
202
                x = js_pow(x, ScriptRuntime.toNumber(args, 1));
 
203
                break;
 
204
 
 
205
            case Id_random:
 
206
                x = Math.random();
 
207
                break;
 
208
 
 
209
            case Id_round:
 
210
                x = ScriptRuntime.toNumber(args, 0);
 
211
                if (x == x && x != Double.POSITIVE_INFINITY
 
212
                    && x != Double.NEGATIVE_INFINITY)
 
213
                {
 
214
                    // Round only finite x
 
215
                    long l = Math.round(x);
 
216
                    if (l != 0) {
 
217
                        x = (double)l;
 
218
                    } else {
 
219
                        // We must propagate the sign of d into the result
 
220
                        if (x < 0.0) {
 
221
                            x = ScriptRuntime.negativeZero;
 
222
                        } else if (x != 0.0) {
 
223
                            x = 0.0;
 
224
                        }
 
225
                    }
 
226
                }
 
227
                break;
 
228
 
 
229
            case Id_sin:
 
230
                x = ScriptRuntime.toNumber(args, 0);
 
231
                x = (x == Double.POSITIVE_INFINITY
 
232
                     || x == Double.NEGATIVE_INFINITY)
 
233
                    ? Double.NaN : Math.sin(x);
 
234
                break;
 
235
 
 
236
            case Id_sqrt:
 
237
                x = ScriptRuntime.toNumber(args, 0);
 
238
                x = Math.sqrt(x);
 
239
                break;
 
240
 
 
241
            case Id_tan:
 
242
                x = ScriptRuntime.toNumber(args, 0);
 
243
                x = Math.tan(x);
 
244
                break;
 
245
 
 
246
            default: throw new IllegalStateException(String.valueOf(methodId));
 
247
        }
 
248
        return ScriptRuntime.wrapNumber(x);
 
249
    }
 
250
 
 
251
    // See Ecma 15.8.2.13
 
252
    private double js_pow(double x, double y) {
 
253
        double result;
 
254
        if (y != y) {
 
255
            // y is NaN, result is always NaN
 
256
            result = y;
 
257
        } else if (y == 0) {
 
258
            // Java's pow(NaN, 0) = NaN; we need 1
 
259
            result = 1.0;
 
260
        } else if (x == 0) {
 
261
            // Many dirrerences from Java's Math.pow
 
262
            if (1 / x > 0) {
 
263
                result = (y > 0) ? 0 : Double.POSITIVE_INFINITY;
 
264
            } else {
 
265
                // x is -0, need to check if y is an odd integer
 
266
                long y_long = (long)y;
 
267
                if (y_long == y && (y_long & 0x1) != 0) {
 
268
                    result = (y > 0) ? -0.0 : Double.NEGATIVE_INFINITY;
 
269
                } else {
 
270
                    result = (y > 0) ? 0.0 : Double.POSITIVE_INFINITY;
 
271
                }
 
272
            }
 
273
        } else {
 
274
            result = Math.pow(x, y);
 
275
            if (result != result) {
 
276
                // Check for broken Java implementations that gives NaN
 
277
                // when they should return something else
 
278
                if (y == Double.POSITIVE_INFINITY) {
 
279
                    if (x < -1.0 || 1.0 < x) {
 
280
                        result = Double.POSITIVE_INFINITY;
 
281
                    } else if (-1.0 < x && x < 1.0) {
 
282
                        result = 0;
 
283
                    }
 
284
                } else if (y == Double.NEGATIVE_INFINITY) {
 
285
                    if (x < -1.0 || 1.0 < x) {
 
286
                        result = 0;
 
287
                    } else if (-1.0 < x && x < 1.0) {
 
288
                        result = Double.POSITIVE_INFINITY;
 
289
                    }
 
290
                } else if (x == Double.POSITIVE_INFINITY) {
 
291
                    result = (y > 0) ? Double.POSITIVE_INFINITY : 0.0;
 
292
                } else if (x == Double.NEGATIVE_INFINITY) {
 
293
                    long y_long = (long)y;
 
294
                    if (y_long == y && (y_long & 0x1) != 0) {
 
295
                        // y is odd integer
 
296
                        result = (y > 0) ? Double.NEGATIVE_INFINITY : -0.0;
 
297
                    } else {
 
298
                        result = (y > 0) ? Double.POSITIVE_INFINITY : 0.0;
 
299
                    }
 
300
                }
 
301
            }
 
302
        }
 
303
        return result;
 
304
    }
 
305
 
 
306
// #string_id_map#
 
307
 
 
308
    protected int findPrototypeId(String s)
 
309
    {
 
310
        int id;
 
311
// #generated# Last update: 2004-03-17 13:51:32 CET
 
312
        L0: { id = 0; String X = null; int c;
 
313
            L: switch (s.length()) {
 
314
            case 1: if (s.charAt(0)=='E') {id=Id_E; break L0;} break L;
 
315
            case 2: if (s.charAt(0)=='P' && s.charAt(1)=='I') {id=Id_PI; break L0;} break L;
 
316
            case 3: switch (s.charAt(0)) {
 
317
                case 'L': if (s.charAt(2)=='2' && s.charAt(1)=='N') {id=Id_LN2; break L0;} break L;
 
318
                case 'a': if (s.charAt(2)=='s' && s.charAt(1)=='b') {id=Id_abs; break L0;} break L;
 
319
                case 'c': if (s.charAt(2)=='s' && s.charAt(1)=='o') {id=Id_cos; break L0;} break L;
 
320
                case 'e': if (s.charAt(2)=='p' && s.charAt(1)=='x') {id=Id_exp; break L0;} break L;
 
321
                case 'l': if (s.charAt(2)=='g' && s.charAt(1)=='o') {id=Id_log; break L0;} break L;
 
322
                case 'm': c=s.charAt(2);
 
323
                    if (c=='n') { if (s.charAt(1)=='i') {id=Id_min; break L0;} }
 
324
                    else if (c=='x') { if (s.charAt(1)=='a') {id=Id_max; break L0;} }
 
325
                    break L;
 
326
                case 'p': if (s.charAt(2)=='w' && s.charAt(1)=='o') {id=Id_pow; break L0;} break L;
 
327
                case 's': if (s.charAt(2)=='n' && s.charAt(1)=='i') {id=Id_sin; break L0;} break L;
 
328
                case 't': if (s.charAt(2)=='n' && s.charAt(1)=='a') {id=Id_tan; break L0;} break L;
 
329
                } break L;
 
330
            case 4: switch (s.charAt(1)) {
 
331
                case 'N': X="LN10";id=Id_LN10; break L;
 
332
                case 'c': X="acos";id=Id_acos; break L;
 
333
                case 'e': X="ceil";id=Id_ceil; break L;
 
334
                case 'q': X="sqrt";id=Id_sqrt; break L;
 
335
                case 's': X="asin";id=Id_asin; break L;
 
336
                case 't': X="atan";id=Id_atan; break L;
 
337
                } break L;
 
338
            case 5: switch (s.charAt(0)) {
 
339
                case 'L': X="LOG2E";id=Id_LOG2E; break L;
 
340
                case 'S': X="SQRT2";id=Id_SQRT2; break L;
 
341
                case 'a': X="atan2";id=Id_atan2; break L;
 
342
                case 'f': X="floor";id=Id_floor; break L;
 
343
                case 'r': X="round";id=Id_round; break L;
 
344
                } break L;
 
345
            case 6: c=s.charAt(0);
 
346
                if (c=='L') { X="LOG10E";id=Id_LOG10E; }
 
347
                else if (c=='r') { X="random";id=Id_random; }
 
348
                break L;
 
349
            case 7: X="SQRT1_2";id=Id_SQRT1_2; break L;
 
350
            case 8: X="toSource";id=Id_toSource; break L;
 
351
            }
 
352
            if (X!=null && X!=s && !X.equals(s)) id = 0;
 
353
        }
 
354
// #/generated#
 
355
        return id;
 
356
    }
 
357
 
 
358
    private static final int
 
359
        Id_toSource     =  1,
 
360
        Id_abs          =  2,
 
361
        Id_acos         =  3,
 
362
        Id_asin         =  4,
 
363
        Id_atan         =  5,
 
364
        Id_atan2        =  6,
 
365
        Id_ceil         =  7,
 
366
        Id_cos          =  8,
 
367
        Id_exp          =  9,
 
368
        Id_floor        = 10,
 
369
        Id_log          = 11,
 
370
        Id_max          = 12,
 
371
        Id_min          = 13,
 
372
        Id_pow          = 14,
 
373
        Id_random       = 15,
 
374
        Id_round        = 16,
 
375
        Id_sin          = 17,
 
376
        Id_sqrt         = 18,
 
377
        Id_tan          = 19,
 
378
 
 
379
        LAST_METHOD_ID  = 19;
 
380
 
 
381
    private static final int
 
382
        Id_E            = LAST_METHOD_ID + 1,
 
383
        Id_PI           = LAST_METHOD_ID + 2,
 
384
        Id_LN10         = LAST_METHOD_ID + 3,
 
385
        Id_LN2          = LAST_METHOD_ID + 4,
 
386
        Id_LOG2E        = LAST_METHOD_ID + 5,
 
387
        Id_LOG10E       = LAST_METHOD_ID + 6,
 
388
        Id_SQRT1_2      = LAST_METHOD_ID + 7,
 
389
        Id_SQRT2        = LAST_METHOD_ID + 8,
 
390
 
 
391
        MAX_ID = LAST_METHOD_ID + 8;
 
392
 
 
393
// #/string_id_map#
 
394
}