Esempio n. 1
0
        /*************************************************************************
        *  Least squares fitting by polynomial.
        *
        *  This subroutine is "lightweight" alternative for more complex and feature-
        *  rich PolynomialFitWC().  See  PolynomialFitWC() for more information about
        *  subroutine parameters (we don't duplicate it here because of length)
        *
        *  -- ALGLIB PROJECT --
        *    Copyright 12.10.2009 by Bochkanov Sergey
        *************************************************************************/
        public static void polynomialfit(ref double[] x,
                                         ref double[] y,
                                         int n,
                                         int m,
                                         ref int info,
                                         ref ratint.barycentricinterpolant p,
                                         ref polynomialfitreport rep)
        {
            int i = 0;

            double[] w  = new double[0];
            double[] xc = new double[0];
            double[] yc = new double[0];
            int[]    dc = new int[0];

            if (n > 0)
            {
                w = new double[n];
                for (i = 0; i <= n - 1; i++)
                {
                    w[i] = 1;
                }
            }
            polynomialfitwc(x, y, ref w, n, xc, yc, ref dc, 0, m, ref info, ref p, ref rep);
        }
Esempio n. 2
0
        private static void brcunset(ref ratint.barycentricinterpolant b)
        {
            double[] x = new double[0];
            double[] y = new double[0];
            double[] w = new double[0];

            x    = new double[1];
            y    = new double[1];
            w    = new double[1];
            x[0] = 0;
            y[0] = 0;
            w[0] = 1;
            ratint.barycentricbuildxyw(ref x, ref y, ref w, 1, ref b);
        }
Esempio n. 3
0
        /*************************************************************************
        *  Lagrange intepolant on Chebyshev grid (second kind).
        *  This function has O(N) complexity.
        *
        *  INPUT PARAMETERS:
        *   A   -   left boundary of [A,B]
        *   B   -   right boundary of [A,B]
        *   Y   -   function values at the nodes, array[0..N-1],
        *           Y[I] = Y(0.5*(B+A) + 0.5*(B-A)*Cos(PI*i/(n-1)))
        *   N   -   number of points, N>=1
        *           for N=1 a constant model is constructed.
        *
        *  OIYTPUT PARAMETERS
        *   P   -   barycentric model which represents Lagrange interpolant
        *           (see ratint unit info and BarycentricCalc() description for
        *           more information).
        *
        *  -- ALGLIB --
        *    Copyright 03.12.2009 by Bochkanov Sergey
        *************************************************************************/
        public static void polynomialbuildcheb2(double a,
                                                double b,
                                                ref double[] y,
                                                int n,
                                                ref ratint.barycentricinterpolant p)
        {
            int i = 0;

            double[] w = new double[0];
            double[] x = new double[0];
            double   v = 0;

            System.Diagnostics.Debug.Assert(n > 0, "PolIntBuildCheb2: N<=0!");

            //
            // Special case: N=1
            //
            if (n == 1)
            {
                x    = new double[1];
                w    = new double[1];
                x[0] = 0.5 * (b + a);
                w[0] = 1;
                ratint.barycentricbuildxyw(ref x, ref y, ref w, 1, ref p);
                return;
            }

            //
            // general case
            //
            x = new double[n];
            w = new double[n];
            v = 1;
            for (i = 0; i <= n - 1; i++)
            {
                if (i == 0 | i == n - 1)
                {
                    w[i] = v * 0.5;
                }
                else
                {
                    w[i] = v;
                }
                x[i] = 0.5 * (b + a) + 0.5 * (b - a) * Math.Cos(Math.PI * i / (n - 1));
                v    = -v;
            }
            ratint.barycentricbuildxyw(ref x, ref y, ref w, n, ref p);
        }
Esempio n. 4
0
        /*************************************************************************
        *  Lagrange intepolant on Chebyshev grid (first kind).
        *  This function has O(N) complexity.
        *
        *  INPUT PARAMETERS:
        *   A   -   left boundary of [A,B]
        *   B   -   right boundary of [A,B]
        *   Y   -   function values at the nodes, array[0..N-1],
        *           Y[I] = Y(0.5*(B+A) + 0.5*(B-A)*Cos(PI*(2*i+1)/(2*n)))
        *   N   -   number of points, N>=1
        *           for N=1 a constant model is constructed.
        *
        *  OIYTPUT PARAMETERS
        *   P   -   barycentric model which represents Lagrange interpolant
        *           (see ratint unit info and BarycentricCalc() description for
        *           more information).
        *
        *  -- ALGLIB --
        *    Copyright 03.12.2009 by Bochkanov Sergey
        *************************************************************************/
        public static void polynomialbuildcheb1(double a,
                                                double b,
                                                ref double[] y,
                                                int n,
                                                ref ratint.barycentricinterpolant p)
        {
            int i = 0;

            double[] w = new double[0];
            double[] x = new double[0];
            double   v = 0;
            double   t = 0;

            System.Diagnostics.Debug.Assert(n > 0, "PolIntBuildCheb1: N<=0!");

            //
            // Special case: N=1
            //
            if (n == 1)
            {
                x    = new double[1];
                w    = new double[1];
                x[0] = 0.5 * (b + a);
                w[0] = 1;
                ratint.barycentricbuildxyw(ref x, ref y, ref w, 1, ref p);
                return;
            }

            //
            // general case
            //
            x = new double[n];
            w = new double[n];
            v = 1;
            for (i = 0; i <= n - 1; i++)
            {
                t    = Math.Tan(0.5 * Math.PI * (2 * i + 1) / (2 * n));
                w[i] = 2 * v * t / (1 + AP.Math.Sqr(t));
                x[i] = 0.5 * (b + a) + 0.5 * (b - a) * (1 - AP.Math.Sqr(t)) / (1 + AP.Math.Sqr(t));
                v    = -v;
            }
            ratint.barycentricbuildxyw(ref x, ref y, ref w, n, ref p);
        }
