All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.adobe.xfa.formcalc.BuiltinMath Maven / Gradle / Ivy

The newest version!
/*
 * ADOBE CONFIDENTIAL
 *
 * Copyright 2007 Adobe Systems Incorporated All Rights Reserved.
 *
 * NOTICE: All information contained herein is, and remains the property of
 * Adobe Systems Incorporated and its suppliers, if any. The intellectual and
 * technical concepts contained herein are proprietary to Adobe Systems
 * Incorporated and its suppliers and may be covered by U.S. and Foreign
 * Patents, patents in process, and are protected by trade secret or copyright
 * law. Dissemination of this information or reproduction of this material
 * is strictly forbidden unless prior written permission is obtained from
 * Adobe Systems Incorporated.
 */
package com.adobe.xfa.formcalc;


/**
 * This class defines static methods to implement
 * the FormCalc arithmetic calculations.
 *
 *  M A T H   F U N C T I O N S
 *      abs, avg, ceil, count, floor, max, min, mod, round, sum.
 *
 * @author Mike P. Tardif
 *
 * @exclude from published api.
 */
final class BuiltinMath {

	/*
	 *  Disallow instances of this class.
	 */
	private BuiltinMath() {
	}

	/*
	 *  Abs   
	 *      This function returns the absolute value of a given number.
	 *
	 */
	static void Abs(CalcParser oParser, CalcSymbol[] oArgSym) {
		final int nArgs = oArgSym.length;
		CalcSymbol oRetSym = null;
		try {
			//
			// check the number of args vs the number required.
			//
			Builtins.minArgs(nArgs, 1);
			Builtins.maxArgs(nArgs, 1);
			//
			// check for error-valued, return-valued and null-valued args.
			//
			Builtins.limitExceptionArgs(oArgSym);
			Builtins.limitNullArgs(oParser, nArgs, oArgSym);
			//
			// promote the arg to a double, and take its absolute value.
			//
			double nVal = oParser.getNumeric(oArgSym[0]);
			oRetSym = new CalcSymbol(Math.abs(nVal));
		} catch (CalcException e) {
			oRetSym = e.getSymbol();
			if (oRetSym.getType() != CalcSymbol.TypeNull)
				oParser.mbInThrow = true;
		}
		//
		// push the result on the stack.
		//
		oParser.mStack.push(oRetSym);
	}


	/*
	 *  Avg   
	 *      This function returns the average value of a given set of numbers.
	 *
	 */
	static void Avg(CalcParser oParser, CalcSymbol[] oArgSym) {
		CalcSymbol oRetSym = null;
		try {
			//
			// check for error-valued and return-valued args.
			//
			Builtins.limitExceptionArgs(oArgSym);
			try {
				//
				// ensure not all args are null.
				//
				oArgSym = Builtins.limitAllNullArgs(oParser, oArgSym);
				//
				// compute the average value in the given set.
				//
				oRetSym = computeAvg(oParser, oArgSym);
			} catch (CalcException e) {
				//
				// all args are null -- return null.
				//
				oRetSym = new CalcSymbol();
			}
		} catch (CalcException e) {
			oRetSym = e.getSymbol();
			if (oRetSym.getType() != CalcSymbol.TypeNull)
				oParser.mbInThrow = true;
		}
		//
		// push the result on the stack.
		//
		oParser.mStack.push(oRetSym);
	}


	/*
	 *  Ceil  
	 *      This function returns the smallest whole number greater than
	 *      or equal to a given number.
	 *
	 */
	static void Ceil(CalcParser oParser, CalcSymbol[] oArgSym) {
		final int nArgs = oArgSym.length;
		CalcSymbol oRetSym = null;
		try {
			//
			// check the number of args vs the number required.
			//
			Builtins.minArgs(nArgs, 1);
			Builtins.maxArgs(nArgs, 1);
			//
			// check for error-valued, return-valued and null-valued args.
			//
			Builtins.limitExceptionArgs(oArgSym);
			Builtins.limitNullArgs(oParser, nArgs, oArgSym);
			//
			// promote the arg to a double, and take its ceiling
			//
			double nVal = oParser.getNumeric(oArgSym[0]);
			oRetSym = new CalcSymbol(Math.ceil(nVal));
		} catch (CalcException e) {
			oRetSym = e.getSymbol();
			if (oRetSym.getType() != CalcSymbol.TypeNull)
				oParser.mbInThrow = true;
		}
		//
		// push the result on the stack.
		//
		oParser.mStack.push(oRetSym);
	}


