/// <summary> /// Main interpolation process (first way) /// Applying both direct and backtrack cubic interpolation /// </summary> /// <param name="f0">The new F-value</param> /// <returns>The new G-value</returns> public double Interpolate(double f0) { if (!isValid) { return(double.NaN); } // filtering data in order to apply back interpolation // remember that the second array (sourceF) has ordering type. Filter.Process(1E-5, ref sourceF); // Step 1. Operator F^-1 (backtrack process) var engine = new Spline(sourceX, sourceF); double value = engine.BackInterpolate(f0); engine = null; // Step 2. Operator G (direct process) engine = new Spline(sourceX, sourceG); double g0 = engine.Interpolate(value); engine = null; return(g0); }
static void Main(string[] args) { long N = 37; double[] srcX = new double[N], srcY = new double[N]; for (long i = 0; i < N; i++) { srcX[i] = Math.Pow((double)i / (N - 1), 2.0); srcY[i] = F(srcX[i]); } double testX = 0.54812; var machine = new Spline(srcX, srcY); double interpolatedY = machine.Interpolate(testX), realY = F(testX); double backInpterpolatedY = machine.BackInterpolate(interpolatedY); double absErrorX = 100.0 * Math.Abs((testX - backInpterpolatedY) / testX), absErrorY = 100.0 * Math.Abs((realY - interpolatedY) / realY); Console.WriteLine("Source X: {0}\nInterpolated X: {1}\nAbsolute error X: {2} percents.\n", testX, backInpterpolatedY, absErrorX); Console.WriteLine("Source Y: {0}\nInterpolated Y: {1}\nAbsolute error Y: {2} percents.", realY, interpolatedY, absErrorY); Console.ReadLine(); }
/// <summary> /// Interpolation with constant axis X and given new axis Y /// Solution of problem: /// F(x, y = y0) => G(x, y = y0) as F(x) => G(x) /// </summary> /// <param name="newY"></param> /// <returns></returns> public double[] Interpolate(double[] f) { if (!isValid) { return(null); } // First step: find the line y = f(x) var exactFY = new double[sizeX]; for (long i = 0; i < sizeX; i++) { var tmpF = GetYByX(i, srcF); // X = x[i] = const, F(x) changes var spline = new Spline(srcY, tmpF); exactFY[i] = spline.BackInterpolate(f[i]); // get the correct point (Y[i], X[i]) spline = null; } // Second step: find the line y = g(x) var newG = new double[sizeX]; for (long i = 0; i < sizeX; i++) { var tmpG = GetYByX(i, srcG); // X = x[i] = const, G(x) changes var spline = new Spline(srcY, tmpG); newG[i] = spline.Interpolate(exactFY[i]); spline = null; } return(newG); }
static void Main(string[] args) { #region Generate source long NF = 10, NG = 17; // Generate pairs ( x, f(x) ) double[] orgX = new double[NF]; double[] orgF = new double[NF]; orgX[0] = 0; orgF[0] = f(orgX[0]); for (long i = 1; i < orgX.LongLength; i++) { orgX[i] = orgX[i - 1] + Generate(0.1, 0.3); orgF[i] = f(orgX[i]); } // Generate pairs ( x, g(x) ) double[] newX = new double[NG]; double[] newG = new double[NG]; double node = (orgX[orgX.LongLength - 1] - orgX[0]) / (newX.LongLength); for (long i = 0; i < newX.LongLength; i++) { newX[i] = i * node + Generate(node) * Generate(0.5, 1); newG[i] = g(newX[i]); } // Show source data Console.WriteLine("\torgX\t\torgF\n ---------------------------"); for (long i = 0; i < orgX.LongLength; i++) { Console.WriteLine("\t{0:F4}\t{1}", orgX[i], orgF[i]); } Console.WriteLine("\n\tnewX\t\tnewG\n ---------------------------"); for (long i = 0; i < newX.LongLength; i++) { Console.WriteLine("\t{0:F4}\t{1}", newX[i], newG[i]); } #endregion #region OperationTest // Custom test double testX = 0.572326; double testF = f(testX); double testG = g(testX); // Mixing method var orgFX = new Spline(orgX, orgF); var newGX = new Spline(newX, newG); double backtrackX = orgFX.BackInterpolate(testF); double resultG = newGX.Interpolate(backtrackX); double error = Math.Abs((testG - resultG) / testG); Console.WriteLine("\n- Custom test #1: F(x) = {0}", testF); Console.WriteLine("\n- Original X: {0}\n- Interpolated X: {1}", testX, backtrackX); Console.WriteLine("\n- Original G(x): {0}\n- Interpolated G(x): {1}\n- Absolute error: {2}", testG, resultG, error); testF = (orgF[0] + orgF[orgF.LongLength - 1]) / 3 * 2; resultG = newGX.Interpolate(orgFX.BackInterpolate(testF)); Console.WriteLine("\n\n- Custom test #2: F(x) = {0} -> G(x) = {1}", testF, resultG); #endregion Console.ReadKey(); }