Free cookie consent management tool by TermsFeed Policy Generator

source: branches/Persistence Test/ALGLIB/reflections.cs @ 3931

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

Moved ALGLIB code into a separate plugin. #783

File size: 10.9 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 reflections
32    {
33        /*************************************************************************
34        Generation of an elementary reflection transformation
35
36        The subroutine generates elementary reflection H of order N, so that, for
37        a given X, the following equality holds true:
38
39            ( X(1) )   ( Beta )
40        H * (  ..  ) = (  0   )
41            ( X(n) )   (  0   )
42
43        where
44                      ( V(1) )
45        H = 1 - Tau * (  ..  ) * ( V(1), ..., V(n) )
46                      ( V(n) )
47
48        where the first component of vector V equals 1.
49
50        Input parameters:
51            X   -   vector. Array whose index ranges within [1..N].
52            N   -   reflection order.
53
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.
59
60        This subroutine is the modification of the DLARFG subroutines from
61        the LAPACK library.
62
63        MODIFICATIONS:
64            24.12.2005 sign(Alpha) was replaced with an analogous to the Fortran SIGN code.
65
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)
74        {
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;
83
84            if( n<=1 )
85            {
86                tau = 0;
87                return;
88            }
89           
90            //
91            // Scale if needed (to avoid overflow/underflow during intermediate
92            // calculations).
93            //
94            mx = 0;
95            for(j=1; j<=n; j++)
96            {
97                mx = Math.Max(Math.Abs(x[j]), mx);
98            }
99            s = 1;
100            if( mx!=0 )
101            {
102                if( mx<=AP.Math.MinRealNumber/AP.Math.MachineEpsilon )
103                {
104                    s = AP.Math.MinRealNumber/AP.Math.MachineEpsilon;
105                    v = 1/s;
106                    for(i_=1; i_<=n;i_++)
107                    {
108                        x[i_] = v*x[i_];
109                    }
110                    mx = mx*v;
111                }
112                else
113                {
114                    if( mx>=AP.Math.MaxRealNumber*AP.Math.MachineEpsilon )
115                    {
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;
123                    }
124                }
125            }
126           
127            //
128            // XNORM = DNRM2( N-1, X, INCX )
129            //
130            alpha = x[1];
131            xnorm = 0;
132            if( mx!=0 )
133            {
134                for(j=2; j<=n; j++)
135                {
136                    xnorm = xnorm+AP.Math.Sqr(x[j]/mx);
137                }
138                xnorm = Math.Sqrt(xnorm)*mx;
139            }
140            if( xnorm==0 )
141            {
142               
143                //
144                // H  =  I
145                //
146                tau = 0;
147                x[1] = x[1]*s;
148                return;
149            }
150           
151            //
152            // general case
153            //
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 )
157            {
158                beta = -beta;
159            }
160            tau = (beta-alpha)/beta;
161            v = 1/(alpha-beta);
162            for(i_=2; i_<=n;i_++)
163            {
164                x[i_] = v*x[i_];
165            }
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 )
218            {
219                return;
220            }
221           
222            //
223            // w := C' * v
224            //
225            vm = m2-m1+1;
226            for(i=n1; i<=n2; i++)
227            {
228                work[i] = 0;
229            }
230            for(i=m1; i<=m2; i++)
231            {
232                t = v[i+1-m1];
233                for(i_=n1; i_<=n2;i_++)
234                {
235                    work[i_] = work[i_] + t*c[i,i_];
236                }
237            }
238           
239            //
240            // C := C - tau * v * w'
241            //
242            for(i=m1; i<=m2; i++)
243            {
244                t = v[i-m1+1]*tau;
245                for(i_=n1; i_<=n2;i_++)
246                {
247                    c[i,i_] = c[i,i_] - t*work[i_];
248                }
249            }
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 )
297            {
298                return;
299            }
300           
301            //
302            // w := C * v
303            //
304            vm = n2-n1+1;
305            for(i=m1; i<=m2; i++)
306            {
307                i1_ = (1)-(n1);
308                t = 0.0;
309                for(i_=n1; i_<=n2;i_++)
310                {
311                    t += c[i,i_]*v[i_+i1_];
312                }
313                work[i] = t;
314            }
315           
316            //
317            // C := C - w * v'
318            //
319            for(i=m1; i<=m2; i++)
320            {
321                t = work[i]*tau;
322                i1_ = (1) - (n1);
323                for(i_=n1; i_<=n2;i_++)
324                {
325                    c[i,i_] = c[i,i_] - t*v[i_+i1_];
326                }
327            }
328        }
329    }
330}
Note: See TracBrowser for help on using the repository browser.