math: Add trigonometric functions and some angle helper functions

This commit adds these new template functions in the `math` namespace:

math.Acos
math.Asin
math.Atan
math.Atan2
math.Cos
math.Pi
math.Sin
math.Tan
math.ToDegrees
math.ToRadians

Co-authored-by: Joe Mooring <joe@mooring.com>
This commit is contained in:
raoulb
2024-07-29 11:05:36 +02:00
committed by GitHub
parent 0e00561620
commit 9d2b5f98d0
14 changed files with 933 additions and 54 deletions

View File

@@ -49,11 +49,51 @@ func (ns *Namespace) Abs(n any) (float64, error) {
return math.Abs(af), nil
}
// Acos returns the arccosine, in radians, of n.
func (ns *Namespace) Acos(n any) (float64, error) {
af, err := cast.ToFloat64E(n)
if err != nil {
return 0, errors.New("requires a numeric argument")
}
return math.Acos(af), nil
}
// Add adds the multivalued addends n1 and n2 or more values.
func (ns *Namespace) Add(inputs ...any) (any, error) {
return ns.doArithmetic(inputs, '+')
}
// Asin returns the arcsine, in radians, of n.
func (ns *Namespace) Asin(n any) (float64, error) {
af, err := cast.ToFloat64E(n)
if err != nil {
return 0, errors.New("requires a numeric argument")
}
return math.Asin(af), nil
}
// Atan returns the arctangent, in radians, of n.
func (ns *Namespace) Atan(n any) (float64, error) {
af, err := cast.ToFloat64E(n)
if err != nil {
return 0, errors.New("requires a numeric argument")
}
return math.Atan(af), nil
}
// Atan2 returns the arc tangent of n/m, using the signs of the two to determine the quadrant of the return value.
func (ns *Namespace) Atan2(n, m any) (float64, error) {
afx, err := cast.ToFloat64E(n)
if err != nil {
return 0, errors.New("requires numeric arguments")
}
afy, err := cast.ToFloat64E(m)
if err != nil {
return 0, errors.New("requires numeric arguments")
}
return math.Atan2(afx, afy), nil
}
// Ceil returns the least integer value greater than or equal to n.
func (ns *Namespace) Ceil(n any) (float64, error) {
xf, err := cast.ToFloat64E(n)
@@ -64,6 +104,15 @@ func (ns *Namespace) Ceil(n any) (float64, error) {
return math.Ceil(xf), nil
}
// Cos returns the cosine of the radian argument n.
func (ns *Namespace) Cos(n any) (float64, error) {
af, err := cast.ToFloat64E(n)
if err != nil {
return 0, errors.New("requires a numeric argument")
}
return math.Cos(af), nil
}
// Div divides n1 by n2.
func (ns *Namespace) Div(inputs ...any) (any, error) {
return ns.doArithmetic(inputs, '/')
@@ -99,22 +148,6 @@ func (ns *Namespace) Min(inputs ...any) (minimum float64, err error) {
return ns.applyOpToScalarsOrSlices("Min", math.Min, inputs...)
}
// Sum returns the sum of all numbers in inputs. Any slices in inputs are flattened.
func (ns *Namespace) Sum(inputs ...any) (sum float64, err error) {
fn := func(x, y float64) float64 {
return x + y
}
return ns.applyOpToScalarsOrSlices("Sum", fn, inputs...)
}
// Product returns the product of all numbers in inputs. Any slices in inputs are flattened.
func (ns *Namespace) Product(inputs ...any) (product float64, err error) {
fn := func(x, y float64) float64 {
return x * y
}
return ns.applyOpToScalarsOrSlices("Product", fn, inputs...)
}
// Mod returns n1 % n2.
func (ns *Namespace) Mod(n1, n2 any) (int64, error) {
ai, erra := cast.ToInt64E(n1)
@@ -146,6 +179,11 @@ func (ns *Namespace) Mul(inputs ...any) (any, error) {
return ns.doArithmetic(inputs, '*')
}
// Pi returns the mathematical constant pi.
func (ns *Namespace) Pi() float64 {
return math.Pi
}
// Pow returns n1 raised to the power of n2.
func (ns *Namespace) Pow(n1, n2 any) (float64, error) {
af, erra := cast.ToFloat64E(n1)
@@ -158,6 +196,14 @@ func (ns *Namespace) Pow(n1, n2 any) (float64, error) {
return math.Pow(af, bf), nil
}
// Product returns the product of all numbers in inputs. Any slices in inputs are flattened.
func (ns *Namespace) Product(inputs ...any) (product float64, err error) {
fn := func(x, y float64) float64 {
return x * y
}
return ns.applyOpToScalarsOrSlices("Product", fn, inputs...)
}
// Rand returns, as a float64, a pseudo-random number in the half-open interval [0.0,1.0).
func (ns *Namespace) Rand() float64 {
return rand.Float64()
@@ -173,6 +219,15 @@ func (ns *Namespace) Round(n any) (float64, error) {
return _round(xf), nil
}
// Sin returns the sine of the radian argument n.
func (ns *Namespace) Sin(n any) (float64, error) {
af, err := cast.ToFloat64E(n)
if err != nil {
return 0, errors.New("requires a numeric argument")
}
return math.Sin(af), nil
}
// Sqrt returns the square root of the number n.
func (ns *Namespace) Sqrt(n any) (float64, error) {
af, err := cast.ToFloat64E(n)
@@ -188,6 +243,43 @@ func (ns *Namespace) Sub(inputs ...any) (any, error) {
return ns.doArithmetic(inputs, '-')
}
// Sum returns the sum of all numbers in inputs. Any slices in inputs are flattened.
func (ns *Namespace) Sum(inputs ...any) (sum float64, err error) {
fn := func(x, y float64) float64 {
return x + y
}
return ns.applyOpToScalarsOrSlices("Sum", fn, inputs...)
}
// Tan returns the tangent of the radian argument n.
func (ns *Namespace) Tan(n any) (float64, error) {
af, err := cast.ToFloat64E(n)
if err != nil {
return 0, errors.New("requires a numeric argument")
}
return math.Tan(af), nil
}
// ToDegrees converts radians into degrees.
func (ns *Namespace) ToDegrees(n any) (float64, error) {
af, err := cast.ToFloat64E(n)
if err != nil {
return 0, errors.New("requires a numeric argument")
}
return af * 180 / math.Pi, nil
}
// ToRadians converts degrees into radians.
func (ns *Namespace) ToRadians(n any) (float64, error) {
af, err := cast.ToFloat64E(n)
if err != nil {
return 0, errors.New("requires a numeric argument")
}
return af * math.Pi / 180, nil
}
func (ns *Namespace) applyOpToScalarsOrSlices(opName string, op func(x, y float64) float64, inputs ...any) (result float64, err error) {
var i int
var hasValue bool