diff options
-rw-r--r-- | calc.go | 78 | ||||
-rw-r--r-- | calc_test.go | 29 |
2 files changed, 107 insertions, 0 deletions
@@ -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", |