/************************************************************************* * This subroutine calculates the value of the bilinear or bicubic spline at * the given point X. * * Input parameters: * C - coefficients table. * Built by BuildBilinearSpline or BuildBicubicSpline. * X, Y- point * * Result: * S(x,y) * * -- ALGLIB PROJECT -- * Copyright 05.07.2007 by Bochkanov Sergey *************************************************************************/ public static double spline2dcalc(ref spline2dinterpolant c, double x, double y) { double result = 0; double v = 0; double vx = 0; double vy = 0; double vxy = 0; spline2ddiff(ref c, x, y, ref v, ref vx, ref vy, ref vxy); result = v; return(result); }
/************************************************************************* * This subroutine makes the copy of the spline model. * * Input parameters: * C - spline interpolant * * Output parameters: * CC - spline copy * * -- ALGLIB PROJECT -- * Copyright 29.06.2007 by Bochkanov Sergey *************************************************************************/ public static void spline2dcopy(ref spline2dinterpolant c, ref spline2dinterpolant cc) { int n = 0; int i_ = 0; System.Diagnostics.Debug.Assert(c.k == 1 | c.k == 3, "Spline2DCopy: incorrect C!"); cc.k = c.k; n = (int)Math.Round(c.c[0]); cc.c = new double[n]; for (i_ = 0; i_ <= n - 1; i_++) { cc.c[i_] = c.c[i_]; } }
/************************************************************************* * Unserialization of the spline interpolant * * INPUT PARAMETERS: * RA - array of real numbers which contains interpolant, * * OUTPUT PARAMETERS: * B - spline interpolant * * -- ALGLIB -- * Copyright 17.08.2009 by Bochkanov Sergey *************************************************************************/ public static void spline2dunserialize(ref double[] ra, ref spline2dinterpolant c) { int clen = 0; int i_ = 0; int i1_ = 0; System.Diagnostics.Debug.Assert((int)Math.Round(ra[1]) == spline2dvnum, "Spline2DUnserialize: corrupted array!"); c.k = (int)Math.Round(ra[2]); clen = (int)Math.Round(ra[3]); c.c = new double[clen]; i1_ = (3) - (0); for (i_ = 0; i_ <= clen - 1; i_++) { c.c[i_] = ra[i_ + i1_]; } }
/************************************************************************* * This subroutine performs linear transformation of the spline. * * Input parameters: * C - spline interpolant. * A, B- transformation coefficients: S2(x,y) = A*S(x,y) + B * * Output parameters: * C - transformed spline * * -- ALGLIB PROJECT -- * Copyright 30.06.2007 by Bochkanov Sergey *************************************************************************/ public static void spline2dlintransf(ref spline2dinterpolant c, double a, double b) { int i = 0; int j = 0; int n = 0; int m = 0; double[] x = new double[0]; double[] y = new double[0]; double[,] f = new double[0, 0]; int typec = 0; typec = (int)Math.Round(c.c[1]); System.Diagnostics.Debug.Assert(typec == -3 | typec == -1, "Spline2DLinTransXY: incorrect C!"); n = (int)Math.Round(c.c[2]); m = (int)Math.Round(c.c[3]); x = new double[n - 1 + 1]; y = new double[m - 1 + 1]; f = new double[m - 1 + 1, n - 1 + 1]; for (j = 0; j <= n - 1; j++) { x[j] = c.c[4 + j]; } for (i = 0; i <= m - 1; i++) { y[i] = c.c[4 + n + i]; } for (i = 0; i <= m - 1; i++) { for (j = 0; j <= n - 1; j++) { f[i, j] = a * c.c[4 + n + m + i * n + j] + b; } } if (typec == -3) { spline2dbuildbicubic(x, y, f, m, n, ref c); } if (typec == -1) { spline2dbuildbilinear(x, y, f, m, n, ref c); } }
/************************************************************************* * Serialization of the spline interpolant * * INPUT PARAMETERS: * B - spline interpolant * * OUTPUT PARAMETERS: * RA - array of real numbers which contains interpolant, * array[0..RLen-1] * RLen - RA lenght * * -- ALGLIB -- * Copyright 17.08.2009 by Bochkanov Sergey *************************************************************************/ public static void spline2dserialize(ref spline2dinterpolant c, ref double[] ra, ref int ralen) { int clen = 0; int i_ = 0; int i1_ = 0; System.Diagnostics.Debug.Assert(c.k == 1 | c.k == 3, "Spline2DSerialize: incorrect C!"); clen = (int)Math.Round(c.c[0]); ralen = 3 + clen; ra = new double[ralen]; ra[0] = ralen; ra[1] = spline2dvnum; ra[2] = c.k; i1_ = (0) - (3); for (i_ = 3; i_ <= 3 + clen - 1; i_++) { ra[i_] = c.c[i_ + i1_]; } }
/************************************************************************* This subroutine builds bicubic vector-valued spline. Input parameters: X - spline abscissas, array[0..N-1] Y - spline ordinates, array[0..M-1] F - function values, array[0..M*N*D-1]: * first D elements store D values at (X[0],Y[0]) * next D elements store D values at (X[1],Y[0]) * general form - D function values at (X[i],Y[j]) are stored at F[D*(J*N+I)...D*(J*N+I)+D-1]. M,N - grid size, M>=2, N>=2 D - vector dimension, D>=1 Output parameters: C - spline interpolant -- ALGLIB PROJECT -- Copyright 16.04.2012 by Bochkanov Sergey *************************************************************************/ public static void spline2dbuildbicubicv(double[] x, int n, double[] y, int m, double[] f, int d, spline2dinterpolant c) { double[,] tf = new double[0,0]; double[,] dx = new double[0,0]; double[,] dy = new double[0,0]; double[,] dxy = new double[0,0]; double t = 0; int i = 0; int j = 0; int k = 0; int di = 0; f = (double[])f.Clone(); alglib.ap.assert(n>=2, "Spline2DBuildBicubicV: N is less than 2"); alglib.ap.assert(m>=2, "Spline2DBuildBicubicV: M is less than 2"); alglib.ap.assert(d>=1, "Spline2DBuildBicubicV: invalid argument D (D<1)"); alglib.ap.assert(alglib.ap.len(x)>=n && alglib.ap.len(y)>=m, "Spline2DBuildBicubicV: length of X or Y is too short (Length(X/Y)<N/M)"); alglib.ap.assert(apserv.isfinitevector(x, n) && apserv.isfinitevector(y, m), "Spline2DBuildBicubicV: X or Y contains NaN or Infinite value"); k = n*m*d; alglib.ap.assert(alglib.ap.len(f)>=k, "Spline2DBuildBicubicV: length of F is too short (Length(F)<N*M*D)"); alglib.ap.assert(apserv.isfinitevector(f, k), "Spline2DBuildBicubicV: F contains NaN or Infinite value"); // // Fill interpolant: // F[0]...F[N*M*D-1]: // f(i,j) table. f(0,0), f(0, 1), f(0,2) and so on... // F[N*M*D]...F[2*N*M*D-1]: // df(i,j)/dx table. // F[2*N*M*D]...F[3*N*M*D-1]: // df(i,j)/dy table. // F[3*N*M*D]...F[4*N*M*D-1]: // d2f(i,j)/dxdy table. // c.k = 3; c.d = d; c.n = n; c.m = m; c.stype = -3; k = 4*k; c.x = new double[c.n]; c.y = new double[c.m]; c.f = new double[k]; tf = new double[c.m, c.n]; for(i=0; i<=c.n-1; i++) { c.x[i] = x[i]; } for(i=0; i<=c.m-1; i++) { c.y[i] = y[i]; } // // Sort points // for(j=0; j<=c.n-1; j++) { k = j; for(i=j+1; i<=c.n-1; i++) { if( (double)(c.x[i])<(double)(c.x[k]) ) { k = i; } } if( k!=j ) { for(i=0; i<=c.m-1; i++) { for(di=0; di<=c.d-1; di++) { t = f[c.d*(i*c.n+j)+di]; f[c.d*(i*c.n+j)+di] = f[c.d*(i*c.n+k)+di]; f[c.d*(i*c.n+k)+di] = t; } } t = c.x[j]; c.x[j] = c.x[k]; c.x[k] = t; } } for(i=0; i<=c.m-1; i++) { k = i; for(j=i+1; j<=c.m-1; j++) { if( (double)(c.y[j])<(double)(c.y[k]) ) { k = j; } } if( k!=i ) { for(j=0; j<=c.n-1; j++) { for(di=0; di<=c.d-1; di++) { t = f[c.d*(i*c.n+j)+di]; f[c.d*(i*c.n+j)+di] = f[c.d*(k*c.n+j)+di]; f[c.d*(k*c.n+j)+di] = t; } } t = c.y[i]; c.y[i] = c.y[k]; c.y[k] = t; } } for(di=0; di<=c.d-1; di++) { for(i=0; i<=c.m-1; i++) { for(j=0; j<=c.n-1; j++) { tf[i,j] = f[c.d*(i*c.n+j)+di]; } } bicubiccalcderivatives(tf, c.x, c.y, c.m, c.n, ref dx, ref dy, ref dxy); for(i=0; i<=c.m-1; i++) { for(j=0; j<=c.n-1; j++) { k = c.d*(i*c.n+j)+di; c.f[k] = tf[i,j]; c.f[c.n*c.m*c.d+k] = dx[i,j]; c.f[2*c.n*c.m*c.d+k] = dy[i,j]; c.f[3*c.n*c.m*c.d+k] = dxy[i,j]; } } } }
/************************************************************************* This subroutine builds bicubic spline coefficients table. Input parameters: X - spline abscissas, array[0..N-1] Y - spline ordinates, array[0..M-1] F - function values, array[0..M-1,0..N-1] M,N - grid size, M>=2, N>=2 Output parameters: C - spline interpolant -- ALGLIB PROJECT -- Copyright 05.07.2007 by Bochkanov Sergey *************************************************************************/ public static void spline2dbuildbicubic(double[] x, double[] y, double[,] f, int m, int n, spline2dinterpolant c) { int i = 0; int j = 0; int k = 0; int tblsize = 0; int shift = 0; double t = 0; double[,] dx = new double[0, 0]; double[,] dy = new double[0, 0]; double[,] dxy = new double[0, 0]; x = (double[])x.Clone(); y = (double[])y.Clone(); f = (double[,])f.Clone(); ap.assert(n >= 2 & m >= 2, "BuildBicubicSpline: N<2 or M<2!"); // // Sort points // for(j = 0; j <= n - 1; j++) { k = j; for(i = j + 1; i <= n - 1; i++) { if((double)(x[i]) < (double)(x[k])) { k = i; } } if(k != j) { for(i = 0; i <= m - 1; i++) { t = f[i, j]; f[i, j] = f[i, k]; f[i, k] = t; } t = x[j]; x[j] = x[k]; x[k] = t; } } for(i = 0; i <= m - 1; i++) { k = i; for(j = i + 1; j <= m - 1; j++) { if((double)(y[j]) < (double)(y[k])) { k = j; } } if(k != i) { for(j = 0; j <= n - 1; j++) { t = f[i, j]; f[i, j] = f[k, j]; f[k, j] = t; } t = y[i]; y[i] = y[k]; y[k] = t; } } // // Fill C: // C[0] - length(C) // C[1] - type(C): // -1 = bilinear interpolant // (see BuildBilinearInterpolant) // -3 = general cubic spline // C[2]: // N (x count) // C[3]: // M (y count) // C[4]...C[4+N-1]: // x[i], i = 0...N-1 // C[4+N]...C[4+N+M-1]: // y[i], i = 0...M-1 // C[4+N+M]...C[4+N+M+(N*M-1)]: // f(i,j) table. f(0,0), f(0, 1), f(0,2) and so on... // C[4+N+M+N*M]...C[4+N+M+(2*N*M-1)]: // df(i,j)/dx table. // C[4+N+M+2*N*M]...C[4+N+M+(3*N*M-1)]: // df(i,j)/dy table. // C[4+N+M+3*N*M]...C[4+N+M+(4*N*M-1)]: // d2f(i,j)/dxdy table. // c.k = 3; tblsize = 4 + n + m + 4 * n * m; c.c = new double[tblsize - 1 + 1]; c.c[0] = tblsize; c.c[1] = -3; c.c[2] = n; c.c[3] = m; for(i = 0; i <= n - 1; i++) { c.c[4 + i] = x[i]; } for(i = 0; i <= m - 1; i++) { c.c[4 + n + i] = y[i]; } bicubiccalcderivatives(f, x, y, m, n, ref dx, ref dy, ref dxy); for(i = 0; i <= m - 1; i++) { for(j = 0; j <= n - 1; j++) { shift = i * n + j; c.c[4 + n + m + shift] = f[i, j]; c.c[4 + n + m + n * m + shift] = dx[i, j]; c.c[4 + n + m + 2 * n * m + shift] = dy[i, j]; c.c[4 + n + m + 3 * n * m + shift] = dxy[i, j]; } } }
/************************************************************************* * This subroutine unpacks two-dimensional spline into the coefficients table * * Input parameters: * C - spline interpolant. * * Result: * M, N- grid size (x-axis and y-axis) * Tbl - coefficients table, unpacked format, * [0..(N-1)*(M-1)-1, 0..19]. * For I = 0...M-2, J=0..N-2: * K = I*(N-1)+J * Tbl[K,0] = X[j] * Tbl[K,1] = X[j+1] * Tbl[K,2] = Y[i] * Tbl[K,3] = Y[i+1] * Tbl[K,4] = C00 * Tbl[K,5] = C01 * Tbl[K,6] = C02 * Tbl[K,7] = C03 * Tbl[K,8] = C10 * Tbl[K,9] = C11 * ... * Tbl[K,19] = C33 * On each grid square spline is equals to: * S(x) = SUM(c[i,j]*(x^i)*(y^j), i=0..3, j=0..3) * t = x-x[j] * u = y-y[i] * * -- ALGLIB PROJECT -- * Copyright 29.06.2007 by Bochkanov Sergey *************************************************************************/ public static void spline2dunpack(ref spline2dinterpolant c, ref int m, ref int n, ref double[,] tbl) { int i = 0; int j = 0; int ci = 0; int cj = 0; int k = 0; int p = 0; int shift = 0; int s1 = 0; int s2 = 0; int s3 = 0; int s4 = 0; int sf = 0; int sfx = 0; int sfy = 0; int sfxy = 0; double y1 = 0; double y2 = 0; double y3 = 0; double y4 = 0; double dt = 0; double du = 0; System.Diagnostics.Debug.Assert((int)Math.Round(c.c[1]) == -3 | (int)Math.Round(c.c[1]) == -1, "SplineUnpack2D: incorrect C!"); n = (int)Math.Round(c.c[2]); m = (int)Math.Round(c.c[3]); tbl = new double[(n - 1) * (m - 1) - 1 + 1, 19 + 1]; // // Fill // for (i = 0; i <= m - 2; i++) { for (j = 0; j <= n - 2; j++) { p = i * (n - 1) + j; tbl[p, 0] = c.c[4 + j]; tbl[p, 1] = c.c[4 + j + 1]; tbl[p, 2] = c.c[4 + n + i]; tbl[p, 3] = c.c[4 + n + i + 1]; dt = 1 / (tbl[p, 1] - tbl[p, 0]); du = 1 / (tbl[p, 3] - tbl[p, 2]); // // Bilinear interpolation // if ((int)Math.Round(c.c[1]) == -1) { for (k = 4; k <= 19; k++) { tbl[p, k] = 0; } shift = 4 + n + m; y1 = c.c[shift + n * i + j]; y2 = c.c[shift + n * i + (j + 1)]; y3 = c.c[shift + n * (i + 1) + (j + 1)]; y4 = c.c[shift + n * (i + 1) + j]; tbl[p, 4] = y1; tbl[p, 4 + 1 * 4 + 0] = y2 - y1; tbl[p, 4 + 0 * 4 + 1] = y4 - y1; tbl[p, 4 + 1 * 4 + 1] = y3 - y2 - y4 + y1; } // // Bicubic interpolation // if ((int)Math.Round(c.c[1]) == -3) { sf = 4 + n + m; sfx = 4 + n + m + n * m; sfy = 4 + n + m + 2 * n * m; sfxy = 4 + n + m + 3 * n * m; s1 = n * i + j; s2 = n * i + (j + 1); s3 = n * (i + 1) + (j + 1); s4 = n * (i + 1) + j; tbl[p, 4 + 0 * 4 + 0] = +(1 * c.c[sf + s1]); tbl[p, 4 + 0 * 4 + 1] = +(1 * c.c[sfy + s1] / du); tbl[p, 4 + 0 * 4 + 2] = -(3 * c.c[sf + s1]) + 3 * c.c[sf + s4] - 2 * c.c[sfy + s1] / du - 1 * c.c[sfy + s4] / du; tbl[p, 4 + 0 * 4 + 3] = +(2 * c.c[sf + s1]) - 2 * c.c[sf + s4] + 1 * c.c[sfy + s1] / du + 1 * c.c[sfy + s4] / du; tbl[p, 4 + 1 * 4 + 0] = +(1 * c.c[sfx + s1] / dt); tbl[p, 4 + 1 * 4 + 1] = +(1 * c.c[sfxy + s1] / (dt * du)); tbl[p, 4 + 1 * 4 + 2] = -(3 * c.c[sfx + s1] / dt) + 3 * c.c[sfx + s4] / dt - 2 * c.c[sfxy + s1] / (dt * du) - 1 * c.c[sfxy + s4] / (dt * du); tbl[p, 4 + 1 * 4 + 3] = +(2 * c.c[sfx + s1] / dt) - 2 * c.c[sfx + s4] / dt + 1 * c.c[sfxy + s1] / (dt * du) + 1 * c.c[sfxy + s4] / (dt * du); tbl[p, 4 + 2 * 4 + 0] = -(3 * c.c[sf + s1]) + 3 * c.c[sf + s2] - 2 * c.c[sfx + s1] / dt - 1 * c.c[sfx + s2] / dt; tbl[p, 4 + 2 * 4 + 1] = -(3 * c.c[sfy + s1] / du) + 3 * c.c[sfy + s2] / du - 2 * c.c[sfxy + s1] / (dt * du) - 1 * c.c[sfxy + s2] / (dt * du); tbl[p, 4 + 2 * 4 + 2] = +(9 * c.c[sf + s1]) - 9 * c.c[sf + s2] + 9 * c.c[sf + s3] - 9 * c.c[sf + s4] + 6 * c.c[sfx + s1] / dt + 3 * c.c[sfx + s2] / dt - 3 * c.c[sfx + s3] / dt - 6 * c.c[sfx + s4] / dt + 6 * c.c[sfy + s1] / du - 6 * c.c[sfy + s2] / du - 3 * c.c[sfy + s3] / du + 3 * c.c[sfy + s4] / du + 4 * c.c[sfxy + s1] / (dt * du) + 2 * c.c[sfxy + s2] / (dt * du) + 1 * c.c[sfxy + s3] / (dt * du) + 2 * c.c[sfxy + s4] / (dt * du); tbl[p, 4 + 2 * 4 + 3] = -(6 * c.c[sf + s1]) + 6 * c.c[sf + s2] - 6 * c.c[sf + s3] + 6 * c.c[sf + s4] - 4 * c.c[sfx + s1] / dt - 2 * c.c[sfx + s2] / dt + 2 * c.c[sfx + s3] / dt + 4 * c.c[sfx + s4] / dt - 3 * c.c[sfy + s1] / du + 3 * c.c[sfy + s2] / du + 3 * c.c[sfy + s3] / du - 3 * c.c[sfy + s4] / du - 2 * c.c[sfxy + s1] / (dt * du) - 1 * c.c[sfxy + s2] / (dt * du) - 1 * c.c[sfxy + s3] / (dt * du) - 2 * c.c[sfxy + s4] / (dt * du); tbl[p, 4 + 3 * 4 + 0] = +(2 * c.c[sf + s1]) - 2 * c.c[sf + s2] + 1 * c.c[sfx + s1] / dt + 1 * c.c[sfx + s2] / dt; tbl[p, 4 + 3 * 4 + 1] = +(2 * c.c[sfy + s1] / du) - 2 * c.c[sfy + s2] / du + 1 * c.c[sfxy + s1] / (dt * du) + 1 * c.c[sfxy + s2] / (dt * du); tbl[p, 4 + 3 * 4 + 2] = -(6 * c.c[sf + s1]) + 6 * c.c[sf + s2] - 6 * c.c[sf + s3] + 6 * c.c[sf + s4] - 3 * c.c[sfx + s1] / dt - 3 * c.c[sfx + s2] / dt + 3 * c.c[sfx + s3] / dt + 3 * c.c[sfx + s4] / dt - 4 * c.c[sfy + s1] / du + 4 * c.c[sfy + s2] / du + 2 * c.c[sfy + s3] / du - 2 * c.c[sfy + s4] / du - 2 * c.c[sfxy + s1] / (dt * du) - 2 * c.c[sfxy + s2] / (dt * du) - 1 * c.c[sfxy + s3] / (dt * du) - 1 * c.c[sfxy + s4] / (dt * du); tbl[p, 4 + 3 * 4 + 3] = +(4 * c.c[sf + s1]) - 4 * c.c[sf + s2] + 4 * c.c[sf + s3] - 4 * c.c[sf + s4] + 2 * c.c[sfx + s1] / dt + 2 * c.c[sfx + s2] / dt - 2 * c.c[sfx + s3] / dt - 2 * c.c[sfx + s4] / dt + 2 * c.c[sfy + s1] / du - 2 * c.c[sfy + s2] / du - 2 * c.c[sfy + s3] / du + 2 * c.c[sfy + s4] / du + 1 * c.c[sfxy + s1] / (dt * du) + 1 * c.c[sfxy + s2] / (dt * du) + 1 * c.c[sfxy + s3] / (dt * du) + 1 * c.c[sfxy + s4] / (dt * du); } // // Rescale Cij // for (ci = 0; ci <= 3; ci++) { for (cj = 0; cj <= 3; cj++) { tbl[p, 4 + ci * 4 + cj] = tbl[p, 4 + ci * 4 + cj] * Math.Pow(dt, ci) * Math.Pow(du, cj); } } } } }
/************************************************************************* * This subroutine calculates the value of the bilinear or bicubic spline at * the given point X and its derivatives. * * Input parameters: * C - spline interpolant. * X, Y- point * * Output parameters: * F - S(x,y) * FX - dS(x,y)/dX * FY - dS(x,y)/dY * FXY - d2S(x,y)/dXdY * * -- ALGLIB PROJECT -- * Copyright 05.07.2007 by Bochkanov Sergey *************************************************************************/ public static void spline2ddiff(ref spline2dinterpolant c, double x, double y, ref double f, ref double fx, ref double fy, ref double fxy) { int n = 0; int m = 0; double t = 0; double dt = 0; double u = 0; double du = 0; int ix = 0; int iy = 0; int l = 0; int r = 0; int h = 0; int shift1 = 0; int s1 = 0; int s2 = 0; int s3 = 0; int s4 = 0; int sf = 0; int sfx = 0; int sfy = 0; int sfxy = 0; double y1 = 0; double y2 = 0; double y3 = 0; double y4 = 0; double v = 0; double t0 = 0; double t1 = 0; double t2 = 0; double t3 = 0; double u0 = 0; double u1 = 0; double u2 = 0; double u3 = 0; System.Diagnostics.Debug.Assert((int)Math.Round(c.c[1]) == -1 | (int)Math.Round(c.c[1]) == -3, "Spline2DDiff: incorrect C!"); n = (int)Math.Round(c.c[2]); m = (int)Math.Round(c.c[3]); // // Binary search in the [ x[0], ..., x[n-2] ] (x[n-1] is not included) // l = 4; r = 4 + n - 2 + 1; while (l != r - 1) { h = (l + r) / 2; if ((double)(c.c[h]) >= (double)(x)) { r = h; } else { l = h; } } t = (x - c.c[l]) / (c.c[l + 1] - c.c[l]); dt = 1.0 / (c.c[l + 1] - c.c[l]); ix = l - 4; // // Binary search in the [ y[0], ..., y[m-2] ] (y[m-1] is not included) // l = 4 + n; r = 4 + n + (m - 2) + 1; while (l != r - 1) { h = (l + r) / 2; if ((double)(c.c[h]) >= (double)(y)) { r = h; } else { l = h; } } u = (y - c.c[l]) / (c.c[l + 1] - c.c[l]); du = 1.0 / (c.c[l + 1] - c.c[l]); iy = l - (4 + n); // // Prepare F, dF/dX, dF/dY, d2F/dXdY // f = 0; fx = 0; fy = 0; fxy = 0; // // Bilinear interpolation // if ((int)Math.Round(c.c[1]) == -1) { shift1 = 4 + n + m; y1 = c.c[shift1 + n * iy + ix]; y2 = c.c[shift1 + n * iy + (ix + 1)]; y3 = c.c[shift1 + n * (iy + 1) + (ix + 1)]; y4 = c.c[shift1 + n * (iy + 1) + ix]; f = (1 - t) * (1 - u) * y1 + t * (1 - u) * y2 + t * u * y3 + (1 - t) * u * y4; fx = (-((1 - u) * y1) + (1 - u) * y2 + u * y3 - u * y4) * dt; fy = (-((1 - t) * y1) - t * y2 + t * y3 + (1 - t) * y4) * du; fxy = (y1 - y2 + y3 - y4) * du * dt; return; } // // Bicubic interpolation // if ((int)Math.Round(c.c[1]) == -3) { // // Prepare info // t0 = 1; t1 = t; t2 = AP.Math.Sqr(t); t3 = t * t2; u0 = 1; u1 = u; u2 = AP.Math.Sqr(u); u3 = u * u2; sf = 4 + n + m; sfx = 4 + n + m + n * m; sfy = 4 + n + m + 2 * n * m; sfxy = 4 + n + m + 3 * n * m; s1 = n * iy + ix; s2 = n * iy + (ix + 1); s3 = n * (iy + 1) + (ix + 1); s4 = n * (iy + 1) + ix; // // Calculate // v = +(1 * c.c[sf + s1]); f = f + v * t0 * u0; v = +(1 * c.c[sfy + s1] / du); f = f + v * t0 * u1; fy = fy + 1 * v * t0 * u0 * du; v = -(3 * c.c[sf + s1]) + 3 * c.c[sf + s4] - 2 * c.c[sfy + s1] / du - 1 * c.c[sfy + s4] / du; f = f + v * t0 * u2; fy = fy + 2 * v * t0 * u1 * du; v = +(2 * c.c[sf + s1]) - 2 * c.c[sf + s4] + 1 * c.c[sfy + s1] / du + 1 * c.c[sfy + s4] / du; f = f + v * t0 * u3; fy = fy + 3 * v * t0 * u2 * du; v = +(1 * c.c[sfx + s1] / dt); f = f + v * t1 * u0; fx = fx + 1 * v * t0 * u0 * dt; v = +(1 * c.c[sfxy + s1] / (dt * du)); f = f + v * t1 * u1; fx = fx + 1 * v * t0 * u1 * dt; fy = fy + 1 * v * t1 * u0 * du; fxy = fxy + 1 * v * t0 * u0 * dt * du; v = -(3 * c.c[sfx + s1] / dt) + 3 * c.c[sfx + s4] / dt - 2 * c.c[sfxy + s1] / (dt * du) - 1 * c.c[sfxy + s4] / (dt * du); f = f + v * t1 * u2; fx = fx + 1 * v * t0 * u2 * dt; fy = fy + 2 * v * t1 * u1 * du; fxy = fxy + 2 * v * t0 * u1 * dt * du; v = +(2 * c.c[sfx + s1] / dt) - 2 * c.c[sfx + s4] / dt + 1 * c.c[sfxy + s1] / (dt * du) + 1 * c.c[sfxy + s4] / (dt * du); f = f + v * t1 * u3; fx = fx + 1 * v * t0 * u3 * dt; fy = fy + 3 * v * t1 * u2 * du; fxy = fxy + 3 * v * t0 * u2 * dt * du; v = -(3 * c.c[sf + s1]) + 3 * c.c[sf + s2] - 2 * c.c[sfx + s1] / dt - 1 * c.c[sfx + s2] / dt; f = f + v * t2 * u0; fx = fx + 2 * v * t1 * u0 * dt; v = -(3 * c.c[sfy + s1] / du) + 3 * c.c[sfy + s2] / du - 2 * c.c[sfxy + s1] / (dt * du) - 1 * c.c[sfxy + s2] / (dt * du); f = f + v * t2 * u1; fx = fx + 2 * v * t1 * u1 * dt; fy = fy + 1 * v * t2 * u0 * du; fxy = fxy + 2 * v * t1 * u0 * dt * du; v = +(9 * c.c[sf + s1]) - 9 * c.c[sf + s2] + 9 * c.c[sf + s3] - 9 * c.c[sf + s4] + 6 * c.c[sfx + s1] / dt + 3 * c.c[sfx + s2] / dt - 3 * c.c[sfx + s3] / dt - 6 * c.c[sfx + s4] / dt + 6 * c.c[sfy + s1] / du - 6 * c.c[sfy + s2] / du - 3 * c.c[sfy + s3] / du + 3 * c.c[sfy + s4] / du + 4 * c.c[sfxy + s1] / (dt * du) + 2 * c.c[sfxy + s2] / (dt * du) + 1 * c.c[sfxy + s3] / (dt * du) + 2 * c.c[sfxy + s4] / (dt * du); f = f + v * t2 * u2; fx = fx + 2 * v * t1 * u2 * dt; fy = fy + 2 * v * t2 * u1 * du; fxy = fxy + 4 * v * t1 * u1 * dt * du; v = -(6 * c.c[sf + s1]) + 6 * c.c[sf + s2] - 6 * c.c[sf + s3] + 6 * c.c[sf + s4] - 4 * c.c[sfx + s1] / dt - 2 * c.c[sfx + s2] / dt + 2 * c.c[sfx + s3] / dt + 4 * c.c[sfx + s4] / dt - 3 * c.c[sfy + s1] / du + 3 * c.c[sfy + s2] / du + 3 * c.c[sfy + s3] / du - 3 * c.c[sfy + s4] / du - 2 * c.c[sfxy + s1] / (dt * du) - 1 * c.c[sfxy + s2] / (dt * du) - 1 * c.c[sfxy + s3] / (dt * du) - 2 * c.c[sfxy + s4] / (dt * du); f = f + v * t2 * u3; fx = fx + 2 * v * t1 * u3 * dt; fy = fy + 3 * v * t2 * u2 * du; fxy = fxy + 6 * v * t1 * u2 * dt * du; v = +(2 * c.c[sf + s1]) - 2 * c.c[sf + s2] + 1 * c.c[sfx + s1] / dt + 1 * c.c[sfx + s2] / dt; f = f + v * t3 * u0; fx = fx + 3 * v * t2 * u0 * dt; v = +(2 * c.c[sfy + s1] / du) - 2 * c.c[sfy + s2] / du + 1 * c.c[sfxy + s1] / (dt * du) + 1 * c.c[sfxy + s2] / (dt * du); f = f + v * t3 * u1; fx = fx + 3 * v * t2 * u1 * dt; fy = fy + 1 * v * t3 * u0 * du; fxy = fxy + 3 * v * t2 * u0 * dt * du; v = -(6 * c.c[sf + s1]) + 6 * c.c[sf + s2] - 6 * c.c[sf + s3] + 6 * c.c[sf + s4] - 3 * c.c[sfx + s1] / dt - 3 * c.c[sfx + s2] / dt + 3 * c.c[sfx + s3] / dt + 3 * c.c[sfx + s4] / dt - 4 * c.c[sfy + s1] / du + 4 * c.c[sfy + s2] / du + 2 * c.c[sfy + s3] / du - 2 * c.c[sfy + s4] / du - 2 * c.c[sfxy + s1] / (dt * du) - 2 * c.c[sfxy + s2] / (dt * du) - 1 * c.c[sfxy + s3] / (dt * du) - 1 * c.c[sfxy + s4] / (dt * du); f = f + v * t3 * u2; fx = fx + 3 * v * t2 * u2 * dt; fy = fy + 2 * v * t3 * u1 * du; fxy = fxy + 6 * v * t2 * u1 * dt * du; v = +(4 * c.c[sf + s1]) - 4 * c.c[sf + s2] + 4 * c.c[sf + s3] - 4 * c.c[sf + s4] + 2 * c.c[sfx + s1] / dt + 2 * c.c[sfx + s2] / dt - 2 * c.c[sfx + s3] / dt - 2 * c.c[sfx + s4] / dt + 2 * c.c[sfy + s1] / du - 2 * c.c[sfy + s2] / du - 2 * c.c[sfy + s3] / du + 2 * c.c[sfy + s4] / du + 1 * c.c[sfxy + s1] / (dt * du) + 1 * c.c[sfxy + s2] / (dt * du) + 1 * c.c[sfxy + s3] / (dt * du) + 1 * c.c[sfxy + s4] / (dt * du); f = f + v * t3 * u3; fx = fx + 3 * v * t2 * u3 * dt; fy = fy + 3 * v * t3 * u2 * du; fxy = fxy + 9 * v * t2 * u2 * dt * du; return; } }
/************************************************************************* This subroutine was deprecated in ALGLIB 3.6.0 We recommend you to switch to Spline2DUnpackV(), which is more flexible and accepts its arguments in more convenient order. -- ALGLIB PROJECT -- Copyright 29.06.2007 by Bochkanov Sergey *************************************************************************/ public static void spline2dunpack(spline2dinterpolant c, ref int m, ref int n, ref double[,] tbl) { int k = 0; int p = 0; int ci = 0; int cj = 0; int s1 = 0; int s2 = 0; int s3 = 0; int s4 = 0; int sfx = 0; int sfy = 0; int sfxy = 0; double y1 = 0; double y2 = 0; double y3 = 0; double y4 = 0; double dt = 0; double du = 0; int i = 0; int j = 0; m = 0; n = 0; tbl = new double[0,0]; alglib.ap.assert(c.stype==-3 || c.stype==-1, "Spline2DUnpack: incorrect C (incorrect parameter C.SType)"); if( c.d!=1 ) { n = 0; m = 0; return; } n = c.n; m = c.m; tbl = new double[(n-1)*(m-1), 20]; sfx = n*m; sfy = 2*n*m; sfxy = 3*n*m; // // Fill // for(i=0; i<=m-2; i++) { for(j=0; j<=n-2; j++) { p = i*(n-1)+j; tbl[p,0] = c.x[j]; tbl[p,1] = c.x[j+1]; tbl[p,2] = c.y[i]; tbl[p,3] = c.y[i+1]; dt = 1/(tbl[p,1]-tbl[p,0]); du = 1/(tbl[p,3]-tbl[p,2]); // // Bilinear interpolation // if( c.stype==-1 ) { for(k=4; k<=19; k++) { tbl[p,k] = 0; } y1 = c.f[n*i+j]; y2 = c.f[n*i+(j+1)]; y3 = c.f[n*(i+1)+(j+1)]; y4 = c.f[n*(i+1)+j]; tbl[p,4] = y1; tbl[p,4+1*4+0] = y2-y1; tbl[p,4+0*4+1] = y4-y1; tbl[p,4+1*4+1] = y3-y2-y4+y1; } // // Bicubic interpolation // if( c.stype==-3 ) { s1 = n*i+j; s2 = n*i+(j+1); s3 = n*(i+1)+(j+1); s4 = n*(i+1)+j; tbl[p,4+0*4+0] = c.f[s1]; tbl[p,4+0*4+1] = c.f[sfy+s1]/du; tbl[p,4+0*4+2] = -(3*c.f[s1])+3*c.f[s4]-2*c.f[sfy+s1]/du-c.f[sfy+s4]/du; tbl[p,4+0*4+3] = 2*c.f[s1]-2*c.f[s4]+c.f[sfy+s1]/du+c.f[sfy+s4]/du; tbl[p,4+1*4+0] = c.f[sfx+s1]/dt; tbl[p,4+1*4+1] = c.f[sfxy+s1]/(dt*du); tbl[p,4+1*4+2] = -(3*c.f[sfx+s1]/dt)+3*c.f[sfx+s4]/dt-2*c.f[sfxy+s1]/(dt*du)-c.f[sfxy+s4]/(dt*du); tbl[p,4+1*4+3] = 2*c.f[sfx+s1]/dt-2*c.f[sfx+s4]/dt+c.f[sfxy+s1]/(dt*du)+c.f[sfxy+s4]/(dt*du); tbl[p,4+2*4+0] = -(3*c.f[s1])+3*c.f[s2]-2*c.f[sfx+s1]/dt-c.f[sfx+s2]/dt; tbl[p,4+2*4+1] = -(3*c.f[sfy+s1]/du)+3*c.f[sfy+s2]/du-2*c.f[sfxy+s1]/(dt*du)-c.f[sfxy+s2]/(dt*du); tbl[p,4+2*4+2] = 9*c.f[s1]-9*c.f[s2]+9*c.f[s3]-9*c.f[s4]+6*c.f[sfx+s1]/dt+3*c.f[sfx+s2]/dt-3*c.f[sfx+s3]/dt-6*c.f[sfx+s4]/dt+6*c.f[sfy+s1]/du-6*c.f[sfy+s2]/du-3*c.f[sfy+s3]/du+3*c.f[sfy+s4]/du+4*c.f[sfxy+s1]/(dt*du)+2*c.f[sfxy+s2]/(dt*du)+c.f[sfxy+s3]/(dt*du)+2*c.f[sfxy+s4]/(dt*du); tbl[p,4+2*4+3] = -(6*c.f[s1])+6*c.f[s2]-6*c.f[s3]+6*c.f[s4]-4*c.f[sfx+s1]/dt-2*c.f[sfx+s2]/dt+2*c.f[sfx+s3]/dt+4*c.f[sfx+s4]/dt-3*c.f[sfy+s1]/du+3*c.f[sfy+s2]/du+3*c.f[sfy+s3]/du-3*c.f[sfy+s4]/du-2*c.f[sfxy+s1]/(dt*du)-c.f[sfxy+s2]/(dt*du)-c.f[sfxy+s3]/(dt*du)-2*c.f[sfxy+s4]/(dt*du); tbl[p,4+3*4+0] = 2*c.f[s1]-2*c.f[s2]+c.f[sfx+s1]/dt+c.f[sfx+s2]/dt; tbl[p,4+3*4+1] = 2*c.f[sfy+s1]/du-2*c.f[sfy+s2]/du+c.f[sfxy+s1]/(dt*du)+c.f[sfxy+s2]/(dt*du); tbl[p,4+3*4+2] = -(6*c.f[s1])+6*c.f[s2]-6*c.f[s3]+6*c.f[s4]-3*c.f[sfx+s1]/dt-3*c.f[sfx+s2]/dt+3*c.f[sfx+s3]/dt+3*c.f[sfx+s4]/dt-4*c.f[sfy+s1]/du+4*c.f[sfy+s2]/du+2*c.f[sfy+s3]/du-2*c.f[sfy+s4]/du-2*c.f[sfxy+s1]/(dt*du)-2*c.f[sfxy+s2]/(dt*du)-c.f[sfxy+s3]/(dt*du)-c.f[sfxy+s4]/(dt*du); tbl[p,4+3*4+3] = 4*c.f[s1]-4*c.f[s2]+4*c.f[s3]-4*c.f[s4]+2*c.f[sfx+s1]/dt+2*c.f[sfx+s2]/dt-2*c.f[sfx+s3]/dt-2*c.f[sfx+s4]/dt+2*c.f[sfy+s1]/du-2*c.f[sfy+s2]/du-2*c.f[sfy+s3]/du+2*c.f[sfy+s4]/du+c.f[sfxy+s1]/(dt*du)+c.f[sfxy+s2]/(dt*du)+c.f[sfxy+s3]/(dt*du)+c.f[sfxy+s4]/(dt*du); } // // Rescale Cij // for(ci=0; ci<=3; ci++) { for(cj=0; cj<=3; cj++) { tbl[p,4+ci*4+cj] = tbl[p,4+ci*4+cj]*Math.Pow(dt, ci)*Math.Pow(du, cj); } } } } }
/************************************************************************* This subroutine was deprecated in ALGLIB 3.6.0 We recommend you to switch to Spline2DBuildBilinearV(), which is more flexible and accepts its arguments in more convenient order. -- ALGLIB PROJECT -- Copyright 05.07.2007 by Bochkanov Sergey *************************************************************************/ public static void spline2dbuildbilinear(double[] x, double[] y, double[,] f, int m, int n, spline2dinterpolant c) { double t = 0; int i = 0; int j = 0; int k = 0; alglib.ap.assert(n>=2, "Spline2DBuildBilinear: N<2"); alglib.ap.assert(m>=2, "Spline2DBuildBilinear: M<2"); alglib.ap.assert(alglib.ap.len(x)>=n && alglib.ap.len(y)>=m, "Spline2DBuildBilinear: length of X or Y is too short (Length(X/Y)<N/M)"); alglib.ap.assert(apserv.isfinitevector(x, n) && apserv.isfinitevector(y, m), "Spline2DBuildBilinear: X or Y contains NaN or Infinite value"); alglib.ap.assert(alglib.ap.rows(f)>=m && alglib.ap.cols(f)>=n, "Spline2DBuildBilinear: size of F is too small (rows(F)<M or cols(F)<N)"); alglib.ap.assert(apserv.apservisfinitematrix(f, m, n), "Spline2DBuildBilinear: F contains NaN or Infinite value"); // // Fill interpolant // c.k = 1; c.n = n; c.m = m; c.d = 1; c.stype = -1; c.x = new double[c.n]; c.y = new double[c.m]; c.f = new double[c.n*c.m]; for(i=0; i<=c.n-1; i++) { c.x[i] = x[i]; } for(i=0; i<=c.m-1; i++) { c.y[i] = y[i]; } for(i=0; i<=c.m-1; i++) { for(j=0; j<=c.n-1; j++) { c.f[i*c.n+j] = f[i,j]; } } // // Sort points // for(j=0; j<=c.n-1; j++) { k = j; for(i=j+1; i<=c.n-1; i++) { if( (double)(c.x[i])<(double)(c.x[k]) ) { k = i; } } if( k!=j ) { for(i=0; i<=c.m-1; i++) { t = c.f[i*c.n+j]; c.f[i*c.n+j] = c.f[i*c.n+k]; c.f[i*c.n+k] = t; } t = c.x[j]; c.x[j] = c.x[k]; c.x[k] = t; } } for(i=0; i<=c.m-1; i++) { k = i; for(j=i+1; j<=c.m-1; j++) { if( (double)(c.y[j])<(double)(c.y[k]) ) { k = j; } } if( k!=i ) { for(j=0; j<=c.n-1; j++) { t = c.f[i*c.n+j]; c.f[i*c.n+j] = c.f[k*c.n+j]; c.f[k*c.n+j] = t; } t = c.y[i]; c.y[i] = c.y[k]; c.y[k] = t; } } }
public override alglib.apobject make_copy() { spline2dinterpolant _result = new spline2dinterpolant(); _result.k = k; _result.stype = stype; _result.n = n; _result.m = m; _result.d = d; _result.x = (double[])x.Clone(); _result.y = (double[])y.Clone(); _result.f = (double[])f.Clone(); return _result; }
/************************************************************************* This subroutine makes the copy of the spline model. Input parameters: C - spline interpolant Output parameters: CC - spline copy -- ALGLIB PROJECT -- Copyright 29.06.2007 by Bochkanov Sergey *************************************************************************/ public static void spline2dcopy(spline2dinterpolant c, spline2dinterpolant cc) { int n = 0; int i_ = 0; ap.assert(c.k == 1 | c.k == 3, "Spline2DCopy: incorrect C!"); cc.k = c.k; n = (int)Math.Round(c.c[0]); cc.c = new double[n]; for(i_ = 0; i_ <= n - 1; i_++) { cc.c[i_] = c.c[i_]; } }
/************************************************************************* This subroutine performs linear transformation of the spline. Input parameters: C - spline interpolant. A, B- transformation coefficients: S2(x,y) = A*S(x,y) + B Output parameters: C - transformed spline -- ALGLIB PROJECT -- Copyright 30.06.2007 by Bochkanov Sergey *************************************************************************/ public static void spline2dlintransf(spline2dinterpolant c, double a, double b) { int i = 0; int j = 0; int n = 0; int m = 0; double[] x = new double[0]; double[] y = new double[0]; double[,] f = new double[0, 0]; int typec = 0; typec = (int)Math.Round(c.c[1]); ap.assert(typec == -3 | typec == -1, "Spline2DLinTransXY: incorrect C!"); n = (int)Math.Round(c.c[2]); m = (int)Math.Round(c.c[3]); x = new double[n - 1 + 1]; y = new double[m - 1 + 1]; f = new double[m - 1 + 1, n - 1 + 1]; for(j = 0; j <= n - 1; j++) { x[j] = c.c[4 + j]; } for(i = 0; i <= m - 1; i++) { y[i] = c.c[4 + n + i]; } for(i = 0; i <= m - 1; i++) { for(j = 0; j <= n - 1; j++) { f[i, j] = a * c.c[4 + n + m + i * n + j] + b; } } if(typec == -3) { spline2dbuildbicubic(x, y, f, m, n, c); } if(typec == -1) { spline2dbuildbilinear(x, y, f, m, n, c); } }
/************************************************************************* This subroutine performs linear transformation of the spline argument. Input parameters: C - spline interpolant AX, BX - transformation coefficients: x = A*t + B AY, BY - transformation coefficients: y = A*u + B Result: C - transformed spline -- ALGLIB PROJECT -- Copyright 30.06.2007 by Bochkanov Sergey *************************************************************************/ public static void spline2dlintransxy(spline2dinterpolant c, double ax, double bx, double ay, double by) { int i = 0; int j = 0; int n = 0; int m = 0; double v = 0; double[] x = new double[0]; double[] y = new double[0]; double[,] f = new double[0, 0]; int typec = 0; typec = (int)Math.Round(c.c[1]); ap.assert(typec == -3 | typec == -1, "Spline2DLinTransXY: incorrect C!"); n = (int)Math.Round(c.c[2]); m = (int)Math.Round(c.c[3]); x = new double[n - 1 + 1]; y = new double[m - 1 + 1]; f = new double[m - 1 + 1, n - 1 + 1]; for(j = 0; j <= n - 1; j++) { x[j] = c.c[4 + j]; } for(i = 0; i <= m - 1; i++) { y[i] = c.c[4 + n + i]; } for(i = 0; i <= m - 1; i++) { for(j = 0; j <= n - 1; j++) { f[i, j] = c.c[4 + n + m + i * n + j]; } } // // Special case: AX=0 or AY=0 // if((double)(ax) == (double)(0)) { for(i = 0; i <= m - 1; i++) { v = spline2dcalc(c, bx, y[i]); for(j = 0; j <= n - 1; j++) { f[i, j] = v; } } if(typec == -3) { spline2dbuildbicubic(x, y, f, m, n, c); } if(typec == -1) { spline2dbuildbilinear(x, y, f, m, n, c); } ax = 1; bx = 0; } if((double)(ay) == (double)(0)) { for(j = 0; j <= n - 1; j++) { v = spline2dcalc(c, x[j], by); for(i = 0; i <= m - 1; i++) { f[i, j] = v; } } if(typec == -3) { spline2dbuildbicubic(x, y, f, m, n, c); } if(typec == -1) { spline2dbuildbilinear(x, y, f, m, n, c); } ay = 1; by = 0; } // // General case: AX<>0, AY<>0 // Unpack, scale and pack again. // for(j = 0; j <= n - 1; j++) { x[j] = (x[j] - bx) / ax; } for(i = 0; i <= m - 1; i++) { y[i] = (y[i] - by) / ay; } if(typec == -3) { spline2dbuildbicubic(x, y, f, m, n, c); } if(typec == -1) { spline2dbuildbilinear(x, y, f, m, n, c); } }
/************************************************************************* This subroutine unpacks two-dimensional spline into the coefficients table Input parameters: C - spline interpolant. Result: M, N- grid size (x-axis and y-axis) Tbl - coefficients table, unpacked format, [0..(N-1)*(M-1)-1, 0..19]. For I = 0...M-2, J=0..N-2: K = I*(N-1)+J Tbl[K,0] = X[j] Tbl[K,1] = X[j+1] Tbl[K,2] = Y[i] Tbl[K,3] = Y[i+1] Tbl[K,4] = C00 Tbl[K,5] = C01 Tbl[K,6] = C02 Tbl[K,7] = C03 Tbl[K,8] = C10 Tbl[K,9] = C11 ... Tbl[K,19] = C33 On each grid square spline is equals to: S(x) = SUM(c[i,j]*(x^i)*(y^j), i=0..3, j=0..3) t = x-x[j] u = y-y[i] -- ALGLIB PROJECT -- Copyright 29.06.2007 by Bochkanov Sergey *************************************************************************/ public static void spline2dunpack(spline2dinterpolant c, ref int m, ref int n, ref double[,] tbl) { int i = 0; int j = 0; int ci = 0; int cj = 0; int k = 0; int p = 0; int shift = 0; int s1 = 0; int s2 = 0; int s3 = 0; int s4 = 0; int sf = 0; int sfx = 0; int sfy = 0; int sfxy = 0; double y1 = 0; double y2 = 0; double y3 = 0; double y4 = 0; double dt = 0; double du = 0; m = 0; n = 0; tbl = new double[0, 0]; ap.assert((int)Math.Round(c.c[1]) == -3 | (int)Math.Round(c.c[1]) == -1, "SplineUnpack2D: incorrect C!"); n = (int)Math.Round(c.c[2]); m = (int)Math.Round(c.c[3]); tbl = new double[(n - 1) * (m - 1) - 1 + 1, 19 + 1]; // // Fill // for(i = 0; i <= m - 2; i++) { for(j = 0; j <= n - 2; j++) { p = i * (n - 1) + j; tbl[p, 0] = c.c[4 + j]; tbl[p, 1] = c.c[4 + j + 1]; tbl[p, 2] = c.c[4 + n + i]; tbl[p, 3] = c.c[4 + n + i + 1]; dt = 1 / (tbl[p, 1] - tbl[p, 0]); du = 1 / (tbl[p, 3] - tbl[p, 2]); // // Bilinear interpolation // if((int)Math.Round(c.c[1]) == -1) { for(k = 4; k <= 19; k++) { tbl[p, k] = 0; } shift = 4 + n + m; y1 = c.c[shift + n * i + j]; y2 = c.c[shift + n * i + (j + 1)]; y3 = c.c[shift + n * (i + 1) + (j + 1)]; y4 = c.c[shift + n * (i + 1) + j]; tbl[p, 4] = y1; tbl[p, 4 + 1 * 4 + 0] = y2 - y1; tbl[p, 4 + 0 * 4 + 1] = y4 - y1; tbl[p, 4 + 1 * 4 + 1] = y3 - y2 - y4 + y1; } // // Bicubic interpolation // if((int)Math.Round(c.c[1]) == -3) { sf = 4 + n + m; sfx = 4 + n + m + n * m; sfy = 4 + n + m + 2 * n * m; sfxy = 4 + n + m + 3 * n * m; s1 = n * i + j; s2 = n * i + (j + 1); s3 = n * (i + 1) + (j + 1); s4 = n * (i + 1) + j; tbl[p, 4 + 0 * 4 + 0] = 1 * c.c[sf + s1]; tbl[p, 4 + 0 * 4 + 1] = 1 * c.c[sfy + s1] / du; tbl[p, 4 + 0 * 4 + 2] = -(3 * c.c[sf + s1]) + 3 * c.c[sf + s4] - 2 * c.c[sfy + s1] / du - 1 * c.c[sfy + s4] / du; tbl[p, 4 + 0 * 4 + 3] = 2 * c.c[sf + s1] - 2 * c.c[sf + s4] + 1 * c.c[sfy + s1] / du + 1 * c.c[sfy + s4] / du; tbl[p, 4 + 1 * 4 + 0] = 1 * c.c[sfx + s1] / dt; tbl[p, 4 + 1 * 4 + 1] = 1 * c.c[sfxy + s1] / (dt * du); tbl[p, 4 + 1 * 4 + 2] = -(3 * c.c[sfx + s1] / dt) + 3 * c.c[sfx + s4] / dt - 2 * c.c[sfxy + s1] / (dt * du) - 1 * c.c[sfxy + s4] / (dt * du); tbl[p, 4 + 1 * 4 + 3] = 2 * c.c[sfx + s1] / dt - 2 * c.c[sfx + s4] / dt + 1 * c.c[sfxy + s1] / (dt * du) + 1 * c.c[sfxy + s4] / (dt * du); tbl[p, 4 + 2 * 4 + 0] = -(3 * c.c[sf + s1]) + 3 * c.c[sf + s2] - 2 * c.c[sfx + s1] / dt - 1 * c.c[sfx + s2] / dt; tbl[p, 4 + 2 * 4 + 1] = -(3 * c.c[sfy + s1] / du) + 3 * c.c[sfy + s2] / du - 2 * c.c[sfxy + s1] / (dt * du) - 1 * c.c[sfxy + s2] / (dt * du); tbl[p, 4 + 2 * 4 + 2] = 9 * c.c[sf + s1] - 9 * c.c[sf + s2] + 9 * c.c[sf + s3] - 9 * c.c[sf + s4] + 6 * c.c[sfx + s1] / dt + 3 * c.c[sfx + s2] / dt - 3 * c.c[sfx + s3] / dt - 6 * c.c[sfx + s4] / dt + 6 * c.c[sfy + s1] / du - 6 * c.c[sfy + s2] / du - 3 * c.c[sfy + s3] / du + 3 * c.c[sfy + s4] / du + 4 * c.c[sfxy + s1] / (dt * du) + 2 * c.c[sfxy + s2] / (dt * du) + 1 * c.c[sfxy + s3] / (dt * du) + 2 * c.c[sfxy + s4] / (dt * du); tbl[p, 4 + 2 * 4 + 3] = -(6 * c.c[sf + s1]) + 6 * c.c[sf + s2] - 6 * c.c[sf + s3] + 6 * c.c[sf + s4] - 4 * c.c[sfx + s1] / dt - 2 * c.c[sfx + s2] / dt + 2 * c.c[sfx + s3] / dt + 4 * c.c[sfx + s4] / dt - 3 * c.c[sfy + s1] / du + 3 * c.c[sfy + s2] / du + 3 * c.c[sfy + s3] / du - 3 * c.c[sfy + s4] / du - 2 * c.c[sfxy + s1] / (dt * du) - 1 * c.c[sfxy + s2] / (dt * du) - 1 * c.c[sfxy + s3] / (dt * du) - 2 * c.c[sfxy + s4] / (dt * du); tbl[p, 4 + 3 * 4 + 0] = 2 * c.c[sf + s1] - 2 * c.c[sf + s2] + 1 * c.c[sfx + s1] / dt + 1 * c.c[sfx + s2] / dt; tbl[p, 4 + 3 * 4 + 1] = 2 * c.c[sfy + s1] / du - 2 * c.c[sfy + s2] / du + 1 * c.c[sfxy + s1] / (dt * du) + 1 * c.c[sfxy + s2] / (dt * du); tbl[p, 4 + 3 * 4 + 2] = -(6 * c.c[sf + s1]) + 6 * c.c[sf + s2] - 6 * c.c[sf + s3] + 6 * c.c[sf + s4] - 3 * c.c[sfx + s1] / dt - 3 * c.c[sfx + s2] / dt + 3 * c.c[sfx + s3] / dt + 3 * c.c[sfx + s4] / dt - 4 * c.c[sfy + s1] / du + 4 * c.c[sfy + s2] / du + 2 * c.c[sfy + s3] / du - 2 * c.c[sfy + s4] / du - 2 * c.c[sfxy + s1] / (dt * du) - 2 * c.c[sfxy + s2] / (dt * du) - 1 * c.c[sfxy + s3] / (dt * du) - 1 * c.c[sfxy + s4] / (dt * du); tbl[p, 4 + 3 * 4 + 3] = 4 * c.c[sf + s1] - 4 * c.c[sf + s2] + 4 * c.c[sf + s3] - 4 * c.c[sf + s4] + 2 * c.c[sfx + s1] / dt + 2 * c.c[sfx + s2] / dt - 2 * c.c[sfx + s3] / dt - 2 * c.c[sfx + s4] / dt + 2 * c.c[sfy + s1] / du - 2 * c.c[sfy + s2] / du - 2 * c.c[sfy + s3] / du + 2 * c.c[sfy + s4] / du + 1 * c.c[sfxy + s1] / (dt * du) + 1 * c.c[sfxy + s2] / (dt * du) + 1 * c.c[sfxy + s3] / (dt * du) + 1 * c.c[sfxy + s4] / (dt * du); } // // Rescale Cij // for(ci = 0; ci <= 3; ci++) { for(cj = 0; cj <= 3; cj++) { tbl[p, 4 + ci * 4 + cj] = tbl[p, 4 + ci * 4 + cj] * Math.Pow(dt, ci) * Math.Pow(du, cj); } } } } }
/************************************************************************* This subroutine calculates the value of the bilinear or bicubic spline at the given point X and its derivatives. Input parameters: C - spline interpolant. X, Y- point Output parameters: F - S(x,y) FX - dS(x,y)/dX FY - dS(x,y)/dY FXY - d2S(x,y)/dXdY -- ALGLIB PROJECT -- Copyright 05.07.2007 by Bochkanov Sergey *************************************************************************/ public static void spline2ddiff(spline2dinterpolant c, double x, double y, ref double f, ref double fx, ref double fy, ref double fxy) { int n = 0; int m = 0; double t = 0; double dt = 0; double u = 0; double du = 0; int ix = 0; int iy = 0; int l = 0; int r = 0; int h = 0; int shift1 = 0; int s1 = 0; int s2 = 0; int s3 = 0; int s4 = 0; int sf = 0; int sfx = 0; int sfy = 0; int sfxy = 0; double y1 = 0; double y2 = 0; double y3 = 0; double y4 = 0; double v = 0; double t0 = 0; double t1 = 0; double t2 = 0; double t3 = 0; double u0 = 0; double u1 = 0; double u2 = 0; double u3 = 0; f = 0; fx = 0; fy = 0; fxy = 0; ap.assert((int)Math.Round(c.c[1]) == -1 | (int)Math.Round(c.c[1]) == -3, "Spline2DDiff: incorrect C!"); n = (int)Math.Round(c.c[2]); m = (int)Math.Round(c.c[3]); // // Binary search in the [ x[0], ..., x[n-2] ] (x[n-1] is not included) // l = 4; r = 4 + n - 2 + 1; while(l != r - 1) { h = (l + r) / 2; if((double)(c.c[h]) >= (double)(x)) { r = h; } else { l = h; } } t = (x - c.c[l]) / (c.c[l + 1] - c.c[l]); dt = 1.0 / (c.c[l + 1] - c.c[l]); ix = l - 4; // // Binary search in the [ y[0], ..., y[m-2] ] (y[m-1] is not included) // l = 4 + n; r = 4 + n + (m - 2) + 1; while(l != r - 1) { h = (l + r) / 2; if((double)(c.c[h]) >= (double)(y)) { r = h; } else { l = h; } } u = (y - c.c[l]) / (c.c[l + 1] - c.c[l]); du = 1.0 / (c.c[l + 1] - c.c[l]); iy = l - (4 + n); // // Prepare F, dF/dX, dF/dY, d2F/dXdY // f = 0; fx = 0; fy = 0; fxy = 0; // // Bilinear interpolation // if((int)Math.Round(c.c[1]) == -1) { shift1 = 4 + n + m; y1 = c.c[shift1 + n * iy + ix]; y2 = c.c[shift1 + n * iy + (ix + 1)]; y3 = c.c[shift1 + n * (iy + 1) + (ix + 1)]; y4 = c.c[shift1 + n * (iy + 1) + ix]; f = (1 - t) * (1 - u) * y1 + t * (1 - u) * y2 + t * u * y3 + (1 - t) * u * y4; fx = (-((1 - u) * y1) + (1 - u) * y2 + u * y3 - u * y4) * dt; fy = (-((1 - t) * y1) - t * y2 + t * y3 + (1 - t) * y4) * du; fxy = (y1 - y2 + y3 - y4) * du * dt; return; } // // Bicubic interpolation // if((int)Math.Round(c.c[1]) == -3) { // // Prepare info // t0 = 1; t1 = t; t2 = math.sqr(t); t3 = t * t2; u0 = 1; u1 = u; u2 = math.sqr(u); u3 = u * u2; sf = 4 + n + m; sfx = 4 + n + m + n * m; sfy = 4 + n + m + 2 * n * m; sfxy = 4 + n + m + 3 * n * m; s1 = n * iy + ix; s2 = n * iy + (ix + 1); s3 = n * (iy + 1) + (ix + 1); s4 = n * (iy + 1) + ix; // // Calculate // v = 1 * c.c[sf + s1]; f = f + v * t0 * u0; v = 1 * c.c[sfy + s1] / du; f = f + v * t0 * u1; fy = fy + 1 * v * t0 * u0 * du; v = -(3 * c.c[sf + s1]) + 3 * c.c[sf + s4] - 2 * c.c[sfy + s1] / du - 1 * c.c[sfy + s4] / du; f = f + v * t0 * u2; fy = fy + 2 * v * t0 * u1 * du; v = 2 * c.c[sf + s1] - 2 * c.c[sf + s4] + 1 * c.c[sfy + s1] / du + 1 * c.c[sfy + s4] / du; f = f + v * t0 * u3; fy = fy + 3 * v * t0 * u2 * du; v = 1 * c.c[sfx + s1] / dt; f = f + v * t1 * u0; fx = fx + 1 * v * t0 * u0 * dt; v = 1 * c.c[sfxy + s1] / (dt * du); f = f + v * t1 * u1; fx = fx + 1 * v * t0 * u1 * dt; fy = fy + 1 * v * t1 * u0 * du; fxy = fxy + 1 * v * t0 * u0 * dt * du; v = -(3 * c.c[sfx + s1] / dt) + 3 * c.c[sfx + s4] / dt - 2 * c.c[sfxy + s1] / (dt * du) - 1 * c.c[sfxy + s4] / (dt * du); f = f + v * t1 * u2; fx = fx + 1 * v * t0 * u2 * dt; fy = fy + 2 * v * t1 * u1 * du; fxy = fxy + 2 * v * t0 * u1 * dt * du; v = 2 * c.c[sfx + s1] / dt - 2 * c.c[sfx + s4] / dt + 1 * c.c[sfxy + s1] / (dt * du) + 1 * c.c[sfxy + s4] / (dt * du); f = f + v * t1 * u3; fx = fx + 1 * v * t0 * u3 * dt; fy = fy + 3 * v * t1 * u2 * du; fxy = fxy + 3 * v * t0 * u2 * dt * du; v = -(3 * c.c[sf + s1]) + 3 * c.c[sf + s2] - 2 * c.c[sfx + s1] / dt - 1 * c.c[sfx + s2] / dt; f = f + v * t2 * u0; fx = fx + 2 * v * t1 * u0 * dt; v = -(3 * c.c[sfy + s1] / du) + 3 * c.c[sfy + s2] / du - 2 * c.c[sfxy + s1] / (dt * du) - 1 * c.c[sfxy + s2] / (dt * du); f = f + v * t2 * u1; fx = fx + 2 * v * t1 * u1 * dt; fy = fy + 1 * v * t2 * u0 * du; fxy = fxy + 2 * v * t1 * u0 * dt * du; v = 9 * c.c[sf + s1] - 9 * c.c[sf + s2] + 9 * c.c[sf + s3] - 9 * c.c[sf + s4] + 6 * c.c[sfx + s1] / dt + 3 * c.c[sfx + s2] / dt - 3 * c.c[sfx + s3] / dt - 6 * c.c[sfx + s4] / dt + 6 * c.c[sfy + s1] / du - 6 * c.c[sfy + s2] / du - 3 * c.c[sfy + s3] / du + 3 * c.c[sfy + s4] / du + 4 * c.c[sfxy + s1] / (dt * du) + 2 * c.c[sfxy + s2] / (dt * du) + 1 * c.c[sfxy + s3] / (dt * du) + 2 * c.c[sfxy + s4] / (dt * du); f = f + v * t2 * u2; fx = fx + 2 * v * t1 * u2 * dt; fy = fy + 2 * v * t2 * u1 * du; fxy = fxy + 4 * v * t1 * u1 * dt * du; v = -(6 * c.c[sf + s1]) + 6 * c.c[sf + s2] - 6 * c.c[sf + s3] + 6 * c.c[sf + s4] - 4 * c.c[sfx + s1] / dt - 2 * c.c[sfx + s2] / dt + 2 * c.c[sfx + s3] / dt + 4 * c.c[sfx + s4] / dt - 3 * c.c[sfy + s1] / du + 3 * c.c[sfy + s2] / du + 3 * c.c[sfy + s3] / du - 3 * c.c[sfy + s4] / du - 2 * c.c[sfxy + s1] / (dt * du) - 1 * c.c[sfxy + s2] / (dt * du) - 1 * c.c[sfxy + s3] / (dt * du) - 2 * c.c[sfxy + s4] / (dt * du); f = f + v * t2 * u3; fx = fx + 2 * v * t1 * u3 * dt; fy = fy + 3 * v * t2 * u2 * du; fxy = fxy + 6 * v * t1 * u2 * dt * du; v = 2 * c.c[sf + s1] - 2 * c.c[sf + s2] + 1 * c.c[sfx + s1] / dt + 1 * c.c[sfx + s2] / dt; f = f + v * t3 * u0; fx = fx + 3 * v * t2 * u0 * dt; v = 2 * c.c[sfy + s1] / du - 2 * c.c[sfy + s2] / du + 1 * c.c[sfxy + s1] / (dt * du) + 1 * c.c[sfxy + s2] / (dt * du); f = f + v * t3 * u1; fx = fx + 3 * v * t2 * u1 * dt; fy = fy + 1 * v * t3 * u0 * du; fxy = fxy + 3 * v * t2 * u0 * dt * du; v = -(6 * c.c[sf + s1]) + 6 * c.c[sf + s2] - 6 * c.c[sf + s3] + 6 * c.c[sf + s4] - 3 * c.c[sfx + s1] / dt - 3 * c.c[sfx + s2] / dt + 3 * c.c[sfx + s3] / dt + 3 * c.c[sfx + s4] / dt - 4 * c.c[sfy + s1] / du + 4 * c.c[sfy + s2] / du + 2 * c.c[sfy + s3] / du - 2 * c.c[sfy + s4] / du - 2 * c.c[sfxy + s1] / (dt * du) - 2 * c.c[sfxy + s2] / (dt * du) - 1 * c.c[sfxy + s3] / (dt * du) - 1 * c.c[sfxy + s4] / (dt * du); f = f + v * t3 * u2; fx = fx + 3 * v * t2 * u2 * dt; fy = fy + 2 * v * t3 * u1 * du; fxy = fxy + 6 * v * t2 * u1 * dt * du; v = 4 * c.c[sf + s1] - 4 * c.c[sf + s2] + 4 * c.c[sf + s3] - 4 * c.c[sf + s4] + 2 * c.c[sfx + s1] / dt + 2 * c.c[sfx + s2] / dt - 2 * c.c[sfx + s3] / dt - 2 * c.c[sfx + s4] / dt + 2 * c.c[sfy + s1] / du - 2 * c.c[sfy + s2] / du - 2 * c.c[sfy + s3] / du + 2 * c.c[sfy + s4] / du + 1 * c.c[sfxy + s1] / (dt * du) + 1 * c.c[sfxy + s2] / (dt * du) + 1 * c.c[sfxy + s3] / (dt * du) + 1 * c.c[sfxy + s4] / (dt * du); f = f + v * t3 * u3; fx = fx + 3 * v * t2 * u3 * dt; fy = fy + 3 * v * t3 * u2 * du; fxy = fxy + 9 * v * t2 * u2 * dt * du; return; } }
/************************************************************************* This subroutine calculates the value of the bilinear or bicubic spline at the given point X. Input parameters: C - coefficients table. Built by BuildBilinearSpline or BuildBicubicSpline. X, Y- point Result: S(x,y) -- ALGLIB PROJECT -- Copyright 05.07.2007 by Bochkanov Sergey *************************************************************************/ public static double spline2dcalc(spline2dinterpolant c, double x, double y) { double result = 0; double v = 0; double vx = 0; double vy = 0; double vxy = 0; spline2ddiff(c, x, y, ref v, ref vx, ref vy, ref vxy); result = v; return result; }
/************************************************************************* This subroutine calculates bilinear or bicubic vector-valued spline at the given point (X,Y). INPUT PARAMETERS: C - spline interpolant. X, Y- point F - output buffer, possibly preallocated array. In case array size is large enough to store result, it is not reallocated. Array which is too short will be reallocated OUTPUT PARAMETERS: F - array[D] (or larger) which stores function values -- ALGLIB PROJECT -- Copyright 16.04.2012 by Bochkanov Sergey *************************************************************************/ public static void spline2dcalcvbuf(spline2dinterpolant c, double x, double y, ref double[] f) { double t = 0; double dt = 0; double u = 0; double du = 0; int ix = 0; int iy = 0; int l = 0; int r = 0; int h = 0; int s1 = 0; int s2 = 0; int s3 = 0; int s4 = 0; int sfx = 0; int sfy = 0; int sfxy = 0; double y1 = 0; double y2 = 0; double y3 = 0; double y4 = 0; double v = 0; double t0 = 0; double t1 = 0; double t2 = 0; double t3 = 0; double u0 = 0; double u1 = 0; double u2 = 0; double u3 = 0; int i = 0; alglib.ap.assert(c.stype==-1 || c.stype==-3, "Spline2DCalcVBuf: incorrect C (incorrect parameter C.SType)"); alglib.ap.assert(math.isfinite(x) && math.isfinite(y), "Spline2DCalcVBuf: either X=NaN/Infinite or Y=NaN/Infinite"); apserv.rvectorsetlengthatleast(ref f, c.d); // // Binary search in the [ x[0], ..., x[n-2] ] (x[n-1] is not included) // l = 0; r = c.n-1; while( l!=r-1 ) { h = (l+r)/2; if( (double)(c.x[h])>=(double)(x) ) { r = h; } else { l = h; } } t = (x-c.x[l])/(c.x[l+1]-c.x[l]); dt = 1.0/(c.x[l+1]-c.x[l]); ix = l; // // Binary search in the [ y[0], ..., y[m-2] ] (y[m-1] is not included) // l = 0; r = c.m-1; while( l!=r-1 ) { h = (l+r)/2; if( (double)(c.y[h])>=(double)(y) ) { r = h; } else { l = h; } } u = (y-c.y[l])/(c.y[l+1]-c.y[l]); du = 1.0/(c.y[l+1]-c.y[l]); iy = l; // // Bilinear interpolation // if( c.stype==-1 ) { for(i=0; i<=c.d-1; i++) { y1 = c.f[c.d*(c.n*iy+ix)+i]; y2 = c.f[c.d*(c.n*iy+(ix+1))+i]; y3 = c.f[c.d*(c.n*(iy+1)+(ix+1))+i]; y4 = c.f[c.d*(c.n*(iy+1)+ix)+i]; f[i] = (1-t)*(1-u)*y1+t*(1-u)*y2+t*u*y3+(1-t)*u*y4; } return; } // // Bicubic interpolation // if( c.stype==-3 ) { // // Prepare info // t0 = 1; t1 = t; t2 = math.sqr(t); t3 = t*t2; u0 = 1; u1 = u; u2 = math.sqr(u); u3 = u*u2; sfx = c.n*c.m*c.d; sfy = 2*c.n*c.m*c.d; sfxy = 3*c.n*c.m*c.d; for(i=0; i<=c.d-1; i++) { // // Prepare F, dF/dX, dF/dY, d2F/dXdY // f[i] = 0; s1 = c.d*(c.n*iy+ix)+i; s2 = c.d*(c.n*iy+(ix+1))+i; s3 = c.d*(c.n*(iy+1)+(ix+1))+i; s4 = c.d*(c.n*(iy+1)+ix)+i; // // Calculate // v = c.f[s1]; f[i] = f[i]+v*t0*u0; v = c.f[sfy+s1]/du; f[i] = f[i]+v*t0*u1; v = -(3*c.f[s1])+3*c.f[s4]-2*c.f[sfy+s1]/du-c.f[sfy+s4]/du; f[i] = f[i]+v*t0*u2; v = 2*c.f[s1]-2*c.f[s4]+c.f[sfy+s1]/du+c.f[sfy+s4]/du; f[i] = f[i]+v*t0*u3; v = c.f[sfx+s1]/dt; f[i] = f[i]+v*t1*u0; v = c.f[sfxy+s1]/(dt*du); f[i] = f[i]+v*t1*u1; v = -(3*c.f[sfx+s1]/dt)+3*c.f[sfx+s4]/dt-2*c.f[sfxy+s1]/(dt*du)-c.f[sfxy+s4]/(dt*du); f[i] = f[i]+v*t1*u2; v = 2*c.f[sfx+s1]/dt-2*c.f[sfx+s4]/dt+c.f[sfxy+s1]/(dt*du)+c.f[sfxy+s4]/(dt*du); f[i] = f[i]+v*t1*u3; v = -(3*c.f[s1])+3*c.f[s2]-2*c.f[sfx+s1]/dt-c.f[sfx+s2]/dt; f[i] = f[i]+v*t2*u0; v = -(3*c.f[sfy+s1]/du)+3*c.f[sfy+s2]/du-2*c.f[sfxy+s1]/(dt*du)-c.f[sfxy+s2]/(dt*du); f[i] = f[i]+v*t2*u1; v = 9*c.f[s1]-9*c.f[s2]+9*c.f[s3]-9*c.f[s4]+6*c.f[sfx+s1]/dt+3*c.f[sfx+s2]/dt-3*c.f[sfx+s3]/dt-6*c.f[sfx+s4]/dt+6*c.f[sfy+s1]/du-6*c.f[sfy+s2]/du-3*c.f[sfy+s3]/du+3*c.f[sfy+s4]/du+4*c.f[sfxy+s1]/(dt*du)+2*c.f[sfxy+s2]/(dt*du)+c.f[sfxy+s3]/(dt*du)+2*c.f[sfxy+s4]/(dt*du); f[i] = f[i]+v*t2*u2; v = -(6*c.f[s1])+6*c.f[s2]-6*c.f[s3]+6*c.f[s4]-4*c.f[sfx+s1]/dt-2*c.f[sfx+s2]/dt+2*c.f[sfx+s3]/dt+4*c.f[sfx+s4]/dt-3*c.f[sfy+s1]/du+3*c.f[sfy+s2]/du+3*c.f[sfy+s3]/du-3*c.f[sfy+s4]/du-2*c.f[sfxy+s1]/(dt*du)-c.f[sfxy+s2]/(dt*du)-c.f[sfxy+s3]/(dt*du)-2*c.f[sfxy+s4]/(dt*du); f[i] = f[i]+v*t2*u3; v = 2*c.f[s1]-2*c.f[s2]+c.f[sfx+s1]/dt+c.f[sfx+s2]/dt; f[i] = f[i]+v*t3*u0; v = 2*c.f[sfy+s1]/du-2*c.f[sfy+s2]/du+c.f[sfxy+s1]/(dt*du)+c.f[sfxy+s2]/(dt*du); f[i] = f[i]+v*t3*u1; v = -(6*c.f[s1])+6*c.f[s2]-6*c.f[s3]+6*c.f[s4]-3*c.f[sfx+s1]/dt-3*c.f[sfx+s2]/dt+3*c.f[sfx+s3]/dt+3*c.f[sfx+s4]/dt-4*c.f[sfy+s1]/du+4*c.f[sfy+s2]/du+2*c.f[sfy+s3]/du-2*c.f[sfy+s4]/du-2*c.f[sfxy+s1]/(dt*du)-2*c.f[sfxy+s2]/(dt*du)-c.f[sfxy+s3]/(dt*du)-c.f[sfxy+s4]/(dt*du); f[i] = f[i]+v*t3*u2; v = 4*c.f[s1]-4*c.f[s2]+4*c.f[s3]-4*c.f[s4]+2*c.f[sfx+s1]/dt+2*c.f[sfx+s2]/dt-2*c.f[sfx+s3]/dt-2*c.f[sfx+s4]/dt+2*c.f[sfy+s1]/du-2*c.f[sfy+s2]/du-2*c.f[sfy+s3]/du+2*c.f[sfy+s4]/du+c.f[sfxy+s1]/(dt*du)+c.f[sfxy+s2]/(dt*du)+c.f[sfxy+s3]/(dt*du)+c.f[sfxy+s4]/(dt*du); f[i] = f[i]+v*t3*u3; } return; } }
/************************************************************************* This subroutine calculates bilinear or bicubic vector-valued spline at the given point (X,Y). INPUT PARAMETERS: C - spline interpolant. X, Y- point OUTPUT PARAMETERS: F - array[D] which stores function values. F is out-parameter and it is reallocated after call to this function. In case you want to reuse previously allocated F, you may use Spline2DCalcVBuf(), which reallocates F only when it is too small. -- ALGLIB PROJECT -- Copyright 16.04.2012 by Bochkanov Sergey *************************************************************************/ public static void spline2dcalcv(spline2dinterpolant c, double x, double y, ref double[] f) { f = new double[0]; alglib.ap.assert(c.stype==-1 || c.stype==-3, "Spline2DCalcV: incorrect C (incorrect parameter C.SType)"); alglib.ap.assert(math.isfinite(x) && math.isfinite(y), "Spline2DCalcV: either X=NaN/Infinite or Y=NaN/Infinite"); f = new double[c.d]; spline2dcalcvbuf(c, x, y, ref f); }
/************************************************************************* This subroutine calculates the value of the bilinear or bicubic spline at the given point X. Input parameters: C - coefficients table. Built by BuildBilinearSpline or BuildBicubicSpline. X, Y- point Result: S(x,y) -- ALGLIB PROJECT -- Copyright 05.07.2007 by Bochkanov Sergey *************************************************************************/ public static double spline2dcalc(spline2dinterpolant c, double x, double y) { double result = 0; double v = 0; double vx = 0; double vy = 0; double vxy = 0; alglib.ap.assert(c.stype==-1 || c.stype==-3, "Spline2DCalc: incorrect C (incorrect parameter C.SType)"); alglib.ap.assert(math.isfinite(x) && math.isfinite(y), "Spline2DCalc: X or Y contains NaN or Infinite value"); if( c.d!=1 ) { result = 0; return result; } spline2ddiff(c, x, y, ref v, ref vx, ref vy, ref vxy); result = v; return result; }
/************************************************************************* This subroutine was deprecated in ALGLIB 3.6.0 We recommend you to switch to Spline2DBuildBicubicV(), which is more flexible and accepts its arguments in more convenient order. -- ALGLIB PROJECT -- Copyright 05.07.2007 by Bochkanov Sergey *************************************************************************/ public static void spline2dbuildbicubic(double[] x, double[] y, double[,] f, int m, int n, spline2dinterpolant c) { int sfx = 0; int sfy = 0; int sfxy = 0; double[,] dx = new double[0,0]; double[,] dy = new double[0,0]; double[,] dxy = new double[0,0]; double t = 0; int i = 0; int j = 0; int k = 0; f = (double[,])f.Clone(); alglib.ap.assert(n>=2, "Spline2DBuildBicubicSpline: N<2"); alglib.ap.assert(m>=2, "Spline2DBuildBicubicSpline: M<2"); alglib.ap.assert(alglib.ap.len(x)>=n && alglib.ap.len(y)>=m, "Spline2DBuildBicubic: length of X or Y is too short (Length(X/Y)<N/M)"); alglib.ap.assert(apserv.isfinitevector(x, n) && apserv.isfinitevector(y, m), "Spline2DBuildBicubic: X or Y contains NaN or Infinite value"); alglib.ap.assert(alglib.ap.rows(f)>=m && alglib.ap.cols(f)>=n, "Spline2DBuildBicubic: size of F is too small (rows(F)<M or cols(F)<N)"); alglib.ap.assert(apserv.apservisfinitematrix(f, m, n), "Spline2DBuildBicubic: F contains NaN or Infinite value"); // // Fill interpolant: // F[0]...F[N*M-1]: // f(i,j) table. f(0,0), f(0, 1), f(0,2) and so on... // F[N*M]...F[2*N*M-1]: // df(i,j)/dx table. // F[2*N*M]...F[3*N*M-1]: // df(i,j)/dy table. // F[3*N*M]...F[4*N*M-1]: // d2f(i,j)/dxdy table. // c.k = 3; c.d = 1; c.n = n; c.m = m; c.stype = -3; sfx = c.n*c.m; sfy = 2*c.n*c.m; sfxy = 3*c.n*c.m; c.x = new double[c.n]; c.y = new double[c.m]; c.f = new double[4*c.n*c.m]; for(i=0; i<=c.n-1; i++) { c.x[i] = x[i]; } for(i=0; i<=c.m-1; i++) { c.y[i] = y[i]; } // // Sort points // for(j=0; j<=c.n-1; j++) { k = j; for(i=j+1; i<=c.n-1; i++) { if( (double)(c.x[i])<(double)(c.x[k]) ) { k = i; } } if( k!=j ) { for(i=0; i<=c.m-1; i++) { t = f[i,j]; f[i,j] = f[i,k]; f[i,k] = t; } t = c.x[j]; c.x[j] = c.x[k]; c.x[k] = t; } } for(i=0; i<=c.m-1; i++) { k = i; for(j=i+1; j<=c.m-1; j++) { if( (double)(c.y[j])<(double)(c.y[k]) ) { k = j; } } if( k!=i ) { for(j=0; j<=c.n-1; j++) { t = f[i,j]; f[i,j] = f[k,j]; f[k,j] = t; } t = c.y[i]; c.y[i] = c.y[k]; c.y[k] = t; } } bicubiccalcderivatives(f, c.x, c.y, c.m, c.n, ref dx, ref dy, ref dxy); for(i=0; i<=c.m-1; i++) { for(j=0; j<=c.n-1; j++) { k = i*c.n+j; c.f[k] = f[i,j]; c.f[sfx+k] = dx[i,j]; c.f[sfy+k] = dy[i,j]; c.f[sfxy+k] = dxy[i,j]; } } }
/************************************************************************* This subroutine calculates the value of the bilinear or bicubic spline at the given point X and its derivatives. Input parameters: C - spline interpolant. X, Y- point Output parameters: F - S(x,y) FX - dS(x,y)/dX FY - dS(x,y)/dY FXY - d2S(x,y)/dXdY -- ALGLIB PROJECT -- Copyright 05.07.2007 by Bochkanov Sergey *************************************************************************/ public static void spline2ddiff(spline2dinterpolant c, double x, double y, ref double f, ref double fx, ref double fy, ref double fxy) { double t = 0; double dt = 0; double u = 0; double du = 0; int ix = 0; int iy = 0; int l = 0; int r = 0; int h = 0; int s1 = 0; int s2 = 0; int s3 = 0; int s4 = 0; int sfx = 0; int sfy = 0; int sfxy = 0; double y1 = 0; double y2 = 0; double y3 = 0; double y4 = 0; double v = 0; double t0 = 0; double t1 = 0; double t2 = 0; double t3 = 0; double u0 = 0; double u1 = 0; double u2 = 0; double u3 = 0; f = 0; fx = 0; fy = 0; fxy = 0; alglib.ap.assert(c.stype==-1 || c.stype==-3, "Spline2DDiff: incorrect C (incorrect parameter C.SType)"); alglib.ap.assert(math.isfinite(x) && math.isfinite(y), "Spline2DDiff: X or Y contains NaN or Infinite value"); // // Prepare F, dF/dX, dF/dY, d2F/dXdY // f = 0; fx = 0; fy = 0; fxy = 0; if( c.d!=1 ) { return; } // // Binary search in the [ x[0], ..., x[n-2] ] (x[n-1] is not included) // l = 0; r = c.n-1; while( l!=r-1 ) { h = (l+r)/2; if( (double)(c.x[h])>=(double)(x) ) { r = h; } else { l = h; } } t = (x-c.x[l])/(c.x[l+1]-c.x[l]); dt = 1.0/(c.x[l+1]-c.x[l]); ix = l; // // Binary search in the [ y[0], ..., y[m-2] ] (y[m-1] is not included) // l = 0; r = c.m-1; while( l!=r-1 ) { h = (l+r)/2; if( (double)(c.y[h])>=(double)(y) ) { r = h; } else { l = h; } } u = (y-c.y[l])/(c.y[l+1]-c.y[l]); du = 1.0/(c.y[l+1]-c.y[l]); iy = l; // // Bilinear interpolation // if( c.stype==-1 ) { y1 = c.f[c.n*iy+ix]; y2 = c.f[c.n*iy+(ix+1)]; y3 = c.f[c.n*(iy+1)+(ix+1)]; y4 = c.f[c.n*(iy+1)+ix]; f = (1-t)*(1-u)*y1+t*(1-u)*y2+t*u*y3+(1-t)*u*y4; fx = (-((1-u)*y1)+(1-u)*y2+u*y3-u*y4)*dt; fy = (-((1-t)*y1)-t*y2+t*y3+(1-t)*y4)*du; fxy = (y1-y2+y3-y4)*du*dt; return; } // // Bicubic interpolation // if( c.stype==-3 ) { // // Prepare info // t0 = 1; t1 = t; t2 = math.sqr(t); t3 = t*t2; u0 = 1; u1 = u; u2 = math.sqr(u); u3 = u*u2; sfx = c.n*c.m; sfy = 2*c.n*c.m; sfxy = 3*c.n*c.m; s1 = c.n*iy+ix; s2 = c.n*iy+(ix+1); s3 = c.n*(iy+1)+(ix+1); s4 = c.n*(iy+1)+ix; // // Calculate // v = c.f[s1]; f = f+v*t0*u0; v = c.f[sfy+s1]/du; f = f+v*t0*u1; fy = fy+v*t0*u0*du; v = -(3*c.f[s1])+3*c.f[s4]-2*c.f[sfy+s1]/du-c.f[sfy+s4]/du; f = f+v*t0*u2; fy = fy+2*v*t0*u1*du; v = 2*c.f[s1]-2*c.f[s4]+c.f[sfy+s1]/du+c.f[sfy+s4]/du; f = f+v*t0*u3; fy = fy+3*v*t0*u2*du; v = c.f[sfx+s1]/dt; f = f+v*t1*u0; fx = fx+v*t0*u0*dt; v = c.f[sfxy+s1]/(dt*du); f = f+v*t1*u1; fx = fx+v*t0*u1*dt; fy = fy+v*t1*u0*du; fxy = fxy+v*t0*u0*dt*du; v = -(3*c.f[sfx+s1]/dt)+3*c.f[sfx+s4]/dt-2*c.f[sfxy+s1]/(dt*du)-c.f[sfxy+s4]/(dt*du); f = f+v*t1*u2; fx = fx+v*t0*u2*dt; fy = fy+2*v*t1*u1*du; fxy = fxy+2*v*t0*u1*dt*du; v = 2*c.f[sfx+s1]/dt-2*c.f[sfx+s4]/dt+c.f[sfxy+s1]/(dt*du)+c.f[sfxy+s4]/(dt*du); f = f+v*t1*u3; fx = fx+v*t0*u3*dt; fy = fy+3*v*t1*u2*du; fxy = fxy+3*v*t0*u2*dt*du; v = -(3*c.f[s1])+3*c.f[s2]-2*c.f[sfx+s1]/dt-c.f[sfx+s2]/dt; f = f+v*t2*u0; fx = fx+2*v*t1*u0*dt; v = -(3*c.f[sfy+s1]/du)+3*c.f[sfy+s2]/du-2*c.f[sfxy+s1]/(dt*du)-c.f[sfxy+s2]/(dt*du); f = f+v*t2*u1; fx = fx+2*v*t1*u1*dt; fy = fy+v*t2*u0*du; fxy = fxy+2*v*t1*u0*dt*du; v = 9*c.f[s1]-9*c.f[s2]+9*c.f[s3]-9*c.f[s4]+6*c.f[sfx+s1]/dt+3*c.f[sfx+s2]/dt-3*c.f[sfx+s3]/dt-6*c.f[sfx+s4]/dt+6*c.f[sfy+s1]/du-6*c.f[sfy+s2]/du-3*c.f[sfy+s3]/du+3*c.f[sfy+s4]/du+4*c.f[sfxy+s1]/(dt*du)+2*c.f[sfxy+s2]/(dt*du)+c.f[sfxy+s3]/(dt*du)+2*c.f[sfxy+s4]/(dt*du); f = f+v*t2*u2; fx = fx+2*v*t1*u2*dt; fy = fy+2*v*t2*u1*du; fxy = fxy+4*v*t1*u1*dt*du; v = -(6*c.f[s1])+6*c.f[s2]-6*c.f[s3]+6*c.f[s4]-4*c.f[sfx+s1]/dt-2*c.f[sfx+s2]/dt+2*c.f[sfx+s3]/dt+4*c.f[sfx+s4]/dt-3*c.f[sfy+s1]/du+3*c.f[sfy+s2]/du+3*c.f[sfy+s3]/du-3*c.f[sfy+s4]/du-2*c.f[sfxy+s1]/(dt*du)-c.f[sfxy+s2]/(dt*du)-c.f[sfxy+s3]/(dt*du)-2*c.f[sfxy+s4]/(dt*du); f = f+v*t2*u3; fx = fx+2*v*t1*u3*dt; fy = fy+3*v*t2*u2*du; fxy = fxy+6*v*t1*u2*dt*du; v = 2*c.f[s1]-2*c.f[s2]+c.f[sfx+s1]/dt+c.f[sfx+s2]/dt; f = f+v*t3*u0; fx = fx+3*v*t2*u0*dt; v = 2*c.f[sfy+s1]/du-2*c.f[sfy+s2]/du+c.f[sfxy+s1]/(dt*du)+c.f[sfxy+s2]/(dt*du); f = f+v*t3*u1; fx = fx+3*v*t2*u1*dt; fy = fy+v*t3*u0*du; fxy = fxy+3*v*t2*u0*dt*du; v = -(6*c.f[s1])+6*c.f[s2]-6*c.f[s3]+6*c.f[s4]-3*c.f[sfx+s1]/dt-3*c.f[sfx+s2]/dt+3*c.f[sfx+s3]/dt+3*c.f[sfx+s4]/dt-4*c.f[sfy+s1]/du+4*c.f[sfy+s2]/du+2*c.f[sfy+s3]/du-2*c.f[sfy+s4]/du-2*c.f[sfxy+s1]/(dt*du)-2*c.f[sfxy+s2]/(dt*du)-c.f[sfxy+s3]/(dt*du)-c.f[sfxy+s4]/(dt*du); f = f+v*t3*u2; fx = fx+3*v*t2*u2*dt; fy = fy+2*v*t3*u1*du; fxy = fxy+6*v*t2*u1*dt*du; v = 4*c.f[s1]-4*c.f[s2]+4*c.f[s3]-4*c.f[s4]+2*c.f[sfx+s1]/dt+2*c.f[sfx+s2]/dt-2*c.f[sfx+s3]/dt-2*c.f[sfx+s4]/dt+2*c.f[sfy+s1]/du-2*c.f[sfy+s2]/du-2*c.f[sfy+s3]/du+2*c.f[sfy+s4]/du+c.f[sfxy+s1]/(dt*du)+c.f[sfxy+s2]/(dt*du)+c.f[sfxy+s3]/(dt*du)+c.f[sfxy+s4]/(dt*du); f = f+v*t3*u3; fx = fx+3*v*t2*u3*dt; fy = fy+3*v*t3*u2*du; fxy = fxy+9*v*t2*u2*dt*du; return; } }
/************************************************************************* Serialization of the spline interpolant INPUT PARAMETERS: B - spline interpolant OUTPUT PARAMETERS: RA - array of real numbers which contains interpolant, array[0..RLen-1] RLen - RA lenght -- ALGLIB -- Copyright 17.08.2009 by Bochkanov Sergey *************************************************************************/ public static void spline2dserialize(ref spline2dinterpolant c, ref double[] ra, ref int ralen) { int clen = 0; int i_ = 0; int i1_ = 0; System.Diagnostics.Debug.Assert(c.k==1 | c.k==3, "Spline2DSerialize: incorrect C!"); clen = (int)Math.Round(c.c[0]); ralen = 3+clen; ra = new double[ralen]; ra[0] = ralen; ra[1] = spline2dvnum; ra[2] = c.k; i1_ = (0) - (3); for(i_=3; i_<=3+clen-1;i_++) { ra[i_] = c.c[i_+i1_]; } }
/************************************************************************* This subroutine performs linear transformation of the spline argument. Input parameters: C - spline interpolant AX, BX - transformation coefficients: x = A*t + B AY, BY - transformation coefficients: y = A*u + B Result: C - transformed spline -- ALGLIB PROJECT -- Copyright 30.06.2007 by Bochkanov Sergey *************************************************************************/ public static void spline2dlintransxy(spline2dinterpolant c, double ax, double bx, double ay, double by) { double[] x = new double[0]; double[] y = new double[0]; double[] f = new double[0]; double[] v = new double[0]; int i = 0; int j = 0; int k = 0; alglib.ap.assert(c.stype==-3 || c.stype==-1, "Spline2DLinTransXY: incorrect C (incorrect parameter C.SType)"); alglib.ap.assert(math.isfinite(ax), "Spline2DLinTransXY: AX is infinite or NaN"); alglib.ap.assert(math.isfinite(bx), "Spline2DLinTransXY: BX is infinite or NaN"); alglib.ap.assert(math.isfinite(ay), "Spline2DLinTransXY: AY is infinite or NaN"); alglib.ap.assert(math.isfinite(by), "Spline2DLinTransXY: BY is infinite or NaN"); x = new double[c.n]; y = new double[c.m]; f = new double[c.m*c.n*c.d]; for(j=0; j<=c.n-1; j++) { x[j] = c.x[j]; } for(i=0; i<=c.m-1; i++) { y[i] = c.y[i]; } for(i=0; i<=c.m-1; i++) { for(j=0; j<=c.n-1; j++) { for(k=0; k<=c.d-1; k++) { f[c.d*(i*c.n+j)+k] = c.f[c.d*(i*c.n+j)+k]; } } } // // Handle different combinations of AX/AY // if( (double)(ax)==(double)(0) && (double)(ay)!=(double)(0) ) { for(i=0; i<=c.m-1; i++) { spline2dcalcvbuf(c, bx, y[i], ref v); y[i] = (y[i]-by)/ay; for(j=0; j<=c.n-1; j++) { for(k=0; k<=c.d-1; k++) { f[c.d*(i*c.n+j)+k] = v[k]; } } } } if( (double)(ax)!=(double)(0) && (double)(ay)==(double)(0) ) { for(j=0; j<=c.n-1; j++) { spline2dcalcvbuf(c, x[j], by, ref v); x[j] = (x[j]-bx)/ax; for(i=0; i<=c.m-1; i++) { for(k=0; k<=c.d-1; k++) { f[c.d*(i*c.n+j)+k] = v[k]; } } } } if( (double)(ax)!=(double)(0) && (double)(ay)!=(double)(0) ) { for(j=0; j<=c.n-1; j++) { x[j] = (x[j]-bx)/ax; } for(i=0; i<=c.m-1; i++) { y[i] = (y[i]-by)/ay; } } if( (double)(ax)==(double)(0) && (double)(ay)==(double)(0) ) { spline2dcalcvbuf(c, bx, by, ref v); for(i=0; i<=c.m-1; i++) { for(j=0; j<=c.n-1; j++) { for(k=0; k<=c.d-1; k++) { f[c.d*(i*c.n+j)+k] = v[k]; } } } } // // Rebuild spline // if( c.stype==-3 ) { spline2dbuildbicubicv(x, c.n, y, c.m, f, c.d, c); } if( c.stype==-1 ) { spline2dbuildbilinearv(x, c.n, y, c.m, f, c.d, c); } }
/************************************************************************* * This subroutine builds bilinear spline coefficients table. * * Input parameters: * X - spline abscissas, array[0..N-1] * Y - spline ordinates, array[0..M-1] * F - function values, array[0..M-1,0..N-1] * M,N - grid size, M>=2, N>=2 * * Output parameters: * C - spline interpolant * * -- ALGLIB PROJECT -- * Copyright 05.07.2007 by Bochkanov Sergey *************************************************************************/ public static void spline2dbuildbilinear(double[] x, double[] y, double[,] f, int m, int n, ref spline2dinterpolant c) { int i = 0; int j = 0; int k = 0; int tblsize = 0; int shift = 0; double t = 0; double[,] dx = new double[0, 0]; double[,] dy = new double[0, 0]; double[,] dxy = new double[0, 0]; x = (double[])x.Clone(); y = (double[])y.Clone(); f = (double[, ])f.Clone(); System.Diagnostics.Debug.Assert(n >= 2 & m >= 2, "Spline2DBuildBilinear: N<2 or M<2!"); // // Sort points // for (j = 0; j <= n - 1; j++) { k = j; for (i = j + 1; i <= n - 1; i++) { if ((double)(x[i]) < (double)(x[k])) { k = i; } } if (k != j) { for (i = 0; i <= m - 1; i++) { t = f[i, j]; f[i, j] = f[i, k]; f[i, k] = t; } t = x[j]; x[j] = x[k]; x[k] = t; } } for (i = 0; i <= m - 1; i++) { k = i; for (j = i + 1; j <= m - 1; j++) { if ((double)(y[j]) < (double)(y[k])) { k = j; } } if (k != i) { for (j = 0; j <= n - 1; j++) { t = f[i, j]; f[i, j] = f[k, j]; f[k, j] = t; } t = y[i]; y[i] = y[k]; y[k] = t; } } // // Fill C: // C[0] - length(C) // C[1] - type(C): // -1 = bilinear interpolant // -3 = general cubic spline // (see BuildBicubicSpline) // C[2]: // N (x count) // C[3]: // M (y count) // C[4]...C[4+N-1]: // x[i], i = 0...N-1 // C[4+N]...C[4+N+M-1]: // y[i], i = 0...M-1 // C[4+N+M]...C[4+N+M+(N*M-1)]: // f(i,j) table. f(0,0), f(0, 1), f(0,2) and so on... // c.k = 1; tblsize = 4 + n + m + n * m; c.c = new double[tblsize - 1 + 1]; c.c[0] = tblsize; c.c[1] = -1; c.c[2] = n; c.c[3] = m; for (i = 0; i <= n - 1; i++) { c.c[4 + i] = x[i]; } for (i = 0; i <= m - 1; i++) { c.c[4 + n + i] = y[i]; } for (i = 0; i <= m - 1; i++) { for (j = 0; j <= n - 1; j++) { shift = i * n + j; c.c[4 + n + m + shift] = f[i, j]; } } }
/************************************************************************* This subroutine makes the copy of the spline model. Input parameters: C - spline interpolant Output parameters: CC - spline copy -- ALGLIB PROJECT -- Copyright 29.06.2007 by Bochkanov Sergey *************************************************************************/ public static void spline2dcopy(ref spline2dinterpolant c, ref spline2dinterpolant cc) { int n = 0; int i_ = 0; System.Diagnostics.Debug.Assert(c.k==1 | c.k==3, "Spline2DCopy: incorrect C!"); cc.k = c.k; n = (int)Math.Round(c.c[0]); cc.c = new double[n]; for(i_=0; i_<=n-1;i_++) { cc.c[i_] = c.c[i_]; } }
/************************************************************************* * This subroutine performs linear transformation of the spline argument. * * Input parameters: * C - spline interpolant * AX, BX - transformation coefficients: x = A*t + B * AY, BY - transformation coefficients: y = A*u + B * Result: * C - transformed spline * * -- ALGLIB PROJECT -- * Copyright 30.06.2007 by Bochkanov Sergey *************************************************************************/ public static void spline2dlintransxy(ref spline2dinterpolant c, double ax, double bx, double ay, double by) { int i = 0; int j = 0; int n = 0; int m = 0; double v = 0; double[] x = new double[0]; double[] y = new double[0]; double[,] f = new double[0, 0]; int typec = 0; typec = (int)Math.Round(c.c[1]); System.Diagnostics.Debug.Assert(typec == -3 | typec == -1, "Spline2DLinTransXY: incorrect C!"); n = (int)Math.Round(c.c[2]); m = (int)Math.Round(c.c[3]); x = new double[n - 1 + 1]; y = new double[m - 1 + 1]; f = new double[m - 1 + 1, n - 1 + 1]; for (j = 0; j <= n - 1; j++) { x[j] = c.c[4 + j]; } for (i = 0; i <= m - 1; i++) { y[i] = c.c[4 + n + i]; } for (i = 0; i <= m - 1; i++) { for (j = 0; j <= n - 1; j++) { f[i, j] = c.c[4 + n + m + i * n + j]; } } // // Special case: AX=0 or AY=0 // if ((double)(ax) == (double)(0)) { for (i = 0; i <= m - 1; i++) { v = spline2dcalc(ref c, bx, y[i]); for (j = 0; j <= n - 1; j++) { f[i, j] = v; } } if (typec == -3) { spline2dbuildbicubic(x, y, f, m, n, ref c); } if (typec == -1) { spline2dbuildbilinear(x, y, f, m, n, ref c); } ax = 1; bx = 0; } if ((double)(ay) == (double)(0)) { for (j = 0; j <= n - 1; j++) { v = spline2dcalc(ref c, x[j], by); for (i = 0; i <= m - 1; i++) { f[i, j] = v; } } if (typec == -3) { spline2dbuildbicubic(x, y, f, m, n, ref c); } if (typec == -1) { spline2dbuildbilinear(x, y, f, m, n, ref c); } ay = 1; by = 0; } // // General case: AX<>0, AY<>0 // Unpack, scale and pack again. // for (j = 0; j <= n - 1; j++) { x[j] = (x[j] - bx) / ax; } for (i = 0; i <= m - 1; i++) { y[i] = (y[i] - by) / ay; } if (typec == -3) { spline2dbuildbicubic(x, y, f, m, n, ref c); } if (typec == -1) { spline2dbuildbilinear(x, y, f, m, n, ref c); } }
/************************************************************************* This subroutine builds bilinear vector-valued spline. Input parameters: X - spline abscissas, array[0..N-1] Y - spline ordinates, array[0..M-1] F - function values, array[0..M*N*D-1]: * first D elements store D values at (X[0],Y[0]) * next D elements store D values at (X[1],Y[0]) * general form - D function values at (X[i],Y[j]) are stored at F[D*(J*N+I)...D*(J*N+I)+D-1]. M,N - grid size, M>=2, N>=2 D - vector dimension, D>=1 Output parameters: C - spline interpolant -- ALGLIB PROJECT -- Copyright 16.04.2012 by Bochkanov Sergey *************************************************************************/ public static void spline2dbuildbilinearv(double[] x, int n, double[] y, int m, double[] f, int d, spline2dinterpolant c) { double t = 0; int i = 0; int j = 0; int k = 0; int i0 = 0; alglib.ap.assert(n>=2, "Spline2DBuildBilinearV: N is less then 2"); alglib.ap.assert(m>=2, "Spline2DBuildBilinearV: M is less then 2"); alglib.ap.assert(d>=1, "Spline2DBuildBilinearV: invalid argument D (D<1)"); alglib.ap.assert(alglib.ap.len(x)>=n && alglib.ap.len(y)>=m, "Spline2DBuildBilinearV: length of X or Y is too short (Length(X/Y)<N/M)"); alglib.ap.assert(apserv.isfinitevector(x, n) && apserv.isfinitevector(y, m), "Spline2DBuildBilinearV: X or Y contains NaN or Infinite value"); k = n*m*d; alglib.ap.assert(alglib.ap.len(f)>=k, "Spline2DBuildBilinearV: length of F is too short (Length(F)<N*M*D)"); alglib.ap.assert(apserv.isfinitevector(f, k), "Spline2DBuildBilinearV: F contains NaN or Infinite value"); // // Fill interpolant // c.k = 1; c.n = n; c.m = m; c.d = d; c.stype = -1; c.x = new double[c.n]; c.y = new double[c.m]; c.f = new double[k]; for(i=0; i<=c.n-1; i++) { c.x[i] = x[i]; } for(i=0; i<=c.m-1; i++) { c.y[i] = y[i]; } for(i=0; i<=k-1; i++) { c.f[i] = f[i]; } // // Sort points // for(j=0; j<=c.n-1; j++) { k = j; for(i=j+1; i<=c.n-1; i++) { if( (double)(c.x[i])<(double)(c.x[k]) ) { k = i; } } if( k!=j ) { for(i=0; i<=c.m-1; i++) { for(i0=0; i0<=c.d-1; i0++) { t = c.f[c.d*(i*c.n+j)+i0]; c.f[c.d*(i*c.n+j)+i0] = c.f[c.d*(i*c.n+k)+i0]; c.f[c.d*(i*c.n+k)+i0] = t; } } t = c.x[j]; c.x[j] = c.x[k]; c.x[k] = t; } } for(i=0; i<=c.m-1; i++) { k = i; for(j=i+1; j<=c.m-1; j++) { if( (double)(c.y[j])<(double)(c.y[k]) ) { k = j; } } if( k!=i ) { for(j=0; j<=c.n-1; j++) { for(i0=0; i0<=c.d-1; i0++) { t = c.f[c.d*(i*c.n+j)+i0]; c.f[c.d*(i*c.n+j)+i0] = c.f[c.d*(k*c.n+j)+i0]; c.f[c.d*(k*c.n+j)+i0] = t; } } t = c.y[i]; c.y[i] = c.y[k]; c.y[k] = t; } } }
/************************************************************************* This subroutine performs linear transformation of the spline. Input parameters: C - spline interpolant. A, B- transformation coefficients: S2(x,y) = A*S(x,y) + B Output parameters: C - transformed spline -- ALGLIB PROJECT -- Copyright 30.06.2007 by Bochkanov Sergey *************************************************************************/ public static void spline2dlintransf(spline2dinterpolant c, double a, double b) { double[] x = new double[0]; double[] y = new double[0]; double[] f = new double[0]; int i = 0; int j = 0; alglib.ap.assert(c.stype==-3 || c.stype==-1, "Spline2DLinTransF: incorrect C (incorrect parameter C.SType)"); x = new double[c.n]; y = new double[c.m]; f = new double[c.m*c.n*c.d]; for(j=0; j<=c.n-1; j++) { x[j] = c.x[j]; } for(i=0; i<=c.m-1; i++) { y[i] = c.y[i]; } for(i=0; i<=c.m*c.n*c.d-1; i++) { f[i] = a*c.f[i]+b; } if( c.stype==-3 ) { spline2dbuildbicubicv(x, c.n, y, c.m, f, c.d, c); } if( c.stype==-1 ) { spline2dbuildbilinearv(x, c.n, y, c.m, f, c.d, c); } }
/************************************************************************* Unserialization of the spline interpolant INPUT PARAMETERS: RA - array of real numbers which contains interpolant, OUTPUT PARAMETERS: B - spline interpolant -- ALGLIB -- Copyright 17.08.2009 by Bochkanov Sergey *************************************************************************/ public static void spline2dunserialize(ref double[] ra, ref spline2dinterpolant c) { int clen = 0; int i_ = 0; int i1_ = 0; System.Diagnostics.Debug.Assert((int)Math.Round(ra[1])==spline2dvnum, "Spline2DUnserialize: corrupted array!"); c.k = (int)Math.Round(ra[2]); clen = (int)Math.Round(ra[3]); c.c = new double[clen]; i1_ = (3) - (0); for(i_=0; i_<=clen-1;i_++) { c.c[i_] = ra[i_+i1_]; } }
/************************************************************************* This subroutine makes the copy of the spline model. Input parameters: C - spline interpolant Output parameters: CC - spline copy -- ALGLIB PROJECT -- Copyright 29.06.2007 by Bochkanov Sergey *************************************************************************/ public static void spline2dcopy(spline2dinterpolant c, spline2dinterpolant cc) { int tblsize = 0; int i_ = 0; alglib.ap.assert(c.k==1 || c.k==3, "Spline2DCopy: incorrect C (incorrect parameter C.K)"); cc.k = c.k; cc.n = c.n; cc.m = c.m; cc.d = c.d; cc.stype = c.stype; tblsize = -1; if( c.stype==-3 ) { tblsize = 4*c.n*c.m*c.d; } if( c.stype==-1 ) { tblsize = c.n*c.m*c.d; } alglib.ap.assert(tblsize>0, "Spline2DCopy: internal error"); cc.x = new double[cc.n]; cc.y = new double[cc.m]; cc.f = new double[tblsize]; for(i_=0; i_<=cc.n-1;i_++) { cc.x[i_] = c.x[i_]; } for(i_=0; i_<=cc.m-1;i_++) { cc.y[i_] = c.y[i_]; } for(i_=0; i_<=tblsize-1;i_++) { cc.f[i_] = c.f[i_]; } }
/************************************************************************* This subroutine builds bilinear spline coefficients table. Input parameters: X - spline abscissas, array[0..N-1] Y - spline ordinates, array[0..M-1] F - function values, array[0..M-1,0..N-1] M,N - grid size, M>=2, N>=2 Output parameters: C - spline interpolant -- ALGLIB PROJECT -- Copyright 05.07.2007 by Bochkanov Sergey *************************************************************************/ public static void spline2dbuildbilinear(double[] x, double[] y, double[,] f, int m, int n, ref spline2dinterpolant c) { int i = 0; int j = 0; int k = 0; int tblsize = 0; int shift = 0; double t = 0; double[,] dx = new double[0,0]; double[,] dy = new double[0,0]; double[,] dxy = new double[0,0]; x = (double[])x.Clone(); y = (double[])y.Clone(); f = (double[,])f.Clone(); System.Diagnostics.Debug.Assert(n>=2 & m>=2, "Spline2DBuildBilinear: N<2 or M<2!"); // // Sort points // for(j=0; j<=n-1; j++) { k = j; for(i=j+1; i<=n-1; i++) { if( (double)(x[i])<(double)(x[k]) ) { k = i; } } if( k!=j ) { for(i=0; i<=m-1; i++) { t = f[i,j]; f[i,j] = f[i,k]; f[i,k] = t; } t = x[j]; x[j] = x[k]; x[k] = t; } } for(i=0; i<=m-1; i++) { k = i; for(j=i+1; j<=m-1; j++) { if( (double)(y[j])<(double)(y[k]) ) { k = j; } } if( k!=i ) { for(j=0; j<=n-1; j++) { t = f[i,j]; f[i,j] = f[k,j]; f[k,j] = t; } t = y[i]; y[i] = y[k]; y[k] = t; } } // // Fill C: // C[0] - length(C) // C[1] - type(C): // -1 = bilinear interpolant // -3 = general cubic spline // (see BuildBicubicSpline) // C[2]: // N (x count) // C[3]: // M (y count) // C[4]...C[4+N-1]: // x[i], i = 0...N-1 // C[4+N]...C[4+N+M-1]: // y[i], i = 0...M-1 // C[4+N+M]...C[4+N+M+(N*M-1)]: // f(i,j) table. f(0,0), f(0, 1), f(0,2) and so on... // c.k = 1; tblsize = 4+n+m+n*m; c.c = new double[tblsize-1+1]; c.c[0] = tblsize; c.c[1] = -1; c.c[2] = n; c.c[3] = m; for(i=0; i<=n-1; i++) { c.c[4+i] = x[i]; } for(i=0; i<=m-1; i++) { c.c[4+n+i] = y[i]; } for(i=0; i<=m-1; i++) { for(j=0; j<=n-1; j++) { shift = i*n+j; c.c[4+n+m+shift] = f[i,j]; } } }