You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@poi.apache.org by ki...@apache.org on 2021/04/13 19:44:38 UTC

svn commit: r1888743 - in /poi/trunk/poi/src: main/java/org/apache/poi/ss/formula/eval/ main/java/org/apache/poi/ss/formula/functions/ test/java/org/apache/poi/ss/formula/functions/

Author: kiwiwings
Date: Tue Apr 13 19:44:38 2021
New Revision: 1888743

URL: http://svn.apache.org/viewvc?rev=1888743&view=rev
Log:
replace over engineered inner classes with lambdas/method references

Added:
    poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Log.java   (with props)
    poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Poisson.java   (with props)
Removed:
    poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Even.java
    poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Odd.java
Modified:
    poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/eval/FunctionEval.java
    poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/ArrayFunction.java
    poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/BooleanFunction.java
    poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Column.java
    poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Fixed0ArgFunction.java
    poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/MathX.java
    poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Na.java
    poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Now.java
    poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/NumericFunction.java
    poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/RowFunc.java
    poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Today.java
    poi/trunk/poi/src/test/java/org/apache/poi/ss/formula/functions/TestRowCol.java

Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/eval/FunctionEval.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/eval/FunctionEval.java?rev=1888743&r1=1888742&r2=1888743&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/eval/FunctionEval.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/eval/FunctionEval.java Tue Apr 13 19:44:38 2021
@@ -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

Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/ArrayFunction.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/ArrayFunction.java?rev=1888743&r1=1888742&r2=1888743&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/ArrayFunction.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/ArrayFunction.java Tue Apr 13 19:44:38 2021
@@ -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 <code>null</code>.
+     * {@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 <code>null</code>.
+     * @return The evaluated result, possibly an {@link ErrorEval}, never {@code null}.
      * <b>Note</b> - Excel uses the error code <i>#NUM!</i> instead of IEEE <i>NaN</i>, 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 <code>null</code>
+     *        {@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 <code>null</code>
+     *      @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 <code>null</code>.
+     * @return The evaluated result, possibly an {@link ErrorEval}, never {@code null}.
      * <b>Note</b> - Excel uses the error code <i>#NUM!</i> instead of IEEE <i>NaN</i>, 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<ValueEval, ValueEval, ValueEval> evalFunc) {
+        return _evaluateTwoArrayArgs(arg0, arg1, srcRowIndex, srcColumnIndex, evalFunc);
+    }
+
+    default ValueEval evaluateOneArrayArg(ValueEval arg0, int srcRowIndex, int srcColumnIndex,
+                                          java.util.function.Function<ValueEval, ValueEval> evalFunc) {
+        return _evaluateOneArrayArg(arg0, srcRowIndex, srcColumnIndex, evalFunc);
+    }
+
+    static ValueEval _evaluateTwoArrayArgs(ValueEval arg0, ValueEval arg1, int srcRowIndex, int srcColumnIndex,
+        BiFunction<ValueEval, ValueEval, ValueEval> 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<ValueEval, ValueEval> evalFunc){
+
+    static ValueEval _evaluateOneArrayArg(ValueEval arg0, int srcRowIndex, int srcColumnIndex,
+        java.util.function.Function<ValueEval, ValueEval> 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);
-
     }
 
 }

Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/BooleanFunction.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/BooleanFunction.java?rev=1888743&r1=1888742&r2=1888743&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/BooleanFunction.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/BooleanFunction.java Tue Apr 13 19:44:38 2021
@@ -34,8 +34,6 @@ import org.apache.poi.ss.formula.eval.Va
  * <li> Numbers: 0 is false. Any other number is TRUE </li>
  * <li> Areas: *all* cells in area are evaluated according to the above rules</li>
  * </ol>
- *
- * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
  */
 public abstract class BooleanFunction implements Function,ArrayFunction {
 
@@ -132,43 +130,12 @@ public abstract class BooleanFunction im
 			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 im
 		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<ValueEval, ValueEval> 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

Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Column.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Column.java?rev=1888743&r1=1888742&r2=1888743&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Column.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Column.java Tue Apr 13 19:44:38 2021
@@ -23,18 +23,19 @@ import org.apache.poi.ss.formula.eval.Nu
 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 Fun
 
         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;
-    }
 }

Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Fixed0ArgFunction.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Fixed0ArgFunction.java?rev=1888743&r1=1888742&r2=1888743&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Fixed0ArgFunction.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Fixed0ArgFunction.java Tue Apr 13 19:44:38 2021
@@ -19,12 +19,15 @@ package org.apache.poi.ss.formula.functi
 
 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) {

Added: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Log.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Log.java?rev=1888743&view=auto
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Log.java (added)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Log.java Tue Apr 13 19:44:38 2021
@@ -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();
+        }
+    }
+}

