summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--calc.go78
-rw-r--r--calc_test.go29
2 files changed, 107 insertions, 0 deletions
diff --git a/calc.go b/calc.go
index 9ba6626..eac0f6c 100644
--- a/calc.go
+++ b/calc.go
@@ -373,6 +373,10 @@ type formulaFuncs struct {
// DOLLARFR
// EFFECT
// ENCODEURL
+// ERF
+// ERF.PRECISE
+// ERFC
+// ERFC.PRECISE
// EVEN
// EXACT
// EXP
@@ -2003,6 +2007,80 @@ func (fn *formulaFuncs) DELTA(argsList *list.List) formulaArg {
return newBoolFormulaArg(number1.Number == number2.Number).ToNumber()
}
+// ERF function calculates the Error Function, integrated between two supplied
+// limits. The syntax of the function is:
+//
+// ERF(lower_limit,[upper_limit])
+//
+func (fn *formulaFuncs) ERF(argsList *list.List) formulaArg {
+ if argsList.Len() < 1 {
+ return newErrorFormulaArg(formulaErrorVALUE, "ERF requires at least 1 argument")
+ }
+ if argsList.Len() > 2 {
+ return newErrorFormulaArg(formulaErrorVALUE, "ERF allows at most 2 arguments")
+ }
+ lower := argsList.Front().Value.(formulaArg).ToNumber()
+ if lower.Type != ArgNumber {
+ return lower
+ }
+ if argsList.Len() == 2 {
+ upper := argsList.Back().Value.(formulaArg).ToNumber()
+ if upper.Type != ArgNumber {
+ return upper
+ }
+ return newNumberFormulaArg(math.Erf(upper.Number) - math.Erf(lower.Number))
+ }
+ return newNumberFormulaArg(math.Erf(lower.Number))
+}
+
+// ERFdotPRECISE function calculates the Error Function, integrated between a
+// supplied lower or upper limit and 0. The syntax of the function is:
+//
+// ERF.PRECISE(x)
+//
+func (fn *formulaFuncs) ERFdotPRECISE(argsList *list.List) formulaArg {
+ if argsList.Len() != 1 {
+ return newErrorFormulaArg(formulaErrorVALUE, "ERF.PRECISE requires 1 argument")
+ }
+ x := argsList.Front().Value.(formulaArg).ToNumber()
+ if x.Type != ArgNumber {
+ return x
+ }
+ return newNumberFormulaArg(math.Erf(x.Number))
+}
+
+// erfc is an implementation of the formula functions ERFC and ERFC.PRECISE.
+func (fn *formulaFuncs) erfc(name string, argsList *list.List) formulaArg {
+ if argsList.Len() != 1 {
+ return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s requires 1 argument", name))
+ }
+ x := argsList.Front().Value.(formulaArg).ToNumber()
+ if x.Type != ArgNumber {
+ return x
+ }
+ return newNumberFormulaArg(math.Erfc(x.Number))
+}
+
+// ERFC function calculates the Complementary Error Function, integrated
+// between a supplied lower limit and infinity. The syntax of the function
+// is:
+//
+// ERFC(x)
+//
+func (fn *formulaFuncs) ERFC(argsList *list.List) formulaArg {
+ return fn.erfc("ERFC", argsList)
+}
+
+// ERFC.PRECISE function calculates the Complementary Error Function,
+// integrated between a supplied lower limit and infinity. The syntax of the
+// function is:
+//
+// ERFC(x)
+//
+func (fn *formulaFuncs) ERFCdotPRECISE(argsList *list.List) formulaArg {
+ return fn.erfc("ERFC.PRECISE", argsList)
+}
+
// GESTEP unction tests whether a supplied number is greater than a supplied
// step size and returns. The syntax of the function is:
//
diff --git a/calc_test.go b/calc_test.go
index 88c58a6..b2fd5f4 100644
--- a/calc_test.go
+++ b/calc_test.go
@@ -143,6 +143,21 @@ func TestCalcCellValue(t *testing.T) {
"=DELTA(1.23,1.23)": "1",
"=DELTA(1)": "0",
"=DELTA(0)": "1",
+ // ERF
+ "=ERF(1.5)": "0.966105146475311",
+ "=ERF(0,1.5)": "0.966105146475311",
+ "=ERF(1,2)": "0.152621472069238",
+ // ERF.PRECISE
+ "=ERF.PRECISE(-1)": "-0.842700792949715",
+ "=ERF.PRECISE(1.5)": "0.966105146475311",
+ // ERFC
+ "=ERFC(0)": "1",
+ "=ERFC(0.5)": "0.479500122186953",
+ "=ERFC(-1)": "1.84270079294971",
+ // ERFC.PRECISE
+ "=ERFC.PRECISE(0)": "1",
+ "=ERFC.PRECISE(0.5)": "0.479500122186953",
+ "=ERFC.PRECISE(-1)": "1.84270079294971",
// GESTEP
"=GESTEP(1.2,0.001)": "1",
"=GESTEP(0.05,0.05)": "1",
@@ -1578,6 +1593,20 @@ func TestCalcCellValue(t *testing.T) {
"=DELTA(0,0,0)": "DELTA allows at most 2 arguments",
"=DELTA(\"\",0)": "strconv.ParseFloat: parsing \"\": invalid syntax",
"=DELTA(0,\"\")": "strconv.ParseFloat: parsing \"\": invalid syntax",
+ // ERF
+ "=ERF()": "ERF requires at least 1 argument",
+ "=ERF(0,0,0)": "ERF allows at most 2 arguments",
+ "=ERF(\"\",0)": "strconv.ParseFloat: parsing \"\": invalid syntax",
+ "=ERF(0,\"\")": "strconv.ParseFloat: parsing \"\": invalid syntax",
+ // ERF.PRECISE
+ "=ERF.PRECISE()": "ERF.PRECISE requires 1 argument",
+ "=ERF.PRECISE(\"\")": "strconv.ParseFloat: parsing \"\": invalid syntax",
+ // ERFC
+ "=ERFC()": "ERFC requires 1 argument",
+ "=ERFC(\"\")": "strconv.ParseFloat: parsing \"\": invalid syntax",
+ // ERFC.PRECISE
+ "=ERFC.PRECISE()": "ERFC.PRECISE requires 1 argument",
+ "=ERFC.PRECISE(\"\")": "strconv.ParseFloat: parsing \"\": invalid syntax",
// GESTEP
"=GESTEP()": "GESTEP requires at least 1 argument",
"=GESTEP(0,0,0)": "GESTEP allows at most 2 arguments",