qrfactor.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583
  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. */
  35. static char rcsid[] = "$Id: qrfactor.c,v 1.5 1994/01/13 05:35:07 des Exp $";
  36. #include <stdio.h>
  37. #include <math.h>
  38. #include "matrix2.h"
  39. #define sign(x) ((x) > 0.0 ? 1 : ((x) < 0.0 ? -1 : 0 ))
  40. extern VEC *Usolve(); /* See matrix2.h */
  41. /* Note: The usual representation of a Householder transformation is taken
  42. to be:
  43. P = I - beta.u.uT
  44. where beta = 2/(uT.u) and u is called the Householder vector
  45. */
  46. /* QRfactor -- forms the QR factorisation of A -- factorisation stored in
  47. compact form as described above ( not quite standard format ) */
  48. #ifndef ANSI_C
  49. MAT *QRfactor(A,diag)
  50. MAT *A;
  51. VEC *diag;
  52. #else
  53. MAT *QRfactor(MAT *A, VEC *diag)
  54. #endif
  55. {
  56. unsigned int k,limit;
  57. Real beta;
  58. STATIC VEC *hh=VNULL, *w=VNULL;
  59. if ( ! A || ! diag )
  60. error(E_NULL,"QRfactor");
  61. limit = min(A->m,A->n);
  62. if ( diag->dim < limit )
  63. error(E_SIZES,"QRfactor");
  64. hh = v_resize(hh,A->m);
  65. w = v_resize(w, A->n);
  66. MEM_STAT_REG(hh,TYPE_VEC);
  67. MEM_STAT_REG(w, TYPE_VEC);
  68. for ( k=0; k<limit; k++ )
  69. {
  70. /* get H/holder vector for the k-th column */
  71. get_col(A,k,hh);
  72. /* hhvec(hh,k,&beta->ve[k],hh,&A->me[k][k]); */
  73. hhvec(hh,k,&beta,hh,&A->me[k][k]);
  74. diag->ve[k] = hh->ve[k];
  75. /* apply H/holder vector to remaining columns */
  76. /* hhtrcols(A,k,k+1,hh,beta->ve[k]); */
  77. _hhtrcols(A,k,k+1,hh,beta,w);
  78. }
  79. #ifdef THREADSAFE
  80. V_FREE(hh); V_FREE(w);
  81. #endif
  82. return (A);
  83. }
  84. /* QRCPfactor -- forms the QR factorisation of A with column pivoting
  85. -- factorisation stored in compact form as described above
  86. ( not quite standard format ) */
  87. #ifndef ANSI_C
  88. MAT *QRCPfactor(A,diag,px)
  89. MAT *A;
  90. VEC *diag;
  91. PERM *px;
  92. #else
  93. MAT *QRCPfactor(MAT *A, VEC *diag, PERM *px)
  94. #endif
  95. {
  96. unsigned int i, i_max, j, k, limit;
  97. STATIC VEC *gamma=VNULL, *tmp1=VNULL, *tmp2=VNULL, *w=VNULL;
  98. Real beta, maxgamma, sum, tmp;
  99. if ( ! A || ! diag || ! px )
  100. error(E_NULL,"QRCPfactor");
  101. limit = min(A->m,A->n);
  102. if ( diag->dim < limit || px->size != A->n )
  103. error(E_SIZES,"QRCPfactor");
  104. tmp1 = v_resize(tmp1,A->m);
  105. tmp2 = v_resize(tmp2,A->m);
  106. gamma = v_resize(gamma,A->n);
  107. w = v_resize(w, A->n);
  108. MEM_STAT_REG(tmp1,TYPE_VEC);
  109. MEM_STAT_REG(tmp2,TYPE_VEC);
  110. MEM_STAT_REG(gamma,TYPE_VEC);
  111. MEM_STAT_REG(w, TYPE_VEC);
  112. /* initialise gamma and px */
  113. for ( j=0; j<A->n; j++ )
  114. {
  115. px->pe[j] = j;
  116. sum = 0.0;
  117. for ( i=0; i<A->m; i++ )
  118. sum += square(A->me[i][j]);
  119. gamma->ve[j] = sum;
  120. }
  121. for ( k=0; k<limit; k++ )
  122. {
  123. /* find "best" column to use */
  124. i_max = k; maxgamma = gamma->ve[k];
  125. for ( i=k+1; i<A->n; i++ )
  126. /* Loop invariant:maxgamma=gamma[i_max]
  127. >=gamma[l];l=k,...,i-1 */
  128. if ( gamma->ve[i] > maxgamma )
  129. { maxgamma = gamma->ve[i]; i_max = i; }
  130. /* swap columns if necessary */
  131. if ( i_max != k )
  132. {
  133. /* swap gamma values */
  134. tmp = gamma->ve[k];
  135. gamma->ve[k] = gamma->ve[i_max];
  136. gamma->ve[i_max] = tmp;
  137. /* update column permutation */
  138. px_transp(px,k,i_max);
  139. /* swap columns of A */
  140. for ( i=0; i<A->m; i++ )
  141. {
  142. tmp = A->me[i][k];
  143. A->me[i][k] = A->me[i][i_max];
  144. A->me[i][i_max] = tmp;
  145. }
  146. }
  147. /* get H/holder vector for the k-th column */
  148. get_col(A,k,tmp1);
  149. /* hhvec(tmp1,k,&beta->ve[k],tmp1,&A->me[k][k]); */
  150. hhvec(tmp1,k,&beta,tmp1,&A->me[k][k]);
  151. diag->ve[k] = tmp1->ve[k];
  152. /* apply H/holder vector to remaining columns */
  153. /* hhtrcols(A,k,k+1,tmp1,beta->ve[k]); */
  154. _hhtrcols(A,k,k+1,tmp1,beta,w);
  155. /* update gamma values */
  156. for ( j=k+1; j<A->n; j++ )
  157. gamma->ve[j] -= square(A->me[k][j]);
  158. }
  159. #ifdef THREADSAFE
  160. V_FREE(gamma); V_FREE(tmp1); V_FREE(tmp2); V_FREE(w);
  161. #endif
  162. return (A);
  163. }
  164. /* Qsolve -- solves Qx = b, Q is an orthogonal matrix stored in compact
  165. form a la QRfactor() -- may be in-situ */
  166. #ifndef ANSI_C
  167. VEC *_Qsolve(QR,diag,b,x,tmp)
  168. MAT *QR;
  169. VEC *diag, *b, *x, *tmp;
  170. #else
  171. VEC *_Qsolve(const MAT *QR, const VEC *diag, const VEC *b,
  172. VEC *x, VEC *tmp)
  173. #endif
  174. {
  175. unsigned int dynamic;
  176. int k, limit;
  177. Real beta, r_ii, tmp_val;
  178. limit = min(QR->m,QR->n);
  179. dynamic = FALSE;
  180. if ( ! QR || ! diag || ! b )
  181. error(E_NULL,"_Qsolve");
  182. if ( diag->dim < limit || b->dim != QR->m )
  183. error(E_SIZES,"_Qsolve");
  184. x = v_resize(x,QR->m);
  185. if ( tmp == VNULL )
  186. dynamic = TRUE;
  187. tmp = v_resize(tmp,QR->m);
  188. /* apply H/holder transforms in normal order */
  189. x = v_copy(b,x);
  190. for ( k = 0 ; k < limit ; k++ )
  191. {
  192. get_col(QR,k,tmp);
  193. r_ii = fabs(tmp->ve[k]);
  194. tmp->ve[k] = diag->ve[k];
  195. tmp_val = (r_ii*fabs(diag->ve[k]));
  196. beta = ( tmp_val == 0.0 ) ? 0.0 : 1.0/tmp_val;
  197. /* hhtrvec(tmp,beta->ve[k],k,x,x); */
  198. hhtrvec(tmp,beta,k,x,x);
  199. }
  200. if ( dynamic )
  201. V_FREE(tmp);
  202. return (x);
  203. }
  204. /* makeQ -- constructs orthogonal matrix from Householder vectors stored in
  205. compact QR form */
  206. #ifndef ANSI_C
  207. MAT *makeQ(QR,diag,Qout)
  208. MAT *QR,*Qout;
  209. VEC *diag;
  210. #else
  211. MAT *makeQ(const MAT *QR,const VEC *diag, MAT *Qout)
  212. #endif
  213. {
  214. STATIC VEC *tmp1=VNULL,*tmp2=VNULL;
  215. unsigned int i, limit;
  216. Real beta, r_ii, tmp_val;
  217. int j;
  218. limit = min(QR->m,QR->n);
  219. if ( ! QR || ! diag )
  220. error(E_NULL,"makeQ");
  221. if ( diag->dim < limit )
  222. error(E_SIZES,"makeQ");
  223. if ( Qout==(MAT *)NULL || Qout->m < QR->m || Qout->n < QR->m )
  224. Qout = m_get(QR->m,QR->m);
  225. tmp1 = v_resize(tmp1,QR->m); /* contains basis vec & columns of Q */
  226. tmp2 = v_resize(tmp2,QR->m); /* contains H/holder vectors */
  227. MEM_STAT_REG(tmp1,TYPE_VEC);
  228. MEM_STAT_REG(tmp2,TYPE_VEC);
  229. for ( i=0; i<QR->m ; i++ )
  230. { /* get i-th column of Q */
  231. /* set up tmp1 as i-th basis vector */
  232. for ( j=0; j<QR->m ; j++ )
  233. tmp1->ve[j] = 0.0;
  234. tmp1->ve[i] = 1.0;
  235. /* apply H/h transforms in reverse order */
  236. for ( j=limit-1; j>=0; j-- )
  237. {
  238. get_col(QR,j,tmp2);
  239. r_ii = fabs(tmp2->ve[j]);
  240. tmp2->ve[j] = diag->ve[j];
  241. tmp_val = (r_ii*fabs(diag->ve[j]));
  242. beta = ( tmp_val == 0.0 ) ? 0.0 : 1.0/tmp_val;
  243. /* hhtrvec(tmp2,beta->ve[j],j,tmp1,tmp1); */
  244. hhtrvec(tmp2,beta,j,tmp1,tmp1);
  245. }
  246. /* insert into Q */
  247. set_col(Qout,i,tmp1);
  248. }
  249. #ifdef THREADSAFE
  250. V_FREE(tmp1); V_FREE(tmp2);
  251. #endif
  252. return (Qout);
  253. }
  254. /* makeR -- constructs upper triangular matrix from QR (compact form)
  255. -- may be in-situ (all it does is zero the lower 1/2) */
  256. #ifndef ANSI_C
  257. MAT *makeR(QR,Rout)
  258. MAT *QR,*Rout;
  259. #else
  260. MAT *makeR(const MAT *QR, MAT *Rout)
  261. #endif
  262. {
  263. unsigned int i,j;
  264. if ( QR==MNULL )
  265. error(E_NULL,"makeR");
  266. Rout = m_copy(QR,Rout);
  267. for ( i=1; i<QR->m; i++ )
  268. for ( j=0; j<QR->n && j<i; j++ )
  269. Rout->me[i][j] = 0.0;
  270. return (Rout);
  271. }
  272. /* QRsolve -- solves the system Q.R.x=b where Q & R are stored in compact form
  273. -- returns x, which is created if necessary */
  274. #ifndef ANSI_C
  275. VEC *QRsolve(QR,diag,b,x)
  276. MAT *QR;
  277. VEC *diag /* , *beta */ , *b, *x;
  278. #else
  279. VEC *QRsolve(const MAT *QR, const VEC *diag, const VEC *b, VEC *x)
  280. #endif
  281. {
  282. int limit;
  283. STATIC VEC *tmp = VNULL;
  284. if ( ! QR || ! diag || ! b )
  285. error(E_NULL,"QRsolve");
  286. limit = min(QR->m,QR->n);
  287. if ( diag->dim < limit || b->dim != QR->m )
  288. error(E_SIZES,"QRsolve");
  289. tmp = v_resize(tmp,limit);
  290. MEM_STAT_REG(tmp,TYPE_VEC);
  291. x = v_resize(x,QR->n);
  292. _Qsolve(QR,diag,b,x,tmp);
  293. x = Usolve(QR,x,x,0.0);
  294. v_resize(x,QR->n);
  295. #ifdef THREADSAFE
  296. V_FREE(tmp);
  297. #endif
  298. return x;
  299. }
  300. /* QRCPsolve -- solves A.x = b where A is factored by QRCPfactor()
  301. -- assumes that A is in the compact factored form */
  302. #ifndef ANSI_C
  303. VEC *QRCPsolve(QR,diag,pivot,b,x)
  304. MAT *QR;
  305. VEC *diag;
  306. PERM *pivot;
  307. VEC *b, *x;
  308. #else
  309. VEC *QRCPsolve(const MAT *QR, const VEC *diag, PERM *pivot,
  310. const VEC *b, VEC *x)
  311. #endif
  312. {
  313. STATIC VEC *tmp=VNULL;
  314. if ( ! QR || ! diag || ! pivot || ! b )
  315. error(E_NULL,"QRCPsolve");
  316. if ( (QR->m > diag->dim &&QR->n > diag->dim) || QR->n != pivot->size )
  317. error(E_SIZES,"QRCPsolve");
  318. tmp = QRsolve(QR,diag,b,tmp);
  319. MEM_STAT_REG(tmp,TYPE_VEC);
  320. x = pxinv_vec(pivot,tmp,x);
  321. #ifdef THREADSAFE
  322. V_FREE(tmp);
  323. #endif
  324. return x;
  325. }
  326. /* Umlt -- compute out = upper_triang(U).x
  327. -- may be in situ */
  328. #ifndef ANSI_C
  329. static VEC *Umlt(U,x,out)
  330. MAT *U;
  331. VEC *x, *out;
  332. #else
  333. static VEC *Umlt(const MAT *U, const VEC *x, VEC *out)
  334. #endif
  335. {
  336. int i, limit;
  337. if ( U == MNULL || x == VNULL )
  338. error(E_NULL,"Umlt");
  339. limit = min(U->m,U->n);
  340. if ( limit != x->dim )
  341. error(E_SIZES,"Umlt");
  342. if ( out == VNULL || out->dim < limit )
  343. out = v_resize(out,limit);
  344. for ( i = 0; i < limit; i++ )
  345. out->ve[i] = __ip__(&(x->ve[i]),&(U->me[i][i]),limit - i);
  346. return out;
  347. }
  348. /* UTmlt -- returns out = upper_triang(U)^T.x */
  349. #ifndef ANSI_C
  350. static VEC *UTmlt(U,x,out)
  351. MAT *U;
  352. VEC *x, *out;
  353. #else
  354. static VEC *UTmlt(const MAT *U, const VEC *x, VEC *out)
  355. #endif
  356. {
  357. Real sum;
  358. int i, j, limit;
  359. if ( U == MNULL || x == VNULL )
  360. error(E_NULL,"UTmlt");
  361. limit = min(U->m,U->n);
  362. if ( out == VNULL || out->dim < limit )
  363. out = v_resize(out,limit);
  364. for ( i = limit-1; i >= 0; i-- )
  365. {
  366. sum = 0.0;
  367. for ( j = 0; j <= i; j++ )
  368. sum += U->me[j][i]*x->ve[j];
  369. out->ve[i] = sum;
  370. }
  371. return out;
  372. }
  373. /* QRTsolve -- solve A^T.sc = c where the QR factors of A are stored in
  374. compact form
  375. -- returns sc
  376. -- original due to Mike Osborne modified Wed 09th Dec 1992 */
  377. #ifndef ANSI_C
  378. VEC *QRTsolve(A,diag,c,sc)
  379. MAT *A;
  380. VEC *diag, *c, *sc;
  381. #else
  382. VEC *QRTsolve(const MAT *A, const VEC *diag, const VEC *c, VEC *sc)
  383. #endif
  384. {
  385. int i, j, k, n, p;
  386. Real beta, r_ii, s, tmp_val;
  387. if ( ! A || ! diag || ! c )
  388. error(E_NULL,"QRTsolve");
  389. if ( diag->dim < min(A->m,A->n) )
  390. error(E_SIZES,"QRTsolve");
  391. sc = v_resize(sc,A->m);
  392. n = sc->dim;
  393. p = c->dim;
  394. if ( n == p )
  395. k = p-2;
  396. else
  397. k = p-1;
  398. v_zero(sc);
  399. sc->ve[0] = c->ve[0]/A->me[0][0];
  400. if ( n == 1)
  401. return sc;
  402. if ( p > 1)
  403. {
  404. for ( i = 1; i < p; i++ )
  405. {
  406. s = 0.0;
  407. for ( j = 0; j < i; j++ )
  408. s += A->me[j][i]*sc->ve[j];
  409. if ( A->me[i][i] == 0.0 )
  410. error(E_SING,"QRTsolve");
  411. sc->ve[i]=(c->ve[i]-s)/A->me[i][i];
  412. }
  413. }
  414. for (i = k; i >= 0; i--)
  415. {
  416. s = diag->ve[i]*sc->ve[i];
  417. for ( j = i+1; j < n; j++ )
  418. s += A->me[j][i]*sc->ve[j];
  419. r_ii = fabs(A->me[i][i]);
  420. tmp_val = (r_ii*fabs(diag->ve[i]));
  421. beta = ( tmp_val == 0.0 ) ? 0.0 : 1.0/tmp_val;
  422. tmp_val = beta*s;
  423. sc->ve[i] -= tmp_val*diag->ve[i];
  424. for ( j = i+1; j < n; j++ )
  425. sc->ve[j] -= tmp_val*A->me[j][i];
  426. }
  427. return sc;
  428. }
  429. /* QRcondest -- returns an estimate of the 2-norm condition number of the
  430. matrix factorised by QRfactor() or QRCPfactor()
  431. -- note that as Q does not affect the 2-norm condition number,
  432. it is not necessary to pass the diag, beta (or pivot) vectors
  433. -- generates a lower bound on the true condition number
  434. -- if the matrix is exactly singular, HUGE_VAL is returned
  435. -- note that QRcondest() is likely to be more reliable for
  436. matrices factored using QRCPfactor() */
  437. #ifndef ANSI_C
  438. double QRcondest(QR)
  439. MAT *QR;
  440. #else
  441. double QRcondest(const MAT *QR)
  442. #endif
  443. {
  444. STATIC VEC *y=VNULL;
  445. Real norm1, norm2, sum, tmp1, tmp2;
  446. int i, j, limit;
  447. if ( QR == MNULL )
  448. error(E_NULL,"QRcondest");
  449. limit = min(QR->m,QR->n);
  450. for ( i = 0; i < limit; i++ )
  451. if ( QR->me[i][i] == 0.0 )
  452. return HUGE_VAL;
  453. y = v_resize(y,limit);
  454. MEM_STAT_REG(y,TYPE_VEC);
  455. /* use the trick for getting a unit vector y with ||R.y||_inf small
  456. from the LU condition estimator */
  457. for ( i = 0; i < limit; i++ )
  458. {
  459. sum = 0.0;
  460. for ( j = 0; j < i; j++ )
  461. sum -= QR->me[j][i]*y->ve[j];
  462. sum -= (sum < 0.0) ? 1.0 : -1.0;
  463. y->ve[i] = sum / QR->me[i][i];
  464. }
  465. UTmlt(QR,y,y);
  466. /* now apply inverse power method to R^T.R */
  467. for ( i = 0; i < 3; i++ )
  468. {
  469. tmp1 = v_norm2(y);
  470. sv_mlt(1/tmp1,y,y);
  471. UTsolve(QR,y,y,0.0);
  472. tmp2 = v_norm2(y);
  473. sv_mlt(1/v_norm2(y),y,y);
  474. Usolve(QR,y,y,0.0);
  475. }
  476. /* now compute approximation for ||R^{-1}||_2 */
  477. norm1 = sqrt(tmp1)*sqrt(tmp2);
  478. /* now use complementary approach to compute approximation to ||R||_2 */
  479. for ( i = limit-1; i >= 0; i-- )
  480. {
  481. sum = 0.0;
  482. for ( j = i+1; j < limit; j++ )
  483. sum += QR->me[i][j]*y->ve[j];
  484. y->ve[i] = (sum >= 0.0) ? 1.0 : -1.0;
  485. y->ve[i] = (QR->me[i][i] >= 0.0) ? y->ve[i] : - y->ve[i];
  486. }
  487. /* now apply power method to R^T.R */
  488. for ( i = 0; i < 3; i++ )
  489. {
  490. tmp1 = v_norm2(y);
  491. sv_mlt(1/tmp1,y,y);
  492. Umlt(QR,y,y);
  493. tmp2 = v_norm2(y);
  494. sv_mlt(1/tmp2,y,y);
  495. UTmlt(QR,y,y);
  496. }
  497. norm2 = sqrt(tmp1)*sqrt(tmp2);
  498. /* printf("QRcondest: norm1 = %g, norm2 = %g\n",norm1,norm2); */
  499. #ifdef THREADSAFE
  500. V_FREE(y);
  501. #endif
  502. return norm1*norm2;
  503. }