zlufctr.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  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. Matrix factorisation routines to work with the other matrix files.
  26. Complex version
  27. */
  28. static char rcsid[] = "$Id: zlufctr.c,v 1.3 1996/08/20 20:07:09 stewart Exp $";
  29. #include <stdio.h>
  30. #include <math.h>
  31. #include "zmatrix.h"
  32. #include "zmatrix2.h"
  33. #define is_zero(z) ((z).re == 0.0 && (z).im == 0.0)
  34. /* Most matrix factorisation routines are in-situ unless otherwise specified */
  35. /* zLUfactor -- Gaussian elimination with scaled partial pivoting
  36. -- Note: returns LU matrix which is A */
  37. ZMAT *zLUfactor(A,pivot)
  38. ZMAT *A;
  39. PERM *pivot;
  40. {
  41. unsigned int i, j, m, n;
  42. int i_max, k, k_max;
  43. Real dtemp, max1;
  44. complex **A_v, *A_piv, *A_row, temp;
  45. STATIC VEC *scale = VNULL;
  46. if ( A==ZMNULL || pivot==PNULL )
  47. error(E_NULL,"zLUfactor");
  48. if ( pivot->size != A->m )
  49. error(E_SIZES,"zLUfactor");
  50. m = A->m; n = A->n;
  51. scale = v_resize(scale,A->m);
  52. MEM_STAT_REG(scale,TYPE_VEC);
  53. A_v = A->me;
  54. /* initialise pivot with identity permutation */
  55. for ( i=0; i<m; i++ )
  56. pivot->pe[i] = i;
  57. /* set scale parameters */
  58. for ( i=0; i<m; i++ )
  59. {
  60. max1 = 0.0;
  61. for ( j=0; j<n; j++ )
  62. {
  63. dtemp = zabs(A_v[i][j]);
  64. max1 = max(max1,dtemp);
  65. }
  66. scale->ve[i] = max1;
  67. }
  68. /* main loop */
  69. k_max = min(m,n)-1;
  70. for ( k=0; k<k_max; k++ )
  71. {
  72. /* find best pivot row */
  73. max1 = 0.0; i_max = -1;
  74. for ( i=k; i<m; i++ )
  75. if ( scale->ve[i] > 0.0 )
  76. {
  77. dtemp = zabs(A_v[i][k])/scale->ve[i];
  78. if ( dtemp > max1 )
  79. { max1 = dtemp; i_max = i; }
  80. }
  81. /* if no pivot then ignore column k... */
  82. if ( i_max == -1 )
  83. continue;
  84. /* do we pivot ? */
  85. if ( i_max != k ) /* yes we do... */
  86. {
  87. px_transp(pivot,i_max,k);
  88. for ( j=0; j<n; j++ )
  89. {
  90. temp = A_v[i_max][j];
  91. A_v[i_max][j] = A_v[k][j];
  92. A_v[k][j] = temp;
  93. }
  94. }
  95. /* row operations */
  96. for ( i=k+1; i<m; i++ ) /* for each row do... */
  97. { /* Note: divide by zero should never happen */
  98. temp = A_v[i][k] = zdiv(A_v[i][k],A_v[k][k]);
  99. A_piv = &(A_v[k][k+1]);
  100. A_row = &(A_v[i][k+1]);
  101. temp.re = - temp.re;
  102. temp.im = - temp.im;
  103. if ( k+1 < n )
  104. __zmltadd__(A_row,A_piv,temp,(int)(n-(k+1)),Z_NOCONJ);
  105. /*********************************************
  106. for ( j=k+1; j<n; j++ )
  107. A_v[i][j] -= temp*A_v[k][j];
  108. (*A_row++) -= temp*(*A_piv++);
  109. *********************************************/
  110. }
  111. }
  112. #ifdef THREADSAFE
  113. V_FREE(scale);
  114. #endif
  115. return A;
  116. }
  117. /* zLUsolve -- given an LU factorisation in A, solve Ax=b */
  118. ZVEC *zLUsolve(A,pivot,b,x)
  119. ZMAT *A;
  120. PERM *pivot;
  121. ZVEC *b,*x;
  122. {
  123. if ( A==ZMNULL || b==ZVNULL || pivot==PNULL )
  124. error(E_NULL,"zLUsolve");
  125. if ( A->m != A->n || A->n != b->dim )
  126. error(E_SIZES,"zLUsolve");
  127. x = px_zvec(pivot,b,x); /* x := P.b */
  128. zLsolve(A,x,x,1.0); /* implicit diagonal = 1 */
  129. zUsolve(A,x,x,0.0); /* explicit diagonal */
  130. return (x);
  131. }
  132. /* zLUAsolve -- given an LU factorisation in A, solve A^*.x=b */
  133. ZVEC *zLUAsolve(LU,pivot,b,x)
  134. ZMAT *LU;
  135. PERM *pivot;
  136. ZVEC *b,*x;
  137. {
  138. if ( ! LU || ! b || ! pivot )
  139. error(E_NULL,"zLUAsolve");
  140. if ( LU->m != LU->n || LU->n != b->dim )
  141. error(E_SIZES,"zLUAsolve");
  142. x = zv_copy(b,x);
  143. zUAsolve(LU,x,x,0.0); /* explicit diagonal */
  144. zLAsolve(LU,x,x,1.0); /* implicit diagonal = 1 */
  145. pxinv_zvec(pivot,x,x); /* x := P^*.x */
  146. return (x);
  147. }
  148. /* zm_inverse -- returns inverse of A, provided A is not too rank deficient
  149. -- uses LU factorisation */
  150. ZMAT *zm_inverse(A,out)
  151. ZMAT *A, *out;
  152. {
  153. int i;
  154. STATIC ZVEC *tmp=ZVNULL, *tmp2=ZVNULL;
  155. STATIC ZMAT *A_cp=ZMNULL;
  156. STATIC PERM *pivot=PNULL;
  157. if ( ! A )
  158. error(E_NULL,"zm_inverse");
  159. if ( A->m != A->n )
  160. error(E_SQUARE,"zm_inverse");
  161. if ( ! out || out->m < A->m || out->n < A->n )
  162. out = zm_resize(out,A->m,A->n);
  163. A_cp = zm_resize(A_cp,A->m,A->n);
  164. A_cp = zm_copy(A,A_cp);
  165. tmp = zv_resize(tmp,A->m);
  166. tmp2 = zv_resize(tmp2,A->m);
  167. pivot = px_resize(pivot,A->m);
  168. MEM_STAT_REG(A_cp,TYPE_ZMAT);
  169. MEM_STAT_REG(tmp, TYPE_ZVEC);
  170. MEM_STAT_REG(tmp2,TYPE_ZVEC);
  171. MEM_STAT_REG(pivot,TYPE_PERM);
  172. tracecatch(zLUfactor(A_cp,pivot),"zm_inverse");
  173. for ( i = 0; i < A->n; i++ )
  174. {
  175. zv_zero(tmp);
  176. tmp->ve[i].re = 1.0;
  177. tmp->ve[i].im = 0.0;
  178. tracecatch(zLUsolve(A_cp,pivot,tmp,tmp2),"zm_inverse");
  179. zset_col(out,i,tmp2);
  180. }
  181. #ifdef THREADSAFE
  182. ZV_FREE(tmp); ZV_FREE(tmp2);
  183. ZM_FREE(A_cp); PX_FREE(pivot);
  184. #endif
  185. return out;
  186. }
  187. /* zLUcondest -- returns an estimate of the condition number of LU given the
  188. LU factorisation in compact form */
  189. double zLUcondest(LU,pivot)
  190. ZMAT *LU;
  191. PERM *pivot;
  192. {
  193. STATIC ZVEC *y = ZVNULL, *z = ZVNULL;
  194. Real cond_est, L_norm, U_norm, norm, sn_inv;
  195. complex sum;
  196. int i, j, n;
  197. if ( ! LU || ! pivot )
  198. error(E_NULL,"zLUcondest");
  199. if ( LU->m != LU->n )
  200. error(E_SQUARE,"zLUcondest");
  201. if ( LU->n != pivot->size )
  202. error(E_SIZES,"zLUcondest");
  203. n = LU->n;
  204. y = zv_resize(y,n);
  205. z = zv_resize(z,n);
  206. MEM_STAT_REG(y,TYPE_ZVEC);
  207. MEM_STAT_REG(z,TYPE_ZVEC);
  208. cond_est = 0.0; /* should never be returned */
  209. for ( i = 0; i < n; i++ )
  210. {
  211. sum.re = 1.0;
  212. sum.im = 0.0;
  213. for ( j = 0; j < i; j++ )
  214. /* sum -= LU->me[j][i]*y->ve[j]; */
  215. sum = zsub(sum,zmlt(LU->me[j][i],y->ve[j]));
  216. /* sum -= (sum < 0.0) ? 1.0 : -1.0; */
  217. sn_inv = 1.0 / zabs(sum);
  218. sum.re += sum.re * sn_inv;
  219. sum.im += sum.im * sn_inv;
  220. if ( is_zero(LU->me[i][i]) )
  221. return HUGE_VAL;
  222. /* y->ve[i] = sum / LU->me[i][i]; */
  223. y->ve[i] = zdiv(sum,LU->me[i][i]);
  224. }
  225. zLAsolve(LU,y,y,1.0);
  226. zLUsolve(LU,pivot,y,z);
  227. /* now estimate norm of A (even though it is not directly available) */
  228. /* actually computes ||L||_inf.||U||_inf */
  229. U_norm = 0.0;
  230. for ( i = 0; i < n; i++ )
  231. {
  232. norm = 0.0;
  233. for ( j = i; j < n; j++ )
  234. norm += zabs(LU->me[i][j]);
  235. if ( norm > U_norm )
  236. U_norm = norm;
  237. }
  238. L_norm = 0.0;
  239. for ( i = 0; i < n; i++ )
  240. {
  241. norm = 1.0;
  242. for ( j = 0; j < i; j++ )
  243. norm += zabs(LU->me[i][j]);
  244. if ( norm > L_norm )
  245. L_norm = norm;
  246. }
  247. tracecatch(cond_est = U_norm*L_norm*zv_norm_inf(z)/zv_norm_inf(y),
  248. "zLUcondest");
  249. #ifdef THREADSAFE
  250. ZV_FREE(y); ZV_FREE(z);
  251. #endif
  252. return cond_est;
  253. }