[2806] | 1 | /*************************************************************************
|
---|
| 2 | Copyright (c) 1992-2007 The University of Tennessee. All rights reserved.
|
---|
| 3 |
|
---|
| 4 | Contributors:
|
---|
| 5 | * Sergey Bochkanov (ALGLIB project). Translation from FORTRAN to
|
---|
| 6 | pseudocode.
|
---|
| 7 |
|
---|
| 8 | See subroutines comments for additional copyrights.
|
---|
| 9 |
|
---|
| 10 | >>> SOURCE LICENSE >>>
|
---|
| 11 | This program is free software; you can redistribute it and/or modify
|
---|
| 12 | it under the terms of the GNU General Public License as published by
|
---|
| 13 | the Free Software Foundation (www.fsf.org); either version 2 of the
|
---|
| 14 | License, or (at your option) any later version.
|
---|
| 15 |
|
---|
| 16 | This program is distributed in the hope that it will be useful,
|
---|
| 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
| 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
| 19 | GNU General Public License for more details.
|
---|
| 20 |
|
---|
| 21 | A copy of the GNU General Public License is available at
|
---|
| 22 | http://www.fsf.org/licensing/licenses
|
---|
| 23 |
|
---|
| 24 | >>> END OF LICENSE >>>
|
---|
| 25 | *************************************************************************/
|
---|
| 26 |
|
---|
| 27 | using System;
|
---|
| 28 |
|
---|
| 29 | namespace alglib
|
---|
| 30 | {
|
---|
| 31 | public class creflections
|
---|
| 32 | {
|
---|
| 33 | /*************************************************************************
|
---|
| 34 | Generation of an elementary complex reflection transformation
|
---|
| 35 |
|
---|
| 36 | The subroutine generates elementary complex reflection H of order N, so
|
---|
| 37 | that, for a given X, the following equality holds true:
|
---|
| 38 |
|
---|
| 39 | ( X(1) ) ( Beta )
|
---|
| 40 | H' * ( .. ) = ( 0 ), H'*H = I, Beta is a real number
|
---|
| 41 | ( X(n) ) ( 0 )
|
---|
| 42 |
|
---|
| 43 | where
|
---|
| 44 |
|
---|
| 45 | ( V(1) )
|
---|
| 46 | H = 1 - Tau * ( .. ) * ( conj(V(1)), ..., conj(V(n)) )
|
---|
| 47 | ( V(n) )
|
---|
| 48 |
|
---|
| 49 | where the first component of vector V equals 1.
|
---|
| 50 |
|
---|
| 51 | Input parameters:
|
---|
| 52 | X - vector. Array with elements [1..N].
|
---|
| 53 | N - reflection order.
|
---|
| 54 |
|
---|
| 55 | Output parameters:
|
---|
| 56 | X - components from 2 to N are replaced by vector V.
|
---|
| 57 | The first component is replaced with parameter Beta.
|
---|
| 58 | Tau - scalar value Tau.
|
---|
| 59 |
|
---|
| 60 | This subroutine is the modification of CLARFG subroutines from the LAPACK
|
---|
| 61 | library. It has similar functionality except for the fact that it doesnt
|
---|
| 62 | handle errors when intermediate results cause an overflow.
|
---|
| 63 |
|
---|
| 64 | -- LAPACK auxiliary routine (version 3.0) --
|
---|
| 65 | Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
|
---|
| 66 | Courant Institute, Argonne National Lab, and Rice University
|
---|
| 67 | September 30, 1994
|
---|
| 68 | *************************************************************************/
|
---|
| 69 | public static void complexgeneratereflection(ref AP.Complex[] x,
|
---|
| 70 | int n,
|
---|
| 71 | ref AP.Complex tau)
|
---|
| 72 | {
|
---|
| 73 | int j = 0;
|
---|
| 74 | AP.Complex alpha = 0;
|
---|
| 75 | double alphi = 0;
|
---|
| 76 | double alphr = 0;
|
---|
| 77 | double beta = 0;
|
---|
| 78 | double xnorm = 0;
|
---|
| 79 | double mx = 0;
|
---|
| 80 | AP.Complex t = 0;
|
---|
| 81 | int i_ = 0;
|
---|
| 82 |
|
---|
| 83 | if( n<=0 )
|
---|
| 84 | {
|
---|
| 85 | tau = 0;
|
---|
| 86 | return;
|
---|
| 87 | }
|
---|
| 88 | alpha = x[1];
|
---|
| 89 | mx = 0;
|
---|
| 90 | for(j=2; j<=n; j++)
|
---|
| 91 | {
|
---|
| 92 | mx = Math.Max(AP.Math.AbsComplex(x[j]), mx);
|
---|
| 93 | }
|
---|
| 94 | xnorm = 0;
|
---|
| 95 | if( (double)(mx)!=(double)(0) )
|
---|
| 96 | {
|
---|
| 97 | for(j=2; j<=n; j++)
|
---|
| 98 | {
|
---|
| 99 | t = x[j]/mx;
|
---|
| 100 | xnorm = xnorm+(t*AP.Math.Conj(t)).x;
|
---|
| 101 | }
|
---|
| 102 | xnorm = Math.Sqrt(xnorm)*mx;
|
---|
| 103 | }
|
---|
| 104 | alphr = alpha.x;
|
---|
| 105 | alphi = alpha.y;
|
---|
| 106 | if( (double)(xnorm)==(double)(0) & (double)(alphi)==(double)(0) )
|
---|
| 107 | {
|
---|
| 108 | tau = 0;
|
---|
| 109 | return;
|
---|
| 110 | }
|
---|
| 111 | mx = Math.Max(Math.Abs(alphr), Math.Abs(alphi));
|
---|
| 112 | mx = Math.Max(mx, Math.Abs(xnorm));
|
---|
| 113 | beta = -(mx*Math.Sqrt(AP.Math.Sqr(alphr/mx)+AP.Math.Sqr(alphi/mx)+AP.Math.Sqr(xnorm/mx)));
|
---|
| 114 | if( (double)(alphr)<(double)(0) )
|
---|
| 115 | {
|
---|
| 116 | beta = -beta;
|
---|
| 117 | }
|
---|
| 118 | tau.x = (beta-alphr)/beta;
|
---|
| 119 | tau.y = -(alphi/beta);
|
---|
| 120 | alpha = 1/(alpha-beta);
|
---|
| 121 | if( n>1 )
|
---|
| 122 | {
|
---|
| 123 | for(i_=2; i_<=n;i_++)
|
---|
| 124 | {
|
---|
| 125 | x[i_] = alpha*x[i_];
|
---|
| 126 | }
|
---|
| 127 | }
|
---|
| 128 | alpha = beta;
|
---|
| 129 | x[1] = alpha;
|
---|
| 130 | }
|
---|
| 131 |
|
---|
| 132 |
|
---|
| 133 | /*************************************************************************
|
---|
| 134 | Application of an elementary reflection to a rectangular matrix of size MxN
|
---|
| 135 |
|
---|
| 136 | The algorithm pre-multiplies the matrix by an elementary reflection
|
---|
| 137 | transformation which is given by column V and scalar Tau (see the
|
---|
| 138 | description of the GenerateReflection). Not the whole matrix but only a
|
---|
| 139 | part of it is transformed (rows from M1 to M2, columns from N1 to N2). Only
|
---|
| 140 | the elements of this submatrix are changed.
|
---|
| 141 |
|
---|
| 142 | Note: the matrix is multiplied by H, not by H'. If it is required to
|
---|
| 143 | multiply the matrix by H', it is necessary to pass Conj(Tau) instead of Tau.
|
---|
| 144 |
|
---|
| 145 | Input parameters:
|
---|
| 146 | C - matrix to be transformed.
|
---|
| 147 | Tau - scalar defining transformation.
|
---|
| 148 | V - column defining transformation.
|
---|
| 149 | Array whose index ranges within [1..M2-M1+1]
|
---|
| 150 | M1, M2 - range of rows to be transformed.
|
---|
| 151 | N1, N2 - range of columns to be transformed.
|
---|
| 152 | WORK - working array whose index goes from N1 to N2.
|
---|
| 153 |
|
---|
| 154 | Output parameters:
|
---|
| 155 | C - the result of multiplying the input matrix C by the
|
---|
| 156 | transformation matrix which is given by Tau and V.
|
---|
| 157 | If N1>N2 or M1>M2, C is not modified.
|
---|
| 158 |
|
---|
| 159 | -- LAPACK auxiliary routine (version 3.0) --
|
---|
| 160 | Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
|
---|
| 161 | Courant Institute, Argonne National Lab, and Rice University
|
---|
| 162 | September 30, 1994
|
---|
| 163 | *************************************************************************/
|
---|
| 164 | public static void complexapplyreflectionfromtheleft(ref AP.Complex[,] c,
|
---|
| 165 | AP.Complex tau,
|
---|
| 166 | ref AP.Complex[] v,
|
---|
| 167 | int m1,
|
---|
| 168 | int m2,
|
---|
| 169 | int n1,
|
---|
| 170 | int n2,
|
---|
| 171 | ref AP.Complex[] work)
|
---|
| 172 | {
|
---|
| 173 | AP.Complex t = 0;
|
---|
| 174 | int i = 0;
|
---|
| 175 | int vm = 0;
|
---|
| 176 | int i_ = 0;
|
---|
| 177 |
|
---|
| 178 | if( tau==0 | n1>n2 | m1>m2 )
|
---|
| 179 | {
|
---|
| 180 | return;
|
---|
| 181 | }
|
---|
| 182 |
|
---|
| 183 | //
|
---|
| 184 | // w := C^T * conj(v)
|
---|
| 185 | //
|
---|
| 186 | vm = m2-m1+1;
|
---|
| 187 | for(i=n1; i<=n2; i++)
|
---|
| 188 | {
|
---|
| 189 | work[i] = 0;
|
---|
| 190 | }
|
---|
| 191 | for(i=m1; i<=m2; i++)
|
---|
| 192 | {
|
---|
| 193 | t = AP.Math.Conj(v[i+1-m1]);
|
---|
| 194 | for(i_=n1; i_<=n2;i_++)
|
---|
| 195 | {
|
---|
| 196 | work[i_] = work[i_] + t*c[i,i_];
|
---|
| 197 | }
|
---|
| 198 | }
|
---|
| 199 |
|
---|
| 200 | //
|
---|
| 201 | // C := C - tau * v * w^T
|
---|
| 202 | //
|
---|
| 203 | for(i=m1; i<=m2; i++)
|
---|
| 204 | {
|
---|
| 205 | t = v[i-m1+1]*tau;
|
---|
| 206 | for(i_=n1; i_<=n2;i_++)
|
---|
| 207 | {
|
---|
| 208 | c[i,i_] = c[i,i_] - t*work[i_];
|
---|
| 209 | }
|
---|
| 210 | }
|
---|
| 211 | }
|
---|
| 212 |
|
---|
| 213 |
|
---|
| 214 | /*************************************************************************
|
---|
| 215 | Application of an elementary reflection to a rectangular matrix of size MxN
|
---|
| 216 |
|
---|
| 217 | The algorithm post-multiplies the matrix by an elementary reflection
|
---|
| 218 | transformation which is given by column V and scalar Tau (see the
|
---|
| 219 | description of the GenerateReflection). Not the whole matrix but only a
|
---|
| 220 | part of it is transformed (rows from M1 to M2, columns from N1 to N2).
|
---|
| 221 | Only the elements of this submatrix are changed.
|
---|
| 222 |
|
---|
| 223 | Input parameters:
|
---|
| 224 | C - matrix to be transformed.
|
---|
| 225 | Tau - scalar defining transformation.
|
---|
| 226 | V - column defining transformation.
|
---|
| 227 | Array whose index ranges within [1..N2-N1+1]
|
---|
| 228 | M1, M2 - range of rows to be transformed.
|
---|
| 229 | N1, N2 - range of columns to be transformed.
|
---|
| 230 | WORK - working array whose index goes from M1 to M2.
|
---|
| 231 |
|
---|
| 232 | Output parameters:
|
---|
| 233 | C - the result of multiplying the input matrix C by the
|
---|
| 234 | transformation matrix which is given by Tau and V.
|
---|
| 235 | If N1>N2 or M1>M2, C is not modified.
|
---|
| 236 |
|
---|
| 237 | -- LAPACK auxiliary routine (version 3.0) --
|
---|
| 238 | Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
|
---|
| 239 | Courant Institute, Argonne National Lab, and Rice University
|
---|
| 240 | September 30, 1994
|
---|
| 241 | *************************************************************************/
|
---|
| 242 | public static void complexapplyreflectionfromtheright(ref AP.Complex[,] c,
|
---|
| 243 | AP.Complex tau,
|
---|
| 244 | ref AP.Complex[] v,
|
---|
| 245 | int m1,
|
---|
| 246 | int m2,
|
---|
| 247 | int n1,
|
---|
| 248 | int n2,
|
---|
| 249 | ref AP.Complex[] work)
|
---|
| 250 | {
|
---|
| 251 | AP.Complex t = 0;
|
---|
| 252 | int i = 0;
|
---|
| 253 | int vm = 0;
|
---|
| 254 | int i_ = 0;
|
---|
| 255 | int i1_ = 0;
|
---|
| 256 |
|
---|
| 257 | if( tau==0 | n1>n2 | m1>m2 )
|
---|
| 258 | {
|
---|
| 259 | return;
|
---|
| 260 | }
|
---|
| 261 |
|
---|
| 262 | //
|
---|
| 263 | // w := C * v
|
---|
| 264 | //
|
---|
| 265 | vm = n2-n1+1;
|
---|
| 266 | for(i=m1; i<=m2; i++)
|
---|
| 267 | {
|
---|
| 268 | i1_ = (1)-(n1);
|
---|
| 269 | t = 0.0;
|
---|
| 270 | for(i_=n1; i_<=n2;i_++)
|
---|
| 271 | {
|
---|
| 272 | t += c[i,i_]*v[i_+i1_];
|
---|
| 273 | }
|
---|
| 274 | work[i] = t;
|
---|
| 275 | }
|
---|
| 276 |
|
---|
| 277 | //
|
---|
| 278 | // C := C - w * conj(v^T)
|
---|
| 279 | //
|
---|
| 280 | for(i_=1; i_<=vm;i_++)
|
---|
| 281 | {
|
---|
| 282 | v[i_] = AP.Math.Conj(v[i_]);
|
---|
| 283 | }
|
---|
| 284 | for(i=m1; i<=m2; i++)
|
---|
| 285 | {
|
---|
| 286 | t = work[i]*tau;
|
---|
| 287 | i1_ = (1) - (n1);
|
---|
| 288 | for(i_=n1; i_<=n2;i_++)
|
---|
| 289 | {
|
---|
| 290 | c[i,i_] = c[i,i_] - t*v[i_+i1_];
|
---|
| 291 | }
|
---|
| 292 | }
|
---|
| 293 | for(i_=1; i_<=vm;i_++)
|
---|
| 294 | {
|
---|
| 295 | v[i_] = AP.Math.Conj(v[i_]);
|
---|
| 296 | }
|
---|
| 297 | }
|
---|
| 298 | }
|
---|
| 299 | }
|
---|