Propchange: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Log.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/MathX.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/MathX.java?rev=1888743&r1=1888742&r2=1888743&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/MathX.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/MathX.java Tue Apr 13 19:44:38 2021
@@ -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:

Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Na.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Na.java?rev=1888743&r1=1888742&r2=1888743&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Na.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Na.java Tue Apr 13 19:44:38 2021
@@ -22,12 +22,9 @@ import org.apache.poi.ss.formula.eval.Va
 
 /**
  * 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;
 	}
 }

Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Now.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Now.java?rev=1888743&r1=1888742&r2=1888743&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Now.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Now.java Tue Apr 13 19:44:38 2021
@@ -19,18 +19,19 @@ package org.apache.poi.ss.formula.functi
 
 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));
 	}

Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/NumericFunction.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/NumericFunction.java?rev=1888743&r1=1888742&r2=1888743&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/NumericFunction.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/NumericFunction.java Tue Apr 13 19:44:38 2021
@@ -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 &lt; amolweb at ya hoo dot com &gt;
- * @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 im
 	}
 
 	/**
-	 * @throws EvaluationException (#NUM!) if <tt>result</tt> is <tt>NaN</tt> or <tt>Infinity</tt>
+	 * @throws EvaluationException (#NUM!) if <tt>result</tt> 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 im
 
 	protected abstract double eval(ValueEval[] args, int srcCellRow, int srcCellCol) throws EvaluationException;
 
-	/* -------------------------------------------------------------------------- */
-	// intermediate sub-classes (one-arg, two-arg and multi-arg)
-
-	public static abstract class OneArg extends Fixed1ArgFunction {
-		protected OneArg() {
-			// no fields to initialise
-		}
-		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;
-	}
-
-	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 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;
+
+	private static ValueEval evaluateDollar(ValueEval[] args, int srcRowIndex, int srcColumnIndex) {
+		if (args.length != 1 && args.length != 2) {
+			return ErrorEval.VALUE_INVALID;
 		}
+		try {
+			double val = singleOperandEvaluate(args[0], srcRowIndex, srcColumnIndex);
+			double d1 = args.length == 1 ? 2.0 : singleOperandEvaluate(args[1], srcRowIndex, srcColumnIndex);
 
-		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);
+		}catch (EvaluationException e) {
+			return e.getErrorEval();
 		}
-	};
-	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 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 = 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 static final Function ATAN2 = twoDouble((d0, d1) ->
+		(d0 == ZERO && d1 == ZERO) ? ErrorEval.DIV_ZERO : Math.atan2(d1, d0)
+	);
 
-		public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) {
-			return evaluate(srcRowIndex, srcColumnIndex, arg0, TRUNC_ARG2_DEFAULT);
-		}
+	public static final Function CEILING = twoDouble(MathX::ceiling);
 
-		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);
-		}
-	};
+	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));
 
-	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 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;
 		}
-		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();
-			}
+		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 = new Log();
+	/* -------------------------------------------------------------------------- */
+
+	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;
+		double dpm = Math.abs(d);
+		long x = ((long) dpm) & PARITY_MASK;
+		return MathX.sign(d) * ((Double.compare(x, dpm) == 0) ? x : (x + 2));
+	}
 
-        /**
-         * 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 };
-
-
-        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();
+			}
+		};
+	}
 }

Added: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Poisson.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Poisson.java?rev=1888743&view=auto
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Poisson.java (added)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Poisson.java Tue Apr 13 19:44:38 2021
@@ -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();
+        }
+    }
+
+}

Propchange: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Poisson.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/RowFunc.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/RowFunc.java?rev=1888743&r1=1888742&r2=1888743&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/RowFunc.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/RowFunc.java Tue Apr 13 19:44:38 2021
@@ -26,18 +26,19 @@ import org.apache.poi.ss.formula.eval.Va
 /**
  * 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 Fu
 
         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;
-    }
 }

Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Today.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Today.java?rev=1888743&r1=1888742&r2=1888743&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Today.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/functions/Today.java Tue Apr 13 19:44:38 2021
@@ -19,6 +19,7 @@ package org.apache.poi.ss.formula.functi
 
 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<br>
  */
-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);

Modified: poi/trunk/poi/src/test/java/org/apache/poi/ss/formula/functions/TestRowCol.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/test/java/org/apache/poi/ss/formula/functions/TestRowCol.java?rev=1888743&r1=1888742&r2=1888743&view=diff
==============================================================================
--- poi/trunk/poi/src/test/java/org/apache/poi/ss/formula/functions/TestRowCol.java (original)
+++ poi/trunk/poi/src/test/java/org/apache/poi/ss/formula/functions/TestRowCol.java Tue Apr 13 19:44:38 2021
@@ -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);



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