	/*
	 *  Count 
	 *      This function returns the count of a given set of numbers.
	 *
	 */
	static void Count(CalcParser oParser, CalcSymbol[] oArgSym) {
		CalcSymbol oRetSym = null;
		try {
			//
			// check for error-valued and return-valued args.
			//
			Builtins.limitExceptionArgs(oArgSym);
			try {
				//
				// ensure not all args are null.
				//
				oArgSym = Builtins.limitAllNullArgs(oParser, oArgSym);
				//
				// compute the count of the given set.
				//
				oRetSym = computeCnt(oParser, oArgSym);
			} catch (CalcException e) {
				//
				// args are null -- return 0.
				//
				oRetSym = new CalcSymbol(0);
			}
		} catch (CalcException e) {
			oRetSym = e.getSymbol();
			if (oRetSym.getType() != CalcSymbol.TypeNull)
				oParser.mbInThrow = true;
		}
		//
		// push the result on the stack.
		//
		oParser.mStack.push(oRetSym);
	}


	/*
	 *  Floor 
	 *      This function returns the largest whole number greater than
	 *      or equal to a given number.
	 *
	 */
	static void Floor(CalcParser oParser, CalcSymbol[] oArgSym) {
		final int nArgs = oArgSym.length;
		CalcSymbol oRetSym = null;
		try {
			//
			// check the number of args vs the number required.
			//
			Builtins.minArgs(nArgs, 1);
			Builtins.maxArgs(nArgs, 1);
			//
			// check for error-valued, return-valued and null-valued args.
			//
			Builtins.limitExceptionArgs(oArgSym);
			Builtins.limitNullArgs(oParser, nArgs, oArgSym);
			//
			// oromote the arg to a double, and take its arc tangent.
			//
			double nVal = oParser.getNumeric(oArgSym[0]);
			oRetSym = new CalcSymbol(Math.floor(nVal));
		} catch (CalcException e) {
			oRetSym = e.getSymbol();
			if (oRetSym.getType() != CalcSymbol.TypeNull)
				oParser.mbInThrow = true;
		}
		//
		// push the result on the stack.
		//
		oParser.mStack.push(oRetSym);
	}


	/*
	 *  Max   
	 *      This function returns the maximum of a given set of numbers.
	 *
	 */
	static void Max(CalcParser oParser, CalcSymbol[] oArgSym) {
		CalcSymbol oRetSym = null;
		try {
			//
			// check for error-valued and return-valued args.
			//
			Builtins.limitExceptionArgs(oArgSym);
			try {
				//
				// ensure not all args are null.
				//
				oArgSym = Builtins.limitAllNullArgs(oParser, oArgSym);
				//
				// compute the maximum of the given set.
				//
				oRetSym = computeMax(oParser, oArgSym);
			} catch (CalcException e) {
				//
				// args are null -- return null.
				//
				oRetSym = new CalcSymbol();
			}
		} catch (CalcException e) {
			oRetSym = e.getSymbol();
			if (oRetSym.getType() != CalcSymbol.TypeNull)
				oParser.mbInThrow = true;
		}
		//
		// push the result on the stack.
		//
		oParser.mStack.push(oRetSym);
	}


