Mercurial > hg > x
comparison matrix.cpp @ 2:fc19d45615d1
* Make all file names lower-case to avoid case ambiguity
(some includes differed in case from the filenames they were
trying to include). Also replace MinGW-specific mem.h with
string.h
author | Chris Cannam |
---|---|
date | Tue, 05 Oct 2010 11:04:40 +0100 |
parents | Matrix.cpp@6422640a802f |
children | 5f3c32dc6e17 |
comparison
equal
deleted
inserted
replaced
1:6422640a802f | 2:fc19d45615d1 |
---|---|
1 //--------------------------------------------------------------------------- | |
2 #include <math.h> | |
3 #include <memory.h> | |
4 #include "matrix.h" | |
5 //--------------------------------------------------------------------------- | |
6 /* | |
7 function BalanceSim: applies a similarity transformation to matrix a so that a is "balanced". This is | |
8 used by various eigenvalue evaluation routines. | |
9 | |
10 In: matrix A[n][n] | |
11 Out: balanced matrix a | |
12 | |
13 No return value. | |
14 */ | |
15 void BalanceSim(int n, double** A) | |
16 { | |
17 if (n<2) return; | |
18 const int radix=2; | |
19 double sqrdx; | |
20 sqrdx=radix*radix; | |
21 bool finish=false; | |
22 while (!finish) | |
23 { | |
24 finish=true; | |
25 for (int i=0; i<n; i++) | |
26 { | |
27 double s, sr=0, sc=0, ar, ac; | |
28 for (int j=0; j<n; j++) | |
29 if (j!=i) | |
30 { | |
31 sc+=fabs(A[j][i]); | |
32 sr+=fabs(A[i][j]); | |
33 } | |
34 if (sc!=0 && sr!=0) | |
35 { | |
36 ar=sr/radix; | |
37 ac=1.0; | |
38 s=sr+sc; | |
39 while (sc<ar) | |
40 { | |
41 ac*=radix; | |
42 sc*=sqrdx; | |
43 } | |
44 ar=sr*radix; | |
45 while (sc>ar) | |
46 { | |
47 ac/=radix; | |
48 sc/=sqrdx; | |
49 } | |
50 } | |
51 if ((sc+sr)/ac<0.95*s) | |
52 { | |
53 finish=false; | |
54 ar=1.0/ac; | |
55 for (int j=0; j<n; j++) A[i][j]*=ar; | |
56 for (int j=0; j<n; j++) A[j][i]*=ac; | |
57 } | |
58 } | |
59 } | |
60 }//BalanceSim | |
61 | |
62 //--------------------------------------------------------------------------- | |
63 /* | |
64 function Choleski: Choleski factorization A=LL', where L is lower triangular. The symmetric matrix | |
65 A[N][N] is positive definite iff A can be factored as LL', where L is lower triangular with nonzero | |
66 diagonl entries. | |
67 | |
68 In: matrix A[N][N] | |
69 Out: mstrix L[N][N]. | |
70 | |
71 Returns 0 if successful. On return content of matrix a is not changed. | |
72 */ | |
73 int Choleski(int N, double** L, double** A) | |
74 { | |
75 if (A[0][0]==0) return 1; | |
76 L[0][0]=sqrt(A[0][0]); | |
77 memset(&L[0][1], 0, sizeof(double)*(N-1)); | |
78 for (int j=1; j<N; j++) L[j][0]=A[j][0]/L[0][0]; | |
79 for (int i=1; i<N-1; i++) | |
80 { | |
81 L[i][i]=A[i][i]; for (int k=0; k<i; k++) L[i][i]-=L[i][k]*L[i][k]; L[i][i]=sqrt(L[i][i]); | |
82 if (L[i][i]==0) return 1; | |
83 for (int j=i+1; j<N; j++) | |
84 { | |
85 L[j][i]=A[j][i]; for (int k=0; k<i; k++) L[j][i]-=L[j][k]*L[i][k]; L[j][i]/=L[i][i]; | |
86 } | |
87 memset(&L[i][i+1], 0, sizeof(double)*(N-1-i)); | |
88 } | |
89 L[N-1][N-1]=A[N-1][N-1]; for (int k=0; k<N-1; k++) L[N-1][N-1]-=L[N-1][k]*L[N-1][k]; L[N-1][N-1]=sqrt(L[N-1][N-1]); | |
90 return 0; | |
91 }//Choleski | |
92 | |
93 //--------------------------------------------------------------------------- | |
94 //matrix duplication routines | |
95 | |
96 /* | |
97 function Copy: duplicate the matrix A as matrix Z. | |
98 | |
99 In: matrix A[M][N] | |
100 Out: matrix Z[M][N] | |
101 | |
102 Returns pointer to Z. Z is created anew if Z=0 is supplied on start. | |
103 */ | |
104 double** Copy(int M, int N, double** Z, double** A, MList* List) | |
105 { | |
106 if (!Z) {Allocate2(double, M, N, Z); if (List) List->Add(Z, 2);} | |
107 int sizeN=sizeof(double)*N; | |
108 for (int m=0; m<M; m++) memcpy(Z[m], A[m], sizeN); | |
109 return Z; | |
110 }//Copy | |
111 //complex version | |
112 cdouble** Copy(int M, int N, cdouble** Z, cdouble** A, MList* List) | |
113 { | |
114 if (!Z) {Allocate2(cdouble, M, N, Z); if (List) List->Add(Z, 2);} | |
115 int sizeN=sizeof(cdouble)*N; | |
116 for (int m=0; m<M; m++) memcpy(Z[m], A[m], sizeN); | |
117 return Z; | |
118 }//Copy | |
119 //version without specifying pre-allocated z | |
120 double** Copy(int M, int N, double** A, MList* List){return Copy(M, N, 0, A, List);} | |
121 cdouble** Copy(int M, int N, cdouble** A, MList* List){return Copy(M, N, 0, A, List);} | |
122 //for square matrices | |
123 double** Copy(int N, double** Z, double ** A, MList* List){return Copy(N, N, Z, A, List);} | |
124 double** Copy(int N, double** A, MList* List){return Copy(N, N, 0, A, List);} | |
125 cdouble** Copy(int N, cdouble** Z, cdouble** A, MList* List){return Copy(N, N, Z, A, List);} | |
126 cdouble** Copy(int N, cdouble** A, MList* List){return Copy(N, N, 0, A, List);} | |
127 | |
128 //--------------------------------------------------------------------------- | |
129 //vector duplication routines | |
130 | |
131 /* | |
132 function Copy: duplicating vector a as vector z | |
133 | |
134 In: vector a[N] | |
135 Out: vector z[N] | |
136 | |
137 Returns pointer to z. z is created anew is z=0 is specified on start. | |
138 */ | |
139 double* Copy(int N, double* z, double* a, MList* List) | |
140 { | |
141 if (!z){z=new double[N]; if (List) List->Add(z, 1);} | |
142 memcpy(z, a, sizeof(double)*N); | |
143 return z; | |
144 }//Copy | |
145 cdouble* Copy(int N, cdouble* z, cdouble* a, MList* List) | |
146 { | |
147 if (!z){z=new cdouble[N]; if (List) List->Add(z, 1);} | |
148 memcpy(z, a, sizeof(cdouble)*N); | |
149 return z; | |
150 }//Copy | |
151 //version without specifying pre-allocated z | |
152 double* Copy(int N, double* a, MList* List){return Copy(N, 0, a, List);} | |
153 cdouble* Copy(int N, cdouble* a, MList* List){return Copy(N, 0, a, List);} | |
154 | |
155 //--------------------------------------------------------------------------- | |
156 /* | |
157 function det: computes determinant by Gaussian elimination method with column pivoting | |
158 | |
159 In: matrix A[N][N] | |
160 | |
161 Returns det(A). On return content of matrix A is unchanged if mode=0. | |
162 */ | |
163 double det(int N, double** A, int mode) | |
164 { | |
165 int c, p, ip, *rp=new int[N]; for (int i=0; i<N; i++) rp[i]=i; | |
166 double m, **b, result=1; | |
167 | |
168 if (mode==0) | |
169 { | |
170 int sizeN=sizeof(double)*N; | |
171 b=new double*[N]; b[0]=new double[N*N]; for (int i=0; i<N; i++) {b[i]=&b[0][i*N]; memcpy(b[i], A[i], sizeN);} | |
172 A=b; | |
173 } | |
174 | |
175 //Gaussian eliminating | |
176 for (int i=0; i<N-1; i++) | |
177 { | |
178 p=i, ip=i+1; | |
179 while (ip<N){if (fabs(A[rp[ip]][i])>fabs(A[rp[p]][i])) p=ip; ip++;} | |
180 if (A[rp[p]][i]==0) {result=0; goto ret;} | |
181 if (p!=i) {c=rp[i]; rp[i]=rp[p]; rp[p]=c; result=-result;} | |
182 for (int j=i+1; j<N; j++) | |
183 { | |
184 m=A[rp[j]][i]/A[rp[i]][i]; | |
185 A[rp[j]][i]=0; | |
186 for (int k=i+1; k<N; k++) A[rp[j]][k]-=m*A[rp[i]][k]; | |
187 } | |
188 } | |
189 if (A[rp[N-1]][N-1]==0) {result=0; goto ret;} | |
190 | |
191 for (int i=0; i<N; i++) | |
192 result*=A[rp[i]][i]; | |
193 | |
194 ret: | |
195 if (mode==0) {delete[] b[0]; delete[] b;} | |
196 delete[] rp; | |
197 return result; | |
198 }//det | |
199 //complex version | |
200 cdouble det(int N, cdouble** A, int mode) | |
201 { | |
202 int c, p, ip, *rp=new int[N]; for (int i=0; i<N; i++) rp[i]=i; | |
203 double mm, mp; | |
204 cdouble m, **b, result=1; | |
205 | |
206 if (mode==0) | |
207 { | |
208 int sizeN=sizeof(cdouble)*N; | |
209 b=new cdouble*[N]; b[0]=new cdouble[N*N]; | |
210 for (int i=0; i<N; i++) {b[i]=&b[0][i*N]; memcpy(b[i], A[i], sizeN);} | |
211 A=b; | |
212 } | |
213 | |
214 //Gaussian elimination | |
215 for (int i=0; i<N-1; i++) | |
216 { | |
217 p=i, ip=i+1; m=A[rp[p]][i]; mp=~m; | |
218 while (ip<N){m=A[rp[ip]][i]; mm=~m; if (mm>mp) mp=mm, p=ip; ip++;} | |
219 if (mp==0) {result=0; goto ret;} | |
220 if (p!=i) {c=rp[i]; rp[i]=rp[p]; rp[p]=c;} | |
221 for (int j=i+1; j<N; j++) | |
222 { | |
223 m=A[rp[j]][i]/A[rp[i]][i]; | |
224 A[rp[j]][i]=0; | |
225 for (int k=i+1; k<N; k++) A[rp[j]][k]-=m*A[rp[i]][k]; | |
226 } | |
227 } | |
228 if (operator==(A[rp[N-1]][N-1],0)) {result=0; goto ret;} | |
229 | |
230 for (int i=0; i<N; i++) result=result*A[rp[i]][i]; | |
231 ret: | |
232 if (mode==0) {delete[] b[0]; delete[] b;} | |
233 delete[] rp; | |
234 return result; | |
235 }//det | |
236 | |
237 //--------------------------------------------------------------------------- | |
238 /* | |
239 function EigPower: power method for solving dominant eigenvalue and eigenvector | |
240 | |
241 In: matrix A[N][N], initial arbitrary vector x[N]. | |
242 Out: eigenvalue l, eigenvector x[N]. | |
243 | |
244 Returns 0 is successful. Content of matrix A is unchangd on return. Initial x[N] must not be zero. | |
245 */ | |
246 int EigPower(int N, double& l, double* x, double** A, double ep, int maxiter) | |
247 { | |
248 int k=0; | |
249 int p=0; for (int i=1; i<N; i++) if (fabs(x[p])<fabs(x[i])) p=i; | |
250 Multiply(N, x, x, 1/x[p]); | |
251 double e, ty,te, *y=new double[N]; | |
252 | |
253 while (k<maxiter) | |
254 { | |
255 MultiplyXy(N, N, y, A, x); | |
256 l=y[p]; | |
257 int p=0; for (int i=1; i<N; i++) if (fabs(y[p])<fabs(y[i])) p=i; | |
258 if (y[p]==0) {l=0; delete[] y; return 0;} | |
259 ty=y[0]/y[p]; e=fabs(x[0]-ty); x[0]=ty; | |
260 for (int i=1; i<N; i++) | |
261 { | |
262 ty=y[i]/y[p]; te=fabs(x[i]-ty); if (e<te) e=te; x[i]=ty; | |
263 } | |
264 if (e<ep) {delete[] y; return 0;} | |
265 k++; | |
266 } | |
267 delete[] y; return 1; | |
268 }//EigPower | |
269 | |
270 //--------------------------------------------------------------------------- | |
271 /* | |
272 function EigPowerA: EigPower with Aitken acceleration | |
273 | |
274 In: matrix A[N][N], initial arbitrary vector x[N]. | |
275 Out: eigenvalue l, eigenvector x[N]. | |
276 | |
277 Returns 0 is successful. Content of matrix A is unchangd on return. Initial x[N] must not be zero. | |
278 */ | |
279 int EigPowerA(int N, double& l, double* x, double** A, double ep, int maxiter) | |
280 { | |
281 int k=0; | |
282 int p=0; for (int i=1; i<N; i++) if (fabs(x[p])<fabs(x[i])) p=i; | |
283 Multiply(N, x, x, 1/x[p]); | |
284 double m, m0=0, m1=0, e, ty,te, *y=new double[N]; | |
285 | |
286 while (k<maxiter) | |
287 { | |
288 MultiplyXy(N, N, y, A, x); | |
289 m=y[p]; | |
290 int p=0; for (int i=1; i<N; i++) if (fabs(y[p])<fabs(y[i])) p=i; | |
291 if (y[p]==0) {l=0; delete[] y; return 0;} | |
292 ty=y[0]/y[p]; e=fabs(x[0]-ty); x[0]=ty; | |
293 for (int i=1; i<N; i++) | |
294 { | |
295 ty=y[i]/y[p]; te=fabs(x[i]-ty); if (e<te) e=te; x[i]=ty; | |
296 } | |
297 if (e<ep && k>2) {l=m0-(m1-m0)*(m1-m0)/(m-2*m1+m0); delete[] y; return 0;} | |
298 k++; m0=m1; m1=m; | |
299 } | |
300 delete[] y; return 1; | |
301 }//EigPowerA | |
302 | |
303 //--------------------------------------------------------------------------- | |
304 /* | |
305 function EigPowerI: Inverse power method for solving the eigenvalue given an approximate non-zero | |
306 eigenvector. | |
307 | |
308 In: matrix A[N][N], approximate eigenvector x[N]. | |
309 Out: eigenvalue l, eigenvector x[N]. | |
310 | |
311 Returns 0 is successful. Content of matrix A is unchangd on return. Initial x[N] must not be zero. | |
312 */ | |
313 int EigPowerI(int N, double& l, double* x, double** A, double ep, int maxiter) | |
314 { | |
315 int sizeN=sizeof(double)*N; | |
316 double* y=new double[N]; MultiplyXy(N, N, y, A, x); | |
317 double q=Inner(N, x, y)/Inner(N, x, x), dt; | |
318 double** aa=new double*[N]; aa[0]=new double[N*N]; | |
319 for (int i=0; i<N; i++) {aa[i]=&aa[0][i*N]; memcpy(aa[i], A[i], sizeN); aa[i][i]-=q;} | |
320 dt=GISCP(N, aa); | |
321 if (dt==0) {l=q; delete[] aa[0]; delete[] aa; delete[] y; return 0;} | |
322 | |
323 int k=0; | |
324 int p=0; for (int i=1; i<N; i++) if (fabs(x[p])<fabs(x[i])) p=i; | |
325 Multiply(N, x, x, 1/x[p]); | |
326 | |
327 double m, e, ty, te; | |
328 while (k<N) | |
329 { | |
330 MultiplyXy(N, N, y, aa, x); | |
331 m=y[p]; | |
332 p=0; for (int i=1; i<N; i++) if (fabs(y[p])<fabs(y[i])) p=i; | |
333 ty=y[0]/y[p]; te=x[0]-ty; e=fabs(te); x[0]=ty; | |
334 for (int i=1; i<N; i++) | |
335 { | |
336 ty=y[i]/y[p]; te=fabs(x[i]-ty); if (e<te) e=te; x[i]=ty; | |
337 } | |
338 if (e<ep) {l=1/m+q; delete[] aa[0]; delete[] aa; delete[] y; return 0;} | |
339 } | |
340 delete[] aa[0]; delete[] aa; | |
341 delete[] y; return 1; | |
342 }//EigPowerI | |
343 | |
344 //--------------------------------------------------------------------------- | |
345 /* | |
346 function EigPowerS: symmetric power method for solving the dominant eigenvalue with its eigenvector | |
347 | |
348 In: matrix A[N][N], initial arbitrary vector x[N]. | |
349 Out: eigenvalue l, eigenvector x[N]. | |
350 | |
351 Returns 0 is successful. Content of matrix A is unchangd on return. Initial x[N] must not be zero. | |
352 */ | |
353 int EigPowerS(int N, double& l, double* x, double** A, double ep, int maxiter) | |
354 { | |
355 int k=0; | |
356 Multiply(N, x, x, 1/sqrt(Inner(N, x, x))); | |
357 double y2, e, ty, te, *y=new double[N]; | |
358 while (k<maxiter) | |
359 { | |
360 MultiplyXy(N, N, y, A, x); | |
361 l=Inner(N, x, y); | |
362 y2=sqrt(Inner(N, y, y)); | |
363 if (y2==0) {l=0; delete[] y; return 0;} | |
364 ty=y[0]/y2; te=x[0]-ty; e=te*te; x[0]=ty; | |
365 for (int i=1; i<N; i++) | |
366 { | |
367 ty=y[i]/y2; te=x[i]-ty; e+=te*te; x[i]=ty; | |
368 } | |
369 e=sqrt(e); | |
370 if (e<ep) {delete[] y; return 0;} | |
371 k++; | |
372 } | |
373 delete[] y; | |
374 return 1; | |
375 }//EigPowerS | |
376 | |
377 //--------------------------------------------------------------------------- | |
378 /* | |
379 function EigPowerWielandt: Wielandt's deflation algorithm for solving a second dominant eigenvalue and | |
380 eigenvector (m,u) given the dominant eigenvalue and eigenvector (l,v). | |
381 | |
382 In: matrix A[N][N], first eigenvalue l with eigenvector v[N] | |
383 Out: second eigenvalue m with eigenvector u | |
384 | |
385 Returns 0 if successful. Content of matrix A is unchangd on return. Initial u[N] must not be zero. | |
386 */ | |
387 int EigPowerWielandt(int N, double& m, double* u, double l, double* v, double** A, double ep, int maxiter) | |
388 { | |
389 int result; | |
390 double** b=new double*[N-1]; b[0]=new double[(N-1)*(N-1)]; for (int i=1; i<N-1; i++) b[i]=&b[0][i*(N-1)]; | |
391 double* w=new double[N]; | |
392 int i=0; for (int j=1; j<N; j++) if (fabs(v[i])<fabs(v[j])) i=j; | |
393 if (i!=0) | |
394 for (int k=0; k<i; k++) | |
395 for (int j=0; j<i; j++) | |
396 b[k][j]=A[k][j]-v[k]*A[i][j]/v[i]; | |
397 if (i!=0 && i!=N-1) | |
398 for (int k=i; k<N-1; k++) | |
399 for (int j=0; j<i; j++) | |
400 b[k][j]=A[k+1][j]-v[k+1]*A[i][j]/v[i], b[j][k]=A[j][k+1]-v[j]*A[i][k+1]/v[i]; | |
401 if (i!=N-1) | |
402 for (int k=i; k<N-1; k++) | |
403 for (int j=i; j<N-1; j++) b[k][j]=A[k+1][j+1]-v[k+1]*A[i][j+1]/v[i]; | |
404 memcpy(w, u, sizeof(double)*(N-1)); | |
405 if ((result=EigPower(N-1, m, w, b, ep, maxiter))==0) | |
406 { //* | |
407 if (i!=N-1) memmove(&w[i+1], &w[i], sizeof(double)*(N-i-1)); | |
408 w[i]=0; | |
409 for (int k=0; k<N; k++) u[k]=(m-l)*w[k]+Inner(N, A[i], w)*v[k]/v[i]; //*/ | |
410 } | |
411 delete[] w; delete[] b[0]; delete[] b; | |
412 return result; | |
413 }//EigPowerWielandt | |
414 | |
415 //--------------------------------------------------------------------------- | |
416 //NR versions of eigensystem | |
417 | |
418 /* | |
419 function EigenValues: solves for eigenvalues of general system | |
420 | |
421 In: matrix A[N][N] | |
422 Out: eigenvalues ev[N] | |
423 | |
424 Returns 0 if successful. Content of matrix A is destroyed on return. | |
425 */ | |
426 int EigenValues(int N, double** A, cdouble* ev) | |
427 { | |
428 BalanceSim(N, A); | |
429 Hessenb(N, A); | |
430 return QR(N, A, ev); | |
431 }//EigenValues | |
432 | |
433 /* | |
434 function EigSym: Solves real symmetric eigensystem A | |
435 | |
436 In: matrix A[N][N] | |
437 Out: eigenvalues d[N], transform matrix Q[N][N], so that diag(d)=Q'AQ, A=Q diag(d) Q', AQ=Q diag(d) | |
438 | |
439 Returns 0 if successful. Content of matrix A is unchanged on return. | |
440 */ | |
441 int EigSym(int N, double** A, double* d, double** Q) | |
442 { | |
443 Copy(N, Q, A); | |
444 double* t=new double[N]; | |
445 HouseHolder(5, Q, d, t); | |
446 double result=QL(5, d, t, Q); | |
447 delete[] t; | |
448 return result; | |
449 }//EigSym | |
450 | |
451 //--------------------------------------------------------------------------- | |
452 /* | |
453 function GEB: Gaussian elimination with backward substitution for solving linear system Ax=b. | |
454 | |
455 In: coefficient matrix A[N][N], vector b[N] | |
456 Out: vector x[N] | |
457 | |
458 Returns 0 if successful. Contents of matrix A and vector b are destroyed on return. | |
459 */ | |
460 int GEB(int N, double* x, double** A, double* b) | |
461 { | |
462 //Gaussian eliminating | |
463 int c, p, *rp=new int[N]; for (int i=0; i<N; i++) rp[i]=i; | |
464 double m; | |
465 for (int i=0; i<N-1; i++) | |
466 { | |
467 p=i; | |
468 while (p<N && A[rp[p]][i]==0) p++; | |
469 if (p>=N) {delete[] rp; return 1;} | |
470 if (p!=i){c=rp[i]; rp[i]=rp[p]; rp[p]=c;} | |
471 for (int j=i+1; j<N; j++) | |
472 { | |
473 m=A[rp[j]][i]/A[rp[i]][i]; | |
474 A[rp[j]][i]=0; | |
475 for (int k=i+1; k<N; k++) A[rp[j]][k]-=m*A[rp[i]][k]; | |
476 b[rp[j]]-=m*b[rp[i]]; | |
477 } | |
478 } | |
479 if (A[rp[N-1]][N-1]==0) {delete[] rp; return 1;} | |
480 else | |
481 { | |
482 //backward substitution | |
483 x[N-1]=b[rp[N-1]]/A[rp[N-1]][N-1]; | |
484 for (int i=N-2; i>=0; i--) | |
485 { | |
486 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]; | |
487 } | |
488 } | |
489 delete[] rp; | |
490 return 0; | |
491 }//GEB | |
492 | |
493 //--------------------------------------------------------------------------- | |
494 /* | |
495 function GESCP: Gaussian elimination with scaled column pivoting for solving linear system Ax=b | |
496 | |
497 In: matrix A[N][N], vector b[N] | |
498 Out: vector x[N] | |
499 | |
500 Returns 0 is successful. Contents of matrix A and vector b are destroyed on return. | |
501 */ | |
502 int GESCP(int N, double* x, double** A, double *b) | |
503 { | |
504 int c, p, ip, *rp=new int[N]; | |
505 double m, *s=new double[N]; | |
506 for (int i=0; i<N; i++) | |
507 { | |
508 s[i]=fabs(A[i][0]); | |
509 for (int j=1; j<N; j++) if (s[i]<fabs(A[i][j])) s[i]=fabs(A[i][j]); | |
510 if (s[i]==0) {delete[] s; delete[] rp; return 1;} | |
511 rp[i]=i; | |
512 } | |
513 //Gaussian eliminating | |
514 for (int i=0; i<N-1; i++) | |
515 { | |
516 p=i, ip=i+1; | |
517 while (ip<N){if (fabs(A[rp[ip]][i])/s[rp[ip]]>fabs(A[rp[p]][i])/s[rp[p]]) p=ip; ip++;} | |
518 if (A[rp[p]][i]==0) {delete[] s; delete[] rp; return 1;} | |
519 if (p!=i) {c=rp[i]; rp[i]=rp[p]; rp[p]=c;} | |
520 for (int j=i+1; j<N; j++) | |
521 { | |
522 m=A[rp[j]][i]/A[rp[i]][i]; | |
523 A[rp[j]][i]=0; | |
524 for (int k=i+1; k<N; k++) A[rp[j]][k]-=m*A[rp[i]][k]; | |
525 b[rp[j]]-=m*b[rp[i]]; | |
526 } | |
527 } | |
528 if (A[rp[N-1]][N-1]==0) {delete[] s; delete[] rp; return 1;} | |
529 //backward substitution | |
530 x[N-1]=b[rp[N-1]]/A[rp[N-1]][N-1]; | |
531 for (int i=N-2; i>=0; i--) | |
532 { | |
533 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]; | |
534 } | |
535 delete[] s; delete[] rp; | |
536 return 0; | |
537 }//GESCP | |
538 | |
539 //--------------------------------------------------------------------------- | |
540 /* | |
541 function GExL: solves linear system xL=a, L being lower-triangular. This is used in LU factorization | |
542 for solving linear systems. | |
543 | |
544 In: lower-triangular matrix L[N][N], vector a[N] | |
545 Out: vector x[N] | |
546 | |
547 No return value. Contents of matrix L and vector a are unchanged at return. | |
548 */ | |
549 void GExL(int N, double* x, double** L, double* a) | |
550 { | |
551 for (int n=N-1; n>=0; n--) | |
552 { | |
553 double xn=a[n]; | |
554 for (int m=n+1; m<N; m++) xn-=x[m]*L[m][n]; | |
555 x[n]=xn/L[n][n]; | |
556 } | |
557 }//GExL | |
558 | |
559 /* | |
560 function GExLAdd: solves linear system *L=a, L being lower-triangular, and add the solution * to x[]. | |
561 | |
562 In: lower-triangular matrix L[N][N], vector a[N] | |
563 Out: updated vector x[N] | |
564 | |
565 No return value. Contents of matrix L and vector a are unchanged at return. | |
566 */ | |
567 void GExLAdd(int N, double* x, double** L, double* a) | |
568 { | |
569 double* lx=new double[N]; | |
570 GExL(N, lx, L, a); | |
571 for (int i=0; i<N; i++) x[i]+=lx[i]; | |
572 delete[] lx; | |
573 }//GExLAdd | |
574 | |
575 /* | |
576 function GExL1: solves linear system xL=(0, 0, ..., 0, a)', L being lower-triangular. | |
577 | |
578 In: lower-triangular matrix L[N][N], a | |
579 Out: vector x[N] | |
580 | |
581 No return value. Contents of matrix L and vector a are unchanged at return. | |
582 */ | |
583 void GExL1(int N, double* x, double** L, double a) | |
584 { | |
585 double xn=a; | |
586 for (int n=N-1; n>=0; n--) | |
587 { | |
588 for (int m=n+1; m<N; m++) xn-=x[m]*L[m][n]; | |
589 x[n]=xn/L[n][n]; | |
590 xn=0; | |
591 } | |
592 }//GExL1 | |
593 | |
594 /* | |
595 function GExL1Add: solves linear system *L=(0, 0, ..., 0, a)', L being lower-triangular, and add the | |
596 solution * to x[]. | |
597 | |
598 In: lower-triangular matrix L[N][N], vector a | |
599 Out: updated vector x[N] | |
600 | |
601 No return value. Contents of matrix L and vector a are unchanged at return. | |
602 */ | |
603 void GExL1Add(int N, double* x, double** L, double a) | |
604 { | |
605 double* lx=new double[N]; | |
606 GExL1(N, lx, L, a); | |
607 for (int i=0; i<N; i++) x[i]+=lx[i]; | |
608 delete[] lx; | |
609 }//GExL1Add | |
610 | |
611 //--------------------------------------------------------------------------- | |
612 /* | |
613 function GICP: matrix inverse using Gaussian elimination with column pivoting: inv(A)->A. | |
614 | |
615 In: matrix A[N][N] | |
616 Out: matrix A[N][N] | |
617 | |
618 Returns the determinant of the inverse matrix, 0 on failure. | |
619 */ | |
620 double GICP(int N, double** A) | |
621 { | |
622 int c, p, ip, *rp=new int[N]; for (int i=0; i<N; i++) rp[i]=i; | |
623 double m, result=1; | |
624 | |
625 //Gaussian eliminating | |
626 for (int i=0; i<N-1; i++) | |
627 { | |
628 p=i, ip=i+1; | |
629 while (ip<N){if (fabs(A[rp[ip]][i])>fabs(A[rp[p]][i])) p=ip; ip++;} | |
630 if (A[rp[p]][i]==0) {delete[] rp; return 0;} | |
631 if (p!=i) {c=rp[i]; rp[i]=rp[p]; rp[p]=c; result=-result;} | |
632 result/=A[rp[i]][i]; | |
633 for (int j=i+1; j<N; j++) | |
634 { | |
635 m=A[rp[j]][i]/A[rp[i]][i]; | |
636 A[rp[j]][i]=-m; | |
637 for (int k=i+1; k<N; k++) A[rp[j]][k]-=m*A[rp[i]][k]; | |
638 for (int k=0; k<i; k++) A[rp[j]][k]-=m*A[rp[i]][k]; | |
639 } | |
640 } | |
641 if (A[rp[N-1]][N-1]==0) {delete[] rp; return 0;} | |
642 result/=A[rp[N-1]][N-1]; | |
643 //backward substitution | |
644 for (int i=0; i<N-1; i++) | |
645 { | |
646 m=A[rp[i]][i]; for (int k=0; k<N; k++) A[rp[i]][k]/=m; A[rp[i]][i]=1/m; | |
647 for (int j=i+1; j<N; j++) | |
648 { | |
649 m=A[rp[i]][j]/A[rp[j]][j]; for (int k=0; k<N; k++) A[rp[i]][k]-=A[rp[j]][k]*m; A[rp[i]][j]=-m; | |
650 } | |
651 } | |
652 m=A[rp[N-1]][N-1]; for (int k=0; k<N-1; k++) A[rp[N-1]][k]/=m; A[rp[N-1]][N-1]=1/m; | |
653 //recover column and row exchange | |
654 double* tm=new double[N]; int sizeN=sizeof(double)*N; | |
655 for (int i=0; i<N; i++) { for (int j=0; j<N; j++) tm[rp[j]]=A[i][j]; memcpy(A[i], tm, sizeN); } | |
656 for (int j=0; j<N; j++) { for (int i=0; i<N; i++) tm[i]=A[rp[i]][j]; for (int i=0; i<N; i++) A[i][j]=tm[i];} | |
657 | |
658 delete[] tm; delete[] rp; | |
659 return result; | |
660 }//GICP | |
661 //complex version | |
662 cdouble GICP(int N, cdouble** A) | |
663 { | |
664 int c, p, ip, *rp=new int[N]; for (int i=0; i<N; i++) rp[i]=i; | |
665 cdouble m, result=1; | |
666 | |
667 //Gaussian eliminating | |
668 for (int i=0; i<N-1; i++) | |
669 { | |
670 p=i, ip=i+1; | |
671 while (ip<N){if (~A[rp[ip]][i]>~A[rp[p]][i]) p=ip; ip++;} | |
672 if (A[rp[p]][i]==0) {delete[] rp; return 0;} | |
673 if (p!=i) {c=rp[i]; rp[i]=rp[p]; rp[p]=c; result=-result;} | |
674 result=result/(A[rp[i]][i]); | |
675 for (int j=i+1; j<N; j++) | |
676 { | |
677 m=A[rp[j]][i]/A[rp[i]][i]; | |
678 A[rp[j]][i]=-m; | |
679 for (int k=i+1; k<N; k++) A[rp[j]][k]-=m*A[rp[i]][k]; | |
680 for (int k=0; k<i; k++) A[rp[j]][k]-=m*A[rp[i]][k]; | |
681 } | |
682 } | |
683 if (A[rp[N-1]][N-1]==0) {delete[] rp; return 0;} | |
684 result=result/A[rp[N-1]][N-1]; | |
685 //backward substitution | |
686 for (int i=0; i<N-1; i++) | |
687 { | |
688 m=A[rp[i]][i]; for (int k=0; k<N; k++) A[rp[i]][k]=A[rp[i]][k]/m; A[rp[i]][i]=cdouble(1)/m; | |
689 for (int j=i+1; j<N; j++) | |
690 { | |
691 m=A[rp[i]][j]/A[rp[j]][j]; for (int k=0; k<N; k++) A[rp[i]][k]-=A[rp[j]][k]*m; A[rp[i]][j]=-m; | |
692 } | |
693 } | |
694 m=A[rp[N-1]][N-1]; for (int k=0; k<N-1; k++) A[rp[N-1]][k]=A[rp[N-1]][k]/m; A[rp[N-1]][N-1]=cdouble(1)/m; | |
695 //recover column and row exchange | |
696 cdouble* tm=new cdouble[N]; int sizeN=sizeof(cdouble)*N; | |
697 for (int i=0; i<N; i++) { for (int j=0; j<N; j++) tm[rp[j]]=A[i][j]; memcpy(A[i], tm, sizeN); } | |
698 for (int j=0; j<N; j++) { for (int i=0; i<N; i++) tm[i]=A[rp[i]][j]; for (int i=0; i<N; i++) A[i][j]=tm[i];} | |
699 | |
700 delete[] tm; delete[] rp; | |
701 return result; | |
702 }//GICP | |
703 | |
704 /* | |
705 function GICP: wrapper function that does not overwrite the input matrix: inv(A)->X. | |
706 | |
707 In: matrix A[N][N] | |
708 Out: matrix X[N][N] | |
709 | |
710 Returns the determinant of the inverse matrix, 0 on failure. | |
711 */ | |
712 double GICP(int N, double** X, double** A) | |
713 { | |
714 Copy(N, X, A); | |
715 return GICP(N, X); | |
716 }//GICP | |
717 | |
718 //--------------------------------------------------------------------------- | |
719 /* | |
720 function GILT: inv(lower trangular of A)->lower trangular of A | |
721 | |
722 In: matrix A[N][N] | |
723 Out: matrix A[N][N] | |
724 | |
725 Returns the determinant of the lower trangular of A | |
726 */ | |
727 double GILT(int N, double** A) | |
728 { | |
729 double result=1; | |
730 A[0][0]=1/A[0][0]; | |
731 for (int i=1; i<N; i++) | |
732 { | |
733 result*=A[i][i]; | |
734 double tmp=1/A[i][i]; | |
735 for (int k=0; k<i; k++) A[i][k]*=tmp; A[i][i]=tmp; | |
736 for (int j=0; j<i; j++) | |
737 { | |
738 double tmp2=A[i][j]; | |
739 for (int k=0; k<j; k++) A[i][k]-=A[j][k]*tmp2; A[i][j]=-A[j][j]*tmp2; | |
740 } | |
741 } | |
742 return result; | |
743 }//GILT | |
744 | |
745 /* | |
746 function GIUT: inv(upper trangular of A)->upper trangular of A | |
747 | |
748 In: matrix A[N][N] | |
749 Out: matrix A[N][N] | |
750 | |
751 Returns the determinant of the upper trangular of A | |
752 */ | |
753 double GIUT(int N, double** A) | |
754 { | |
755 double result=1; | |
756 A[0][0]=1/A[0][0]; | |
757 for (int i=1; i<N; i++) | |
758 { | |
759 result*=A[i][i]; | |
760 double tmp=1/A[i][i]; | |
761 for (int k=0; k<i; k++) A[k][i]*=tmp; A[i][i]=tmp; | |
762 for (int j=0; j<i; j++) | |
763 { | |
764 double tmp2=A[j][i]; | |
765 for (int k=0; k<j; k++) A[k][i]-=A[k][j]*tmp2; A[j][i]=-A[j][j]*tmp2; | |
766 } | |
767 } | |
768 return result; | |
769 }//GIUT | |
770 | |
771 //--------------------------------------------------------------------------- | |
772 /* | |
773 function GISCP: matrix inverse using Gaussian elimination w. scaled column pivoting: inv(A)->A. | |
774 | |
775 In: matrix A[N][N] | |
776 Out: matrix A[N][N] | |
777 | |
778 Returns the determinant of the inverse matrix, 0 on failure. | |
779 */ | |
780 double GISCP(int N, double** A) | |
781 { | |
782 int c, p, ip, *rp=new int[N]; for (int i=0; i<N; i++) rp[i]=i; | |
783 double m, result=1, *s=new double[N]; | |
784 | |
785 for (int i=0; i<N; i++) | |
786 { | |
787 s[i]=A[i][0]; | |
788 for (int j=1; j<N; j++) if (fabs(s[i])<fabs(A[i][j])) s[i]=A[i][j]; | |
789 if (s[i]==0) {delete[] s; delete[] rp; return 0;} | |
790 rp[i]=i; | |
791 } | |
792 | |
793 //Gaussian eliminating | |
794 for (int i=0; i<N-1; i++) | |
795 { | |
796 p=i, ip=i+1; | |
797 while (ip<N){if (fabs(A[rp[ip]][i]/s[rp[ip]])>fabs(A[rp[p]][i]/s[rp[p]])) p=ip; ip++;} | |
798 if (A[rp[p]][i]==0) {delete[] s; delete[] rp; return 0;} | |
799 if (p!=i) {c=rp[i]; rp[i]=rp[p]; rp[p]=c; result=-result;} | |
800 result/=A[rp[i]][i]; | |
801 for (int j=i+1; j<N; j++) | |
802 { | |
803 m=A[rp[j]][i]/A[rp[i]][i]; | |
804 A[rp[j]][i]=-m; | |
805 for (int k=i+1; k<N; k++) A[rp[j]][k]-=m*A[rp[i]][k]; | |
806 for (int k=0; k<i; k++) A[rp[j]][k]-=m*A[rp[i]][k]; | |
807 } | |
808 } | |
809 if (A[rp[N-1]][N-1]==0) {delete[] s; delete[] rp; return 0;} | |
810 result/=A[rp[N-1]][N-1]; | |
811 //backward substitution | |
812 for (int i=0; i<N-1; i++) | |
813 { | |
814 m=A[rp[i]][i]; for (int k=0; k<N; k++) A[rp[i]][k]/=m; A[rp[i]][i]=1/m; | |
815 for (int j=i+1; j<N; j++) | |
816 { | |
817 m=A[rp[i]][j]/A[rp[j]][j]; for (int k=0; k<N; k++) A[rp[i]][k]-=A[rp[j]][k]*m; A[rp[i]][j]=-m; | |
818 } | |
819 } | |
820 m=A[rp[N-1]][N-1]; for (int k=0; k<N-1; k++) A[rp[N-1]][k]/=m; A[rp[N-1]][N-1]=1/m; | |
821 //recover column and row exchange | |
822 double* tm=new double[N]; int sizeN=sizeof(double)*N; | |
823 for (int i=0; i<N; i++) { for (int j=0; j<N; j++) tm[rp[j]]=A[i][j]; memcpy(A[i], tm, sizeN); } | |
824 for (int j=0; j<N; j++) { for (int i=0; i<N; i++) tm[i]=A[rp[i]][j]; for (int i=0; i<N; i++) A[i][j]=tm[i];} | |
825 | |
826 delete[] tm; delete[] s; delete[] rp; | |
827 return result; | |
828 }//GISCP | |
829 | |
830 /* | |
831 function GISCP: wrapper function that does not overwrite input matrix A: inv(A)->X. | |
832 | |
833 In: matrix A[N][N] | |
834 Out: matrix X[N][N] | |
835 | |
836 Returns the determinant of the inverse matrix, 0 on failure. | |
837 */ | |
838 double GISCP(int N, double** X, double** A) | |
839 { | |
840 Copy(N, X, A); | |
841 return GISCP(N, X); | |
842 }//GISCP | |
843 | |
844 //--------------------------------------------------------------------------- | |
845 /* | |
846 function GSI: Gaussian-Seidel iterative algorithm for solving linear system Ax=b. Breaks down if any | |
847 Aii=0, like the Jocobi method JI(...). | |
848 | |
849 Gaussian-Seidel iteration is x(k)=(D-L)^(-1)(Ux(k-1)+b), where D is diagonal, L is lower triangular, | |
850 U is upper triangular and A=L+D+U. | |
851 | |
852 In: matrix A[N][N], vector b[N], initial vector x0[N] | |
853 Out: vector x0[N] | |
854 | |
855 Returns 0 is successful. Contents of matrix A and vector b remain unchanged on return. | |
856 */ | |
857 int GSI(int N, double* x0, double** A, double* b, double ep, int maxiter) | |
858 { | |
859 double e, *x=new double[N]; | |
860 int k=0, sizeN=sizeof(double)*N; | |
861 while (k<maxiter) | |
862 { | |
863 for (int i=0; i<N; i++) | |
864 { | |
865 x[i]=b[i]; | |
866 for (int j=0; j<i; j++) x[i]-=A[i][j]*x[j]; | |
867 for (int j=i+1; j<N; j++) x[i]-=A[i][j]*x0[j]; | |
868 x[i]/=A[i][i]; | |
869 } | |
870 e=0; for (int j=0; j<N; j++) e+=fabs(x[j]-x0[j]); | |
871 memcpy(x0, x, sizeN); | |
872 if (e<ep) break; | |
873 k++; | |
874 } | |
875 delete[] x; | |
876 if (k>=maxiter) return 1; | |
877 return 0; | |
878 }//GSI | |
879 | |
880 //--------------------------------------------------------------------------- | |
881 /* | |
882 function Hessenb: reducing a square matrix A to upper Hessenberg form | |
883 | |
884 In: matrix A[N][N] | |
885 Out: matrix A[N][N], in upper Hessenberg form | |
886 | |
887 No return value. | |
888 */ | |
889 void Hessenb(int N, double** A) | |
890 { | |
891 double x, y; | |
892 for (int m=1; m<N-1; m++) | |
893 { | |
894 x=0; | |
895 int i=m; | |
896 for (int j=m; j<N; j++) | |
897 { | |
898 if (fabs(A[j][m-1]) > fabs(x)) | |
899 { | |
900 x=A[j][m-1]; | |
901 i=j; | |
902 } | |
903 } | |
904 if (i!=m) | |
905 { | |
906 for (int j=m-1; j<N; j++) | |
907 { | |
908 double tmp=A[i][j]; | |
909 A[i][j]=A[m][j]; | |
910 A[m][j]=tmp; | |
911 } | |
912 for (int j=0; j<N; j++) | |
913 { | |
914 double tmp=A[j][i]; | |
915 A[j][i]=A[j][m]; | |
916 A[j][m]=tmp; | |
917 } | |
918 } | |
919 if (x!=0) | |
920 { | |
921 for (i=m+1; i<N; i++) | |
922 { | |
923 if ((y=A[i][m-1])!=0) | |
924 { | |
925 y/=x; | |
926 A[i][m-1]=0; | |
927 for (int j=m; j<N; j++) A[i][j]-=y*A[m][j]; | |
928 for (int j=0; j<N; j++) A[j][m]+=y*A[j][i]; | |
929 } | |
930 } | |
931 } | |
932 } | |
933 }//Hessenb | |
934 | |
935 //--------------------------------------------------------------------------- | |
936 /* | |
937 function HouseHolder: house holder method converting a symmetric matrix into a tridiagonal symmetric | |
938 matrix, or a non-symmetric matrix into an upper-Hessenberg matrix, using similarity transformation. | |
939 | |
940 In: matrix A[N][N] | |
941 Out: matrix A[N][N] after transformation | |
942 | |
943 No return value. | |
944 */ | |
945 void HouseHolder(int N, double** A) | |
946 { | |
947 double q, alf, prod, r2, *v=new double[N], *u=new double[N], *z=new double[N]; | |
948 for (int k=0; k<N-2; k++) | |
949 { | |
950 q=Inner(N-1-k, &A[k][k+1], &A[k][k+1]); | |
951 | |
952 if (A[k][k+1]==0) alf=sqrt(q); | |
953 else alf=-sqrt(q)*A[k+1][k]/fabs(A[k+1][k]); | |
954 | |
955 r2=alf*(alf-A[k+1][k]); | |
956 | |
957 v[k]=0; v[k+1]=A[k][k+1]-alf; | |
958 memcpy(&v[k+2], &A[k][k+2], sizeof(double)*(N-k-2)); | |
959 | |
960 for (int j=k; j<N; j++) u[j]=Inner(N-1-k, &A[j][k+1], &v[k+1])/r2; | |
961 | |
962 prod=Inner(N-1-k, &v[k+1], &u[k+1]); | |
963 | |
964 MultiAdd(N-k, &z[k], &u[k], &v[k], -prod/2/r2); | |
965 | |
966 for (int l=k+1; l<N-1; l++) | |
967 { | |
968 for (int j=l+1; j<N; j++) A[l][j]=A[j][l]=A[j][l]-v[l]*z[j]-v[j]*z[l]; | |
969 A[l][l]=A[l][l]-2*v[l]*z[l]; | |
970 } | |
971 | |
972 A[N-1][N-1]=A[N-1][N-1]-2*v[N-1]*z[N-1]; | |
973 | |
974 for (int j=k+2; j<N; j++) A[k][j]=A[j][k]=0; | |
975 | |
976 A[k][k+1]=A[k+1][k]=A[k+1][k]-v[k+1]*z[k]; | |
977 } | |
978 delete[] u; delete[] v; delete[] z; | |
979 }//HouseHolder | |
980 | |
981 /* | |
982 function HouseHolder: house holder transformation T=Q'AQ or A=QTQ', where T is tridiagonal and Q is | |
983 unitary i.e. QQ'=I. | |
984 | |
985 In: matrix A[N][N] | |
986 Out: matrix tridiagonal matrix T[N][N] and unitary matrix Q[N][N] | |
987 | |
988 No return value. Identical A and T allowed. Content of matrix A is unchanged if A!=T. | |
989 */ | |
990 void HouseHolder(int N, double** T, double** Q, double** A) | |
991 { | |
992 double g, alf, prod, r2, *v=new double[N], *u=new double[N], *z=new double[N]; | |
993 int sizeN=sizeof(double)*N; | |
994 if (T!=A) for (int i=0; i<N; i++) memcpy(T[i], A[i], sizeN); | |
995 for (int i=0; i<N; i++) {memset(Q[i], 0, sizeN); Q[i][i]=1;} | |
996 for (int k=0; k<N-2; k++) | |
997 { | |
998 g=Inner(N-1-k, &T[k][k+1], &T[k][k+1]); | |
999 | |
1000 if (T[k][k+1]==0) alf=sqrt(g); | |
1001 else alf=-sqrt(g)*T[k+1][k]/fabs(T[k+1][k]); | |
1002 | |
1003 r2=alf*(alf-T[k+1][k]); | |
1004 | |
1005 v[k]=0; v[k+1]=T[k][k+1]-alf; | |
1006 memcpy(&v[k+2], &T[k][k+2], sizeof(double)*(N-k-2)); | |
1007 | |
1008 for (int j=k; j<N; j++) u[j]=Inner(N-1-k, &T[j][k+1], &v[k+1])/r2; | |
1009 | |
1010 prod=Inner(N-1-k, &v[k+1], &u[k+1]); | |
1011 | |
1012 MultiAdd(N-k, &z[k], &u[k], &v[k], -prod/2/r2); | |
1013 | |
1014 for (int l=k+1; l<N-1; l++) | |
1015 { | |
1016 for (int j=l+1; j<N; j++) T[l][j]=T[j][l]=T[j][l]-v[l]*z[j]-v[j]*z[l]; | |
1017 T[l][l]=T[l][l]-2*v[l]*z[l]; | |
1018 } | |
1019 | |
1020 T[N-1][N-1]=T[N-1][N-1]-2*v[N-1]*z[N-1]; | |
1021 | |
1022 for (int j=k+2; j<N; j++) T[k][j]=T[j][k]=0; | |
1023 | |
1024 T[k][k+1]=T[k+1][k]=T[k+1][k]-v[k+1]*z[k]; | |
1025 | |
1026 for (int i=0; i<N; i++) | |
1027 MultiAdd(N-k, &Q[i][k], &Q[i][k], &v[k], -Inner(N-k, &Q[i][k], &v[k])/r2); | |
1028 } | |
1029 delete[] u; delete[] v; delete[] z; | |
1030 }//HouseHolder | |
1031 | |
1032 /* | |
1033 function HouseHolder: nr version of householder method for transforming symmetric matrix A to QTQ', | |
1034 where T is tridiagonal and Q is orthonormal. | |
1035 | |
1036 In: matrix A[N][N] | |
1037 Out: A[N][N]: now containing Q | |
1038 d[N]: containing diagonal elements of T | |
1039 sd[N]: containing subdiagonal elements of T as sd[1:N-1]. | |
1040 | |
1041 No return value. | |
1042 */ | |
1043 void HouseHolder(int N, double **A, double* d, double* sd) | |
1044 { | |
1045 for (int i=N-1; i>=1; i--) | |
1046 { | |
1047 int l=i-1; | |
1048 double h=0, scale=0; | |
1049 if (l>0) | |
1050 { | |
1051 for (int k=0; k<=l; k++) scale+=fabs(A[i][k]); | |
1052 if (scale==0.0) sd[i]=A[i][l]; | |
1053 else | |
1054 { | |
1055 for (int k=0; k<=l; k++) | |
1056 { | |
1057 A[i][k]/=scale; | |
1058 h+=A[i][k]*A[i][k]; | |
1059 } | |
1060 double f=A[i][l]; | |
1061 double g=(f>=0?-sqrt(h): sqrt(h)); | |
1062 sd[i]=scale*g; | |
1063 h-=f*g; | |
1064 A[i][l]=f-g; | |
1065 f=0; | |
1066 for (int j=0; j<=l; j++) | |
1067 { | |
1068 A[j][i]=A[i][j]/h; | |
1069 g=0; | |
1070 for (int k=0; k<=j; k++) g+=A[j][k]*A[i][k]; | |
1071 for (int k=j+1; k<=l; k++) g+=A[k][j]*A[i][k]; | |
1072 sd[j]=g/h; | |
1073 f+=sd[j]*A[i][j]; | |
1074 } | |
1075 double hh=f/(h+h); | |
1076 for (int j=0; j<=l; j++) | |
1077 { | |
1078 f=A[i][j]; | |
1079 sd[j]=g=sd[j]-hh*f; | |
1080 for (int k=0; k<=j; k++) A[j][k]-=(f*sd[k]+g*A[i][k]); | |
1081 } | |
1082 } | |
1083 } | |
1084 else | |
1085 sd[i]=A[i][l]; | |
1086 d[i]=h; | |
1087 } | |
1088 | |
1089 d[0]=sd[0]=0; | |
1090 | |
1091 for (int i=0; i<N; i++) | |
1092 { | |
1093 int l=i-1; | |
1094 if (d[i]) | |
1095 { | |
1096 for (int j=0; j<=l; j++) | |
1097 { | |
1098 double g=0.0; | |
1099 for (int k=0; k<=l; k++) g+=A[i][k]*A[k][j]; | |
1100 for (int k=0; k<=l; k++) A[k][j]-=g*A[k][i]; | |
1101 } | |
1102 } | |
1103 d[i]=A[i][i]; | |
1104 A[i][i]=1.0; | |
1105 for (int j=0; j<=l; j++) A[j][i]=A[i][j]=0.0; | |
1106 } | |
1107 }//HouseHolder | |
1108 | |
1109 //--------------------------------------------------------------------------- | |
1110 /* | |
1111 function Inner: inner product z=y'x | |
1112 | |
1113 In: vectors x[N], y[N] | |
1114 | |
1115 Returns inner product of x and y. | |
1116 */ | |
1117 double Inner(int N, double* x, double* y) | |
1118 { | |
1119 double result=0; | |
1120 for (int i=0; i<N; i++) result+=x[i]*y[i]; | |
1121 return result; | |
1122 }//Inner | |
1123 //complex versions | |
1124 cdouble Inner(int N, double* x, cdouble* y) | |
1125 { | |
1126 cdouble result=0; | |
1127 for (int i=0; i<N; i++) result+=x[i]**y[i]; | |
1128 return result; | |
1129 }//Inner | |
1130 cdouble Inner(int N, cdouble* x, cdouble* y) | |
1131 { | |
1132 cdouble result=0; | |
1133 for (int i=0; i<N; i++) result+=x[i]^y[i]; | |
1134 return result; | |
1135 }//Inner | |
1136 cdouble Inner(int N, cfloat* x, cdouble* y) | |
1137 { | |
1138 cdouble result=0; | |
1139 for (int i=0; i<N; i++) result+=x[i]^y[i]; | |
1140 return result; | |
1141 }//Inner | |
1142 cfloat Inner(int N, cfloat* x, cfloat* y) | |
1143 { | |
1144 cfloat result=0; | |
1145 for (int i=0; i<N; i++) result+=x[i]^y[i]; | |
1146 return result; | |
1147 }//Inner | |
1148 | |
1149 /* | |
1150 function Inner: inner product z=tr(Y'X) | |
1151 | |
1152 In: matrices X[M][N], Y[M][N] | |
1153 | |
1154 Returns inner product of X and Y. | |
1155 */ | |
1156 double Inner(int M, int N, double** X, double** Y) | |
1157 { | |
1158 double result=0; | |
1159 for (int m=0; m<M; m++) for (int n=0; n<N; n++) result+=X[m][n]*Y[m][n]; | |
1160 return result; | |
1161 }//Inner | |
1162 | |
1163 //--------------------------------------------------------------------------- | |
1164 /* | |
1165 function JI: Jacobi interative algorithm for solving linear system Ax=b Breaks down if A[i][i]=0 for | |
1166 any i. Reorder A so that this does not happen. | |
1167 | |
1168 Jacobi iteration is x(k)=D^(-1)((L+U)x(k-1)+b), D is diagonal, L is lower triangular, U is upper | |
1169 triangular and A=L+D+U. | |
1170 | |
1171 In: matrix A[N][N], vector b[N], initial vector x0[N] | |
1172 Out: vector x0[N] | |
1173 | |
1174 Returns 0 if successful. Contents of matrix A and vector b are unchanged on return. | |
1175 */ | |
1176 int JI(int N, double* x0, double** A, double* b, double ep, int maxiter) | |
1177 { | |
1178 double e, *x=new double[N]; | |
1179 int k=0, sizeN=sizeof(double)*N; | |
1180 while (k<maxiter) | |
1181 { | |
1182 for (int i=0; i<N; i++) | |
1183 { | |
1184 x[i]=b[i]; for (int j=0; j<N; j++) if (j!=i) x[i]-=A[i][j]*x0[j]; x[i]=x[i]/A[i][i]; | |
1185 } | |
1186 e=0; for (int j=0; j<N; j++) e+=fabs(x[j]-x0[j]); //inf-norm used here | |
1187 memcpy(x0, x, sizeN); | |
1188 if (e<ep) break; | |
1189 k++; | |
1190 } | |
1191 delete[] x; | |
1192 if (k>=maxiter) return 1; | |
1193 else return 0; | |
1194 }//JI | |
1195 | |
1196 //--------------------------------------------------------------------------- | |
1197 /* | |
1198 function LDL: LDL' decomposition A=LDL', where L is lower triangular and D is diagonal identical l and | |
1199 a allowed. | |
1200 | |
1201 The symmetric matrix A is positive definite iff A can be factorized as LDL', where L is lower | |
1202 triangular with ones on its diagonal and D is diagonal with positive diagonal entries. | |
1203 | |
1204 If a symmetric matrix A can be reduced by Gaussian elimination without row interchanges, then it can | |
1205 be factored into LDL', where L is lower triangular with ones on its diagonal and D is diagonal with | |
1206 non-zero diagonal entries. | |
1207 | |
1208 In: matrix A[N][N] | |
1209 Out: lower triangular matrix L[N][N], vector d[N] containing diagonal elements of D | |
1210 | |
1211 Returns 0 if successful. Content of matrix A is unchanged on return. | |
1212 */ | |
1213 int LDL(int N, double** L, double* d, double** A) | |
1214 { | |
1215 double* v=new double[N]; | |
1216 | |
1217 if (A[0][0]==0) {delete[] v; return 1;} | |
1218 d[0]=A[0][0]; for (int j=1; j<N; j++) L[j][0]=A[j][0]/d[0]; | |
1219 for (int i=1; i<N; i++) | |
1220 { | |
1221 for (int j=0; j<i; j++) v[j]=L[i][j]*d[j]; | |
1222 d[i]=A[i][i]; for (int j=0; j<i; j++) d[i]-=L[i][j]*v[j]; | |
1223 if (d[i]==0) {delete[] v; return 1;} | |
1224 for (int j=i+1; j<N; j++) | |
1225 { | |
1226 L[j][i]=A[j][i]; for (int k=0; k<i; k++) L[j][i]-=L[j][k]*v[k]; L[j][i]/=d[i]; | |
1227 } | |
1228 } | |
1229 delete[] v; | |
1230 | |
1231 for (int i=0; i<N; i++) {L[i][i]=1; memset(&L[i][i+1], 0, sizeof(double)*(N-1-i));} | |
1232 return 0; | |
1233 }//LDL | |
1234 | |
1235 //--------------------------------------------------------------------------- | |
1236 /* | |
1237 function LQ_GS: LQ decomposition using Gram-Schmidt method | |
1238 | |
1239 In: matrix A[M][N], M<=N | |
1240 Out: matrices L[M][M], Q[M][N] | |
1241 | |
1242 No return value. | |
1243 */ | |
1244 void LQ_GS(int M, int N, double** A, double** L, double** Q) | |
1245 { | |
1246 double *u=new double[N]; | |
1247 for (int m=0; m<M; m++) | |
1248 { | |
1249 memset(L[m], 0, sizeof(double)*M); | |
1250 memcpy(u, A[m], sizeof(double)*N); | |
1251 for (int k=0; k<m; k++) | |
1252 { | |
1253 double ip=0; for (int n=0; n<N; n++) ip+=Q[k][n]*u[n]; | |
1254 for (int n=0; n<N; n++) u[n]-=ip*Q[k][n]; | |
1255 L[m][k]=ip; | |
1256 } | |
1257 double iu=0; for (int n=0; n<N; n++) iu+=u[n]*u[n]; iu=sqrt(iu); | |
1258 L[m][m]=iu; iu=1.0/iu; | |
1259 for (int n=0; n<N; n++) Q[m][n]=u[n]*iu; | |
1260 } | |
1261 delete[] u; | |
1262 }//LQ_GS | |
1263 | |
1264 //--------------------------------------------------------------------------- | |
1265 /* | |
1266 function LSLinear2: 2-dtage LS solution of A[M][N]x[N][1]=y[M][1], M>=N. Use of this function requires | |
1267 the submatrix A[N][N] be invertible. | |
1268 | |
1269 In: matrix A[M][N], vector y[M], M>=N. | |
1270 Out: vector x[N]. | |
1271 | |
1272 No return value. Contents of matrix A and vector y are unchanged on return. | |
1273 */ | |
1274 void LSLinear2(int M, int N, double* x, double** A, double* y) | |
1275 { | |
1276 double** A1=Copy(N, N, 0, A); | |
1277 LU(N, x, A1, y); | |
1278 if (M>N) | |
1279 { | |
1280 double** B=&A[N]; | |
1281 double* Del=MultiplyXy(M-N, N, B, x); | |
1282 MultiAdd(M-N, Del, Del, &y[N], -1); | |
1283 double** A2=MultiplyXtX(N, N, A); | |
1284 MultiplyXtX(N, M-N, A1, B); | |
1285 MultiAdd(N, N, A2, A2, A1, 1); | |
1286 double* b2=MultiplyXty(N, M-N, B, Del); | |
1287 double* dx=new double[N]; | |
1288 GESCP(N, dx, A2, b2); | |
1289 MultiAdd(N, x, x, dx, -1); | |
1290 delete[] dx; | |
1291 delete[] Del; | |
1292 delete[] b2; | |
1293 DeAlloc2(A2); | |
1294 } | |
1295 DeAlloc2(A1); | |
1296 }//LSLinear2 | |
1297 | |
1298 //--------------------------------------------------------------------------- | |
1299 /* | |
1300 function LU: LU decomposition A=LU, where L is lower triangular with diagonal entries 1 and U is upper | |
1301 triangular. | |
1302 | |
1303 LU is possible if A can be reduced by Gaussian elimination without row interchanges. | |
1304 | |
1305 In: matrix A[N][N] | |
1306 Out: matrices L[N][N] and U[N][N], subject to input values of L and U: | |
1307 if L euqals NULL, L is not returned | |
1308 if U equals NULL or A, U is returned in A, s.t. A is modified | |
1309 if L equals A, L is returned in A, s.t. A is modified | |
1310 if L equals U, L and U are returned in the same matrix | |
1311 when L and U are returned in the same matrix, diagonal of L (all 1) is not returned | |
1312 | |
1313 Returns 0 if successful. | |
1314 */ | |
1315 int LU(int N, double** L, double** U, double** A) | |
1316 { | |
1317 double* diagl=new double[N]; | |
1318 for (int i=0; i<N; i++) diagl[i]=1; | |
1319 | |
1320 int sizeN=sizeof(double)*N; | |
1321 if (U==0) U=A; | |
1322 if (U!=A) for (int i=0; i<N; i++) memcpy(U[i], A[i], sizeN); | |
1323 int result=LU_Direct(0, N, diagl, U); | |
1324 if (result==0) | |
1325 { | |
1326 if (L!=U) | |
1327 { | |
1328 if (L!=0) for (int i=0; i<N; i++) {memcpy(L[i], U[i], sizeof(double)*i); L[i][i]=1; memset(&L[i][i+1], 0, sizeof(double)*(N-i-1));} | |
1329 for (int i=1; i<N; i++) memset(U[i], 0, sizeof(double)*i); | |
1330 } | |
1331 } | |
1332 delete[] diagl; | |
1333 return result; | |
1334 }//LU | |
1335 | |
1336 /* | |
1337 function LU: Solving linear system Ax=y by LU factorization | |
1338 | |
1339 In: matrix A[N][N], vector y[N] | |
1340 Out: x[N] | |
1341 | |
1342 No return value. On return A contains its LU factorization (with pivoting, diag mode 1), y remains | |
1343 unchanged. | |
1344 */ | |
1345 void LU(int N, double* x, double** A, double* y, int* ind) | |
1346 { | |
1347 int parity; | |
1348 bool allocind=!ind; | |
1349 if (allocind) ind=new int[N]; | |
1350 LUCP(A, N, ind, parity, 1); | |
1351 for (int i=0; i<N; i++) x[i]=y[ind[i]]; | |
1352 for (int i=0; i<N; i++) | |
1353 { | |
1354 for (int j=i+1; j<N; j++) x[j]=x[j]-x[i]*A[j][i]; | |
1355 } | |
1356 for (int i=N-1; i>=0; i--) | |
1357 { | |
1358 x[i]/=A[i][i]; | |
1359 for (int j=0; j<i; j++) x[j]=x[j]-x[i]*A[j][i]; | |
1360 } | |
1361 if (allocind) delete[] ind; | |
1362 }//LU | |
1363 | |
1364 //--------------------------------------------------------------------------- | |
1365 /* | |
1366 LU_DiagL shows the original procedure for calculating A=LU in separate buffers substitute l and u by a | |
1367 gives the stand-still method LU_Direct(). | |
1368 *//* | |
1369 void LU_DiagL(int N, double** l, double* diagl, double** u, double** a) | |
1370 { | |
1371 l[0][0]=diagl[0]; u[0][0]=a[0][0]/l[0][0]; //here to signal failure if l[00]u[00]=0 | |
1372 for (int j=1; j<N; j++) u[0][j]=a[0][j]/l[0][0], l[j][0]=a[j][0]/u[0][0]; | |
1373 memset(&l[0][1], 0, sizeof(double)*(N-1)); | |
1374 for (int i=1; i<N-1; i++) | |
1375 { | |
1376 l[i][i]=diagl[i]; | |
1377 u[i][i]=a[i][i]; for (int k=0; k<i; k++) u[i][i]-=l[i][k]*u[k][i]; u[i][i]/=l[i][i]; //here to signal failure if l[ii]u[ii]=0 | |
1378 for (int j=i+1; j<N; j++) | |
1379 { | |
1380 u[i][j]=a[i][j]; for (int k=0; k<i; k++) u[i][j]-=l[i][k]*u[k][j]; u[i][j]/=l[i][i]; | |
1381 l[j][i]=a[j][i]; for (int k=0; k<i; k++) l[j][i]-=l[j][k]*u[k][i]; l[j][i]/=u[i][i]; | |
1382 } | |
1383 memset(&l[i][i+1], 0, sizeof(double)*(N-1-i)), memset(u[i], 0, sizeof(double)*i); | |
1384 } | |
1385 l[N-1][N-1]=diagl[N-1]; | |
1386 u[N-1][N-1]=a[N-1][N-1]; for (int k=0; k<N-1; k++) u[N-1][N-1]-=l[N-1][k]*u[k][N-1]; u[N-1][N-1]/=l[N-1][N-1]; | |
1387 memset(u[N-1], 0, sizeof(double)*(N-1)); | |
1388 } //LU_DiagL*/ | |
1389 | |
1390 //--------------------------------------------------------------------------- | |
1391 /* | |
1392 function LU_Direct: LU factorization A=LU. | |
1393 | |
1394 In: matrix A[N][N], vector diag[N] specifying main diagonal of L or U, according to mode (0=LDiag, | |
1395 1=UDiag). | |
1396 Out: matrix A[N][N] now containing L and U. | |
1397 | |
1398 Returns 0 if successful. | |
1399 */ | |
1400 int LU_Direct(int mode, int N, double* diag, double** A) | |
1401 { | |
1402 if (mode==0) | |
1403 { | |
1404 if (A[0][0]==0) return 1; | |
1405 A[0][0]=A[0][0]/diag[0]; | |
1406 for (int j=1; j<N; j++) A[0][j]=A[0][j]/diag[0], A[j][0]=A[j][0]/A[0][0]; | |
1407 for (int i=1; i<N-1; i++) | |
1408 { | |
1409 for (int k=0; k<i; k++) A[i][i]-=A[i][k]*A[k][i]; A[i][i]/=diag[i]; | |
1410 if (A[i][i]==0) return 2; | |
1411 for (int j=i+1; j<N; j++) | |
1412 { | |
1413 for (int k=0; k<i; k++) A[i][j]-=A[i][k]*A[k][j]; A[i][j]/=diag[i]; | |
1414 for (int k=0; k<i; k++) A[j][i]-=A[j][k]*A[k][i]; A[j][i]/=A[i][i]; | |
1415 } | |
1416 } | |
1417 for (int k=0; k<N-1; k++) A[N-1][N-1]-=A[N-1][k]*A[k][N-1]; A[N-1][N-1]/=diag[N-1]; | |
1418 } | |
1419 else if (mode==1) | |
1420 { | |
1421 A[0][0]=A[0][0]/diag[0]; | |
1422 if (A[0][0]==0) return 1; | |
1423 for (int j=1; j<N; j++) A[0][j]=A[0][j]/A[0][0], A[j][0]=A[j][0]/diag[0]; | |
1424 for (int i=1; i<N-1; i++) | |
1425 { | |
1426 for (int k=0; k<i; k++) A[i][i]-=A[i][k]*A[k][i]; A[i][i]/=diag[i]; | |
1427 if (A[i][i]==0) return 2; | |
1428 for (int j=i+1; j<N; j++) | |
1429 { | |
1430 for (int k=0; k<i; k++) A[i][j]-=A[i][k]*A[k][j]; A[i][j]/=A[i][i]; | |
1431 for (int k=0; k<i; k++) A[j][i]-=A[j][k]*A[k][i]; A[j][i]/=diag[i]; | |
1432 } | |
1433 } | |
1434 for (int k=0; k<N-1; k++) A[N-1][N-1]-=A[N-1][k]*A[k][N-1]; A[N-1][N-1]/=diag[N-1]; | |
1435 } | |
1436 return 0; | |
1437 }//LU_Direct | |
1438 | |
1439 //--------------------------------------------------------------------------- | |
1440 /* | |
1441 function LU_PD: LU factorization for pentadiagonal A=LU | |
1442 | |
1443 In: pentadiagonal matrix A[N][N] stored in a compact format, i.e. A[i][j]->b[i-j, j] | |
1444 the main diagonal is b[0][0]~b[0][N-1] | |
1445 the 1st upper subdiagonal is b[-1][1]~b[-1][N-1] | |
1446 the 2nd upper subdiagonal is b[-2][2]~b[-2][N-1] | |
1447 the 1st lower subdiagonal is b[1][0]~b[1][N-2] | |
1448 the 2nd lower subdiagonal is b[2][0]~b[2][N-3] | |
1449 | |
1450 Out: L[N][N] and U[N][N], main diagonal of L being all 1 (probably), stored in a compact format in | |
1451 b[-2:2][N]. | |
1452 | |
1453 Returns 0 if successful. | |
1454 */ | |
1455 int LU_PD(int N, double** b) | |
1456 { | |
1457 if (b[0][0]==0) return 1; | |
1458 b[1][0]/=b[0][0], b[2][0]/=b[0][0]; | |
1459 | |
1460 //i=1, not to double b[*][i-2], b[-2][i] | |
1461 b[0][1]-=b[1][0]*b[-1][1]; | |
1462 if (b[0][1]==0) return 2; | |
1463 b[-1][2]-=b[1][0]*b[-2][2]; | |
1464 b[1][1]-=b[2][0]*b[-1][1]; | |
1465 b[1][1]/=b[0][1]; | |
1466 b[2][1]/=b[0][1]; | |
1467 | |
1468 for (int i=2; i<N-2; i++) | |
1469 { | |
1470 b[0][i]-=b[2][i-2]*b[-2][i]; | |
1471 b[0][i]-=b[1][i-1]*b[-1][i]; | |
1472 if (b[0][i]==0) return 2; | |
1473 b[-1][i+1]-=b[1][i-1]*b[-2][i+1]; | |
1474 b[1][i]-=b[2][i-1]*b[-1][i]; | |
1475 b[1][i]/=b[0][i]; | |
1476 b[2][i]/=b[0][i]; | |
1477 } | |
1478 //i=N-2, not to tough b[2][i] | |
1479 b[0][N-2]-=b[2][N-4]*b[-2][N-2]; | |
1480 b[0][N-2]-=b[1][N-3]*b[-1][N-2]; | |
1481 if (b[0][N-2]==0) return 2; | |
1482 b[-1][N-1]-=b[1][N-3]*b[-2][N-1]; | |
1483 b[1][N-2]-=b[2][N-3]*b[-1][N-2]; | |
1484 b[1][N-2]/=b[0][N-2]; | |
1485 | |
1486 b[0][N-1]-=b[2][N-3]*b[-2][N-1]; | |
1487 b[0][N-1]-=b[1][N-2]*b[-1][N-1]; | |
1488 return 0; | |
1489 }//LU_PD | |
1490 | |
1491 /* | |
1492 This old version is kept here as a reference. | |
1493 *//* | |
1494 int LU_PD(int N, double** b) | |
1495 { | |
1496 if (b[0][0]==0) return 1; | |
1497 for (int j=1; j<3; j++) b[j][0]=b[j][0]/b[0][0]; | |
1498 for (int i=1; i<N-1; i++) | |
1499 { | |
1500 for (int k=i-2; k<i; k++) b[0][i]-=b[i-k][k]*b[k-i][i]; | |
1501 if (b[0][i]==0) return 2; | |
1502 for (int j=i+1; j<i+3; j++) | |
1503 { | |
1504 for (int k=j-2; k<i; k++) b[i-j][j]-=b[i-k][k]*b[k-j][j]; | |
1505 for (int k=j-2; k<i; k++) b[j-i][i]-=b[j-k][k]*b[k-i][i]; | |
1506 b[j-i][i]/=b[0][i]; | |
1507 } | |
1508 } | |
1509 for (int k=N-3; k<N-1; k++) b[0][N-1]-=b[N-1-k][k]*b[k-N+1][N-1]; | |
1510 return 0; | |
1511 }//LU_PD*/ | |
1512 | |
1513 /* | |
1514 function LU_PD: solve pentadiagonal system Ax=c | |
1515 | |
1516 In: pentadiagonal matrix A[N][N] stored in a compact format in b[-2:2][N], vector c[N] | |
1517 Out: vector c now containing x. | |
1518 | |
1519 Returns 0 if successful. On return b is in the LU form. | |
1520 */ | |
1521 int LU_PD(int N, double** b, double* c) | |
1522 { | |
1523 int result=LU_PD(N, b); | |
1524 if (result==0) | |
1525 { | |
1526 //L loop | |
1527 c[1]=c[1]-b[1][0]*c[0]; | |
1528 for (int i=2; i<N; i++) | |
1529 c[i]=c[i]-b[1][i-1]*c[i-1]-b[2][i-2]*c[i-2]; | |
1530 //U loop | |
1531 c[N-1]/=b[0][N-1]; | |
1532 c[N-2]=(c[N-2]-b[-1][N-1]*c[N-1])/b[0][N-2]; | |
1533 for (int i=N-3; i>=0; i--) | |
1534 c[i]=(c[i]-b[-1][i+1]*c[i+1]-b[-2][i+2]*c[i+2])/b[0][i]; | |
1535 } | |
1536 return result; | |
1537 }//LU_PD | |
1538 | |
1539 //--------------------------------------------------------------------------- | |
1540 /* | |
1541 function LUCP: LU decomposition A=LU with column pivoting | |
1542 | |
1543 In: matrix A[N][N] | |
1544 Out: matrix A[N][N] now holding L and U by L_U[i][j]=A[ind[i]][j], where L_U | |
1545 hosts L and U according to mode: | |
1546 mode=0: L diag=abs(U diag), U diag as return | |
1547 mode=1: L diag=1, U diag as return | |
1548 mode=2: U diag=1, L diag as return | |
1549 | |
1550 Returns the determinant of A. | |
1551 */ | |
1552 double LUCP(double **A, int N, int *ind, int &parity, int mode) | |
1553 { | |
1554 double det=1; | |
1555 parity=1; | |
1556 | |
1557 for (int i=0; i<N; i++) ind[i]=i; | |
1558 double vmax, *norm=new double[N]; //norm[n] is the maxima of row n | |
1559 for (int i=0; i<N; i++) | |
1560 { | |
1561 vmax=fabs(A[i][0]); | |
1562 double tmp; | |
1563 for (int j=1; j<N; j++) if ((tmp=fabs(A[i][j]))>vmax) vmax=tmp; | |
1564 if (vmax==0) { parity=0; goto deletenorm; } //det=0 at this point | |
1565 norm[i]=1/vmax; | |
1566 } | |
1567 | |
1568 int maxind; | |
1569 for (int j=0; j<N; j++) | |
1570 { //Column j | |
1571 for (int i=0; i<j; i++) | |
1572 { | |
1573 //row i, i<j | |
1574 double tmp=A[i][j]; | |
1575 for (int k=0; k<i; k++) tmp-=A[i][k]*A[k][j]; | |
1576 A[i][j]=tmp; | |
1577 } | |
1578 for (int i=j; i<N; i++) | |
1579 { | |
1580 //row i, i>=j | |
1581 double tmp=A[i][j]; for (int k=0; k<j; k++) tmp-=A[i][k]*A[k][j]; A[i][j]=tmp; | |
1582 double tmp2=norm[i]*fabs(tmp); | |
1583 if (i==j || tmp2>=vmax) maxind=i, vmax=tmp2; | |
1584 } | |
1585 if (vmax==0) { parity=0; goto deletenorm; } //pivot being zero | |
1586 if (j!=maxind) | |
1587 { | |
1588 //do column pivoting: switching rows | |
1589 for (int k=0; k<N; k++) { double tmp=A[maxind][k]; A[maxind][k]=A[j][k]; A[j][k]=tmp; } | |
1590 parity=-parity; | |
1591 norm[maxind]=norm[j]; | |
1592 } | |
1593 int itmp=ind[j]; ind[j]=ind[maxind]; ind[maxind]=itmp; | |
1594 if (j!=N-1) | |
1595 { | |
1596 double den=1/A[j][j]; | |
1597 for (int i=j+1; i<N; i++) A[i][j]*=den; | |
1598 } | |
1599 det*=A[j][j]; | |
1600 } //Go back for the next column in the reduction. | |
1601 | |
1602 if (mode==0) | |
1603 { | |
1604 for (int i=0; i<N-1; i++) | |
1605 { | |
1606 double den=sqrt(fabs(A[i][i])); | |
1607 double iden=1/den; | |
1608 for (int j=i+1; j<N; j++) A[j][i]*=den, A[i][j]*=iden; | |
1609 A[i][i]*=iden; | |
1610 } | |
1611 A[N-1][N-1]/=sqrt(fabs(A[N-1][N-1])); | |
1612 } | |
1613 else if (mode==2) | |
1614 { | |
1615 for (int i=0; i<N-1; i++) | |
1616 { | |
1617 double den=A[i][i]; | |
1618 double iden=1/den; | |
1619 for (int j=i+1; j<N; j++) A[j][i]*=den, A[i][j]*=iden; | |
1620 } | |
1621 } | |
1622 | |
1623 deletenorm: | |
1624 delete[] norm; | |
1625 return det*parity; | |
1626 }//LUCP | |
1627 | |
1628 //--------------------------------------------------------------------------- | |
1629 /* | |
1630 function maxind: returns the index of the maximal value of data[from:(to-1)]. | |
1631 | |
1632 In: vector data containing at least $to entries. | |
1633 Out: the index to the maximal entry of data[from:(to-1)] | |
1634 | |
1635 Returns the index to the maximal value. | |
1636 */ | |
1637 int maxind(double* data, int from, int to) | |
1638 { | |
1639 int result=from; | |
1640 for (int i=from+1; i<to; i++) if (data[result]<data[i]) result=i; | |
1641 return result; | |
1642 }//maxind | |
1643 | |
1644 //--------------------------------------------------------------------------- | |
1645 /* | |
1646 macro Multiply_vect: matrix-vector multiplications | |
1647 | |
1648 Each expansion of this macro implements two functions named $MULTIPLY that do matrix-vector | |
1649 multiplication. Functions are named after their exact functions. For example, MultiplyXty() does | |
1650 multiplication of the transpose of matrix X with vector y, where postfix "t" attched to Y stands for | |
1651 transpose. Likewise, the postfix "c" stands for conjugate, and "h" stnads for Hermitian (conjugate | |
1652 transpose). | |
1653 | |
1654 Two dimension arguments are needed by each function. The first of the two is the number of entries to | |
1655 the output vector; the second of the two is the "other" dimension of the matrix multiplier. | |
1656 */ | |
1657 #define Multiply_vect(MULTIPLY, DbZ, DbX, DbY, xx, yy) \ | |
1658 DbZ* MULTIPLY(int M, int N, DbZ* z, DbX* x, DbY* y, MList* List) \ | |
1659 { \ | |
1660 if (!z){z=new DbZ[M]; if (List) List->Add(z, 1);} \ | |
1661 for (int m=0; m<M; m++){z[m]=0; for (int n=0; n<N; n++) z[m]+=xx*yy;} \ | |
1662 return z; \ | |
1663 } \ | |
1664 DbZ* MULTIPLY(int M, int N, DbX* x, DbY* y, MList* List) \ | |
1665 { \ | |
1666 DbZ* z=new DbZ[M]; if (List) List->Add(z, 1); \ | |
1667 for (int m=0; m<M; m++){z[m]=0; for (int n=0; n<N; n++) z[m]+=xx*yy;} \ | |
1668 return z; \ | |
1669 } | |
1670 //function MultiplyXy: z[M]=x[M][N]y[N], identical z and y NOT ALLOWED | |
1671 Multiply_vect(MultiplyXy, double, double*, double, x[m][n], y[n]) | |
1672 Multiply_vect(MultiplyXy, cdouble, cdouble*, cdouble, x[m][n], y[n]) | |
1673 Multiply_vect(MultiplyXy, cdouble, double*, cdouble, x[m][n], y[n]) | |
1674 //function MultiplyxY: z[M]=x[N]y[N][M], identical z and x NOT ALLOWED | |
1675 Multiply_vect(MultiplyxY, double, double, double*, x[n], y[n][m]) | |
1676 Multiply_vect(MultiplyxY, cdouble, cdouble, cdouble*, x[n], y[n][m]) | |
1677 //function MultiplyXty: z[M]=xt[M][N]y[N] | |
1678 Multiply_vect(MultiplyXty, double, double*, double, x[n][m], y[n]) | |
1679 Multiply_vect(MultiplyXty, cdouble, cdouble*, cdouble, x[n][m], y[n]) | |
1680 //function MultiplyXhy: z[M]=xh[M][N]y[N] | |
1681 Multiply_vect(MultiplyXhy, cdouble, cdouble*, cdouble, *x[n][m], y[n]) | |
1682 //function MultiplyxYt: z[M]=x[N]yt[N][M] | |
1683 Multiply_vect(MultiplyxYt, double, double, double*, x[n], y[m][n]) | |
1684 //function MultiplyXcy: z[M]=(x*)[M][N]y[N] | |
1685 Multiply_vect(MultiplyXcy, cdouble, cdouble*, cdouble, *x[m][n], y[n]) | |
1686 Multiply_vect(MultiplyXcy, cdouble, cdouble*, cfloat, *x[m][n], y[n]) | |
1687 | |
1688 //--------------------------------------------------------------------------- | |
1689 /* | |
1690 function Norm1: L-1 norm of a square matrix A | |
1691 | |
1692 In: matrix A[N][N] | |
1693 Out: its L-1 norm | |
1694 | |
1695 Returns the L-1 norm. | |
1696 */ | |
1697 double Norm1(int N, double** A) | |
1698 { | |
1699 double result=0, norm; | |
1700 for (int i=0; i<N; i++) | |
1701 { | |
1702 norm=0; for (int j=0; j<N; j++) norm+=fabs(A[i][j]); | |
1703 if (result<norm) result=norm; | |
1704 } | |
1705 return result; | |
1706 }//Norm1 | |
1707 | |
1708 //--------------------------------------------------------------------------- | |
1709 /* | |
1710 function QL: QL method for solving tridiagonal symmetric matrix eigenvalue problem. | |
1711 | |
1712 In: A[N][N]: tridiagonal symmetric matrix stored in d[N] and sd[] arranged so that d[0:n-1] contains | |
1713 the diagonal elements of A, sd[0]=0, sd[1:n-1] contains the subdiagonal elements of A. | |
1714 z[N][N]: pre-transform matrix z[N][N] compatible with HouseHolder() routine. | |
1715 Out: d[N]: the eigenvalues of A | |
1716 z[N][N] the eigenvectors of A. | |
1717 | |
1718 Returns 0 if successful. sd[] should have storage for at least N+1 entries. | |
1719 */ | |
1720 int QL(int N, double* d, double* sd, double** z) | |
1721 { | |
1722 const int maxiter=30; | |
1723 for (int i=1; i<N; i++) sd[i-1]=sd[i]; | |
1724 sd[N]=0.0; | |
1725 for (int l=0; l<N; l++) | |
1726 { | |
1727 int iter=0, m; | |
1728 do | |
1729 { | |
1730 for (m=l; m<N-1; m++) | |
1731 { | |
1732 double dd=fabs(d[m])+fabs(d[m+1]); | |
1733 if (fabs(sd[m])+dd==dd) break; | |
1734 } | |
1735 if (m!=l) | |
1736 { | |
1737 iter++; | |
1738 if (iter>=maxiter) return 1; | |
1739 double g=(d[l+1]-d[l])/(2*sd[l]); | |
1740 double r=sqrt(g*g+1); | |
1741 g=d[m]-d[l]+sd[l]/(g+(g>=0?r:-r)); | |
1742 double s=1, c=1, p=0; | |
1743 int i; | |
1744 for (i=m-1; i>=l; i--) | |
1745 { | |
1746 double f=s*sd[i], b=c*sd[i]; | |
1747 sd[i+1]=(r=sqrt(f*f+g*g)); | |
1748 if (r==0) | |
1749 { | |
1750 d[i+1]-=p; | |
1751 sd[m]=0; | |
1752 break; | |
1753 } | |
1754 s=f/r, c=g/r; | |
1755 g=d[i+1]-p; | |
1756 r=(d[i]-g)*s+2.0*c*b; | |
1757 p=s*r; | |
1758 d[i+1]=g+p; | |
1759 g=c*r-b; | |
1760 for (int k=0; k<N; k++) | |
1761 { | |
1762 f=z[k][i+1]; | |
1763 z[k][i+1]=s*z[k][i]+c*f; | |
1764 z[k][i]=c*z[k][i]-s*f; | |
1765 } | |
1766 } | |
1767 if (r==0 && i>=l) continue; | |
1768 d[l]-=p; | |
1769 sd[l]=g; | |
1770 sd[m]=0.0; | |
1771 } | |
1772 } | |
1773 while (m!=l); | |
1774 } | |
1775 return 0; | |
1776 }//QL | |
1777 | |
1778 //--------------------------------------------------------------------------- | |
1779 /* | |
1780 function QR: nr version of QR method for solving upper Hessenberg system A. This is compatible with | |
1781 Hessenb method. | |
1782 | |
1783 In: matrix A[N][N] | |
1784 Out: vector ev[N] of eigenvalues | |
1785 | |
1786 Returns 0 on success. Content of matrix A is destroyed on return. | |
1787 */ | |
1788 int QR(int N, double **A, cdouble* ev) | |
1789 { | |
1790 int n=N, m, l, k, j, iter, i, mmin, maxiter=30; | |
1791 double **a=A, z, y, x, w, v, u, t=0, s, r, q, p, a1=0; | |
1792 for (i=0; i<n; i++) for (j=i-1>0?i-1:0; j<n; j++) a1+=fabs(a[i][j]); | |
1793 n--; | |
1794 while (n>=0) | |
1795 { | |
1796 iter=0; | |
1797 do | |
1798 { | |
1799 for (l=n; l>0; l--) | |
1800 { | |
1801 s=fabs(a[l-1][l-1])+fabs(a[l][l]); | |
1802 if (s==0) s=a1; | |
1803 if (fabs(a[l][l-1])+s==s) {a[l][l-1]=0; break;} | |
1804 } | |
1805 x=a[n][n]; | |
1806 if (l==n) {ev[n].x=x+t; ev[n--].y=0;} | |
1807 else | |
1808 { | |
1809 y=a[n-1][n-1], w=a[n][n-1]*a[n-1][n]; | |
1810 if (l==(n-1)) | |
1811 { | |
1812 p=0.5*(y-x); | |
1813 q=p*p+w; | |
1814 z=sqrt(fabs(q)); | |
1815 x+=t; | |
1816 if (q>=0) | |
1817 { | |
1818 z=p+(p>=0?z:-z); | |
1819 ev[n-1].x=ev[n].x=x+z; | |
1820 if (z) ev[n].x=x-w/z; | |
1821 ev[n-1].y=ev[n].y=0; | |
1822 } | |
1823 else | |
1824 { | |
1825 ev[n-1].x=ev[n].x=x+p; | |
1826 ev[n].y=z; ev[n-1].y=-z; | |
1827 } | |
1828 n-=2; | |
1829 } | |
1830 else | |
1831 { | |
1832 if (iter>=maxiter) return 1; | |
1833 if (iter%10==9) | |
1834 { | |
1835 t+=x; | |
1836 for (i=0; i<=n; i++) a[i][i]-=x; | |
1837 s=fabs(a[n][n-1])+fabs(a[n-1][n-2]); | |
1838 y=x=0.75*s; | |
1839 w=-0.4375*s*s; | |
1840 } | |
1841 iter++; | |
1842 for (m=n-2; m>=l; m--) | |
1843 { | |
1844 z=a[m][m]; | |
1845 r=x-z; s=y-z; | |
1846 p=(r*s-w)/a[m+1][m]+a[m][m+1]; q=a[m+1][m+1]-z-r-s; r=a[m+2][m+1]; | |
1847 s=fabs(p)+fabs(q)+fabs(r); | |
1848 p/=s; q/=s; r/=s; | |
1849 if (m==l) break; | |
1850 u=fabs(a[m][m-1])*(fabs(q)+fabs(r)); | |
1851 v=fabs(p)*(fabs(a[m-1][m-1])+fabs(z)+fabs(a[m+1][m+1])); | |
1852 if (u+v==v) break; | |
1853 } | |
1854 for (i=m+2; i<=n; i++) | |
1855 { | |
1856 a[i][i-2]=0; | |
1857 if (i!=m+2) a[i][i-3]=0; | |
1858 } | |
1859 for (k=m; k<=n-1; k++) | |
1860 { | |
1861 if (k!=m) | |
1862 { | |
1863 p=a[k][k-1]; | |
1864 q=a[k+1][k-1]; | |
1865 r=0; | |
1866 if (k!=n-1) r=a[k+2][k-1]; | |
1867 x=fabs(p)+fabs(q)+fabs(r); | |
1868 if (x!=0) p/=x, q/=x, r/=x; | |
1869 } | |
1870 if (p>=0) s=sqrt(p*p+q*q+r*r); | |
1871 else s=-sqrt(p*p+q*q+r*r); | |
1872 if (s!=0) | |
1873 { | |
1874 if (k==m) | |
1875 { | |
1876 if (l!=m) a[k][k-1]=-a[k][k-1]; | |
1877 } | |
1878 else a[k][k-1]=-s*x; | |
1879 p+=s; | |
1880 x=p/s; y=q/s; z=r/s; q/=p; r/=p; | |
1881 for (j=k; j<=n; j++) | |
1882 { | |
1883 p=a[k][j]+q*a[k+1][j]; | |
1884 if (k!=n-1) | |
1885 { | |
1886 p+=r*a[k+2][j]; | |
1887 a[k+2][j]-=p*z; | |
1888 } | |
1889 a[k+1][j]-=p*y; a[k][j]-=p*x; | |
1890 } | |
1891 mmin=n<k+3?n:k+3; | |
1892 for (i=l; i<=mmin; i++) | |
1893 { | |
1894 p=x*a[i][k]+y*a[i][k+1]; | |
1895 if (k!=(n-1)) | |
1896 { | |
1897 p+=z*a[i][k+2]; | |
1898 a[i][k+2]-=p*r; | |
1899 } | |
1900 a[i][k+1]-=p*q; a[i][k]-=p; | |
1901 } | |
1902 } | |
1903 } | |
1904 } | |
1905 } | |
1906 } while (n>l+1); | |
1907 } | |
1908 return 0; | |
1909 }//QR | |
1910 | |
1911 /* | |
1912 function QR_GS: QR decomposition A=QR using Gram-Schmidt method | |
1913 | |
1914 In: matrix A[M][N], M>=N | |
1915 Out: Q[M][N], R[N][N] | |
1916 | |
1917 No return value. | |
1918 */ | |
1919 void QR_GS(int M, int N, double** A, double** Q, double** R) | |
1920 { | |
1921 double *u=new double[M]; | |
1922 for (int n=0; n<N; n++) | |
1923 { | |
1924 memset(R[n], 0, sizeof(double)*N); | |
1925 for (int m=0; m<M; m++) u[m]=A[m][n]; | |
1926 for (int k=0; k<n; k++) | |
1927 { | |
1928 double ip=0; for (int m=0; m<M; m++) ip+=u[m]*Q[m][k]; | |
1929 for (int m=0; m<M; m++) u[m]-=ip*Q[m][k]; | |
1930 R[k][n]=ip; | |
1931 } | |
1932 double iu=0; for (int m=0; m<M; m++) iu+=u[m]*u[m]; iu=sqrt(iu); | |
1933 R[n][n]=iu; | |
1934 iu=1.0/iu; for (int m=0; m<M; m++) Q[m][n]=u[m]*iu; | |
1935 } | |
1936 delete[] u; | |
1937 }//QR_GS | |
1938 | |
1939 /* | |
1940 function QR_householder: QR decomposition using householder transform | |
1941 | |
1942 In: A[M][N], M>=N | |
1943 Out: Q[M][M], R[M][N] | |
1944 | |
1945 No return value. | |
1946 */ | |
1947 void QR_householder(int M, int N, double** A, double** Q, double** R) | |
1948 { | |
1949 double *u=new double[M*3], *ur=&u[M], *qu=&u[M*2]; | |
1950 for (int m=0; m<M; m++) | |
1951 { | |
1952 memcpy(R[m], A[m], sizeof(double)*N); | |
1953 memset(Q[m], 0, sizeof(double)*M); Q[m][m]=1; | |
1954 } | |
1955 for (int n=0; n<N; n++) | |
1956 { | |
1957 double alf=0; for (int m=n; m<M; m++) alf+=R[m][n]*R[m][n]; alf=sqrt(alf); | |
1958 if (R[n][n]>0) alf=-alf; | |
1959 for (int m=n; m<M; m++) u[m]=R[m][n]; u[n]=u[n]-alf; | |
1960 double iu2=0; for (int m=n; m<M; m++) iu2+=u[m]*u[m]; iu2=2.0/iu2; | |
1961 for (int m=n; m<N; m++) | |
1962 { | |
1963 ur[m]=0; for (int k=n; k<M; k++) ur[m]+=u[k]*R[k][m]; | |
1964 } | |
1965 for (int m=0; m<M; m++) | |
1966 { | |
1967 qu[m]=0; for (int k=n; k<M; k++) qu[m]+=Q[m][k]*u[k]; | |
1968 } | |
1969 for (int m=n; m<M; m++) u[m]=u[m]*iu2; | |
1970 for (int m=n; m<M; m++) for (int k=n; k<N; k++) R[m][k]-=u[m]*ur[k]; | |
1971 for (int m=0; m<M; m++) for (int k=n; k<M; k++) Q[m][k]-=qu[m]*u[k]; | |
1972 } | |
1973 delete[] u; | |
1974 }//QR_householder | |
1975 | |
1976 //--------------------------------------------------------------------------- | |
1977 /* | |
1978 function QU: Unitary decomposition A=QU, where Q is unitary and U is upper triangular | |
1979 | |
1980 In: matrix A[N][N] | |
1981 Out: matrices Q[N][N], A[n][n] now containing U | |
1982 | |
1983 No return value. | |
1984 */ | |
1985 void QU(int N, double** Q, double** A) | |
1986 { | |
1987 int sizeN=sizeof(double)*N; | |
1988 for (int i=0; i<N; i++) {memset(Q[i], 0, sizeN); Q[i][i]=1;} | |
1989 | |
1990 double m, s, c, *tmpi=new double[N], *tmpj=new double[N]; | |
1991 for (int i=1; i<N; i++) for (int j=0; j<i; j++) | |
1992 if (A[i][j]!=0) | |
1993 { | |
1994 m=sqrt(A[j][j]*A[j][j]+A[i][j]*A[i][j]); | |
1995 s=A[i][j]/m; | |
1996 c=A[j][j]/m; | |
1997 for (int k=0; k<N; k++) tmpi[k]=-s*A[j][k]+c*A[i][k], tmpj[k]=c*A[j][k]+s*A[i][k]; | |
1998 memcpy(A[i], tmpi, sizeN), memcpy(A[j], tmpj, sizeN); | |
1999 for (int k=0; k<N; k++) tmpi[k]=-s*Q[j][k]+c*Q[i][k], tmpj[k]=c*Q[j][k]+s*Q[i][k]; | |
2000 memcpy(Q[i], tmpi, sizeN), memcpy(Q[j], tmpj, sizeN); | |
2001 } | |
2002 delete[] tmpi; delete[] tmpj; | |
2003 transpose(N, Q); | |
2004 }//QU | |
2005 | |
2006 //--------------------------------------------------------------------------- | |
2007 /* | |
2008 function Real: extracts the real part of matrix X | |
2009 | |
2010 In: matrix x[M][N]; | |
2011 Out: matrix z[M][N] | |
2012 | |
2013 Returns pointer to z. z is created anew if z=0 is specified on start. | |
2014 */ | |
2015 double** Real(int M, int N, double** z, cdouble** x, MList* List) | |
2016 { | |
2017 if (!z){Allocate2(double, M, N, z); if (List) List->Add(z, 2);} | |
2018 for (int m=0; m<M; m++) for (int n=0; n<N; n++) z[m][n]=x[m][n].x; | |
2019 return z; | |
2020 }//Real | |
2021 double** Real(int M, int N, cdouble** x, MList* List){return Real(M, N, 0, x, List);} | |
2022 | |
2023 //--------------------------------------------------------------------------- | |
2024 /* | |
2025 function Roots: finds the roots of a polynomial. x^N+p[N-1]x^(N-1)+p[N-2]x^(N-2)...+p[0] | |
2026 | |
2027 In: vector p[N] of polynomial coefficients. | |
2028 Out: vector r[N] of roots. | |
2029 | |
2030 Returns 0 if successful. | |
2031 */ | |
2032 int Roots(int N, double* p, cdouble* r) | |
2033 { | |
2034 double** A=new double*[N]; A[0]=new double[N*N]; for (int i=1; i<N; i++) A[i]=&A[0][i*N]; | |
2035 for (int i=0; i<N; i++) A[0][i]=-p[N-1-i]; | |
2036 if (N>1) memset(A[1], 0, sizeof(double)*N*(N-1)); | |
2037 for (int i=1; i<N; i++) A[i][i-1]=1; | |
2038 BalanceSim(N, A); | |
2039 double result=QR(N, A, r); | |
2040 delete[] A[0]; delete[] A; | |
2041 return result; | |
2042 }//Roots | |
2043 //real implementation | |
2044 int Roots(int N, double* p, double* rr, double* ri) | |
2045 { | |
2046 cdouble* r=new cdouble[N]; | |
2047 int result=Roots(N, p, r); | |
2048 for (int n=0; n<N; n++) rr[n]=r[n].x, ri[n]=r[n].y; | |
2049 delete[] r; | |
2050 return result; | |
2051 }//Roots | |
2052 | |
2053 //--------------------------------------------------------------------------- | |
2054 /* | |
2055 function SorI: Sor iteration algorithm for solving linear system Ax=b. | |
2056 | |
2057 Sor method is an extension of the Gaussian-Siedel method, with the latter equivalent to the former | |
2058 with w set to 1. The Sor iteration is given by x(k)=(D-wL)^(-1)(((1-w)D+wU)x(k-1)+wb), where 0<w<2, D | |
2059 is diagonal, L is lower triangular, U is upper triangular and A=L+D+U. Sor method converges if A is | |
2060 positive definite. | |
2061 | |
2062 In: matrix A[N][N], vector b[N], initial vector x0[N] | |
2063 Out: vector x0[N] | |
2064 | |
2065 Returns 0 if successful. Contents of matrix A and vector b are unchanged on return. | |
2066 */ | |
2067 int SorI(int N, double* x0, double** a, double* b, double w, double ep, int maxiter) | |
2068 { | |
2069 double e, v=1-w, *x=new double[N]; | |
2070 int k=0, sizeN=sizeof(double)*N; | |
2071 while (k<maxiter) | |
2072 { | |
2073 for (int i=0; i<N; i++) | |
2074 { | |
2075 x[i]=b[i]; | |
2076 for (int j=0; j<i; j++) x[i]-=a[i][j]*x[j]; | |
2077 for (int j=i+1; j<N; j++) x[i]-=a[i][j]*x0[j]; | |
2078 x[i]=v*x0[i]+w*x[i]/a[i][i]; | |
2079 } | |
2080 e=0; for (int j=0; j<N; j++) e+=fabs(x[j]-x0[j]); | |
2081 memcpy(x0, x, sizeN); | |
2082 if (e<ep) break; | |
2083 k++; | |
2084 } | |
2085 delete[] x; | |
2086 if (k>=maxiter) return 1; | |
2087 return 0; | |
2088 }//SorI | |
2089 | |
2090 //--------------------------------------------------------------------------- | |
2091 //Submatrix routines | |
2092 | |
2093 /* | |
2094 function SetSubMatrix: copy matrix x[Y][X] into matrix z at (Y1, X1). | |
2095 | |
2096 In: matrix x[Y][X], matrix z with dimensions no less than [Y+Y1][X+X1] | |
2097 Out: matrix z, updated. | |
2098 | |
2099 No return value. | |
2100 */ | |
2101 void SetSubMatrix(double** z, double** x, int Y1, int Y, int X1, int X) | |
2102 { | |
2103 for (int y=0; y<Y; y++) memcpy(&z[Y1+y][X1], x[y], sizeof(double)*X); | |
2104 }//SetSubMatrix | |
2105 //complex version | |
2106 void SetSubMatrix(cdouble** z, cdouble** x, int Y1, int Y, int X1, int X) | |
2107 { | |
2108 for (int y=0; y<Y; y++) memcpy(&z[Y1+y][X1], x[y], sizeof(cdouble)*X); | |
2109 }//SetSubMatrix | |
2110 | |
2111 /* | |
2112 function SubMatrix: extract a submatrix of x at (Y1, X1) to z[Y][X]. | |
2113 | |
2114 In: matrix x of dimensions no less than [Y+Y1][X+X1] | |
2115 Out: matrix z[Y][X]. | |
2116 | |
2117 Returns pointer to z. z is created anew if z=0 is specifid on start. | |
2118 */ | |
2119 cdouble** SubMatrix(cdouble** z, cdouble** x, int Y1, int Y, int X1, int X, MList* List) | |
2120 { | |
2121 if (!z) {Allocate2(cdouble, Y, X, z); if (List) List->Add(z, 2);} | |
2122 for (int y=0; y<Y; y++) memcpy(z[y], &x[Y1+y][X1], sizeof(cdouble)*X); | |
2123 return z; | |
2124 }//SetSubMatrix | |
2125 //wrapper function | |
2126 cdouble** SubMatrix(cdouble** x, int Y1, int Y, int X1, int X, MList* List) | |
2127 { | |
2128 return SubMatrix(0, x, Y1, Y, X1, X, List); | |
2129 }//SetSubMatrix | |
2130 | |
2131 /* | |
2132 function SubVector: extract a subvector of x at X1 to z[X]. | |
2133 | |
2134 In: vector x no shorter than X+X1. | |
2135 Out: vector z[X]. | |
2136 | |
2137 Returns pointer to z. z is created anew if z=0 is specifid on start. | |
2138 */ | |
2139 cdouble* SubVector(cdouble* z, cdouble* x, int X1, int X, MList* List) | |
2140 { | |
2141 if (!z){z=new cdouble[X]; if (List) List->Add(z, 1);} | |
2142 memcpy(z, &x[X1], sizeof(cdouble)*X); | |
2143 return z; | |
2144 }//SubVector | |
2145 //wrapper function | |
2146 cdouble* SubVector(cdouble* x, int X1, int X, MList* List) | |
2147 { | |
2148 return SubVector(0, x, X1, X, List); | |
2149 }//SubVector | |
2150 | |
2151 //--------------------------------------------------------------------------- | |
2152 /* | |
2153 function transpose: matrix transpose: A'->A | |
2154 | |
2155 In: matrix a[N][N] | |
2156 Out: matrix a[N][N] after transpose | |
2157 | |
2158 No return value. | |
2159 */ | |
2160 void transpose(int N, double** a) | |
2161 { | |
2162 double tmp; | |
2163 for (int i=1; i<N; i++) for (int j=0; j<i; j++) {tmp=a[i][j]; a[i][j]=a[j][i]; a[j][i]=tmp;} | |
2164 }//transpose | |
2165 //complex version | |
2166 void transpose(int N, cdouble** a) | |
2167 { | |
2168 cdouble tmp; | |
2169 for (int i=1; i<N; i++) for (int j=0; j<i; j++) {tmp=a[i][j]; a[i][j]=a[j][i]; a[j][i]=tmp;} | |
2170 }//transpose | |
2171 | |
2172 /* | |
2173 function transpose: matrix transpose: A'->Z | |
2174 | |
2175 In: matrix a[M][N] | |
2176 Out: matrix z[N][M] | |
2177 | |
2178 Returns pointer to z. z is created anew if z=0 is specifid on start. | |
2179 */ | |
2180 double** transpose(int N, int M, double** ta, double** a, MList* List) | |
2181 { | |
2182 if (!ta) {Allocate2(double, N, M, ta); if (List) List->Add(ta, 2);} | |
2183 for (int n=0; n<N; n++) for (int m=0; m<M; m++) ta[n][m]=a[m][n]; | |
2184 return ta; | |
2185 }//transpose | |
2186 //wrapper function | |
2187 double** transpose(int N, int M, double** a, MList* List) | |
2188 { | |
2189 return transpose(N, M, 0, a, List); | |
2190 }//transpose | |
2191 | |
2192 //--------------------------------------------------------------------------- | |
2193 /* | |
2194 function Unitary: given x & y s.t. |x|=|y|, find unitary matrix P s.t. Px=y. P is given in closed form | |
2195 as I-(x-y)(x-y)'/(x-y)'x | |
2196 | |
2197 In: vectors x[N] and y[N] | |
2198 Out: matrix P[N][N] | |
2199 | |
2200 Returns pointer to P. P is created anew if P=0 is specified on start. | |
2201 */ | |
2202 double** Unitary(int N, double** P, double* x, double* y, MList* List) | |
2203 { | |
2204 if (!P) {Allocate2(double, N, N, P); if (List) List->Add(P, 2);} | |
2205 int sizeN=sizeof(double)*N; | |
2206 for (int i=0; i<N; i++) {memset(P[i], 0, sizeN); P[i][i]=1;} | |
2207 | |
2208 double* w=MultiAdd(N, x, y, -1.0); //w=x-y | |
2209 double m=Inner(N, x, w); //m=(x-y)'x | |
2210 if (m!=0) | |
2211 { | |
2212 m=1.0/m; //m=1/(x-y)'x | |
2213 double* mw=Multiply(N, w, m); | |
2214 for (int i=0; i<N; i++) for (int j=0; j<N; j++) P[i][j]=P[i][j]-mw[i]*w[j]; | |
2215 delete[] mw; | |
2216 } | |
2217 delete[] w; | |
2218 return P; | |
2219 }//Unitary | |
2220 //complex version | |
2221 cdouble** Unitary(int N, cdouble** P, cdouble* x, cdouble* y, MList* List) | |
2222 { | |
2223 if (!P) {Allocate2(cdouble, N, N, P);} | |
2224 int sizeN=sizeof(cdouble)*N; | |
2225 for (int i=0; i<N; i++) {memset(P[i], 0, sizeN); P[i][i]=1;} | |
2226 | |
2227 cdouble *w=MultiAdd(N, x, y, -1); | |
2228 cdouble m=Inner(N, x, w); | |
2229 if (m!=0) | |
2230 { | |
2231 m=m.cinv(); | |
2232 cdouble *mw=Multiply(N, w, m); | |
2233 for (int i=0; i<N; i++) for (int j=0; j<N; j++) P[i][j]=P[i][j]-(mw[i]^w[j]), | |
2234 delete[] mw; | |
2235 } | |
2236 delete[] w; | |
2237 if (List) List->Add(P, 2); | |
2238 return P; | |
2239 }//Unitary | |
2240 //wrapper functions | |
2241 double** Unitary(int N, double* x, double* y, MList* List){return Unitary(N, 0, x, y, List);} | |
2242 cdouble** Unitary(int N, cdouble* x, cdouble* y, MList* List){return Unitary(N, 0, x, y, List);} | |
2243 | |
2244 | |
2245 |