Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.LinearRegression/3.2/alglib/rotations.cs @ 2211

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

Added linear regression plugin. #697

File size: 17.4 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
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are
12met:
13
14- Redistributions of source code must retain the above copyright
15  notice, this list of conditions and the following disclaimer.
16
17- Redistributions in binary form must reproduce the above copyright
18  notice, this list of conditions and the following disclaimer listed
19  in this license in the documentation and/or other materials
20  provided with the distribution.
21
22- Neither the name of the copyright holders nor the names of its
23  contributors may be used to endorse or promote products derived from
24  this software without specific prior written permission.
25
26THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37*************************************************************************/
38
39using System;
40
41class rotations
42{
43    /*************************************************************************
44    Application of a sequence of  elementary rotations to a matrix
45
46    The algorithm pre-multiplies the matrix by a sequence of rotation
47    transformations which is given by arrays C and S. Depending on the value
48    of the IsForward parameter either 1 and 2, 3 and 4 and so on (if IsForward=true)
49    rows are rotated, or the rows N and N-1, N-2 and N-3 and so on, are rotated.
50
51    Not the whole matrix but only a part of it is transformed (rows from M1 to
52    M2, columns from N1 to N2). Only the elements of this submatrix are changed.
53
54    Input parameters:
55        IsForward   -   the sequence of the rotation application.
56        M1,M2       -   the range of rows to be transformed.
57        N1, N2      -   the range of columns to be transformed.
58        C,S         -   transformation coefficients.
59                        Array whose index ranges within [1..M2-M1].
60        A           -   processed matrix.
61        WORK        -   working array whose index ranges within [N1..N2].
62
63    Output parameters:
64        A           -   transformed matrix.
65
66    Utility subroutine.
67    *************************************************************************/
68    public static void applyrotationsfromtheleft(bool isforward,
69        int m1,
70        int m2,
71        int n1,
72        int n2,
73        ref double[] c,
74        ref double[] s,
75        ref double[,] a,
76        ref double[] work)
77    {
78        int j = 0;
79        int jp1 = 0;
80        double ctemp = 0;
81        double stemp = 0;
82        double temp = 0;
83        int i_ = 0;
84
85        if( m1>m2 | n1>n2 )
86        {
87            return;
88        }
89       
90        //
91        // Form  P * A
92        //
93        if( isforward )
94        {
95            if( n1!=n2 )
96            {
97               
98                //
99                // Common case: N1<>N2
100                //
101                for(j=m1; j<=m2-1; j++)
102                {
103                    ctemp = c[j-m1+1];
104                    stemp = s[j-m1+1];
105                    if( ctemp!=1 | stemp!=0 )
106                    {
107                        jp1 = j+1;
108                        for(i_=n1; i_<=n2;i_++)
109                        {
110                            work[i_] = ctemp*a[jp1,i_];
111                        }
112                        for(i_=n1; i_<=n2;i_++)
113                        {
114                            work[i_] = work[i_] - stemp*a[j,i_];
115                        }
116                        for(i_=n1; i_<=n2;i_++)
117                        {
118                            a[j,i_] = ctemp*a[j,i_];
119                        }
120                        for(i_=n1; i_<=n2;i_++)
121                        {
122                            a[j,i_] = a[j,i_] + stemp*a[jp1,i_];
123                        }
124                        for(i_=n1; i_<=n2;i_++)
125                        {
126                            a[jp1,i_] = work[i_];
127                        }
128                    }
129                }
130            }
131            else
132            {
133               
134                //
135                // Special case: N1=N2
136                //
137                for(j=m1; j<=m2-1; j++)
138                {
139                    ctemp = c[j-m1+1];
140                    stemp = s[j-m1+1];
141                    if( ctemp!=1 | stemp!=0 )
142                    {
143                        temp = a[j+1,n1];
144                        a[j+1,n1] = ctemp*temp-stemp*a[j,n1];
145                        a[j,n1] = stemp*temp+ctemp*a[j,n1];
146                    }
147                }
148            }
149        }
150        else
151        {
152            if( n1!=n2 )
153            {
154               
155                //
156                // Common case: N1<>N2
157                //
158                for(j=m2-1; j>=m1; j--)
159                {
160                    ctemp = c[j-m1+1];
161                    stemp = s[j-m1+1];
162                    if( ctemp!=1 | stemp!=0 )
163                    {
164                        jp1 = j+1;
165                        for(i_=n1; i_<=n2;i_++)
166                        {
167                            work[i_] = ctemp*a[jp1,i_];
168                        }
169                        for(i_=n1; i_<=n2;i_++)
170                        {
171                            work[i_] = work[i_] - stemp*a[j,i_];
172                        }
173                        for(i_=n1; i_<=n2;i_++)
174                        {
175                            a[j,i_] = ctemp*a[j,i_];
176                        }
177                        for(i_=n1; i_<=n2;i_++)
178                        {
179                            a[j,i_] = a[j,i_] + stemp*a[jp1,i_];
180                        }
181                        for(i_=n1; i_<=n2;i_++)
182                        {
183                            a[jp1,i_] = work[i_];
184                        }
185                    }
186                }
187            }
188            else
189            {
190               
191                //
192                // Special case: N1=N2
193                //
194                for(j=m2-1; j>=m1; j--)
195                {
196                    ctemp = c[j-m1+1];
197                    stemp = s[j-m1+1];
198                    if( ctemp!=1 | stemp!=0 )
199                    {
200                        temp = a[j+1,n1];
201                        a[j+1,n1] = ctemp*temp-stemp*a[j,n1];
202                        a[j,n1] = stemp*temp+ctemp*a[j,n1];
203                    }
204                }
205            }
206        }
207    }
208
209
210    /*************************************************************************
211    Application of a sequence of  elementary rotations to a matrix
212
213    The algorithm post-multiplies the matrix by a sequence of rotation
214    transformations which is given by arrays C and S. Depending on the value
215    of the IsForward parameter either 1 and 2, 3 and 4 and so on (if IsForward=true)
216    rows are rotated, or the rows N and N-1, N-2 and N-3 and so on are rotated.
217
218    Not the whole matrix but only a part of it is transformed (rows from M1
219    to M2, columns from N1 to N2). Only the elements of this submatrix are changed.
220
221    Input parameters:
222        IsForward   -   the sequence of the rotation application.
223        M1,M2       -   the range of rows to be transformed.
224        N1, N2      -   the range of columns to be transformed.
225        C,S         -   transformation coefficients.
226                        Array whose index ranges within [1..N2-N1].
227        A           -   processed matrix.
228        WORK        -   working array whose index ranges within [M1..M2].
229
230    Output parameters:
231        A           -   transformed matrix.
232
233    Utility subroutine.
234    *************************************************************************/
235    public static void applyrotationsfromtheright(bool isforward,
236        int m1,
237        int m2,
238        int n1,
239        int n2,
240        ref double[] c,
241        ref double[] s,
242        ref double[,] a,
243        ref double[] work)
244    {
245        int j = 0;
246        int jp1 = 0;
247        double ctemp = 0;
248        double stemp = 0;
249        double temp = 0;
250        int i_ = 0;
251
252       
253        //
254        // Form A * P'
255        //
256        if( isforward )
257        {
258            if( m1!=m2 )
259            {
260               
261                //
262                // Common case: M1<>M2
263                //
264                for(j=n1; j<=n2-1; j++)
265                {
266                    ctemp = c[j-n1+1];
267                    stemp = s[j-n1+1];
268                    if( ctemp!=1 | stemp!=0 )
269                    {
270                        jp1 = j+1;
271                        for(i_=m1; i_<=m2;i_++)
272                        {
273                            work[i_] = ctemp*a[i_,jp1];
274                        }
275                        for(i_=m1; i_<=m2;i_++)
276                        {
277                            work[i_] = work[i_] - stemp*a[i_,j];
278                        }
279                        for(i_=m1; i_<=m2;i_++)
280                        {
281                            a[i_,j] = ctemp*a[i_,j];
282                        }
283                        for(i_=m1; i_<=m2;i_++)
284                        {
285                            a[i_,j] = a[i_,j] + stemp*a[i_,jp1];
286                        }
287                        for(i_=m1; i_<=m2;i_++)
288                        {
289                            a[i_,jp1] = work[i_];
290                        }
291                    }
292                }
293            }
294            else
295            {
296               
297                //
298                // Special case: M1=M2
299                //
300                for(j=n1; j<=n2-1; j++)
301                {
302                    ctemp = c[j-n1+1];
303                    stemp = s[j-n1+1];
304                    if( ctemp!=1 | stemp!=0 )
305                    {
306                        temp = a[m1,j+1];
307                        a[m1,j+1] = ctemp*temp-stemp*a[m1,j];
308                        a[m1,j] = stemp*temp+ctemp*a[m1,j];
309                    }
310                }
311            }
312        }
313        else
314        {
315            if( m1!=m2 )
316            {
317               
318                //
319                // Common case: M1<>M2
320                //
321                for(j=n2-1; j>=n1; j--)
322                {
323                    ctemp = c[j-n1+1];
324                    stemp = s[j-n1+1];
325                    if( ctemp!=1 | stemp!=0 )
326                    {
327                        jp1 = j+1;
328                        for(i_=m1; i_<=m2;i_++)
329                        {
330                            work[i_] = ctemp*a[i_,jp1];
331                        }
332                        for(i_=m1; i_<=m2;i_++)
333                        {
334                            work[i_] = work[i_] - stemp*a[i_,j];
335                        }
336                        for(i_=m1; i_<=m2;i_++)
337                        {
338                            a[i_,j] = ctemp*a[i_,j];
339                        }
340                        for(i_=m1; i_<=m2;i_++)
341                        {
342                            a[i_,j] = a[i_,j] + stemp*a[i_,jp1];
343                        }
344                        for(i_=m1; i_<=m2;i_++)
345                        {
346                            a[i_,jp1] = work[i_];
347                        }
348                    }
349                }
350            }
351            else
352            {
353               
354                //
355                // Special case: M1=M2
356                //
357                for(j=n2-1; j>=n1; j--)
358                {
359                    ctemp = c[j-n1+1];
360                    stemp = s[j-n1+1];
361                    if( ctemp!=1 | stemp!=0 )
362                    {
363                        temp = a[m1,j+1];
364                        a[m1,j+1] = ctemp*temp-stemp*a[m1,j];
365                        a[m1,j] = stemp*temp+ctemp*a[m1,j];
366                    }
367                }
368            }
369        }
370    }
371
372
373    /*************************************************************************
374    The subroutine generates the elementary rotation, so that:
375
376    [  CS  SN  ]  .  [ F ]  =  [ R ]
377    [ -SN  CS  ]     [ G ]     [ 0 ]
378
379    CS**2 + SN**2 = 1
380    *************************************************************************/
381    public static void generaterotation(double f,
382        double g,
383        ref double cs,
384        ref double sn,
385        ref double r)
386    {
387        double f1 = 0;
388        double g1 = 0;
389
390        if( g==0 )
391        {
392            cs = 1;
393            sn = 0;
394            r = f;
395        }
396        else
397        {
398            if( f==0 )
399            {
400                cs = 0;
401                sn = 1;
402                r = g;
403            }
404            else
405            {
406                f1 = f;
407                g1 = g;
408                r = Math.Sqrt(AP.Math.Sqr(f1)+AP.Math.Sqr(g1));
409                cs = f1/r;
410                sn = g1/r;
411                if( Math.Abs(f)>Math.Abs(g) & cs<0 )
412                {
413                    cs = -cs;
414                    sn = -sn;
415                    r = -r;
416                }
417            }
418        }
419    }
420
421
422    private static void testrotations()
423    {
424        double[,] al1 = new double[0,0];
425        double[,] al2 = new double[0,0];
426        double[,] ar1 = new double[0,0];
427        double[,] ar2 = new double[0,0];
428        double[] cl = new double[0];
429        double[] sl = new double[0];
430        double[] cr = new double[0];
431        double[] sr = new double[0];
432        double[] w = new double[0];
433        int m = 0;
434        int n = 0;
435        int maxmn = 0;
436        double t = 0;
437        int pass = 0;
438        int passcount = 0;
439        int i = 0;
440        int j = 0;
441        double err = 0;
442        double maxerr = 0;
443        bool isforward = new bool();
444
445        passcount = 1000;
446        maxerr = 0;
447        for(pass=1; pass<=passcount; pass++)
448        {
449           
450            //
451            // settings
452            //
453            m = 2+AP.Math.RandomInteger(50);
454            n = 2+AP.Math.RandomInteger(50);
455            isforward = AP.Math.RandomReal()>0.5;
456            maxmn = Math.Max(m, n);
457            al1 = new double[m+1, n+1];
458            al2 = new double[m+1, n+1];
459            ar1 = new double[m+1, n+1];
460            ar2 = new double[m+1, n+1];
461            cl = new double[m-1+1];
462            sl = new double[m-1+1];
463            cr = new double[n-1+1];
464            sr = new double[n-1+1];
465            w = new double[maxmn+1];
466           
467            //
468            // matrices and rotaions
469            //
470            for(i=1; i<=m; i++)
471            {
472                for(j=1; j<=n; j++)
473                {
474                    al1[i,j] = 2*AP.Math.RandomReal()-1;
475                    al2[i,j] = al1[i,j];
476                    ar1[i,j] = al1[i,j];
477                    ar2[i,j] = al1[i,j];
478                }
479            }
480            for(i=1; i<=m-1; i++)
481            {
482                t = 2*Math.PI*AP.Math.RandomReal();
483                cl[i] = Math.Cos(t);
484                sl[i] = Math.Sin(t);
485            }
486            for(j=1; j<=n-1; j++)
487            {
488                t = 2*Math.PI*AP.Math.RandomReal();
489                cr[j] = Math.Cos(t);
490                sr[j] = Math.Sin(t);
491            }
492           
493            //
494            // Test left
495            //
496            applyrotationsfromtheleft(isforward, 1, m, 1, n, ref cl, ref sl, ref al1, ref w);
497            for(j=1; j<=n; j++)
498            {
499                applyrotationsfromtheleft(isforward, 1, m, j, j, ref cl, ref sl, ref al2, ref w);
500            }
501            err = 0;
502            for(i=1; i<=m; i++)
503            {
504                for(j=1; j<=n; j++)
505                {
506                    err = Math.Max(err, Math.Abs(al1[i,j]-al2[i,j]));
507                }
508            }
509            maxerr = Math.Max(err, maxerr);
510           
511            //
512            // Test right
513            //
514            applyrotationsfromtheright(isforward, 1, m, 1, n, ref cr, ref sr, ref ar1, ref w);
515            for(i=1; i<=m; i++)
516            {
517                applyrotationsfromtheright(isforward, i, i, 1, n, ref cr, ref sr, ref ar2, ref w);
518            }
519            err = 0;
520            for(i=1; i<=m; i++)
521            {
522                for(j=1; j<=n; j++)
523                {
524                    err = Math.Max(err, Math.Abs(ar1[i,j]-ar2[i,j]));
525                }
526            }
527            maxerr = Math.Max(err, maxerr);
528        }
529        System.Console.Write("TESTING ROTATIONS");
530        System.Console.WriteLine();
531        System.Console.Write("Pass count ");
532        System.Console.Write("{0,0:d}",passcount);
533        System.Console.WriteLine();
534        System.Console.Write("Error is ");
535        System.Console.Write("{0,5:E3}",maxerr);
536        System.Console.WriteLine();
537    }
538}
Note: See TracBrowser for help on using the repository browser.