From 240b02daecdabd3e314bd662d56665cbb6cdf5fd Mon Sep 17 00:00:00 2001 From: Andreas Beeker Date: Tue, 13 Apr 2021 19:44:38 +0000 Subject: [PATCH] replace over engineered inner classes with lambdas/method references git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1888743 13f79535-47bb-0310-9956-ffa450edef68 --- .../poi/ss/formula/eval/FunctionEval.java | 14 +- .../ss/formula/functions/ArrayFunction.java | 28 +- .../ss/formula/functions/BooleanFunction.java | 65 +- .../poi/ss/formula/functions/Column.java | 30 +- .../apache/poi/ss/formula/functions/Even.java | 49 -- .../formula/functions/Fixed0ArgFunction.java | 5 +- .../apache/poi/ss/formula/functions/Log.java | 50 ++ .../poi/ss/formula/functions/MathX.java | 21 +- .../apache/poi/ss/formula/functions/Na.java | 9 +- .../apache/poi/ss/formula/functions/Now.java | 11 +- .../ss/formula/functions/NumericFunction.java | 562 +++++------------- .../apache/poi/ss/formula/functions/Odd.java | 39 -- .../poi/ss/formula/functions/Poisson.java | 115 ++++ .../poi/ss/formula/functions/RowFunc.java | 30 +- .../poi/ss/formula/functions/Today.java | 8 +- .../poi/ss/formula/functions/TestRowCol.java | 6 +- 16 files changed, 437 insertions(+), 605 deletions(-) delete mode 100644 poi/src/main/java/org/apache/poi/ss/formula/functions/Even.java create mode 100644 poi/src/main/java/org/apache/poi/ss/formula/functions/Log.java delete mode 100644 poi/src/main/java/org/apache/poi/ss/formula/functions/Odd.java create mode 100644 poi/src/main/java/org/apache/poi/ss/formula/functions/Poisson.java diff --git a/poi/src/main/java/org/apache/poi/ss/formula/eval/FunctionEval.java b/poi/src/main/java/org/apache/poi/ss/formula/eval/FunctionEval.java index da670439a9..b5fdb8a8c8 100644 --- a/poi/src/main/java/org/apache/poi/ss/formula/eval/FunctionEval.java +++ b/poi/src/main/java/org/apache/poi/ss/formula/eval/FunctionEval.java @@ -73,9 +73,9 @@ public final class FunctionEval { retval[5] = AggregateFunction.AVERAGE; retval[6] = AggregateFunction.MIN; retval[7] = AggregateFunction.MAX; - retval[8] = new RowFunc(); // ROW - retval[9] = new Column(); - retval[10] = new Na(); + retval[8] = RowFunc::evaluate; // ROW + retval[9] = Column::evaluate; + retval[10] = Na::evaluate; retval[11] = new Npv(); retval[12] = AggregateFunction.STDEV; retval[13] = NumericFunction.DOLLAR; @@ -137,7 +137,7 @@ public final class FunctionEval { retval[71] = CalendarFieldFunction.HOUR; retval[72] = CalendarFieldFunction.MINUTE; retval[73] = CalendarFieldFunction.SECOND; - retval[74] = new Now(); + retval[74] = Now::evaluate; retval[75] = new Areas(); retval[76] = new Rows(); retval[77] = new Columns(); @@ -226,7 +226,7 @@ public final class FunctionEval { retval[216] = new Rank(); retval[219] = new Address(); retval[220] = new Days360(); - retval[221] = new Today(); + retval[221] = Today::evaluate; //222: VBD retval[227] = AggregateFunction.MEDIAN; @@ -259,7 +259,7 @@ public final class FunctionEval { retval[276] = NumericFunction.COMBIN; // 277: CONFIDENCE // 278:CRITBINOM - retval[279] = new Even(); + retval[279] = NumericFunction.EVEN; // 280: EXPONDIST // 281: FDIST // 282: FINV @@ -278,7 +278,7 @@ public final class FunctionEval { // 295: NORMINV // 296: NORMSINV // 297: STANDARDIZE - retval[298] = new Odd(); + retval[298] = NumericFunction.ODD; // 299: PERMUT retval[300] = NumericFunction.POISSON; // 301: TDIST diff --git a/poi/src/main/java/org/apache/poi/ss/formula/functions/ArrayFunction.java b/poi/src/main/java/org/apache/poi/ss/formula/functions/ArrayFunction.java index 0e842fc5c9..46b89d5013 100644 --- a/poi/src/main/java/org/apache/poi/ss/formula/functions/ArrayFunction.java +++ b/poi/src/main/java/org/apache/poi/ss/formula/functions/ArrayFunction.java @@ -29,13 +29,13 @@ import java.util.function.BiFunction; */ public interface ArrayFunction { - + /** * @param args the evaluated function arguments. Empty values are represented with - * {@link BlankEval} or {@link MissingArgEval}, never null. + * {@link BlankEval} or {@link MissingArgEval}, never {@code null}. * @param srcRowIndex row index of the cell containing the formula under evaluation * @param srcColumnIndex column index of the cell containing the formula under evaluation - * @return The evaluated result, possibly an {@link ErrorEval}, never null. + * @return The evaluated result, possibly an {@link ErrorEval}, never {@code null}. * Note - Excel uses the error code #NUM! instead of IEEE NaN, so when * numeric functions evaluate to {@link Double#NaN} be sure to translate the result to {@link * ErrorEval#NUM_ERROR}. @@ -47,19 +47,29 @@ public interface ArrayFunction { * Evaluate an array function with two arguments. * * @param arg0 the first function argument. Empty values are represented with - * {@link BlankEval} or {@link MissingArgEval}, never null + * {@link BlankEval} or {@link MissingArgEval}, never {@code null} * @param arg1 the first function argument. Empty values are represented with - * @link BlankEval} or {@link MissingArgEval}, never null + * @link BlankEval} or {@link MissingArgEval}, never {@code null} * * @param srcRowIndex row index of the cell containing the formula under evaluation * @param srcColumnIndex column index of the cell containing the formula under evaluation - * @return The evaluated result, possibly an {@link ErrorEval}, never null. + * @return The evaluated result, possibly an {@link ErrorEval}, never {@code null}. * Note - Excel uses the error code #NUM! instead of IEEE NaN, so when * numeric functions evaluate to {@link Double#NaN} be sure to translate the result to {@link * ErrorEval#NUM_ERROR}. */ default ValueEval evaluateTwoArrayArgs(ValueEval arg0, ValueEval arg1, int srcRowIndex, int srcColumnIndex, BiFunction evalFunc) { + return _evaluateTwoArrayArgs(arg0, arg1, srcRowIndex, srcColumnIndex, evalFunc); + } + + default ValueEval evaluateOneArrayArg(ValueEval arg0, int srcRowIndex, int srcColumnIndex, + java.util.function.Function evalFunc) { + return _evaluateOneArrayArg(arg0, srcRowIndex, srcColumnIndex, evalFunc); + } + + static ValueEval _evaluateTwoArrayArgs(ValueEval arg0, ValueEval arg1, int srcRowIndex, int srcColumnIndex, + BiFunction evalFunc) { int w1, w2, h1, h2; int a1FirstCol = 0, a1FirstRow = 0; if (arg0 instanceof AreaEval) { @@ -150,8 +160,9 @@ public interface ArrayFunction { return new CacheAreaEval(srcRowIndex, srcColumnIndex, srcRowIndex + height - 1, srcColumnIndex + width - 1, vals); } - default ValueEval evaluateOneArrayArg(ValueEval arg0, int srcRowIndex, int srcColumnIndex, - java.util.function.Function evalFunc){ + + static ValueEval _evaluateOneArrayArg(ValueEval arg0, int srcRowIndex, int srcColumnIndex, + java.util.function.Function evalFunc){ int w1, w2, h1, h2; int a1FirstCol = 0, a1FirstRow = 0; if (arg0 instanceof AreaEval) { @@ -204,7 +215,6 @@ public interface ArrayFunction { } return new CacheAreaEval(srcRowIndex, srcColumnIndex, srcRowIndex + height - 1, srcColumnIndex + width - 1, vals); - } } diff --git a/poi/src/main/java/org/apache/poi/ss/formula/functions/BooleanFunction.java b/poi/src/main/java/org/apache/poi/ss/formula/functions/BooleanFunction.java index 5177b851a6..885609ae41 100644 --- a/poi/src/main/java/org/apache/poi/ss/formula/functions/BooleanFunction.java +++ b/poi/src/main/java/org/apache/poi/ss/formula/functions/BooleanFunction.java @@ -34,8 +34,6 @@ import org.apache.poi.ss.formula.eval.ValueEval; *
  • Numbers: 0 is false. Any other number is TRUE
  • *
  • Areas: *all* cells in area are evaluated according to the above rules
  • * - * - * @author Amol S. Deshmukh < amolweb at ya hoo dot com > */ public abstract class BooleanFunction implements Function,ArrayFunction { @@ -132,43 +130,12 @@ public abstract class BooleanFunction implements Function,ArrayFunction { return cumulativeResult || currentValue; } }; - public static final Function FALSE = new Fixed0ArgFunction() { - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex) { - return BoolEval.FALSE; - } - }; - public static final Function TRUE = new Fixed0ArgFunction() { - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex) { - return BoolEval.TRUE; - } - }; - abstract static class Boolean1ArgFunction extends Fixed1ArgFunction implements ArrayFunction { - @Override - public ValueEval evaluateArray(ValueEval[] args, int srcRowIndex, int srcColumnIndex) { - if (args.length != 1) { - return ErrorEval.VALUE_INVALID; - } - return evaluateOneArrayArg(args[0], srcRowIndex, srcColumnIndex, - vA -> evaluate(srcRowIndex, srcColumnIndex, vA)); - } + public static final Function FALSE = BooleanFunction::evaluateFalse; - } + public static final Function TRUE = BooleanFunction::evaluateTrue; - public static final Function NOT = new Boolean1ArgFunction() { - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) { - boolean boolArgVal; - try { - ValueEval ve = OperandResolver.getSingleValue(arg0, srcRowIndex, srcColumnIndex); - Boolean b = OperandResolver.coerceValueToBoolean(ve, false); - boolArgVal = b == null ? false : b; - } catch (EvaluationException e) { - return e.getErrorEval(); - } - - return BoolEval.valueOf(!boolArgVal); - } - }; + public static final Function NOT = BooleanFunction::evaluateNot; @Override public ValueEval evaluateArray(ValueEval[] args, int srcRowIndex, int srcColumnIndex) { @@ -178,4 +145,30 @@ public abstract class BooleanFunction implements Function,ArrayFunction { return evaluateOneArrayArg(args[0], srcRowIndex, srcColumnIndex, vA -> evaluate(new ValueEval[]{vA}, srcRowIndex, srcColumnIndex)); } + + private static ValueEval evaluateFalse(ValueEval[] args, int srcRowIndex, int srcColumnIndex) { + return args.length != 0 ? ErrorEval.VALUE_INVALID : BoolEval.FALSE; + } + + private static ValueEval evaluateTrue(ValueEval[] args, int srcRowIndex, int srcColumnIndex) { + return args.length != 0 ? ErrorEval.VALUE_INVALID : BoolEval.TRUE; + } + + private static ValueEval evaluateNot(ValueEval[] args, int srcRowIndex, int srcColumnIndex) { + if (args.length != 1) { + return ErrorEval.VALUE_INVALID; + } + java.util.function.Function notInner = (va) -> { + try { + ValueEval ve = OperandResolver.getSingleValue(va, srcRowIndex, srcColumnIndex); + Boolean b = OperandResolver.coerceValueToBoolean(ve, false); + boolean boolArgVal = b != null && b; + return BoolEval.valueOf(!boolArgVal); + } catch (EvaluationException e) { + return e.getErrorEval(); + } + }; + + return ArrayFunction._evaluateOneArrayArg(args[0], srcRowIndex, srcColumnIndex, notInner); + } } \ No newline at end of file diff --git a/poi/src/main/java/org/apache/poi/ss/formula/functions/Column.java b/poi/src/main/java/org/apache/poi/ss/formula/functions/Column.java index 9c152bb17f..6e2c9bcb09 100644 --- a/poi/src/main/java/org/apache/poi/ss/formula/functions/Column.java +++ b/poi/src/main/java/org/apache/poi/ss/formula/functions/Column.java @@ -23,18 +23,19 @@ import org.apache.poi.ss.formula.eval.NumberEval; import org.apache.poi.ss.formula.eval.RefEval; import org.apache.poi.ss.formula.eval.ValueEval; -public final class Column implements Function0Arg, Function1Arg { +public final class Column { + public static ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) { + if (args.length > 1) { + return ErrorEval.VALUE_INVALID; + } - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex) { - return new NumberEval(srcColumnIndex+1.); - } - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) { int rnum; - - if (arg0 instanceof AreaEval) { - rnum = ((AreaEval) arg0).getFirstColumn(); - } else if (arg0 instanceof RefEval) { - rnum = ((RefEval) arg0).getColumn(); + if (args.length == 0) { + rnum = srcColumnIndex; + } else if (args[0] instanceof AreaEval) { + rnum = ((AreaEval) args[0]).getFirstColumn(); + } else if (args[0] instanceof RefEval) { + rnum = ((RefEval) args[0]).getColumn(); } else { // anything else is not valid argument return ErrorEval.VALUE_INVALID; @@ -42,13 +43,4 @@ public final class Column implements Function0Arg, Function1Arg { return new NumberEval(rnum + 1.); } - public ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) { - switch (args.length) { - case 1: - return evaluate(srcRowIndex, srcColumnIndex, args[0]); - case 0: - return new NumberEval(srcColumnIndex+1.); - } - return ErrorEval.VALUE_INVALID; - } } diff --git a/poi/src/main/java/org/apache/poi/ss/formula/functions/Even.java b/poi/src/main/java/org/apache/poi/ss/formula/functions/Even.java deleted file mode 100644 index f691265324..0000000000 --- a/poi/src/main/java/org/apache/poi/ss/formula/functions/Even.java +++ /dev/null @@ -1,49 +0,0 @@ -/* ==================================================================== - 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.ss.formula.functions; - - -/** - * @author Amol S. Deshmukh < amolweb at ya hoo dot com > - * - */ -public final class Even extends NumericFunction.OneArg { - - private static final long PARITY_MASK = 0xFFFFFFFFFFFFFFFEL; - - protected double evaluate(double d) { - if (d==0) { - return 0; - } - long result; - if (d>0) { - result = calcEven(d); - } else { - result = -calcEven(-d); - } - return result; - } - - private static long calcEven(double d) { - long x = ((long) d) & PARITY_MASK; - if (x == d) { - return x; - } - return x + 2; - } -} diff --git a/poi/src/main/java/org/apache/poi/ss/formula/functions/Fixed0ArgFunction.java b/poi/src/main/java/org/apache/poi/ss/formula/functions/Fixed0ArgFunction.java index dbb1695ba7..6ad247f4f5 100644 --- a/poi/src/main/java/org/apache/poi/ss/formula/functions/Fixed0ArgFunction.java +++ b/poi/src/main/java/org/apache/poi/ss/formula/functions/Fixed0ArgFunction.java @@ -19,12 +19,15 @@ package org.apache.poi.ss.formula.functions; import org.apache.poi.ss.formula.eval.ErrorEval; import org.apache.poi.ss.formula.eval.ValueEval; +import org.apache.poi.util.Removal; /** * Convenience base class for functions that only take zero arguments. * - * @author Josh Micich + * @deprecated replaced by lambda expressions in 5.0.1 */ +@Deprecated +@Removal(version = "6.0.0") public abstract class Fixed0ArgFunction implements Function0Arg { public final ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) { if (args.length != 0) { diff --git a/poi/src/main/java/org/apache/poi/ss/formula/functions/Log.java b/poi/src/main/java/org/apache/poi/ss/formula/functions/Log.java new file mode 100644 index 0000000000..d477405be9 --- /dev/null +++ b/poi/src/main/java/org/apache/poi/ss/formula/functions/Log.java @@ -0,0 +1,50 @@ +/* ==================================================================== + 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.ss.formula.functions; + +import org.apache.poi.ss.formula.eval.ErrorEval; +import org.apache.poi.ss.formula.eval.EvaluationException; +import org.apache.poi.ss.formula.eval.NumberEval; +import org.apache.poi.ss.formula.eval.ValueEval; + +public class Log { + private static final double TEN = 10.0; + private static final double LOG_10_TO_BASE_e = Math.log(TEN); + + public static ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) { + if (args.length != 1 && args.length != 2) { + return ErrorEval.VALUE_INVALID; + } + + try { + double d0 = NumericFunction.singleOperandEvaluate(args[0], srcRowIndex, srcColumnIndex); + double result; + if (args.length == 1) { + result = Math.log(d0) / LOG_10_TO_BASE_e; + } else { + double d1 = NumericFunction.singleOperandEvaluate(args[1], srcRowIndex, srcColumnIndex); + double logE = Math.log(d0); + result = (Double.compare(d1, Math.E) == 0) ? logE : (logE / Math.log(d1)); + } + NumericFunction.checkValue(result); + return new NumberEval(result); + } catch (EvaluationException e) { + return e.getErrorEval(); + } + } +} diff --git a/poi/src/main/java/org/apache/poi/ss/formula/functions/MathX.java b/poi/src/main/java/org/apache/poi/ss/formula/functions/MathX.java index c88923faf6..7b33de57ec 100644 --- a/poi/src/main/java/org/apache/poi/ss/formula/functions/MathX.java +++ b/poi/src/main/java/org/apache/poi/ss/formula/functions/MathX.java @@ -51,6 +51,12 @@ final class MathX { return round(n, p, java.math.RoundingMode.HALF_UP); } + public static double round(double n, double p) { + return round(n, (int)p); + } + + + /** * Returns a value rounded-up to p digits after decimal. * If p is negative, then the number is rounded to @@ -70,6 +76,11 @@ final class MathX { return round(n, p, java.math.RoundingMode.UP); } + public static double roundUp(double n, double p) { + return roundUp(n, (int)p); + } + + /** * Returns a value rounded to p digits after decimal. * If p is negative, then the number is rounded to @@ -88,7 +99,11 @@ final class MathX { public static double roundDown(double n, int p) { return round(n, p, java.math.RoundingMode.DOWN); } - + + public static double roundDown(double n, double p) { + return roundDown(n, (int)p); + } + private static double round(double n, int p, java.math.RoundingMode rounding) { if (Double.isNaN(n) || Double.isInfinite(n)) { return Double.NaN; @@ -273,6 +288,10 @@ final class MathX { return d; } + public static double factorial(double d) { + return factorial((int)d); + } + /** * returns the remainder resulting from operation: diff --git a/poi/src/main/java/org/apache/poi/ss/formula/functions/Na.java b/poi/src/main/java/org/apache/poi/ss/formula/functions/Na.java index 3224867704..15db474163 100644 --- a/poi/src/main/java/org/apache/poi/ss/formula/functions/Na.java +++ b/poi/src/main/java/org/apache/poi/ss/formula/functions/Na.java @@ -22,12 +22,9 @@ import org.apache.poi.ss.formula.eval.ValueEval; /** * Implementation of Excel function NA() - * - * @author Josh Micich */ -public final class Na extends Fixed0ArgFunction { - - public ValueEval evaluate(int srcCellRow, int srcCellCol) { - return ErrorEval.NA; +public final class Na { + public static ValueEval evaluate(ValueEval[] args, int srcCellRow, int srcCellCol) { + return args.length != 0 ? ErrorEval.VALUE_INVALID : ErrorEval.NA; } } diff --git a/poi/src/main/java/org/apache/poi/ss/formula/functions/Now.java b/poi/src/main/java/org/apache/poi/ss/formula/functions/Now.java index e0fcf22fd3..c840d923a2 100644 --- a/poi/src/main/java/org/apache/poi/ss/formula/functions/Now.java +++ b/poi/src/main/java/org/apache/poi/ss/formula/functions/Now.java @@ -19,18 +19,19 @@ package org.apache.poi.ss.formula.functions; import java.util.Date; +import org.apache.poi.ss.formula.eval.ErrorEval; import org.apache.poi.ss.formula.eval.NumberEval; import org.apache.poi.ss.formula.eval.ValueEval; import org.apache.poi.ss.usermodel.DateUtil; /** * Implementation of Excel NOW() Function - * - * @author Frank Taffelt */ -public final class Now extends Fixed0ArgFunction { - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex) { +public final class Now { + public static ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) { + if (args.length != 0) { + return ErrorEval.VALUE_INVALID; + } Date now = new Date(System.currentTimeMillis()); return new NumberEval(DateUtil.getExcelDate(now)); } diff --git a/poi/src/main/java/org/apache/poi/ss/formula/functions/NumericFunction.java b/poi/src/main/java/org/apache/poi/ss/formula/functions/NumericFunction.java index b0e85d903e..74597910b5 100644 --- a/poi/src/main/java/org/apache/poi/ss/formula/functions/NumericFunction.java +++ b/poi/src/main/java/org/apache/poi/ss/formula/functions/NumericFunction.java @@ -17,18 +17,17 @@ package org.apache.poi.ss.formula.functions; +import static org.apache.poi.ss.formula.eval.ErrorEval.VALUE_INVALID; + import org.apache.poi.ss.formula.eval.*; -/** - * @author Amol S. Deshmukh < amolweb at ya hoo dot com > - * @author Josh Micich - * @author Stephen Wolke (smwolke at geistig.com) - */ public abstract class NumericFunction implements Function { - static final double ZERO = 0.0; - static final double TEN = 10.0; - static final double LOG_10_TO_BASE_e = Math.log(TEN); + private static final double ZERO = 0.0; + private static final double TEN = 10.0; + private static final double LOG_10_TO_BASE_e = Math.log(TEN); + private static final long PARITY_MASK = 0xFFFFFFFFFFFFFFFEL; + protected static double singleOperandEvaluate(ValueEval arg, int srcRowIndex, int srcColumnIndex) throws EvaluationException { if (arg == null) { @@ -41,7 +40,7 @@ public abstract class NumericFunction implements Function { } /** - * @throws EvaluationException (#NUM!) if result is NaN or Infinity + * @throws EvaluationException (#NUM!) if result is {@code NaN} or {@code Infinity} */ public static void checkValue(double result) throws EvaluationException { if (Double.isNaN(result) || Double.isInfinite(result)) { @@ -62,432 +61,179 @@ public abstract class NumericFunction implements Function { protected abstract double eval(ValueEval[] args, int srcCellRow, int srcCellCol) throws EvaluationException; - /* -------------------------------------------------------------------------- */ - // intermediate sub-classes (one-arg, two-arg and multi-arg) + public static final Function ABS = oneDouble(Math::abs); + public static final Function ACOS = oneDouble(Math::acos); + public static final Function ACOSH = oneDouble(MathX::acosh); + public static final Function ASIN = oneDouble(Math::asin); + public static final Function ASINH = oneDouble(MathX::asinh); + public static final Function ATAN = oneDouble(Math::atan); + public static final Function ATANH = oneDouble(MathX::atanh); + public static final Function COS = oneDouble(Math::cos); + public static final Function COSH = oneDouble(MathX::cosh); + public static final Function DEGREES = oneDouble(Math::toDegrees); + public static final Function DOLLAR = NumericFunction::evaluateDollar; - public static abstract class OneArg extends Fixed1ArgFunction { - protected OneArg() { - // no fields to initialise + private static ValueEval evaluateDollar(ValueEval[] args, int srcRowIndex, int srcColumnIndex) { + if (args.length != 1 && args.length != 2) { + return ErrorEval.VALUE_INVALID; } - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) { - double result; - try { - double d = singleOperandEvaluate(arg0, srcRowIndex, srcColumnIndex); - result = evaluate(d); - checkValue(result); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - return new NumberEval(result); - } - protected final double eval(ValueEval[] args, int srcCellRow, int srcCellCol) throws EvaluationException { - if (args.length != 1) { - throw new EvaluationException(ErrorEval.VALUE_INVALID); - } - double d = singleOperandEvaluate(args[0], srcCellRow, srcCellCol); - return evaluate(d); - } - protected abstract double evaluate(double d) throws EvaluationException; - } + try { + double val = singleOperandEvaluate(args[0], srcRowIndex, srcColumnIndex); + double d1 = args.length == 1 ? 2.0 : singleOperandEvaluate(args[1], srcRowIndex, srcColumnIndex); - public static abstract class TwoArg extends Fixed2ArgFunction { - protected TwoArg() { - // no fields to initialise - } - - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) { - double result; - try { - double d0 = singleOperandEvaluate(arg0, srcRowIndex, srcColumnIndex); - double d1 = singleOperandEvaluate(arg1, srcRowIndex, srcColumnIndex); - result = evaluate(d0, d1); - checkValue(result); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - return new NumberEval(result); - } - - protected abstract double evaluate(double d0, double d1) throws EvaluationException; - } - - /* -------------------------------------------------------------------------- */ - - public static final Function ABS = new OneArg() { - protected double evaluate(double d) { - return Math.abs(d); - } - }; - public static final Function ACOS = new OneArg() { - protected double evaluate(double d) { - return Math.acos(d); - } - }; - public static final Function ACOSH = new OneArg() { - protected double evaluate(double d) { - return MathX.acosh(d); - } - }; - public static final Function ASIN = new OneArg() { - protected double evaluate(double d) { - return Math.asin(d); - } - }; - public static final Function ASINH = new OneArg() { - protected double evaluate(double d) { - return MathX.asinh(d); - } - }; - public static final Function ATAN = new OneArg() { - protected double evaluate(double d) { - return Math.atan(d); - } - }; - public static final Function ATANH = new OneArg() { - protected double evaluate(double d) { - return MathX.atanh(d); - } - }; - public static final Function COS = new OneArg() { - protected double evaluate(double d) { - return Math.cos(d); - } - }; - public static final Function COSH = new OneArg() { - protected double evaluate(double d) { - return MathX.cosh(d); - } - }; - public static final Function DEGREES = new OneArg() { - protected double evaluate(double d) { - return Math.toDegrees(d); - } - }; - static final NumberEval DOLLAR_ARG2_DEFAULT = new NumberEval(2.0); - public static final Function DOLLAR = new Var1or2ArgFunction() { - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) { - return evaluate(srcRowIndex, srcColumnIndex, arg0, DOLLAR_ARG2_DEFAULT); - } - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, - ValueEval arg1) { - double val; - double d1; - try { - val = singleOperandEvaluate(arg0, srcRowIndex, srcColumnIndex); - d1 = singleOperandEvaluate(arg1, srcRowIndex, srcColumnIndex); - } catch (EvaluationException e) { - return e.getErrorEval(); - } // second arg converts to int by truncating toward zero int nPlaces = (int)d1; if (nPlaces > 127) { - return ErrorEval.VALUE_INVALID; + return VALUE_INVALID; } - // TODO - DOLLAR() function impl is NQR // result should be StringEval, with leading '$' and thousands separators // current junits are asserting incorrect behaviour return new NumberEval(val); - } - }; - public static final Function EXP = new OneArg() { - protected double evaluate(double d) { - return Math.pow(Math.E, d); - } - }; - public static final Function FACT = new OneArg() { - protected double evaluate(double d) { - return MathX.factorial((int)d); - } - }; - public static final Function INT = new OneArg() { - protected double evaluate(double d) { - return Math.round(d-0.5); - } - }; - public static final Function LN = new OneArg() { - protected double evaluate(double d) { - return Math.log(d); - } - }; - public static final Function LOG10 = new OneArg() { - protected double evaluate(double d) { - return Math.log(d) / LOG_10_TO_BASE_e; - } - }; - public static final Function RADIANS = new OneArg() { - protected double evaluate(double d) { - return Math.toRadians(d); - } - }; - public static final Function SIGN = new OneArg() { - protected double evaluate(double d) { - return MathX.sign(d); - } - }; - public static final Function SIN = new OneArg() { - protected double evaluate(double d) { - return Math.sin(d); - } - }; - public static final Function SINH = new OneArg() { - protected double evaluate(double d) { - return MathX.sinh(d); - } - }; - public static final Function SQRT = new OneArg() { - protected double evaluate(double d) { - return Math.sqrt(d); - } - }; - - public static final Function TAN = new OneArg() { - protected double evaluate(double d) { - return Math.tan(d); - } - }; - public static final Function TANH = new OneArg() { - protected double evaluate(double d) { - return MathX.tanh(d); - } - }; - - /* -------------------------------------------------------------------------- */ - - public static final Function ATAN2 = new TwoArg() { - protected double evaluate(double d0, double d1) throws EvaluationException { - if (d0 == ZERO && d1 == ZERO) { - throw new EvaluationException(ErrorEval.DIV_ZERO); - } - return Math.atan2(d1, d0); - } - }; - public static final Function CEILING = new TwoArg() { - protected double evaluate(double d0, double d1) { - return MathX.ceiling(d0, d1); - } - }; - public static final Function COMBIN = new TwoArg() { - protected double evaluate(double d0, double d1) throws EvaluationException { - if (d0 > Integer.MAX_VALUE || d1 > Integer.MAX_VALUE) { - throw new EvaluationException(ErrorEval.NUM_ERROR); - } - return MathX.nChooseK((int) d0, (int) d1); - } - }; - public static final Function FLOOR = new TwoArg() { - protected double evaluate(double d0, double d1) throws EvaluationException { - if (d1 == ZERO) { - if (d0 == ZERO) { - return ZERO; - } - throw new EvaluationException(ErrorEval.DIV_ZERO); - } - return MathX.floor(d0, d1); - } - }; - public static final Function MOD = new TwoArg() { - protected double evaluate(double d0, double d1) throws EvaluationException { - if (d1 == ZERO) { - throw new EvaluationException(ErrorEval.DIV_ZERO); - } - return MathX.mod(d0, d1); - } - }; - public static final Function POWER = new TwoArg() { - protected double evaluate(double d0, double d1) { - return Math.pow(d0, d1); - } - }; - public static final Function ROUND = new TwoArg() { - protected double evaluate(double d0, double d1) { - return MathX.round(d0, (int)d1); - } - }; - public static final Function ROUNDDOWN = new TwoArg() { - protected double evaluate(double d0, double d1) { - return MathX.roundDown(d0, (int)d1); - } - }; - public static final Function ROUNDUP = new TwoArg() { - protected double evaluate(double d0, double d1) { - return MathX.roundUp(d0, (int)d1); - } - }; - static final NumberEval TRUNC_ARG2_DEFAULT = new NumberEval(0); - public static final Function TRUNC = new Var1or2ArgFunction() { - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) { - return evaluate(srcRowIndex, srcColumnIndex, arg0, TRUNC_ARG2_DEFAULT); - } - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) { - double result; - try { - double d0 = singleOperandEvaluate(arg0, srcRowIndex, srcColumnIndex); - double d1 = singleOperandEvaluate(arg1, srcRowIndex, srcColumnIndex); - result = MathX.roundDown(d0, (int)d1); - checkValue(result); - }catch (EvaluationException e) { - return e.getErrorEval(); - } - return new NumberEval(result); - } - }; - - /* -------------------------------------------------------------------------- */ - - private static final class Log extends Var1or2ArgFunction { - public Log() { - // no instance fields - } - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) { - double result; - try { - double d0 = NumericFunction.singleOperandEvaluate(arg0, srcRowIndex, srcColumnIndex); - result = Math.log(d0) / LOG_10_TO_BASE_e; - NumericFunction.checkValue(result); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - return new NumberEval(result); - } - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, - ValueEval arg1) { - double result; - try { - double d0 = NumericFunction.singleOperandEvaluate(arg0, srcRowIndex, srcColumnIndex); - double d1 = NumericFunction.singleOperandEvaluate(arg1, srcRowIndex, srcColumnIndex); - double logE = Math.log(d0); - if (Double.compare(d1, Math.E) == 0) { - result = logE; - } else { - result = logE / Math.log(d1); - } - NumericFunction.checkValue(result); - } catch (EvaluationException e) { - return e.getErrorEval(); - } - return new NumberEval(result); + }catch (EvaluationException e) { + return e.getErrorEval(); } } - public static final Function LOG = new Log(); + public static final Function EXP = oneDouble(d -> Math.pow(Math.E, d)); + public static final Function FACT = oneDouble(MathX::factorial); + public static final Function INT = oneDouble(d -> Math.round(d-0.5)); + public static final Function LN = oneDouble(Math::log); + public static final Function LOG10 = oneDouble(d -> Math.log(d) / LOG_10_TO_BASE_e); + public static final Function RADIANS = oneDouble(Math::toRadians); + public static final Function SIGN = oneDouble(MathX::sign); + public static final Function SIN = oneDouble(Math::sin); + public static final Function SINH = oneDouble(MathX::sinh); + public static final Function SQRT = oneDouble(Math::sqrt); + public static final Function TAN = oneDouble(Math::tan); + public static final Function TANH = oneDouble(MathX::tanh); + + /* -------------------------------------------------------------------------- */ + + public static final Function ATAN2 = twoDouble((d0, d1) -> + (d0 == ZERO && d1 == ZERO) ? ErrorEval.DIV_ZERO : Math.atan2(d1, d0) + ); + + public static final Function CEILING = twoDouble(MathX::ceiling); + + public static final Function COMBIN = twoDouble((d0, d1) -> + (d0 > Integer.MAX_VALUE || d1 > Integer.MAX_VALUE) ? ErrorEval.NUM_ERROR : MathX.nChooseK((int) d0, (int) d1)); + + public static final Function FLOOR = twoDouble((d0, d1) -> + (d1 == ZERO) ? (d0 == ZERO ? ZERO : ErrorEval.DIV_ZERO) : MathX.floor(d0, d1)); + + public static final Function MOD = twoDouble((d0, d1) -> + (d1 == ZERO) ? ErrorEval.DIV_ZERO : MathX.mod(d0, d1)); + + public static final Function POWER = twoDouble(Math::pow); + + public static final Function ROUND = twoDouble(MathX::round); + public static final Function ROUNDDOWN = twoDouble(MathX::roundDown); + public static final Function ROUNDUP = twoDouble(MathX::roundUp); + public static final Function TRUNC = NumericFunction::evaluateTrunc; + + private static ValueEval evaluateTrunc(ValueEval[] args, int srcRowIndex, int srcColumnIndex) { + if (args.length != 1 && args.length != 2) { + return ErrorEval.VALUE_INVALID; + } + try { + double d0 = singleOperandEvaluate(args[0], srcRowIndex, srcColumnIndex); + double d1 = args.length == 1 ? 0 : singleOperandEvaluate(args[1], srcRowIndex, srcColumnIndex); + double result = MathX.roundDown(d0, d1); + checkValue(result); + return new NumberEval(result); + }catch (EvaluationException e) { + return e.getErrorEval(); + } + } + + /* -------------------------------------------------------------------------- */ + + public static final Function LOG = Log::evaluate; static final NumberEval PI_EVAL = new NumberEval(Math.PI); - public static final Function PI = new Fixed0ArgFunction() { - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex) { - return PI_EVAL; + public static final Function PI = NumericFunction::evaluatePI; + + private static ValueEval evaluatePI(ValueEval[] args, int srcRowIndex, int srcColumnIndex) { + return (args.length != 0) ? ErrorEval.VALUE_INVALID : PI_EVAL; + } + + public static final Function RAND = NumericFunction::evaluateRand; + + private static ValueEval evaluateRand(ValueEval[] args, int srcRowIndex, int srcColumnIndex) { + return (args.length != 0) ? ErrorEval.VALUE_INVALID : new NumberEval(Math.random()); + } + + public static final Function POISSON = Poisson::evaluate; + + public static final Function ODD = oneDouble(NumericFunction::evaluateOdd); + + private static double evaluateOdd(double d) { + if (d==0) { + return 1; } - }; - public static final Function RAND = new Fixed0ArgFunction() { - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex) { - return new NumberEval(Math.random()); + double dpm = Math.abs(d)+1; + long x = ((long) dpm) & PARITY_MASK; + return MathX.sign(d) * ((Double.compare(x, dpm) == 0) ? x-1 : x+1); + } + + + public static final Function EVEN = oneDouble(NumericFunction::evaluateEven); + + private static double evaluateEven(double d) { + if (d==0) { + return 0; } - }; - public static final Function POISSON = new Fixed3ArgFunction() { - private static final double DEFAULT_RETURN_RESULT =1; - - /** - * This checks is x = 0 and the mean = 0. - * Excel currently returns the value 1 where as the - * maths common implementation will error. - * @param x The number. - * @param mean The mean. - * @return If a default value should be returned. - */ - private boolean isDefaultResult(double x, double mean) { - - if ( x == 0 && mean == 0 ) { - return true; - } - return false; - } - - private boolean checkArgument(double aDouble) throws EvaluationException { - - NumericFunction.checkValue(aDouble); - - // make sure that the number is positive - if (aDouble < 0) { - throw new EvaluationException(ErrorEval.NUM_ERROR); - } - - return true; - } - - private double probability(int k, double lambda) { - return Math.pow(lambda, k) * Math.exp(-lambda) / factorial(k); - } - - private double cumulativeProbability(int x, double lambda) { - double result = 0; - for(int k = 0; k <= x; k++){ - result += probability(k, lambda); - } - return result; - } - - /** All long-representable factorials */ - private final long[] FACTORIALS = new long[] { - 1l, 1l, 2l, - 6l, 24l, 120l, - 720l, 5040l, 40320l, - 362880l, 3628800l, 39916800l, - 479001600l, 6227020800l, 87178291200l, - 1307674368000l, 20922789888000l, 355687428096000l, - 6402373705728000l, 121645100408832000l, 2432902008176640000l }; + double dpm = Math.abs(d); + long x = ((long) dpm) & PARITY_MASK; + return MathX.sign(d) * ((Double.compare(x, dpm) == 0) ? x : (x + 2)); + } - public long factorial(final int n) { - if (n < 0 || n > 20) { - throw new IllegalArgumentException("Valid argument should be in the range [0..20]"); - } - return FACTORIALS[n]; - } - - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1, ValueEval arg2) { - - // arguments/result for this function - double mean=0; - double x=0; - boolean cumulative = ((BoolEval)arg2).getBooleanValue(); - double result=0; - - try { - x = NumericFunction.singleOperandEvaluate(arg0, srcRowIndex, srcColumnIndex); - mean = NumericFunction.singleOperandEvaluate(arg1, srcRowIndex, srcColumnIndex); - - // check for default result : excel implementation for 0,0 - // is different to Math Common. - if (isDefaultResult(x,mean)) { - return new NumberEval(DEFAULT_RETURN_RESULT); - } - // check the arguments : as per excel function def - checkArgument(x); - checkArgument(mean); - - // truncate x : as per excel function def - if ( cumulative ) { - result = cumulativeProbability((int)x, mean); - } else { - result = probability((int)x, mean); - } - - // check the result - NumericFunction.checkValue(result); + private interface OneDoubleIf { + double apply(double d); + } + private static Function oneDouble(OneDoubleIf doubleFun) { + return (args, srcCellRow, srcCellCol) -> { + if (args.length != 1) { + return VALUE_INVALID; + } + try { + double d = singleOperandEvaluate(args[0], srcCellRow, srcCellCol); + double res = doubleFun.apply(d); + return (Double.isNaN(res) || Double.isInfinite(res)) ? ErrorEval.NUM_ERROR : new NumberEval(res); } catch (EvaluationException e) { return e.getErrorEval(); } + }; + } - return new NumberEval(result); + private interface TwoDoubleIf { + Object apply(double d1, double d2); + } - } - }; + private static Function twoDouble(TwoDoubleIf doubleFun) { + return (args, srcCellRow, srcCellCol) -> { + if (args.length != 2) { + return VALUE_INVALID; + } + try { + double d1 = singleOperandEvaluate(args[0], srcCellRow, srcCellCol); + double d2 = singleOperandEvaluate(args[1], srcCellRow, srcCellCol); + Object res = doubleFun.apply(d1, d2); + if (res instanceof ErrorEval) { + return (ErrorEval)res; + } + assert(res instanceof Double); + double d = (Double)res; + return (Double.isNaN(d) || Double.isInfinite(d)) ? ErrorEval.NUM_ERROR : new NumberEval(d); + } catch (EvaluationException e) { + return e.getErrorEval(); + } + }; + } } diff --git a/poi/src/main/java/org/apache/poi/ss/formula/functions/Odd.java b/poi/src/main/java/org/apache/poi/ss/formula/functions/Odd.java deleted file mode 100644 index 6762fcb5f7..0000000000 --- a/poi/src/main/java/org/apache/poi/ss/formula/functions/Odd.java +++ /dev/null @@ -1,39 +0,0 @@ -/* ==================================================================== - 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.ss.formula.functions; - -/** - * @author Amol S. Deshmukh < amolweb at ya hoo dot com > - * - */ -public final class Odd extends NumericFunction.OneArg { - private static final long PARITY_MASK = 0xFFFFFFFFFFFFFFFEL; - - protected double evaluate(double d) { - if (d==0) { - return 1; - } - return (d>0) ? calcOdd(d) : -calcOdd(-d); - } - - private static long calcOdd(double d) { - double dpm1 = d+1; - long x = ((long) dpm1) & PARITY_MASK; - return ( Double.compare(x, dpm1) == 0 ) ? x-1 : x+1; - } -} diff --git a/poi/src/main/java/org/apache/poi/ss/formula/functions/Poisson.java b/poi/src/main/java/org/apache/poi/ss/formula/functions/Poisson.java new file mode 100644 index 0000000000..8e67a6c5d4 --- /dev/null +++ b/poi/src/main/java/org/apache/poi/ss/formula/functions/Poisson.java @@ -0,0 +1,115 @@ +/* ==================================================================== + 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.ss.formula.functions; + +import org.apache.poi.ss.formula.eval.BoolEval; +import org.apache.poi.ss.formula.eval.ErrorEval; +import org.apache.poi.ss.formula.eval.EvaluationException; +import org.apache.poi.ss.formula.eval.NumberEval; +import org.apache.poi.ss.formula.eval.ValueEval; + +public class Poisson { + + private static final double DEFAULT_RETURN_RESULT =1; + + /** All long-representable factorials */ + private static final long[] FACTORIALS = { + 1L, 1L, 2L, + 6L, 24L, 120L, + 720L, 5040L, 40320L, + 362880L, 3628800L, 39916800L, + 479001600L, 6227020800L, 87178291200L, + 1307674368000L, 20922789888000L, 355687428096000L, + 6402373705728000L, 121645100408832000L, 2432902008176640000L }; + + /** + * This checks is x = 0 and the mean = 0. + * Excel currently returns the value 1 where as the + * maths common implementation will error. + * @param x The number. + * @param mean The mean. + * @return If a default value should be returned. + */ + private static boolean isDefaultResult(double x, double mean) { + return x == 0 && mean == 0; + } + + private static void checkArgument(double aDouble) throws EvaluationException { + NumericFunction.checkValue(aDouble); + + // make sure that the number is positive + if (aDouble < 0) { + throw new EvaluationException(ErrorEval.NUM_ERROR); + } + } + + private static double probability(int k, double lambda) { + return Math.pow(lambda, k) * Math.exp(-lambda) / factorial(k); + } + + private static double cumulativeProbability(int x, double lambda) { + double result = 0; + for(int k = 0; k <= x; k++){ + result += probability(k, lambda); + } + return result; + } + + private static long factorial(final int n) { + if (n < 0 || n > 20) { + throw new IllegalArgumentException("Valid argument should be in the range [0..20]"); + } + return FACTORIALS[n]; + } + + public static ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) { + if (args.length != 3) { + return ErrorEval.VALUE_INVALID; + } + ValueEval arg0 = args[0]; + ValueEval arg1 = args[1]; + ValueEval arg2 = args[2]; + + try { + // arguments/result for this function + double x = NumericFunction.singleOperandEvaluate(arg0, srcRowIndex, srcColumnIndex); + double mean = NumericFunction.singleOperandEvaluate(arg1, srcRowIndex, srcColumnIndex); + + // check for default result : excel implementation for 0,0 + // is different to Math Common. + if (isDefaultResult(x,mean)) { + return new NumberEval(DEFAULT_RETURN_RESULT); + } + // check the arguments : as per excel function def + checkArgument(x); + checkArgument(mean); + + // truncate x : as per excel function def + boolean cumulative = ((BoolEval)arg2).getBooleanValue(); + double result = cumulative ? cumulativeProbability((int) x, mean) : probability((int) x, mean); + + // check the result + NumericFunction.checkValue(result); + + return new NumberEval(result); + } catch (EvaluationException e) { + return e.getErrorEval(); + } + } + +} diff --git a/poi/src/main/java/org/apache/poi/ss/formula/functions/RowFunc.java b/poi/src/main/java/org/apache/poi/ss/formula/functions/RowFunc.java index 17d7acfdfe..b8786f2b0b 100644 --- a/poi/src/main/java/org/apache/poi/ss/formula/functions/RowFunc.java +++ b/poi/src/main/java/org/apache/poi/ss/formula/functions/RowFunc.java @@ -26,18 +26,19 @@ import org.apache.poi.ss.formula.eval.ValueEval; /** * Implementation for the Excel function ROW */ -public final class RowFunc implements Function0Arg, Function1Arg { +public final class RowFunc { + public static ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) { + if (args.length > 1) { + return ErrorEval.VALUE_INVALID; + } - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex) { - return new NumberEval(srcRowIndex+1.); - } - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) { int rnum; - - if (arg0 instanceof AreaEval) { - rnum = ((AreaEval) arg0).getFirstRow(); - } else if (arg0 instanceof RefEval) { - rnum = ((RefEval) arg0).getRow(); + if (args.length == 0) { + rnum = srcRowIndex; + } else if (args[0] instanceof AreaEval) { + rnum = ((AreaEval) args[0]).getFirstRow(); + } else if (args[0] instanceof RefEval) { + rnum = ((RefEval) args[0]).getRow(); } else { // anything else is not valid argument return ErrorEval.VALUE_INVALID; @@ -45,13 +46,4 @@ public final class RowFunc implements Function0Arg, Function1Arg { return new NumberEval(rnum + 1.); } - public ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) { - switch (args.length) { - case 1: - return evaluate(srcRowIndex, srcColumnIndex, args[0]); - case 0: - return new NumberEval(srcRowIndex+1.); - } - return ErrorEval.VALUE_INVALID; - } } diff --git a/poi/src/main/java/org/apache/poi/ss/formula/functions/Today.java b/poi/src/main/java/org/apache/poi/ss/formula/functions/Today.java index 677d1f0e48..5c38a69151 100644 --- a/poi/src/main/java/org/apache/poi/ss/formula/functions/Today.java +++ b/poi/src/main/java/org/apache/poi/ss/formula/functions/Today.java @@ -19,6 +19,7 @@ package org.apache.poi.ss.formula.functions; import java.util.Calendar; +import org.apache.poi.ss.formula.eval.ErrorEval; import org.apache.poi.ss.formula.eval.NumberEval; import org.apache.poi.ss.formula.eval.ValueEval; import org.apache.poi.ss.usermodel.DateUtil; @@ -27,8 +28,11 @@ import org.apache.poi.util.LocaleUtil; /** * Implementation of Excel TODAY() Function
    */ -public final class Today extends Fixed0ArgFunction { - public ValueEval evaluate(int srcRowIndex, int srcColumnIndex) { +public final class Today { + public static ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) { + if (args.length != 0) { + return ErrorEval.VALUE_INVALID; + } Calendar now = LocaleUtil.getLocaleCalendar(); now.clear(Calendar.HOUR); now.set(Calendar.HOUR_OF_DAY,0); diff --git a/poi/src/test/java/org/apache/poi/ss/formula/functions/TestRowCol.java b/poi/src/test/java/org/apache/poi/ss/formula/functions/TestRowCol.java index eb2812e0e4..8250d4bd78 100644 --- a/poi/src/test/java/org/apache/poi/ss/formula/functions/TestRowCol.java +++ b/poi/src/test/java/org/apache/poi/ss/formula/functions/TestRowCol.java @@ -24,14 +24,12 @@ import org.junit.jupiter.api.Test; /** * Tests for ROW(), ROWS(), COLUMN(), COLUMNS() - * - * @author Josh Micich */ final class TestRowCol { @Test void testCol() { - Function target = new Column(); + Function target = Column::evaluate; { ValueEval[] args = { EvalFactory.createRefEval("C5"), }; double actual = NumericFunctionInvoker.invoke(target, args); @@ -46,7 +44,7 @@ final class TestRowCol { @Test void testRow() { - Function target = new RowFunc(); + Function target = RowFunc::evaluate; { ValueEval[] args = { EvalFactory.createRefEval("C5"), }; double actual = NumericFunctionInvoker.invoke(target, args);