From 991934497e88dcd4134a369a213bb5072c51c139 Mon Sep 17 00:00:00 2001 From: Joe Mooring Date: Wed, 13 May 2020 13:35:07 -0400 Subject: [PATCH] Add math.Pow Closes #7266 --- docs/content/en/functions/math.md | 2 +- tpl/math/init.go | 7 ++++++ tpl/math/math.go | 12 ++++++++++ tpl/math/math_test.go | 40 +++++++++++++++++++++++++++++++ 4 files changed, 60 insertions(+), 1 deletion(-) diff --git a/docs/content/en/functions/math.md b/docs/content/en/functions/math.md index 29fe1698..58cc5d5d 100644 --- a/docs/content/en/functions/math.md +++ b/docs/content/en/functions/math.md @@ -38,4 +38,4 @@ aliases: [] | `math.Round` | Returns the nearest integer, rounding half away from zero. | `{{math.Round 1.5}}` → `2` | | `math.Log` | Returns the natural logarithm of the given number. | `{{math.Log 42}}` → `3.737` | | `math.Sqrt` | Returns the square root of the given number. | `{{math.Sqrt 81}}` → `9` | - +| `math.Pow` | Returns the first number raised to the power of the second number. | `{{math.Pow 2 3}}` → `8` | diff --git a/tpl/math/init.go b/tpl/math/init.go index 45240c5e..e7f9114b 100644 --- a/tpl/math/init.go +++ b/tpl/math/init.go @@ -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{ diff --git a/tpl/math/math.go b/tpl/math/math.go index 950d9590..ecaf61eb 100644 --- a/tpl/math/math.go +++ b/tpl/math/math.go @@ -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) diff --git a/tpl/math/math_test.go b/tpl/math/math_test.go index 70f6749b..c48f7183 100644 --- a/tpl/math/math_test.go +++ b/tpl/math/math_test.go @@ -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) + } +}