chfactor.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  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. /* CHfactor.c 1.2 11/25/87 */
  28. static char rcsid[] = "$Id: chfactor.c,v 1.2 1994/01/13 05:36:36 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. /* CHfactor -- Cholesky L.L' factorisation of A in-situ */
  35. #ifndef ANSI_C
  36. MAT *CHfactor(A)
  37. MAT *A;
  38. #else
  39. MAT *CHfactor(MAT *A)
  40. #endif
  41. {
  42. unsigned int i, j, k, n;
  43. Real **A_ent, *A_piv, *A_row, sum, tmp;
  44. if ( A==(MAT *)NULL )
  45. error(E_NULL,"CHfactor");
  46. if ( A->m != A->n )
  47. error(E_SQUARE,"CHfactor");
  48. n = A->n; A_ent = A->me;
  49. for ( k=0; k<n; k++ )
  50. {
  51. /* do diagonal element */
  52. sum = A_ent[k][k];
  53. A_piv = A_ent[k];
  54. for ( j=0; j<k; j++ )
  55. {
  56. /* tmp = A_ent[k][j]; */
  57. tmp = *A_piv++;
  58. sum -= tmp*tmp;
  59. }
  60. if ( sum <= 0.0 )
  61. error(E_POSDEF,"CHfactor");
  62. A_ent[k][k] = sqrt(sum);
  63. /* set values of column k */
  64. for ( i=k+1; i<n; i++ )
  65. {
  66. sum = A_ent[i][k];
  67. A_piv = A_ent[k];
  68. A_row = A_ent[i];
  69. sum -= __ip__(A_row,A_piv,(int)k);
  70. /************************************************
  71. for ( j=0; j<k; j++ )
  72. sum -= A_ent[i][j]*A_ent[k][j];
  73. sum -= (*A_row++)*(*A_piv++);
  74. ************************************************/
  75. A_ent[j][i] = A_ent[i][j] = sum/A_ent[k][k];
  76. }
  77. }
  78. return (A);
  79. }
  80. /* CHsolve -- given a CHolesky factorisation in A, solve A.x=b */
  81. #ifndef ANSI_C
  82. VEC *CHsolve(A,b,x)
  83. MAT *A;
  84. VEC *b,*x;
  85. #else
  86. VEC *CHsolve(const MAT *A, const VEC *b, VEC *x)
  87. #endif
  88. {
  89. if ( A==MNULL || b==VNULL )
  90. error(E_NULL,"CHsolve");
  91. if ( A->m != A->n || A->n != b->dim )
  92. error(E_SIZES,"CHsolve");
  93. x = v_resize(x,b->dim);
  94. Lsolve(A,b,x,0.0);
  95. Usolve(A,x,x,0.0);
  96. return (x);
  97. }
  98. /* LDLfactor -- L.D.L' factorisation of A in-situ */
  99. #ifndef ANSI_C
  100. MAT *LDLfactor(A)
  101. MAT *A;
  102. #else
  103. MAT *LDLfactor(MAT *A)
  104. #endif
  105. {
  106. unsigned int i, k, n, p;
  107. Real **A_ent;
  108. Real d, sum;
  109. STATIC VEC *r = VNULL;
  110. if ( ! A )
  111. error(E_NULL,"LDLfactor");
  112. if ( A->m != A->n )
  113. error(E_SQUARE,"LDLfactor");
  114. n = A->n; A_ent = A->me;
  115. r = v_resize(r,n);
  116. MEM_STAT_REG(r,TYPE_VEC);
  117. for ( k = 0; k < n; k++ )
  118. {
  119. sum = 0.0;
  120. for ( p = 0; p < k; p++ )
  121. {
  122. r->ve[p] = A_ent[p][p]*A_ent[k][p];
  123. sum += r->ve[p]*A_ent[k][p];
  124. }
  125. d = A_ent[k][k] -= sum;
  126. if ( d == 0.0 )
  127. error(E_SING,"LDLfactor");
  128. for ( i = k+1; i < n; i++ )
  129. {
  130. sum = __ip__(A_ent[i],r->ve,(int)k);
  131. /****************************************
  132. sum = 0.0;
  133. for ( p = 0; p < k; p++ )
  134. sum += A_ent[i][p]*r->ve[p];
  135. ****************************************/
  136. A_ent[i][k] = (A_ent[i][k] - sum)/d;
  137. }
  138. }
  139. #ifdef THREADSAFE
  140. V_FREE(r);
  141. #endif
  142. return A;
  143. }
  144. /* LDLsolve -- solves linear system A.x = b with A factored by LDLfactor()
  145. -- returns x, which is created if it is NULL on entry */
  146. #ifndef ANSI_C
  147. VEC *LDLsolve(LDL,b,x)
  148. MAT *LDL;
  149. VEC *b, *x;
  150. #else
  151. VEC *LDLsolve(const MAT *LDL, const VEC *b, VEC *x)
  152. #endif
  153. {
  154. if ( ! LDL || ! b )
  155. error(E_NULL,"LDLsolve");
  156. if ( LDL->m != LDL->n )
  157. error(E_SQUARE,"LDLsolve");
  158. if ( LDL->m != b->dim )
  159. error(E_SIZES,"LDLsolve");
  160. x = v_resize(x,b->dim);
  161. Lsolve(LDL,b,x,1.0);
  162. Dsolve(LDL,x,x);
  163. LTsolve(LDL,x,x,1.0);
  164. return x;
  165. }
  166. /* MCHfactor -- Modified Cholesky L.L' factorisation of A in-situ */
  167. #ifndef ANSI_C
  168. MAT *MCHfactor(A,tol)
  169. MAT *A;
  170. double tol;
  171. #else
  172. MAT *MCHfactor(MAT *A, double tol)
  173. #endif
  174. {
  175. unsigned int i, j, k, n;
  176. Real **A_ent, *A_piv, *A_row, sum, tmp;
  177. if ( A==(MAT *)NULL )
  178. error(E_NULL,"MCHfactor");
  179. if ( A->m != A->n )
  180. error(E_SQUARE,"MCHfactor");
  181. if ( tol <= 0.0 )
  182. error(E_RANGE,"MCHfactor");
  183. n = A->n; A_ent = A->me;
  184. for ( k=0; k<n; k++ )
  185. {
  186. /* do diagonal element */
  187. sum = A_ent[k][k];
  188. A_piv = A_ent[k];
  189. for ( j=0; j<k; j++ )
  190. {
  191. /* tmp = A_ent[k][j]; */
  192. tmp = *A_piv++;
  193. sum -= tmp*tmp;
  194. }
  195. if ( sum <= tol )
  196. sum = tol;
  197. A_ent[k][k] = sqrt(sum);
  198. /* set values of column k */
  199. for ( i=k+1; i<n; i++ )
  200. {
  201. sum = A_ent[i][k];
  202. A_piv = A_ent[k];
  203. A_row = A_ent[i];
  204. sum -= __ip__(A_row,A_piv,(int)k);
  205. /************************************************
  206. for ( j=0; j<k; j++ )
  207. sum -= A_ent[i][j]*A_ent[k][j];
  208. sum -= (*A_row++)*(*A_piv++);
  209. ************************************************/
  210. A_ent[j][i] = A_ent[i][j] = sum/A_ent[k][k];
  211. }
  212. }
  213. return (A);
  214. }