Пример #1
0
        /*************************************************************************
        *  This subroutine builds Hermite spline interpolant.
        *
        *  INPUT PARAMETERS:
        *   X           -   spline nodes, array[0..N-1]
        *   Y           -   function values, array[0..N-1]
        *   D           -   derivatives, array[0..N-1]
        *   N           -   points count (optional):
        * N>=2
        * if given, only first N points are used to build spline
        * if not given, automatically detected from X/Y sizes
        *                     (len(X) must be equal to len(Y))
        *
        *  OUTPUT PARAMETERS:
        *   C           -   spline interpolant.
        *
        *
        *  ORDER OF POINTS
        *
        *  Subroutine automatically sorts points, so caller may pass unsorted array.
        *
        *  -- ALGLIB PROJECT --
        *    Copyright 23.06.2007 by Bochkanov Sergey
        *************************************************************************/
        public static void spline1dbuildhermite(double[] x,
                                                double[] y,
                                                double[] d,
                                                int n,
                                                spline1dinterpolant c)
        {
            int    i      = 0;
            double delta  = 0;
            double delta2 = 0;
            double delta3 = 0;

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

            alglib.ap.assert(n >= 2, "Spline1DBuildHermite: N<2!");
            alglib.ap.assert(alglib.ap.len(x) >= n, "Spline1DBuildHermite: Length(X)<N!");
            alglib.ap.assert(alglib.ap.len(y) >= n, "Spline1DBuildHermite: Length(Y)<N!");
            alglib.ap.assert(alglib.ap.len(d) >= n, "Spline1DBuildHermite: Length(D)<N!");

            //
            // check and sort points
            //
            alglib.ap.assert(apserv.isfinitevector(x, n), "Spline1DBuildHermite: X contains infinite or NAN values!");
            alglib.ap.assert(apserv.isfinitevector(y, n), "Spline1DBuildHermite: Y contains infinite or NAN values!");
            alglib.ap.assert(apserv.isfinitevector(d, n), "Spline1DBuildHermite: D contains infinite or NAN values!");
            heapsortdpoints(ref x, ref y, ref d, n);
            alglib.ap.assert(apserv.aredistinct(x, n), "Spline1DBuildHermite: at least two consequent points are too close!");

            //
            // Build
            //
            c.x          = new double[n];
            c.c          = new double[4 * (n - 1) + 2];
            c.periodic   = false;
            c.k          = 3;
            c.n          = n;
            c.continuity = 1;
            for (i = 0; i <= n - 1; i++)
            {
                c.x[i] = x[i];
            }
            for (i = 0; i <= n - 2; i++)
            {
                delta          = x[i + 1] - x[i];
                delta2         = math.sqr(delta);
                delta3         = delta * delta2;
                c.c[4 * i + 0] = y[i];
                c.c[4 * i + 1] = d[i];
                c.c[4 * i + 2] = (3 * (y[i + 1] - y[i]) - 2 * d[i] * delta - d[i + 1] * delta) / delta2;
                c.c[4 * i + 3] = (2 * (y[i] - y[i + 1]) + d[i] * delta + d[i + 1] * delta) / delta3;
            }
            c.c[4 * (n - 1) + 0] = y[n - 1];
            c.c[4 * (n - 1) + 1] = d[n - 1];
        }
Пример #2
0
        /*************************************************************************
        *  This subroutine calculates the value of the spline at the given point X.
        *
        *  INPUT PARAMETERS:
        *   C   -   spline interpolant
        *   X   -   point
        *
        *  Result:
        *   S(x)
        *
        *  -- ALGLIB PROJECT --
        *    Copyright 23.06.2007 by Bochkanov Sergey
        *************************************************************************/
        public static double spline1dcalc(spline1dinterpolant c, double x)
        {
            double result = 0;
            int    l      = 0;
            int    r      = 0;
            int    m      = 0;
            double t      = 0;

            alglib.ap.assert(c.k == 3, "Spline1DCalc: internal error");
            alglib.ap.assert(!Double.IsInfinity(x), "Spline1DCalc: infinite X!");

            //
            // special case: NaN
            //
            if (Double.IsNaN(x))
            {
                result = Double.NaN;
                return(result);
            }

            //
            // correct if periodic
            //
            if (c.periodic)
            {
                apserv.apperiodicmap(ref x, c.x[0], c.x[c.n - 1], ref t);
            }

            //
            // Binary search in the [ x[0], ..., x[n-2] ] (x[n-1] is not included)
            //
            l = 0;
            r = c.n - 2 + 1;
            while (l != r - 1)
            {
                m = (l + r) / 2;
                if (c.x[m] >= x)
                {
                    r = m;
                }
                else
                {
                    l = m;
                }
            }

            //
            // Interpolation
            //
            x      = x - c.x[l];
            m      = 4 * l;
            result = c.c[m] + x * (c.c[m + 1] + x * (c.c[m + 2] + x * c.c[m + 3]));
            return(result);
        }
Пример #3
0
            public override alglib.apobject make_copy()
            {
                spline1dinterpolant _result = new spline1dinterpolant();

                _result.periodic   = periodic;
                _result.n          = n;
                _result.k          = k;
                _result.continuity = continuity;
                _result.x          = (double[])x.Clone();
                _result.c          = (double[])c.Clone();
                return(_result);
            }
Пример #4
0
        /*************************************************************************
        *  Эта подпрограмма строит интеполянт линейного сплайна
        *
        *  ВХОДНЫЕ ПАРАМЕТРЫ:
        *   X   -   узлы сплайна, массив[0..N-1]
        *   Y   -   значения функци, массив[0..N-1]
        *   N   -   число точек (опционально):
        * N>=2
        * если задано, для построения сплайна используются только первые N точек
        * если не указано, автоматически определяется по размерам X / Y
        *             (length(X) должно быть равно length(Y))
        *
        *  ВЫХОДНЫЕ ПАРАМЕТРЫ:
        *   C   -   интерполянт сплайна
        *
        *
        *  ПОРЯДОК ТОЧЕК:
        *
        *  Подпрограмма автоматически сортирует точки, поэтому вызывающий может передать несортированный массив.
        *
        *  -- ALGLIB PROJECT --
        *    Copyright 24.06.2007 by Bochkanov Sergey
        *************************************************************************/
        public static void spline1dbuildlinear(double[] x, double[] y, int n, spline1dinterpolant c)
        {
            int i = 0;

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

            alglib.ap.assert(n > 1, "Spline1DBuildLinear: N<2!");
            alglib.ap.assert(alglib.ap.len(x) >= n, "Spline1DBuildLinear: Length(X)<N!");
            alglib.ap.assert(alglib.ap.len(y) >= n, "Spline1DBuildLinear: Length(Y)<N!");

            //
            // check and sort points
            //
            alglib.ap.assert(apserv.isfinitevector(x, n), "Spline1DBuildLinear: X contains infinite or NAN values!");
            alglib.ap.assert(apserv.isfinitevector(y, n), "Spline1DBuildLinear: Y contains infinite or NAN values!");
            Heapsortpoints(ref x, ref y, n);
            alglib.ap.assert(apserv.aredistinct(x, n), "Spline1DBuildLinear: at least two consequent points are too close!");

            //
            // Build
            //
            c.periodic   = false;
            c.n          = n;
            c.k          = 3;
            c.continuity = 0;
            c.x          = new double[n];
            c.c          = new double[4 * (n - 1) + 2];
            for (i = 0; i <= n - 1; i++)
            {
                c.x[i] = x[i];
            }
            for (i = 0; i <= n - 2; i++)
            {
                c.c[4 * i + 0] = y[i];
                c.c[4 * i + 1] = (y[i + 1] - y[i]) / (x[i + 1] - x[i]);
                c.c[4 * i + 2] = 0;
                c.c[4 * i + 3] = 0;
            }
            c.c[4 * (n - 1) + 0] = y[n - 1];
            c.c[4 * (n - 1) + 1] = c.c[4 * (n - 2) + 1];
        }
Пример #5
0
        /*************************************************************************
        This subroutine builds linear spline interpolant

        INPUT PARAMETERS:
            X   -   spline nodes, array[0..N-1]
            Y   -   function values, array[0..N-1]
            N   -   points count, N>=2
            
        OUTPUT PARAMETERS:
            C   -   spline interpolant


        ORDER OF POINTS

        Subroutine automatically sorts points, so caller may pass unsorted array.

          -- ALGLIB PROJECT --
             Copyright 24.06.2007 by Bochkanov Sergey
        *************************************************************************/
        public static void spline1dbuildlinear(double[] x,
            double[] y,
            int n,
            ref spline1dinterpolant c)
        {
            int i = 0;

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

            System.Diagnostics.Debug.Assert(n>1, "Spline1DBuildLinear: N<2!");
            
            //
            // Sort points
            //
            heapsortpoints(ref x, ref y, n);
            
            //
            // Build
            //
            c.periodic = false;
            c.n = n;
            c.k = 3;
            c.x = new double[n];
            c.c = new double[4*(n-1)];
            for(i=0; i<=n-1; i++)
            {
                c.x[i] = x[i];
            }
            for(i=0; i<=n-2; i++)
            {
                c.c[4*i+0] = y[i];
                c.c[4*i+1] = (y[i+1]-y[i])/(x[i+1]-x[i]);
                c.c[4*i+2] = 0;
                c.c[4*i+3] = 0;
            }
        }
Пример #6
0
        /*************************************************************************
        This subroutine makes the copy of the spline.

        INPUT PARAMETERS:
            C   -   spline interpolant.

        Result:
            CC  -   spline copy

          -- ALGLIB PROJECT --
             Copyright 29.06.2007 by Bochkanov Sergey
        *************************************************************************/
        public static void spline1dcopy(spline1dinterpolant c,
            spline1dinterpolant cc)
        {
            int s = 0;
            int i_ = 0;

            cc.periodic = c.periodic;
            cc.n = c.n;
            cc.k = c.k;
            cc.continuity = c.continuity;
            cc.x = new double[cc.n];
            for(i_=0; i_<=cc.n-1;i_++)
            {
                cc.x[i_] = c.x[i_];
            }
            s = alglib.ap.len(c.c);
            cc.c = new double[s];
            for(i_=0; i_<=s-1;i_++)
            {
                cc.c[i_] = c.c[i_];
            }
        }
Пример #7
0
        /*************************************************************************
        This subroutine calculates the value of the spline at the given point X.

        INPUT PARAMETERS:
            C   -   spline interpolant
            X   -   point

        Result:
            S(x)

          -- ALGLIB PROJECT --
             Copyright 23.06.2007 by Bochkanov Sergey
        *************************************************************************/
        public static double spline1dcalc(spline1dinterpolant c,
            double x)
        {
            double result = 0;
            int l = 0;
            int r = 0;
            int m = 0;
            double t = 0;

            alglib.ap.assert(c.k==3, "Spline1DCalc: internal error");
            alglib.ap.assert(!Double.IsInfinity(x), "Spline1DCalc: infinite X!");
            
            //
            // special case: NaN
            //
            if( Double.IsNaN(x) )
            {
                result = Double.NaN;
                return result;
            }
            
            //
            // correct if periodic
            //
            if( c.periodic )
            {
                apserv.apperiodicmap(ref x, c.x[0], c.x[c.n-1], ref t);
            }
            
            //
            // Binary search in the [ x[0], ..., x[n-2] ] (x[n-1] is not included)
            //
            l = 0;
            r = c.n-2+1;
            while( l!=r-1 )
            {
                m = (l+r)/2;
                if( c.x[m]>=x )
                {
                    r = m;
                }
                else
                {
                    l = m;
                }
            }
            
            //
            // Interpolation
            //
            x = x-c.x[l];
            m = 4*l;
            result = c.c[m]+x*(c.c[m+1]+x*(c.c[m+2]+x*c.c[m+3]));
            return result;
        }
Пример #8
0
        /*************************************************************************
        This subroutine builds Hermite spline interpolant.

        INPUT PARAMETERS:
            X           -   spline nodes, array[0..N-1]
            Y           -   function values, array[0..N-1]
            D           -   derivatives, array[0..N-1]
            N           -   points count (optional):
                            * N>=2
                            * if given, only first N points are used to build spline
                            * if not given, automatically detected from X/Y sizes
                              (len(X) must be equal to len(Y))

        OUTPUT PARAMETERS:
            C           -   spline interpolant.


        ORDER OF POINTS

        Subroutine automatically sorts points, so caller may pass unsorted array.

          -- ALGLIB PROJECT --
             Copyright 23.06.2007 by Bochkanov Sergey
        *************************************************************************/
        public static void spline1dbuildhermite(double[] x,
            double[] y,
            double[] d,
            int n,
            spline1dinterpolant c)
        {
            int i = 0;
            double delta = 0;
            double delta2 = 0;
            double delta3 = 0;

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

            alglib.ap.assert(n>=2, "Spline1DBuildHermite: N<2!");
            alglib.ap.assert(alglib.ap.len(x)>=n, "Spline1DBuildHermite: Length(X)<N!");
            alglib.ap.assert(alglib.ap.len(y)>=n, "Spline1DBuildHermite: Length(Y)<N!");
            alglib.ap.assert(alglib.ap.len(d)>=n, "Spline1DBuildHermite: Length(D)<N!");
            
            //
            // check and sort points
            //
            alglib.ap.assert(apserv.isfinitevector(x, n), "Spline1DBuildHermite: X contains infinite or NAN values!");
            alglib.ap.assert(apserv.isfinitevector(y, n), "Spline1DBuildHermite: Y contains infinite or NAN values!");
            alglib.ap.assert(apserv.isfinitevector(d, n), "Spline1DBuildHermite: D contains infinite or NAN values!");
            heapsortdpoints(ref x, ref y, ref d, n);
            alglib.ap.assert(apserv.aredistinct(x, n), "Spline1DBuildHermite: at least two consequent points are too close!");
            
            //
            // Build
            //
            c.x = new double[n];
            c.c = new double[4*(n-1)+2];
            c.periodic = false;
            c.k = 3;
            c.n = n;
            c.continuity = 1;
            for(i=0; i<=n-1; i++)
            {
                c.x[i] = x[i];
            }
            for(i=0; i<=n-2; i++)
            {
                delta = x[i+1]-x[i];
                delta2 = math.sqr(delta);
                delta3 = delta*delta2;
                c.c[4*i+0] = y[i];
                c.c[4*i+1] = d[i];
                c.c[4*i+2] = (3*(y[i+1]-y[i])-2*d[i]*delta-d[i+1]*delta)/delta2;
                c.c[4*i+3] = (2*(y[i]-y[i+1])+d[i]*delta+d[i+1]*delta)/delta3;
            }
            c.c[4*(n-1)+0] = y[n-1];
            c.c[4*(n-1)+1] = d[n-1];
        }
Пример #9
0
            /*************************************************************************
            This subroutine performs linear transformation of the spline.

            INPUT PARAMETERS:
                C   -   spline interpolant.
                A, B-   transformation coefficients: S2(x) = A*S(x) + B
            Result:
                C   -   transformed spline

              -- ALGLIB PROJECT --
                 Copyright 30.06.2007 by Bochkanov Sergey
            *************************************************************************/
            public static void spline1dlintransy(spline1dinterpolant c,
                double a,
                double b) {
                int i = 0;
                int j = 0;
                int n = 0;

                n = c.n;
                for(i = 0; i <= n - 2; i++) {
                    c.c[(c.k + 1) * i] = a * c.c[(c.k + 1) * i] + b;
                    for(j = 1; j <= c.k; j++) {
                        c.c[(c.k + 1) * i + j] = a * c.c[(c.k + 1) * i + j];
                    }
                }
            }
Пример #10
0
            /*************************************************************************
            This subroutine makes the copy of the spline.

            INPUT PARAMETERS:
                C   -   spline interpolant.

            Result:
                CC  -   spline copy

              -- ALGLIB PROJECT --
                 Copyright 29.06.2007 by Bochkanov Sergey
            *************************************************************************/
            public static void spline1dcopy(spline1dinterpolant c,
                spline1dinterpolant cc) {
                int i_ = 0;

                cc.periodic = c.periodic;
                cc.n = c.n;
                cc.k = c.k;
                cc.x = new double[cc.n];
                for(i_ = 0; i_ <= cc.n - 1; i_++) {
                    cc.x[i_] = c.x[i_];
                }
                cc.c = new double[(cc.k + 1) * (cc.n - 1)];
                for(i_ = 0; i_ <= (cc.k + 1) * (cc.n - 1) - 1; i_++) {
                    cc.c[i_] = c.c[i_];
                }
            }
Пример #11
0
        /*************************************************************************
        This function builds monotone cubic Hermite interpolant. This interpolant
        is monotonic in [x(0),x(n-1)] and is constant outside of this interval.

        In  case  y[]  form  non-monotonic  sequence,  interpolant  is  piecewise
        monotonic.  Say, for x=(0,1,2,3,4)  and  y=(0,1,2,1,0)  interpolant  will
        monotonically grow at [0..2] and monotonically decrease at [2..4].

        INPUT PARAMETERS:
            X           -   spline nodes, array[0..N-1]. Subroutine automatically
                            sorts points, so caller may pass unsorted array.
            Y           -   function values, array[0..N-1]
            N           -   the number of points(N>=2).

        OUTPUT PARAMETERS:
            C           -   spline interpolant.

         -- ALGLIB PROJECT --
             Copyright 21.06.2012 by Bochkanov Sergey
        *************************************************************************/
        public static void spline1dbuildmonotone(double[] x,
            double[] y,
            int n,
            spline1dinterpolant c)
        {
            double[] d = new double[0];
            double[] ex = new double[0];
            double[] ey = new double[0];
            int[] p = new int[0];
            double delta = 0;
            double alpha = 0;
            double beta = 0;
            int tmpn = 0;
            int sn = 0;
            double ca = 0;
            double cb = 0;
            double epsilon = 0;
            int i = 0;
            int j = 0;

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

            
            //
            // Check lengths of arguments
            //
            alglib.ap.assert(n>=2, "Spline1DBuildMonotone: N<2");
            alglib.ap.assert(alglib.ap.len(x)>=n, "Spline1DBuildMonotone: Length(X)<N");
            alglib.ap.assert(alglib.ap.len(y)>=n, "Spline1DBuildMonotone: Length(Y)<N");
            
            //
            // Check and sort points
            //
            alglib.ap.assert(apserv.isfinitevector(x, n), "Spline1DBuildMonotone: X contains infinite or NAN values");
            alglib.ap.assert(apserv.isfinitevector(y, n), "Spline1DBuildMonotone: Y contains infinite or NAN values");
            heapsortppoints(ref x, ref y, ref p, n);
            alglib.ap.assert(apserv.aredistinct(x, n), "Spline1DBuildMonotone: at least two consequent points are too close");
            epsilon = math.machineepsilon;
            n = n+2;
            d = new double[n];
            ex = new double[n];
            ey = new double[n];
            ex[0] = x[0]-Math.Abs(x[1]-x[0]);
            ex[n-1] = x[n-3]+Math.Abs(x[n-3]-x[n-4]);
            ey[0] = y[0];
            ey[n-1] = y[n-3];
            for(i=1; i<=n-2; i++)
            {
                ex[i] = x[i-1];
                ey[i] = y[i-1];
            }
            
            //
            // Init sign of the function for first segment
            //
            i = 0;
            ca = 0;
            do
            {
                ca = ey[i+1]-ey[i];
                i = i+1;
            }
            while( !((double)(ca)!=(double)(0) || i>n-2) );
            if( (double)(ca)!=(double)(0) )
            {
                ca = ca/Math.Abs(ca);
            }
            i = 0;
            while( i<n-1 )
            {
                
                //
                // Partition of the segment [X0;Xn]
                //
                tmpn = 1;
                for(j=i; j<=n-2; j++)
                {
                    cb = ey[j+1]-ey[j];
                    if( (double)(ca*cb)>=(double)(0) )
                    {
                        tmpn = tmpn+1;
                    }
                    else
                    {
                        ca = cb/Math.Abs(cb);
                        break;
                    }
                }
                sn = i+tmpn;
                alglib.ap.assert(tmpn>=2, "Spline1DBuildMonotone: internal error");
                
                //
                // Calculate derivatives for current segment
                //
                d[i] = 0;
                d[sn-1] = 0;
                for(j=i+1; j<=sn-2; j++)
                {
                    d[j] = ((ey[j]-ey[j-1])/(ex[j]-ex[j-1])+(ey[j+1]-ey[j])/(ex[j+1]-ex[j]))/2;
                }
                for(j=i; j<=sn-2; j++)
                {
                    delta = (ey[j+1]-ey[j])/(ex[j+1]-ex[j]);
                    if( (double)(Math.Abs(delta))<=(double)(epsilon) )
                    {
                        d[j] = 0;
                        d[j+1] = 0;
                    }
                    else
                    {
                        alpha = d[j]/delta;
                        beta = d[j+1]/delta;
                        if( (double)(alpha)!=(double)(0) )
                        {
                            cb = alpha*Math.Sqrt(1+math.sqr(beta/alpha));
                        }
                        else
                        {
                            if( (double)(beta)!=(double)(0) )
                            {
                                cb = beta;
                            }
                            else
                            {
                                continue;
                            }
                        }
                        if( (double)(cb)>(double)(3) )
                        {
                            d[j] = 3*alpha*delta/cb;
                            d[j+1] = 3*beta*delta/cb;
                        }
                    }
                }
                
                //
                // Transition to next segment
                //
                i = sn-1;
            }
            spline1dbuildhermite(ex, ey, d, n, c);
            c.continuity = 2;
        }
Пример #12
0
        /*************************************************************************
        *  This subroutine differentiates the spline.
        *
        *  INPUT PARAMETERS:
        *   C   -   spline interpolant.
        *   X   -   point
        *
        *  Result:
        *   S   -   S(x)
        *   DS  -   S'(x)
        *   D2S -   S''(x)
        *
        *  -- ALGLIB PROJECT --
        *    Copyright 24.06.2007 by Bochkanov Sergey
        *************************************************************************/
        public static void spline1ddiff(spline1dinterpolant c,
                                        double x,
                                        ref double s,
                                        ref double ds,
                                        ref double d2s)
        {
            int    l = 0;
            int    r = 0;
            int    m = 0;
            double t = 0;

            s   = 0;
            ds  = 0;
            d2s = 0;

            alglib.ap.assert(c.k == 3, "Spline1DDiff: internal error");
            alglib.ap.assert(!Double.IsInfinity(x), "Spline1DDiff: infinite X!");

            //
            // special case: NaN
            //
            if (Double.IsNaN(x))
            {
                s   = Double.NaN;
                ds  = Double.NaN;
                d2s = Double.NaN;
                return;
            }

            //
            // correct if periodic
            //
            if (c.periodic)
            {
                apserv.apperiodicmap(ref x, c.x[0], c.x[c.n - 1], ref t);
            }

            //
            // Binary search
            //
            l = 0;
            r = c.n - 2 + 1;
            while (l != r - 1)
            {
                m = (l + r) / 2;
                if (c.x[m] >= x)
                {
                    r = m;
                }
                else
                {
                    l = m;
                }
            }

            //
            // Differentiation
            //
            x   = x - c.x[l];
            m   = 4 * l;
            s   = c.c[m] + x * (c.c[m + 1] + x * (c.c[m + 2] + x * c.c[m + 3]));
            ds  = c.c[m + 1] + 2 * x * c.c[m + 2] + 3 * math.sqr(x) * c.c[m + 3];
            d2s = 2 * c.c[m + 2] + 6 * x * c.c[m + 3];
        }
Пример #13
0
        /*************************************************************************
        *  This subroutine builds Akima spline interpolant
        *
        *  INPUT PARAMETERS:
        *   X           -   spline nodes, array[0..N-1]
        *   Y           -   function values, array[0..N-1]
        *   N           -   points count (optional):
        * N>=2
        * if given, only first N points are used to build spline
        * if not given, automatically detected from X/Y sizes
        *                     (len(X) must be equal to len(Y))
        *
        *  OUTPUT PARAMETERS:
        *   C           -   spline interpolant
        *
        *
        *  ORDER OF POINTS
        *
        *  Subroutine automatically sorts points, so caller may pass unsorted array.
        *
        *  -- ALGLIB PROJECT --
        *    Copyright 24.06.2007 by Bochkanov Sergey
        *************************************************************************/
        public static void spline1dbuildakima(double[] x, double[] y, int n, spline1dinterpolant c)
        {
            int i = 0;

            double[] d    = new double[0];
            double[] w    = new double[0];
            double[] diff = new double[0];

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

            alglib.ap.assert(n >= 2, "Spline1DBuildAkima: N<2!");
            alglib.ap.assert(alglib.ap.len(x) >= n, "Spline1DBuildAkima: Length(X)<N!");
            alglib.ap.assert(alglib.ap.len(y) >= n, "Spline1DBuildAkima: Length(Y)<N!");

            //
            // check and sort points
            //
            alglib.ap.assert(apserv.isfinitevector(x, n), "Spline1DBuildAkima: X contains infinite or NAN values!");
            alglib.ap.assert(apserv.isfinitevector(y, n), "Spline1DBuildAkima: Y contains infinite or NAN values!");
            heapsortpoints(ref x, ref y, n);
            alglib.ap.assert(apserv.aredistinct(x, n), "Spline1DBuildAkima: at least two consequent points are too close!");

            //
            // Handle special cases: N=2, N=3, N=4
            //
            if (n <= 4)
            {
                spline1dbuildcubic(x, y, n, 0, 0.0, 0, 0.0, c);
                return;
            }

            //
            // Prepare W (weights), Diff (divided differences)
            //
            w    = new double[n - 1];
            diff = new double[n - 1];
            for (i = 0; i <= n - 2; i++)
            {
                diff[i] = (y[i + 1] - y[i]) / (x[i + 1] - x[i]);
            }
            for (i = 1; i <= n - 2; i++)
            {
                w[i] = Math.Abs(diff[i] - diff[i - 1]);
            }

            //
            // Prepare Hermite interpolation scheme
            //
            d = new double[n];
            for (i = 2; i <= n - 3; i++)
            {
                if ((double)(Math.Abs(w[i - 1]) + Math.Abs(w[i + 1])) != (double)(0))
                {
                    d[i] = (w[i + 1] * diff[i - 1] + w[i - 1] * diff[i]) / (w[i + 1] + w[i - 1]);
                }
                else
                {
                    d[i] = ((x[i + 1] - x[i]) * diff[i - 1] + (x[i] - x[i - 1]) * diff[i]) / (x[i + 1] - x[i - 1]);
                }
            }
            d[0]     = diffthreepoint(x[0], x[0], y[0], x[1], y[1], x[2], y[2]);
            d[1]     = diffthreepoint(x[1], x[0], y[0], x[1], y[1], x[2], y[2]);
            d[n - 2] = diffthreepoint(x[n - 2], x[n - 3], y[n - 3], x[n - 2], y[n - 2], x[n - 1], y[n - 1]);
            d[n - 1] = diffthreepoint(x[n - 1], x[n - 3], y[n - 3], x[n - 2], y[n - 2], x[n - 1], y[n - 1]);

            //
            // Build Akima spline using Hermite interpolation scheme
            //
            spline1dbuildhermite(x, y, d, n, c);
        }
Пример #14
0
        /*************************************************************************
        *  This subroutine builds Catmull-Rom spline interpolant.
        *
        *  INPUT PARAMETERS:
        *   X           -   spline nodes, array[0..N-1].
        *   Y           -   function values, array[0..N-1].
        *
        *  OPTIONAL PARAMETERS:
        *   N           -   points count:
        * N>=2
        * if given, only first N points are used to build spline
        * if not given, automatically detected from X/Y sizes
        *                     (len(X) must be equal to len(Y))
        *   BoundType   -   boundary condition type:
        * -1 for periodic boundary condition
        *  0 for parabolically terminated spline (default)
        *   Tension     -   tension parameter:
        * tension=0   corresponds to classic Catmull-Rom spline (default)
        * 0<tension<1 corresponds to more general form - cardinal spline
        *
        *  OUTPUT PARAMETERS:
        *   C           -   spline interpolant
        *
        *
        *  ORDER OF POINTS
        *
        *  Subroutine automatically sorts points, so caller may pass unsorted array.
        *
        *  PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS:
        *
        *  Problems with periodic boundary conditions have Y[first_point]=Y[last_point].
        *  However, this subroutine doesn't require you to specify equal  values  for
        *  the first and last points - it automatically forces them  to  be  equal by
        *  copying  Y[first_point]  (corresponds  to the leftmost,  minimal  X[])  to
        *  Y[last_point]. However it is recommended to pass consistent values of Y[],
        *  i.e. to make Y[first_point]=Y[last_point].
        *
        *  -- ALGLIB PROJECT --
        *    Copyright 23.06.2007 by Bochkanov Sergey
        *************************************************************************/
        public static void spline1dbuildcatmullrom(double[] x,
                                                   double[] y,
                                                   int n,
                                                   int boundtype,
                                                   double tension,
                                                   spline1dinterpolant c)
        {
            double[] d = new double[0];
            int      i = 0;

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

            alglib.ap.assert(n >= 2, "Spline1DBuildCatmullRom: N<2!");
            alglib.ap.assert(boundtype == -1 || boundtype == 0, "Spline1DBuildCatmullRom: incorrect BoundType!");
            alglib.ap.assert((double)(tension) >= (double)(0), "Spline1DBuildCatmullRom: Tension<0!");
            alglib.ap.assert((double)(tension) <= (double)(1), "Spline1DBuildCatmullRom: Tension>1!");
            alglib.ap.assert(alglib.ap.len(x) >= n, "Spline1DBuildCatmullRom: Length(X)<N!");
            alglib.ap.assert(alglib.ap.len(y) >= n, "Spline1DBuildCatmullRom: Length(Y)<N!");

            //
            // check and sort points
            //
            alglib.ap.assert(apserv.isfinitevector(x, n), "Spline1DBuildCatmullRom: X contains infinite or NAN values!");
            alglib.ap.assert(apserv.isfinitevector(y, n), "Spline1DBuildCatmullRom: Y contains infinite or NAN values!");
            heapsortpoints(ref x, ref y, n);
            alglib.ap.assert(apserv.aredistinct(x, n), "Spline1DBuildCatmullRom: at least two consequent points are too close!");

            //
            // Special cases:
            // * N=2, parabolic terminated boundary condition on both ends
            // * N=2, periodic boundary condition
            //
            if (n == 2 && boundtype == 0)
            {
                //
                // Just linear spline
                //
                spline1dbuildlinear(x, y, n, c);
                return;
            }
            if (n == 2 && boundtype == -1)
            {
                //
                // Same as cubic spline with periodic conditions
                //
                spline1dbuildcubic(x, y, n, -1, 0.0, -1, 0.0, c);
                return;
            }

            //
            // Periodic or non-periodic boundary conditions
            //
            if (boundtype == -1)
            {
                //
                // Periodic boundary conditions
                //
                y[n - 1] = y[0];
                d        = new double[n];
                d[0]     = (y[1] - y[n - 2]) / (2 * (x[1] - x[0] + x[n - 1] - x[n - 2]));
                for (i = 1; i <= n - 2; i++)
                {
                    d[i] = (1 - tension) * (y[i + 1] - y[i - 1]) / (x[i + 1] - x[i - 1]);
                }
                d[n - 1] = d[0];

                //
                // Now problem is reduced to the cubic Hermite spline
                //
                spline1dbuildhermite(x, y, d, n, c);
                c.periodic = true;
            }
            else
            {
                //
                // Non-periodic boundary conditions
                //
                d = new double[n];
                for (i = 1; i <= n - 2; i++)
                {
                    d[i] = (1 - tension) * (y[i + 1] - y[i - 1]) / (x[i + 1] - x[i - 1]);
                }
                d[0]     = 2 * (y[1] - y[0]) / (x[1] - x[0]) - d[1];
                d[n - 1] = 2 * (y[n - 1] - y[n - 2]) / (x[n - 1] - x[n - 2]) - d[n - 2];

                //
                // Now problem is reduced to the cubic Hermite spline
                //
                spline1dbuildhermite(x, y, d, n, c);
            }
        }
Пример #15
0
        /*************************************************************************
        This subroutine performs linear transformation of the spline argument.

        INPUT PARAMETERS:
            C   -   spline interpolant.
            A, B-   transformation coefficients: x = A*t + B
        Result:
            C   -   transformed spline

          -- ALGLIB PROJECT --
             Copyright 30.06.2007 by Bochkanov Sergey
        *************************************************************************/
        public static void spline1dlintransx(spline1dinterpolant c,
            double a,
            double b)
        {
            int i = 0;
            int n = 0;
            double v = 0;
            double dv = 0;
            double d2v = 0;
            double[] x = new double[0];
            double[] y = new double[0];
            double[] d = new double[0];
            bool isperiodic = new bool();
            int contval = 0;

            alglib.ap.assert(c.k==3, "Spline1DLinTransX: internal error");
            n = c.n;
            x = new double[n];
            y = new double[n];
            d = new double[n];
            
            //
            // Unpack, X, Y, dY/dX.
            // Scale and pack with Spline1DBuildHermite again.
            //
            if( (double)(a)==(double)(0) )
            {
                
                //
                // Special case: A=0
                //
                v = spline1dcalc(c, b);
                for(i=0; i<=n-1; i++)
                {
                    x[i] = c.x[i];
                    y[i] = v;
                    d[i] = 0.0;
                }
            }
            else
            {
                
                //
                // General case, A<>0
                //
                for(i=0; i<=n-1; i++)
                {
                    x[i] = c.x[i];
                    spline1ddiff(c, x[i], ref v, ref dv, ref d2v);
                    x[i] = (x[i]-b)/a;
                    y[i] = v;
                    d[i] = a*dv;
                }
            }
            isperiodic = c.periodic;
            contval = c.continuity;
            if( contval>0 )
            {
                spline1dbuildhermite(x, y, d, n, c);
            }
            else
            {
                spline1dbuildlinear(x, y, n, c);
            }
            c.periodic = isperiodic;
            c.continuity = contval;
        }
Пример #16
0
        /*************************************************************************
        This subroutine integrates the spline.

        INPUT PARAMETERS:
            C   -   spline interpolant.
            X   -   right bound of the integration interval [a, x],
                    here 'a' denotes min(x[])
        Result:
            integral(S(t)dt,a,x)

          -- ALGLIB PROJECT --
             Copyright 23.06.2007 by Bochkanov Sergey
        *************************************************************************/
        public static double spline1dintegrate(spline1dinterpolant c,
            double x)
        {
            double result = 0;
            int n = 0;
            int i = 0;
            int j = 0;
            int l = 0;
            int r = 0;
            int m = 0;
            double w = 0;
            double v = 0;
            double t = 0;
            double intab = 0;
            double additionalterm = 0;

            n = c.n;
            
            //
            // Periodic splines require special treatment. We make
            // following transformation:
            //
            //     integral(S(t)dt,A,X) = integral(S(t)dt,A,Z)+AdditionalTerm
            //
            // here X may lie outside of [A,B], Z lies strictly in [A,B],
            // AdditionalTerm is equals to integral(S(t)dt,A,B) times some
            // integer number (may be zero).
            //
            if( c.periodic && ((double)(x)<(double)(c.x[0]) || (double)(x)>(double)(c.x[c.n-1])) )
            {
                
                //
                // compute integral(S(x)dx,A,B)
                //
                intab = 0;
                for(i=0; i<=c.n-2; i++)
                {
                    w = c.x[i+1]-c.x[i];
                    m = (c.k+1)*i;
                    intab = intab+c.c[m]*w;
                    v = w;
                    for(j=1; j<=c.k; j++)
                    {
                        v = v*w;
                        intab = intab+c.c[m+j]*v/(j+1);
                    }
                }
                
                //
                // map X into [A,B]
                //
                apserv.apperiodicmap(ref x, c.x[0], c.x[c.n-1], ref t);
                additionalterm = t*intab;
            }
            else
            {
                additionalterm = 0;
            }
            
            //
            // Binary search in the [ x[0], ..., x[n-2] ] (x[n-1] is not included)
            //
            l = 0;
            r = n-2+1;
            while( l!=r-1 )
            {
                m = (l+r)/2;
                if( (double)(c.x[m])>=(double)(x) )
                {
                    r = m;
                }
                else
                {
                    l = m;
                }
            }
            
            //
            // Integration
            //
            result = 0;
            for(i=0; i<=l-1; i++)
            {
                w = c.x[i+1]-c.x[i];
                m = (c.k+1)*i;
                result = result+c.c[m]*w;
                v = w;
                for(j=1; j<=c.k; j++)
                {
                    v = v*w;
                    result = result+c.c[m+j]*v/(j+1);
                }
            }
            w = x-c.x[l];
            m = (c.k+1)*l;
            v = w;
            result = result+c.c[m]*w;
            for(j=1; j<=c.k; j++)
            {
                v = v*w;
                result = result+c.c[m+j]*v/(j+1);
            }
            result = result+additionalterm;
            return result;
        }
Пример #17
0
        /*************************************************************************
        *  This subroutine integrates the spline.
        *
        *  INPUT PARAMETERS:
        *   C   -   spline interpolant.
        *   X   -   правая граница интервала интегрирования [a, x],
        *           здесь 'a' обозначает min(x[])
        *  Result:
        *   integral(S(t)dt,a,x)
        *
        *  -- ALGLIB PROJECT --
        *    Copyright 23.06.2007 by Bochkanov Sergey
        *************************************************************************/
        public static double spline1dintegrate(spline1dinterpolant c, double x)
        {
            double result         = 0;
            int    n              = 0;
            int    i              = 0;
            int    j              = 0;
            int    l              = 0;
            int    r              = 0;
            int    m              = 0;
            double w              = 0;
            double v              = 0;
            double t              = 0;
            double intab          = 0;
            double additionalterm = 0;

            n = c.n;

            //
            // Periodic splines require special treatment. We make
            // following transformation:
            //
            //     integral(S(t)dt,A,X) = integral(S(t)dt,A,Z)+AdditionalTerm
            //
            // here X may lie outside of [A,B], Z lies strictly in [A,B],
            // AdditionalTerm is equals to integral(S(t)dt,A,B) times some
            // integer number (may be zero).
            //
            if (c.periodic && ((double)(x) < (double)(c.x[0]) || (double)(x) > (double)(c.x[c.n - 1])))
            {
                //
                // compute integral(S(x)dx,A,B)
                //
                intab = 0;
                for (i = 0; i <= c.n - 2; i++)
                {
                    w     = c.x[i + 1] - c.x[i];
                    m     = (c.k + 1) * i;
                    intab = intab + c.c[m] * w;
                    v     = w;
                    for (j = 1; j <= c.k; j++)
                    {
                        v     = v * w;
                        intab = intab + c.c[m + j] * v / (j + 1);
                    }
                }

                //
                // map X into [A,B]
                //
                apserv.apperiodicmap(ref x, c.x[0], c.x[c.n - 1], ref t);
                additionalterm = t * intab;
            }
            else
            {
                additionalterm = 0;
            }

            //
            // Binary search in the [ x[0], ..., x[n-2] ] (x[n-1] is not included)
            //
            l = 0;
            r = n - 2 + 1;
            while (l != r - 1)
            {
                m = (l + r) / 2;
                if ((double)(c.x[m]) >= (double)(x))
                {
                    r = m;
                }
                else
                {
                    l = m;
                }
            }

            //
            // Integration
            //
            result = 0;
            for (i = 0; i <= l - 1; i++)
            {
                w      = c.x[i + 1] - c.x[i];
                m      = (c.k + 1) * i;
                result = result + c.c[m] * w;
                v      = w;
                for (j = 1; j <= c.k; j++)
                {
                    v      = v * w;
                    result = result + c.c[m + j] * v / (j + 1);
                }
            }
            w      = x - c.x[l];
            m      = (c.k + 1) * l;
            v      = w;
            result = result + c.c[m] * w;
            for (j = 1; j <= c.k; j++)
            {
                v      = v * w;
                result = result + c.c[m + j] * v / (j + 1);
            }
            result = result + additionalterm;
            return(result);
        }
Пример #18
0
        /*************************************************************************
        This subroutine builds linear spline interpolant

        INPUT PARAMETERS:
            X   -   spline nodes, array[0..N-1]
            Y   -   function values, array[0..N-1]
            N   -   points count (optional):
                    * N>=2
                    * if given, only first N points are used to build spline
                    * if not given, automatically detected from X/Y sizes
                      (len(X) must be equal to len(Y))
            
        OUTPUT PARAMETERS:
            C   -   spline interpolant


        ORDER OF POINTS

        Subroutine automatically sorts points, so caller may pass unsorted array.

          -- ALGLIB PROJECT --
             Copyright 24.06.2007 by Bochkanov Sergey
        *************************************************************************/
        public static void spline1dbuildlinear(double[] x,
            double[] y,
            int n,
            spline1dinterpolant c)
        {
            int i = 0;

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

            alglib.ap.assert(n>1, "Spline1DBuildLinear: N<2!");
            alglib.ap.assert(alglib.ap.len(x)>=n, "Spline1DBuildLinear: Length(X)<N!");
            alglib.ap.assert(alglib.ap.len(y)>=n, "Spline1DBuildLinear: Length(Y)<N!");
            
            //
            // check and sort points
            //
            alglib.ap.assert(apserv.isfinitevector(x, n), "Spline1DBuildLinear: X contains infinite or NAN values!");
            alglib.ap.assert(apserv.isfinitevector(y, n), "Spline1DBuildLinear: Y contains infinite or NAN values!");
            heapsortpoints(ref x, ref y, n);
            alglib.ap.assert(apserv.aredistinct(x, n), "Spline1DBuildLinear: at least two consequent points are too close!");
            
            //
            // Build
            //
            c.periodic = false;
            c.n = n;
            c.k = 3;
            c.continuity = 0;
            c.x = new double[n];
            c.c = new double[4*(n-1)+2];
            for(i=0; i<=n-1; i++)
            {
                c.x[i] = x[i];
            }
            for(i=0; i<=n-2; i++)
            {
                c.c[4*i+0] = y[i];
                c.c[4*i+1] = (y[i+1]-y[i])/(x[i+1]-x[i]);
                c.c[4*i+2] = 0;
                c.c[4*i+3] = 0;
            }
            c.c[4*(n-1)+0] = y[n-1];
            c.c[4*(n-1)+1] = c.c[4*(n-2)+1];
        }
Пример #19
0
        /*************************************************************************
        This subroutine builds Catmull-Rom spline interpolant.

        INPUT PARAMETERS:
            X           -   spline nodes, array[0..N-1].
            Y           -   function values, array[0..N-1].
            N           -   points count, N>=2
            BoundType   -   boundary condition type:
                            * -1 for periodic boundary condition
                            *  0 for parabolically terminated spline
            Tension     -   tension parameter:
                            * tension=0   corresponds to classic Catmull-Rom spline
                            * 0<tension<1 corresponds to more general form - cardinal spline

        OUTPUT PARAMETERS:
            C           -   spline interpolant


        ORDER OF POINTS

        Subroutine automatically sorts points, so caller may pass unsorted array.

        PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS:

        Problems with periodic boundary conditions have Y[first_point]=Y[last_point].
        However, this subroutine doesn't require you to specify equal  values  for
        the first and last points - it automatically forces them to be equal.

          -- ALGLIB PROJECT --
             Copyright 23.06.2007 by Bochkanov Sergey
        *************************************************************************/
        public static void spline1dbuildcatmullrom(double[] x,
            double[] y,
            int n,
            int boundtype,
            double tension,
            ref spline1dinterpolant c)
        {
            double[] a1 = new double[0];
            double[] a2 = new double[0];
            double[] a3 = new double[0];
            double[] b = new double[0];
            double[] d = new double[0];
            double[] dt = new double[0];
            int i = 0;
            double v = 0;

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

            System.Diagnostics.Debug.Assert(n>=2, "Spline1DBuildCatmullRom: N<2!");
            System.Diagnostics.Debug.Assert(boundtype==-1 | boundtype==0, "Spline1DBuildCatmullRom: incorrect BoundType!");
            
            //
            // Special cases:
            // * N=2, parabolic terminated boundary condition on both ends
            // * N=2, periodic boundary condition
            //
            if( n==2 & boundtype==0 )
            {
                
                //
                // Just linear spline
                //
                spline1dbuildlinear(x, y, n, ref c);
                return;
            }
            if( n==2 & boundtype==-1 )
            {
                
                //
                // Same as cubic spline with periodic conditions
                //
                spline1dbuildcubic(x, y, n, -1, 0.0, -1, 0.0, ref c);
                return;
            }
            
            //
            // Periodic or non-periodic boundary conditions
            //
            if( boundtype==-1 )
            {
                
                //
                // Sort points.
                //
                heapsortpoints(ref x, ref y, n);
                y[n-1] = y[0];
                
                //
                // Periodic boundary conditions
                //
                d = new double[n];
                d[0] = (y[1]-y[n-2])/(2*(x[1]-x[0]+x[n-1]-x[n-2]));
                for(i=1; i<=n-2; i++)
                {
                    d[i] = (1-tension)*(y[i+1]-y[i-1])/(x[i+1]-x[i-1]);
                }
                d[n-1] = d[0];
                
                //
                // Now problem is reduced to the cubic Hermite spline
                //
                spline1dbuildhermite(x, y, d, n, ref c);
                c.periodic = true;
            }
            else
            {
                
                //
                // Sort points.
                //
                heapsortpoints(ref x, ref y, n);
                
                //
                // Non-periodic boundary conditions
                //
                d = new double[n];
                for(i=1; i<=n-2; i++)
                {
                    d[i] = (1-tension)*(y[i+1]-y[i-1])/(x[i+1]-x[i-1]);
                }
                d[0] = 2*(y[1]-y[0])/(x[1]-x[0])-d[1];
                d[n-1] = 2*(y[n-1]-y[n-2])/(x[n-1]-x[n-2])-d[n-2];
                
                //
                // Now problem is reduced to the cubic Hermite spline
                //
                spline1dbuildhermite(x, y, d, n, ref c);
            }
        }
Пример #20
0
    public static void spline1dfithermite(double[] x, double[] y, int m, out int info, out spline1dinterpolant s, out spline1dfitreport rep)
    {
        int n;
        if( (ap.len(x)!=ap.len(y)))
            throw new alglibexception("Error while calling 'spline1dfithermite': looks like one of arguments has wrong size");
        info = 0;
        s = new spline1dinterpolant();
        rep = new spline1dfitreport();
        n = ap.len(x);
        lsfit.spline1dfithermite(x, y, n, m, ref info, s.innerobj, rep.innerobj);

        return;
    }
Пример #21
0
        /*************************************************************************
        This subroutine builds Hermite spline interpolant.

        INPUT PARAMETERS:
            X           -   spline nodes, array[0..N-1]
            Y           -   function values, array[0..N-1]
            D           -   derivatives, array[0..N-1]
            N           -   points count, N>=2

        OUTPUT PARAMETERS:
            C           -   spline interpolant.


        ORDER OF POINTS

        Subroutine automatically sorts points, so caller may pass unsorted array.

          -- ALGLIB PROJECT --
             Copyright 23.06.2007 by Bochkanov Sergey
        *************************************************************************/
        public static void spline1dbuildhermite(double[] x,
            double[] y,
            double[] d,
            int n,
            ref spline1dinterpolant c)
        {
            int i = 0;
            double delta = 0;
            double delta2 = 0;
            double delta3 = 0;

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

            System.Diagnostics.Debug.Assert(n>=2, "BuildHermiteSpline: N<2!");
            
            //
            // Sort points
            //
            heapsortdpoints(ref x, ref y, ref d, n);
            
            //
            // Build
            //
            c.x = new double[n];
            c.c = new double[4*(n-1)];
            c.periodic = false;
            c.k = 3;
            c.n = n;
            for(i=0; i<=n-1; i++)
            {
                c.x[i] = x[i];
            }
            for(i=0; i<=n-2; i++)
            {
                delta = x[i+1]-x[i];
                delta2 = AP.Math.Sqr(delta);
                delta3 = delta*delta2;
                c.c[4*i+0] = y[i];
                c.c[4*i+1] = d[i];
                c.c[4*i+2] = (3*(y[i+1]-y[i])-2*d[i]*delta-d[i+1]*delta)/delta2;
                c.c[4*i+3] = (2*(y[i]-y[i+1])+d[i]*delta+d[i+1]*delta)/delta3;
            }
        }
Пример #22
0
            /*************************************************************************
            This subroutine performs linear transformation of the spline argument.

            INPUT PARAMETERS:
                C   -   spline interpolant.
                A, B-   transformation coefficients: x = A*t + B
            Result:
                C   -   transformed spline

              -- ALGLIB PROJECT --
                 Copyright 30.06.2007 by Bochkanov Sergey
            *************************************************************************/
            public static void spline1dlintransx(spline1dinterpolant c,
                double a,
                double b) {
                int i = 0;
                int j = 0;
                int n = 0;
                double v = 0;
                double dv = 0;
                double d2v = 0;
                double[] x = new double[0];
                double[] y = new double[0];
                double[] d = new double[0];

                n = c.n;

                //
                // Special case: A=0
                //
                if((double)(a) == (double)(0)) {
                    v = spline1dcalc(c, b);
                    for(i = 0; i <= n - 2; i++) {
                        c.c[(c.k + 1) * i] = v;
                        for(j = 1; j <= c.k; j++) {
                            c.c[(c.k + 1) * i + j] = 0;
                        }
                    }
                    return;
                }

                //
                // General case: A<>0.
                // Unpack, X, Y, dY/dX.
                // Scale and pack again.
                //
                ap.assert(c.k == 3, "Spline1DLinTransX: internal error");
                x = new double[n - 1 + 1];
                y = new double[n - 1 + 1];
                d = new double[n - 1 + 1];
                for(i = 0; i <= n - 1; i++) {
                    x[i] = c.x[i];
                    spline1ddiff(c, x[i], ref v, ref dv, ref d2v);
                    x[i] = (x[i] - b) / a;
                    y[i] = v;
                    d[i] = a * dv;
                }
                spline1dbuildhermite(x, y, d, n, c);
            }
Пример #23
0
        /*************************************************************************
        This subroutine builds Akima spline interpolant

        INPUT PARAMETERS:
            X           -   spline nodes, array[0..N-1]
            Y           -   function values, array[0..N-1]
            N           -   points count, N>=5

        OUTPUT PARAMETERS:
            C           -   spline interpolant


        ORDER OF POINTS

        Subroutine automatically sorts points, so caller may pass unsorted array.

          -- ALGLIB PROJECT --
             Copyright 24.06.2007 by Bochkanov Sergey
        *************************************************************************/
        public static void spline1dbuildakima(double[] x,
            double[] y,
            int n,
            ref spline1dinterpolant c)
        {
            int i = 0;
            double[] d = new double[0];
            double[] w = new double[0];
            double[] diff = new double[0];

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

            System.Diagnostics.Debug.Assert(n>=5, "BuildAkimaSpline: N<5!");
            
            //
            // Sort points
            //
            heapsortpoints(ref x, ref y, n);
            
            //
            // Prepare W (weights), Diff (divided differences)
            //
            w = new double[n-1];
            diff = new double[n-1];
            for(i=0; i<=n-2; i++)
            {
                diff[i] = (y[i+1]-y[i])/(x[i+1]-x[i]);
            }
            for(i=1; i<=n-2; i++)
            {
                w[i] = Math.Abs(diff[i]-diff[i-1]);
            }
            
            //
            // Prepare Hermite interpolation scheme
            //
            d = new double[n];
            for(i=2; i<=n-3; i++)
            {
                if( (double)(Math.Abs(w[i-1])+Math.Abs(w[i+1]))!=(double)(0) )
                {
                    d[i] = (w[i+1]*diff[i-1]+w[i-1]*diff[i])/(w[i+1]+w[i-1]);
                }
                else
                {
                    d[i] = ((x[i+1]-x[i])*diff[i-1]+(x[i]-x[i-1])*diff[i])/(x[i+1]-x[i-1]);
                }
            }
            d[0] = diffthreepoint(x[0], x[0], y[0], x[1], y[1], x[2], y[2]);
            d[1] = diffthreepoint(x[1], x[0], y[0], x[1], y[1], x[2], y[2]);
            d[n-2] = diffthreepoint(x[n-2], x[n-3], y[n-3], x[n-2], y[n-2], x[n-1], y[n-1]);
            d[n-1] = diffthreepoint(x[n-1], x[n-3], y[n-3], x[n-2], y[n-2], x[n-1], y[n-1]);
            
            //
            // Build Akima spline using Hermite interpolation scheme
            //
            spline1dbuildhermite(x, y, d, n, ref c);
        }
Пример #24
0
        /*************************************************************************
        This subroutine builds Catmull-Rom spline interpolant.

        INPUT PARAMETERS:
            X           -   spline nodes, array[0..N-1].
            Y           -   function values, array[0..N-1].
            
        OPTIONAL PARAMETERS:
            N           -   points count:
                            * N>=2
                            * if given, only first N points are used to build spline
                            * if not given, automatically detected from X/Y sizes
                              (len(X) must be equal to len(Y))
            BoundType   -   boundary condition type:
                            * -1 for periodic boundary condition
                            *  0 for parabolically terminated spline (default)
            Tension     -   tension parameter:
                            * tension=0   corresponds to classic Catmull-Rom spline (default)
                            * 0<tension<1 corresponds to more general form - cardinal spline

        OUTPUT PARAMETERS:
            C           -   spline interpolant


        ORDER OF POINTS

        Subroutine automatically sorts points, so caller may pass unsorted array.

        PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS:

        Problems with periodic boundary conditions have Y[first_point]=Y[last_point].
        However, this subroutine doesn't require you to specify equal  values  for
        the first and last points - it automatically forces them  to  be  equal by
        copying  Y[first_point]  (corresponds  to the leftmost,  minimal  X[])  to
        Y[last_point]. However it is recommended to pass consistent values of Y[],
        i.e. to make Y[first_point]=Y[last_point].

          -- ALGLIB PROJECT --
             Copyright 23.06.2007 by Bochkanov Sergey
        *************************************************************************/
        public static void spline1dbuildcatmullrom(double[] x,
            double[] y,
            int n,
            int boundtype,
            double tension,
            spline1dinterpolant c)
        {
            double[] d = new double[0];
            int i = 0;

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

            alglib.ap.assert(n>=2, "Spline1DBuildCatmullRom: N<2!");
            alglib.ap.assert(boundtype==-1 || boundtype==0, "Spline1DBuildCatmullRom: incorrect BoundType!");
            alglib.ap.assert((double)(tension)>=(double)(0), "Spline1DBuildCatmullRom: Tension<0!");
            alglib.ap.assert((double)(tension)<=(double)(1), "Spline1DBuildCatmullRom: Tension>1!");
            alglib.ap.assert(alglib.ap.len(x)>=n, "Spline1DBuildCatmullRom: Length(X)<N!");
            alglib.ap.assert(alglib.ap.len(y)>=n, "Spline1DBuildCatmullRom: Length(Y)<N!");
            
            //
            // check and sort points
            //
            alglib.ap.assert(apserv.isfinitevector(x, n), "Spline1DBuildCatmullRom: X contains infinite or NAN values!");
            alglib.ap.assert(apserv.isfinitevector(y, n), "Spline1DBuildCatmullRom: Y contains infinite or NAN values!");
            heapsortpoints(ref x, ref y, n);
            alglib.ap.assert(apserv.aredistinct(x, n), "Spline1DBuildCatmullRom: at least two consequent points are too close!");
            
            //
            // Special cases:
            // * N=2, parabolic terminated boundary condition on both ends
            // * N=2, periodic boundary condition
            //
            if( n==2 && boundtype==0 )
            {
                
                //
                // Just linear spline
                //
                spline1dbuildlinear(x, y, n, c);
                return;
            }
            if( n==2 && boundtype==-1 )
            {
                
                //
                // Same as cubic spline with periodic conditions
                //
                spline1dbuildcubic(x, y, n, -1, 0.0, -1, 0.0, c);
                return;
            }
            
            //
            // Periodic or non-periodic boundary conditions
            //
            if( boundtype==-1 )
            {
                
                //
                // Periodic boundary conditions
                //
                y[n-1] = y[0];
                d = new double[n];
                d[0] = (y[1]-y[n-2])/(2*(x[1]-x[0]+x[n-1]-x[n-2]));
                for(i=1; i<=n-2; i++)
                {
                    d[i] = (1-tension)*(y[i+1]-y[i-1])/(x[i+1]-x[i-1]);
                }
                d[n-1] = d[0];
                
                //
                // Now problem is reduced to the cubic Hermite spline
                //
                spline1dbuildhermite(x, y, d, n, c);
                c.periodic = true;
            }
            else
            {
                
                //
                // Non-periodic boundary conditions
                //
                d = new double[n];
                for(i=1; i<=n-2; i++)
                {
                    d[i] = (1-tension)*(y[i+1]-y[i-1])/(x[i+1]-x[i-1]);
                }
                d[0] = 2*(y[1]-y[0])/(x[1]-x[0])-d[1];
                d[n-1] = 2*(y[n-1]-y[n-2])/(x[n-1]-x[n-2])-d[n-2];
                
                //
                // Now problem is reduced to the cubic Hermite spline
                //
                spline1dbuildhermite(x, y, d, n, c);
            }
        }
Пример #25
0
        /*************************************************************************
        Weighted  fitting  by Hermite spline,  with constraints on function values
        or first derivatives.

        Equidistant grid with M nodes on [min(x,xc),max(x,xc)] is  used  to  build
        basis functions. Basis functions are Hermite splines.  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
            Spline1DFitCubicWC()    -   fitting by Cubic splines (less flexible,
                                        more smooth)
            Spline1DFitHermite()    -   "lightweight" Hermite 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 spline 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 (= 2 * number of nodes),
                    M>=4,
                    M IS EVEN!

        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
                                -2 means odd M was passed (which is not supported)
                                -1 means another errors in parameters passed
                                   (N<=0, for example)
            S   -   spline interpolant.
            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.

        IMPORTANT:
            this subroitine supports only even M's


        ORDER OF POINTS

        Subroutine automatically sorts points, so caller may pass unsorted array.

        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:
        * excessive constraints can be inconsistent. Splines are  piecewise  cubic
          functions, and it is easy to create an example, where  large  number  of
          constraints  concentrated  in  small  area will result in inconsistency.
          Just because spline is not flexible enough to satisfy all of  them.  And
          same constraints spread across the  [min(x),max(x)]  will  be  perfectly
          consistent.
        * 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  M>=4  and   constraints  on   the  function  value
          (AND/OR its derivative) at the interval boundaries.
        * another special case is M>=4  and  ONE  constraint on the function value
          (OR, BUT NOT AND, derivative) anywhere in [min(x),max(x)]

        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 spline1dfithermitewc(ref double[] x,
            ref double[] y,
            ref double[] w,
            int n,
            ref double[] xc,
            ref double[] yc,
            ref int[] dc,
            int k,
            int m,
            ref int info,
            ref spline1dinterpolant s,
            ref spline1dfitreport rep)
        {
            spline1dfitinternal(1, x, y, ref w, n, xc, yc, ref dc, k, m, ref info, ref s, ref rep);
        }
Пример #26
0
        /*************************************************************************
        This subroutine builds Akima spline interpolant

        INPUT PARAMETERS:
            X           -   spline nodes, array[0..N-1]
            Y           -   function values, array[0..N-1]
            N           -   points count (optional):
                            * N>=2
                            * if given, only first N points are used to build spline
                            * if not given, automatically detected from X/Y sizes
                              (len(X) must be equal to len(Y))

        OUTPUT PARAMETERS:
            C           -   spline interpolant


        ORDER OF POINTS

        Subroutine automatically sorts points, so caller may pass unsorted array.

          -- ALGLIB PROJECT --
             Copyright 24.06.2007 by Bochkanov Sergey
        *************************************************************************/
        public static void spline1dbuildakima(double[] x,
            double[] y,
            int n,
            spline1dinterpolant c)
        {
            int i = 0;
            double[] d = new double[0];
            double[] w = new double[0];
            double[] diff = new double[0];

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

            alglib.ap.assert(n>=2, "Spline1DBuildAkima: N<2!");
            alglib.ap.assert(alglib.ap.len(x)>=n, "Spline1DBuildAkima: Length(X)<N!");
            alglib.ap.assert(alglib.ap.len(y)>=n, "Spline1DBuildAkima: Length(Y)<N!");
            
            //
            // check and sort points
            //
            alglib.ap.assert(apserv.isfinitevector(x, n), "Spline1DBuildAkima: X contains infinite or NAN values!");
            alglib.ap.assert(apserv.isfinitevector(y, n), "Spline1DBuildAkima: Y contains infinite or NAN values!");
            heapsortpoints(ref x, ref y, n);
            alglib.ap.assert(apserv.aredistinct(x, n), "Spline1DBuildAkima: at least two consequent points are too close!");
            
            //
            // Handle special cases: N=2, N=3, N=4
            //
            if( n<=4 )
            {
                spline1dbuildcubic(x, y, n, 0, 0.0, 0, 0.0, c);
                return;
            }
            
            //
            // Prepare W (weights), Diff (divided differences)
            //
            w = new double[n-1];
            diff = new double[n-1];
            for(i=0; i<=n-2; i++)
            {
                diff[i] = (y[i+1]-y[i])/(x[i+1]-x[i]);
            }
            for(i=1; i<=n-2; i++)
            {
                w[i] = Math.Abs(diff[i]-diff[i-1]);
            }
            
            //
            // Prepare Hermite interpolation scheme
            //
            d = new double[n];
            for(i=2; i<=n-3; i++)
            {
                if( (double)(Math.Abs(w[i-1])+Math.Abs(w[i+1]))!=(double)(0) )
                {
                    d[i] = (w[i+1]*diff[i-1]+w[i-1]*diff[i])/(w[i+1]+w[i-1]);
                }
                else
                {
                    d[i] = ((x[i+1]-x[i])*diff[i-1]+(x[i]-x[i-1])*diff[i])/(x[i+1]-x[i-1]);
                }
            }
            d[0] = diffthreepoint(x[0], x[0], y[0], x[1], y[1], x[2], y[2]);
            d[1] = diffthreepoint(x[1], x[0], y[0], x[1], y[1], x[2], y[2]);
            d[n-2] = diffthreepoint(x[n-2], x[n-3], y[n-3], x[n-2], y[n-2], x[n-1], y[n-1]);
            d[n-1] = diffthreepoint(x[n-1], x[n-3], y[n-3], x[n-2], y[n-2], x[n-1], y[n-1]);
            
            //
            // Build Akima spline using Hermite interpolation scheme
            //
            spline1dbuildhermite(x, y, d, n, c);
        }
Пример #27
0
        /*************************************************************************
        Least squares fitting by Hermite spline.

        This subroutine is "lightweight" alternative for more complex and feature-
        rich Spline1DFitHermiteWC().  See Spline1DFitHermiteWC()  description  for
        more information about subroutine parameters (we don't duplicate  it  here
        because of length).

          -- ALGLIB PROJECT --
             Copyright 18.08.2009 by Bochkanov Sergey
        *************************************************************************/
        public static void spline1dfithermite(ref double[] x,
            ref double[] y,
            int n,
            int m,
            ref int info,
            ref spline1dinterpolant s,
            ref spline1dfitreport rep)
        {
            int i = 0;
            double[] w = new double[0];
            double[] xc = new double[0];
            double[] yc = new double[0];
            int[] dc = new int[0];

            if( n>0 )
            {
                w = new double[n];
                for(i=0; i<=n-1; i++)
                {
                    w[i] = 1;
                }
            }
            spline1dfithermitewc(ref x, ref y, ref w, n, ref xc, ref yc, ref dc, 0, m, ref info, ref s, ref rep);
        }
Пример #28
0
        /*************************************************************************
        This subroutine differentiates the spline.

        INPUT PARAMETERS:
            C   -   spline interpolant.
            X   -   point

        Result:
            S   -   S(x)
            DS  -   S'(x)
            D2S -   S''(x)

          -- ALGLIB PROJECT --
             Copyright 24.06.2007 by Bochkanov Sergey
        *************************************************************************/
        public static void spline1ddiff(spline1dinterpolant c,
            double x,
            ref double s,
            ref double ds,
            ref double d2s)
        {
            int l = 0;
            int r = 0;
            int m = 0;
            double t = 0;

            s = 0;
            ds = 0;
            d2s = 0;

            alglib.ap.assert(c.k==3, "Spline1DDiff: internal error");
            alglib.ap.assert(!Double.IsInfinity(x), "Spline1DDiff: infinite X!");
            
            //
            // special case: NaN
            //
            if( Double.IsNaN(x) )
            {
                s = Double.NaN;
                ds = Double.NaN;
                d2s = Double.NaN;
                return;
            }
            
            //
            // correct if periodic
            //
            if( c.periodic )
            {
                apserv.apperiodicmap(ref x, c.x[0], c.x[c.n-1], ref t);
            }
            
            //
            // Binary search
            //
            l = 0;
            r = c.n-2+1;
            while( l!=r-1 )
            {
                m = (l+r)/2;
                if( c.x[m]>=x )
                {
                    r = m;
                }
                else
                {
                    l = m;
                }
            }
            
            //
            // Differentiation
            //
            x = x-c.x[l];
            m = 4*l;
            s = c.c[m]+x*(c.c[m+1]+x*(c.c[m+2]+x*c.c[m+3]));
            ds = c.c[m+1]+2*x*c.c[m+2]+3*math.sqr(x)*c.c[m+3];
            d2s = 2*c.c[m+2]+6*x*c.c[m+3];
        }
Пример #29
0
        /*************************************************************************
        This subroutine calculates the value of the spline at the given point X.

        INPUT PARAMETERS:
            C   -   spline interpolant
            X   -   point

        Result:
            S(x)

          -- ALGLIB PROJECT --
             Copyright 23.06.2007 by Bochkanov Sergey
        *************************************************************************/
        public static double spline1dcalc(ref spline1dinterpolant c,
            double x)
        {
            double result = 0;
            int l = 0;
            int r = 0;
            int m = 0;
            double t = 0;

            System.Diagnostics.Debug.Assert(c.k==3, "Spline1DCalc: internal error");
            
            //
            // correct if periodic
            //
            if( c.periodic )
            {
                apserv.apperiodicmap(ref x, c.x[0], c.x[c.n-1], ref t);
            }
            
            //
            // Binary search in the [ x[0], ..., x[n-2] ] (x[n-1] is not included)
            //
            l = 0;
            r = c.n-2+1;
            while( l!=r-1 )
            {
                m = (l+r)/2;
                if( (double)(c.x[m])>=(double)(x) )
                {
                    r = m;
                }
                else
                {
                    l = m;
                }
            }
            
            //
            // Interpolation
            //
            x = x-c.x[l];
            m = 4*l;
            result = c.c[m]+x*(c.c[m+1]+x*(c.c[m+2]+x*c.c[m+3]));
            return result;
        }
Пример #30
0
        /*************************************************************************
        This subroutine unpacks the spline into the coefficients table.

        INPUT PARAMETERS:
            C   -   spline interpolant.
            X   -   point

        OUTPUT PARAMETERS:
            Tbl -   coefficients table, unpacked format, array[0..N-2, 0..5].
                    For I = 0...N-2:
                        Tbl[I,0] = X[i]
                        Tbl[I,1] = X[i+1]
                        Tbl[I,2] = C0
                        Tbl[I,3] = C1
                        Tbl[I,4] = C2
                        Tbl[I,5] = C3
                    On [x[i], x[i+1]] spline is equals to:
                        S(x) = C0 + C1*t + C2*t^2 + C3*t^3
                        t = x-x[i]
                        
        NOTE:
            You  can rebuild spline with  Spline1DBuildHermite()  function,  which
            accepts as inputs function values and derivatives at nodes, which  are
            easy to calculate when you have coefficients.

          -- ALGLIB PROJECT --
             Copyright 29.06.2007 by Bochkanov Sergey
        *************************************************************************/
        public static void spline1dunpack(spline1dinterpolant c,
            ref int n,
            ref double[,] tbl)
        {
            int i = 0;
            int j = 0;

            n = 0;
            tbl = new double[0,0];

            tbl = new double[c.n-2+1, 2+c.k+1];
            n = c.n;
            
            //
            // Fill
            //
            for(i=0; i<=n-2; i++)
            {
                tbl[i,0] = c.x[i];
                tbl[i,1] = c.x[i+1];
                for(j=0; j<=c.k; j++)
                {
                    tbl[i,2+j] = c.c[(c.k+1)*i+j];
                }
            }
        }
Пример #31
0
    /*************************************************************************
    Weighted fitting by penalized cubic spline.

    Equidistant grid with M nodes on [min(x,xc),max(x,xc)] is  used  to  build
    basis functions. Basis functions are cubic splines with  natural  boundary
    conditions. Problem is regularized by  adding non-linearity penalty to the
    usual least squares penalty function:

        S(x) = arg min { LS + P }, where
        LS   = SUM { w[i]^2*(y[i] - S(x[i]))^2 } - least squares penalty
        P    = C*10^rho*integral{ S''(x)^2*dx } - non-linearity penalty
        rho  - tunable constant given by user
        C    - automatically determined scale parameter,
               makes penalty invariant with respect to scaling of X, Y, W.

    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
                problem.
        N   -   number of points (optional):
                * N>0
                * if given, only first N elements of X/Y/W are processed
                * if not given, automatically determined from X/Y/W sizes
        M   -   number of basis functions ( = number_of_nodes), M>=4.
        Rho -   regularization  constant  passed   by   user.   It   penalizes
                nonlinearity in the regression spline. It  is  logarithmically
                scaled,  i.e.  actual  value  of  regularization  constant  is
                calculated as 10^Rho. It is automatically scaled so that:
                * Rho=2.0 corresponds to moderate amount of nonlinearity
                * generally, it should be somewhere in the [-8.0,+8.0]
                If you do not want to penalize nonlineary,
                pass small Rho. Values as low as -15 should work.

    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 or
                               Cholesky decomposition; problem may be
                               too ill-conditioned (very rare)
        S   -   spline interpolant.
        Rep -   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.

    NOTE 1: additional nodes are added to the spline outside  of  the  fitting
    interval to force linearity when x<min(x,xc) or x>max(x,xc).  It  is  done
    for consistency - we penalize non-linearity  at [min(x,xc),max(x,xc)],  so
    it is natural to force linearity outside of this interval.

    NOTE 2: function automatically sorts points,  so  caller may pass unsorted
    array.

      -- ALGLIB PROJECT --
         Copyright 19.10.2010 by Bochkanov Sergey
    *************************************************************************/
    public static void spline1dfitpenalizedw(double[] x, double[] y, double[] w, int n, int m, double rho, out int info, out spline1dinterpolant s, out spline1dfitreport rep)
    {
        info = 0;
        s = new spline1dinterpolant();
        rep = new spline1dfitreport();
        lsfit.spline1dfitpenalizedw(x, y, w, n, m, rho, ref info, s.innerobj, rep.innerobj);
        return;
    }
Пример #32
0
        /*************************************************************************
        This subroutine performs linear transformation of the spline.

        INPUT PARAMETERS:
            C   -   spline interpolant.
            A, B-   transformation coefficients: S2(x) = A*S(x) + B
        Result:
            C   -   transformed spline

          -- ALGLIB PROJECT --
             Copyright 30.06.2007 by Bochkanov Sergey
        *************************************************************************/
        public static void spline1dlintransy(spline1dinterpolant c,
            double a,
            double b)
        {
            int i = 0;
            int j = 0;
            int n = 0;

            alglib.ap.assert(c.k==3, "Spline1DLinTransX: internal error");
            n = c.n;
            for(i=0; i<=n-2; i++)
            {
                c.c[4*i] = a*c.c[4*i]+b;
                for(j=1; j<=3; j++)
                {
                    c.c[4*i+j] = a*c.c[4*i+j];
                }
            }
            c.c[4*(n-1)+0] = a*c.c[4*(n-1)+0]+b;
            c.c[4*(n-1)+1] = a*c.c[4*(n-1)+1];
        }
Пример #33
0
    /*************************************************************************
    Weighted  fitting  by Hermite spline,  with constraints on function values
    or first derivatives.

    Equidistant grid with M nodes on [min(x,xc),max(x,xc)] is  used  to  build
    basis functions. Basis functions are Hermite splines.  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
        Spline1DFitCubicWC()    -   fitting by Cubic splines (less flexible,
                                    more smooth)
        Spline1DFitHermite()    -   "lightweight" Hermite 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 (optional):
                * N>0
                * if given, only first N elements of X/Y/W are processed
                * if not given, automatically determined from X/Y/W sizes
        XC  -   points where spline 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 (optional):
                * 0<=K<M.
                * K=0 means no constraints (XC/YC/DC are not used)
                * if given, only first K elements of XC/YC/DC are used
                * if not given, automatically determined from XC/YC/DC
        M   -   number of basis functions (= 2 * number of nodes),
                M>=4,
                M IS EVEN!

    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
                            -2 means odd M was passed (which is not supported)
                            -1 means another errors in parameters passed
                               (N<=0, for example)
        S   -   spline interpolant.
        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.

    IMPORTANT:
        this subroitine supports only even M's


    ORDER OF POINTS

    Subroutine automatically sorts points, so caller may pass unsorted array.

    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:
    * excessive constraints can be inconsistent. Splines are  piecewise  cubic
      functions, and it is easy to create an example, where  large  number  of
      constraints  concentrated  in  small  area will result in inconsistency.
      Just because spline is not flexible enough to satisfy all of  them.  And
      same constraints spread across the  [min(x),max(x)]  will  be  perfectly
      consistent.
    * 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  M>=4  and   constraints  on   the  function  value
      (AND/OR its derivative) at the interval boundaries.
    * another special case is M>=4  and  ONE  constraint on the function value
      (OR, BUT NOT AND, derivative) anywhere in [min(x),max(x)]

    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 spline1dfithermitewc(double[] x, double[] y, double[] w, int n, double[] xc, double[] yc, int[] dc, int k, int m, out int info, out spline1dinterpolant s, out spline1dfitreport rep)
    {
        info = 0;
        s = new spline1dinterpolant();
        rep = new spline1dfitreport();
        lsfit.spline1dfithermitewc(x, y, w, n, xc, yc, dc, k, m, ref info, s.innerobj, rep.innerobj);
        return;
    }
Пример #34
0
        /*************************************************************************
        This function finds all roots and extrema of the spline S(x)  defined  at
        [A,B] (interval which contains spline nodes).

        It  does not extrapolates function, so roots and extrema located  outside 
        of [A,B] will not be found. It returns all isolated (including  multiple)
        roots and extrema.

        INPUT PARAMETERS
            C           -   spline interpolant
            
        OUTPUT PARAMETERS
            R           -   array[NR], contains roots of the spline. 
                            In case there is no roots, this array has zero length.
            NR          -   number of roots, >=0
            DR          -   is set to True in case there is at least one interval
                            where spline is just a zero constant. Such degenerate
                            cases are not reported in the R/NR
            E           -   array[NE], contains  extrema  (maximums/minimums)  of 
                            the spline. In case there is no extrema,  this  array 
                            has zero length.
            ET          -   array[NE], extrema types:
                            * ET[i]>0 in case I-th extrema is a minimum
                            * ET[i]<0 in case I-th extrema is a maximum
            NE          -   number of extrema, >=0
            DE          -   is set to True in case there is at least one interval
                            where spline is a constant. Such degenerate cases are  
                            not reported in the E/NE.
                            
        NOTES:

        1. This function does NOT report following kinds of roots:
           * intervals where function is constantly zero
           * roots which are outside of [A,B] (note: it CAN return A or B)

        2. This function does NOT report following kinds of extrema:
           * intervals where function is a constant
           * extrema which are outside of (A,B) (note: it WON'T return A or B)
           
         -- ALGLIB PROJECT --
             Copyright 26.09.2011 by Bochkanov Sergey   
        *************************************************************************/
        public static void spline1drootsandextrema(spline1dinterpolant c,
            ref double[] r,
            ref int nr,
            ref bool dr,
            ref double[] e,
            ref int[] et,
            ref int ne,
            ref bool de)
        {
            double pl = 0;
            double ml = 0;
            double pll = 0;
            double pr = 0;
            double mr = 0;
            double[] tr = new double[0];
            double[] tmpr = new double[0];
            double[] tmpe = new double[0];
            int[] tmpet = new int[0];
            double[] tmpc = new double[0];
            double x0 = 0;
            double x1 = 0;
            double x2 = 0;
            double ex0 = 0;
            double ex1 = 0;
            int tne = 0;
            int tnr = 0;
            int i = 0;
            int j = 0;
            bool nstep = new bool();

            r = new double[0];
            nr = 0;
            dr = new bool();
            e = new double[0];
            et = new int[0];
            ne = 0;
            de = new bool();

            
            //
            //exception handling
            //
            alglib.ap.assert(c.k==3, "Spline1DRootsAndExtrema : incorrect parameter C.K!");
            alglib.ap.assert(c.continuity>=0, "Spline1DRootsAndExtrema : parameter C.Continuity must not be less than 0!");
            
            //
            //initialization of variable
            //
            nr = 0;
            ne = 0;
            dr = false;
            de = false;
            nstep = true;
            
            //
            //consider case, when C.Continuty=0
            //
            if( c.continuity==0 )
            {
                
                //
                //allocation for auxiliary arrays 
                //'TmpR ' - it stores a time value for roots
                //'TmpE ' - it stores a time value for extremums
                //'TmpET '- it stores a time value for extremums type
                //
                apserv.rvectorsetlengthatleast(ref tmpr, 3*(c.n-1));
                apserv.rvectorsetlengthatleast(ref tmpe, 2*(c.n-1));
                apserv.ivectorsetlengthatleast(ref tmpet, 2*(c.n-1));
                
                //
                //start calculating
                //
                for(i=0; i<=c.n-2; i++)
                {
                    
                    //
                    //initialization pL, mL, pR, mR
                    //
                    pl = c.c[4*i];
                    ml = c.c[4*i+1];
                    pr = c.c[4*(i+1)];
                    mr = c.c[4*i+1]+2*c.c[4*i+2]*(c.x[i+1]-c.x[i])+3*c.c[4*i+3]*(c.x[i+1]-c.x[i])*(c.x[i+1]-c.x[i]);
                    
                    //
                    //pre-searching roots and extremums
                    //
                    solvecubicpolinom(pl, ml, pr, mr, c.x[i], c.x[i+1], ref x0, ref x1, ref x2, ref ex0, ref ex1, ref tnr, ref tne, ref tr);
                    dr = dr || tnr==-1;
                    de = de || tne==-1;
                    
                    //
                    //searching of roots
                    //
                    if( tnr==1 && nstep )
                    {
                        
                        //
                        //is there roots?
                        //
                        if( nr>0 )
                        {
                            
                            //
                            //is a next root equal a previous root?
                            //if is't, then write new root
                            //
                            if( (double)(x0)!=(double)(tmpr[nr-1]) )
                            {
                                tmpr[nr] = x0;
                                nr = nr+1;
                            }
                        }
                        else
                        {
                            
                            //
                            //write a first root
                            //
                            tmpr[nr] = x0;
                            nr = nr+1;
                        }
                    }
                    else
                    {
                        
                        //
                        //case when function at a segment identically to zero
                        //then we have to clear a root, if the one located on a 
                        //constant segment
                        //
                        if( tnr==-1 )
                        {
                            
                            //
                            //safe state variable as constant
                            //
                            if( nstep )
                            {
                                nstep = false;
                            }
                            
                            //
                            //clear the root, if there is
                            //
                            if( nr>0 )
                            {
                                if( (double)(c.x[i])==(double)(tmpr[nr-1]) )
                                {
                                    nr = nr-1;
                                }
                            }
                            
                            //
                            //change state for 'DR'
                            //
                            if( !dr )
                            {
                                dr = true;
                            }
                        }
                        else
                        {
                            nstep = true;
                        }
                    }
                    
                    //
                    //searching of extremums
                    //
                    if( i>0 )
                    {
                        pll = c.c[4*(i-1)];
                        
                        //
                        //if pL=pLL or pL=pR then
                        //
                        if( tne==-1 )
                        {
                            if( !de )
                            {
                                de = true;
                            }
                        }
                        else
                        {
                            if( (double)(pl)>(double)(pll) && (double)(pl)>(double)(pr) )
                            {
                                
                                //
                                //maximum
                                //
                                tmpet[ne] = -1;
                                tmpe[ne] = c.x[i];
                                ne = ne+1;
                            }
                            else
                            {
                                if( (double)(pl)<(double)(pll) && (double)(pl)<(double)(pr) )
                                {
                                    
                                    //
                                    //minimum
                                    //
                                    tmpet[ne] = 1;
                                    tmpe[ne] = c.x[i];
                                    ne = ne+1;
                                }
                            }
                        }
                    }
                }
                
                //
                //write final result
                //
                apserv.rvectorsetlengthatleast(ref r, nr);
                apserv.rvectorsetlengthatleast(ref e, ne);
                apserv.ivectorsetlengthatleast(ref et, ne);
                
                //
                //write roots
                //
                for(i=0; i<=nr-1; i++)
                {
                    r[i] = tmpr[i];
                }
                
                //
                //write extremums and their types
                //
                for(i=0; i<=ne-1; i++)
                {
                    e[i] = tmpe[i];
                    et[i] = tmpet[i];
                }
            }
            else
            {
                
                //
                //case, when C.Continuity>=1 
                //'TmpR ' - it stores a time value for roots
                //'TmpC' - it stores a time value for extremums and 
                //their function value (TmpC={EX0,F(EX0), EX1,F(EX1), ..., EXn,F(EXn)};)
                //'TmpE' - it stores a time value for extremums only
                //'TmpET'- it stores a time value for extremums type
                //
                apserv.rvectorsetlengthatleast(ref tmpr, 2*c.n-1);
                apserv.rvectorsetlengthatleast(ref tmpc, 4*c.n);
                apserv.rvectorsetlengthatleast(ref tmpe, 2*c.n);
                apserv.ivectorsetlengthatleast(ref tmpet, 2*c.n);
                
                //
                //start calculating
                //
                for(i=0; i<=c.n-2; i++)
                {
                    
                    //
                    //we calculate pL,mL, pR,mR as Fi+1(F'i+1) at left border
                    //
                    pl = c.c[4*i];
                    ml = c.c[4*i+1];
                    pr = c.c[4*(i+1)];
                    mr = c.c[4*(i+1)+1];
                    
                    //
                    //calculating roots and extremums at [X[i],X[i+1]]
                    //
                    solvecubicpolinom(pl, ml, pr, mr, c.x[i], c.x[i+1], ref x0, ref x1, ref x2, ref ex0, ref ex1, ref tnr, ref tne, ref tr);
                    
                    //
                    //searching roots
                    //
                    if( tnr>0 )
                    {
                        
                        //
                        //re-init tR
                        //
                        if( tnr>=1 )
                        {
                            tr[0] = x0;
                        }
                        if( tnr>=2 )
                        {
                            tr[1] = x1;
                        }
                        if( tnr==3 )
                        {
                            tr[2] = x2;
                        }
                        
                        //
                        //start root selection
                        //
                        if( nr>0 )
                        {
                            if( (double)(tmpr[nr-1])!=(double)(x0) )
                            {
                                
                                //
                                //previous segment was't constant identical zero
                                //
                                if( nstep )
                                {
                                    for(j=0; j<=tnr-1; j++)
                                    {
                                        tmpr[nr+j] = tr[j];
                                    }
                                    nr = nr+tnr;
                                }
                                else
                                {
                                    
                                    //
                                    //previous segment was constant identical zero
                                    //and we must ignore [NR+j-1] root
                                    //
                                    for(j=1; j<=tnr-1; j++)
                                    {
                                        tmpr[nr+j-1] = tr[j];
                                    }
                                    nr = nr+tnr-1;
                                    nstep = true;
                                }
                            }
                            else
                            {
                                for(j=1; j<=tnr-1; j++)
                                {
                                    tmpr[nr+j-1] = tr[j];
                                }
                                nr = nr+tnr-1;
                            }
                        }
                        else
                        {
                            
                            //
                            //write first root
                            //
                            for(j=0; j<=tnr-1; j++)
                            {
                                tmpr[nr+j] = tr[j];
                            }
                            nr = nr+tnr;
                        }
                    }
                    else
                    {
                        if( tnr==-1 )
                        {
                            
                            //
                            //decrement 'NR' if at previous step was writen a root
                            //(previous segment identical zero)
                            //
                            if( nr>0 && nstep )
                            {
                                nr = nr-1;
                            }
                            
                            //
                            //previous segment is't constant
                            //
                            if( nstep )
                            {
                                nstep = false;
                            }
                            
                            //
                            //rewrite 'DR'
                            //
                            if( !dr )
                            {
                                dr = true;
                            }
                        }
                    }
                    
                    //
                    //searching extremums
                    //write all term like extremums
                    //
                    if( tne==1 )
                    {
                        if( ne>0 )
                        {
                            
                            //
                            //just ignore identical extremums
                            //because he must be one
                            //
                            if( (double)(tmpc[ne-2])!=(double)(ex0) )
                            {
                                tmpc[ne] = ex0;
                                tmpc[ne+1] = c.c[4*i]+c.c[4*i+1]*(ex0-c.x[i])+c.c[4*i+2]*(ex0-c.x[i])*(ex0-c.x[i])+c.c[4*i+3]*(ex0-c.x[i])*(ex0-c.x[i])*(ex0-c.x[i]);
                                ne = ne+2;
                            }
                        }
                        else
                        {
                            
                            //
                            //write first extremum and it function value
                            //
                            tmpc[ne] = ex0;
                            tmpc[ne+1] = c.c[4*i]+c.c[4*i+1]*(ex0-c.x[i])+c.c[4*i+2]*(ex0-c.x[i])*(ex0-c.x[i])+c.c[4*i+3]*(ex0-c.x[i])*(ex0-c.x[i])*(ex0-c.x[i]);
                            ne = ne+2;
                        }
                    }
                    else
                    {
                        if( tne==2 )
                        {
                            if( ne>0 )
                            {
                                
                                //
                                //ignore identical extremum
                                //
                                if( (double)(tmpc[ne-2])!=(double)(ex0) )
                                {
                                    tmpc[ne] = ex0;
                                    tmpc[ne+1] = c.c[4*i]+c.c[4*i+1]*(ex0-c.x[i])+c.c[4*i+2]*(ex0-c.x[i])*(ex0-c.x[i])+c.c[4*i+3]*(ex0-c.x[i])*(ex0-c.x[i])*(ex0-c.x[i]);
                                    ne = ne+2;
                                }
                            }
                            else
                            {
                                
                                //
                                //write first extremum
                                //
                                tmpc[ne] = ex0;
                                tmpc[ne+1] = c.c[4*i]+c.c[4*i+1]*(ex0-c.x[i])+c.c[4*i+2]*(ex0-c.x[i])*(ex0-c.x[i])+c.c[4*i+3]*(ex0-c.x[i])*(ex0-c.x[i])*(ex0-c.x[i]);
                                ne = ne+2;
                            }
                            
                            //
                            //write second extremum
                            //
                            tmpc[ne] = ex1;
                            tmpc[ne+1] = c.c[4*i]+c.c[4*i+1]*(ex1-c.x[i])+c.c[4*i+2]*(ex1-c.x[i])*(ex1-c.x[i])+c.c[4*i+3]*(ex1-c.x[i])*(ex1-c.x[i])*(ex1-c.x[i]);
                            ne = ne+2;
                        }
                        else
                        {
                            if( tne==-1 )
                            {
                                if( !de )
                                {
                                    de = true;
                                }
                            }
                        }
                    }
                }
                
                //
                //checking of arrays
                //get number of extremums (tNe=NE/2)
                //initialize pL as value F0(X[0]) and
                //initialize pR as value Fn-1(X[N])
                //
                tne = ne/2;
                ne = 0;
                pl = c.c[0];
                pr = c.c[4*(c.n-1)];
                for(i=0; i<=tne-1; i++)
                {
                    if( i>0 && i<tne-1 )
                    {
                        if( (double)(tmpc[2*i+1])>(double)(tmpc[2*(i-1)+1]) && (double)(tmpc[2*i+1])>(double)(tmpc[2*(i+1)+1]) )
                        {
                            
                            //
                            //maximum
                            //
                            tmpe[ne] = tmpc[2*i];
                            tmpet[ne] = -1;
                            ne = ne+1;
                        }
                        else
                        {
                            if( (double)(tmpc[2*i+1])<(double)(tmpc[2*(i-1)+1]) && (double)(tmpc[2*i+1])<(double)(tmpc[2*(i+1)+1]) )
                            {
                                
                                //
                                //minimum
                                //
                                tmpe[ne] = tmpc[2*i];
                                tmpet[ne] = 1;
                                ne = ne+1;
                            }
                        }
                    }
                    else
                    {
                        if( i==0 )
                        {
                            if( (double)(tmpc[2*i])!=(double)(c.x[0]) )
                            {
                                if( (double)(tmpc[2*i+1])>(double)(pl) && (double)(tmpc[2*i+1])>(double)(tmpc[2*(i+1)+1]) )
                                {
                                    
                                    //
                                    //maximum
                                    //
                                    tmpe[ne] = tmpc[2*i];
                                    tmpet[ne] = -1;
                                    ne = ne+1;
                                }
                                else
                                {
                                    if( (double)(tmpc[2*i+1])<(double)(pl) && (double)(tmpc[2*i+1])<(double)(tmpc[2*(i+1)+1]) )
                                    {
                                        
                                        //
                                        //minimum
                                        //
                                        tmpe[ne] = tmpc[2*i];
                                        tmpet[ne] = 1;
                                        ne = ne+1;
                                    }
                                }
                            }
                        }
                        else
                        {
                            if( i==tne-1 )
                            {
                                if( (double)(tmpc[2*i])!=(double)(c.x[c.n-1]) )
                                {
                                    if( (double)(tmpc[2*i+1])>(double)(tmpc[2*(i-1)+1]) && (double)(tmpc[2*i+1])>(double)(pr) )
                                    {
                                        
                                        //
                                        //maximum
                                        //
                                        tmpe[ne] = tmpc[2*i];
                                        tmpet[ne] = -1;
                                        ne = ne+1;
                                    }
                                    else
                                    {
                                        if( (double)(tmpc[2*i+1])<(double)(tmpc[2*(i-1)+1]) && (double)(tmpc[2*i+1])<(double)(pr) )
                                        {
                                            
                                            //
                                            //minimum
                                            //
                                            tmpe[ne] = tmpc[2*i];
                                            tmpet[ne] = 1;
                                            ne = ne+1;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                
                //
                //final results
                //allocate R, E, ET
                //
                apserv.rvectorsetlengthatleast(ref r, nr);
                apserv.rvectorsetlengthatleast(ref e, ne);
                apserv.ivectorsetlengthatleast(ref et, ne);
                
                //
                //write result for extremus and their types
                //
                for(i=0; i<=ne-1; i++)
                {
                    e[i] = tmpe[i];
                    et[i] = tmpet[i];
                }
                
                //
                //write result for roots
                //
                for(i=0; i<=nr-1; i++)
                {
                    r[i] = tmpr[i];
                }
            }
        }
Пример #35
0
    public static void spline1dfithermitewc(double[] x, double[] y, double[] w, double[] xc, double[] yc, int[] dc, int m, out int info, out spline1dinterpolant s, out spline1dfitreport rep)
    {
        int n;
        int k;
        if( (ap.len(x)!=ap.len(y)) || (ap.len(x)!=ap.len(w)))
            throw new alglibexception("Error while calling 'spline1dfithermitewc': looks like one of arguments has wrong size");
        if( (ap.len(xc)!=ap.len(yc)) || (ap.len(xc)!=ap.len(dc)))
            throw new alglibexception("Error while calling 'spline1dfithermitewc': looks like one of arguments has wrong size");
        info = 0;
        s = new spline1dinterpolant();
        rep = new spline1dfitreport();
        n = ap.len(x);
        k = ap.len(xc);
        lsfit.spline1dfithermitewc(x, y, w, n, xc, yc, dc, k, m, ref info, s.innerobj, rep.innerobj);

        return;
    }
Пример #36
0
 public override alglib.apobject make_copy()
 {
     spline1dinterpolant _result = new spline1dinterpolant();
     _result.periodic = periodic;
     _result.n = n;
     _result.k = k;
     _result.continuity = continuity;
     _result.x = (double[])x.Clone();
     _result.c = (double[])c.Clone();
     return _result;
 }
Пример #37
0
    /*************************************************************************
    Least squares fitting by Hermite spline.

    This subroutine is "lightweight" alternative for more complex and feature-
    rich Spline1DFitHermiteWC().  See Spline1DFitHermiteWC()  description  for
    more information about subroutine parameters (we don't duplicate  it  here
    because of length).

      -- ALGLIB PROJECT --
         Copyright 18.08.2009 by Bochkanov Sergey
    *************************************************************************/
    public static void spline1dfithermite(double[] x, double[] y, int n, int m, out int info, out spline1dinterpolant s, out spline1dfitreport rep)
    {
        info = 0;
        s = new spline1dinterpolant();
        rep = new spline1dfitreport();
        lsfit.spline1dfithermite(x, y, n, m, ref info, s.innerobj, rep.innerobj);
        return;
    }
Пример #38
0
        /*************************************************************************
        This subroutine builds cubic spline interpolant.

        INPUT PARAMETERS:
            X           -   spline nodes, array[0..N-1].
            Y           -   function values, array[0..N-1].
            
        OPTIONAL PARAMETERS:
            N           -   points count:
                            * N>=2
                            * if given, only first N points are used to build spline
                            * if not given, automatically detected from X/Y sizes
                              (len(X) must be equal to len(Y))
            BoundLType  -   boundary condition type for the left boundary
            BoundL      -   left boundary condition (first or second derivative,
                            depending on the BoundLType)
            BoundRType  -   boundary condition type for the right boundary
            BoundR      -   right boundary condition (first or second derivative,
                            depending on the BoundRType)

        OUTPUT PARAMETERS:
            C           -   spline interpolant

        ORDER OF POINTS

        Subroutine automatically sorts points, so caller may pass unsorted array.

        SETTING BOUNDARY VALUES:

        The BoundLType/BoundRType parameters can have the following values:
            * -1, which corresonds to the periodic (cyclic) boundary conditions.
                  In this case:
                  * both BoundLType and BoundRType must be equal to -1.
                  * BoundL/BoundR are ignored
                  * Y[last] is ignored (it is assumed to be equal to Y[first]).
            *  0, which  corresponds  to  the  parabolically   terminated  spline
                  (BoundL and/or BoundR are ignored).
            *  1, which corresponds to the first derivative boundary condition
            *  2, which corresponds to the second derivative boundary condition
            *  by default, BoundType=0 is used

        PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS:

        Problems with periodic boundary conditions have Y[first_point]=Y[last_point].
        However, this subroutine doesn't require you to specify equal  values  for
        the first and last points - it automatically forces them  to  be  equal by
        copying  Y[first_point]  (corresponds  to the leftmost,  minimal  X[])  to
        Y[last_point]. However it is recommended to pass consistent values of Y[],
        i.e. to make Y[first_point]=Y[last_point].

          -- ALGLIB PROJECT --
             Copyright 23.06.2007 by Bochkanov Sergey
        *************************************************************************/
        public static void spline1dbuildcubic(double[] x,
            double[] y,
            int n,
            int boundltype,
            double boundl,
            int boundrtype,
            double boundr,
            spline1dinterpolant c)
        {
            double[] a1 = new double[0];
            double[] a2 = new double[0];
            double[] a3 = new double[0];
            double[] b = new double[0];
            double[] dt = new double[0];
            double[] d = new double[0];
            int[] p = new int[0];
            int ylen = 0;

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

            
            //
            // check correctness of boundary conditions
            //
            alglib.ap.assert(((boundltype==-1 || boundltype==0) || boundltype==1) || boundltype==2, "Spline1DBuildCubic: incorrect BoundLType!");
            alglib.ap.assert(((boundrtype==-1 || boundrtype==0) || boundrtype==1) || boundrtype==2, "Spline1DBuildCubic: incorrect BoundRType!");
            alglib.ap.assert((boundrtype==-1 && boundltype==-1) || (boundrtype!=-1 && boundltype!=-1), "Spline1DBuildCubic: incorrect BoundLType/BoundRType!");
            if( boundltype==1 || boundltype==2 )
            {
                alglib.ap.assert(math.isfinite(boundl), "Spline1DBuildCubic: BoundL is infinite or NAN!");
            }
            if( boundrtype==1 || boundrtype==2 )
            {
                alglib.ap.assert(math.isfinite(boundr), "Spline1DBuildCubic: BoundR is infinite or NAN!");
            }
            
            //
            // check lengths of arguments
            //
            alglib.ap.assert(n>=2, "Spline1DBuildCubic: N<2!");
            alglib.ap.assert(alglib.ap.len(x)>=n, "Spline1DBuildCubic: Length(X)<N!");
            alglib.ap.assert(alglib.ap.len(y)>=n, "Spline1DBuildCubic: Length(Y)<N!");
            
            //
            // check and sort points
            //
            ylen = n;
            if( boundltype==-1 )
            {
                ylen = n-1;
            }
            alglib.ap.assert(apserv.isfinitevector(x, n), "Spline1DBuildCubic: X contains infinite or NAN values!");
            alglib.ap.assert(apserv.isfinitevector(y, ylen), "Spline1DBuildCubic: Y contains infinite or NAN values!");
            heapsortppoints(ref x, ref y, ref p, n);
            alglib.ap.assert(apserv.aredistinct(x, n), "Spline1DBuildCubic: at least two consequent points are too close!");
            
            //
            // Now we've checked and preordered everything,
            // so we can call internal function to calculate derivatives,
            // and then build Hermite spline using these derivatives
            //
            if( boundltype==-1 || boundrtype==-1 )
            {
                y[n-1] = y[0];
            }
            spline1dgriddiffcubicinternal(x, ref y, n, boundltype, boundl, boundrtype, boundr, ref d, ref a1, ref a2, ref a3, ref b, ref dt);
            spline1dbuildhermite(x, y, d, n, c);
            c.periodic = boundltype==-1 || boundrtype==-1;
            c.continuity = 2;
        }
Пример #39
0
        /*************************************************************************
        *  This subroutine builds cubic spline interpolant.
        *
        *  INPUT PARAMETERS:
        *   X           -   spline nodes, array[0..N-1].
        *   Y           -   function values, array[0..N-1].
        *
        *  OPTIONAL PARAMETERS:
        *   N           -   points count:
        * N>=2
        * if given, only first N points are used to build spline
        * if not given, automatically detected from X/Y sizes
        *                     (len(X) must be equal to len(Y))
        *   BoundLType  -   boundary condition type for the left boundary
        *   BoundL      -   left boundary condition (first or second derivative,
        *                   depending on the BoundLType)
        *   BoundRType  -   boundary condition type for the right boundary
        *   BoundR      -   right boundary condition (first or second derivative,
        *                   depending on the BoundRType)
        *
        *  OUTPUT PARAMETERS:
        *   C           -   spline interpolant
        *
        *  ORDER OF POINTS
        *
        *  Subroutine automatically sorts points, so caller may pass unsorted array.
        *
        *  SETTING BOUNDARY VALUES:
        *
        *  The BoundLType/BoundRType parameters can have the following values:
        * -1, which corresonds to the periodic (cyclic) boundary conditions.
        *         In this case:
        * both BoundLType and BoundRType must be equal to -1.
        * BoundL/BoundR are ignored
        * Y[last] is ignored (it is assumed to be equal to Y[first]).
        *  0, which  corresponds  to  the  parabolically   terminated  spline
        *         (BoundL and/or BoundR are ignored).
        *  1, which corresponds to the first derivative boundary condition
        *  2, which corresponds to the second derivative boundary condition
        *  by default, BoundType=0 is used
        *
        *  PROBLEMS WITH PERIODIC BOUNDARY CONDITIONS:
        *
        *  Problems with periodic boundary conditions have Y[first_point]=Y[last_point].
        *  However, this subroutine doesn't require you to specify equal  values  for
        *  the first and last points - it automatically forces them  to  be  equal by
        *  copying  Y[first_point]  (corresponds  to the leftmost,  minimal  X[])  to
        *  Y[last_point]. However it is recommended to pass consistent values of Y[],
        *  i.e. to make Y[first_point]=Y[last_point].
        *
        *  -- ALGLIB PROJECT --
        *    Copyright 23.06.2007 by Bochkanov Sergey
        *************************************************************************/
        public static void spline1dbuildcubic(double[] x,
                                              double[] y,
                                              int n,
                                              int boundltype,
                                              double boundl,
                                              int boundrtype,
                                              double boundr,
                                              spline1dinterpolant c)
        {
            double[] a1   = new double[0];
            double[] a2   = new double[0];
            double[] a3   = new double[0];
            double[] b    = new double[0];
            double[] dt   = new double[0];
            double[] d    = new double[0];
            int[]    p    = new int[0];
            int      ylen = 0;

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


            //
            // check correctness of boundary conditions
            //
            alglib.ap.assert(((boundltype == -1 || boundltype == 0) || boundltype == 1) || boundltype == 2, "Spline1DBuildCubic: incorrect BoundLType!");
            alglib.ap.assert(((boundrtype == -1 || boundrtype == 0) || boundrtype == 1) || boundrtype == 2, "Spline1DBuildCubic: incorrect BoundRType!");
            alglib.ap.assert((boundrtype == -1 && boundltype == -1) || (boundrtype != -1 && boundltype != -1), "Spline1DBuildCubic: incorrect BoundLType/BoundRType!");
            if (boundltype == 1 || boundltype == 2)
            {
                alglib.ap.assert(math.isfinite(boundl), "Spline1DBuildCubic: BoundL is infinite or NAN!");
            }
            if (boundrtype == 1 || boundrtype == 2)
            {
                alglib.ap.assert(math.isfinite(boundr), "Spline1DBuildCubic: BoundR is infinite or NAN!");
            }

            //
            // check lengths of arguments
            //
            alglib.ap.assert(n >= 2, "Spline1DBuildCubic: N<2!");
            alglib.ap.assert(alglib.ap.len(x) >= n, "Spline1DBuildCubic: Length(X)<N!");
            alglib.ap.assert(alglib.ap.len(y) >= n, "Spline1DBuildCubic: Length(Y)<N!");

            //
            // check and sort points
            //
            ylen = n;
            if (boundltype == -1)
            {
                ylen = n - 1;
            }
            alglib.ap.assert(apserv.isfinitevector(x, n), "Spline1DBuildCubic: X contains infinite or NAN values!");
            alglib.ap.assert(apserv.isfinitevector(y, ylen), "Spline1DBuildCubic: Y contains infinite or NAN values!");
            heapsortppoints(ref x, ref y, ref p, n);
            alglib.ap.assert(apserv.aredistinct(x, n), "Spline1DBuildCubic: at least two consequent points are too close!");

            //
            // Now we've checked and preordered everything,
            // so we can call internal function to calculate derivatives,
            // and then build Hermite spline using these derivatives
            //
            if (boundltype == -1 || boundrtype == -1)
            {
                y[n - 1] = y[0];
            }
            spline1dgriddiffcubicinternal(x, ref y, n, boundltype, boundl, boundrtype, boundr, ref d, ref a1, ref a2, ref a3, ref b, ref dt);
            spline1dbuildhermite(x, y, d, n, c);
            c.periodic   = boundltype == -1 || boundrtype == -1;
            c.continuity = 2;
        }