/************************************************************************* 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; }
/************************************************************************* 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); }
/************************************************************************* 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; }
/************************************************************************* 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)); } } }