From d184e5059c72c15df055192b01da0fd8c5b0fc5c Mon Sep 17 00:00:00 2001 From: Chris Dennis Date: Mon, 24 Feb 2020 22:45:04 +0000 Subject: tpl: Add math.Sqrt Fixes #6941 --- tpl/math/init.go | 7 +++++++ tpl/math/math.go | 12 ++++++++++++ tpl/math/math_test.go | 45 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+) (limited to 'tpl') diff --git a/tpl/math/init.go b/tpl/math/init.go index bbffb23aa..45240c5e1 100644 --- a/tpl/math/init.go +++ b/tpl/math/init.go @@ -64,6 +64,13 @@ func init() { }, ) + ns.AddMethodMapping(ctx.Sqrt, + nil, + [][2]string{ + {"{{math.Sqrt 81}}", "9"}, + }, + ) + ns.AddMethodMapping(ctx.Mod, []string{"mod"}, [][2]string{ diff --git a/tpl/math/math.go b/tpl/math/math.go index 08be42b47..950d95905 100644 --- a/tpl/math/math.go +++ b/tpl/math/math.go @@ -72,6 +72,18 @@ func (ns *Namespace) Log(a interface{}) (float64, error) { return math.Log(af), nil } +// Sqrt returns the square root of a number. +// NOTE: will return for NaN for negative values of a +func (ns *Namespace) Sqrt(a interface{}) (float64, error) { + af, err := cast.ToFloat64E(a) + + if err != nil { + return 0, errors.New("Sqrt operator can't be used with non integer or float value") + } + + return math.Sqrt(af), nil +} + // Mod returns a % b. func (ns *Namespace) Mod(a, b interface{}) (int64, error) { ai, erra := cast.ToInt64E(a) diff --git a/tpl/math/math_test.go b/tpl/math/math_test.go index 0beec8204..70f6749ba 100644 --- a/tpl/math/math_test.go +++ b/tpl/math/math_test.go @@ -153,6 +153,51 @@ func TestLog(t *testing.T) { c.Assert(err, qt.IsNil) c.Assert(result, qt.Equals, test.expect) } + + // Separate test for Log(-1) -- returns NaN + result, err := ns.Log(-1) + c.Assert(err, qt.IsNil) + c.Assert(result, qt.Satisfies, math.IsNaN) +} + +func TestSqrt(t *testing.T) { + t.Parallel() + c := qt.New(t) + + ns := New() + + for _, test := range []struct { + a interface{} + expect interface{} + }{ + {81, float64(9)}, + {0.25, float64(0.5)}, + {0, float64(0)}, + {"abc", false}, + } { + + result, err := ns.Sqrt(test.a) + + 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 + if result != math.Inf(-1) { + result = float64(int(result*10000)) / 10000 + } + + c.Assert(err, qt.IsNil) + c.Assert(result, qt.Equals, test.expect) + } + + // Separate test for Sqrt(-1) -- returns NaN + result, err := ns.Sqrt(-1) + c.Assert(err, qt.IsNil) + c.Assert(result, qt.Satisfies, math.IsNaN) + } func TestMod(t *testing.T) { -- cgit v1.2.3