NEURON
zsolve.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  Complex case
31 */
32 
33 static char rcsid[] = "zsolve.c,v 1.1 1997/12/04 17:56:17 hines Exp";
34 
35 #include <stdio.h>
36 #include "zmatrix2.h"
37 #include <math.h>
38 
39 
40 #define is_zero(z) ((z).re == 0.0 && (z).im == 0.0 )
41 
42 /* Most matrix factorisation routines are in-situ unless otherwise specified */
43 
44 /* zUsolve -- back substitution with optional over-riding diagonal
45  -- can be in-situ but doesn't need to be */
46 ZVEC *zUsolve(matrix,b,out,diag)
47 ZMAT *matrix;
48 ZVEC *b, *out;
49 double diag;
50 {
51  u_int dim /* , j */;
52  int i, i_lim;
53  complex **mat_ent, *mat_row, *b_ent, *out_ent, *out_col, sum;
54 
55  if ( matrix==ZMNULL || b==ZVNULL )
56  error(E_NULL,"zUsolve");
57  dim = min(matrix->m,matrix->n);
58  if ( b->dim < dim )
59  error(E_SIZES,"zUsolve");
60  if ( out==ZVNULL || out->dim < dim )
61  out = zv_resize(out,matrix->n);
62  mat_ent = matrix->me; b_ent = b->ve; out_ent = out->ve;
63 
64  for ( i=dim-1; i>=0; i-- )
65  if ( ! is_zero(b_ent[i]) )
66  break;
67  else
68  out_ent[i].re = out_ent[i].im = 0.0;
69  i_lim = i;
70 
71  for ( i = i_lim; i>=0; i-- )
72  {
73  sum = b_ent[i];
74  mat_row = &(mat_ent[i][i+1]);
75  out_col = &(out_ent[i+1]);
76  sum = zsub(sum,__zip__(mat_row,out_col,i_lim-i,Z_NOCONJ));
77  /******************************************************
78  for ( j=i+1; j<=i_lim; j++ )
79  sum -= mat_ent[i][j]*out_ent[j];
80  sum -= (*mat_row++)*(*out_col++);
81  ******************************************************/
82  if ( diag == 0.0 )
83  {
84  if ( is_zero(mat_ent[i][i]) )
85  error(E_SING,"zUsolve");
86  else
87  /* out_ent[i] = sum/mat_ent[i][i]; */
88  out_ent[i] = zdiv(sum,mat_ent[i][i]);
89  }
90  else
91  {
92  /* out_ent[i] = sum/diag; */
93  out_ent[i].re = sum.re / diag;
94  out_ent[i].im = sum.im / diag;
95  }
96  }
97 
98  return (out);
99 }
100 
101 /* zLsolve -- forward elimination with (optional) default diagonal value */
102 ZVEC *zLsolve(matrix,b,out,diag)
103 ZMAT *matrix;
104 ZVEC *b,*out;
105 double diag;
106 {
107  u_int dim, i, i_lim /* , j */;
108  complex **mat_ent, *mat_row, *b_ent, *out_ent, *out_col, sum;
109 
110  if ( matrix==ZMNULL || b==ZVNULL )
111  error(E_NULL,"zLsolve");
112  dim = min(matrix->m,matrix->n);
113  if ( b->dim < dim )
114  error(E_SIZES,"zLsolve");
115  if ( out==ZVNULL || out->dim < dim )
116  out = zv_resize(out,matrix->n);
117  mat_ent = matrix->me; b_ent = b->ve; out_ent = out->ve;
118 
119  for ( i=0; i<dim; i++ )
120  if ( ! is_zero(b_ent[i]) )
121  break;
122  else
123  out_ent[i].re = out_ent[i].im = 0.0;
124  i_lim = i;
125 
126  for ( i = i_lim; i<dim; i++ )
127  {
128  sum = b_ent[i];
129  mat_row = &(mat_ent[i][i_lim]);
130  out_col = &(out_ent[i_lim]);
131  sum = zsub(sum,__zip__(mat_row,out_col,(int)(i-i_lim),Z_NOCONJ));
132  /*****************************************************
133  for ( j=i_lim; j<i; j++ )
134  sum -= mat_ent[i][j]*out_ent[j];
135  sum -= (*mat_row++)*(*out_col++);
136  ******************************************************/
137  if ( diag == 0.0 )
138  {
139  if ( is_zero(mat_ent[i][i]) )
140  error(E_SING,"zLsolve");
141  else
142  out_ent[i] = zdiv(sum,mat_ent[i][i]);
143  }
144  else
145  {
146  out_ent[i].re = sum.re / diag;
147  out_ent[i].im = sum.im / diag;
148  }
149  }
150 
151  return (out);
152 }
153 
154 
155 /* zUAsolve -- forward elimination with (optional) default diagonal value
156  using UPPER triangular part of matrix */
157 ZVEC *zUAsolve(U,b,out,diag)
158 ZMAT *U;
159 ZVEC *b,*out;
160 double diag;
161 {
162  u_int dim, i, i_lim /* , j */;
163  complex **U_me, *b_ve, *out_ve, tmp;
164  Real invdiag;
165 
166  if ( ! U || ! b )
167  error(E_NULL,"zUAsolve");
168  dim = min(U->m,U->n);
169  if ( b->dim < dim )
170  error(E_SIZES,"zUAsolve");
171  out = zv_resize(out,U->n);
172  U_me = U->me; b_ve = b->ve; out_ve = out->ve;
173 
174  for ( i=0; i<dim; i++ )
175  if ( ! is_zero(b_ve[i]) )
176  break;
177  else
178  out_ve[i].re = out_ve[i].im = 0.0;
179  i_lim = i;
180  if ( b != out )
181  {
182  __zzero__(out_ve,out->dim);
183  /* MEM_COPY(&(b_ve[i_lim]),&(out_ve[i_lim]),
184  (dim-i_lim)*sizeof(complex)); */
185  MEMCOPY(&(b_ve[i_lim]),&(out_ve[i_lim]),dim-i_lim,complex);
186  }
187 
188  if ( diag == 0.0 )
189  {
190  for ( ; i<dim; i++ )
191  {
192  tmp = zconj(U_me[i][i]);
193  if ( is_zero(tmp) )
194  error(E_SING,"zUAsolve");
195  /* out_ve[i] /= tmp; */
196  out_ve[i] = zdiv(out_ve[i],tmp);
197  tmp.re = - out_ve[i].re;
198  tmp.im = - out_ve[i].im;
199  __zmltadd__(&(out_ve[i+1]),&(U_me[i][i+1]),tmp,dim-i-1,Z_CONJ);
200  }
201  }
202  else
203  {
204  invdiag = 1.0/diag;
205  for ( ; i<dim; i++ )
206  {
207  out_ve[i].re *= invdiag;
208  out_ve[i].im *= invdiag;
209  tmp.re = - out_ve[i].re;
210  tmp.im = - out_ve[i].im;
211  __zmltadd__(&(out_ve[i+1]),&(U_me[i][i+1]),tmp,dim-i-1,Z_CONJ);
212  }
213  }
214  return (out);
215 }
216 
217 /* zDsolve -- solves Dx=b where D is the diagonal of A -- may be in-situ */
219 ZMAT *A;
220 ZVEC *b,*x;
221 {
222  u_int dim, i;
223 
224  if ( ! A || ! b )
225  error(E_NULL,"zDsolve");
226  dim = min(A->m,A->n);
227  if ( b->dim < dim )
228  error(E_SIZES,"zDsolve");
229  x = zv_resize(x,A->n);
230 
231  dim = b->dim;
232  for ( i=0; i<dim; i++ )
233  if ( is_zero(A->me[i][i]) )
234  error(E_SING,"zDsolve");
235  else
236  x->ve[i] = zdiv(b->ve[i],A->me[i][i]);
237 
238  return (x);
239 }
240 
241 /* zLAsolve -- back substitution with optional over-riding diagonal
242  using the LOWER triangular part of matrix
243  -- can be in-situ but doesn't need to be */
244 ZVEC *zLAsolve(L,b,out,diag)
245 ZMAT *L;
246 ZVEC *b, *out;
247 double diag;
248 {
249  u_int dim;
250  int i, i_lim;
251  complex **L_me, *b_ve, *out_ve, tmp;
252  Real invdiag;
253 
254  if ( ! L || ! b )
255  error(E_NULL,"zLAsolve");
256  dim = min(L->m,L->n);
257  if ( b->dim < dim )
258  error(E_SIZES,"zLAsolve");
259  out = zv_resize(out,L->n);
260  L_me = L->me; b_ve = b->ve; out_ve = out->ve;
261 
262  for ( i=dim-1; i>=0; i-- )
263  if ( ! is_zero(b_ve[i]) )
264  break;
265  i_lim = i;
266 
267  if ( b != out )
268  {
269  __zzero__(out_ve,out->dim);
270  /* MEM_COPY(b_ve,out_ve,(i_lim+1)*sizeof(complex)); */
271  MEMCOPY(b_ve,out_ve,i_lim+1,complex);
272  }
273 
274  if ( diag == 0.0 )
275  {
276  for ( ; i>=0; i-- )
277  {
278  tmp = zconj(L_me[i][i]);
279  if ( is_zero(tmp) )
280  error(E_SING,"zLAsolve");
281  out_ve[i] = zdiv(out_ve[i],tmp);
282  tmp.re = - out_ve[i].re;
283  tmp.im = - out_ve[i].im;
284  __zmltadd__(out_ve,L_me[i],tmp,i,Z_CONJ);
285  }
286  }
287  else
288  {
289  invdiag = 1.0/diag;
290  for ( ; i>=0; i-- )
291  {
292  out_ve[i].re *= invdiag;
293  out_ve[i].im *= invdiag;
294  tmp.re = - out_ve[i].re;
295  tmp.im = - out_ve[i].im;
296  __zmltadd__(out_ve,L_me[i],tmp,i,Z_CONJ);
297  }
298  }
299 
300  return (out);
301 }
#define error(err_num, fn_name)
Definition: err.h:73
#define E_NULL
Definition: err.h:102
#define E_SING
Definition: err.h:98
#define E_SIZES
Definition: err.h:95
#define diag(s)
Definition: fmenu.cpp:192
#define Real
Definition: machine.h:189
uint32_t u_int
Definition: machine.h:38
#define MEMCOPY(from, to, n_items, type)
Definition: matrix.h:147
#define min(a, b)
Definition: matrix.h:157
#define i
Definition: md1redef.h:12
#define A(i)
Definition: multisplit.cpp:63
Definition: zmatrix.h:50
Definition: zmatrix.h:44
complex * ve
Definition: zmatrix.h:46
u_int dim
Definition: zmatrix.h:45
Real re
Definition: zmatrix.h:40
Real im
Definition: zmatrix.h:40
complex zdiv(complex z1, complex z2)
Definition: zfunc.c:166
complex zsub(complex z1, complex z2)
Definition: zfunc.c:107
complex zconj(complex z)
Definition: zfunc.c:233
void __zzero__(complex *zp, int len)
Definition: zmachine.c:160
complex __zip__(complex *zp1, complex *zp2, int len, int flag)
Definition: zmachine.c:56
void __zmltadd__(complex *zp1, complex *zp2, complex s, int len, int flag)
Definition: zmachine.c:87
#define Z_CONJ
Definition: zmatrix.h:60
ZVEC * zv_resize(ZVEC *x, int new_dim)
Definition: zmemory.c:362
#define ZVNULL
Definition: zmatrix.h:57
#define ZMNULL
Definition: zmatrix.h:58
#define Z_NOCONJ
Definition: zmatrix.h:61
ZVEC * zUAsolve(ZMAT *U, ZVEC *b, ZVEC *out, double diag)
Definition: zsolve.c:157
ZVEC * zUsolve(ZMAT *matrix, ZVEC *b, ZVEC *out, double diag)
Definition: zsolve.c:46
ZVEC * zLAsolve(ZMAT *L, ZVEC *b, ZVEC *out, double diag)
Definition: zsolve.c:244
#define is_zero(z)
Definition: zsolve.c:40
ZVEC * zLsolve(ZMAT *matrix, ZVEC *b, ZVEC *out, double diag)
Definition: zsolve.c:102
ZVEC * zDsolve(ZMAT *A, ZVEC *b, ZVEC *x)
Definition: zsolve.c:218
static char rcsid[]
Definition: zsolve.c:33