/* * Work in this file is derived from code originally written by Hans-Peter Moser: * http://www.mosismath.com/PeriodicSplines/PeriodicSplines.html */ namespace Connected.Components; public class PeriodicSpline : SplineInterpolator { public PeriodicSpline(double[] xs, double[] ys, int resolution = 10) : base(xs, ys, resolution) { m = new Matrix(n - 1); gauss = new MatrixSolver(n - 1, m); a = new double[n + 1]; b = new double[n + 1]; c = new double[n + 1]; d = new double[n + 1]; h = new double[n]; CalcParameters(); Integrate(); Interpolate(); } public void CalcParameters() { for (int i = 0; i < n; i++) a[i] = GivenYs[i]; for (int i = 0; i < n - 1; i++) h[i] = GivenXs[i + 1] - GivenXs[i]; a[n] = GivenYs[1]; h[n - 1] = h[0]; for (int i = 0; i < n - 1; i++) for (int k = 0; k < n - 1; k++) { m.a[i, k] = 0.0; m.y[i] = 0.0; m.x[i] = 0.0; } for (int i = 0; i < n - 1; i++) { if (i == 0) { m.a[i, 0] = 2.0 * (h[0] + h[1]); m.a[i, 1] = h[1]; } else { m.a[i, i - 1] = h[i]; m.a[i, i] = 2.0 * (h[i] + h[i + 1]); if (i < n - 2) m.a[i, i + 1] = h[i + 1]; } if ((h[i] != 0.0) && (h[i + 1] != 0.0)) m.y[i] = ((a[i + 2] - a[i + 1]) / h[i + 1] - (a[i + 1] - a[i]) / h[i]) * 3.0; else m.y[i] = 0.0; } m.a[0, n - 2] = h[0]; m.a[n - 2, 0] = h[0]; if (gauss.Eliminate() == false) throw new InvalidOperationException(); gauss.Solve(); for (int i = 1; i < n; i++) c[i] = m.x[i - 1]; c[0] = c[n - 1]; for (int i = 0; i < n; i++) { if (h[i] != 0.0) { d[i] = 1.0 / 3.0 / h[i] * (c[i + 1] - c[i]); b[i] = 1.0 / h[i] * (a[i + 1] - a[i]) - h[i] / 3.0 * (c[i + 1] + 2 * c[i]); } } } }