/// <summary> /// Perform a SVD fit. /// </summary> /// <param name="x">The X matrix.</param> /// <param name="y">The Y matrix.</param> /// <param name="a">The A matrix.</param> /// <param name="funcs">The RBF functions.</param> /// <returns>The fit.</returns> public static double Svdfit(double[][] x, double[][] y, double[][] a, IRadialBasisFunction[] funcs) { int i, j, k; double wmax, tmp, thresh, sum, TOL = 1e-13d; //Allocated memory for svd matrices double[][] u = EngineArray.AllocateDouble2D(x.Length, funcs.Length); double[][] v = EngineArray.AllocateDouble2D(funcs.Length, funcs.Length); var w = new double[funcs.Length]; //Fill input matrix with values based on fitting functions and input coordinates for (i = 0; i < x.Length; i++) { for (j = 0; j < funcs.Length; j++) { u[i][j] = funcs[j].Calculate(x[i]); } } //Perform decomposition Svdcmp(u, w, v); //Check for w values that are close to zero and replace them with zeros such that they are ignored in backsub wmax = 0; for (j = 0; j < funcs.Length; j++) { if (w[j] > wmax) { wmax = w[j]; } } thresh = TOL * wmax; for (j = 0; j < funcs.Length; j++) { if (w[j] < thresh) { w[j] = 0; } } //Perform back substitution to get result Svdbksb(u, w, v, y, a); //Calculate chi squared for the fit double chisq = 0; for (k = 0; k < y[0].Length; k++) { for (i = 0; i < y.Length; i++) { sum = 0.0d; for (j = 0; j < funcs.Length; j++) { sum += a[j][k] * funcs[j].Calculate(x[i]); } tmp = (y[i][k] - sum); chisq += tmp * tmp; } } return(Math.Sqrt(chisq / (y.Length * y[0].Length))); }