github.com/anakojm/hugo-katex@v0.0.0-20231023141351-42d6f5de9c0b/tpl/math/math_test.go (about)

     1  // Copyright 2017 The Hugo Authors. All rights reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  // http://www.apache.org/licenses/LICENSE-2.0
     7  //
     8  // Unless required by applicable law or agreed to in writing, software
     9  // distributed under the License is distributed on an "AS IS" BASIS,
    10  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package math
    15  
    16  import (
    17  	"math"
    18  	"testing"
    19  
    20  	qt "github.com/frankban/quicktest"
    21  )
    22  
    23  func TestBasicNSArithmetic(t *testing.T) {
    24  	t.Parallel()
    25  	c := qt.New(t)
    26  
    27  	ns := New()
    28  
    29  	type TestCase struct {
    30  		fn     func(inputs ...any) (any, error)
    31  		values []any
    32  		expect any
    33  	}
    34  
    35  	for _, test := range []TestCase{
    36  		{ns.Add, []any{4, 2}, int64(6)},
    37  		{ns.Add, []any{4, 2, 5}, int64(11)},
    38  		{ns.Add, []any{1.0, "foo"}, false},
    39  		{ns.Add, []any{0}, false},
    40  		{ns.Sub, []any{4, 2}, int64(2)},
    41  		{ns.Sub, []any{4, 2, 5}, int64(-3)},
    42  		{ns.Sub, []any{1.0, "foo"}, false},
    43  		{ns.Sub, []any{0}, false},
    44  		{ns.Mul, []any{4, 2}, int64(8)},
    45  		{ns.Mul, []any{4, 2, 5}, int64(40)},
    46  		{ns.Mul, []any{1.0, "foo"}, false},
    47  		{ns.Mul, []any{0}, false},
    48  		{ns.Div, []any{4, 2}, int64(2)},
    49  		{ns.Div, []any{4, 2, 5}, int64(0)},
    50  		{ns.Div, []any{1.0, "foo"}, false},
    51  		{ns.Div, []any{0}, false},
    52  	} {
    53  
    54  		result, err := test.fn(test.values...)
    55  
    56  		if b, ok := test.expect.(bool); ok && !b {
    57  			c.Assert(err, qt.Not(qt.IsNil))
    58  			continue
    59  		}
    60  
    61  		c.Assert(err, qt.IsNil)
    62  		c.Assert(result, qt.Equals, test.expect)
    63  	}
    64  }
    65  
    66  func TestAbs(t *testing.T) {
    67  	t.Parallel()
    68  	c := qt.New(t)
    69  	ns := New()
    70  
    71  	for _, test := range []struct {
    72  		x      any
    73  		expect any
    74  	}{
    75  		{0.0, 0.0},
    76  		{1.5, 1.5},
    77  		{-1.5, 1.5},
    78  		{-2, 2.0},
    79  		{"abc", false},
    80  	} {
    81  		result, err := ns.Abs(test.x)
    82  
    83  		if b, ok := test.expect.(bool); ok && !b {
    84  			c.Assert(err, qt.Not(qt.IsNil))
    85  			continue
    86  		}
    87  
    88  		c.Assert(err, qt.IsNil)
    89  		c.Assert(result, qt.Equals, test.expect)
    90  	}
    91  }
    92  
    93  func TestCeil(t *testing.T) {
    94  	t.Parallel()
    95  	c := qt.New(t)
    96  	ns := New()
    97  
    98  	for _, test := range []struct {
    99  		x      any
   100  		expect any
   101  	}{
   102  		{0.1, 1.0},
   103  		{0.5, 1.0},
   104  		{1.1, 2.0},
   105  		{1.5, 2.0},
   106  		{-0.1, 0.0},
   107  		{-0.5, 0.0},
   108  		{-1.1, -1.0},
   109  		{-1.5, -1.0},
   110  		{"abc", false},
   111  	} {
   112  
   113  		result, err := ns.Ceil(test.x)
   114  
   115  		if b, ok := test.expect.(bool); ok && !b {
   116  			c.Assert(err, qt.Not(qt.IsNil))
   117  			continue
   118  		}
   119  
   120  		c.Assert(err, qt.IsNil)
   121  		c.Assert(result, qt.Equals, test.expect)
   122  	}
   123  }
   124  
   125  func TestFloor(t *testing.T) {
   126  	t.Parallel()
   127  	c := qt.New(t)
   128  
   129  	ns := New()
   130  
   131  	for _, test := range []struct {
   132  		x      any
   133  		expect any
   134  	}{
   135  		{0.1, 0.0},
   136  		{0.5, 0.0},
   137  		{1.1, 1.0},
   138  		{1.5, 1.0},
   139  		{-0.1, -1.0},
   140  		{-0.5, -1.0},
   141  		{-1.1, -2.0},
   142  		{-1.5, -2.0},
   143  		{"abc", false},
   144  	} {
   145  
   146  		result, err := ns.Floor(test.x)
   147  
   148  		if b, ok := test.expect.(bool); ok && !b {
   149  			c.Assert(err, qt.Not(qt.IsNil))
   150  			continue
   151  		}
   152  
   153  		c.Assert(err, qt.IsNil)
   154  		c.Assert(result, qt.Equals, test.expect)
   155  	}
   156  }
   157  
   158  func TestLog(t *testing.T) {
   159  	t.Parallel()
   160  	c := qt.New(t)
   161  
   162  	ns := New()
   163  
   164  	for _, test := range []struct {
   165  		a      any
   166  		expect any
   167  	}{
   168  		{1, 0.0},
   169  		{3, 1.0986},
   170  		{0, math.Inf(-1)},
   171  		{1.0, 0.0},
   172  		{3.1, 1.1314},
   173  		{"abc", false},
   174  	} {
   175  
   176  		result, err := ns.Log(test.a)
   177  
   178  		if b, ok := test.expect.(bool); ok && !b {
   179  			c.Assert(err, qt.Not(qt.IsNil))
   180  			continue
   181  		}
   182  
   183  		// we compare only 4 digits behind point if its a real float
   184  		// otherwise we usually get different float values on the last positions
   185  		if result != math.Inf(-1) {
   186  			result = float64(int(result*10000)) / 10000
   187  		}
   188  
   189  		c.Assert(err, qt.IsNil)
   190  		c.Assert(result, qt.Equals, test.expect)
   191  	}
   192  
   193  	// Separate test for Log(-1) -- returns NaN
   194  	result, err := ns.Log(-1)
   195  	c.Assert(err, qt.IsNil)
   196  	c.Assert(result, qt.Satisfies, math.IsNaN)
   197  }
   198  
   199  func TestSqrt(t *testing.T) {
   200  	t.Parallel()
   201  	c := qt.New(t)
   202  
   203  	ns := New()
   204  
   205  	for _, test := range []struct {
   206  		a      any
   207  		expect any
   208  	}{
   209  		{81, 9.0},
   210  		{0.25, 0.5},
   211  		{0, 0.0},
   212  		{"abc", false},
   213  	} {
   214  
   215  		result, err := ns.Sqrt(test.a)
   216  
   217  		if b, ok := test.expect.(bool); ok && !b {
   218  			c.Assert(err, qt.Not(qt.IsNil))
   219  			continue
   220  		}
   221  
   222  		// we compare only 4 digits behind point if its a real float
   223  		// otherwise we usually get different float values on the last positions
   224  		if result != math.Inf(-1) {
   225  			result = float64(int(result*10000)) / 10000
   226  		}
   227  
   228  		c.Assert(err, qt.IsNil)
   229  		c.Assert(result, qt.Equals, test.expect)
   230  	}
   231  
   232  	// Separate test for Sqrt(-1) -- returns NaN
   233  	result, err := ns.Sqrt(-1)
   234  	c.Assert(err, qt.IsNil)
   235  	c.Assert(result, qt.Satisfies, math.IsNaN)
   236  }
   237  
   238  func TestMod(t *testing.T) {
   239  	t.Parallel()
   240  	c := qt.New(t)
   241  
   242  	ns := New()
   243  
   244  	for _, test := range []struct {
   245  		a      any
   246  		b      any
   247  		expect any
   248  	}{
   249  		{3, 2, int64(1)},
   250  		{3, 1, int64(0)},
   251  		{3, 0, false},
   252  		{0, 3, int64(0)},
   253  		{3.1, 2, int64(1)},
   254  		{3, 2.1, int64(1)},
   255  		{3.1, 2.1, int64(1)},
   256  		{int8(3), int8(2), int64(1)},
   257  		{int16(3), int16(2), int64(1)},
   258  		{int32(3), int32(2), int64(1)},
   259  		{int64(3), int64(2), int64(1)},
   260  		{"3", "2", int64(1)},
   261  		{"3.1", "2", false},
   262  		{"aaa", "0", false},
   263  		{"3", "aaa", false},
   264  	} {
   265  
   266  		result, err := ns.Mod(test.a, test.b)
   267  
   268  		if b, ok := test.expect.(bool); ok && !b {
   269  			c.Assert(err, qt.Not(qt.IsNil))
   270  			continue
   271  		}
   272  
   273  		c.Assert(err, qt.IsNil)
   274  		c.Assert(result, qt.Equals, test.expect)
   275  	}
   276  }
   277  
   278  func TestModBool(t *testing.T) {
   279  	t.Parallel()
   280  	c := qt.New(t)
   281  
   282  	ns := New()
   283  
   284  	for _, test := range []struct {
   285  		a      any
   286  		b      any
   287  		expect any
   288  	}{
   289  		{3, 3, true},
   290  		{3, 2, false},
   291  		{3, 1, true},
   292  		{3, 0, nil},
   293  		{0, 3, true},
   294  		{3.1, 2, false},
   295  		{3, 2.1, false},
   296  		{3.1, 2.1, false},
   297  		{int8(3), int8(3), true},
   298  		{int8(3), int8(2), false},
   299  		{int16(3), int16(3), true},
   300  		{int16(3), int16(2), false},
   301  		{int32(3), int32(3), true},
   302  		{int32(3), int32(2), false},
   303  		{int64(3), int64(3), true},
   304  		{int64(3), int64(2), false},
   305  		{"3", "3", true},
   306  		{"3", "2", false},
   307  		{"3.1", "2", nil},
   308  		{"aaa", "0", nil},
   309  		{"3", "aaa", nil},
   310  	} {
   311  
   312  		result, err := ns.ModBool(test.a, test.b)
   313  
   314  		if test.expect == nil {
   315  			c.Assert(err, qt.Not(qt.IsNil))
   316  			continue
   317  		}
   318  
   319  		c.Assert(err, qt.IsNil)
   320  		c.Assert(result, qt.Equals, test.expect)
   321  	}
   322  }
   323  
   324  func TestRound(t *testing.T) {
   325  	t.Parallel()
   326  	c := qt.New(t)
   327  
   328  	ns := New()
   329  
   330  	for _, test := range []struct {
   331  		x      any
   332  		expect any
   333  	}{
   334  		{0.1, 0.0},
   335  		{0.5, 1.0},
   336  		{1.1, 1.0},
   337  		{1.5, 2.0},
   338  		{-0.1, -0.0},
   339  		{-0.5, -1.0},
   340  		{-1.1, -1.0},
   341  		{-1.5, -2.0},
   342  		{"abc", false},
   343  	} {
   344  
   345  		result, err := ns.Round(test.x)
   346  
   347  		if b, ok := test.expect.(bool); ok && !b {
   348  			c.Assert(err, qt.Not(qt.IsNil))
   349  			continue
   350  		}
   351  
   352  		c.Assert(err, qt.IsNil)
   353  		c.Assert(result, qt.Equals, test.expect)
   354  	}
   355  }
   356  
   357  func TestPow(t *testing.T) {
   358  	t.Parallel()
   359  	c := qt.New(t)
   360  
   361  	ns := New()
   362  
   363  	for _, test := range []struct {
   364  		a      any
   365  		b      any
   366  		expect any
   367  	}{
   368  		{0, 0, 1.0},
   369  		{2, 0, 1.0},
   370  		{2, 3, 8.0},
   371  		{-2, 3, -8.0},
   372  		{2, -3, 0.125},
   373  		{-2, -3, -0.125},
   374  		{0.2, 3, 0.008},
   375  		{2, 0.3, 1.2311},
   376  		{0.2, 0.3, 0.617},
   377  		{"aaa", "3", false},
   378  		{"2", "aaa", false},
   379  	} {
   380  
   381  		result, err := ns.Pow(test.a, test.b)
   382  
   383  		if b, ok := test.expect.(bool); ok && !b {
   384  			c.Assert(err, qt.Not(qt.IsNil))
   385  			continue
   386  		}
   387  
   388  		// we compare only 4 digits behind point if its a real float
   389  		// otherwise we usually get different float values on the last positions
   390  		result = float64(int(result*10000)) / 10000
   391  
   392  		c.Assert(err, qt.IsNil)
   393  		c.Assert(result, qt.Equals, test.expect)
   394  	}
   395  }
   396  
   397  func TestMax(t *testing.T) {
   398  	t.Parallel()
   399  	c := qt.New(t)
   400  
   401  	ns := New()
   402  
   403  	type TestCase struct {
   404  		values []any
   405  		expect any
   406  	}
   407  
   408  	for _, test := range []TestCase{
   409  		// two values
   410  		{[]any{-1, -1}, -1.0},
   411  		{[]any{-1, 0}, 0.0},
   412  		{[]any{-1, 1}, 1.0},
   413  		{[]any{0, -1}, 0.0},
   414  		{[]any{0, 0}, 0.0},
   415  		{[]any{0, 1}, 1.0},
   416  		{[]any{1, -1}, 1.0},
   417  		{[]any{1, 0}, 1.0},
   418  		{[]any{32}, 32.0},
   419  		{[]any{1, 1}, 1.0},
   420  		{[]any{1.2, 1.23}, 1.23},
   421  		{[]any{-1.2, -1.23}, -1.2},
   422  		{[]any{0, "a"}, false},
   423  		{[]any{"a", 0}, false},
   424  		{[]any{"a", "b"}, false},
   425  		// Issue #11030
   426  		{[]any{7, []any{3, 4}}, 7.0},
   427  		{[]any{8, []any{3, 12}, 3}, 12.0},
   428  		{[]any{[]any{3, 5, 2}}, 5.0},
   429  		{[]any{3, []int{3, 6}, 3}, 6.0},
   430  		// No values.
   431  		{[]any{}, false},
   432  
   433  		// multi values
   434  		{[]any{-1, -2, -3}, -1.0},
   435  		{[]any{1, 2, 3}, 3.0},
   436  		{[]any{"a", 2, 3}, false},
   437  	} {
   438  		result, err := ns.Max(test.values...)
   439  
   440  		if b, ok := test.expect.(bool); ok && !b {
   441  			c.Assert(err, qt.Not(qt.IsNil))
   442  			continue
   443  		}
   444  
   445  		msg := qt.Commentf("values: %v", test.values)
   446  		c.Assert(err, qt.IsNil, msg)
   447  		c.Assert(result, qt.Equals, test.expect, msg)
   448  	}
   449  }
   450  
   451  func TestMin(t *testing.T) {
   452  	t.Parallel()
   453  	c := qt.New(t)
   454  
   455  	ns := New()
   456  
   457  	type TestCase struct {
   458  		values []any
   459  		expect any
   460  	}
   461  
   462  	for _, test := range []TestCase{
   463  		// two values
   464  		{[]any{-1, -1}, -1.0},
   465  		{[]any{-1, 0}, -1.0},
   466  		{[]any{-1, 1}, -1.0},
   467  		{[]any{0, -1}, -1.0},
   468  		{[]any{0, 0}, 0.0},
   469  		{[]any{0, 1}, 0.0},
   470  		{[]any{1, -1}, -1.0},
   471  		{[]any{1, 0}, 0.0},
   472  		{[]any{1, 1}, 1.0},
   473  		{[]any{2}, 2.0},
   474  		{[]any{1.2, 1.23}, 1.2},
   475  		{[]any{-1.2, -1.23}, -1.23},
   476  		{[]any{0, "a"}, false},
   477  		{[]any{"a", 0}, false},
   478  		{[]any{"a", "b"}, false},
   479  		// Issue #11030
   480  		{[]any{1, []any{3, 4}}, 1.0},
   481  		{[]any{8, []any{3, 2}, 3}, 2.0},
   482  		{[]any{[]any{3, 2, 2}}, 2.0},
   483  		{[]any{8, []int{3, 2}, 3}, 2.0},
   484  
   485  		// No values.
   486  		{[]any{}, false},
   487  
   488  		// multi values
   489  		{[]any{-1, -2, -3}, -3.0},
   490  		{[]any{1, 2, 3}, 1.0},
   491  		{[]any{"a", 2, 3}, false},
   492  	} {
   493  
   494  		result, err := ns.Min(test.values...)
   495  
   496  		if b, ok := test.expect.(bool); ok && !b {
   497  			c.Assert(err, qt.Not(qt.IsNil))
   498  			continue
   499  		}
   500  
   501  		c.Assert(err, qt.IsNil, qt.Commentf("values: %v", test.values))
   502  		c.Assert(result, qt.Equals, test.expect)
   503  	}
   504  }
   505  
   506  func TestSum(t *testing.T) {
   507  	t.Parallel()
   508  	c := qt.New(t)
   509  
   510  	ns := New()
   511  
   512  	mustSum := func(values ...any) any {
   513  		result, err := ns.Sum(values...)
   514  		c.Assert(err, qt.IsNil)
   515  		return result
   516  	}
   517  
   518  	c.Assert(mustSum(1, 2, 3), qt.Equals, 6.0)
   519  	c.Assert(mustSum(1, 2, 3.0), qt.Equals, 6.0)
   520  	c.Assert(mustSum(1, 2, []any{3, 4}), qt.Equals, 10.0)
   521  	c.Assert(mustSum(23), qt.Equals, 23.0)
   522  	c.Assert(mustSum([]any{23}), qt.Equals, 23.0)
   523  	c.Assert(mustSum([]any{}), qt.Equals, 0.0)
   524  
   525  	_, err := ns.Sum()
   526  	c.Assert(err, qt.Not(qt.IsNil))
   527  
   528  }
   529  
   530  func TestProduct(t *testing.T) {
   531  	t.Parallel()
   532  	c := qt.New(t)
   533  
   534  	ns := New()
   535  
   536  	mustProduct := func(values ...any) any {
   537  		result, err := ns.Product(values...)
   538  		c.Assert(err, qt.IsNil)
   539  		return result
   540  	}
   541  
   542  	c.Assert(mustProduct(2, 2, 3), qt.Equals, 12.0)
   543  	c.Assert(mustProduct(1, 2, 3.0), qt.Equals, 6.0)
   544  	c.Assert(mustProduct(1, 2, []any{3, 4}), qt.Equals, 24.0)
   545  	c.Assert(mustProduct(3.0), qt.Equals, 3.0)
   546  	c.Assert(mustProduct([]string{}), qt.Equals, 0.0)
   547  
   548  	_, err := ns.Product()
   549  	c.Assert(err, qt.Not(qt.IsNil))
   550  
   551  }