39 lines
1.4 KiB
Go
39 lines
1.4 KiB
Go
// Copyright (c) 2026 Petr Balvín <opensource@petrbalvin.org> (https://petrbalvin.org)
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package core
|
|
|
|
import "testing"
|
|
|
|
// TestInterpolateQueryOnKnotTakesTheLeftSegment pins the segment choice
|
|
// for a query landing exactly on a knot: the bisection takes the first
|
|
// knot at or above the query, so the left segment is used and the query
|
|
// sits at its upper end with t exactly 1. With a lower y of zero the
|
|
// interpolation is exactly the knot's own y. A repeated knot makes the
|
|
// choice observable: the query returns the first of the repeated ys,
|
|
// where the right segment would return the second.
|
|
func TestInterpolateQueryOnKnotTakesTheLeftSegment(t *testing.T) {
|
|
xs := mustFloats(t, []float64{0, 1, 2, 3})
|
|
ys := mustFloats(t, []float64{0, 10, 20, 30})
|
|
q := mustFloats(t, []float64{1, 2})
|
|
out, err := Interpolate(xs, ys, q)
|
|
if err != nil {
|
|
t.Fatalf("Interpolate: %v", err)
|
|
}
|
|
for i, w := range []float64{10, 20} {
|
|
if got := out.FloatAt(i); got != w {
|
|
t.Fatalf("query on knot %v answered %v, want exactly %v", q.FloatAt(i), got, w)
|
|
}
|
|
}
|
|
dup, err := Interpolate(
|
|
mustFloats(t, []float64{0, 1, 1, 2}),
|
|
mustFloats(t, []float64{10, 20, 30, 40}),
|
|
mustFloats(t, []float64{1}))
|
|
if err != nil {
|
|
t.Fatalf("Interpolate: %v", err)
|
|
}
|
|
if got := dup.FloatAt(0); got != 20 {
|
|
t.Fatalf("query on a repeated knot answered %v, want the left segment's 20", got)
|
|
}
|
|
}
|