poi-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From j...@apache.org
Subject svn commit: r690761 - in /poi/trunk/src: java/org/apache/poi/hssf/record/formula/eval/ java/org/apache/poi/hssf/record/formula/functions/ testcases/org/apache/poi/hssf/record/formula/functions/
Date Sun, 31 Aug 2008 19:08:36 GMT
Author: josh
Date: Sun Aug 31 12:08:36 2008
New Revision: 690761

URL: http://svn.apache.org/viewvc?rev=690761&view=rev
Log:
removed AreaEval.getValues (initial work for bug 45358)

Modified:
    poi/trunk/src/java/org/apache/poi/hssf/record/formula/eval/AreaEval.java
    poi/trunk/src/java/org/apache/poi/hssf/record/formula/eval/AreaEvalBase.java
    poi/trunk/src/java/org/apache/poi/hssf/record/formula/eval/NumberEval.java
    poi/trunk/src/java/org/apache/poi/hssf/record/formula/functions/Index.java
    poi/trunk/src/java/org/apache/poi/hssf/record/formula/functions/MultiOperandNumericFunction.java
    poi/trunk/src/java/org/apache/poi/hssf/record/formula/functions/Sumx2my2.java
    poi/trunk/src/java/org/apache/poi/hssf/record/formula/functions/Sumx2py2.java
    poi/trunk/src/java/org/apache/poi/hssf/record/formula/functions/Sumxmy2.java
    poi/trunk/src/java/org/apache/poi/hssf/record/formula/functions/XYNumericFunction.java
    poi/trunk/src/testcases/org/apache/poi/hssf/record/formula/functions/TestSumproduct.java

Modified: poi/trunk/src/java/org/apache/poi/hssf/record/formula/eval/AreaEval.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/formula/eval/AreaEval.java?rev=690761&r1=690760&r2=690761&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/formula/eval/AreaEval.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/formula/eval/AreaEval.java Sun Aug 31 12:08:36
2008
@@ -62,13 +62,6 @@
     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 
      * indexes in the sheet and not relative indexes within the area.  

Modified: poi/trunk/src/java/org/apache/poi/hssf/record/formula/eval/AreaEvalBase.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/formula/eval/AreaEvalBase.java?rev=690761&r1=690760&r2=690761&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/formula/eval/AreaEvalBase.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/formula/eval/AreaEvalBase.java Sun Aug 31
12:08:36 2008
@@ -77,11 +77,6 @@
 		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;

Modified: poi/trunk/src/java/org/apache/poi/hssf/record/formula/eval/NumberEval.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/formula/eval/NumberEval.java?rev=690761&r1=690760&r2=690761&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/formula/eval/NumberEval.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/formula/eval/NumberEval.java Sun Aug 31
12:08:36 2008
@@ -69,5 +69,11 @@
             }
         }
     }
-    
+    public final String toString() {
+        StringBuffer sb = new StringBuffer(64);
+        sb.append(getClass().getName()).append(" [");
+        sb.append(getStringValue());
+        sb.append("]");
+        return sb.toString();
+    }
 }

Modified: poi/trunk/src/java/org/apache/poi/hssf/record/formula/functions/Index.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/formula/functions/Index.java?rev=690761&r1=690760&r2=690761&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/formula/functions/Index.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/formula/functions/Index.java Sun Aug 31
12:08:36 2008
@@ -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 @@
 			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 @@
 					// 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;
 	}
 }

Modified: poi/trunk/src/java/org/apache/poi/hssf/record/formula/functions/MultiOperandNumericFunction.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/formula/functions/MultiOperandNumericFunction.java?rev=690761&r1=690760&r2=690761&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/formula/functions/MultiOperandNumericFunction.java
(original)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/formula/functions/MultiOperandNumericFunction.java
Sun Aug 31 12:08:36 2008
@@ -126,30 +126,34 @@
         
         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();
         }

Modified: poi/trunk/src/java/org/apache/poi/hssf/record/formula/functions/Sumx2my2.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/formula/functions/Sumx2my2.java?rev=690761&r1=690760&r2=690761&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/formula/functions/Sumx2my2.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/formula/functions/Sumx2my2.java Sun Aug
31 12:08:36 2008
@@ -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 @@
  */
 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;
+	}
 }

Modified: poi/trunk/src/java/org/apache/poi/hssf/record/formula/functions/Sumx2py2.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/formula/functions/Sumx2py2.java?rev=690761&r1=690760&r2=690761&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/formula/functions/Sumx2py2.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/formula/functions/Sumx2py2.java Sun Aug
31 12:08:36 2008
@@ -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 @@
  */
 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;
+	}
 }

Modified: poi/trunk/src/java/org/apache/poi/hssf/record/formula/functions/Sumxmy2.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/formula/functions/Sumxmy2.java?rev=690761&r1=690760&r2=690761&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/formula/functions/Sumxmy2.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/formula/functions/Sumxmy2.java Sun Aug 31
12:08:36 2008
@@ -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 @@
  */
 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;
+	}
 }

Modified: poi/trunk/src/java/org/apache/poi/hssf/record/formula/functions/XYNumericFunction.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/formula/functions/XYNumericFunction.java?rev=690761&r1=690760&r2=690761&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/formula/functions/XYNumericFunction.java
(original)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/formula/functions/XYNumericFunction.java
Sun Aug 31 12:08:36 2008
@@ -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.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 &lt; amolweb at ya hoo dot com &gt;
- *
+ * 
  */
 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;
+		}
+	}
+
+	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 DoubleArrayPair(double[] xArray, double[] yArray) {
-			_xArray = xArray;
-			_yArray = yArray;
+	private static final class RefValueArray extends ValueArray {
+		private final RefEval _ref;
+		public RefValueArray(RefEval ref) {
+			super(1);
+			_ref = ref;
 		}
-		public double[] getXArray() {
-			return _xArray;
+		protected ValueEval getItemInternal(int index) {
+			return _ref.getInnerValueEval();
 		}
-		public double[] getYArray() {
-			return _yArray;
+	}
+
+	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
+			}
+		}
+		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);
 		}
-		
-        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++;
-		    }
-		}
-        
-		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 (argY instanceof ErrorEval) {
-			throw new EvaluationException((ErrorEval) argY);
-		}
-    	
-        Eval[] xEvals;
-		Eval[] yEvals;
-		if (argX instanceof AreaEval) {
-		    AreaEval ae = (AreaEval) argX;
-		    xEvals = ae.getValues();
-		} else {
-		    xEvals = new Eval[] { argX, };
-		}
-		
-		if (argY instanceof AreaEval) {
-		    AreaEval ae = (AreaEval) argY;
-		    yEvals = ae.getValues();
-		} else {
-		    yEvals = new Eval[] { argY, };
-		}
-		
-		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;
-    }
+		throw new RuntimeException("Unexpected eval class (" + arg.getClass().getName() + ")");
+	}
 }

Modified: poi/trunk/src/testcases/org/apache/poi/hssf/record/formula/functions/TestSumproduct.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/hssf/record/formula/functions/TestSumproduct.java?rev=690761&r1=690760&r2=690761&view=diff
==============================================================================
--- poi/trunk/src/testcases/org/apache/poi/hssf/record/formula/functions/TestSumproduct.java
(original)
+++ poi/trunk/src/testcases/org/apache/poi/hssf/record/formula/functions/TestSumproduct.java
Sun Aug 31 12:08:36 2008
@@ -113,7 +113,6 @@
 		};
 		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));



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org


Mime
View raw message