diff --git a/docs/content/en/functions/math.md b/docs/content/en/functions/math.md index 4abf34d1d..e0222f3b2 100644 --- a/docs/content/en/functions/math.md +++ b/docs/content/en/functions/math.md @@ -3,7 +3,7 @@ title: Math description: Hugo provides mathematical operators in templates. date: 2017-02-01 publishdate: 2017-02-01 -lastmod: 2023-03-11 +lastmod: 2023-05-15 keywords: [math, operators] categories: [functions] menu: @@ -31,6 +31,7 @@ aliases: [] | | *If one of the numbers is a float, the result is a float.* | `{{ div 6 4.0 }}` → `1.5` | | `mod` | Modulus of two integers. | `{{ mod 15 3 }}` → `0` | | `modBool` | Boolean of modulus of two integers. Evaluates to `true` if result equals 0. | `{{ modBool 15 3 }}` → `true` | +| `math.Abs` | Returns the absolute value of the given number. | `{{ math.Abs -2.1 }}` → `2.1` | | `math.Ceil` | Returns the least integer value greater than or equal to the given number. | `{{ math.Ceil 2.1 }}` → `3` | | `math.Floor` | Returns the greatest integer value less than or equal to the given number. | `{{ math.Floor 1.9 }}` → `1` | | `math.Log` | Returns the natural logarithm of the given number. | `{{ math.Log 42 }}` → `3.737` | diff --git a/tpl/math/init.go b/tpl/math/init.go index 67aa95f41..8596ff647 100644 --- a/tpl/math/init.go +++ b/tpl/math/init.go @@ -31,6 +31,13 @@ func init() { Context: func(cctx context.Context, args ...any) (any, error) { return ctx, nil }, } + ns.AddMethodMapping(ctx.Abs, + nil, + [][2]string{ + {"{{ math.Abs -2.1 }}", "2.1"}, + }, + ) + ns.AddMethodMapping(ctx.Add, []string{"add"}, [][2]string{ diff --git a/tpl/math/math.go b/tpl/math/math.go index 67c6d06c5..d73f212a6 100644 --- a/tpl/math/math.go +++ b/tpl/math/math.go @@ -35,6 +35,16 @@ func New() *Namespace { // Namespace provides template functions for the "math" namespace. type Namespace struct{} +// Abs returns the absolute value of n. +func (ns *Namespace) Abs(n any) (float64, error) { + af, err := cast.ToFloat64E(n) + if err != nil { + return 0, errors.New("the math.Abs function requires a numeric argument") + } + + return math.Abs(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, '+') diff --git a/tpl/math/math_test.go b/tpl/math/math_test.go index 3e83405fd..fad86938d 100644 --- a/tpl/math/math_test.go +++ b/tpl/math/math_test.go @@ -63,6 +63,33 @@ func TestBasicNSArithmetic(t *testing.T) { } } +func TestAbs(t *testing.T) { + t.Parallel() + c := qt.New(t) + ns := New() + + for _, test := range []struct { + x any + expect any + }{ + {0.0, 0.0}, + {1.5, 1.5}, + {-1.5, 1.5}, + {-2, 2.0}, + {"abc", false}, + } { + result, err := ns.Abs(test.x) + + if b, ok := test.expect.(bool); ok && !b { + c.Assert(err, qt.Not(qt.IsNil)) + continue + } + + c.Assert(err, qt.IsNil) + c.Assert(result, qt.Equals, test.expect) + } +} + func TestCeil(t *testing.T) { t.Parallel() c := qt.New(t)