From: Josh Micich Date: Sun, 31 Aug 2008 19:08:36 +0000 (+0000) Subject: removed AreaEval.getValues (initial work for bug 45358) X-Git-Tag: REL_3_2_FINAL~109 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=908e676d5710909b54366133bcc535338fb667de;p=poi.git removed AreaEval.getValues (initial work for bug 45358) git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@690761 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/AreaEval.java b/src/java/org/apache/poi/hssf/record/formula/eval/AreaEval.java index 182b9b618b..eaecf267ac 100644 --- a/src/java/org/apache/poi/hssf/record/formula/eval/AreaEval.java +++ b/src/java/org/apache/poi/hssf/record/formula/eval/AreaEval.java @@ -61,13 +61,6 @@ public interface AreaEval extends ValueEval { */ boolean isColumn(); - /** - * The array of values in this area. Although the area - * maybe 1D (ie. isRow() or isColumn() returns true) or 2D - * the returned array is 1D. - */ - ValueEval[] getValues(); - /** * @return the ValueEval from within this area at the specified row and col index. Never * null (possibly {@link BlankEval}). The specified indexes should be absolute diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/AreaEvalBase.java b/src/java/org/apache/poi/hssf/record/formula/eval/AreaEvalBase.java index 1686e75f33..0a812102dc 100644 --- a/src/java/org/apache/poi/hssf/record/formula/eval/AreaEvalBase.java +++ b/src/java/org/apache/poi/hssf/record/formula/eval/AreaEvalBase.java @@ -77,11 +77,6 @@ abstract class AreaEvalBase implements AreaEval { return _lastRow; } - public final ValueEval[] getValues() { - // TODO - clone() - but some junits rely on not cloning at the moment - return _values; - } - public final ValueEval getValueAt(int row, int col) { int rowOffsetIx = row - _firstRow; int colOffsetIx = col - _firstColumn; diff --git a/src/java/org/apache/poi/hssf/record/formula/eval/NumberEval.java b/src/java/org/apache/poi/hssf/record/formula/eval/NumberEval.java index 44a017f631..e22957bd4a 100644 --- a/src/java/org/apache/poi/hssf/record/formula/eval/NumberEval.java +++ b/src/java/org/apache/poi/hssf/record/formula/eval/NumberEval.java @@ -69,5 +69,11 @@ public class NumberEval implements NumericValueEval, StringValueEval { } } } - + public final String toString() { + StringBuffer sb = new StringBuffer(64); + sb.append(getClass().getName()).append(" ["); + sb.append(getStringValue()); + sb.append("]"); + return sb.toString(); + } } diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Index.java b/src/java/org/apache/poi/hssf/record/formula/functions/Index.java index aebf6aab0d..3c93c0846b 100644 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Index.java +++ b/src/java/org/apache/poi/hssf/record/formula/functions/Index.java @@ -1,28 +1,28 @@ -/* -* Licensed to the Apache Software Foundation (ASF) under one or more -* contributor license agreements. See the NOTICE file distributed with -* this work for additional information regarding copyright ownership. -* The ASF licenses this file to You 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. -*/ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You 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 org.apache.poi.hssf.record.formula.functions; import org.apache.poi.hssf.record.formula.eval.AreaEval; import org.apache.poi.hssf.record.formula.eval.ErrorEval; import org.apache.poi.hssf.record.formula.eval.Eval; -import org.apache.poi.hssf.record.formula.eval.NumberEval; -import org.apache.poi.hssf.record.formula.eval.RefEval; +import org.apache.poi.hssf.record.formula.eval.EvaluationException; +import org.apache.poi.hssf.record.formula.eval.OperandResolver; +import org.apache.poi.hssf.record.formula.eval.ValueEval; /** * Implementation for the Excel function INDEX

@@ -51,15 +51,23 @@ public final class Index implements Function { return ErrorEval.VALUE_INVALID; } Eval firstArg = args[0]; - if(firstArg instanceof AreaEval) { - AreaEval reference = (AreaEval) firstArg; + if(!(firstArg instanceof AreaEval)) { + + // else the other variation of this function takes an array as the first argument + // it seems like interface 'ArrayEval' does not even exist yet - int rowIx = 0; - int columnIx = 0; - int areaIx = 0; + throw new RuntimeException("Incomplete code - cannot handle first arg of type (" + + firstArg.getClass().getName() + ")"); + } + AreaEval reference = (AreaEval) firstArg; + + int rowIx = 0; + int columnIx = 0; + int areaIx = 0; + try { switch(nArgs) { case 4: - areaIx = convertIndexArgToZeroBase(args[3]); + areaIx = convertIndexArgToZeroBase(args[3], srcCellRow, srcCellCol); throw new RuntimeException("Incomplete code" + " - don't know how to support the 'area_num' parameter yet)"); // Excel expression might look like this "INDEX( (A1:B4, C3:D6, D2:E5 ), 1, 2, 3) @@ -68,41 +76,41 @@ public final class Index implements Function { // The formula parser doesn't seem to support this yet. Not sure if the evaluator does either case 3: - columnIx = convertIndexArgToZeroBase(args[2]); + columnIx = convertIndexArgToZeroBase(args[2], srcCellRow, srcCellCol); case 2: - rowIx = convertIndexArgToZeroBase(args[1]); + rowIx = convertIndexArgToZeroBase(args[1], srcCellRow, srcCellCol); break; default: // too many arguments return ErrorEval.VALUE_INVALID; } - - int nColumns = reference.getLastColumn()-reference.getFirstColumn()+1; - int index = rowIx * nColumns + columnIx; - - return reference.getValues()[index]; + return getValueFromArea(reference, rowIx, columnIx); + } catch (EvaluationException e) { + return e.getErrorEval(); } - - // else the other variation of this function takes an array as the first argument - // it seems like interface 'ArrayEval' does not even exist yet - - throw new RuntimeException("Incomplete code - cannot handle first arg of type (" - + firstArg.getClass().getName() + ")"); } + private static ValueEval getValueFromArea(AreaEval ae, int rowIx, int columnIx) throws EvaluationException { + int width = ae.getWidth(); + int height = ae.getHeight(); + + // Slightly irregular logic for bounds checking errors + if (rowIx >= height || columnIx >= width) { + throw new EvaluationException(ErrorEval.REF_INVALID); + } + if (rowIx < 0 || columnIx < 0) { + throw new EvaluationException(ErrorEval.VALUE_INVALID); + } + return ae.getRelativeValue(rowIx, columnIx); + } + /** * takes a NumberEval representing a 1-based index and returns the zero-based int value */ - private static int convertIndexArgToZeroBase(Eval ev) { - NumberEval ne; - if(ev instanceof RefEval) { - // TODO - write junit to justify this - RefEval re = (RefEval) ev; - ne = (NumberEval) re.getInnerValueEval(); - } else { - ne = (NumberEval)ev; - } + private static int convertIndexArgToZeroBase(Eval arg, int srcCellRow, short srcCellCol) throws EvaluationException { - return (int)ne.getNumberValue() - 1; + ValueEval ev = OperandResolver.getSingleValue(arg, srcCellRow, srcCellCol); + int oneBasedVal = OperandResolver.coerceValueToInt(ev); + return oneBasedVal - 1; } } diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/MultiOperandNumericFunction.java b/src/java/org/apache/poi/hssf/record/formula/functions/MultiOperandNumericFunction.java index 0e7cce217e..a9e98ae313 100644 --- a/src/java/org/apache/poi/hssf/record/formula/functions/MultiOperandNumericFunction.java +++ b/src/java/org/apache/poi/hssf/record/formula/functions/MultiOperandNumericFunction.java @@ -126,30 +126,34 @@ public abstract class MultiOperandNumericFunction extends NumericFunction { if (operand instanceof AreaEval) { AreaEval ae = (AreaEval) operand; - ValueEval[] values = ae.getValues(); DoubleList retval = new DoubleList(); - for (int j=0, jSize=values.length; j * @@ -30,7 +31,13 @@ package org.apache.poi.hssf.record.formula.functions; */ public final class Sumx2my2 extends XYNumericFunction { - protected double evaluate(double[] xArray, double[] yArray) { - return MathX.sumx2my2(xArray, yArray); - } + private static final Accumulator XSquaredMinusYSquaredAccumulator = new Accumulator() { + public double accumulate(double x, double y) { + return x * x - y * y; + } + }; + + protected Accumulator createAccumulator() { + return XSquaredMinusYSquaredAccumulator; + } } diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Sumx2py2.java b/src/java/org/apache/poi/hssf/record/formula/functions/Sumx2py2.java index dfd730d12c..c3af0bd380 100644 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Sumx2py2.java +++ b/src/java/org/apache/poi/hssf/record/formula/functions/Sumx2py2.java @@ -1,22 +1,23 @@ -/* -* Licensed to the Apache Software Foundation (ASF) under one or more -* contributor license agreements. See the NOTICE file distributed with -* this work for additional information regarding copyright ownership. -* The ASF licenses this file to You 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. -*/ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You 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 org.apache.poi.hssf.record.formula.functions; + /** * Implementation of Excel function SUMX2PY2()

* @@ -30,7 +31,13 @@ package org.apache.poi.hssf.record.formula.functions; */ public final class Sumx2py2 extends XYNumericFunction { - protected double evaluate(double[] xArray, double[] yArray) { - return MathX.sumx2py2(xArray, yArray); - } + private static final Accumulator XSquaredPlusYSquaredAccumulator = new Accumulator() { + public double accumulate(double x, double y) { + return x * x + y * y; + } + }; + + protected Accumulator createAccumulator() { + return XSquaredPlusYSquaredAccumulator; + } } diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/Sumxmy2.java b/src/java/org/apache/poi/hssf/record/formula/functions/Sumxmy2.java index a1b2fec9b2..4fa11e36ba 100644 --- a/src/java/org/apache/poi/hssf/record/formula/functions/Sumxmy2.java +++ b/src/java/org/apache/poi/hssf/record/formula/functions/Sumxmy2.java @@ -1,19 +1,19 @@ -/* -* Licensed to the Apache Software Foundation (ASF) under one or more -* contributor license agreements. See the NOTICE file distributed with -* this work for additional information regarding copyright ownership. -* The ASF licenses this file to You 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. -*/ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You 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 org.apache.poi.hssf.record.formula.functions; @@ -30,7 +30,14 @@ package org.apache.poi.hssf.record.formula.functions; */ public final class Sumxmy2 extends XYNumericFunction { - protected double evaluate(double[] xArray, double[] yArray) { - return MathX.sumxmy2(xArray, yArray); - } + private static final Accumulator XMinusYSquaredAccumulator = new Accumulator() { + public double accumulate(double x, double y) { + double xmy = x - y; + return xmy * xmy; + } + }; + + protected Accumulator createAccumulator() { + return XMinusYSquaredAccumulator; + } } diff --git a/src/java/org/apache/poi/hssf/record/formula/functions/XYNumericFunction.java b/src/java/org/apache/poi/hssf/record/formula/functions/XYNumericFunction.java index b989c33a26..1d83b363fd 100644 --- a/src/java/org/apache/poi/hssf/record/formula/functions/XYNumericFunction.java +++ b/src/java/org/apache/poi/hssf/record/formula/functions/XYNumericFunction.java @@ -1,19 +1,19 @@ -/* -* Licensed to the Apache Software Foundation (ASF) under one or more -* contributor license agreements. See the NOTICE file distributed with -* this work for additional information regarding copyright ownership. -* The ASF licenses this file to You 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. -*/ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You 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 org.apache.poi.hssf.record.formula.functions; @@ -24,180 +24,162 @@ import org.apache.poi.hssf.record.formula.eval.EvaluationException; import org.apache.poi.hssf.record.formula.eval.NumberEval; import org.apache.poi.hssf.record.formula.eval.RefEval; import org.apache.poi.hssf.record.formula.eval.ValueEval; +import org.apache.poi.hssf.record.formula.functions.LookupUtils.ValueVector; /** * @author Amol S. Deshmukh < amolweb at ya hoo dot com > - * + * */ public abstract class XYNumericFunction implements Function { - protected static final int X = 0; - protected static final int Y = 1; - - protected static final class DoubleArrayPair { - private final double[] _xArray; - private final double[] _yArray; + private static abstract class ValueArray implements ValueVector { + private final int _size; + protected ValueArray(int size) { + _size = size; + } + public ValueEval getItem(int index) { + if (index < 0 || index > _size) { + throw new IllegalArgumentException("Specified index " + index + + " is outside range (0.." + (_size - 1) + ")"); + } + return getItemInternal(index); + } + protected abstract ValueEval getItemInternal(int index); + public final int getSize() { + return _size; + } + } - public DoubleArrayPair(double[] xArray, double[] yArray) { - _xArray = xArray; - _yArray = yArray; + private static final class SingleCellValueArray extends ValueArray { + private final ValueEval _value; + public SingleCellValueArray(ValueEval value) { + super(1); + _value = value; } - public double[] getXArray() { - return _xArray; + protected ValueEval getItemInternal(int index) { + return _value; + } + } + + private static final class RefValueArray extends ValueArray { + private final RefEval _ref; + public RefValueArray(RefEval ref) { + super(1); + _ref = ref; } - public double[] getYArray() { - return _yArray; + protected ValueEval getItemInternal(int index) { + return _ref.getInnerValueEval(); } - } + } + private static final class AreaValueArray extends ValueArray { + private final AreaEval _ae; + private final int _width; + + public AreaValueArray(AreaEval ae) { + super(ae.getWidth() * ae.getHeight()); + _ae = ae; + _width = ae.getWidth(); + } + protected ValueEval getItemInternal(int index) { + int rowIx = index / _width; + int colIx = index % _width; + return _ae.getRelativeValue(rowIx, colIx); + } + } + + protected static interface Accumulator { + double accumulate(double x, double y); + } + + /** + * Constructs a new instance of the Accumulator used to calculated this function + */ + protected abstract Accumulator createAccumulator(); + + public final Eval evaluate(Eval[] args, int srcCellRow, short srcCellCol) { + if (args.length != 2) { + return ErrorEval.VALUE_INVALID; + } - public final Eval evaluate(Eval[] args, int srcCellRow, short srcCellCol) { - if(args.length != 2) { - return ErrorEval.VALUE_INVALID; - } - - double[][] values; + double result; try { - values = getValues(args[0], args[1]); + ValueVector vvX = createValueVector(args[0]); + ValueVector vvY = createValueVector(args[1]); + int size = vvX.getSize(); + if (size == 0 || vvY.getSize() != size) { + return ErrorEval.NA; + } + result = evaluateInternal(vvX, vvY, size); } catch (EvaluationException e) { return e.getErrorEval(); } - if (values==null - || values[X] == null || values[Y] == null - || values[X].length == 0 || values[Y].length == 0 - || values[X].length != values[Y].length) { - return ErrorEval.VALUE_INVALID; - } - - double d = evaluate(values[X], values[Y]); - if (Double.isNaN(d) || Double.isInfinite(d)) { + if (Double.isNaN(result) || Double.isInfinite(result)) { return ErrorEval.NUM_ERROR; } - return new NumberEval(d); - } - protected abstract double evaluate(double[] xArray, double[] yArray); - - /** - * 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 null. - */ - private static double[][] getNumberArray(Eval[] xops, Eval[] yops) throws EvaluationException { - - // check for errors first: size mismatch, value errors in x, value errors in y - - int nArrayItems = xops.length; - if(nArrayItems != yops.length) { - throw new EvaluationException(ErrorEval.NA); - } - for (int i = 0; i < xops.length; i++) { - Eval eval = xops[i]; - if (eval instanceof ErrorEval) { - throw new EvaluationException((ErrorEval) eval); + return new NumberEval(result); + } + + private double evaluateInternal(ValueVector x, ValueVector y, int size) + throws EvaluationException { + Accumulator acc = createAccumulator(); + + // error handling is as if the x is fully evaluated before y + ErrorEval firstXerr = null; + ErrorEval firstYerr = null; + boolean accumlatedSome = false; + double result = 0.0; + + for (int i = 0; i < size; i++) { + ValueEval vx = x.getItem(i); + ValueEval vy = y.getItem(i); + if (vx instanceof ErrorEval) { + if (firstXerr == null) { + firstXerr = (ErrorEval) vx; + continue; + } } - } - for (int i = 0; i < yops.length; i++) { - Eval eval = yops[i]; - if (eval instanceof ErrorEval) { - throw new EvaluationException((ErrorEval) eval); + if (vy instanceof ErrorEval) { + if (firstYerr == null) { + firstYerr = (ErrorEval) vy; + continue; + } + } + // only count pairs if both elements are numbers + if (vx instanceof NumberEval && vy instanceof NumberEval) { + accumlatedSome = true; + NumberEval nx = (NumberEval) vx; + NumberEval ny = (NumberEval) vy; + result += acc.accumulate(nx.getNumberValue(), ny.getNumberValue()); + } else { + // all other combinations of value types are silently ignored } } - - double[] xResult = new double[nArrayItems]; - double[] yResult = new double[nArrayItems]; - - int count = 0; - - for (int i=0, iSize=nArrayItems; i len) { - tarr = new double[len]; - System.arraycopy(arr, 0, tarr, 0, len); - } - return tarr; - } - - private static boolean isNumberEval(Eval eval) { - boolean retval = false; - - if (eval instanceof NumberEval) { - retval = true; - } - else if (eval instanceof RefEval) { - RefEval re = (RefEval) eval; - ValueEval ve = re.getInnerValueEval(); - retval = (ve instanceof NumberEval); - } - - return retval; - } - - private static double getDoubleValue(Eval eval) { - double retval = 0; - if (eval instanceof NumberEval) { - NumberEval ne = (NumberEval) eval; - retval = ne.getNumberValue(); - } - else if (eval instanceof RefEval) { - RefEval re = (RefEval) eval; - ValueEval ve = re.getInnerValueEval(); - retval = (ve instanceof NumberEval) - ? ((NumberEval) ve).getNumberValue() - : Double.NaN; - } - else if (eval instanceof ErrorEval) { - retval = Double.NaN; - } - return retval; - } + if (firstXerr != null) { + throw new EvaluationException(firstXerr); + } + if (firstYerr != null) { + throw new EvaluationException(firstYerr); + } + if (!accumlatedSome) { + throw new EvaluationException(ErrorEval.DIV_ZERO); + } + return result; + } + + private static ValueVector createValueVector(Eval arg) throws EvaluationException { + if (arg instanceof ErrorEval) { + throw new EvaluationException((ErrorEval) arg); + } + if (arg instanceof AreaEval) { + return new AreaValueArray((AreaEval) arg); + } + if (arg instanceof RefEval) { + return new RefValueArray((RefEval) arg); + } + if (arg instanceof ValueEval) { + return new SingleCellValueArray((ValueEval) arg); + } + throw new RuntimeException("Unexpected eval class (" + arg.getClass().getName() + ")"); + } } diff --git a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestSumproduct.java b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestSumproduct.java index 2f9a6314be..884b9b4a36 100755 --- a/src/testcases/org/apache/poi/hssf/record/formula/functions/TestSumproduct.java +++ b/src/testcases/org/apache/poi/hssf/record/formula/functions/TestSumproduct.java @@ -113,7 +113,6 @@ public final class TestSumproduct extends TestCase { }; AreaEval aeA = EvalFactory.createAreaEval("A1:A2", aValues); AreaEval aeB = EvalFactory.createAreaEval("B1:B2", new ValueEval[2]); - aeB.getValues()[1] = ErrorEval.REF_INVALID; Eval[] args = { aeA, aeB, }; assertEquals(ErrorEval.REF_INVALID, invokeSumproduct(args));