zsolve.c 7.4 KB

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