*/
public abstract class MultiOperandNumericFunction implements Function {
- private final boolean _isReferenceBoolCounted;
- private final boolean _isBlankCounted;
+ private final boolean _isReferenceBoolCounted;
+ private final boolean _isBlankCounted;
protected MultiOperandNumericFunction(boolean isReferenceBoolCounted, boolean isBlankCounted) {
_isReferenceBoolCounted = isReferenceBoolCounted;
_isBlankCounted = isBlankCounted;
}
- static final double[] EMPTY_DOUBLE_ARRAY = { };
-
- private static class DoubleList {
- private double[] _array;
- private int _count;
-
- public DoubleList() {
- _array = new double[8];
- _count = 0;
- }
-
- public double[] toArray() {
- if(_count < 1) {
- return EMPTY_DOUBLE_ARRAY;
- }
- double[] result = new double[_count];
- System.arraycopy(_array, 0, result, 0, _count);
- return result;
- }
-
- private void ensureCapacity(int reqSize) {
- if(reqSize > _array.length) {
- int newSize = reqSize * 3 / 2; // grow with 50% extra
- double[] newArr = new double[newSize];
- System.arraycopy(_array, 0, newArr, 0, _count);
- _array = newArr;
- }
- }
-
- public void add(double value) {
- ensureCapacity(_count + 1);
- _array[_count] = value;
- _count++;
- }
- }
-
- private static final int DEFAULT_MAX_NUM_OPERANDS = SpreadsheetVersion.EXCEL2007.getMaxFunctionArgs();
-
- public final ValueEval evaluate(ValueEval[] args, int srcCellRow, int srcCellCol) {
- try {
- double[] values = getNumberArray(args);
- double d = evaluate(values);
- if (Double.isNaN(d) || Double.isInfinite(d)) {
- return ErrorEval.NUM_ERROR;
- }
- return new NumberEval(d);
- } catch (EvaluationException e) {
- return e.getErrorEval();
- }
- }
-
- protected abstract double evaluate(double[] values) throws EvaluationException;
-
- /**
- * Maximum number of operands accepted by this function.
- * Subclasses may override to change default value.
- */
- protected int getMaxNumOperands() {
- return DEFAULT_MAX_NUM_OPERANDS;
- }
-
- /**
- * Returns a double array that contains values for the numeric cells
- * from among the list of operands. Blanks and Blank equivalent cells
- * are ignored. Error operands or cells containing operands of type
- * that are considered invalid and would result in #VALUE! error in
- * excel cause this function to return <code>null</code>.
- *
- * @return never <code>null</code>
- */
- protected final double[] getNumberArray(ValueEval[] operands) throws EvaluationException {
- if (operands.length > getMaxNumOperands()) {
- throw EvaluationException.invalidValue();
- }
- DoubleList retval = new DoubleList();
-
- for (int i=0, iSize=operands.length; i<iSize; i++) {
- collectValues(operands[i], retval);
- }
- return retval.toArray();
- }
+ static final double[] EMPTY_DOUBLE_ARRAY = {};
+
+ private static class DoubleList {
+ private double[] _array;
+ private int _count;
+
+ public DoubleList() {
+ _array = new double[8];
+ _count = 0;
+ }
+
+ public double[] toArray() {
+ if (_count < 1) {
+ return EMPTY_DOUBLE_ARRAY;
+ }
+ double[] result = new double[_count];
+ System.arraycopy(_array, 0, result, 0, _count);
+ return result;
+ }
+
+ private void ensureCapacity(int reqSize) {
+ if (reqSize > _array.length) {
+ int newSize = reqSize * 3 / 2; // grow with 50% extra
+ double[] newArr = new double[newSize];
+ System.arraycopy(_array, 0, newArr, 0, _count);
+ _array = newArr;
+ }
+ }
+
+ public void add(double value) {
+ ensureCapacity(_count + 1);
+ _array[_count] = value;
+ _count++;
+ }
+ }
+
+ private static final int DEFAULT_MAX_NUM_OPERANDS = SpreadsheetVersion.EXCEL2007.getMaxFunctionArgs();
+
+ public final ValueEval evaluate(ValueEval[] args, int srcCellRow, int srcCellCol) {
+ try {
+ double[] values = getNumberArray(args);
+ double d = evaluate(values);
+ if (Double.isNaN(d) || Double.isInfinite(d)) {
+ return ErrorEval.NUM_ERROR;
+ }
+ return new NumberEval(d);
+ } catch (EvaluationException e) {
+ return e.getErrorEval();
+ }
+ }
+
+ protected abstract double evaluate(double[] values) throws EvaluationException;
+
+ /**
+ * Maximum number of operands accepted by this function.
+ * Subclasses may override to change default value.
+ */
+ protected int getMaxNumOperands() {
+ return DEFAULT_MAX_NUM_OPERANDS;
+ }
+
+ /**
+ * Returns a double array that contains values for the numeric cells
+ * from among the list of operands. Blanks and Blank equivalent cells
+ * are ignored. Error operands or cells containing operands of type
+ * that are considered invalid and would result in #VALUE! error in
+ * excel cause this function to return <code>null</code>.
+ *
+ * @return never <code>null</code>
+ */
+ protected final double[] getNumberArray(ValueEval[] operands) throws EvaluationException {
+ if (operands.length > getMaxNumOperands()) {
+ throw EvaluationException.invalidValue();
+ }
+ DoubleList retval = new DoubleList();
+
+ for (int i = 0, iSize = operands.length; i < iSize; i++) {
+ collectValues(operands[i], retval);
+ }
+ return retval.toArray();
+ }
/**
- * Whether to count nested subtotals.
+ * Whether to count nested subtotals.
*/
- public boolean isSubtotalCounted(){
+ public boolean isSubtotalCounted() {
return true;
}
- /**
- * Collects values from a single argument
- */
- private void collectValues(ValueEval operand, DoubleList temp) throws EvaluationException {
+ /**
+ * Collects values from a single argument
+ */
+ private void collectValues(ValueEval operand, DoubleList temp) throws EvaluationException {
if (operand instanceof ThreeDEval) {
ThreeDEval ae = (ThreeDEval) operand;
- for (int sIx=ae.getFirstSheetIndex(); sIx <= ae.getLastSheetIndex(); sIx++) {
+ for (int sIx = ae.getFirstSheetIndex(); sIx <= ae.getLastSheetIndex(); sIx++) {
int width = ae.getWidth();
int height = ae.getHeight();
- for (int rrIx=0; rrIx<height; rrIx++) {
- for (int rcIx=0; rcIx<width; rcIx++) {
+ for (int rrIx = 0; rrIx < height; rrIx++) {
+ for (int rcIx = 0; rcIx < width; rcIx++) {
ValueEval ve = ae.getValue(sIx, rrIx, rcIx);
- if(!isSubtotalCounted() && ae.isSubTotal(rrIx, rcIx)) continue;
+ if (!isSubtotalCounted() && ae.isSubTotal(rrIx, rcIx)) continue;
collectValue(ve, true, temp);
}
}
}
return;
}
- if (operand instanceof TwoDEval) {
- TwoDEval ae = (TwoDEval) operand;
- int width = ae.getWidth();
- int height = ae.getHeight();
- for (int rrIx=0; rrIx<height; rrIx++) {
- for (int rcIx=0; rcIx<width; rcIx++) {
- ValueEval ve = ae.getValue(rrIx, rcIx);
- if(!isSubtotalCounted() && ae.isSubTotal(rrIx, rcIx)) continue;
+ if (operand instanceof TwoDEval) {
+ TwoDEval ae = (TwoDEval) operand;
+ int width = ae.getWidth();
+ int height = ae.getHeight();
+ for (int rrIx = 0; rrIx < height; rrIx++) {
+ for (int rcIx = 0; rcIx < width; rcIx++) {
+ ValueEval ve = ae.getValue(rrIx, rcIx);
+ if (!isSubtotalCounted() && ae.isSubTotal(rrIx, rcIx)) continue;
collectValue(ve, true, temp);
- }
- }
- return;
- }
- if (operand instanceof RefEval) {
- RefEval re = (RefEval) operand;
- for (int sIx = re.getFirstSheetIndex(); sIx <= re.getLastSheetIndex(); sIx++) {
- collectValue(re.getInnerValueEval(sIx), true, temp);
- }
- return;
- }
- collectValue(operand, false, temp);
- }
- private void collectValue(ValueEval ve, boolean isViaReference, DoubleList temp) throws EvaluationException {
- if (ve == null) {
- throw new IllegalArgumentException("ve must not be null");
- }
- if (ve instanceof BoolEval) {
- if (!isViaReference || _isReferenceBoolCounted) {
- BoolEval boolEval = (BoolEval) ve;
- temp.add(boolEval.getNumberValue());
- }
- return;
- }
- if (ve instanceof NumericValueEval) {
- NumericValueEval ne = (NumericValueEval) ve;
- temp.add(ne.getNumberValue());
- return;
- }
- if (ve instanceof StringValueEval) {
- if (isViaReference) {
- // ignore all ref strings
- return;
- }
- String s = ((StringValueEval) ve).getStringValue();
- Double d = OperandResolver.parseDouble(s);
- if(d == null) {
- throw new EvaluationException(ErrorEval.VALUE_INVALID);
- }
- temp.add(d.doubleValue());
- return;
- }
- if (ve instanceof ErrorEval) {
- throw new EvaluationException((ErrorEval) ve);
- }
- if (ve == BlankEval.instance) {
- if (_isBlankCounted) {
- temp.add(0.0);
- }
- return;
- }
- if (ve == MissingArgEval.instance) {
- temp.add(0.0);
- return;
- }
- throw new RuntimeException("Invalid ValueEval type passed for conversion: ("
- + ve.getClass() + ")");
- }
+ }
+ }
+ return;
+ }
+ if (operand instanceof RefEval) {
+ RefEval re = (RefEval) operand;
+ for (int sIx = re.getFirstSheetIndex(); sIx <= re.getLastSheetIndex(); sIx++) {
+ collectValue(re.getInnerValueEval(sIx), true, temp);
+ }
+ return;
+ }
+ collectValue(operand, false, temp);
+ }
+
+ private void collectValue(ValueEval ve, boolean isViaReference, DoubleList temp) throws EvaluationException {
+ if (ve == null) {
+ throw new IllegalArgumentException("ve must not be null");
+ }
+ if (ve instanceof BoolEval) {
+ if (!isViaReference || _isReferenceBoolCounted) {
+ BoolEval boolEval = (BoolEval) ve;
+ temp.add(boolEval.getNumberValue());
+ }
+ return;
+ }
+ if (ve instanceof NumericValueEval) {
+ NumericValueEval ne = (NumericValueEval) ve;
+ temp.add(ne.getNumberValue());
+ return;
+ }
+ if (ve instanceof StringValueEval) {
+ if (isViaReference) {
+ // ignore all ref strings
+ return;
+ }
+ String s = ((StringValueEval) ve).getStringValue();
+ Double d = OperandResolver.parseDouble(s);
+ if (d == null) {
+ throw new EvaluationException(ErrorEval.VALUE_INVALID);
+ }
+ temp.add(d.doubleValue());
+ return;
+ }
+ if (ve instanceof ErrorEval) {
+ throw new EvaluationException((ErrorEval) ve);
+ }
+ if (ve == BlankEval.instance) {
+ if (_isBlankCounted) {
+ temp.add(0.0);
+ }
+ return;
+ }
+ if (ve == MissingArgEval.instance) {
+ temp.add(0.0);
+ return;
+ }
+ throw new RuntimeException("Invalid ValueEval type passed for conversion: ("
+ + ve.getClass() + ")");
+ }
}