Пример #1
0
 public barycentricinterpolant(ratint.barycentricinterpolant obj)
 {
     _innerobj = obj;
 }
Пример #2
0
        /*************************************************************************
        Conversion from barycentric representation to Chebyshev basis.
        This function has O(N^2) complexity.

        INPUT PARAMETERS:
            P   -   polynomial in barycentric form
            A,B -   base interval for Chebyshev polynomials (see below)
                    A<>B

        OUTPUT PARAMETERS
            T   -   coefficients of Chebyshev representation;
                    P(x) = sum { T[i]*Ti(2*(x-A)/(B-A)-1), i=0..N-1 },
                    where Ti - I-th Chebyshev polynomial.

        NOTES:
            barycentric interpolant passed as P may be either polynomial  obtained
            from  polynomial  interpolation/ fitting or rational function which is
            NOT polynomial. We can't distinguish between these two cases, and this
            algorithm just tries to work assuming that P IS a polynomial.  If not,
            algorithm will return results, but they won't have any meaning.

          -- ALGLIB --
             Copyright 30.09.2010 by Bochkanov Sergey
        *************************************************************************/
        public static void polynomialbar2cheb(ratint.barycentricinterpolant p,
            double a,
            double b,
            ref double[] t)
        {
            int i = 0;
            int k = 0;
            double[] vp = new double[0];
            double[] vx = new double[0];
            double[] tk = new double[0];
            double[] tk1 = new double[0];
            double v = 0;
            int i_ = 0;

            t = new double[0];

            alglib.ap.assert(math.isfinite(a), "PolynomialBar2Cheb: A is not finite!");
            alglib.ap.assert(math.isfinite(b), "PolynomialBar2Cheb: B is not finite!");
            alglib.ap.assert((double)(a)!=(double)(b), "PolynomialBar2Cheb: A=B!");
            alglib.ap.assert(p.n>0, "PolynomialBar2Cheb: P is not correctly initialized barycentric interpolant!");
            
            //
            // Calculate function values on a Chebyshev grid
            //
            vp = new double[p.n];
            vx = new double[p.n];
            for(i=0; i<=p.n-1; i++)
            {
                vx[i] = Math.Cos(Math.PI*(i+0.5)/p.n);
                vp[i] = ratint.barycentriccalc(p, 0.5*(vx[i]+1)*(b-a)+a);
            }
            
            //
            // T[0]
            //
            t = new double[p.n];
            v = 0;
            for(i=0; i<=p.n-1; i++)
            {
                v = v+vp[i];
            }
            t[0] = v/p.n;
            
            //
            // other T's.
            //
            // NOTES:
            // 1. TK stores T{k} on VX, TK1 stores T{k-1} on VX
            // 2. we can do same calculations with fast DCT, but it
            //    * adds dependencies
            //    * still leaves us with O(N^2) algorithm because
            //      preparation of function values is O(N^2) process
            //
            if( p.n>1 )
            {
                tk = new double[p.n];
                tk1 = new double[p.n];
                for(i=0; i<=p.n-1; i++)
                {
                    tk[i] = vx[i];
                    tk1[i] = 1;
                }
                for(k=1; k<=p.n-1; k++)
                {
                    
                    //
                    // calculate discrete product of function vector and TK
                    //
                    v = 0.0;
                    for(i_=0; i_<=p.n-1;i_++)
                    {
                        v += tk[i_]*vp[i_];
                    }
                    t[k] = v/(0.5*p.n);
                    
                    //
                    // Update TK and TK1
                    //
                    for(i=0; i<=p.n-1; i++)
                    {
                        v = 2*vx[i]*tk[i]-tk1[i];
                        tk1[i] = tk[i];
                        tk[i] = v;
                    }
                }
            }
        }
        /*************************************************************************
        Weighted  fitting  by  Chebyshev  polynomial  in  barycentric  form,  with
        constraints on function values or first derivatives.

        Small regularizing term is used when solving constrained tasks (to improve
        stability).

        Task is linear, so linear least squares solver is used. Complexity of this
        computational scheme is O(N*M^2), mostly dominated by least squares solver

        SEE ALSO:
            PolynomialFit()

        INPUT PARAMETERS:
            X   -   points, array[0..N-1].
            Y   -   function values, array[0..N-1].
            W   -   weights, array[0..N-1]
                    Each summand in square  sum  of  approximation deviations from
                    given  values  is  multiplied  by  the square of corresponding
                    weight. Fill it by 1's if you don't  want  to  solve  weighted
                    task.
            N   -   number of points, N>0.
            XC  -   points where polynomial values/derivatives are constrained,
                    array[0..K-1].
            YC  -   values of constraints, array[0..K-1]
            DC  -   array[0..K-1], types of constraints:
                    * DC[i]=0   means that P(XC[i])=YC[i]
                    * DC[i]=1   means that P'(XC[i])=YC[i]
                    SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS
            K   -   number of constraints, 0<=K<M.
                    K=0 means no constraints (XC/YC/DC are not used in such cases)
            M   -   number of basis functions (= polynomial_degree + 1), M>=1

        OUTPUT PARAMETERS:
            Info-   same format as in LSFitLinearW() subroutine:
                    * Info>0    task is solved
                    * Info<=0   an error occured:
                                -4 means inconvergence of internal SVD
                                -3 means inconsistent constraints
            P   -   interpolant in barycentric form.
            Rep -   report, same format as in LSFitLinearW() subroutine.
                    Following fields are set:
                    * RMSError      rms error on the (X,Y).
                    * AvgError      average error on the (X,Y).
                    * AvgRelError   average relative error on the non-zero Y
                    * MaxError      maximum error
                                    NON-WEIGHTED ERRORS ARE CALCULATED

        IMPORTANT:
            this subroitine doesn't calculate task's condition number for K<>0.

        SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES:

        Setting constraints can lead  to undesired  results,  like ill-conditioned
        behavior, or inconsistency being detected. From the other side,  it allows
        us to improve quality of the fit. Here we summarize  our  experience  with
        constrained regression splines:
        * even simple constraints can be inconsistent, see  Wikipedia  article  on
          this subject: http://en.wikipedia.org/wiki/Birkhoff_interpolation
        * the  greater  is  M (given  fixed  constraints),  the  more chances that
          constraints will be consistent
        * in the general case, consistency of constraints is NOT GUARANTEED.
        * in the one special cases, however, we can  guarantee  consistency.  This
          case  is:  M>1  and constraints on the function values (NOT DERIVATIVES)

        Our final recommendation is to use constraints  WHEN  AND  ONLY  when  you
        can't solve your task without them. Anything beyond  special  cases  given
        above is not guaranteed and may result in inconsistency.

          -- ALGLIB PROJECT --
             Copyright 10.12.2009 by Bochkanov Sergey
        *************************************************************************/
        public static void polynomialfitwc(double[] x,
            double[] y,
            double[] w,
            int n,
            double[] xc,
            double[] yc,
            int[] dc,
            int k,
            int m,
            ref int info,
            ratint.barycentricinterpolant p,
            polynomialfitreport rep)
        {
            double xa = 0;
            double xb = 0;
            double sa = 0;
            double sb = 0;
            double[] xoriginal = new double[0];
            double[] yoriginal = new double[0];
            double[] y2 = new double[0];
            double[] w2 = new double[0];
            double[] tmp = new double[0];
            double[] tmp2 = new double[0];
            double[] tmpdiff = new double[0];
            double[] bx = new double[0];
            double[] by = new double[0];
            double[] bw = new double[0];
            double[,] fmatrix = new double[0,0];
            double[,] cmatrix = new double[0,0];
            int i = 0;
            int j = 0;
            double mx = 0;
            double decay = 0;
            double u = 0;
            double v = 0;
            double s = 0;
            int relcnt = 0;
            lsfit.lsfitreport lrep = new lsfit.lsfitreport();
            int i_ = 0;

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

            ap.assert(n>0, "PolynomialFitWC: N<=0!");
            ap.assert(m>0, "PolynomialFitWC: M<=0!");
            ap.assert(k>=0, "PolynomialFitWC: K<0!");
            ap.assert(k<m, "PolynomialFitWC: K>=M!");
            ap.assert(ap.len(x)>=n, "PolynomialFitWC: Length(X)<N!");
            ap.assert(ap.len(y)>=n, "PolynomialFitWC: Length(Y)<N!");
            ap.assert(ap.len(w)>=n, "PolynomialFitWC: Length(W)<N!");
            ap.assert(ap.len(xc)>=k, "PolynomialFitWC: Length(XC)<K!");
            ap.assert(ap.len(yc)>=k, "PolynomialFitWC: Length(YC)<K!");
            ap.assert(ap.len(dc)>=k, "PolynomialFitWC: Length(DC)<K!");
            ap.assert(apserv.isfinitevector(x, n), "PolynomialFitWC: X contains infinite or NaN values!");
            ap.assert(apserv.isfinitevector(y, n), "PolynomialFitWC: Y contains infinite or NaN values!");
            ap.assert(apserv.isfinitevector(w, n), "PolynomialFitWC: X contains infinite or NaN values!");
            ap.assert(apserv.isfinitevector(xc, k), "PolynomialFitWC: XC contains infinite or NaN values!");
            ap.assert(apserv.isfinitevector(yc, k), "PolynomialFitWC: YC contains infinite or NaN values!");
            for(i=0; i<=k-1; i++)
            {
                ap.assert(dc[i]==0 | dc[i]==1, "PolynomialFitWC: one of DC[] is not 0 or 1!");
            }
            
            //
            // weight decay for correct handling of task which becomes
            // degenerate after constraints are applied
            //
            decay = 10000*math.machineepsilon;
            
            //
            // Scale X, Y, XC, YC
            //
            lsfit.lsfitscalexy(ref x, ref y, n, ref xc, ref yc, dc, k, ref xa, ref xb, ref sa, ref sb, ref xoriginal, ref yoriginal);
            
            //
            // allocate space, initialize/fill:
            // * FMatrix-   values of basis functions at X[]
            // * CMatrix-   values (derivatives) of basis functions at XC[]
            // * fill constraints matrix
            // * fill first N rows of design matrix with values
            // * fill next M rows of design matrix with regularizing term
            // * append M zeros to Y
            // * append M elements, mean(abs(W)) each, to W
            //
            y2 = new double[n+m];
            w2 = new double[n+m];
            tmp = new double[m];
            tmpdiff = new double[m];
            fmatrix = new double[n+m, m];
            if( k>0 )
            {
                cmatrix = new double[k, m+1];
            }
            
            //
            // Fill design matrix, Y2, W2:
            // * first N rows with basis functions for original points
            // * next M rows with decay terms
            //
            for(i=0; i<=n-1; i++)
            {
                
                //
                // prepare Ith row
                // use Tmp for calculations to avoid multidimensional arrays overhead
                //
                for(j=0; j<=m-1; j++)
                {
                    if( j==0 )
                    {
                        tmp[j] = 1;
                    }
                    else
                    {
                        if( j==1 )
                        {
                            tmp[j] = x[i];
                        }
                        else
                        {
                            tmp[j] = 2*x[i]*tmp[j-1]-tmp[j-2];
                        }
                    }
                }
                for(i_=0; i_<=m-1;i_++)
                {
                    fmatrix[i,i_] = tmp[i_];
                }
            }
            for(i=0; i<=m-1; i++)
            {
                for(j=0; j<=m-1; j++)
                {
                    if( i==j )
                    {
                        fmatrix[n+i,j] = decay;
                    }
                    else
                    {
                        fmatrix[n+i,j] = 0;
                    }
                }
            }
            for(i_=0; i_<=n-1;i_++)
            {
                y2[i_] = y[i_];
            }
            for(i_=0; i_<=n-1;i_++)
            {
                w2[i_] = w[i_];
            }
            mx = 0;
            for(i=0; i<=n-1; i++)
            {
                mx = mx+Math.Abs(w[i]);
            }
            mx = mx/n;
            for(i=0; i<=m-1; i++)
            {
                y2[n+i] = 0;
                w2[n+i] = mx;
            }
            
            //
            // fill constraints matrix
            //
            for(i=0; i<=k-1; i++)
            {
                
                //
                // prepare Ith row
                // use Tmp for basis function values,
                // TmpDiff for basos function derivatives
                //
                for(j=0; j<=m-1; j++)
                {
                    if( j==0 )
                    {
                        tmp[j] = 1;
                        tmpdiff[j] = 0;
                    }
                    else
                    {
                        if( j==1 )
                        {
                            tmp[j] = xc[i];
                            tmpdiff[j] = 1;
                        }
                        else
                        {
                            tmp[j] = 2*xc[i]*tmp[j-1]-tmp[j-2];
                            tmpdiff[j] = 2*(tmp[j-1]+xc[i]*tmpdiff[j-1])-tmpdiff[j-2];
                        }
                    }
                }
                if( dc[i]==0 )
                {
                    for(i_=0; i_<=m-1;i_++)
                    {
                        cmatrix[i,i_] = tmp[i_];
                    }
                }
                if( dc[i]==1 )
                {
                    for(i_=0; i_<=m-1;i_++)
                    {
                        cmatrix[i,i_] = tmpdiff[i_];
                    }
                }
                cmatrix[i,m] = yc[i];
            }
            
            //
            // Solve constrained task
            //
            if( k>0 )
            {
                
                //
                // solve using regularization
                //
                lsfit.lsfitlinearwc(y2, w2, fmatrix, cmatrix, n+m, m, k, ref info, ref tmp, lrep);
            }
            else
            {
                
                //
                // no constraints, no regularization needed
                //
                lsfit.lsfitlinearwc(y, w, fmatrix, cmatrix, n, m, 0, ref info, ref tmp, lrep);
            }
            if( info<0 )
            {
                return;
            }
            
            //
            // Generate barycentric model and scale it
            // * BX, BY store barycentric model nodes
            // * FMatrix is reused (remember - it is at least MxM, what we need)
            //
            // Model intialization is done in O(M^2). In principle, it can be
            // done in O(M*log(M)), but before it we solved task with O(N*M^2)
            // complexity, so it is only a small amount of total time spent.
            //
            bx = new double[m];
            by = new double[m];
            bw = new double[m];
            tmp2 = new double[m];
            s = 1;
            for(i=0; i<=m-1; i++)
            {
                if( m!=1 )
                {
                    u = Math.Cos(Math.PI*i/(m-1));
                }
                else
                {
                    u = 0;
                }
                v = 0;
                for(j=0; j<=m-1; j++)
                {
                    if( j==0 )
                    {
                        tmp2[j] = 1;
                    }
                    else
                    {
                        if( j==1 )
                        {
                            tmp2[j] = u;
                        }
                        else
                        {
                            tmp2[j] = 2*u*tmp2[j-1]-tmp2[j-2];
                        }
                    }
                    v = v+tmp[j]*tmp2[j];
                }
                bx[i] = u;
                by[i] = v;
                bw[i] = s;
                if( i==0 | i==m-1 )
                {
                    bw[i] = 0.5*bw[i];
                }
                s = -s;
            }
            ratint.barycentricbuildxyw(bx, by, bw, m, p);
            ratint.barycentriclintransx(p, 2/(xb-xa), -((xa+xb)/(xb-xa)));
            ratint.barycentriclintransy(p, sb-sa, sa);
            
            //
            // Scale absolute errors obtained from LSFitLinearW.
            // Relative error should be calculated separately
            // (because of shifting/scaling of the task)
            //
            rep.taskrcond = lrep.taskrcond;
            rep.rmserror = lrep.rmserror*(sb-sa);
            rep.avgerror = lrep.avgerror*(sb-sa);
            rep.maxerror = lrep.maxerror*(sb-sa);
            rep.avgrelerror = 0;
            relcnt = 0;
            for(i=0; i<=n-1; i++)
            {
                if( (double)(yoriginal[i])!=(double)(0) )
                {
                    rep.avgrelerror = rep.avgrelerror+Math.Abs(ratint.barycentriccalc(p, xoriginal[i])-yoriginal[i])/Math.Abs(yoriginal[i]);
                    relcnt = relcnt+1;
                }
            }
            if( relcnt!=0 )
            {
                rep.avgrelerror = rep.avgrelerror/relcnt;
            }
        }
