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
12 "golang.org/x/exp/rand"
23 func AreSlicesEqual(t *testing.T, truth, comp []float64, str string) {
24 if !EqualApprox(comp, truth, EqTolerance) {
25 t.Errorf(str+". Expected %v, returned %v", truth, comp)
29 func Panics(fun func()) (b bool) {
40 func TestAdd(t *testing.T) {
41 a := []float64{1, 2, 3}
42 b := []float64{4, 5, 6}
43 c := []float64{7, 8, 9}
44 truth := []float64{12, 15, 18}
45 n := make([]float64, len(a))
50 AreSlicesEqual(t, truth, n, "Wrong addition of slices new receiver")
53 AreSlicesEqual(t, truth, n, "Wrong addition of slices for no new receiver")
55 // Test that it panics
56 if !Panics(func() { Add(make([]float64, 2), make([]float64, 3)) }) {
57 t.Errorf("Did not panic with length mismatch")
61 func TestAddTo(t *testing.T) {
62 a := []float64{1, 2, 3}
63 b := []float64{4, 5, 6}
64 truth := []float64{5, 7, 9}
65 n1 := make([]float64, len(a))
68 AreSlicesEqual(t, truth, n1, "Bad addition from mutator")
69 AreSlicesEqual(t, truth, n2, "Bad addition from returned slice")
71 // Test that it panics
72 if !Panics(func() { AddTo(make([]float64, 2), make([]float64, 3), make([]float64, 3)) }) {
73 t.Errorf("Did not panic with length mismatch")
75 if !Panics(func() { AddTo(make([]float64, 3), make([]float64, 3), make([]float64, 2)) }) {
76 t.Errorf("Did not panic with length mismatch")
81 func TestAddConst(t *testing.T) {
82 s := []float64{3, 4, 1, 7, 5}
84 truth := []float64{9, 10, 7, 13, 11}
86 AreSlicesEqual(t, truth, s, "Wrong addition of constant")
89 func TestAddScaled(t *testing.T) {
90 s := []float64{3, 4, 1, 7, 5}
92 dst := []float64{1, 2, 3, 4, 5}
93 ans := []float64{19, 26, 9, 46, 35}
94 AddScaled(dst, alpha, s)
95 if !EqualApprox(dst, ans, EqTolerance) {
96 t.Errorf("Adding scaled did not match")
99 if !Panics(func() { AddScaled(dst, alpha, short) }) {
100 t.Errorf("Doesn't panic if s is smaller than dst")
102 if !Panics(func() { AddScaled(short, alpha, s) }) {
103 t.Errorf("Doesn't panic if dst is smaller than s")
107 func TestAddScaledTo(t *testing.T) {
108 s := []float64{3, 4, 1, 7, 5}
110 y := []float64{1, 2, 3, 4, 5}
111 dst1 := make([]float64, 5)
112 ans := []float64{19, 26, 9, 46, 35}
113 dst2 := AddScaledTo(dst1, y, alpha, s)
114 if !EqualApprox(dst1, ans, EqTolerance) {
115 t.Errorf("AddScaledTo did not match for mutator")
117 if !EqualApprox(dst2, ans, EqTolerance) {
118 t.Errorf("AddScaledTo did not match for returned slice")
120 AddScaledTo(dst1, y, alpha, s)
121 if !EqualApprox(dst1, ans, EqTolerance) {
122 t.Errorf("Reusing dst did not match")
124 short := []float64{1}
125 if !Panics(func() { AddScaledTo(dst1, y, alpha, short) }) {
126 t.Errorf("Doesn't panic if s is smaller than dst")
128 if !Panics(func() { AddScaledTo(short, y, alpha, s) }) {
129 t.Errorf("Doesn't panic if dst is smaller than s")
131 if !Panics(func() { AddScaledTo(dst1, short, alpha, s) }) {
132 t.Errorf("Doesn't panic if y is smaller than dst")
136 func TestArgsort(t *testing.T) {
137 s := []float64{3, 4, 1, 7, 5}
138 inds := make([]int, len(s))
142 sortedS := []float64{1, 3, 4, 5, 7}
143 trueInds := []int{2, 0, 1, 4, 3}
145 if !Equal(s, sortedS) {
146 t.Error("elements not sorted correctly")
148 for i := range trueInds {
149 if trueInds[i] != inds[i] {
150 t.Error("inds not correct")
155 if !Panics(func() { Argsort(s, inds) }) {
156 t.Error("does not panic if lengths do not match")
160 func TestCount(t *testing.T) {
161 s := []float64{3, 4, 1, 7, 5}
162 f := func(v float64) bool { return v > 3.5 }
166 t.Errorf("Wrong number of elements counted")
170 func TestCumProd(t *testing.T) {
171 s := []float64{3, 4, 1, 7, 5}
172 receiver := make([]float64, len(s))
173 result := CumProd(receiver, s)
174 truth := []float64{3, 12, 12, 84, 420}
175 AreSlicesEqual(t, truth, receiver, "Wrong cumprod mutated with new receiver")
176 AreSlicesEqual(t, truth, result, "Wrong cumprod result with new receiver")
178 AreSlicesEqual(t, truth, receiver, "Wrong cumprod returned with reused receiver")
180 // Test that it panics
181 if !Panics(func() { CumProd(make([]float64, 2), make([]float64, 3)) }) {
182 t.Errorf("Did not panic with length mismatch")
185 // Test empty CumProd
186 emptyReceiver := make([]float64, 0)
188 CumProd(emptyReceiver, emptyReceiver)
189 AreSlicesEqual(t, truth, emptyReceiver, "Wrong cumprod returned with empty receiver")
193 func TestCumSum(t *testing.T) {
194 s := []float64{3, 4, 1, 7, 5}
195 receiver := make([]float64, len(s))
196 result := CumSum(receiver, s)
197 truth := []float64{3, 7, 8, 15, 20}
198 AreSlicesEqual(t, truth, receiver, "Wrong cumsum mutated with new receiver")
199 AreSlicesEqual(t, truth, result, "Wrong cumsum returned with new receiver")
201 AreSlicesEqual(t, truth, receiver, "Wrong cumsum returned with reused receiver")
203 // Test that it panics
204 if !Panics(func() { CumSum(make([]float64, 2), make([]float64, 3)) }) {
205 t.Errorf("Did not panic with length mismatch")
209 emptyReceiver := make([]float64, 0)
211 CumSum(emptyReceiver, emptyReceiver)
212 AreSlicesEqual(t, truth, emptyReceiver, "Wrong cumsum returned with empty receiver")
216 func TestDistance(t *testing.T) {
217 norms := []float64{1, 2, 4, math.Inf(1)}
227 []float64{8, 9, 10, -12},
228 []float64{8, 9, 10, -12},
231 []float64{1, 2, 3, -4, -5, 8},
232 []float64{-9.2, -6.8, 9, -3, -2, 1},
236 for j, test := range slices {
237 tmp := make([]float64, len(test.s))
238 for i, L := range norms {
239 dist := Distance(test.s, test.t, L)
243 if dist != norm { // Use equality because they should be identical
244 t.Errorf("Distance does not match norm for case %v, %v. Expected %v, Found %v.", i, j, norm, dist)
249 if !Panics(func() { Distance([]float64{}, norms, 1) }) {
250 t.Errorf("Did not panic with unequal lengths")
255 func TestDiv(t *testing.T) {
256 s1 := []float64{5, 12, 27}
257 s2 := []float64{1, 2, 3}
258 ans := []float64{5, 6, 9}
260 if !EqualApprox(s1, ans, EqTolerance) {
261 t.Errorf("Mul doesn't give correct answer")
263 s1short := []float64{1}
264 if !Panics(func() { Div(s1short, s2) }) {
265 t.Errorf("Did not panic with unequal lengths")
267 s2short := []float64{1}
268 if !Panics(func() { Div(s1, s2short) }) {
269 t.Errorf("Did not panic with unequal lengths")
273 func TestDivTo(t *testing.T) {
274 s1 := []float64{5, 12, 27}
275 s1orig := []float64{5, 12, 27}
276 s2 := []float64{1, 2, 3}
277 s2orig := []float64{1, 2, 3}
278 dst1 := make([]float64, 3)
279 ans := []float64{5, 6, 9}
280 dst2 := DivTo(dst1, s1, s2)
281 if !EqualApprox(dst1, ans, EqTolerance) {
282 t.Errorf("DivTo doesn't give correct answer in mutated slice")
284 if !EqualApprox(dst2, ans, EqTolerance) {
285 t.Errorf("DivTo doesn't give correct answer in returned slice")
287 if !EqualApprox(s1, s1orig, EqTolerance) {
288 t.Errorf("S1 changes during multo")
290 if !EqualApprox(s2, s2orig, EqTolerance) {
291 t.Errorf("s2 changes during multo")
294 if !EqualApprox(dst1, ans, EqTolerance) {
295 t.Errorf("DivTo doesn't give correct answer reusing dst")
297 dstShort := []float64{1}
298 if !Panics(func() { DivTo(dstShort, s1, s2) }) {
299 t.Errorf("Did not panic with s1 wrong length")
301 s1short := []float64{1}
302 if !Panics(func() { DivTo(dst1, s1short, s2) }) {
303 t.Errorf("Did not panic with s1 wrong length")
305 s2short := []float64{1}
306 if !Panics(func() { DivTo(dst1, s1, s2short) }) {
307 t.Errorf("Did not panic with s2 wrong length")
311 func TestDot(t *testing.T) {
312 s1 := []float64{1, 2, 3, 4}
313 s2 := []float64{-3, 4, 5, -6}
317 t.Errorf("Dot product computed incorrectly")
320 // Test that it panics
321 if !Panics(func() { Dot(make([]float64, 2), make([]float64, 3)) }) {
322 t.Errorf("Did not panic with length mismatch")
326 func TestEquals(t *testing.T) {
327 s1 := []float64{1, 2, 3, 4}
328 s2 := []float64{1, 2, 3, 4}
330 t.Errorf("Equal slices returned as unequal")
332 s2 = []float64{1, 2, 3, 4 + 1e-14}
334 t.Errorf("Unequal slices returned as equal")
336 if Equal(s1, []float64{}) {
337 t.Errorf("Unequal slice lengths returned as equal")
341 func TestEqualApprox(t *testing.T) {
342 s1 := []float64{1, 2, 3, 4}
343 s2 := []float64{1, 2, 3, 4 + 1e-10}
344 if EqualApprox(s1, s2, 1e-13) {
345 t.Errorf("Unequal slices returned as equal for absolute")
347 if !EqualApprox(s1, s2, 1e-5) {
348 t.Errorf("Equal slices returned as unequal for absolute")
350 s1 = []float64{1, 2, 3, 1000}
351 s2 = []float64{1, 2, 3, 1000 * (1 + 1e-7)}
352 if EqualApprox(s1, s2, 1e-8) {
353 t.Errorf("Unequal slices returned as equal for relative")
355 if !EqualApprox(s1, s2, 1e-5) {
356 t.Errorf("Equal slices returned as unequal for relative")
358 if EqualApprox(s1, []float64{}, 1e-5) {
359 t.Errorf("Unequal slice lengths returned as equal")
363 func TestEqualFunc(t *testing.T) {
364 s1 := []float64{1, 2, 3, 4}
365 s2 := []float64{1, 2, 3, 4}
366 eq := func(x, y float64) bool { return x == y }
367 if !EqualFunc(s1, s2, eq) {
368 t.Errorf("Equal slices returned as unequal")
370 s2 = []float64{1, 2, 3, 4 + 1e-14}
371 if EqualFunc(s1, s2, eq) {
372 t.Errorf("Unequal slices returned as equal")
374 if EqualFunc(s1, []float64{}, eq) {
375 t.Errorf("Unequal slice lengths returned as equal")
379 func TestEqualsRelative(t *testing.T) {
380 var equalityTests = []struct {
385 {1000000, 1000001, 0, true},
386 {1000001, 1000000, 0, true},
387 {10000, 10001, 0, false},
388 {10001, 10000, 0, false},
389 {-1000000, -1000001, 0, true},
390 {-1000001, -1000000, 0, true},
391 {-10000, -10001, 0, false},
392 {-10001, -10000, 0, false},
393 {1.0000001, 1.0000002, 0, true},
394 {1.0000002, 1.0000001, 0, true},
395 {1.0002, 1.0001, 0, false},
396 {1.0001, 1.0002, 0, false},
397 {-1.000001, -1.000002, 0, true},
398 {-1.000002, -1.000001, 0, true},
399 {-1.0001, -1.0002, 0, false},
400 {-1.0002, -1.0001, 0, false},
401 {0.000000001000001, 0.000000001000002, 0, true},
402 {0.000000001000002, 0.000000001000001, 0, true},
403 {0.000000000001002, 0.000000000001001, 0, false},
404 {0.000000000001001, 0.000000000001002, 0, false},
405 {-0.000000001000001, -0.000000001000002, 0, true},
406 {-0.000000001000002, -0.000000001000001, 0, true},
407 {-0.000000000001002, -0.000000000001001, 0, false},
408 {-0.000000000001001, -0.000000000001002, 0, false},
412 {0.00000001, 0, 0, false},
413 {0, 0.00000001, 0, false},
414 {-0.00000001, 0, 0, false},
415 {0, -0.00000001, 0, false},
416 {0, 1e-310, 0.01, true},
417 {1e-310, 0, 0.01, true},
418 {1e-310, 0, 0.000001, false},
419 {0, 1e-310, 0.000001, false},
420 {0, -1e-310, 0.1, true},
421 {-1e-310, 0, 0.1, true},
422 {-1e-310, 0, 0.00000001, false},
423 {0, -1e-310, 0.00000001, false},
424 {math.Inf(1), math.Inf(1), 0, true},
425 {math.Inf(-1), math.Inf(-1), 0, true},
426 {math.Inf(-1), math.Inf(1), 0, false},
427 {math.Inf(1), math.MaxFloat64, 0, false},
428 {math.Inf(-1), -math.MaxFloat64, 0, false},
429 {math.NaN(), math.NaN(), 0, false},
430 {math.NaN(), 0, 0, false},
431 {-0, math.NaN(), 0, false},
432 {math.NaN(), -0, 0, false},
433 {0, math.NaN(), 0, false},
434 {math.NaN(), math.Inf(1), 0, false},
435 {math.Inf(1), math.NaN(), 0, false},
436 {math.NaN(), math.Inf(-1), 0, false},
437 {math.Inf(-1), math.NaN(), 0, false},
438 {math.NaN(), math.MaxFloat64, 0, false},
439 {math.MaxFloat64, math.NaN(), 0, false},
440 {math.NaN(), -math.MaxFloat64, 0, false},
441 {-math.MaxFloat64, math.NaN(), 0, false},
442 {math.NaN(), math.SmallestNonzeroFloat64, 0, false},
443 {math.SmallestNonzeroFloat64, math.NaN(), 0, false},
444 {math.NaN(), -math.SmallestNonzeroFloat64, 0, false},
445 {-math.SmallestNonzeroFloat64, math.NaN(), 0, false},
446 {1.000000001, -1.0, 0, false},
447 {-1.0, 1.000000001, 0, false},
448 {-1.000000001, 1.0, 0, false},
449 {1.0, -1.000000001, 0, false},
450 {10 * math.SmallestNonzeroFloat64, 10 * -math.SmallestNonzeroFloat64, 0, true},
451 {1e11 * math.SmallestNonzeroFloat64, 1e11 * -math.SmallestNonzeroFloat64, 0, false},
452 {math.SmallestNonzeroFloat64, -math.SmallestNonzeroFloat64, 0, true},
453 {-math.SmallestNonzeroFloat64, math.SmallestNonzeroFloat64, 0, true},
454 {math.SmallestNonzeroFloat64, 0, 0, true},
455 {0, math.SmallestNonzeroFloat64, 0, true},
456 {-math.SmallestNonzeroFloat64, 0, 0, true},
457 {0, -math.SmallestNonzeroFloat64, 0, true},
458 {0.000000001, -math.SmallestNonzeroFloat64, 0, false},
459 {0.000000001, math.SmallestNonzeroFloat64, 0, false},
460 {math.SmallestNonzeroFloat64, 0.000000001, 0, false},
461 {-math.SmallestNonzeroFloat64, 0.000000001, 0, false},
463 for _, ts := range equalityTests {
467 if equal := EqualWithinRel(ts.a, ts.b, ts.tol); equal != ts.equal {
468 t.Errorf("Relative equality of %g and %g with tolerance %g returned: %v. Expected: %v",
469 ts.a, ts.b, ts.tol, equal, ts.equal)
474 func nextAfterN(x, y float64, n int) float64 {
475 for i := 0; i < n; i++ {
476 x = math.Nextafter(x, y)
481 func TestEqualsULP(t *testing.T) {
482 if f := 67329.242; !EqualWithinULP(f, nextAfterN(f, math.Inf(1), 10), 10) {
483 t.Errorf("Equal values returned as unequal")
485 if f := 67329.242; EqualWithinULP(f, nextAfterN(f, math.Inf(1), 5), 1) {
486 t.Errorf("Unequal values returned as equal")
488 if f := 67329.242; EqualWithinULP(nextAfterN(f, math.Inf(1), 5), f, 1) {
489 t.Errorf("Unequal values returned as equal")
491 if f := nextAfterN(0, math.Inf(1), 2); !EqualWithinULP(f, nextAfterN(f, math.Inf(-1), 5), 10) {
492 t.Errorf("Equal values returned as unequal")
494 if !EqualWithinULP(67329.242, 67329.242, 10) {
495 t.Errorf("Equal float64s not returned as equal")
497 if EqualWithinULP(1, math.NaN(), 10) {
498 t.Errorf("NaN returned as equal")
503 func TestEqualLengths(t *testing.T) {
504 s1 := []float64{1, 2, 3, 4}
505 s2 := []float64{1, 2, 3, 4}
506 s3 := []float64{1, 2, 3}
507 if !EqualLengths(s1, s2) {
508 t.Errorf("Equal lengths returned as unequal")
510 if EqualLengths(s1, s3) {
511 t.Errorf("Unequal lengths returned as equal")
513 if !EqualLengths(s1) {
514 t.Errorf("Single slice returned as unequal")
517 t.Errorf("No slices returned as unequal")
521 func eqIntSlice(one, two []int) string {
522 if len(one) != len(two) {
523 return "Length mismatch"
525 for i, val := range one {
527 return "Index " + strconv.Itoa(i) + " mismatch"
533 func TestFind(t *testing.T) {
534 s := []float64{3, 4, 1, 7, 5}
535 f := func(v float64) bool { return v > 3.5 }
536 allTrueInds := []int{1, 3, 4}
538 // Test finding first two elements
539 inds, err := Find(nil, f, s, 2)
541 t.Errorf("Find first two: Improper error return")
543 trueInds := allTrueInds[:2]
544 str := eqIntSlice(inds, trueInds)
546 t.Errorf("Find first two: " + str)
549 // Test finding no elements with non nil slice
550 inds = []int{1, 2, 3, 4, 5, 6}
551 inds, err = Find(inds, f, s, 0)
553 t.Errorf("Find no elements: Improper error return")
555 str = eqIntSlice(inds, []int{})
557 t.Errorf("Find no non-nil: " + str)
560 // Test finding first two elements with non nil slice
561 inds = []int{1, 2, 3, 4, 5, 6}
562 inds, err = Find(inds, f, s, 2)
564 t.Errorf("Find first two non-nil: Improper error return")
566 str = eqIntSlice(inds, trueInds)
568 t.Errorf("Find first two non-nil: " + str)
571 // Test finding too many elements
572 inds, err = Find(inds, f, s, 4)
574 t.Errorf("Request too many: No error returned")
576 str = eqIntSlice(inds, allTrueInds)
578 t.Errorf("Request too many: Does not match all of the inds: " + str)
581 // Test finding all elements
582 inds, err = Find(nil, f, s, -1)
584 t.Errorf("Find all: Improper error returned")
586 str = eqIntSlice(inds, allTrueInds)
588 t.Errorf("Find all: Does not match all of the inds: " + str)
592 func TestHasNaN(t *testing.T) {
593 for i, test := range []struct {
599 s: []float64{1, 2, 3, 4},
602 s: []float64{1, math.NaN(), 3, 4},
606 s: []float64{1, 2, 3, math.NaN()},
612 t.Errorf("HasNaN mismatch case %d. Expected %v, Found %v", i, test.ans, b)
617 func TestLogSpan(t *testing.T) {
618 receiver1 := make([]float64, 6)
619 truth := []float64{0.001, 0.01, 0.1, 1, 10, 100}
620 receiver2 := LogSpan(receiver1, 0.001, 100)
621 tst := make([]float64, 6)
622 for i := range truth {
623 tst[i] = receiver1[i] / truth[i]
625 comp := make([]float64, 6)
626 for i := range comp {
629 AreSlicesEqual(t, comp, tst, "Improper logspace from mutator")
631 for i := range truth {
632 tst[i] = receiver2[i] / truth[i]
634 AreSlicesEqual(t, comp, tst, "Improper logspace from returned slice")
636 if !Panics(func() { LogSpan(nil, 1, 5) }) {
637 t.Errorf("Span accepts nil argument")
639 if !Panics(func() { LogSpan(make([]float64, 1), 1, 5) }) {
640 t.Errorf("Span accepts argument of len = 1")
644 func TestLogSumExp(t *testing.T) {
645 s := []float64{1, 2, 3, 4, 5}
647 // http://www.wolframalpha.com/input/?i=log%28exp%281%29+%2B+exp%282%29+%2B+exp%283%29+%2B+exp%284%29+%2B+exp%285%29%29
648 truth := 5.4519143959375933331957225109748087179338972737576824
649 if math.Abs(val-truth) > EqTolerance {
650 t.Errorf("Wrong logsumexp for many values")
653 // http://www.wolframalpha.com/input/?i=log%28exp%281%29+%2B+exp%282%29%29
654 truth = 2.3132616875182228340489954949678556419152800856703483
656 if math.Abs(val-truth) > EqTolerance {
657 t.Errorf("Wrong logsumexp for two values. %v expected, %v found", truth, val)
659 // This case would normally underflow
660 s = []float64{-1001, -1002, -1003, -1004, -1005}
661 // http://www.wolframalpha.com/input/?i=log%28exp%28-1001%29%2Bexp%28-1002%29%2Bexp%28-1003%29%2Bexp%28-1004%29%2Bexp%28-1005%29%29
662 truth = -1000.54808560406240666680427748902519128206610272624
664 if math.Abs(val-truth) > EqTolerance {
665 t.Errorf("Doesn't match for underflow case. %v expected, %v found", truth, val)
667 // positive infinite case
668 s = []float64{1, 2, 3, 4, 5, math.Inf(1)}
672 t.Errorf("Doesn't match for pos Infinity case. %v expected, %v found", truth, val)
674 // negative infinite case
675 s = []float64{1, 2, 3, 4, 5, math.Inf(-1)}
677 truth = 5.4519143959375933331957225109748087179338972737576824 // same as first case
678 if math.Abs(val-truth) > EqTolerance {
679 t.Errorf("Wrong logsumexp for values with negative infinity")
684 func TestMaxAndIdx(t *testing.T) {
685 s := []float64{3, 4, 1, 7, 5}
689 t.Errorf("Wrong value returned")
692 t.Errorf("Wrong index returned")
696 func TestMinAndIdx(t *testing.T) {
697 s := []float64{3, 4, 1, 7, 5}
701 t.Errorf("Wrong value returned")
704 t.Errorf("Wrong index returned")
708 func TestMul(t *testing.T) {
709 s1 := []float64{1, 2, 3}
710 s2 := []float64{1, 2, 3}
711 ans := []float64{1, 4, 9}
713 if !EqualApprox(s1, ans, EqTolerance) {
714 t.Errorf("Mul doesn't give correct answer")
716 s1short := []float64{1}
717 if !Panics(func() { Mul(s1short, s2) }) {
718 t.Errorf("Did not panic with unequal lengths")
720 s2short := []float64{1}
721 if !Panics(func() { Mul(s1, s2short) }) {
722 t.Errorf("Did not panic with unequal lengths")
726 func TestMulTo(t *testing.T) {
727 s1 := []float64{1, 2, 3}
728 s1orig := []float64{1, 2, 3}
729 s2 := []float64{1, 2, 3}
730 s2orig := []float64{1, 2, 3}
731 dst1 := make([]float64, 3)
732 ans := []float64{1, 4, 9}
733 dst2 := MulTo(dst1, s1, s2)
734 if !EqualApprox(dst1, ans, EqTolerance) {
735 t.Errorf("MulTo doesn't give correct answer in mutated slice")
737 if !EqualApprox(dst2, ans, EqTolerance) {
738 t.Errorf("MulTo doesn't give correct answer in returned slice")
740 if !EqualApprox(s1, s1orig, EqTolerance) {
741 t.Errorf("S1 changes during multo")
743 if !EqualApprox(s2, s2orig, EqTolerance) {
744 t.Errorf("s2 changes during multo")
747 if !EqualApprox(dst1, ans, EqTolerance) {
748 t.Errorf("MulTo doesn't give correct answer reusing dst")
750 dstShort := []float64{1}
751 if !Panics(func() { MulTo(dstShort, s1, s2) }) {
752 t.Errorf("Did not panic with s1 wrong length")
754 s1short := []float64{1}
755 if !Panics(func() { MulTo(dst1, s1short, s2) }) {
756 t.Errorf("Did not panic with s1 wrong length")
758 s2short := []float64{1}
759 if !Panics(func() { MulTo(dst1, s1, s2short) }) {
760 t.Errorf("Did not panic with s2 wrong length")
764 func TestNaNWith(t *testing.T) {
769 {0, math.Float64bits(0 / func() float64 { return 0 }())}, // Hide the division by zero from the compiler.
770 {1, math.Float64bits(math.NaN())},
771 {1954, 0x7ff80000000007a2}, // R NA.
774 for _, test := range tests {
775 nan := NaNWith(test.payload)
776 if !math.IsNaN(nan) {
777 t.Errorf("expected NaN value, got:%f", nan)
780 bits := math.Float64bits(nan)
787 if bits != test.bits {
788 t.Errorf("expected NaN bit representation: got:%x want:%x", bits, test.bits)
793 func TestNaNPayload(t *testing.T) {
799 {0 / func() float64 { return 0 }(), 0, true}, // Hide the division by zero from the compiler.
801 // The following two line are written explicitly to defend against potential changes to math.Copysign.
802 {math.Float64frombits(math.Float64bits(math.NaN()) | (1 << 63)), 1, true}, // math.Copysign(math.NaN(), -1)
803 {math.Float64frombits(math.Float64bits(math.NaN()) &^ (1 << 63)), 1, true}, // math.Copysign(math.NaN(), 1)
805 {NaNWith(1954), 1954, true}, // R NA.
807 {math.Copysign(0, -1), 0, false},
809 {math.Inf(-1), 0, false},
810 {math.Inf(1), 0, false},
812 {math.Float64frombits(0x7ff0000000000001), 0, false}, // Signalling NaN.
815 for _, test := range tests {
816 payload, ok := NaNPayload(test.f)
817 if payload != test.payload {
818 t.Errorf("expected NaN payload: got:%x want:%x", payload, test.payload)
821 t.Errorf("expected NaN status: got:%t want:%t", ok, test.ok)
826 func TestNearest(t *testing.T) {
827 s := []float64{6.2, 3, 5, 6.2, 8}
828 ind := Nearest(s, 2.0)
830 t.Errorf("Wrong index returned when value is less than all of elements")
832 ind = Nearest(s, 9.0)
834 t.Errorf("Wrong index returned when value is greater than all of elements")
836 ind = Nearest(s, 3.1)
838 t.Errorf("Wrong index returned when value is greater than closest element")
840 ind = Nearest(s, 3.1)
842 t.Errorf("Wrong index returned when value is greater than closest element")
844 ind = Nearest(s, 2.9)
846 t.Errorf("Wrong index returned when value is less than closest element")
850 t.Errorf("Wrong index returned when value is equal to element")
852 ind = Nearest(s, 6.2)
854 t.Errorf("Wrong index returned when value is equal to several elements")
858 t.Errorf("Wrong index returned when value is exactly between two closest elements")
862 func TestNearestWithinSpan(t *testing.T) {
863 if !Panics(func() { NearestWithinSpan(10, 8, 2, 4.5) }) {
864 t.Errorf("Did not panic when upper bound is lower than greater bound")
866 for i, test := range []struct {
923 if idx := NearestWithinSpan(test.length, test.lower, test.upper, test.value); test.idx != idx {
924 t.Errorf("Case %v mismatch: Want: %v, Got: %v", i, test.idx, idx)
929 func TestNorm(t *testing.T) {
930 s := []float64{-1, -3.4, 5, -6}
931 val := Norm(s, math.Inf(1))
933 if math.Abs(val-truth) > EqTolerance {
934 t.Errorf("Doesn't match for inf norm. %v expected, %v found", truth, val)
936 // 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
938 truth = 8.5767126569566267590651614132751986658027271236078592
939 if math.Abs(val-truth) > EqTolerance {
940 t.Errorf("Doesn't match for inf norm. %v expected, %v found", truth, val)
942 // 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
944 truth = 7.2514321388020228478109121239004816430071237369356233
945 if math.Abs(val-truth) > EqTolerance {
946 t.Errorf("Doesn't match for inf norm. %v expected, %v found", truth, val)
949 //http://www.wolframalpha.com/input/?i=%7C-1%7C+%2B+%7C-3.4%7C+%2B+%7C5%7C%2B++%7C6%7C
952 if math.Abs(val-truth) > EqTolerance {
953 t.Errorf("Doesn't match for inf norm. %v expected, %v found", truth, val)
957 func TestProd(t *testing.T) {
961 t.Errorf("Val not returned as default when slice length is zero")
963 s = []float64{3, 4, 1, 7, 5}
966 t.Errorf("Wrong prod returned. Expected %v returned %v", 420, val)
970 func TestReverse(t *testing.T) {
971 for _, s := range [][]float64{
976 {9, 8, 7, 6, 5, 4, 3, 2, 1, 0},
979 for i, v := range s {
981 t.Errorf("unexpected values for element %d: got:%v want:%v", i, v, i)
987 func TestRound(t *testing.T) {
988 for _, test := range []struct {
993 {x: 0, prec: 1, want: 0},
994 {x: math.Inf(1), prec: 1, want: math.Inf(1)},
995 {x: math.NaN(), prec: 1, want: math.NaN()},
996 {x: func() float64 { var f float64; return -f }(), prec: 1, want: 0},
997 {x: math.MaxFloat64 / 2, prec: 1, want: math.MaxFloat64 / 2},
998 {x: 1 << 64, prec: 1, want: 1 << 64},
999 {x: 454.4445, prec: 3, want: 454.445},
1000 {x: 454.44445, prec: 4, want: 454.4445},
1001 {x: 0.42499, prec: 4, want: 0.425},
1002 {x: 0.42599, prec: 4, want: 0.426},
1003 {x: 0.424999999999993, prec: 2, want: 0.42},
1004 {x: 0.425, prec: 2, want: 0.43},
1005 {x: 0.425000000000001, prec: 2, want: 0.43},
1006 {x: 123.4244999999999, prec: 3, want: 123.424},
1007 {x: 123.4245, prec: 3, want: 123.425},
1008 {x: 123.4245000000001, prec: 3, want: 123.425},
1010 {x: 454.45, prec: 0, want: 454},
1011 {x: 454.45, prec: 1, want: 454.5},
1012 {x: 454.45, prec: 2, want: 454.45},
1013 {x: 454.45, prec: 3, want: 454.45},
1014 {x: 454.445, prec: 0, want: 454},
1015 {x: 454.445, prec: 1, want: 454.4},
1016 {x: 454.445, prec: 2, want: 454.45},
1017 {x: 454.445, prec: 3, want: 454.445},
1018 {x: 454.445, prec: 4, want: 454.445},
1019 {x: 454.55, prec: 0, want: 455},
1020 {x: 454.55, prec: 1, want: 454.6},
1021 {x: 454.55, prec: 2, want: 454.55},
1022 {x: 454.55, prec: 3, want: 454.55},
1023 {x: 454.455, prec: 0, want: 454},
1024 {x: 454.455, prec: 1, want: 454.5},
1025 {x: 454.455, prec: 2, want: 454.46},
1026 {x: 454.455, prec: 3, want: 454.455},
1027 {x: 454.455, prec: 4, want: 454.455},
1029 // Negative precision.
1030 {x: 454.45, prec: -1, want: 450},
1031 {x: 454.45, prec: -2, want: 500},
1032 {x: 500, prec: -3, want: 1000},
1033 {x: 500, prec: -4, want: 0},
1034 {x: 1500, prec: -3, want: 2000},
1035 {x: 1500, prec: -4, want: 0},
1037 for _, sign := range []float64{1, -1} {
1038 got := Round(sign*test.x, test.prec)
1039 want := sign * test.want
1043 if (got != want || math.Signbit(got) != math.Signbit(want)) && !(math.IsNaN(got) && math.IsNaN(want)) {
1044 t.Errorf("unexpected result for Round(%g, %d): got: %g, want: %g", sign*test.x, test.prec, got, want)
1050 func TestRoundEven(t *testing.T) {
1051 for _, test := range []struct {
1056 {x: 0, prec: 1, want: 0},
1057 {x: math.Inf(1), prec: 1, want: math.Inf(1)},
1058 {x: math.NaN(), prec: 1, want: math.NaN()},
1059 {x: func() float64 { var f float64; return -f }(), prec: 1, want: 0},
1060 {x: math.MaxFloat64 / 2, prec: 1, want: math.MaxFloat64 / 2},
1061 {x: 1 << 64, prec: 1, want: 1 << 64},
1062 {x: 454.4445, prec: 3, want: 454.444},
1063 {x: 454.44445, prec: 4, want: 454.4444},
1064 {x: 0.42499, prec: 4, want: 0.425},
1065 {x: 0.42599, prec: 4, want: 0.426},
1066 {x: 0.424999999999993, prec: 2, want: 0.42},
1067 {x: 0.425, prec: 2, want: 0.42},
1068 {x: 0.425000000000001, prec: 2, want: 0.43},
1069 {x: 123.4244999999999, prec: 3, want: 123.424},
1070 {x: 123.4245, prec: 3, want: 123.424},
1071 {x: 123.4245000000001, prec: 3, want: 123.425},
1073 {x: 454.45, prec: 0, want: 454},
1074 {x: 454.45, prec: 1, want: 454.4},
1075 {x: 454.45, prec: 2, want: 454.45},
1076 {x: 454.45, prec: 3, want: 454.45},
1077 {x: 454.445, prec: 0, want: 454},
1078 {x: 454.445, prec: 1, want: 454.4},
1079 {x: 454.445, prec: 2, want: 454.44},
1080 {x: 454.445, prec: 3, want: 454.445},
1081 {x: 454.445, prec: 4, want: 454.445},
1082 {x: 454.55, prec: 0, want: 455},
1083 {x: 454.55, prec: 1, want: 454.6},
1084 {x: 454.55, prec: 2, want: 454.55},
1085 {x: 454.55, prec: 3, want: 454.55},
1086 {x: 454.455, prec: 0, want: 454},
1087 {x: 454.455, prec: 1, want: 454.5},
1088 {x: 454.455, prec: 2, want: 454.46},
1089 {x: 454.455, prec: 3, want: 454.455},
1090 {x: 454.455, prec: 4, want: 454.455},
1092 // Negative precision.
1093 {x: 454.45, prec: -1, want: 450},
1094 {x: 454.45, prec: -2, want: 500},
1095 {x: 500, prec: -3, want: 0},
1096 {x: 500, prec: -4, want: 0},
1097 {x: 1500, prec: -3, want: 2000},
1098 {x: 1500, prec: -4, want: 0},
1100 for _, sign := range []float64{1, -1} {
1101 got := RoundEven(sign*test.x, test.prec)
1102 want := sign * test.want
1106 if (got != want || math.Signbit(got) != math.Signbit(want)) && !(math.IsNaN(got) && math.IsNaN(want)) {
1107 t.Errorf("unexpected result for RoundEven(%g, %d): got: %g, want: %g", sign*test.x, test.prec, got, want)
1113 func TestSame(t *testing.T) {
1114 s1 := []float64{1, 2, 3, 4}
1115 s2 := []float64{1, 2, 3, 4}
1117 t.Errorf("Equal slices returned as unequal")
1119 s2 = []float64{1, 2, 3, 4 + 1e-14}
1121 t.Errorf("Unequal slices returned as equal")
1123 if Same(s1, []float64{}) {
1124 t.Errorf("Unequal slice lengths returned as equal")
1126 s1 = []float64{1, 2, math.NaN(), 4}
1127 s2 = []float64{1, 2, math.NaN(), 4}
1129 t.Errorf("Slices with matching NaN values returned as unequal")
1131 s1 = []float64{1, 2, math.NaN(), 4}
1132 s2 = []float64{1, math.NaN(), 3, 4}
1134 t.Errorf("Slices with unmatching NaN values returned as equal")
1138 func TestScale(t *testing.T) {
1139 s := []float64{3, 4, 1, 7, 5}
1141 truth := []float64{15, 20, 5, 35, 25}
1143 AreSlicesEqual(t, truth, s, "Bad scaling")
1146 func TestSpan(t *testing.T) {
1147 receiver1 := make([]float64, 5)
1148 truth := []float64{1, 2, 3, 4, 5}
1149 receiver2 := Span(receiver1, 1, 5)
1150 AreSlicesEqual(t, truth, receiver1, "Improper linspace from mutator")
1151 AreSlicesEqual(t, truth, receiver2, "Improper linspace from returned slice")
1152 receiver1 = make([]float64, 6)
1153 truth = []float64{0, 0.2, 0.4, 0.6, 0.8, 1.0}
1154 Span(receiver1, 0, 1)
1155 AreSlicesEqual(t, truth, receiver1, "Improper linspace")
1156 if !Panics(func() { Span(nil, 1, 5) }) {
1157 t.Errorf("Span accepts nil argument")
1159 if !Panics(func() { Span(make([]float64, 1), 1, 5) }) {
1160 t.Errorf("Span accepts argument of len = 1")
1164 func TestSub(t *testing.T) {
1165 s := []float64{3, 4, 1, 7, 5}
1166 v := []float64{1, 2, 3, 4, 5}
1167 truth := []float64{2, 2, -2, 3, 0}
1169 AreSlicesEqual(t, truth, s, "Bad subtract")
1170 // Test that it panics
1171 if !Panics(func() { Sub(make([]float64, 2), make([]float64, 3)) }) {
1172 t.Errorf("Did not panic with length mismatch")
1176 func TestSubTo(t *testing.T) {
1177 s := []float64{3, 4, 1, 7, 5}
1178 v := []float64{1, 2, 3, 4, 5}
1179 truth := []float64{2, 2, -2, 3, 0}
1180 dst1 := make([]float64, len(s))
1181 dst2 := SubTo(dst1, s, v)
1182 AreSlicesEqual(t, truth, dst1, "Bad subtract from mutator")
1183 AreSlicesEqual(t, truth, dst2, "Bad subtract from returned slice")
1184 // Test that all mismatch combinations panic
1185 if !Panics(func() { SubTo(make([]float64, 2), make([]float64, 3), make([]float64, 3)) }) {
1186 t.Errorf("Did not panic with dst different length")
1188 if !Panics(func() { SubTo(make([]float64, 3), make([]float64, 2), make([]float64, 3)) }) {
1189 t.Errorf("Did not panic with subtractor different length")
1191 if !Panics(func() { SubTo(make([]float64, 3), make([]float64, 3), make([]float64, 2)) }) {
1192 t.Errorf("Did not panic with subtractee different length")
1196 func TestSum(t *testing.T) {
1200 t.Errorf("Val not returned as default when slice length is zero")
1202 s = []float64{3, 4, 1, 7, 5}
1205 t.Errorf("Wrong sum returned")
1209 func TestWithin(t *testing.T) {
1210 for i, test := range []struct {
1217 s: []float64{1, 2, 5, 9},
1222 s: []float64{1, 2, 5, 9},
1227 s: []float64{1, 2, 5, 9},
1232 s: []float64{1, 2, 5, 9},
1237 s: []float64{1, 2, 5, 9},
1242 s: []float64{1, 2, 5, 9},
1247 s: []float64{1, 2, 5, 9},
1252 s: []float64{1, 2, 5, 9},
1257 s: []float64{5, 2, 6},
1269 panics := Panics(func() { idx = Within(test.s, test.v) })
1272 t.Errorf("Case %v: bad panic", i)
1278 t.Errorf("Case %v: did not panic when it should", i)
1282 if idx != test.idx {
1283 t.Errorf("Case %v: Idx mismatch. Want: %v, got: %v", i, test.idx, idx)
1289 func randomSlice(l int) []float64 {
1290 s := make([]float64, l)
1292 s[i] = rand.Float64()
1297 func benchmarkMin(b *testing.B, size int) {
1298 s := randomSlice(size)
1300 for i := 0; i < b.N; i++ {
1304 func BenchmarkMinSmall(b *testing.B) { benchmarkMin(b, Small) }
1305 func BenchmarkMinMed(b *testing.B) { benchmarkMin(b, Medium) }
1306 func BenchmarkMinLarge(b *testing.B) { benchmarkMin(b, Large) }
1307 func BenchmarkMinHuge(b *testing.B) { benchmarkMin(b, Huge) }
1309 func benchmarkAdd(b *testing.B, size int) {
1310 s1 := randomSlice(size)
1311 s2 := randomSlice(size)
1313 for i := 0; i < b.N; i++ {
1317 func BenchmarkAddSmall(b *testing.B) { benchmarkAdd(b, Small) }
1318 func BenchmarkAddMed(b *testing.B) { benchmarkAdd(b, Medium) }
1319 func BenchmarkAddLarge(b *testing.B) { benchmarkAdd(b, Large) }
1320 func BenchmarkAddHuge(b *testing.B) { benchmarkAdd(b, Huge) }
1322 func benchmarkAddTo(b *testing.B, size int) {
1323 s1 := randomSlice(size)
1324 s2 := randomSlice(size)
1325 dst := randomSlice(size)
1327 for i := 0; i < b.N; i++ {
1331 func BenchmarkAddToSmall(b *testing.B) { benchmarkAddTo(b, Small) }
1332 func BenchmarkAddToMed(b *testing.B) { benchmarkAddTo(b, Medium) }
1333 func BenchmarkAddToLarge(b *testing.B) { benchmarkAddTo(b, Large) }
1334 func BenchmarkAddToHuge(b *testing.B) { benchmarkAddTo(b, Huge) }
1336 func benchmarkCumProd(b *testing.B, size int) {
1337 s := randomSlice(size)
1338 dst := randomSlice(size)
1340 for i := 0; i < b.N; i++ {
1344 func BenchmarkCumProdSmall(b *testing.B) { benchmarkCumProd(b, Small) }
1345 func BenchmarkCumProdMed(b *testing.B) { benchmarkCumProd(b, Medium) }
1346 func BenchmarkCumProdLarge(b *testing.B) { benchmarkCumProd(b, Large) }
1347 func BenchmarkCumProdHuge(b *testing.B) { benchmarkCumProd(b, Huge) }
1349 func benchmarkCumSum(b *testing.B, size int) {
1350 s := randomSlice(size)
1351 dst := randomSlice(size)
1353 for i := 0; i < b.N; i++ {
1357 func BenchmarkCumSumSmall(b *testing.B) { benchmarkCumSum(b, Small) }
1358 func BenchmarkCumSumMed(b *testing.B) { benchmarkCumSum(b, Medium) }
1359 func BenchmarkCumSumLarge(b *testing.B) { benchmarkCumSum(b, Large) }
1360 func BenchmarkCumSumHuge(b *testing.B) { benchmarkCumSum(b, Huge) }
1362 func benchmarkDiv(b *testing.B, size int) {
1363 s := randomSlice(size)
1364 dst := randomSlice(size)
1366 for i := 0; i < b.N; i++ {
1370 func BenchmarkDivSmall(b *testing.B) { benchmarkDiv(b, Small) }
1371 func BenchmarkDivMed(b *testing.B) { benchmarkDiv(b, Medium) }
1372 func BenchmarkDivLarge(b *testing.B) { benchmarkDiv(b, Large) }
1373 func BenchmarkDivHuge(b *testing.B) { benchmarkDiv(b, Huge) }
1375 func benchmarkDivTo(b *testing.B, size int) {
1376 s1 := randomSlice(size)
1377 s2 := randomSlice(size)
1378 dst := randomSlice(size)
1380 for i := 0; i < b.N; i++ {
1384 func BenchmarkDivToSmall(b *testing.B) { benchmarkDivTo(b, Small) }
1385 func BenchmarkDivToMed(b *testing.B) { benchmarkDivTo(b, Medium) }
1386 func BenchmarkDivToLarge(b *testing.B) { benchmarkDivTo(b, Large) }
1387 func BenchmarkDivToHuge(b *testing.B) { benchmarkDivTo(b, Huge) }
1389 func benchmarkSub(b *testing.B, size int) {
1390 s1 := randomSlice(size)
1391 s2 := randomSlice(size)
1393 for i := 0; i < b.N; i++ {
1397 func BenchmarkSubSmall(b *testing.B) { benchmarkSub(b, Small) }
1398 func BenchmarkSubMed(b *testing.B) { benchmarkSub(b, Medium) }
1399 func BenchmarkSubLarge(b *testing.B) { benchmarkSub(b, Large) }
1400 func BenchmarkSubHuge(b *testing.B) { benchmarkSub(b, Huge) }
1402 func benchmarkSubTo(b *testing.B, size int) {
1403 s1 := randomSlice(size)
1404 s2 := randomSlice(size)
1405 dst := randomSlice(size)
1407 for i := 0; i < b.N; i++ {
1411 func BenchmarkSubToSmall(b *testing.B) { benchmarkSubTo(b, Small) }
1412 func BenchmarkSubToMed(b *testing.B) { benchmarkSubTo(b, Medium) }
1413 func BenchmarkSubToLarge(b *testing.B) { benchmarkSubTo(b, Large) }
1414 func BenchmarkSubToHuge(b *testing.B) { benchmarkSubTo(b, Huge) }
1416 func benchmarkLogSumExp(b *testing.B, size int) {
1417 s := randomSlice(size)
1419 for i := 0; i < b.N; i++ {
1423 func BenchmarkLogSumExpSmall(b *testing.B) { benchmarkLogSumExp(b, Small) }
1424 func BenchmarkLogSumExpMed(b *testing.B) { benchmarkLogSumExp(b, Medium) }
1425 func BenchmarkLogSumExpLarge(b *testing.B) { benchmarkLogSumExp(b, Large) }
1426 func BenchmarkLogSumExpHuge(b *testing.B) { benchmarkLogSumExp(b, Huge) }
1428 func benchmarkDot(b *testing.B, size int) {
1429 s1 := randomSlice(size)
1430 s2 := randomSlice(size)
1432 for i := 0; i < b.N; i++ {
1436 func BenchmarkDotSmall(b *testing.B) { benchmarkDot(b, Small) }
1437 func BenchmarkDotMed(b *testing.B) { benchmarkDot(b, Medium) }
1438 func BenchmarkDotLarge(b *testing.B) { benchmarkDot(b, Large) }
1439 func BenchmarkDotHuge(b *testing.B) { benchmarkDot(b, Huge) }
1441 func benchmarkAddScaledTo(b *testing.B, size int) {
1442 dst := randomSlice(size)
1443 y := randomSlice(size)
1444 s := randomSlice(size)
1446 for i := 0; i < b.N; i++ {
1447 AddScaledTo(dst, y, 2.3, s)
1450 func BenchmarkAddScaledToSmall(b *testing.B) { benchmarkAddScaledTo(b, Small) }
1451 func BenchmarkAddScaledToMedium(b *testing.B) { benchmarkAddScaledTo(b, Medium) }
1452 func BenchmarkAddScaledToLarge(b *testing.B) { benchmarkAddScaledTo(b, Large) }
1453 func BenchmarkAddScaledToHuge(b *testing.B) { benchmarkAddScaledTo(b, Huge) }
1455 func benchmarkScale(b *testing.B, size int) {
1456 dst := randomSlice(size)
1458 for i := 0; i < b.N; i += 2 {
1463 func BenchmarkScaleSmall(b *testing.B) { benchmarkScale(b, Small) }
1464 func BenchmarkScaleMedium(b *testing.B) { benchmarkScale(b, Medium) }
1465 func BenchmarkScaleLarge(b *testing.B) { benchmarkScale(b, Large) }
1466 func BenchmarkScaleHuge(b *testing.B) { benchmarkScale(b, Huge) }