]> source.dussan.org Git - poi.git/commitdiff
Bug 55058: patch for missing function FactDouble
authorCédric Walter <cedricwalter@apache.org>
Thu, 10 Oct 2013 10:10:54 +0000 (10:10 +0000)
committerCédric Walter <cedricwalter@apache.org>
Thu, 10 Oct 2013 10:10:54 +0000 (10:10 +0000)
Returns the double factorial of a number: FACTDOUBLE(number)

Number     is the value for which to return the double factorial. If number is not an integer, it is truncated.

Remarks
If number is nonnumeric, FACTDOUBLE returns the #VALUE! error value.
If number is negative, FACTDOUBLE returns the #NUM! error value.

Has  a cache for more speed of previously calculated factorial
Add additional sanity check/integration test FormulaEvalTestData.xls

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1530907 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/poi/ss/formula/atp/AnalysisToolPak.java
src/java/org/apache/poi/ss/formula/functions/FactDouble.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/formula/functions/TestFactDoubleFunctionsFromSpreadsheet.java [new file with mode: 0644]
test-data/spreadsheet/FactDoubleFunctionTestCaseData.xls [new file with mode: 0644]
test-data/spreadsheet/FormulaEvalTestData.xls

index 1a191b174d8c8f1cd5e8558e40b3bbaeff73e7ce..5274b234868c6252a5f6c1812611962432794a9b 100644 (file)
@@ -101,7 +101,7 @@ public final class AnalysisToolPak implements UDFFinder {
         r(m, "EOMONTH", null);
         r(m, "ERF", null);
         r(m, "ERFC", null);
-        r(m, "FACTDOUBLE", null);
+        r(m, "FACTDOUBLE", FactDouble.instance);
         r(m, "FVSCHEDULE", null);
         r(m, "GCD", null);
         r(m, "GESTEP", null);
diff --git a/src/java/org/apache/poi/ss/formula/functions/FactDouble.java b/src/java/org/apache/poi/ss/formula/functions/FactDouble.java
new file mode 100644 (file)
index 0000000..28c2171
--- /dev/null
@@ -0,0 +1,86 @@
+/* ====================================================================\r
+   Licensed to the Apache Software Foundation (ASF) under one or more\r
+   contributor license agreements.  See the NOTICE file distributed with\r
+   this work for additional information regarding copyright ownership.\r
+   The ASF licenses this file to You under the Apache License, Version 2.0\r
+   (the "License"); you may not use this file except in compliance with\r
+   the License.  You may obtain a copy of the License at\r
+\r
+       http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+   Unless required by applicable law or agreed to in writing, software\r
+   distributed under the License is distributed on an "AS IS" BASIS,\r
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+   See the License for the specific language governing permissions and\r
+   limitations under the License.\r
+==================================================================== */\r
+\r
+package org.apache.poi.ss.formula.functions;\r
+\r
+import org.apache.poi.ss.formula.OperationEvaluationContext;\r
+import org.apache.poi.ss.formula.eval.*;\r
+\r
+import java.math.BigInteger;\r
+import java.util.HashMap;\r
+\r
+/**\r
+ * Implementation for Excel FACTDOUBLE() function.<p/>\r
+ * <p/>\r
+ * <b>Syntax</b>:<br/> <b>FACTDOUBLE  </b>(<b>number</b>)<br/>\r
+ * <p/>\r
+ * Returns the double factorial of a number.\r
+ * <p/>\r
+ * Number is the value for which to return the double factorial. If number is not an integer, it is truncated.\r
+ * <p/>\r
+ * Remarks\r
+ * <ul>\r
+ * <li>If number is nonnumeric, FACTDOUBLE returns the #VALUE! error value.</li>\r
+ * <li>If number is negative, FACTDOUBLE returns the #NUM! error value.</li>\r
+ * </ul>\r
+ * Use a cache for more speed of previously calculated factorial\r
+ *\r
+ * @author cedric dot walter @ gmail dot com\r
+ */\r
+public class FactDouble extends Fixed1ArgFunction implements FreeRefFunction {\r
+\r
+    public static final FreeRefFunction instance = new FactDouble();\r
+\r
+    //Caching of previously calculated factorial for speed\r
+    static HashMap<Integer, BigInteger> cache = new HashMap<Integer, BigInteger>();\r
+\r
+    public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval numberVE) {\r
+        int number;\r
+        try {\r
+            number = OperandResolver.coerceValueToInt(numberVE);\r
+        } catch (EvaluationException e) {\r
+            return ErrorEval.VALUE_INVALID;\r
+        }\r
+\r
+        if (number < 0) {\r
+            return ErrorEval.NUM_ERROR;\r
+        }\r
+\r
+        return new NumberEval(factorial(number).longValue());\r
+    }\r
+\r
+    public static BigInteger factorial(int n) {\r
+        if (n == 0 || n < 0) {\r
+            return BigInteger.ONE;\r
+        }\r
+\r
+        if (cache.containsKey(n))  {\r
+            return cache.get(n);\r
+        }\r
+\r
+        BigInteger result = BigInteger.valueOf(n).multiply(factorial(n - 2));\r
+        cache.put(n, result);\r
+        return result;\r
+    }\r
+\r
+    public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) {\r
+        if (args.length != 1) {\r
+            return ErrorEval.VALUE_INVALID;\r
+        }\r
+        return evaluate(ec.getRowIndex(), ec.getColumnIndex(), args[0]);\r
+    }\r
+}\r
diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestFactDoubleFunctionsFromSpreadsheet.java b/src/testcases/org/apache/poi/ss/formula/functions/TestFactDoubleFunctionsFromSpreadsheet.java
new file mode 100644 (file)
index 0000000..d56e14d
--- /dev/null
@@ -0,0 +1,30 @@
+/* ====================================================================\r
+   Licensed to the Apache Software Foundation (ASF) under one or more\r
+   contributor license agreements.  See the NOTICE file distributed with\r
+   this work for additional information regarding copyright ownership.\r
+   The ASF licenses this file to You under the Apache License, Version 2.0\r
+   (the "License"); you may not use this file except in compliance with\r
+   the License.  You may obtain a copy of the License at\r
+\r
+       http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+   Unless required by applicable law or agreed to in writing, software\r
+   distributed under the License is distributed on an "AS IS" BASIS,\r
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+   See the License for the specific language governing permissions and\r
+   limitations under the License.\r
+==================================================================== */\r
+\r
+package org.apache.poi.ss.formula.functions;\r
+\r
+/**\r
+ * Tests FactDouble() as loaded from a test data spreadsheet.<p/>\r
+ *\r
+ * @author cedric dot walter @ gmail dot com\r
+ */\r
+public class TestFactDoubleFunctionsFromSpreadsheet extends BaseTestFunctionsFromSpreadsheet {\r
+\r
+    protected String getFilename() {\r
+        return "FactDoubleFunctionTestCaseData.xls";\r
+    }\r
+}\r
diff --git a/test-data/spreadsheet/FactDoubleFunctionTestCaseData.xls b/test-data/spreadsheet/FactDoubleFunctionTestCaseData.xls
new file mode 100644 (file)
index 0000000..885acc1
Binary files /dev/null and b/test-data/spreadsheet/FactDoubleFunctionTestCaseData.xls differ
index df81bc8a78f2b08e0e17ea7794fd86cc234fe20c..672febdf1fe37b428a64402720cb402346d39623 100644 (file)
Binary files a/test-data/spreadsheet/FormulaEvalTestData.xls and b/test-data/spreadsheet/FormulaEvalTestData.xls differ