Пример #4
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;
            }
        }
Пример #5
0
        /*************************************************************************
        Lagrange intepolant: generation of the model on equidistant grid.
        This function has O(N) complexity.

        INPUT PARAMETERS:
            A   -   left boundary of [A,B]
            B   -   right boundary of [A,B]
            Y   -   function values at the nodes, array[0..N-1]
            N   -   number of points, N>=1
                    for N=1 a constant model is constructed.

        OUTPUT PARAMETERS
            P   -   barycentric model which represents Lagrange interpolant
                    (see ratint unit info and BarycentricCalc() description for
                    more information).

          -- ALGLIB --
             Copyright 03.12.2009 by Bochkanov Sergey
        *************************************************************************/
        public static void polynomialbuildeqdist(double a,
            double b,
            double[] y,
            int n,
            ratint.barycentricinterpolant p)
        {
            int i = 0;
            double[] w = new double[0];
            double[] x = new double[0];
            double v = 0;

            alglib.ap.assert(n>0, "PolynomialBuildEqDist: N<=0!");
            alglib.ap.assert(alglib.ap.len(y)>=n, "PolynomialBuildEqDist: Length(Y)<N!");
            alglib.ap.assert(math.isfinite(a), "PolynomialBuildEqDist: A is infinite or NaN!");
            alglib.ap.assert(math.isfinite(b), "PolynomialBuildEqDist: B is infinite or NaN!");
            alglib.ap.assert(apserv.isfinitevector(y, n), "PolynomialBuildEqDist: Y contains infinite or NaN values!");
            alglib.ap.assert((double)(b)!=(double)(a), "PolynomialBuildEqDist: B=A!");
            alglib.ap.assert((double)(a+(b-a)/n)!=(double)(a), "PolynomialBuildEqDist: B is too close to A!");
            
            //
            // Special case: N=1
            //
            if( n==1 )
            {
                x = new double[1];
                w = new double[1];
                x[0] = 0.5*(b+a);
                w[0] = 1;
                ratint.barycentricbuildxyw(x, y, w, 1, p);
                return;
            }
            
            //
            // general case
            //
            x = new double[n];
            w = new double[n];
            v = 1;
            for(i=0; i<=n-1; i++)
            {
                w[i] = v;
                x[i] = a+(b-a)*i/(n-1);
                v = -(v*(n-1-i));
                v = v/(i+1);
            }
            ratint.barycentricbuildxyw(x, y, w, n, p);
        }
