2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
18 package org
.apache
.poi
.hssf
.record
.formula
.functions
;
20 import org
.apache
.poi
.hssf
.record
.formula
.eval
.AreaEval
;
21 import org
.apache
.poi
.hssf
.record
.formula
.eval
.BlankEval
;
22 import org
.apache
.poi
.hssf
.record
.formula
.eval
.Eval
;
23 import org
.apache
.poi
.hssf
.record
.formula
.eval
.NumericValueEval
;
24 import org
.apache
.poi
.hssf
.record
.formula
.eval
.Ref2DEval
;
25 import org
.apache
.poi
.hssf
.record
.formula
.eval
.RefEval
;
26 import org
.apache
.poi
.hssf
.record
.formula
.eval
.ValueEval
;
27 import org
.apache
.poi
.hssf
.record
.formula
.eval
.ValueEvalToNumericXlator
;
30 * @author Amol S. Deshmukh < amolweb at ya hoo dot com >
31 * This is the super class for all excel function evaluator
32 * classes that take variable number of operands, and
33 * where the order of operands does not matter
35 public abstract class MultiOperandNumericFunction
extends NumericFunction
{
36 static final double[] EMPTY_DOUBLE_ARRAY
= { };
38 private static class DoubleList
{
39 private double[] _array
;
43 _array
= new double[8];
47 public double[] toArray() {
49 return EMPTY_DOUBLE_ARRAY
;
51 double[] result
= new double[_count
];
52 System
.arraycopy(_array
, 0, result
, 0, _count
);
56 public void add(double[] values
) {
57 int addLen
= values
.length
;
58 ensureCapacity(_count
+ addLen
);
59 System
.arraycopy(values
, 0, _array
, _count
, addLen
);
63 private void ensureCapacity(int reqSize
) {
64 if(reqSize
> _array
.length
) {
65 int newSize
= reqSize
* 3 / 2; // grow with 50% extra
66 double[] newArr
= new double[newSize
];
67 System
.arraycopy(_array
, 0, newArr
, 0, _count
);
72 public void add(double value
) {
73 ensureCapacity(_count
+ 1);
74 _array
[_count
] = value
;
79 private static final int DEFAULT_MAX_NUM_OPERANDS
= 30;
81 protected abstract ValueEvalToNumericXlator
getXlator();
84 * Maximum number of operands accepted by this function.
85 * Subclasses may override to change default value.
87 protected int getMaxNumOperands() {
88 return DEFAULT_MAX_NUM_OPERANDS
;
92 * Returns a double array that contains values for the numeric cells
93 * from among the list of operands. Blanks and Blank equivalent cells
94 * are ignored. Error operands or cells containing operands of type
95 * that are considered invalid and would result in #VALUE! error in
96 * excel cause this function to return <code>null</code>.
102 protected double[] getNumberArray(Eval
[] operands
, int srcRow
, short srcCol
) {
103 if (operands
.length
> getMaxNumOperands()) {
106 DoubleList retval
= new DoubleList();
108 for (int i
=0, iSize
=operands
.length
; i
<iSize
; i
++) {
109 double[] temp
= getNumberArray(operands
[i
], srcRow
, srcCol
);
111 return null; // error occurred.
115 return retval
.toArray();
119 * Same as getNumberArray(Eval[], int, short) except that this
120 * takes Eval instead of Eval[].
125 protected double[] getNumberArray(Eval operand
, int srcRow
, short srcCol
) {
127 if (operand
instanceof AreaEval
) {
128 AreaEval ae
= (AreaEval
) operand
;
129 ValueEval
[] values
= ae
.getValues();
130 DoubleList retval
= new DoubleList();
131 for (int j
=0, jSize
=values
.length
; j
<jSize
; j
++) {
133 * TODO: For an AreaEval, we are constructing a RefEval
135 * For now this is a tempfix solution since this may
136 * require a more generic fix at the level of
137 * HSSFFormulaEvaluator where we store an array
138 * of RefEvals as the "values" array.
140 RefEval re
= new Ref2DEval(null, values
[j
]);
141 ValueEval ve
= singleOperandEvaluate(re
, srcRow
, srcCol
);
143 if (ve
instanceof NumericValueEval
) {
144 NumericValueEval nve
= (NumericValueEval
) ve
;
145 retval
.add(nve
.getNumberValue());
147 else if (ve
instanceof BlankEval
) {
148 // note - blanks are ignored, so returned array will be smaller.
151 return null; // indicate to calling subclass that error occurred
154 return retval
.toArray();
157 // for ValueEvals other than AreaEval
158 ValueEval ve
= singleOperandEvaluate(operand
, srcRow
, srcCol
);
160 if (ve
instanceof NumericValueEval
) {
161 NumericValueEval nve
= (NumericValueEval
) ve
;
162 return new double[] { nve
.getNumberValue(), };
165 if (ve
instanceof BlankEval
) {
167 return EMPTY_DOUBLE_ARRAY
;
173 * Ensures that a two dimensional array has all sub-arrays present and the same length
174 * @return <code>false</code> if any sub-array is missing, or is of different length
176 protected static final boolean areSubArraysConsistent(double[][] values
) {
178 if (values
== null || values
.length
< 1) {
179 // TODO this doesn't seem right. Fix or add comment.
183 if (values
[0] == null) {
186 int outerMax
= values
.length
;
187 int innerMax
= values
[0].length
;
188 for (int i
=1; i
<outerMax
; i
++) { // note - 'i=1' start at second sub-array
189 double[] subArr
= values
[i
];
190 if (subArr
== null) {
193 if (innerMax
!= subArr
.length
) {