Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/ALGLIB/rotations.cs @ 2474

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

Moved ALGLIB code into a separate plugin. #783

File size: 18.5 KB
Line 
1/*************************************************************************
2Copyright (c) 1992-2007 The University of Tennessee.  All rights reserved.
3
4Contributors:
5    * Sergey Bochkanov (ALGLIB project). Translation from FORTRAN to
6      pseudocode.
7
8See subroutines comments for additional copyrights.
9
10>>> SOURCE LICENSE >>>
11This program is free software; you can redistribute it and/or modify
12it under the terms of the GNU General Public License as published by
13the Free Software Foundation (www.fsf.org); either version 2 of the
14License, or (at your option) any later version.
15
16This program is distributed in the hope that it will be useful,
17but WITHOUT ANY WARRANTY; without even the implied warranty of
18MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19GNU General Public License for more details.
20
21A copy of the GNU General Public License is available at
22http://www.fsf.org/licensing/licenses
23
24>>> END OF LICENSE >>>
25*************************************************************************/
26
27using System;
28
29namespace alglib
30{
31    public class rotations
32    {
33        /*************************************************************************
34        Application of a sequence of  elementary rotations to a matrix
35
36        The algorithm pre-multiplies the matrix by a sequence of rotation
37        transformations which is given by arrays C and S. Depending on the value
38        of the IsForward parameter either 1 and 2, 3 and 4 and so on (if IsForward=true)
39        rows are rotated, or the rows N and N-1, N-2 and N-3 and so on, are rotated.
40
41        Not the whole matrix but only a part of it is transformed (rows from M1 to
42        M2, columns from N1 to N2). Only the elements of this submatrix are changed.
43
44        Input parameters:
45            IsForward   -   the sequence of the rotation application.
46            M1,M2       -   the range of rows to be transformed.
47            N1, N2      -   the range of columns to be transformed.
48            C,S         -   transformation coefficients.
49                            Array whose index ranges within [1..M2-M1].
50            A           -   processed matrix.
51            WORK        -   working array whose index ranges within [N1..N2].
52
53        Output parameters:
54            A           -   transformed matrix.
55
56        Utility subroutine.
57        *************************************************************************/
58        public static void applyrotationsfromtheleft(bool isforward,
59            int m1,
60            int m2,
61            int n1,
62            int n2,
63            ref double[] c,
64            ref double[] s,
65            ref double[,] a,
66            ref double[] work)
67        {
68            int j = 0;
69            int jp1 = 0;
70            double ctemp = 0;
71            double stemp = 0;
72            double temp = 0;
73            int i_ = 0;
74
75            if( m1>m2 | n1>n2 )
76            {
77                return;
78            }
79           
80            //
81            // Form  P * A
82            //
83            if( isforward )
84            {
85                if( n1!=n2 )
86                {
87                   
88                    //
89                    // Common case: N1<>N2
90                    //
91                    for(j=m1; j<=m2-1; j++)
92                    {
93                        ctemp = c[j-m1+1];
94                        stemp = s[j-m1+1];
95                        if( ctemp!=1 | stemp!=0 )
96                        {
97                            jp1 = j+1;
98                            for(i_=n1; i_<=n2;i_++)
99                            {
100                                work[i_] = ctemp*a[jp1,i_];
101                            }
102                            for(i_=n1; i_<=n2;i_++)
103                            {
104                                work[i_] = work[i_] - stemp*a[j,i_];
105                            }
106                            for(i_=n1; i_<=n2;i_++)
107                            {
108                                a[j,i_] = ctemp*a[j,i_];
109                            }
110                            for(i_=n1; i_<=n2;i_++)
111                            {
112                                a[j,i_] = a[j,i_] + stemp*a[jp1,i_];
113                            }
114                            for(i_=n1; i_<=n2;i_++)
115                            {
116                                a[jp1,i_] = work[i_];
117                            }
118                        }
119                    }
120                }
121                else
122                {
123                   
124                    //
125                    // Special case: N1=N2
126                    //
127                    for(j=m1; j<=m2-1; j++)
128                    {
129                        ctemp = c[j-m1+1];
130                        stemp = s[j-m1+1];
131                        if( ctemp!=1 | stemp!=0 )
132                        {
133                            temp = a[j+1,n1];
134                            a[j+1,n1] = ctemp*temp-stemp*a[j,n1];
135                            a[j,n1] = stemp*temp+ctemp*a[j,n1];
136                        }
137                    }
138                }
139            }
140            else
141            {
142                if( n1!=n2 )
143                {
144                   
145                    //
146                    // Common case: N1<>N2
147                    //
148                    for(j=m2-1; j>=m1; j--)
149                    {
150                        ctemp = c[j-m1+1];
151                        stemp = s[j-m1+1];
152                        if( ctemp!=1 | stemp!=0 )
153                        {
154                            jp1 = j+1;
155                            for(i_=n1; i_<=n2;i_++)
156                            {
157                                work[i_] = ctemp*a[jp1,i_];
158                            }
159                            for(i_=n1; i_<=n2;i_++)
160                            {
161                                work[i_] = work[i_] - stemp*a[j,i_];
162                            }
163                            for(i_=n1; i_<=n2;i_++)
164                            {
165                                a[j,i_] = ctemp*a[j,i_];
166                            }
167                            for(i_=n1; i_<=n2;i_++)
168                            {
169                                a[j,i_] = a[j,i_] + stemp*a[jp1,i_];
170                            }
171                            for(i_=n1; i_<=n2;i_++)
172                            {
173                                a[jp1,i_] = work[i_];
174                            }
175                        }
176                    }
177                }
178                else
179                {
180                   
181                    //
182                    // Special case: N1=N2
183                    //
184                    for(j=m2-1; j>=m1; j--)
185                    {
186                        ctemp = c[j-m1+1];
187                        stemp = s[j-m1+1];
188                        if( ctemp!=1 | stemp!=0 )
189                        {
190                            temp = a[j+1,n1];
191                            a[j+1,n1] = ctemp*temp-stemp*a[j,n1];
192                            a[j,n1] = stemp*temp+ctemp*a[j,n1];
193                        }
194                    }
195                }
196            }
197        }
198
199
200        /*************************************************************************
201        Application of a sequence of  elementary rotations to a matrix
202
203        The algorithm post-multiplies the matrix by a sequence of rotation
204        transformations which is given by arrays C and S. Depending on the value
205        of the IsForward parameter either 1 and 2, 3 and 4 and so on (if IsForward=true)
206        rows are rotated, or the rows N and N-1, N-2 and N-3 and so on are rotated.
207
208        Not the whole matrix but only a part of it is transformed (rows from M1
209        to M2, columns from N1 to N2). Only the elements of this submatrix are changed.
210
211        Input parameters:
212            IsForward   -   the sequence of the rotation application.
213            M1,M2       -   the range of rows to be transformed.
214            N1, N2      -   the range of columns to be transformed.
215            C,S         -   transformation coefficients.
216                            Array whose index ranges within [1..N2-N1].
217            A           -   processed matrix.
218            WORK        -   working array whose index ranges within [M1..M2].
219
220        Output parameters:
221            A           -   transformed matrix.
222
223        Utility subroutine.
224        *************************************************************************/
225        public static void applyrotationsfromtheright(bool isforward,
226            int m1,
227            int m2,
228            int n1,
229            int n2,
230            ref double[] c,
231            ref double[] s,
232            ref double[,] a,
233            ref double[] work)
234        {
235            int j = 0;
236            int jp1 = 0;
237            double ctemp = 0;
238            double stemp = 0;
239            double temp = 0;
240            int i_ = 0;
241
242           
243            //
244            // Form A * P'
245            //
246            if( isforward )
247            {
248                if( m1!=m2 )
249                {
250                   
251                    //
252                    // Common case: M1<>M2
253                    //
254                    for(j=n1; j<=n2-1; j++)
255                    {
256                        ctemp = c[j-n1+1];
257                        stemp = s[j-n1+1];
258                        if( ctemp!=1 | stemp!=0 )
259                        {
260                            jp1 = j+1;
261                            for(i_=m1; i_<=m2;i_++)
262                            {
263                                work[i_] = ctemp*a[i_,jp1];
264                            }
265                            for(i_=m1; i_<=m2;i_++)
266                            {
267                                work[i_] = work[i_] - stemp*a[i_,j];
268                            }
269                            for(i_=m1; i_<=m2;i_++)
270                            {
271                                a[i_,j] = ctemp*a[i_,j];
272                            }
273                            for(i_=m1; i_<=m2;i_++)
274                            {
275                                a[i_,j] = a[i_,j] + stemp*a[i_,jp1];
276                            }
277                            for(i_=m1; i_<=m2;i_++)
278                            {
279                                a[i_,jp1] = work[i_];
280                            }
281                        }
282                    }
283                }
284                else
285                {
286                   
287                    //
288                    // Special case: M1=M2
289                    //
290                    for(j=n1; j<=n2-1; j++)
291                    {
292                        ctemp = c[j-n1+1];
293                        stemp = s[j-n1+1];
294                        if( ctemp!=1 | stemp!=0 )
295                        {
296                            temp = a[m1,j+1];
297                            a[m1,j+1] = ctemp*temp-stemp*a[m1,j];
298                            a[m1,j] = stemp*temp+ctemp*a[m1,j];
299                        }
300                    }
301                }
302            }
303            else
304            {
305                if( m1!=m2 )
306                {
307                   
308                    //
309                    // Common case: M1<>M2
310                    //
311                    for(j=n2-1; j>=n1; j--)
312                    {
313                        ctemp = c[j-n1+1];
314                        stemp = s[j-n1+1];
315                        if( ctemp!=1 | stemp!=0 )
316                        {
317                            jp1 = j+1;
318                            for(i_=m1; i_<=m2;i_++)
319                            {
320                                work[i_] = ctemp*a[i_,jp1];
321                            }
322                            for(i_=m1; i_<=m2;i_++)
323                            {
324                                work[i_] = work[i_] - stemp*a[i_,j];
325                            }
326                            for(i_=m1; i_<=m2;i_++)
327                            {
328                                a[i_,j] = ctemp*a[i_,j];
329                            }
330                            for(i_=m1; i_<=m2;i_++)
331                            {
332                                a[i_,j] = a[i_,j] + stemp*a[i_,jp1];
333                            }
334                            for(i_=m1; i_<=m2;i_++)
335                            {
336                                a[i_,jp1] = work[i_];
337                            }
338                        }
339                    }
340                }
341                else
342                {
343                   
344                    //
345                    // Special case: M1=M2
346                    //
347                    for(j=n2-1; j>=n1; j--)
348                    {
349                        ctemp = c[j-n1+1];
350                        stemp = s[j-n1+1];
351                        if( ctemp!=1 | stemp!=0 )
352                        {
353                            temp = a[m1,j+1];
354                            a[m1,j+1] = ctemp*temp-stemp*a[m1,j];
355                            a[m1,j] = stemp*temp+ctemp*a[m1,j];
356                        }
357                    }
358                }
359            }
360        }
361
362
363        /*************************************************************************
364        The subroutine generates the elementary rotation, so that:
365
366        [  CS  SN  ]  .  [ F ]  =  [ R ]
367        [ -SN  CS  ]     [ G ]     [ 0 ]
368
369        CS**2 + SN**2 = 1
370        *************************************************************************/
371        public static void generaterotation(double f,
372            double g,
373            ref double cs,
374            ref double sn,
375            ref double r)
376        {
377            double f1 = 0;
378            double g1 = 0;
379
380            if( g==0 )
381            {
382                cs = 1;
383                sn = 0;
384                r = f;
385            }
386            else
387            {
388                if( f==0 )
389                {
390                    cs = 0;
391                    sn = 1;
392                    r = g;
393                }
394                else
395                {
396                    f1 = f;
397                    g1 = g;
398                    r = Math.Sqrt(AP.Math.Sqr(f1)+AP.Math.Sqr(g1));
399                    cs = f1/r;
400                    sn = g1/r;
401                    if( Math.Abs(f)>Math.Abs(g) & cs<0 )
402                    {
403                        cs = -cs;
404                        sn = -sn;
405                        r = -r;
406                    }
407                }
408            }
409        }
410
411
412        private static void testrotations()
413        {
414            double[,] al1 = new double[0,0];
415            double[,] al2 = new double[0,0];
416            double[,] ar1 = new double[0,0];
417            double[,] ar2 = new double[0,0];
418            double[] cl = new double[0];
419            double[] sl = new double[0];
420            double[] cr = new double[0];
421            double[] sr = new double[0];
422            double[] w = new double[0];
423            int m = 0;
424            int n = 0;
425            int maxmn = 0;
426            double t = 0;
427            int pass = 0;
428            int passcount = 0;
429            int i = 0;
430            int j = 0;
431            double err = 0;
432            double maxerr = 0;
433            bool isforward = new bool();
434
435            passcount = 1000;
436            maxerr = 0;
437            for(pass=1; pass<=passcount; pass++)
438            {
439               
440                //
441                // settings
442                //
443                m = 2+AP.Math.RandomInteger(50);
444                n = 2+AP.Math.RandomInteger(50);
445                isforward = AP.Math.RandomReal()>0.5;
446                maxmn = Math.Max(m, n);
447                al1 = new double[m+1, n+1];
448                al2 = new double[m+1, n+1];
449                ar1 = new double[m+1, n+1];
450                ar2 = new double[m+1, n+1];
451                cl = new double[m-1+1];
452                sl = new double[m-1+1];
453                cr = new double[n-1+1];
454                sr = new double[n-1+1];
455                w = new double[maxmn+1];
456               
457                //
458                // matrices and rotaions
459                //
460                for(i=1; i<=m; i++)
461                {
462                    for(j=1; j<=n; j++)
463                    {
464                        al1[i,j] = 2*AP.Math.RandomReal()-1;
465                        al2[i,j] = al1[i,j];
466                        ar1[i,j] = al1[i,j];
467                        ar2[i,j] = al1[i,j];
468                    }
469                }
470                for(i=1; i<=m-1; i++)
471                {
472                    t = 2*Math.PI*AP.Math.RandomReal();
473                    cl[i] = Math.Cos(t);
474                    sl[i] = Math.Sin(t);
475                }
476                for(j=1; j<=n-1; j++)
477                {
478                    t = 2*Math.PI*AP.Math.RandomReal();
479                    cr[j] = Math.Cos(t);
480                    sr[j] = Math.Sin(t);
481                }
482               
483                //
484                // Test left
485                //
486                applyrotationsfromtheleft(isforward, 1, m, 1, n, ref cl, ref sl, ref al1, ref w);
487                for(j=1; j<=n; j++)
488                {
489                    applyrotationsfromtheleft(isforward, 1, m, j, j, ref cl, ref sl, ref al2, ref w);
490                }
491                err = 0;
492                for(i=1; i<=m; i++)
493                {
494                    for(j=1; j<=n; j++)
495                    {
496                        err = Math.Max(err, Math.Abs(al1[i,j]-al2[i,j]));
497                    }
498                }
499                maxerr = Math.Max(err, maxerr);
500               
501                //
502                // Test right
503                //
504                applyrotationsfromtheright(isforward, 1, m, 1, n, ref cr, ref sr, ref ar1, ref w);
505                for(i=1; i<=m; i++)
506                {
507                    applyrotationsfromtheright(isforward, i, i, 1, n, ref cr, ref sr, ref ar2, ref w);
508                }
509                err = 0;
510                for(i=1; i<=m; i++)
511                {
512                    for(j=1; j<=n; j++)
513                    {
514                        err = Math.Max(err, Math.Abs(ar1[i,j]-ar2[i,j]));
515                    }
516                }
517                maxerr = Math.Max(err, maxerr);
518            }
519            System.Console.Write("TESTING ROTATIONS");
520            System.Console.WriteLine();
521            System.Console.Write("Pass count ");
522            System.Console.Write("{0,0:d}",passcount);
523            System.Console.WriteLine();
524            System.Console.Write("Error is ");
525            System.Console.Write("{0,5:E3}",maxerr);
526            System.Console.WriteLine();
527        }
528    }
529}
Note: See TracBrowser for help on using the repository browser.