com.adobe.xfa.formcalc.BuiltinMath Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aem-sdk-api Show documentation
Show all versions of aem-sdk-api Show documentation
The Adobe Experience Manager SDK
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;
}
}