Esempio n. 5
0
        /*************************************************************************
        *  Lagrange intepolant: generation of the model on equidistant grid.
        *  This function has O(N) complexity.
        *
        *  INPUT PARAMETERS:
        *   A   -   left boundary of [A,B]
        *   B   -   right boundary of [A,B]
        *   Y   -   function values at the nodes, array[0..N-1]
        *   N   -   number of points, N>=1
        *           for N=1 a constant model is constructed.
        *
        *  OIYTPUT PARAMETERS
        *   P   -   barycentric model which represents Lagrange interpolant
        *           (see ratint unit info and BarycentricCalc() description for
        *           more information).
        *
        *  -- ALGLIB --
        *    Copyright 03.12.2009 by Bochkanov Sergey
        *************************************************************************/
        public static void polynomialbuildeqdist(double a,
                                                 double b,
                                                 ref double[] y,
                                                 int n,
                                                 ref ratint.barycentricinterpolant p)
        {
            int i = 0;

            double[] w = new double[0];
            double[] x = new double[0];
            double   v = 0;

            System.Diagnostics.Debug.Assert(n > 0, "PolIntBuildEqDist: N<=0!");

            //
            // Special case: N=1
            //
            if (n == 1)
            {
                x    = new double[1];
                w    = new double[1];
                x[0] = 0.5 * (b + a);
                w[0] = 1;
                ratint.barycentricbuildxyw(ref x, ref y, ref w, 1, ref p);
                return;
            }

            //
            // general case
            //
            x = new double[n];
            w = new double[n];
            v = 1;
            for (i = 0; i <= n - 1; i++)
            {
                w[i] = v;
                x[i] = a + (b - a) * i / (n - 1);
                v    = -(v * (n - 1 - i));
                v    = v / (i + 1);
            }
            ratint.barycentricbuildxyw(ref x, ref y, ref w, n, ref p);
        }
        public static bool testri(bool silent)
        {
            bool result = new bool();
            bool waserrors = new bool();
            bool bcerrors = new bool();
            bool nperrors = new bool();
            bool fiterrors = new bool();
            double threshold = 0;
            double lipschitztol = 0;
            int maxn = 0;
            int passcount = 0;
            ratint.barycentricinterpolant b1 = new ratint.barycentricinterpolant();
            ratint.barycentricinterpolant b2 = new ratint.barycentricinterpolant();
            double[] x = new double[0];
            double[] x2 = new double[0];
            double[] y = new double[0];
            double[] y2 = new double[0];
            double[] w = new double[0];
            double[] w2 = new double[0];
            double[] xc = new double[0];
            double[] yc = new double[0];
            int[] dc = new int[0];
            double h = 0;
            double s1 = 0;
            double s2 = 0;
            bool bsame = new bool();
            int n = 0;
            int m = 0;
            int n2 = 0;
            int i = 0;
            int j = 0;
            int k = 0;
            int d = 0;
            int pass = 0;
            double err = 0;
            double maxerr = 0;
            double t = 0;
            double a = 0;
            double b = 0;
            double s = 0;
            double v = 0;
            double v0 = 0;
            double v1 = 0;
            double v2 = 0;
            double v3 = 0;
            double d0 = 0;
            double d1 = 0;
            double d2 = 0;
            int info = 0;
            int info2 = 0;
            double xmin = 0;
            double xmax = 0;
            double refrms = 0;
            double refavg = 0;
            double refavgrel = 0;
            double refmax = 0;
            double[] ra = new double[0];
            double[] ra2 = new double[0];
            int ralen = 0;
            ratint.barycentricfitreport rep = new ratint.barycentricfitreport();
            ratint.barycentricfitreport rep2 = new ratint.barycentricfitreport();
            ratint.barycentricinterpolant b3 = new ratint.barycentricinterpolant();
            ratint.barycentricinterpolant b4 = new ratint.barycentricinterpolant();
            int i_ = 0;

            nperrors = false;
            bcerrors = false;
            fiterrors = false;
            waserrors = false;
            
            //
            // PassCount        number of repeated passes
            // Threshold        error tolerance
            // LipschitzTol     Lipschitz constant increase allowed
            //                  when calculating constant on a twice denser grid
            //
            passcount = 5;
            maxn = 15;
            threshold = 1000000*AP.Math.MachineEpsilon;
            lipschitztol = 1.3;
            
            //
            // Basic barycentric functions
            //
            for(n=1; n<=10; n++)
            {
                
                //
                // randomized tests
                //
                for(pass=1; pass<=passcount; pass++)
                {
                    
                    //
                    // generate weights from polynomial interpolation
                    //
                    v0 = 1+0.4*AP.Math.RandomReal()-0.2;
                    v1 = 2*AP.Math.RandomReal()-1;
                    v2 = 2*AP.Math.RandomReal()-1;
                    v3 = 2*AP.Math.RandomReal()-1;
                    x = new double[n];
                    y = new double[n];
                    w = new double[n];
                    for(i=0; i<=n-1; i++)
                    {
                        if( n==1 )
                        {
                            x[i] = 0;
                        }
                        else
                        {
                            x[i] = v0*Math.Cos(i*Math.PI/(n-1));
                        }
                        y[i] = Math.Sin(v1*x[i])+Math.Cos(v2*x[i])+Math.Exp(v3*x[i]);
                    }
                    for(j=0; j<=n-1; j++)
                    {
                        w[j] = 1;
                        for(k=0; k<=n-1; k++)
                        {
                            if( k!=j )
                            {
                                w[j] = w[j]/(x[j]-x[k]);
                            }
                        }
                    }
                    ratint.barycentricbuildxyw(ref x, ref y, ref w, n, ref b1);
                    
                    //
                    // unpack, then pack again and compare
                    //
                    brcunset(ref b2);
                    ratint.barycentricunpack(ref b1, ref n2, ref x2, ref y2, ref w2);
                    bcerrors = bcerrors | n2!=n;
                    ratint.barycentricbuildxyw(ref x2, ref y2, ref w2, n2, ref b2);
                    t = 2*AP.Math.RandomReal()-1;
                    bcerrors = bcerrors | (double)(Math.Abs(ratint.barycentriccalc(ref b1, t)-ratint.barycentriccalc(ref b2, t)))>(double)(threshold);
                    
                    //
                    // serialize, unserialize, compare
                    //
                    brcunset(ref b2);
                    ratint.barycentricserialize(ref b1, ref ra, ref ralen);
                    ra2 = new double[ralen];
                    for(i_=0; i_<=ralen-1;i_++)
                    {
                        ra2[i_] = ra[i_];
                    }
                    ratint.barycentricunserialize(ref ra2, ref b2);
                    t = 2*AP.Math.RandomReal()-1;
                    bcerrors = bcerrors | (double)(Math.Abs(ratint.barycentriccalc(ref b1, t)-ratint.barycentriccalc(ref b2, t)))>(double)(threshold);
                    
                    //
                    // copy, compare
                    //
                    brcunset(ref b2);
                    ratint.barycentriccopy(ref b1, ref b2);
                    t = 2*AP.Math.RandomReal()-1;
                    bcerrors = bcerrors | (double)(Math.Abs(ratint.barycentriccalc(ref b1, t)-ratint.barycentriccalc(ref b2, t)))>(double)(threshold);
                    
                    //
                    // test interpolation properties
                    //
                    for(i=0; i<=n-1; i++)
                    {
                        
                        //
                        // test interpolation at nodes
                        //
                        bcerrors = bcerrors | (double)(Math.Abs(ratint.barycentriccalc(ref b1, x[i])-y[i]))>(double)(threshold*Math.Abs(y[i]));
                        
                        //
                        // compare with polynomial interpolation
                        //
                        t = 2*AP.Math.RandomReal()-1;
                        poldiff2(ref x, y, n, t, ref v0, ref v1, ref v2);
                        bcerrors = bcerrors | (double)(Math.Abs(ratint.barycentriccalc(ref b1, t)-v0))>(double)(threshold*Math.Max(Math.Abs(v0), 1));
                        
                        //
                        // test continuity between nodes
                        // calculate Lipschitz constant on two grids -
                        // dense and even more dense. If Lipschitz constant
                        // on a denser grid is significantly increased,
                        // continuity test is failed
                        //
                        t = 3.0;
                        k = 100;
                        s1 = 0;
                        for(j=0; j<=k-1; j++)
                        {
                            v1 = x[i]+(t-x[i])*j/k;
                            v2 = x[i]+(t-x[i])*(j+1)/k;
                            s1 = Math.Max(s1, Math.Abs(ratint.barycentriccalc(ref b1, v2)-ratint.barycentriccalc(ref b1, v1))/Math.Abs(v2-v1));
                        }
                        k = 2*k;
                        s2 = 0;
                        for(j=0; j<=k-1; j++)
                        {
                            v1 = x[i]+(t-x[i])*j/k;
                            v2 = x[i]+(t-x[i])*(j+1)/k;
                            s2 = Math.Max(s2, Math.Abs(ratint.barycentriccalc(ref b1, v2)-ratint.barycentriccalc(ref b1, v1))/Math.Abs(v2-v1));
                        }
                        bcerrors = bcerrors | (double)(s2)>(double)(lipschitztol*s1) & (double)(s1)>(double)(threshold*k);
                    }
                    
                    //
                    // test differentiation properties
                    //
                    for(i=0; i<=n-1; i++)
                    {
                        t = 2*AP.Math.RandomReal()-1;
                        poldiff2(ref x, y, n, t, ref v0, ref v1, ref v2);
                        d0 = 0;
                        d1 = 0;
                        d2 = 0;
                        ratint.barycentricdiff1(ref b1, t, ref d0, ref d1);
                        bcerrors = bcerrors | (double)(Math.Abs(v0-d0))>(double)(threshold*Math.Max(Math.Abs(v0), 1));
                        bcerrors = bcerrors | (double)(Math.Abs(v1-d1))>(double)(threshold*Math.Max(Math.Abs(v1), 1));
                        d0 = 0;
                        d1 = 0;
                        d2 = 0;
                        ratint.barycentricdiff2(ref b1, t, ref d0, ref d1, ref d2);
                        bcerrors = bcerrors | (double)(Math.Abs(v0-d0))>(double)(threshold*Math.Max(Math.Abs(v0), 1));
                        bcerrors = bcerrors | (double)(Math.Abs(v1-d1))>(double)(threshold*Math.Max(Math.Abs(v1), 1));
                        bcerrors = bcerrors | (double)(Math.Abs(v2-d2))>(double)(Math.Sqrt(threshold)*Math.Max(Math.Abs(v2), 1));
                    }
                    
                    //
                    // test linear translation
                    //
                    t = 2*AP.Math.RandomReal()-1;
                    a = 2*AP.Math.RandomReal()-1;
                    b = 2*AP.Math.RandomReal()-1;
                    brcunset(ref b2);
                    ratint.barycentriccopy(ref b1, ref b2);
                    ratint.barycentriclintransx(ref b2, a, b);
                    bcerrors = bcerrors | (double)(Math.Abs(ratint.barycentriccalc(ref b1, a*t+b)-ratint.barycentriccalc(ref b2, t)))>(double)(threshold);
                    a = 0;
                    b = 2*AP.Math.RandomReal()-1;
                    brcunset(ref b2);
                    ratint.barycentriccopy(ref b1, ref b2);
                    ratint.barycentriclintransx(ref b2, a, b);
                    bcerrors = bcerrors | (double)(Math.Abs(ratint.barycentriccalc(ref b1, a*t+b)-ratint.barycentriccalc(ref b2, t)))>(double)(threshold);
                    a = 2*AP.Math.RandomReal()-1;
                    b = 2*AP.Math.RandomReal()-1;
                    brcunset(ref b2);
                    ratint.barycentriccopy(ref b1, ref b2);
                    ratint.barycentriclintransy(ref b2, a, b);
                    bcerrors = bcerrors | (double)(Math.Abs(a*ratint.barycentriccalc(ref b1, t)+b-ratint.barycentriccalc(ref b2, t)))>(double)(threshold);
                }
            }
            for(pass=0; pass<=3; pass++)
            {
                
                //
                // Crash-test: small numbers, large numbers
                //
                x = new double[4];
                y = new double[4];
                w = new double[4];
                h = 1;
                if( pass%2==0 )
                {
                    h = 100*AP.Math.MinRealNumber;
                }
                if( pass%2==1 )
                {
                    h = 0.01*AP.Math.MaxRealNumber;
                }
                x[0] = 0*h;
                x[1] = 1*h;
                x[2] = 2*h;
                x[3] = 3*h;
                y[0] = 0*h;
                y[1] = 1*h;
                y[2] = 2*h;
                y[3] = 3*h;
                w[0] = -(1/(x[1]-x[0]));
                w[1] = +(1*(1/(x[1]-x[0])+1/(x[2]-x[1])));
                w[2] = -(1*(1/(x[2]-x[1])+1/(x[3]-x[2])));
                w[3] = +(1/(x[3]-x[2]));
                if( pass/2==0 )
                {
                    v0 = 0;
                }
                if( pass/2==1 )
                {
                    v0 = 0.6*h;
                }
                ratint.barycentricbuildxyw(ref x, ref y, ref w, 4, ref b1);
                t = ratint.barycentriccalc(ref b1, v0);
                d0 = 0;
                d1 = 0;
                d2 = 0;
                ratint.barycentricdiff1(ref b1, v0, ref d0, ref d1);
                bcerrors = bcerrors | (double)(Math.Abs(t-v0))>(double)(threshold*v0);
                bcerrors = bcerrors | (double)(Math.Abs(d0-v0))>(double)(threshold*v0);
                bcerrors = bcerrors | (double)(Math.Abs(d1-1))>(double)(1000*threshold);
            }
            
            //
            // crash test: large abscissas, small argument
            //
            // test for errors in D0 is not very strict
            // because renormalization used in Diff1()
            // destroys part of precision.
            //
            x = new double[4];
            y = new double[4];
            w = new double[4];
            h = 0.01*AP.Math.MaxRealNumber;
            x[0] = 0*h;
            x[1] = 1*h;
            x[2] = 2*h;
            x[3] = 3*h;
            y[0] = 0*h;
            y[1] = 1*h;
            y[2] = 2*h;
            y[3] = 3*h;
            w[0] = -(1/(x[1]-x[0]));
            w[1] = +(1*(1/(x[1]-x[0])+1/(x[2]-x[1])));
            w[2] = -(1*(1/(x[2]-x[1])+1/(x[3]-x[2])));
            w[3] = +(1/(x[3]-x[2]));
            v0 = 100*AP.Math.MinRealNumber;
            ratint.barycentricbuildxyw(ref x, ref y, ref w, 4, ref b1);
            t = ratint.barycentriccalc(ref b1, v0);
            d0 = 0;
            d1 = 0;
            d2 = 0;
            ratint.barycentricdiff1(ref b1, v0, ref d0, ref d1);
            bcerrors = bcerrors | (double)(Math.Abs(t))>(double)(v0*(1+threshold));
            bcerrors = bcerrors | (double)(Math.Abs(d0))>(double)(v0*(1+threshold));
            bcerrors = bcerrors | (double)(Math.Abs(d1-1))>(double)(1000*threshold);
            
            //
            // crash test: test safe barycentric formula
            //
            x = new double[4];
            y = new double[4];
            w = new double[4];
            h = 2*AP.Math.MinRealNumber;
            x[0] = 0*h;
            x[1] = 1*h;
            x[2] = 2*h;
            x[3] = 3*h;
            y[0] = 0*h;
            y[1] = 1*h;
            y[2] = 2*h;
            y[3] = 3*h;
            w[0] = -(1/(x[1]-x[0]));
            w[1] = +(1*(1/(x[1]-x[0])+1/(x[2]-x[1])));
            w[2] = -(1*(1/(x[2]-x[1])+1/(x[3]-x[2])));
            w[3] = +(1/(x[3]-x[2]));
            v0 = AP.Math.MinRealNumber;
            ratint.barycentricbuildxyw(ref x, ref y, ref w, 4, ref b1);
            t = ratint.barycentriccalc(ref b1, v0);
            bcerrors = bcerrors | (double)(Math.Abs(t-v0)/v0)>(double)(threshold);
            
            //
            // Testing "No Poles" interpolation
            //
            maxerr = 0;
            for(pass=1; pass<=passcount-1; pass++)
            {
                x = new double[1];
                y = new double[1];
                x[0] = 2*AP.Math.RandomReal()-1;
                y[0] = 2*AP.Math.RandomReal()-1;
                ratint.barycentricbuildfloaterhormann(ref x, ref y, 1, 1, ref b1);
                maxerr = Math.Max(maxerr, Math.Abs(ratint.barycentriccalc(ref b1, 2*AP.Math.RandomReal()-1)-y[0]));
            }
            for(n=2; n<=10; n++)
            {
                
                //
                // compare interpolant built by subroutine
                // with interpolant built by hands
                //
                x = new double[n];
                y = new double[n];
                w = new double[n];
                w2 = new double[n];
                
                //
                // D=1, non-equidistant nodes
                //
                for(pass=1; pass<=passcount; pass++)
                {
                    
                    //
                    // Initialize X, Y, W
                    //
                    a = -1-1*AP.Math.RandomReal();
                    b = +1+1*AP.Math.RandomReal();
                    for(i=0; i<=n-1; i++)
                    {
                        x[i] = Math.Atan((b-a)*i/(n-1)+a);
                    }
                    for(i=0; i<=n-1; i++)
                    {
                        y[i] = 2*AP.Math.RandomReal()-1;
                    }
                    w[0] = -(1/(x[1]-x[0]));
                    s = 1;
                    for(i=1; i<=n-2; i++)
                    {
                        w[i] = s*(1/(x[i]-x[i-1])+1/(x[i+1]-x[i]));
                        s = -s;
                    }
                    w[n-1] = s/(x[n-1]-x[n-2]);
                    for(i=0; i<=n-1; i++)
                    {
                        k = AP.Math.RandomInteger(n);
                        if( k!=i )
                        {
                            t = x[i];
                            x[i] = x[k];
                            x[k] = t;
                            t = y[i];
                            y[i] = y[k];
                            y[k] = t;
                            t = w[i];
                            w[i] = w[k];
                            w[k] = t;
                        }
                    }
                    
                    //
                    // Build and test
                    //
                    ratint.barycentricbuildfloaterhormann(ref x, ref y, n, 1, ref b1);
                    ratint.barycentricbuildxyw(ref x, ref y, ref w, n, ref b2);
                    for(i=1; i<=2*n; i++)
                    {
                        t = a+(b-a)*AP.Math.RandomReal();
                        maxerr = Math.Max(maxerr, Math.Abs(ratint.barycentriccalc(ref b1, t)-ratint.barycentriccalc(ref b2, t)));
                    }
                }
                
                //
                // D = 0, 1, 2. Equidistant nodes.
                //
                for(d=0; d<=2; d++)
                {
                    for(pass=1; pass<=passcount; pass++)
                    {
                        
                        //
                        // Skip incorrect (N,D) pairs
                        //
                        if( n<2*d )
                        {
                            continue;
                        }
                        
                        //
                        // Initialize X, Y, W
                        //
                        a = -1-1*AP.Math.RandomReal();
                        b = +1+1*AP.Math.RandomReal();
                        for(i=0; i<=n-1; i++)
                        {
                            x[i] = (b-a)*i/(n-1)+a;
                        }
                        for(i=0; i<=n-1; i++)
                        {
                            y[i] = 2*AP.Math.RandomReal()-1;
                        }
                        s = 1;
                        if( d==0 )
                        {
                            for(i=0; i<=n-1; i++)
                            {
                                w[i] = s;
                                s = -s;
                            }
                        }
                        if( d==1 )
                        {
                            w[0] = -s;
                            for(i=1; i<=n-2; i++)
                            {
                                w[i] = 2*s;
                                s = -s;
                            }
                            w[n-1] = s;
                        }
                        if( d==2 )
                        {
                            w[0] = s;
                            w[1] = -(3*s);
                            for(i=2; i<=n-3; i++)
                            {
                                w[i] = 4*s;
                                s = -s;
                            }
                            w[n-2] = 3*s;
                            w[n-1] = -s;
                        }
                        
                        //
                        // Mix
                        //
                        for(i=0; i<=n-1; i++)
                        {
                            k = AP.Math.RandomInteger(n);
                            if( k!=i )
                            {
                                t = x[i];
                                x[i] = x[k];
                                x[k] = t;
                                t = y[i];
                                y[i] = y[k];
                                y[k] = t;
                                t = w[i];
                                w[i] = w[k];
                                w[k] = t;
                            }
                        }
                        
                        //
                        // Build and test
                        //
                        ratint.barycentricbuildfloaterhormann(ref x, ref y, n, d, ref b1);
                        ratint.barycentricbuildxyw(ref x, ref y, ref w, n, ref b2);
                        for(i=1; i<=2*n; i++)
                        {
                            t = a+(b-a)*AP.Math.RandomReal();
                            maxerr = Math.Max(maxerr, Math.Abs(ratint.barycentriccalc(ref b1, t)-ratint.barycentriccalc(ref b2, t)));
                        }
                    }
                }
            }
            if( (double)(maxerr)>(double)(threshold) )
            {
                nperrors = true;
            }
            
            //
            // Test rational fitting:
            //
            for(pass=1; pass<=passcount; pass++)
            {
                for(n=2; n<=maxn; n++)
                {
                    
                    //
                    // N=M+K fitting (i.e. interpolation)
                    //
                    for(k=0; k<=n-1; k++)
                    {
                        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] = (double)(i)/((double)(n-1));
                            y[i] = 2*AP.Math.RandomReal()-1;
                            w[i] = 1+AP.Math.RandomReal();
                        }
                        for(i=0; i<=k-1; i++)
                        {
                            xc[i] = ((double)(n-k+i))/((double)(n-1));
                            yc[i] = 2*AP.Math.RandomReal()-1;
                            dc[i] = 0;
                        }
                        ratint.barycentricfitfloaterhormannwc(ref x, ref y, ref w, n-k, ref xc, ref yc, ref dc, k, n, ref info, ref b1, ref rep);
                        if( info<=0 )
                        {
                            fiterrors = true;
                        }
                        else
                        {
                            for(i=0; i<=n-k-1; i++)
                            {
                                fiterrors = fiterrors | (double)(Math.Abs(ratint.barycentriccalc(ref b1, x[i])-y[i]))>(double)(threshold);
                            }
                            for(i=0; i<=k-1; i++)
                            {
                                fiterrors = fiterrors | (double)(Math.Abs(ratint.barycentriccalc(ref b1, xc[i])-yc[i]))>(double)(threshold);
                            }
                        }
                    }
                    
                    //
                    // Testing constraints on derivatives:
                    // * several M's are tried
                    // * several K's are tried - 1, 2.
                    // * constraints at the ends of the interval
                    //
                    for(m=3; m<=5; m++)
                    {
                        for(k=1; k<=2; k++)
                        {
                            x = new double[n];
                            y = new double[n];
                            w = new double[n];
                            xc = new double[2];
                            yc = new double[2];
                            dc = new int[2];
                            for(i=0; i<=n-1; i++)
                            {
                                x[i] = 2*AP.Math.RandomReal()-1;
                                y[i] = 2*AP.Math.RandomReal()-1;
                                w[i] = 1+AP.Math.RandomReal();
                            }
                            xc[0] = -1;
                            yc[0] = 2*AP.Math.RandomReal()-1;
                            dc[0] = 0;
                            xc[1] = +1;
                            yc[1] = 2*AP.Math.RandomReal()-1;
                            dc[1] = 0;
                            ratint.barycentricfitfloaterhormannwc(ref x, ref y, ref w, n, ref xc, ref yc, ref dc, k, m, ref info, ref b1, ref rep);
                            if( info<=0 )
                            {
                                fiterrors = true;
                            }
                            else
                            {
                                for(i=0; i<=k-1; i++)
                                {
                                    ratint.barycentricdiff1(ref b1, xc[i], ref v0, ref v1);
                                    fiterrors = fiterrors | (double)(Math.Abs(v0-yc[i]))>(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 = AP.Math.MaxRealNumber;
                    xmax = -AP.Math.MaxRealNumber;
                    for(i=0; i<=n-1; i++)
                    {
                        x2[i] = 2*Math.PI*AP.Math.RandomReal();
                        y2[i] = Math.Sin(x2[i]);
                        w2[i] = 1;
                        xmin = Math.Min(xmin, x2[i]);
                        xmax = Math.Max(xmax, x2[i]);
                    }
                    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]);
                    }
                    ratint.barycentricbuildfloaterhormann(ref x, ref y, m, 3, ref b1);
                    ratint.barycentricfitfloaterhormannwc(ref x2, ref y2, ref w2, n, ref xc, ref yc, ref dc, 0, m, ref info, ref b2, ref rep);
                    if( info<=0 )
                    {
                        fiterrors = true;
                    }
                    else
                    {
                        
                        //
                        // calculate B1 (interpolant) RMS error, compare with B2 error
                        //
                        v1 = 0;
                        v2 = 0;
                        for(i=0; i<=n-1; i++)
                        {
                            v1 = v1+AP.Math.Sqr(ratint.barycentriccalc(ref b1, x2[i])-y2[i]);
                            v2 = v2+AP.Math.Sqr(ratint.barycentriccalc(ref b2, 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;
                    }
                    ratint.barycentricfitfloaterhormannwc(ref x, ref y, ref w, n, ref xc, ref yc, ref dc, 0, m, ref info, ref b1, ref rep);
                    ratint.barycentricfitfloaterhormann(ref x, ref y, n, m, ref info2, ref b2, ref rep2);
                    if( info<=0 | info2<=0 )
                    {
                        fiterrors = true;
                    }
                    else
                    {
                        
                        //
                        // calculate B1 (interpolant), compare with B2
                        // compare RMS errors
                        //
                        t = 2*AP.Math.RandomReal()-1;
                        v1 = ratint.barycentriccalc(ref b1, t);
                        v2 = ratint.barycentriccalc(ref b2, 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
                //
                ratint.barycentricfitfloaterhormann(ref x, ref y, 4, 2, ref info, ref b1, ref rep);
                if( info<=0 )
                {
                    fiterrors = true;
                }
                else
                {
                    s = ratint.barycentriccalc(ref b1, 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 = bcerrors | nperrors | fiterrors;
            if( !silent )
            {
                System.Console.Write("TESTING RATIONAL INTERPOLATION");
                System.Console.WriteLine();
                System.Console.Write("BASIC BARYCENTRIC FUNCTIONS:             ");
                if( bcerrors )
                {
                    System.Console.Write("FAILED");
                    System.Console.WriteLine();
                }
                else
                {
                    System.Console.Write("OK");
                    System.Console.WriteLine();
                }
                System.Console.Write("FLOATER-HORMANN:                         ");
                if( nperrors )
                {
                    System.Console.Write("FAILED");
                    System.Console.WriteLine();
                }
                else
                {
                    System.Console.Write("OK");
                    System.Console.WriteLine();
                }
                System.Console.Write("RATIONAL FITTING:                        ");
                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;
        }
Esempio n. 7
0
        /*************************************************************************
        *  Lagrange intepolant: generation of the model on the general grid.
        *  This function has O(N^2) complexity.
        *
        *  INPUT PARAMETERS:
        *   X   -   abscissas, array[0..N-1]
        *   Y   -   function values, array[0..N-1]
        *   N   -   number of points, N>=1
        *
        *  OIYTPUT PARAMETERS
        *   P   -   barycentric model which represents Lagrange interpolant
        *           (see ratint unit info and BarycentricCalc() description for
        *           more information).
        *
        *  -- ALGLIB --
        *    Copyright 02.12.2009 by Bochkanov Sergey
        *************************************************************************/
        public static void polynomialbuild(ref double[] x,
                                           ref double[] y,
                                           int n,
                                           ref ratint.barycentricinterpolant p)
        {
            int j = 0;
            int k = 0;

            double[] w  = new double[0];
            double   b  = 0;
            double   a  = 0;
            double   v  = 0;
            double   mx = 0;
            int      i_ = 0;

            System.Diagnostics.Debug.Assert(n > 0, "PolIntBuild: N<=0!");

            //
            // calculate W[j]
            // multi-pass algorithm is used to avoid overflow
            //
            w = new double[n];
            a = x[0];
            b = x[0];
            for (j = 0; j <= n - 1; j++)
            {
                w[j] = 1;
                a    = Math.Min(a, x[j]);
                b    = Math.Max(b, x[j]);
            }
            for (k = 0; k <= n - 1; k++)
            {
                //
                // W[K] is used instead of 0.0 because
                // cycle on J does not touch K-th element
                // and we MUST get maximum from ALL elements
                //
                mx = Math.Abs(w[k]);
                for (j = 0; j <= n - 1; j++)
                {
                    if (j != k)
                    {
                        v    = (b - a) / (x[j] - x[k]);
                        w[j] = w[j] * v;
                        mx   = Math.Max(mx, Math.Abs(w[j]));
                    }
                }
                if (k % 5 == 0)
                {
                    //
                    // every 5-th run we renormalize W[]
                    //
                    v = 1 / mx;
                    for (i_ = 0; i_ <= n - 1; i_++)
                    {
                        w[i_] = v * w[i_];
                    }
                }
            }
            ratint.barycentricbuildxyw(ref x, ref y, ref w, n, ref p);
        }
        /*************************************************************************
        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;
        }
Esempio n. 9
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);
        }
Esempio n. 10
0
        /*************************************************************************
        *  Weighted  fitting  by  Chebyshev  polynomial  in  barycentric  form,  with
        *  constraints on function values or first derivatives.
        *
        *  Small regularizing term is used when solving constrained tasks (to improve
        *  stability).
        *
        *  Task is linear, so linear least squares solver is used. Complexity of this
        *  computational scheme is O(N*M^2), mostly dominated by least squares solver
        *
        *  SEE ALSO:
        *   PolynomialFit()
        *
        *  INPUT PARAMETERS:
        *   X   -   points, array[0..N-1].
        *   Y   -   function values, array[0..N-1].
        *   W   -   weights, array[0..N-1]
        *           Each summand in square  sum  of  approximation deviations from
        *           given  values  is  multiplied  by  the square of corresponding
        *           weight. Fill it by 1's if you don't  want  to  solve  weighted
        *           task.
        *   N   -   number of points, N>0.
        *   XC  -   points where polynomial values/derivatives are constrained,
        *           array[0..K-1].
        *   YC  -   values of constraints, array[0..K-1]
        *   DC  -   array[0..K-1], types of constraints:
        * DC[i]=0   means that P(XC[i])=YC[i]
        * DC[i]=1   means that P'(XC[i])=YC[i]
        *           SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS
        *   K   -   number of constraints, 0<=K<M.
        *           K=0 means no constraints (XC/YC/DC are not used in such cases)
        *   M   -   number of basis functions (= polynomial_degree + 1), M>=1
        *
        *  OUTPUT PARAMETERS:
        *   Info-   same format as in LSFitLinearW() subroutine:
        * Info>0    task is solved
        * Info<=0   an error occured:
        *                       -4 means inconvergence of internal SVD
        *                       -3 means inconsistent constraints
        *                       -1 means another errors in parameters passed
        *                          (N<=0, for example)
        *   P   -   interpolant in barycentric form.
        *   Rep -   report, same format as in LSFitLinearW() subroutine.
        *           Following fields are set:
        * RMSError      rms error on the (X,Y).
        * AvgError      average error on the (X,Y).
        * AvgRelError   average relative error on the non-zero Y
        * MaxError      maximum error
        *                           NON-WEIGHTED ERRORS ARE CALCULATED
        *
        *  IMPORTANT:
        *   this subroitine doesn't calculate task's condition number for K<>0.
        *
        *  SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES:
        *
        *  Setting constraints can lead  to undesired  results,  like ill-conditioned
        *  behavior, or inconsistency being detected. From the other side,  it allows
        *  us to improve quality of the fit. Here we summarize  our  experience  with
        *  constrained regression splines:
        * even simple constraints can be inconsistent, see  Wikipedia  article  on
        *  this subject: http://en.wikipedia.org/wiki/Birkhoff_interpolation
        * the  greater  is  M (given  fixed  constraints),  the  more chances that
        *  constraints will be consistent
        * in the general case, consistency of constraints is NOT GUARANTEED.
        * in the one special cases, however, we can  guarantee  consistency.  This
        *  case  is:  M>1  and constraints on the function values (NOT DERIVATIVES)
        *
        *  Our final recommendation is to use constraints  WHEN  AND  ONLY  when  you
        *  can't solve your task without them. Anything beyond  special  cases  given
        *  above is not guaranteed and may result in inconsistency.
        *
        *  -- ALGLIB PROJECT --
        *    Copyright 10.12.2009 by Bochkanov Sergey
        *************************************************************************/
        public static void polynomialfitwc(double[] x,
                                           double[] y,
                                           ref double[] w,
                                           int n,
                                           double[] xc,
                                           double[] yc,
                                           ref int[] dc,
                                           int k,
                                           int m,
                                           ref int info,
                                           ref ratint.barycentricinterpolant p,
                                           ref polynomialfitreport rep)
        {
            double xa = 0;
            double xb = 0;
            double sa = 0;
            double sb = 0;

            double[] xoriginal = new double[0];
            double[] yoriginal = new double[0];
            double[] y2        = new double[0];
            double[] w2        = new double[0];
            double[] tmp       = new double[0];
            double[] tmp2      = new double[0];
            double[] tmpdiff   = new double[0];
            double[] bx        = new double[0];
            double[] by        = new double[0];
            double[] bw        = new double[0];
            double[,] fmatrix = new double[0, 0];
            double[,] cmatrix = new double[0, 0];
            int    i      = 0;
            int    j      = 0;
            double mx     = 0;
            double decay  = 0;
            double u      = 0;
            double v      = 0;
            double s      = 0;
            int    relcnt = 0;

            lsfit.lsfitreport lrep = new lsfit.lsfitreport();
            int i_ = 0;

            x  = (double[])x.Clone();
            y  = (double[])y.Clone();
            xc = (double[])xc.Clone();
            yc = (double[])yc.Clone();

            if (m < 1 | n < 1 | k < 0 | k >= m)
            {
                info = -1;
                return;
            }
            for (i = 0; i <= k - 1; i++)
            {
                info = 0;
                if (dc[i] < 0)
                {
                    info = -1;
                }
                if (dc[i] > 1)
                {
                    info = -1;
                }
                if (info < 0)
                {
                    return;
                }
            }

            //
            // weight decay for correct handling of task which becomes
            // degenerate after constraints are applied
            //
            decay = 10000 * AP.Math.MachineEpsilon;

            //
            // Scale X, Y, XC, YC
            //
            lsfit.lsfitscalexy(ref x, ref y, n, ref xc, ref yc, ref dc, k, ref xa, ref xb, ref sa, ref sb, ref xoriginal, ref yoriginal);

            //
            // allocate space, initialize/fill:
            // * FMatrix-   values of basis functions at X[]
            // * CMatrix-   values (derivatives) of basis functions at XC[]
            // * fill constraints matrix
            // * fill first N rows of design matrix with values
            // * fill next M rows of design matrix with regularizing term
            // * append M zeros to Y
            // * append M elements, mean(abs(W)) each, to W
            //
            y2      = new double[n + m];
            w2      = new double[n + m];
            tmp     = new double[m];
            tmpdiff = new double[m];
            fmatrix = new double[n + m, m];
            if (k > 0)
            {
                cmatrix = new double[k, m + 1];
            }

            //
            // Fill design matrix, Y2, W2:
            // * first N rows with basis functions for original points
            // * next M rows with decay terms
            //
            for (i = 0; i <= n - 1; i++)
            {
                //
                // prepare Ith row
                // use Tmp for calculations to avoid multidimensional arrays overhead
                //
                for (j = 0; j <= m - 1; j++)
                {
                    if (j == 0)
                    {
                        tmp[j] = 1;
                    }
                    else
                    {
                        if (j == 1)
                        {
                            tmp[j] = x[i];
                        }
                        else
                        {
                            tmp[j] = 2 * x[i] * tmp[j - 1] - tmp[j - 2];
                        }
                    }
                }
                for (i_ = 0; i_ <= m - 1; i_++)
                {
                    fmatrix[i, i_] = tmp[i_];
                }
            }
            for (i = 0; i <= m - 1; i++)
            {
                for (j = 0; j <= m - 1; j++)
                {
                    if (i == j)
                    {
                        fmatrix[n + i, j] = decay;
                    }
                    else
                    {
                        fmatrix[n + i, j] = 0;
                    }
                }
            }
            for (i_ = 0; i_ <= n - 1; i_++)
            {
                y2[i_] = y[i_];
            }
            for (i_ = 0; i_ <= n - 1; i_++)
            {
                w2[i_] = w[i_];
            }
            mx = 0;
            for (i = 0; i <= n - 1; i++)
            {
                mx = mx + Math.Abs(w[i]);
            }
            mx = mx / n;
            for (i = 0; i <= m - 1; i++)
            {
                y2[n + i] = 0;
                w2[n + i] = mx;
            }

            //
            // fill constraints matrix
            //
            for (i = 0; i <= k - 1; i++)
            {
                //
                // prepare Ith row
                // use Tmp for basis function values,
                // TmpDiff for basos function derivatives
                //
                for (j = 0; j <= m - 1; j++)
                {
                    if (j == 0)
                    {
                        tmp[j]     = 1;
                        tmpdiff[j] = 0;
                    }
                    else
                    {
                        if (j == 1)
                        {
                            tmp[j]     = xc[i];
                            tmpdiff[j] = 1;
                        }
                        else
                        {
                            tmp[j]     = 2 * xc[i] * tmp[j - 1] - tmp[j - 2];
                            tmpdiff[j] = 2 * (tmp[j - 1] + xc[i] * tmpdiff[j - 1]) - tmpdiff[j - 2];
                        }
                    }
                }
                if (dc[i] == 0)
                {
                    for (i_ = 0; i_ <= m - 1; i_++)
                    {
                        cmatrix[i, i_] = tmp[i_];
                    }
                }
                if (dc[i] == 1)
                {
                    for (i_ = 0; i_ <= m - 1; i_++)
                    {
                        cmatrix[i, i_] = tmpdiff[i_];
                    }
                }
                cmatrix[i, m] = yc[i];
            }

            //
            // Solve constrained task
            //
            if (k > 0)
            {
                //
                // solve using regularization
                //
                lsfit.lsfitlinearwc(y2, ref w2, ref fmatrix, cmatrix, n + m, m, k, ref info, ref tmp, ref lrep);
            }
            else
            {
                //
                // no constraints, no regularization needed
                //
                lsfit.lsfitlinearwc(y, ref w, ref fmatrix, cmatrix, n, m, 0, ref info, ref tmp, ref lrep);
            }
            if (info < 0)
            {
                return;
            }

            //
            // Generate barycentric model and scale it
            // * BX, BY store barycentric model nodes
            // * FMatrix is reused (remember - it is at least MxM, what we need)
            //
            // Model intialization is done in O(M^2). In principle, it can be
            // done in O(M*log(M)), but before it we solved task with O(N*M^2)
            // complexity, so it is only a small amount of total time spent.
            //
            bx   = new double[m];
            by   = new double[m];
            bw   = new double[m];
            tmp2 = new double[m];
            s    = 1;
            for (i = 0; i <= m - 1; i++)
            {
                if (m != 1)
                {
                    u = Math.Cos(Math.PI * i / (m - 1));
                }
                else
                {
                    u = 0;
                }
                v = 0;
                for (j = 0; j <= m - 1; j++)
                {
                    if (j == 0)
                    {
                        tmp2[j] = 1;
                    }
                    else
                    {
                        if (j == 1)
                        {
                            tmp2[j] = u;
                        }
                        else
                        {
                            tmp2[j] = 2 * u * tmp2[j - 1] - tmp2[j - 2];
                        }
                    }
                    v = v + tmp[j] * tmp2[j];
                }
                bx[i] = u;
                by[i] = v;
                bw[i] = s;
                if (i == 0 | i == m - 1)
                {
                    bw[i] = 0.5 * bw[i];
                }
                s = -s;
            }
            ratint.barycentricbuildxyw(ref bx, ref by, ref bw, m, ref p);
            ratint.barycentriclintransx(ref p, 2 / (xb - xa), -((xa + xb) / (xb - xa)));
            ratint.barycentriclintransy(ref p, sb - sa, sa);

            //
            // Scale absolute errors obtained from LSFitLinearW.
            // Relative error should be calculated separately
            // (because of shifting/scaling of the task)
            //
            rep.taskrcond   = lrep.taskrcond;
            rep.rmserror    = lrep.rmserror * (sb - sa);
            rep.avgerror    = lrep.avgerror * (sb - sa);
            rep.maxerror    = lrep.maxerror * (sb - sa);
            rep.avgrelerror = 0;
            relcnt          = 0;
            for (i = 0; i <= n - 1; i++)
            {
                if ((double)(yoriginal[i]) != (double)(0))
                {
                    rep.avgrelerror = rep.avgrelerror + Math.Abs(ratint.barycentriccalc(ref p, xoriginal[i]) - yoriginal[i]) / Math.Abs(yoriginal[i]);
                    relcnt          = relcnt + 1;
                }
            }
            if (relcnt != 0)
            {
                rep.avgrelerror = rep.avgrelerror / relcnt;
            }
        }
Esempio n. 11
0
        public static bool testri(bool silent)
        {
            bool   result       = new bool();
            bool   waserrors    = new bool();
            bool   bcerrors     = new bool();
            bool   nperrors     = new bool();
            bool   fiterrors    = new bool();
            double threshold    = 0;
            double lipschitztol = 0;
            int    maxn         = 0;
            int    passcount    = 0;

            ratint.barycentricinterpolant b1 = new ratint.barycentricinterpolant();
            ratint.barycentricinterpolant b2 = new ratint.barycentricinterpolant();
            double[] x         = new double[0];
            double[] x2        = new double[0];
            double[] y         = new double[0];
            double[] y2        = new double[0];
            double[] w         = new double[0];
            double[] w2        = new double[0];
            double[] xc        = new double[0];
            double[] yc        = new double[0];
            int[]    dc        = new int[0];
            double   h         = 0;
            double   s1        = 0;
            double   s2        = 0;
            bool     bsame     = new bool();
            int      n         = 0;
            int      m         = 0;
            int      n2        = 0;
            int      i         = 0;
            int      j         = 0;
            int      k         = 0;
            int      d         = 0;
            int      pass      = 0;
            double   err       = 0;
            double   maxerr    = 0;
            double   t         = 0;
            double   a         = 0;
            double   b         = 0;
            double   s         = 0;
            double   v         = 0;
            double   v0        = 0;
            double   v1        = 0;
            double   v2        = 0;
            double   v3        = 0;
            double   d0        = 0;
            double   d1        = 0;
            double   d2        = 0;
            int      info      = 0;
            int      info2     = 0;
            double   xmin      = 0;
            double   xmax      = 0;
            double   refrms    = 0;
            double   refavg    = 0;
            double   refavgrel = 0;
            double   refmax    = 0;

            double[] ra    = new double[0];
            double[] ra2   = new double[0];
            int      ralen = 0;

            ratint.barycentricfitreport   rep  = new ratint.barycentricfitreport();
            ratint.barycentricfitreport   rep2 = new ratint.barycentricfitreport();
            ratint.barycentricinterpolant b3   = new ratint.barycentricinterpolant();
            ratint.barycentricinterpolant b4   = new ratint.barycentricinterpolant();
            int i_ = 0;

            nperrors  = false;
            bcerrors  = false;
            fiterrors = false;
            waserrors = false;

            //
            // PassCount        number of repeated passes
            // Threshold        error tolerance
            // LipschitzTol     Lipschitz constant increase allowed
            //                  when calculating constant on a twice denser grid
            //
            passcount    = 5;
            maxn         = 15;
            threshold    = 1000000 * AP.Math.MachineEpsilon;
            lipschitztol = 1.3;

            //
            // Basic barycentric functions
            //
            for (n = 1; n <= 10; n++)
            {
                //
                // randomized tests
                //
                for (pass = 1; pass <= passcount; pass++)
                {
                    //
                    // generate weights from polynomial interpolation
                    //
                    v0 = 1 + 0.4 * AP.Math.RandomReal() - 0.2;
                    v1 = 2 * AP.Math.RandomReal() - 1;
                    v2 = 2 * AP.Math.RandomReal() - 1;
                    v3 = 2 * AP.Math.RandomReal() - 1;
                    x  = new double[n];
                    y  = new double[n];
                    w  = new double[n];
                    for (i = 0; i <= n - 1; i++)
                    {
                        if (n == 1)
                        {
                            x[i] = 0;
                        }
                        else
                        {
                            x[i] = v0 * Math.Cos(i * Math.PI / (n - 1));
                        }
                        y[i] = Math.Sin(v1 * x[i]) + Math.Cos(v2 * x[i]) + Math.Exp(v3 * x[i]);
                    }
                    for (j = 0; j <= n - 1; j++)
                    {
                        w[j] = 1;
                        for (k = 0; k <= n - 1; k++)
                        {
                            if (k != j)
                            {
                                w[j] = w[j] / (x[j] - x[k]);
                            }
                        }
                    }
                    ratint.barycentricbuildxyw(ref x, ref y, ref w, n, ref b1);

                    //
                    // unpack, then pack again and compare
                    //
                    brcunset(ref b2);
                    ratint.barycentricunpack(ref b1, ref n2, ref x2, ref y2, ref w2);
                    bcerrors = bcerrors | n2 != n;
                    ratint.barycentricbuildxyw(ref x2, ref y2, ref w2, n2, ref b2);
                    t        = 2 * AP.Math.RandomReal() - 1;
                    bcerrors = bcerrors | (double)(Math.Abs(ratint.barycentriccalc(ref b1, t) - ratint.barycentriccalc(ref b2, t))) > (double)(threshold);

                    //
                    // serialize, unserialize, compare
                    //
                    brcunset(ref b2);
                    ratint.barycentricserialize(ref b1, ref ra, ref ralen);
                    ra2 = new double[ralen];
                    for (i_ = 0; i_ <= ralen - 1; i_++)
                    {
                        ra2[i_] = ra[i_];
                    }
                    ratint.barycentricunserialize(ref ra2, ref b2);
                    t        = 2 * AP.Math.RandomReal() - 1;
                    bcerrors = bcerrors | (double)(Math.Abs(ratint.barycentriccalc(ref b1, t) - ratint.barycentriccalc(ref b2, t))) > (double)(threshold);

                    //
                    // copy, compare
                    //
                    brcunset(ref b2);
                    ratint.barycentriccopy(ref b1, ref b2);
                    t        = 2 * AP.Math.RandomReal() - 1;
                    bcerrors = bcerrors | (double)(Math.Abs(ratint.barycentriccalc(ref b1, t) - ratint.barycentriccalc(ref b2, t))) > (double)(threshold);

                    //
                    // test interpolation properties
                    //
                    for (i = 0; i <= n - 1; i++)
                    {
                        //
                        // test interpolation at nodes
                        //
                        bcerrors = bcerrors | (double)(Math.Abs(ratint.barycentriccalc(ref b1, x[i]) - y[i])) > (double)(threshold * Math.Abs(y[i]));

                        //
                        // compare with polynomial interpolation
                        //
                        t = 2 * AP.Math.RandomReal() - 1;
                        poldiff2(ref x, y, n, t, ref v0, ref v1, ref v2);
                        bcerrors = bcerrors | (double)(Math.Abs(ratint.barycentriccalc(ref b1, t) - v0)) > (double)(threshold * Math.Max(Math.Abs(v0), 1));

                        //
                        // test continuity between nodes
                        // calculate Lipschitz constant on two grids -
                        // dense and even more dense. If Lipschitz constant
                        // on a denser grid is significantly increased,
                        // continuity test is failed
                        //
                        t  = 3.0;
                        k  = 100;
                        s1 = 0;
                        for (j = 0; j <= k - 1; j++)
                        {
                            v1 = x[i] + (t - x[i]) * j / k;
                            v2 = x[i] + (t - x[i]) * (j + 1) / k;
                            s1 = Math.Max(s1, Math.Abs(ratint.barycentriccalc(ref b1, v2) - ratint.barycentriccalc(ref b1, v1)) / Math.Abs(v2 - v1));
                        }
                        k  = 2 * k;
                        s2 = 0;
                        for (j = 0; j <= k - 1; j++)
                        {
                            v1 = x[i] + (t - x[i]) * j / k;
                            v2 = x[i] + (t - x[i]) * (j + 1) / k;
                            s2 = Math.Max(s2, Math.Abs(ratint.barycentriccalc(ref b1, v2) - ratint.barycentriccalc(ref b1, v1)) / Math.Abs(v2 - v1));
                        }
                        bcerrors = bcerrors | (double)(s2) > (double)(lipschitztol * s1) & (double)(s1) > (double)(threshold * k);
                    }

                    //
                    // test differentiation properties
                    //
                    for (i = 0; i <= n - 1; i++)
                    {
                        t = 2 * AP.Math.RandomReal() - 1;
                        poldiff2(ref x, y, n, t, ref v0, ref v1, ref v2);
                        d0 = 0;
                        d1 = 0;
                        d2 = 0;
                        ratint.barycentricdiff1(ref b1, t, ref d0, ref d1);
                        bcerrors = bcerrors | (double)(Math.Abs(v0 - d0)) > (double)(threshold * Math.Max(Math.Abs(v0), 1));
                        bcerrors = bcerrors | (double)(Math.Abs(v1 - d1)) > (double)(threshold * Math.Max(Math.Abs(v1), 1));
                        d0       = 0;
                        d1       = 0;
                        d2       = 0;
                        ratint.barycentricdiff2(ref b1, t, ref d0, ref d1, ref d2);
                        bcerrors = bcerrors | (double)(Math.Abs(v0 - d0)) > (double)(threshold * Math.Max(Math.Abs(v0), 1));
                        bcerrors = bcerrors | (double)(Math.Abs(v1 - d1)) > (double)(threshold * Math.Max(Math.Abs(v1), 1));
                        bcerrors = bcerrors | (double)(Math.Abs(v2 - d2)) > (double)(Math.Sqrt(threshold) * Math.Max(Math.Abs(v2), 1));
                    }

                    //
                    // test linear translation
                    //
                    t = 2 * AP.Math.RandomReal() - 1;
                    a = 2 * AP.Math.RandomReal() - 1;
                    b = 2 * AP.Math.RandomReal() - 1;
                    brcunset(ref b2);
                    ratint.barycentriccopy(ref b1, ref b2);
                    ratint.barycentriclintransx(ref b2, a, b);
                    bcerrors = bcerrors | (double)(Math.Abs(ratint.barycentriccalc(ref b1, a * t + b) - ratint.barycentriccalc(ref b2, t))) > (double)(threshold);
                    a        = 0;
                    b        = 2 * AP.Math.RandomReal() - 1;
                    brcunset(ref b2);
                    ratint.barycentriccopy(ref b1, ref b2);
                    ratint.barycentriclintransx(ref b2, a, b);
                    bcerrors = bcerrors | (double)(Math.Abs(ratint.barycentriccalc(ref b1, a * t + b) - ratint.barycentriccalc(ref b2, t))) > (double)(threshold);
                    a        = 2 * AP.Math.RandomReal() - 1;
                    b        = 2 * AP.Math.RandomReal() - 1;
                    brcunset(ref b2);
                    ratint.barycentriccopy(ref b1, ref b2);
                    ratint.barycentriclintransy(ref b2, a, b);
                    bcerrors = bcerrors | (double)(Math.Abs(a * ratint.barycentriccalc(ref b1, t) + b - ratint.barycentriccalc(ref b2, t))) > (double)(threshold);
                }
            }
            for (pass = 0; pass <= 3; pass++)
            {
                //
                // Crash-test: small numbers, large numbers
                //
                x = new double[4];
                y = new double[4];
                w = new double[4];
                h = 1;
                if (pass % 2 == 0)
                {
                    h = 100 * AP.Math.MinRealNumber;
                }
                if (pass % 2 == 1)
                {
                    h = 0.01 * AP.Math.MaxRealNumber;
                }
                x[0] = 0 * h;
                x[1] = 1 * h;
                x[2] = 2 * h;
                x[3] = 3 * h;
                y[0] = 0 * h;
                y[1] = 1 * h;
                y[2] = 2 * h;
                y[3] = 3 * h;
                w[0] = -(1 / (x[1] - x[0]));
                w[1] = +(1 * (1 / (x[1] - x[0]) + 1 / (x[2] - x[1])));
                w[2] = -(1 * (1 / (x[2] - x[1]) + 1 / (x[3] - x[2])));
                w[3] = +(1 / (x[3] - x[2]));
                if (pass / 2 == 0)
                {
                    v0 = 0;
                }
                if (pass / 2 == 1)
                {
                    v0 = 0.6 * h;
                }
                ratint.barycentricbuildxyw(ref x, ref y, ref w, 4, ref b1);
                t  = ratint.barycentriccalc(ref b1, v0);
                d0 = 0;
                d1 = 0;
                d2 = 0;
                ratint.barycentricdiff1(ref b1, v0, ref d0, ref d1);
                bcerrors = bcerrors | (double)(Math.Abs(t - v0)) > (double)(threshold * v0);
                bcerrors = bcerrors | (double)(Math.Abs(d0 - v0)) > (double)(threshold * v0);
                bcerrors = bcerrors | (double)(Math.Abs(d1 - 1)) > (double)(1000 * threshold);
            }

            //
            // crash test: large abscissas, small argument
            //
            // test for errors in D0 is not very strict
            // because renormalization used in Diff1()
            // destroys part of precision.
            //
            x    = new double[4];
            y    = new double[4];
            w    = new double[4];
            h    = 0.01 * AP.Math.MaxRealNumber;
            x[0] = 0 * h;
            x[1] = 1 * h;
            x[2] = 2 * h;
            x[3] = 3 * h;
            y[0] = 0 * h;
            y[1] = 1 * h;
            y[2] = 2 * h;
            y[3] = 3 * h;
            w[0] = -(1 / (x[1] - x[0]));
            w[1] = +(1 * (1 / (x[1] - x[0]) + 1 / (x[2] - x[1])));
            w[2] = -(1 * (1 / (x[2] - x[1]) + 1 / (x[3] - x[2])));
            w[3] = +(1 / (x[3] - x[2]));
            v0   = 100 * AP.Math.MinRealNumber;
            ratint.barycentricbuildxyw(ref x, ref y, ref w, 4, ref b1);
            t  = ratint.barycentriccalc(ref b1, v0);
            d0 = 0;
            d1 = 0;
            d2 = 0;
            ratint.barycentricdiff1(ref b1, v0, ref d0, ref d1);
            bcerrors = bcerrors | (double)(Math.Abs(t)) > (double)(v0 * (1 + threshold));
            bcerrors = bcerrors | (double)(Math.Abs(d0)) > (double)(v0 * (1 + threshold));
            bcerrors = bcerrors | (double)(Math.Abs(d1 - 1)) > (double)(1000 * threshold);

            //
            // crash test: test safe barycentric formula
            //
            x    = new double[4];
            y    = new double[4];
            w    = new double[4];
            h    = 2 * AP.Math.MinRealNumber;
            x[0] = 0 * h;
            x[1] = 1 * h;
            x[2] = 2 * h;
            x[3] = 3 * h;
            y[0] = 0 * h;
            y[1] = 1 * h;
            y[2] = 2 * h;
            y[3] = 3 * h;
            w[0] = -(1 / (x[1] - x[0]));
            w[1] = +(1 * (1 / (x[1] - x[0]) + 1 / (x[2] - x[1])));
            w[2] = -(1 * (1 / (x[2] - x[1]) + 1 / (x[3] - x[2])));
            w[3] = +(1 / (x[3] - x[2]));
            v0   = AP.Math.MinRealNumber;
            ratint.barycentricbuildxyw(ref x, ref y, ref w, 4, ref b1);
            t        = ratint.barycentriccalc(ref b1, v0);
            bcerrors = bcerrors | (double)(Math.Abs(t - v0) / v0) > (double)(threshold);

            //
            // Testing "No Poles" interpolation
            //
            maxerr = 0;
            for (pass = 1; pass <= passcount - 1; pass++)
            {
                x    = new double[1];
                y    = new double[1];
                x[0] = 2 * AP.Math.RandomReal() - 1;
                y[0] = 2 * AP.Math.RandomReal() - 1;
                ratint.barycentricbuildfloaterhormann(ref x, ref y, 1, 1, ref b1);
                maxerr = Math.Max(maxerr, Math.Abs(ratint.barycentriccalc(ref b1, 2 * AP.Math.RandomReal() - 1) - y[0]));
            }
            for (n = 2; n <= 10; n++)
            {
                //
                // compare interpolant built by subroutine
                // with interpolant built by hands
                //
                x  = new double[n];
                y  = new double[n];
                w  = new double[n];
                w2 = new double[n];

                //
                // D=1, non-equidistant nodes
                //
                for (pass = 1; pass <= passcount; pass++)
                {
                    //
                    // Initialize X, Y, W
                    //
                    a = -1 - 1 * AP.Math.RandomReal();
                    b = +1 + 1 * AP.Math.RandomReal();
                    for (i = 0; i <= n - 1; i++)
                    {
                        x[i] = Math.Atan((b - a) * i / (n - 1) + a);
                    }
                    for (i = 0; i <= n - 1; i++)
                    {
                        y[i] = 2 * AP.Math.RandomReal() - 1;
                    }
                    w[0] = -(1 / (x[1] - x[0]));
                    s    = 1;
                    for (i = 1; i <= n - 2; i++)
                    {
                        w[i] = s * (1 / (x[i] - x[i - 1]) + 1 / (x[i + 1] - x[i]));
                        s    = -s;
                    }
                    w[n - 1] = s / (x[n - 1] - x[n - 2]);
                    for (i = 0; i <= n - 1; i++)
                    {
                        k = AP.Math.RandomInteger(n);
                        if (k != i)
                        {
                            t    = x[i];
                            x[i] = x[k];
                            x[k] = t;
                            t    = y[i];
                            y[i] = y[k];
                            y[k] = t;
                            t    = w[i];
                            w[i] = w[k];
                            w[k] = t;
                        }
                    }

                    //
                    // Build and test
                    //
                    ratint.barycentricbuildfloaterhormann(ref x, ref y, n, 1, ref b1);
                    ratint.barycentricbuildxyw(ref x, ref y, ref w, n, ref b2);
                    for (i = 1; i <= 2 * n; i++)
                    {
                        t      = a + (b - a) * AP.Math.RandomReal();
                        maxerr = Math.Max(maxerr, Math.Abs(ratint.barycentriccalc(ref b1, t) - ratint.barycentriccalc(ref b2, t)));
                    }
                }

                //
                // D = 0, 1, 2. Equidistant nodes.
                //
                for (d = 0; d <= 2; d++)
                {
                    for (pass = 1; pass <= passcount; pass++)
                    {
                        //
                        // Skip incorrect (N,D) pairs
                        //
                        if (n < 2 * d)
                        {
                            continue;
                        }

                        //
                        // Initialize X, Y, W
                        //
                        a = -1 - 1 * AP.Math.RandomReal();
                        b = +1 + 1 * AP.Math.RandomReal();
                        for (i = 0; i <= n - 1; i++)
                        {
                            x[i] = (b - a) * i / (n - 1) + a;
                        }
                        for (i = 0; i <= n - 1; i++)
                        {
                            y[i] = 2 * AP.Math.RandomReal() - 1;
                        }
                        s = 1;
                        if (d == 0)
                        {
                            for (i = 0; i <= n - 1; i++)
                            {
                                w[i] = s;
                                s    = -s;
                            }
                        }
                        if (d == 1)
                        {
                            w[0] = -s;
                            for (i = 1; i <= n - 2; i++)
                            {
                                w[i] = 2 * s;
                                s    = -s;
                            }
                            w[n - 1] = s;
                        }
                        if (d == 2)
                        {
                            w[0] = s;
                            w[1] = -(3 * s);
                            for (i = 2; i <= n - 3; i++)
                            {
                                w[i] = 4 * s;
                                s    = -s;
                            }
                            w[n - 2] = 3 * s;
                            w[n - 1] = -s;
                        }

                        //
                        // Mix
                        //
                        for (i = 0; i <= n - 1; i++)
                        {
                            k = AP.Math.RandomInteger(n);
                            if (k != i)
                            {
                                t    = x[i];
                                x[i] = x[k];
                                x[k] = t;
                                t    = y[i];
                                y[i] = y[k];
                                y[k] = t;
                                t    = w[i];
                                w[i] = w[k];
                                w[k] = t;
                            }
                        }

                        //
                        // Build and test
                        //
                        ratint.barycentricbuildfloaterhormann(ref x, ref y, n, d, ref b1);
                        ratint.barycentricbuildxyw(ref x, ref y, ref w, n, ref b2);
                        for (i = 1; i <= 2 * n; i++)
                        {
                            t      = a + (b - a) * AP.Math.RandomReal();
                            maxerr = Math.Max(maxerr, Math.Abs(ratint.barycentriccalc(ref b1, t) - ratint.barycentriccalc(ref b2, t)));
                        }
                    }
                }
            }
            if ((double)(maxerr) > (double)(threshold))
            {
                nperrors = true;
            }

            //
            // Test rational fitting:
            //
            for (pass = 1; pass <= passcount; pass++)
            {
                for (n = 2; n <= maxn; n++)
                {
                    //
                    // N=M+K fitting (i.e. interpolation)
                    //
                    for (k = 0; k <= n - 1; k++)
                    {
                        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] = (double)(i) / ((double)(n - 1));
                            y[i] = 2 * AP.Math.RandomReal() - 1;
                            w[i] = 1 + AP.Math.RandomReal();
                        }
                        for (i = 0; i <= k - 1; i++)
                        {
                            xc[i] = ((double)(n - k + i)) / ((double)(n - 1));
                            yc[i] = 2 * AP.Math.RandomReal() - 1;
                            dc[i] = 0;
                        }
                        ratint.barycentricfitfloaterhormannwc(ref x, ref y, ref w, n - k, ref xc, ref yc, ref dc, k, n, ref info, ref b1, ref rep);
                        if (info <= 0)
                        {
                            fiterrors = true;
                        }
                        else
                        {
                            for (i = 0; i <= n - k - 1; i++)
                            {
                                fiterrors = fiterrors | (double)(Math.Abs(ratint.barycentriccalc(ref b1, x[i]) - y[i])) > (double)(threshold);
                            }
                            for (i = 0; i <= k - 1; i++)
                            {
                                fiterrors = fiterrors | (double)(Math.Abs(ratint.barycentriccalc(ref b1, xc[i]) - yc[i])) > (double)(threshold);
                            }
                        }
                    }

                    //
                    // Testing constraints on derivatives:
                    // * several M's are tried
                    // * several K's are tried - 1, 2.
                    // * constraints at the ends of the interval
                    //
                    for (m = 3; m <= 5; m++)
                    {
                        for (k = 1; k <= 2; k++)
                        {
                            x  = new double[n];
                            y  = new double[n];
                            w  = new double[n];
                            xc = new double[2];
                            yc = new double[2];
                            dc = new int[2];
                            for (i = 0; i <= n - 1; i++)
                            {
                                x[i] = 2 * AP.Math.RandomReal() - 1;
                                y[i] = 2 * AP.Math.RandomReal() - 1;
                                w[i] = 1 + AP.Math.RandomReal();
                            }
                            xc[0] = -1;
                            yc[0] = 2 * AP.Math.RandomReal() - 1;
                            dc[0] = 0;
                            xc[1] = +1;
                            yc[1] = 2 * AP.Math.RandomReal() - 1;
                            dc[1] = 0;
                            ratint.barycentricfitfloaterhormannwc(ref x, ref y, ref w, n, ref xc, ref yc, ref dc, k, m, ref info, ref b1, ref rep);
                            if (info <= 0)
                            {
                                fiterrors = true;
                            }
                            else
                            {
                                for (i = 0; i <= k - 1; i++)
                                {
                                    ratint.barycentricdiff1(ref b1, xc[i], ref v0, ref v1);
                                    fiterrors = fiterrors | (double)(Math.Abs(v0 - yc[i])) > (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 = AP.Math.MaxRealNumber;
                    xmax = -AP.Math.MaxRealNumber;
                    for (i = 0; i <= n - 1; i++)
                    {
                        x2[i] = 2 * Math.PI * AP.Math.RandomReal();
                        y2[i] = Math.Sin(x2[i]);
                        w2[i] = 1;
                        xmin  = Math.Min(xmin, x2[i]);
                        xmax  = Math.Max(xmax, x2[i]);
                    }
                    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]);
                    }
                    ratint.barycentricbuildfloaterhormann(ref x, ref y, m, 3, ref b1);
                    ratint.barycentricfitfloaterhormannwc(ref x2, ref y2, ref w2, n, ref xc, ref yc, ref dc, 0, m, ref info, ref b2, ref rep);
                    if (info <= 0)
                    {
                        fiterrors = true;
                    }
                    else
                    {
                        //
                        // calculate B1 (interpolant) RMS error, compare with B2 error
                        //
                        v1 = 0;
                        v2 = 0;
                        for (i = 0; i <= n - 1; i++)
                        {
                            v1 = v1 + AP.Math.Sqr(ratint.barycentriccalc(ref b1, x2[i]) - y2[i]);
                            v2 = v2 + AP.Math.Sqr(ratint.barycentriccalc(ref b2, 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;
                    }
                    ratint.barycentricfitfloaterhormannwc(ref x, ref y, ref w, n, ref xc, ref yc, ref dc, 0, m, ref info, ref b1, ref rep);
                    ratint.barycentricfitfloaterhormann(ref x, ref y, n, m, ref info2, ref b2, ref rep2);
                    if (info <= 0 | info2 <= 0)
                    {
                        fiterrors = true;
                    }
                    else
                    {
                        //
                        // calculate B1 (interpolant), compare with B2
                        // compare RMS errors
                        //
                        t         = 2 * AP.Math.RandomReal() - 1;
                        v1        = ratint.barycentriccalc(ref b1, t);
                        v2        = ratint.barycentriccalc(ref b2, 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
                //
                ratint.barycentricfitfloaterhormann(ref x, ref y, 4, 2, ref info, ref b1, ref rep);
                if (info <= 0)
                {
                    fiterrors = true;
                }
                else
                {
                    s         = ratint.barycentriccalc(ref b1, 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 = bcerrors | nperrors | fiterrors;
            if (!silent)
            {
                System.Console.Write("TESTING RATIONAL INTERPOLATION");
                System.Console.WriteLine();
                System.Console.Write("BASIC BARYCENTRIC FUNCTIONS:             ");
                if (bcerrors)
                {
                    System.Console.Write("FAILED");
                    System.Console.WriteLine();
                }
                else
                {
                    System.Console.Write("OK");
                    System.Console.WriteLine();
                }
                System.Console.Write("FLOATER-HORMANN:                         ");
                if (nperrors)
                {
                    System.Console.Write("FAILED");
                    System.Console.WriteLine();
                }
                else
                {
                    System.Console.Write("OK");
                    System.Console.WriteLine();
                }
                System.Console.Write("RATIONAL FITTING:                        ");
                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);
        }