lufactor.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  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. */
  27. /* LUfactor.c 1.5 11/25/87 */
  28. static char rcsid[] = "$Id: lufactor.c,v 1.10 1995/05/16 17:26:44 des Exp $";
  29. #include <stdio.h>
  30. #include <math.h>
  31. #include "matrix.h"
  32. #include "matrix2.h"
  33. /* Most matrix factorisation routines are in-situ unless otherwise specified */
  34. /* LUfactor -- gaussian elimination with scaled partial pivoting
  35. -- Note: returns LU matrix which is A */
  36. #ifndef ANSI_C
  37. MAT *LUfactor(A,pivot)
  38. MAT *A;
  39. PERM *pivot;
  40. #else
  41. MAT *LUfactor(MAT *A, PERM *pivot)
  42. #endif
  43. {
  44. unsigned int i, j, m, n;
  45. int i_max, k, k_max;
  46. Real **A_v, *A_piv, *A_row;
  47. Real max1, temp, tiny;
  48. STATIC VEC *scale = VNULL;
  49. if ( A==(MAT *)NULL || pivot==(PERM *)NULL )
  50. error(E_NULL,"LUfactor");
  51. if ( pivot->size != A->m )
  52. error(E_SIZES,"LUfactor");
  53. m = A->m; n = A->n;
  54. scale = v_resize(scale,A->m);
  55. MEM_STAT_REG(scale,TYPE_VEC);
  56. A_v = A->me;
  57. tiny = 10.0/HUGE_VAL;
  58. /* initialise pivot with identity permutation */
  59. for ( i=0; i<m; i++ )
  60. pivot->pe[i] = i;
  61. /* set scale parameters */
  62. for ( i=0; i<m; i++ )
  63. {
  64. max1 = 0.0;
  65. for ( j=0; j<n; j++ )
  66. {
  67. temp = fabs(A_v[i][j]);
  68. max1 = max(max1,temp);
  69. }
  70. scale->ve[i] = max1;
  71. }
  72. /* main loop */
  73. k_max = min(m,n)-1;
  74. for ( k=0; k<k_max; k++ )
  75. {
  76. /* find best pivot row */
  77. max1 = 0.0; i_max = -1;
  78. for ( i=k; i<m; i++ )
  79. if ( fabs(scale->ve[i]) >= tiny*fabs(A_v[i][k]) )
  80. {
  81. temp = fabs(A_v[i][k])/scale->ve[i];
  82. if ( temp > max1 )
  83. { max1 = temp; i_max = i; }
  84. }
  85. /* if no pivot then ignore column k... */
  86. if ( i_max == -1 )
  87. {
  88. /* set pivot entry A[k][k] exactly to zero,
  89. rather than just "small" */
  90. A_v[k][k] = 0.0;
  91. continue;
  92. }
  93. /* do we pivot ? */
  94. if ( i_max != k ) /* yes we do... */
  95. {
  96. px_transp(pivot,i_max,k);
  97. for ( j=0; j<n; j++ )
  98. {
  99. temp = A_v[i_max][j];
  100. A_v[i_max][j] = A_v[k][j];
  101. A_v[k][j] = temp;
  102. }
  103. }
  104. /* row operations */
  105. for ( i=k+1; i<m; i++ ) /* for each row do... */
  106. { /* Note: divide by zero should never happen */
  107. temp = A_v[i][k] = A_v[i][k]/A_v[k][k];
  108. A_piv = &(A_v[k][k+1]);
  109. A_row = &(A_v[i][k+1]);
  110. if ( k+1 < n )
  111. __mltadd__(A_row,A_piv,-temp,(int)(n-(k+1)));
  112. /*********************************************
  113. for ( j=k+1; j<n; j++ )
  114. A_v[i][j] -= temp*A_v[k][j];
  115. (*A_row++) -= temp*(*A_piv++);
  116. *********************************************/
  117. }
  118. }
  119. #ifdef THREADSAFE
  120. V_FREE(scale);
  121. #endif
  122. return A;
  123. }
  124. /* LUsolve -- given an LU factorisation in A, solve Ax=b */
  125. #ifndef ANSI_C
  126. VEC *LUsolve(LU,pivot,b,x)
  127. MAT *LU;
  128. PERM *pivot;
  129. VEC *b,*x;
  130. #else
  131. VEC *LUsolve(const MAT *LU, PERM *pivot, const VEC *b, VEC *x)
  132. #endif
  133. {
  134. if ( ! LU || ! b || ! pivot )
  135. error(E_NULL,"LUsolve");
  136. if ( LU->m != LU->n || LU->n != b->dim )
  137. error(E_SIZES,"LUsolve");
  138. x = v_resize(x,b->dim);
  139. px_vec(pivot,b,x); /* x := P.b */
  140. Lsolve(LU,x,x,1.0); /* implicit diagonal = 1 */
  141. Usolve(LU,x,x,0.0); /* explicit diagonal */
  142. return (x);
  143. }
  144. /* LUTsolve -- given an LU factorisation in A, solve A^T.x=b */
  145. #ifndef ANSI_C
  146. VEC *LUTsolve(LU,pivot,b,x)
  147. MAT *LU;
  148. PERM *pivot;
  149. VEC *b,*x;
  150. #else
  151. VEC *LUTsolve(const MAT *LU, PERM *pivot, const VEC *b, VEC *x)
  152. #endif
  153. {
  154. if ( ! LU || ! b || ! pivot )
  155. error(E_NULL,"LUTsolve");
  156. if ( LU->m != LU->n || LU->n != b->dim )
  157. error(E_SIZES,"LUTsolve");
  158. x = v_copy(b,x);
  159. UTsolve(LU,x,x,0.0); /* explicit diagonal */
  160. LTsolve(LU,x,x,1.0); /* implicit diagonal = 1 */
  161. pxinv_vec(pivot,x,x); /* x := P^T.tmp */
  162. return (x);
  163. }
  164. /* m_inverse -- returns inverse of A, provided A is not too rank deficient
  165. -- uses LU factorisation */
  166. #ifndef ANSI_C
  167. MAT *m_inverse(A,out)
  168. MAT *A, *out;
  169. #else
  170. MAT *m_inverse(const MAT *A, MAT *out)
  171. #endif
  172. {
  173. int i;
  174. STATIC VEC *tmp = VNULL, *tmp2 = VNULL;
  175. STATIC MAT *A_cp = MNULL;
  176. STATIC PERM *pivot = PNULL;
  177. if ( ! A )
  178. error(E_NULL,"m_inverse");
  179. if ( A->m != A->n )
  180. error(E_SQUARE,"m_inverse");
  181. if ( ! out || out->m < A->m || out->n < A->n )
  182. out = m_resize(out,A->m,A->n);
  183. A_cp = m_resize(A_cp,A->m,A->n);
  184. A_cp = m_copy(A,A_cp);
  185. tmp = v_resize(tmp,A->m);
  186. tmp2 = v_resize(tmp2,A->m);
  187. pivot = px_resize(pivot,A->m);
  188. MEM_STAT_REG(A_cp,TYPE_MAT);
  189. MEM_STAT_REG(tmp, TYPE_VEC);
  190. MEM_STAT_REG(tmp2,TYPE_VEC);
  191. MEM_STAT_REG(pivot,TYPE_PERM);
  192. tracecatch(LUfactor(A_cp,pivot),"m_inverse");
  193. for ( i = 0; i < A->n; i++ )
  194. {
  195. v_zero(tmp);
  196. tmp->ve[i] = 1.0;
  197. tracecatch(LUsolve(A_cp,pivot,tmp,tmp2),"m_inverse");
  198. set_col(out,i,tmp2);
  199. }
  200. #ifdef THREADSAFE
  201. V_FREE(tmp); V_FREE(tmp2);
  202. M_FREE(A_cp); PX_FREE(pivot);
  203. #endif
  204. return out;
  205. }
  206. /* LUcondest -- returns an estimate of the condition number of LU given the
  207. LU factorisation in compact form */
  208. #ifndef ANSI_C
  209. double LUcondest(LU,pivot)
  210. MAT *LU;
  211. PERM *pivot;
  212. #else
  213. double LUcondest(const MAT *LU, PERM *pivot)
  214. #endif
  215. {
  216. STATIC VEC *y = VNULL, *z = VNULL;
  217. Real cond_est, L_norm, U_norm, sum, tiny;
  218. int i, j, n;
  219. if ( ! LU || ! pivot )
  220. error(E_NULL,"LUcondest");
  221. if ( LU->m != LU->n )
  222. error(E_SQUARE,"LUcondest");
  223. if ( LU->n != pivot->size )
  224. error(E_SIZES,"LUcondest");
  225. tiny = 10.0/HUGE_VAL;
  226. n = LU->n;
  227. y = v_resize(y,n);
  228. z = v_resize(z,n);
  229. MEM_STAT_REG(y,TYPE_VEC);
  230. MEM_STAT_REG(z,TYPE_VEC);
  231. for ( i = 0; i < n; i++ )
  232. {
  233. sum = 0.0;
  234. for ( j = 0; j < i; j++ )
  235. sum -= LU->me[j][i]*y->ve[j];
  236. sum -= (sum < 0.0) ? 1.0 : -1.0;
  237. if ( fabs(LU->me[i][i]) <= tiny*fabs(sum) )
  238. return HUGE_VAL;
  239. y->ve[i] = sum / LU->me[i][i];
  240. }
  241. catch(E_SING,
  242. LTsolve(LU,y,y,1.0);
  243. LUsolve(LU,pivot,y,z);
  244. ,
  245. return HUGE_VAL);
  246. /* now estimate norm of A (even though it is not directly available) */
  247. /* actually computes ||L||_inf.||U||_inf */
  248. U_norm = 0.0;
  249. for ( i = 0; i < n; i++ )
  250. {
  251. sum = 0.0;
  252. for ( j = i; j < n; j++ )
  253. sum += fabs(LU->me[i][j]);
  254. if ( sum > U_norm )
  255. U_norm = sum;
  256. }
  257. L_norm = 0.0;
  258. for ( i = 0; i < n; i++ )
  259. {
  260. sum = 1.0;
  261. for ( j = 0; j < i; j++ )
  262. sum += fabs(LU->me[i][j]);
  263. if ( sum > L_norm )
  264. L_norm = sum;
  265. }
  266. tracecatch(cond_est = U_norm*L_norm*v_norm_inf(z)/v_norm_inf(y),
  267. "LUcondest");
  268. #ifdef THREADSAFE
  269. V_FREE(y); V_FREE(z);
  270. #endif
  271. return cond_est;
  272. }