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