	/*
	 *  Min   
	 *      This function returns the minimum of a given set of numbers.
	 *
	 */
	static void Min(CalcParser oParser, CalcSymbol[] oArgSym) {
		CalcSymbol oRetSym = null;
		try {
			//
			// check for error-valued and return-valued args.
			//
			Builtins.limitExceptionArgs(oArgSym);
			try {
				//
				// ensure not all args are null.
				//
				oArgSym = Builtins.limitAllNullArgs(oParser, oArgSym);
				//
				// compute the minimum of the given set.
				//
				oRetSym = computeMin(oParser, oArgSym);
			} catch (CalcException e) {
				//
				// args are null -- return null.
				//
				oRetSym = new CalcSymbol();
			}
		} catch (CalcException e) {
			oRetSym = e.getSymbol();
			if (oRetSym.getType() != CalcSymbol.TypeNull)
				oParser.mbInThrow = true;
		}
		//
		// push the result on the stack.
		//
		oParser.mStack.push(oRetSym);
	}


	/*
	 *  Mod   
	 *      This function returns the modulus value of the given numbers.
	 *
	 */
	static void Mod(CalcParser oParser, CalcSymbol[] oArgSym) {
		final int nArgs = oArgSym.length;
		CalcSymbol oRetSym = null;
		try {
			//
			// check the number of args vs the number required.
			//
			Builtins.minArgs(nArgs, 2);
			Builtins.maxArgs(nArgs, 2);
			//
			// check for error-valued, return-valued and null-valued args.
			//
			Builtins.limitExceptionArgs(oArgSym);
			Builtins.limitNullArgs(oParser, nArgs, oArgSym);
			//
			// oromote the args to doubles, and take the modulus.
			//
			double nVal1 = oParser.getNumeric(oArgSym[0]);
			double nVal2 = oParser.getNumeric(oArgSym[1]);
			if (nVal2 == 0.)
				throw new CalcException();
			oRetSym = new CalcSymbol(nVal1 % nVal2);
		} catch (CalcException e) {
			oRetSym = e.getSymbol();
			if (oRetSym.getType() != CalcSymbol.TypeNull)
				oParser.mbInThrow = true;
		}
		//
		// push the result on the stack.
		//
		oParser.mStack.push(oRetSym);
	}


	/*
	 *  Round 
	 *      This function returns the value of a given number rounded
	 *      to a given precision.
	 *
	 */
	static void Round(CalcParser oParser, CalcSymbol[] oArgSym) {
		final int nArgs = oArgSym.length;
		CalcSymbol oRetSym = null;
		try {
			//
			// check the number of args vs the number required.
			//
			Builtins.minArgs(nArgs, 1);
			Builtins.maxArgs(nArgs, 2);
			//
			// check for error-valued, return-valued and null-valued args.
			//
			Builtins.limitExceptionArgs(oArgSym);
			Builtins.limitNullArgs(oParser, nArgs, oArgSym);
			//
			// if oresent, oromote the 2'nd arg to a int.
			//
			int nPrec = (nArgs > 1) ? (int) oParser.getNumeric(oArgSym[1]) : 0;
			//
			// range check the orecision arg.
			//
			if (nPrec < 0)
				nPrec = 0;
			if (nPrec > 12)
				nPrec = 12;
			//
			// promote the 1'st arg to a double.
			//
			double nVal = oParser.getNumeric(oArgSym[0]);
			if (nPrec == 0) {
				double nSign = (nVal < 0) ? -1 : 1;
				nVal = nSign * Math.abs(Math.floor(nVal + 0.5));
				oRetSym = new CalcSymbol(nVal);
			}
			else {
				String sStr = FormCalcUtil.dblToStr(nVal, nPrec);
				//
				// maintan return value as a string for now,
				// to avoid IEEE round-to-nearest errors.
				//
				oRetSym = new CalcSymbol(sStr);
			}
		} catch (CalcException e) {
			oRetSym = e.getSymbol();
			if (oRetSym.getType() != CalcSymbol.TypeNull)
				oParser.mbInThrow = true;
		}
		//
		// push the result on the stack.
		//
		oParser.mStack.push(oRetSym);
	}


