update.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  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. /* update.c 1.3 11/25/87 */
  28. static char rcsid[] = "$Id: update.c,v 1.2 1994/01/13 05:26:06 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. /* LDLupdate -- updates a CHolesky factorisation, replacing LDL' by
  35. MD~M' = LDL' + alpha.w.w' Note: w is overwritten
  36. Ref: Gill et al Math Comp 28, p516 Algorithm C1 */
  37. #ifndef ANSI_C
  38. MAT *LDLupdate(CHmat,w,alpha)
  39. MAT *CHmat;
  40. VEC *w;
  41. double alpha;
  42. #else
  43. MAT *LDLupdate(MAT *CHmat, VEC *w, double alpha)
  44. #endif
  45. {
  46. unsigned int i,j;
  47. Real diag,new_diag,beta,p;
  48. if ( CHmat==(MAT *)NULL || w==(VEC *)NULL )
  49. error(E_NULL,"LDLupdate");
  50. if ( CHmat->m != CHmat->n || w->dim != CHmat->m )
  51. error(E_SIZES,"LDLupdate");
  52. for ( j=0; j < w->dim; j++ )
  53. {
  54. p = w->ve[j];
  55. diag = CHmat->me[j][j];
  56. new_diag = CHmat->me[j][j] = diag + alpha*p*p;
  57. if ( new_diag <= 0.0 )
  58. error(E_POSDEF,"LDLupdate");
  59. beta = p*alpha/new_diag;
  60. alpha *= diag/new_diag;
  61. for ( i=j+1; i < w->dim; i++ )
  62. {
  63. w->ve[i] -= p*CHmat->me[i][j];
  64. CHmat->me[i][j] += beta*w->ve[i];
  65. CHmat->me[j][i] = CHmat->me[i][j];
  66. }
  67. }
  68. return (CHmat);
  69. }
  70. /* QRupdate -- updates QR factorisation in expanded form (seperate matrices)
  71. Finds Q+, R+ s.t. Q+.R+ = Q.(R+u.v') and Q+ orthogonal, R+ upper triang
  72. Ref: Golub & van Loan Matrix Computations pp437-443
  73. -- does not update Q if it is NULL */
  74. #ifndef ANSI_C
  75. MAT *QRupdate(Q,R,u,v)
  76. MAT *Q,*R;
  77. VEC *u,*v;
  78. #else
  79. MAT *QRupdate(MAT *Q, MAT *R, VEC *u, VEC *v)
  80. #endif
  81. {
  82. int i,j,k;
  83. Real c,s,temp;
  84. if ( ! R || ! u || ! v )
  85. error(E_NULL,"QRupdate");
  86. if ( ( Q && ( Q->m != Q->n || R->m != Q->n ) ) ||
  87. u->dim != R->m || v->dim != R->n )
  88. error(E_SIZES,"QRupdate");
  89. /* find largest k s.t. u[k] != 0 */
  90. for ( k=R->m-1; k>=0; k-- )
  91. if ( u->ve[k] != 0.0 )
  92. break;
  93. /* transform R+u.v' to Hessenberg form */
  94. for ( i=k-1; i>=0; i-- )
  95. {
  96. /* get Givens rotation */
  97. givens(u->ve[i],u->ve[i+1],&c,&s);
  98. rot_rows(R,i,i+1,c,s,R);
  99. if ( Q )
  100. rot_cols(Q,i,i+1,c,s,Q);
  101. rot_vec(u,i,i+1,c,s,u);
  102. }
  103. /* add into R */
  104. temp = u->ve[0];
  105. for ( j=0; j<R->n; j++ )
  106. R->me[0][j] += temp*v->ve[j];
  107. /* transform Hessenberg to upper triangular */
  108. for ( i=0; i<k; i++ )
  109. {
  110. givens(R->me[i][i],R->me[i+1][i],&c,&s);
  111. rot_rows(R,i,i+1,c,s,R);
  112. if ( Q )
  113. rot_cols(Q,i,i+1,c,s,Q);
  114. }
  115. return R;
  116. }