Пример #6
0
        /*************************************************************************
        Lagrange intepolant on Chebyshev grid (second kind).
        This function has O(N) complexity.

        INPUT PARAMETERS:
            A   -   left boundary of [A,B]
            B   -   right boundary of [A,B]
            Y   -   function values at the nodes, array[0..N-1],
                    Y[I] = Y(0.5*(B+A) + 0.5*(B-A)*Cos(PI*i/(n-1)))
            N   -   number of points, N>=1
                    for N=1 a constant model is constructed.

        OUTPUT PARAMETERS
            P   -   barycentric model which represents Lagrange interpolant
                    (see ratint unit info and BarycentricCalc() description for
                    more information).

          -- ALGLIB --
             Copyright 03.12.2009 by Bochkanov Sergey
        *************************************************************************/
        public static void polynomialbuildcheb2(double a,
            double b,
            double[] y,
            int n,
            ratint.barycentricinterpolant p)
        {
            int i = 0;
            double[] w = new double[0];
            double[] x = new double[0];
            double v = 0;

            alglib.ap.assert(n>0, "PolynomialBuildCheb2: N<=0!");
            alglib.ap.assert(alglib.ap.len(y)>=n, "PolynomialBuildCheb2: Length(Y)<N!");
            alglib.ap.assert(math.isfinite(a), "PolynomialBuildCheb2: A is infinite or NaN!");
            alglib.ap.assert(math.isfinite(b), "PolynomialBuildCheb2: B is infinite or NaN!");
            alglib.ap.assert((double)(b)!=(double)(a), "PolynomialBuildCheb2: B=A!");
            alglib.ap.assert(apserv.isfinitevector(y, n), "PolynomialBuildCheb2: Y contains infinite or NaN values!");
            
            //
            // Special case: N=1
            //
            if( n==1 )
            {
                x = new double[1];
                w = new double[1];
                x[0] = 0.5*(b+a);
                w[0] = 1;
                ratint.barycentricbuildxyw(x, y, w, 1, p);
                return;
            }
            
            //
            // general case
            //
            x = new double[n];
            w = new double[n];
            v = 1;
            for(i=0; i<=n-1; i++)
            {
                if( i==0 || i==n-1 )
                {
                    w[i] = v*0.5;
                }
                else
                {
                    w[i] = v;
                }
                x[i] = 0.5*(b+a)+0.5*(b-a)*Math.Cos(Math.PI*i/(n-1));
                v = -v;
            }
            ratint.barycentricbuildxyw(x, y, w, n, p);
        }
Пример #7
0
        /*************************************************************************
        Fitting by polynomials in barycentric form. This function provides  simple
        unterface for unconstrained unweighted fitting. See  PolynomialFitWC()  if
        you need constrained fitting.

        Task is linear, so linear least squares solver is used. Complexity of this
        computational scheme is O(N*M^2), mostly dominated by least squares solver

        SEE ALSO:
            PolynomialFitWC()

        INPUT PARAMETERS:
            X   -   points, array[0..N-1].
            Y   -   function values, array[0..N-1].
            N   -   number of points, N>0
                    * if given, only leading N elements of X/Y are used
                    * if not given, automatically determined from sizes of X/Y
            M   -   number of basis functions (= polynomial_degree + 1), M>=1

        OUTPUT PARAMETERS:
            Info-   same format as in LSFitLinearW() subroutine:
                    * Info>0    task is solved
                    * Info<=0   an error occured:
                                -4 means inconvergence of internal SVD
            P   -   interpolant in barycentric form.
            Rep -   report, same format as in LSFitLinearW() subroutine.
                    Following fields are set:
                    * RMSError      rms error on the (X,Y).
                    * AvgError      average error on the (X,Y).
                    * AvgRelError   average relative error on the non-zero Y
                    * MaxError      maximum error
                                    NON-WEIGHTED ERRORS ARE CALCULATED

        NOTES:
            you can convert P from barycentric form  to  the  power  or  Chebyshev
            basis with PolynomialBar2Pow() or PolynomialBar2Cheb() functions  from
            POLINT subpackage.

          -- ALGLIB PROJECT --
             Copyright 10.12.2009 by Bochkanov Sergey
        *************************************************************************/
        public static void polynomialfit(double[] x,
            double[] y,
            int n,
            int m,
            ref int info,
            ratint.barycentricinterpolant p,
            polynomialfitreport rep)
        {
            int i = 0;
            double[] w = new double[0];
            double[] xc = new double[0];
            double[] yc = new double[0];
            int[] dc = new int[0];

            info = 0;

            alglib.ap.assert(n>0, "PolynomialFit: N<=0!");
            alglib.ap.assert(m>0, "PolynomialFit: M<=0!");
            alglib.ap.assert(alglib.ap.len(x)>=n, "PolynomialFit: Length(X)<N!");
            alglib.ap.assert(alglib.ap.len(y)>=n, "PolynomialFit: Length(Y)<N!");
            alglib.ap.assert(apserv.isfinitevector(x, n), "PolynomialFit: X contains infinite or NaN values!");
            alglib.ap.assert(apserv.isfinitevector(y, n), "PolynomialFit: Y contains infinite or NaN values!");
            w = new double[n];
            for(i=0; i<=n-1; i++)
            {
                w[i] = 1;
            }
            polynomialfitwc(x, y, w, n, xc, yc, dc, 0, m, ref info, p, rep);
        }
