Example #1
0
        private void Form1_Load(object sender, EventArgs e)
        {
            xarray            = new double[100];
            yarray            = new double[100];
            n                 = 0;
            p                 = new ratint.barycentricinterpolant();
            B                 = new Bitmap(pictureBox1.ClientSize.Width, pictureBox1.ClientSize.Height);
            pictureBox1.Image = B;
            G                 = Graphics.FromImage(B);
            G.SmoothingMode   = System.Drawing.Drawing2D.SmoothingMode.HighQuality;

            G.FillRectangle(new SolidBrush(Color.White), 0, 0, B.Width, B.Height);
        }
        /*************************************************************************
        Unit test
        *************************************************************************/
        private static void testpolynomialfitting(ref bool fiterrors)
        {
            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 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();
            lsfit.polynomialfitreport rep = new lsfit.polynomialfitreport();
            lsfit.polynomialfitreport rep2 = new lsfit.polynomialfitreport();
            int n = 0;
            int m = 0;
            int maxn = 0;
            int pass = 0;
            int passcount = 0;

            fiterrors = false;
            maxn = 5;
            passcount = 20;
            threshold = 1.0E8*math.machineepsilon;
            
            //
            // Test polunomial 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+math.randomreal();
                        }
                        for(i=0; i<=k-1; i++)
                        {
                            xc[i] = xfull[n-k+i];
                            yc[i] = yfull[n-k+i];
                            dc[i] = 0;
                        }
                        lsfit.polynomialfitwc(x, y, w, n-k, xc, yc, dc, k, n, ref info, p1, rep);
                        if( info<=0 )
                        {
                            fiterrors = true;
                        }
                        else
                        {
                            for(i=0; i<=n-k-1; i++)
                            {
                                fiterrors = fiterrors | (double)(Math.Abs(ratint.barycentriccalc(p1, x[i])-y[i]))>(double)(threshold);
                            }
                            for(i=0; i<=k-1; i++)
                            {
                                fiterrors = fiterrors | (double)(Math.Abs(ratint.barycentriccalc(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+math.randomreal();
                                }
                                xc[0] = 0;
                                yc[0] = 2*math.randomreal()-1;
                                dc[0] = 0;
                                xc[1] = 0;
                                yc[1] = 2*math.randomreal()-1;
                                dc[1] = 1;
                                lsfit.polynomialfitwc(x, y, w, n, xc, yc, dc, k, m, ref info, p1, rep);
                                if( info<=0 )
                                {
                                    fiterrors = true;
                                }
                                else
                                {
                                    ratint.barycentricdiff1(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*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(x, y, m, p1);
                    lsfit.polynomialfitwc(x2, y2, w2, n, xc, yc, dc, 0, m, ref info, p2, 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+math.sqr(ratint.barycentriccalc(p1, x2[i])-y2[i]);
                            v2 = v2+math.sqr(ratint.barycentriccalc(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*math.randomreal()-1;
                        y[i] = 2*math.randomreal()-1;
                        w[i] = 1;
                    }
                    lsfit.polynomialfitwc(x, y, w, n, xc, yc, dc, 0, m, ref info, p1, rep);
                    lsfit.polynomialfit(x, y, n, m, ref info2, p2, rep2);
                    if( info<=0 | info2<=0 )
                    {
                        fiterrors = true;
                    }
                    else
                    {
                        
                        //
                        // calculate P1 (interpolant), compare with P2 error
                        // compare RMS errors
                        //
                        t = 2*math.randomreal()-1;
                        v1 = ratint.barycentriccalc(p1, t);
                        v2 = ratint.barycentriccalc(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(m=1; m<=maxn; m++)
            {
                for(pass=1; pass<=passcount; pass++)
                {
                    ap.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*maxn;
                    if( pass==1 )
                    {
                        v1 = 0;
                        v2 = 0;
                        v = 0;
                    }
                    else
                    {
                        v1 = math.randomreal();
                        v2 = math.randomreal();
                        v = 1+math.randomreal();
                    }
                    x = new double[n];
                    y = new double[n];
                    w = new double[n];
                    for(i=0; i<=maxn-1; i++)
                    {
                        x[4*i+0] = i;
                        y[4*i+0] = v-v2;
                        w[4*i+0] = 1;
                        x[4*i+1] = i;
                        y[4*i+1] = v-v1;
                        w[4*i+1] = 1;
                        x[4*i+2] = i;
                        y[4*i+2] = v+v1;
                        w[4*i+2] = 1;
                        x[4*i+3] = i;
                        y[4*i+3] = v+v2;
                        w[4*i+3] = 1;
                    }
                    refrms = Math.Sqrt((math.sqr(v1)+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
                    //
                    lsfit.polynomialfit(x, y, n, m, ref info, p, rep);
                    if( info<=0 )
                    {
                        fiterrors = true;
                    }
                    else
                    {
                        s = ratint.barycentriccalc(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);
                    }
                }
            }
        }
        /*************************************************************************
        Unit test
        *************************************************************************/
        public static bool testpolint(bool silent)
        {
            bool result = new bool();
            bool waserrors = new bool();
            bool interrors = new bool();
            double threshold = 0;
            double[] x = new double[0];
            double[] y = new double[0];
            double[] w = new double[0];
            double[] c = 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];
            double v = 0;
            double v0 = 0;
            double v1 = 0;
            double v2 = 0;
            double v3 = 0;
            double v4 = 0;
            double pscale = 0;
            double poffset = 0;
            ratint.barycentricinterpolant p = new ratint.barycentricinterpolant();
            ratint.barycentricinterpolant p1 = new ratint.barycentricinterpolant();
            ratint.barycentricinterpolant p2 = new ratint.barycentricinterpolant();
            int n = 0;
            int maxn = 0;
            int pass = 0;
            int passcount = 0;

            waserrors = false;
            interrors = false;
            maxn = 5;
            passcount = 20;
            threshold = 1.0E8*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*math.randomreal()-1;
                        b = 2*math.randomreal()-1;
                    }
                    while( (double)(Math.Abs(a-b))<=(double)(0.2) );
                    t = a+(1.2*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, y, n, t)-internalpolint(x, y, n, t)))>(double)(threshold);
                    
                    //
                    // test "slow" equidistant interpolation (create barycentric model)
                    //
                    brcunset(p);
                    polint.polynomialbuild(x, y, n, p);
                    interrors = interrors | (double)(Math.Abs(ratint.barycentriccalc(p, t)-internalpolint(x, y, n, t)))>(double)(threshold);
                    
                    //
                    // test "fast" interpolation (create "fast" barycentric model)
                    //
                    brcunset(p);
                    polint.polynomialbuildeqdist(a, b, y, n, p);
                    interrors = interrors | (double)(Math.Abs(ratint.barycentriccalc(p, t)-internalpolint(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*math.randomreal()-1;
                        b = 2*math.randomreal()-1;
                    }
                    while( (double)(Math.Abs(a-b))<=(double)(0.2) );
                    t = a+(1.2*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, y, n, t)-internalpolint(x, y, n, t)))>(double)(threshold);
                    
                    //
                    // test "slow" interpolation (create barycentric model)
                    //
                    brcunset(p);
                    polint.polynomialbuild(x, y, n, p);
                    interrors = interrors | (double)(Math.Abs(ratint.barycentriccalc(p, t)-internalpolint(x, y, n, t)))>(double)(threshold);
                    
                    //
                    // test "fast" interpolation (create "fast" barycentric model)
                    //
                    brcunset(p);
                    polint.polynomialbuildcheb1(a, b, y, n, p);
                    interrors = interrors | (double)(Math.Abs(ratint.barycentriccalc(p, t)-internalpolint(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*math.randomreal()-1;
                        b = 2*math.randomreal()-1;
                    }
                    while( (double)(Math.Abs(a-b))<=(double)(0.2) );
                    t = a+(1.2*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, y, n, t)-internalpolint(x, y, n, t)))>(double)(threshold);
                    
                    //
                    // test "slow" interpolation (create barycentric model)
                    //
                    brcunset(p);
                    polint.polynomialbuild(x, y, n, p);
                    interrors = interrors | (double)(Math.Abs(ratint.barycentriccalc(p, t)-internalpolint(x, y, n, t)))>(double)(threshold);
                    
                    //
                    // test "fast" interpolation (create "fast" barycentric model)
                    //
                    brcunset(p);
                    polint.polynomialbuildcheb2(a, b, y, n, p);
                    interrors = interrors | (double)(Math.Abs(ratint.barycentriccalc(p, t)-internalpolint(x, y, n, t)))>(double)(threshold);
                }
            }
            
            //
            // Testing conversion Barycentric<->Chebyshev
            //
            for(pass=1; pass<=passcount; pass++)
            {
                for(k=1; k<=3; k++)
                {
                    
                    //
                    // Allocate
                    //
                    x = new double[k];
                    y = new double[k];
                    
                    //
                    // Generate problem
                    //
                    a = 2*math.randomreal()-1;
                    b = a+(0.1+math.randomreal())*(2*math.randominteger(2)-1);
                    v0 = 2*math.randomreal()-1;
                    v1 = 2*math.randomreal()-1;
                    v2 = 2*math.randomreal()-1;
                    if( k==1 )
                    {
                        x[0] = 0.5*(a+b);
                        y[0] = v0;
                    }
                    if( k==2 )
                    {
                        x[0] = a;
                        y[0] = v0-v1;
                        x[1] = b;
                        y[1] = v0+v1;
                    }
                    if( k==3 )
                    {
                        x[0] = a;
                        y[0] = v0-v1+v2;
                        x[1] = 0.5*(a+b);
                        y[1] = v0-v2;
                        x[2] = b;
                        y[2] = v0+v1+v2;
                    }
                    
                    //
                    // Test forward conversion
                    //
                    polint.polynomialbuild(x, y, k, p);
                    c = new double[1];
                    polint.polynomialbar2cheb(p, a, b, ref c);
                    interrors = interrors | ap.len(c)!=k;
                    if( k>=1 )
                    {
                        interrors = interrors | (double)(Math.Abs(c[0]-v0))>(double)(threshold);
                    }
                    if( k>=2 )
                    {
                        interrors = interrors | (double)(Math.Abs(c[1]-v1))>(double)(threshold);
                    }
                    if( k>=3 )
                    {
                        interrors = interrors | (double)(Math.Abs(c[2]-v2))>(double)(threshold);
                    }
                    
                    //
                    // Test backward conversion
                    //
                    polint.polynomialcheb2bar(c, k, a, b, p2);
                    v = a+math.randomreal()*(b-a);
                    interrors = interrors | (double)(Math.Abs(ratint.barycentriccalc(p, v)-ratint.barycentriccalc(p2, v)))>(double)(threshold);
                }
            }
            
            //
            // Testing conversion Barycentric<->Power
            //
            for(pass=1; pass<=passcount; pass++)
            {
                for(k=1; k<=5; k++)
                {
                    
                    //
                    // Allocate
                    //
                    x = new double[k];
                    y = new double[k];
                    
                    //
                    // Generate problem
                    //
                    poffset = 2*math.randomreal()-1;
                    pscale = (0.1+math.randomreal())*(2*math.randominteger(2)-1);
                    v0 = 2*math.randomreal()-1;
                    v1 = 2*math.randomreal()-1;
                    v2 = 2*math.randomreal()-1;
                    v3 = 2*math.randomreal()-1;
                    v4 = 2*math.randomreal()-1;
                    if( k==1 )
                    {
                        x[0] = poffset;
                        y[0] = v0;
                    }
                    if( k==2 )
                    {
                        x[0] = poffset-pscale;
                        y[0] = v0-v1;
                        x[1] = poffset+pscale;
                        y[1] = v0+v1;
                    }
                    if( k==3 )
                    {
                        x[0] = poffset-pscale;
                        y[0] = v0-v1+v2;
                        x[1] = poffset;
                        y[1] = v0;
                        x[2] = poffset+pscale;
                        y[2] = v0+v1+v2;
                    }
                    if( k==4 )
                    {
                        x[0] = poffset-pscale;
                        y[0] = v0-v1+v2-v3;
                        x[1] = poffset-0.5*pscale;
                        y[1] = v0-0.5*v1+0.25*v2-0.125*v3;
                        x[2] = poffset+0.5*pscale;
                        y[2] = v0+0.5*v1+0.25*v2+0.125*v3;
                        x[3] = poffset+pscale;
                        y[3] = v0+v1+v2+v3;
                    }
                    if( k==5 )
                    {
                        x[0] = poffset-pscale;
                        y[0] = v0-v1+v2-v3+v4;
                        x[1] = poffset-0.5*pscale;
                        y[1] = v0-0.5*v1+0.25*v2-0.125*v3+0.0625*v4;
                        x[2] = poffset;
                        y[2] = v0;
                        x[3] = poffset+0.5*pscale;
                        y[3] = v0+0.5*v1+0.25*v2+0.125*v3+0.0625*v4;
                        x[4] = poffset+pscale;
                        y[4] = v0+v1+v2+v3+v4;
                    }
                    
                    //
                    // Test forward conversion
                    //
                    polint.polynomialbuild(x, y, k, p);
                    c = new double[1];
                    polint.polynomialbar2pow(p, poffset, pscale, ref c);
                    interrors = interrors | ap.len(c)!=k;
                    if( k>=1 )
                    {
                        interrors = interrors | (double)(Math.Abs(c[0]-v0))>(double)(threshold);
                    }
                    if( k>=2 )
                    {
                        interrors = interrors | (double)(Math.Abs(c[1]-v1))>(double)(threshold);
                    }
                    if( k>=3 )
                    {
                        interrors = interrors | (double)(Math.Abs(c[2]-v2))>(double)(threshold);
                    }
                    if( k>=4 )
                    {
                        interrors = interrors | (double)(Math.Abs(c[3]-v3))>(double)(threshold);
                    }
                    if( k>=5 )
                    {
                        interrors = interrors | (double)(Math.Abs(c[4]-v4))>(double)(threshold);
                    }
                    
                    //
                    // Test backward conversion
                    //
                    polint.polynomialpow2bar(c, k, poffset, pscale, p2);
                    v = poffset+(2*math.randomreal()-1)*pscale;
                    interrors = interrors | (double)(Math.Abs(ratint.barycentriccalc(p, v)-ratint.barycentriccalc(p2, v)))>(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*math.maxrealnumber);
                b = 0.1*math.maxrealnumber;
                apserv.taskgenint1dequidist(a, b, n, ref x, ref y);
                polint.polynomialbuild(x, y, n, p);
                for(i=0; i<=n-1; i++)
                {
                    interrors = interrors | (double)(p.w[i])==(double)(0);
                }
            }
            
            //
            // report
            //
            waserrors = interrors;
            if( !silent )
            {
                System.Console.Write("TESTING POLYNOMIAL INTERPOLATION");
                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();
                }
                if( waserrors )
                {
                    System.Console.Write("TEST FAILED");
                    System.Console.WriteLine();
                }
                else
                {
                    System.Console.Write("TEST PASSED");
                    System.Console.WriteLine();
                }
                System.Console.WriteLine();
                System.Console.WriteLine();
            }
            
            //
            // end
            //
            result = !waserrors;
            return result;
        }
        public static bool testratint(bool silent)
        {
            bool result = new bool();
            bool waserrors = new bool();
            bool bcerrors = new bool();
            bool nperrors = 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;
            int n = 0;
            int n2 = 0;
            int i = 0;
            int j = 0;
            int k = 0;
            int d = 0;
            int pass = 0;
            double maxerr = 0;
            double t = 0;
            double a = 0;
            double b = 0;
            double s = 0;
            double v0 = 0;
            double v1 = 0;
            double v2 = 0;
            double v3 = 0;
            double d0 = 0;
            double d1 = 0;
            double d2 = 0;

            nperrors = false;
            bcerrors = 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*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*math.randomreal()-0.2;
                    v1 = 2*math.randomreal()-1;
                    v2 = 2*math.randomreal()-1;
                    v3 = 2*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(x, y, w, n, b1);
                    
                    //
                    // unpack, then pack again and compare
                    //
                    brcunset(b2);
                    ratint.barycentricunpack(b1, ref n2, ref x2, ref y2, ref w2);
                    bcerrors = bcerrors | n2!=n;
                    ratint.barycentricbuildxyw(x2, y2, w2, n2, b2);
                    t = 2*math.randomreal()-1;
                    bcerrors = bcerrors | (double)(Math.Abs(ratint.barycentriccalc(b1, t)-ratint.barycentriccalc(b2, t)))>(double)(threshold);
                    
                    //
                    // copy, compare
                    //
                    brcunset(b2);
                    ratint.barycentriccopy(b1, b2);
                    t = 2*math.randomreal()-1;
                    bcerrors = bcerrors | (double)(Math.Abs(ratint.barycentriccalc(b1, t)-ratint.barycentriccalc(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(b1, x[i])-y[i]))>(double)(threshold*Math.Abs(y[i]));
                        
                        //
                        // compare with polynomial interpolation
                        //
                        t = 2*math.randomreal()-1;
                        poldiff2(x, y, n, t, ref v0, ref v1, ref v2);
                        bcerrors = bcerrors | (double)(Math.Abs(ratint.barycentriccalc(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(b1, v2)-ratint.barycentriccalc(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(b1, v2)-ratint.barycentriccalc(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*math.randomreal()-1;
                        poldiff2(x, y, n, t, ref v0, ref v1, ref v2);
                        d0 = 0;
                        d1 = 0;
                        d2 = 0;
                        ratint.barycentricdiff1(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(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*math.randomreal()-1;
                    a = 2*math.randomreal()-1;
                    b = 2*math.randomreal()-1;
                    brcunset(b2);
                    ratint.barycentriccopy(b1, b2);
                    ratint.barycentriclintransx(b2, a, b);
                    bcerrors = bcerrors | (double)(Math.Abs(ratint.barycentriccalc(b1, a*t+b)-ratint.barycentriccalc(b2, t)))>(double)(threshold);
                    a = 0;
                    b = 2*math.randomreal()-1;
                    brcunset(b2);
                    ratint.barycentriccopy(b1, b2);
                    ratint.barycentriclintransx(b2, a, b);
                    bcerrors = bcerrors | (double)(Math.Abs(ratint.barycentriccalc(b1, a*t+b)-ratint.barycentriccalc(b2, t)))>(double)(threshold);
                    a = 2*math.randomreal()-1;
                    b = 2*math.randomreal()-1;
                    brcunset(b2);
                    ratint.barycentriccopy(b1, b2);
                    ratint.barycentriclintransy(b2, a, b);
                    bcerrors = bcerrors | (double)(Math.Abs(a*ratint.barycentriccalc(b1, t)+b-ratint.barycentriccalc(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*math.minrealnumber;
                }
                if( pass%2==1 )
                {
                    h = 0.01*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(x, y, w, 4, b1);
                t = ratint.barycentriccalc(b1, v0);
                d0 = 0;
                d1 = 0;
                d2 = 0;
                ratint.barycentricdiff1(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*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*math.minrealnumber;
            ratint.barycentricbuildxyw(x, y, w, 4, b1);
            t = ratint.barycentriccalc(b1, v0);
            d0 = 0;
            d1 = 0;
            d2 = 0;
            ratint.barycentricdiff1(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*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 = math.minrealnumber;
            ratint.barycentricbuildxyw(x, y, w, 4, b1);
            t = ratint.barycentriccalc(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*math.randomreal()-1;
                y[0] = 2*math.randomreal()-1;
                ratint.barycentricbuildfloaterhormann(x, y, 1, 1, b1);
                maxerr = Math.Max(maxerr, Math.Abs(ratint.barycentriccalc(b1, 2*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*math.randomreal();
                    b = 1+1*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*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 = 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(x, y, n, 1, b1);
                    ratint.barycentricbuildxyw(x, y, w, n, b2);
                    for(i=1; i<=2*n; i++)
                    {
                        t = a+(b-a)*math.randomreal();
                        maxerr = Math.Max(maxerr, Math.Abs(ratint.barycentriccalc(b1, t)-ratint.barycentriccalc(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*math.randomreal();
                        b = 1+1*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*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 = 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(x, y, n, d, b1);
                        ratint.barycentricbuildxyw(x, y, w, n, b2);
                        for(i=1; i<=2*n; i++)
                        {
                            t = a+(b-a)*math.randomreal();
                            maxerr = Math.Max(maxerr, Math.Abs(ratint.barycentriccalc(b1, t)-ratint.barycentriccalc(b2, t)));
                        }
                    }
                }
            }
            if( (double)(maxerr)>(double)(threshold) )
            {
                nperrors = true;
            }
            
            //
            // report
            //
            waserrors = bcerrors | nperrors;
            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();
                }
                if( waserrors )
                {
                    System.Console.Write("TEST FAILED");
                    System.Console.WriteLine();
                }
                else
                {
                    System.Console.Write("TEST PASSED");
                    System.Console.WriteLine();
                }
                System.Console.WriteLine();
                System.Console.WriteLine();
            }
            
            //
            // end
            //
            result = !waserrors;
            return result;
        }
    public static int Main(string[] args)
    {
        double[] x = new double[0];
        double[] y = new double[0];
        int n = 0;
        int i = 0;
        double t = 0;
        ratint.barycentricinterpolant p = new ratint.barycentricinterpolant();
        double v = 0;
        double dv = 0;
        double d2v = 0;
        double err = 0;
        double maxerr = 0;

        
        //
        // Demonstration
        //
        System.Console.Write("POLYNOMIAL INTERPOLATION");
        System.Console.WriteLine();
        System.Console.WriteLine();
        System.Console.Write("F(x)=sin(x), [0, pi]");
        System.Console.WriteLine();
        System.Console.Write("Second degree polynomial is used");
        System.Console.WriteLine();
        System.Console.WriteLine();
        
        //
        // Create polynomial interpolant
        //
        n = 3;
        x = new double[n];
        y = new double[n];
        for(i=0; i<=n-1; i++)
        {
            x[i] = Math.PI*i/(n-1);
            y[i] = Math.Sin(x[i]);
        }
        polint.polynomialbuild(ref x, ref y, n, ref p);
        
        //
        // Output results
        //
        ratint.barycentricdiff2(ref p, 0, ref v, ref dv, ref d2v);
        System.Console.Write("                 P(x)    F(x) ");
        System.Console.WriteLine();
        System.Console.Write("function       ");
        System.Console.Write("{0,6:F3}",ratint.barycentriccalc(ref p, 0));
        System.Console.Write("  ");
        System.Console.Write("{0,6:F3}",0);
        System.Console.Write(" ");
        System.Console.WriteLine();
        System.Console.Write("d/dx(0)        ");
        System.Console.Write("{0,6:F3}",dv);
        System.Console.Write("  ");
        System.Console.Write("{0,6:F3}",1);
        System.Console.Write(" ");
        System.Console.WriteLine();
        System.Console.Write("d2/dx2(0)      ");
        System.Console.Write("{0,6:F3}",d2v);
        System.Console.Write("  ");
        System.Console.Write("{0,6:F3}",0);
        System.Console.Write(" ");
        System.Console.WriteLine();
        System.Console.WriteLine();
        System.Console.WriteLine();
        return 0;
    }
    public static int Main(string[] args)
    {
        int m = 0;
        int n = 0;
        double[] x = new double[0];
        double[] y = new double[0];
        double[] w = new double[0];
        double[] xc = new double[0];
        double[] yc = new double[0];
        int[] dc = new int[0];
        polint.polynomialfitreport rep = new polint.polynomialfitreport();
        int info = 0;
        ratint.barycentricinterpolant p = new ratint.barycentricinterpolant();
        int i = 0;
        int j = 0;
        double a = 0;
        double b = 0;
        double v = 0;
        double dv = 0;

        System.Console.WriteLine();
        System.Console.WriteLine();
        System.Console.Write("Fitting exp(2*x) at [-1,+1] by polinomial");
        System.Console.WriteLine();
        System.Console.WriteLine();
        System.Console.Write("Fit type             rms.err max.err    p(0)   dp(0)");
        System.Console.WriteLine();
        
        //
        // Prepare points
        //
        m = 5;
        a = -1;
        b = +1;
        n = 1000;
        x = new double[n];
        y = new double[n];
        w = new double[n];
        for(i=0; i<=n-1; i++)
        {
            x[i] = a+(b-a)*i/(n-1);
            y[i] = Math.Exp(2*x[i]);
            w[i] = 1.0;
        }
        
        //
        // Fitting:
        // a) f(x)=exp(2*x) at [-1,+1]
        // b) by 5th degree polynomial
        // c) without constraints
        //
        polint.polynomialfit(ref x, ref y, n, m, ref info, ref p, ref rep);
        ratint.barycentricdiff1(ref p, 0.0, ref v, ref dv);
        System.Console.Write("Unconstrained        ");
        System.Console.Write("{0,7:F4}",rep.rmserror);
        System.Console.Write(" ");
        System.Console.Write("{0,7:F4}",rep.maxerror);
        System.Console.Write(" ");
        System.Console.Write("{0,7:F4}",v);
        System.Console.Write(" ");
        System.Console.Write("{0,7:F4}",dv);
        System.Console.WriteLine();
        
        //
        // Fitting:
        // a) f(x)=exp(2*x) at [-1,+1]
        // b) by 5th degree polynomial
        // c) constrained: p(0)=1
        //
        xc = new double[1];
        yc = new double[1];
        dc = new int[1];
        xc[0] = 0;
        yc[0] = 1;
        dc[0] = 0;
        polint.polynomialfitwc(x, y, ref w, n, xc, yc, ref dc, 1, m, ref info, ref p, ref rep);
        ratint.barycentricdiff1(ref p, 0.0, ref v, ref dv);
        System.Console.Write("Constrained, p(0)=1  ");
        System.Console.Write("{0,7:F4}",rep.rmserror);
        System.Console.Write(" ");
        System.Console.Write("{0,7:F4}",rep.maxerror);
        System.Console.Write(" ");
        System.Console.Write("{0,7:F4}",v);
        System.Console.Write(" ");
        System.Console.Write("{0,7:F4}",dv);
        System.Console.WriteLine();
        
        //
        // Fitting:
        // a) f(x)=exp(2*x) at [-1,+1]
        // b) by 5th degree polynomial
        // c) constrained: dp(0)=2
        //
        xc = new double[1];
        yc = new double[1];
        dc = new int[1];
        xc[0] = 0;
        yc[0] = 2;
        dc[0] = 1;
        polint.polynomialfitwc(x, y, ref w, n, xc, yc, ref dc, 1, m, ref info, ref p, ref rep);
        ratint.barycentricdiff1(ref p, 0.0, ref v, ref dv);
        System.Console.Write("Constrained, dp(0)=2 ");
        System.Console.Write("{0,7:F4}",rep.rmserror);
        System.Console.Write(" ");
        System.Console.Write("{0,7:F4}",rep.maxerror);
        System.Console.Write(" ");
        System.Console.Write("{0,7:F4}",v);
        System.Console.Write(" ");
        System.Console.Write("{0,7:F4}",dv);
        System.Console.WriteLine();
        
        //
        // Fitting:
        // a) f(x)=exp(2*x) at [-1,+1]
        // b) by 5th degree polynomial
        // c) constrained: p(0)=1, dp(0)=2
        //
        xc = new double[2];
        yc = new double[2];
        dc = new int[2];
        xc[0] = 0;
        yc[0] = 1;
        dc[0] = 0;
        xc[1] = 0;
        yc[1] = 2;
        dc[1] = 1;
        polint.polynomialfitwc(x, y, ref w, n, xc, yc, ref dc, 2, m, ref info, ref p, ref rep);
        ratint.barycentricdiff1(ref p, 0.0, ref v, ref dv);
        System.Console.Write("Constrained, both    ");
        System.Console.Write("{0,7:F4}",rep.rmserror);
        System.Console.Write(" ");
        System.Console.Write("{0,7:F4}",rep.maxerror);
        System.Console.Write(" ");
        System.Console.Write("{0,7:F4}",v);
        System.Console.Write(" ");
        System.Console.Write("{0,7:F4}",dv);
        System.Console.WriteLine();
        System.Console.WriteLine();
        System.Console.WriteLine();
        return 0;
    }
Example #7
0
 public barycentricinterpolant(ratint.barycentricinterpolant obj)
 {
     _innerobj = obj;
 }
    public static int Main(string[] args)
    {
        int m = 0;
        int n = 0;

        double[] x  = new double[0];
        double[] y  = new double[0];
        double[] w  = new double[0];
        double[] xc = new double[0];
        double[] yc = new double[0];
        int[]    dc = new int[0];
        polint.polynomialfitreport rep = new polint.polynomialfitreport();
        int info = 0;

        ratint.barycentricinterpolant p = new ratint.barycentricinterpolant();
        int    i  = 0;
        int    j  = 0;
        double a  = 0;
        double b  = 0;
        double v  = 0;
        double dv = 0;

        System.Console.WriteLine();
        System.Console.WriteLine();
        System.Console.Write("Fitting exp(2*x) at [-1,+1] by polinomial");
        System.Console.WriteLine();
        System.Console.WriteLine();
        System.Console.Write("Fit type             rms.err max.err    p(0)   dp(0)");
        System.Console.WriteLine();

        //
        // Prepare points
        //
        m = 5;
        a = -1;
        b = +1;
        n = 1000;
        x = new double[n];
        y = new double[n];
        w = new double[n];
        for (i = 0; i <= n - 1; i++)
        {
            x[i] = a + (b - a) * i / (n - 1);
            y[i] = Math.Exp(2 * x[i]);
            w[i] = 1.0;
        }

        //
        // Fitting:
        // a) f(x)=exp(2*x) at [-1,+1]
        // b) by 5th degree polynomial
        // c) without constraints
        //
        polint.polynomialfit(ref x, ref y, n, m, ref info, ref p, ref rep);
        ratint.barycentricdiff1(ref p, 0.0, ref v, ref dv);
        System.Console.Write("Unconstrained        ");
        System.Console.Write("{0,7:F4}", rep.rmserror);
        System.Console.Write(" ");
        System.Console.Write("{0,7:F4}", rep.maxerror);
        System.Console.Write(" ");
        System.Console.Write("{0,7:F4}", v);
        System.Console.Write(" ");
        System.Console.Write("{0,7:F4}", dv);
        System.Console.WriteLine();

        //
        // Fitting:
        // a) f(x)=exp(2*x) at [-1,+1]
        // b) by 5th degree polynomial
        // c) constrained: p(0)=1
        //
        xc    = new double[1];
        yc    = new double[1];
        dc    = new int[1];
        xc[0] = 0;
        yc[0] = 1;
        dc[0] = 0;
        polint.polynomialfitwc(x, y, ref w, n, xc, yc, ref dc, 1, m, ref info, ref p, ref rep);
        ratint.barycentricdiff1(ref p, 0.0, ref v, ref dv);
        System.Console.Write("Constrained, p(0)=1  ");
        System.Console.Write("{0,7:F4}", rep.rmserror);
        System.Console.Write(" ");
        System.Console.Write("{0,7:F4}", rep.maxerror);
        System.Console.Write(" ");
        System.Console.Write("{0,7:F4}", v);
        System.Console.Write(" ");
        System.Console.Write("{0,7:F4}", dv);
        System.Console.WriteLine();

        //
        // Fitting:
        // a) f(x)=exp(2*x) at [-1,+1]
        // b) by 5th degree polynomial
        // c) constrained: dp(0)=2
        //
        xc    = new double[1];
        yc    = new double[1];
        dc    = new int[1];
        xc[0] = 0;
        yc[0] = 2;
        dc[0] = 1;
        polint.polynomialfitwc(x, y, ref w, n, xc, yc, ref dc, 1, m, ref info, ref p, ref rep);
        ratint.barycentricdiff1(ref p, 0.0, ref v, ref dv);
        System.Console.Write("Constrained, dp(0)=2 ");
        System.Console.Write("{0,7:F4}", rep.rmserror);
        System.Console.Write(" ");
        System.Console.Write("{0,7:F4}", rep.maxerror);
        System.Console.Write(" ");
        System.Console.Write("{0,7:F4}", v);
        System.Console.Write(" ");
        System.Console.Write("{0,7:F4}", dv);
        System.Console.WriteLine();

        //
        // Fitting:
        // a) f(x)=exp(2*x) at [-1,+1]
        // b) by 5th degree polynomial
        // c) constrained: p(0)=1, dp(0)=2
        //
        xc    = new double[2];
        yc    = new double[2];
        dc    = new int[2];
        xc[0] = 0;
        yc[0] = 1;
        dc[0] = 0;
        xc[1] = 0;
        yc[1] = 2;
        dc[1] = 1;
        polint.polynomialfitwc(x, y, ref w, n, xc, yc, ref dc, 2, m, ref info, ref p, ref rep);
        ratint.barycentricdiff1(ref p, 0.0, ref v, ref dv);
        System.Console.Write("Constrained, both    ");
        System.Console.Write("{0,7:F4}", rep.rmserror);
        System.Console.Write(" ");
        System.Console.Write("{0,7:F4}", rep.maxerror);
        System.Console.Write(" ");
        System.Console.Write("{0,7:F4}", v);
        System.Console.Write(" ");
        System.Console.Write("{0,7:F4}", dv);
        System.Console.WriteLine();
        System.Console.WriteLine();
        System.Console.WriteLine();
        return(0);
    }
Example #9
0
        /*************************************************************************
        Internal Floater-Hormann fitting subroutine for fixed D
        *************************************************************************/
        private static void barycentricfitwcfixedd(double[] x,
            double[] y,
            double[] w,
            int n,
            double[] xc,
            double[] yc,
            int[] dc,
            int k,
            int m,
            int d,
            ref int info,
            ratint.barycentricinterpolant b,
            barycentricfitreport rep)
        {
            double[,] fmatrix = new double[0,0];
            double[,] cmatrix = new double[0,0];
            double[] y2 = new double[0];
            double[] w2 = new double[0];
            double[] sx = new double[0];
            double[] sy = new double[0];
            double[] sbf = new double[0];
            double[] xoriginal = new double[0];
            double[] yoriginal = new double[0];
            double[] tmp = new double[0];
            lsfitreport lrep = new lsfitreport();
            double v0 = 0;
            double v1 = 0;
            double mx = 0;
            ratint.barycentricinterpolant b2 = new ratint.barycentricinterpolant();
            int i = 0;
            int j = 0;
            int relcnt = 0;
            double xa = 0;
            double xb = 0;
            double sa = 0;
            double sb = 0;
            double decay = 0;
            int i_ = 0;

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

            if( ((n<1 || m<2) || 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*math.machineepsilon;
            
            //
            // Scale X, Y, XC, YC
            //
            lsfitscalexy(ref x, ref y, ref w, n, ref xc, ref yc, dc, k, ref xa, ref xb, ref sa, ref sb, ref xoriginal, ref yoriginal);
            
            //
            // allocate space, initialize:
            // * FMatrix-   values of basis functions at X[]
            // * CMatrix-   values (derivatives) of basis functions at XC[]
            //
            y2 = new double[n+m];
            w2 = new double[n+m];
            fmatrix = new double[n+m, m];
            if( k>0 )
            {
                cmatrix = new double[k, m+1];
            }
            y2 = new double[n+m];
            w2 = new double[n+m];
            
            //
            // Prepare design and constraints matrices:
            // * 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
            //
            sx = new double[m];
            sy = new double[m];
            sbf = new double[m];
            for(j=0; j<=m-1; j++)
            {
                sx[j] = (double)(2*j)/(double)(m-1)-1;
            }
            for(i=0; i<=m-1; i++)
            {
                sy[i] = 1;
            }
            ratint.barycentricbuildfloaterhormann(sx, sy, m, d, b2);
            mx = 0;
            for(i=0; i<=n-1; i++)
            {
                barycentriccalcbasis(b2, x[i], ref sbf);
                for(i_=0; i_<=m-1;i_++)
                {
                    fmatrix[i,i_] = sbf[i_];
                }
                y2[i] = y[i];
                w2[i] = w[i];
                mx = mx+Math.Abs(w[i])/n;
            }
            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;
                    }
                }
                y2[n+i] = 0;
                w2[n+i] = mx;
            }
            if( k>0 )
            {
                for(j=0; j<=m-1; j++)
                {
                    for(i=0; i<=m-1; i++)
                    {
                        sy[i] = 0;
                    }
                    sy[j] = 1;
                    ratint.barycentricbuildfloaterhormann(sx, sy, m, d, b2);
                    for(i=0; i<=k-1; i++)
                    {
                        alglib.ap.assert(dc[i]>=0 && dc[i]<=1, "BarycentricFit: internal error!");
                        ratint.barycentricdiff1(b2, xc[i], ref v0, ref v1);
                        if( dc[i]==0 )
                        {
                            cmatrix[i,j] = v0;
                        }
                        if( dc[i]==1 )
                        {
                            cmatrix[i,j] = v1;
                        }
                    }
                }
                for(i=0; i<=k-1; i++)
                {
                    cmatrix[i,m] = yc[i];
                }
            }
            
            //
            // Solve constrained task
            //
            if( k>0 )
            {
                
                //
                // solve using regularization
                //
                lsfitlinearwc(y2, w2, fmatrix, cmatrix, n+m, m, k, ref info, ref tmp, lrep);
            }
            else
            {
                
                //
                // no constraints, no regularization needed
                //
                lsfitlinearwc(y, w, fmatrix, cmatrix, n, m, k, ref info, ref tmp, lrep);
            }
            if( info<0 )
            {
                return;
            }
            
            //
            // Generate interpolant and scale it
            //
            for(i_=0; i_<=m-1;i_++)
            {
                sy[i_] = tmp[i_];
            }
            ratint.barycentricbuildfloaterhormann(sx, sy, m, d, b);
            ratint.barycentriclintransx(b, 2/(xb-xa), -((xa+xb)/(xb-xa)));
            ratint.barycentriclintransy(b, 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(b, xoriginal[i])-yoriginal[i])/Math.Abs(yoriginal[i]);
                    relcnt = relcnt+1;
                }
            }
            if( relcnt!=0 )
            {
                rep.avgrelerror = rep.avgrelerror/relcnt;
            }
        }
Example #10
0
        /*************************************************************************
        Weghted rational least  squares  fitting  using  Floater-Hormann  rational
        functions  with  optimal  D  chosen  from  [0,9],  with  constraints   and
        individual weights.

        Equidistant  grid  with M node on [min(x),max(x)]  is  used to build basis
        functions. Different values of D are tried, optimal D (least WEIGHTED root
        mean square error) is chosen.  Task  is  linear,  so  linear least squares
        solver  is  used.  Complexity  of  this  computational  scheme is O(N*M^2)
        (mostly dominated by the least squares solver).

        SEE ALSO
        * BarycentricFitFloaterHormann(), "lightweight" fitting without invididual
          weights and constraints.

        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 function 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 S(XC[i])=YC[i]
                    * DC[i]=1   means that S'(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 ( = number_of_nodes), M>=2.

        OUTPUT PARAMETERS:
            Info-   same format as in LSFitLinearWC() 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)
            B   -   barycentric interpolant.
            Rep -   report, same format as in LSFitLinearWC() subroutine.
                    Following fields are set:
                    * DBest         best value of the D parameter
                    * 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 subroutine 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 barycentric interpolants:
        * excessive  constraints  can  be  inconsistent.   Floater-Hormann   basis
          functions aren't as flexible as splines (although they are very smooth).
        * the more evenly constraints are spread across [min(x),max(x)],  the more
          chances that they will be consistent
        * 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 several special cases, however, we CAN guarantee consistency.
        * one of this cases is constraints on the function  VALUES at the interval
          boundaries. Note that consustency of the  constraints  on  the  function
          DERIVATIVES is NOT guaranteed (you can use in such cases  cubic  splines
          which are more flexible).
        * another  special  case  is ONE constraint on the function value (OR, but
          not AND, derivative) anywhere in the interval

        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 18.08.2009 by Bochkanov Sergey
        *************************************************************************/
        public static void barycentricfitfloaterhormannwc(double[] x,
            double[] y,
            double[] w,
            int n,
            double[] xc,
            double[] yc,
            int[] dc,
            int k,
            int m,
            ref int info,
            ratint.barycentricinterpolant b,
            barycentricfitreport rep)
        {
            int d = 0;
            int i = 0;
            double wrmscur = 0;
            double wrmsbest = 0;
            ratint.barycentricinterpolant locb = new ratint.barycentricinterpolant();
            barycentricfitreport locrep = new barycentricfitreport();
            int locinfo = 0;

            info = 0;

            alglib.ap.assert(n>0, "BarycentricFitFloaterHormannWC: N<=0!");
            alglib.ap.assert(m>0, "BarycentricFitFloaterHormannWC: M<=0!");
            alglib.ap.assert(k>=0, "BarycentricFitFloaterHormannWC: K<0!");
            alglib.ap.assert(k<m, "BarycentricFitFloaterHormannWC: K>=M!");
            alglib.ap.assert(alglib.ap.len(x)>=n, "BarycentricFitFloaterHormannWC: Length(X)<N!");
            alglib.ap.assert(alglib.ap.len(y)>=n, "BarycentricFitFloaterHormannWC: Length(Y)<N!");
            alglib.ap.assert(alglib.ap.len(w)>=n, "BarycentricFitFloaterHormannWC: Length(W)<N!");
            alglib.ap.assert(alglib.ap.len(xc)>=k, "BarycentricFitFloaterHormannWC: Length(XC)<K!");
            alglib.ap.assert(alglib.ap.len(yc)>=k, "BarycentricFitFloaterHormannWC: Length(YC)<K!");
            alglib.ap.assert(alglib.ap.len(dc)>=k, "BarycentricFitFloaterHormannWC: Length(DC)<K!");
            alglib.ap.assert(apserv.isfinitevector(x, n), "BarycentricFitFloaterHormannWC: X contains infinite or NaN values!");
            alglib.ap.assert(apserv.isfinitevector(y, n), "BarycentricFitFloaterHormannWC: Y contains infinite or NaN values!");
            alglib.ap.assert(apserv.isfinitevector(w, n), "BarycentricFitFloaterHormannWC: X contains infinite or NaN values!");
            alglib.ap.assert(apserv.isfinitevector(xc, k), "BarycentricFitFloaterHormannWC: XC contains infinite or NaN values!");
            alglib.ap.assert(apserv.isfinitevector(yc, k), "BarycentricFitFloaterHormannWC: YC contains infinite or NaN values!");
            for(i=0; i<=k-1; i++)
            {
                alglib.ap.assert(dc[i]==0 || dc[i]==1, "BarycentricFitFloaterHormannWC: one of DC[] is not 0 or 1!");
            }
            
            //
            // Find optimal D
            //
            // Info is -3 by default (degenerate constraints).
            // If LocInfo will always be equal to -3, Info will remain equal to -3.
            // If at least once LocInfo will be -4, Info will be -4.
            //
            wrmsbest = math.maxrealnumber;
            rep.dbest = -1;
            info = -3;
            for(d=0; d<=Math.Min(9, n-1); d++)
            {
                barycentricfitwcfixedd(x, y, w, n, xc, yc, dc, k, m, d, ref locinfo, locb, locrep);
                alglib.ap.assert((locinfo==-4 || locinfo==-3) || locinfo>0, "BarycentricFitFloaterHormannWC: unexpected result from BarycentricFitWCFixedD!");
                if( locinfo>0 )
                {
                    
                    //
                    // Calculate weghted RMS
                    //
                    wrmscur = 0;
                    for(i=0; i<=n-1; i++)
                    {
                        wrmscur = wrmscur+math.sqr(w[i]*(y[i]-ratint.barycentriccalc(locb, x[i])));
                    }
                    wrmscur = Math.Sqrt(wrmscur/n);
                    if( (double)(wrmscur)<(double)(wrmsbest) || rep.dbest<0 )
                    {
                        ratint.barycentriccopy(locb, b);
                        rep.dbest = d;
                        info = 1;
                        rep.rmserror = locrep.rmserror;
                        rep.avgerror = locrep.avgerror;
                        rep.avgrelerror = locrep.avgrelerror;
                        rep.maxerror = locrep.maxerror;
                        rep.taskrcond = locrep.taskrcond;
                        wrmsbest = wrmscur;
                    }
                }
                else
                {
                    if( locinfo!=-3 && info<0 )
                    {
                        info = locinfo;
                    }
                }
            }
        }
Example #11
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*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*math.randomreal()-1;
                        b = 2*math.randomreal()-1;
                    }
                    while( (double)(Math.Abs(a-b))<=(double)(0.2) );
                    t = a+(1.2*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, y, n, t)-internalpolint(x, y, n, t)))>(double)(threshold);
                    
                    //
                    // test "slow" equidistant interpolation (create barycentric model)
                    //
                    brcunset(p);
                    polint.polynomialbuild(x, y, n, p);
                    interrors = interrors | (double)(Math.Abs(ratint.barycentriccalc(p, t)-internalpolint(x, y, n, t)))>(double)(threshold);
                    
                    //
                    // test "fast" interpolation (create "fast" barycentric model)
                    //
                    brcunset(p);
                    polint.polynomialbuildeqdist(a, b, y, n, p);
                    interrors = interrors | (double)(Math.Abs(ratint.barycentriccalc(p, t)-internalpolint(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*math.randomreal()-1;
                        b = 2*math.randomreal()-1;
                    }
                    while( (double)(Math.Abs(a-b))<=(double)(0.2) );
                    t = a+(1.2*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, y, n, t)-internalpolint(x, y, n, t)))>(double)(threshold);
                    
                    //
                    // test "slow" interpolation (create barycentric model)
                    //
                    brcunset(p);
                    polint.polynomialbuild(x, y, n, p);
                    interrors = interrors | (double)(Math.Abs(ratint.barycentriccalc(p, t)-internalpolint(x, y, n, t)))>(double)(threshold);
                    
                    //
                    // test "fast" interpolation (create "fast" barycentric model)
                    //
                    brcunset(p);
                    polint.polynomialbuildcheb1(a, b, y, n, p);
                    interrors = interrors | (double)(Math.Abs(ratint.barycentriccalc(p, t)-internalpolint(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*math.randomreal()-1;
                        b = 2*math.randomreal()-1;
                    }
                    while( (double)(Math.Abs(a-b))<=(double)(0.2) );
                    t = a+(1.2*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, y, n, t)-internalpolint(x, y, n, t)))>(double)(threshold);
                    
                    //
                    // test "slow" interpolation (create barycentric model)
                    //
                    brcunset(p);
                    polint.polynomialbuild(x, y, n, p);
                    interrors = interrors | (double)(Math.Abs(ratint.barycentriccalc(p, t)-internalpolint(x, y, n, t)))>(double)(threshold);
                    
                    //
                    // test "fast" interpolation (create "fast" barycentric model)
                    //
                    brcunset(p);
                    polint.polynomialbuildcheb2(a, b, y, n, p);
                    interrors = interrors | (double)(Math.Abs(ratint.barycentriccalc(p, t)-internalpolint(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*math.maxrealnumber);
                b = 0.1*math.maxrealnumber;
                apserv.taskgenint1dequidist(a, b, n, ref x, ref y);
                polint.polynomialbuild(x, y, n, 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+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, w, n-k, xc, yc, dc, k, n, ref info, p1, rep);
                        if( info<=0 )
                        {
                            fiterrors = true;
                        }
                        else
                        {
                            for(i=0; i<=n-k-1; i++)
                            {
                                fiterrors = fiterrors | (double)(Math.Abs(ratint.barycentriccalc(p1, x[i])-y[i]))>(double)(threshold);
                            }
                            for(i=0; i<=k-1; i++)
                            {
                                fiterrors = fiterrors | (double)(Math.Abs(ratint.barycentriccalc(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+math.randomreal();
                                }
                                xc[0] = 0;
                                yc[0] = 2*math.randomreal()-1;
                                dc[0] = 0;
                                xc[1] = 0;
                                yc[1] = 2*math.randomreal()-1;
                                dc[1] = 1;
                                polint.polynomialfitwc(x, y, w, n, xc, yc, dc, k, m, ref info, p1, rep);
                                if( info<=0 )
                                {
                                    fiterrors = true;
                                }
                                else
                                {
                                    ratint.barycentricdiff1(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*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(x, y, m, p1);
                    polint.polynomialfitwc(x2, y2, w2, n, xc, yc, dc, 0, m, ref info, p2, 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+math.sqr(ratint.barycentriccalc(p1, x2[i])-y2[i]);
                            v2 = v2+math.sqr(ratint.barycentriccalc(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*math.randomreal()-1;
                        y[i] = 2*math.randomreal()-1;
                        w[i] = 1;
                    }
                    polint.polynomialfitwc(x, y, w, n, xc, yc, dc, 0, m, ref info, p1, rep);
                    polint.polynomialfit(x, y, n, m, ref info2, p2, rep2);
                    if( info<=0 | info2<=0 )
                    {
                        fiterrors = true;
                    }
                    else
                    {
                        
                        //
                        // calculate P1 (interpolant), compare with P2 error
                        // compare RMS errors
                        //
                        t = 2*math.randomreal()-1;
                        v1 = ratint.barycentriccalc(p1, t);
                        v2 = ratint.barycentriccalc(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++)
            {
                ap.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 = math.randomreal();
                    v2 = math.randomreal();
                    v = 1+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((math.sqr(v1)+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(x, y, 4, 1, ref info, p, rep);
                if( info<=0 )
                {
                    fiterrors = true;
                }
                else
                {
                    s = ratint.barycentriccalc(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;
        }
Example #12
0
        public static bool testratint(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();

            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*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*math.randomreal()-0.2;
                    v1 = 2*math.randomreal()-1;
                    v2 = 2*math.randomreal()-1;
                    v3 = 2*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(x, y, w, n, b1);
                    
                    //
                    // unpack, then pack again and compare
                    //
                    brcunset(b2);
                    ratint.barycentricunpack(b1, ref n2, ref x2, ref y2, ref w2);
                    bcerrors = bcerrors | n2!=n;
                    ratint.barycentricbuildxyw(x2, y2, w2, n2, b2);
                    t = 2*math.randomreal()-1;
                    bcerrors = bcerrors | (double)(Math.Abs(ratint.barycentriccalc(b1, t)-ratint.barycentriccalc(b2, t)))>(double)(threshold);
                    
                    //
                    // copy, compare
                    //
                    brcunset(b2);
                    ratint.barycentriccopy(b1, b2);
                    t = 2*math.randomreal()-1;
                    bcerrors = bcerrors | (double)(Math.Abs(ratint.barycentriccalc(b1, t)-ratint.barycentriccalc(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(b1, x[i])-y[i]))>(double)(threshold*Math.Abs(y[i]));
                        
                        //
                        // compare with polynomial interpolation
                        //
                        t = 2*math.randomreal()-1;
                        poldiff2(x, y, n, t, ref v0, ref v1, ref v2);
                        bcerrors = bcerrors | (double)(Math.Abs(ratint.barycentriccalc(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(b1, v2)-ratint.barycentriccalc(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(b1, v2)-ratint.barycentriccalc(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*math.randomreal()-1;
                        poldiff2(x, y, n, t, ref v0, ref v1, ref v2);
                        d0 = 0;
                        d1 = 0;
                        d2 = 0;
                        ratint.barycentricdiff1(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(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*math.randomreal()-1;
                    a = 2*math.randomreal()-1;
                    b = 2*math.randomreal()-1;
                    brcunset(b2);
                    ratint.barycentriccopy(b1, b2);
                    ratint.barycentriclintransx(b2, a, b);
                    bcerrors = bcerrors | (double)(Math.Abs(ratint.barycentriccalc(b1, a*t+b)-ratint.barycentriccalc(b2, t)))>(double)(threshold);
                    a = 0;
                    b = 2*math.randomreal()-1;
                    brcunset(b2);
                    ratint.barycentriccopy(b1, b2);
                    ratint.barycentriclintransx(b2, a, b);
                    bcerrors = bcerrors | (double)(Math.Abs(ratint.barycentriccalc(b1, a*t+b)-ratint.barycentriccalc(b2, t)))>(double)(threshold);
                    a = 2*math.randomreal()-1;
                    b = 2*math.randomreal()-1;
                    brcunset(b2);
                    ratint.barycentriccopy(b1, b2);
                    ratint.barycentriclintransy(b2, a, b);
                    bcerrors = bcerrors | (double)(Math.Abs(a*ratint.barycentriccalc(b1, t)+b-ratint.barycentriccalc(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*math.minrealnumber;
                }
                if( pass%2==1 )
                {
                    h = 0.01*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(x, y, w, 4, b1);
                t = ratint.barycentriccalc(b1, v0);
                d0 = 0;
                d1 = 0;
                d2 = 0;
                ratint.barycentricdiff1(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*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*math.minrealnumber;
            ratint.barycentricbuildxyw(x, y, w, 4, b1);
            t = ratint.barycentriccalc(b1, v0);
            d0 = 0;
            d1 = 0;
            d2 = 0;
            ratint.barycentricdiff1(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*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 = math.minrealnumber;
            ratint.barycentricbuildxyw(x, y, w, 4, b1);
            t = ratint.barycentriccalc(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*math.randomreal()-1;
                y[0] = 2*math.randomreal()-1;
                ratint.barycentricbuildfloaterhormann(x, y, 1, 1, b1);
                maxerr = Math.Max(maxerr, Math.Abs(ratint.barycentriccalc(b1, 2*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*math.randomreal();
                    b = 1+1*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*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 = 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(x, y, n, 1, b1);
                    ratint.barycentricbuildxyw(x, y, w, n, b2);
                    for(i=1; i<=2*n; i++)
                    {
                        t = a+(b-a)*math.randomreal();
                        maxerr = Math.Max(maxerr, Math.Abs(ratint.barycentriccalc(b1, t)-ratint.barycentriccalc(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*math.randomreal();
                        b = 1+1*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*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 = 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(x, y, n, d, b1);
                        ratint.barycentricbuildxyw(x, y, w, n, b2);
                        for(i=1; i<=2*n; i++)
                        {
                            t = a+(b-a)*math.randomreal();
                            maxerr = Math.Max(maxerr, Math.Abs(ratint.barycentriccalc(b1, t)-ratint.barycentriccalc(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*math.randomreal()-1;
                            w[i] = 1+math.randomreal();
                        }
                        for(i=0; i<=k-1; i++)
                        {
                            xc[i] = (double)(n-k+i)/(double)(n-1);
                            yc[i] = 2*math.randomreal()-1;
                            dc[i] = 0;
                        }
                        ratint.barycentricfitfloaterhormannwc(x, y, w, n-k, xc, yc, dc, k, n, ref info, b1, rep);
                        if( info<=0 )
                        {
                            fiterrors = true;
                        }
                        else
                        {
                            for(i=0; i<=n-k-1; i++)
                            {
                                fiterrors = fiterrors | (double)(Math.Abs(ratint.barycentriccalc(b1, x[i])-y[i]))>(double)(threshold);
                            }
                            for(i=0; i<=k-1; i++)
                            {
                                fiterrors = fiterrors | (double)(Math.Abs(ratint.barycentriccalc(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*math.randomreal()-1;
                                y[i] = 2*math.randomreal()-1;
                                w[i] = 1+math.randomreal();
                            }
                            xc[0] = -1;
                            yc[0] = 2*math.randomreal()-1;
                            dc[0] = 0;
                            xc[1] = 1;
                            yc[1] = 2*math.randomreal()-1;
                            dc[1] = 0;
                            ratint.barycentricfitfloaterhormannwc(x, y, w, n, xc, yc, dc, k, m, ref info, b1, rep);
                            if( info<=0 )
                            {
                                fiterrors = true;
                            }
                            else
                            {
                                for(i=0; i<=k-1; i++)
                                {
                                    ratint.barycentricdiff1(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 = math.maxrealnumber;
                    xmax = -math.maxrealnumber;
                    for(i=0; i<=n-1; i++)
                    {
                        x2[i] = 2*Math.PI*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(x, y, m, 3, b1);
                    ratint.barycentricfitfloaterhormannwc(x2, y2, w2, n, xc, yc, dc, 0, m, ref info, b2, 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+math.sqr(ratint.barycentriccalc(b1, x2[i])-y2[i]);
                            v2 = v2+math.sqr(ratint.barycentriccalc(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*math.randomreal()-1;
                        y[i] = 2*math.randomreal()-1;
                        w[i] = 1;
                    }
                    ratint.barycentricfitfloaterhormannwc(x, y, w, n, xc, yc, dc, 0, m, ref info, b1, rep);
                    ratint.barycentricfitfloaterhormann(x, y, n, m, ref info2, b2, rep2);
                    if( info<=0 | info2<=0 )
                    {
                        fiterrors = true;
                    }
                    else
                    {
                        
                        //
                        // calculate B1 (interpolant), compare with B2
                        // compare RMS errors
                        //
                        t = 2*math.randomreal()-1;
                        v1 = ratint.barycentriccalc(b1, t);
                        v2 = ratint.barycentriccalc(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++)
            {
                ap.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 = math.randomreal();
                    v2 = math.randomreal();
                    v = 1+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((math.sqr(v1)+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(x, y, 4, 2, ref info, b1, rep);
                if( info<=0 )
                {
                    fiterrors = true;
                }
                else
                {
                    s = ratint.barycentriccalc(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;
        }
Example #13
0
    public static int Main(string[] args)
    {
        int m = 0;
        int n = 0;
        int d = 0;

        double[] x  = new double[0];
        double[] y  = new double[0];
        double[] w  = new double[0];
        double[] xc = new double[0];
        double[] yc = new double[0];
        int[]    dc = new int[0];
        ratint.barycentricfitreport rep = new ratint.barycentricfitreport();
        int info = 0;

        ratint.barycentricinterpolant r = new ratint.barycentricinterpolant();
        int    i  = 0;
        int    j  = 0;
        double a  = 0;
        double b  = 0;
        double v  = 0;
        double dv = 0;

        System.Console.WriteLine();
        System.Console.WriteLine();
        System.Console.Write("Fitting exp(2*x) at [-1,+1] by:");
        System.Console.WriteLine();
        System.Console.Write("1. constrained/unconstrained Floater-Hormann functions");
        System.Console.WriteLine();
        System.Console.WriteLine();
        System.Console.Write("Fit type                rms.err max.err    p(0)   dp(0)  DBest");
        System.Console.WriteLine();

        //
        // Prepare points
        //
        m = 5;
        a = -1;
        b = +1;
        n = 10000;
        x = new double[n];
        y = new double[n];
        w = new double[n];
        for (i = 0; i <= n - 1; i++)
        {
            x[i] = a + (b - a) * i / (n - 1);
            y[i] = Math.Exp(2 * x[i]);
            w[i] = 1.0;
        }

        //
        // Fitting:
        // a) f(x)=exp(2*x) at [-1,+1]
        // b) by 5 Floater-Hormann functions
        // c) without constraints
        //
        ratint.barycentricfitfloaterhormann(ref x, ref y, n, m, ref info, ref r, ref rep);
        ratint.barycentricdiff1(ref r, 0.0, ref v, ref dv);
        System.Console.Write("Unconstrained FH        ");
        System.Console.Write("{0,7:F4}", rep.rmserror);
        System.Console.Write(" ");
        System.Console.Write("{0,7:F4}", rep.maxerror);
        System.Console.Write(" ");
        System.Console.Write("{0,7:F4}", v);
        System.Console.Write(" ");
        System.Console.Write("{0,7:F4}", dv);
        System.Console.Write("      ");
        System.Console.Write("{0,0:d}", rep.dbest);
        System.Console.WriteLine();

        //
        // Fitting:
        // a) f(x)=exp(2*x) at [-1,+1]
        // b) by 5 Floater-Hormann functions
        // c) constrained: p(0)=1
        //
        xc    = new double[1];
        yc    = new double[1];
        dc    = new int[1];
        xc[0] = 0;
        yc[0] = 1;
        dc[0] = 0;
        ratint.barycentricfitfloaterhormannwc(ref x, ref y, ref w, n, ref xc, ref yc, ref dc, 1, m, ref info, ref r, ref rep);
        ratint.barycentricdiff1(ref r, 0.0, ref v, ref dv);
        System.Console.Write("Constrained FH, p(0)=1  ");
        System.Console.Write("{0,7:F4}", rep.rmserror);
        System.Console.Write(" ");
        System.Console.Write("{0,7:F4}", rep.maxerror);
        System.Console.Write(" ");
        System.Console.Write("{0,7:F4}", v);
        System.Console.Write(" ");
        System.Console.Write("{0,7:F4}", dv);
        System.Console.Write("      ");
        System.Console.Write("{0,0:d}", rep.dbest);
        System.Console.WriteLine();

        //
        // Fitting:
        // a) f(x)=exp(2*x) at [-1,+1]
        // b) by 5 Floater-Hormann functions
        // c) constrained: dp(0)=2
        //
        xc    = new double[1];
        yc    = new double[1];
        dc    = new int[1];
        xc[0] = 0;
        yc[0] = 2;
        dc[0] = 1;
        ratint.barycentricfitfloaterhormannwc(ref x, ref y, ref w, n, ref xc, ref yc, ref dc, 1, m, ref info, ref r, ref rep);
        ratint.barycentricdiff1(ref r, 0.0, ref v, ref dv);
        System.Console.Write("Constrained FH, dp(0)=2 ");
        System.Console.Write("{0,7:F4}", rep.rmserror);
        System.Console.Write(" ");
        System.Console.Write("{0,7:F4}", rep.maxerror);
        System.Console.Write(" ");
        System.Console.Write("{0,7:F4}", v);
        System.Console.Write(" ");
        System.Console.Write("{0,7:F4}", dv);
        System.Console.Write("      ");
        System.Console.Write("{0,0:d}", rep.dbest);
        System.Console.WriteLine();

        //
        // Fitting:
        // a) f(x)=exp(2*x) at [-1,+1]
        // b) by 5 Floater-Hormann functions
        // c) constrained: p(0)=1, dp(0)=2
        //
        xc    = new double[2];
        yc    = new double[2];
        dc    = new int[2];
        xc[0] = 0;
        yc[0] = 1;
        dc[0] = 0;
        xc[1] = 0;
        yc[1] = 2;
        dc[1] = 1;
        ratint.barycentricfitfloaterhormannwc(ref x, ref y, ref w, n, ref xc, ref yc, ref dc, 2, m, ref info, ref r, ref rep);
        ratint.barycentricdiff1(ref r, 0.0, ref v, ref dv);
        System.Console.Write("Constrained FH, both    ");
        System.Console.Write("{0,7:F4}", rep.rmserror);
        System.Console.Write(" ");
        System.Console.Write("{0,7:F4}", rep.maxerror);
        System.Console.Write(" ");
        System.Console.Write("{0,7:F4}", v);
        System.Console.Write(" ");
        System.Console.Write("{0,7:F4}", dv);
        System.Console.Write("      ");
        System.Console.Write("{0,0:d}", rep.dbest);
        System.Console.WriteLine();
        System.Console.WriteLine();
        System.Console.WriteLine();
        return(0);
    }
        private static void testrationalfitting(ref bool fiterrors)
        {
            double threshold = 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];
            int n = 0;
            int m = 0;
            int i = 0;
            int k = 0;
            int pass = 0;
            double t = 0;
            double s = 0;
            double v = 0;
            double v0 = 0;
            double v1 = 0;
            double v2 = 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;
            lsfit.barycentricfitreport rep = new lsfit.barycentricfitreport();
            lsfit.barycentricfitreport rep2 = new lsfit.barycentricfitreport();

            fiterrors = 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*math.machineepsilon;
            
            //
            // 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*math.randomreal()-1;
                            w[i] = 1+math.randomreal();
                        }
                        for(i=0; i<=k-1; i++)
                        {
                            xc[i] = (double)(n-k+i)/(double)(n-1);
                            yc[i] = 2*math.randomreal()-1;
                            dc[i] = 0;
                        }
                        lsfit.barycentricfitfloaterhormannwc(x, y, w, n-k, xc, yc, dc, k, n, ref info, b1, rep);
                        if( info<=0 )
                        {
                            fiterrors = true;
                        }
                        else
                        {
                            for(i=0; i<=n-k-1; i++)
                            {
                                fiterrors = fiterrors | (double)(Math.Abs(ratint.barycentriccalc(b1, x[i])-y[i]))>(double)(threshold);
                            }
                            for(i=0; i<=k-1; i++)
                            {
                                fiterrors = fiterrors | (double)(Math.Abs(ratint.barycentriccalc(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*math.randomreal()-1;
                                y[i] = 2*math.randomreal()-1;
                                w[i] = 1+math.randomreal();
                            }
                            xc[0] = -1;
                            yc[0] = 2*math.randomreal()-1;
                            dc[0] = 0;
                            xc[1] = 1;
                            yc[1] = 2*math.randomreal()-1;
                            dc[1] = 0;
                            lsfit.barycentricfitfloaterhormannwc(x, y, w, n, xc, yc, dc, k, m, ref info, b1, rep);
                            if( info<=0 )
                            {
                                fiterrors = true;
                            }
                            else
                            {
                                for(i=0; i<=k-1; i++)
                                {
                                    ratint.barycentricdiff1(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 = math.maxrealnumber;
                    xmax = -math.maxrealnumber;
                    for(i=0; i<=n-1; i++)
                    {
                        x2[i] = 2*Math.PI*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(x, y, m, 3, b1);
                    lsfit.barycentricfitfloaterhormannwc(x2, y2, w2, n, xc, yc, dc, 0, m, ref info, b2, 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+math.sqr(ratint.barycentriccalc(b1, x2[i])-y2[i]);
                            v2 = v2+math.sqr(ratint.barycentriccalc(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*math.randomreal()-1;
                        y[i] = 2*math.randomreal()-1;
                        w[i] = 1;
                    }
                    lsfit.barycentricfitfloaterhormannwc(x, y, w, n, xc, yc, dc, 0, m, ref info, b1, rep);
                    lsfit.barycentricfitfloaterhormann(x, y, n, m, ref info2, b2, rep2);
                    if( info<=0 | info2<=0 )
                    {
                        fiterrors = true;
                    }
                    else
                    {
                        
                        //
                        // calculate B1 (interpolant), compare with B2
                        // compare RMS errors
                        //
                        t = 2*math.randomreal()-1;
                        v1 = ratint.barycentriccalc(b1, t);
                        v2 = ratint.barycentriccalc(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++)
            {
                ap.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 = math.randomreal();
                    v2 = math.randomreal();
                    v = 1+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((math.sqr(v1)+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
                //
                lsfit.barycentricfitfloaterhormann(x, y, 4, 2, ref info, b1, rep);
                if( info<=0 )
                {
                    fiterrors = true;
                }
                else
                {
                    s = ratint.barycentriccalc(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);
                }
            }
        }
Example #15
0
        //
        // Public declarations
        //

        public barycentricinterpolant()
        {
            _innerobj = new ratint.barycentricinterpolant();
        }
    public static int Main(string[] args)
    {
        double[] x = new double[0];
        double[] y = new double[0];
        int      n = 0;
        int      i = 0;
        double   t = 0;

        ratint.barycentricinterpolant p = new ratint.barycentricinterpolant();
        double v      = 0;
        double dv     = 0;
        double d2v    = 0;
        double err    = 0;
        double maxerr = 0;


        //
        // Demonstration
        //
        System.Console.Write("POLYNOMIAL INTERPOLATION");
        System.Console.WriteLine();
        System.Console.WriteLine();
        System.Console.Write("F(x)=sin(x), [0, pi]");
        System.Console.WriteLine();
        System.Console.Write("Second degree polynomial is used");
        System.Console.WriteLine();
        System.Console.WriteLine();

        //
        // Create polynomial interpolant
        //
        n = 3;
        x = new double[n];
        y = new double[n];
        for (i = 0; i <= n - 1; i++)
        {
            x[i] = Math.PI * i / (n - 1);
            y[i] = Math.Sin(x[i]);
        }
        polint.polynomialbuild(ref x, ref y, n, ref p);

        //
        // Output results
        //
        ratint.barycentricdiff2(ref p, 0, ref v, ref dv, ref d2v);
        System.Console.Write("                 P(x)    F(x) ");
        System.Console.WriteLine();
        System.Console.Write("function       ");
        System.Console.Write("{0,6:F3}", ratint.barycentriccalc(ref p, 0));
        System.Console.Write("  ");
        System.Console.Write("{0,6:F3}", 0);
        System.Console.Write(" ");
        System.Console.WriteLine();
        System.Console.Write("d/dx(0)        ");
        System.Console.Write("{0,6:F3}", dv);
        System.Console.Write("  ");
        System.Console.Write("{0,6:F3}", 1);
        System.Console.Write(" ");
        System.Console.WriteLine();
        System.Console.Write("d2/dx2(0)      ");
        System.Console.Write("{0,6:F3}", d2v);
        System.Console.Write("  ");
        System.Console.Write("{0,6:F3}", 0);
        System.Console.Write(" ");
        System.Console.WriteLine();
        System.Console.WriteLine();
        System.Console.WriteLine();
        return(0);
    }
    public static int Main(string[] args)
    {
        int m = 0;
        int n = 0;
        int d = 0;
        double[] x = new double[0];
        double[] y = new double[0];
        double[] w = new double[0];
        double[] xc = new double[0];
        double[] yc = new double[0];
        int[] dc = new int[0];
        ratint.barycentricfitreport rep = new ratint.barycentricfitreport();
        int info = 0;
        ratint.barycentricinterpolant r = new ratint.barycentricinterpolant();
        int i = 0;
        int j = 0;
        double a = 0;
        double b = 0;
        double v = 0;
        double dv = 0;

        System.Console.WriteLine();
        System.Console.WriteLine();
        System.Console.Write("Fitting exp(2*x) at [-1,+1] by:");
        System.Console.WriteLine();
        System.Console.Write("1. constrained/unconstrained Floater-Hormann functions");
        System.Console.WriteLine();
        System.Console.WriteLine();
        System.Console.Write("Fit type                rms.err max.err    p(0)   dp(0)  DBest");
        System.Console.WriteLine();
        
        //
        // Prepare points
        //
        m = 5;
        a = -1;
        b = +1;
        n = 10000;
        x = new double[n];
        y = new double[n];
        w = new double[n];
        for(i=0; i<=n-1; i++)
        {
            x[i] = a+(b-a)*i/(n-1);
            y[i] = Math.Exp(2*x[i]);
            w[i] = 1.0;
        }
        
        //
        // Fitting:
        // a) f(x)=exp(2*x) at [-1,+1]
        // b) by 5 Floater-Hormann functions
        // c) without constraints
        //
        ratint.barycentricfitfloaterhormann(ref x, ref y, n, m, ref info, ref r, ref rep);
        ratint.barycentricdiff1(ref r, 0.0, ref v, ref dv);
        System.Console.Write("Unconstrained FH        ");
        System.Console.Write("{0,7:F4}",rep.rmserror);
        System.Console.Write(" ");
        System.Console.Write("{0,7:F4}",rep.maxerror);
        System.Console.Write(" ");
        System.Console.Write("{0,7:F4}",v);
        System.Console.Write(" ");
        System.Console.Write("{0,7:F4}",dv);
        System.Console.Write("      ");
        System.Console.Write("{0,0:d}",rep.dbest);
        System.Console.WriteLine();
        
        //
        // Fitting:
        // a) f(x)=exp(2*x) at [-1,+1]
        // b) by 5 Floater-Hormann functions
        // c) constrained: p(0)=1
        //
        xc = new double[1];
        yc = new double[1];
        dc = new int[1];
        xc[0] = 0;
        yc[0] = 1;
        dc[0] = 0;
        ratint.barycentricfitfloaterhormannwc(ref x, ref y, ref w, n, ref xc, ref yc, ref dc, 1, m, ref info, ref r, ref rep);
        ratint.barycentricdiff1(ref r, 0.0, ref v, ref dv);
        System.Console.Write("Constrained FH, p(0)=1  ");
        System.Console.Write("{0,7:F4}",rep.rmserror);
        System.Console.Write(" ");
        System.Console.Write("{0,7:F4}",rep.maxerror);
        System.Console.Write(" ");
        System.Console.Write("{0,7:F4}",v);
        System.Console.Write(" ");
        System.Console.Write("{0,7:F4}",dv);
        System.Console.Write("      ");
        System.Console.Write("{0,0:d}",rep.dbest);
        System.Console.WriteLine();
        
        //
        // Fitting:
        // a) f(x)=exp(2*x) at [-1,+1]
        // b) by 5 Floater-Hormann functions
        // c) constrained: dp(0)=2
        //
        xc = new double[1];
        yc = new double[1];
        dc = new int[1];
        xc[0] = 0;
        yc[0] = 2;
        dc[0] = 1;
        ratint.barycentricfitfloaterhormannwc(ref x, ref y, ref w, n, ref xc, ref yc, ref dc, 1, m, ref info, ref r, ref rep);
        ratint.barycentricdiff1(ref r, 0.0, ref v, ref dv);
        System.Console.Write("Constrained FH, dp(0)=2 ");
        System.Console.Write("{0,7:F4}",rep.rmserror);
        System.Console.Write(" ");
        System.Console.Write("{0,7:F4}",rep.maxerror);
        System.Console.Write(" ");
        System.Console.Write("{0,7:F4}",v);
        System.Console.Write(" ");
        System.Console.Write("{0,7:F4}",dv);
        System.Console.Write("      ");
        System.Console.Write("{0,0:d}",rep.dbest);
        System.Console.WriteLine();
        
        //
        // Fitting:
        // a) f(x)=exp(2*x) at [-1,+1]
        // b) by 5 Floater-Hormann functions
        // c) constrained: p(0)=1, dp(0)=2
        //
        xc = new double[2];
        yc = new double[2];
        dc = new int[2];
        xc[0] = 0;
        yc[0] = 1;
        dc[0] = 0;
        xc[1] = 0;
        yc[1] = 2;
        dc[1] = 1;
        ratint.barycentricfitfloaterhormannwc(ref x, ref y, ref w, n, ref xc, ref yc, ref dc, 2, m, ref info, ref r, ref rep);
        ratint.barycentricdiff1(ref r, 0.0, ref v, ref dv);
        System.Console.Write("Constrained FH, both    ");
        System.Console.Write("{0,7:F4}",rep.rmserror);
        System.Console.Write(" ");
        System.Console.Write("{0,7:F4}",rep.maxerror);
        System.Console.Write(" ");
        System.Console.Write("{0,7:F4}",v);
        System.Console.Write(" ");
        System.Console.Write("{0,7:F4}",dv);
        System.Console.Write("      ");
        System.Console.Write("{0,0:d}",rep.dbest);
        System.Console.WriteLine();
        System.Console.WriteLine();
        System.Console.WriteLine();
        return 0;
    }