/************************************************************************* * Numerical differentiation. *************************************************************************/ private static void twodnumder(ref spline2d.spline2dinterpolant c, double x, double y, double h, ref double f, ref double fx, ref double fy, ref double fxy) { f = spline2d.spline2dcalc(ref c, x, y); fx = (spline2d.spline2dcalc(ref c, x + h, y) - spline2d.spline2dcalc(ref c, x - h, y)) / (2 * h); fy = (spline2d.spline2dcalc(ref c, x, y + h) - spline2d.spline2dcalc(ref c, x, y - h)) / (2 * h); fxy = (spline2d.spline2dcalc(ref c, x + h, y + h) - spline2d.spline2dcalc(ref c, x - h, y + h) - spline2d.spline2dcalc(ref c, x + h, y - h) + spline2d.spline2dcalc(ref c, x - h, y - h)) / AP.Math.Sqr(2 * h); }
/************************************************************************* * Unset spline, i.e. initialize it with random garbage *************************************************************************/ private static void unsetspline2d(ref spline2d.spline2dinterpolant c) { double[] x = new double[0]; double[] y = new double[0]; double[,] f = new double[0, 0]; x = new double[2]; y = new double[2]; f = new double[2, 2]; x[0] = -1; x[1] = +1; y[0] = -1; y[1] = +1; f[0, 0] = 0; f[0, 1] = 0; f[1, 0] = 0; f[1, 1] = 0; spline2d.spline2dbuildbilinear(x, y, f, 2, 2, ref c); }
/************************************************************************* LinTrans test *************************************************************************/ private static bool testlintrans(ref spline2d.spline2dinterpolant c, double ax, double bx, double ay, double by) { bool result = new bool(); double err = 0; double a1 = 0; double a2 = 0; double b1 = 0; double b2 = 0; double tx = 0; double ty = 0; double vx = 0; double vy = 0; double v1 = 0; double v2 = 0; int pass = 0; int passcount = 0; int xjob = 0; int yjob = 0; spline2d.spline2dinterpolant c2 = new spline2d.spline2dinterpolant(); passcount = 5; err = 0; for(xjob=0; xjob<=1; xjob++) { for(yjob=0; yjob<=1; yjob++) { for(pass=1; pass<=passcount; pass++) { // // Prepare // do { a1 = 2*AP.Math.RandomReal()-1; } while( (double)(a1)==(double)(0) ); a1 = a1*xjob; b1 = 2*AP.Math.RandomReal()-1; do { a2 = 2*AP.Math.RandomReal()-1; } while( (double)(a2)==(double)(0) ); a2 = a2*yjob; b2 = 2*AP.Math.RandomReal()-1; // // Test XY // spline2d.spline2dcopy(ref c, ref c2); spline2d.spline2dlintransxy(ref c2, a1, b1, a2, b2); tx = ax+AP.Math.RandomReal()*(bx-ax); ty = ay+AP.Math.RandomReal()*(by-ay); if( xjob==0 ) { tx = b1; vx = ax+AP.Math.RandomReal()*(bx-ax); } else { vx = (tx-b1)/a1; } if( yjob==0 ) { ty = b2; vy = ay+AP.Math.RandomReal()*(by-ay); } else { vy = (ty-b2)/a2; } v1 = spline2d.spline2dcalc(ref c, tx, ty); v2 = spline2d.spline2dcalc(ref c2, vx, vy); err = Math.Max(err, Math.Abs(v1-v2)); // // Test F // spline2d.spline2dcopy(ref c, ref c2); spline2d.spline2dlintransf(ref c2, a1, b1); tx = ax+AP.Math.RandomReal()*(bx-ax); ty = ay+AP.Math.RandomReal()*(by-ay); v1 = spline2d.spline2dcalc(ref c, tx, ty); v2 = spline2d.spline2dcalc(ref c2, tx, ty); err = Math.Max(err, Math.Abs(a1*v1+b1-v2)); } } } result = (double)(err)<(double)(10000*AP.Math.MachineEpsilon); return result; }
public static bool test2dinterpolation(bool silent) { bool result = new bool(); bool waserrors = new bool(); bool blerrors = new bool(); bool bcerrors = new bool(); bool dserrors = new bool(); bool cperrors = new bool(); bool uperrors = new bool(); bool lterrors = new bool(); bool syerrors = new bool(); bool rlerrors = new bool(); bool rcerrors = new bool(); int pass = 0; int passcount = 0; int jobtype = 0; double lstep = 0; double h = 0; double[] x = new double[0]; double[] y = new double[0]; spline2d.spline2dinterpolant c = new spline2d.spline2dinterpolant(); spline2d.spline2dinterpolant c2 = new spline2d.spline2dinterpolant(); double[] lx = new double[0]; double[] ly = new double[0]; double[,] f = new double[0,0]; double[,] fr = new double[0,0]; double[,] ft = new double[0,0]; double ax = 0; double ay = 0; double bx = 0; double by = 0; int i = 0; int j = 0; int k = 0; int n = 0; int m = 0; int n2 = 0; int m2 = 0; double err = 0; double t = 0; double t1 = 0; double t2 = 0; double l1 = 0; double l1x = 0; double l1y = 0; double l1xy = 0; double l2 = 0; double l2x = 0; double l2y = 0; double l2xy = 0; double fm = 0; double f1 = 0; double f2 = 0; double f3 = 0; double f4 = 0; double v1 = 0; double v1x = 0; double v1y = 0; double v1xy = 0; double v2 = 0; double v2x = 0; double v2y = 0; double v2xy = 0; double mf = 0; double[] ra = new double[0]; double[] ra2 = new double[0]; int ralen = 0; int i_ = 0; waserrors = false; passcount = 10; h = 0.00001; lstep = 0.001; blerrors = false; bcerrors = false; dserrors = false; cperrors = false; uperrors = false; lterrors = false; syerrors = false; rlerrors = false; rcerrors = false; // // Test: bilinear, bicubic // for(n=2; n<=7; n++) { for(m=2; m<=7; m++) { x = new double[n-1+1]; y = new double[m-1+1]; lx = new double[2*n-2+1]; ly = new double[2*m-2+1]; f = new double[m-1+1, n-1+1]; ft = new double[n-1+1, m-1+1]; for(pass=1; pass<=passcount; pass++) { // // Prepare task: // * X and Y stores grid // * F stores function values // * LX and LY stores twice dense grid (for Lipschitz testing) // ax = -1-AP.Math.RandomReal(); bx = +1+AP.Math.RandomReal(); ay = -1-AP.Math.RandomReal(); by = +1+AP.Math.RandomReal(); for(j=0; j<=n-1; j++) { x[j] = 0.5*(bx+ax)-0.5*(bx-ax)*Math.Cos(Math.PI*(2*j+1)/(2*n)); if( j==0 ) { x[j] = ax; } if( j==n-1 ) { x[j] = bx; } lx[2*j] = x[j]; if( j>0 ) { lx[2*j-1] = 0.5*(x[j]+x[j-1]); } } for(j=0; j<=n-1; j++) { k = AP.Math.RandomInteger(n); if( k!=j ) { t = x[j]; x[j] = x[k]; x[k] = t; } } for(i=0; i<=m-1; i++) { y[i] = 0.5*(by+ay)-0.5*(by-ay)*Math.Cos(Math.PI*(2*i+1)/(2*m)); if( i==0 ) { y[i] = ay; } if( i==m-1 ) { y[i] = by; } ly[2*i] = y[i]; if( i>0 ) { ly[2*i-1] = 0.5*(y[i]+y[i-1]); } } for(i=0; i<=m-1; i++) { k = AP.Math.RandomInteger(m); if( k!=i ) { t = y[i]; y[i] = y[k]; y[k] = t; } } for(i=0; i<=m-1; i++) { for(j=0; j<=n-1; j++) { f[i,j] = Math.Exp(0.6*x[j])-Math.Exp(-(0.3*y[i])+0.08*x[j])+2*Math.Cos(Math.PI*(x[j]+1.2*y[i]))+0.1*Math.Cos(20*x[j]+15*y[i]); } } // // Test bilinear interpolation: // * interpolation at the nodes // * linearity // * continuity // * differentiation in the inner points // spline2d.spline2dbuildbilinear(x, y, f, m, n, ref c); err = 0; for(i=0; i<=m-1; i++) { for(j=0; j<=n-1; j++) { err = Math.Max(err, Math.Abs(f[i,j]-spline2d.spline2dcalc(ref c, x[j], y[i]))); } } blerrors = blerrors | (double)(err)>(double)(10000*AP.Math.MachineEpsilon); err = 0; for(i=0; i<=m-2; i++) { for(j=0; j<=n-2; j++) { // // Test for linearity between grid points // (test point - geometric center of the cell) // fm = spline2d.spline2dcalc(ref c, lx[2*j+1], ly[2*i+1]); f1 = spline2d.spline2dcalc(ref c, lx[2*j], ly[2*i]); f2 = spline2d.spline2dcalc(ref c, lx[2*j+2], ly[2*i]); f3 = spline2d.spline2dcalc(ref c, lx[2*j+2], ly[2*i+2]); f4 = spline2d.spline2dcalc(ref c, lx[2*j], ly[2*i+2]); err = Math.Max(err, Math.Abs(0.25*(f1+f2+f3+f4)-fm)); } } blerrors = blerrors | (double)(err)>(double)(10000*AP.Math.MachineEpsilon); lconst(ref c, ref lx, ref ly, m, n, lstep, ref l1, ref l1x, ref l1y, ref l1xy); lconst(ref c, ref lx, ref ly, m, n, lstep/3, ref l2, ref l2x, ref l2y, ref l2xy); blerrors = blerrors | (double)(l2/l1)>(double)(1.2); err = 0; for(i=0; i<=m-2; i++) { for(j=0; j<=n-2; j++) { spline2d.spline2ddiff(ref c, lx[2*j+1], ly[2*i+1], ref v1, ref v1x, ref v1y, ref v1xy); twodnumder(ref c, lx[2*j+1], ly[2*i+1], h, ref v2, ref v2x, ref v2y, ref v2xy); err = Math.Max(err, Math.Abs(v1-v2)); err = Math.Max(err, Math.Abs(v1x-v2x)); err = Math.Max(err, Math.Abs(v1y-v2y)); err = Math.Max(err, Math.Abs(v1xy-v2xy)); } } dserrors = dserrors | (double)(err)>(double)(1.0E-3); uperrors = uperrors | !testunpack(ref c, ref lx, ref ly); lterrors = lterrors | !testlintrans(ref c, ax, bx, ay, by); // // Test bicubic interpolation. // * interpolation at the nodes // * smoothness // * differentiation // spline2d.spline2dbuildbicubic(x, y, f, m, n, ref c); err = 0; for(i=0; i<=m-1; i++) { for(j=0; j<=n-1; j++) { err = Math.Max(err, Math.Abs(f[i,j]-spline2d.spline2dcalc(ref c, x[j], y[i]))); } } bcerrors = bcerrors | (double)(err)>(double)(10000*AP.Math.MachineEpsilon); lconst(ref c, ref lx, ref ly, m, n, lstep, ref l1, ref l1x, ref l1y, ref l1xy); lconst(ref c, ref lx, ref ly, m, n, lstep/3, ref l2, ref l2x, ref l2y, ref l2xy); bcerrors = bcerrors | (double)(l2/l1)>(double)(1.2); bcerrors = bcerrors | (double)(l2x/l1x)>(double)(1.2); bcerrors = bcerrors | (double)(l2y/l1y)>(double)(1.2); if( (double)(l2xy)>(double)(0.01) & (double)(l1xy)>(double)(0.01) ) { // // Cross-derivative continuity is tested only when // bigger than 0.01. When the task size is too // small, the d2F/dXdY is nearly zero and Lipschitz // constant ratio is ill-conditioned. // bcerrors = bcerrors | (double)(l2xy/l1xy)>(double)(1.2); } err = 0; for(i=0; i<=2*m-2; i++) { for(j=0; j<=2*n-2; j++) { spline2d.spline2ddiff(ref c, lx[j], ly[i], ref v1, ref v1x, ref v1y, ref v1xy); twodnumder(ref c, lx[j], ly[i], h, ref v2, ref v2x, ref v2y, ref v2xy); err = Math.Max(err, Math.Abs(v1-v2)); err = Math.Max(err, Math.Abs(v1x-v2x)); err = Math.Max(err, Math.Abs(v1y-v2y)); err = Math.Max(err, Math.Abs(v1xy-v2xy)); } } dserrors = dserrors | (double)(err)>(double)(1.0E-3); uperrors = uperrors | !testunpack(ref c, ref lx, ref ly); lterrors = lterrors | !testlintrans(ref c, ax, bx, ay, by); // // Copy/Serialise test // if( (double)(AP.Math.RandomReal())>(double)(0.5) ) { spline2d.spline2dbuildbicubic(x, y, f, m, n, ref c); } else { spline2d.spline2dbuildbilinear(x, y, f, m, n, ref c); } unsetspline2d(ref c2); spline2d.spline2dcopy(ref c, ref c2); err = 0; for(i=1; i<=5; i++) { t1 = ax+(bx-ax)*AP.Math.RandomReal(); t2 = ay+(by-ay)*AP.Math.RandomReal(); err = Math.Max(err, Math.Abs(spline2d.spline2dcalc(ref c, t1, t2)-spline2d.spline2dcalc(ref c2, t1, t2))); } cperrors = cperrors | (double)(err)>(double)(10000*AP.Math.MachineEpsilon); unsetspline2d(ref c2); spline2d.spline2dserialize(ref c, ref ra, ref ralen); ra2 = new double[ralen]; for(i_=0; i_<=ralen-1;i_++) { ra2[i_] = ra[i_]; } spline2d.spline2dunserialize(ref ra2, ref c2); err = 0; for(i=1; i<=5; i++) { t1 = ax+(bx-ax)*AP.Math.RandomReal(); t2 = ay+(by-ay)*AP.Math.RandomReal(); err = Math.Max(err, Math.Abs(spline2d.spline2dcalc(ref c, t1, t2)-spline2d.spline2dcalc(ref c2, t1, t2))); } cperrors = cperrors | (double)(err)>(double)(10000*AP.Math.MachineEpsilon); // // Special symmetry test // err = 0; for(jobtype=0; jobtype<=1; jobtype++) { // // Prepare // for(i=0; i<=m-1; i++) { for(j=0; j<=n-1; j++) { ft[j,i] = f[i,j]; } } if( jobtype==0 ) { spline2d.spline2dbuildbilinear(x, y, f, m, n, ref c); spline2d.spline2dbuildbilinear(y, x, ft, n, m, ref c2); } else { spline2d.spline2dbuildbicubic(x, y, f, m, n, ref c); spline2d.spline2dbuildbicubic(y, x, ft, n, m, ref c2); } // // Test // for(i=1; i<=10; i++) { t1 = ax+(bx-ax)*AP.Math.RandomReal(); t2 = ay+(by-ay)*AP.Math.RandomReal(); err = Math.Max(err, Math.Abs(spline2d.spline2dcalc(ref c, t1, t2)-spline2d.spline2dcalc(ref c2, t2, t1))); } } syerrors = syerrors | (double)(err)>(double)(10000*AP.Math.MachineEpsilon); } } } // // Test resample // for(m=2; m<=6; m++) { for(n=2; n<=6; n++) { f = new double[m-1+1, n-1+1]; x = new double[n-1+1]; y = new double[m-1+1]; for(j=0; j<=n-1; j++) { x[j] = (double)(j)/((double)(n-1)); } for(i=0; i<=m-1; i++) { y[i] = (double)(i)/((double)(m-1)); } for(i=0; i<=m-1; i++) { for(j=0; j<=n-1; j++) { f[i,j] = Math.Exp(0.6*x[j])-Math.Exp(-(0.3*y[i])+0.08*x[j])+2*Math.Cos(Math.PI*(x[j]+1.2*y[i]))+0.1*Math.Cos(20*x[j]+15*y[i]); } } for(m2=2; m2<=6; m2++) { for(n2=2; n2<=6; n2++) { for(pass=1; pass<=passcount; pass++) { for(jobtype=0; jobtype<=1; jobtype++) { if( jobtype==0 ) { spline2d.spline2dresamplebilinear(ref f, m, n, ref fr, m2, n2); spline2d.spline2dbuildbilinear(x, y, f, m, n, ref c); } if( jobtype==1 ) { spline2d.spline2dresamplebicubic(ref f, m, n, ref fr, m2, n2); spline2d.spline2dbuildbicubic(x, y, f, m, n, ref c); } err = 0; mf = 0; for(i=0; i<=m2-1; i++) { for(j=0; j<=n2-1; j++) { v1 = spline2d.spline2dcalc(ref c, (double)(j)/((double)(n2-1)), (double)(i)/((double)(m2-1))); v2 = fr[i,j]; err = Math.Max(err, Math.Abs(v1-v2)); mf = Math.Max(mf, Math.Abs(v1)); } } if( jobtype==0 ) { rlerrors = rlerrors | (double)(err/mf)>(double)(10000*AP.Math.MachineEpsilon); } if( jobtype==1 ) { rcerrors = rcerrors | (double)(err/mf)>(double)(10000*AP.Math.MachineEpsilon); } } } } } } } // // report // waserrors = blerrors | bcerrors | dserrors | cperrors | uperrors | lterrors | syerrors | rlerrors | rcerrors; if( !silent ) { System.Console.Write("TESTING 2D INTERPOLATION"); System.Console.WriteLine(); // // Normal tests // System.Console.Write("BILINEAR TEST: "); if( blerrors ) { System.Console.Write("FAILED"); System.Console.WriteLine(); } else { System.Console.Write("OK"); System.Console.WriteLine(); } System.Console.Write("BICUBIC TEST: "); if( bcerrors ) { System.Console.Write("FAILED"); System.Console.WriteLine(); } else { System.Console.Write("OK"); System.Console.WriteLine(); } System.Console.Write("DIFFERENTIATION TEST: "); if( dserrors ) { System.Console.Write("FAILED"); System.Console.WriteLine(); } else { System.Console.Write("OK"); System.Console.WriteLine(); } System.Console.Write("COPY/SERIALIZE TEST: "); if( cperrors ) { System.Console.Write("FAILED"); System.Console.WriteLine(); } else { System.Console.Write("OK"); System.Console.WriteLine(); } System.Console.Write("UNPACK TEST: "); if( uperrors ) { System.Console.Write("FAILED"); System.Console.WriteLine(); } else { System.Console.Write("OK"); System.Console.WriteLine(); } System.Console.Write("LIN.TRANS. TEST: "); if( lterrors ) { System.Console.Write("FAILED"); System.Console.WriteLine(); } else { System.Console.Write("OK"); System.Console.WriteLine(); } System.Console.Write("SPECIAL SYMMETRY TEST: "); if( syerrors ) { System.Console.Write("FAILED"); System.Console.WriteLine(); } else { System.Console.Write("OK"); System.Console.WriteLine(); } System.Console.Write("BILINEAR RESAMPLING TEST: "); if( rlerrors ) { System.Console.Write("FAILED"); System.Console.WriteLine(); } else { System.Console.Write("OK"); System.Console.WriteLine(); } System.Console.Write("BICUBIC RESAMPLING TEST: "); if( rcerrors ) { System.Console.Write("FAILED"); System.Console.WriteLine(); } else { System.Console.Write("OK"); System.Console.WriteLine(); } // // Summary // if( waserrors ) { System.Console.Write("TEST FAILED"); System.Console.WriteLine(); } else { System.Console.Write("TEST PASSED"); System.Console.WriteLine(); } System.Console.WriteLine(); System.Console.WriteLine(); } // // end // result = !waserrors; return result; }
/************************************************************************* * LinTrans test *************************************************************************/ private static bool testlintrans(ref spline2d.spline2dinterpolant c, double ax, double bx, double ay, double by) { bool result = new bool(); double err = 0; double a1 = 0; double a2 = 0; double b1 = 0; double b2 = 0; double tx = 0; double ty = 0; double vx = 0; double vy = 0; double v1 = 0; double v2 = 0; int pass = 0; int passcount = 0; int xjob = 0; int yjob = 0; spline2d.spline2dinterpolant c2 = new spline2d.spline2dinterpolant(); passcount = 5; err = 0; for (xjob = 0; xjob <= 1; xjob++) { for (yjob = 0; yjob <= 1; yjob++) { for (pass = 1; pass <= passcount; pass++) { // // Prepare // do { a1 = 2 * AP.Math.RandomReal() - 1; }while((double)(a1) == (double)(0)); a1 = a1 * xjob; b1 = 2 * AP.Math.RandomReal() - 1; do { a2 = 2 * AP.Math.RandomReal() - 1; }while((double)(a2) == (double)(0)); a2 = a2 * yjob; b2 = 2 * AP.Math.RandomReal() - 1; // // Test XY // spline2d.spline2dcopy(ref c, ref c2); spline2d.spline2dlintransxy(ref c2, a1, b1, a2, b2); tx = ax + AP.Math.RandomReal() * (bx - ax); ty = ay + AP.Math.RandomReal() * (by - ay); if (xjob == 0) { tx = b1; vx = ax + AP.Math.RandomReal() * (bx - ax); } else { vx = (tx - b1) / a1; } if (yjob == 0) { ty = b2; vy = ay + AP.Math.RandomReal() * (by - ay); } else { vy = (ty - b2) / a2; } v1 = spline2d.spline2dcalc(ref c, tx, ty); v2 = spline2d.spline2dcalc(ref c2, vx, vy); err = Math.Max(err, Math.Abs(v1 - v2)); // // Test F // spline2d.spline2dcopy(ref c, ref c2); spline2d.spline2dlintransf(ref c2, a1, b1); tx = ax + AP.Math.RandomReal() * (bx - ax); ty = ay + AP.Math.RandomReal() * (by - ay); v1 = spline2d.spline2dcalc(ref c, tx, ty); v2 = spline2d.spline2dcalc(ref c2, tx, ty); err = Math.Max(err, Math.Abs(a1 * v1 + b1 - v2)); } } } result = (double)(err) < (double)(10000 * AP.Math.MachineEpsilon); return(result); }
/************************************************************************* * Unpack test *************************************************************************/ private static bool testunpack(ref spline2d.spline2dinterpolant c, ref double[] lx, ref double[] ly) { bool result = new bool(); int i = 0; int j = 0; int n = 0; int m = 0; int ci = 0; int cj = 0; int p = 0; double err = 0; double tx = 0; double ty = 0; double v1 = 0; double v2 = 0; int pass = 0; int passcount = 0; double[,] tbl = new double[0, 0]; passcount = 20; err = 0; spline2d.spline2dunpack(ref c, ref m, ref n, ref tbl); for (i = 0; i <= m - 2; i++) { for (j = 0; j <= n - 2; j++) { for (pass = 1; pass <= passcount; pass++) { p = (n - 1) * i + j; tx = (0.001 + 0.999 * AP.Math.RandomReal()) * (tbl[p, 1] - tbl[p, 0]); ty = (0.001 + 0.999 * AP.Math.RandomReal()) * (tbl[p, 3] - tbl[p, 2]); // // Interpolation properties // v1 = 0; for (ci = 0; ci <= 3; ci++) { for (cj = 0; cj <= 3; cj++) { v1 = v1 + tbl[p, 4 + ci * 4 + cj] * Math.Pow(tx, ci) * Math.Pow(ty, cj); } } v2 = spline2d.spline2dcalc(ref c, tbl[p, 0] + tx, tbl[p, 2] + ty); err = Math.Max(err, Math.Abs(v1 - v2)); // // Grid correctness // err = Math.Max(err, Math.Abs(lx[2 * j] - tbl[p, 0])); err = Math.Max(err, Math.Abs(lx[2 * (j + 1)] - tbl[p, 1])); err = Math.Max(err, Math.Abs(ly[2 * i] - tbl[p, 2])); err = Math.Max(err, Math.Abs(ly[2 * (i + 1)] - tbl[p, 3])); } } } result = (double)(err) < (double)(10000 * AP.Math.MachineEpsilon); return(result); }
public static bool test2dinterpolation(bool silent) { bool result = new bool(); bool waserrors = new bool(); bool blerrors = new bool(); bool bcerrors = new bool(); bool dserrors = new bool(); bool cperrors = new bool(); bool uperrors = new bool(); bool lterrors = new bool(); bool syerrors = new bool(); bool rlerrors = new bool(); bool rcerrors = new bool(); int pass = 0; int passcount = 0; int jobtype = 0; double lstep = 0; double h = 0; double[] x = new double[0]; double[] y = new double[0]; spline2d.spline2dinterpolant c = new spline2d.spline2dinterpolant(); spline2d.spline2dinterpolant c2 = new spline2d.spline2dinterpolant(); double[] lx = new double[0]; double[] ly = new double[0]; double[,] f = new double[0, 0]; double[,] fr = new double[0, 0]; double[,] ft = new double[0, 0]; double ax = 0; double ay = 0; double bx = 0; double by = 0; int i = 0; int j = 0; int k = 0; int n = 0; int m = 0; int n2 = 0; int m2 = 0; double err = 0; double t = 0; double t1 = 0; double t2 = 0; double l1 = 0; double l1x = 0; double l1y = 0; double l1xy = 0; double l2 = 0; double l2x = 0; double l2y = 0; double l2xy = 0; double fm = 0; double f1 = 0; double f2 = 0; double f3 = 0; double f4 = 0; double v1 = 0; double v1x = 0; double v1y = 0; double v1xy = 0; double v2 = 0; double v2x = 0; double v2y = 0; double v2xy = 0; double mf = 0; double[] ra = new double[0]; double[] ra2 = new double[0]; int ralen = 0; int i_ = 0; waserrors = false; passcount = 10; h = 0.00001; lstep = 0.001; blerrors = false; bcerrors = false; dserrors = false; cperrors = false; uperrors = false; lterrors = false; syerrors = false; rlerrors = false; rcerrors = false; // // Test: bilinear, bicubic // for (n = 2; n <= 7; n++) { for (m = 2; m <= 7; m++) { x = new double[n - 1 + 1]; y = new double[m - 1 + 1]; lx = new double[2 * n - 2 + 1]; ly = new double[2 * m - 2 + 1]; f = new double[m - 1 + 1, n - 1 + 1]; ft = new double[n - 1 + 1, m - 1 + 1]; for (pass = 1; pass <= passcount; pass++) { // // Prepare task: // * X and Y stores grid // * F stores function values // * LX and LY stores twice dense grid (for Lipschitz testing) // ax = -1 - AP.Math.RandomReal(); bx = +1 + AP.Math.RandomReal(); ay = -1 - AP.Math.RandomReal(); by = +1 + AP.Math.RandomReal(); for (j = 0; j <= n - 1; j++) { x[j] = 0.5 * (bx + ax) - 0.5 * (bx - ax) * Math.Cos(Math.PI * (2 * j + 1) / (2 * n)); if (j == 0) { x[j] = ax; } if (j == n - 1) { x[j] = bx; } lx[2 * j] = x[j]; if (j > 0) { lx[2 * j - 1] = 0.5 * (x[j] + x[j - 1]); } } for (j = 0; j <= n - 1; j++) { k = AP.Math.RandomInteger(n); if (k != j) { t = x[j]; x[j] = x[k]; x[k] = t; } } for (i = 0; i <= m - 1; i++) { y[i] = 0.5 * (by + ay) - 0.5 * (by - ay) * Math.Cos(Math.PI * (2 * i + 1) / (2 * m)); if (i == 0) { y[i] = ay; } if (i == m - 1) { y[i] = by; } ly[2 * i] = y[i]; if (i > 0) { ly[2 * i - 1] = 0.5 * (y[i] + y[i - 1]); } } for (i = 0; i <= m - 1; i++) { k = AP.Math.RandomInteger(m); if (k != i) { t = y[i]; y[i] = y[k]; y[k] = t; } } for (i = 0; i <= m - 1; i++) { for (j = 0; j <= n - 1; j++) { f[i, j] = Math.Exp(0.6 * x[j]) - Math.Exp(-(0.3 * y[i]) + 0.08 * x[j]) + 2 * Math.Cos(Math.PI * (x[j] + 1.2 * y[i])) + 0.1 * Math.Cos(20 * x[j] + 15 * y[i]); } } // // Test bilinear interpolation: // * interpolation at the nodes // * linearity // * continuity // * differentiation in the inner points // spline2d.spline2dbuildbilinear(x, y, f, m, n, ref c); err = 0; for (i = 0; i <= m - 1; i++) { for (j = 0; j <= n - 1; j++) { err = Math.Max(err, Math.Abs(f[i, j] - spline2d.spline2dcalc(ref c, x[j], y[i]))); } } blerrors = blerrors | (double)(err) > (double)(10000 * AP.Math.MachineEpsilon); err = 0; for (i = 0; i <= m - 2; i++) { for (j = 0; j <= n - 2; j++) { // // Test for linearity between grid points // (test point - geometric center of the cell) // fm = spline2d.spline2dcalc(ref c, lx[2 * j + 1], ly[2 * i + 1]); f1 = spline2d.spline2dcalc(ref c, lx[2 * j], ly[2 * i]); f2 = spline2d.spline2dcalc(ref c, lx[2 * j + 2], ly[2 * i]); f3 = spline2d.spline2dcalc(ref c, lx[2 * j + 2], ly[2 * i + 2]); f4 = spline2d.spline2dcalc(ref c, lx[2 * j], ly[2 * i + 2]); err = Math.Max(err, Math.Abs(0.25 * (f1 + f2 + f3 + f4) - fm)); } } blerrors = blerrors | (double)(err) > (double)(10000 * AP.Math.MachineEpsilon); lconst(ref c, ref lx, ref ly, m, n, lstep, ref l1, ref l1x, ref l1y, ref l1xy); lconst(ref c, ref lx, ref ly, m, n, lstep / 3, ref l2, ref l2x, ref l2y, ref l2xy); blerrors = blerrors | (double)(l2 / l1) > (double)(1.2); err = 0; for (i = 0; i <= m - 2; i++) { for (j = 0; j <= n - 2; j++) { spline2d.spline2ddiff(ref c, lx[2 * j + 1], ly[2 * i + 1], ref v1, ref v1x, ref v1y, ref v1xy); twodnumder(ref c, lx[2 * j + 1], ly[2 * i + 1], h, ref v2, ref v2x, ref v2y, ref v2xy); err = Math.Max(err, Math.Abs(v1 - v2)); err = Math.Max(err, Math.Abs(v1x - v2x)); err = Math.Max(err, Math.Abs(v1y - v2y)); err = Math.Max(err, Math.Abs(v1xy - v2xy)); } } dserrors = dserrors | (double)(err) > (double)(1.0E-3); uperrors = uperrors | !testunpack(ref c, ref lx, ref ly); lterrors = lterrors | !testlintrans(ref c, ax, bx, ay, by); // // Test bicubic interpolation. // * interpolation at the nodes // * smoothness // * differentiation // spline2d.spline2dbuildbicubic(x, y, f, m, n, ref c); err = 0; for (i = 0; i <= m - 1; i++) { for (j = 0; j <= n - 1; j++) { err = Math.Max(err, Math.Abs(f[i, j] - spline2d.spline2dcalc(ref c, x[j], y[i]))); } } bcerrors = bcerrors | (double)(err) > (double)(10000 * AP.Math.MachineEpsilon); lconst(ref c, ref lx, ref ly, m, n, lstep, ref l1, ref l1x, ref l1y, ref l1xy); lconst(ref c, ref lx, ref ly, m, n, lstep / 3, ref l2, ref l2x, ref l2y, ref l2xy); bcerrors = bcerrors | (double)(l2 / l1) > (double)(1.2); bcerrors = bcerrors | (double)(l2x / l1x) > (double)(1.2); bcerrors = bcerrors | (double)(l2y / l1y) > (double)(1.2); if ((double)(l2xy) > (double)(0.01) & (double)(l1xy) > (double)(0.01)) { // // Cross-derivative continuity is tested only when // bigger than 0.01. When the task size is too // small, the d2F/dXdY is nearly zero and Lipschitz // constant ratio is ill-conditioned. // bcerrors = bcerrors | (double)(l2xy / l1xy) > (double)(1.2); } err = 0; for (i = 0; i <= 2 * m - 2; i++) { for (j = 0; j <= 2 * n - 2; j++) { spline2d.spline2ddiff(ref c, lx[j], ly[i], ref v1, ref v1x, ref v1y, ref v1xy); twodnumder(ref c, lx[j], ly[i], h, ref v2, ref v2x, ref v2y, ref v2xy); err = Math.Max(err, Math.Abs(v1 - v2)); err = Math.Max(err, Math.Abs(v1x - v2x)); err = Math.Max(err, Math.Abs(v1y - v2y)); err = Math.Max(err, Math.Abs(v1xy - v2xy)); } } dserrors = dserrors | (double)(err) > (double)(1.0E-3); uperrors = uperrors | !testunpack(ref c, ref lx, ref ly); lterrors = lterrors | !testlintrans(ref c, ax, bx, ay, by); // // Copy/Serialise test // if ((double)(AP.Math.RandomReal()) > (double)(0.5)) { spline2d.spline2dbuildbicubic(x, y, f, m, n, ref c); } else { spline2d.spline2dbuildbilinear(x, y, f, m, n, ref c); } unsetspline2d(ref c2); spline2d.spline2dcopy(ref c, ref c2); err = 0; for (i = 1; i <= 5; i++) { t1 = ax + (bx - ax) * AP.Math.RandomReal(); t2 = ay + (by - ay) * AP.Math.RandomReal(); err = Math.Max(err, Math.Abs(spline2d.spline2dcalc(ref c, t1, t2) - spline2d.spline2dcalc(ref c2, t1, t2))); } cperrors = cperrors | (double)(err) > (double)(10000 * AP.Math.MachineEpsilon); unsetspline2d(ref c2); spline2d.spline2dserialize(ref c, ref ra, ref ralen); ra2 = new double[ralen]; for (i_ = 0; i_ <= ralen - 1; i_++) { ra2[i_] = ra[i_]; } spline2d.spline2dunserialize(ref ra2, ref c2); err = 0; for (i = 1; i <= 5; i++) { t1 = ax + (bx - ax) * AP.Math.RandomReal(); t2 = ay + (by - ay) * AP.Math.RandomReal(); err = Math.Max(err, Math.Abs(spline2d.spline2dcalc(ref c, t1, t2) - spline2d.spline2dcalc(ref c2, t1, t2))); } cperrors = cperrors | (double)(err) > (double)(10000 * AP.Math.MachineEpsilon); // // Special symmetry test // err = 0; for (jobtype = 0; jobtype <= 1; jobtype++) { // // Prepare // for (i = 0; i <= m - 1; i++) { for (j = 0; j <= n - 1; j++) { ft[j, i] = f[i, j]; } } if (jobtype == 0) { spline2d.spline2dbuildbilinear(x, y, f, m, n, ref c); spline2d.spline2dbuildbilinear(y, x, ft, n, m, ref c2); } else { spline2d.spline2dbuildbicubic(x, y, f, m, n, ref c); spline2d.spline2dbuildbicubic(y, x, ft, n, m, ref c2); } // // Test // for (i = 1; i <= 10; i++) { t1 = ax + (bx - ax) * AP.Math.RandomReal(); t2 = ay + (by - ay) * AP.Math.RandomReal(); err = Math.Max(err, Math.Abs(spline2d.spline2dcalc(ref c, t1, t2) - spline2d.spline2dcalc(ref c2, t2, t1))); } } syerrors = syerrors | (double)(err) > (double)(10000 * AP.Math.MachineEpsilon); } } } // // Test resample // for (m = 2; m <= 6; m++) { for (n = 2; n <= 6; n++) { f = new double[m - 1 + 1, n - 1 + 1]; x = new double[n - 1 + 1]; y = new double[m - 1 + 1]; for (j = 0; j <= n - 1; j++) { x[j] = (double)(j) / ((double)(n - 1)); } for (i = 0; i <= m - 1; i++) { y[i] = (double)(i) / ((double)(m - 1)); } for (i = 0; i <= m - 1; i++) { for (j = 0; j <= n - 1; j++) { f[i, j] = Math.Exp(0.6 * x[j]) - Math.Exp(-(0.3 * y[i]) + 0.08 * x[j]) + 2 * Math.Cos(Math.PI * (x[j] + 1.2 * y[i])) + 0.1 * Math.Cos(20 * x[j] + 15 * y[i]); } } for (m2 = 2; m2 <= 6; m2++) { for (n2 = 2; n2 <= 6; n2++) { for (pass = 1; pass <= passcount; pass++) { for (jobtype = 0; jobtype <= 1; jobtype++) { if (jobtype == 0) { spline2d.spline2dresamplebilinear(ref f, m, n, ref fr, m2, n2); spline2d.spline2dbuildbilinear(x, y, f, m, n, ref c); } if (jobtype == 1) { spline2d.spline2dresamplebicubic(ref f, m, n, ref fr, m2, n2); spline2d.spline2dbuildbicubic(x, y, f, m, n, ref c); } err = 0; mf = 0; for (i = 0; i <= m2 - 1; i++) { for (j = 0; j <= n2 - 1; j++) { v1 = spline2d.spline2dcalc(ref c, (double)(j) / ((double)(n2 - 1)), (double)(i) / ((double)(m2 - 1))); v2 = fr[i, j]; err = Math.Max(err, Math.Abs(v1 - v2)); mf = Math.Max(mf, Math.Abs(v1)); } } if (jobtype == 0) { rlerrors = rlerrors | (double)(err / mf) > (double)(10000 * AP.Math.MachineEpsilon); } if (jobtype == 1) { rcerrors = rcerrors | (double)(err / mf) > (double)(10000 * AP.Math.MachineEpsilon); } } } } } } } // // report // waserrors = blerrors | bcerrors | dserrors | cperrors | uperrors | lterrors | syerrors | rlerrors | rcerrors; if (!silent) { System.Console.Write("TESTING 2D INTERPOLATION"); System.Console.WriteLine(); // // Normal tests // System.Console.Write("BILINEAR TEST: "); if (blerrors) { System.Console.Write("FAILED"); System.Console.WriteLine(); } else { System.Console.Write("OK"); System.Console.WriteLine(); } System.Console.Write("BICUBIC TEST: "); if (bcerrors) { System.Console.Write("FAILED"); System.Console.WriteLine(); } else { System.Console.Write("OK"); System.Console.WriteLine(); } System.Console.Write("DIFFERENTIATION TEST: "); if (dserrors) { System.Console.Write("FAILED"); System.Console.WriteLine(); } else { System.Console.Write("OK"); System.Console.WriteLine(); } System.Console.Write("COPY/SERIALIZE TEST: "); if (cperrors) { System.Console.Write("FAILED"); System.Console.WriteLine(); } else { System.Console.Write("OK"); System.Console.WriteLine(); } System.Console.Write("UNPACK TEST: "); if (uperrors) { System.Console.Write("FAILED"); System.Console.WriteLine(); } else { System.Console.Write("OK"); System.Console.WriteLine(); } System.Console.Write("LIN.TRANS. TEST: "); if (lterrors) { System.Console.Write("FAILED"); System.Console.WriteLine(); } else { System.Console.Write("OK"); System.Console.WriteLine(); } System.Console.Write("SPECIAL SYMMETRY TEST: "); if (syerrors) { System.Console.Write("FAILED"); System.Console.WriteLine(); } else { System.Console.Write("OK"); System.Console.WriteLine(); } System.Console.Write("BILINEAR RESAMPLING TEST: "); if (rlerrors) { System.Console.Write("FAILED"); System.Console.WriteLine(); } else { System.Console.Write("OK"); System.Console.WriteLine(); } System.Console.Write("BICUBIC RESAMPLING TEST: "); if (rcerrors) { System.Console.Write("FAILED"); System.Console.WriteLine(); } else { System.Console.Write("OK"); System.Console.WriteLine(); } // // Summary // if (waserrors) { System.Console.Write("TEST FAILED"); System.Console.WriteLine(); } else { System.Console.Write("TEST PASSED"); System.Console.WriteLine(); } System.Console.WriteLine(); System.Console.WriteLine(); } // // end // result = !waserrors; return(result); }
/************************************************************************* * Lipschitz constants for spline inself, first and second derivatives. *************************************************************************/ private static void lconst(ref spline2d.spline2dinterpolant c, ref double[] lx, ref double[] ly, int m, int n, double lstep, ref double lc, ref double lcx, ref double lcy, ref double lcxy) { int i = 0; int j = 0; double f1 = 0; double f2 = 0; double f3 = 0; double f4 = 0; double fx1 = 0; double fx2 = 0; double fx3 = 0; double fx4 = 0; double fy1 = 0; double fy2 = 0; double fy3 = 0; double fy4 = 0; double fxy1 = 0; double fxy2 = 0; double fxy3 = 0; double fxy4 = 0; double s2lstep = 0; lc = 0; lcx = 0; lcy = 0; lcxy = 0; s2lstep = Math.Sqrt(2) * lstep; for (i = 0; i <= m - 1; i++) { for (j = 0; j <= n - 1; j++) { // // Calculate // twodnumder(ref c, lx[j] - lstep / 2, ly[i] - lstep / 2, lstep / 4, ref f1, ref fx1, ref fy1, ref fxy1); twodnumder(ref c, lx[j] + lstep / 2, ly[i] - lstep / 2, lstep / 4, ref f2, ref fx2, ref fy2, ref fxy2); twodnumder(ref c, lx[j] + lstep / 2, ly[i] + lstep / 2, lstep / 4, ref f3, ref fx3, ref fy3, ref fxy3); twodnumder(ref c, lx[j] - lstep / 2, ly[i] + lstep / 2, lstep / 4, ref f4, ref fx4, ref fy4, ref fxy4); // // Lipschitz constant for the function itself // lc = Math.Max(lc, Math.Abs((f1 - f2) / lstep)); lc = Math.Max(lc, Math.Abs((f2 - f3) / lstep)); lc = Math.Max(lc, Math.Abs((f3 - f4) / lstep)); lc = Math.Max(lc, Math.Abs((f4 - f1) / lstep)); lc = Math.Max(lc, Math.Abs((f1 - f3) / s2lstep)); lc = Math.Max(lc, Math.Abs((f2 - f4) / s2lstep)); // // Lipschitz constant for the first derivative // lcx = Math.Max(lcx, Math.Abs((fx1 - fx2) / lstep)); lcx = Math.Max(lcx, Math.Abs((fx2 - fx3) / lstep)); lcx = Math.Max(lcx, Math.Abs((fx3 - fx4) / lstep)); lcx = Math.Max(lcx, Math.Abs((fx4 - fx1) / lstep)); lcx = Math.Max(lcx, Math.Abs((fx1 - fx3) / s2lstep)); lcx = Math.Max(lcx, Math.Abs((fx2 - fx4) / s2lstep)); // // Lipschitz constant for the first derivative // lcy = Math.Max(lcy, Math.Abs((fy1 - fy2) / lstep)); lcy = Math.Max(lcy, Math.Abs((fy2 - fy3) / lstep)); lcy = Math.Max(lcy, Math.Abs((fy3 - fy4) / lstep)); lcy = Math.Max(lcy, Math.Abs((fy4 - fy1) / lstep)); lcy = Math.Max(lcy, Math.Abs((fy1 - fy3) / s2lstep)); lcy = Math.Max(lcy, Math.Abs((fy2 - fy4) / s2lstep)); // // Lipschitz constant for the cross-derivative // lcxy = Math.Max(lcxy, Math.Abs((fxy1 - fxy2) / lstep)); lcxy = Math.Max(lcxy, Math.Abs((fxy2 - fxy3) / lstep)); lcxy = Math.Max(lcxy, Math.Abs((fxy3 - fxy4) / lstep)); lcxy = Math.Max(lcxy, Math.Abs((fxy4 - fxy1) / lstep)); lcxy = Math.Max(lcxy, Math.Abs((fxy1 - fxy3) / s2lstep)); lcxy = Math.Max(lcxy, Math.Abs((fxy2 - fxy4) / s2lstep)); } } }