/* * Copyright (c) 1998-2011 Caucho Technology -- all rights reserved * * This file is part of Resin(R) Open Source * * Each copy or derived work must preserve the copyright notice and this * notice unmodified. * * Resin Open Source is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Resin Open Source is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty * of NON-INFRINGEMENT. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with Resin Open Source; if not, write to the * Free SoftwareFoundation, Inc. * 59 Temple Place, Suite 330 * Boston, MA 02111-1307 USA * * @author Scott Ferguson */ package com.caucho.es; import java.util.Random; /** * JavaScript object */ class NativeMath extends Native { static final int ABS = 1; static final int ACOS = 2; static final int ASIN = 3; static final int ATAN = 4; static final int ATAN2 = 5; static final int CEIL = 6; static final int COS = 7; static final int EXP = 8; static final int FLOOR = 9; static final int LOG = 10; static final int MAX = 11; static final int MIN = 12; static final int POW = 13; static final int RANDOM = 14; static final int ROUND = 15; static final int SET_SEED = 16; static final int SIN = 17; static final int SQRT = 18; static final int TAN = 19; Random random; // XXX: s/b in global? /** * Create a new object based on a prototype */ private NativeMath(String name, int n, int len) { super(name, len); this.n = n; } /** * Creates the native Object object */ static ESObject create(Global resin) { ESObject math = new ESObject("Math", null); put(math, "abs", ABS, 1); put(math, "asin", ASIN, 1); put(math, "acos", ACOS, 1); put(math, "atan", ATAN, 1); put(math, "atan2", ATAN2, 2); put(math, "ceil", CEIL, 1); put(math, "cos", COS, 1); put(math, "exp", EXP, 1); put(math, "floor", FLOOR, 1); put(math, "log", LOG, 1); put(math, "max", MAX, 2); put(math, "min", MIN, 2); put(math, "pow", POW, 2); put(math, "round", ROUND, 1); put(math, "sin", SIN, 1); put(math, "sqrt", SQRT, 1); put(math, "tan", TAN, 1); put(math, "random", RANDOM, 0); put(math, "setSeed", SET_SEED, 1); int flags = DONT_ENUM|DONT_DELETE|READ_ONLY; math.put("E", ESNumber.create(Math.E), flags); math.put("LN10", ESNumber.create(Math.log(10.0)), flags); math.put("LN2", ESNumber.create(Math.log(2.0)), flags); math.put("LOG2E", ESNumber.create(1.0 / Math.log(2.0)), flags); math.put("LOG10E", ESNumber.create(1.0 / Math.log(10.0)), flags); math.put("PI", ESNumber.create(Math.PI), flags); math.put("SQRT1_2", ESNumber.create(Math.sqrt(0.5)), flags); math.put("SQRT2", ESNumber.create(Math.sqrt(2.0)), flags); // XXX: potential problems. Random random = new Random(); try { ((NativeMath) math.getProperty("random")).random = random; ((NativeMath) math.getProperty("setSeed")).random = random; } catch (Throwable e) { } math.setClean(); return math; } private static void put(ESObject obj, String name, int n, int length) { obj.put(name, new NativeMath(name, n, length), DONT_ENUM); } public ESBase call(Call eval, int length) throws Throwable { double arg; double value; switch (n) { case ABS: if (length == 0) return esUndefined; arg = eval.getArg(0).toNum(); return ESNumber.create(arg == 0 ? 0 : (arg < 0 ? -arg : arg)); case ACOS: if (length == 0) return esUndefined; return ESNumber.create(Math.acos(eval.getArg(0).toNum())); case ASIN: if (length == 0) return esUndefined; return ESNumber.create(Math.asin(eval.getArg(0).toNum())); case ATAN: if (length == 0) return esUndefined; return ESNumber.create(Math.atan(eval.getArg(0).toNum())); case ATAN2: if (length < 2) return esUndefined; return ESNumber.create(Math.atan2(eval.getArg(0).toNum(), eval.getArg(1).toNum())); case CEIL: if (length == 0) return esUndefined; return ESNumber.create(Math.ceil(eval.getArg(0).toNum())); case COS: if (length == 0) return esUndefined; return ESNumber.create(Math.cos(eval.getArg(0).toNum())); case EXP: if (length == 0) return esUndefined; return ESNumber.create(Math.exp(eval.getArg(0).toNum())); case FLOOR: if (length == 0) return esUndefined; return ESNumber.create(Math.floor(eval.getArg(0).toNum())); case LOG: if (length == 0) return esUndefined; return ESNumber.create(Math.log(eval.getArg(0).toNum())); case MAX: arg = -1.0/0.0; for (int i = 0; i < length; i++) { double v = eval.getArg(i).toNum(); arg = Math.max(v, arg); } return ESNumber.create(arg); case MIN: arg = 1.0/0.0; for (int i = 0; i < length; i++) { double v = eval.getArg(i).toNum(); arg = Math.min(v, arg); } return ESNumber.create(arg); case POW: if (length < 2) return esUndefined; return ESNumber.create(Math.pow(eval.getArg(0).toNum(), eval.getArg(1).toNum())); case RANDOM: { if (length > 1) { int n = eval.getArg(0).toInt32(); if (n > 0) return ESNumber.create((int) (random.nextDouble() * n)); } else { return ESNumber.create(random.nextDouble()); } } case ROUND: if (length == 0) return esUndefined; arg = eval.getArg(0).toNum(); if (arg >= -0.5 && arg < 0.5) return ESNumber.create(Math.rint(arg)); else return ESNumber.create(Math.floor(arg + 0.5)); case SET_SEED: if (length != 0) random.setSeed((long) eval.getArg(0).toNum()); return esUndefined; case SIN: if (length == 0) return esUndefined; return ESNumber.create(Math.sin(eval.getArg(0).toNum())); case SQRT: if (length == 0) return esUndefined; return ESNumber.create(Math.sqrt(eval.getArg(0).toNum())); case TAN: if (length == 0) return esUndefined; return ESNumber.create(Math.tan(eval.getArg(0).toNum())); default: throw new ESException("Undefined math function"); } } }