comparison Matrix.h @ 1:6422640a802f

first upload
author Wen X <xue.wen@elec.qmul.ac.uk>
date Tue, 05 Oct 2010 10:45:57 +0100
parents
children
comparison
equal deleted inserted replaced
0:9b9f21935f24 1:6422640a802f
1 #ifndef MatrixH
2 #define MatrixH
3
4 /*
5 Matrix.cpp - matrix operations.
6
7 Matrices are accessed by double pointers as MATRIX[Y][X], where Y is the row index.
8 */
9
10 #include "xcomplex.h"
11 #include "arrayalloc.h"
12
13 //--Similar balance----------------------------------------------------------
14 void BalanceSim(int n, double** A);
15
16 //--Choleski factorization---------------------------------------------------
17 int Choleski(int N, double** L, double** A);
18
19 //--matrix copy--------------------------------------------------------------
20 double** Copy(int M, int N, double** Z, double** A, MList* List=0);
21 double** Copy(int M, int N, double** A, MList* List=0);
22 double** Copy(int N, double** Z, double ** A, MList* List=0);
23 double** Copy(int N, double ** A, MList* List=0);
24 cdouble** Copy(int M, int N, cdouble** Z, cdouble** A, MList* List=0);
25 cdouble** Copy(int M, int N, cdouble** A, MList* List=0);
26 cdouble** Copy(int N, cdouble** Z, cdouble** A, MList* List=0);
27 cdouble** Copy(int N, cdouble** A, MList* List=0);
28 double* Copy(int N, double* z, double* a, MList* List=0);
29 double* Copy(int N, double* a, MList* List=0);
30 cdouble* Copy(int N, cdouble* z, cdouble* a, MList* List=0);
31 cdouble* Copy(int N, cdouble* a, MList* List=0);
32
33 //--matrix determinant calculation-------------------------------------------
34 double det(int N, double** A, int mode=0);
35 cdouble det(int N, cdouble** A, int mode=0);
36
37 //--power methods for solving eigenproblems----------------------------------
38 int EigPower(int N, double& l, double* x, double** A, double ep=1e-6, int maxiter=50);
39 int EigPowerA(int N, double& l, double* x, double** A, double ep=1e-6, int maxiter=50);
40 int EigPowerI(int N, double& l, double* x, double** A, double ep=1e-6, int maxiter=50);
41 int EigPowerS(int N, double& l, double* x, double** A, double ep=1e-6, int maxiter=50);
42 int EigPowerWielandt(int N, double& m, double* u, double l, double* v, double** A, double ep=1e-06, int maxiter=50);
43 int EigenValues(int N, double** A, cdouble* ev);
44 int EigSym(int N, double** A, double* d, double** Q);
45
46 //--Gaussian elimination for solving linear systems--------------------------
47 int GEB(int N, double* x, double** A, double* b);
48 int GESCP(int N, double* x, double** A, double*b);
49 void GExL(int N, double* x, double** L, double* a);
50 void GExLAdd(int N, double* x, double** L, double* a);
51 void GExL1(int N, double* x, double** L, double a);
52 void GExL1Add(int N, double* x, double** L, double a);
53
54 /*
55 template GECP: Gaussian elimination with maximal column pivoting for solving linear system Ax=b
56
57 In: matrix A[N][N], vector b[N]
58 Out: vector x[N]
59
60 Returns 0 if successful. Contents of matrix A and vector b are destroyed on return.
61 */
62 template<class T, class Ta>int GECP(int N, T* x, Ta** A, T *b, Ta* logdet=0)
63 {
64 if (logdet) *logdet=1E-302; int c, p, ip, *rp=new int[N]; for (int i=0; i<N; i++) rp[i]=i;
65 Ta m;
66 //Gaussian eliminating
67 for (int i=0; i<N-1; i++)
68 {
69 p=i, ip=i+1;
70 while (ip<N){if (fabs(A[rp[ip]][i])>fabs(A[rp[p]][i])) p=ip; ip++;}
71 if (A[rp[p]][i]==0) {delete[] rp; return 1;}
72 if (p!=i) {c=rp[i]; rp[i]=rp[p]; rp[p]=c;}
73 for (int j=i+1; j<N; j++)
74 {
75 m=A[rp[j]][i]/A[rp[i]][i];
76 A[rp[j]][i]=0;
77 for (int k=i+1; k<N; k++) A[rp[j]][k]-=m*A[rp[i]][k];
78 b[rp[j]]-=m*b[rp[i]];
79 }
80 }
81 if (A[rp[N-1]][N-1]==0) {delete[] rp; return 1;}
82 //backward substitution
83 x[N-1]=b[rp[N-1]]/A[rp[N-1]][N-1];
84 for (int i=N-2; i>=0; i--)
85 {
86 x[i]=b[rp[i]]; for (int j=i+1; j<N; j++) x[i]-=A[rp[i]][j]*x[j]; x[i]/=A[rp[i]][i];
87 }
88 if (logdet){*logdet=log(fabs(A[rp[0]][0])); for (int n=1; n<N; n++) *logdet+=log(fabs(A[rp[n]][n]));}
89 delete[] rp;
90 return 0;
91 }//GECP
92
93 //--inverse lower and upper triangular matrices------------------------------
94 double GILT(int N, double** A);
95 double GIUT(int N, double** A);
96
97 //--inverse matrix calculation with gaussian elimination---------------------
98 double GICP(int N, double** X, double** A);
99 double GICP(int N, double** A);
100 cdouble GICP(int N, cdouble** A);
101 double GISCP(int N, double** X, double** A);
102 double GISCP(int N, double** A);
103
104 //--Gaussian-Seidel method for solving linear systems------------------------
105 int GSI(int N, double* x0, double** A, double* b, double ep=1e-4, int maxiter=50);
106
107 //Reduction to upper Heissenberg matrix by elimination with pivoting
108 void Hessenb(int n, double** A);
109
110 //--Householder algorithm converting a matrix tridiagonal--------------------
111 void HouseHolder(int N, double** A);
112 void HouseHolder(int N, double** T, double** Q, double** A);
113 void HouseHolder(int n, double **A, double* d, double* sd);
114
115 //--inner product------------------------------------------------------------
116 double Inner(int N, double* x, double* y);
117 cdouble Inner(int N, double* x, cdouble* y);
118 cdouble Inner(int N, cdouble* x, cdouble* y);
119 cdouble Inner(int N, cfloat* x, cdouble* y);
120 cfloat Inner(int N, cfloat* x, cfloat* y);
121 double Inner(int M, int N, double** X, double** Y);
122
123 /*
124 template Inner: Inner product <xw, y>
125
126 In: vectors x[N], w[N] and y[N]
127
128 Returns inner product of xw and y.
129 */
130 template<class Tx, class Tw>cdouble Inner(int N, Tx* x, Tw* w, cdouble* y)
131 {
132 cdouble result=0;
133 for (int i=0; i<N; i++) result+=(x[i]*w[i])**y[i];
134 return result;
135 }//Inner
136 template<class Tx, class Tw>cdouble Inner(int N, Tx* x, Tw* w, double* y)
137 {
138 cdouble result=0;
139 for (int i=0; i<N; i++) result+=x[i]*w[i]*y[i];
140 return result;
141 }//Inner
142
143 //--Jacobi iterative method for solving linear systems-----------------------
144 int JI(int N, double* x, double** A, double* b, double ep=1e-4, int maxiter=50);
145
146 //--LDL factorization of a symmetric matrix----------------------------------
147 int LDL(int N, double** L, double* d, double** A);
148
149 //--LQ factorization by Gram-Schmidt-----------------------------------------
150 void LQ_GS(int M, int N, double** A, double** L, double** Q);
151
152 //--1-stage Least-square solution of overdetermined linear system------------
153 /*
154 template LSLinera: direct LS solution of A[M][N]x[N]=y[M], M>=N.
155
156 In: matrix A[M][N], vector y[M]
157 Out: vector x[N]
158
159 Returns the log determinant of AtA. Contents of matrix A and vector y are unchanged on return.
160 */
161 template <class T> T LSLinear(int M, int N, T* x, T** A, T* y)
162 {
163 MList* mlist=new MList;
164 T** AtA=MultiplyXtX(N, M, A, mlist);
165 T* Aty=MultiplyXty(N, M, A, y, mlist);
166 T result; GECP(N, x, AtA, Aty, &result);
167 delete mlist;
168 return result;
169 }//LSLinear
170
171 //--2-stage Least-square solution of overdetermined linear system------------
172 void LSLinear2(int M, int N, double* x, double** A, double* y);
173
174 //--LU factorization of a non-singular matrix--------------------------------
175 int LU_Direct(int mode, int N, double* diag, double** a);
176 int LU(int N, double** l, double** u, double** a); void LU_DiagL(int N, double** l, double* diagl, double** u, double** a);
177 int LU_PD(int N, double** b);
178 int LU_PD(int N, double** b, double* c);
179 double LUCP(double **a, int N, int *ind, int& parity, int mode=1);
180
181 //--LU factorization method for solving a linear system----------------------
182 void LU(int N, double* x, double** A, double* y, int* ind=0);
183
184 //--find maximum of vector---------------------------------------------------
185 int maxind(double* data, int from, int to);
186
187 //--matrix linear combination------------------------------------------------
188 /*
189 template MultiAdd: matrix linear combination Z=X+aY
190
191 In: matrices X[M][N], Y[M][N], scalar a
192 Out: matrix Z[M][N]
193
194 Returns pointer to Z. Z is created anew if Z=0 is specified on start.
195 */
196 template<class Tz, class Tx, class Ty, class Ta> Tz** MultiAdd(int M, int N, Tz** Z, Tx** X, Ty** Y, Ta a, MList* List=0)
197 {
198 if (!Z){Allocate2(Tz, M, N, Z); if (List) List->Add(Z, 2);}
199 for (int i=0; i<M; i++) for (int j=0; j<N; j++) Z[i][j]=X[i][j]+a*Y[i][j];
200 return Z;
201 }//MultiAdd
202
203 /*
204 template MultiAdd: vector linear combination z=x+ay
205
206 In: vectors x[N], y[N], scalar a
207 Out: vector z[N]
208
209 Returns pointer to z. z is created anew if z=0 is specified on start.
210 */
211 template<class Tz, class Tx, class Ty, class Ta> Tz* MultiAdd(int N, Tz* z, Tx* x, Ty* y, Ta a, MList* List=0)
212 {
213 if (!z){z=new Tz[N]; if (List) List->Add(z, 1);}
214 for (int i=0; i<N; i++) z[i]=x[i]+Ty(a)*y[i];
215 return z;
216 }//MultiAdd
217 template<class Tx, class Ty, class Ta> Tx* MultiAdd(int N, Tx* x, Ty* y, Ta a, MList* List=0)
218 {
219 return MultiAdd(N, (Tx*)0, x, y, a, List);
220 }//MultiAdd
221
222 //--matrix multiplication by constant----------------------------------------
223 /*
224 template Multiply: matrix-constant multiplication Z=aX
225
226 In: matrix X[M][N], scalar a
227 Out: matrix Z[M][N]
228
229 Returns pointer to Z. Z is created anew if Z=0 is specified on start.
230 */
231 template<class Tz, class Tx, class Ta> Tz** Multiply(int M, int N, Tz** Z, Tx** X, Ta a, MList* List=0)
232 {
233 if (!Z){Allocate2(Tz, M, N, Z); if (List) List->Add(Z, 2);}
234 for (int i=0; i<M; i++) for (int j=0; j<N; j++) Z[i][j]=a*X[i][j];
235 return Z;
236 }//Multiply
237
238 /*
239 template Multiply: vector-constant multiplication z=ax
240
241 In: matrix x[N], scalar a
242 Out: matrix z[N]
243
244 Returns pointer to z. z is created anew if z=0 is specified on start.
245 */
246 template<class Tz, class Tx, class Ta> Tz* Multiply(int N, Tz* z, Tx* x, Ta a, MList* List=0)
247 {
248 if (!z){z=new Tz[N]; if (List) List->Add(z, 1);}
249 for (int i=0; i<N; i++) z[i]=x[i]*a;
250 return z;
251 }//Multiply
252 template<class Tx, class Ta>Tx* Multiply(int N, Tx* x, Ta a, MList* List=0)
253 {
254 return Multiply(N, (Tx*)0, x, a, List);
255 }//Multiply
256
257 //--matrix multiplication operations-----------------------------------------
258 /*
259 macro Multiply_full: matrix-matrix multiplication z=xy and multiplication-accumulation z=z+xy.
260
261 Each expansion of the macro defines three function templates; two are named $MULTIPLY and do matrix
262 multiplication only; one is named $MULTIADD and accumulates the multiplicated result on top of a
263 specified matrix. One of the two $MULTIPLY functions allows using a pre-allocated matrix to accept
264 the matrix product, while the other directly allocates a new matrix and returns the pointer.
265
266 Functions are named after their exact functions. For example, MultiplyXYc multiplies matrix X with
267 the complex conjugate of matrix Y, where postfix "c" attched to Y stands for conjugate. Likewise,
268 the postfix "t" stands for transpose, and "h" stnads for Hermitian (conjugate transpose).
269
270 Three dimension arguments are needed by each function template. The first and last of the three are
271 the number of rows and columns, respectively, of the product (output) matrix. The middle one is the
272 "other", common dimension of both multiplier matrices.
273 */
274 #define Multiply_full(MULTIPLY, MULTIADD, xx, yy) \
275 template<class Tx, class Ty>Tx** MULTIPLY(int N, int M, int K, Tx** z, Tx** x, Ty** y, MList* List=0){ \
276 if (!z) {Allocate2(Tx, N, K, z); if (List) List->Add(z, 2);} \
277 for (int n=0; n<N; n++) for (int k=0; k<K; k++){ \
278 Tx zz=0; for (int m=0; m<M; m++) zz+=xx*yy; z[n][k]=zz;} return z;} \
279 template<class Tx, class Ty>Tx** MULTIPLY(int N, int M, int K, Tx** x, Ty** y, MList* List=0){ \
280 Tx** Allocate2(Tx, N, K, z); if (List) List->Add(z, 2); \
281 for (int n=0; n<N; n++) for (int k=0; k<K; k++){ \
282 Tx zz=0; for (int m=0; m<M; m++) zz+=xx*yy; z[n][k]=zz;} return z;} \
283 template<class Tx, class Ty>void MULTIADD(int N, int M, int K, Tx** z, Tx** x, Ty** y){ \
284 for (int n=0; n<N; n++) for (int k=0; k<K; k++){ \
285 Tx zz=0; for (int m=0; m<M; m++) zz+=xx*yy; z[n][k]+=zz;}}
286 Multiply_full(MultiplyXY, MultiAddXY, x[n][m], y[m][k]) //z[N][K]=x[N][M]y[M][K], identical z and x or y not allowed
287 Multiply_full(MultiplyXYc, MultiAddXYc, x[n][m], *y[m][k]) //z[N][K]=x[N][M](y*)[M][K], identical z and x or y not allowed
288 Multiply_full(MultiplyXYt, MultiAddXYt, x[n][m], y[k][m]) //z[N][K]=x[N][M]Yt[M][K], identical z and x or y not allowed
289 Multiply_full(MultiplyXYh, MultiAddXYh, x[n][m], *y[k][m]) //z[N][K]=x[N][M](Yt*)[M][K], identical z and x or y not allowed
290
291 /*
292 macro Multiply_square: square matrix multiplication z=xy and multiplication-accumulation z=z+xy.
293 Identical z and x allowed for multiplication but not for multiplication-accumulation.
294
295 Each expansion of the macro defines three function templates; two are named $MULTIPLY and do matrix
296 multiplication only; one is named $MULTIADD and accumulates the multiplicated result on top of a
297 specified matrix. One of the two $MULTIPLY functions allows using a pre-allocated matrix to accept
298 the matrix product, while the other directly allocates a new matrix and returns the pointer.
299 */
300 #define Multiply_square(MULTIPLY, MULTIADD) \
301 template<class T>T** MULTIPLY(int N, T** z, T** x, T** y, MList* List=0){ \
302 if (!z){Allocate2(T, N, N, z); if (List) List->Add(z, 2);} \
303 if (z!=x) MULTIPLY(N, N, N, z, x, y); else{ \
304 T* tmp=new T[N]; int sizeN=sizeof(T)*N; for (int i=0; i<N; i++){ \
305 MULTIPLY(1, N, N, &tmp, &x[i], y); memcpy(z[i], tmp, sizeN);} delete[] tmp;} \
306 return z;} \
307 template<class T>T** MULTIPLY(int N, T** x, T** y, MList* List=0){return MULTIPLY(N, N, N, x, y, List);}\
308 template<class T>void MULTIADD(int N, T** z, T** x, T** y){MULTIADD(N, N, N, z, x, y);}
309 Multiply_square(MultiplyXY, MultiAddXY)
310
311 /*
312 macro Multiply_xx: matrix self multiplication z=xx and self-multiplication-accumulation z=z+xx.
313
314 Each expansion of the macro defines three function templates; two are named $MULTIPLY and do matrix
315 multiplication only; one is named $MULTIADD and accumulates the multiplicated result on top of a
316 specified matrix. One of the two $MULTIPLY functions allows using a pre-allocated matrix to accept
317 the matrix product, while the other directly allocates a new matrix and returns the pointer.
318 */
319 #define Multiply_xx(MULTIPLY, MULTIADD, xx1, xx2, zzt) \
320 template<class T>T** MULTIPLY(int M, int N, T** z, T** x, MList* List=0){ \
321 if (!z){Allocate2(T, M, M, z); if (List) List->Add(z, 2);} \
322 for (int m=0; m<M; m++) for (int k=0; k<=m; k++){ \
323 T zz=0; for (int n=0; n<N; n++) zz+=xx1*xx2; z[m][k]=zz; if (m!=k) z[k][m]=zzt;} \
324 return z;} \
325 template<class T>T** MULTIPLY(int M, int N, T ** x, MList* List=0){ \
326 T** Allocate2(T, M, M, z); if (List) List->Add(z, 2); \
327 for (int m=0; m<M; m++) for (int k=0; k<=m; k++){ \
328 T zz=0; for (int n=0; n<N; n++) zz+=xx1*xx2; z[m][k]=zz; if (m!=k) z[k][m]=zzt;} \
329 return z;} \
330 template<class T>void MULTIADD(int M, int N, T** z, T** x){ \
331 for (int m=0; m<M; m++) for (int k=0; k<=m; k++){ \
332 T zz=0; for (int n=0; n<N; n++) zz+=xx1*xx2; z[m][k]+=zz; if (m!=k) z[k][m]+=zzt;}}
333 Multiply_xx(MultiplyXtX, MultiAddXtX, x[n][m], x[n][k], zz) //z[M][M]=xt[M][N]x[N][M], identical z and x NOT ALLOWED.
334 Multiply_xx(MultiplyXXt, MultiAddXXt, x[m][n], x[k][n], zz) //z[M][M]=X[M][N]xt[N][M], identical z and x NOT ALLOWED.
335 Multiply_xx(MultiplyXhX, MultiAddXhX, *x[n][m], x[n][k], *zz) //z[M][M]=(xt*)[M][N]x[N][M], identical z and x NOT ALLOWED.
336 Multiply_xx(MultiplyXXh, MultiAddXXh, x[m][n], *x[k][n], *zz) //z[M][M]=x[M][N](xt*)[N][M], identical z and x NOT ALLOWED.
337 Multiply_xx(MultiplyXcXt, MultiAddXcXt, *x[m][n], x[k][n], *zz) //z[M][M]=(x*)[M][N]xt[N][M], identical z and x NOT ALLOWED.
338
339 //matrix-vector multiplication routines
340 double* MultiplyXy(int M, int N, double* z, double** x, double* y, MList* List=0);
341 double* MultiplyXy(int M, int N, double** x, double* y, MList* List=0);
342 cdouble* MultiplyXy(int M, int N, cdouble* z, cdouble** x, cdouble* y, MList* List=0);
343 cdouble* MultiplyXy(int M, int N, cdouble** x, cdouble* y, MList* List=0);
344 cdouble* MultiplyXy(int M, int N, cdouble* z, double** x, cdouble* y, MList* List=0);
345 cdouble* MultiplyXy(int M, int N, double** x, cdouble* y, MList* List=0);
346 double* MultiplyxY(int M, int N, double* zt, double* xt, double** y, MList* List=0);
347 double* MultiplyxY(int M, int N, double* xt, double** y, MList* List=0);
348 cdouble* MultiplyxY(int M, int N, cdouble* zt, cdouble* xt, cdouble** y, MList* List=0);
349 cdouble* MultiplyxY(int M, int N, cdouble* xt, cdouble** y, MList* List=0);
350 double* MultiplyXty(int M, int N, double* z, double** x, double* y, MList* List=0);
351 double* MultiplyXty(int M, int N, double** x, double* y, MList* List=0);
352 cdouble* MultiplyXty(int M, int N, cdouble* z, cdouble** x, cdouble* y, MList* List=0);
353 cdouble* MultiplyXty(int M, int N, cdouble** x, cdouble* y, MList* List=0);
354 cdouble* MultiplyXhy(int M, int N, cdouble* z, cdouble** x, cdouble* y, MList* List=0);
355 cdouble* MultiplyXhy(int M, int N, cdouble** x, cdouble* y, MList* List=0);
356 cdouble* MultiplyXcy(int M, int N, cdouble* z, cdouble** x, cfloat* y, MList* List=0);
357 cdouble* MultiplyXcy(int M, int N, cdouble** x, cfloat* y, MList* List=0);
358 cdouble* MultiplyXcy(int M, int N, cdouble* z, cdouble** x, cdouble* y, MList* List=0);
359 cdouble* MultiplyXcy(int M, int N, cdouble** x, cdouble* y, MList* List=0);
360 double* MultiplyxYt(int M, int N, double* zt, double* xt, double** y, MList* MList=0);
361 double* MultiplyxYt(int M, int N, double* xt, double** y, MList* MList=0);
362
363 //--matrix norms-------------------------------------------------------------
364 double Norm1(int N, double** A);
365
366 //--QR factorization---------------------------------------------------------
367 void QR_GS(int M, int N, double** A, double** Q, double** R);
368 void QR_householder(int M, int N, double** A, double** Q, double** R);
369
370 //--QR factorization of a tridiagonal matrix---------------------------------
371 int QL(int N, double* d, double* sd, double** z);
372 int QR(int N, double **A, cdouble* ev);
373
374 //--QU factorization of a matrix---------------------------------------------
375 void QU(int N, double** Q, double** A);
376
377 //--Extract the real part----------------------------------------------------
378 double** Real(int M, int N, double** z, cdouble** x, MList* List);
379 double** Real(int M, int N, cdouble** x, MList* List);
380
381 //--Finding roots of real polynomials----------------------------------------
382 int Roots(int N, double* p, double* rr, double* ri);
383
384 //--Sor iterative method for solving linear systems--------------------------
385 int SorI(int N, double* x0, double** a, double* b, double w=1, double ep=1e-4, int maxiter=50);
386
387 //--Submatrix----------------------------------------------------------------
388 void SetSubMatrix(double** z, double** x, int Y1, int Y, int X1, int X);
389 void SetSubMatrix(cdouble** z, cdouble** x, int Y1, int Y, int X1, int X);
390 cdouble** SubMatrix(cdouble** z, cdouble** x, int Y1, int Y, int X1, int X, MList* List=0);
391 cdouble** SubMatrix(cdouble** x, int Y1, int Y, int X1, int X, MList* List=0);
392 cdouble* SubVector(cdouble* z, cdouble* x, int X1, int X, MList* List=0);
393 cdouble* SubVector(cdouble* x, int X1, int X, MList* List=0);
394
395 //--matrix transpose operation-----------------------------------------------
396 void transpose(int N, double** a);
397 void transpose(int N, cdouble** a);
398 double** transpose(int N, int M, double** ta, double** a, MList* List=0); //z[NM]=a[MN]'
399 double** transpose(int N, int M, double** a, MList* List=0);
400
401 //--rotation matrix converting between vectors-------------------------------
402 double** Unitary(int N, double** P, double* x, double* y, MList* List=0);
403 double** Unitary(int N, double* x, double* y, MList* List=0);
404 cdouble** Unitary(int N, cdouble** P, cdouble* x, cdouble* y, MList* List=0);
405 cdouble** Unitary(int N, cdouble* x, cdouble* y, MList* List=0);
406
407 #endif