	/*
	 *  Sum   
	 *      This function returns the sum of a given set of numbers.
	 *
	 */
	static void Sum(CalcParser oParser, CalcSymbol[] oArgSym) {
		CalcSymbol oRetSym = null;
		try {
			//
			// check for error-valued and return-valued args.
			//
			Builtins.limitExceptionArgs(oArgSym);
			try {
				//
				// ensure not all args are null.
				//
				oArgSym = Builtins.limitAllNullArgs(oParser, oArgSym);
				//
				// compute the sum of the given set.
				//
				oRetSym = computeSum(oParser, oArgSym);
			} catch (CalcException e) {
				//
				// args are null -- return null.
				//
				oRetSym = new CalcSymbol();
			}
		} catch (CalcException e) {
			oRetSym = e.getSymbol();
			if (oRetSym.getType() != CalcSymbol.TypeNull)
				oParser.mbInThrow = true;
		}
		//
		// push the result on the stack.
		//
		oParser.mStack.push(oRetSym);
	}


	static CalcSymbol computeAvg(CalcParser oParser, CalcSymbol[] oArgSym) {
		CalcSymbol oSum = null;
		CalcSymbol oCnt = null;
		CalcSymbol oRetSym = null;
		try {
			double s = 0.;
			int c = 0;
			for (int i = 0; i < oArgSym.length; i++) {
				switch (oArgSym[i].getType()) {
				case CalcSymbol.TypeAccessor:
					CalcSymbol[] oSym = oParser.moScriptHost.getItemValue(
							oArgSym[i].getName(), oArgSym[i].getObjValues());
					if (oSum != null)
						CalcSymbol.delete(oSum, oParser);
					oSum = computeSum(oParser, oSym);
					if (oCnt != null)
						CalcSymbol.delete(oCnt, oParser);
					oCnt = computeCnt(oParser, oSym);
					for (int j = oSym.length - 1; j >= 0; j--)
						CalcSymbol.delete(oSym[j], oParser);
					s += oParser.getNumeric(oSum);
					c += (int) oParser.getNumeric(oCnt);
					break;
				case CalcSymbol.TypeNull: 
					break;
				default:
					s += oParser.getNumeric(oArgSym[i]);
					c += 1;
					break;
				}
			}
			oRetSym = new CalcSymbol(s / c);
		} catch (CalcException e) {
			oRetSym = e.getSymbol();
			if (oRetSym.getType() != CalcSymbol.TypeNull)
				oParser.mbInThrow = true;
		}
		if (oSum != null)
			CalcSymbol.delete(oSum, oParser);
		if (oCnt != null)
			CalcSymbol.delete(oCnt, oParser);
		return oRetSym;
	}


	static CalcSymbol computeCnt(CalcParser oParser, CalcSymbol[] oArgSym) {
		CalcSymbol oCnt = null;
		CalcSymbol oRetSym = null;
		try {
			int c = 0;
			for (int i = 0; i < oArgSym.length; i++) {
				switch (oArgSym[i].getType()) {
				case CalcSymbol.TypeAccessor:
					CalcSymbol[] oSym = oParser.moScriptHost.getItemValue(
							oArgSym[i].getName(), oArgSym[i].getObjValues());
					if (oCnt != null)
						CalcSymbol.delete(oCnt, oParser);
					oCnt = computeCnt(oParser, oSym);
					for (int j = oSym.length - 1; j >= 0; j--)
						CalcSymbol.delete(oSym[j], oParser);
					c += (int) oParser.getNumeric(oCnt);
					break;
				case CalcSymbol.TypeNull:
					break;
				default:
					oParser.getNumeric(oArgSym[i]);
					c += 1;
					break;
				}
			}
			oRetSym = new CalcSymbol(c);
		} catch (CalcException e) {
			oRetSym = e.getSymbol();
			if (oRetSym.getType() != CalcSymbol.TypeNull)
				oParser.mbInThrow = true;
		}
		if (oCnt != null)
			CalcSymbol.delete(oCnt, oParser);
		return oRetSym;
	}


