solve.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  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. /* solve.c 1.2 11/25/87 */
  28. static char rcsid[] = "$Id: solve.c,v 1.3 1994/01/13 05:29:57 des Exp $";
  29. #include <stdio.h>
  30. #include <math.h>
  31. #include "matrix2.h"
  32. /* Most matrix factorisation routines are in-situ unless otherwise specified */
  33. /* Usolve -- back substitution with optional over-riding diagonal
  34. -- can be in-situ but doesn't need to be */
  35. #ifndef ANSI_C
  36. VEC *Usolve(matrix,b,out,diag)
  37. MAT *matrix;
  38. VEC *b, *out;
  39. double diag;
  40. #else
  41. VEC *Usolve(const MAT *matrix, const VEC *b, VEC *out, double diag)
  42. #endif
  43. {
  44. unsigned int dim /* , j */;
  45. int i, i_lim;
  46. Real **mat_ent, *mat_row, *b_ent, *out_ent, *out_col, sum, tiny;
  47. if ( matrix==MNULL || b==VNULL )
  48. error(E_NULL,"Usolve");
  49. dim = min(matrix->m,matrix->n);
  50. if ( b->dim < dim )
  51. error(E_SIZES,"Usolve");
  52. if ( out==VNULL || out->dim < dim )
  53. out = v_resize(out,matrix->n);
  54. mat_ent = matrix->me; b_ent = b->ve; out_ent = out->ve;
  55. tiny = 10.0/HUGE_VAL;
  56. for ( i=dim-1; i>=0; i-- )
  57. if ( b_ent[i] != 0.0 )
  58. break;
  59. else
  60. out_ent[i] = 0.0;
  61. i_lim = i;
  62. for ( ; i>=0; i-- )
  63. {
  64. sum = b_ent[i];
  65. mat_row = &(mat_ent[i][i+1]);
  66. out_col = &(out_ent[i+1]);
  67. sum -= __ip__(mat_row,out_col,i_lim-i);
  68. /******************************************************
  69. for ( j=i+1; j<=i_lim; j++ )
  70. sum -= mat_ent[i][j]*out_ent[j];
  71. sum -= (*mat_row++)*(*out_col++);
  72. ******************************************************/
  73. if ( diag==0.0 )
  74. {
  75. if ( fabs(mat_ent[i][i]) <= tiny*fabs(sum) )
  76. error(E_SING,"Usolve");
  77. else
  78. out_ent[i] = sum/mat_ent[i][i];
  79. }
  80. else
  81. out_ent[i] = sum/diag;
  82. }
  83. return (out);
  84. }
  85. /* Lsolve -- forward elimination with (optional) default diagonal value */
  86. #ifndef ANSI_C
  87. VEC *Lsolve(matrix,b,out,diag)
  88. MAT *matrix;
  89. VEC *b,*out;
  90. double diag;
  91. #else
  92. VEC *Lsolve(const MAT *matrix, const VEC *b, VEC *out, double diag)
  93. #endif
  94. {
  95. unsigned int dim, i, i_lim /* , j */;
  96. Real **mat_ent, *mat_row, *b_ent, *out_ent, *out_col, sum, tiny;
  97. if ( matrix==(MAT *)NULL || b==(VEC *)NULL )
  98. error(E_NULL,"Lsolve");
  99. dim = min(matrix->m,matrix->n);
  100. if ( b->dim < dim )
  101. error(E_SIZES,"Lsolve");
  102. if ( out==(VEC *)NULL || out->dim < dim )
  103. out = v_resize(out,matrix->n);
  104. mat_ent = matrix->me; b_ent = b->ve; out_ent = out->ve;
  105. for ( i=0; i<dim; i++ )
  106. if ( b_ent[i] != 0.0 )
  107. break;
  108. else
  109. out_ent[i] = 0.0;
  110. i_lim = i;
  111. tiny = 10.0/HUGE_VAL;
  112. for ( ; i<dim; i++ )
  113. {
  114. sum = b_ent[i];
  115. mat_row = &(mat_ent[i][i_lim]);
  116. out_col = &(out_ent[i_lim]);
  117. sum -= __ip__(mat_row,out_col,(int)(i-i_lim));
  118. /*****************************************************
  119. for ( j=i_lim; j<i; j++ )
  120. sum -= mat_ent[i][j]*out_ent[j];
  121. sum -= (*mat_row++)*(*out_col++);
  122. ******************************************************/
  123. if ( diag==0.0 )
  124. {
  125. if ( fabs(mat_ent[i][i]) <= tiny*fabs(sum) )
  126. error(E_SING,"Lsolve");
  127. else
  128. out_ent[i] = sum/mat_ent[i][i];
  129. }
  130. else
  131. out_ent[i] = sum/diag;
  132. }
  133. return (out);
  134. }
  135. /* UTsolve -- forward elimination with (optional) default diagonal value
  136. using UPPER triangular part of matrix */
  137. #ifndef ANSI_C
  138. VEC *UTsolve(U,b,out,diag)
  139. MAT *U;
  140. VEC *b,*out;
  141. double diag;
  142. #else
  143. VEC *UTsolve(const MAT *U, const VEC *b, VEC *out, double diag)
  144. #endif
  145. {
  146. unsigned int dim, i, i_lim;
  147. Real **U_me, *b_ve, *out_ve, tmp, invdiag, tiny;
  148. if ( ! U || ! b )
  149. error(E_NULL,"UTsolve");
  150. dim = min(U->m,U->n);
  151. if ( b->dim < dim )
  152. error(E_SIZES,"UTsolve");
  153. out = v_resize(out,U->n);
  154. U_me = U->me; b_ve = b->ve; out_ve = out->ve;
  155. tiny = 10.0/HUGE_VAL;
  156. for ( i=0; i<dim; i++ )
  157. if ( b_ve[i] != 0.0 )
  158. break;
  159. else
  160. out_ve[i] = 0.0;
  161. i_lim = i;
  162. if ( b != out )
  163. {
  164. __zero__(out_ve,out->dim);
  165. MEM_COPY(&(b_ve[i_lim]),&(out_ve[i_lim]),(dim-i_lim)*sizeof(Real));
  166. }
  167. if ( diag == 0.0 )
  168. {
  169. for ( ; i<dim; i++ )
  170. {
  171. tmp = U_me[i][i];
  172. if ( fabs(tmp) <= tiny*fabs(out_ve[i]) )
  173. error(E_SING,"UTsolve");
  174. out_ve[i] /= tmp;
  175. __mltadd__(&(out_ve[i+1]),&(U_me[i][i+1]),-out_ve[i],dim-i-1);
  176. }
  177. }
  178. else
  179. {
  180. invdiag = 1.0/diag;
  181. for ( ; i<dim; i++ )
  182. {
  183. out_ve[i] *= invdiag;
  184. __mltadd__(&(out_ve[i+1]),&(U_me[i][i+1]),-out_ve[i],dim-i-1);
  185. }
  186. }
  187. return (out);
  188. }
  189. /* Dsolve -- solves Dx=b where D is the diagonal of A -- may be in-situ */
  190. #ifndef ANSI_C
  191. VEC *Dsolve(A,b,x)
  192. MAT *A;
  193. VEC *b,*x;
  194. #else
  195. VEC *Dsolve(const MAT *A, const VEC *b, VEC *x)
  196. #endif
  197. {
  198. unsigned int dim, i;
  199. Real tiny;
  200. if ( ! A || ! b )
  201. error(E_NULL,"Dsolve");
  202. dim = min(A->m,A->n);
  203. if ( b->dim < dim )
  204. error(E_SIZES,"Dsolve");
  205. x = v_resize(x,A->n);
  206. tiny = 10.0/HUGE_VAL;
  207. dim = b->dim;
  208. for ( i=0; i<dim; i++ )
  209. if ( fabs(A->me[i][i]) <= tiny*fabs(b->ve[i]) )
  210. error(E_SING,"Dsolve");
  211. else
  212. x->ve[i] = b->ve[i]/A->me[i][i];
  213. return (x);
  214. }
  215. /* LTsolve -- back substitution with optional over-riding diagonal
  216. using the LOWER triangular part of matrix
  217. -- can be in-situ but doesn't need to be */
  218. #ifndef ANSI_C
  219. VEC *LTsolve(L,b,out,diag)
  220. MAT *L;
  221. VEC *b, *out;
  222. double diag;
  223. #else
  224. VEC *LTsolve(const MAT *L, const VEC *b, VEC *out, double diag)
  225. #endif
  226. {
  227. unsigned int dim;
  228. int i, i_lim;
  229. Real **L_me, *b_ve, *out_ve, tmp, invdiag, tiny;
  230. if ( ! L || ! b )
  231. error(E_NULL,"LTsolve");
  232. dim = min(L->m,L->n);
  233. if ( b->dim < dim )
  234. error(E_SIZES,"LTsolve");
  235. out = v_resize(out,L->n);
  236. L_me = L->me; b_ve = b->ve; out_ve = out->ve;
  237. tiny = 10.0/HUGE_VAL;
  238. for ( i=dim-1; i>=0; i-- )
  239. if ( b_ve[i] != 0.0 )
  240. break;
  241. i_lim = i;
  242. if ( b != out )
  243. {
  244. __zero__(out_ve,out->dim);
  245. MEM_COPY(b_ve,out_ve,(i_lim+1)*sizeof(Real));
  246. }
  247. if ( diag == 0.0 )
  248. {
  249. for ( ; i>=0; i-- )
  250. {
  251. tmp = L_me[i][i];
  252. if ( fabs(tmp) <= tiny*fabs(out_ve[i]) )
  253. error(E_SING,"LTsolve");
  254. out_ve[i] /= tmp;
  255. __mltadd__(out_ve,L_me[i],-out_ve[i],i);
  256. }
  257. }
  258. else
  259. {
  260. invdiag = 1.0/diag;
  261. for ( ; i>=0; i-- )
  262. {
  263. out_ve[i] *= invdiag;
  264. __mltadd__(out_ve,L_me[i],-out_ve[i],i);
  265. }
  266. }
  267. return (out);
  268. }