/* * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.sf.antcontrib.math; import org.apache.tools.ant.BuildException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; /** * Utility class for executing calculations. * * @author inger */ public class Math { public static final Number evaluate(String operation, String datatype, boolean strict, Evaluateable operands[]) { if (datatype == null) datatype = "double"; try { operation = operation.toLowerCase(); Method m = Math.class.getDeclaredMethod(operation, new Class[]{ String.class, Boolean.TYPE, operands.getClass() }); Number n = (Number) m.invoke(null, new Object[]{ datatype, strict ? Boolean.TRUE : Boolean.FALSE, operands }); return n; } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.getTargetException().printStackTrace(); } return null; } public static final Number add(String datatype, boolean strict, Evaluateable operands[]) { Number result = null; Number numbers[] = new Number[operands.length]; for (int i = 0; i < operands.length; i++) numbers[i] = operands[i].evaluate(); if (datatype.equalsIgnoreCase("int")) { int sum = 0; for (int i = 0; i < numbers.length; i++) sum += numbers[i].intValue(); result = new Integer(sum); } else if (datatype.equalsIgnoreCase("long")) { long sum = 0; for (int i = 0; i < numbers.length; i++) sum += numbers[i].longValue(); result = new Long(sum); } else if (datatype.equalsIgnoreCase("float")) { float sum = 0; for (int i = 0; i < numbers.length; i++) sum += numbers[i].floatValue(); result = new Float(sum); } else if (datatype.equalsIgnoreCase("double")) { double sum = 0; for (int i = 0; i < numbers.length; i++) sum += numbers[i].doubleValue(); result = new Double(sum); } return result; } public static final Number subtract(String datatype, boolean strict, Evaluateable operands[]) { Number result = null; Number numbers[] = new Number[operands.length]; for (int i = 0; i < operands.length; i++) numbers[i] = operands[i].evaluate(); if (datatype.equalsIgnoreCase("int")) { int sum = numbers[0].intValue(); for (int i = 1; i < numbers.length; i++) sum -= numbers[i].intValue(); result = new Integer(sum); } else if (datatype.equalsIgnoreCase("long")) { long sum = numbers[0].longValue(); for (int i = 1; i < numbers.length; i++) sum -= numbers[i].longValue(); result = new Long(sum); } else if (datatype.equalsIgnoreCase("float")) { float sum = numbers[0].floatValue(); for (int i = 1; i < numbers.length; i++) sum -= numbers[i].floatValue(); result = new Float(sum); } else if (datatype.equalsIgnoreCase("double")) { double sum = numbers[0].doubleValue(); for (int i = 1; i < numbers.length; i++) sum -= numbers[i].doubleValue(); result = new Double(sum); } return result; } public static final Number multiply(String datatype, boolean strict, Evaluateable operands[]) { Number result = null; Number numbers[] = new Number[operands.length]; for (int i = 0; i < operands.length; i++) numbers[i] = operands[i].evaluate(); if (datatype.equalsIgnoreCase("int")) { int sum = 1; for (int i = 0; i < numbers.length; i++) sum *= numbers[i].intValue(); result = new Integer(sum); } else if (datatype.equalsIgnoreCase("long")) { long sum = 1; for (int i = 0; i < numbers.length; i++) sum *= numbers[i].longValue(); result = new Long(sum); } else if (datatype.equalsIgnoreCase("float")) { float sum = 1; for (int i = 0; i < numbers.length; i++) sum *= numbers[i].floatValue(); result = new Float(sum); } else if (datatype.equalsIgnoreCase("double")) { double sum = 1; for (int i = 0; i < numbers.length; i++) sum *= numbers[i].doubleValue(); result = new Double(sum); } return result; } public static final Number divide(String datatype, boolean strict, Evaluateable operands[]) { Number result = null; Number numbers[] = new Number[operands.length]; for (int i = 0; i < operands.length; i++) numbers[i] = operands[i].evaluate(); if (datatype.equalsIgnoreCase("int")) { int sum = numbers[0].intValue(); for (int i = 1; i < numbers.length; i++) sum /= numbers[i].intValue(); result = new Integer(sum); } else if (datatype.equalsIgnoreCase("long")) { long sum = numbers[0].longValue(); for (int i = 1; i < numbers.length; i++) sum /= numbers[i].longValue(); result = new Long(sum); } else if (datatype.equalsIgnoreCase("float")) { float sum = numbers[0].floatValue(); for (int i = 1; i < numbers.length; i++) sum /= numbers[i].floatValue(); result = new Float(sum); } else if (datatype.equalsIgnoreCase("double")) { double sum = numbers[0].doubleValue(); for (int i = 1; i < numbers.length; i++) sum /= numbers[i].doubleValue(); result = new Double(sum); } return result; } public static final Number mod(String datatype, boolean strict, Evaluateable operands[]) { Number result = null; Number numbers[] = new Number[operands.length]; for (int i = 0; i < operands.length; i++) numbers[i] = operands[i].evaluate(); if (datatype.equalsIgnoreCase("int")) { int sum = numbers[0].intValue(); for (int i = 1; i < numbers.length; i++) sum %= numbers[i].intValue(); result = new Integer(sum); } else if (datatype.equalsIgnoreCase("long")) { long sum = numbers[0].longValue(); for (int i = 1; i < numbers.length; i++) sum %= numbers[i].longValue(); result = new Long(sum); } else if (datatype.equalsIgnoreCase("float")) { float sum = numbers[0].floatValue(); for (int i = 1; i < numbers.length; i++) sum %= numbers[i].floatValue(); result = new Float(sum); } else if (datatype.equalsIgnoreCase("double")) { double sum = numbers[0].doubleValue(); for (int i = 1; i < numbers.length; i++) sum %= numbers[i].doubleValue(); result = new Double(sum); } return result; } public static final Number convert(Number n, String datatype) { if (datatype == null) datatype = "double"; if (datatype.equals("int")) return new Integer(n.intValue()); if (datatype.equals("long")) return new Long(n.longValue()); if (datatype.equals("float")) return new Float(n.floatValue()); if (datatype.equals("double")) return new Double(n.doubleValue()); throw new BuildException("Invalid datatype."); } public static final Number execute(String method, String datatype, boolean strict, Class paramTypes[], Object params[]) { try { Class c = null; if (strict) { c = Thread.currentThread().getContextClassLoader().loadClass("java.lang.StrictMath"); } else { c = Thread.currentThread().getContextClassLoader().loadClass("java.lang.Math"); } Method m = c.getDeclaredMethod(method, paramTypes); Number n = (Number) m.invoke(null, params); return convert(n, datatype); } catch (ClassNotFoundException e) { throw new BuildException(e); } catch (NoSuchMethodException e) { throw new BuildException(e); } catch (IllegalAccessException e) { throw new BuildException(e); } catch (InvocationTargetException e) { throw new BuildException(e); } } public static final Number random(String datatype, boolean strict, Evaluateable operands[]) { return execute("random", datatype, strict, new Class[0], new Object[0]); } public static Class getPrimitiveClass(String datatype) { if (datatype == null) return Double.TYPE; if (datatype.equals("int")) return Integer.TYPE; if (datatype.equals("long")) return Long.TYPE; if (datatype.equals("float")) return Float.TYPE; if (datatype.equals("double")) return Double.TYPE; throw new BuildException("Invalid datatype."); } public static final Number abs(String datatype, boolean strict, Evaluateable operands[]) { Object ops[] = new Object[]{convert(operands[0].evaluate(), datatype)}; Class params[] = new Class[]{getPrimitiveClass(datatype)}; return execute("abs", datatype, strict, params, ops); } private static final Number doOneDoubleArg(String operation, String datatype, boolean strict, Evaluateable operands[]) { Object ops[] = new Object[]{convert(operands[0].evaluate(), "double")}; Class params[] = new Class[]{Double.TYPE}; return execute(operation, datatype, strict, params, ops); } public static final Number acos(String datatype, boolean strict, Evaluateable operands[]) { return doOneDoubleArg("acos", datatype, strict, operands); } public static final Number asin(String datatype, boolean strict, Evaluateable operands[]) { return doOneDoubleArg("asin", datatype, strict, operands); } public static final Number atan(String datatype, boolean strict, Evaluateable operands[]) { return doOneDoubleArg("atan", datatype, strict, operands); } public static final Number atan2(String datatype, boolean strict, Evaluateable operands[]) { Object ops[] = new Object[]{convert(operands[0].evaluate(), "double"), convert(operands[1].evaluate(), "double")}; Class params[] = new Class[]{Double.TYPE, Double.TYPE}; return execute("atan2", datatype, strict, params, ops); } public static final Number sin(String datatype, boolean strict, Evaluateable operands[]) { return doOneDoubleArg("sin", datatype, strict, operands); } public static final Number tan(String datatype, boolean strict, Evaluateable operands[]) { return doOneDoubleArg("sin", datatype, strict, operands); } public static final Number cos(String datatype, boolean strict, Evaluateable operands[]) { return doOneDoubleArg("cos", datatype, strict, operands); } public static final Number ceil(String datatype, boolean strict, Evaluateable operands[]) { return doOneDoubleArg("ceil", datatype, strict, operands); } public static final Number floor(String datatype, boolean strict, Evaluateable operands[]) { return doOneDoubleArg("floor", datatype, strict, operands); } public static final Number exp(String datatype, boolean strict, Evaluateable operands[]) { return doOneDoubleArg("exp", datatype, strict, operands); } public static final Number rint(String datatype, boolean strict, Evaluateable operands[]) { return doOneDoubleArg("rint", datatype, strict, operands); } public static final Number round(String datatype, boolean strict, Evaluateable operands[]) { Object ops[] = new Object[]{convert(operands[0].evaluate(), datatype)}; Class params[] = new Class[]{getPrimitiveClass(datatype)}; return execute("round", datatype, strict, params, ops); } public static final Number sqrt(String datatype, boolean strict, Evaluateable operands[]) { return doOneDoubleArg("sqrt", datatype, strict, operands); } public static final Number degrees(String datatype, boolean strict, Evaluateable operands[]) { return todegrees(datatype, strict, operands); } public static final Number todegrees(String datatype, boolean strict, Evaluateable operands[]) { return doOneDoubleArg("toDegrees", datatype, strict, operands); } public static final Number radians(String datatype, boolean strict, Evaluateable operands[]) { return toradians(datatype, strict, operands); } public static final Number toradians(String datatype, boolean strict, Evaluateable operands[]) { return doOneDoubleArg("toRadians", datatype, strict, operands); } public static final Number ieeeremainder(String datatype, boolean strict, Evaluateable operands[]) { Object ops[] = new Object[]{convert(operands[0].evaluate(), "double"), convert(operands[1].evaluate(), "double")}; Class params[] = new Class[]{Double.TYPE, Double.TYPE}; return execute("IEEERemainder", datatype, strict, params, ops); } public static final Number min(String datatype, boolean strict, Evaluateable operands[]) { Object ops[] = new Object[]{convert(operands[0].evaluate(), datatype), convert(operands[1].evaluate(), datatype)}; Class params[] = new Class[]{getPrimitiveClass(datatype), getPrimitiveClass(datatype)}; return execute("min", datatype, strict, params, ops); } public static final Number max(String datatype, boolean strict, Evaluateable operands[]) { Object ops[] = new Object[]{convert(operands[0].evaluate(), datatype), convert(operands[1].evaluate(), datatype)}; Class params[] = new Class[]{getPrimitiveClass(datatype), getPrimitiveClass(datatype)}; return execute("max", datatype, strict, params, ops); } }