94 lines
2.8 KiB
Go
94 lines
2.8 KiB
Go
package numerics
|
|
|
|
import (
|
|
"math"
|
|
"testing"
|
|
)
|
|
|
|
func TestAxisLocate(t *testing.T) {
|
|
a := Axis{Left: -90, Step: 0.5, N: 361, Name: "lat"}
|
|
|
|
b, err := a.Locate(-90)
|
|
if err != nil || b.Lo != 0 || b.Hi != 1 || b.Frac != 0 {
|
|
t.Errorf("Locate(-90) = %+v, %v; want {0 1 0}, nil", b, err)
|
|
}
|
|
|
|
b, err = a.Locate(0)
|
|
if err != nil || b.Lo != 180 || b.Hi != 181 || b.Frac != 0 {
|
|
t.Errorf("Locate(0) = %+v, %v; want {180 181 0}, nil", b, err)
|
|
}
|
|
|
|
b, err = a.Locate(-89.75)
|
|
if err != nil || b.Lo != 0 || b.Hi != 1 || math.Abs(b.Frac-0.5) > 1e-12 {
|
|
t.Errorf("Locate(-89.75) = %+v, %v; want frac=0.5", b, err)
|
|
}
|
|
|
|
// 90 is exactly on the upper boundary — there's no Hi above it
|
|
if _, err := a.Locate(90); err == nil {
|
|
t.Errorf("Locate(90) should error, got nil")
|
|
}
|
|
|
|
if _, err := a.Locate(-91); err == nil {
|
|
t.Errorf("Locate(-91) should error, got nil")
|
|
}
|
|
}
|
|
|
|
func TestAxisLocateWrap(t *testing.T) {
|
|
a := Axis{Left: 0, Step: 0.5, N: 720, Wrap: true, Name: "lng"}
|
|
|
|
b, err := a.Locate(0)
|
|
if err != nil || b.Lo != 0 || b.Hi != 1 || b.Frac != 0 {
|
|
t.Errorf("Locate(0) = %+v, %v", b, err)
|
|
}
|
|
|
|
// Right up against the wrap boundary
|
|
b, err = a.Locate(359.75)
|
|
if err != nil || b.Lo != 719 || b.Hi != 0 || math.Abs(b.Frac-0.5) > 1e-12 {
|
|
t.Errorf("Locate(359.75) = %+v, %v; want {719 0 0.5}", b, err)
|
|
}
|
|
|
|
// 360 is outside the half-open interval
|
|
if _, err := a.Locate(360); err == nil {
|
|
t.Errorf("Locate(360) should error, got nil")
|
|
}
|
|
}
|
|
|
|
func TestEvalTrilinear(t *testing.T) {
|
|
// Field f(i,j,k) = 100*i + 10*j + k.
|
|
f := func(i, j, k int) float64 { return 100*float64(i) + 10*float64(j) + float64(k) }
|
|
|
|
// At all fractions = 0.5, expected value is the mean of the 8 corners.
|
|
bs := [3]Bracket{{Lo: 0, Hi: 1, Frac: 0.5}, {Lo: 0, Hi: 1, Frac: 0.5}, {Lo: 0, Hi: 1, Frac: 0.5}}
|
|
got := EvalTrilinear(bs, f)
|
|
want := (0 + 1 + 10 + 11 + 100 + 101 + 110 + 111) / 8.0
|
|
if math.Abs(got-want) > 1e-12 {
|
|
t.Errorf("EvalTrilinear at center = %v, want %v", got, want)
|
|
}
|
|
|
|
// At all fractions = 0, expected value is f(lo, lo, lo) = 0.
|
|
bs = [3]Bracket{{Lo: 0, Hi: 1, Frac: 0}, {Lo: 0, Hi: 1, Frac: 0}, {Lo: 0, Hi: 1, Frac: 0}}
|
|
got = EvalTrilinear(bs, f)
|
|
if got != 0 {
|
|
t.Errorf("EvalTrilinear at (lo,lo,lo) = %v, want 0", got)
|
|
}
|
|
|
|
// Asymmetric: linear field f(i,j,k) = i should give frac of axis 0 exactly.
|
|
f2 := func(i, _, _ int) float64 { return float64(i) }
|
|
bs = [3]Bracket{{Lo: 0, Hi: 1, Frac: 0.3}, {Lo: 0, Hi: 1, Frac: 0.7}, {Lo: 0, Hi: 1, Frac: 0.9}}
|
|
got = EvalTrilinear(bs, f2)
|
|
if math.Abs(got-0.3) > 1e-12 {
|
|
t.Errorf("EvalTrilinear of i-field = %v, want 0.3", got)
|
|
}
|
|
}
|
|
|
|
func TestLerp(t *testing.T) {
|
|
if Lerp(10, 20, 0) != 10 {
|
|
t.Errorf("Lerp(10, 20, 0) != 10")
|
|
}
|
|
if Lerp(10, 20, 1) != 20 {
|
|
t.Errorf("Lerp(10, 20, 1) != 20")
|
|
}
|
|
if math.Abs(Lerp(10, 20, 0.25)-12.5) > 1e-12 {
|
|
t.Errorf("Lerp(10, 20, 0.25) != 12.5")
|
|
}
|
|
}
|