shithub: hugo

Download patch

ref: 991934497e88dcd4134a369a213bb5072c51c139
parent: 558c09305e2be16953238c6c0e828f62b950e4f5
author: Joe Mooring <joe.mooring@veriphor.com>
date: Wed May 13 09:35:07 EDT 2020

Add math.Pow

Closes #7266

--- a/docs/content/en/functions/math.md
+++ b/docs/content/en/functions/math.md
@@ -38,4 +38,4 @@
 | `math.Round` | Returns the nearest integer, rounding half away from zero.                  | `{{math.Round 1.5}}` &rarr; `2`  |
 | `math.Log`   | Returns the natural logarithm of the given number.                          | `{{math.Log 42}}` &rarr; `3.737` |
 | `math.Sqrt`  | Returns the square root of the given number.                                | `{{math.Sqrt 81}}` &rarr; `9`    |
-
+| `math.Pow`   | Returns the first number raised to the power of the second number.          | `{{math.Pow 2 3}}` &rarr; `8`    |
--- a/tpl/math/init.go
+++ b/tpl/math/init.go
@@ -92,6 +92,13 @@
 			},
 		)
 
+		ns.AddMethodMapping(ctx.Pow,
+			[]string{"pow"},
+			[][2]string{
+				{"{{math.Pow 2 3}}", "8"},
+			},
+		)
+
 		ns.AddMethodMapping(ctx.Round,
 			nil,
 			[][2]string{
--- a/tpl/math/math.go
+++ b/tpl/math/math.go
@@ -115,6 +115,18 @@
 	return _math.DoArithmetic(a, b, '*')
 }
 
+// Pow returns a raised to the power of b.
+func (ns *Namespace) Pow(a, b interface{}) (float64, error) {
+	af, erra := cast.ToFloat64E(a)
+	bf, errb := cast.ToFloat64E(b)
+
+	if erra != nil || errb != nil {
+		return 0, errors.New("Pow operator can't be used with non-float value")
+	}
+
+	return math.Pow(af, bf), nil
+}
+
 // Round returns the nearest integer, rounding half away from zero.
 func (ns *Namespace) Round(x interface{}) (float64, error) {
 	xf, err := cast.ToFloat64E(x)
--- a/tpl/math/math_test.go
+++ b/tpl/math/math_test.go
@@ -318,3 +318,43 @@
 		c.Assert(result, qt.Equals, test.expect)
 	}
 }
+
+func TestPow(t *testing.T) {
+	t.Parallel()
+	c := qt.New(t)
+
+	ns := New()
+
+	for _, test := range []struct {
+		a      interface{}
+		b      interface{}
+		expect interface{}
+	}{
+		{0, 0, float64(1)},
+		{2, 0, float64(1)},
+		{2, 3, float64(8)},
+		{-2, 3, float64(-8)},
+		{2, -3, float64(0.125)},
+		{-2, -3, float64(-0.125)},
+		{0.2, 3, float64(0.008)},
+		{2, 0.3, float64(1.2311)},
+		{0.2, 0.3, float64(0.617)},
+		{"aaa", "3", false},
+		{"2", "aaa", false},
+	} {
+
+		result, err := ns.Pow(test.a, test.b)
+
+		if b, ok := test.expect.(bool); ok && !b {
+			c.Assert(err, qt.Not(qt.IsNil))
+			continue
+		}
+
+		// we compare only 4 digits behind point if its a real float
+		// otherwise we usually get different float values on the last positions
+		result = float64(int(result*10000)) / 10000
+
+		c.Assert(err, qt.IsNil)
+		c.Assert(result, qt.Equals, test.expect)
+	}
+}