summaryrefslogtreecommitdiff
path: root/calc.go
diff options
context:
space:
mode:
Diffstat (limited to 'calc.go')
-rw-r--r--calc.go260
1 files changed, 260 insertions, 0 deletions
diff --git a/calc.go b/calc.go
index fb94e27..cc39ba5 100644
--- a/calc.go
+++ b/calc.go
@@ -2078,6 +2078,141 @@ func (fn *formulaFuncs) ROMAN(argsList *list.List) (result string, err error) {
return
}
+type roundMode byte
+
+const (
+ closest roundMode = iota
+ down
+ up
+)
+
+// round rounds a supplied number up or down.
+func (fn *formulaFuncs) round(number, digits float64, mode roundMode) float64 {
+ significance := 1.0
+ if digits > 0 {
+ significance = math.Pow(1/10.0, digits)
+ } else {
+ significance = math.Pow(10.0, -digits)
+ }
+ val, res := math.Modf(number / significance)
+ switch mode {
+ case closest:
+ const eps = 0.499999999
+ if res >= eps {
+ val++
+ } else if res <= -eps {
+ val--
+ }
+ case down:
+ case up:
+ if res > 0 {
+ val++
+ } else if res < 0 {
+ val--
+ }
+ }
+ return val * significance
+}
+
+// ROUND function rounds a supplied number up or down, to a specified number
+// of decimal places. The syntax of the function is:
+//
+// ROUND(number,num_digits)
+//
+func (fn *formulaFuncs) ROUND(argsList *list.List) (result string, err error) {
+ if argsList.Len() != 2 {
+ err = errors.New("ROUND requires 2 numeric arguments")
+ return
+ }
+ var number, digits float64
+ if number, err = strconv.ParseFloat(argsList.Front().Value.(formulaArg).Value, 64); err != nil {
+ return
+ }
+ if digits, err = strconv.ParseFloat(argsList.Back().Value.(formulaArg).Value, 64); err != nil {
+ return
+ }
+ result = fmt.Sprintf("%g", fn.round(number, digits, closest))
+ return
+}
+
+// ROUNDDOWN function rounds a supplied number down towards zero, to a
+// specified number of decimal places. The syntax of the function is:
+//
+// ROUNDDOWN(number,num_digits)
+//
+func (fn *formulaFuncs) ROUNDDOWN(argsList *list.List) (result string, err error) {
+ if argsList.Len() != 2 {
+ err = errors.New("ROUNDDOWN requires 2 numeric arguments")
+ return
+ }
+ var number, digits float64
+ if number, err = strconv.ParseFloat(argsList.Front().Value.(formulaArg).Value, 64); err != nil {
+ return
+ }
+ if digits, err = strconv.ParseFloat(argsList.Back().Value.(formulaArg).Value, 64); err != nil {
+ return
+ }
+ result = fmt.Sprintf("%g", fn.round(number, digits, down))
+ return
+}
+
+// ROUNDUP function rounds a supplied number up, away from zero, to a
+// specified number of decimal places. The syntax of the function is:
+//
+// ROUNDUP(number,num_digits)
+//
+func (fn *formulaFuncs) ROUNDUP(argsList *list.List) (result string, err error) {
+ if argsList.Len() != 2 {
+ err = errors.New("ROUNDUP requires 2 numeric arguments")
+ return
+ }
+ var number, digits float64
+ if number, err = strconv.ParseFloat(argsList.Front().Value.(formulaArg).Value, 64); err != nil {
+ return
+ }
+ if digits, err = strconv.ParseFloat(argsList.Back().Value.(formulaArg).Value, 64); err != nil {
+ return
+ }
+ result = fmt.Sprintf("%g", fn.round(number, digits, up))
+ return
+}
+
+// SEC function calculates the secant of a given angle. The syntax of the
+// function is:
+//
+// SEC(number)
+//
+func (fn *formulaFuncs) SEC(argsList *list.List) (result string, err error) {
+ if argsList.Len() != 1 {
+ err = errors.New("SEC requires 1 numeric argument")
+ return
+ }
+ var number float64
+ if number, err = strconv.ParseFloat(argsList.Front().Value.(formulaArg).Value, 64); err != nil {
+ return
+ }
+ result = fmt.Sprintf("%g", math.Cos(number))
+ return
+}
+
+// SECH function calculates the hyperbolic secant (sech) of a supplied angle.
+// The syntax of the function is:
+//
+// SECH(number)
+//
+func (fn *formulaFuncs) SECH(argsList *list.List) (result string, err error) {
+ if argsList.Len() != 1 {
+ err = errors.New("SECH requires 1 numeric argument")
+ return
+ }
+ var number float64
+ if number, err = strconv.ParseFloat(argsList.Front().Value.(formulaArg).Value, 64); err != nil {
+ return
+ }
+ result = fmt.Sprintf("%g", 1/math.Cosh(number))
+ return
+}
+
// SIGN function returns the arithmetic sign (+1, -1 or 0) of a supplied
// number. I.e. if the number is positive, the Sign function returns +1, if
// the number is negative, the function returns -1 and if the number is 0
@@ -2106,6 +2241,42 @@ func (fn *formulaFuncs) SIGN(argsList *list.List) (result string, err error) {
return
}
+// SIN function calculates the sine of a given angle. The syntax of the
+// function is:
+//
+// SIN(number)
+//
+func (fn *formulaFuncs) SIN(argsList *list.List) (result string, err error) {
+ if argsList.Len() != 1 {
+ err = errors.New("SIN requires 1 numeric argument")
+ return
+ }
+ var number float64
+ if number, err = strconv.ParseFloat(argsList.Front().Value.(formulaArg).Value, 64); err != nil {
+ return
+ }
+ result = fmt.Sprintf("%g", math.Sin(number))
+ return
+}
+
+// SINH function calculates the hyperbolic sine (sinh) of a supplied number.
+// The syntax of the function is:
+//
+// SINH(number)
+//
+func (fn *formulaFuncs) SINH(argsList *list.List) (result string, err error) {
+ if argsList.Len() != 1 {
+ err = errors.New("SINH requires 1 numeric argument")
+ return
+ }
+ var number float64
+ if number, err = strconv.ParseFloat(argsList.Front().Value.(formulaArg).Value, 64); err != nil {
+ return
+ }
+ result = fmt.Sprintf("%g", math.Sinh(number))
+ return
+}
+
// SQRT function calculates the positive square root of a supplied number. The
// syntax of the function is:
//
@@ -2133,6 +2304,24 @@ func (fn *formulaFuncs) SQRT(argsList *list.List) (result string, err error) {
return
}
+// SQRTPI function returns the square root of a supplied number multiplied by
+// the mathematical constant, π. The syntax of the function is:
+//
+// SQRTPI(number)
+//
+func (fn *formulaFuncs) SQRTPI(argsList *list.List) (result string, err error) {
+ if argsList.Len() != 1 {
+ err = errors.New("SQRTPI requires 1 numeric argument")
+ return
+ }
+ var number float64
+ if number, err = strconv.ParseFloat(argsList.Front().Value.(formulaArg).Value, 64); err != nil {
+ return
+ }
+ result = fmt.Sprintf("%g", math.Sqrt(number*math.Pi))
+ return
+}
+
// SUM function adds together a supplied set of numbers and returns the sum of
// these values. The syntax of the function is:
//
@@ -2153,3 +2342,74 @@ func (fn *formulaFuncs) SUM(argsList *list.List) (result string, err error) {
result = fmt.Sprintf("%g", sum)
return
}
+
+// TAN function calculates the tangent of a given angle. The syntax of the
+// function is:
+//
+// TAN(number)
+//
+func (fn *formulaFuncs) TAN(argsList *list.List) (result string, err error) {
+ if argsList.Len() != 1 {
+ err = errors.New("TAN requires 1 numeric argument")
+ return
+ }
+ var number float64
+ if number, err = strconv.ParseFloat(argsList.Front().Value.(formulaArg).Value, 64); err != nil {
+ return
+ }
+ result = fmt.Sprintf("%g", math.Tan(number))
+ return
+}
+
+// TANH function calculates the hyperbolic tangent (tanh) of a supplied
+// number. The syntax of the function is:
+//
+// TANH(number)
+//
+func (fn *formulaFuncs) TANH(argsList *list.List) (result string, err error) {
+ if argsList.Len() != 1 {
+ err = errors.New("TANH requires 1 numeric argument")
+ return
+ }
+ var number float64
+ if number, err = strconv.ParseFloat(argsList.Front().Value.(formulaArg).Value, 64); err != nil {
+ return
+ }
+ result = fmt.Sprintf("%g", math.Tanh(number))
+ return
+}
+
+// TRUNC function truncates a supplied number to a specified number of decimal
+// places. The syntax of the function is:
+//
+// TRUNC(number,[number_digits])
+//
+func (fn *formulaFuncs) TRUNC(argsList *list.List) (result string, err error) {
+ if argsList.Len() == 0 {
+ err = errors.New("TRUNC requires at least 1 argument")
+ return
+ }
+ var number, digits, adjust, rtrim float64
+ if number, err = strconv.ParseFloat(argsList.Front().Value.(formulaArg).Value, 64); err != nil {
+ return
+ }
+ if argsList.Len() > 1 {
+ if digits, err = strconv.ParseFloat(argsList.Back().Value.(formulaArg).Value, 64); err != nil {
+ return
+ }
+ digits = math.Floor(digits)
+ }
+ adjust = math.Pow(10, digits)
+ x := int((math.Abs(number) - math.Abs(float64(int(number)))) * adjust)
+ if x != 0 {
+ if rtrim, err = strconv.ParseFloat(strings.TrimRight(strconv.Itoa(x), "0"), 64); err != nil {
+ return
+ }
+ }
+ if (digits > 0) && (rtrim < adjust/10) {
+ result = fmt.Sprintf("%g", number)
+ return
+ }
+ result = fmt.Sprintf("%g", float64(int(number*adjust))/adjust)
+ return
+}