github.com/gopherd/gonum@v0.0.4/cmplxs/cmplxs_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 cmplxs
     6  
     7  import (
     8  	"fmt"
     9  	"math"
    10  	"math/cmplx"
    11  	"strconv"
    12  	"testing"
    13  
    14  	"math/rand"
    15  
    16  	"github.com/gopherd/gonum/cmplxs/cscalar"
    17  	"github.com/gopherd/gonum/floats"
    18  )
    19  
    20  const (
    21  	EqTolerance = 1e-14
    22  	Small       = 10
    23  	Medium      = 1000
    24  	Large       = 100000
    25  	Huge        = 10000000
    26  )
    27  
    28  func areSlicesEqual(t *testing.T, truth, comp []complex128, str string) {
    29  	if !EqualApprox(comp, truth, EqTolerance) {
    30  		t.Errorf(str+". Expected %v, returned %v", truth, comp)
    31  	}
    32  }
    33  
    34  func areSlicesSame(t *testing.T, truth, comp []complex128, str string) {
    35  	ok := len(truth) == len(comp)
    36  	if ok {
    37  		for i, a := range truth {
    38  			if !cscalar.EqualWithinAbsOrRel(a, comp[i], EqTolerance, EqTolerance) && !cscalar.Same(a, comp[i]) {
    39  				ok = false
    40  				break
    41  			}
    42  		}
    43  	}
    44  	if !ok {
    45  		t.Errorf(str+". Expected %v, returned %v", truth, comp)
    46  	}
    47  }
    48  
    49  func Panics(fun func()) (b bool) {
    50  	defer func() {
    51  		err := recover()
    52  		if err != nil {
    53  			b = true
    54  		}
    55  	}()
    56  	fun()
    57  	return
    58  }
    59  
    60  func TestAdd(t *testing.T) {
    61  	a := []complex128{1 + 1i, 2 + 2i, 3 + 3i}
    62  	b := []complex128{4 + 4i, 5 + 5i, 6 + 6i}
    63  	c := []complex128{7 + 7i, 8 + 8i, 9 + 9i}
    64  	truth := []complex128{12 + 12i, 15 + 15i, 18 + 18i}
    65  	n := make([]complex128, len(a))
    66  
    67  	Add(n, a)
    68  	Add(n, b)
    69  	Add(n, c)
    70  	areSlicesEqual(t, truth, n, "Wrong addition of slices new receiver")
    71  	Add(a, b)
    72  	Add(a, c)
    73  	areSlicesEqual(t, truth, n, "Wrong addition of slices for no new receiver")
    74  
    75  	// Test that it panics
    76  	if !Panics(func() { Add(make([]complex128, 2), make([]complex128, 3)) }) {
    77  		t.Errorf("Did not panic with length mismatch")
    78  	}
    79  }
    80  
    81  func TestAddTo(t *testing.T) {
    82  	a := []complex128{1 + 1i, 2 + 2i, 3 + 3i}
    83  	b := []complex128{4 + 4i, 5 + 5i, 6 + 6i}
    84  	truth := []complex128{5 + 5i, 7 + 7i, 9 + 9i}
    85  	n1 := make([]complex128, 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([]complex128, 2), make([]complex128, 3), make([]complex128, 3)) }) {
    93  		t.Errorf("Did not panic with length mismatch")
    94  	}
    95  	if !Panics(func() { AddTo(make([]complex128, 3), make([]complex128, 3), make([]complex128, 2)) }) {
    96  		t.Errorf("Did not panic with length mismatch")
    97  	}
    98  }
    99  
   100  func TestAddConst(t *testing.T) {
   101  	s := []complex128{3 + 1i, 4 + 2i, 1 + 3i, 7 + 4i, 5 + 5i}
   102  	c := 6 + 1i
   103  	truth := []complex128{9 + 2i, 10 + 3i, 7 + 4i, 13 + 5i, 11 + 6i}
   104  	AddConst(c, s)
   105  	areSlicesEqual(t, truth, s, "Wrong addition of constant")
   106  }
   107  
   108  func TestAddScaled(t *testing.T) {
   109  	s := []complex128{3, 4, 1, 7, 5}
   110  	alpha := 6 + 1i
   111  	dst := []complex128{1, 2, 3, 4, 5}
   112  	ans := []complex128{19 + 3i, 26 + 4i, 9 + 1i, 46 + 7i, 35 + 5i}
   113  	AddScaled(dst, alpha, s)
   114  	if !EqualApprox(dst, ans, EqTolerance) {
   115  		t.Errorf("Adding scaled did not match. Expected %v, returned %v", ans, dst)
   116  	}
   117  	short := []complex128{1}
   118  	if !Panics(func() { AddScaled(dst, alpha, short) }) {
   119  		t.Errorf("Doesn't panic if s is smaller than dst")
   120  	}
   121  	if !Panics(func() { AddScaled(short, alpha, s) }) {
   122  		t.Errorf("Doesn't panic if dst is smaller than s")
   123  	}
   124  }
   125  
   126  func TestAddScaledTo(t *testing.T) {
   127  	s := []complex128{3, 4, 1, 7, 5}
   128  	alpha := 6 + 1i
   129  	y := []complex128{1, 2, 3, 4, 5}
   130  	dst1 := make([]complex128, 5)
   131  	ans := []complex128{19 + 3i, 26 + 4i, 9 + 1i, 46 + 7i, 35 + 5i}
   132  	dst2 := AddScaledTo(dst1, y, alpha, s)
   133  	if !EqualApprox(dst1, ans, EqTolerance) {
   134  		t.Errorf("AddScaledTo did not match for mutator")
   135  	}
   136  	if !EqualApprox(dst2, ans, EqTolerance) {
   137  		t.Errorf("AddScaledTo did not match for returned slice")
   138  	}
   139  	AddScaledTo(dst1, y, alpha, s)
   140  	if !EqualApprox(dst1, ans, EqTolerance) {
   141  		t.Errorf("Reusing dst did not match")
   142  	}
   143  	short := []complex128{1}
   144  	if !Panics(func() { AddScaledTo(dst1, y, alpha, short) }) {
   145  		t.Errorf("Doesn't panic if s is smaller than dst")
   146  	}
   147  	if !Panics(func() { AddScaledTo(short, y, alpha, s) }) {
   148  		t.Errorf("Doesn't panic if dst is smaller than s")
   149  	}
   150  	if !Panics(func() { AddScaledTo(dst1, short, alpha, s) }) {
   151  		t.Errorf("Doesn't panic if y is smaller than dst")
   152  	}
   153  }
   154  
   155  func TestCount(t *testing.T) {
   156  	s := []complex128{3, 4, 1, 7, 5}
   157  	f := func(v complex128) bool { return cmplx.Abs(v) > 3.5 }
   158  	truth := 3
   159  	n := Count(f, s)
   160  	if n != truth {
   161  		t.Errorf("Wrong number of elements counted")
   162  	}
   163  }
   164  
   165  func TestCumProd(t *testing.T) {
   166  	s := []complex128{3 + 1i, 4 + 2i, 1 + 3i, 7 + 4i, 5 + 5i}
   167  	receiver := make([]complex128, len(s))
   168  	result := CumProd(receiver, s)
   169  	truth := []complex128{3 + 1i, 10 + 10i, -20 + 40i, -300 + 200i, -2500 - 500i}
   170  	areSlicesEqual(t, truth, receiver, "Wrong cumprod mutated with new receiver")
   171  	areSlicesEqual(t, truth, result, "Wrong cumprod result with new receiver")
   172  	CumProd(receiver, s)
   173  	areSlicesEqual(t, truth, receiver, "Wrong cumprod returned with reused receiver")
   174  
   175  	// Test that it panics
   176  	if !Panics(func() { CumProd(make([]complex128, 2), make([]complex128, 3)) }) {
   177  		t.Errorf("Did not panic with length mismatch")
   178  	}
   179  
   180  	// Test empty CumProd
   181  	emptyReceiver := make([]complex128, 0)
   182  	truth = []complex128{}
   183  	CumProd(emptyReceiver, emptyReceiver)
   184  	areSlicesEqual(t, truth, emptyReceiver, "Wrong cumprod returned with empty receiver")
   185  }
   186  
   187  func TestComplex(t *testing.T) {
   188  	for i, test := range []struct {
   189  		dst        []complex128
   190  		real, imag []float64
   191  		want       []complex128
   192  		panics     bool
   193  	}{
   194  		{},
   195  		{
   196  			dst:  make([]complex128, 4),
   197  			real: []float64{1, 2, 3, 4},
   198  			imag: []float64{1, 2, 3, 4},
   199  			want: []complex128{1 + 1i, 2 + 2i, 3 + 3i, 4 + 4i},
   200  		},
   201  		{
   202  			dst:    make([]complex128, 3),
   203  			real:   []float64{1, 2, 3, 4},
   204  			imag:   []float64{1, 2, 3, 4},
   205  			panics: true,
   206  		},
   207  		{
   208  			dst:    make([]complex128, 4),
   209  			real:   []float64{1, 2, 3},
   210  			imag:   []float64{1, 2, 3, 4},
   211  			panics: true,
   212  		},
   213  		{
   214  			dst:    make([]complex128, 4),
   215  			real:   []float64{1, 2, 3, 4},
   216  			imag:   []float64{1, 2, 3},
   217  			panics: true,
   218  		},
   219  		{
   220  			dst:  make([]complex128, 4),
   221  			real: []float64{1, 2, 3, 4},
   222  			imag: []float64{1, 2, 3, math.NaN()},
   223  			want: []complex128{1 + 1i, 2 + 2i, 3 + 3i, cmplx.NaN()},
   224  		},
   225  	} {
   226  		var got []complex128
   227  		panicked := Panics(func() {
   228  			got = Complex(test.dst, test.real, test.imag)
   229  		})
   230  		if panicked != test.panics {
   231  			if panicked {
   232  				t.Errorf("unexpected panic for test %d", i)
   233  			} else {
   234  				t.Errorf("expected panic for test %d", i)
   235  			}
   236  		}
   237  		if panicked || test.panics {
   238  			continue
   239  		}
   240  		if !Same(got, test.dst) {
   241  			t.Errorf("mismatch between dst and return test %d: got:%v want:%v", i, got, test.dst)
   242  		}
   243  		if !Same(got, test.want) {
   244  			t.Errorf("unexpected result for test %d: got:%v want:%v", i, got, test.want)
   245  		}
   246  	}
   247  
   248  }
   249  
   250  func TestCumSum(t *testing.T) {
   251  	s := []complex128{3 + 1i, 4 + 2i, 1 + 3i, 7 + 4i, 5 + 5i}
   252  	receiver := make([]complex128, len(s))
   253  	result := CumSum(receiver, s)
   254  	truth := []complex128{3 + 1i, 7 + 3i, 8 + 6i, 15 + 10i, 20 + 15i}
   255  	areSlicesEqual(t, truth, receiver, "Wrong cumsum mutated with new receiver")
   256  	areSlicesEqual(t, truth, result, "Wrong cumsum returned with new receiver")
   257  	CumSum(receiver, s)
   258  	areSlicesEqual(t, truth, receiver, "Wrong cumsum returned with reused receiver")
   259  
   260  	// Test that it panics
   261  	if !Panics(func() { CumSum(make([]complex128, 2), make([]complex128, 3)) }) {
   262  		t.Errorf("Did not panic with length mismatch")
   263  	}
   264  
   265  	// Test empty CumSum
   266  	emptyReceiver := make([]complex128, 0)
   267  	truth = []complex128{}
   268  	CumSum(emptyReceiver, emptyReceiver)
   269  	areSlicesEqual(t, truth, emptyReceiver, "Wrong cumsum returned with empty receiver")
   270  }
   271  
   272  func TestDistance(t *testing.T) {
   273  	norms := []float64{1, 2, 4, math.Inf(1)}
   274  	slices := []struct {
   275  		s []complex128
   276  		t []complex128
   277  	}{
   278  		{
   279  			nil,
   280  			nil,
   281  		},
   282  		{
   283  			[]complex128{8 + 1i, 9 + 2i, 10 + 3i, -12 + 4i},
   284  			[]complex128{8 + 1i, 9 + 2i, 10 + 3i, -12 + 4i},
   285  		},
   286  		{
   287  			[]complex128{1 + 1i, 2 + 2i, 3 + 3i, -4 + 4i, -5 + 5i, 8 + 6i},
   288  			[]complex128{-9.2 - 1i, -6.8 - 2i, 9 - 3i, -3 - 4i, -2 - 5i, 1 - 6i},
   289  		},
   290  	}
   291  
   292  	for j, test := range slices {
   293  		tmp := make([]complex128, len(test.s))
   294  		for i, L := range norms {
   295  			dist := Distance(test.s, test.t, L)
   296  			copy(tmp, test.s)
   297  			Sub(tmp, test.t)
   298  			norm := Norm(tmp, L)
   299  			if dist != norm { // Use equality because they should be identical.
   300  				t.Errorf("Distance does not match norm for case %v, %v. Expected %v, Found %v.", i, j, norm, dist)
   301  			}
   302  		}
   303  	}
   304  
   305  	if !Panics(func() { Distance([]complex128{}, []complex128{1}, 1) }) {
   306  		t.Errorf("Did not panic with unequal lengths")
   307  	}
   308  }
   309  
   310  func TestDiv(t *testing.T) {
   311  	s1 := []complex128{5 - 5i, 12 + 2i, 27 - 3i}
   312  	s2 := []complex128{1 - 1i, 2 + 2i, 3 - 1i}
   313  	ans := []complex128{5 + 0i, 3.5 - 2.5i, 8.4 + 1.8i}
   314  	Div(s1, s2)
   315  	if !EqualApprox(s1, ans, EqTolerance) {
   316  		t.Errorf("Div doesn't give correct answer. Expected %v, Found %v.", ans, s1)
   317  	}
   318  	s1short := []complex128{1}
   319  	if !Panics(func() { Div(s1short, s2) }) {
   320  		t.Errorf("Did not panic with unequal lengths")
   321  	}
   322  	s2short := []complex128{1}
   323  	if !Panics(func() { Div(s1, s2short) }) {
   324  		t.Errorf("Did not panic with unequal lengths")
   325  	}
   326  }
   327  
   328  func TestDivTo(t *testing.T) {
   329  	s1 := []complex128{5 - 5i, 12 + 2i, 27 - 3i}
   330  	s1orig := []complex128{5 - 5i, 12 + 2i, 27 - 3i}
   331  	s2 := []complex128{1 - 1i, 2 + 2i, 3 - 1i}
   332  	s2orig := []complex128{1 - 1i, 2 + 2i, 3 - 1i}
   333  	dst1 := make([]complex128, 3)
   334  	ans := []complex128{5 + 0i, 3.5 - 2.5i, 8.4 + 1.8i}
   335  	dst2 := DivTo(dst1, s1, s2)
   336  	if !EqualApprox(dst1, ans, EqTolerance) {
   337  		t.Errorf("DivTo doesn't give correct answer in mutated slice")
   338  	}
   339  	if !EqualApprox(dst2, ans, EqTolerance) {
   340  		t.Errorf("DivTo doesn't give correct answer in returned slice")
   341  	}
   342  	if !EqualApprox(s1, s1orig, EqTolerance) {
   343  		t.Errorf("S1 changes during multo")
   344  	}
   345  	if !EqualApprox(s2, s2orig, EqTolerance) {
   346  		t.Errorf("s2 changes during multo")
   347  	}
   348  	DivTo(dst1, s1, s2)
   349  	if !EqualApprox(dst1, ans, EqTolerance) {
   350  		t.Errorf("DivTo doesn't give correct answer reusing dst")
   351  	}
   352  	dstShort := []complex128{1}
   353  	if !Panics(func() { DivTo(dstShort, s1, s2) }) {
   354  		t.Errorf("Did not panic with s1 wrong length")
   355  	}
   356  	s1short := []complex128{1}
   357  	if !Panics(func() { DivTo(dst1, s1short, s2) }) {
   358  		t.Errorf("Did not panic with s1 wrong length")
   359  	}
   360  	s2short := []complex128{1}
   361  	if !Panics(func() { DivTo(dst1, s1, s2short) }) {
   362  		t.Errorf("Did not panic with s2 wrong length")
   363  	}
   364  }
   365  
   366  func TestDot(t *testing.T) {
   367  	s1 := []complex128{1 + 1i, 2 + 2i, 3 + 3i, 4 + 4i}
   368  	s2 := []complex128{-3 + 4i, 4 + 3i, 5 + 2i, -6 + 1i}
   369  	truth := 16 + 24i
   370  	ans := Dot(s1, s2)
   371  	if ans != truth {
   372  		t.Errorf("Dot product computed incorrectly. Expected %v, Found %v.", truth, ans)
   373  	}
   374  
   375  	// Test that it panics
   376  	if !Panics(func() { Dot(make([]complex128, 2), make([]complex128, 3)) }) {
   377  		t.Errorf("Did not panic with length mismatch")
   378  	}
   379  }
   380  
   381  func TestEquals(t *testing.T) {
   382  	s1 := []complex128{1 + 1i, 2 + 4i, 3 + 8i, 4 + 16i}
   383  	s2 := []complex128{1 + 1i, 2 + 4i, 3 + 8i, 4 + 16i}
   384  	if !Equal(s1, s2) {
   385  		t.Errorf("Equal slices returned as unequal")
   386  	}
   387  	s2 = []complex128{1 + 1i, 2 + 4i, 3 + 8i, 4 + 16i + 1e-14}
   388  	if Equal(s1, s2) {
   389  		t.Errorf("Unequal slices returned as equal")
   390  	}
   391  	if Equal(s1, []complex128{}) {
   392  		t.Errorf("Unequal slice lengths returned as equal")
   393  	}
   394  }
   395  
   396  func TestEqualApprox(t *testing.T) {
   397  	s1 := []complex128{1 + 1i, 2 + 4i, 3 + 8i, 4 + 16i}
   398  	s2 := []complex128{1 + 1i, 2 + 4i, 3 + 8i, 4 + 16i + 1e-10}
   399  	if EqualApprox(s1, s2, 1e-13) {
   400  		t.Errorf("Unequal slices returned as equal for absolute")
   401  	}
   402  	if !EqualApprox(s1, s2, 1e-5) {
   403  		t.Errorf("Equal slices returned as unequal for absolute")
   404  	}
   405  	s1 = []complex128{1 + 1i, 2 + 4i, 3 + 8i, 1000 + 1000i}
   406  	s2 = []complex128{1 + 1i, 2 + 4i, 3 + 8i, (1000 + 1000i) * (1 + 1e-7)}
   407  	if EqualApprox(s1, s2, 1e-8) {
   408  		t.Errorf("Unequal slices returned as equal for relative")
   409  	}
   410  	if !EqualApprox(s1, s2, 1e-5) {
   411  		t.Errorf("Equal slices returned as unequal for relative")
   412  	}
   413  	if EqualApprox(s1, []complex128{}, 1e-5) {
   414  		t.Errorf("Unequal slice lengths returned as equal")
   415  	}
   416  }
   417  
   418  func TestEqualFunc(t *testing.T) {
   419  	s1 := []complex128{1 + 1i, 2 + 4i, 3 + 8i, 4 + 16i}
   420  	s2 := []complex128{1 + 1i, 2 + 4i, 3 + 8i, 4 + 16i}
   421  	eq := func(x, y complex128) bool { return x == y }
   422  	if !EqualFunc(s1, s2, eq) {
   423  		t.Errorf("Equal slices returned as unequal")
   424  	}
   425  	s2 = []complex128{1 + 1i, 2 + 4i, 3 + 8i, 4 + 16i + 1e-14}
   426  	if EqualFunc(s1, s2, eq) {
   427  		t.Errorf("Unequal slices returned as equal")
   428  	}
   429  	if EqualFunc(s1, []complex128{}, eq) {
   430  		t.Errorf("Unequal slice lengths returned as equal")
   431  	}
   432  }
   433  
   434  func TestEqualLengths(t *testing.T) {
   435  	s1 := []complex128{1 + 1i, 2 + 2i, 3 + 3i, 4 + 4i}
   436  	s2 := []complex128{1 + 1i, 2 + 2i, 3 + 3i, 4 + 4i}
   437  	s3 := []complex128{1 + 1i, 2 + 2i, 3 + 3i}
   438  	if !EqualLengths(s1, s2) {
   439  		t.Errorf("Equal lengths returned as unequal")
   440  	}
   441  	if EqualLengths(s1, s3) {
   442  		t.Errorf("Unequal lengths returned as equal")
   443  	}
   444  	if !EqualLengths(s1) {
   445  		t.Errorf("Single slice returned as unequal")
   446  	}
   447  	if !EqualLengths() {
   448  		t.Errorf("No slices returned as unequal")
   449  	}
   450  }
   451  
   452  func eqIntSlice(one, two []int) string {
   453  	if len(one) != len(two) {
   454  		return "Length mismatch"
   455  	}
   456  	for i, val := range one {
   457  		if val != two[i] {
   458  			return "Index " + strconv.Itoa(i) + " mismatch"
   459  		}
   460  	}
   461  	return ""
   462  }
   463  
   464  func TestFind(t *testing.T) {
   465  	s := []complex128{3 + 1i, 4 - 1i, 1 + 2i, 7 + 10i, 5 - 100i}
   466  	f := func(v complex128) bool { return cmplx.Abs(v) > 3.5 }
   467  	allTrueInds := []int{1, 3, 4}
   468  
   469  	// Test finding first two elements
   470  	inds, err := Find(nil, f, s, 2)
   471  	if err != nil {
   472  		t.Errorf("Find first two: Improper error return")
   473  	}
   474  	trueInds := allTrueInds[:2]
   475  	str := eqIntSlice(inds, trueInds)
   476  	if str != "" {
   477  		t.Errorf("Find first two: " + str)
   478  	}
   479  
   480  	// Test finding no elements with non nil slice
   481  	inds = []int{1, 2, 3, 4, 5, 6}
   482  	inds, err = Find(inds, f, s, 0)
   483  	if err != nil {
   484  		t.Errorf("Find no elements: Improper error return")
   485  	}
   486  	str = eqIntSlice(inds, []int{})
   487  	if str != "" {
   488  		t.Errorf("Find no non-nil: " + str)
   489  	}
   490  
   491  	// Test finding first two elements with non nil slice
   492  	inds = []int{1, 2, 3, 4, 5, 6}
   493  	inds, err = Find(inds, f, s, 2)
   494  	if err != nil {
   495  		t.Errorf("Find first two non-nil: Improper error return")
   496  	}
   497  	str = eqIntSlice(inds, trueInds)
   498  	if str != "" {
   499  		t.Errorf("Find first two non-nil: " + str)
   500  	}
   501  
   502  	// Test finding too many elements
   503  	inds, err = Find(inds, f, s, 4)
   504  	if err == nil {
   505  		t.Errorf("Request too many: No error returned")
   506  	}
   507  	str = eqIntSlice(inds, allTrueInds)
   508  	if str != "" {
   509  		t.Errorf("Request too many: Does not match all of the inds: " + str)
   510  	}
   511  
   512  	// Test finding all elements
   513  	inds, err = Find(nil, f, s, -1)
   514  	if err != nil {
   515  		t.Errorf("Find all: Improper error returned")
   516  	}
   517  	str = eqIntSlice(inds, allTrueInds)
   518  	if str != "" {
   519  		t.Errorf("Find all: Does not match all of the inds: " + str)
   520  	}
   521  }
   522  
   523  func TestHasNaN(t *testing.T) {
   524  	for i, test := range []struct {
   525  		s   []complex128
   526  		ans bool
   527  	}{
   528  		{},
   529  		{
   530  			s: []complex128{1 + 1i, 2 + 2i, 3 + 3i, 4 + 4i},
   531  		},
   532  		{
   533  			s:   []complex128{1 + 1i, cmplx.NaN(), 3 + 3i, 4 + 4i},
   534  			ans: true,
   535  		},
   536  		{
   537  			s:   []complex128{1 + 1i, 2 + 2i, 3 + 3i, cmplx.NaN()},
   538  			ans: true,
   539  		},
   540  	} {
   541  		b := HasNaN(test.s)
   542  		if b != test.ans {
   543  			t.Errorf("HasNaN mismatch case %d. Expected %v, Found %v", i, test.ans, b)
   544  		}
   545  	}
   546  }
   547  
   548  func TestImag(t *testing.T) {
   549  	for i, test := range []struct {
   550  		dst    []float64
   551  		src    []complex128
   552  		want   []float64
   553  		panics bool
   554  	}{
   555  		{},
   556  		{
   557  			dst:  make([]float64, 4),
   558  			src:  []complex128{1 + 1i, 2 + 2i, 3 + 3i, 4 + 4i},
   559  			want: []float64{1, 2, 3, 4},
   560  		},
   561  		{
   562  			dst:    make([]float64, 3),
   563  			src:    []complex128{1 + 1i, 2 + 2i, 3 + 3i, 4 + 4i},
   564  			panics: true,
   565  		},
   566  		{
   567  			dst:  make([]float64, 4),
   568  			src:  []complex128{1 + 1i, 2 + 2i, 3 + 3i, cmplx.NaN()},
   569  			want: []float64{1, 2, 3, math.NaN()},
   570  		},
   571  	} {
   572  		var got []float64
   573  		panicked := Panics(func() {
   574  			got = Imag(test.dst, test.src)
   575  		})
   576  		if panicked != test.panics {
   577  			if panicked {
   578  				t.Errorf("unexpected panic for test %d", i)
   579  			} else {
   580  				t.Errorf("expected panic for test %d", i)
   581  			}
   582  		}
   583  		if panicked || test.panics {
   584  			continue
   585  		}
   586  		if !floats.Same(got, test.dst) {
   587  			t.Errorf("mismatch between dst and return test %d: got:%v want:%v", i, got, test.dst)
   588  		}
   589  		if !floats.Same(got, test.want) {
   590  			t.Errorf("unexpected result for test %d: got:%v want:%v", i, got, test.want)
   591  		}
   592  	}
   593  
   594  }
   595  
   596  func TestLogSpan(t *testing.T) {
   597  	// FIXME(kortschak)
   598  	receiver1 := make([]complex128, 6)
   599  	truth := []complex128{0.001, 0.01, 0.1, 1, 10, 100}
   600  	receiver2 := LogSpan(receiver1, 0.001, 100)
   601  	tst := make([]complex128, 6)
   602  	for i := range truth {
   603  		tst[i] = receiver1[i] / truth[i]
   604  	}
   605  	comp := make([]complex128, 6)
   606  	for i := range comp {
   607  		comp[i] = 1
   608  	}
   609  	areSlicesEqual(t, comp, tst, "Improper logspace from mutator")
   610  
   611  	for i := range truth {
   612  		tst[i] = receiver2[i] / truth[i]
   613  	}
   614  	areSlicesEqual(t, comp, tst, "Improper logspace from returned slice")
   615  
   616  	if !Panics(func() { LogSpan(nil, 1, 5) }) {
   617  		t.Errorf("Span accepts nil argument")
   618  	}
   619  	if !Panics(func() { LogSpan(make([]complex128, 1), 1, 5) }) {
   620  		t.Errorf("Span accepts argument of len = 1")
   621  	}
   622  }
   623  
   624  func TestMaxAbsAndIdx(t *testing.T) {
   625  	for _, test := range []struct {
   626  		in      []complex128
   627  		wantIdx int
   628  		wantVal complex128
   629  		desc    string
   630  	}{
   631  		{
   632  			in:      []complex128{3 + 1i, 4 + 1i, 1 + 1i, 7 + 1i, 5 + 1i},
   633  			wantIdx: 3,
   634  			wantVal: 7 + 1i,
   635  			desc:    "with only finite entries",
   636  		},
   637  		{
   638  			in:      []complex128{cmplx.NaN(), 4 + 1i, 1 + 1i, 7 + 1i, 5 + 1i},
   639  			wantIdx: 3,
   640  			wantVal: 7 + 1i,
   641  			desc:    "with leading NaN",
   642  		},
   643  		{
   644  			in:      []complex128{cmplx.NaN(), cmplx.NaN(), cmplx.NaN()},
   645  			wantIdx: 0,
   646  			wantVal: cmplx.NaN(),
   647  			desc:    "when only NaN elements exist",
   648  		},
   649  		{
   650  			in:      []complex128{cmplx.NaN(), cmplx.Inf()},
   651  			wantIdx: 1,
   652  			wantVal: cmplx.Inf(),
   653  			desc:    "leading NaN followed by Inf",
   654  		},
   655  	} {
   656  		ind := MaxAbsIdx(test.in)
   657  		if ind != test.wantIdx {
   658  			t.Errorf("Wrong index "+test.desc+": got:%d want:%d", ind, test.wantIdx)
   659  		}
   660  		val := MaxAbs(test.in)
   661  		if !cscalar.Same(val, test.wantVal) {
   662  			t.Errorf("Wrong value "+test.desc+": got:%f want:%f", val, test.wantVal)
   663  		}
   664  	}
   665  }
   666  
   667  func TestMinAbsAndIdx(t *testing.T) {
   668  	for _, test := range []struct {
   669  		in      []complex128
   670  		wantIdx int
   671  		wantVal complex128
   672  		desc    string
   673  	}{
   674  		{
   675  			in:      []complex128{3 + 1i, 4 + 1i, 1 + 1i, 7 + 1i, 5 + 1i},
   676  			wantIdx: 2,
   677  			wantVal: 1 + 1i,
   678  			desc:    "with only finite entries",
   679  		},
   680  		{
   681  			in:      []complex128{cmplx.NaN(), 4 + 1i, 1 + 1i, 7 + 1i, 5 + 1i},
   682  			wantIdx: 2,
   683  			wantVal: 1 + 1i,
   684  			desc:    "with leading NaN",
   685  		},
   686  		{
   687  			in:      []complex128{cmplx.NaN(), cmplx.NaN(), cmplx.NaN()},
   688  			wantIdx: 0,
   689  			wantVal: cmplx.NaN(),
   690  			desc:    "when only NaN elements exist",
   691  		},
   692  		{
   693  			in:      []complex128{cmplx.NaN(), cmplx.Inf()},
   694  			wantIdx: 1,
   695  			wantVal: cmplx.Inf(),
   696  			desc:    "leading NaN followed by Inf",
   697  		},
   698  	} {
   699  		ind := MinAbsIdx(test.in)
   700  		if ind != test.wantIdx {
   701  			t.Errorf("Wrong index "+test.desc+": got:%d want:%d", ind, test.wantIdx)
   702  		}
   703  		val := MinAbs(test.in)
   704  		if !cscalar.Same(val, test.wantVal) {
   705  			t.Errorf("Wrong value "+test.desc+": got:%f want:%f", val, test.wantVal)
   706  		}
   707  	}
   708  }
   709  
   710  func TestMul(t *testing.T) {
   711  	s1 := []complex128{1 + 1i, 2 + 2i, 3 + 3i}
   712  	s2 := []complex128{1 + 1i, 2 + 2i, 3 + 3i}
   713  	ans := []complex128{0 + 2i, 0 + 8i, 0 + 18i}
   714  	Mul(s1, s2)
   715  	if !EqualApprox(s1, ans, EqTolerance) {
   716  		t.Errorf("Mul doesn't give correct answer. Expected %v, Found %v", ans, s1)
   717  	}
   718  	s1short := []complex128{1}
   719  	if !Panics(func() { Mul(s1short, s2) }) {
   720  		t.Errorf("Did not panic with unequal lengths")
   721  	}
   722  	s2short := []complex128{1}
   723  	if !Panics(func() { Mul(s1, s2short) }) {
   724  		t.Errorf("Did not panic with unequal lengths")
   725  	}
   726  }
   727  
   728  func TestMulConj(t *testing.T) {
   729  	s1 := []complex128{2 + 1i, 3 + 2i, 4 + 3i}
   730  	s2 := []complex128{1 + 2i, 2 + 3i, 3 + 4i}
   731  	s2orig := []complex128{1 + 2i, 2 + 3i, 3 + 4i}
   732  	ans := []complex128{4 - 3i, 12 - 5i, 24 - 7i}
   733  	MulConj(s1, s2)
   734  	if !Equal(s1, ans) {
   735  		t.Errorf("MulConj doesn't give correct answer. Expected %v, Found %v", ans, s1)
   736  	}
   737  	if !Equal(s2, s2orig) {
   738  		t.Errorf("s2 changes during MulTo")
   739  	}
   740  	s1short := []complex128{1}
   741  	if !Panics(func() { MulConj(s1short, s2) }) {
   742  		t.Errorf("Did not panic with unequal lengths")
   743  	}
   744  	s2short := []complex128{1}
   745  	if !Panics(func() { MulConj(s1, s2short) }) {
   746  		t.Errorf("Did not panic with unequal lengths")
   747  	}
   748  }
   749  
   750  func TestMulConjTo(t *testing.T) {
   751  	s1 := []complex128{2 + 1i, 3 + 2i, 4 + 3i}
   752  	s1orig := []complex128{2 + 1i, 3 + 2i, 4 + 3i}
   753  	s2 := []complex128{1 + 2i, 2 + 3i, 3 + 4i}
   754  	s2orig := []complex128{1 + 2i, 2 + 3i, 3 + 4i}
   755  	dst1 := make([]complex128, 3)
   756  	ans := []complex128{4 - 3i, 12 - 5i, 24 - 7i}
   757  	dst2 := MulConjTo(dst1, s1, s2)
   758  	if !Equal(dst1, ans) {
   759  		t.Errorf("MulConjTo doesn't give correct answer in mutated slice")
   760  	}
   761  	if !Equal(dst2, ans) {
   762  		t.Errorf("MulConjTo doesn't give correct answer in returned slice")
   763  	}
   764  	if !Equal(s1, s1orig) {
   765  		t.Errorf("S1 changes during MulConjTo")
   766  	}
   767  	if !Equal(s2, s2orig) {
   768  		t.Errorf("s2 changes during MulConjTo")
   769  	}
   770  	MulConjTo(dst1, s1, s2)
   771  	if !Equal(dst1, ans) {
   772  		t.Errorf("MulConjTo doesn't give correct answer reusing dst")
   773  	}
   774  	dstShort := []complex128{1}
   775  	if !Panics(func() { MulConjTo(dstShort, s1, s2) }) {
   776  		t.Errorf("Did not panic with dst wrong length")
   777  	}
   778  	s1short := []complex128{1}
   779  	if !Panics(func() { MulConjTo(dst1, s1short, s2) }) {
   780  		t.Errorf("Did not panic with s1 wrong length")
   781  	}
   782  	s2short := []complex128{1}
   783  	if !Panics(func() { MulConjTo(dst1, s1, s2short) }) {
   784  		t.Errorf("Did not panic with s2 wrong length")
   785  	}
   786  }
   787  
   788  func TestMulTo(t *testing.T) {
   789  	s1 := []complex128{1 + 1i, 2 + 2i, 3 + 3i}
   790  	s1orig := []complex128{1 + 1i, 2 + 2i, 3 + 3i}
   791  	s2 := []complex128{1 + 1i, 2 + 2i, 3 + 3i}
   792  	s2orig := []complex128{1 + 1i, 2 + 2i, 3 + 3i}
   793  	dst1 := make([]complex128, 3)
   794  	ans := []complex128{0 + 2i, 0 + 8i, 0 + 18i}
   795  	dst2 := MulTo(dst1, s1, s2)
   796  	if !EqualApprox(dst1, ans, EqTolerance) {
   797  		t.Errorf("MulTo doesn't give correct answer in mutated slice")
   798  	}
   799  	if !EqualApprox(dst2, ans, EqTolerance) {
   800  		t.Errorf("MulTo doesn't give correct answer in returned slice")
   801  	}
   802  	if !EqualApprox(s1, s1orig, EqTolerance) {
   803  		t.Errorf("S1 changes during multo")
   804  	}
   805  	if !EqualApprox(s2, s2orig, EqTolerance) {
   806  		t.Errorf("s2 changes during multo")
   807  	}
   808  	MulTo(dst1, s1, s2)
   809  	if !EqualApprox(dst1, ans, EqTolerance) {
   810  		t.Errorf("MulTo doesn't give correct answer reusing dst")
   811  	}
   812  	dstShort := []complex128{1}
   813  	if !Panics(func() { MulTo(dstShort, s1, s2) }) {
   814  		t.Errorf("Did not panic with s1 wrong length")
   815  	}
   816  	s1short := []complex128{1}
   817  	if !Panics(func() { MulTo(dst1, s1short, s2) }) {
   818  		t.Errorf("Did not panic with s1 wrong length")
   819  	}
   820  	s2short := []complex128{1}
   821  	if !Panics(func() { MulTo(dst1, s1, s2short) }) {
   822  		t.Errorf("Did not panic with s2 wrong length")
   823  	}
   824  }
   825  
   826  // Complexify
   827  
   828  func TestNearestIdx(t *testing.T) {
   829  	for _, test := range []struct {
   830  		in    []complex128
   831  		query complex128
   832  		want  int
   833  		desc  string
   834  	}{
   835  		{
   836  			in:    []complex128{6.2, 3, 5, 6.2, 8},
   837  			query: 2,
   838  			want:  1,
   839  			desc:  "Wrong index returned when value is less than all of elements",
   840  		},
   841  		{
   842  			in:    []complex128{6.2, 3, 5, 6.2, 8},
   843  			query: 9,
   844  			want:  4,
   845  			desc:  "Wrong index returned when value is greater than all of elements",
   846  		},
   847  		{
   848  			in:    []complex128{6.2, 3, 5, 6.2, 8},
   849  			query: 3.1,
   850  			want:  1,
   851  			desc:  "Wrong index returned when value is greater than closest element",
   852  		},
   853  		{
   854  			in:    []complex128{6.2, 3, 5, 6.2, 8},
   855  			query: 2.9,
   856  			want:  1,
   857  			desc:  "Wrong index returned when value is less than closest element",
   858  		},
   859  		{
   860  			in:    []complex128{6.2, 3, 5, 6.2, 8},
   861  			query: 3,
   862  			want:  1,
   863  			desc:  "Wrong index returned when value is equal to element",
   864  		},
   865  		{
   866  			in:    []complex128{6.2, 3, 5, 6.2, 8},
   867  			query: 6.2,
   868  			want:  0,
   869  			desc:  "Wrong index returned when value is equal to several elements",
   870  		},
   871  		{
   872  			in:    []complex128{6.2, 3, 5, 6.2, 8},
   873  			query: 4,
   874  			want:  1,
   875  			desc:  "Wrong index returned when value is exactly between two closest elements",
   876  		},
   877  		{
   878  			in:    []complex128{cmplx.NaN(), 3, 2, -1},
   879  			query: 2,
   880  			want:  2,
   881  			desc:  "Wrong index returned when initial element is NaN",
   882  		},
   883  		{
   884  			in:    []complex128{0, cmplx.NaN(), -1, 2},
   885  			query: cmplx.NaN(),
   886  			want:  0,
   887  			desc:  "Wrong index returned when query is NaN and a NaN element exists",
   888  		},
   889  		{
   890  			in:    []complex128{0, cmplx.NaN(), -1, 2},
   891  			query: cmplx.Inf(),
   892  			want:  3,
   893  			desc:  "Wrong index returned when query is Inf and no Inf element exists",
   894  		},
   895  		{
   896  			in:    []complex128{cmplx.NaN(), cmplx.NaN(), cmplx.NaN()},
   897  			query: 1,
   898  			want:  0,
   899  			desc:  "Wrong index returned when query is a number and only NaN elements exist",
   900  		},
   901  		{
   902  			in:    []complex128{cmplx.NaN(), cmplx.Inf()},
   903  			query: 1,
   904  			want:  1,
   905  			desc:  "Wrong index returned when query is a number and single NaN precedes Inf",
   906  		},
   907  	} {
   908  		ind := NearestIdx(test.in, test.query)
   909  		if ind != test.want {
   910  			t.Errorf(test.desc+": got:%d want:%d", ind, test.want)
   911  		}
   912  	}
   913  }
   914  
   915  func TestNorm(t *testing.T) {
   916  	s := []complex128{-1, -3.4, 5, -6}
   917  	val := Norm(s, math.Inf(1))
   918  	truth := 6.0
   919  	if math.Abs(val-truth) > EqTolerance {
   920  		t.Errorf("Doesn't match for inf norm. %v expected, %v found", truth, val)
   921  	}
   922  	// 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
   923  	val = Norm(s, 2)
   924  	truth = 8.5767126569566267590651614132751986658027271236078592
   925  	if math.Abs(val-truth) > EqTolerance {
   926  		t.Errorf("Doesn't match for inf norm. %v expected, %v found", truth, val)
   927  	}
   928  	// 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
   929  	val = Norm(s, 3)
   930  	truth = 7.2514321388020228478109121239004816430071237369356233
   931  	if math.Abs(val-truth) > EqTolerance {
   932  		t.Errorf("Doesn't match for inf norm. %v expected, %v found", truth, val)
   933  	}
   934  
   935  	//http://www.wolframalpha.com/input/?i=%7C-1%7C+%2B+%7C-3.4%7C+%2B+%7C5%7C%2B++%7C6%7C
   936  	val = Norm(s, 1)
   937  	truth = 15.4
   938  	if math.Abs(val-truth) > EqTolerance {
   939  		t.Errorf("Doesn't match for inf norm. %v expected, %v found", truth, val)
   940  	}
   941  }
   942  
   943  func TestProd(t *testing.T) {
   944  	s := []complex128{}
   945  	val := Prod(s)
   946  	if val != 1 {
   947  		t.Errorf("Val not returned as default when slice length is zero")
   948  	}
   949  	s = []complex128{3, 4, 1, 7, 5}
   950  	val = Prod(s)
   951  	if val != 420 {
   952  		t.Errorf("Wrong prod returned. Expected %v returned %v", 420, val)
   953  	}
   954  }
   955  
   956  func TestReverse(t *testing.T) {
   957  	for _, s := range [][]complex128{
   958  		{0},
   959  		{1, 0},
   960  		{2, 1, 0},
   961  		{3, 2, 1, 0},
   962  		{9, 8, 7, 6, 5, 4, 3, 2, 1, 0},
   963  	} {
   964  		Reverse(s)
   965  		for i, v := range s {
   966  			if v != complex(float64(i), 0) {
   967  				t.Errorf("unexpected values for element %d: got:%v want:%v", i, v, i)
   968  			}
   969  		}
   970  	}
   971  }
   972  
   973  func TestReal(t *testing.T) {
   974  	for i, test := range []struct {
   975  		dst    []float64
   976  		src    []complex128
   977  		want   []float64
   978  		panics bool
   979  	}{
   980  		{},
   981  		{
   982  			dst:  make([]float64, 4),
   983  			src:  []complex128{1 + 1i, 2 + 2i, 3 + 3i, 4 + 4i},
   984  			want: []float64{1, 2, 3, 4},
   985  		},
   986  		{
   987  			dst:    make([]float64, 3),
   988  			src:    []complex128{1 + 1i, 2 + 2i, 3 + 3i, 4 + 4i},
   989  			panics: true,
   990  		},
   991  		{
   992  			dst:  make([]float64, 4),
   993  			src:  []complex128{1 + 1i, 2 + 2i, 3 + 3i, cmplx.NaN()},
   994  			want: []float64{1, 2, 3, math.NaN()},
   995  		},
   996  	} {
   997  		var got []float64
   998  		panicked := Panics(func() {
   999  			got = Real(test.dst, test.src)
  1000  		})
  1001  		if panicked != test.panics {
  1002  			if panicked {
  1003  				t.Errorf("unexpected panic for test %d", i)
  1004  			} else {
  1005  				t.Errorf("expected panic for test %d", i)
  1006  			}
  1007  		}
  1008  		if panicked || test.panics {
  1009  			continue
  1010  		}
  1011  		if !floats.Same(got, test.dst) {
  1012  			t.Errorf("mismatch between dst and return test %d: got:%v want:%v", i, got, test.dst)
  1013  		}
  1014  		if !floats.Same(got, test.want) {
  1015  			t.Errorf("unexpected result for test %d: got:%v want:%v", i, got, test.want)
  1016  		}
  1017  	}
  1018  
  1019  }
  1020  func TestSame(t *testing.T) {
  1021  	s1 := []complex128{1 + 1i, 2 + 2i, 3 + 3i, 4 + 4i}
  1022  	s2 := []complex128{1 + 1i, 2 + 2i, 3 + 3i, 4 + 4i}
  1023  	if !Same(s1, s2) {
  1024  		t.Errorf("Equal slices returned as unequal")
  1025  	}
  1026  	s2 = []complex128{1 + 1i, 2 + 2i, 3 + 3i, 4 + 4i + 1e-14}
  1027  	if Same(s1, s2) {
  1028  		t.Errorf("Unequal slices returned as equal")
  1029  	}
  1030  	if Same(s1, []complex128{}) {
  1031  		t.Errorf("Unequal slice lengths returned as equal")
  1032  	}
  1033  	s1 = []complex128{1 + 1i, 2 + 2i, cmplx.NaN(), 4 + 4i}
  1034  	s2 = []complex128{1 + 1i, 2 + 2i, cmplx.NaN(), 4 + 4i}
  1035  	if !Same(s1, s2) {
  1036  		t.Errorf("Slices with matching NaN values returned as unequal")
  1037  	}
  1038  	s1 = []complex128{1 + 1i, 2 + 2i, cmplx.NaN(), 4 + 4i}
  1039  	s2 = []complex128{1 + 1i, cmplx.NaN(), 3 + 3i, 4 + 4i}
  1040  	if Same(s1, s2) {
  1041  		t.Errorf("Slices with unmatching NaN values returned as equal")
  1042  	}
  1043  }
  1044  
  1045  func TestScale(t *testing.T) {
  1046  	s := []complex128{3, 4, 1, 7, 5}
  1047  	c := 4 + 5i
  1048  	truth := []complex128{12 + 15i, 16 + 20i, 4 + 5i, 28 + 35i, 20 + 25i}
  1049  	Scale(c, s)
  1050  	areSlicesEqual(t, truth, s, "Bad scaling")
  1051  }
  1052  
  1053  func TestScaleReal(t *testing.T) {
  1054  	s := []complex128{3 + 4i, 4 + 5i, 1 + 2i, 7 + 6i, 5 + 2i}
  1055  	f := 5.0
  1056  	truth := []complex128{15 + 20i, 20 + 25i, 5 + 10i, 35 + 30i, 25 + 10i}
  1057  	ScaleReal(f, s)
  1058  	areSlicesEqual(t, truth, s, "Bad scaling")
  1059  }
  1060  
  1061  func TestScaleRealTo(t *testing.T) {
  1062  	s := []complex128{3 + 4i, 4 + 5i, 1 + 2i, 7 + 6i, 5 + 2i}
  1063  	sCopy := make([]complex128, len(s))
  1064  	copy(sCopy, s)
  1065  	f := 5.0
  1066  	truth := []complex128{15 + 20i, 20 + 25i, 5 + 10i, 35 + 30i, 25 + 10i}
  1067  	dst := make([]complex128, len(s))
  1068  	ScaleRealTo(dst, f, s)
  1069  	if !Same(dst, truth) {
  1070  		t.Errorf("ScaleRealTo dst does not match. Got %v, want %v", dst, truth)
  1071  	}
  1072  	if !Same(s, sCopy) {
  1073  		t.Errorf("SourceRealTo s modified during call. Got %v, want %v", s, sCopy)
  1074  	}
  1075  }
  1076  
  1077  func TestScaleTo(t *testing.T) {
  1078  	s := []complex128{3, 4, 1, 7, 5}
  1079  	sCopy := make([]complex128, len(s))
  1080  	copy(sCopy, s)
  1081  	c := 4 + 5i
  1082  	truth := []complex128{12 + 15i, 16 + 20i, 4 + 5i, 28 + 35i, 20 + 25i}
  1083  	dst := make([]complex128, len(s))
  1084  	ScaleTo(dst, c, s)
  1085  	if !Same(dst, truth) {
  1086  		t.Errorf("ScaleTo dst does not match. Got %v, want %v", dst, truth)
  1087  	}
  1088  	if !Same(s, sCopy) {
  1089  		t.Errorf("SourceTo s modified during call. Got %v, want %v", s, sCopy)
  1090  	}
  1091  }
  1092  
  1093  func TestSpan(t *testing.T) {
  1094  	receiver1 := make([]complex128, 5)
  1095  	truth := []complex128{1 + 1i, 2 + 2i, 3 + 3i, 4 + 4i, 5 + 5i}
  1096  	receiver2 := Span(receiver1, 1+1i, 5+5i)
  1097  	areSlicesEqual(t, truth, receiver1, "Improper linspace from mutator")
  1098  	areSlicesEqual(t, truth, receiver2, "Improper linspace from returned slice")
  1099  	receiver1 = make([]complex128, 6)
  1100  	truth = []complex128{0, 0.2 + 0.4i, 0.4 + 0.8i, 0.6 + 1.2i, 0.8 + 1.6i, 1 + 2i}
  1101  	Span(receiver1, 0, 1+2i)
  1102  	areSlicesEqual(t, truth, receiver1, "Improper linspace")
  1103  	if !Panics(func() { Span(nil, 1, 5) }) {
  1104  		t.Errorf("Span accepts nil argument")
  1105  	}
  1106  	if !Panics(func() { Span(make([]complex128, 1), 1, 5) }) {
  1107  		t.Errorf("Span accepts argument of len = 1")
  1108  	}
  1109  
  1110  	for _, test := range []struct {
  1111  		n    int
  1112  		l, u complex128
  1113  		want []complex128
  1114  	}{
  1115  		{
  1116  			n: 5, l: cmplx.Inf(), u: cmplx.Inf(),
  1117  			want: []complex128{cmplx.Inf(), cmplx.Inf(), cmplx.Inf(), cmplx.Inf(), cmplx.Inf()},
  1118  		},
  1119  		{
  1120  			n: 5, l: cmplx.Inf(), u: cmplx.NaN(),
  1121  			want: []complex128{cmplx.Inf(), cmplx.NaN(), cmplx.NaN(), cmplx.NaN(), cmplx.NaN()},
  1122  		},
  1123  		{
  1124  			n: 5, l: cmplx.NaN(), u: cmplx.Inf(),
  1125  			want: []complex128{cmplx.NaN(), cmplx.NaN(), cmplx.NaN(), cmplx.NaN(), cmplx.Inf()},
  1126  		},
  1127  		{
  1128  			n: 5, l: 42, u: cmplx.Inf(),
  1129  			want: []complex128{42, cmplx.Inf(), cmplx.Inf(), cmplx.Inf(), cmplx.Inf()},
  1130  		},
  1131  		{
  1132  			n: 5, l: 42, u: cmplx.NaN(),
  1133  			want: []complex128{42, cmplx.NaN(), cmplx.NaN(), cmplx.NaN(), cmplx.NaN()},
  1134  		},
  1135  		{
  1136  			n: 5, l: cmplx.Inf(), u: 42,
  1137  			want: []complex128{cmplx.Inf(), cmplx.Inf(), cmplx.Inf(), cmplx.Inf(), 42},
  1138  		},
  1139  		{
  1140  			n: 5, l: cmplx.NaN(), u: 42,
  1141  			want: []complex128{cmplx.NaN(), cmplx.NaN(), cmplx.NaN(), cmplx.NaN(), 42},
  1142  		},
  1143  	} {
  1144  		got := Span(make([]complex128, test.n), test.l, test.u)
  1145  		areSlicesSame(t, test.want, got,
  1146  			fmt.Sprintf("Unexpected slice of length %d for %f to %f", test.n, test.l, test.u))
  1147  	}
  1148  }
  1149  
  1150  func TestSub(t *testing.T) {
  1151  	s := []complex128{3 + 2i, 4 + 3i, 1 + 7i, 7 + 1i, 5 - 1i}
  1152  	v := []complex128{1 + 1i, 2 + 4i, 3, 4, 5 - 1i}
  1153  	truth := []complex128{2 + 1i, 2 - 1i, -2 + 7i, 3 + 1i, 0}
  1154  	Sub(s, v)
  1155  	areSlicesEqual(t, truth, s, "Bad subtract")
  1156  	// Test that it panics
  1157  	if !Panics(func() { Sub(make([]complex128, 2), make([]complex128, 3)) }) {
  1158  		t.Errorf("Did not panic with length mismatch")
  1159  	}
  1160  }
  1161  
  1162  func TestSubTo(t *testing.T) {
  1163  	s := []complex128{3 + 2i, 4 + 3i, 1 + 7i, 7 + 1i, 5 - 1i}
  1164  	v := []complex128{1 + 1i, 2 + 4i, 3, 4, 5 - 1i}
  1165  	truth := []complex128{2 + 1i, 2 - 1i, -2 + 7i, 3 + 1i, 0}
  1166  	dst1 := make([]complex128, len(s))
  1167  	dst2 := SubTo(dst1, s, v)
  1168  	areSlicesEqual(t, truth, dst1, "Bad subtract from mutator")
  1169  	areSlicesEqual(t, truth, dst2, "Bad subtract from returned slice")
  1170  	// Test that all mismatch combinations panic
  1171  	if !Panics(func() { SubTo(make([]complex128, 2), make([]complex128, 3), make([]complex128, 3)) }) {
  1172  		t.Errorf("Did not panic with dst different length")
  1173  	}
  1174  	if !Panics(func() { SubTo(make([]complex128, 3), make([]complex128, 2), make([]complex128, 3)) }) {
  1175  		t.Errorf("Did not panic with subtractor different length")
  1176  	}
  1177  	if !Panics(func() { SubTo(make([]complex128, 3), make([]complex128, 3), make([]complex128, 2)) }) {
  1178  		t.Errorf("Did not panic with subtractee different length")
  1179  	}
  1180  }
  1181  
  1182  func TestSum(t *testing.T) {
  1183  	s := []complex128{}
  1184  	val := Sum(s)
  1185  	if val != 0 {
  1186  		t.Errorf("Val not returned as default when slice length is zero")
  1187  	}
  1188  	s = []complex128{3 + 1i, 4 + 2i, 1 + 3i, 7 + 4i, 5 + 5i}
  1189  	val = Sum(s)
  1190  	if val != 20+15i {
  1191  		t.Errorf("Wrong sum returned")
  1192  	}
  1193  }
  1194  
  1195  func randomSlice(l int, src rand.Source) []complex128 {
  1196  	rnd := rand.New(src)
  1197  	s := make([]complex128, l)
  1198  	for i := range s {
  1199  		s[i] = complex(rnd.Float64(), rnd.Float64())
  1200  	}
  1201  	return s
  1202  }
  1203  
  1204  func benchmarkAdd(b *testing.B, size int) {
  1205  	src := rand.NewSource(1)
  1206  	s1 := randomSlice(size, src)
  1207  	s2 := randomSlice(size, src)
  1208  	b.ResetTimer()
  1209  	for i := 0; i < b.N; i++ {
  1210  		Add(s1, s2)
  1211  	}
  1212  }
  1213  func BenchmarkAddSmall(b *testing.B) { benchmarkAdd(b, Small) }
  1214  func BenchmarkAddMed(b *testing.B)   { benchmarkAdd(b, Medium) }
  1215  func BenchmarkAddLarge(b *testing.B) { benchmarkAdd(b, Large) }
  1216  func BenchmarkAddHuge(b *testing.B)  { benchmarkAdd(b, Huge) }
  1217  
  1218  func benchmarkAddTo(b *testing.B, size int) {
  1219  	src := rand.NewSource(1)
  1220  	s1 := randomSlice(size, src)
  1221  	s2 := randomSlice(size, src)
  1222  	dst := randomSlice(size, src)
  1223  	b.ResetTimer()
  1224  	for i := 0; i < b.N; i++ {
  1225  		AddTo(dst, s1, s2)
  1226  	}
  1227  }
  1228  func BenchmarkAddToSmall(b *testing.B) { benchmarkAddTo(b, Small) }
  1229  func BenchmarkAddToMed(b *testing.B)   { benchmarkAddTo(b, Medium) }
  1230  func BenchmarkAddToLarge(b *testing.B) { benchmarkAddTo(b, Large) }
  1231  func BenchmarkAddToHuge(b *testing.B)  { benchmarkAddTo(b, Huge) }
  1232  
  1233  func benchmarkCumProd(b *testing.B, size int) {
  1234  	src := rand.NewSource(1)
  1235  	s := randomSlice(size, src)
  1236  	dst := randomSlice(size, src)
  1237  	b.ResetTimer()
  1238  	for i := 0; i < b.N; i++ {
  1239  		CumProd(dst, s)
  1240  	}
  1241  }
  1242  func BenchmarkCumProdSmall(b *testing.B) { benchmarkCumProd(b, Small) }
  1243  func BenchmarkCumProdMed(b *testing.B)   { benchmarkCumProd(b, Medium) }
  1244  func BenchmarkCumProdLarge(b *testing.B) { benchmarkCumProd(b, Large) }
  1245  func BenchmarkCumProdHuge(b *testing.B)  { benchmarkCumProd(b, Huge) }
  1246  
  1247  func benchmarkCumSum(b *testing.B, size int) {
  1248  	src := rand.NewSource(1)
  1249  	s := randomSlice(size, src)
  1250  	dst := randomSlice(size, src)
  1251  	b.ResetTimer()
  1252  	for i := 0; i < b.N; i++ {
  1253  		CumSum(dst, s)
  1254  	}
  1255  }
  1256  func BenchmarkCumSumSmall(b *testing.B) { benchmarkCumSum(b, Small) }
  1257  func BenchmarkCumSumMed(b *testing.B)   { benchmarkCumSum(b, Medium) }
  1258  func BenchmarkCumSumLarge(b *testing.B) { benchmarkCumSum(b, Large) }
  1259  func BenchmarkCumSumHuge(b *testing.B)  { benchmarkCumSum(b, Huge) }
  1260  
  1261  func benchmarkDiv(b *testing.B, size int) {
  1262  	src := rand.NewSource(1)
  1263  	s := randomSlice(size, src)
  1264  	dst := randomSlice(size, src)
  1265  	b.ResetTimer()
  1266  	for i := 0; i < b.N; i++ {
  1267  		Div(dst, s)
  1268  	}
  1269  }
  1270  func BenchmarkDivSmall(b *testing.B) { benchmarkDiv(b, Small) }
  1271  func BenchmarkDivMed(b *testing.B)   { benchmarkDiv(b, Medium) }
  1272  func BenchmarkDivLarge(b *testing.B) { benchmarkDiv(b, Large) }
  1273  func BenchmarkDivHuge(b *testing.B)  { benchmarkDiv(b, Huge) }
  1274  
  1275  func benchmarkDivTo(b *testing.B, size int) {
  1276  	src := rand.NewSource(1)
  1277  	s1 := randomSlice(size, src)
  1278  	s2 := randomSlice(size, src)
  1279  	dst := randomSlice(size, src)
  1280  	b.ResetTimer()
  1281  	for i := 0; i < b.N; i++ {
  1282  		DivTo(dst, s1, s2)
  1283  	}
  1284  }
  1285  func BenchmarkDivToSmall(b *testing.B) { benchmarkDivTo(b, Small) }
  1286  func BenchmarkDivToMed(b *testing.B)   { benchmarkDivTo(b, Medium) }
  1287  func BenchmarkDivToLarge(b *testing.B) { benchmarkDivTo(b, Large) }
  1288  func BenchmarkDivToHuge(b *testing.B)  { benchmarkDivTo(b, Huge) }
  1289  
  1290  func benchmarkSub(b *testing.B, size int) {
  1291  	src := rand.NewSource(1)
  1292  	s1 := randomSlice(size, src)
  1293  	s2 := randomSlice(size, src)
  1294  	b.ResetTimer()
  1295  	for i := 0; i < b.N; i++ {
  1296  		Sub(s1, s2)
  1297  	}
  1298  }
  1299  func BenchmarkSubSmall(b *testing.B) { benchmarkSub(b, Small) }
  1300  func BenchmarkSubMed(b *testing.B)   { benchmarkSub(b, Medium) }
  1301  func BenchmarkSubLarge(b *testing.B) { benchmarkSub(b, Large) }
  1302  func BenchmarkSubHuge(b *testing.B)  { benchmarkSub(b, Huge) }
  1303  
  1304  func benchmarkSubTo(b *testing.B, size int) {
  1305  	src := rand.NewSource(1)
  1306  	s1 := randomSlice(size, src)
  1307  	s2 := randomSlice(size, src)
  1308  	dst := randomSlice(size, src)
  1309  	b.ResetTimer()
  1310  	for i := 0; i < b.N; i++ {
  1311  		SubTo(dst, s1, s2)
  1312  	}
  1313  }
  1314  func BenchmarkSubToSmall(b *testing.B) { benchmarkSubTo(b, Small) }
  1315  func BenchmarkSubToMed(b *testing.B)   { benchmarkSubTo(b, Medium) }
  1316  func BenchmarkSubToLarge(b *testing.B) { benchmarkSubTo(b, Large) }
  1317  func BenchmarkSubToHuge(b *testing.B)  { benchmarkSubTo(b, Huge) }
  1318  
  1319  func benchmarkDot(b *testing.B, size int) {
  1320  	src := rand.NewSource(1)
  1321  	s1 := randomSlice(size, src)
  1322  	s2 := randomSlice(size, src)
  1323  	b.ResetTimer()
  1324  	for i := 0; i < b.N; i++ {
  1325  		Dot(s1, s2)
  1326  	}
  1327  }
  1328  func BenchmarkDotSmall(b *testing.B) { benchmarkDot(b, Small) }
  1329  func BenchmarkDotMed(b *testing.B)   { benchmarkDot(b, Medium) }
  1330  func BenchmarkDotLarge(b *testing.B) { benchmarkDot(b, Large) }
  1331  func BenchmarkDotHuge(b *testing.B)  { benchmarkDot(b, Huge) }
  1332  
  1333  func benchmarkAddScaledTo(b *testing.B, size int) {
  1334  	src := rand.NewSource(1)
  1335  	dst := randomSlice(size, src)
  1336  	y := randomSlice(size, src)
  1337  	s := randomSlice(size, src)
  1338  	b.ResetTimer()
  1339  	for i := 0; i < b.N; i++ {
  1340  		AddScaledTo(dst, y, 2.3, s)
  1341  	}
  1342  }
  1343  func BenchmarkAddScaledToSmall(b *testing.B)  { benchmarkAddScaledTo(b, Small) }
  1344  func BenchmarkAddScaledToMedium(b *testing.B) { benchmarkAddScaledTo(b, Medium) }
  1345  func BenchmarkAddScaledToLarge(b *testing.B)  { benchmarkAddScaledTo(b, Large) }
  1346  func BenchmarkAddScaledToHuge(b *testing.B)   { benchmarkAddScaledTo(b, Huge) }
  1347  
  1348  func benchmarkScale(b *testing.B, size int) {
  1349  	src := rand.NewSource(1)
  1350  	dst := randomSlice(size, src)
  1351  	b.ResetTimer()
  1352  	for i := 0; i < b.N; i += 2 {
  1353  		Scale(2.0, dst)
  1354  		Scale(0.5, dst)
  1355  	}
  1356  }
  1357  func BenchmarkScaleSmall(b *testing.B)  { benchmarkScale(b, Small) }
  1358  func BenchmarkScaleMedium(b *testing.B) { benchmarkScale(b, Medium) }
  1359  func BenchmarkScaleLarge(b *testing.B)  { benchmarkScale(b, Large) }
  1360  func BenchmarkScaleHuge(b *testing.B)   { benchmarkScale(b, Huge) }
  1361  
  1362  func benchmarkNorm2(b *testing.B, size int) {
  1363  	src := rand.NewSource(1)
  1364  	s := randomSlice(size, src)
  1365  	b.ResetTimer()
  1366  	for i := 0; i < b.N; i++ {
  1367  		Norm(s, 2)
  1368  	}
  1369  }
  1370  func BenchmarkNorm2Small(b *testing.B)  { benchmarkNorm2(b, Small) }
  1371  func BenchmarkNorm2Medium(b *testing.B) { benchmarkNorm2(b, Medium) }
  1372  func BenchmarkNorm2Large(b *testing.B)  { benchmarkNorm2(b, Large) }
  1373  func BenchmarkNorm2Huge(b *testing.B)   { benchmarkNorm2(b, Huge) }