Пример #8
0
        /*************************************************************************
        Conversion from power basis to barycentric representation.
        This function has O(N^2) complexity.

        INPUT PARAMETERS:
            A   -   coefficients, P(x) = sum { A[i]*((X-C)/S)^i, i=0..N-1 }
            N   -   number of coefficients (polynomial degree plus 1)
                    * if given, only leading N elements of A are used
                    * if not given, automatically determined from size of A
            C   -   offset (see below); 0.0 is used as default value.
            S   -   scale (see below);  1.0 is used as default value. S<>0.

        OUTPUT PARAMETERS
            P   -   polynomial in barycentric form


        NOTES:
        1.  this function accepts offset and scale, which can be  set  to  improve
            numerical properties of polynomial. For example, if you interpolate on
            [-1,+1],  you  can  set C=0 and S=1 and convert from sum of 1, x, x^2,
            x^3 and so on. In most cases you it is exactly what you need.

            However, if your interpolation model was built on [999,1001], you will
            see significant growth of numerical errors when using {1, x, x^2, x^3}
            as  input  basis.  Converting  from  sum  of  1, (x-1000), (x-1000)^2,
            (x-1000)^3 will be better option (you have to specify 1000.0 as offset
            C and 1.0 as scale S).

        2.  power basis is ill-conditioned and tricks described above can't  solve
            this problem completely. This function  will  return barycentric model
            in any case, but for N>8 accuracy well degrade. However, N's less than
            5 are pretty safe.

          -- ALGLIB --
             Copyright 30.09.2010 by Bochkanov Sergey
        *************************************************************************/
        public static void polynomialpow2bar(double[] a,
            int n,
            double c,
            double s,
            ratint.barycentricinterpolant p)
        {
            int i = 0;
            int k = 0;
            double[] y = new double[0];
            double vx = 0;
            double vy = 0;
            double px = 0;

            alglib.ap.assert(math.isfinite(c), "PolynomialPow2Bar: C is not finite!");
            alglib.ap.assert(math.isfinite(s), "PolynomialPow2Bar: S is not finite!");
            alglib.ap.assert((double)(s)!=(double)(0), "PolynomialPow2Bar: S is zero!");
            alglib.ap.assert(n>=1, "PolynomialPow2Bar: N<1");
            alglib.ap.assert(alglib.ap.len(a)>=n, "PolynomialPow2Bar: Length(A)<N");
            alglib.ap.assert(apserv.isfinitevector(a, n), "PolynomialPow2Bar: A[] contains INF or NAN");
            
            //
            // Calculate function values on a Chebyshev grid spanning [-1,+1]
            //
            y = new double[n];
            for(i=0; i<=n-1; i++)
            {
                
                //
                // Calculate value on a grid spanning [-1,+1]
                //
                vx = Math.Cos(Math.PI*(i+0.5)/n);
                vy = a[0];
                px = vx;
                for(k=1; k<=n-1; k++)
                {
                    vy = vy+px*a[k];
                    px = px*vx;
                }
                y[i] = vy;
            }
            
            //
            // Build barycentric interpolant, map grid from [-1,+1] to [A,B]
            //
            polynomialbuildcheb1(c-s, c+s, y, n, p);
        }
Пример #9
0
 /*************************************************************************
 Single-threaded stub. HPC ALGLIB replaces it by multithreaded code.
 *************************************************************************/
 public static void _pexec_barycentricfitfloaterhormann(double[] x,
     double[] y,
     int n,
     int m,
     ref int info,
     ratint.barycentricinterpolant b,
     barycentricfitreport rep)
 {
     barycentricfitfloaterhormann(x,y,n,m,ref info,b,rep);
 }
Пример #10
0
        /*************************************************************************
        Conversion from barycentric representation to power basis.
        This function has O(N^2) complexity.

        INPUT PARAMETERS:
            P   -   polynomial in barycentric form
            C   -   offset (see below); 0.0 is used as default value.
            S   -   scale (see below);  1.0 is used as default value. S<>0.

        OUTPUT PARAMETERS
            A   -   coefficients, P(x) = sum { A[i]*((X-C)/S)^i, i=0..N-1 }
            N   -   number of coefficients (polynomial degree plus 1)

        NOTES:
        1.  this function accepts offset and scale, which can be  set  to  improve
            numerical properties of polynomial. For example, if P was obtained  as
            result of interpolation on [-1,+1],  you  can  set  C=0  and  S=1  and
            represent  P  as sum of 1, x, x^2, x^3 and so on. In most cases you it
            is exactly what you need.

            However, if your interpolation model was built on [999,1001], you will
            see significant growth of numerical errors when using {1, x, x^2, x^3}
            as basis. Representing P as sum of 1, (x-1000), (x-1000)^2, (x-1000)^3
            will be better option. Such representation can be  obtained  by  using
            1000.0 as offset C and 1.0 as scale S.

        2.  power basis is ill-conditioned and tricks described above can't  solve
            this problem completely. This function  will  return  coefficients  in
            any  case,  but  for  N>8  they  will  become unreliable. However, N's
            less than 5 are pretty safe.
            
        3.  barycentric interpolant passed as P may be either polynomial  obtained
            from  polynomial  interpolation/ fitting or rational function which is
            NOT polynomial. We can't distinguish between these two cases, and this
            algorithm just tries to work assuming that P IS a polynomial.  If not,
            algorithm will return results, but they won't have any meaning.

          -- ALGLIB --
             Copyright 30.09.2010 by Bochkanov Sergey
        *************************************************************************/
        public static void polynomialbar2pow(ratint.barycentricinterpolant p,
            double c,
            double s,
            ref double[] a)
        {
            int i = 0;
            int k = 0;
            double e = 0;
            double d = 0;
            double[] vp = new double[0];
            double[] vx = new double[0];
            double[] tk = new double[0];
            double[] tk1 = new double[0];
            double[] t = new double[0];
            double v = 0;
            double c0 = 0;
            double s0 = 0;
            double va = 0;
            double vb = 0;
            double[] vai = new double[0];
            double[] vbi = new double[0];
            double minx = 0;
            double maxx = 0;
            int i_ = 0;

            a = new double[0];

            
            //
            // We have barycentric model built using set of points X[], and we
            // want to convert it to power basis centered about point  C  with
            // scale S: I-th basis function is ((X-C)/S)^i.
            //
            // We use following three-stage algorithm:
            //
            // 1. we build Chebyshev representation of polynomial using
            //    intermediate center C0 and scale S0, which are derived from X[]:
            //    C0 = 0.5*(min(X)+max(X)), S0 = 0.5*(max(X)-min(X)). Chebyshev
            //    representation is built by sampling points around center C0,
            //    with typical distance between them proportional to S0.
            // 2. then we transform form Chebyshev basis to intermediate power
            //    basis, using same center/scale C0/S0.
            // 3. after that, we apply linear transformation to intermediate
            //    power basis which moves it to final center/scale C/S.
            //
            // The idea of such multi-stage algorithm is that it is much easier to
            // transform barycentric model to Chebyshev basis, and only later to
            // power basis, than transforming it directly to power basis. It is
            // also more numerically stable to sample points using intermediate C0/S0,
            // which are derived from user-supplied model, than using "final" C/S,
            // which may be unsuitable for sampling (say, if S=1, we may have stability
            // problems when working with models built from dataset with non-unit
            // scale of abscissas).
            //
            alglib.ap.assert(math.isfinite(c), "PolynomialBar2Pow: C is not finite!");
            alglib.ap.assert(math.isfinite(s), "PolynomialBar2Pow: S is not finite!");
            alglib.ap.assert((double)(s)!=(double)(0), "PolynomialBar2Pow: S=0!");
            alglib.ap.assert(p.n>0, "PolynomialBar2Pow: P is not correctly initialized barycentric interpolant!");
            
            //
            // Select intermediate center/scale
            //
            minx = p.x[0];
            maxx = p.x[0];
            for(i=1; i<=p.n-1; i++)
            {
                minx = Math.Min(minx, p.x[i]);
                maxx = Math.Max(maxx, p.x[i]);
            }
            if( (double)(minx)==(double)(maxx) )
            {
                c0 = minx;
                s0 = 1.0;
            }
            else
            {
                c0 = 0.5*(maxx+minx);
                s0 = 0.5*(maxx-minx);
            }
            
            //
            // Calculate function values on a Chebyshev grid using intermediate C0/S0
            //
            vp = new double[p.n+1];
            vx = new double[p.n];
            for(i=0; i<=p.n-1; i++)
            {
                vx[i] = Math.Cos(Math.PI*(i+0.5)/p.n);
                vp[i] = ratint.barycentriccalc(p, s0*vx[i]+c0);
            }
            
            //
            // T[0]
            //
            t = new double[p.n];
            v = 0;
            for(i=0; i<=p.n-1; i++)
            {
                v = v+vp[i];
            }
            t[0] = v/p.n;
            
            //
            // other T's.
            //
            // NOTES:
            // 1. TK stores T{k} on VX, TK1 stores T{k-1} on VX
            // 2. we can do same calculations with fast DCT, but it
            //    * adds dependencies
            //    * still leaves us with O(N^2) algorithm because
            //      preparation of function values is O(N^2) process
            //
            if( p.n>1 )
            {
                tk = new double[p.n];
                tk1 = new double[p.n];
                for(i=0; i<=p.n-1; i++)
                {
                    tk[i] = vx[i];
                    tk1[i] = 1;
                }
                for(k=1; k<=p.n-1; k++)
                {
                    
                    //
                    // calculate discrete product of function vector and TK
                    //
                    v = 0.0;
                    for(i_=0; i_<=p.n-1;i_++)
                    {
                        v += tk[i_]*vp[i_];
                    }
                    t[k] = v/(0.5*p.n);
                    
                    //
                    // Update TK and TK1
                    //
                    for(i=0; i<=p.n-1; i++)
                    {
                        v = 2*vx[i]*tk[i]-tk1[i];
                        tk1[i] = tk[i];
                        tk[i] = v;
                    }
                }
            }
            
            //
            // Convert from Chebyshev basis to power basis
            //
            a = new double[p.n];
            for(i=0; i<=p.n-1; i++)
            {
                a[i] = 0;
            }
            d = 0;
            for(i=0; i<=p.n-1; i++)
            {
                for(k=i; k<=p.n-1; k++)
                {
                    e = a[k];
                    a[k] = 0;
                    if( i<=1 && k==i )
                    {
                        a[k] = 1;
                    }
                    else
                    {
                        if( i!=0 )
                        {
                            a[k] = 2*d;
                        }
                        if( k>i+1 )
                        {
                            a[k] = a[k]-a[k-2];
                        }
                    }
                    d = e;
                }
                d = a[i];
                e = 0;
                k = i;
                while( k<=p.n-1 )
                {
                    e = e+a[k]*t[k];
                    k = k+2;
                }
                a[i] = e;
            }
            
            //
            // Apply linear transformation which converts basis from intermediate
            // one Fi=((x-C0)/S0)^i to final one Fi=((x-C)/S)^i.
            //
            // We have y=(x-C0)/S0, z=(x-C)/S, and coefficients A[] for basis Fi(y).
            // Because we have y=A*z+B, for A=s/s0 and B=c/s0-c0/s0, we can perform
            // substitution and get coefficients A_new[] in basis Fi(z).
            //
            alglib.ap.assert(alglib.ap.len(vp)>=p.n+1, "PolynomialBar2Pow: internal error");
            alglib.ap.assert(alglib.ap.len(t)>=p.n, "PolynomialBar2Pow: internal error");
            for(i=0; i<=p.n-1; i++)
            {
                t[i] = 0.0;
            }
            va = s/s0;
            vb = c/s0-c0/s0;
            vai = new double[p.n];
            vbi = new double[p.n];
            vai[0] = 1;
            vbi[0] = 1;
            for(k=1; k<=p.n-1; k++)
            {
                vai[k] = vai[k-1]*va;
                vbi[k] = vbi[k-1]*vb;
            }
            for(k=0; k<=p.n-1; k++)
            {
                
                //
                // Generate set of binomial coefficients in VP[]
                //
                if( k>0 )
                {
                    vp[k] = 1;
                    for(i=k-1; i>=1; i--)
                    {
                        vp[i] = vp[i]+vp[i-1];
                    }
                    vp[0] = 1;
                }
                else
                {
                    vp[0] = 1;
                }
                
                //
                // Update T[] with expansion of K-th basis function
                //
                for(i=0; i<=k; i++)
                {
                    t[i] = t[i]+a[k]*vai[i]*vbi[k-i]*vp[i];
                }
            }
            for(k=0; k<=p.n-1; k++)
            {
                a[k] = t[k];
            }
        }
