github.com/jingcheng-WU/gonum@v0.9.1-0.20210323123734-f1a2a11a8f7b/floats/floats_test.go (about)

     1  // Copyright ©2013 The Gonum Authors. All rights reserved.
     2  // Use of this code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package floats
     6  
     7  import (
     8  	"fmt"
     9  	"math"
    10  	"strconv"
    11  	"testing"
    12  
    13  	"golang.org/x/exp/rand"
    14  
    15  	"github.com/jingcheng-WU/gonum/floats/scalar"
    16  )
    17  
    18  const (
    19  	EqTolerance = 1e-14
    20  	Small       = 10
    21  	Medium      = 1000
    22  	Large       = 100000
    23  	Huge        = 10000000
    24  )
    25  
    26  func areSlicesEqual(t *testing.T, truth, comp []float64, str string) {
    27  	if !EqualApprox(comp, truth, EqTolerance) {
    28  		t.Errorf(str+". Expected %v, returned %v", truth, comp)
    29  	}
    30  }
    31  
    32  func areSlicesSame(t *testing.T, truth, comp []float64, str string) {
    33  	ok := len(truth) == len(comp)
    34  	if ok {
    35  		for i, a := range truth {
    36  			if !scalar.EqualWithinAbsOrRel(a, comp[i], EqTolerance, EqTolerance) && !scalar.Same(a, comp[i]) {
    37  				ok = false
    38  				break
    39  			}
    40  		}
    41  	}
    42  	if !ok {
    43  		t.Errorf(str+". Expected %v, returned %v", truth, comp)
    44  	}
    45  }
    46  
    47  func Panics(fun func()) (b bool) {
    48  	defer func() {
    49  		err := recover()
    50  		if err != nil {
    51  			b = true
    52  		}
    53  	}()
    54  	fun()
    55  	return
    56  }
    57  
    58  func TestAdd(t *testing.T) {
    59  	t.Parallel()
    60  	a := []float64{1, 2, 3}
    61  	b := []float64{4, 5, 6}
    62  	c := []float64{7, 8, 9}
    63  	truth := []float64{12, 15, 18}
    64  	n := make([]float64, len(a))
    65  
    66  	Add(n, a)
    67  	Add(n, b)
    68  	Add(n, c)
    69  	areSlicesEqual(t, truth, n, "Wrong addition of slices new receiver")
    70  	Add(a, b)
    71  	Add(a, c)
    72  	areSlicesEqual(t, truth, n, "Wrong addition of slices for no new receiver")
    73  
    74  	// Test that it panics
    75  	if !Panics(func() { Add(make([]float64, 2), make([]float64, 3)) }) {
    76  		t.Errorf("Did not panic with length mismatch")
    77  	}
    78  }
    79  
    80  func TestAddTo(t *testing.T) {
    81  	t.Parallel()
    82  	a := []float64{1, 2, 3}
    83  	b := []float64{4, 5, 6}
    84  	truth := []float64{5, 7, 9}
    85  	n1 := make([]float64, len(a))
    86  
    87  	n2 := AddTo(n1, a, b)
    88  	areSlicesEqual(t, truth, n1, "Bad addition from mutator")
    89  	areSlicesEqual(t, truth, n2, "Bad addition from returned slice")
    90  
    91  	// Test that it panics
    92  	if !Panics(func() { AddTo(make([]float64, 2), make([]float64, 3), make([]float64, 3)) }) {
    93  		t.Errorf("Did not panic with length mismatch")
    94  	}
    95  	if !Panics(func() { AddTo(make([]float64, 3), make([]float64, 3), make([]float64, 2)) }) {
    96  		t.Errorf("Did not panic with length mismatch")
    97  	}
    98  }
    99  
   100  func TestAddConst(t *testing.T) {
   101  	t.Parallel()
   102  	s := []float64{3, 4, 1, 7, 5}
   103  	c := 6.0
   104  	truth := []float64{9, 10, 7, 13, 11}
   105  	AddConst(c, s)
   106  	areSlicesEqual(t, truth, s, "Wrong addition of constant")
   107  }
   108  
   109  func TestAddScaled(t *testing.T) {
   110  	t.Parallel()
   111  	s := []float64{3, 4, 1, 7, 5}
   112  	alpha := 6.0
   113  	dst := []float64{1, 2, 3, 4, 5}
   114  	ans := []float64{19, 26, 9, 46, 35}
   115  	AddScaled(dst, alpha, s)
   116  	if !EqualApprox(dst, ans, EqTolerance) {
   117  		t.Errorf("Adding scaled did not match")
   118  	}
   119  	short := []float64{1}
   120  	if !Panics(func() { AddScaled(dst, alpha, short) }) {
   121  		t.Errorf("Doesn't panic if s is smaller than dst")
   122  	}
   123  	if !Panics(func() { AddScaled(short, alpha, s) }) {
   124  		t.Errorf("Doesn't panic if dst is smaller than s")
   125  	}
   126  }
   127  
   128  func TestAddScaledTo(t *testing.T) {
   129  	t.Parallel()
   130  	s := []float64{3, 4, 1, 7, 5}
   131  	alpha := 6.0
   132  	y := []float64{1, 2, 3, 4, 5}
   133  	dst1 := make([]float64, 5)
   134  	ans := []float64{19, 26, 9, 46, 35}
   135  	dst2 := AddScaledTo(dst1, y, alpha, s)
   136  	if !EqualApprox(dst1, ans, EqTolerance) {
   137  		t.Errorf("AddScaledTo did not match for mutator")
   138  	}
   139  	if !EqualApprox(dst2, ans, EqTolerance) {
   140  		t.Errorf("AddScaledTo did not match for returned slice")
   141  	}
   142  	AddScaledTo(dst1, y, alpha, s)
   143  	if !EqualApprox(dst1, ans, EqTolerance) {
   144  		t.Errorf("Reusing dst did not match")
   145  	}
   146  	short := []float64{1}
   147  	if !Panics(func() { AddScaledTo(dst1, y, alpha, short) }) {
   148  		t.Errorf("Doesn't panic if s is smaller than dst")
   149  	}
   150  	if !Panics(func() { AddScaledTo(short, y, alpha, s) }) {
   151  		t.Errorf("Doesn't panic if dst is smaller than s")
   152  	}
   153  	if !Panics(func() { AddScaledTo(dst1, short, alpha, s) }) {
   154  		t.Errorf("Doesn't panic if y is smaller than dst")
   155  	}
   156  }
   157  
   158  func TestArgsort(t *testing.T) {
   159  	t.Parallel()
   160  	s := []float64{3, 4, 1, 7, 5}
   161  	inds := make([]int, len(s))
   162  
   163  	Argsort(s, inds)
   164  
   165  	sortedS := []float64{1, 3, 4, 5, 7}
   166  	trueInds := []int{2, 0, 1, 4, 3}
   167  
   168  	if !Equal(s, sortedS) {
   169  		t.Error("elements not sorted correctly")
   170  	}
   171  	for i := range trueInds {
   172  		if trueInds[i] != inds[i] {
   173  			t.Error("inds not correct")
   174  		}
   175  	}
   176  
   177  	inds = []int{1, 2}
   178  	if !Panics(func() { Argsort(s, inds) }) {
   179  		t.Error("does not panic if lengths do not match")
   180  	}
   181  }
   182  
   183  func TestCount(t *testing.T) {
   184  	t.Parallel()
   185  	s := []float64{3, 4, 1, 7, 5}
   186  	f := func(v float64) bool { return v > 3.5 }
   187  	truth := 3
   188  	n := Count(f, s)
   189  	if n != truth {
   190  		t.Errorf("Wrong number of elements counted")
   191  	}
   192  }
   193  
   194  func TestCumProd(t *testing.T) {
   195  	t.Parallel()
   196  	s := []float64{3, 4, 1, 7, 5}
   197  	receiver := make([]float64, len(s))
   198  	result := CumProd(receiver, s)
   199  	truth := []float64{3, 12, 12, 84, 420}
   200  	areSlicesEqual(t, truth, receiver, "Wrong cumprod mutated with new receiver")
   201  	areSlicesEqual(t, truth, result, "Wrong cumprod result with new receiver")
   202  	CumProd(receiver, s)
   203  	areSlicesEqual(t, truth, receiver, "Wrong cumprod returned with reused receiver")
   204  
   205  	// Test that it panics
   206  	if !Panics(func() { CumProd(make([]float64, 2), make([]float64, 3)) }) {
   207  		t.Errorf("Did not panic with length mismatch")
   208  	}
   209  
   210  	// Test empty CumProd
   211  	emptyReceiver := make([]float64, 0)
   212  	truth = []float64{}
   213  	CumProd(emptyReceiver, emptyReceiver)
   214  	areSlicesEqual(t, truth, emptyReceiver, "Wrong cumprod returned with empty receiver")
   215  }
   216  
   217  func TestCumSum(t *testing.T) {
   218  	t.Parallel()
   219  	s := []float64{3, 4, 1, 7, 5}
   220  	receiver := make([]float64, len(s))
   221  	result := CumSum(receiver, s)
   222  	truth := []float64{3, 7, 8, 15, 20}
   223  	areSlicesEqual(t, truth, receiver, "Wrong cumsum mutated with new receiver")
   224  	areSlicesEqual(t, truth, result, "Wrong cumsum returned with new receiver")
   225  	CumSum(receiver, s)
   226  	areSlicesEqual(t, truth, receiver, "Wrong cumsum returned with reused receiver")
   227  
   228  	// Test that it panics
   229  	if !Panics(func() { CumSum(make([]float64, 2), make([]float64, 3)) }) {
   230  		t.Errorf("Did not panic with length mismatch")
   231  	}
   232  
   233  	// Test empty CumSum
   234  	emptyReceiver := make([]float64, 0)
   235  	truth = []float64{}
   236  	CumSum(emptyReceiver, emptyReceiver)
   237  	areSlicesEqual(t, truth, emptyReceiver, "Wrong cumsum returned with empty receiver")
   238  }
   239  
   240  func TestDistance(t *testing.T) {
   241  	t.Parallel()
   242  	norms := []float64{1, 2, 4, math.Inf(1)}
   243  	slices := []struct {
   244  		s []float64
   245  		t []float64
   246  	}{
   247  		{
   248  			nil,
   249  			nil,
   250  		},
   251  		{
   252  			[]float64{8, 9, 10, -12},
   253  			[]float64{8, 9, 10, -12},
   254  		},
   255  		{
   256  			[]float64{1, 2, 3, -4, -5, 8},
   257  			[]float64{-9.2, -6.8, 9, -3, -2, 1},
   258  		},
   259  	}
   260  
   261  	for j, test := range slices {
   262  		tmp := make([]float64, len(test.s))
   263  		for i, L := range norms {
   264  			dist := Distance(test.s, test.t, L)
   265  			copy(tmp, test.s)
   266  			Sub(tmp, test.t)
   267  			norm := Norm(tmp, L)
   268  			if dist != norm { // Use equality because they should be identical.
   269  				t.Errorf("Distance does not match norm for case %v, %v. Expected %v, Found %v.", i, j, norm, dist)
   270  			}
   271  		}
   272  	}
   273  
   274  	if !Panics(func() { Distance([]float64{}, norms, 1) }) {
   275  		t.Errorf("Did not panic with unequal lengths")
   276  	}
   277  }
   278  
   279  func TestDiv(t *testing.T) {
   280  	t.Parallel()
   281  	s1 := []float64{5, 12, 27}
   282  	s2 := []float64{1, 2, 3}
   283  	ans := []float64{5, 6, 9}
   284  	Div(s1, s2)
   285  	if !EqualApprox(s1, ans, EqTolerance) {
   286  		t.Errorf("Div doesn't give correct answer")
   287  	}
   288  	s1short := []float64{1}
   289  	if !Panics(func() { Div(s1short, s2) }) {
   290  		t.Errorf("Did not panic with unequal lengths")
   291  	}
   292  	s2short := []float64{1}
   293  	if !Panics(func() { Div(s1, s2short) }) {
   294  		t.Errorf("Did not panic with unequal lengths")
   295  	}
   296  }
   297  
   298  func TestDivTo(t *testing.T) {
   299  	t.Parallel()
   300  	s1 := []float64{5, 12, 27}
   301  	s1orig := []float64{5, 12, 27}
   302  	s2 := []float64{1, 2, 3}
   303  	s2orig := []float64{1, 2, 3}
   304  	dst1 := make([]float64, 3)
   305  	ans := []float64{5, 6, 9}
   306  	dst2 := DivTo(dst1, s1, s2)
   307  	if !EqualApprox(dst1, ans, EqTolerance) {
   308  		t.Errorf("DivTo doesn't give correct answer in mutated slice")
   309  	}
   310  	if !EqualApprox(dst2, ans, EqTolerance) {
   311  		t.Errorf("DivTo doesn't give correct answer in returned slice")
   312  	}
   313  	if !EqualApprox(s1, s1orig, EqTolerance) {
   314  		t.Errorf("S1 changes during multo")
   315  	}
   316  	if !EqualApprox(s2, s2orig, EqTolerance) {
   317  		t.Errorf("s2 changes during multo")
   318  	}
   319  	DivTo(dst1, s1, s2)
   320  	if !EqualApprox(dst1, ans, EqTolerance) {
   321  		t.Errorf("DivTo doesn't give correct answer reusing dst")
   322  	}
   323  	dstShort := []float64{1}
   324  	if !Panics(func() { DivTo(dstShort, s1, s2) }) {
   325  		t.Errorf("Did not panic with s1 wrong length")
   326  	}
   327  	s1short := []float64{1}
   328  	if !Panics(func() { DivTo(dst1, s1short, s2) }) {
   329  		t.Errorf("Did not panic with s1 wrong length")
   330  	}
   331  	s2short := []float64{1}
   332  	if !Panics(func() { DivTo(dst1, s1, s2short) }) {
   333  		t.Errorf("Did not panic with s2 wrong length")
   334  	}
   335  }
   336  
   337  func TestDot(t *testing.T) {
   338  	t.Parallel()
   339  	s1 := []float64{1, 2, 3, 4}
   340  	s2 := []float64{-3, 4, 5, -6}
   341  	truth := -4.0
   342  	ans := Dot(s1, s2)
   343  	if ans != truth {
   344  		t.Errorf("Dot product computed incorrectly")
   345  	}
   346  
   347  	// Test that it panics
   348  	if !Panics(func() { Dot(make([]float64, 2), make([]float64, 3)) }) {
   349  		t.Errorf("Did not panic with length mismatch")
   350  	}
   351  }
   352  
   353  func TestEquals(t *testing.T) {
   354  	t.Parallel()
   355  	s1 := []float64{1, 2, 3, 4}
   356  	s2 := []float64{1, 2, 3, 4}
   357  	if !Equal(s1, s2) {
   358  		t.Errorf("Equal slices returned as unequal")
   359  	}
   360  	s2 = []float64{1, 2, 3, 4 + 1e-14}
   361  	if Equal(s1, s2) {
   362  		t.Errorf("Unequal slices returned as equal")
   363  	}
   364  	if Equal(s1, []float64{}) {
   365  		t.Errorf("Unequal slice lengths returned as equal")
   366  	}
   367  }
   368  
   369  func TestEqualApprox(t *testing.T) {
   370  	t.Parallel()
   371  	s1 := []float64{1, 2, 3, 4}
   372  	s2 := []float64{1, 2, 3, 4 + 1e-10}
   373  	if EqualApprox(s1, s2, 1e-13) {
   374  		t.Errorf("Unequal slices returned as equal for absolute")
   375  	}
   376  	if !EqualApprox(s1, s2, 1e-5) {
   377  		t.Errorf("Equal slices returned as unequal for absolute")
   378  	}
   379  	s1 = []float64{1, 2, 3, 1000}
   380  	s2 = []float64{1, 2, 3, 1000 * (1 + 1e-7)}
   381  	if EqualApprox(s1, s2, 1e-8) {
   382  		t.Errorf("Unequal slices returned as equal for relative")
   383  	}
   384  	if !EqualApprox(s1, s2, 1e-5) {
   385  		t.Errorf("Equal slices returned as unequal for relative")
   386  	}
   387  	if EqualApprox(s1, []float64{}, 1e-5) {
   388  		t.Errorf("Unequal slice lengths returned as equal")
   389  	}
   390  }
   391  
   392  func TestEqualFunc(t *testing.T) {
   393  	t.Parallel()
   394  	s1 := []float64{1, 2, 3, 4}
   395  	s2 := []float64{1, 2, 3, 4}
   396  	eq := func(x, y float64) bool { return x == y }
   397  	if !EqualFunc(s1, s2, eq) {
   398  		t.Errorf("Equal slices returned as unequal")
   399  	}
   400  	s2 = []float64{1, 2, 3, 4 + 1e-14}
   401  	if EqualFunc(s1, s2, eq) {
   402  		t.Errorf("Unequal slices returned as equal")
   403  	}
   404  	if EqualFunc(s1, []float64{}, eq) {
   405  		t.Errorf("Unequal slice lengths returned as equal")
   406  	}
   407  }
   408  
   409  func TestEqualsRelative(t *testing.T) {
   410  	t.Parallel()
   411  	equalityTests := []struct {
   412  		a, b  float64
   413  		tol   float64
   414  		equal bool
   415  	}{
   416  		{1000000, 1000001, 0, true},
   417  		{1000001, 1000000, 0, true},
   418  		{10000, 10001, 0, false},
   419  		{10001, 10000, 0, false},
   420  		{-1000000, -1000001, 0, true},
   421  		{-1000001, -1000000, 0, true},
   422  		{-10000, -10001, 0, false},
   423  		{-10001, -10000, 0, false},
   424  		{1.0000001, 1.0000002, 0, true},
   425  		{1.0000002, 1.0000001, 0, true},
   426  		{1.0002, 1.0001, 0, false},
   427  		{1.0001, 1.0002, 0, false},
   428  		{-1.000001, -1.000002, 0, true},
   429  		{-1.000002, -1.000001, 0, true},
   430  		{-1.0001, -1.0002, 0, false},
   431  		{-1.0002, -1.0001, 0, false},
   432  		{0.000000001000001, 0.000000001000002, 0, true},
   433  		{0.000000001000002, 0.000000001000001, 0, true},
   434  		{0.000000000001002, 0.000000000001001, 0, false},
   435  		{0.000000000001001, 0.000000000001002, 0, false},
   436  		{-0.000000001000001, -0.000000001000002, 0, true},
   437  		{-0.000000001000002, -0.000000001000001, 0, true},
   438  		{-0.000000000001002, -0.000000000001001, 0, false},
   439  		{-0.000000000001001, -0.000000000001002, 0, false},
   440  		{0, 0, 0, true},
   441  		{0, -0, 0, true},
   442  		{-0, -0, 0, true},
   443  		{0.00000001, 0, 0, false},
   444  		{0, 0.00000001, 0, false},
   445  		{-0.00000001, 0, 0, false},
   446  		{0, -0.00000001, 0, false},
   447  		{0, 1e-310, 0.01, true},
   448  		{1e-310, 0, 0.01, true},
   449  		{1e-310, 0, 0.000001, false},
   450  		{0, 1e-310, 0.000001, false},
   451  		{0, -1e-310, 0.1, true},
   452  		{-1e-310, 0, 0.1, true},
   453  		{-1e-310, 0, 0.00000001, false},
   454  		{0, -1e-310, 0.00000001, false},
   455  		{math.Inf(1), math.Inf(1), 0, true},
   456  		{math.Inf(-1), math.Inf(-1), 0, true},
   457  		{math.Inf(-1), math.Inf(1), 0, false},
   458  		{math.Inf(1), math.MaxFloat64, 0, false},
   459  		{math.Inf(-1), -math.MaxFloat64, 0, false},
   460  		{math.NaN(), math.NaN(), 0, false},
   461  		{math.NaN(), 0, 0, false},
   462  		{-0, math.NaN(), 0, false},
   463  		{math.NaN(), -0, 0, false},
   464  		{0, math.NaN(), 0, false},
   465  		{math.NaN(), math.Inf(1), 0, false},
   466  		{math.Inf(1), math.NaN(), 0, false},
   467  		{math.NaN(), math.Inf(-1), 0, false},
   468  		{math.Inf(-1), math.NaN(), 0, false},
   469  		{math.NaN(), math.MaxFloat64, 0, false},
   470  		{math.MaxFloat64, math.NaN(), 0, false},
   471  		{math.NaN(), -math.MaxFloat64, 0, false},
   472  		{-math.MaxFloat64, math.NaN(), 0, false},
   473  		{math.NaN(), math.SmallestNonzeroFloat64, 0, false},
   474  		{math.SmallestNonzeroFloat64, math.NaN(), 0, false},
   475  		{math.NaN(), -math.SmallestNonzeroFloat64, 0, false},
   476  		{-math.SmallestNonzeroFloat64, math.NaN(), 0, false},
   477  		{1.000000001, -1.0, 0, false},
   478  		{-1.0, 1.000000001, 0, false},
   479  		{-1.000000001, 1.0, 0, false},
   480  		{1.0, -1.000000001, 0, false},
   481  		{10 * math.SmallestNonzeroFloat64, 10 * -math.SmallestNonzeroFloat64, 0, true},
   482  		{1e11 * math.SmallestNonzeroFloat64, 1e11 * -math.SmallestNonzeroFloat64, 0, false},
   483  		{math.SmallestNonzeroFloat64, -math.SmallestNonzeroFloat64, 0, true},
   484  		{-math.SmallestNonzeroFloat64, math.SmallestNonzeroFloat64, 0, true},
   485  		{math.SmallestNonzeroFloat64, 0, 0, true},
   486  		{0, math.SmallestNonzeroFloat64, 0, true},
   487  		{-math.SmallestNonzeroFloat64, 0, 0, true},
   488  		{0, -math.SmallestNonzeroFloat64, 0, true},
   489  		{0.000000001, -math.SmallestNonzeroFloat64, 0, false},
   490  		{0.000000001, math.SmallestNonzeroFloat64, 0, false},
   491  		{math.SmallestNonzeroFloat64, 0.000000001, 0, false},
   492  		{-math.SmallestNonzeroFloat64, 0.000000001, 0, false},
   493  	}
   494  	for _, ts := range equalityTests {
   495  		if ts.tol == 0 {
   496  			ts.tol = 1e-5
   497  		}
   498  		if equal := scalar.EqualWithinRel(ts.a, ts.b, ts.tol); equal != ts.equal {
   499  			t.Errorf("Relative equality of %g and %g with tolerance %g returned: %v. Expected: %v",
   500  				ts.a, ts.b, ts.tol, equal, ts.equal)
   501  		}
   502  	}
   503  }
   504  
   505  func TestEqualLengths(t *testing.T) {
   506  	t.Parallel()
   507  	s1 := []float64{1, 2, 3, 4}
   508  	s2 := []float64{1, 2, 3, 4}
   509  	s3 := []float64{1, 2, 3}
   510  	if !EqualLengths(s1, s2) {
   511  		t.Errorf("Equal lengths returned as unequal")
   512  	}
   513  	if EqualLengths(s1, s3) {
   514  		t.Errorf("Unequal lengths returned as equal")
   515  	}
   516  	if !EqualLengths(s1) {
   517  		t.Errorf("Single slice returned as unequal")
   518  	}
   519  	if !EqualLengths() {
   520  		t.Errorf("No slices returned as unequal")
   521  	}
   522  }
   523  
   524  func eqIntSlice(one, two []int) string {
   525  	if len(one) != len(two) {
   526  		return "Length mismatch"
   527  	}
   528  	for i, val := range one {
   529  		if val != two[i] {
   530  			return "Index " + strconv.Itoa(i) + " mismatch"
   531  		}
   532  	}
   533  	return ""
   534  }
   535  
   536  func TestFind(t *testing.T) {
   537  	t.Parallel()
   538  	s := []float64{3, 4, 1, 7, 5}
   539  	f := func(v float64) bool { return v > 3.5 }
   540  	allTrueInds := []int{1, 3, 4}
   541  
   542  	// Test finding first two elements
   543  	inds, err := Find(nil, f, s, 2)
   544  	if err != nil {
   545  		t.Errorf("Find first two: Improper error return")
   546  	}
   547  	trueInds := allTrueInds[:2]
   548  	str := eqIntSlice(inds, trueInds)
   549  	if str != "" {
   550  		t.Errorf("Find first two: " + str)
   551  	}
   552  
   553  	// Test finding no elements with non nil slice
   554  	inds = []int{1, 2, 3, 4, 5, 6}
   555  	inds, err = Find(inds, f, s, 0)
   556  	if err != nil {
   557  		t.Errorf("Find no elements: Improper error return")
   558  	}
   559  	str = eqIntSlice(inds, []int{})
   560  	if str != "" {
   561  		t.Errorf("Find no non-nil: " + str)
   562  	}
   563  
   564  	// Test finding first two elements with non nil slice
   565  	inds = []int{1, 2, 3, 4, 5, 6}
   566  	inds, err = Find(inds, f, s, 2)
   567  	if err != nil {
   568  		t.Errorf("Find first two non-nil: Improper error return")
   569  	}
   570  	str = eqIntSlice(inds, trueInds)
   571  	if str != "" {
   572  		t.Errorf("Find first two non-nil: " + str)
   573  	}
   574  
   575  	// Test finding too many elements
   576  	inds, err = Find(inds, f, s, 4)
   577  	if err == nil {
   578  		t.Errorf("Request too many: No error returned")
   579  	}
   580  	str = eqIntSlice(inds, allTrueInds)
   581  	if str != "" {
   582  		t.Errorf("Request too many: Does not match all of the inds: " + str)
   583  	}
   584  
   585  	// Test finding all elements
   586  	inds, err = Find(nil, f, s, -1)
   587  	if err != nil {
   588  		t.Errorf("Find all: Improper error returned")
   589  	}
   590  	str = eqIntSlice(inds, allTrueInds)
   591  	if str != "" {
   592  		t.Errorf("Find all: Does not match all of the inds: " + str)
   593  	}
   594  }
   595  
   596  func TestHasNaN(t *testing.T) {
   597  	t.Parallel()
   598  	for i, test := range []struct {
   599  		s   []float64
   600  		ans bool
   601  	}{
   602  		{},
   603  		{
   604  			s: []float64{1, 2, 3, 4},
   605  		},
   606  		{
   607  			s:   []float64{1, math.NaN(), 3, 4},
   608  			ans: true,
   609  		},
   610  		{
   611  			s:   []float64{1, 2, 3, math.NaN()},
   612  			ans: true,
   613  		},
   614  	} {
   615  		b := HasNaN(test.s)
   616  		if b != test.ans {
   617  			t.Errorf("HasNaN mismatch case %d. Expected %v, Found %v", i, test.ans, b)
   618  		}
   619  	}
   620  }
   621  
   622  func TestLogSpan(t *testing.T) {
   623  	t.Parallel()
   624  	receiver1 := make([]float64, 6)
   625  	truth := []float64{0.001, 0.01, 0.1, 1, 10, 100}
   626  	receiver2 := LogSpan(receiver1, 0.001, 100)
   627  	tst := make([]float64, 6)
   628  	for i := range truth {
   629  		tst[i] = receiver1[i] / truth[i]
   630  	}
   631  	comp := make([]float64, 6)
   632  	for i := range comp {
   633  		comp[i] = 1
   634  	}
   635  	areSlicesEqual(t, comp, tst, "Improper logspace from mutator")
   636  
   637  	for i := range truth {
   638  		tst[i] = receiver2[i] / truth[i]
   639  	}
   640  	areSlicesEqual(t, comp, tst, "Improper logspace from returned slice")
   641  
   642  	if !Panics(func() { LogSpan(nil, 1, 5) }) {
   643  		t.Errorf("Span accepts nil argument")
   644  	}
   645  	if !Panics(func() { LogSpan(make([]float64, 1), 1, 5) }) {
   646  		t.Errorf("Span accepts argument of len = 1")
   647  	}
   648  }
   649  
   650  func TestLogSumExp(t *testing.T) {
   651  	t.Parallel()
   652  	s := []float64{1, 2, 3, 4, 5}
   653  	val := LogSumExp(s)
   654  	// http://www.wolframalpha.com/input/?i=log%28exp%281%29+%2B+exp%282%29+%2B+exp%283%29+%2B+exp%284%29+%2B+exp%285%29%29
   655  	truth := 5.4519143959375933331957225109748087179338972737576824
   656  	if math.Abs(val-truth) > EqTolerance {
   657  		t.Errorf("Wrong logsumexp for many values")
   658  	}
   659  	s = []float64{1, 2}
   660  	// http://www.wolframalpha.com/input/?i=log%28exp%281%29+%2B+exp%282%29%29
   661  	truth = 2.3132616875182228340489954949678556419152800856703483
   662  	val = LogSumExp(s)
   663  	if math.Abs(val-truth) > EqTolerance {
   664  		t.Errorf("Wrong logsumexp for two values. %v expected, %v found", truth, val)
   665  	}
   666  	// This case would normally underflow
   667  	s = []float64{-1001, -1002, -1003, -1004, -1005}
   668  	// http://www.wolframalpha.com/input/?i=log%28exp%28-1001%29%2Bexp%28-1002%29%2Bexp%28-1003%29%2Bexp%28-1004%29%2Bexp%28-1005%29%29
   669  	truth = -1000.54808560406240666680427748902519128206610272624
   670  	val = LogSumExp(s)
   671  	if math.Abs(val-truth) > EqTolerance {
   672  		t.Errorf("Doesn't match for underflow case. %v expected, %v found", truth, val)
   673  	}
   674  	// positive infinite case
   675  	s = []float64{1, 2, 3, 4, 5, math.Inf(1)}
   676  	val = LogSumExp(s)
   677  	truth = math.Inf(1)
   678  	if val != truth {
   679  		t.Errorf("Doesn't match for pos Infinity case. %v expected, %v found", truth, val)
   680  	}
   681  	// negative infinite case
   682  	s = []float64{1, 2, 3, 4, 5, math.Inf(-1)}
   683  	val = LogSumExp(s)
   684  	truth = 5.4519143959375933331957225109748087179338972737576824 // same as first case
   685  	if math.Abs(val-truth) > EqTolerance {
   686  		t.Errorf("Wrong logsumexp for values with negative infinity")
   687  	}
   688  }
   689  
   690  func TestMaxAndIdx(t *testing.T) {
   691  	t.Parallel()
   692  	for _, test := range []struct {
   693  		in      []float64
   694  		wantIdx int
   695  		wantVal float64
   696  		desc    string
   697  	}{
   698  		{
   699  			in:      []float64{3, 4, 1, 7, 5},
   700  			wantIdx: 3,
   701  			wantVal: 7,
   702  			desc:    "with only finite entries",
   703  		},
   704  		{
   705  			in:      []float64{math.NaN(), 4, 1, 7, 5},
   706  			wantIdx: 3,
   707  			wantVal: 7,
   708  			desc:    "with leading NaN",
   709  		},
   710  		{
   711  			in:      []float64{math.NaN(), math.NaN(), math.NaN()},
   712  			wantIdx: 0,
   713  			wantVal: math.NaN(),
   714  			desc:    "when only NaN elements exist",
   715  		},
   716  		{
   717  			in:      []float64{math.NaN(), math.Inf(-1)},
   718  			wantIdx: 1,
   719  			wantVal: math.Inf(-1),
   720  			desc:    "leading NaN followed by -Inf",
   721  		},
   722  		{
   723  			in:      []float64{math.NaN(), math.Inf(1)},
   724  			wantIdx: 1,
   725  			wantVal: math.Inf(1),
   726  			desc:    "leading NaN followed by +Inf",
   727  		},
   728  	} {
   729  		ind := MaxIdx(test.in)
   730  		if ind != test.wantIdx {
   731  			t.Errorf("Wrong index "+test.desc+": got:%d want:%d", ind, test.wantIdx)
   732  		}
   733  		val := Max(test.in)
   734  		if !scalar.Same(val, test.wantVal) {
   735  			t.Errorf("Wrong value "+test.desc+": got:%f want:%f", val, test.wantVal)
   736  		}
   737  	}
   738  	if !Panics(func() { MaxIdx([]float64{}) }) {
   739  		t.Errorf("Expected panic with zero length")
   740  	}
   741  }
   742  
   743  func TestMinAndIdx(t *testing.T) {
   744  	t.Parallel()
   745  	for _, test := range []struct {
   746  		in      []float64
   747  		wantIdx int
   748  		wantVal float64
   749  		desc    string
   750  	}{
   751  		{
   752  			in:      []float64{3, 4, 1, 7, 5},
   753  			wantIdx: 2,
   754  			wantVal: 1,
   755  			desc:    "with only finite entries",
   756  		},
   757  		{
   758  			in:      []float64{math.NaN(), 4, 1, 7, 5},
   759  			wantIdx: 2,
   760  			wantVal: 1,
   761  			desc:    "with leading NaN",
   762  		},
   763  		{
   764  			in:      []float64{math.NaN(), math.NaN(), math.NaN()},
   765  			wantIdx: 0,
   766  			wantVal: math.NaN(),
   767  			desc:    "when only NaN elements exist",
   768  		},
   769  		{
   770  			in:      []float64{math.NaN(), math.Inf(-1)},
   771  			wantIdx: 1,
   772  			wantVal: math.Inf(-1),
   773  			desc:    "leading NaN followed by -Inf",
   774  		},
   775  		{
   776  			in:      []float64{math.NaN(), math.Inf(1)},
   777  			wantIdx: 1,
   778  			wantVal: math.Inf(1),
   779  			desc:    "leading NaN followed by +Inf",
   780  		},
   781  	} {
   782  		ind := MinIdx(test.in)
   783  		if ind != test.wantIdx {
   784  			t.Errorf("Wrong index "+test.desc+": got:%d want:%d", ind, test.wantIdx)
   785  		}
   786  		val := Min(test.in)
   787  		if !scalar.Same(val, test.wantVal) {
   788  			t.Errorf("Wrong value "+test.desc+": got:%f want:%f", val, test.wantVal)
   789  		}
   790  	}
   791  	if !Panics(func() { MinIdx([]float64{}) }) {
   792  		t.Errorf("Expected panic with zero length")
   793  	}
   794  }
   795  
   796  func TestMul(t *testing.T) {
   797  	t.Parallel()
   798  	s1 := []float64{1, 2, 3}
   799  	s2 := []float64{1, 2, 3}
   800  	ans := []float64{1, 4, 9}
   801  	Mul(s1, s2)
   802  	if !EqualApprox(s1, ans, EqTolerance) {
   803  		t.Errorf("Mul doesn't give correct answer")
   804  	}
   805  	s1short := []float64{1}
   806  	if !Panics(func() { Mul(s1short, s2) }) {
   807  		t.Errorf("Did not panic with unequal lengths")
   808  	}
   809  	s2short := []float64{1}
   810  	if !Panics(func() { Mul(s1, s2short) }) {
   811  		t.Errorf("Did not panic with unequal lengths")
   812  	}
   813  }
   814  
   815  func TestMulTo(t *testing.T) {
   816  	t.Parallel()
   817  	s1 := []float64{1, 2, 3}
   818  	s1orig := []float64{1, 2, 3}
   819  	s2 := []float64{1, 2, 3}
   820  	s2orig := []float64{1, 2, 3}
   821  	dst1 := make([]float64, 3)
   822  	ans := []float64{1, 4, 9}
   823  	dst2 := MulTo(dst1, s1, s2)
   824  	if !EqualApprox(dst1, ans, EqTolerance) {
   825  		t.Errorf("MulTo doesn't give correct answer in mutated slice")
   826  	}
   827  	if !EqualApprox(dst2, ans, EqTolerance) {
   828  		t.Errorf("MulTo doesn't give correct answer in returned slice")
   829  	}
   830  	if !EqualApprox(s1, s1orig, EqTolerance) {
   831  		t.Errorf("S1 changes during multo")
   832  	}
   833  	if !EqualApprox(s2, s2orig, EqTolerance) {
   834  		t.Errorf("s2 changes during multo")
   835  	}
   836  	MulTo(dst1, s1, s2)
   837  	if !EqualApprox(dst1, ans, EqTolerance) {
   838  		t.Errorf("MulTo doesn't give correct answer reusing dst")
   839  	}
   840  	dstShort := []float64{1}
   841  	if !Panics(func() { MulTo(dstShort, s1, s2) }) {
   842  		t.Errorf("Did not panic with s1 wrong length")
   843  	}
   844  	s1short := []float64{1}
   845  	if !Panics(func() { MulTo(dst1, s1short, s2) }) {
   846  		t.Errorf("Did not panic with s1 wrong length")
   847  	}
   848  	s2short := []float64{1}
   849  	if !Panics(func() { MulTo(dst1, s1, s2short) }) {
   850  		t.Errorf("Did not panic with s2 wrong length")
   851  	}
   852  }
   853  
   854  func TestNearestIdx(t *testing.T) {
   855  	t.Parallel()
   856  	for _, test := range []struct {
   857  		in    []float64
   858  		query float64
   859  		want  int
   860  		desc  string
   861  	}{
   862  		{
   863  			in:    []float64{6.2, 3, 5, 6.2, 8},
   864  			query: 2,
   865  			want:  1,
   866  			desc:  "Wrong index returned when value is less than all of elements",
   867  		},
   868  		{
   869  			in:    []float64{6.2, 3, 5, 6.2, 8},
   870  			query: 9,
   871  			want:  4,
   872  			desc:  "Wrong index returned when value is greater than all of elements",
   873  		},
   874  		{
   875  			in:    []float64{6.2, 3, 5, 6.2, 8},
   876  			query: 3.1,
   877  			want:  1,
   878  			desc:  "Wrong index returned when value is greater than closest element",
   879  		},
   880  		{
   881  			in:    []float64{6.2, 3, 5, 6.2, 8},
   882  			query: 2.9,
   883  			want:  1,
   884  			desc:  "Wrong index returned when value is less than closest element",
   885  		},
   886  		{
   887  			in:    []float64{6.2, 3, 5, 6.2, 8},
   888  			query: 3,
   889  			want:  1,
   890  			desc:  "Wrong index returned when value is equal to element",
   891  		},
   892  		{
   893  			in:    []float64{6.2, 3, 5, 6.2, 8},
   894  			query: 6.2,
   895  			want:  0,
   896  			desc:  "Wrong index returned when value is equal to several elements",
   897  		},
   898  		{
   899  			in:    []float64{6.2, 3, 5, 6.2, 8},
   900  			query: 4,
   901  			want:  1,
   902  			desc:  "Wrong index returned when value is exactly between two closest elements",
   903  		},
   904  		{
   905  			in:    []float64{math.NaN(), 3, 2, -1},
   906  			query: 2,
   907  			want:  2,
   908  			desc:  "Wrong index returned when initial element is NaN",
   909  		},
   910  		{
   911  			in:    []float64{0, math.NaN(), -1, 2},
   912  			query: math.NaN(),
   913  			want:  0,
   914  			desc:  "Wrong index returned when query is NaN and a NaN element exists",
   915  		},
   916  		{
   917  			in:    []float64{0, math.NaN(), -1, 2},
   918  			query: math.Inf(1),
   919  			want:  3,
   920  			desc:  "Wrong index returned when query is +Inf and no +Inf element exists",
   921  		},
   922  		{
   923  			in:    []float64{0, math.NaN(), -1, 2},
   924  			query: math.Inf(-1),
   925  			want:  2,
   926  			desc:  "Wrong index returned when query is -Inf and no -Inf element exists",
   927  		},
   928  		{
   929  			in:    []float64{math.NaN(), math.NaN(), math.NaN()},
   930  			query: 1,
   931  			want:  0,
   932  			desc:  "Wrong index returned when query is a number and only NaN elements exist",
   933  		},
   934  		{
   935  			in:    []float64{math.NaN(), math.Inf(-1)},
   936  			query: 1,
   937  			want:  1,
   938  			desc:  "Wrong index returned when query is a number and single NaN precedes -Inf",
   939  		},
   940  	} {
   941  		ind := NearestIdx(test.in, test.query)
   942  		if ind != test.want {
   943  			t.Errorf(test.desc+": got:%d want:%d", ind, test.want)
   944  		}
   945  	}
   946  	if !Panics(func() { NearestIdx([]float64{}, 0) }) {
   947  		t.Errorf("Expected panic with zero length")
   948  	}
   949  }
   950  
   951  func TestNearestIdxForSpan(t *testing.T) {
   952  	t.Parallel()
   953  	for i, test := range []struct {
   954  		length int
   955  		lower  float64
   956  		upper  float64
   957  		value  float64
   958  		idx    int
   959  	}{
   960  		{
   961  			length: 13,
   962  			lower:  7,
   963  			upper:  8.2,
   964  			value:  6,
   965  			idx:    0,
   966  		},
   967  		{
   968  			length: 13,
   969  			lower:  7,
   970  			upper:  8.2,
   971  			value:  10,
   972  			idx:    12,
   973  		},
   974  		{
   975  			length: 13,
   976  			lower:  7,
   977  			upper:  8.2,
   978  			value:  7.19,
   979  			idx:    2,
   980  		},
   981  		{
   982  			length: 13,
   983  			lower:  7,
   984  			upper:  8.2,
   985  			value:  7.21,
   986  			idx:    2,
   987  		},
   988  		{
   989  			length: 13,
   990  			lower:  7,
   991  			upper:  8.2,
   992  			value:  7.2,
   993  			idx:    2,
   994  		},
   995  		{
   996  			length: 13,
   997  			lower:  7,
   998  			upper:  8.2,
   999  			value:  7.151,
  1000  			idx:    2,
  1001  		},
  1002  		{
  1003  			length: 13,
  1004  			lower:  7,
  1005  			upper:  8.2,
  1006  			value:  7.249,
  1007  			idx:    2,
  1008  		},
  1009  		{
  1010  			length: 4,
  1011  			lower:  math.Inf(-1),
  1012  			upper:  math.Inf(1),
  1013  			value:  math.Copysign(0, -1),
  1014  			idx:    0,
  1015  		},
  1016  		{
  1017  			length: 5,
  1018  			lower:  math.Inf(-1),
  1019  			upper:  math.Inf(1),
  1020  			value:  0,
  1021  			idx:    2,
  1022  		},
  1023  		{
  1024  			length: 5,
  1025  			lower:  math.Inf(-1),
  1026  			upper:  math.Inf(1),
  1027  			value:  math.Inf(-1),
  1028  			idx:    0,
  1029  		},
  1030  		{
  1031  			length: 5,
  1032  			lower:  math.Inf(-1),
  1033  			upper:  math.Inf(1),
  1034  			value:  math.Inf(1),
  1035  			idx:    3,
  1036  		},
  1037  		{
  1038  			length: 4,
  1039  			lower:  math.Inf(-1),
  1040  			upper:  math.Inf(1),
  1041  			value:  0,
  1042  			idx:    2,
  1043  		},
  1044  		{
  1045  			length: 4,
  1046  			lower:  math.Inf(-1),
  1047  			upper:  math.Inf(1),
  1048  			value:  math.Inf(1),
  1049  			idx:    2,
  1050  		},
  1051  		{
  1052  			length: 4,
  1053  			lower:  math.Inf(-1),
  1054  			upper:  math.Inf(1),
  1055  			value:  math.Inf(-1),
  1056  			idx:    0,
  1057  		},
  1058  		{
  1059  			length: 5,
  1060  			lower:  math.Inf(1),
  1061  			upper:  math.Inf(1),
  1062  			value:  1,
  1063  			idx:    0,
  1064  		},
  1065  		{
  1066  			length: 5,
  1067  			lower:  math.NaN(),
  1068  			upper:  math.NaN(),
  1069  			value:  1,
  1070  			idx:    0,
  1071  		},
  1072  		{
  1073  			length: 5,
  1074  			lower:  0,
  1075  			upper:  1,
  1076  			value:  math.NaN(),
  1077  			idx:    0,
  1078  		},
  1079  		{
  1080  			length: 5,
  1081  			lower:  math.NaN(),
  1082  			upper:  1,
  1083  			value:  0,
  1084  			idx:    4,
  1085  		},
  1086  		{
  1087  			length: 5,
  1088  			lower:  math.Inf(-1),
  1089  			upper:  1,
  1090  			value:  math.Inf(-1),
  1091  			idx:    0,
  1092  		},
  1093  		{
  1094  			length: 5,
  1095  			lower:  math.Inf(-1),
  1096  			upper:  1,
  1097  			value:  0,
  1098  			idx:    4,
  1099  		},
  1100  		{
  1101  			length: 5,
  1102  			lower:  math.Inf(1),
  1103  			upper:  1,
  1104  			value:  math.Inf(1),
  1105  			idx:    0,
  1106  		},
  1107  		{
  1108  			length: 5,
  1109  			lower:  math.Inf(1),
  1110  			upper:  1,
  1111  			value:  0,
  1112  			idx:    4,
  1113  		},
  1114  		{
  1115  			length: 5,
  1116  			lower:  100,
  1117  			upper:  math.Inf(-1),
  1118  			value:  math.Inf(-1),
  1119  			idx:    4,
  1120  		},
  1121  		{
  1122  			length: 5,
  1123  			lower:  100,
  1124  			upper:  math.Inf(-1),
  1125  			value:  200,
  1126  			idx:    0,
  1127  		},
  1128  		{
  1129  			length: 5,
  1130  			lower:  100,
  1131  			upper:  math.Inf(1),
  1132  			value:  math.Inf(1),
  1133  			idx:    4,
  1134  		},
  1135  		{
  1136  			length: 5,
  1137  			lower:  100,
  1138  			upper:  math.Inf(1),
  1139  			value:  200,
  1140  			idx:    0,
  1141  		},
  1142  		{
  1143  			length: 5,
  1144  			lower:  -1,
  1145  			upper:  2,
  1146  			value:  math.Inf(-1),
  1147  			idx:    0,
  1148  		},
  1149  		{
  1150  			length: 5,
  1151  			lower:  -1,
  1152  			upper:  2,
  1153  			value:  math.Inf(1),
  1154  			idx:    4,
  1155  		},
  1156  		{
  1157  			length: 5,
  1158  			lower:  1,
  1159  			upper:  -2,
  1160  			value:  math.Inf(-1),
  1161  			idx:    4,
  1162  		},
  1163  		{
  1164  			length: 5,
  1165  			lower:  1,
  1166  			upper:  -2,
  1167  			value:  math.Inf(1),
  1168  			idx:    0,
  1169  		},
  1170  		{
  1171  			length: 5,
  1172  			lower:  2,
  1173  			upper:  0,
  1174  			value:  3,
  1175  			idx:    0,
  1176  		},
  1177  		{
  1178  			length: 5,
  1179  			lower:  2,
  1180  			upper:  0,
  1181  			value:  -1,
  1182  			idx:    4,
  1183  		},
  1184  	} {
  1185  		if idx := NearestIdxForSpan(test.length, test.lower, test.upper, test.value); test.idx != idx {
  1186  			t.Errorf("Case %v mismatch: Want: %v, Got: %v", i, test.idx, idx)
  1187  		}
  1188  	}
  1189  	if !Panics(func() { NearestIdxForSpan(1, 0, 1, 0.5) }) {
  1190  		t.Errorf("Expected panic for short span length")
  1191  	}
  1192  }
  1193  
  1194  func TestNorm(t *testing.T) {
  1195  	t.Parallel()
  1196  	s := []float64{-1, -3.4, 5, -6}
  1197  	val := Norm(s, math.Inf(1))
  1198  	truth := 6.0
  1199  	if math.Abs(val-truth) > EqTolerance {
  1200  		t.Errorf("Doesn't match for inf norm. %v expected, %v found", truth, val)
  1201  	}
  1202  	// http://www.wolframalpha.com/input/?i=%28%28-1%29%5E2+%2B++%28-3.4%29%5E2+%2B+5%5E2%2B++6%5E2%29%5E%281%2F2%29
  1203  	val = Norm(s, 2)
  1204  	truth = 8.5767126569566267590651614132751986658027271236078592
  1205  	if math.Abs(val-truth) > EqTolerance {
  1206  		t.Errorf("Doesn't match for inf norm. %v expected, %v found", truth, val)
  1207  	}
  1208  	// http://www.wolframalpha.com/input/?i=%28%28%7C-1%7C%29%5E3+%2B++%28%7C-3.4%7C%29%5E3+%2B+%7C5%7C%5E3%2B++%7C6%7C%5E3%29%5E%281%2F3%29
  1209  	val = Norm(s, 3)
  1210  	truth = 7.2514321388020228478109121239004816430071237369356233
  1211  	if math.Abs(val-truth) > EqTolerance {
  1212  		t.Errorf("Doesn't match for inf norm. %v expected, %v found", truth, val)
  1213  	}
  1214  
  1215  	//http://www.wolframalpha.com/input/?i=%7C-1%7C+%2B+%7C-3.4%7C+%2B+%7C5%7C%2B++%7C6%7C
  1216  	val = Norm(s, 1)
  1217  	truth = 15.4
  1218  	if math.Abs(val-truth) > EqTolerance {
  1219  		t.Errorf("Doesn't match for inf norm. %v expected, %v found", truth, val)
  1220  	}
  1221  }
  1222  
  1223  func TestProd(t *testing.T) {
  1224  	t.Parallel()
  1225  	s := []float64{}
  1226  	val := Prod(s)
  1227  	if val != 1 {
  1228  		t.Errorf("Val not returned as default when slice length is zero")
  1229  	}
  1230  	s = []float64{3, 4, 1, 7, 5}
  1231  	val = Prod(s)
  1232  	if val != 420 {
  1233  		t.Errorf("Wrong prod returned. Expected %v returned %v", 420, val)
  1234  	}
  1235  }
  1236  
  1237  func TestReverse(t *testing.T) {
  1238  	t.Parallel()
  1239  	for _, s := range [][]float64{
  1240  		{0},
  1241  		{1, 0},
  1242  		{2, 1, 0},
  1243  		{3, 2, 1, 0},
  1244  		{9, 8, 7, 6, 5, 4, 3, 2, 1, 0},
  1245  	} {
  1246  		Reverse(s)
  1247  		for i, v := range s {
  1248  			if v != float64(i) {
  1249  				t.Errorf("unexpected values for element %d: got:%v want:%v", i, v, i)
  1250  			}
  1251  		}
  1252  	}
  1253  }
  1254  
  1255  func TestSame(t *testing.T) {
  1256  	t.Parallel()
  1257  	s1 := []float64{1, 2, 3, 4}
  1258  	s2 := []float64{1, 2, 3, 4}
  1259  	if !Same(s1, s2) {
  1260  		t.Errorf("Equal slices returned as unequal")
  1261  	}
  1262  	s2 = []float64{1, 2, 3, 4 + 1e-14}
  1263  	if Same(s1, s2) {
  1264  		t.Errorf("Unequal slices returned as equal")
  1265  	}
  1266  	if Same(s1, []float64{}) {
  1267  		t.Errorf("Unequal slice lengths returned as equal")
  1268  	}
  1269  	s1 = []float64{1, 2, math.NaN(), 4}
  1270  	s2 = []float64{1, 2, math.NaN(), 4}
  1271  	if !Same(s1, s2) {
  1272  		t.Errorf("Slices with matching NaN values returned as unequal")
  1273  	}
  1274  	s1 = []float64{1, 2, math.NaN(), 4}
  1275  	s2 = []float64{1, math.NaN(), 3, 4}
  1276  	if Same(s1, s2) {
  1277  		t.Errorf("Slices with unmatching NaN values returned as equal")
  1278  	}
  1279  }
  1280  
  1281  func TestScale(t *testing.T) {
  1282  	t.Parallel()
  1283  	s := []float64{3, 4, 1, 7, 5}
  1284  	c := 5.0
  1285  	truth := []float64{15, 20, 5, 35, 25}
  1286  	Scale(c, s)
  1287  	areSlicesEqual(t, truth, s, "Bad scaling")
  1288  }
  1289  
  1290  func TestScaleTo(t *testing.T) {
  1291  	t.Parallel()
  1292  	s := []float64{3, 4, 1, 7, 5}
  1293  	sCopy := make([]float64, len(s))
  1294  	copy(sCopy, s)
  1295  	c := 5.0
  1296  	truth := []float64{15, 20, 5, 35, 25}
  1297  	dst := make([]float64, len(s))
  1298  	ScaleTo(dst, c, s)
  1299  	if !Same(dst, truth) {
  1300  		t.Errorf("Scale to does not match. Got %v, want %v", dst, truth)
  1301  	}
  1302  	if !Same(s, sCopy) {
  1303  		t.Errorf("Source modified during call. Got %v, want %v", s, sCopy)
  1304  	}
  1305  	if !Panics(func() { ScaleTo(dst, 0, []float64{1}) }) {
  1306  		t.Errorf("Expected panic with different slice lengths")
  1307  	}
  1308  }
  1309  
  1310  func TestSpan(t *testing.T) {
  1311  	t.Parallel()
  1312  	receiver1 := make([]float64, 5)
  1313  	truth := []float64{1, 2, 3, 4, 5}
  1314  	receiver2 := Span(receiver1, 1, 5)
  1315  	areSlicesEqual(t, truth, receiver1, "Improper linspace from mutator")
  1316  	areSlicesEqual(t, truth, receiver2, "Improper linspace from returned slice")
  1317  	receiver1 = make([]float64, 6)
  1318  	truth = []float64{0, 0.2, 0.4, 0.6, 0.8, 1.0}
  1319  	Span(receiver1, 0, 1)
  1320  	areSlicesEqual(t, truth, receiver1, "Improper linspace")
  1321  	if !Panics(func() { Span(nil, 1, 5) }) {
  1322  		t.Errorf("Span accepts nil argument")
  1323  	}
  1324  	if !Panics(func() { Span(make([]float64, 1), 1, 5) }) {
  1325  		t.Errorf("Span accepts argument of len = 1")
  1326  	}
  1327  
  1328  	for _, test := range []struct {
  1329  		n    int
  1330  		l, u float64
  1331  		want []float64
  1332  	}{
  1333  		{
  1334  			n: 4, l: math.Inf(-1), u: math.Inf(1),
  1335  			want: []float64{math.Inf(-1), math.Inf(-1), math.Inf(1), math.Inf(1)},
  1336  		},
  1337  		{
  1338  			n: 4, l: math.Inf(1), u: math.Inf(-1),
  1339  			want: []float64{math.Inf(1), math.Inf(1), math.Inf(-1), math.Inf(-1)},
  1340  		},
  1341  		{
  1342  			n: 5, l: math.Inf(-1), u: math.Inf(1),
  1343  			want: []float64{math.Inf(-1), math.Inf(-1), 0, math.Inf(1), math.Inf(1)},
  1344  		},
  1345  		{
  1346  			n: 5, l: math.Inf(1), u: math.Inf(-1),
  1347  			want: []float64{math.Inf(1), math.Inf(1), 0, math.Inf(-1), math.Inf(-1)},
  1348  		},
  1349  		{
  1350  			n: 5, l: math.Inf(1), u: math.Inf(1),
  1351  			want: []float64{math.Inf(1), math.Inf(1), math.Inf(1), math.Inf(1), math.Inf(1)},
  1352  		},
  1353  		{
  1354  			n: 5, l: math.Inf(-1), u: math.Inf(-1),
  1355  			want: []float64{math.Inf(-1), math.Inf(-1), math.Inf(-1), math.Inf(-1), math.Inf(-1)},
  1356  		},
  1357  		{
  1358  			n: 5, l: math.Inf(-1), u: math.NaN(),
  1359  			want: []float64{math.Inf(-1), math.NaN(), math.NaN(), math.NaN(), math.NaN()},
  1360  		},
  1361  		{
  1362  			n: 5, l: math.Inf(1), u: math.NaN(),
  1363  			want: []float64{math.Inf(1), math.NaN(), math.NaN(), math.NaN(), math.NaN()},
  1364  		},
  1365  		{
  1366  			n: 5, l: math.NaN(), u: math.Inf(-1),
  1367  			want: []float64{math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.Inf(-1)},
  1368  		},
  1369  		{
  1370  			n: 5, l: math.NaN(), u: math.Inf(1),
  1371  			want: []float64{math.NaN(), math.NaN(), math.NaN(), math.NaN(), math.Inf(1)},
  1372  		},
  1373  		{
  1374  			n: 5, l: 42, u: math.Inf(-1),
  1375  			want: []float64{42, math.Inf(-1), math.Inf(-1), math.Inf(-1), math.Inf(-1)},
  1376  		},
  1377  		{
  1378  			n: 5, l: 42, u: math.Inf(1),
  1379  			want: []float64{42, math.Inf(1), math.Inf(1), math.Inf(1), math.Inf(1)},
  1380  		},
  1381  		{
  1382  			n: 5, l: 42, u: math.NaN(),
  1383  			want: []float64{42, math.NaN(), math.NaN(), math.NaN(), math.NaN()},
  1384  		},
  1385  		{
  1386  			n: 5, l: math.Inf(-1), u: 42,
  1387  			want: []float64{math.Inf(-1), math.Inf(-1), math.Inf(-1), math.Inf(-1), 42},
  1388  		},
  1389  		{
  1390  			n: 5, l: math.Inf(1), u: 42,
  1391  			want: []float64{math.Inf(1), math.Inf(1), math.Inf(1), math.Inf(1), 42},
  1392  		},
  1393  		{
  1394  			n: 5, l: math.NaN(), u: 42,
  1395  			want: []float64{math.NaN(), math.NaN(), math.NaN(), math.NaN(), 42},
  1396  		},
  1397  	} {
  1398  		got := Span(make([]float64, test.n), test.l, test.u)
  1399  		areSlicesSame(t, test.want, got,
  1400  			fmt.Sprintf("Unexpected slice of length %d for %f to %f", test.n, test.l, test.u))
  1401  	}
  1402  }
  1403  
  1404  func TestSub(t *testing.T) {
  1405  	t.Parallel()
  1406  	s := []float64{3, 4, 1, 7, 5}
  1407  	v := []float64{1, 2, 3, 4, 5}
  1408  	truth := []float64{2, 2, -2, 3, 0}
  1409  	Sub(s, v)
  1410  	areSlicesEqual(t, truth, s, "Bad subtract")
  1411  	// Test that it panics
  1412  	if !Panics(func() { Sub(make([]float64, 2), make([]float64, 3)) }) {
  1413  		t.Errorf("Did not panic with length mismatch")
  1414  	}
  1415  }
  1416  
  1417  func TestSubTo(t *testing.T) {
  1418  	t.Parallel()
  1419  	s := []float64{3, 4, 1, 7, 5}
  1420  	v := []float64{1, 2, 3, 4, 5}
  1421  	truth := []float64{2, 2, -2, 3, 0}
  1422  	dst1 := make([]float64, len(s))
  1423  	dst2 := SubTo(dst1, s, v)
  1424  	areSlicesEqual(t, truth, dst1, "Bad subtract from mutator")
  1425  	areSlicesEqual(t, truth, dst2, "Bad subtract from returned slice")
  1426  	// Test that all mismatch combinations panic
  1427  	if !Panics(func() { SubTo(make([]float64, 2), make([]float64, 3), make([]float64, 3)) }) {
  1428  		t.Errorf("Did not panic with dst different length")
  1429  	}
  1430  	if !Panics(func() { SubTo(make([]float64, 3), make([]float64, 2), make([]float64, 3)) }) {
  1431  		t.Errorf("Did not panic with subtractor different length")
  1432  	}
  1433  	if !Panics(func() { SubTo(make([]float64, 3), make([]float64, 3), make([]float64, 2)) }) {
  1434  		t.Errorf("Did not panic with subtractee different length")
  1435  	}
  1436  }
  1437  
  1438  func TestSum(t *testing.T) {
  1439  	t.Parallel()
  1440  	s := []float64{}
  1441  	val := Sum(s)
  1442  	if val != 0 {
  1443  		t.Errorf("Val not returned as default when slice length is zero")
  1444  	}
  1445  	s = []float64{3, 4, 1, 7, 5}
  1446  	val = Sum(s)
  1447  	if val != 20 {
  1448  		t.Errorf("Wrong sum returned")
  1449  	}
  1450  }
  1451  
  1452  func TestWithin(t *testing.T) {
  1453  	t.Parallel()
  1454  	for i, test := range []struct {
  1455  		s      []float64
  1456  		v      float64
  1457  		idx    int
  1458  		panics bool
  1459  	}{
  1460  		{
  1461  			s:   []float64{1, 2, 5, 9},
  1462  			v:   1,
  1463  			idx: 0,
  1464  		},
  1465  		{
  1466  			s:   []float64{1, 2, 5, 9},
  1467  			v:   9,
  1468  			idx: -1,
  1469  		},
  1470  		{
  1471  			s:   []float64{1, 2, 5, 9},
  1472  			v:   1.5,
  1473  			idx: 0,
  1474  		},
  1475  		{
  1476  			s:   []float64{1, 2, 5, 9},
  1477  			v:   2,
  1478  			idx: 1,
  1479  		},
  1480  		{
  1481  			s:   []float64{1, 2, 5, 9},
  1482  			v:   2.5,
  1483  			idx: 1,
  1484  		},
  1485  		{
  1486  			s:   []float64{1, 2, 5, 9},
  1487  			v:   -3,
  1488  			idx: -1,
  1489  		},
  1490  		{
  1491  			s:   []float64{1, 2, 5, 9},
  1492  			v:   15,
  1493  			idx: -1,
  1494  		},
  1495  		{
  1496  			s:   []float64{1, 2, 5, 9},
  1497  			v:   math.NaN(),
  1498  			idx: -1,
  1499  		},
  1500  		{
  1501  			s:      []float64{5, 2, 6},
  1502  			panics: true,
  1503  		},
  1504  		{
  1505  			panics: true,
  1506  		},
  1507  		{
  1508  			s:      []float64{1},
  1509  			panics: true,
  1510  		},
  1511  	} {
  1512  		var idx int
  1513  		panics := Panics(func() { idx = Within(test.s, test.v) })
  1514  		if panics {
  1515  			if !test.panics {
  1516  				t.Errorf("Case %v: bad panic", i)
  1517  			}
  1518  			continue
  1519  		}
  1520  		if test.panics {
  1521  			if !panics {
  1522  				t.Errorf("Case %v: did not panic when it should", i)
  1523  			}
  1524  			continue
  1525  		}
  1526  		if idx != test.idx {
  1527  			t.Errorf("Case %v: Idx mismatch. Want: %v, got: %v", i, test.idx, idx)
  1528  		}
  1529  	}
  1530  }
  1531  
  1532  func TestSumCompensated(t *testing.T) {
  1533  	t.Parallel()
  1534  	k := 100000
  1535  	s1 := make([]float64, 2*k+1)
  1536  	for i := -k; i <= k; i++ {
  1537  		s1[i+k] = 0.2 * float64(i)
  1538  	}
  1539  	s2 := make([]float64, k+1)
  1540  	for i := 0; i < k; i++ {
  1541  		s2[i] = 10. / float64(k)
  1542  	}
  1543  	s2[k] = -10
  1544  
  1545  	for i, test := range []struct {
  1546  		s    []float64
  1547  		want float64
  1548  	}{
  1549  		{
  1550  			// Fails if we use simple Sum.
  1551  			s:    s1,
  1552  			want: 0,
  1553  		},
  1554  		{
  1555  			// Fails if we use simple Sum.
  1556  			s:    s2,
  1557  			want: 0,
  1558  		},
  1559  		{
  1560  			s:    []float64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
  1561  			want: 55,
  1562  		},
  1563  		{
  1564  			s:    []float64{1.2e20, 0.1, -2.4e20, -0.1, 1.2e20, 0.2, 0.2},
  1565  			want: 0.4,
  1566  		},
  1567  		{
  1568  			s:    []float64{1, 1e100, 1, -1e100},
  1569  			want: 2,
  1570  		},
  1571  	} {
  1572  		got := SumCompensated(test.s)
  1573  		if math.Abs(got-test.want) > EqTolerance {
  1574  			t.Errorf("Wrong sum returned in test case %d. Want: %g, got: %g", i, test.want, got)
  1575  		}
  1576  	}
  1577  }
  1578  
  1579  func randomSlice(l int, src rand.Source) []float64 {
  1580  	rnd := rand.New(src)
  1581  	s := make([]float64, l)
  1582  	for i := range s {
  1583  		s[i] = rnd.Float64()
  1584  	}
  1585  	return s
  1586  }
  1587  
  1588  func benchmarkMin(b *testing.B, size int) {
  1589  	src := rand.NewSource(1)
  1590  	s := randomSlice(size, src)
  1591  	b.ResetTimer()
  1592  	for i := 0; i < b.N; i++ {
  1593  		Min(s)
  1594  	}
  1595  }
  1596  func BenchmarkMinSmall(b *testing.B) { benchmarkMin(b, Small) }
  1597  func BenchmarkMinMed(b *testing.B)   { benchmarkMin(b, Medium) }
  1598  func BenchmarkMinLarge(b *testing.B) { benchmarkMin(b, Large) }
  1599  func BenchmarkMinHuge(b *testing.B)  { benchmarkMin(b, Huge) }
  1600  
  1601  func benchmarkAdd(b *testing.B, size int) {
  1602  	src := rand.NewSource(1)
  1603  	s1 := randomSlice(size, src)
  1604  	s2 := randomSlice(size, src)
  1605  	b.ResetTimer()
  1606  	for i := 0; i < b.N; i++ {
  1607  		Add(s1, s2)
  1608  	}
  1609  }
  1610  func BenchmarkAddSmall(b *testing.B) { benchmarkAdd(b, Small) }
  1611  func BenchmarkAddMed(b *testing.B)   { benchmarkAdd(b, Medium) }
  1612  func BenchmarkAddLarge(b *testing.B) { benchmarkAdd(b, Large) }
  1613  func BenchmarkAddHuge(b *testing.B)  { benchmarkAdd(b, Huge) }
  1614  
  1615  func benchmarkAddTo(b *testing.B, size int) {
  1616  	src := rand.NewSource(1)
  1617  	s1 := randomSlice(size, src)
  1618  	s2 := randomSlice(size, src)
  1619  	dst := randomSlice(size, src)
  1620  	b.ResetTimer()
  1621  	for i := 0; i < b.N; i++ {
  1622  		AddTo(dst, s1, s2)
  1623  	}
  1624  }
  1625  func BenchmarkAddToSmall(b *testing.B) { benchmarkAddTo(b, Small) }
  1626  func BenchmarkAddToMed(b *testing.B)   { benchmarkAddTo(b, Medium) }
  1627  func BenchmarkAddToLarge(b *testing.B) { benchmarkAddTo(b, Large) }
  1628  func BenchmarkAddToHuge(b *testing.B)  { benchmarkAddTo(b, Huge) }
  1629  
  1630  func benchmarkCumProd(b *testing.B, size int) {
  1631  	src := rand.NewSource(1)
  1632  	s := randomSlice(size, src)
  1633  	dst := randomSlice(size, src)
  1634  	b.ResetTimer()
  1635  	for i := 0; i < b.N; i++ {
  1636  		CumProd(dst, s)
  1637  	}
  1638  }
  1639  func BenchmarkCumProdSmall(b *testing.B) { benchmarkCumProd(b, Small) }
  1640  func BenchmarkCumProdMed(b *testing.B)   { benchmarkCumProd(b, Medium) }
  1641  func BenchmarkCumProdLarge(b *testing.B) { benchmarkCumProd(b, Large) }
  1642  func BenchmarkCumProdHuge(b *testing.B)  { benchmarkCumProd(b, Huge) }
  1643  
  1644  func benchmarkCumSum(b *testing.B, size int) {
  1645  	src := rand.NewSource(1)
  1646  	s := randomSlice(size, src)
  1647  	dst := randomSlice(size, src)
  1648  	b.ResetTimer()
  1649  	for i := 0; i < b.N; i++ {
  1650  		CumSum(dst, s)
  1651  	}
  1652  }
  1653  func BenchmarkCumSumSmall(b *testing.B) { benchmarkCumSum(b, Small) }
  1654  func BenchmarkCumSumMed(b *testing.B)   { benchmarkCumSum(b, Medium) }
  1655  func BenchmarkCumSumLarge(b *testing.B) { benchmarkCumSum(b, Large) }
  1656  func BenchmarkCumSumHuge(b *testing.B)  { benchmarkCumSum(b, Huge) }
  1657  
  1658  func benchmarkDiv(b *testing.B, size int) {
  1659  	src := rand.NewSource(1)
  1660  	s := randomSlice(size, src)
  1661  	dst := randomSlice(size, src)
  1662  	b.ResetTimer()
  1663  	for i := 0; i < b.N; i++ {
  1664  		Div(dst, s)
  1665  	}
  1666  }
  1667  func BenchmarkDivSmall(b *testing.B) { benchmarkDiv(b, Small) }
  1668  func BenchmarkDivMed(b *testing.B)   { benchmarkDiv(b, Medium) }
  1669  func BenchmarkDivLarge(b *testing.B) { benchmarkDiv(b, Large) }
  1670  func BenchmarkDivHuge(b *testing.B)  { benchmarkDiv(b, Huge) }
  1671  
  1672  func benchmarkDivTo(b *testing.B, size int) {
  1673  	src := rand.NewSource(1)
  1674  	s1 := randomSlice(size, src)
  1675  	s2 := randomSlice(size, src)
  1676  	dst := randomSlice(size, src)
  1677  	b.ResetTimer()
  1678  	for i := 0; i < b.N; i++ {
  1679  		DivTo(dst, s1, s2)
  1680  	}
  1681  }
  1682  func BenchmarkDivToSmall(b *testing.B) { benchmarkDivTo(b, Small) }
  1683  func BenchmarkDivToMed(b *testing.B)   { benchmarkDivTo(b, Medium) }
  1684  func BenchmarkDivToLarge(b *testing.B) { benchmarkDivTo(b, Large) }
  1685  func BenchmarkDivToHuge(b *testing.B)  { benchmarkDivTo(b, Huge) }
  1686  
  1687  func benchmarkSub(b *testing.B, size int) {
  1688  	src := rand.NewSource(1)
  1689  	s1 := randomSlice(size, src)
  1690  	s2 := randomSlice(size, src)
  1691  	b.ResetTimer()
  1692  	for i := 0; i < b.N; i++ {
  1693  		Sub(s1, s2)
  1694  	}
  1695  }
  1696  func BenchmarkSubSmall(b *testing.B) { benchmarkSub(b, Small) }
  1697  func BenchmarkSubMed(b *testing.B)   { benchmarkSub(b, Medium) }
  1698  func BenchmarkSubLarge(b *testing.B) { benchmarkSub(b, Large) }
  1699  func BenchmarkSubHuge(b *testing.B)  { benchmarkSub(b, Huge) }
  1700  
  1701  func benchmarkSubTo(b *testing.B, size int) {
  1702  	src := rand.NewSource(1)
  1703  	s1 := randomSlice(size, src)
  1704  	s2 := randomSlice(size, src)
  1705  	dst := randomSlice(size, src)
  1706  	b.ResetTimer()
  1707  	for i := 0; i < b.N; i++ {
  1708  		SubTo(dst, s1, s2)
  1709  	}
  1710  }
  1711  func BenchmarkSubToSmall(b *testing.B) { benchmarkSubTo(b, Small) }
  1712  func BenchmarkSubToMed(b *testing.B)   { benchmarkSubTo(b, Medium) }
  1713  func BenchmarkSubToLarge(b *testing.B) { benchmarkSubTo(b, Large) }
  1714  func BenchmarkSubToHuge(b *testing.B)  { benchmarkSubTo(b, Huge) }
  1715  
  1716  func benchmarkLogSumExp(b *testing.B, size int) {
  1717  	src := rand.NewSource(1)
  1718  	s := randomSlice(size, src)
  1719  	b.ResetTimer()
  1720  	for i := 0; i < b.N; i++ {
  1721  		LogSumExp(s)
  1722  	}
  1723  }
  1724  func BenchmarkLogSumExpSmall(b *testing.B) { benchmarkLogSumExp(b, Small) }
  1725  func BenchmarkLogSumExpMed(b *testing.B)   { benchmarkLogSumExp(b, Medium) }
  1726  func BenchmarkLogSumExpLarge(b *testing.B) { benchmarkLogSumExp(b, Large) }
  1727  func BenchmarkLogSumExpHuge(b *testing.B)  { benchmarkLogSumExp(b, Huge) }
  1728  
  1729  func benchmarkDot(b *testing.B, size int) {
  1730  	src := rand.NewSource(1)
  1731  	s1 := randomSlice(size, src)
  1732  	s2 := randomSlice(size, src)
  1733  	b.ResetTimer()
  1734  	for i := 0; i < b.N; i++ {
  1735  		Dot(s1, s2)
  1736  	}
  1737  }
  1738  func BenchmarkDotSmall(b *testing.B) { benchmarkDot(b, Small) }
  1739  func BenchmarkDotMed(b *testing.B)   { benchmarkDot(b, Medium) }
  1740  func BenchmarkDotLarge(b *testing.B) { benchmarkDot(b, Large) }
  1741  func BenchmarkDotHuge(b *testing.B)  { benchmarkDot(b, Huge) }
  1742  
  1743  func benchmarkAddScaledTo(b *testing.B, size int) {
  1744  	src := rand.NewSource(1)
  1745  	dst := randomSlice(size, src)
  1746  	y := randomSlice(size, src)
  1747  	s := randomSlice(size, src)
  1748  	b.ResetTimer()
  1749  	for i := 0; i < b.N; i++ {
  1750  		AddScaledTo(dst, y, 2.3, s)
  1751  	}
  1752  }
  1753  func BenchmarkAddScaledToSmall(b *testing.B)  { benchmarkAddScaledTo(b, Small) }
  1754  func BenchmarkAddScaledToMedium(b *testing.B) { benchmarkAddScaledTo(b, Medium) }
  1755  func BenchmarkAddScaledToLarge(b *testing.B)  { benchmarkAddScaledTo(b, Large) }
  1756  func BenchmarkAddScaledToHuge(b *testing.B)   { benchmarkAddScaledTo(b, Huge) }
  1757  
  1758  func benchmarkScale(b *testing.B, size int) {
  1759  	src := rand.NewSource(1)
  1760  	dst := randomSlice(size, src)
  1761  	b.ResetTimer()
  1762  	for i := 0; i < b.N; i += 2 {
  1763  		Scale(2.0, dst)
  1764  		Scale(0.5, dst)
  1765  	}
  1766  }
  1767  func BenchmarkScaleSmall(b *testing.B)  { benchmarkScale(b, Small) }
  1768  func BenchmarkScaleMedium(b *testing.B) { benchmarkScale(b, Medium) }
  1769  func BenchmarkScaleLarge(b *testing.B)  { benchmarkScale(b, Large) }
  1770  func BenchmarkScaleHuge(b *testing.B)   { benchmarkScale(b, Huge) }
  1771  
  1772  func benchmarkNorm2(b *testing.B, size int) {
  1773  	src := rand.NewSource(1)
  1774  	s := randomSlice(size, src)
  1775  	b.ResetTimer()
  1776  	for i := 0; i < b.N; i++ {
  1777  		Norm(s, 2)
  1778  	}
  1779  }
  1780  func BenchmarkNorm2Small(b *testing.B)  { benchmarkNorm2(b, Small) }
  1781  func BenchmarkNorm2Medium(b *testing.B) { benchmarkNorm2(b, Medium) }
  1782  func BenchmarkNorm2Large(b *testing.B)  { benchmarkNorm2(b, Large) }
  1783  func BenchmarkNorm2Huge(b *testing.B)   { benchmarkNorm2(b, Huge) }
  1784  
  1785  func benchmarkSumCompensated(b *testing.B, size int) {
  1786  	src := rand.NewSource(1)
  1787  	s := randomSlice(size, src)
  1788  	b.ResetTimer()
  1789  	for i := 0; i < b.N; i++ {
  1790  		SumCompensated(s)
  1791  	}
  1792  }
  1793  
  1794  func BenchmarkSumCompensatedSmall(b *testing.B)  { benchmarkSumCompensated(b, Small) }
  1795  func BenchmarkSumCompensatedMedium(b *testing.B) { benchmarkSumCompensated(b, Medium) }
  1796  func BenchmarkSumCompensatedLarge(b *testing.B)  { benchmarkSumCompensated(b, Large) }
  1797  func BenchmarkSumCompensatedHuge(b *testing.B)   { benchmarkSumCompensated(b, Huge) }
  1798  
  1799  func benchmarkSum(b *testing.B, size int) {
  1800  	src := rand.NewSource(1)
  1801  	s := randomSlice(size, src)
  1802  	b.ResetTimer()
  1803  	for i := 0; i < b.N; i++ {
  1804  		Sum(s)
  1805  	}
  1806  }
  1807  
  1808  func BenchmarkSumSmall(b *testing.B)  { benchmarkSum(b, Small) }
  1809  func BenchmarkSumMedium(b *testing.B) { benchmarkSum(b, Medium) }
  1810  func BenchmarkSumLarge(b *testing.B)  { benchmarkSum(b, Large) }
  1811  func BenchmarkSumHuge(b *testing.B)   { benchmarkSum(b, Huge) }