mirror of https://github.com/apache/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
This commit is contained in:
parent
b944df7e56
commit
908e676d57
|
@ -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
|
||||
* <code>null</code> (possibly {@link BlankEval}). The specified indexes should be absolute
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<p/>
|
||||
|
@ -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)) {
|
||||
|
||||
int rowIx = 0;
|
||||
int columnIx = 0;
|
||||
int areaIx = 0;
|
||||
// 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() + ")");
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<jSize; j++) {
|
||||
/*
|
||||
* TODO: For an AreaEval, we are constructing a RefEval
|
||||
* per element.
|
||||
* For now this is a tempfix solution since this may
|
||||
* require a more generic fix at the level of
|
||||
* HSSFFormulaEvaluator where we store an array
|
||||
* of RefEvals as the "values" array.
|
||||
*/
|
||||
RefEval re = new Ref2DEval(null, values[j]);
|
||||
ValueEval ve = singleOperandEvaluate(re, srcRow, srcCol);
|
||||
|
||||
if (ve instanceof NumericValueEval) {
|
||||
NumericValueEval nve = (NumericValueEval) ve;
|
||||
retval.add(nve.getNumberValue());
|
||||
}
|
||||
else if (ve instanceof BlankEval) {
|
||||
// note - blanks are ignored, so returned array will be smaller.
|
||||
}
|
||||
else {
|
||||
return null; // indicate to calling subclass that error occurred
|
||||
}
|
||||
int width = ae.getWidth();
|
||||
int height = ae.getHeight();
|
||||
for (int rrIx=0; rrIx<height; rrIx++) {
|
||||
for (int rcIx=0; rcIx<width; rcIx++) {
|
||||
ValueEval ve1 = ae.getRelativeValue(rrIx, rcIx);
|
||||
/*
|
||||
* TODO: For an AreaEval, we are constructing a RefEval
|
||||
* per element.
|
||||
* For now this is a tempfix solution since this may
|
||||
* require a more generic fix at the level of
|
||||
* HSSFFormulaEvaluator where we store an array
|
||||
* of RefEvals as the "values" array.
|
||||
*/
|
||||
RefEval re = new Ref2DEval(null, ve1);
|
||||
ValueEval ve = singleOperandEvaluate(re, srcRow, srcCol);
|
||||
|
||||
if (ve instanceof NumericValueEval) {
|
||||
NumericValueEval nve = (NumericValueEval) ve;
|
||||
retval.add(nve.getNumberValue());
|
||||
}
|
||||
else if (ve instanceof BlankEval) {
|
||||
// note - blanks are ignored, so returned array will be smaller.
|
||||
}
|
||||
else {
|
||||
return null; // indicate to calling subclass that error occurred
|
||||
}
|
||||
}
|
||||
}
|
||||
return retval.toArray();
|
||||
}
|
||||
|
|
|
@ -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 SUMX2MY2()<p/>
|
||||
*
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()<p/>
|
||||
*
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
public DoubleArrayPair(double[] xArray, double[] yArray) {
|
||||
_xArray = xArray;
|
||||
_yArray = yArray;
|
||||
private static abstract class ValueArray implements ValueVector {
|
||||
private final int _size;
|
||||
protected ValueArray(int size) {
|
||||
_size = size;
|
||||
}
|
||||
public double[] getXArray() {
|
||||
return _xArray;
|
||||
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);
|
||||
}
|
||||
public double[] getYArray() {
|
||||
return _yArray;
|
||||
protected abstract ValueEval getItemInternal(int index);
|
||||
public final int getSize() {
|
||||
return _size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final class SingleCellValueArray extends ValueArray {
|
||||
private final ValueEval _value;
|
||||
public SingleCellValueArray(ValueEval value) {
|
||||
super(1);
|
||||
_value = value;
|
||||
}
|
||||
protected ValueEval getItemInternal(int index) {
|
||||
return _value;
|
||||
}
|
||||
}
|
||||
|
||||
public final Eval evaluate(Eval[] args, int srcCellRow, short srcCellCol) {
|
||||
if(args.length != 2) {
|
||||
return ErrorEval.VALUE_INVALID;
|
||||
}
|
||||
|
||||
double[][] values;
|
||||
private static final class RefValueArray extends ValueArray {
|
||||
private final RefEval _ref;
|
||||
public RefValueArray(RefEval ref) {
|
||||
super(1);
|
||||
_ref = ref;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
return new NumberEval(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
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;
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < yops.length; i++) {
|
||||
Eval eval = yops[i];
|
||||
if (eval instanceof ErrorEval) {
|
||||
throw new EvaluationException((ErrorEval) eval);
|
||||
}
|
||||
if (firstXerr != null) {
|
||||
throw new EvaluationException(firstXerr);
|
||||
}
|
||||
|
||||
double[] xResult = new double[nArrayItems];
|
||||
double[] yResult = new double[nArrayItems];
|
||||
|
||||
int count = 0;
|
||||
|
||||
for (int i=0, iSize=nArrayItems; i<iSize; i++) {
|
||||
Eval xEval = xops[i];
|
||||
Eval yEval = yops[i];
|
||||
|
||||
if (isNumberEval(xEval) && isNumberEval(yEval)) {
|
||||
xResult[count] = getDoubleValue(xEval);
|
||||
yResult[count] = getDoubleValue(yEval);
|
||||
if (Double.isNaN(xResult[count]) || Double.isNaN(xResult[count])) {
|
||||
throw new EvaluationException(ErrorEval.NUM_ERROR);
|
||||
}
|
||||
count++;
|
||||
}
|
||||
if (firstYerr != null) {
|
||||
throw new EvaluationException(firstYerr);
|
||||
}
|
||||
|
||||
return new double[][] {
|
||||
trimToSize(xResult, count),
|
||||
trimToSize(yResult, count),
|
||||
};
|
||||
}
|
||||
|
||||
private static double[][] getValues(Eval argX, Eval argY) throws EvaluationException {
|
||||
|
||||
if (argX instanceof ErrorEval) {
|
||||
throw new EvaluationException((ErrorEval) argX);
|
||||
if (!accumlatedSome) {
|
||||
throw new EvaluationException(ErrorEval.DIV_ZERO);
|
||||
}
|
||||
if (argY instanceof ErrorEval) {
|
||||
throw new EvaluationException((ErrorEval) argY);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static ValueVector createValueVector(Eval arg) throws EvaluationException {
|
||||
if (arg instanceof ErrorEval) {
|
||||
throw new EvaluationException((ErrorEval) arg);
|
||||
}
|
||||
|
||||
Eval[] xEvals;
|
||||
Eval[] yEvals;
|
||||
if (argX instanceof AreaEval) {
|
||||
AreaEval ae = (AreaEval) argX;
|
||||
xEvals = ae.getValues();
|
||||
} else {
|
||||
xEvals = new Eval[] { argX, };
|
||||
if (arg instanceof AreaEval) {
|
||||
return new AreaValueArray((AreaEval) arg);
|
||||
}
|
||||
|
||||
if (argY instanceof AreaEval) {
|
||||
AreaEval ae = (AreaEval) argY;
|
||||
yEvals = ae.getValues();
|
||||
} else {
|
||||
yEvals = new Eval[] { argY, };
|
||||
if (arg instanceof RefEval) {
|
||||
return new RefValueArray((RefEval) arg);
|
||||
}
|
||||
|
||||
return getNumberArray(xEvals, yEvals);
|
||||
}
|
||||
|
||||
private static double[] trimToSize(double[] arr, int len) {
|
||||
double[] tarr = arr;
|
||||
if (arr.length > 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 (arg instanceof ValueEval) {
|
||||
return new SingleCellValueArray((ValueEval) arg);
|
||||
}
|
||||
throw new RuntimeException("Unexpected eval class (" + arg.getClass().getName() + ")");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
|
Loading…
Reference in New Issue