public pspline2interpolant(pspline.pspline2interpolant obj) { _innerobj = obj; }
public static bool testpspline(bool silent) { bool result = new bool(); bool waserrors = new bool(); bool p2errors = new bool(); bool p3errors = new bool(); double nonstrictthreshold = 0; double threshold = 0; int passcount = 0; double lstep = 0; double h = 0; int maxn = 0; int periodicity = 0; int skind = 0; int pkind = 0; bool periodic = new bool(); double a = 0; double b = 0; int n = 0; int tmpn = 0; int i = 0; double vx = 0; double vy = 0; double vz = 0; double vx2 = 0; double vy2 = 0; double vz2 = 0; double vdx = 0; double vdy = 0; double vdz = 0; double vdx2 = 0; double vdy2 = 0; double vdz2 = 0; double vd2x = 0; double vd2y = 0; double vd2z = 0; double vd2x2 = 0; double vd2y2 = 0; double vd2z2 = 0; double v0 = 0; double v1 = 0; double[] x = new double[0]; double[] y = new double[0]; double[] z = new double[0]; double[] t = new double[0]; double[] t2 = new double[0]; double[] t3 = new double[0]; double[,] xy = new double[0,0]; double[,] xyz = new double[0,0]; pspline.pspline2interpolant p2 = new pspline.pspline2interpolant(); pspline.pspline3interpolant p3 = new pspline.pspline3interpolant(); spline1d.spline1dinterpolant s = new spline1d.spline1dinterpolant(); int i_ = 0; waserrors = false; passcount = 20; lstep = 0.005; h = 0.00001; maxn = 10; threshold = 10000*math.machineepsilon; nonstrictthreshold = 0.00001; p2errors = false; p3errors = false; // // Test basic properties of 2- and 3-dimensional splines: // * PSpline2ParameterValues() properties // * values at nodes // * for periodic splines - periodicity properties // // Variables used: // * N points count // * SKind spline // * PKind parameterization // * Periodicity whether we have periodic spline or not // for(n=2; n<=maxn; n++) { for(skind=0; skind<=2; skind++) { for(pkind=0; pkind<=2; pkind++) { for(periodicity=0; periodicity<=1; periodicity++) { periodic = periodicity==1; // // skip unsupported combinations of parameters // if( periodic & n<3 ) { continue; } if( periodic & skind==0 ) { continue; } if( n<5 & skind==0 ) { continue; } // // init // xy = new double[n, 2]; xyz = new double[n, 3]; apserv.taskgenint1dequidist(-1, 1, n, ref t2, ref x); for(i_=0; i_<=n-1;i_++) { xy[i_,0] = x[i_]; } for(i_=0; i_<=n-1;i_++) { xyz[i_,0] = x[i_]; } apserv.taskgenint1dequidist(-1, 1, n, ref t2, ref y); for(i_=0; i_<=n-1;i_++) { xy[i_,1] = y[i_]; } for(i_=0; i_<=n-1;i_++) { xyz[i_,1] = y[i_]; } apserv.taskgenint1dequidist(-1, 1, n, ref t2, ref z); for(i_=0; i_<=n-1;i_++) { xyz[i_,2] = z[i_]; } unsetp2(p2); unsetp3(p3); if( periodic ) { pspline.pspline2buildperiodic(xy, n, skind, pkind, p2); pspline.pspline3buildperiodic(xyz, n, skind, pkind, p3); } else { pspline.pspline2build(xy, n, skind, pkind, p2); pspline.pspline3build(xyz, n, skind, pkind, p3); } // // PSpline2ParameterValues() properties // pspline.pspline2parametervalues(p2, ref tmpn, ref t2); if( tmpn!=n ) { p2errors = true; continue; } pspline.pspline3parametervalues(p3, ref tmpn, ref t3); if( tmpn!=n ) { p3errors = true; continue; } p2errors = p2errors | (double)(t2[0])!=(double)(0); p3errors = p3errors | (double)(t3[0])!=(double)(0); for(i=1; i<=n-1; i++) { p2errors = p2errors | (double)(t2[i])<=(double)(t2[i-1]); p3errors = p3errors | (double)(t3[i])<=(double)(t3[i-1]); } if( periodic ) { p2errors = p2errors | (double)(t2[n-1])>=(double)(1); p3errors = p3errors | (double)(t3[n-1])>=(double)(1); } else { p2errors = p2errors | (double)(t2[n-1])!=(double)(1); p3errors = p3errors | (double)(t3[n-1])!=(double)(1); } // // Now we have parameter values stored at T, // and want to test whether the actully correspond to // points // for(i=0; i<=n-1; i++) { // // 2-dimensional test // pspline.pspline2calc(p2, t2[i], ref vx, ref vy); p2errors = p2errors | (double)(Math.Abs(vx-x[i]))>(double)(threshold); p2errors = p2errors | (double)(Math.Abs(vy-y[i]))>(double)(threshold); // // 3-dimensional test // pspline.pspline3calc(p3, t3[i], ref vx, ref vy, ref vz); p3errors = p3errors | (double)(Math.Abs(vx-x[i]))>(double)(threshold); p3errors = p3errors | (double)(Math.Abs(vy-y[i]))>(double)(threshold); p3errors = p3errors | (double)(Math.Abs(vz-z[i]))>(double)(threshold); } // // Test periodicity (if needed) // if( periodic ) { // // periodicity at nodes // for(i=0; i<=n-1; i++) { // // 2-dimensional test // pspline.pspline2calc(p2, t2[i]+math.randominteger(10)-5, ref vx, ref vy); p2errors = p2errors | (double)(Math.Abs(vx-x[i]))>(double)(threshold); p2errors = p2errors | (double)(Math.Abs(vy-y[i]))>(double)(threshold); pspline.pspline2diff(p2, t2[i]+math.randominteger(10)-5, ref vx, ref vdx, ref vy, ref vdy); p2errors = p2errors | (double)(Math.Abs(vx-x[i]))>(double)(threshold); p2errors = p2errors | (double)(Math.Abs(vy-y[i]))>(double)(threshold); pspline.pspline2diff2(p2, t2[i]+math.randominteger(10)-5, ref vx, ref vdx, ref vd2x, ref vy, ref vdy, ref vd2y); p2errors = p2errors | (double)(Math.Abs(vx-x[i]))>(double)(threshold); p2errors = p2errors | (double)(Math.Abs(vy-y[i]))>(double)(threshold); // // 3-dimensional test // pspline.pspline3calc(p3, t3[i]+math.randominteger(10)-5, ref vx, ref vy, ref vz); p3errors = p3errors | (double)(Math.Abs(vx-x[i]))>(double)(threshold); p3errors = p3errors | (double)(Math.Abs(vy-y[i]))>(double)(threshold); p3errors = p3errors | (double)(Math.Abs(vz-z[i]))>(double)(threshold); pspline.pspline3diff(p3, t3[i]+math.randominteger(10)-5, ref vx, ref vdx, ref vy, ref vdy, ref vz, ref vdz); p3errors = p3errors | (double)(Math.Abs(vx-x[i]))>(double)(threshold); p3errors = p3errors | (double)(Math.Abs(vy-y[i]))>(double)(threshold); p3errors = p3errors | (double)(Math.Abs(vz-z[i]))>(double)(threshold); pspline.pspline3diff2(p3, t3[i]+math.randominteger(10)-5, ref vx, ref vdx, ref vd2x, ref vy, ref vdy, ref vd2y, ref vz, ref vdz, ref vd2z); p3errors = p3errors | (double)(Math.Abs(vx-x[i]))>(double)(threshold); p3errors = p3errors | (double)(Math.Abs(vy-y[i]))>(double)(threshold); p3errors = p3errors | (double)(Math.Abs(vz-z[i]))>(double)(threshold); } // // periodicity between nodes // v0 = math.randomreal(); pspline.pspline2calc(p2, v0, ref vx, ref vy); pspline.pspline2calc(p2, v0+math.randominteger(10)-5, ref vx2, ref vy2); p2errors = p2errors | (double)(Math.Abs(vx-vx2))>(double)(threshold); p2errors = p2errors | (double)(Math.Abs(vy-vy2))>(double)(threshold); pspline.pspline3calc(p3, v0, ref vx, ref vy, ref vz); pspline.pspline3calc(p3, v0+math.randominteger(10)-5, ref vx2, ref vy2, ref vz2); p3errors = p3errors | (double)(Math.Abs(vx-vx2))>(double)(threshold); p3errors = p3errors | (double)(Math.Abs(vy-vy2))>(double)(threshold); p3errors = p3errors | (double)(Math.Abs(vz-vz2))>(double)(threshold); // // near-boundary test for continuity of function values and derivatives: // 2-dimensional curve // ap.assert(skind==1 | skind==2, "TEST: unexpected spline type!"); v0 = 100*math.machineepsilon; v1 = 1-v0; pspline.pspline2calc(p2, v0, ref vx, ref vy); pspline.pspline2calc(p2, v1, ref vx2, ref vy2); p2errors = p2errors | (double)(Math.Abs(vx-vx2))>(double)(threshold); p2errors = p2errors | (double)(Math.Abs(vy-vy2))>(double)(threshold); pspline.pspline2diff(p2, v0, ref vx, ref vdx, ref vy, ref vdy); pspline.pspline2diff(p2, v1, ref vx2, ref vdx2, ref vy2, ref vdy2); p2errors = p2errors | (double)(Math.Abs(vx-vx2))>(double)(threshold); p2errors = p2errors | (double)(Math.Abs(vy-vy2))>(double)(threshold); p2errors = p2errors | (double)(Math.Abs(vdx-vdx2))>(double)(nonstrictthreshold); p2errors = p2errors | (double)(Math.Abs(vdy-vdy2))>(double)(nonstrictthreshold); pspline.pspline2diff2(p2, v0, ref vx, ref vdx, ref vd2x, ref vy, ref vdy, ref vd2y); pspline.pspline2diff2(p2, v1, ref vx2, ref vdx2, ref vd2x2, ref vy2, ref vdy2, ref vd2y2); p2errors = p2errors | (double)(Math.Abs(vx-vx2))>(double)(threshold); p2errors = p2errors | (double)(Math.Abs(vy-vy2))>(double)(threshold); p2errors = p2errors | (double)(Math.Abs(vdx-vdx2))>(double)(nonstrictthreshold); p2errors = p2errors | (double)(Math.Abs(vdy-vdy2))>(double)(nonstrictthreshold); if( skind==2 ) { // // second derivative test only for cubic splines // p2errors = p2errors | (double)(Math.Abs(vd2x-vd2x2))>(double)(nonstrictthreshold); p2errors = p2errors | (double)(Math.Abs(vd2y-vd2y2))>(double)(nonstrictthreshold); } // // near-boundary test for continuity of function values and derivatives: // 3-dimensional curve // ap.assert(skind==1 | skind==2, "TEST: unexpected spline type!"); v0 = 100*math.machineepsilon; v1 = 1-v0; pspline.pspline3calc(p3, v0, ref vx, ref vy, ref vz); pspline.pspline3calc(p3, v1, ref vx2, ref vy2, ref vz2); p3errors = p3errors | (double)(Math.Abs(vx-vx2))>(double)(threshold); p3errors = p3errors | (double)(Math.Abs(vy-vy2))>(double)(threshold); p3errors = p3errors | (double)(Math.Abs(vz-vz2))>(double)(threshold); pspline.pspline3diff(p3, v0, ref vx, ref vdx, ref vy, ref vdy, ref vz, ref vdz); pspline.pspline3diff(p3, v1, ref vx2, ref vdx2, ref vy2, ref vdy2, ref vz2, ref vdz2); p3errors = p3errors | (double)(Math.Abs(vx-vx2))>(double)(threshold); p3errors = p3errors | (double)(Math.Abs(vy-vy2))>(double)(threshold); p3errors = p3errors | (double)(Math.Abs(vz-vz2))>(double)(threshold); p3errors = p3errors | (double)(Math.Abs(vdx-vdx2))>(double)(nonstrictthreshold); p3errors = p3errors | (double)(Math.Abs(vdy-vdy2))>(double)(nonstrictthreshold); p3errors = p3errors | (double)(Math.Abs(vdz-vdz2))>(double)(nonstrictthreshold); pspline.pspline3diff2(p3, v0, ref vx, ref vdx, ref vd2x, ref vy, ref vdy, ref vd2y, ref vz, ref vdz, ref vd2z); pspline.pspline3diff2(p3, v1, ref vx2, ref vdx2, ref vd2x2, ref vy2, ref vdy2, ref vd2y2, ref vz2, ref vdz2, ref vd2z2); p3errors = p3errors | (double)(Math.Abs(vx-vx2))>(double)(threshold); p3errors = p3errors | (double)(Math.Abs(vy-vy2))>(double)(threshold); p3errors = p3errors | (double)(Math.Abs(vz-vz2))>(double)(threshold); p3errors = p3errors | (double)(Math.Abs(vdx-vdx2))>(double)(nonstrictthreshold); p3errors = p3errors | (double)(Math.Abs(vdy-vdy2))>(double)(nonstrictthreshold); p3errors = p3errors | (double)(Math.Abs(vdz-vdz2))>(double)(nonstrictthreshold); if( skind==2 ) { // // second derivative test only for cubic splines // p3errors = p3errors | (double)(Math.Abs(vd2x-vd2x2))>(double)(nonstrictthreshold); p3errors = p3errors | (double)(Math.Abs(vd2y-vd2y2))>(double)(nonstrictthreshold); p3errors = p3errors | (double)(Math.Abs(vd2z-vd2z2))>(double)(nonstrictthreshold); } } } } } } // // Test differentiation, tangents, calculation between nodes. // // Because differentiation is done in parameterization/spline/periodicity // oblivious manner, we don't have to test all possible combinations // of spline types and parameterizations. // // Actually we test special combination with properties which allow us // to easily solve this problem: // * 2 (3) variables // * first variable is sampled from equidistant grid on [0,1] // * other variables are random // * uniform parameterization is used // * periodicity - none // * spline type - any (we use cubic splines) // Same problem allows us to test calculation BETWEEN nodes. // for(n=2; n<=maxn; n++) { // // init // xy = new double[n, 2]; xyz = new double[n, 3]; apserv.taskgenint1dequidist(0, 1, n, ref t, ref x); for(i_=0; i_<=n-1;i_++) { xy[i_,0] = x[i_]; } for(i_=0; i_<=n-1;i_++) { xyz[i_,0] = x[i_]; } apserv.taskgenint1dequidist(0, 1, n, ref t, ref y); for(i_=0; i_<=n-1;i_++) { xy[i_,1] = y[i_]; } for(i_=0; i_<=n-1;i_++) { xyz[i_,1] = y[i_]; } apserv.taskgenint1dequidist(0, 1, n, ref t, ref z); for(i_=0; i_<=n-1;i_++) { xyz[i_,2] = z[i_]; } unsetp2(p2); unsetp3(p3); pspline.pspline2build(xy, n, 2, 0, p2); pspline.pspline3build(xyz, n, 2, 0, p3); // // Test 2D/3D spline: // * build non-parametric cubic spline from T and X/Y // * calculate its value and derivatives at V0 // * compare with Spline2Calc/Spline2Diff/Spline2Diff2 // Because of task properties both variants should // return same answer. // v0 = math.randomreal(); spline1d.spline1dbuildcubic(t, x, n, 0, 0.0, 0, 0.0, s); spline1d.spline1ddiff(s, v0, ref vx2, ref vdx2, ref vd2x2); spline1d.spline1dbuildcubic(t, y, n, 0, 0.0, 0, 0.0, s); spline1d.spline1ddiff(s, v0, ref vy2, ref vdy2, ref vd2y2); spline1d.spline1dbuildcubic(t, z, n, 0, 0.0, 0, 0.0, s); spline1d.spline1ddiff(s, v0, ref vz2, ref vdz2, ref vd2z2); // // 2D test // pspline.pspline2calc(p2, v0, ref vx, ref vy); p2errors = p2errors | (double)(Math.Abs(vx-vx2))>(double)(threshold); p2errors = p2errors | (double)(Math.Abs(vy-vy2))>(double)(threshold); pspline.pspline2diff(p2, v0, ref vx, ref vdx, ref vy, ref vdy); p2errors = p2errors | (double)(Math.Abs(vx-vx2))>(double)(threshold); p2errors = p2errors | (double)(Math.Abs(vy-vy2))>(double)(threshold); p2errors = p2errors | (double)(Math.Abs(vdx-vdx2))>(double)(threshold); p2errors = p2errors | (double)(Math.Abs(vdy-vdy2))>(double)(threshold); pspline.pspline2diff2(p2, v0, ref vx, ref vdx, ref vd2x, ref vy, ref vdy, ref vd2y); p2errors = p2errors | (double)(Math.Abs(vx-vx2))>(double)(threshold); p2errors = p2errors | (double)(Math.Abs(vy-vy2))>(double)(threshold); p2errors = p2errors | (double)(Math.Abs(vdx-vdx2))>(double)(threshold); p2errors = p2errors | (double)(Math.Abs(vdy-vdy2))>(double)(threshold); p2errors = p2errors | (double)(Math.Abs(vd2x-vd2x2))>(double)(threshold); p2errors = p2errors | (double)(Math.Abs(vd2y-vd2y2))>(double)(threshold); // // 3D test // pspline.pspline3calc(p3, v0, ref vx, ref vy, ref vz); p3errors = p3errors | (double)(Math.Abs(vx-vx2))>(double)(threshold); p3errors = p3errors | (double)(Math.Abs(vy-vy2))>(double)(threshold); p3errors = p3errors | (double)(Math.Abs(vz-vz2))>(double)(threshold); pspline.pspline3diff(p3, v0, ref vx, ref vdx, ref vy, ref vdy, ref vz, ref vdz); p3errors = p3errors | (double)(Math.Abs(vx-vx2))>(double)(threshold); p3errors = p3errors | (double)(Math.Abs(vy-vy2))>(double)(threshold); p3errors = p3errors | (double)(Math.Abs(vz-vz2))>(double)(threshold); p3errors = p3errors | (double)(Math.Abs(vdx-vdx2))>(double)(threshold); p3errors = p3errors | (double)(Math.Abs(vdy-vdy2))>(double)(threshold); p3errors = p3errors | (double)(Math.Abs(vdz-vdz2))>(double)(threshold); pspline.pspline3diff2(p3, v0, ref vx, ref vdx, ref vd2x, ref vy, ref vdy, ref vd2y, ref vz, ref vdz, ref vd2z); p3errors = p3errors | (double)(Math.Abs(vx-vx2))>(double)(threshold); p3errors = p3errors | (double)(Math.Abs(vy-vy2))>(double)(threshold); p3errors = p3errors | (double)(Math.Abs(vz-vz2))>(double)(threshold); p3errors = p3errors | (double)(Math.Abs(vdx-vdx2))>(double)(threshold); p3errors = p3errors | (double)(Math.Abs(vdy-vdy2))>(double)(threshold); p3errors = p3errors | (double)(Math.Abs(vdz-vdz2))>(double)(threshold); p3errors = p3errors | (double)(Math.Abs(vd2x-vd2x2))>(double)(threshold); p3errors = p3errors | (double)(Math.Abs(vd2y-vd2y2))>(double)(threshold); p3errors = p3errors | (double)(Math.Abs(vd2z-vd2z2))>(double)(threshold); // // Test tangents for 2D/3D // pspline.pspline2tangent(p2, v0, ref vx, ref vy); p2errors = p2errors | (double)(Math.Abs(vx-vdx2/apserv.safepythag2(vdx2, vdy2)))>(double)(threshold); p2errors = p2errors | (double)(Math.Abs(vy-vdy2/apserv.safepythag2(vdx2, vdy2)))>(double)(threshold); pspline.pspline3tangent(p3, v0, ref vx, ref vy, ref vz); p3errors = p3errors | (double)(Math.Abs(vx-vdx2/apserv.safepythag3(vdx2, vdy2, vdz2)))>(double)(threshold); p3errors = p3errors | (double)(Math.Abs(vy-vdy2/apserv.safepythag3(vdx2, vdy2, vdz2)))>(double)(threshold); p3errors = p3errors | (double)(Math.Abs(vz-vdz2/apserv.safepythag3(vdx2, vdy2, vdz2)))>(double)(threshold); } // // Arc length test. // // Simple problem with easy solution (points on a straight line with // uniform parameterization). // for(n=2; n<=maxn; n++) { xy = new double[n, 2]; xyz = new double[n, 3]; for(i=0; i<=n-1; i++) { xy[i,0] = i; xy[i,1] = i; xyz[i,0] = i; xyz[i,1] = i; xyz[i,2] = i; } pspline.pspline2build(xy, n, 1, 0, p2); pspline.pspline3build(xyz, n, 1, 0, p3); a = math.randomreal(); b = math.randomreal(); p2errors = p2errors | (double)(Math.Abs(pspline.pspline2arclength(p2, a, b)-(b-a)*Math.Sqrt(2)*(n-1)))>(double)(nonstrictthreshold); p3errors = p3errors | (double)(Math.Abs(pspline.pspline3arclength(p3, a, b)-(b-a)*Math.Sqrt(3)*(n-1)))>(double)(nonstrictthreshold); } // // report // waserrors = p2errors | p3errors; if( !silent ) { System.Console.Write("TESTING SPLINE INTERPOLATION"); System.Console.WriteLine(); // // Normal tests // System.Console.Write("2D TEST: "); if( p2errors ) { System.Console.Write("FAILED"); System.Console.WriteLine(); } else { System.Console.Write("OK"); System.Console.WriteLine(); } System.Console.Write("3D TEST: "); if( p3errors ) { System.Console.Write("FAILED"); System.Console.WriteLine(); } else { System.Console.Write("OK"); System.Console.WriteLine(); } 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; }
// // Public declarations // public pspline2interpolant() { _innerobj = new pspline.pspline2interpolant(); }