Пример #11
0
 /*************************************************************************
 Single-threaded stub. HPC ALGLIB replaces it by multithreaded code.
 *************************************************************************/
 public static void _pexec_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)
 {
     barycentricfitfloaterhormannwc(x,y,w,n,xc,yc,dc,k,m,ref info,b,rep);
 }
Пример #12
0
 /*************************************************************************
 Single-threaded stub. HPC ALGLIB replaces it by multithreaded code.
 *************************************************************************/
 public static void _pexec_polynomialfitwc(double[] x,
     double[] y,
     double[] w,
     int n,
     double[] xc,
     double[] yc,
     int[] dc,
     int k,
     int m,
     ref int info,
     ratint.barycentricinterpolant p,
     polynomialfitreport rep)
 {
     polynomialfitwc(x,y,w,n,xc,yc,dc,k,m,ref info,p,rep);
 }
Пример #13
0
 /*************************************************************************
 Single-threaded stub. HPC ALGLIB replaces it by multithreaded code.
 *************************************************************************/
 public static void _pexec_polynomialfit(double[] x,
     double[] y,
     int n,
     int m,
     ref int info,
     ratint.barycentricinterpolant p,
     polynomialfitreport rep)
 {
     polynomialfit(x,y,n,m,ref info,p,rep);
 }
Пример #14
0
        /*************************************************************************
        Conversion from Chebyshev basis to barycentric representation.
        This function has O(N^2) complexity.

        INPUT PARAMETERS:
            T   -   coefficients of Chebyshev representation;
                    P(x) = sum { T[i]*Ti(2*(x-A)/(B-A)-1), i=0..N },
                    where Ti - I-th Chebyshev polynomial.
            N   -   number of coefficients:
                    * if given, only leading N elements of T are used
                    * if not given, automatically determined from size of T
            A,B -   base interval for Chebyshev polynomials (see above)
                    A<B

        OUTPUT PARAMETERS
            P   -   polynomial in barycentric form

          -- ALGLIB --
             Copyright 30.09.2010 by Bochkanov Sergey
        *************************************************************************/
        public static void polynomialcheb2bar(double[] t,
            int n,
            double a,
            double b,
            ratint.barycentricinterpolant p)
        {
            int i = 0;
            int k = 0;
            double[] y = new double[0];
            double tk = 0;
            double tk1 = 0;
            double vx = 0;
            double vy = 0;
            double v = 0;

            alglib.ap.assert(math.isfinite(a), "PolynomialBar2Cheb: A is not finite!");
            alglib.ap.assert(math.isfinite(b), "PolynomialBar2Cheb: B is not finite!");
            alglib.ap.assert((double)(a)!=(double)(b), "PolynomialBar2Cheb: A=B!");
            alglib.ap.assert(n>=1, "PolynomialBar2Cheb: N<1");
            alglib.ap.assert(alglib.ap.len(t)>=n, "PolynomialBar2Cheb: Length(T)<N");
            alglib.ap.assert(apserv.isfinitevector(t, n), "PolynomialBar2Cheb: T[] contains INF or NAN");
            
            //
            // Calculate function values on a Chebyshev grid spanning [-1,+1]
            //
            y = new double[n];
            for(i=0; i<=n-1; i++)
            {
                
                //
                // Calculate value on a grid spanning [-1,+1]
                //
                vx = Math.Cos(Math.PI*(i+0.5)/n);
                vy = t[0];
                tk1 = 1;
                tk = vx;
                for(k=1; k<=n-1; k++)
                {
                    vy = vy+t[k]*tk;
                    v = 2*vx*tk-tk1;
                    tk1 = tk;
                    tk = v;
                }
                y[i] = vy;
            }
            
            //
            // Build barycentric interpolant, map grid from [-1,+1] to [A,B]
            //
            polynomialbuildcheb1(a, b, y, n, p);
        }
