1 /* -*- Mode: java; tab-width: 4; indent-tabs-mode: 1; c-basic-offset: 4 -*-
\r
3 * The contents of this file are subject to the Netscape Public
\r
4 * License Version 1.1 (the "License"); you may not use this file
\r
5 * except in compliance with the License. You may obtain a copy of
\r
6 * the License at http://www.mozilla.org/NPL/
\r
8 * Software distributed under the License is distributed on an "AS
\r
9 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
\r
10 * implied. See the License for the specific language governing
\r
11 * rights and limitations under the License.
\r
13 * The Original Code is Rhino code, released
\r
16 * The Initial Developer of the Original Code is Netscape
\r
17 * Communications Corporation. Portions created by Netscape are
\r
18 * Copyright (C) 1997-1999 Netscape Communications Corporation. All
\r
25 * Alternatively, the contents of this file may be used under the
\r
26 * terms of the GNU Public License (the "GPL"), in which case the
\r
27 * provisions of the GPL are applicable instead of those above.
\r
28 * If you wish to allow use of your version of this file only
\r
29 * under the terms of the GPL and not to allow others to use your
\r
30 * version of this file under the NPL, indicate your decision by
\r
31 * deleting the provisions above and replace them with the notice
\r
32 * and other provisions required by the GPL. If you do not delete
\r
33 * the provisions above, a recipient may use your version of this
\r
34 * file under either the NPL or the GPL.
\r
37 package org.mozilla.javascript;
\r
40 * This class implements the Math native object.
\r
42 * @author Norris Boyd
\r
45 public class NativeMath extends IdScriptable
\r
47 public static void init(Context cx, Scriptable scope, boolean sealed) {
\r
48 NativeMath obj = new NativeMath();
\r
49 obj.setSealFunctionsFlag(sealed);
\r
50 obj.setFunctionParametrs(cx);
\r
51 obj.setPrototype(getObjectPrototype(scope));
\r
52 obj.setParentScope(scope);
\r
53 if (sealed) { obj.sealObject(); }
\r
54 ScriptableObject.defineProperty(scope, "Math", obj,
\r
55 ScriptableObject.DONTENUM);
\r
58 public String getClassName() { return "Math"; }
\r
60 protected int getIdDefaultAttributes(int id) {
\r
61 if (id > LAST_METHOD_ID) {
\r
62 return DONTENUM | READONLY | PERMANENT;
\r
64 return super.getIdDefaultAttributes(id);
\r
67 protected Object getIdValue(int id) {
\r
68 if (id > LAST_METHOD_ID) {
\r
69 return cacheIdValue(id, wrap_double(getField(id)));
\r
71 return super.getIdValue(id);
\r
74 private double getField(int fieldId) {
\r
76 case Id_E: return E;
\r
77 case Id_PI: return PI;
\r
78 case Id_LN10: return LN10;
\r
79 case Id_LN2: return LN2;
\r
80 case Id_LOG2E: return LOG2E;
\r
81 case Id_LOG10E: return LOG10E;
\r
82 case Id_SQRT1_2: return SQRT1_2;
\r
83 case Id_SQRT2: return SQRT2;
\r
85 return 0; // Unreachable
\r
88 public int methodArity(int methodId) {
\r
90 case Id_abs: return 1;
\r
91 case Id_acos: return 1;
\r
92 case Id_asin: return 1;
\r
93 case Id_atan: return 1;
\r
94 case Id_atan2: return 2;
\r
95 case Id_ceil: return 1;
\r
96 case Id_cos: return 1;
\r
97 case Id_exp: return 1;
\r
98 case Id_floor: return 1;
\r
99 case Id_log: return 1;
\r
100 case Id_max: return 2;
\r
101 case Id_min: return 2;
\r
102 case Id_pow: return 2;
\r
103 case Id_random: return 0;
\r
104 case Id_round: return 1;
\r
105 case Id_sin: return 1;
\r
106 case Id_sqrt: return 1;
\r
107 case Id_tan: return 1;
\r
109 return super.methodArity(methodId);
\r
112 public Object execMethod
\r
113 (int methodId, IdFunction f,
\r
114 Context cx, Scriptable scope, Scriptable thisObj, Object[] args)
\r
115 throws JavaScriptException
\r
117 switch (methodId) {
\r
118 case Id_abs: return wrap_double
\r
119 (js_abs(ScriptRuntime.toNumber(args, 0)));
\r
121 case Id_acos: return wrap_double
\r
122 (js_acos(ScriptRuntime.toNumber(args, 0)));
\r
124 case Id_asin: return wrap_double
\r
125 (js_asin(ScriptRuntime.toNumber(args, 0)));
\r
127 case Id_atan: return wrap_double
\r
128 (js_atan(ScriptRuntime.toNumber(args, 0)));
\r
130 case Id_atan2: return wrap_double
\r
131 (js_atan2(ScriptRuntime.toNumber(args, 0),
\r
132 ScriptRuntime.toNumber(args, 1)));
\r
134 case Id_ceil: return wrap_double
\r
135 (js_ceil(ScriptRuntime.toNumber(args, 0)));
\r
137 case Id_cos: return wrap_double
\r
138 (js_cos(ScriptRuntime.toNumber(args, 0)));
\r
140 case Id_exp: return wrap_double
\r
141 (js_exp(ScriptRuntime.toNumber(args, 0)));
\r
143 case Id_floor: return wrap_double
\r
144 (js_floor(ScriptRuntime.toNumber(args, 0)));
\r
146 case Id_log: return wrap_double
\r
147 (js_log(ScriptRuntime.toNumber(args, 0)));
\r
149 case Id_max: return wrap_double
\r
152 case Id_min: return wrap_double
\r
155 case Id_pow: return wrap_double
\r
156 (js_pow(ScriptRuntime.toNumber(args, 0),
\r
157 ScriptRuntime.toNumber(args, 1)));
\r
159 case Id_random: return wrap_double
\r
162 case Id_round: return wrap_double
\r
163 (js_round(ScriptRuntime.toNumber(args, 0)));
\r
165 case Id_sin: return wrap_double
\r
166 (js_sin(ScriptRuntime.toNumber(args, 0)));
\r
168 case Id_sqrt: return wrap_double
\r
169 (js_sqrt(ScriptRuntime.toNumber(args, 0)));
\r
171 case Id_tan: return wrap_double
\r
172 (js_tan(ScriptRuntime.toNumber(args, 0)));
\r
174 return super.execMethod(methodId, f, cx, scope, thisObj, args);
\r
177 private double js_abs(double x) {
\r
178 // abs(-0.0) should be 0.0, but -0.0 < 0.0 == false
\r
179 return (x == 0.0) ? 0.0 : (x < 0.0) ? -x : x;
\r
182 private double js_acos(double x) {
\r
183 return (x == x && -1.0 <= x && x <= 1.0) ? Math.acos(x) : Double.NaN;
\r
186 private double js_asin(double x) {
\r
187 return (x == x && -1.0 <= x && x <= 1.0) ? Math.asin(x) : Double.NaN;
\r
190 private double js_atan(double x) { return Math.atan(x); }
\r
192 private double js_atan2(double x, double y) { return Math.atan2(x, y); }
\r
194 private double js_ceil(double x) { return Math.ceil(x); }
\r
196 private double js_cos(double x) { return Math.cos(x); }
\r
198 private double js_exp(double x) {
\r
199 return (x == Double.POSITIVE_INFINITY) ? x
\r
200 : (x == Double.NEGATIVE_INFINITY) ? 0.0
\r
204 private double js_floor(double x) { return Math.floor(x); }
\r
206 private double js_log(double x) {
\r
207 // Java's log(<0) = -Infinity; we need NaN
\r
208 return (x < 0) ? Double.NaN : Math.log(x);
\r
211 private double js_max(Object[] args) {
\r
212 double result = Double.NEGATIVE_INFINITY;
\r
213 if (args.length == 0)
\r
215 for (int i = 0; i < args.length; i++) {
\r
216 double d = ScriptRuntime.toNumber(args[i]);
\r
217 if (d != d) return d;
\r
218 // if (result < d) result = d; does not work due to -0.0 >= +0.0
\r
219 result = Math.max(result, d);
\r
224 private double js_min(Object[] args) {
\r
225 double result = Double.POSITIVE_INFINITY;
\r
226 if (args.length == 0)
\r
228 for (int i = 0; i < args.length; i++) {
\r
229 double d = ScriptRuntime.toNumber(args[i]);
\r
230 if (d != d) return d;
\r
231 // if (result > d) result = d; does not work due to -0.0 >= +0.0
\r
232 result = Math.min(result, d);
\r
237 private double js_pow(double x, double y) {
\r
238 if (y == 0) return 1.0; // Java's pow(NaN, 0) = NaN; we need 1
\r
239 if ((x == 0) && (y < 0)) {
\r
241 // x is +0, Java is -oo, we need +oo
\r
242 return Double.POSITIVE_INFINITY;
\r
244 /* if x is -0 and y is an odd integer, -oo */
\r
245 int y_int = (int)y;
\r
246 if (y_int == y && (y_int & 0x1) != 0)
\r
247 return Double.NEGATIVE_INFINITY;
\r
248 return Double.POSITIVE_INFINITY;
\r
250 return Math.pow(x, y);
\r
253 private double js_random() { return Math.random(); }
\r
255 private double js_round(double d) {
\r
258 if (d == Double.POSITIVE_INFINITY || d == Double.NEGATIVE_INFINITY)
\r
260 long l = Math.round(d);
\r
262 // We must propagate the sign of d into the result
\r
264 return ScriptRuntime.negativeZero;
\r
265 return d == 0.0 ? d : 0.0;
\r
270 private double js_sin(double x) { return Math.sin(x); }
\r
272 private double js_sqrt(double x) { return Math.sqrt(x); }
\r
274 private double js_tan(double x) { return Math.tan(x); }
\r
276 protected int maxInstanceId() { return MAX_INSTANCE_ID; }
\r
278 protected String getIdName(int id) {
\r
280 case Id_abs: return "abs";
\r
281 case Id_acos: return "acos";
\r
282 case Id_asin: return "asin";
\r
283 case Id_atan: return "atan";
\r
284 case Id_atan2: return "atan2";
\r
285 case Id_ceil: return "ceil";
\r
286 case Id_cos: return "cos";
\r
287 case Id_exp: return "exp";
\r
288 case Id_floor: return "floor";
\r
289 case Id_log: return "log";
\r
290 case Id_max: return "max";
\r
291 case Id_min: return "min";
\r
292 case Id_pow: return "pow";
\r
293 case Id_random: return "random";
\r
294 case Id_round: return "round";
\r
295 case Id_sin: return "sin";
\r
296 case Id_sqrt: return "sqrt";
\r
297 case Id_tan: return "tan";
\r
299 case Id_E: return "E";
\r
300 case Id_PI: return "PI";
\r
301 case Id_LN10: return "LN10";
\r
302 case Id_LN2: return "LN2";
\r
303 case Id_LOG2E: return "LOG2E";
\r
304 case Id_LOG10E: return "LOG10E";
\r
305 case Id_SQRT1_2: return "SQRT1_2";
\r
306 case Id_SQRT2: return "SQRT2";
\r
313 protected int mapNameToId(String s) {
\r
315 // #generated# Last update: 2001-03-23 13:50:14 GMT+01:00
\r
316 L0: { id = 0; String X = null; int c;
\r
317 L: switch (s.length()) {
\r
318 case 1: if (s.charAt(0)=='E') {id=Id_E; break L0;} break L;
\r
319 case 2: if (s.charAt(0)=='P' && s.charAt(1)=='I') {id=Id_PI; break L0;} break L;
\r
320 case 3: switch (s.charAt(0)) {
\r
321 case 'L': if (s.charAt(2)=='2' && s.charAt(1)=='N') {id=Id_LN2; break L0;} break L;
\r
322 case 'a': if (s.charAt(2)=='s' && s.charAt(1)=='b') {id=Id_abs; break L0;} break L;
\r
323 case 'c': if (s.charAt(2)=='s' && s.charAt(1)=='o') {id=Id_cos; break L0;} break L;
\r
324 case 'e': if (s.charAt(2)=='p' && s.charAt(1)=='x') {id=Id_exp; break L0;} break L;
\r
325 case 'l': if (s.charAt(2)=='g' && s.charAt(1)=='o') {id=Id_log; break L0;} break L;
\r
326 case 'm': c=s.charAt(2);
\r
327 if (c=='n') { if (s.charAt(1)=='i') {id=Id_min; break L0;} }
\r
328 else if (c=='x') { if (s.charAt(1)=='a') {id=Id_max; break L0;} }
\r
330 case 'p': if (s.charAt(2)=='w' && s.charAt(1)=='o') {id=Id_pow; break L0;} break L;
\r
331 case 's': if (s.charAt(2)=='n' && s.charAt(1)=='i') {id=Id_sin; break L0;} break L;
\r
332 case 't': if (s.charAt(2)=='n' && s.charAt(1)=='a') {id=Id_tan; break L0;} break L;
\r
334 case 4: switch (s.charAt(1)) {
\r
335 case 'N': X="LN10";id=Id_LN10; break L;
\r
336 case 'c': X="acos";id=Id_acos; break L;
\r
337 case 'e': X="ceil";id=Id_ceil; break L;
\r
338 case 'q': X="sqrt";id=Id_sqrt; break L;
\r
339 case 's': X="asin";id=Id_asin; break L;
\r
340 case 't': X="atan";id=Id_atan; break L;
\r
342 case 5: switch (s.charAt(0)) {
\r
343 case 'L': X="LOG2E";id=Id_LOG2E; break L;
\r
344 case 'S': X="SQRT2";id=Id_SQRT2; break L;
\r
345 case 'a': X="atan2";id=Id_atan2; break L;
\r
346 case 'f': X="floor";id=Id_floor; break L;
\r
347 case 'r': X="round";id=Id_round; break L;
\r
349 case 6: c=s.charAt(0);
\r
350 if (c=='L') { X="LOG10E";id=Id_LOG10E; }
\r
351 else if (c=='r') { X="random";id=Id_random; }
\r
353 case 7: X="SQRT1_2";id=Id_SQRT1_2; break L;
\r
355 if (X!=null && X!=s && !X.equals(s)) id = 0;
\r
361 private static final int
\r
381 LAST_METHOD_ID = 18,
\r
392 MAX_INSTANCE_ID = 26;
\r
394 // #/string_id_map#
\r
396 private static final double
\r
399 LN10 = 2.302585092994046,
\r
400 LN2 = 0.6931471805599453,
\r
401 LOG2E = 1.4426950408889634,
\r
402 LOG10E = 0.4342944819032518,
\r
403 SQRT1_2 = 0.7071067811865476,
\r
404 SQRT2 = 1.4142135623730951;
\r