hsehldr.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  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. */
  30. /* hsehldr.c 1.3 10/8/87 */
  31. static char rcsid[] = "$Id: hsehldr.c,v 1.2 1994/01/13 05:36:29 des Exp $";
  32. #include <stdio.h>
  33. #include <math.h>
  34. #include "matrix.h"
  35. #include "matrix2.h"
  36. /* hhvec -- calulates Householder vector to eliminate all entries after the
  37. i0 entry of the vector vec. It is returned as out. May be in-situ */
  38. #ifndef ANSI_C
  39. VEC *hhvec(vec,i0,beta,out,newval)
  40. VEC *vec,*out;
  41. unsigned int i0;
  42. Real *beta,*newval;
  43. #else
  44. VEC *hhvec(const VEC *vec, unsigned int i0, Real *beta,
  45. VEC *out, Real *newval)
  46. #endif
  47. {
  48. Real norm;
  49. out = _v_copy(vec,out,i0);
  50. norm = sqrt(_in_prod(out,out,i0));
  51. if ( norm <= 0.0 )
  52. {
  53. *beta = 0.0;
  54. return (out);
  55. }
  56. *beta = 1.0/(norm * (norm+fabs(out->ve[i0])));
  57. if ( out->ve[i0] > 0.0 )
  58. *newval = -norm;
  59. else
  60. *newval = norm;
  61. out->ve[i0] -= *newval;
  62. return (out);
  63. }
  64. /* hhtrvec -- apply Householder transformation to vector
  65. -- that is, out <- (I-beta.hh(i0:n).hh(i0:n)^T).in
  66. -- may be in-situ */
  67. #ifndef ANSI_C
  68. VEC *hhtrvec(hh,beta,i0,in,out)
  69. VEC *hh,*in,*out; /* hh = Householder vector */
  70. unsigned int i0;
  71. double beta;
  72. #else
  73. VEC *hhtrvec(const VEC *hh, double beta, unsigned int i0,
  74. const VEC *in, VEC *out)
  75. #endif
  76. {
  77. Real scale;
  78. /* unsigned int i; */
  79. if ( hh==VNULL || in==VNULL )
  80. error(E_NULL,"hhtrvec");
  81. if ( in->dim != hh->dim )
  82. error(E_SIZES,"hhtrvec");
  83. if ( i0 > in->dim )
  84. error(E_BOUNDS,"hhtrvec");
  85. scale = beta*_in_prod(hh,in,i0);
  86. out = v_copy(in,out);
  87. __mltadd__(&(out->ve[i0]),&(hh->ve[i0]),-scale,(int)(in->dim-i0));
  88. /************************************************************
  89. for ( i=i0; i<in->dim; i++ )
  90. out->ve[i] = in->ve[i] - scale*hh->ve[i];
  91. ************************************************************/
  92. return (out);
  93. }
  94. /* hhtrrows -- transform a matrix by a Householder vector by rows
  95. starting at row i0 from column j0 -- in-situ
  96. -- that is, M(i0:m,j0:n) <- M(i0:m,j0:n)(I-beta.hh(j0:n).hh(j0:n)^T) */
  97. #ifndef ANSI_C
  98. MAT *hhtrrows(M,i0,j0,hh,beta)
  99. MAT *M;
  100. unsigned int i0, j0;
  101. VEC *hh;
  102. double beta;
  103. #else
  104. MAT *hhtrrows(MAT *M, unsigned int i0, unsigned int j0,
  105. const VEC *hh, double beta)
  106. #endif
  107. {
  108. Real ip, scale;
  109. int i /*, j */;
  110. if ( M==MNULL || hh==VNULL )
  111. error(E_NULL,"hhtrrows");
  112. if ( M->n != hh->dim )
  113. error(E_RANGE,"hhtrrows");
  114. if ( i0 > M->m || j0 > M->n )
  115. error(E_BOUNDS,"hhtrrows");
  116. if ( beta == 0.0 ) return (M);
  117. /* for each row ... */
  118. for ( i = i0; i < M->m; i++ )
  119. { /* compute inner product */
  120. ip = __ip__(&(M->me[i][j0]),&(hh->ve[j0]),(int)(M->n-j0));
  121. /**************************************************
  122. ip = 0.0;
  123. for ( j = j0; j < M->n; j++ )
  124. ip += M->me[i][j]*hh->ve[j];
  125. **************************************************/
  126. scale = beta*ip;
  127. if ( scale == 0.0 )
  128. continue;
  129. /* do operation */
  130. __mltadd__(&(M->me[i][j0]),&(hh->ve[j0]),-scale,
  131. (int)(M->n-j0));
  132. /**************************************************
  133. for ( j = j0; j < M->n; j++ )
  134. M->me[i][j] -= scale*hh->ve[j];
  135. **************************************************/
  136. }
  137. return (M);
  138. }
  139. /* hhtrcols -- transform a matrix by a Householder vector by columns
  140. starting at row i0 from column j0
  141. -- that is, M(i0:m,j0:n) <- (I-beta.hh(i0:m).hh(i0:m)^T)M(i0:m,j0:n)
  142. -- in-situ
  143. -- calls _hhtrcols() with the scratch vector w
  144. -- Meschach internal routines should call _hhtrcols() to
  145. avoid excessive memory allocation/de-allocation
  146. */
  147. #ifndef ANSI_C
  148. MAT *hhtrcols(M,i0,j0,hh,beta)
  149. MAT *M;
  150. unsigned int i0, j0;
  151. VEC *hh;
  152. double beta;
  153. #else
  154. MAT *hhtrcols(MAT *M, unsigned int i0, unsigned int j0,
  155. const VEC *hh, double beta)
  156. #endif
  157. {
  158. STATIC VEC *w = VNULL;
  159. if ( M == MNULL || hh == VNULL || w == VNULL )
  160. error(E_NULL,"hhtrcols");
  161. if ( M->m != hh->dim )
  162. error(E_SIZES,"hhtrcols");
  163. if ( i0 > M->m || j0 > M->n )
  164. error(E_BOUNDS,"hhtrcols");
  165. if ( ! w || w->dim < M->n )
  166. w = v_resize(w,M->n);
  167. MEM_STAT_REG(w,TYPE_VEC);
  168. M = _hhtrcols(M,i0,j0,hh,beta,w);
  169. #ifdef THREADSAFE
  170. V_FREE(w);
  171. #endif
  172. return M;
  173. }
  174. /* _hhtrcols -- transform a matrix by a Householder vector by columns
  175. starting at row i0 from column j0
  176. -- that is, M(i0:m,j0:n) <- (I-beta.hh(i0:m).hh(i0:m)^T)M(i0:m,j0:n)
  177. -- in-situ
  178. -- scratch vector w passed as argument
  179. -- raises error if w == NULL
  180. */
  181. #ifndef ANSI_C
  182. MAT *_hhtrcols(M,i0,j0,hh,beta,w)
  183. MAT *M;
  184. unsigned int i0, j0;
  185. VEC *hh;
  186. double beta;
  187. VEC *w;
  188. #else
  189. MAT *_hhtrcols(MAT *M, unsigned int i0, unsigned int j0,
  190. const VEC *hh, double beta, VEC *w)
  191. #endif
  192. {
  193. /* Real ip, scale; */
  194. int i /*, k */;
  195. /* STATIC VEC *w = VNULL; */
  196. if ( M == MNULL || hh == VNULL || w == VNULL )
  197. error(E_NULL,"_hhtrcols");
  198. if ( M->m != hh->dim )
  199. error(E_SIZES,"_hhtrcols");
  200. if ( i0 > M->m || j0 > M->n )
  201. error(E_BOUNDS,"_hhtrcols");
  202. if ( beta == 0.0 ) return (M);
  203. if ( w->dim < M->n )
  204. w = v_resize(w,M->n);
  205. /* MEM_STAT_REG(w,TYPE_VEC); */
  206. v_zero(w);
  207. for ( i = i0; i < M->m; i++ )
  208. if ( hh->ve[i] != 0.0 )
  209. __mltadd__(&(w->ve[j0]),&(M->me[i][j0]),hh->ve[i],
  210. (int)(M->n-j0));
  211. for ( i = i0; i < M->m; i++ )
  212. if ( hh->ve[i] != 0.0 )
  213. __mltadd__(&(M->me[i][j0]),&(w->ve[j0]),-beta*hh->ve[i],
  214. (int)(M->n-j0));
  215. return (M);
  216. }