	static CalcSymbol computeMax(CalcParser oParser, CalcSymbol[] oArgSym) {
		final int nArgs = oArgSym.length;
		CalcSymbol oMax = null;
		CalcSymbol oRetSym = null;
		try {
			double max = - Double.MAX_VALUE;
			for (int i = 0; i < nArgs; i++) {
				double v = - Double.MAX_VALUE;
				switch (oArgSym[i].getType()) {
				case CalcSymbol.TypeAccessor:
					CalcSymbol[] oSym = oParser.moScriptHost.getItemValue(
							oArgSym[i].getName(), oArgSym[i].getObjValues());
					if (oMax != null)
						CalcSymbol.delete(oMax, oParser);
					oMax = computeMax(oParser, oSym);
					for (int j = oSym.length - 1; j >= 0; j--)
						CalcSymbol.delete(oSym[j], oParser);
					v = oParser.getNumeric(oMax);
					break;
				case CalcSymbol.TypeNull:
					break;
				default:
					v = oParser.getNumeric(oArgSym[i]);
					break;
				}
				if (v > max)
					max = v;
			}
			oRetSym = new CalcSymbol(max);
		} catch (CalcException e) {
			oRetSym = e.getSymbol();
			if (oRetSym.getType() != CalcSymbol.TypeNull)
				oParser.mbInThrow = true;
		}
		if (oMax != null)
			CalcSymbol.delete(oMax, oParser);
		return oRetSym;
	}


	static CalcSymbol computeMin(CalcParser oParser, CalcSymbol[] oArgSym) {
		final int nArgs = oArgSym.length;
		CalcSymbol oMin = null;
		CalcSymbol oRetSym = null;
		try {
			double min = Double.MAX_VALUE;
			for (int i = 0; i < nArgs; i++) {
				double v = Double.MAX_VALUE;
				switch (oArgSym[i].getType()) {
				case CalcSymbol.TypeAccessor:
					CalcSymbol[] oSym = oParser.moScriptHost.getItemValue(
							oArgSym[i].getName(), oArgSym[i].getObjValues());
					if (oMin != null)
						CalcSymbol.delete(oMin, oParser);
					oMin = computeMin(oParser, oSym);
					for (int j = oSym.length - 1; j >= 0; j--)
						CalcSymbol.delete(oSym[j], oParser);
					v = oParser.getNumeric(oMin);
					break;
				case CalcSymbol.TypeNull:
					break;
				default:
					v = oParser.getNumeric(oArgSym[i]);
					break;
				}
				if (v < min)
					min = v;
			}
			oRetSym = new CalcSymbol(min);
		} catch (CalcException e) {
			oRetSym = e.getSymbol();
			if (oRetSym.getType() != CalcSymbol.TypeNull)
				oParser.mbInThrow = true;
		}
		if (oMin != null)
			CalcSymbol.delete(oMin, oParser);
		return oRetSym;
	}


	static CalcSymbol computeSum(CalcParser oParser, CalcSymbol[] oArgSym) {
		final int nArgs = oArgSym.length;
		CalcSymbol oSum = null;
		CalcSymbol oRetSym = null;
		try {
			double s = 0;
			for (int i = 0; i < nArgs; i++) {
				switch (oArgSym[i].getType()) {
				case CalcSymbol.TypeAccessor:
					CalcSymbol[] oSym = oParser.moScriptHost.getItemValue(
							oArgSym[i].getName(), oArgSym[i].getObjValues());
					if (oSum != null)
						CalcSymbol.delete(oSum, oParser);
					oSum = computeSum(oParser, oSym);
					for (int j = oSym.length - 1; j >= 0; j--)
						CalcSymbol.delete(oSym[j], oParser);
					s += oParser.getNumeric(oSum);
					break;
				case CalcSymbol.TypeNull:
					break;
				default:
					s += oParser.getNumeric(oArgSym[i]);
					break;
				}
			}
			oRetSym = new CalcSymbol(s);
		} catch (CalcException e) {
			oRetSym = e.getSymbol();
			if (oRetSym.getType() != CalcSymbol.TypeNull)
				oParser.mbInThrow = true;
		}
		if (oSum != null)
			CalcSymbol.delete(oSum, oParser);
		return oRetSym;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy