Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.LinearRegression/3.2/alglib/spline3.cs @ 2154

Last change on this file since 2154 was 2154, checked in by gkronber, 15 years ago

Added linear regression plugin. #697

File size: 36.5 KB
Line 
1/*************************************************************************
2Copyright (c) 2007, Sergey Bochkanov (ALGLIB project).
3
4Redistribution and use in source and binary forms, with or without
5modification, are permitted provided that the following conditions are
6met:
7
8- Redistributions of source code must retain the above copyright
9  notice, this list of conditions and the following disclaimer.
10
11- Redistributions in binary form must reproduce the above copyright
12  notice, this list of conditions and the following disclaimer listed
13  in this license in the documentation and/or other materials
14  provided with the distribution.
15
16- Neither the name of the copyright holders nor the names of its
17  contributors may be used to endorse or promote products derived from
18  this software without specific prior written permission.
19
20THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31*************************************************************************/
32
33using System;
34
35class spline3
36{
37    /*************************************************************************
38    This subroutine builds linear spline coefficients table.
39
40    Input parameters:
41        X   -   spline nodes, array[0..N-1]
42        Y   -   function values, array[0..N-1]
43        N   -   points count, N>=2
44       
45    Output parameters:
46        C   -   coefficients table.  Used  by  SplineInterpolation  and  other
47                subroutines from this file.
48
49      -- ALGLIB PROJECT --
50         Copyright 24.06.2007 by Bochkanov Sergey
51    *************************************************************************/
52    public static void buildlinearspline(double[] x,
53        double[] y,
54        int n,
55        ref double[] c)
56    {
57        int i = 0;
58        int tblsize = 0;
59
60        x = (double[])x.Clone();
61        y = (double[])y.Clone();
62
63        System.Diagnostics.Debug.Assert(n>=2, "BuildLinearSpline: N<2!");
64       
65        //
66        // Sort points
67        //
68        heapsortpoints(ref x, ref y, n);
69       
70        //
71        // Fill C:
72        //  C[0]            -   length(C)
73        //  C[1]            -   type(C):
74        //                      3 - general cubic spline
75        //  C[2]            -   N
76        //  C[3]...C[3+N-1] -   x[i], i = 0...N-1
77        //  C[3+N]...C[3+N+(N-1)*4-1] - coefficients table
78        //
79        tblsize = 3+n+(n-1)*4;
80        c = new double[tblsize-1+1];
81        c[0] = tblsize;
82        c[1] = 3;
83        c[2] = n;
84        for(i=0; i<=n-1; i++)
85        {
86            c[3+i] = x[i];
87        }
88        for(i=0; i<=n-2; i++)
89        {
90            c[3+n+4*i+0] = y[i];
91            c[3+n+4*i+1] = (y[i+1]-y[i])/(x[i+1]-x[i]);
92            c[3+n+4*i+2] = 0;
93            c[3+n+4*i+3] = 0;
94        }
95    }
96
97
98    /*************************************************************************
99    This subroutine builds cubic spline coefficients table.
100
101    Input parameters:
102        X           -   spline nodes, array[0..N-1]
103        Y           -   function values, array[0..N-1]
104        N           -   points count, N>=2
105        BoundLType  -   boundary condition type for the left boundary
106        BoundL      -   left boundary condition (first or second derivative,
107                        depending on the BoundLType)
108        BoundRType  -   boundary condition type for the right boundary
109        BoundR      -   right boundary condition (first or second derivative,
110                        depending on the BoundRType)
111
112    Output parameters:
113        C           -   coefficients table.  Used  by  SplineInterpolation and
114                        other subroutines from this file.
115                       
116    The BoundLType/BoundRType parameters can have the following values:
117        * 0,   which  corresponds  to  the  parabolically   terminated  spline
118          (BoundL/BoundR are ignored).
119        * 1, which corresponds to the first derivative boundary condition
120        * 2, which corresponds to the second derivative boundary condition
121
122      -- ALGLIB PROJECT --
123         Copyright 23.06.2007 by Bochkanov Sergey
124    *************************************************************************/
125    public static void buildcubicspline(double[] x,
126        double[] y,
127        int n,
128        int boundltype,
129        double boundl,
130        int boundrtype,
131        double boundr,
132        ref double[] c)
133    {
134        double[] a1 = new double[0];
135        double[] a2 = new double[0];
136        double[] a3 = new double[0];
137        double[] b = new double[0];
138        double[] d = new double[0];
139        int i = 0;
140        int tblsize = 0;
141        double delta = 0;
142        double delta2 = 0;
143        double delta3 = 0;
144
145        x = (double[])x.Clone();
146        y = (double[])y.Clone();
147
148        System.Diagnostics.Debug.Assert(n>=2, "BuildCubicSpline: N<2!");
149        System.Diagnostics.Debug.Assert(boundltype==0 | boundltype==1 | boundltype==2, "BuildCubicSpline: incorrect BoundLType!");
150        System.Diagnostics.Debug.Assert(boundrtype==0 | boundrtype==1 | boundrtype==2, "BuildCubicSpline: incorrect BoundRType!");
151        a1 = new double[n-1+1];
152        a2 = new double[n-1+1];
153        a3 = new double[n-1+1];
154        b = new double[n-1+1];
155       
156        //
157        // Special case:
158        // * N=2
159        // * parabolic terminated boundary condition on both ends
160        //
161        if( n==2 & boundltype==0 & boundrtype==0 )
162        {
163           
164            //
165            // Change task type
166            //
167            boundltype = 2;
168            boundl = 0;
169            boundrtype = 2;
170            boundr = 0;
171        }
172       
173        //
174        //
175        // Sort points
176        //
177        heapsortpoints(ref x, ref y, n);
178       
179        //
180        // Left boundary conditions
181        //
182        if( boundltype==0 )
183        {
184            a1[0] = 0;
185            a2[0] = 1;
186            a3[0] = 1;
187            b[0] = 2*(y[1]-y[0])/(x[1]-x[0]);
188        }
189        if( boundltype==1 )
190        {
191            a1[0] = 0;
192            a2[0] = 1;
193            a3[0] = 0;
194            b[0] = boundl;
195        }
196        if( boundltype==2 )
197        {
198            a1[0] = 0;
199            a2[0] = 2;
200            a3[0] = 1;
201            b[0] = 3*(y[1]-y[0])/(x[1]-x[0])-0.5*boundl*(x[1]-x[0]);
202        }
203       
204        //
205        // Central conditions
206        //
207        for(i=1; i<=n-2; i++)
208        {
209            a1[i] = x[i+1]-x[i];
210            a2[i] = 2*(x[i+1]-x[i-1]);
211            a3[i] = x[i]-x[i-1];
212            b[i] = 3*(y[i]-y[i-1])/(x[i]-x[i-1])*(x[i+1]-x[i])+3*(y[i+1]-y[i])/(x[i+1]-x[i])*(x[i]-x[i-1]);
213        }
214       
215        //
216        // Right boundary conditions
217        //
218        if( boundrtype==0 )
219        {
220            a1[n-1] = 1;
221            a2[n-1] = 1;
222            a3[n-1] = 0;
223            b[n-1] = 2*(y[n-1]-y[n-2])/(x[n-1]-x[n-2]);
224        }
225        if( boundrtype==1 )
226        {
227            a1[n-1] = 0;
228            a2[n-1] = 1;
229            a3[n-1] = 0;
230            b[n-1] = boundr;
231        }
232        if( boundrtype==2 )
233        {
234            a1[n-1] = 1;
235            a2[n-1] = 2;
236            a3[n-1] = 0;
237            b[n-1] = 3*(y[n-1]-y[n-2])/(x[n-1]-x[n-2])+0.5*boundr*(x[n-1]-x[n-2]);
238        }
239       
240        //
241        // Solve
242        //
243        solvetridiagonal(a1, a2, a3, b, n, ref d);
244       
245        //
246        // Now problem is reduced to the cubic Hermite spline
247        //
248        buildhermitespline(x, y, d, n, ref c);
249    }
250
251
252    /*************************************************************************
253    This subroutine builds cubic Hermite spline coefficients table.
254
255    Input parameters:
256        X           -   spline nodes, array[0..N-1]
257        Y           -   function values, array[0..N-1]
258        D           -   derivatives, array[0..N-1]
259        N           -   points count, N>=2
260
261    Output parameters:
262        C           -   coefficients table.  Used  by  SplineInterpolation and
263                        other subroutines from this file.
264
265      -- ALGLIB PROJECT --
266         Copyright 23.06.2007 by Bochkanov Sergey
267    *************************************************************************/
268    public static void buildhermitespline(double[] x,
269        double[] y,
270        double[] d,
271        int n,
272        ref double[] c)
273    {
274        int i = 0;
275        int tblsize = 0;
276        double delta = 0;
277        double delta2 = 0;
278        double delta3 = 0;
279
280        x = (double[])x.Clone();
281        y = (double[])y.Clone();
282        d = (double[])d.Clone();
283
284        System.Diagnostics.Debug.Assert(n>=2, "BuildHermiteSpline: N<2!");
285       
286        //
287        // Sort points
288        //
289        heapsortdpoints(ref x, ref y, ref d, n);
290       
291        //
292        // Fill C:
293        //  C[0]            -   length(C)
294        //  C[1]            -   type(C):
295        //                      3 - general cubic spline
296        //  C[2]            -   N
297        //  C[3]...C[3+N-1] -   x[i], i = 0...N-1
298        //  C[3+N]...C[3+N+(N-1)*4-1] - coefficients table
299        //
300        tblsize = 3+n+(n-1)*4;
301        c = new double[tblsize-1+1];
302        c[0] = tblsize;
303        c[1] = 3;
304        c[2] = n;
305        for(i=0; i<=n-1; i++)
306        {
307            c[3+i] = x[i];
308        }
309        for(i=0; i<=n-2; i++)
310        {
311            delta = x[i+1]-x[i];
312            delta2 = AP.Math.Sqr(delta);
313            delta3 = delta*delta2;
314            c[3+n+4*i+0] = y[i];
315            c[3+n+4*i+1] = d[i];
316            c[3+n+4*i+2] = (3*(y[i+1]-y[i])-2*d[i]*delta-d[i+1]*delta)/delta2;
317            c[3+n+4*i+3] = (2*(y[i]-y[i+1])+d[i]*delta+d[i+1]*delta)/delta3;
318        }
319    }
320
321
322    /*************************************************************************
323    This subroutine builds Akima spline coefficients table.
324
325    Input parameters:
326        X           -   spline nodes, array[0..N-1]
327        Y           -   function values, array[0..N-1]
328        N           -   points count, N>=5
329
330    Output parameters:
331        C           -   coefficients table.  Used  by  SplineInterpolation and
332                        other subroutines from this file.
333
334      -- ALGLIB PROJECT --
335         Copyright 24.06.2007 by Bochkanov Sergey
336    *************************************************************************/
337    public static void buildakimaspline(double[] x,
338        double[] y,
339        int n,
340        ref double[] c)
341    {
342        int i = 0;
343        double[] d = new double[0];
344        double[] w = new double[0];
345        double[] diff = new double[0];
346
347        x = (double[])x.Clone();
348        y = (double[])y.Clone();
349
350        System.Diagnostics.Debug.Assert(n>=5, "BuildAkimaSpline: N<5!");
351       
352        //
353        // Sort points
354        //
355        heapsortpoints(ref x, ref y, n);
356       
357        //
358        // Prepare W (weights), Diff (divided differences)
359        //
360        w = new double[n-2+1];
361        diff = new double[n-2+1];
362        for(i=0; i<=n-2; i++)
363        {
364            diff[i] = (y[i+1]-y[i])/(x[i+1]-x[i]);
365        }
366        for(i=1; i<=n-2; i++)
367        {
368            w[i] = Math.Abs(diff[i]-diff[i-1]);
369        }
370       
371        //
372        // Prepare Hermite interpolation scheme
373        //
374        d = new double[n-1+1];
375        for(i=2; i<=n-3; i++)
376        {
377            if( Math.Abs(w[i-1])+Math.Abs(w[i+1])!=0 )
378            {
379                d[i] = (w[i+1]*diff[i-1]+w[i-1]*diff[i])/(w[i+1]+w[i-1]);
380            }
381            else
382            {
383                d[i] = ((x[i+1]-x[i])*diff[i-1]+(x[i]-x[i-1])*diff[i])/(x[i+1]-x[i-1]);
384            }
385        }
386        d[0] = diffthreepoint(x[0], x[0], y[0], x[1], y[1], x[2], y[2]);
387        d[1] = diffthreepoint(x[1], x[0], y[0], x[1], y[1], x[2], y[2]);
388        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]);
389        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]);
390       
391        //
392        // Build Akima spline using Hermite interpolation scheme
393        //
394        buildhermitespline(x, y, d, n, ref c);
395    }
396
397
398    /*************************************************************************
399    This subroutine calculates the value of the spline at the given point X.
400
401    Input parameters:
402        C           -   coefficients table. Built by BuildLinearSpline,
403                        BuildHermiteSpline, BuildCubicSpline, BuildAkimaSpline.
404        X           -   point
405
406    Result:
407        S(x)
408
409      -- ALGLIB PROJECT --
410         Copyright 23.06.2007 by Bochkanov Sergey
411    *************************************************************************/
412    public static double splineinterpolation(ref double[] c,
413        double x)
414    {
415        double result = 0;
416        int n = 0;
417        int l = 0;
418        int r = 0;
419        int m = 0;
420
421        System.Diagnostics.Debug.Assert((int)Math.Round(c[1])==3, "SplineInterpolation: incorrect C!");
422        n = (int)Math.Round(c[2]);
423       
424        //
425        // Binary search in the [ x[0], ..., x[n-2] ] (x[n-1] is not included)
426        //
427        l = 3;
428        r = 3+n-2+1;
429        while( l!=r-1 )
430        {
431            m = (l+r)/2;
432            if( c[m]>=x )
433            {
434                r = m;
435            }
436            else
437            {
438                l = m;
439            }
440        }
441       
442        //
443        // Interpolation
444        //
445        x = x-c[l];
446        m = 3+n+4*(l-3);
447        result = c[m]+x*(c[m+1]+x*(c[m+2]+x*c[m+3]));
448        return result;
449    }
450
451
452    /*************************************************************************
453    This subroutine differentiates the spline.
454
455    Input parameters:
456        C   -   coefficients table. Built by BuildLinearSpline,
457                BuildHermiteSpline, BuildCubicSpline, BuildAkimaSpline.
458        X   -   point
459
460    Result:
461        S   -   S(x)
462        DS  -   S'(x)
463        D2S -   S''(x)
464
465      -- ALGLIB PROJECT --
466         Copyright 24.06.2007 by Bochkanov Sergey
467    *************************************************************************/
468    public static void splinedifferentiation(ref double[] c,
469        double x,
470        ref double s,
471        ref double ds,
472        ref double d2s)
473    {
474        int n = 0;
475        int l = 0;
476        int r = 0;
477        int m = 0;
478
479        System.Diagnostics.Debug.Assert((int)Math.Round(c[1])==3, "SplineInterpolation: incorrect C!");
480        n = (int)Math.Round(c[2]);
481       
482        //
483        // Binary search
484        //
485        l = 3;
486        r = 3+n-2+1;
487        while( l!=r-1 )
488        {
489            m = (l+r)/2;
490            if( c[m]>=x )
491            {
492                r = m;
493            }
494            else
495            {
496                l = m;
497            }
498        }
499       
500        //
501        // Differentiation
502        //
503        x = x-c[l];
504        m = 3+n+4*(l-3);
505        s = c[m]+x*(c[m+1]+x*(c[m+2]+x*c[m+3]));
506        ds = c[m+1]+2*x*c[m+2]+3*AP.Math.Sqr(x)*c[m+3];
507        d2s = 2*c[m+2]+6*x*c[m+3];
508    }
509
510
511    /*************************************************************************
512    This subroutine makes the copy of the spline.
513
514    Input parameters:
515        C   -   coefficients table. Built by BuildLinearSpline,
516                BuildHermiteSpline, BuildCubicSpline, BuildAkimaSpline.
517
518    Result:
519        CC  -   spline copy
520
521      -- ALGLIB PROJECT --
522         Copyright 29.06.2007 by Bochkanov Sergey
523    *************************************************************************/
524    public static void splinecopy(ref double[] c,
525        ref double[] cc)
526    {
527        int s = 0;
528        int i_ = 0;
529
530        s = (int)Math.Round(c[0]);
531        cc = new double[s-1+1];
532        for(i_=0; i_<=s-1;i_++)
533        {
534            cc[i_] = c[i_];
535        }
536    }
537
538
539    /*************************************************************************
540    This subroutine unpacks the spline into the coefficients table.
541
542    Input parameters:
543        C   -   coefficients table. Built by BuildLinearSpline,
544                BuildHermiteSpline, BuildCubicSpline, BuildAkimaSpline.
545        X   -   point
546
547    Result:
548        Tbl -   coefficients table, unpacked format, array[0..N-2, 0..5].
549                For I = 0...N-2:
550                    Tbl[I,0] = X[i]
551                    Tbl[I,1] = X[i+1]
552                    Tbl[I,2] = C0
553                    Tbl[I,3] = C1
554                    Tbl[I,4] = C2
555                    Tbl[I,5] = C3
556                On [x[i], x[i+1]] spline is equals to:
557                    S(x) = C0 + C1*t + C2*t^2 + C3*t^3
558                    t = x-x[i]
559
560      -- ALGLIB PROJECT --
561         Copyright 29.06.2007 by Bochkanov Sergey
562    *************************************************************************/
563    public static void splineunpack(ref double[] c,
564        ref int n,
565        ref double[,] tbl)
566    {
567        int i = 0;
568
569        System.Diagnostics.Debug.Assert((int)Math.Round(c[1])==3, "SplineUnpack: incorrect C!");
570        n = (int)Math.Round(c[2]);
571        tbl = new double[n-2+1, 5+1];
572       
573        //
574        // Fill
575        //
576        for(i=0; i<=n-2; i++)
577        {
578            tbl[i,0] = c[3+i];
579            tbl[i,1] = c[3+i+1];
580            tbl[i,2] = c[3+n+4*i];
581            tbl[i,3] = c[3+n+4*i+1];
582            tbl[i,4] = c[3+n+4*i+2];
583            tbl[i,5] = c[3+n+4*i+3];
584        }
585    }
586
587
588    /*************************************************************************
589    This subroutine performs linear transformation of the spline argument.
590
591    Input parameters:
592        C   -   coefficients table. Built by BuildLinearSpline,
593                BuildHermiteSpline, BuildCubicSpline, BuildAkimaSpline.
594        A, B-   transformation coefficients: x = A*t + B
595    Result:
596        C   -   transformed spline
597
598      -- ALGLIB PROJECT --
599         Copyright 30.06.2007 by Bochkanov Sergey
600    *************************************************************************/
601    public static void splinelintransx(ref double[] c,
602        double a,
603        double b)
604    {
605        int i = 0;
606        int n = 0;
607        double v = 0;
608        double dv = 0;
609        double d2v = 0;
610        double[] x = new double[0];
611        double[] y = new double[0];
612        double[] d = new double[0];
613
614        System.Diagnostics.Debug.Assert((int)Math.Round(c[1])==3, "SplineLinTransX: incorrect C!");
615        n = (int)Math.Round(c[2]);
616       
617        //
618        // Special case: A=0
619        //
620        if( a==0 )
621        {
622            v = splineinterpolation(ref c, b);
623            for(i=0; i<=n-2; i++)
624            {
625                c[3+n+4*i] = v;
626                c[3+n+4*i+1] = 0;
627                c[3+n+4*i+2] = 0;
628                c[3+n+4*i+3] = 0;
629            }
630            return;
631        }
632       
633        //
634        // General case: A<>0.
635        // Unpack, X, Y, dY/dX.
636        // Scale and pack again.
637        //
638        x = new double[n-1+1];
639        y = new double[n-1+1];
640        d = new double[n-1+1];
641        for(i=0; i<=n-1; i++)
642        {
643            x[i] = c[3+i];
644            splinedifferentiation(ref c, x[i], ref v, ref dv, ref d2v);
645            x[i] = (x[i]-b)/a;
646            y[i] = v;
647            d[i] = a*dv;
648        }
649        buildhermitespline(x, y, d, n, ref c);
650    }
651
652
653    /*************************************************************************
654    This subroutine performs linear transformation of the spline.
655
656    Input parameters:
657        C   -   coefficients table. Built by BuildLinearSpline,
658                BuildHermiteSpline, BuildCubicSpline, BuildAkimaSpline.
659        A, B-   transformation coefficients: S2(x) = A*S(x) + B
660    Result:
661        C   -   transformed spline
662
663      -- ALGLIB PROJECT --
664         Copyright 30.06.2007 by Bochkanov Sergey
665    *************************************************************************/
666    public static void splinelintransy(ref double[] c,
667        double a,
668        double b)
669    {
670        int i = 0;
671        int n = 0;
672        double v = 0;
673        double dv = 0;
674        double d2v = 0;
675        double[] x = new double[0];
676        double[] y = new double[0];
677        double[] d = new double[0];
678
679        System.Diagnostics.Debug.Assert((int)Math.Round(c[1])==3, "SplineLinTransX: incorrect C!");
680        n = (int)Math.Round(c[2]);
681       
682        //
683        // Special case: A=0
684        //
685        for(i=0; i<=n-2; i++)
686        {
687            c[3+n+4*i] = a*c[3+n+4*i]+b;
688            c[3+n+4*i+1] = a*c[3+n+4*i+1];
689            c[3+n+4*i+2] = a*c[3+n+4*i+2];
690            c[3+n+4*i+3] = a*c[3+n+4*i+3];
691        }
692    }
693
694
695    /*************************************************************************
696    This subroutine integrates the spline.
697
698    Input parameters:
699        C   -   coefficients table. Built by BuildLinearSpline,
700                BuildHermiteSpline, BuildCubicSpline, BuildAkimaSpline.
701        X   -   right bound of the integration interval [a, x]
702    Result:
703        integral(S(t)dt,a,x)
704
705      -- ALGLIB PROJECT --
706         Copyright 23.06.2007 by Bochkanov Sergey
707    *************************************************************************/
708    public static double splineintegration(ref double[] c,
709        double x)
710    {
711        double result = 0;
712        int n = 0;
713        int i = 0;
714        int l = 0;
715        int r = 0;
716        int m = 0;
717        double w = 0;
718
719        System.Diagnostics.Debug.Assert((int)Math.Round(c[1])==3, "SplineIntegration: incorrect C!");
720        n = (int)Math.Round(c[2]);
721       
722        //
723        // Binary search in the [ x[0], ..., x[n-2] ] (x[n-1] is not included)
724        //
725        l = 3;
726        r = 3+n-2+1;
727        while( l!=r-1 )
728        {
729            m = (l+r)/2;
730            if( c[m]>=x )
731            {
732                r = m;
733            }
734            else
735            {
736                l = m;
737            }
738        }
739       
740        //
741        // Integration
742        //
743        result = 0;
744        for(i=3; i<=l-1; i++)
745        {
746            w = c[i+1]-c[i];
747            m = 3+n+4*(i-3);
748            result = result+c[m]*w;
749            result = result+c[m+1]*AP.Math.Sqr(w)/2;
750            result = result+c[m+2]*AP.Math.Sqr(w)*w/3;
751            result = result+c[m+3]*AP.Math.Sqr(AP.Math.Sqr(w))/4;
752        }
753        w = x-c[l];
754        m = 3+n+4*(l-3);
755        result = result+c[m]*w;
756        result = result+c[m+1]*AP.Math.Sqr(w)/2;
757        result = result+c[m+2]*AP.Math.Sqr(w)*w/3;
758        result = result+c[m+3]*AP.Math.Sqr(AP.Math.Sqr(w))/4;
759        return result;
760    }
761
762
763    /*************************************************************************
764    Obsolete subroutine, left for backward compatibility.
765    *************************************************************************/
766    public static void spline3buildtable(int n,
767        int diffn,
768        double[] x,
769        double[] y,
770        double boundl,
771        double boundr,
772        ref double[,] ctbl)
773    {
774        bool c = new bool();
775        int e = 0;
776        int g = 0;
777        double tmp = 0;
778        int nxm1 = 0;
779        int i = 0;
780        int j = 0;
781        double dx = 0;
782        double dxj = 0;
783        double dyj = 0;
784        double dxjp1 = 0;
785        double dyjp1 = 0;
786        double dxp = 0;
787        double dyp = 0;
788        double yppa = 0;
789        double yppb = 0;
790        double pj = 0;
791        double b1 = 0;
792        double b2 = 0;
793        double b3 = 0;
794        double b4 = 0;
795
796        x = (double[])x.Clone();
797        y = (double[])y.Clone();
798
799        n = n-1;
800        g = (n+1)/2;
801        do
802        {
803            i = g;
804            do
805            {
806                j = i-g;
807                c = true;
808                do
809                {
810                    if( x[j]<=x[j+g] )
811                    {
812                        c = false;
813                    }
814                    else
815                    {
816                        tmp = x[j];
817                        x[j] = x[j+g];
818                        x[j+g] = tmp;
819                        tmp = y[j];
820                        y[j] = y[j+g];
821                        y[j+g] = tmp;
822                    }
823                    j = j-1;
824                }
825                while( j>=0 & c );
826                i = i+1;
827            }
828            while( i<=n );
829            g = g/2;
830        }
831        while( g>0 );
832        ctbl = new double[4+1, n+1];
833        n = n+1;
834        if( diffn==1 )
835        {
836            b1 = 1;
837            b2 = 6/(x[1]-x[0])*((y[1]-y[0])/(x[1]-x[0])-boundl);
838            b3 = 1;
839            b4 = 6/(x[n-1]-x[n-2])*(boundr-(y[n-1]-y[n-2])/(x[n-1]-x[n-2]));
840        }
841        else
842        {
843            b1 = 0;
844            b2 = 2*boundl;
845            b3 = 0;
846            b4 = 2*boundr;
847        }
848        nxm1 = n-1;
849        if( n>=2 )
850        {
851            if( n>2 )
852            {
853                dxj = x[1]-x[0];
854                dyj = y[1]-y[0];
855                j = 2;
856                while( j<=nxm1 )
857                {
858                    dxjp1 = x[j]-x[j-1];
859                    dyjp1 = y[j]-y[j-1];
860                    dxp = dxj+dxjp1;
861                    ctbl[1,j-1] = dxjp1/dxp;
862                    ctbl[2,j-1] = 1-ctbl[1,j-1];
863                    ctbl[3,j-1] = 6*(dyjp1/dxjp1-dyj/dxj)/dxp;
864                    dxj = dxjp1;
865                    dyj = dyjp1;
866                    j = j+1;
867                }
868            }
869            ctbl[1,0] = -(b1/2);
870            ctbl[2,0] = b2/2;
871            if( n!=2 )
872            {
873                j = 2;
874                while( j<=nxm1 )
875                {
876                    pj = ctbl[2,j-1]*ctbl[1,j-2]+2;
877                    ctbl[1,j-1] = -(ctbl[1,j-1]/pj);
878                    ctbl[2,j-1] = (ctbl[3,j-1]-ctbl[2,j-1]*ctbl[2,j-2])/pj;
879                    j = j+1;
880                }
881            }
882            yppb = (b4-b3*ctbl[2,nxm1-1])/(b3*ctbl[1,nxm1-1]+2);
883            i = 1;
884            while( i<=nxm1 )
885            {
886                j = n-i;
887                yppa = ctbl[1,j-1]*yppb+ctbl[2,j-1];
888                dx = x[j]-x[j-1];
889                ctbl[3,j-1] = (yppb-yppa)/dx/6;
890                ctbl[2,j-1] = yppa/2;
891                ctbl[1,j-1] = (y[j]-y[j-1])/dx-(ctbl[2,j-1]+ctbl[3,j-1]*dx)*dx;
892                yppb = yppa;
893                i = i+1;
894            }
895            for(i=1; i<=n; i++)
896            {
897                ctbl[0,i-1] = y[i-1];
898                ctbl[4,i-1] = x[i-1];
899            }
900        }
901    }
902
903
904    /*************************************************************************
905    Obsolete subroutine, left for backward compatibility.
906    *************************************************************************/
907    public static double spline3interpolate(int n,
908        ref double[,] c,
909        double x)
910    {
911        double result = 0;
912        int i = 0;
913        int l = 0;
914        int half = 0;
915        int first = 0;
916        int middle = 0;
917
918        n = n-1;
919        l = n;
920        first = 0;
921        while( l>0 )
922        {
923            half = l/2;
924            middle = first+half;
925            if( c[4,middle]<x )
926            {
927                first = middle+1;
928                l = l-half-1;
929            }
930            else
931            {
932                l = half;
933            }
934        }
935        i = first-1;
936        if( i<0 )
937        {
938            i = 0;
939        }
940        result = c[0,i]+(x-c[4,i])*(c[1,i]+(x-c[4,i])*(c[2,i]+c[3,i]*(x-c[4,i])));
941        return result;
942    }
943
944
945    /*************************************************************************
946    Internal subroutine. Heap sort.
947    *************************************************************************/
948    private static void heapsortpoints(ref double[] x,
949        ref double[] y,
950        int n)
951    {
952        int i = 0;
953        int j = 0;
954        int k = 0;
955        int t = 0;
956        double tmp = 0;
957        bool isascending = new bool();
958        bool isdescending = new bool();
959
960       
961        //
962        // Test for already sorted set
963        //
964        isascending = true;
965        isdescending = true;
966        for(i=1; i<=n-1; i++)
967        {
968            isascending = isascending & x[i]>x[i-1];
969            isdescending = isdescending & x[i]<x[i-1];
970        }
971        if( isascending )
972        {
973            return;
974        }
975        if( isdescending )
976        {
977            for(i=0; i<=n-1; i++)
978            {
979                j = n-1-i;
980                if( j<=i )
981                {
982                    break;
983                }
984                tmp = x[i];
985                x[i] = x[j];
986                x[j] = tmp;
987                tmp = y[i];
988                y[i] = y[j];
989                y[j] = tmp;
990            }
991            return;
992        }
993       
994        //
995        // Special case: N=1
996        //
997        if( n==1 )
998        {
999            return;
1000        }
1001       
1002        //
1003        // General case
1004        //
1005        i = 2;
1006        do
1007        {
1008            t = i;
1009            while( t!=1 )
1010            {
1011                k = t/2;
1012                if( x[k-1]>=x[t-1] )
1013                {
1014                    t = 1;
1015                }
1016                else
1017                {
1018                    tmp = x[k-1];
1019                    x[k-1] = x[t-1];
1020                    x[t-1] = tmp;
1021                    tmp = y[k-1];
1022                    y[k-1] = y[t-1];
1023                    y[t-1] = tmp;
1024                    t = k;
1025                }
1026            }
1027            i = i+1;
1028        }
1029        while( i<=n );
1030        i = n-1;
1031        do
1032        {
1033            tmp = x[i];
1034            x[i] = x[0];
1035            x[0] = tmp;
1036            tmp = y[i];
1037            y[i] = y[0];
1038            y[0] = tmp;
1039            t = 1;
1040            while( t!=0 )
1041            {
1042                k = 2*t;
1043                if( k>i )
1044                {
1045                    t = 0;
1046                }
1047                else
1048                {
1049                    if( k<i )
1050                    {
1051                        if( x[k]>x[k-1] )
1052                        {
1053                            k = k+1;
1054                        }
1055                    }
1056                    if( x[t-1]>=x[k-1] )
1057                    {
1058                        t = 0;
1059                    }
1060                    else
1061                    {
1062                        tmp = x[k-1];
1063                        x[k-1] = x[t-1];
1064                        x[t-1] = tmp;
1065                        tmp = y[k-1];
1066                        y[k-1] = y[t-1];
1067                        y[t-1] = tmp;
1068                        t = k;
1069                    }
1070                }
1071            }
1072            i = i-1;
1073        }
1074        while( i>=1 );
1075    }
1076
1077
1078    /*************************************************************************
1079    Internal subroutine. Heap sort.
1080    *************************************************************************/
1081    private static void heapsortdpoints(ref double[] x,
1082        ref double[] y,
1083        ref double[] d,
1084        int n)
1085    {
1086        int i = 0;
1087        int j = 0;
1088        int k = 0;
1089        int t = 0;
1090        double tmp = 0;
1091        bool isascending = new bool();
1092        bool isdescending = new bool();
1093
1094       
1095        //
1096        // Test for already sorted set
1097        //
1098        isascending = true;
1099        isdescending = true;
1100        for(i=1; i<=n-1; i++)
1101        {
1102            isascending = isascending & x[i]>x[i-1];
1103            isdescending = isdescending & x[i]<x[i-1];
1104        }
1105        if( isascending )
1106        {
1107            return;
1108        }
1109        if( isdescending )
1110        {
1111            for(i=0; i<=n-1; i++)
1112            {
1113                j = n-1-i;
1114                if( j<=i )
1115                {
1116                    break;
1117                }
1118                tmp = x[i];
1119                x[i] = x[j];
1120                x[j] = tmp;
1121                tmp = y[i];
1122                y[i] = y[j];
1123                y[j] = tmp;
1124                tmp = d[i];
1125                d[i] = d[j];
1126                d[j] = tmp;
1127            }
1128            return;
1129        }
1130       
1131        //
1132        // Special case: N=1
1133        //
1134        if( n==1 )
1135        {
1136            return;
1137        }
1138       
1139        //
1140        // General case
1141        //
1142        i = 2;
1143        do
1144        {
1145            t = i;
1146            while( t!=1 )
1147            {
1148                k = t/2;
1149                if( x[k-1]>=x[t-1] )
1150                {
1151                    t = 1;
1152                }
1153                else
1154                {
1155                    tmp = x[k-1];
1156                    x[k-1] = x[t-1];
1157                    x[t-1] = tmp;
1158                    tmp = y[k-1];
1159                    y[k-1] = y[t-1];
1160                    y[t-1] = tmp;
1161                    tmp = d[k-1];
1162                    d[k-1] = d[t-1];
1163                    d[t-1] = tmp;
1164                    t = k;
1165                }
1166            }
1167            i = i+1;
1168        }
1169        while( i<=n );
1170        i = n-1;
1171        do
1172        {
1173            tmp = x[i];
1174            x[i] = x[0];
1175            x[0] = tmp;
1176            tmp = y[i];
1177            y[i] = y[0];
1178            y[0] = tmp;
1179            tmp = d[i];
1180            d[i] = d[0];
1181            d[0] = tmp;
1182            t = 1;
1183            while( t!=0 )
1184            {
1185                k = 2*t;
1186                if( k>i )
1187                {
1188                    t = 0;
1189                }
1190                else
1191                {
1192                    if( k<i )
1193                    {
1194                        if( x[k]>x[k-1] )
1195                        {
1196                            k = k+1;
1197                        }
1198                    }
1199                    if( x[t-1]>=x[k-1] )
1200                    {
1201                        t = 0;
1202                    }
1203                    else
1204                    {
1205                        tmp = x[k-1];
1206                        x[k-1] = x[t-1];
1207                        x[t-1] = tmp;
1208                        tmp = y[k-1];
1209                        y[k-1] = y[t-1];
1210                        y[t-1] = tmp;
1211                        tmp = d[k-1];
1212                        d[k-1] = d[t-1];
1213                        d[t-1] = tmp;
1214                        t = k;
1215                    }
1216                }
1217            }
1218            i = i-1;
1219        }
1220        while( i>=1 );
1221    }
1222
1223
1224    /*************************************************************************
1225    Internal subroutine. Tridiagonal solver.
1226    *************************************************************************/
1227    private static void solvetridiagonal(double[] a,
1228        double[] b,
1229        double[] c,
1230        double[] d,
1231        int n,
1232        ref double[] x)
1233    {
1234        int k = 0;
1235        double t = 0;
1236
1237        a = (double[])a.Clone();
1238        b = (double[])b.Clone();
1239        c = (double[])c.Clone();
1240        d = (double[])d.Clone();
1241
1242        x = new double[n-1+1];
1243        a[0] = 0;
1244        c[n-1] = 0;
1245        for(k=1; k<=n-1; k++)
1246        {
1247            t = a[k]/b[k-1];
1248            b[k] = b[k]-t*c[k-1];
1249            d[k] = d[k]-t*d[k-1];
1250        }
1251        x[n-1] = d[n-1]/b[n-1];
1252        for(k=n-2; k>=0; k--)
1253        {
1254            x[k] = (d[k]-c[k]*x[k+1])/b[k];
1255        }
1256    }
1257
1258
1259    /*************************************************************************
1260    Internal subroutine. Three-point differentiation
1261    *************************************************************************/
1262    private static double diffthreepoint(double t,
1263        double x0,
1264        double f0,
1265        double x1,
1266        double f1,
1267        double x2,
1268        double f2)
1269    {
1270        double result = 0;
1271        double a = 0;
1272        double b = 0;
1273
1274        t = t-x0;
1275        x1 = x1-x0;
1276        x2 = x2-x0;
1277        a = (f2-f0-x2/x1*(f1-f0))/(AP.Math.Sqr(x2)-x1*x2);
1278        b = (f1-f0-a*AP.Math.Sqr(x1))/x1;
1279        result = 2*a*t+b;
1280        return result;
1281    }
1282}
Note: See TracBrowser for help on using the repository browser.