NEURON
chfactor.c
Go to the documentation of this file.
1 #include <../../nrnconf.h>
2 
3 /**************************************************************************
4 **
5 ** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved.
6 **
7 ** Meschach Library
8 **
9 ** This Meschach Library is provided "as is" without any express
10 ** or implied warranty of any kind with respect to this software.
11 ** In particular the authors shall not be liable for any direct,
12 ** indirect, special, incidental or consequential damages arising
13 ** in any way from use of the software.
14 **
15 ** Everyone is granted permission to copy, modify and redistribute this
16 ** Meschach Library, provided:
17 ** 1. All copies contain this copyright notice.
18 ** 2. All modified copies shall carry a notice stating who
19 ** made the last modification and the date of such modification.
20 ** 3. No charge is made for this software or works derived from it.
21 ** This clause shall not be construed as constraining other software
22 ** distributed on the same medium as this software, nor is a
23 ** distribution fee considered a charge.
24 **
25 ***************************************************************************/
26 
27 
28 /*
29  Matrix factorisation routines to work with the other matrix files.
30 */
31 
32 /* CHfactor.c 1.2 11/25/87 */
33 static char rcsid[] = "chfactor.c,v 1.1 1997/12/04 17:55:15 hines Exp";
34 
35 #include <stdio.h>
36 #include "matrix.h"
37 #include "matrix2.h"
38 #include <math.h>
39 
40 
41 /* Most matrix factorisation routines are in-situ unless otherwise specified */
42 
43 /* CHfactor -- Cholesky L.L' factorisation of A in-situ */
45 MAT *A;
46 {
47  u_int i, j, k, n;
48  Real **A_ent, *A_piv, *A_row, sum, tmp;
49 
50  if ( A==(MAT *)NULL )
51  error(E_NULL,"CHfactor");
52  if ( A->m != A->n )
53  error(E_SQUARE,"CHfactor");
54  n = A->n; A_ent = A->me;
55 
56  for ( k=0; k<n; k++ )
57  {
58  /* do diagonal element */
59  sum = A_ent[k][k];
60  A_piv = A_ent[k];
61  for ( j=0; j<k; j++ )
62  {
63  /* tmp = A_ent[k][j]; */
64  tmp = *A_piv++;
65  sum -= tmp*tmp;
66  }
67  if ( sum <= 0.0 )
68  error(E_POSDEF,"CHfactor");
69  A_ent[k][k] = sqrt(sum);
70 
71  /* set values of column k */
72  for ( i=k+1; i<n; i++ )
73  {
74  sum = A_ent[i][k];
75  A_piv = A_ent[k];
76  A_row = A_ent[i];
77  sum -= __ip__(A_row,A_piv,(int)k);
78  /************************************************
79  for ( j=0; j<k; j++ )
80  sum -= A_ent[i][j]*A_ent[k][j];
81  sum -= (*A_row++)*(*A_piv++);
82  ************************************************/
83  A_ent[j][i] = A_ent[i][j] = sum/A_ent[k][k];
84  }
85  }
86 
87  return (A);
88 }
89 
90 
91 /* CHsolve -- given a CHolesky factorisation in A, solve A.x=b */
92 VEC *CHsolve(A,b,x)
93 MAT *A;
94 VEC *b,*x;
95 {
96  if ( A==(MAT *)NULL || b==(VEC *)NULL )
97  error(E_NULL,"CHsolve");
98  if ( A->m != A->n || A->n != b->dim )
99  error(E_SIZES,"CHsolve");
100  x = v_resize(x,b->dim);
101  Lsolve(A,b,x,0.0);
102  Usolve(A,x,x,0.0);
103 
104  return (x);
105 }
106 
107 /* LDLfactor -- L.D.L' factorisation of A in-situ */
109 MAT *A;
110 {
111  u_int i, k, n, p;
112  Real **A_ent;
113  Real d, sum;
114  static VEC *r = VNULL;
115 
116  if ( ! A )
117  error(E_NULL,"LDLfactor");
118  if ( A->m != A->n )
119  error(E_SQUARE,"LDLfactor");
120  n = A->n; A_ent = A->me;
121  r = v_resize(r,n);
123 
124  for ( k = 0; k < n; k++ )
125  {
126  sum = 0.0;
127  for ( p = 0; p < k; p++ )
128  {
129  r->ve[p] = A_ent[p][p]*A_ent[k][p];
130  sum += r->ve[p]*A_ent[k][p];
131  }
132  d = A_ent[k][k] -= sum;
133 
134  if ( d == 0.0 )
135  error(E_SING,"LDLfactor");
136  for ( i = k+1; i < n; i++ )
137  {
138  sum = __ip__(A_ent[i],r->ve,(int)k);
139  /****************************************
140  sum = 0.0;
141  for ( p = 0; p < k; p++ )
142  sum += A_ent[i][p]*r->ve[p];
143  ****************************************/
144  A_ent[i][k] = (A_ent[i][k] - sum)/d;
145  }
146  }
147 
148  return A;
149 }
150 
151 VEC *LDLsolve(LDL,b,x)
152 MAT *LDL;
153 VEC *b, *x;
154 {
155  if ( ! LDL || ! b )
156  error(E_NULL,"LDLsolve");
157  if ( LDL->m != LDL->n )
158  error(E_SQUARE,"LDLsolve");
159  if ( LDL->m != b->dim )
160  error(E_SIZES,"LDLsolve");
161  x = v_resize(x,b->dim);
162 
163  Lsolve(LDL,b,x,1.0);
164  Dsolve(LDL,x,x);
165  LTsolve(LDL,x,x,1.0);
166 
167  return x;
168 }
169 
170 /* MCHfactor -- Modified Cholesky L.L' factorisation of A in-situ */
172 MAT *A;
173 double tol;
174 {
175  u_int i, j, k, n;
176  Real **A_ent, *A_piv, *A_row, sum, tmp;
177 
178  if ( A==(MAT *)NULL )
179  error(E_NULL,"MCHfactor");
180  if ( A->m != A->n )
181  error(E_SQUARE,"MCHfactor");
182  if ( tol <= 0.0 )
183  error(E_RANGE,"MCHfactor");
184  n = A->n; A_ent = A->me;
185 
186  for ( k=0; k<n; k++ )
187  {
188  /* do diagonal element */
189  sum = A_ent[k][k];
190  A_piv = A_ent[k];
191  for ( j=0; j<k; j++ )
192  {
193  /* tmp = A_ent[k][j]; */
194  tmp = *A_piv++;
195  sum -= tmp*tmp;
196  }
197  if ( sum <= tol )
198  sum = tol;
199  A_ent[k][k] = sqrt(sum);
200 
201  /* set values of column k */
202  for ( i=k+1; i<n; i++ )
203  {
204  sum = A_ent[i][k];
205  A_piv = A_ent[k];
206  A_row = A_ent[i];
207  sum -= __ip__(A_row,A_piv,(int)k);
208  /************************************************
209  for ( j=0; j<k; j++ )
210  sum -= A_ent[i][j]*A_ent[k][j];
211  sum -= (*A_row++)*(*A_piv++);
212  ************************************************/
213  A_ent[j][i] = A_ent[i][j] = sum/A_ent[k][k];
214  }
215  }
216 
217  return (A);
218 }
MAT * LDLfactor(MAT *A)
Definition: chfactor.c:108
MAT * MCHfactor(MAT *A, double tol)
Definition: chfactor.c:171
VEC * LDLsolve(MAT *LDL, VEC *b, VEC *x)
Definition: chfactor.c:151
VEC * CHsolve(MAT *A, VEC *b, VEC *x)
Definition: chfactor.c:92
MAT * CHfactor(MAT *A)
Definition: chfactor.c:44
static char rcsid[]
Definition: chfactor.c:33
#define E_SQUARE
Definition: err.h:103
#define error(err_num, fn_name)
Definition: err.h:73
#define E_RANGE
Definition: err.h:104
#define E_NULL
Definition: err.h:102
#define E_SING
Definition: err.h:98
#define E_SIZES
Definition: err.h:95
#define E_POSDEF
Definition: err.h:99
static Object ** v_resize(void *v)
Definition: ivocvect.cpp:1383
double __ip__(Real *dp1, Real *dp2, int len)
Definition: machine.c:40
#define Real
Definition: machine.h:189
uint32_t u_int
Definition: machine.h:38
VEC * LTsolve(MAT *A, VEC *b, VEC *x, double diag_val)
VEC * Lsolve(MAT *A, VEC *b, VEC *x, double diag_val)
VEC * Usolve(MAT *A, VEC *b, VEC *x, double diag_val)
VEC * Dsolve(MAT *A, VEC *b, VEC *x)
#define VNULL
Definition: matrix.h:631
#define i
Definition: md1redef.h:12
#define TYPE_VEC
Definition: meminfo.h:52
#define MEM_STAT_REG(var, type)
Definition: meminfo.h:133
sqrt
Definition: extdef.h:3
#define A(i)
Definition: multisplit.cpp:63
int const size_t const size_t n
Definition: nrngsl.h:11
size_t p
size_t j
static philox4x32_key_t k
Definition: nrnran123.cpp:11
#define NULL
Definition: sptree.h:16
Definition: matrix.h:73
Definition: matrix.h:67
u_int dim
Definition: matrix.h:68
Real * ve
Definition: matrix.h:69