Пример #15
0
        /*************************************************************************
        Weighted  fitting by polynomials in barycentric form, with constraints  on
        function values or first derivatives.

        Small regularizing term is used when solving constrained tasks (to improve
        stability).

        Task is linear, so linear least squares solver is used. Complexity of this
        computational scheme is O(N*M^2), mostly dominated by least squares solver

        SEE ALSO:
            PolynomialFit()

        INPUT PARAMETERS:
            X   -   points, array[0..N-1].
            Y   -   function values, array[0..N-1].
            W   -   weights, array[0..N-1]
                    Each summand in square  sum  of  approximation deviations from
                    given  values  is  multiplied  by  the square of corresponding
                    weight. Fill it by 1's if you don't  want  to  solve  weighted
                    task.
            N   -   number of points, N>0.
                    * if given, only leading N elements of X/Y/W are used
                    * if not given, automatically determined from sizes of X/Y/W
            XC  -   points where polynomial values/derivatives are constrained,
                    array[0..K-1].
            YC  -   values of constraints, array[0..K-1]
            DC  -   array[0..K-1], types of constraints:
                    * DC[i]=0   means that P(XC[i])=YC[i]
                    * DC[i]=1   means that P'(XC[i])=YC[i]
                    SEE BELOW FOR IMPORTANT INFORMATION ON CONSTRAINTS
            K   -   number of constraints, 0<=K<M.
                    K=0 means no constraints (XC/YC/DC are not used in such cases)
            M   -   number of basis functions (= polynomial_degree + 1), M>=1

        OUTPUT PARAMETERS:
            Info-   same format as in LSFitLinearW() subroutine:
                    * Info>0    task is solved
                    * Info<=0   an error occured:
                                -4 means inconvergence of internal SVD
                                -3 means inconsistent constraints
            P   -   interpolant in barycentric form.
            Rep -   report, same format as in LSFitLinearW() subroutine.
                    Following fields are set:
                    * RMSError      rms error on the (X,Y).
                    * AvgError      average error on the (X,Y).
                    * AvgRelError   average relative error on the non-zero Y
                    * MaxError      maximum error
                                    NON-WEIGHTED ERRORS ARE CALCULATED

        IMPORTANT:
            this subroitine doesn't calculate task's condition number for K<>0.

        NOTES:
            you can convert P from barycentric form  to  the  power  or  Chebyshev
            basis with PolynomialBar2Pow() or PolynomialBar2Cheb() functions  from
            POLINT subpackage.

        SETTING CONSTRAINTS - DANGERS AND OPPORTUNITIES:

        Setting constraints can lead  to undesired  results,  like ill-conditioned
        behavior, or inconsistency being detected. From the other side,  it allows
        us to improve quality of the fit. Here we summarize  our  experience  with
        constrained regression splines:
        * even simple constraints can be inconsistent, see  Wikipedia  article  on
          this subject: http://en.wikipedia.org/wiki/Birkhoff_interpolation
        * the  greater  is  M (given  fixed  constraints),  the  more chances that
          constraints will be consistent
        * in the general case, consistency of constraints is NOT GUARANTEED.
        * in the one special cases, however, we can  guarantee  consistency.  This
          case  is:  M>1  and constraints on the function values (NOT DERIVATIVES)

        Our final recommendation is to use constraints  WHEN  AND  ONLY  when  you
        can't solve your task without them. Anything beyond  special  cases  given
        above is not guaranteed and may result in inconsistency.

          -- ALGLIB PROJECT --
             Copyright 10.12.2009 by Bochkanov Sergey
        *************************************************************************/
        public static void polynomialfitwc(double[] x,
            double[] y,
            double[] w,
            int n,
            double[] xc,
            double[] yc,
            int[] dc,
            int k,
            int m,
            ref int info,
            ratint.barycentricinterpolant p,
            polynomialfitreport rep)
        {
            double xa = 0;
            double xb = 0;
            double sa = 0;
            double sb = 0;
            double[] xoriginal = new double[0];
            double[] yoriginal = new double[0];
            double[] y2 = new double[0];
            double[] w2 = new double[0];
            double[] tmp = new double[0];
            double[] tmp2 = new double[0];
            double[] bx = new double[0];
            double[] by = new double[0];
            double[] bw = new double[0];
            int i = 0;
            int j = 0;
            double u = 0;
            double v = 0;
            double s = 0;
            int relcnt = 0;
            lsfitreport lrep = new lsfitreport();

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

            alglib.ap.assert(n>0, "PolynomialFitWC: N<=0!");
            alglib.ap.assert(m>0, "PolynomialFitWC: M<=0!");
            alglib.ap.assert(k>=0, "PolynomialFitWC: K<0!");
            alglib.ap.assert(k<m, "PolynomialFitWC: K>=M!");
            alglib.ap.assert(alglib.ap.len(x)>=n, "PolynomialFitWC: Length(X)<N!");
            alglib.ap.assert(alglib.ap.len(y)>=n, "PolynomialFitWC: Length(Y)<N!");
            alglib.ap.assert(alglib.ap.len(w)>=n, "PolynomialFitWC: Length(W)<N!");
            alglib.ap.assert(alglib.ap.len(xc)>=k, "PolynomialFitWC: Length(XC)<K!");
            alglib.ap.assert(alglib.ap.len(yc)>=k, "PolynomialFitWC: Length(YC)<K!");
            alglib.ap.assert(alglib.ap.len(dc)>=k, "PolynomialFitWC: Length(DC)<K!");
            alglib.ap.assert(apserv.isfinitevector(x, n), "PolynomialFitWC: X contains infinite or NaN values!");
            alglib.ap.assert(apserv.isfinitevector(y, n), "PolynomialFitWC: Y contains infinite or NaN values!");
            alglib.ap.assert(apserv.isfinitevector(w, n), "PolynomialFitWC: X contains infinite or NaN values!");
            alglib.ap.assert(apserv.isfinitevector(xc, k), "PolynomialFitWC: XC contains infinite or NaN values!");
            alglib.ap.assert(apserv.isfinitevector(yc, k), "PolynomialFitWC: YC contains infinite or NaN values!");
            for(i=0; i<=k-1; i++)
            {
                alglib.ap.assert(dc[i]==0 || dc[i]==1, "PolynomialFitWC: one of DC[] is not 0 or 1!");
            }
            
            //
            // Scale X, Y, XC, YC.
            // Solve scaled problem using internal Chebyshev fitting function.
            //
            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);
            internalchebyshevfit(x, y, w, n, xc, yc, dc, k, m, ref info, ref tmp, lrep);
            if( info<0 )
            {
                return;
            }
            
            //
            // Generate barycentric model and scale it
            // * BX, BY store barycentric model nodes
            // * FMatrix is reused (remember - it is at least MxM, what we need)
            //
            // Model intialization is done in O(M^2). In principle, it can be
            // done in O(M*log(M)), but before it we solved task with O(N*M^2)
            // complexity, so it is only a small amount of total time spent.
            //
            bx = new double[m];
            by = new double[m];
            bw = new double[m];
            tmp2 = new double[m];
            s = 1;
            for(i=0; i<=m-1; i++)
            {
                if( m!=1 )
                {
                    u = Math.Cos(Math.PI*i/(m-1));
                }
                else
                {
                    u = 0;
                }
                v = 0;
                for(j=0; j<=m-1; j++)
                {
                    if( j==0 )
                    {
                        tmp2[j] = 1;
                    }
                    else
                    {
                        if( j==1 )
                        {
                            tmp2[j] = u;
                        }
                        else
                        {
                            tmp2[j] = 2*u*tmp2[j-1]-tmp2[j-2];
                        }
                    }
                    v = v+tmp[j]*tmp2[j];
                }
                bx[i] = u;
                by[i] = v;
                bw[i] = s;
                if( i==0 || i==m-1 )
                {
                    bw[i] = 0.5*bw[i];
                }
                s = -s;
            }
            ratint.barycentricbuildxyw(bx, by, bw, m, p);
            ratint.barycentriclintransx(p, 2/(xb-xa), -((xa+xb)/(xb-xa)));
            ratint.barycentriclintransy(p, sb-sa, sa);
            
            //
            // Scale absolute errors obtained from LSFitLinearW.
            // Relative error should be calculated separately
            // (because of shifting/scaling of the task)
            //
            rep.taskrcond = lrep.taskrcond;
            rep.rmserror = lrep.rmserror*(sb-sa);
            rep.avgerror = lrep.avgerror*(sb-sa);
            rep.maxerror = lrep.maxerror*(sb-sa);
            rep.avgrelerror = 0;
            relcnt = 0;
            for(i=0; i<=n-1; i++)
            {
                if( (double)(yoriginal[i])!=(double)(0) )
                {
                    rep.avgrelerror = rep.avgrelerror+Math.Abs(ratint.barycentriccalc(p, xoriginal[i])-yoriginal[i])/Math.Abs(yoriginal[i]);
                    relcnt = relcnt+1;
                }
            }
            if( relcnt!=0 )
            {
                rep.avgrelerror = rep.avgrelerror/relcnt;
            }
        }
