Add math.Pow
authorJoe Mooring <joe.mooring@veriphor.com>
Wed, 13 May 2020 17:35:07 +0000 (13:35 -0400)
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Thu, 14 May 2020 08:00:31 +0000 (10:00 +0200)
Closes #7266

docs/content/en/functions/math.md
tpl/math/init.go
tpl/math/math.go
tpl/math/math_test.go

index 29fe16985ebc57ba424e27958fdb137e79fff64e..58cc5d5db6ea41c5540fe362085ec2056c56b9a6 100644 (file)
@@ -38,4 +38,4 @@ aliases: []
 | `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`    |
index 45240c5e1aca4dfae3bceffb22969d4f350257b5..e7f9114ba47dc573b871d773711a778826ac860c 100644 (file)
@@ -92,6 +92,13 @@ func init() {
                        },
                )
 
+               ns.AddMethodMapping(ctx.Pow,
+                       []string{"pow"},
+                       [][2]string{
+                               {"{{math.Pow 2 3}}", "8"},
+                       },
+               )
+
                ns.AddMethodMapping(ctx.Round,
                        nil,
                        [][2]string{
index 950d95905dd3095bc13d68835bc223f95ac273d3..ecaf61ebc3c673f59bb2155faa745791638f5ca9 100644 (file)
@@ -115,6 +115,18 @@ func (ns *Namespace) Mul(a, b interface{}) (interface{}, error) {
        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)
index 70f6749baff865cbbef74db656020bdf672c2568..c48f7183779bac2f21272640170086278fee98d3 100644 (file)
@@ -318,3 +318,43 @@ func TestRound(t *testing.T) {
                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)
+       }
+}