shithub: hugo

Download patch

ref: d184e5059c72c15df055192b01da0fd8c5b0fc5c
parent: 322c285ba2f3aa95826fe2135646b4d35f4d2a30
author: Chris Dennis <ssa@fbcs.co.uk>
date: Mon Feb 24 17:45:04 EST 2020

tpl: Add math.Sqrt

Fixes #6941

--- a/docs/content/en/functions/math.md
+++ b/docs/content/en/functions/math.md
@@ -4,7 +4,7 @@
 godocref:
 date: 2017-02-01
 publishdate: 2017-02-01
-lastmod: 2017-02-01
+lastmod: 2020-02-23
 keywords: [math, operators]
 categories: [functions]
 menu:
@@ -36,3 +36,6 @@
 | `math.Ceil`  | Returns the least integer value greater than or equal to the given number.  | `{{math.Ceil 2.1}}` &rarr; `3`   |
 | `math.Floor` | Returns the greatest integer value less than or equal to the given number.  | `{{math.Floor 1.9}}` &rarr; `1`  |
 | `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`    |
+
--- a/tpl/math/init.go
+++ b/tpl/math/init.go
@@ -64,6 +64,13 @@
 			},
 		)
 
+		ns.AddMethodMapping(ctx.Sqrt,
+			nil,
+			[][2]string{
+				{"{{math.Sqrt 81}}", "9"},
+			},
+		)
+
 		ns.AddMethodMapping(ctx.Mod,
 			[]string{"mod"},
 			[][2]string{
--- a/tpl/math/math.go
+++ b/tpl/math/math.go
@@ -72,6 +72,18 @@
 	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)
--- a/tpl/math/math_test.go
+++ b/tpl/math/math_test.go
@@ -153,6 +153,51 @@
 		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) {