Пример #16
0
        /*************************************************************************
        Conversion from barycentric representation to power basis.
        This function has O(N^2) complexity.

        INPUT PARAMETERS:
            P   -   polynomial in barycentric form
            C   -   offset (see below); 0.0 is used as default value.
            S   -   scale (see below);  1.0 is used as default value. S<>0.

        OUTPUT PARAMETERS
            A   -   coefficients, P(x) = sum { A[i]*((X-C)/S)^i, i=0..N-1 }
            N   -   number of coefficients (polynomial degree plus 1)

        NOTES:
        1.  this function accepts offset and scale, which can be  set  to  improve
            numerical properties of polynomial. For example, if P was obtained  as
            result of interpolation on [-1,+1],  you  can  set  C=0  and  S=1  and
            represent  P  as sum of 1, x, x^2, x^3 and so on. In most cases you it
            is exactly what you need.

            However, if your interpolation model was built on [999,1001], you will
            see significant growth of numerical errors when using {1, x, x^2, x^3}
            as basis. Representing P as sum of 1, (x-1000), (x-1000)^2, (x-1000)^3
            will be better option. Such representation can be  obtained  by  using
            1000.0 as offset C and 1.0 as scale S.

        2.  power basis is ill-conditioned and tricks described above can't  solve
            this problem completely. This function  will  return  coefficients  in
            any  case,  but  for  N>8  they  will  become unreliable. However, N's
            less than 5 are pretty safe.
            
        3.  barycentric interpolant passed as P may be either polynomial  obtained
            from  polynomial  interpolation/ fitting or rational function which is
            NOT polynomial. We can't distinguish between these two cases, and this
            algorithm just tries to work assuming that P IS a polynomial.  If not,
            algorithm will return results, but they won't have any meaning.

          -- ALGLIB --
             Copyright 30.09.2010 by Bochkanov Sergey
        *************************************************************************/
        public static void polynomialbar2pow(ratint.barycentricinterpolant p,
            double c,
            double s,
            ref double[] a)
        {
            int i = 0;
            int k = 0;
            double e = 0;
            double d = 0;
            double[] vp = new double[0];
            double[] vx = new double[0];
            double[] tk = new double[0];
            double[] tk1 = new double[0];
            double[] t = new double[0];
            double v = 0;
            int i_ = 0;

            a = new double[0];

            alglib.ap.assert(math.isfinite(c), "PolynomialBar2Pow: C is not finite!");
            alglib.ap.assert(math.isfinite(s), "PolynomialBar2Pow: S is not finite!");
            alglib.ap.assert((double)(s)!=(double)(0), "PolynomialBar2Pow: S=0!");
            alglib.ap.assert(p.n>0, "PolynomialBar2Pow: P is not correctly initialized barycentric interpolant!");
            
            //
            // Calculate function values on a Chebyshev grid
            //
            vp = new double[p.n];
            vx = new double[p.n];
            for(i=0; i<=p.n-1; i++)
            {
                vx[i] = Math.Cos(Math.PI*(i+0.5)/p.n);
                vp[i] = ratint.barycentriccalc(p, s*vx[i]+c);
            }
            
            //
            // T[0]
            //
            t = new double[p.n];
            v = 0;
            for(i=0; i<=p.n-1; i++)
            {
                v = v+vp[i];
            }
            t[0] = v/p.n;
            
            //
            // other T's.
            //
            // NOTES:
            // 1. TK stores T{k} on VX, TK1 stores T{k-1} on VX
            // 2. we can do same calculations with fast DCT, but it
            //    * adds dependencies
            //    * still leaves us with O(N^2) algorithm because
            //      preparation of function values is O(N^2) process
            //
            if( p.n>1 )
            {
                tk = new double[p.n];
                tk1 = new double[p.n];
                for(i=0; i<=p.n-1; i++)
                {
                    tk[i] = vx[i];
                    tk1[i] = 1;
                }
                for(k=1; k<=p.n-1; k++)
                {
                    
                    //
                    // calculate discrete product of function vector and TK
                    //
                    v = 0.0;
                    for(i_=0; i_<=p.n-1;i_++)
                    {
                        v += tk[i_]*vp[i_];
                    }
                    t[k] = v/(0.5*p.n);
                    
                    //
                    // Update TK and TK1
                    //
                    for(i=0; i<=p.n-1; i++)
                    {
                        v = 2*vx[i]*tk[i]-tk1[i];
                        tk1[i] = tk[i];
                        tk[i] = v;
                    }
                }
            }
            
            //
            // Convert from Chebyshev basis to power basis
            //
            a = new double[p.n];
            for(i=0; i<=p.n-1; i++)
            {
                a[i] = 0;
            }
            d = 0;
            for(i=0; i<=p.n-1; i++)
            {
                for(k=i; k<=p.n-1; k++)
                {
                    e = a[k];
                    a[k] = 0;
                    if( i<=1 && k==i )
                    {
                        a[k] = 1;
                    }
                    else
                    {
                        if( i!=0 )
                        {
                            a[k] = 2*d;
                        }
                        if( k>i+1 )
                        {
                            a[k] = a[k]-a[k-2];
                        }
                    }
                    d = e;
                }
                d = a[i];
                e = 0;
                k = i;
                while( k<=p.n-1 )
                {
                    e = e+a[k]*t[k];
                    k = k+2;
                }
                a[i] = e;
            }
        }
Пример #17
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;
                    }
                }
            }
        }
