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) }