zqrfctr.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548
  1. /**************************************************************************
  2. **
  3. ** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved.
  4. **
  5. ** Meschach Library
  6. **
  7. ** This Meschach Library is provided "as is" without any express
  8. ** or implied warranty of any kind with respect to this software.
  9. ** In particular the authors shall not be liable for any direct,
  10. ** indirect, special, incidental or consequential damages arising
  11. ** in any way from use of the software.
  12. **
  13. ** Everyone is granted permission to copy, modify and redistribute this
  14. ** Meschach Library, provided:
  15. ** 1. All copies contain this copyright notice.
  16. ** 2. All modified copies shall carry a notice stating who
  17. ** made the last modification and the date of such modification.
  18. ** 3. No charge is made for this software or works derived from it.
  19. ** This clause shall not be construed as constraining other software
  20. ** distributed on the same medium as this software, nor is a
  21. ** distribution fee considered a charge.
  22. **
  23. ***************************************************************************/
  24. /*
  25. This file contains the routines needed to perform QR factorisation
  26. of matrices, as well as Householder transformations.
  27. The internal "factored form" of a matrix A is not quite standard.
  28. The diagonal of A is replaced by the diagonal of R -- not by the 1st non-zero
  29. entries of the Householder vectors. The 1st non-zero entries are held in
  30. the diag parameter of QRfactor(). The reason for this non-standard
  31. representation is that it enables direct use of the Usolve() function
  32. rather than requiring that a seperate function be written just for this case.
  33. See, e.g., QRsolve() below for more details.
  34. Complex version
  35. */
  36. static char rcsid[] = "$Id: zqrfctr.c,v 1.1 1994/01/13 04:21:22 des Exp $";
  37. #include <stdio.h>
  38. #include <math.h>
  39. #include "zmatrix.h"
  40. #include "zmatrix2.h"
  41. #define is_zero(z) ((z).re == 0.0 && (z).im == 0.0)
  42. #define sign(x) ((x) > 0.0 ? 1 : ((x) < 0.0 ? -1 : 0 ))
  43. /* Note: The usual representation of a Householder transformation is taken
  44. to be:
  45. P = I - beta.u.u*
  46. where beta = 2/(u*.u) and u is called the Householder vector
  47. (u* is the conjugate transposed vector of u
  48. */
  49. /* zQRfactor -- forms the QR factorisation of A
  50. -- factorisation stored in compact form as described above
  51. (not quite standard format) */
  52. ZMAT *zQRfactor(A,diag)
  53. ZMAT *A;
  54. ZVEC *diag;
  55. {
  56. unsigned int k,limit;
  57. Real beta;
  58. STATIC ZVEC *tmp1=ZVNULL, *w=ZVNULL;
  59. if ( ! A || ! diag )
  60. error(E_NULL,"zQRfactor");
  61. limit = min(A->m,A->n);
  62. if ( diag->dim < limit )
  63. error(E_SIZES,"zQRfactor");
  64. tmp1 = zv_resize(tmp1,A->m);
  65. w = zv_resize(w, A->n);
  66. MEM_STAT_REG(tmp1,TYPE_ZVEC);
  67. MEM_STAT_REG(w, TYPE_ZVEC);
  68. for ( k=0; k<limit; k++ )
  69. {
  70. /* get H/holder vector for the k-th column */
  71. zget_col(A,k,tmp1);
  72. zhhvec(tmp1,k,&beta,tmp1,&A->me[k][k]);
  73. diag->ve[k] = tmp1->ve[k];
  74. /* apply H/holder vector to remaining columns */
  75. tracecatch(_zhhtrcols(A,k,k+1,tmp1,beta,w),"zQRfactor");
  76. }
  77. #ifdef THREADSAFE
  78. ZV_FREE(tmp1); ZV_FREE(w);
  79. #endif
  80. return (A);
  81. }
  82. /* zQRCPfactor -- forms the QR factorisation of A with column pivoting
  83. -- factorisation stored in compact form as described above
  84. ( not quite standard format ) */
  85. ZMAT *zQRCPfactor(A,diag,px)
  86. ZMAT *A;
  87. ZVEC *diag;
  88. PERM *px;
  89. {
  90. unsigned int i, i_max, j, k, limit;
  91. STATIC ZVEC *tmp1=ZVNULL, *tmp2=ZVNULL, *w=ZVNULL;
  92. STATIC VEC *gamma=VNULL;
  93. Real beta;
  94. Real maxgamma, sum, tmp;
  95. complex ztmp;
  96. if ( ! A || ! diag || ! px )
  97. error(E_NULL,"QRCPfactor");
  98. limit = min(A->m,A->n);
  99. if ( diag->dim < limit || px->size != A->n )
  100. error(E_SIZES,"QRCPfactor");
  101. tmp1 = zv_resize(tmp1,A->m);
  102. tmp2 = zv_resize(tmp2,A->m);
  103. gamma = v_resize(gamma,A->n);
  104. w = zv_resize(w,A->n);
  105. MEM_STAT_REG(tmp1,TYPE_ZVEC);
  106. MEM_STAT_REG(tmp2,TYPE_ZVEC);
  107. MEM_STAT_REG(gamma,TYPE_VEC);
  108. MEM_STAT_REG(w, TYPE_ZVEC);
  109. /* initialise gamma and px */
  110. for ( j=0; j<A->n; j++ )
  111. {
  112. px->pe[j] = j;
  113. sum = 0.0;
  114. for ( i=0; i<A->m; i++ )
  115. sum += square(A->me[i][j].re) + square(A->me[i][j].im);
  116. gamma->ve[j] = sum;
  117. }
  118. for ( k=0; k<limit; k++ )
  119. {
  120. /* find "best" column to use */
  121. i_max = k; maxgamma = gamma->ve[k];
  122. for ( i=k+1; i<A->n; i++ )
  123. /* Loop invariant:maxgamma=gamma[i_max]
  124. >=gamma[l];l=k,...,i-1 */
  125. if ( gamma->ve[i] > maxgamma )
  126. { maxgamma = gamma->ve[i]; i_max = i; }
  127. /* swap columns if necessary */
  128. if ( i_max != k )
  129. {
  130. /* swap gamma values */
  131. tmp = gamma->ve[k];
  132. gamma->ve[k] = gamma->ve[i_max];
  133. gamma->ve[i_max] = tmp;
  134. /* update column permutation */
  135. px_transp(px,k,i_max);
  136. /* swap columns of A */
  137. for ( i=0; i<A->m; i++ )
  138. {
  139. ztmp = A->me[i][k];
  140. A->me[i][k] = A->me[i][i_max];
  141. A->me[i][i_max] = ztmp;
  142. }
  143. }
  144. /* get H/holder vector for the k-th column */
  145. zget_col(A,k,tmp1);
  146. /* hhvec(tmp1,k,&beta->ve[k],tmp1,&A->me[k][k]); */
  147. zhhvec(tmp1,k,&beta,tmp1,&A->me[k][k]);
  148. diag->ve[k] = tmp1->ve[k];
  149. /* apply H/holder vector to remaining columns */
  150. _zhhtrcols(A,k,k+1,tmp1,beta,w);
  151. /* update gamma values */
  152. for ( j=k+1; j<A->n; j++ )
  153. gamma->ve[j] -= square(A->me[k][j].re)+square(A->me[k][j].im);
  154. }
  155. #ifdef THREADSAFE
  156. ZV_FREE(tmp1); ZV_FREE(tmp2); V_FREE(gamma); ZV_FREE(w);
  157. #endif
  158. return (A);
  159. }
  160. /* zQsolve -- solves Qx = b, Q is an orthogonal matrix stored in compact
  161. form a la QRfactor()
  162. -- may be in-situ */
  163. ZVEC *_zQsolve(QR,diag,b,x,tmp)
  164. ZMAT *QR;
  165. ZVEC *diag, *b, *x, *tmp;
  166. {
  167. unsigned int dynamic;
  168. int k, limit;
  169. Real beta, r_ii, tmp_val;
  170. limit = min(QR->m,QR->n);
  171. dynamic = FALSE;
  172. if ( ! QR || ! diag || ! b )
  173. error(E_NULL,"_zQsolve");
  174. if ( diag->dim < limit || b->dim != QR->m )
  175. error(E_SIZES,"_zQsolve");
  176. x = zv_resize(x,QR->m);
  177. if ( tmp == ZVNULL )
  178. dynamic = TRUE;
  179. tmp = zv_resize(tmp,QR->m);
  180. /* apply H/holder transforms in normal order */
  181. x = zv_copy(b,x);
  182. for ( k = 0 ; k < limit ; k++ )
  183. {
  184. zget_col(QR,k,tmp);
  185. r_ii = zabs(tmp->ve[k]);
  186. tmp->ve[k] = diag->ve[k];
  187. tmp_val = (r_ii*zabs(diag->ve[k]));
  188. beta = ( tmp_val == 0.0 ) ? 0.0 : 1.0/tmp_val;
  189. /* hhtrvec(tmp,beta->ve[k],k,x,x); */
  190. zhhtrvec(tmp,beta,k,x,x);
  191. }
  192. if ( dynamic )
  193. ZV_FREE(tmp);
  194. return (x);
  195. }
  196. /* zmakeQ -- constructs orthogonal matrix from Householder vectors stored in
  197. compact QR form */
  198. ZMAT *zmakeQ(QR,diag,Qout)
  199. ZMAT *QR,*Qout;
  200. ZVEC *diag;
  201. {
  202. STATIC ZVEC *tmp1=ZVNULL,*tmp2=ZVNULL;
  203. unsigned int i, limit;
  204. Real beta, r_ii, tmp_val;
  205. int j;
  206. limit = min(QR->m,QR->n);
  207. if ( ! QR || ! diag )
  208. error(E_NULL,"zmakeQ");
  209. if ( diag->dim < limit )
  210. error(E_SIZES,"zmakeQ");
  211. Qout = zm_resize(Qout,QR->m,QR->m);
  212. tmp1 = zv_resize(tmp1,QR->m); /* contains basis vec & columns of Q */
  213. tmp2 = zv_resize(tmp2,QR->m); /* contains H/holder vectors */
  214. MEM_STAT_REG(tmp1,TYPE_ZVEC);
  215. MEM_STAT_REG(tmp2,TYPE_ZVEC);
  216. for ( i=0; i<QR->m ; i++ )
  217. { /* get i-th column of Q */
  218. /* set up tmp1 as i-th basis vector */
  219. for ( j=0; j<QR->m ; j++ )
  220. tmp1->ve[j].re = tmp1->ve[j].im = 0.0;
  221. tmp1->ve[i].re = 1.0;
  222. /* apply H/h transforms in reverse order */
  223. for ( j=limit-1; j>=0; j-- )
  224. {
  225. zget_col(QR,j,tmp2);
  226. r_ii = zabs(tmp2->ve[j]);
  227. tmp2->ve[j] = diag->ve[j];
  228. tmp_val = (r_ii*zabs(diag->ve[j]));
  229. beta = ( tmp_val == 0.0 ) ? 0.0 : 1.0/tmp_val;
  230. /* hhtrvec(tmp2,beta->ve[j],j,tmp1,tmp1); */
  231. zhhtrvec(tmp2,beta,j,tmp1,tmp1);
  232. }
  233. /* insert into Q */
  234. zset_col(Qout,i,tmp1);
  235. }
  236. #ifdef THREADSAFE
  237. ZV_FREE(tmp1); ZV_FREE(tmp2);
  238. #endif
  239. return (Qout);
  240. }
  241. /* zmakeR -- constructs upper triangular matrix from QR (compact form)
  242. -- may be in-situ (all it does is zero the lower 1/2) */
  243. ZMAT *zmakeR(QR,Rout)
  244. ZMAT *QR,*Rout;
  245. {
  246. unsigned int i,j;
  247. if ( QR==ZMNULL )
  248. error(E_NULL,"zmakeR");
  249. Rout = zm_copy(QR,Rout);
  250. for ( i=1; i<QR->m; i++ )
  251. for ( j=0; j<QR->n && j<i; j++ )
  252. Rout->me[i][j].re = Rout->me[i][j].im = 0.0;
  253. return (Rout);
  254. }
  255. /* zQRsolve -- solves the system Q.R.x=b where Q & R are stored in compact form
  256. -- returns x, which is created if necessary */
  257. ZVEC *zQRsolve(QR,diag,b,x)
  258. ZMAT *QR;
  259. ZVEC *diag, *b, *x;
  260. {
  261. int limit;
  262. STATIC ZVEC *tmp = ZVNULL;
  263. if ( ! QR || ! diag || ! b )
  264. error(E_NULL,"zQRsolve");
  265. limit = min(QR->m,QR->n);
  266. if ( diag->dim < limit || b->dim != QR->m )
  267. error(E_SIZES,"zQRsolve");
  268. tmp = zv_resize(tmp,limit);
  269. MEM_STAT_REG(tmp,TYPE_ZVEC);
  270. x = zv_resize(x,QR->n);
  271. _zQsolve(QR,diag,b,x,tmp);
  272. x = zUsolve(QR,x,x,0.0);
  273. x = zv_resize(x,QR->n);
  274. #ifdef THREADSAFE
  275. ZV_FREE(tmp);
  276. #endif
  277. return x;
  278. }
  279. /* zQRAsolve -- solves the system (Q.R)*.x = b
  280. -- Q & R are stored in compact form
  281. -- returns x, which is created if necessary */
  282. ZVEC *zQRAsolve(QR,diag,b,x)
  283. ZMAT *QR;
  284. ZVEC *diag, *b, *x;
  285. {
  286. int j, limit;
  287. Real beta, r_ii, tmp_val;
  288. STATIC ZVEC *tmp = ZVNULL;
  289. if ( ! QR || ! diag || ! b )
  290. error(E_NULL,"zQRAsolve");
  291. limit = min(QR->m,QR->n);
  292. if ( diag->dim < limit || b->dim != QR->n )
  293. error(E_SIZES,"zQRAsolve");
  294. x = zv_resize(x,QR->m);
  295. x = zUAsolve(QR,b,x,0.0);
  296. x = zv_resize(x,QR->m);
  297. tmp = zv_resize(tmp,x->dim);
  298. MEM_STAT_REG(tmp,TYPE_ZVEC);
  299. /* printf("zQRAsolve: tmp->dim = %d, x->dim = %d\n", tmp->dim, x->dim); */
  300. /* apply H/h transforms in reverse order */
  301. for ( j=limit-1; j>=0; j-- )
  302. {
  303. zget_col(QR,j,tmp);
  304. tmp = zv_resize(tmp,QR->m);
  305. r_ii = zabs(tmp->ve[j]);
  306. tmp->ve[j] = diag->ve[j];
  307. tmp_val = (r_ii*zabs(diag->ve[j]));
  308. beta = ( tmp_val == 0.0 ) ? 0.0 : 1.0/tmp_val;
  309. zhhtrvec(tmp,beta,j,x,x);
  310. }
  311. #ifdef THREADSAFE
  312. ZV_FREE(tmp);
  313. #endif
  314. return x;
  315. }
  316. /* zQRCPsolve -- solves A.x = b where A is factored by QRCPfactor()
  317. -- assumes that A is in the compact factored form */
  318. ZVEC *zQRCPsolve(QR,diag,pivot,b,x)
  319. ZMAT *QR;
  320. ZVEC *diag;
  321. PERM *pivot;
  322. ZVEC *b, *x;
  323. {
  324. if ( ! QR || ! diag || ! pivot || ! b )
  325. error(E_NULL,"zQRCPsolve");
  326. if ( (QR->m > diag->dim && QR->n > diag->dim) || QR->n != pivot->size )
  327. error(E_SIZES,"zQRCPsolve");
  328. x = zQRsolve(QR,diag,b,x);
  329. x = pxinv_zvec(pivot,x,x);
  330. return x;
  331. }
  332. /* zUmlt -- compute out = upper_triang(U).x
  333. -- may be in situ */
  334. ZVEC *zUmlt(U,x,out)
  335. ZMAT *U;
  336. ZVEC *x, *out;
  337. {
  338. int i, limit;
  339. if ( U == ZMNULL || x == ZVNULL )
  340. error(E_NULL,"zUmlt");
  341. limit = min(U->m,U->n);
  342. if ( limit != x->dim )
  343. error(E_SIZES,"zUmlt");
  344. if ( out == ZVNULL || out->dim < limit )
  345. out = zv_resize(out,limit);
  346. for ( i = 0; i < limit; i++ )
  347. out->ve[i] = __zip__(&(x->ve[i]),&(U->me[i][i]),limit - i,Z_NOCONJ);
  348. return out;
  349. }
  350. /* zUAmlt -- returns out = upper_triang(U)^T.x */
  351. ZVEC *zUAmlt(U,x,out)
  352. ZMAT *U;
  353. ZVEC *x, *out;
  354. {
  355. /* complex sum; */
  356. complex tmp;
  357. int i, limit;
  358. if ( U == ZMNULL || x == ZVNULL )
  359. error(E_NULL,"zUAmlt");
  360. limit = min(U->m,U->n);
  361. if ( out == ZVNULL || out->dim < limit )
  362. out = zv_resize(out,limit);
  363. for ( i = limit-1; i >= 0; i-- )
  364. {
  365. tmp = x->ve[i];
  366. out->ve[i].re = out->ve[i].im = 0.0;
  367. __zmltadd__(&(out->ve[i]),&(U->me[i][i]),tmp,limit-i-1,Z_CONJ);
  368. }
  369. return out;
  370. }
  371. /* zQRcondest -- returns an estimate of the 2-norm condition number of the
  372. matrix factorised by QRfactor() or QRCPfactor()
  373. -- note that as Q does not affect the 2-norm condition number,
  374. it is not necessary to pass the diag, beta (or pivot) vectors
  375. -- generates a lower bound on the true condition number
  376. -- if the matrix is exactly singular, HUGE_VAL is returned
  377. -- note that QRcondest() is likely to be more reliable for
  378. matrices factored using QRCPfactor() */
  379. double zQRcondest(QR)
  380. ZMAT *QR;
  381. {
  382. STATIC ZVEC *y=ZVNULL;
  383. Real norm, norm1, norm2, tmp1, tmp2;
  384. complex sum, tmp;
  385. int i, j, limit;
  386. if ( QR == ZMNULL )
  387. error(E_NULL,"zQRcondest");
  388. limit = min(QR->m,QR->n);
  389. for ( i = 0; i < limit; i++ )
  390. /* if ( QR->me[i][i] == 0.0 ) */
  391. if ( is_zero(QR->me[i][i]) )
  392. return HUGE_VAL;
  393. y = zv_resize(y,limit);
  394. MEM_STAT_REG(y,TYPE_ZVEC);
  395. /* use the trick for getting a unit vector y with ||R.y||_inf small
  396. from the LU condition estimator */
  397. for ( i = 0; i < limit; i++ )
  398. {
  399. sum.re = sum.im = 0.0;
  400. for ( j = 0; j < i; j++ )
  401. /* sum -= QR->me[j][i]*y->ve[j]; */
  402. sum = zsub(sum,zmlt(QR->me[j][i],y->ve[j]));
  403. /* sum -= (sum < 0.0) ? 1.0 : -1.0; */
  404. norm1 = zabs(sum);
  405. if ( norm1 == 0.0 )
  406. sum.re = 1.0;
  407. else
  408. {
  409. sum.re += sum.re / norm1;
  410. sum.im += sum.im / norm1;
  411. }
  412. /* y->ve[i] = sum / QR->me[i][i]; */
  413. y->ve[i] = zdiv(sum,QR->me[i][i]);
  414. }
  415. zUAmlt(QR,y,y);
  416. /* now apply inverse power method to R*.R */
  417. for ( i = 0; i < 3; i++ )
  418. {
  419. tmp1 = zv_norm2(y);
  420. zv_mlt(zmake(1.0/tmp1,0.0),y,y);
  421. zUAsolve(QR,y,y,0.0);
  422. tmp2 = zv_norm2(y);
  423. zv_mlt(zmake(1.0/tmp2,0.0),y,y);
  424. zUsolve(QR,y,y,0.0);
  425. }
  426. /* now compute approximation for ||R^{-1}||_2 */
  427. norm1 = sqrt(tmp1)*sqrt(tmp2);
  428. /* now use complementary approach to compute approximation to ||R||_2 */
  429. for ( i = limit-1; i >= 0; i-- )
  430. {
  431. sum.re = sum.im = 0.0;
  432. for ( j = i+1; j < limit; j++ )
  433. sum = zadd(sum,zmlt(QR->me[i][j],y->ve[j]));
  434. if ( is_zero(QR->me[i][i]) )
  435. return HUGE_VAL;
  436. tmp = zdiv(sum,QR->me[i][i]);
  437. if ( is_zero(tmp) )
  438. {
  439. y->ve[i].re = 1.0;
  440. y->ve[i].im = 0.0;
  441. }
  442. else
  443. {
  444. norm = zabs(tmp);
  445. y->ve[i].re = sum.re / norm;
  446. y->ve[i].im = sum.im / norm;
  447. }
  448. /* y->ve[i] = (sum >= 0.0) ? 1.0 : -1.0; */
  449. /* y->ve[i] = (QR->me[i][i] >= 0.0) ? y->ve[i] : - y->ve[i]; */
  450. }
  451. /* now apply power method to R*.R */
  452. for ( i = 0; i < 3; i++ )
  453. {
  454. tmp1 = zv_norm2(y);
  455. zv_mlt(zmake(1.0/tmp1,0.0),y,y);
  456. zUmlt(QR,y,y);
  457. tmp2 = zv_norm2(y);
  458. zv_mlt(zmake(1.0/tmp2,0.0),y,y);
  459. zUAmlt(QR,y,y);
  460. }
  461. norm2 = sqrt(tmp1)*sqrt(tmp2);
  462. /* printf("QRcondest: norm1 = %g, norm2 = %g\n",norm1,norm2); */
  463. #ifdef THREADSAFE
  464. ZV_FREE(y);
  465. #endif
  466. return norm1*norm2;
  467. }