feat: initial release
Release / gates (push) Successful in 4m38s
Test / test (push) Successful in 5m16s
Release / release (push) Successful in 35s

Assisted-by: GLM 5.3 Flash
This commit is contained in:
2026-09-03 10:00:00 +02:00
commit af4ee19703
617 changed files with 191195 additions and 0 deletions
+41
View File
@@ -0,0 +1,41 @@
// Copyright (c) 2026 Petr Balvín <opensource@petrbalvin.org> (https://petrbalvin.org)
// SPDX-License-Identifier: MIT
package integrate
import (
"math"
"testing"
"sourcedock.dev/petrbalvin/tensor/internal/core"
)
// TestFixedStepTimeGrid pins the exact time grid of the fixed-step
// solvers: the stage times come from t0 + i·h, never from an
// accumulated t += h, whose rounding walks over a long run. On
// y' = cos t from t0 = 1e6 the walk used to hold the answer at an
// error of 1.1e-8 that no step count refined away; the grid puts RK4
// at its own truncation floor and lets the first-order schemes show
// their h. The tolerances sit an order below the old walk, so the pin
// fails on an accumulated-time build.
func TestFixedStepTimeGrid(t *testing.T) {
const t0, span, steps = 1e6, 1e-1, 1e5
cos := func(t float64, y *core.Array) (*core.Array, error) {
return core.FromFloats([]float64{math.Cos(t)}, 1)
}
exact := math.Sin(t0 + span)
end, err := IntegrateRK4(cos, t0, t0+span, mustFloats(t, []float64{math.Sin(t0)}), steps)
if err != nil {
t.Fatalf("IntegrateRK4: %v", err)
}
if got := math.Abs(end.FloatAt(0) - exact); got > 1e-11 {
t.Fatalf("RK4 error %.3e exceeds 1e-11: the stage times have left the exact grid", got)
}
end, err = IntegrateBackwardEuler(cos, t0, t0+span, mustFloats(t, []float64{math.Sin(t0)}), 1e6, ODEOptions{})
if err != nil {
t.Fatalf("IntegrateBackwardEuler: %v", err)
}
if got := math.Abs(end.FloatAt(0) - exact); got > 5e-9 {
t.Fatalf("backward Euler error %.3e exceeds 5e-9: the step times have left the exact grid", got)
}
}