/*************************************************************************
        Unit test
        *************************************************************************/
        public static bool testpolint(bool silent)
        {
            bool result = new bool();
            bool waserrors = new bool();
            bool interrors = new bool();
            bool fiterrors = new bool();
            double threshold = 0;
            double[] x = new double[0];
            double[] y = new double[0];
            double[] w = new double[0];
            double[] x2 = new double[0];
            double[] y2 = new double[0];
            double[] w2 = new double[0];
            double[] xfull = new double[0];
            double[] yfull = new double[0];
            double a = 0;
            double b = 0;
            double t = 0;
            int i = 0;
            int k = 0;
            double[] xc = new double[0];
            double[] yc = new double[0];
            int[] dc = new int[0];
            int info = 0;
            int info2 = 0;
            double v = 0;
            double v0 = 0;
            double v1 = 0;
            double v2 = 0;
            double s = 0;
            double xmin = 0;
            double xmax = 0;
            double refrms = 0;
            double refavg = 0;
            double refavgrel = 0;
            double refmax = 0;
            ratint.barycentricinterpolant p = new ratint.barycentricinterpolant();
            ratint.barycentricinterpolant p1 = new ratint.barycentricinterpolant();
            ratint.barycentricinterpolant p2 = new ratint.barycentricinterpolant();
            polint.polynomialfitreport rep = new polint.polynomialfitreport();
            polint.polynomialfitreport rep2 = new polint.polynomialfitreport();
            int n = 0;
            int m = 0;
            int maxn = 0;
            int pass = 0;
            int passcount = 0;

            waserrors = false;
            interrors = false;
            fiterrors = false;
            maxn = 5;
            passcount = 20;
            threshold = 1.0E8*AP.Math.MachineEpsilon;
            
            //
            // Test equidistant interpolation
            //
            for(pass=1; pass<=passcount; pass++)
            {
                for(n=1; n<=maxn; n++)
                {
                    
                    //
                    // prepare task:
                    // * equidistant points
                    // * random Y
                    // * T in [A,B] or near (within 10% of its width)
                    //
                    do
                    {
                        a = 2*AP.Math.RandomReal()-1;
                        b = 2*AP.Math.RandomReal()-1;
                    }
                    while( (double)(Math.Abs(a-b))<=(double)(0.2) );
                    t = a+(1.2*AP.Math.RandomReal()-0.1)*(b-a);
                    apserv.taskgenint1dequidist(a, b, n, ref x, ref y);
                    
                    //
                    // test "fast" equidistant interpolation (no barycentric model)
                    //
                    interrors = interrors | (double)(Math.Abs(polint.polynomialcalceqdist(a, b, ref y, n, t)-internalpolint(ref x, y, n, t)))>(double)(threshold);
                    
                    //
                    // test "slow" equidistant interpolation (create barycentric model)
                    //
                    brcunset(ref p);
                    polint.polynomialbuild(ref x, ref y, n, ref p);
                    interrors = interrors | (double)(Math.Abs(ratint.barycentriccalc(ref p, t)-internalpolint(ref x, y, n, t)))>(double)(threshold);
                    
                    //
                    // test "fast" interpolation (create "fast" barycentric model)
                    //
                    brcunset(ref p);
                    polint.polynomialbuildeqdist(a, b, ref y, n, ref p);
                    interrors = interrors | (double)(Math.Abs(ratint.barycentriccalc(ref p, t)-internalpolint(ref x, y, n, t)))>(double)(threshold);
                }
            }
            
            //
            // Test Chebyshev-1 interpolation
            //
            for(pass=1; pass<=passcount; pass++)
            {
                for(n=1; n<=maxn; n++)
                {
                    
                    //
                    // prepare task:
                    // * equidistant points
                    // * random Y
                    // * T in [A,B] or near (within 10% of its width)
                    //
                    do
                    {
                        a = 2*AP.Math.RandomReal()-1;
                        b = 2*AP.Math.RandomReal()-1;
                    }
                    while( (double)(Math.Abs(a-b))<=(double)(0.2) );
                    t = a+(1.2*AP.Math.RandomReal()-0.1)*(b-a);
                    apserv.taskgenint1dcheb1(a, b, n, ref x, ref y);
                    
                    //
                    // test "fast" interpolation (no barycentric model)
                    //
                    interrors = interrors | (double)(Math.Abs(polint.polynomialcalccheb1(a, b, ref y, n, t)-internalpolint(ref x, y, n, t)))>(double)(threshold);
                    
                    //
                    // test "slow" interpolation (create barycentric model)
                    //
                    brcunset(ref p);
                    polint.polynomialbuild(ref x, ref y, n, ref p);
                    interrors = interrors | (double)(Math.Abs(ratint.barycentriccalc(ref p, t)-internalpolint(ref x, y, n, t)))>(double)(threshold);
                    
                    //
                    // test "fast" interpolation (create "fast" barycentric model)
                    //
                    brcunset(ref p);
                    polint.polynomialbuildcheb1(a, b, ref y, n, ref p);
                    interrors = interrors | (double)(Math.Abs(ratint.barycentriccalc(ref p, t)-internalpolint(ref x, y, n, t)))>(double)(threshold);
                }
            }
            
            //
            // Test Chebyshev-2 interpolation
            //
            for(pass=1; pass<=passcount; pass++)
            {
                for(n=1; n<=maxn; n++)
                {
                    
                    //
                    // prepare task:
                    // * equidistant points
                    // * random Y
                    // * T in [A,B] or near (within 10% of its width)
                    //
                    do
                    {
                        a = 2*AP.Math.RandomReal()-1;
                        b = 2*AP.Math.RandomReal()-1;
                    }
                    while( (double)(Math.Abs(a-b))<=(double)(0.2) );
                    t = a+(1.2*AP.Math.RandomReal()-0.1)*(b-a);
                    apserv.taskgenint1dcheb2(a, b, n, ref x, ref y);
                    
                    //
                    // test "fast" interpolation (no barycentric model)
                    //
                    interrors = interrors | (double)(Math.Abs(polint.polynomialcalccheb2(a, b, ref y, n, t)-internalpolint(ref x, y, n, t)))>(double)(threshold);
                    
                    //
                    // test "slow" interpolation (create barycentric model)
                    //
                    brcunset(ref p);
                    polint.polynomialbuild(ref x, ref y, n, ref p);
                    interrors = interrors | (double)(Math.Abs(ratint.barycentriccalc(ref p, t)-internalpolint(ref x, y, n, t)))>(double)(threshold);
                    
                    //
                    // test "fast" interpolation (create "fast" barycentric model)
                    //
                    brcunset(ref p);
                    polint.polynomialbuildcheb2(a, b, ref y, n, ref p);
                    interrors = interrors | (double)(Math.Abs(ratint.barycentriccalc(ref p, t)-internalpolint(ref x, y, n, t)))>(double)(threshold);
                }
            }
            
            //
            // crash-test: ability to solve tasks which will overflow/underflow
            // weights with straightforward implementation
            //
            for(n=1; n<=20; n++)
            {
                a = -(0.1*AP.Math.MaxRealNumber);
                b = +(0.1*AP.Math.MaxRealNumber);
                apserv.taskgenint1dequidist(a, b, n, ref x, ref y);
                polint.polynomialbuild(ref x, ref y, n, ref p);
                for(i=0; i<=n-1; i++)
                {
                    interrors = interrors | (double)(p.w[i])==(double)(0);
                }
            }
            
            //
            // Test rational fitting:
            //
            for(pass=1; pass<=passcount; pass++)
            {
                for(n=1; n<=maxn; n++)
                {
                    
                    //
                    // N=M+K fitting (i.e. interpolation)
                    //
                    for(k=0; k<=n-1; k++)
                    {
                        apserv.taskgenint1d(-1, 1, n, ref xfull, ref yfull);
                        x = new double[n-k];
                        y = new double[n-k];
                        w = new double[n-k];
                        if( k>0 )
                        {
                            xc = new double[k];
                            yc = new double[k];
                            dc = new int[k];
                        }
                        for(i=0; i<=n-k-1; i++)
                        {
                            x[i] = xfull[i];
                            y[i] = yfull[i];
                            w[i] = 1+AP.Math.RandomReal();
                        }
                        for(i=0; i<=k-1; i++)
                        {
                            xc[i] = xfull[n-k+i];
                            yc[i] = yfull[n-k+i];
                            dc[i] = 0;
                        }
                        polint.polynomialfitwc(x, y, ref w, n-k, xc, yc, ref dc, k, n, ref info, ref p1, ref rep);
                        if( info<=0 )
                        {
                            fiterrors = true;
                        }
                        else
                        {
                            for(i=0; i<=n-k-1; i++)
                            {
                                fiterrors = fiterrors | (double)(Math.Abs(ratint.barycentriccalc(ref p1, x[i])-y[i]))>(double)(threshold);
                            }
                            for(i=0; i<=k-1; i++)
                            {
                                fiterrors = fiterrors | (double)(Math.Abs(ratint.barycentriccalc(ref p1, xc[i])-yc[i]))>(double)(threshold);
                            }
                        }
                    }
                    
                    //
                    // Testing constraints on derivatives.
                    // Special tasks which will always have solution:
                    // 1. P(0)=YC[0]
                    // 2. P(0)=YC[0], P'(0)=YC[1]
                    //
                    if( n>1 )
                    {
                        for(m=3; m<=5; m++)
                        {
                            for(k=1; k<=2; k++)
                            {
                                apserv.taskgenint1d(-1, 1, n, ref x, ref y);
                                w = new double[n];
                                xc = new double[2];
                                yc = new double[2];
                                dc = new int[2];
                                for(i=0; i<=n-1; i++)
                                {
                                    w[i] = 1+AP.Math.RandomReal();
                                }
                                xc[0] = 0;
                                yc[0] = 2*AP.Math.RandomReal()-1;
                                dc[0] = 0;
                                xc[1] = 0;
                                yc[1] = 2*AP.Math.RandomReal()-1;
                                dc[1] = 1;
                                polint.polynomialfitwc(x, y, ref w, n, xc, yc, ref dc, k, m, ref info, ref p1, ref rep);
                                if( info<=0 )
                                {
                                    fiterrors = true;
                                }
                                else
                                {
                                    ratint.barycentricdiff1(ref p1, 0.0, ref v0, ref v1);
                                    fiterrors = fiterrors | (double)(Math.Abs(v0-yc[0]))>(double)(threshold);
                                    if( k==2 )
                                    {
                                        fiterrors = fiterrors | (double)(Math.Abs(v1-yc[1]))>(double)(threshold);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            for(m=2; m<=8; m++)
            {
                for(pass=1; pass<=passcount; pass++)
                {
                    
                    //
                    // General fitting
                    //
                    // interpolating function through M nodes should have
                    // greater RMS error than fitting it through the same M nodes
                    //
                    n = 100;
                    x2 = new double[n];
                    y2 = new double[n];
                    w2 = new double[n];
                    xmin = 0;
                    xmax = 2*Math.PI;
                    for(i=0; i<=n-1; i++)
                    {
                        x2[i] = 2*Math.PI*AP.Math.RandomReal();
                        y2[i] = Math.Sin(x2[i]);
                        w2[i] = 1;
                    }
                    x = new double[m];
                    y = new double[m];
                    for(i=0; i<=m-1; i++)
                    {
                        x[i] = xmin+(xmax-xmin)*i/(m-1);
                        y[i] = Math.Sin(x[i]);
                    }
                    polint.polynomialbuild(ref x, ref y, m, ref p1);
                    polint.polynomialfitwc(x2, y2, ref w2, n, xc, yc, ref dc, 0, m, ref info, ref p2, ref rep);
                    if( info<=0 )
                    {
                        fiterrors = true;
                    }
                    else
                    {
                        
                        //
                        // calculate P1 (interpolant) RMS error, compare with P2 error
                        //
                        v1 = 0;
                        v2 = 0;
                        for(i=0; i<=n-1; i++)
                        {
                            v1 = v1+AP.Math.Sqr(ratint.barycentriccalc(ref p1, x2[i])-y2[i]);
                            v2 = v2+AP.Math.Sqr(ratint.barycentriccalc(ref p2, x2[i])-y2[i]);
                        }
                        v1 = Math.Sqrt(v1/n);
                        v2 = Math.Sqrt(v2/n);
                        fiterrors = fiterrors | (double)(v2)>(double)(v1);
                        fiterrors = fiterrors | (double)(Math.Abs(v2-rep.rmserror))>(double)(threshold);
                    }
                    
                    //
                    // compare weighted and non-weighted
                    //
                    n = 20;
                    x = new double[n];
                    y = new double[n];
                    w = new double[n];
                    for(i=0; i<=n-1; i++)
                    {
                        x[i] = 2*AP.Math.RandomReal()-1;
                        y[i] = 2*AP.Math.RandomReal()-1;
                        w[i] = 1;
                    }
                    polint.polynomialfitwc(x, y, ref w, n, xc, yc, ref dc, 0, m, ref info, ref p1, ref rep);
                    polint.polynomialfit(ref x, ref y, n, m, ref info2, ref p2, ref rep2);
                    if( info<=0 | info2<=0 )
                    {
                        fiterrors = true;
                    }
                    else
                    {
                        
                        //
                        // calculate P1 (interpolant), compare with P2 error
                        // compare RMS errors
                        //
                        t = 2*AP.Math.RandomReal()-1;
                        v1 = ratint.barycentriccalc(ref p1, t);
                        v2 = ratint.barycentriccalc(ref p2, t);
                        fiterrors = fiterrors | (double)(v2)!=(double)(v1);
                        fiterrors = fiterrors | (double)(rep.rmserror)!=(double)(rep2.rmserror);
                        fiterrors = fiterrors | (double)(rep.avgerror)!=(double)(rep2.avgerror);
                        fiterrors = fiterrors | (double)(rep.avgrelerror)!=(double)(rep2.avgrelerror);
                        fiterrors = fiterrors | (double)(rep.maxerror)!=(double)(rep2.maxerror);
                    }
                }
            }
            for(pass=1; pass<=passcount; pass++)
            {
                System.Diagnostics.Debug.Assert(passcount>=2, "PassCount should be 2 or greater!");
                
                //
                // solve simple task (all X[] are the same, Y[] are specially
                // calculated to ensure simple form of all types of errors)
                // and check correctness of the errors calculated by subroutines
                //
                // First pass is done with zero Y[], other passes - with random Y[].
                // It should test both ability to correctly calculate errors and
                // ability to not fail while working with zeros :)
                //
                n = 4;
                if( pass==1 )
                {
                    v1 = 0;
                    v2 = 0;
                    v = 0;
                }
                else
                {
                    v1 = AP.Math.RandomReal();
                    v2 = AP.Math.RandomReal();
                    v = 1+AP.Math.RandomReal();
                }
                x = new double[4];
                y = new double[4];
                w = new double[4];
                x[0] = 0;
                y[0] = v-v2;
                w[0] = 1;
                x[1] = 0;
                y[1] = v-v1;
                w[1] = 1;
                x[2] = 0;
                y[2] = v+v1;
                w[2] = 1;
                x[3] = 0;
                y[3] = v+v2;
                w[3] = 1;
                refrms = Math.Sqrt((AP.Math.Sqr(v1)+AP.Math.Sqr(v2))/2);
                refavg = (Math.Abs(v1)+Math.Abs(v2))/2;
                if( pass==1 )
                {
                    refavgrel = 0;
                }
                else
                {
                    refavgrel = 0.25*(Math.Abs(v2)/Math.Abs(v-v2)+Math.Abs(v1)/Math.Abs(v-v1)+Math.Abs(v1)/Math.Abs(v+v1)+Math.Abs(v2)/Math.Abs(v+v2));
                }
                refmax = Math.Max(v1, v2);
                
                //
                // Test errors correctness
                //
                polint.polynomialfit(ref x, ref y, 4, 1, ref info, ref p, ref rep);
                if( info<=0 )
                {
                    fiterrors = true;
                }
                else
                {
                    s = ratint.barycentriccalc(ref p, 0);
                    fiterrors = fiterrors | (double)(Math.Abs(s-v))>(double)(threshold);
                    fiterrors = fiterrors | (double)(Math.Abs(rep.rmserror-refrms))>(double)(threshold);
                    fiterrors = fiterrors | (double)(Math.Abs(rep.avgerror-refavg))>(double)(threshold);
                    fiterrors = fiterrors | (double)(Math.Abs(rep.avgrelerror-refavgrel))>(double)(threshold);
                    fiterrors = fiterrors | (double)(Math.Abs(rep.maxerror-refmax))>(double)(threshold);
                }
            }
            
            //
            // report
            //
            waserrors = interrors | fiterrors;
            if( !silent )
            {
                System.Console.Write("TESTING POLYNOMIAL INTERPOLATION AND FITTING");
                System.Console.WriteLine();
                
                //
                // Normal tests
                //
                System.Console.Write("INTERPOLATION TEST:                      ");
                if( interrors )
                {
                    System.Console.Write("FAILED");
                    System.Console.WriteLine();
                }
                else
                {
                    System.Console.Write("OK");
                    System.Console.WriteLine();
                }
                System.Console.Write("FITTING TEST:                            ");
                if( fiterrors )
                {
                    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;
        }
示例#2
0
        /*************************************************************************
        *  Unit test
        *************************************************************************/
        public static bool testpolint(bool silent)
        {
            bool   result    = new bool();
            bool   waserrors = new bool();
            bool   interrors = new bool();
            bool   fiterrors = new bool();
            double threshold = 0;

            double[] x     = new double[0];
            double[] y     = new double[0];
            double[] w     = new double[0];
            double[] x2    = new double[0];
            double[] y2    = new double[0];
            double[] w2    = new double[0];
            double[] xfull = new double[0];
            double[] yfull = new double[0];
            double   a     = 0;
            double   b     = 0;
            double   t     = 0;
            int      i     = 0;
            int      k     = 0;

            double[] xc        = new double[0];
            double[] yc        = new double[0];
            int[]    dc        = new int[0];
            int      info      = 0;
            int      info2     = 0;
            double   v         = 0;
            double   v0        = 0;
            double   v1        = 0;
            double   v2        = 0;
            double   s         = 0;
            double   xmin      = 0;
            double   xmax      = 0;
            double   refrms    = 0;
            double   refavg    = 0;
            double   refavgrel = 0;
            double   refmax    = 0;

            ratint.barycentricinterpolant p    = new ratint.barycentricinterpolant();
            ratint.barycentricinterpolant p1   = new ratint.barycentricinterpolant();
            ratint.barycentricinterpolant p2   = new ratint.barycentricinterpolant();
            polint.polynomialfitreport    rep  = new polint.polynomialfitreport();
            polint.polynomialfitreport    rep2 = new polint.polynomialfitreport();
            int n         = 0;
            int m         = 0;
            int maxn      = 0;
            int pass      = 0;
            int passcount = 0;

            waserrors = false;
            interrors = false;
            fiterrors = false;
            maxn      = 5;
            passcount = 20;
            threshold = 1.0E8 * AP.Math.MachineEpsilon;

            //
            // Test equidistant interpolation
            //
            for (pass = 1; pass <= passcount; pass++)
            {
                for (n = 1; n <= maxn; n++)
                {
                    //
                    // prepare task:
                    // * equidistant points
                    // * random Y
                    // * T in [A,B] or near (within 10% of its width)
                    //
                    do
                    {
                        a = 2 * AP.Math.RandomReal() - 1;
                        b = 2 * AP.Math.RandomReal() - 1;
                    }while((double)(Math.Abs(a - b)) <= (double)(0.2));
                    t = a + (1.2 * AP.Math.RandomReal() - 0.1) * (b - a);
                    apserv.taskgenint1dequidist(a, b, n, ref x, ref y);

                    //
                    // test "fast" equidistant interpolation (no barycentric model)
                    //
                    interrors = interrors | (double)(Math.Abs(polint.polynomialcalceqdist(a, b, ref y, n, t) - internalpolint(ref x, y, n, t))) > (double)(threshold);

                    //
                    // test "slow" equidistant interpolation (create barycentric model)
                    //
                    brcunset(ref p);
                    polint.polynomialbuild(ref x, ref y, n, ref p);
                    interrors = interrors | (double)(Math.Abs(ratint.barycentriccalc(ref p, t) - internalpolint(ref x, y, n, t))) > (double)(threshold);

                    //
                    // test "fast" interpolation (create "fast" barycentric model)
                    //
                    brcunset(ref p);
                    polint.polynomialbuildeqdist(a, b, ref y, n, ref p);
                    interrors = interrors | (double)(Math.Abs(ratint.barycentriccalc(ref p, t) - internalpolint(ref x, y, n, t))) > (double)(threshold);
                }
            }

            //
            // Test Chebyshev-1 interpolation
            //
            for (pass = 1; pass <= passcount; pass++)
            {
                for (n = 1; n <= maxn; n++)
                {
                    //
                    // prepare task:
                    // * equidistant points
                    // * random Y
                    // * T in [A,B] or near (within 10% of its width)
                    //
                    do
                    {
                        a = 2 * AP.Math.RandomReal() - 1;
                        b = 2 * AP.Math.RandomReal() - 1;
                    }while((double)(Math.Abs(a - b)) <= (double)(0.2));
                    t = a + (1.2 * AP.Math.RandomReal() - 0.1) * (b - a);
                    apserv.taskgenint1dcheb1(a, b, n, ref x, ref y);

                    //
                    // test "fast" interpolation (no barycentric model)
                    //
                    interrors = interrors | (double)(Math.Abs(polint.polynomialcalccheb1(a, b, ref y, n, t) - internalpolint(ref x, y, n, t))) > (double)(threshold);

                    //
                    // test "slow" interpolation (create barycentric model)
                    //
                    brcunset(ref p);
                    polint.polynomialbuild(ref x, ref y, n, ref p);
                    interrors = interrors | (double)(Math.Abs(ratint.barycentriccalc(ref p, t) - internalpolint(ref x, y, n, t))) > (double)(threshold);

                    //
                    // test "fast" interpolation (create "fast" barycentric model)
                    //
                    brcunset(ref p);
                    polint.polynomialbuildcheb1(a, b, ref y, n, ref p);
                    interrors = interrors | (double)(Math.Abs(ratint.barycentriccalc(ref p, t) - internalpolint(ref x, y, n, t))) > (double)(threshold);
                }
            }

            //
            // Test Chebyshev-2 interpolation
            //
            for (pass = 1; pass <= passcount; pass++)
            {
                for (n = 1; n <= maxn; n++)
                {
                    //
                    // prepare task:
                    // * equidistant points
                    // * random Y
                    // * T in [A,B] or near (within 10% of its width)
                    //
                    do
                    {
                        a = 2 * AP.Math.RandomReal() - 1;
                        b = 2 * AP.Math.RandomReal() - 1;
                    }while((double)(Math.Abs(a - b)) <= (double)(0.2));
                    t = a + (1.2 * AP.Math.RandomReal() - 0.1) * (b - a);
                    apserv.taskgenint1dcheb2(a, b, n, ref x, ref y);

                    //
                    // test "fast" interpolation (no barycentric model)
                    //
                    interrors = interrors | (double)(Math.Abs(polint.polynomialcalccheb2(a, b, ref y, n, t) - internalpolint(ref x, y, n, t))) > (double)(threshold);

                    //
                    // test "slow" interpolation (create barycentric model)
                    //
                    brcunset(ref p);
                    polint.polynomialbuild(ref x, ref y, n, ref p);
                    interrors = interrors | (double)(Math.Abs(ratint.barycentriccalc(ref p, t) - internalpolint(ref x, y, n, t))) > (double)(threshold);

                    //
                    // test "fast" interpolation (create "fast" barycentric model)
                    //
                    brcunset(ref p);
                    polint.polynomialbuildcheb2(a, b, ref y, n, ref p);
                    interrors = interrors | (double)(Math.Abs(ratint.barycentriccalc(ref p, t) - internalpolint(ref x, y, n, t))) > (double)(threshold);
                }
            }

            //
            // crash-test: ability to solve tasks which will overflow/underflow
            // weights with straightforward implementation
            //
            for (n = 1; n <= 20; n++)
            {
                a = -(0.1 * AP.Math.MaxRealNumber);
                b = +(0.1 * AP.Math.MaxRealNumber);
                apserv.taskgenint1dequidist(a, b, n, ref x, ref y);
                polint.polynomialbuild(ref x, ref y, n, ref p);
                for (i = 0; i <= n - 1; i++)
                {
                    interrors = interrors | (double)(p.w[i]) == (double)(0);
                }
            }

            //
            // Test rational fitting:
            //
            for (pass = 1; pass <= passcount; pass++)
            {
                for (n = 1; n <= maxn; n++)
                {
                    //
                    // N=M+K fitting (i.e. interpolation)
                    //
                    for (k = 0; k <= n - 1; k++)
                    {
                        apserv.taskgenint1d(-1, 1, n, ref xfull, ref yfull);
                        x = new double[n - k];
                        y = new double[n - k];
                        w = new double[n - k];
                        if (k > 0)
                        {
                            xc = new double[k];
                            yc = new double[k];
                            dc = new int[k];
                        }
                        for (i = 0; i <= n - k - 1; i++)
                        {
                            x[i] = xfull[i];
                            y[i] = yfull[i];
                            w[i] = 1 + AP.Math.RandomReal();
                        }
                        for (i = 0; i <= k - 1; i++)
                        {
                            xc[i] = xfull[n - k + i];
                            yc[i] = yfull[n - k + i];
                            dc[i] = 0;
                        }
                        polint.polynomialfitwc(x, y, ref w, n - k, xc, yc, ref dc, k, n, ref info, ref p1, ref rep);
                        if (info <= 0)
                        {
                            fiterrors = true;
                        }
                        else
                        {
                            for (i = 0; i <= n - k - 1; i++)
                            {
                                fiterrors = fiterrors | (double)(Math.Abs(ratint.barycentriccalc(ref p1, x[i]) - y[i])) > (double)(threshold);
                            }
                            for (i = 0; i <= k - 1; i++)
                            {
                                fiterrors = fiterrors | (double)(Math.Abs(ratint.barycentriccalc(ref p1, xc[i]) - yc[i])) > (double)(threshold);
                            }
                        }
                    }

                    //
                    // Testing constraints on derivatives.
                    // Special tasks which will always have solution:
                    // 1. P(0)=YC[0]
                    // 2. P(0)=YC[0], P'(0)=YC[1]
                    //
                    if (n > 1)
                    {
                        for (m = 3; m <= 5; m++)
                        {
                            for (k = 1; k <= 2; k++)
                            {
                                apserv.taskgenint1d(-1, 1, n, ref x, ref y);
                                w  = new double[n];
                                xc = new double[2];
                                yc = new double[2];
                                dc = new int[2];
                                for (i = 0; i <= n - 1; i++)
                                {
                                    w[i] = 1 + AP.Math.RandomReal();
                                }
                                xc[0] = 0;
                                yc[0] = 2 * AP.Math.RandomReal() - 1;
                                dc[0] = 0;
                                xc[1] = 0;
                                yc[1] = 2 * AP.Math.RandomReal() - 1;
                                dc[1] = 1;
                                polint.polynomialfitwc(x, y, ref w, n, xc, yc, ref dc, k, m, ref info, ref p1, ref rep);
                                if (info <= 0)
                                {
                                    fiterrors = true;
                                }
                                else
                                {
                                    ratint.barycentricdiff1(ref p1, 0.0, ref v0, ref v1);
                                    fiterrors = fiterrors | (double)(Math.Abs(v0 - yc[0])) > (double)(threshold);
                                    if (k == 2)
                                    {
                                        fiterrors = fiterrors | (double)(Math.Abs(v1 - yc[1])) > (double)(threshold);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            for (m = 2; m <= 8; m++)
            {
                for (pass = 1; pass <= passcount; pass++)
                {
                    //
                    // General fitting
                    //
                    // interpolating function through M nodes should have
                    // greater RMS error than fitting it through the same M nodes
                    //
                    n    = 100;
                    x2   = new double[n];
                    y2   = new double[n];
                    w2   = new double[n];
                    xmin = 0;
                    xmax = 2 * Math.PI;
                    for (i = 0; i <= n - 1; i++)
                    {
                        x2[i] = 2 * Math.PI * AP.Math.RandomReal();
                        y2[i] = Math.Sin(x2[i]);
                        w2[i] = 1;
                    }
                    x = new double[m];
                    y = new double[m];
                    for (i = 0; i <= m - 1; i++)
                    {
                        x[i] = xmin + (xmax - xmin) * i / (m - 1);
                        y[i] = Math.Sin(x[i]);
                    }
                    polint.polynomialbuild(ref x, ref y, m, ref p1);
                    polint.polynomialfitwc(x2, y2, ref w2, n, xc, yc, ref dc, 0, m, ref info, ref p2, ref rep);
                    if (info <= 0)
                    {
                        fiterrors = true;
                    }
                    else
                    {
                        //
                        // calculate P1 (interpolant) RMS error, compare with P2 error
                        //
                        v1 = 0;
                        v2 = 0;
                        for (i = 0; i <= n - 1; i++)
                        {
                            v1 = v1 + AP.Math.Sqr(ratint.barycentriccalc(ref p1, x2[i]) - y2[i]);
                            v2 = v2 + AP.Math.Sqr(ratint.barycentriccalc(ref p2, x2[i]) - y2[i]);
                        }
                        v1        = Math.Sqrt(v1 / n);
                        v2        = Math.Sqrt(v2 / n);
                        fiterrors = fiterrors | (double)(v2) > (double)(v1);
                        fiterrors = fiterrors | (double)(Math.Abs(v2 - rep.rmserror)) > (double)(threshold);
                    }

                    //
                    // compare weighted and non-weighted
                    //
                    n = 20;
                    x = new double[n];
                    y = new double[n];
                    w = new double[n];
                    for (i = 0; i <= n - 1; i++)
                    {
                        x[i] = 2 * AP.Math.RandomReal() - 1;
                        y[i] = 2 * AP.Math.RandomReal() - 1;
                        w[i] = 1;
                    }
                    polint.polynomialfitwc(x, y, ref w, n, xc, yc, ref dc, 0, m, ref info, ref p1, ref rep);
                    polint.polynomialfit(ref x, ref y, n, m, ref info2, ref p2, ref rep2);
                    if (info <= 0 | info2 <= 0)
                    {
                        fiterrors = true;
                    }
                    else
                    {
                        //
                        // calculate P1 (interpolant), compare with P2 error
                        // compare RMS errors
                        //
                        t         = 2 * AP.Math.RandomReal() - 1;
                        v1        = ratint.barycentriccalc(ref p1, t);
                        v2        = ratint.barycentriccalc(ref p2, t);
                        fiterrors = fiterrors | (double)(v2) != (double)(v1);
                        fiterrors = fiterrors | (double)(rep.rmserror) != (double)(rep2.rmserror);
                        fiterrors = fiterrors | (double)(rep.avgerror) != (double)(rep2.avgerror);
                        fiterrors = fiterrors | (double)(rep.avgrelerror) != (double)(rep2.avgrelerror);
                        fiterrors = fiterrors | (double)(rep.maxerror) != (double)(rep2.maxerror);
                    }
                }
            }
            for (pass = 1; pass <= passcount; pass++)
            {
                System.Diagnostics.Debug.Assert(passcount >= 2, "PassCount should be 2 or greater!");

                //
                // solve simple task (all X[] are the same, Y[] are specially
                // calculated to ensure simple form of all types of errors)
                // and check correctness of the errors calculated by subroutines
                //
                // First pass is done with zero Y[], other passes - with random Y[].
                // It should test both ability to correctly calculate errors and
                // ability to not fail while working with zeros :)
                //
                n = 4;
                if (pass == 1)
                {
                    v1 = 0;
                    v2 = 0;
                    v  = 0;
                }
                else
                {
                    v1 = AP.Math.RandomReal();
                    v2 = AP.Math.RandomReal();
                    v  = 1 + AP.Math.RandomReal();
                }
                x      = new double[4];
                y      = new double[4];
                w      = new double[4];
                x[0]   = 0;
                y[0]   = v - v2;
                w[0]   = 1;
                x[1]   = 0;
                y[1]   = v - v1;
                w[1]   = 1;
                x[2]   = 0;
                y[2]   = v + v1;
                w[2]   = 1;
                x[3]   = 0;
                y[3]   = v + v2;
                w[3]   = 1;
                refrms = Math.Sqrt((AP.Math.Sqr(v1) + AP.Math.Sqr(v2)) / 2);
                refavg = (Math.Abs(v1) + Math.Abs(v2)) / 2;
                if (pass == 1)
                {
                    refavgrel = 0;
                }
                else
                {
                    refavgrel = 0.25 * (Math.Abs(v2) / Math.Abs(v - v2) + Math.Abs(v1) / Math.Abs(v - v1) + Math.Abs(v1) / Math.Abs(v + v1) + Math.Abs(v2) / Math.Abs(v + v2));
                }
                refmax = Math.Max(v1, v2);

                //
                // Test errors correctness
                //
                polint.polynomialfit(ref x, ref y, 4, 1, ref info, ref p, ref rep);
                if (info <= 0)
                {
                    fiterrors = true;
                }
                else
                {
                    s         = ratint.barycentriccalc(ref p, 0);
                    fiterrors = fiterrors | (double)(Math.Abs(s - v)) > (double)(threshold);
                    fiterrors = fiterrors | (double)(Math.Abs(rep.rmserror - refrms)) > (double)(threshold);
                    fiterrors = fiterrors | (double)(Math.Abs(rep.avgerror - refavg)) > (double)(threshold);
                    fiterrors = fiterrors | (double)(Math.Abs(rep.avgrelerror - refavgrel)) > (double)(threshold);
                    fiterrors = fiterrors | (double)(Math.Abs(rep.maxerror - refmax)) > (double)(threshold);
                }
            }

            //
            // report
            //
            waserrors = interrors | fiterrors;
            if (!silent)
            {
                System.Console.Write("TESTING POLYNOMIAL INTERPOLATION AND FITTING");
                System.Console.WriteLine();

                //
                // Normal tests
                //
                System.Console.Write("INTERPOLATION TEST:                      ");
                if (interrors)
                {
                    System.Console.Write("FAILED");
                    System.Console.WriteLine();
                }
                else
                {
                    System.Console.Write("OK");
                    System.Console.WriteLine();
                }
                System.Console.Write("FITTING TEST:                            ");
                if (fiterrors)
                {
                    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);
        }