Repository navigation
Expand file tree
/
Copy pathinterp_test.go
More file actions
81 lines (75 loc) · 2.75 KB
/
Copy pathinterp_test.go
File metadata and controls
81 lines (75 loc) · 2.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
package stats_test
import (
"fmt"
"math"
"reflect"
"testing"
"github.com/montanaflynn/stats"
)
func ExampleInterp() {
out, _ := stats.Interp([]float64{1.5}, []float64{1, 2}, []float64{10, 20})
fmt.Println(out)
// Output: [15]
}
func TestInterp(t *testing.T) {
for _, c := range []struct {
x []float64
xp []float64
fp []float64
out []float64
}{
{[]float64{1.5}, []float64{1, 2}, []float64{10, 20}, []float64{15}},
{[]float64{0, 1, 1.5, 2.5, 4}, []float64{1, 2, 3}, []float64{10, 20, 40}, []float64{10, 10, 15, 30, 40}},
{[]float64{2.5, 4}, []float64{1, 2, 3, 5}, []float64{3, 2, 0, 4}, []float64{1, 2}},
{[]float64{-1, 0.5, 2}, []float64{1}, []float64{5}, []float64{5, 5, 5}},
{[]float64{-10}, []float64{0, 1}, []float64{2, 4}, []float64{2}},
{[]float64{10}, []float64{0, 1}, []float64{2, 4}, []float64{4}},
// Exact knot hits return fp[j] exactly even when the naive
// arithmetic would suffer catastrophic cancellation
{[]float64{2}, []float64{1, 2, 3}, []float64{1e16, 1, 1}, []float64{1}},
// Knot spacing that overflows float64
{[]float64{0}, []float64{-math.MaxFloat64, math.MaxFloat64}, []float64{0, 100}, []float64{50}},
{[]float64{math.MaxFloat64 / 2}, []float64{-math.MaxFloat64, math.MaxFloat64}, []float64{0, 100}, []float64{75}},
// fp spread that overflows float64
{[]float64{0.5}, []float64{0, 1}, []float64{-math.MaxFloat64, math.MaxFloat64}, []float64{0}},
} {
got, err := stats.Interp(c.x, c.xp, c.fp)
if err != nil {
t.Errorf("Returned an error")
}
if !reflect.DeepEqual(c.out, got) {
t.Errorf("Interp(%.1f, %.1f, %.1f) => %.1f != %.1f", c.x, c.xp, c.fp, got, c.out)
}
}
}
func TestInterpInvalidInput(t *testing.T) {
for _, c := range []struct {
x []float64
xp []float64
fp []float64
err error
}{
{[]float64{}, []float64{1, 2}, []float64{10, 20}, stats.ErrEmptyInput},
{[]float64{1.5}, []float64{}, []float64{}, stats.ErrEmptyInput},
{[]float64{1.5}, []float64{1, 2}, []float64{10}, stats.ErrSize},
{[]float64{1.5}, []float64{2, 1}, []float64{10, 20}, stats.ErrBounds},
{[]float64{1.5}, []float64{1, 1}, []float64{10, 20}, stats.ErrBounds},
{[]float64{1.5}, []float64{1, math.NaN(), 3}, []float64{10, 20, 30}, stats.ErrBounds},
{[]float64{1.5}, []float64{math.NaN()}, []float64{10}, stats.ErrBounds},
} {
_, err := stats.Interp(c.x, c.xp, c.fp)
if err != c.err {
t.Errorf("Interp(%.1f, %.1f, %.1f) => %v != %v", c.x, c.xp, c.fp, err, c.err)
}
}
}
func TestInterpNaNInput(t *testing.T) {
x := []float64{1.5, math.NaN(), 2.5}
got, err := stats.Interp(x, []float64{1, 2, 3}, []float64{10, 20, 30})
if err != nil {
t.Fatalf("Returned an error: %v", err)
}
if got[0] != 15 || !math.IsNaN(got[1]) || got[2] != 25 {
t.Errorf("Interp(%v, ...) => %v != [15 NaN 25]", x, got)
}
}