package visad.util; import Jama.Matrix; import Jama.LUDecomposition; import java.util.Arrays; public class CubicInterpolator { LUDecomposition solver; double[][] solution = null; double x0 = 0; double x1 = 0; double x2 = 0; double x0_last = 0; double x0_save; float[] values0 = null; float[] values1 = null; float[] values2 = null; float[] values0_last = null; float[] values0_save = null; int numSpatialPts = 1; boolean doIntrp = true; boolean[] needed = null; boolean[] computed = null; public CubicInterpolator(boolean doIntrp, int numSpatialPts) { this.doIntrp = doIntrp; this.numSpatialPts = numSpatialPts; this.solution = new double[4][numSpatialPts]; this.needed = new boolean[numSpatialPts]; this.computed = new boolean[numSpatialPts]; Arrays.fill(needed, false); Arrays.fill(computed, false); } private void buildSolver() { double x0_p3 = x0*x0*x0; double x1_p3 = x1*x1*x1; double x0_p2 = x0*x0; double x1_p2 = x1*x1; Matrix coeffs = new Matrix(new double[][] { {x0_p3, x0_p2, x0, 1}, {x1_p3, x1_p2, x1, 1}, {3*x0_p2, 2*x0, 1, 0}, {3*x1_p2, 2*x1, 1, 0}}, 4, 4); solver = new LUDecomposition(coeffs); } public void interpolate(double xt, float[] interpValues) { if (!doIntrp) { if (xt == x0) { System.arraycopy(values0, 0, interpValues, 0, numSpatialPts); } else if (xt == x1) { System.arraycopy(values1, 0, interpValues, 0, numSpatialPts); } return; } java.util.Arrays.fill(interpValues, Float.NaN); for (int k=0; k<numSpatialPts; k++) { if (!computed[k]) { // don't need to interp at these locations, at this time continue; } interpValues[k] = (float) cubic_poly(xt, solution[0][k], solution[1][k], solution[2][k], solution[3][k]); } } public void next(double x0, double x1, double x2, float[] values0, float[] values1, float[] values2) { this.x0 = x0; this.x1 = x1; this.x2 = x2; this.values0 = values0; this.values1 = values1; this.values2 = values2; this.x0_last = x0_save; this.x0_save = x0; this.values0_last = values0_save; this.values0_save = values0; Arrays.fill(computed, false); if (!doIntrp) { return; } buildSolver(); } public void update(boolean[] needed) { java.util.Arrays.fill(this.needed, false); for (int k=0; k<numSpatialPts; k++) { if (needed[k]) { if (!computed[k]) { this.needed[k] = true; } } } if (doIntrp) { getSolution(); } } private void getSolution() { for (int k=0; k<numSpatialPts; k++) { if (!this.needed[k]) { continue; } double D1_1 = Double.NaN; double D1_0 = Double.NaN; double y0 = values0[k]; double y1 = values1[k]; if (values0_last == null) { D1_0 = (values1[k] - values0[k])/(x1 - x0); } else { D1_0 = (values1[k] - values0_last[k])/(x1 - x0_last); } D1_1 = (values2[k] - values0[k])/(x2 - x0); double[] sol = getSolution(y0, y1, D1_0, D1_1); solution[0][k] = sol[0]; solution[1][k] = sol[1]; solution[2][k] = sol[2]; solution[3][k] = sol[3]; computed[k] = true; } } private double[] getSolution(double y0, double y1, double D1_0, double D1_1) { Matrix constants = new Matrix(new double[][] { {y0}, {y1}, {D1_0}, {D1_1} }, 4, 1); double[][] solution = (solver.solve(constants)).getArray(); return new double[] {solution[0][0], solution[1][0], solution[2][0], solution[3][0]}; } public static double cubic_poly_D1(double x, double a, double b, double c) { return 3*a*x*x + 2*b*x + c; } public static double cubic_poly(double x, double a, double b, double c, double d) { return a*x*x*x + b*x*x + c*x + d; } }