github.com/jingcheng-WU/gonum@v0.9.1-0.20210323123734-f1a2a11a8f7b/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  	"golang.org/x/exp/rand"
    15  
    16  	"github.com/jingcheng-WU/gonum/cmplxs/cscalar"
    17  	"github.com/jingcheng-WU/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 TestMulTo(t *testing.T) {
   729  	s1 := []complex128{1 + 1i, 2 + 2i, 3 + 3i}
   730  	s1orig := []complex128{1 + 1i, 2 + 2i, 3 + 3i}
   731  	s2 := []complex128{1 + 1i, 2 + 2i, 3 + 3i}
   732  	s2orig := []complex128{1 + 1i, 2 + 2i, 3 + 3i}
   733  	dst1 := make([]complex128, 3)
   734  	ans := []complex128{0 + 2i, 0 + 8i, 0 + 18i}
   735  	dst2 := MulTo(dst1, s1, s2)
   736  	if !EqualApprox(dst1, ans, EqTolerance) {
   737  		t.Errorf("MulTo doesn't give correct answer in mutated slice")
   738  	}
   739  	if !EqualApprox(dst2, ans, EqTolerance) {
   740  		t.Errorf("MulTo doesn't give correct answer in returned slice")
   741  	}
   742  	if !EqualApprox(s1, s1orig, EqTolerance) {
   743  		t.Errorf("S1 changes during multo")
   744  	}
   745  	if !EqualApprox(s2, s2orig, EqTolerance) {
   746  		t.Errorf("s2 changes during multo")
   747  	}
   748  	MulTo(dst1, s1, s2)
   749  	if !EqualApprox(dst1, ans, EqTolerance) {
   750  		t.Errorf("MulTo doesn't give correct answer reusing dst")
   751  	}
   752  	dstShort := []complex128{1}
   753  	if !Panics(func() { MulTo(dstShort, s1, s2) }) {
   754  		t.Errorf("Did not panic with s1 wrong length")
   755  	}
   756  	s1short := []complex128{1}
   757  	if !Panics(func() { MulTo(dst1, s1short, s2) }) {
   758  		t.Errorf("Did not panic with s1 wrong length")
   759  	}
   760  	s2short := []complex128{1}
   761  	if !Panics(func() { MulTo(dst1, s1, s2short) }) {
   762  		t.Errorf("Did not panic with s2 wrong length")
   763  	}
   764  }
   765  
   766  // Complexify
   767  
   768  func TestNearestIdx(t *testing.T) {
   769  	for _, test := range []struct {
   770  		in    []complex128
   771  		query complex128
   772  		want  int
   773  		desc  string
   774  	}{
   775  		{
   776  			in:    []complex128{6.2, 3, 5, 6.2, 8},
   777  			query: 2,
   778  			want:  1,
   779  			desc:  "Wrong index returned when value is less than all of elements",
   780  		},
   781  		{
   782  			in:    []complex128{6.2, 3, 5, 6.2, 8},
   783  			query: 9,
   784  			want:  4,
   785  			desc:  "Wrong index returned when value is greater than all of elements",
   786  		},
   787  		{
   788  			in:    []complex128{6.2, 3, 5, 6.2, 8},
   789  			query: 3.1,
   790  			want:  1,
   791  			desc:  "Wrong index returned when value is greater than closest element",
   792  		},
   793  		{
   794  			in:    []complex128{6.2, 3, 5, 6.2, 8},
   795  			query: 2.9,
   796  			want:  1,
   797  			desc:  "Wrong index returned when value is less than closest element",
   798  		},
   799  		{
   800  			in:    []complex128{6.2, 3, 5, 6.2, 8},
   801  			query: 3,
   802  			want:  1,
   803  			desc:  "Wrong index returned when value is equal to element",
   804  		},
   805  		{
   806  			in:    []complex128{6.2, 3, 5, 6.2, 8},
   807  			query: 6.2,
   808  			want:  0,
   809  			desc:  "Wrong index returned when value is equal to several elements",
   810  		},
   811  		{
   812  			in:    []complex128{6.2, 3, 5, 6.2, 8},
   813  			query: 4,
   814  			want:  1,
   815  			desc:  "Wrong index returned when value is exactly between two closest elements",
   816  		},
   817  		{
   818  			in:    []complex128{cmplx.NaN(), 3, 2, -1},
   819  			query: 2,
   820  			want:  2,
   821  			desc:  "Wrong index returned when initial element is NaN",
   822  		},
   823  		{
   824  			in:    []complex128{0, cmplx.NaN(), -1, 2},
   825  			query: cmplx.NaN(),
   826  			want:  0,
   827  			desc:  "Wrong index returned when query is NaN and a NaN element exists",
   828  		},
   829  		{
   830  			in:    []complex128{0, cmplx.NaN(), -1, 2},
   831  			query: cmplx.Inf(),
   832  			want:  3,
   833  			desc:  "Wrong index returned when query is Inf and no Inf element exists",
   834  		},
   835  		{
   836  			in:    []complex128{cmplx.NaN(), cmplx.NaN(), cmplx.NaN()},
   837  			query: 1,
   838  			want:  0,
   839  			desc:  "Wrong index returned when query is a number and only NaN elements exist",
   840  		},
   841  		{
   842  			in:    []complex128{cmplx.NaN(), cmplx.Inf()},
   843  			query: 1,
   844  			want:  1,
   845  			desc:  "Wrong index returned when query is a number and single NaN precedes Inf",
   846  		},
   847  	} {
   848  		ind := NearestIdx(test.in, test.query)
   849  		if ind != test.want {
   850  			t.Errorf(test.desc+": got:%d want:%d", ind, test.want)
   851  		}
   852  	}
   853  }
   854  
   855  func TestNorm(t *testing.T) {
   856  	s := []complex128{-1, -3.4, 5, -6}
   857  	val := Norm(s, math.Inf(1))
   858  	truth := 6.0
   859  	if math.Abs(val-truth) > EqTolerance {
   860  		t.Errorf("Doesn't match for inf norm. %v expected, %v found", truth, val)
   861  	}
   862  	// 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
   863  	val = Norm(s, 2)
   864  	truth = 8.5767126569566267590651614132751986658027271236078592
   865  	if math.Abs(val-truth) > EqTolerance {
   866  		t.Errorf("Doesn't match for inf norm. %v expected, %v found", truth, val)
   867  	}
   868  	// 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
   869  	val = Norm(s, 3)
   870  	truth = 7.2514321388020228478109121239004816430071237369356233
   871  	if math.Abs(val-truth) > EqTolerance {
   872  		t.Errorf("Doesn't match for inf norm. %v expected, %v found", truth, val)
   873  	}
   874  
   875  	//http://www.wolframalpha.com/input/?i=%7C-1%7C+%2B+%7C-3.4%7C+%2B+%7C5%7C%2B++%7C6%7C
   876  	val = Norm(s, 1)
   877  	truth = 15.4
   878  	if math.Abs(val-truth) > EqTolerance {
   879  		t.Errorf("Doesn't match for inf norm. %v expected, %v found", truth, val)
   880  	}
   881  }
   882  
   883  func TestProd(t *testing.T) {
   884  	s := []complex128{}
   885  	val := Prod(s)
   886  	if val != 1 {
   887  		t.Errorf("Val not returned as default when slice length is zero")
   888  	}
   889  	s = []complex128{3, 4, 1, 7, 5}
   890  	val = Prod(s)
   891  	if val != 420 {
   892  		t.Errorf("Wrong prod returned. Expected %v returned %v", 420, val)
   893  	}
   894  }
   895  
   896  func TestReverse(t *testing.T) {
   897  	for _, s := range [][]complex128{
   898  		{0},
   899  		{1, 0},
   900  		{2, 1, 0},
   901  		{3, 2, 1, 0},
   902  		{9, 8, 7, 6, 5, 4, 3, 2, 1, 0},
   903  	} {
   904  		Reverse(s)
   905  		for i, v := range s {
   906  			if v != complex(float64(i), 0) {
   907  				t.Errorf("unexpected values for element %d: got:%v want:%v", i, v, i)
   908  			}
   909  		}
   910  	}
   911  }
   912  
   913  func TestReal(t *testing.T) {
   914  	for i, test := range []struct {
   915  		dst    []float64
   916  		src    []complex128
   917  		want   []float64
   918  		panics bool
   919  	}{
   920  		{},
   921  		{
   922  			dst:  make([]float64, 4),
   923  			src:  []complex128{1 + 1i, 2 + 2i, 3 + 3i, 4 + 4i},
   924  			want: []float64{1, 2, 3, 4},
   925  		},
   926  		{
   927  			dst:    make([]float64, 3),
   928  			src:    []complex128{1 + 1i, 2 + 2i, 3 + 3i, 4 + 4i},
   929  			panics: true,
   930  		},
   931  		{
   932  			dst:  make([]float64, 4),
   933  			src:  []complex128{1 + 1i, 2 + 2i, 3 + 3i, cmplx.NaN()},
   934  			want: []float64{1, 2, 3, math.NaN()},
   935  		},
   936  	} {
   937  		var got []float64
   938  		panicked := Panics(func() {
   939  			got = Real(test.dst, test.src)
   940  		})
   941  		if panicked != test.panics {
   942  			if panicked {
   943  				t.Errorf("unexpected panic for test %d", i)
   944  			} else {
   945  				t.Errorf("expected panic for test %d", i)
   946  			}
   947  		}
   948  		if panicked || test.panics {
   949  			continue
   950  		}
   951  		if !floats.Same(got, test.dst) {
   952  			t.Errorf("mismatch between dst and return test %d: got:%v want:%v", i, got, test.dst)
   953  		}
   954  		if !floats.Same(got, test.want) {
   955  			t.Errorf("unexpected result for test %d: got:%v want:%v", i, got, test.want)
   956  		}
   957  	}
   958  
   959  }
   960  func TestSame(t *testing.T) {
   961  	s1 := []complex128{1 + 1i, 2 + 2i, 3 + 3i, 4 + 4i}
   962  	s2 := []complex128{1 + 1i, 2 + 2i, 3 + 3i, 4 + 4i}
   963  	if !Same(s1, s2) {
   964  		t.Errorf("Equal slices returned as unequal")
   965  	}
   966  	s2 = []complex128{1 + 1i, 2 + 2i, 3 + 3i, 4 + 4i + 1e-14}
   967  	if Same(s1, s2) {
   968  		t.Errorf("Unequal slices returned as equal")
   969  	}
   970  	if Same(s1, []complex128{}) {
   971  		t.Errorf("Unequal slice lengths returned as equal")
   972  	}
   973  	s1 = []complex128{1 + 1i, 2 + 2i, cmplx.NaN(), 4 + 4i}
   974  	s2 = []complex128{1 + 1i, 2 + 2i, cmplx.NaN(), 4 + 4i}
   975  	if !Same(s1, s2) {
   976  		t.Errorf("Slices with matching NaN values returned as unequal")
   977  	}
   978  	s1 = []complex128{1 + 1i, 2 + 2i, cmplx.NaN(), 4 + 4i}
   979  	s2 = []complex128{1 + 1i, cmplx.NaN(), 3 + 3i, 4 + 4i}
   980  	if Same(s1, s2) {
   981  		t.Errorf("Slices with unmatching NaN values returned as equal")
   982  	}
   983  }
   984  
   985  func TestScale(t *testing.T) {
   986  	s := []complex128{3, 4, 1, 7, 5}
   987  	c := 5 + 5i
   988  	truth := []complex128{15 + 15i, 20 + 20i, 5 + 5i, 35 + 35i, 25 + 25i}
   989  	Scale(c, s)
   990  	areSlicesEqual(t, truth, s, "Bad scaling")
   991  }
   992  
   993  func TestScaleTo(t *testing.T) {
   994  	s := []complex128{3, 4, 1, 7, 5}
   995  	sCopy := make([]complex128, len(s))
   996  	copy(sCopy, s)
   997  	c := 5 + 5i
   998  	truth := []complex128{15 + 15i, 20 + 20i, 5 + 5i, 35 + 35i, 25 + 25i}
   999  	dst := make([]complex128, len(s))
  1000  	ScaleTo(dst, c, s)
  1001  	if !Same(dst, truth) {
  1002  		t.Errorf("Scale to does not match. Got %v, want %v", dst, truth)
  1003  	}
  1004  	if !Same(s, sCopy) {
  1005  		t.Errorf("Source modified during call. Got %v, want %v", s, sCopy)
  1006  	}
  1007  }
  1008  
  1009  func TestSpan(t *testing.T) {
  1010  	receiver1 := make([]complex128, 5)
  1011  	truth := []complex128{1 + 1i, 2 + 2i, 3 + 3i, 4 + 4i, 5 + 5i}
  1012  	receiver2 := Span(receiver1, 1+1i, 5+5i)
  1013  	areSlicesEqual(t, truth, receiver1, "Improper linspace from mutator")
  1014  	areSlicesEqual(t, truth, receiver2, "Improper linspace from returned slice")
  1015  	receiver1 = make([]complex128, 6)
  1016  	truth = []complex128{0, 0.2 + 0.4i, 0.4 + 0.8i, 0.6 + 1.2i, 0.8 + 1.6i, 1 + 2i}
  1017  	Span(receiver1, 0, 1+2i)
  1018  	areSlicesEqual(t, truth, receiver1, "Improper linspace")
  1019  	if !Panics(func() { Span(nil, 1, 5) }) {
  1020  		t.Errorf("Span accepts nil argument")
  1021  	}
  1022  	if !Panics(func() { Span(make([]complex128, 1), 1, 5) }) {
  1023  		t.Errorf("Span accepts argument of len = 1")
  1024  	}
  1025  
  1026  	for _, test := range []struct {
  1027  		n    int
  1028  		l, u complex128
  1029  		want []complex128
  1030  	}{
  1031  		{
  1032  			n: 5, l: cmplx.Inf(), u: cmplx.Inf(),
  1033  			want: []complex128{cmplx.Inf(), cmplx.Inf(), cmplx.Inf(), cmplx.Inf(), cmplx.Inf()},
  1034  		},
  1035  		{
  1036  			n: 5, l: cmplx.Inf(), u: cmplx.NaN(),
  1037  			want: []complex128{cmplx.Inf(), cmplx.NaN(), cmplx.NaN(), cmplx.NaN(), cmplx.NaN()},
  1038  		},
  1039  		{
  1040  			n: 5, l: cmplx.NaN(), u: cmplx.Inf(),
  1041  			want: []complex128{cmplx.NaN(), cmplx.NaN(), cmplx.NaN(), cmplx.NaN(), cmplx.Inf()},
  1042  		},
  1043  		{
  1044  			n: 5, l: 42, u: cmplx.Inf(),
  1045  			want: []complex128{42, cmplx.Inf(), cmplx.Inf(), cmplx.Inf(), cmplx.Inf()},
  1046  		},
  1047  		{
  1048  			n: 5, l: 42, u: cmplx.NaN(),
  1049  			want: []complex128{42, cmplx.NaN(), cmplx.NaN(), cmplx.NaN(), cmplx.NaN()},
  1050  		},
  1051  		{
  1052  			n: 5, l: cmplx.Inf(), u: 42,
  1053  			want: []complex128{cmplx.Inf(), cmplx.Inf(), cmplx.Inf(), cmplx.Inf(), 42},
  1054  		},
  1055  		{
  1056  			n: 5, l: cmplx.NaN(), u: 42,
  1057  			want: []complex128{cmplx.NaN(), cmplx.NaN(), cmplx.NaN(), cmplx.NaN(), 42},
  1058  		},
  1059  	} {
  1060  		got := Span(make([]complex128, test.n), test.l, test.u)
  1061  		areSlicesSame(t, test.want, got,
  1062  			fmt.Sprintf("Unexpected slice of length %d for %f to %f", test.n, test.l, test.u))
  1063  	}
  1064  }
  1065  
  1066  func TestSub(t *testing.T) {
  1067  	s := []complex128{3 + 2i, 4 + 3i, 1 + 7i, 7 + 1i, 5 - 1i}
  1068  	v := []complex128{1 + 1i, 2 + 4i, 3, 4, 5 - 1i}
  1069  	truth := []complex128{2 + 1i, 2 - 1i, -2 + 7i, 3 + 1i, 0}
  1070  	Sub(s, v)
  1071  	areSlicesEqual(t, truth, s, "Bad subtract")
  1072  	// Test that it panics
  1073  	if !Panics(func() { Sub(make([]complex128, 2), make([]complex128, 3)) }) {
  1074  		t.Errorf("Did not panic with length mismatch")
  1075  	}
  1076  }
  1077  
  1078  func TestSubTo(t *testing.T) {
  1079  	s := []complex128{3 + 2i, 4 + 3i, 1 + 7i, 7 + 1i, 5 - 1i}
  1080  	v := []complex128{1 + 1i, 2 + 4i, 3, 4, 5 - 1i}
  1081  	truth := []complex128{2 + 1i, 2 - 1i, -2 + 7i, 3 + 1i, 0}
  1082  	dst1 := make([]complex128, len(s))
  1083  	dst2 := SubTo(dst1, s, v)
  1084  	areSlicesEqual(t, truth, dst1, "Bad subtract from mutator")
  1085  	areSlicesEqual(t, truth, dst2, "Bad subtract from returned slice")
  1086  	// Test that all mismatch combinations panic
  1087  	if !Panics(func() { SubTo(make([]complex128, 2), make([]complex128, 3), make([]complex128, 3)) }) {
  1088  		t.Errorf("Did not panic with dst different length")
  1089  	}
  1090  	if !Panics(func() { SubTo(make([]complex128, 3), make([]complex128, 2), make([]complex128, 3)) }) {
  1091  		t.Errorf("Did not panic with subtractor different length")
  1092  	}
  1093  	if !Panics(func() { SubTo(make([]complex128, 3), make([]complex128, 3), make([]complex128, 2)) }) {
  1094  		t.Errorf("Did not panic with subtractee different length")
  1095  	}
  1096  }
  1097  
  1098  func TestSum(t *testing.T) {
  1099  	s := []complex128{}
  1100  	val := Sum(s)
  1101  	if val != 0 {
  1102  		t.Errorf("Val not returned as default when slice length is zero")
  1103  	}
  1104  	s = []complex128{3 + 1i, 4 + 2i, 1 + 3i, 7 + 4i, 5 + 5i}
  1105  	val = Sum(s)
  1106  	if val != 20+15i {
  1107  		t.Errorf("Wrong sum returned")
  1108  	}
  1109  }
  1110  
  1111  func randomSlice(l int, src rand.Source) []complex128 {
  1112  	rnd := rand.New(src)
  1113  	s := make([]complex128, l)
  1114  	for i := range s {
  1115  		s[i] = complex(rnd.Float64(), rnd.Float64())
  1116  	}
  1117  	return s
  1118  }
  1119  
  1120  func benchmarkAdd(b *testing.B, size int) {
  1121  	src := rand.NewSource(1)
  1122  	s1 := randomSlice(size, src)
  1123  	s2 := randomSlice(size, src)
  1124  	b.ResetTimer()
  1125  	for i := 0; i < b.N; i++ {
  1126  		Add(s1, s2)
  1127  	}
  1128  }
  1129  func BenchmarkAddSmall(b *testing.B) { benchmarkAdd(b, Small) }
  1130  func BenchmarkAddMed(b *testing.B)   { benchmarkAdd(b, Medium) }
  1131  func BenchmarkAddLarge(b *testing.B) { benchmarkAdd(b, Large) }
  1132  func BenchmarkAddHuge(b *testing.B)  { benchmarkAdd(b, Huge) }
  1133  
  1134  func benchmarkAddTo(b *testing.B, size int) {
  1135  	src := rand.NewSource(1)
  1136  	s1 := randomSlice(size, src)
  1137  	s2 := randomSlice(size, src)
  1138  	dst := randomSlice(size, src)
  1139  	b.ResetTimer()
  1140  	for i := 0; i < b.N; i++ {
  1141  		AddTo(dst, s1, s2)
  1142  	}
  1143  }
  1144  func BenchmarkAddToSmall(b *testing.B) { benchmarkAddTo(b, Small) }
  1145  func BenchmarkAddToMed(b *testing.B)   { benchmarkAddTo(b, Medium) }
  1146  func BenchmarkAddToLarge(b *testing.B) { benchmarkAddTo(b, Large) }
  1147  func BenchmarkAddToHuge(b *testing.B)  { benchmarkAddTo(b, Huge) }
  1148  
  1149  func benchmarkCumProd(b *testing.B, size int) {
  1150  	src := rand.NewSource(1)
  1151  	s := randomSlice(size, src)
  1152  	dst := randomSlice(size, src)
  1153  	b.ResetTimer()
  1154  	for i := 0; i < b.N; i++ {
  1155  		CumProd(dst, s)
  1156  	}
  1157  }
  1158  func BenchmarkCumProdSmall(b *testing.B) { benchmarkCumProd(b, Small) }
  1159  func BenchmarkCumProdMed(b *testing.B)   { benchmarkCumProd(b, Medium) }
  1160  func BenchmarkCumProdLarge(b *testing.B) { benchmarkCumProd(b, Large) }
  1161  func BenchmarkCumProdHuge(b *testing.B)  { benchmarkCumProd(b, Huge) }
  1162  
  1163  func benchmarkCumSum(b *testing.B, size int) {
  1164  	src := rand.NewSource(1)
  1165  	s := randomSlice(size, src)
  1166  	dst := randomSlice(size, src)
  1167  	b.ResetTimer()
  1168  	for i := 0; i < b.N; i++ {
  1169  		CumSum(dst, s)
  1170  	}
  1171  }
  1172  func BenchmarkCumSumSmall(b *testing.B) { benchmarkCumSum(b, Small) }
  1173  func BenchmarkCumSumMed(b *testing.B)   { benchmarkCumSum(b, Medium) }
  1174  func BenchmarkCumSumLarge(b *testing.B) { benchmarkCumSum(b, Large) }
  1175  func BenchmarkCumSumHuge(b *testing.B)  { benchmarkCumSum(b, Huge) }
  1176  
  1177  func benchmarkDiv(b *testing.B, size int) {
  1178  	src := rand.NewSource(1)
  1179  	s := randomSlice(size, src)
  1180  	dst := randomSlice(size, src)
  1181  	b.ResetTimer()
  1182  	for i := 0; i < b.N; i++ {
  1183  		Div(dst, s)
  1184  	}
  1185  }
  1186  func BenchmarkDivSmall(b *testing.B) { benchmarkDiv(b, Small) }
  1187  func BenchmarkDivMed(b *testing.B)   { benchmarkDiv(b, Medium) }
  1188  func BenchmarkDivLarge(b *testing.B) { benchmarkDiv(b, Large) }
  1189  func BenchmarkDivHuge(b *testing.B)  { benchmarkDiv(b, Huge) }
  1190  
  1191  func benchmarkDivTo(b *testing.B, size int) {
  1192  	src := rand.NewSource(1)
  1193  	s1 := randomSlice(size, src)
  1194  	s2 := randomSlice(size, src)
  1195  	dst := randomSlice(size, src)
  1196  	b.ResetTimer()
  1197  	for i := 0; i < b.N; i++ {
  1198  		DivTo(dst, s1, s2)
  1199  	}
  1200  }
  1201  func BenchmarkDivToSmall(b *testing.B) { benchmarkDivTo(b, Small) }
  1202  func BenchmarkDivToMed(b *testing.B)   { benchmarkDivTo(b, Medium) }
  1203  func BenchmarkDivToLarge(b *testing.B) { benchmarkDivTo(b, Large) }
  1204  func BenchmarkDivToHuge(b *testing.B)  { benchmarkDivTo(b, Huge) }
  1205  
  1206  func benchmarkSub(b *testing.B, size int) {
  1207  	src := rand.NewSource(1)
  1208  	s1 := randomSlice(size, src)
  1209  	s2 := randomSlice(size, src)
  1210  	b.ResetTimer()
  1211  	for i := 0; i < b.N; i++ {
  1212  		Sub(s1, s2)
  1213  	}
  1214  }
  1215  func BenchmarkSubSmall(b *testing.B) { benchmarkSub(b, Small) }
  1216  func BenchmarkSubMed(b *testing.B)   { benchmarkSub(b, Medium) }
  1217  func BenchmarkSubLarge(b *testing.B) { benchmarkSub(b, Large) }
  1218  func BenchmarkSubHuge(b *testing.B)  { benchmarkSub(b, Huge) }
  1219  
  1220  func benchmarkSubTo(b *testing.B, size int) {
  1221  	src := rand.NewSource(1)
  1222  	s1 := randomSlice(size, src)
  1223  	s2 := randomSlice(size, src)
  1224  	dst := randomSlice(size, src)
  1225  	b.ResetTimer()
  1226  	for i := 0; i < b.N; i++ {
  1227  		SubTo(dst, s1, s2)
  1228  	}
  1229  }
  1230  func BenchmarkSubToSmall(b *testing.B) { benchmarkSubTo(b, Small) }
  1231  func BenchmarkSubToMed(b *testing.B)   { benchmarkSubTo(b, Medium) }
  1232  func BenchmarkSubToLarge(b *testing.B) { benchmarkSubTo(b, Large) }
  1233  func BenchmarkSubToHuge(b *testing.B)  { benchmarkSubTo(b, Huge) }
  1234  
  1235  func benchmarkDot(b *testing.B, size int) {
  1236  	src := rand.NewSource(1)
  1237  	s1 := randomSlice(size, src)
  1238  	s2 := randomSlice(size, src)
  1239  	b.ResetTimer()
  1240  	for i := 0; i < b.N; i++ {
  1241  		Dot(s1, s2)
  1242  	}
  1243  }
  1244  func BenchmarkDotSmall(b *testing.B) { benchmarkDot(b, Small) }
  1245  func BenchmarkDotMed(b *testing.B)   { benchmarkDot(b, Medium) }
  1246  func BenchmarkDotLarge(b *testing.B) { benchmarkDot(b, Large) }
  1247  func BenchmarkDotHuge(b *testing.B)  { benchmarkDot(b, Huge) }
  1248  
  1249  func benchmarkAddScaledTo(b *testing.B, size int) {
  1250  	src := rand.NewSource(1)
  1251  	dst := randomSlice(size, src)
  1252  	y := randomSlice(size, src)
  1253  	s := randomSlice(size, src)
  1254  	b.ResetTimer()
  1255  	for i := 0; i < b.N; i++ {
  1256  		AddScaledTo(dst, y, 2.3, s)
  1257  	}
  1258  }
  1259  func BenchmarkAddScaledToSmall(b *testing.B)  { benchmarkAddScaledTo(b, Small) }
  1260  func BenchmarkAddScaledToMedium(b *testing.B) { benchmarkAddScaledTo(b, Medium) }
  1261  func BenchmarkAddScaledToLarge(b *testing.B)  { benchmarkAddScaledTo(b, Large) }
  1262  func BenchmarkAddScaledToHuge(b *testing.B)   { benchmarkAddScaledTo(b, Huge) }
  1263  
  1264  func benchmarkScale(b *testing.B, size int) {
  1265  	src := rand.NewSource(1)
  1266  	dst := randomSlice(size, src)
  1267  	b.ResetTimer()
  1268  	for i := 0; i < b.N; i += 2 {
  1269  		Scale(2.0, dst)
  1270  		Scale(0.5, dst)
  1271  	}
  1272  }
  1273  func BenchmarkScaleSmall(b *testing.B)  { benchmarkScale(b, Small) }
  1274  func BenchmarkScaleMedium(b *testing.B) { benchmarkScale(b, Medium) }
  1275  func BenchmarkScaleLarge(b *testing.B)  { benchmarkScale(b, Large) }
  1276  func BenchmarkScaleHuge(b *testing.B)   { benchmarkScale(b, Huge) }
  1277  
  1278  func benchmarkNorm2(b *testing.B, size int) {
  1279  	src := rand.NewSource(1)
  1280  	s := randomSlice(size, src)
  1281  	b.ResetTimer()
  1282  	for i := 0; i < b.N; i++ {
  1283  		Norm(s, 2)
  1284  	}
  1285  }
  1286  func BenchmarkNorm2Small(b *testing.B)  { benchmarkNorm2(b, Small) }
  1287  func BenchmarkNorm2Medium(b *testing.B) { benchmarkNorm2(b, Medium) }
  1288  func BenchmarkNorm2Large(b *testing.B)  { benchmarkNorm2(b, Large) }
  1289  func BenchmarkNorm2Huge(b *testing.B)   { benchmarkNorm2(b, Huge) }