zhsehldr.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  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. Files for matrix computations
  26. Householder transformation file. Contains routines for calculating
  27. householder transformations, applying them to vectors and matrices
  28. by both row & column.
  29. Complex version
  30. */
  31. static char rcsid[] = "$Id: zhsehldr.c,v 1.2 1994/04/07 01:43:47 des Exp $";
  32. #include <stdio.h>
  33. #include <math.h>
  34. #include "zmatrix.h"
  35. #include "zmatrix2.h"
  36. #define is_zero(z) ((z).re == 0.0 && (z).im == 0.0)
  37. /* zhhvec -- calulates Householder vector to eliminate all entries after the
  38. i0 entry of the vector vec. It is returned as out. May be in-situ */
  39. ZVEC *zhhvec(vec,i0,beta,out,newval)
  40. ZVEC *vec,*out;
  41. int i0;
  42. Real *beta;
  43. complex *newval;
  44. {
  45. complex tmp;
  46. Real norm, abs_val;
  47. if ( i0 < 0 || i0 >= vec->dim )
  48. error(E_BOUNDS,"zhhvec");
  49. out = _zv_copy(vec,out,i0);
  50. tmp = _zin_prod(out,out,i0,Z_CONJ);
  51. if ( tmp.re <= 0.0 )
  52. {
  53. *beta = 0.0;
  54. *newval = out->ve[i0];
  55. return (out);
  56. }
  57. norm = sqrt(tmp.re);
  58. abs_val = zabs(out->ve[i0]);
  59. *beta = 1.0/(norm * (norm+abs_val));
  60. if ( abs_val == 0.0 )
  61. {
  62. newval->re = norm;
  63. newval->im = 0.0;
  64. }
  65. else
  66. {
  67. abs_val = -norm / abs_val;
  68. newval->re = abs_val*out->ve[i0].re;
  69. newval->im = abs_val*out->ve[i0].im;
  70. } abs_val = -norm / abs_val;
  71. out->ve[i0].re -= newval->re;
  72. out->ve[i0].im -= newval->im;
  73. return (out);
  74. }
  75. /* zhhtrvec -- apply Householder transformation to vector -- may be in-situ */
  76. ZVEC *zhhtrvec(hh,beta,i0,in,out)
  77. ZVEC *hh,*in,*out; /* hh = Householder vector */
  78. int i0;
  79. double beta;
  80. {
  81. complex scale, tmp;
  82. /* unsigned int i; */
  83. if ( hh==ZVNULL || in==ZVNULL )
  84. error(E_NULL,"zhhtrvec");
  85. if ( in->dim != hh->dim )
  86. error(E_SIZES,"zhhtrvec");
  87. if ( i0 < 0 || i0 > in->dim )
  88. error(E_BOUNDS,"zhhvec");
  89. tmp = _zin_prod(hh,in,i0,Z_CONJ);
  90. scale.re = -beta*tmp.re;
  91. scale.im = -beta*tmp.im;
  92. out = zv_copy(in,out);
  93. __zmltadd__(&(out->ve[i0]),&(hh->ve[i0]),scale,
  94. (int)(in->dim-i0),Z_NOCONJ);
  95. /************************************************************
  96. for ( i=i0; i<in->dim; i++ )
  97. out->ve[i] = in->ve[i] - scale*hh->ve[i];
  98. ************************************************************/
  99. return (out);
  100. }
  101. /* zhhtrrows -- transform a matrix by a Householder vector by rows
  102. starting at row i0 from column j0
  103. -- in-situ
  104. -- that is, M(i0:m,j0:n) <- M(i0:m,j0:n)(I-beta.hh(j0:n).hh(j0:n)^T) */
  105. ZMAT *zhhtrrows(M,i0,j0,hh,beta)
  106. ZMAT *M;
  107. int i0, j0;
  108. ZVEC *hh;
  109. double beta;
  110. {
  111. complex ip, scale;
  112. int i /*, j */;
  113. if ( M==ZMNULL || hh==ZVNULL )
  114. error(E_NULL,"zhhtrrows");
  115. if ( M->n != hh->dim )
  116. error(E_RANGE,"zhhtrrows");
  117. if ( i0 < 0 || i0 > M->m || j0 < 0 || j0 > M->n )
  118. error(E_BOUNDS,"zhhtrrows");
  119. if ( beta == 0.0 ) return (M);
  120. /* for each row ... */
  121. for ( i = i0; i < M->m; i++ )
  122. { /* compute inner product */
  123. ip = __zip__(&(M->me[i][j0]),&(hh->ve[j0]),
  124. (int)(M->n-j0),Z_NOCONJ);
  125. /**************************************************
  126. ip = 0.0;
  127. for ( j = j0; j < M->n; j++ )
  128. ip += M->me[i][j]*hh->ve[j];
  129. **************************************************/
  130. scale.re = -beta*ip.re;
  131. scale.im = -beta*ip.im;
  132. /* if ( scale == 0.0 ) */
  133. if ( is_zero(scale) )
  134. continue;
  135. /* do operation */
  136. __zmltadd__(&(M->me[i][j0]),&(hh->ve[j0]),scale,
  137. (int)(M->n-j0),Z_CONJ);
  138. /**************************************************
  139. for ( j = j0; j < M->n; j++ )
  140. M->me[i][j] -= scale*hh->ve[j];
  141. **************************************************/
  142. }
  143. return (M);
  144. }
  145. /* zhhtrcols -- transform a matrix by a Householder vector by columns
  146. starting at row i0 from column j0
  147. -- that is, M(i0:m,j0:n) <- (I-beta.hh(i0:m).hh(i0:m)^T)M(i0:m,j0:n)
  148. -- in-situ
  149. -- calls _zhhtrcols() with the scratch vector w
  150. -- Meschach internal routines should call _zhhtrcols() to
  151. avoid excessive memory allocation/de-allocation
  152. */
  153. ZMAT *zhhtrcols(M,i0,j0,hh,beta)
  154. ZMAT *M;
  155. int i0, j0;
  156. ZVEC *hh;
  157. double beta;
  158. {
  159. /* Real ip, scale; */
  160. complex scale;
  161. int i /*, k */;
  162. STATIC ZVEC *w = ZVNULL;
  163. if ( M==ZMNULL || hh==ZVNULL )
  164. error(E_NULL,"zhhtrcols");
  165. if ( M->m != hh->dim )
  166. error(E_SIZES,"zhhtrcols");
  167. if ( i0 < 0 || i0 > M->m || j0 < 0 || j0 > M->n )
  168. error(E_BOUNDS,"zhhtrcols");
  169. if ( beta == 0.0 ) return (M);
  170. if ( ! w || w->dim < M->n )
  171. w = zv_resize(w,M->n);
  172. MEM_STAT_REG(w,TYPE_ZVEC);
  173. M = _zhhtrcols(M,i0,j0,hh,beta,w);
  174. #ifdef THREADSAFE
  175. ZV_FREE(w);
  176. #endif
  177. return M;
  178. }
  179. /* _zhhtrcols -- transform a matrix by a Householder vector by columns
  180. starting at row i0 from column j0
  181. -- that is, M(i0:m,j0:n) <- (I-beta.hh(i0:m).hh(i0:m)^T)M(i0:m,j0:n)
  182. -- in-situ
  183. -- scratch vector w passed as argument
  184. -- raises error if w == NULL */
  185. ZMAT *_zhhtrcols(M,i0,j0,hh,beta,w)
  186. ZMAT *M;
  187. int i0, j0;
  188. ZVEC *hh;
  189. double beta;
  190. ZVEC *w;
  191. {
  192. /* Real ip, scale; */
  193. complex scale;
  194. int i /*, k */;
  195. if ( M==ZMNULL || hh==ZVNULL )
  196. error(E_NULL,"zhhtrcols");
  197. if ( M->m != hh->dim )
  198. error(E_SIZES,"zhhtrcols");
  199. if ( i0 < 0 || i0 > M->m || j0 < 0 || j0 > M->n )
  200. error(E_BOUNDS,"zhhtrcols");
  201. if ( beta == 0.0 ) return (M);
  202. if ( w->dim < M->n )
  203. w = zv_resize(w,M->n);
  204. zv_zero(w);
  205. for ( i = i0; i < M->m; i++ )
  206. /* if ( hh->ve[i] != 0.0 ) */
  207. if ( ! is_zero(hh->ve[i]) )
  208. __zmltadd__(&(w->ve[j0]),&(M->me[i][j0]),hh->ve[i],
  209. (int)(M->n-j0),Z_CONJ);
  210. for ( i = i0; i < M->m; i++ )
  211. /* if ( hh->ve[i] != 0.0 ) */
  212. if ( ! is_zero(hh->ve[i]) )
  213. {
  214. scale.re = -beta*hh->ve[i].re;
  215. scale.im = -beta*hh->ve[i].im;
  216. __zmltadd__(&(M->me[i][j0]),&(w->ve[j0]),scale,
  217. (int)(M->n-j0),Z_CONJ);
  218. }
  219. return (M);
  220. }