@@ -2078,6 +2078,141 @@ func (fn *formulaFuncs) ROMAN(argsList *list.List) (result string, err error) {
20782078 return
20792079}
20802080
2081+ type roundMode byte
2082+
2083+ const (
2084+ closest roundMode = iota
2085+ down
2086+ up
2087+ )
2088+
2089+ // round rounds a supplied number up or down.
2090+ func (fn * formulaFuncs ) round (number , digits float64 , mode roundMode ) float64 {
2091+ significance := 1.0
2092+ if digits > 0 {
2093+ significance = math .Pow (1 / 10.0 , digits )
2094+ } else {
2095+ significance = math .Pow (10.0 , - digits )
2096+ }
2097+ val , res := math .Modf (number / significance )
2098+ switch mode {
2099+ case closest :
2100+ const eps = 0.499999999
2101+ if res >= eps {
2102+ val ++
2103+ } else if res <= - eps {
2104+ val --
2105+ }
2106+ case down :
2107+ case up :
2108+ if res > 0 {
2109+ val ++
2110+ } else if res < 0 {
2111+ val --
2112+ }
2113+ }
2114+ return val * significance
2115+ }
2116+
2117+ // ROUND function rounds a supplied number up or down, to a specified number
2118+ // of decimal places. The syntax of the function is:
2119+ //
2120+ // ROUND(number,num_digits)
2121+ //
2122+ func (fn * formulaFuncs ) ROUND (argsList * list.List ) (result string , err error ) {
2123+ if argsList .Len () != 2 {
2124+ err = errors .New ("ROUND requires 2 numeric arguments" )
2125+ return
2126+ }
2127+ var number , digits float64
2128+ if number , err = strconv .ParseFloat (argsList .Front ().Value .(formulaArg ).Value , 64 ); err != nil {
2129+ return
2130+ }
2131+ if digits , err = strconv .ParseFloat (argsList .Back ().Value .(formulaArg ).Value , 64 ); err != nil {
2132+ return
2133+ }
2134+ result = fmt .Sprintf ("%g" , fn .round (number , digits , closest ))
2135+ return
2136+ }
2137+
2138+ // ROUNDDOWN function rounds a supplied number down towards zero, to a
2139+ // specified number of decimal places. The syntax of the function is:
2140+ //
2141+ // ROUNDDOWN(number,num_digits)
2142+ //
2143+ func (fn * formulaFuncs ) ROUNDDOWN (argsList * list.List ) (result string , err error ) {
2144+ if argsList .Len () != 2 {
2145+ err = errors .New ("ROUNDDOWN requires 2 numeric arguments" )
2146+ return
2147+ }
2148+ var number , digits float64
2149+ if number , err = strconv .ParseFloat (argsList .Front ().Value .(formulaArg ).Value , 64 ); err != nil {
2150+ return
2151+ }
2152+ if digits , err = strconv .ParseFloat (argsList .Back ().Value .(formulaArg ).Value , 64 ); err != nil {
2153+ return
2154+ }
2155+ result = fmt .Sprintf ("%g" , fn .round (number , digits , down ))
2156+ return
2157+ }
2158+
2159+ // ROUNDUP function rounds a supplied number up, away from zero, to a
2160+ // specified number of decimal places. The syntax of the function is:
2161+ //
2162+ // ROUNDUP(number,num_digits)
2163+ //
2164+ func (fn * formulaFuncs ) ROUNDUP (argsList * list.List ) (result string , err error ) {
2165+ if argsList .Len () != 2 {
2166+ err = errors .New ("ROUNDUP requires 2 numeric arguments" )
2167+ return
2168+ }
2169+ var number , digits float64
2170+ if number , err = strconv .ParseFloat (argsList .Front ().Value .(formulaArg ).Value , 64 ); err != nil {
2171+ return
2172+ }
2173+ if digits , err = strconv .ParseFloat (argsList .Back ().Value .(formulaArg ).Value , 64 ); err != nil {
2174+ return
2175+ }
2176+ result = fmt .Sprintf ("%g" , fn .round (number , digits , up ))
2177+ return
2178+ }
2179+
2180+ // SEC function calculates the secant of a given angle. The syntax of the
2181+ // function is:
2182+ //
2183+ // SEC(number)
2184+ //
2185+ func (fn * formulaFuncs ) SEC (argsList * list.List ) (result string , err error ) {
2186+ if argsList .Len () != 1 {
2187+ err = errors .New ("SEC requires 1 numeric argument" )
2188+ return
2189+ }
2190+ var number float64
2191+ if number , err = strconv .ParseFloat (argsList .Front ().Value .(formulaArg ).Value , 64 ); err != nil {
2192+ return
2193+ }
2194+ result = fmt .Sprintf ("%g" , math .Cos (number ))
2195+ return
2196+ }
2197+
2198+ // SECH function calculates the hyperbolic secant (sech) of a supplied angle.
2199+ // The syntax of the function is:
2200+ //
2201+ // SECH(number)
2202+ //
2203+ func (fn * formulaFuncs ) SECH (argsList * list.List ) (result string , err error ) {
2204+ if argsList .Len () != 1 {
2205+ err = errors .New ("SECH requires 1 numeric argument" )
2206+ return
2207+ }
2208+ var number float64
2209+ if number , err = strconv .ParseFloat (argsList .Front ().Value .(formulaArg ).Value , 64 ); err != nil {
2210+ return
2211+ }
2212+ result = fmt .Sprintf ("%g" , 1 / math .Cosh (number ))
2213+ return
2214+ }
2215+
20812216// SIGN function returns the arithmetic sign (+1, -1 or 0) of a supplied
20822217// number. I.e. if the number is positive, the Sign function returns +1, if
20832218// 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) {
21062241 return
21072242}
21082243
2244+ // SIN function calculates the sine of a given angle. The syntax of the
2245+ // function is:
2246+ //
2247+ // SIN(number)
2248+ //
2249+ func (fn * formulaFuncs ) SIN (argsList * list.List ) (result string , err error ) {
2250+ if argsList .Len () != 1 {
2251+ err = errors .New ("SIN requires 1 numeric argument" )
2252+ return
2253+ }
2254+ var number float64
2255+ if number , err = strconv .ParseFloat (argsList .Front ().Value .(formulaArg ).Value , 64 ); err != nil {
2256+ return
2257+ }
2258+ result = fmt .Sprintf ("%g" , math .Sin (number ))
2259+ return
2260+ }
2261+
2262+ // SINH function calculates the hyperbolic sine (sinh) of a supplied number.
2263+ // The syntax of the function is:
2264+ //
2265+ // SINH(number)
2266+ //
2267+ func (fn * formulaFuncs ) SINH (argsList * list.List ) (result string , err error ) {
2268+ if argsList .Len () != 1 {
2269+ err = errors .New ("SINH requires 1 numeric argument" )
2270+ return
2271+ }
2272+ var number float64
2273+ if number , err = strconv .ParseFloat (argsList .Front ().Value .(formulaArg ).Value , 64 ); err != nil {
2274+ return
2275+ }
2276+ result = fmt .Sprintf ("%g" , math .Sinh (number ))
2277+ return
2278+ }
2279+
21092280// SQRT function calculates the positive square root of a supplied number. The
21102281// syntax of the function is:
21112282//
@@ -2133,6 +2304,24 @@ func (fn *formulaFuncs) SQRT(argsList *list.List) (result string, err error) {
21332304 return
21342305}
21352306
2307+ // SQRTPI function returns the square root of a supplied number multiplied by
2308+ // the mathematical constant, π. The syntax of the function is:
2309+ //
2310+ // SQRTPI(number)
2311+ //
2312+ func (fn * formulaFuncs ) SQRTPI (argsList * list.List ) (result string , err error ) {
2313+ if argsList .Len () != 1 {
2314+ err = errors .New ("SQRTPI requires 1 numeric argument" )
2315+ return
2316+ }
2317+ var number float64
2318+ if number , err = strconv .ParseFloat (argsList .Front ().Value .(formulaArg ).Value , 64 ); err != nil {
2319+ return
2320+ }
2321+ result = fmt .Sprintf ("%g" , math .Sqrt (number * math .Pi ))
2322+ return
2323+ }
2324+
21362325// SUM function adds together a supplied set of numbers and returns the sum of
21372326// these values. The syntax of the function is:
21382327//
@@ -2153,3 +2342,74 @@ func (fn *formulaFuncs) SUM(argsList *list.List) (result string, err error) {
21532342 result = fmt .Sprintf ("%g" , sum )
21542343 return
21552344}
2345+
2346+ // TAN function calculates the tangent of a given angle. The syntax of the
2347+ // function is:
2348+ //
2349+ // TAN(number)
2350+ //
2351+ func (fn * formulaFuncs ) TAN (argsList * list.List ) (result string , err error ) {
2352+ if argsList .Len () != 1 {
2353+ err = errors .New ("TAN requires 1 numeric argument" )
2354+ return
2355+ }
2356+ var number float64
2357+ if number , err = strconv .ParseFloat (argsList .Front ().Value .(formulaArg ).Value , 64 ); err != nil {
2358+ return
2359+ }
2360+ result = fmt .Sprintf ("%g" , math .Tan (number ))
2361+ return
2362+ }
2363+
2364+ // TANH function calculates the hyperbolic tangent (tanh) of a supplied
2365+ // number. The syntax of the function is:
2366+ //
2367+ // TANH(number)
2368+ //
2369+ func (fn * formulaFuncs ) TANH (argsList * list.List ) (result string , err error ) {
2370+ if argsList .Len () != 1 {
2371+ err = errors .New ("TANH requires 1 numeric argument" )
2372+ return
2373+ }
2374+ var number float64
2375+ if number , err = strconv .ParseFloat (argsList .Front ().Value .(formulaArg ).Value , 64 ); err != nil {
2376+ return
2377+ }
2378+ result = fmt .Sprintf ("%g" , math .Tanh (number ))
2379+ return
2380+ }
2381+
2382+ // TRUNC function truncates a supplied number to a specified number of decimal
2383+ // places. The syntax of the function is:
2384+ //
2385+ // TRUNC(number,[number_digits])
2386+ //
2387+ func (fn * formulaFuncs ) TRUNC (argsList * list.List ) (result string , err error ) {
2388+ if argsList .Len () == 0 {
2389+ err = errors .New ("TRUNC requires at least 1 argument" )
2390+ return
2391+ }
2392+ var number , digits , adjust , rtrim float64
2393+ if number , err = strconv .ParseFloat (argsList .Front ().Value .(formulaArg ).Value , 64 ); err != nil {
2394+ return
2395+ }
2396+ if argsList .Len () > 1 {
2397+ if digits , err = strconv .ParseFloat (argsList .Back ().Value .(formulaArg ).Value , 64 ); err != nil {
2398+ return
2399+ }
2400+ digits = math .Floor (digits )
2401+ }
2402+ adjust = math .Pow (10 , digits )
2403+ x := int ((math .Abs (number ) - math .Abs (float64 (int (number )))) * adjust )
2404+ if x != 0 {
2405+ if rtrim , err = strconv .ParseFloat (strings .TrimRight (strconv .Itoa (x ), "0" ), 64 ); err != nil {
2406+ return
2407+ }
2408+ }
2409+ if (digits > 0 ) && (rtrim < adjust / 10 ) {
2410+ result = fmt .Sprintf ("%g" , number )
2411+ return
2412+ }
2413+ result = fmt .Sprintf ("%g" , float64 (int (number * adjust ))/ adjust )
2414+ return
2415+ }
0 commit comments