Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/ALGLIB/spline2d.cs @ 2599

Last change on this file since 2599 was 2563, checked in by gkronber, 14 years ago

Updated ALGLIB to latest version. #751 (Plugin for for data-modeling with ANN (integrated into CEDMA))

File size: 43.8 KB
Line 
1/*************************************************************************
2Copyright (c) 2007, Sergey Bochkanov (ALGLIB project).
3
4>>> SOURCE LICENSE >>>
5This program is free software; you can redistribute it and/or modify
6it under the terms of the GNU General Public License as published by
7the Free Software Foundation (www.fsf.org); either version 2 of the
8License, or (at your option) any later version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13GNU General Public License for more details.
14
15A copy of the GNU General Public License is available at
16http://www.fsf.org/licensing/licenses
17
18>>> END OF LICENSE >>>
19*************************************************************************/
20
21using System;
22
23namespace alglib
24{
25    public class spline2d
26    {
27        /*************************************************************************
28        2-dimensional spline inteprolant
29        *************************************************************************/
30        public struct spline2dinterpolant
31        {
32            public int k;
33            public double[] c;
34        };
35
36
37
38
39        public const int spline2dvnum = 12;
40
41
42        /*************************************************************************
43        This subroutine builds bilinear spline coefficients table.
44
45        Input parameters:
46            X   -   spline abscissas, array[0..N-1]
47            Y   -   spline ordinates, array[0..M-1]
48            F   -   function values, array[0..M-1,0..N-1]
49            M,N -   grid size, M>=2, N>=2
50
51        Output parameters:
52            C   -   spline interpolant
53
54          -- ALGLIB PROJECT --
55             Copyright 05.07.2007 by Bochkanov Sergey
56        *************************************************************************/
57        public static void spline2dbuildbilinear(double[] x,
58            double[] y,
59            double[,] f,
60            int m,
61            int n,
62            ref spline2dinterpolant c)
63        {
64            int i = 0;
65            int j = 0;
66            int k = 0;
67            int tblsize = 0;
68            int shift = 0;
69            double t = 0;
70            double[,] dx = new double[0,0];
71            double[,] dy = new double[0,0];
72            double[,] dxy = new double[0,0];
73
74            x = (double[])x.Clone();
75            y = (double[])y.Clone();
76            f = (double[,])f.Clone();
77
78            System.Diagnostics.Debug.Assert(n>=2 & m>=2, "Spline2DBuildBilinear: N<2 or M<2!");
79           
80            //
81            // Sort points
82            //
83            for(j=0; j<=n-1; j++)
84            {
85                k = j;
86                for(i=j+1; i<=n-1; i++)
87                {
88                    if( (double)(x[i])<(double)(x[k]) )
89                    {
90                        k = i;
91                    }
92                }
93                if( k!=j )
94                {
95                    for(i=0; i<=m-1; i++)
96                    {
97                        t = f[i,j];
98                        f[i,j] = f[i,k];
99                        f[i,k] = t;
100                    }
101                    t = x[j];
102                    x[j] = x[k];
103                    x[k] = t;
104                }
105            }
106            for(i=0; i<=m-1; i++)
107            {
108                k = i;
109                for(j=i+1; j<=m-1; j++)
110                {
111                    if( (double)(y[j])<(double)(y[k]) )
112                    {
113                        k = j;
114                    }
115                }
116                if( k!=i )
117                {
118                    for(j=0; j<=n-1; j++)
119                    {
120                        t = f[i,j];
121                        f[i,j] = f[k,j];
122                        f[k,j] = t;
123                    }
124                    t = y[i];
125                    y[i] = y[k];
126                    y[k] = t;
127                }
128            }
129           
130            //
131            // Fill C:
132            //  C[0]            -   length(C)
133            //  C[1]            -   type(C):
134            //                      -1 = bilinear interpolant
135            //                      -3 = general cubic spline
136            //                           (see BuildBicubicSpline)
137            //  C[2]:
138            //      N (x count)
139            //  C[3]:
140            //      M (y count)
141            //  C[4]...C[4+N-1]:
142            //      x[i], i = 0...N-1
143            //  C[4+N]...C[4+N+M-1]:
144            //      y[i], i = 0...M-1
145            //  C[4+N+M]...C[4+N+M+(N*M-1)]:
146            //      f(i,j) table. f(0,0), f(0, 1), f(0,2) and so on...
147            //
148            c.k = 1;
149            tblsize = 4+n+m+n*m;
150            c.c = new double[tblsize-1+1];
151            c.c[0] = tblsize;
152            c.c[1] = -1;
153            c.c[2] = n;
154            c.c[3] = m;
155            for(i=0; i<=n-1; i++)
156            {
157                c.c[4+i] = x[i];
158            }
159            for(i=0; i<=m-1; i++)
160            {
161                c.c[4+n+i] = y[i];
162            }
163            for(i=0; i<=m-1; i++)
164            {
165                for(j=0; j<=n-1; j++)
166                {
167                    shift = i*n+j;
168                    c.c[4+n+m+shift] = f[i,j];
169                }
170            }
171        }
172
173
174        /*************************************************************************
175        This subroutine builds bicubic spline coefficients table.
176
177        Input parameters:
178            X   -   spline abscissas, array[0..N-1]
179            Y   -   spline ordinates, array[0..M-1]
180            F   -   function values, array[0..M-1,0..N-1]
181            M,N -   grid size, M>=2, N>=2
182
183        Output parameters:
184            C   -   spline interpolant
185
186          -- ALGLIB PROJECT --
187             Copyright 05.07.2007 by Bochkanov Sergey
188        *************************************************************************/
189        public static void spline2dbuildbicubic(double[] x,
190            double[] y,
191            double[,] f,
192            int m,
193            int n,
194            ref spline2dinterpolant c)
195        {
196            int i = 0;
197            int j = 0;
198            int k = 0;
199            int tblsize = 0;
200            int shift = 0;
201            double t = 0;
202            double[,] dx = new double[0,0];
203            double[,] dy = new double[0,0];
204            double[,] dxy = new double[0,0];
205
206            x = (double[])x.Clone();
207            y = (double[])y.Clone();
208            f = (double[,])f.Clone();
209
210            System.Diagnostics.Debug.Assert(n>=2 & m>=2, "BuildBicubicSpline: N<2 or M<2!");
211           
212            //
213            // Sort points
214            //
215            for(j=0; j<=n-1; j++)
216            {
217                k = j;
218                for(i=j+1; i<=n-1; i++)
219                {
220                    if( (double)(x[i])<(double)(x[k]) )
221                    {
222                        k = i;
223                    }
224                }
225                if( k!=j )
226                {
227                    for(i=0; i<=m-1; i++)
228                    {
229                        t = f[i,j];
230                        f[i,j] = f[i,k];
231                        f[i,k] = t;
232                    }
233                    t = x[j];
234                    x[j] = x[k];
235                    x[k] = t;
236                }
237            }
238            for(i=0; i<=m-1; i++)
239            {
240                k = i;
241                for(j=i+1; j<=m-1; j++)
242                {
243                    if( (double)(y[j])<(double)(y[k]) )
244                    {
245                        k = j;
246                    }
247                }
248                if( k!=i )
249                {
250                    for(j=0; j<=n-1; j++)
251                    {
252                        t = f[i,j];
253                        f[i,j] = f[k,j];
254                        f[k,j] = t;
255                    }
256                    t = y[i];
257                    y[i] = y[k];
258                    y[k] = t;
259                }
260            }
261           
262            //
263            // Fill C:
264            //  C[0]            -   length(C)
265            //  C[1]            -   type(C):
266            //                      -1 = bilinear interpolant
267            //                           (see BuildBilinearInterpolant)
268            //                      -3 = general cubic spline
269            //  C[2]:
270            //      N (x count)
271            //  C[3]:
272            //      M (y count)
273            //  C[4]...C[4+N-1]:
274            //      x[i], i = 0...N-1
275            //  C[4+N]...C[4+N+M-1]:
276            //      y[i], i = 0...M-1
277            //  C[4+N+M]...C[4+N+M+(N*M-1)]:
278            //      f(i,j) table. f(0,0), f(0, 1), f(0,2) and so on...
279            //  C[4+N+M+N*M]...C[4+N+M+(2*N*M-1)]:
280            //      df(i,j)/dx table.
281            //  C[4+N+M+2*N*M]...C[4+N+M+(3*N*M-1)]:
282            //      df(i,j)/dy table.
283            //  C[4+N+M+3*N*M]...C[4+N+M+(4*N*M-1)]:
284            //      d2f(i,j)/dxdy table.
285            //
286            c.k = 3;
287            tblsize = 4+n+m+4*n*m;
288            c.c = new double[tblsize-1+1];
289            c.c[0] = tblsize;
290            c.c[1] = -3;
291            c.c[2] = n;
292            c.c[3] = m;
293            for(i=0; i<=n-1; i++)
294            {
295                c.c[4+i] = x[i];
296            }
297            for(i=0; i<=m-1; i++)
298            {
299                c.c[4+n+i] = y[i];
300            }
301            bicubiccalcderivatives(ref f, ref x, ref y, m, n, ref dx, ref dy, ref dxy);
302            for(i=0; i<=m-1; i++)
303            {
304                for(j=0; j<=n-1; j++)
305                {
306                    shift = i*n+j;
307                    c.c[4+n+m+shift] = f[i,j];
308                    c.c[4+n+m+n*m+shift] = dx[i,j];
309                    c.c[4+n+m+2*n*m+shift] = dy[i,j];
310                    c.c[4+n+m+3*n*m+shift] = dxy[i,j];
311                }
312            }
313        }
314
315
316        /*************************************************************************
317        This subroutine calculates the value of the bilinear or bicubic spline  at
318        the given point X.
319
320        Input parameters:
321            C   -   coefficients table.
322                    Built by BuildBilinearSpline or BuildBicubicSpline.
323            X, Y-   point
324
325        Result:
326            S(x,y)
327
328          -- ALGLIB PROJECT --
329             Copyright 05.07.2007 by Bochkanov Sergey
330        *************************************************************************/
331        public static double spline2dcalc(ref spline2dinterpolant c,
332            double x,
333            double y)
334        {
335            double result = 0;
336            double v = 0;
337            double vx = 0;
338            double vy = 0;
339            double vxy = 0;
340
341            spline2ddiff(ref c, x, y, ref v, ref vx, ref vy, ref vxy);
342            result = v;
343            return result;
344        }
345
346
347        /*************************************************************************
348        This subroutine calculates the value of the bilinear or bicubic spline  at
349        the given point X and its derivatives.
350
351        Input parameters:
352            C   -   spline interpolant.
353            X, Y-   point
354
355        Output parameters:
356            F   -   S(x,y)
357            FX  -   dS(x,y)/dX
358            FY  -   dS(x,y)/dY
359            FXY -   d2S(x,y)/dXdY
360
361          -- ALGLIB PROJECT --
362             Copyright 05.07.2007 by Bochkanov Sergey
363        *************************************************************************/
364        public static void spline2ddiff(ref spline2dinterpolant c,
365            double x,
366            double y,
367            ref double f,
368            ref double fx,
369            ref double fy,
370            ref double fxy)
371        {
372            int n = 0;
373            int m = 0;
374            double t = 0;
375            double dt = 0;
376            double u = 0;
377            double du = 0;
378            int i = 0;
379            int j = 0;
380            int ix = 0;
381            int iy = 0;
382            int l = 0;
383            int r = 0;
384            int h = 0;
385            int shift1 = 0;
386            int s1 = 0;
387            int s2 = 0;
388            int s3 = 0;
389            int s4 = 0;
390            int sf = 0;
391            int sfx = 0;
392            int sfy = 0;
393            int sfxy = 0;
394            double y1 = 0;
395            double y2 = 0;
396            double y3 = 0;
397            double y4 = 0;
398            double v = 0;
399            double t0 = 0;
400            double t1 = 0;
401            double t2 = 0;
402            double t3 = 0;
403            double u0 = 0;
404            double u1 = 0;
405            double u2 = 0;
406            double u3 = 0;
407
408            System.Diagnostics.Debug.Assert((int)Math.Round(c.c[1])==-1 | (int)Math.Round(c.c[1])==-3, "Spline2DDiff: incorrect C!");
409            n = (int)Math.Round(c.c[2]);
410            m = (int)Math.Round(c.c[3]);
411           
412            //
413            // Binary search in the [ x[0], ..., x[n-2] ] (x[n-1] is not included)
414            //
415            l = 4;
416            r = 4+n-2+1;
417            while( l!=r-1 )
418            {
419                h = (l+r)/2;
420                if( (double)(c.c[h])>=(double)(x) )
421                {
422                    r = h;
423                }
424                else
425                {
426                    l = h;
427                }
428            }
429            t = (x-c.c[l])/(c.c[l+1]-c.c[l]);
430            dt = 1.0/(c.c[l+1]-c.c[l]);
431            ix = l-4;
432           
433            //
434            // Binary search in the [ y[0], ..., y[m-2] ] (y[m-1] is not included)
435            //
436            l = 4+n;
437            r = 4+n+(m-2)+1;
438            while( l!=r-1 )
439            {
440                h = (l+r)/2;
441                if( (double)(c.c[h])>=(double)(y) )
442                {
443                    r = h;
444                }
445                else
446                {
447                    l = h;
448                }
449            }
450            u = (y-c.c[l])/(c.c[l+1]-c.c[l]);
451            du = 1.0/(c.c[l+1]-c.c[l]);
452            iy = l-(4+n);
453           
454            //
455            // Prepare F, dF/dX, dF/dY, d2F/dXdY
456            //
457            f = 0;
458            fx = 0;
459            fy = 0;
460            fxy = 0;
461           
462            //
463            // Bilinear interpolation
464            //
465            if( (int)Math.Round(c.c[1])==-1 )
466            {
467                shift1 = 4+n+m;
468                y1 = c.c[shift1+n*iy+ix];
469                y2 = c.c[shift1+n*iy+(ix+1)];
470                y3 = c.c[shift1+n*(iy+1)+(ix+1)];
471                y4 = c.c[shift1+n*(iy+1)+ix];
472                f = (1-t)*(1-u)*y1+t*(1-u)*y2+t*u*y3+(1-t)*u*y4;
473                fx = (-((1-u)*y1)+(1-u)*y2+u*y3-u*y4)*dt;
474                fy = (-((1-t)*y1)-t*y2+t*y3+(1-t)*y4)*du;
475                fxy = (y1-y2+y3-y4)*du*dt;
476                return;
477            }
478           
479            //
480            // Bicubic interpolation
481            //
482            if( (int)Math.Round(c.c[1])==-3 )
483            {
484               
485                //
486                // Prepare info
487                //
488                t0 = 1;
489                t1 = t;
490                t2 = AP.Math.Sqr(t);
491                t3 = t*t2;
492                u0 = 1;
493                u1 = u;
494                u2 = AP.Math.Sqr(u);
495                u3 = u*u2;
496                sf = 4+n+m;
497                sfx = 4+n+m+n*m;
498                sfy = 4+n+m+2*n*m;
499                sfxy = 4+n+m+3*n*m;
500                s1 = n*iy+ix;
501                s2 = n*iy+(ix+1);
502                s3 = n*(iy+1)+(ix+1);
503                s4 = n*(iy+1)+ix;
504               
505                //
506                // Calculate
507                //
508                v = +(1*c.c[sf+s1]);
509                f = f+v*t0*u0;
510                v = +(1*c.c[sfy+s1]/du);
511                f = f+v*t0*u1;
512                fy = fy+1*v*t0*u0*du;
513                v = -(3*c.c[sf+s1])+3*c.c[sf+s4]-2*c.c[sfy+s1]/du-1*c.c[sfy+s4]/du;
514                f = f+v*t0*u2;
515                fy = fy+2*v*t0*u1*du;
516                v = +(2*c.c[sf+s1])-2*c.c[sf+s4]+1*c.c[sfy+s1]/du+1*c.c[sfy+s4]/du;
517                f = f+v*t0*u3;
518                fy = fy+3*v*t0*u2*du;
519                v = +(1*c.c[sfx+s1]/dt);
520                f = f+v*t1*u0;
521                fx = fx+1*v*t0*u0*dt;
522                v = +(1*c.c[sfxy+s1]/(dt*du));
523                f = f+v*t1*u1;
524                fx = fx+1*v*t0*u1*dt;
525                fy = fy+1*v*t1*u0*du;
526                fxy = fxy+1*v*t0*u0*dt*du;
527                v = -(3*c.c[sfx+s1]/dt)+3*c.c[sfx+s4]/dt-2*c.c[sfxy+s1]/(dt*du)-1*c.c[sfxy+s4]/(dt*du);
528                f = f+v*t1*u2;
529                fx = fx+1*v*t0*u2*dt;
530                fy = fy+2*v*t1*u1*du;
531                fxy = fxy+2*v*t0*u1*dt*du;
532                v = +(2*c.c[sfx+s1]/dt)-2*c.c[sfx+s4]/dt+1*c.c[sfxy+s1]/(dt*du)+1*c.c[sfxy+s4]/(dt*du);
533                f = f+v*t1*u3;
534                fx = fx+1*v*t0*u3*dt;
535                fy = fy+3*v*t1*u2*du;
536                fxy = fxy+3*v*t0*u2*dt*du;
537                v = -(3*c.c[sf+s1])+3*c.c[sf+s2]-2*c.c[sfx+s1]/dt-1*c.c[sfx+s2]/dt;
538                f = f+v*t2*u0;
539                fx = fx+2*v*t1*u0*dt;
540                v = -(3*c.c[sfy+s1]/du)+3*c.c[sfy+s2]/du-2*c.c[sfxy+s1]/(dt*du)-1*c.c[sfxy+s2]/(dt*du);
541                f = f+v*t2*u1;
542                fx = fx+2*v*t1*u1*dt;
543                fy = fy+1*v*t2*u0*du;
544                fxy = fxy+2*v*t1*u0*dt*du;
545                v = +(9*c.c[sf+s1])-9*c.c[sf+s2]+9*c.c[sf+s3]-9*c.c[sf+s4]+6*c.c[sfx+s1]/dt+3*c.c[sfx+s2]/dt-3*c.c[sfx+s3]/dt-6*c.c[sfx+s4]/dt+6*c.c[sfy+s1]/du-6*c.c[sfy+s2]/du-3*c.c[sfy+s3]/du+3*c.c[sfy+s4]/du+4*c.c[sfxy+s1]/(dt*du)+2*c.c[sfxy+s2]/(dt*du)+1*c.c[sfxy+s3]/(dt*du)+2*c.c[sfxy+s4]/(dt*du);
546                f = f+v*t2*u2;
547                fx = fx+2*v*t1*u2*dt;
548                fy = fy+2*v*t2*u1*du;
549                fxy = fxy+4*v*t1*u1*dt*du;
550                v = -(6*c.c[sf+s1])+6*c.c[sf+s2]-6*c.c[sf+s3]+6*c.c[sf+s4]-4*c.c[sfx+s1]/dt-2*c.c[sfx+s2]/dt+2*c.c[sfx+s3]/dt+4*c.c[sfx+s4]/dt-3*c.c[sfy+s1]/du+3*c.c[sfy+s2]/du+3*c.c[sfy+s3]/du-3*c.c[sfy+s4]/du-2*c.c[sfxy+s1]/(dt*du)-1*c.c[sfxy+s2]/(dt*du)-1*c.c[sfxy+s3]/(dt*du)-2*c.c[sfxy+s4]/(dt*du);
551                f = f+v*t2*u3;
552                fx = fx+2*v*t1*u3*dt;
553                fy = fy+3*v*t2*u2*du;
554                fxy = fxy+6*v*t1*u2*dt*du;
555                v = +(2*c.c[sf+s1])-2*c.c[sf+s2]+1*c.c[sfx+s1]/dt+1*c.c[sfx+s2]/dt;
556                f = f+v*t3*u0;
557                fx = fx+3*v*t2*u0*dt;
558                v = +(2*c.c[sfy+s1]/du)-2*c.c[sfy+s2]/du+1*c.c[sfxy+s1]/(dt*du)+1*c.c[sfxy+s2]/(dt*du);
559                f = f+v*t3*u1;
560                fx = fx+3*v*t2*u1*dt;
561                fy = fy+1*v*t3*u0*du;
562                fxy = fxy+3*v*t2*u0*dt*du;
563                v = -(6*c.c[sf+s1])+6*c.c[sf+s2]-6*c.c[sf+s3]+6*c.c[sf+s4]-3*c.c[sfx+s1]/dt-3*c.c[sfx+s2]/dt+3*c.c[sfx+s3]/dt+3*c.c[sfx+s4]/dt-4*c.c[sfy+s1]/du+4*c.c[sfy+s2]/du+2*c.c[sfy+s3]/du-2*c.c[sfy+s4]/du-2*c.c[sfxy+s1]/(dt*du)-2*c.c[sfxy+s2]/(dt*du)-1*c.c[sfxy+s3]/(dt*du)-1*c.c[sfxy+s4]/(dt*du);
564                f = f+v*t3*u2;
565                fx = fx+3*v*t2*u2*dt;
566                fy = fy+2*v*t3*u1*du;
567                fxy = fxy+6*v*t2*u1*dt*du;
568                v = +(4*c.c[sf+s1])-4*c.c[sf+s2]+4*c.c[sf+s3]-4*c.c[sf+s4]+2*c.c[sfx+s1]/dt+2*c.c[sfx+s2]/dt-2*c.c[sfx+s3]/dt-2*c.c[sfx+s4]/dt+2*c.c[sfy+s1]/du-2*c.c[sfy+s2]/du-2*c.c[sfy+s3]/du+2*c.c[sfy+s4]/du+1*c.c[sfxy+s1]/(dt*du)+1*c.c[sfxy+s2]/(dt*du)+1*c.c[sfxy+s3]/(dt*du)+1*c.c[sfxy+s4]/(dt*du);
569                f = f+v*t3*u3;
570                fx = fx+3*v*t2*u3*dt;
571                fy = fy+3*v*t3*u2*du;
572                fxy = fxy+9*v*t2*u2*dt*du;
573                return;
574            }
575        }
576
577
578        /*************************************************************************
579        This subroutine unpacks two-dimensional spline into the coefficients table
580
581        Input parameters:
582            C   -   spline interpolant.
583
584        Result:
585            M, N-   grid size (x-axis and y-axis)
586            Tbl -   coefficients table, unpacked format,
587                    [0..(N-1)*(M-1)-1, 0..19].
588                    For I = 0...M-2, J=0..N-2:
589                        K =  I*(N-1)+J
590                        Tbl[K,0] = X[j]
591                        Tbl[K,1] = X[j+1]
592                        Tbl[K,2] = Y[i]
593                        Tbl[K,3] = Y[i+1]
594                        Tbl[K,4] = C00
595                        Tbl[K,5] = C01
596                        Tbl[K,6] = C02
597                        Tbl[K,7] = C03
598                        Tbl[K,8] = C10
599                        Tbl[K,9] = C11
600                        ...
601                        Tbl[K,19] = C33
602                    On each grid square spline is equals to:
603                        S(x) = SUM(c[i,j]*(x^i)*(y^j), i=0..3, j=0..3)
604                        t = x-x[j]
605                        u = y-y[i]
606
607          -- ALGLIB PROJECT --
608             Copyright 29.06.2007 by Bochkanov Sergey
609        *************************************************************************/
610        public static void spline2dunpack(ref spline2dinterpolant c,
611            ref int m,
612            ref int n,
613            ref double[,] tbl)
614        {
615            int i = 0;
616            int j = 0;
617            int ci = 0;
618            int cj = 0;
619            int k = 0;
620            int p = 0;
621            int shift = 0;
622            int s1 = 0;
623            int s2 = 0;
624            int s3 = 0;
625            int s4 = 0;
626            int sf = 0;
627            int sfx = 0;
628            int sfy = 0;
629            int sfxy = 0;
630            double y1 = 0;
631            double y2 = 0;
632            double y3 = 0;
633            double y4 = 0;
634            double dt = 0;
635            double du = 0;
636
637            System.Diagnostics.Debug.Assert((int)Math.Round(c.c[1])==-3 | (int)Math.Round(c.c[1])==-1, "SplineUnpack2D: incorrect C!");
638            n = (int)Math.Round(c.c[2]);
639            m = (int)Math.Round(c.c[3]);
640            tbl = new double[(n-1)*(m-1)-1+1, 19+1];
641           
642            //
643            // Fill
644            //
645            for(i=0; i<=m-2; i++)
646            {
647                for(j=0; j<=n-2; j++)
648                {
649                    p = i*(n-1)+j;
650                    tbl[p,0] = c.c[4+j];
651                    tbl[p,1] = c.c[4+j+1];
652                    tbl[p,2] = c.c[4+n+i];
653                    tbl[p,3] = c.c[4+n+i+1];
654                    dt = 1/(tbl[p,1]-tbl[p,0]);
655                    du = 1/(tbl[p,3]-tbl[p,2]);
656                   
657                    //
658                    // Bilinear interpolation
659                    //
660                    if( (int)Math.Round(c.c[1])==-1 )
661                    {
662                        for(k=4; k<=19; k++)
663                        {
664                            tbl[p,k] = 0;
665                        }
666                        shift = 4+n+m;
667                        y1 = c.c[shift+n*i+j];
668                        y2 = c.c[shift+n*i+(j+1)];
669                        y3 = c.c[shift+n*(i+1)+(j+1)];
670                        y4 = c.c[shift+n*(i+1)+j];
671                        tbl[p,4] = y1;
672                        tbl[p,4+1*4+0] = y2-y1;
673                        tbl[p,4+0*4+1] = y4-y1;
674                        tbl[p,4+1*4+1] = y3-y2-y4+y1;
675                    }
676                   
677                    //
678                    // Bicubic interpolation
679                    //
680                    if( (int)Math.Round(c.c[1])==-3 )
681                    {
682                        sf = 4+n+m;
683                        sfx = 4+n+m+n*m;
684                        sfy = 4+n+m+2*n*m;
685                        sfxy = 4+n+m+3*n*m;
686                        s1 = n*i+j;
687                        s2 = n*i+(j+1);
688                        s3 = n*(i+1)+(j+1);
689                        s4 = n*(i+1)+j;
690                        tbl[p,4+0*4+0] = +(1*c.c[sf+s1]);
691                        tbl[p,4+0*4+1] = +(1*c.c[sfy+s1]/du);
692                        tbl[p,4+0*4+2] = -(3*c.c[sf+s1])+3*c.c[sf+s4]-2*c.c[sfy+s1]/du-1*c.c[sfy+s4]/du;
693                        tbl[p,4+0*4+3] = +(2*c.c[sf+s1])-2*c.c[sf+s4]+1*c.c[sfy+s1]/du+1*c.c[sfy+s4]/du;
694                        tbl[p,4+1*4+0] = +(1*c.c[sfx+s1]/dt);
695                        tbl[p,4+1*4+1] = +(1*c.c[sfxy+s1]/(dt*du));
696                        tbl[p,4+1*4+2] = -(3*c.c[sfx+s1]/dt)+3*c.c[sfx+s4]/dt-2*c.c[sfxy+s1]/(dt*du)-1*c.c[sfxy+s4]/(dt*du);
697                        tbl[p,4+1*4+3] = +(2*c.c[sfx+s1]/dt)-2*c.c[sfx+s4]/dt+1*c.c[sfxy+s1]/(dt*du)+1*c.c[sfxy+s4]/(dt*du);
698                        tbl[p,4+2*4+0] = -(3*c.c[sf+s1])+3*c.c[sf+s2]-2*c.c[sfx+s1]/dt-1*c.c[sfx+s2]/dt;
699                        tbl[p,4+2*4+1] = -(3*c.c[sfy+s1]/du)+3*c.c[sfy+s2]/du-2*c.c[sfxy+s1]/(dt*du)-1*c.c[sfxy+s2]/(dt*du);
700                        tbl[p,4+2*4+2] = +(9*c.c[sf+s1])-9*c.c[sf+s2]+9*c.c[sf+s3]-9*c.c[sf+s4]+6*c.c[sfx+s1]/dt+3*c.c[sfx+s2]/dt-3*c.c[sfx+s3]/dt-6*c.c[sfx+s4]/dt+6*c.c[sfy+s1]/du-6*c.c[sfy+s2]/du-3*c.c[sfy+s3]/du+3*c.c[sfy+s4]/du+4*c.c[sfxy+s1]/(dt*du)+2*c.c[sfxy+s2]/(dt*du)+1*c.c[sfxy+s3]/(dt*du)+2*c.c[sfxy+s4]/(dt*du);
701                        tbl[p,4+2*4+3] = -(6*c.c[sf+s1])+6*c.c[sf+s2]-6*c.c[sf+s3]+6*c.c[sf+s4]-4*c.c[sfx+s1]/dt-2*c.c[sfx+s2]/dt+2*c.c[sfx+s3]/dt+4*c.c[sfx+s4]/dt-3*c.c[sfy+s1]/du+3*c.c[sfy+s2]/du+3*c.c[sfy+s3]/du-3*c.c[sfy+s4]/du-2*c.c[sfxy+s1]/(dt*du)-1*c.c[sfxy+s2]/(dt*du)-1*c.c[sfxy+s3]/(dt*du)-2*c.c[sfxy+s4]/(dt*du);
702                        tbl[p,4+3*4+0] = +(2*c.c[sf+s1])-2*c.c[sf+s2]+1*c.c[sfx+s1]/dt+1*c.c[sfx+s2]/dt;
703                        tbl[p,4+3*4+1] = +(2*c.c[sfy+s1]/du)-2*c.c[sfy+s2]/du+1*c.c[sfxy+s1]/(dt*du)+1*c.c[sfxy+s2]/(dt*du);
704                        tbl[p,4+3*4+2] = -(6*c.c[sf+s1])+6*c.c[sf+s2]-6*c.c[sf+s3]+6*c.c[sf+s4]-3*c.c[sfx+s1]/dt-3*c.c[sfx+s2]/dt+3*c.c[sfx+s3]/dt+3*c.c[sfx+s4]/dt-4*c.c[sfy+s1]/du+4*c.c[sfy+s2]/du+2*c.c[sfy+s3]/du-2*c.c[sfy+s4]/du-2*c.c[sfxy+s1]/(dt*du)-2*c.c[sfxy+s2]/(dt*du)-1*c.c[sfxy+s3]/(dt*du)-1*c.c[sfxy+s4]/(dt*du);
705                        tbl[p,4+3*4+3] = +(4*c.c[sf+s1])-4*c.c[sf+s2]+4*c.c[sf+s3]-4*c.c[sf+s4]+2*c.c[sfx+s1]/dt+2*c.c[sfx+s2]/dt-2*c.c[sfx+s3]/dt-2*c.c[sfx+s4]/dt+2*c.c[sfy+s1]/du-2*c.c[sfy+s2]/du-2*c.c[sfy+s3]/du+2*c.c[sfy+s4]/du+1*c.c[sfxy+s1]/(dt*du)+1*c.c[sfxy+s2]/(dt*du)+1*c.c[sfxy+s3]/(dt*du)+1*c.c[sfxy+s4]/(dt*du);
706                    }
707                   
708                    //
709                    // Rescale Cij
710                    //
711                    for(ci=0; ci<=3; ci++)
712                    {
713                        for(cj=0; cj<=3; cj++)
714                        {
715                            tbl[p,4+ci*4+cj] = tbl[p,4+ci*4+cj]*Math.Pow(dt, ci)*Math.Pow(du, cj);
716                        }
717                    }
718                }
719            }
720        }
721
722
723        /*************************************************************************
724        This subroutine performs linear transformation of the spline argument.
725
726        Input parameters:
727            C       -   spline interpolant
728            AX, BX  -   transformation coefficients: x = A*t + B
729            AY, BY  -   transformation coefficients: y = A*u + B
730        Result:
731            C   -   transformed spline
732
733          -- ALGLIB PROJECT --
734             Copyright 30.06.2007 by Bochkanov Sergey
735        *************************************************************************/
736        public static void spline2dlintransxy(ref spline2dinterpolant c,
737            double ax,
738            double bx,
739            double ay,
740            double by)
741        {
742            int i = 0;
743            int j = 0;
744            int n = 0;
745            int m = 0;
746            double v = 0;
747            double[] x = new double[0];
748            double[] y = new double[0];
749            double[,] f = new double[0,0];
750            int typec = 0;
751
752            typec = (int)Math.Round(c.c[1]);
753            System.Diagnostics.Debug.Assert(typec==-3 | typec==-1, "Spline2DLinTransXY: incorrect C!");
754            n = (int)Math.Round(c.c[2]);
755            m = (int)Math.Round(c.c[3]);
756            x = new double[n-1+1];
757            y = new double[m-1+1];
758            f = new double[m-1+1, n-1+1];
759            for(j=0; j<=n-1; j++)
760            {
761                x[j] = c.c[4+j];
762            }
763            for(i=0; i<=m-1; i++)
764            {
765                y[i] = c.c[4+n+i];
766            }
767            for(i=0; i<=m-1; i++)
768            {
769                for(j=0; j<=n-1; j++)
770                {
771                    f[i,j] = c.c[4+n+m+i*n+j];
772                }
773            }
774           
775            //
776            // Special case: AX=0 or AY=0
777            //
778            if( (double)(ax)==(double)(0) )
779            {
780                for(i=0; i<=m-1; i++)
781                {
782                    v = spline2dcalc(ref c, bx, y[i]);
783                    for(j=0; j<=n-1; j++)
784                    {
785                        f[i,j] = v;
786                    }
787                }
788                if( typec==-3 )
789                {
790                    spline2dbuildbicubic(x, y, f, m, n, ref c);
791                }
792                if( typec==-1 )
793                {
794                    spline2dbuildbilinear(x, y, f, m, n, ref c);
795                }
796                ax = 1;
797                bx = 0;
798            }
799            if( (double)(ay)==(double)(0) )
800            {
801                for(j=0; j<=n-1; j++)
802                {
803                    v = spline2dcalc(ref c, x[j], by);
804                    for(i=0; i<=m-1; i++)
805                    {
806                        f[i,j] = v;
807                    }
808                }
809                if( typec==-3 )
810                {
811                    spline2dbuildbicubic(x, y, f, m, n, ref c);
812                }
813                if( typec==-1 )
814                {
815                    spline2dbuildbilinear(x, y, f, m, n, ref c);
816                }
817                ay = 1;
818                by = 0;
819            }
820           
821            //
822            // General case: AX<>0, AY<>0
823            // Unpack, scale and pack again.
824            //
825            for(j=0; j<=n-1; j++)
826            {
827                x[j] = (x[j]-bx)/ax;
828            }
829            for(i=0; i<=m-1; i++)
830            {
831                y[i] = (y[i]-by)/ay;
832            }
833            if( typec==-3 )
834            {
835                spline2dbuildbicubic(x, y, f, m, n, ref c);
836            }
837            if( typec==-1 )
838            {
839                spline2dbuildbilinear(x, y, f, m, n, ref c);
840            }
841        }
842
843
844        /*************************************************************************
845        This subroutine performs linear transformation of the spline.
846
847        Input parameters:
848            C   -   spline interpolant.
849            A, B-   transformation coefficients: S2(x,y) = A*S(x,y) + B
850           
851        Output parameters:
852            C   -   transformed spline
853
854          -- ALGLIB PROJECT --
855             Copyright 30.06.2007 by Bochkanov Sergey
856        *************************************************************************/
857        public static void spline2dlintransf(ref spline2dinterpolant c,
858            double a,
859            double b)
860        {
861            int i = 0;
862            int j = 0;
863            int n = 0;
864            int m = 0;
865            double v = 0;
866            double[] x = new double[0];
867            double[] y = new double[0];
868            double[,] f = new double[0,0];
869            int typec = 0;
870
871            typec = (int)Math.Round(c.c[1]);
872            System.Diagnostics.Debug.Assert(typec==-3 | typec==-1, "Spline2DLinTransXY: incorrect C!");
873            n = (int)Math.Round(c.c[2]);
874            m = (int)Math.Round(c.c[3]);
875            x = new double[n-1+1];
876            y = new double[m-1+1];
877            f = new double[m-1+1, n-1+1];
878            for(j=0; j<=n-1; j++)
879            {
880                x[j] = c.c[4+j];
881            }
882            for(i=0; i<=m-1; i++)
883            {
884                y[i] = c.c[4+n+i];
885            }
886            for(i=0; i<=m-1; i++)
887            {
888                for(j=0; j<=n-1; j++)
889                {
890                    f[i,j] = a*c.c[4+n+m+i*n+j]+b;
891                }
892            }
893            if( typec==-3 )
894            {
895                spline2dbuildbicubic(x, y, f, m, n, ref c);
896            }
897            if( typec==-1 )
898            {
899                spline2dbuildbilinear(x, y, f, m, n, ref c);
900            }
901        }
902
903
904        /*************************************************************************
905        This subroutine makes the copy of the spline model.
906
907        Input parameters:
908            C   -   spline interpolant
909
910        Output parameters:
911            CC  -   spline copy
912
913          -- ALGLIB PROJECT --
914             Copyright 29.06.2007 by Bochkanov Sergey
915        *************************************************************************/
916        public static void spline2dcopy(ref spline2dinterpolant c,
917            ref spline2dinterpolant cc)
918        {
919            int n = 0;
920            int i_ = 0;
921
922            System.Diagnostics.Debug.Assert(c.k==1 | c.k==3, "Spline2DCopy: incorrect C!");
923            cc.k = c.k;
924            n = (int)Math.Round(c.c[0]);
925            cc.c = new double[n];
926            for(i_=0; i_<=n-1;i_++)
927            {
928                cc.c[i_] = c.c[i_];
929            }
930        }
931
932
933        /*************************************************************************
934        Serialization of the spline interpolant
935
936        INPUT PARAMETERS:
937            B   -   spline interpolant
938
939        OUTPUT PARAMETERS:
940            RA      -   array of real numbers which contains interpolant,
941                        array[0..RLen-1]
942            RLen    -   RA lenght
943
944          -- ALGLIB --
945             Copyright 17.08.2009 by Bochkanov Sergey
946        *************************************************************************/
947        public static void spline2dserialize(ref spline2dinterpolant c,
948            ref double[] ra,
949            ref int ralen)
950        {
951            int clen = 0;
952            int i_ = 0;
953            int i1_ = 0;
954
955            System.Diagnostics.Debug.Assert(c.k==1 | c.k==3, "Spline2DSerialize: incorrect C!");
956            clen = (int)Math.Round(c.c[0]);
957            ralen = 3+clen;
958            ra = new double[ralen];
959            ra[0] = ralen;
960            ra[1] = spline2dvnum;
961            ra[2] = c.k;
962            i1_ = (0) - (3);
963            for(i_=3; i_<=3+clen-1;i_++)
964            {
965                ra[i_] = c.c[i_+i1_];
966            }
967        }
968
969
970        /*************************************************************************
971        Unserialization of the spline interpolant
972
973        INPUT PARAMETERS:
974            RA  -   array of real numbers which contains interpolant,
975
976        OUTPUT PARAMETERS:
977            B   -   spline interpolant
978
979          -- ALGLIB --
980             Copyright 17.08.2009 by Bochkanov Sergey
981        *************************************************************************/
982        public static void spline2dunserialize(ref double[] ra,
983            ref spline2dinterpolant c)
984        {
985            int clen = 0;
986            int i_ = 0;
987            int i1_ = 0;
988
989            System.Diagnostics.Debug.Assert((int)Math.Round(ra[1])==spline2dvnum, "Spline2DUnserialize: corrupted array!");
990            c.k = (int)Math.Round(ra[2]);
991            clen = (int)Math.Round(ra[3]);
992            c.c = new double[clen];
993            i1_ = (3) - (0);
994            for(i_=0; i_<=clen-1;i_++)
995            {
996                c.c[i_] = ra[i_+i1_];
997            }
998        }
999
1000
1001        /*************************************************************************
1002        Bicubic spline resampling
1003
1004        Input parameters:
1005            A           -   function values at the old grid,
1006                            array[0..OldHeight-1, 0..OldWidth-1]
1007            OldHeight   -   old grid height, OldHeight>1
1008            OldWidth    -   old grid width, OldWidth>1
1009            NewHeight   -   new grid height, NewHeight>1
1010            NewWidth    -   new grid width, NewWidth>1
1011           
1012        Output parameters:
1013            B           -   function values at the new grid,
1014                            array[0..NewHeight-1, 0..NewWidth-1]
1015
1016          -- ALGLIB routine --
1017             15 May, 2007
1018             Copyright by Bochkanov Sergey
1019        *************************************************************************/
1020        public static void spline2dresamplebicubic(ref double[,] a,
1021            int oldheight,
1022            int oldwidth,
1023            ref double[,] b,
1024            int newheight,
1025            int newwidth)
1026        {
1027            double[,] buf = new double[0,0];
1028            double[] x = new double[0];
1029            double[] y = new double[0];
1030            spline1d.spline1dinterpolant c = new spline1d.spline1dinterpolant();
1031            int i = 0;
1032            int j = 0;
1033            int mw = 0;
1034            int mh = 0;
1035
1036            System.Diagnostics.Debug.Assert(oldwidth>1 & oldheight>1, "Spline2DResampleBicubic: width/height less than 1");
1037            System.Diagnostics.Debug.Assert(newwidth>1 & newheight>1, "Spline2DResampleBicubic: width/height less than 1");
1038           
1039            //
1040            // Prepare
1041            //
1042            mw = Math.Max(oldwidth, newwidth);
1043            mh = Math.Max(oldheight, newheight);
1044            b = new double[newheight-1+1, newwidth-1+1];
1045            buf = new double[oldheight-1+1, newwidth-1+1];
1046            x = new double[Math.Max(mw, mh)-1+1];
1047            y = new double[Math.Max(mw, mh)-1+1];
1048           
1049            //
1050            // Horizontal interpolation
1051            //
1052            for(i=0; i<=oldheight-1; i++)
1053            {
1054               
1055                //
1056                // Fill X, Y
1057                //
1058                for(j=0; j<=oldwidth-1; j++)
1059                {
1060                    x[j] = (double)(j)/((double)(oldwidth-1));
1061                    y[j] = a[i,j];
1062                }
1063               
1064                //
1065                // Interpolate and place result into temporary matrix
1066                //
1067                spline1d.spline1dbuildcubic(x, y, oldwidth, 0, 0.0, 0, 0.0, ref c);
1068                for(j=0; j<=newwidth-1; j++)
1069                {
1070                    buf[i,j] = spline1d.spline1dcalc(ref c, (double)(j)/((double)(newwidth-1)));
1071                }
1072            }
1073           
1074            //
1075            // Vertical interpolation
1076            //
1077            for(j=0; j<=newwidth-1; j++)
1078            {
1079               
1080                //
1081                // Fill X, Y
1082                //
1083                for(i=0; i<=oldheight-1; i++)
1084                {
1085                    x[i] = (double)(i)/((double)(oldheight-1));
1086                    y[i] = buf[i,j];
1087                }
1088               
1089                //
1090                // Interpolate and place result into B
1091                //
1092                spline1d.spline1dbuildcubic(x, y, oldheight, 0, 0.0, 0, 0.0, ref c);
1093                for(i=0; i<=newheight-1; i++)
1094                {
1095                    b[i,j] = spline1d.spline1dcalc(ref c, (double)(i)/((double)(newheight-1)));
1096                }
1097            }
1098        }
1099
1100
1101        /*************************************************************************
1102        Bilinear spline resampling
1103
1104        Input parameters:
1105            A           -   function values at the old grid,
1106                            array[0..OldHeight-1, 0..OldWidth-1]
1107            OldHeight   -   old grid height, OldHeight>1
1108            OldWidth    -   old grid width, OldWidth>1
1109            NewHeight   -   new grid height, NewHeight>1
1110            NewWidth    -   new grid width, NewWidth>1
1111
1112        Output parameters:
1113            B           -   function values at the new grid,
1114                            array[0..NewHeight-1, 0..NewWidth-1]
1115
1116          -- ALGLIB routine --
1117             09.07.2007
1118             Copyright by Bochkanov Sergey
1119        *************************************************************************/
1120        public static void spline2dresamplebilinear(ref double[,] a,
1121            int oldheight,
1122            int oldwidth,
1123            ref double[,] b,
1124            int newheight,
1125            int newwidth)
1126        {
1127            int i = 0;
1128            int j = 0;
1129            int l = 0;
1130            int c = 0;
1131            double t = 0;
1132            double u = 0;
1133
1134            b = new double[newheight-1+1, newwidth-1+1];
1135            for(i=0; i<=newheight-1; i++)
1136            {
1137                for(j=0; j<=newwidth-1; j++)
1138                {
1139                    l = i*(oldheight-1)/(newheight-1);
1140                    if( l==oldheight-1 )
1141                    {
1142                        l = oldheight-2;
1143                    }
1144                    u = (double)(i)/((double)(newheight-1))*(oldheight-1)-l;
1145                    c = j*(oldwidth-1)/(newwidth-1);
1146                    if( c==oldwidth-1 )
1147                    {
1148                        c = oldwidth-2;
1149                    }
1150                    t = (double)(j*(oldwidth-1))/((double)(newwidth-1))-c;
1151                    b[i,j] = (1-t)*(1-u)*a[l,c]+t*(1-u)*a[l,c+1]+t*u*a[l+1,c+1]+(1-t)*u*a[l+1,c];
1152                }
1153            }
1154        }
1155
1156
1157        /*************************************************************************
1158        Internal subroutine.
1159        Calculation of the first derivatives and the cross-derivative.
1160        *************************************************************************/
1161        private static void bicubiccalcderivatives(ref double[,] a,
1162            ref double[] x,
1163            ref double[] y,
1164            int m,
1165            int n,
1166            ref double[,] dx,
1167            ref double[,] dy,
1168            ref double[,] dxy)
1169        {
1170            int i = 0;
1171            int j = 0;
1172            int k = 0;
1173            double[] xt = new double[0];
1174            double[] ft = new double[0];
1175            double[] c = new double[0];
1176            double s = 0;
1177            double ds = 0;
1178            double d2s = 0;
1179            double v = 0;
1180
1181            dx = new double[m-1+1, n-1+1];
1182            dy = new double[m-1+1, n-1+1];
1183            dxy = new double[m-1+1, n-1+1];
1184           
1185            //
1186            // dF/dX
1187            //
1188            xt = new double[n-1+1];
1189            ft = new double[n-1+1];
1190            for(i=0; i<=m-1; i++)
1191            {
1192                for(j=0; j<=n-1; j++)
1193                {
1194                    xt[j] = x[j];
1195                    ft[j] = a[i,j];
1196                }
1197                spline3.buildcubicspline(xt, ft, n, 0, 0.0, 0, 0.0, ref c);
1198                for(j=0; j<=n-1; j++)
1199                {
1200                    spline3.splinedifferentiation(ref c, x[j], ref s, ref ds, ref d2s);
1201                    dx[i,j] = ds;
1202                }
1203            }
1204           
1205            //
1206            // dF/dY
1207            //
1208            xt = new double[m-1+1];
1209            ft = new double[m-1+1];
1210            for(j=0; j<=n-1; j++)
1211            {
1212                for(i=0; i<=m-1; i++)
1213                {
1214                    xt[i] = y[i];
1215                    ft[i] = a[i,j];
1216                }
1217                spline3.buildcubicspline(xt, ft, m, 0, 0.0, 0, 0.0, ref c);
1218                for(i=0; i<=m-1; i++)
1219                {
1220                    spline3.splinedifferentiation(ref c, y[i], ref s, ref ds, ref d2s);
1221                    dy[i,j] = ds;
1222                }
1223            }
1224           
1225            //
1226            // d2F/dXdY
1227            //
1228            xt = new double[n-1+1];
1229            ft = new double[n-1+1];
1230            for(i=0; i<=m-1; i++)
1231            {
1232                for(j=0; j<=n-1; j++)
1233                {
1234                    xt[j] = x[j];
1235                    ft[j] = dy[i,j];
1236                }
1237                spline3.buildcubicspline(xt, ft, n, 0, 0.0, 0, 0.0, ref c);
1238                for(j=0; j<=n-1; j++)
1239                {
1240                    spline3.splinedifferentiation(ref c, x[j], ref s, ref ds, ref d2s);
1241                    dxy[i,j] = ds;
1242                }
1243            }
1244        }
1245    }
1246}
Note: See TracBrowser for help on using the repository browser.