Пример #18
0
        /*************************************************************************
        Lagrange intepolant: generation of the model on the general grid.
        This function has O(N^2) complexity.

        INPUT PARAMETERS:
            X   -   abscissas, array[0..N-1]
            Y   -   function values, array[0..N-1]
            N   -   number of points, N>=1

        OUTPUT PARAMETERS
            P   -   barycentric model which represents Lagrange interpolant
                    (see ratint unit info and BarycentricCalc() description for
                    more information).

          -- ALGLIB --
             Copyright 02.12.2009 by Bochkanov Sergey
        *************************************************************************/
        public static void polynomialbuild(double[] x,
            double[] y,
            int n,
            ratint.barycentricinterpolant p)
        {
            int j = 0;
            int k = 0;
            double[] w = new double[0];
            double b = 0;
            double a = 0;
            double v = 0;
            double mx = 0;
            double[] sortrbuf = new double[0];
            double[] sortrbuf2 = new double[0];
            int i_ = 0;

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

            alglib.ap.assert(n>0, "PolynomialBuild: N<=0!");
            alglib.ap.assert(alglib.ap.len(x)>=n, "PolynomialBuild: Length(X)<N!");
            alglib.ap.assert(alglib.ap.len(y)>=n, "PolynomialBuild: Length(Y)<N!");
            alglib.ap.assert(apserv.isfinitevector(x, n), "PolynomialBuild: X contains infinite or NaN values!");
            alglib.ap.assert(apserv.isfinitevector(y, n), "PolynomialBuild: Y contains infinite or NaN values!");
            tsort.tagsortfastr(ref x, ref y, ref sortrbuf, ref sortrbuf2, n);
            alglib.ap.assert(apserv.aredistinct(x, n), "PolynomialBuild: at least two consequent points are too close!");
            
            //
            // calculate W[j]
            // multi-pass algorithm is used to avoid overflow
            //
            w = new double[n];
            a = x[0];
            b = x[0];
            for(j=0; j<=n-1; j++)
            {
                w[j] = 1;
                a = Math.Min(a, x[j]);
                b = Math.Max(b, x[j]);
            }
            for(k=0; k<=n-1; k++)
            {
                
                //
                // W[K] is used instead of 0.0 because
                // cycle on J does not touch K-th element
                // and we MUST get maximum from ALL elements
                //
                mx = Math.Abs(w[k]);
                for(j=0; j<=n-1; j++)
                {
                    if( j!=k )
                    {
                        v = (b-a)/(x[j]-x[k]);
                        w[j] = w[j]*v;
                        mx = Math.Max(mx, Math.Abs(w[j]));
                    }
                }
                if( k%5==0 )
                {
                    
                    //
                    // every 5-th run we renormalize W[]
                    //
                    v = 1/mx;
                    for(i_=0; i_<=n-1;i_++)
                    {
                        w[i_] = v*w[i_];
                    }
                }
            }
            ratint.barycentricbuildxyw(x, y, w, n, p);
        }
Пример #19
0
        /*************************************************************************
        Rational least squares fitting using  Floater-Hormann  rational  functions
        with optimal D chosen from [0,9].

        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  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).

        INPUT PARAMETERS:
            X   -   points, array[0..N-1].
            Y   -   function values, array[0..N-1].
            N   -   number of points, N>0.
            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
            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

          -- ALGLIB PROJECT --
             Copyright 18.08.2009 by Bochkanov Sergey
        *************************************************************************/
        public static void barycentricfitfloaterhormann(double[] x,
            double[] y,
            int n,
            int m,
            ref int info,
            ratint.barycentricinterpolant b,
            barycentricfitreport rep)
        {
            double[] w = new double[0];
            double[] xc = new double[0];
            double[] yc = new double[0];
            int[] dc = new int[0];
            int i = 0;

            info = 0;

            alglib.ap.assert(n>0, "BarycentricFitFloaterHormann: N<=0!");
            alglib.ap.assert(m>0, "BarycentricFitFloaterHormann: M<=0!");
            alglib.ap.assert(alglib.ap.len(x)>=n, "BarycentricFitFloaterHormann: Length(X)<N!");
            alglib.ap.assert(alglib.ap.len(y)>=n, "BarycentricFitFloaterHormann: Length(Y)<N!");
            alglib.ap.assert(apserv.isfinitevector(x, n), "BarycentricFitFloaterHormann: X contains infinite or NaN values!");
            alglib.ap.assert(apserv.isfinitevector(y, n), "BarycentricFitFloaterHormann: Y contains infinite or NaN values!");
            w = new double[n];
            for(i=0; i<=n-1; i++)
            {
                w[i] = 1;
            }
            barycentricfitfloaterhormannwc(x, y, w, n, xc, yc, dc, 0, m, ref info, b, rep);
        }
Пример #20
0
        /*************************************************************************
        Lagrange intepolant on Chebyshev grid (first kind).
        This function has O(N) complexity.

        INPUT PARAMETERS:
            A   -   left boundary of [A,B]
            B   -   right boundary of [A,B]
            Y   -   function values at the nodes, array[0..N-1],
                    Y[I] = Y(0.5*(B+A) + 0.5*(B-A)*Cos(PI*(2*i+1)/(2*n)))
            N   -   number of points, N>=1
                    for N=1 a constant model is constructed.

        OUTPUT PARAMETERS
            P   -   barycentric model which represents Lagrange interpolant
                    (see ratint unit info and BarycentricCalc() description for
                    more information).

          -- ALGLIB --
             Copyright 03.12.2009 by Bochkanov Sergey
        *************************************************************************/
        public static void polynomialbuildcheb1(double a,
            double b,
            double[] y,
            int n,
            ratint.barycentricinterpolant p)
        {
            int i = 0;
            double[] w = new double[0];
            double[] x = new double[0];
            double v = 0;
            double t = 0;

            alglib.ap.assert(n>0, "PolynomialBuildCheb1: N<=0!");
            alglib.ap.assert(alglib.ap.len(y)>=n, "PolynomialBuildCheb1: Length(Y)<N!");
            alglib.ap.assert(math.isfinite(a), "PolynomialBuildCheb1: A is infinite or NaN!");
            alglib.ap.assert(math.isfinite(b), "PolynomialBuildCheb1: B is infinite or NaN!");
            alglib.ap.assert(apserv.isfinitevector(y, n), "PolynomialBuildCheb1: Y contains infinite or NaN values!");
            alglib.ap.assert((double)(b)!=(double)(a), "PolynomialBuildCheb1: B=A!");
            
            //
            // Special case: N=1
            //
            if( n==1 )
            {
                x = new double[1];
                w = new double[1];
                x[0] = 0.5*(b+a);
                w[0] = 1;
                ratint.barycentricbuildxyw(x, y, w, 1, p);
                return;
            }
            
            //
            // general case
            //
            x = new double[n];
            w = new double[n];
            v = 1;
            for(i=0; i<=n-1; i++)
            {
                t = Math.Tan(0.5*Math.PI*(2*i+1)/(2*n));
                w[i] = 2*v*t/(1+math.sqr(t));
                x[i] = 0.5*(b+a)+0.5*(b-a)*(1-math.sqr(t))/(1+math.sqr(t));
                v = -v;
            }
            ratint.barycentricbuildxyw(x, y, w, n, p);
        }
Пример #21
0
        /*************************************************************************
        Internal subroutine, calculates barycentric basis functions.
        Used for efficient simultaneous calculation of N basis functions.

          -- ALGLIB --
             Copyright 17.08.2009 by Bochkanov Sergey
        *************************************************************************/
        private static void barycentriccalcbasis(ratint.barycentricinterpolant b,
            double t,
            ref double[] y)
        {
            double s2 = 0;
            double s = 0;
            double v = 0;
            int i = 0;
            int j = 0;
            int i_ = 0;

            
            //
            // special case: N=1
            //
            if( b.n==1 )
            {
                y[0] = 1;
                return;
            }
            
            //
            // Here we assume that task is normalized, i.e.:
            // 1. abs(Y[i])<=1
            // 2. abs(W[i])<=1
            // 3. X[] is ordered
            //
            // First, we decide: should we use "safe" formula (guarded
            // against overflow) or fast one?
            //
            s = Math.Abs(t-b.x[0]);
            for(i=0; i<=b.n-1; i++)
            {
                v = b.x[i];
                if( (double)(v)==(double)(t) )
                {
                    for(j=0; j<=b.n-1; j++)
                    {
                        y[j] = 0;
                    }
                    y[i] = 1;
                    return;
                }
                v = Math.Abs(t-v);
                if( (double)(v)<(double)(s) )
                {
                    s = v;
                }
            }
            s2 = 0;
            for(i=0; i<=b.n-1; i++)
            {
                v = s/(t-b.x[i]);
                v = v*b.w[i];
                y[i] = v;
                s2 = s2+v;
            }
            v = 1/s2;
            for(i_=0; i_<=b.n-1;i_++)
            {
                y[i_] = v*y[i_];
            }
        }
Пример #22
0
        private static void brcunset(ratint.barycentricinterpolant b)
        {
            double[] x = new double[0];
            double[] y = new double[0];
            double[] w = new double[0];

            x = new double[1];
            y = new double[1];
            w = new double[1];
            x[0] = 0;
            y[0] = 0;
            w[0] = 1;
            ratint.barycentricbuildxyw(x, y, w, 1, b);
        }
 public barycentricfitreport(ratint.barycentricfitreport obj)
 {
     _innerobj = obj;
 }