Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/ALGLIB/reflections.cs @ 2515

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

Moved ALGLIB code into a separate plugin. #783

File size: 10.9 KB
RevLine 
[2154]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
[2430]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.
[2154]15
[2430]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.
[2154]20
[2430]21A copy of the GNU General Public License is available at
22http://www.fsf.org/licensing/licenses
[2154]23
[2430]24>>> END OF LICENSE >>>
[2154]25*************************************************************************/
26
27using System;
28
[2430]29namespace alglib
[2154]30{
[2430]31    public class reflections
32    {
33        /*************************************************************************
34        Generation of an elementary reflection transformation
[2154]35
[2430]36        The subroutine generates elementary reflection H of order N, so that, for
37        a given X, the following equality holds true:
[2154]38
[2430]39            ( X(1) )   ( Beta )
40        H * (  ..  ) = (  0   )
41            ( X(n) )   (  0   )
[2154]42
[2430]43        where
44                      ( V(1) )
45        H = 1 - Tau * (  ..  ) * ( V(1), ..., V(n) )
46                      ( V(n) )
[2154]47
[2430]48        where the first component of vector V equals 1.
[2154]49
[2430]50        Input parameters:
51            X   -   vector. Array whose index ranges within [1..N].
52            N   -   reflection order.
[2154]53
[2430]54        Output parameters:
55            X   -   components from 2 to N are replaced with vector V.
56                    The first component is replaced with parameter Beta.
57            Tau -   scalar value Tau. If X is a null vector, Tau equals 0,
58                    otherwise 1 <= Tau <= 2.
[2154]59
[2430]60        This subroutine is the modification of the DLARFG subroutines from
61        the LAPACK library.
[2154]62
[2430]63        MODIFICATIONS:
64            24.12.2005 sign(Alpha) was replaced with an analogous to the Fortran SIGN code.
[2154]65
[2430]66          -- LAPACK auxiliary routine (version 3.0) --
67             Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
68             Courant Institute, Argonne National Lab, and Rice University
69             September 30, 1994
70        *************************************************************************/
71        public static void generatereflection(ref double[] x,
72            int n,
73            ref double tau)
[2154]74        {
[2430]75            int j = 0;
76            double alpha = 0;
77            double xnorm = 0;
78            double v = 0;
79            double beta = 0;
80            double mx = 0;
81            double s = 0;
82            int i_ = 0;
[2154]83
[2430]84            if( n<=1 )
[2154]85            {
[2430]86                tau = 0;
87                return;
[2154]88            }
89           
90            //
[2430]91            // Scale if needed (to avoid overflow/underflow during intermediate
92            // calculations).
[2154]93            //
[2430]94            mx = 0;
95            for(j=1; j<=n; j++)
[2154]96            {
[2430]97                mx = Math.Max(Math.Abs(x[j]), mx);
[2154]98            }
[2430]99            s = 1;
100            if( mx!=0 )
[2154]101            {
[2430]102                if( mx<=AP.Math.MinRealNumber/AP.Math.MachineEpsilon )
[2154]103                {
[2430]104                    s = AP.Math.MinRealNumber/AP.Math.MachineEpsilon;
105                    v = 1/s;
106                    for(i_=1; i_<=n;i_++)
[2154]107                    {
[2430]108                        x[i_] = v*x[i_];
[2154]109                    }
[2430]110                    mx = mx*v;
111                }
112                else
113                {
114                    if( mx>=AP.Math.MaxRealNumber*AP.Math.MachineEpsilon )
[2154]115                    {
[2430]116                        s = AP.Math.MaxRealNumber*AP.Math.MachineEpsilon;
117                        v = 1/s;
118                        for(i_=1; i_<=n;i_++)
119                        {
120                            x[i_] = v*x[i_];
121                        }
122                        mx = mx*v;
[2154]123                    }
124                }
125            }
[2430]126           
127            //
128            // XNORM = DNRM2( N-1, X, INCX )
129            //
130            alpha = x[1];
131            xnorm = 0;
132            if( mx!=0 )
[2154]133            {
[2430]134                for(j=2; j<=n; j++)
[2154]135                {
[2430]136                    xnorm = xnorm+AP.Math.Sqr(x[j]/mx);
[2154]137                }
[2430]138                xnorm = Math.Sqrt(xnorm)*mx;
[2154]139            }
[2430]140            if( xnorm==0 )
141            {
142               
143                //
144                // H  =  I
145                //
146                tau = 0;
147                x[1] = x[1]*s;
148                return;
149            }
[2154]150           
151            //
[2430]152            // general case
[2154]153            //
[2430]154            mx = Math.Max(Math.Abs(alpha), Math.Abs(xnorm));
155            beta = -(mx*Math.Sqrt(AP.Math.Sqr(alpha/mx)+AP.Math.Sqr(xnorm/mx)));
156            if( alpha<0 )
[2154]157            {
[2430]158                beta = -beta;
[2154]159            }
[2430]160            tau = (beta-alpha)/beta;
161            v = 1/(alpha-beta);
162            for(i_=2; i_<=n;i_++)
[2154]163            {
[2430]164                x[i_] = v*x[i_];
[2154]165            }
[2430]166            x[1] = beta;
167           
168            //
169            // Scale back outputs
170            //
171            x[1] = x[1]*s;
172        }
173
174
175        /*************************************************************************
176        Application of an elementary reflection to a rectangular matrix of size MxN
177
178        The algorithm pre-multiplies the matrix by an elementary reflection transformation
179        which is given by column V and scalar Tau (see the description of the
180        GenerateReflection procedure). Not the whole matrix but only a part of it
181        is transformed (rows from M1 to M2, columns from N1 to N2). Only the elements
182        of this submatrix are changed.
183
184        Input parameters:
185            C       -   matrix to be transformed.
186            Tau     -   scalar defining the transformation.
187            V       -   column defining the transformation.
188                        Array whose index ranges within [1..M2-M1+1].
189            M1, M2  -   range of rows to be transformed.
190            N1, N2  -   range of columns to be transformed.
191            WORK    -   working array whose indexes goes from N1 to N2.
192
193        Output parameters:
194            C       -   the result of multiplying the input matrix C by the
195                        transformation matrix which is given by Tau and V.
196                        If N1>N2 or M1>M2, C is not modified.
197
198          -- LAPACK auxiliary routine (version 3.0) --
199             Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
200             Courant Institute, Argonne National Lab, and Rice University
201             September 30, 1994
202        *************************************************************************/
203        public static void applyreflectionfromtheleft(ref double[,] c,
204            double tau,
205            ref double[] v,
206            int m1,
207            int m2,
208            int n1,
209            int n2,
210            ref double[] work)
211        {
212            double t = 0;
213            int i = 0;
214            int vm = 0;
215            int i_ = 0;
216
217            if( tau==0 | n1>n2 | m1>m2 )
[2154]218            {
[2430]219                return;
[2154]220            }
[2430]221           
222            //
223            // w := C' * v
224            //
225            vm = m2-m1+1;
226            for(i=n1; i<=n2; i++)
[2154]227            {
[2430]228                work[i] = 0;
[2154]229            }
[2430]230            for(i=m1; i<=m2; i++)
[2154]231            {
[2430]232                t = v[i+1-m1];
233                for(i_=n1; i_<=n2;i_++)
[2154]234                {
[2430]235                    work[i_] = work[i_] + t*c[i,i_];
[2154]236                }
237            }
238           
239            //
[2430]240            // C := C - tau * v * w'
[2154]241            //
[2430]242            for(i=m1; i<=m2; i++)
[2154]243            {
[2430]244                t = v[i-m1+1]*tau;
245                for(i_=n1; i_<=n2;i_++)
[2154]246                {
[2430]247                    c[i,i_] = c[i,i_] - t*work[i_];
[2154]248                }
249            }
[2430]250        }
251
252
253        /*************************************************************************
254        Application of an elementary reflection to a rectangular matrix of size MxN
255
256        The algorithm post-multiplies the matrix by an elementary reflection transformation
257        which is given by column V and scalar Tau (see the description of the
258        GenerateReflection procedure). Not the whole matrix but only a part of it
259        is transformed (rows from M1 to M2, columns from N1 to N2). Only the
260        elements of this submatrix are changed.
261
262        Input parameters:
263            C       -   matrix to be transformed.
264            Tau     -   scalar defining the transformation.
265            V       -   column defining the transformation.
266                        Array whose index ranges within [1..N2-N1+1].
267            M1, M2  -   range of rows to be transformed.
268            N1, N2  -   range of columns to be transformed.
269            WORK    -   working array whose indexes goes from M1 to M2.
270
271        Output parameters:
272            C       -   the result of multiplying the input matrix C by the
273                        transformation matrix which is given by Tau and V.
274                        If N1>N2 or M1>M2, C is not modified.
275
276          -- LAPACK auxiliary routine (version 3.0) --
277             Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
278             Courant Institute, Argonne National Lab, and Rice University
279             September 30, 1994
280        *************************************************************************/
281        public static void applyreflectionfromtheright(ref double[,] c,
282            double tau,
283            ref double[] v,
284            int m1,
285            int m2,
286            int n1,
287            int n2,
288            ref double[] work)
289        {
290            double t = 0;
291            int i = 0;
292            int vm = 0;
293            int i_ = 0;
294            int i1_ = 0;
295
296            if( tau==0 | n1>n2 | m1>m2 )
[2154]297            {
[2430]298                return;
[2154]299            }
[2430]300           
301            //
302            // w := C * v
303            //
304            vm = n2-n1+1;
305            for(i=m1; i<=m2; i++)
[2154]306            {
[2430]307                i1_ = (1)-(n1);
308                t = 0.0;
309                for(i_=n1; i_<=n2;i_++)
[2154]310                {
[2430]311                    t += c[i,i_]*v[i_+i1_];
[2154]312                }
[2430]313                work[i] = t;
[2154]314            }
[2430]315           
316            //
317            // C := C - w * v'
318            //
319            for(i=m1; i<=m2; i++)
[2154]320            {
[2430]321                t = work[i]*tau;
322                i1_ = (1) - (n1);
323                for(i_=n1; i_<=n2;i_++)
[2154]324                {
[2430]325                    c[i,i_] = c[i,i_] - t*v[i_+i1_];
[2154]326                }
327            }
328        }
329    }
330}
Note: See TracBrowser for help on using the repository browser.