diff --git a/src/java/org/apache/poi/ss/formula/atp/AnalysisToolPak.java b/src/java/org/apache/poi/ss/formula/atp/AnalysisToolPak.java
index 1a191b174d..5274b23486 100644
--- a/src/java/org/apache/poi/ss/formula/atp/AnalysisToolPak.java
+++ b/src/java/org/apache/poi/ss/formula/atp/AnalysisToolPak.java
@@ -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
index 0000000000..28c2171869
--- /dev/null
+++ b/src/java/org/apache/poi/ss/formula/functions/FactDouble.java
@@ -0,0 +1,86 @@
+/* ====================================================================
+ 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.OperationEvaluationContext;
+import org.apache.poi.ss.formula.eval.*;
+
+import java.math.BigInteger;
+import java.util.HashMap;
+
+/**
+ * Implementation for Excel FACTDOUBLE() function.
+ *
+ * Syntax:
FACTDOUBLE (number)
+ *
+ * Returns the double factorial of a 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.
+ *
+ * Use a cache for more speed of previously calculated factorial
+ *
+ * @author cedric dot walter @ gmail dot com
+ */
+public class FactDouble extends Fixed1ArgFunction implements FreeRefFunction {
+
+ public static final FreeRefFunction instance = new FactDouble();
+
+ //Caching of previously calculated factorial for speed
+ static HashMap cache = new HashMap();
+
+ public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval numberVE) {
+ int number;
+ try {
+ number = OperandResolver.coerceValueToInt(numberVE);
+ } catch (EvaluationException e) {
+ return ErrorEval.VALUE_INVALID;
+ }
+
+ if (number < 0) {
+ return ErrorEval.NUM_ERROR;
+ }
+
+ return new NumberEval(factorial(number).longValue());
+ }
+
+ public static BigInteger factorial(int n) {
+ if (n == 0 || n < 0) {
+ return BigInteger.ONE;
+ }
+
+ if (cache.containsKey(n)) {
+ return cache.get(n);
+ }
+
+ BigInteger result = BigInteger.valueOf(n).multiply(factorial(n - 2));
+ cache.put(n, result);
+ return result;
+ }
+
+ public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) {
+ if (args.length != 1) {
+ return ErrorEval.VALUE_INVALID;
+ }
+ return evaluate(ec.getRowIndex(), ec.getColumnIndex(), args[0]);
+ }
+}
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
index 0000000000..d56e14df2c
--- /dev/null
+++ b/src/testcases/org/apache/poi/ss/formula/functions/TestFactDoubleFunctionsFromSpreadsheet.java
@@ -0,0 +1,30 @@
+/* ====================================================================
+ 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;
+
+/**
+ * Tests FactDouble() as loaded from a test data spreadsheet.
+ *
+ * @author cedric dot walter @ gmail dot com
+ */
+public class TestFactDoubleFunctionsFromSpreadsheet extends BaseTestFunctionsFromSpreadsheet {
+
+ protected String getFilename() {
+ return "FactDoubleFunctionTestCaseData.xls";
+ }
+}
diff --git a/test-data/spreadsheet/FactDoubleFunctionTestCaseData.xls b/test-data/spreadsheet/FactDoubleFunctionTestCaseData.xls
new file mode 100644
index 0000000000..885acc157f
Binary files /dev/null and b/test-data/spreadsheet/FactDoubleFunctionTestCaseData.xls differ
diff --git a/test-data/spreadsheet/FormulaEvalTestData.xls b/test-data/spreadsheet/FormulaEvalTestData.xls
index df81bc8a78..672febdf1f 100644
Binary files a/test-data/spreadsheet/FormulaEvalTestData.xls and b/test-data/spreadsheet/FormulaEvalTestData.xls differ