NEURON
zvecop.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 #include <stdio.h>
29 #include "matrix.h"
30 #include "zmatrix.h"
31 static char rcsid[] = "zvecop.c,v 1.1 1997/12/04 17:56:19 hines Exp";
32 
33 
34 
35 /* _zin_prod -- inner product of two vectors from i0 downwards
36  -- flag != 0 means compute sum_i a[i]*.b[i];
37  -- flag == 0 means compute sum_i a[i].b[i] */
38 complex _zin_prod(a,b,i0,flag)
39 ZVEC *a,*b;
40 u_int i0, flag;
41 {
42  u_int limit;
43 
44  if ( a==ZVNULL || b==ZVNULL )
45  error(E_NULL,"_zin_prod");
46  limit = min(a->dim,b->dim);
47  if ( i0 > limit )
48  error(E_BOUNDS,"_zin_prod");
49 
50  return __zip__(&(a->ve[i0]),&(b->ve[i0]),(int)(limit-i0),flag);
51 }
52 
53 /* zv_mlt -- scalar-vector multiply -- may be in-situ */
54 ZVEC *zv_mlt(scalar,vector,out)
55 complex scalar;
56 ZVEC *vector,*out;
57 {
58  /* u_int dim, i; */
59  /* complex *out_ve, *vec_ve; */
60 
61  if ( vector==ZVNULL )
62  error(E_NULL,"zv_mlt");
63  if ( out==ZVNULL || out->dim != vector->dim )
64  out = zv_resize(out,vector->dim);
65  if ( scalar.re == 0.0 && scalar.im == 0.0 )
66  return zv_zero(out);
67  if ( scalar.re == 1.0 && scalar.im == 0.0 )
68  return zv_copy(vector,out);
69 
70  __zmlt__(vector->ve,scalar,out->ve,(int)(vector->dim));
71 
72  return (out);
73 }
74 
75 /* zv_add -- vector addition -- may be in-situ */
76 ZVEC *zv_add(vec1,vec2,out)
77 ZVEC *vec1,*vec2,*out;
78 {
79  u_int dim;
80 
81  if ( vec1==ZVNULL || vec2==ZVNULL )
82  error(E_NULL,"zv_add");
83  if ( vec1->dim != vec2->dim )
84  error(E_SIZES,"zv_add");
85  if ( out==ZVNULL || out->dim != vec1->dim )
86  out = zv_resize(out,vec1->dim);
87  dim = vec1->dim;
88  __zadd__(vec1->ve,vec2->ve,out->ve,(int)dim);
89 
90  return (out);
91 }
92 
93 /* zv_mltadd -- scalar/vector multiplication and addition
94  -- out = v1 + scale.v2 */
95 ZVEC *zv_mltadd(v1,v2,scale,out)
96 ZVEC *v1,*v2,*out;
97 complex scale;
98 {
99  /* register u_int dim, i; */
100  /* complex *out_ve, *v1_ve, *v2_ve; */
101 
102  if ( v1==ZVNULL || v2==ZVNULL )
103  error(E_NULL,"zv_mltadd");
104  if ( v1->dim != v2->dim )
105  error(E_SIZES,"zv_mltadd");
106  if ( scale.re == 0.0 && scale.im == 0.0 )
107  return zv_copy(v1,out);
108  if ( scale.re == 1.0 && scale.im == 0.0 )
109  return zv_add(v1,v2,out);
110 
111  if ( v2 != out )
112  {
113  tracecatch(out = zv_copy(v1,out),"zv_mltadd");
114 
115  /* dim = v1->dim; */
116  __zmltadd__(out->ve,v2->ve,scale,(int)(v1->dim),0);
117  }
118  else
119  {
120  tracecatch(out = zv_mlt(scale,v2,out),"zv_mltadd");
121  out = zv_add(v1,out,out);
122  }
123 
124  return (out);
125 }
126 
127 /* zv_sub -- vector subtraction -- may be in-situ */
128 ZVEC *zv_sub(vec1,vec2,out)
129 ZVEC *vec1,*vec2,*out;
130 {
131  /* u_int i, dim; */
132  /* complex *out_ve, *vec1_ve, *vec2_ve; */
133 
134  if ( vec1==ZVNULL || vec2==ZVNULL )
135  error(E_NULL,"zv_sub");
136  if ( vec1->dim != vec2->dim )
137  error(E_SIZES,"zv_sub");
138  if ( out==ZVNULL || out->dim != vec1->dim )
139  out = zv_resize(out,vec1->dim);
140 
141  __zsub__(vec1->ve,vec2->ve,out->ve,(int)(vec1->dim));
142 
143  return (out);
144 }
145 
146 /* zv_map -- maps function f over components of x: out[i] = f(x[i])
147  -- _zv_map sets out[i] = f(x[i],params) */
148 ZVEC *zv_map(f,x,out)
149 #ifdef PROTOYPES_IN_STRUCT
150 complex (*f)(complex);
151 #else
152 complex (*f)();
153 #endif
154 ZVEC *x, *out;
155 {
156  complex *x_ve, *out_ve;
157  int i, dim;
158 
159  if ( ! x || ! f )
160  error(E_NULL,"zv_map");
161  if ( ! out || out->dim != x->dim )
162  out = zv_resize(out,x->dim);
163 
164  dim = x->dim; x_ve = x->ve; out_ve = out->ve;
165  for ( i = 0; i < dim; i++ )
166  out_ve[i] = (*f)(x_ve[i]);
167 
168  return out;
169 }
170 
171 ZVEC *_zv_map(f,params,x,out)
172 #ifdef PROTOTYPES_IN_STRUCT
173 complex (*f)(void *,complex);
174 #else
175 complex (*f)();
176 #endif
177 ZVEC *x, *out;
178 void *params;
179 {
180  complex *x_ve, *out_ve;
181  int i, dim;
182 
183  if ( ! x || ! f )
184  error(E_NULL,"_zv_map");
185  if ( ! out || out->dim != x->dim )
186  out = zv_resize(out,x->dim);
187 
188  dim = x->dim; x_ve = x->ve; out_ve = out->ve;
189  for ( i = 0; i < dim; i++ )
190  out_ve[i] = (*f)(params,x_ve[i]);
191 
192  return out;
193 }
194 
195 /* zv_lincomb -- returns sum_i a[i].v[i], a[i] real, v[i] vectors */
197 int n; /* number of a's and v's */
198 complex a[];
199 ZVEC *v[], *out;
200 {
201  int i;
202 
203  if ( ! a || ! v )
204  error(E_NULL,"zv_lincomb");
205  if ( n <= 0 )
206  return ZVNULL;
207 
208  for ( i = 1; i < n; i++ )
209  if ( out == v[i] )
210  error(E_INSITU,"zv_lincomb");
211 
212  out = zv_mlt(a[0],v[0],out);
213  for ( i = 1; i < n; i++ )
214  {
215  if ( ! v[i] )
216  error(E_NULL,"zv_lincomb");
217  if ( v[i]->dim != out->dim )
218  error(E_SIZES,"zv_lincomb");
219  out = zv_mltadd(out,v[i],a[i],out);
220  }
221 
222  return out;
223 }
224 
225 
226 #ifdef ANSI_C
227 
228 
229 /* zv_linlist -- linear combinations taken from a list of arguments;
230  calling:
231  zv_linlist(out,v1,a1,v2,a2,...,vn,an,NULL);
232  where vi are vectors (ZVEC *) and ai are numbers (complex)
233 */
234 
235 ZVEC *zv_linlist(ZVEC *out,ZVEC *v1,complex a1,...)
236 {
237  va_list ap;
238  ZVEC *par;
239  complex a_par;
240 
241  if ( ! v1 )
242  return ZVNULL;
243 
244  va_start(ap, a1);
245  out = zv_mlt(a1,v1,out);
246 
247  while ((par = va_arg(ap,ZVEC *))) { /* NULL ends the list*/
248  a_par = va_arg(ap,complex);
249  if (a_par.re == 0.0 && a_par.im == 0.0) continue;
250  if ( out == par )
251  error(E_INSITU,"zv_linlist");
252  if ( out->dim != par->dim )
253  error(E_SIZES,"zv_linlist");
254 
255  if (a_par.re == 1.0 && a_par.im == 0.0)
256  out = zv_add(out,par,out);
257  else if (a_par.re == -1.0 && a_par.im == 0.0)
258  out = zv_sub(out,par,out);
259  else
260  out = zv_mltadd(out,par,a_par,out);
261  }
262 
263  va_end(ap);
264  return out;
265 }
266 
267 
268 #elif VARARGS
269 
270 /* zv_linlist -- linear combinations taken from a list of arguments;
271  calling:
272  zv_linlist(out,v1,a1,v2,a2,...,vn,an,NULL);
273  where vi are vectors (ZVEC *) and ai are numbers (complex)
274 */
275 ZVEC *zv_linlist(va_alist) va_dcl
276 {
277  va_list ap;
278  ZVEC *par, *out;
279  complex a_par;
280 
281  va_start(ap);
282  out = va_arg(ap,ZVEC *);
283  par = va_arg(ap,ZVEC *);
284  if ( ! par ) {
285  va_end(ap);
286  return ZVNULL;
287  }
288 
289  a_par = va_arg(ap,complex);
290  out = zv_mlt(a_par,par,out);
291 
292  while ((par = va_arg(ap,ZVEC *))) { /* NULL ends the list*/
293  a_par = va_arg(ap,complex);
294  if (a_par.re == 0.0 && a_par.im == 0.0) continue;
295  if ( out == par )
296  error(E_INSITU,"zv_linlist");
297  if ( out->dim != par->dim )
298  error(E_SIZES,"zv_linlist");
299 
300  if (a_par.re == 1.0 && a_par.im == 0.0)
301  out = zv_add(out,par,out);
302  else if (a_par.re == -1.0 && a_par.im == 0.0)
303  out = zv_sub(out,par,out);
304  else
305  out = zv_mltadd(out,par,a_par,out);
306  }
307 
308  va_end(ap);
309  return out;
310 }
311 
312 
313 #endif
314 
315 
316 
317 /* zv_star -- computes componentwise (Hadamard) product of x1 and x2
318  -- result out is returned */
319 ZVEC *zv_star(x1, x2, out)
320 ZVEC *x1, *x2, *out;
321 {
322  int i;
323  Real t_re, t_im;
324 
325  if ( ! x1 || ! x2 )
326  error(E_NULL,"zv_star");
327  if ( x1->dim != x2->dim )
328  error(E_SIZES,"zv_star");
329  out = zv_resize(out,x1->dim);
330 
331  for ( i = 0; i < x1->dim; i++ )
332  {
333  /* out->ve[i] = x1->ve[i] * x2->ve[i]; */
334  t_re = x1->ve[i].re*x2->ve[i].re - x1->ve[i].im*x2->ve[i].im;
335  t_im = x1->ve[i].re*x2->ve[i].im + x1->ve[i].im*x2->ve[i].re;
336  out->ve[i].re = t_re;
337  out->ve[i].im = t_im;
338  }
339 
340  return out;
341 }
342 
343 /* zv_slash -- computes componentwise ratio of x2 and x1
344  -- out[i] = x2[i] / x1[i]
345  -- if x1[i] == 0 for some i, then raise E_SING error
346  -- result out is returned */
347 ZVEC *zv_slash(x1, x2, out)
348 ZVEC *x1, *x2, *out;
349 {
350  int i;
351  Real r2, t_re, t_im;
352  complex tmp;
353 
354  if ( ! x1 || ! x2 )
355  error(E_NULL,"zv_slash");
356  if ( x1->dim != x2->dim )
357  error(E_SIZES,"zv_slash");
358  out = zv_resize(out,x1->dim);
359 
360  for ( i = 0; i < x1->dim; i++ )
361  {
362  r2 = x1->ve[i].re*x1->ve[i].re + x1->ve[i].im*x1->ve[i].im;
363  if ( r2 == 0.0 )
364  error(E_SING,"zv_slash");
365  tmp.re = x1->ve[i].re / r2;
366  tmp.im = - x1->ve[i].im / r2;
367  t_re = tmp.re*x2->ve[i].re - tmp.im*x2->ve[i].im;
368  t_im = tmp.re*x2->ve[i].im - tmp.im*x2->ve[i].re;
369  out->ve[i].re = t_re;
370  out->ve[i].im = t_im;
371  }
372 
373  return out;
374 }
375 
376 /* zv_sum -- returns sum of entries of a vector */
378 ZVEC *x;
379 {
380  int i;
381  complex sum;
382 
383  if ( ! x )
384  error(E_NULL,"zv_sum");
385 
386  sum.re = sum.im = 0.0;
387  for ( i = 0; i < x->dim; i++ )
388  {
389  sum.re += x->ve[i].re;
390  sum.im += x->ve[i].im;
391  }
392 
393  return sum;
394 }
395 
396 /* px_zvec -- permute vector */
397 ZVEC *px_zvec(px,vector,out)
398 PERM *px;
399 ZVEC *vector,*out;
400 {
401  u_int old_i, i, size, start;
402  complex tmp;
403 
404  if ( px==PNULL || vector==ZVNULL )
405  error(E_NULL,"px_zvec");
406  if ( px->size > vector->dim )
407  error(E_SIZES,"px_zvec");
408  if ( out==ZVNULL || out->dim < vector->dim )
409  out = zv_resize(out,vector->dim);
410 
411  size = px->size;
412  if ( size == 0 )
413  return zv_copy(vector,out);
414 
415  if ( out != vector )
416  {
417  for ( i=0; i<size; i++ )
418  if ( px->pe[i] >= size )
419  error(E_BOUNDS,"px_vec");
420  else
421  out->ve[i] = vector->ve[px->pe[i]];
422  }
423  else
424  { /* in situ algorithm */
425  start = 0;
426  while ( start < size )
427  {
428  old_i = start;
429  i = px->pe[old_i];
430  if ( i >= size )
431  {
432  start++;
433  continue;
434  }
435  tmp = vector->ve[start];
436  while ( TRUE )
437  {
438  vector->ve[old_i] = vector->ve[i];
439  px->pe[old_i] = i+size;
440  old_i = i;
441  i = px->pe[old_i];
442  if ( i >= size )
443  break;
444  if ( i == start )
445  {
446  vector->ve[old_i] = tmp;
447  px->pe[old_i] = i+size;
448  break;
449  }
450  }
451  start++;
452  }
453 
454  for ( i = 0; i < size; i++ )
455  if ( px->pe[i] < size )
456  error(E_BOUNDS,"px_vec");
457  else
458  px->pe[i] = px->pe[i]-size;
459  }
460 
461  return out;
462 }
463 
464 /* pxinv_zvec -- apply the inverse of px to x, returning the result in out
465  -- may NOT be in situ */
466 ZVEC *pxinv_zvec(px,x,out)
467 PERM *px;
468 ZVEC *x, *out;
469 {
470  u_int i, size;
471 
472  if ( ! px || ! x )
473  error(E_NULL,"pxinv_zvec");
474  if ( px->size > x->dim )
475  error(E_SIZES,"pxinv_zvec");
476  if ( ! out || out->dim < x->dim )
477  out = zv_resize(out,x->dim);
478 
479  size = px->size;
480  if ( size == 0 )
481  return zv_copy(x,out);
482  if ( out != x )
483  {
484  for ( i=0; i<size; i++ )
485  if ( px->pe[i] >= size )
486  error(E_BOUNDS,"pxinv_vec");
487  else
488  out->ve[px->pe[i]] = x->ve[i];
489  }
490  else
491  { /* in situ algorithm --- cheat's way out */
492  px_inv(px,px);
493  px_zvec(px,x,out);
494  px_inv(px,px);
495  }
496 
497 
498  return out;
499 }
500 
501 /* zv_rand -- randomise a complex vector; uniform in [0,1)+[0,1)*i */
503 ZVEC *x;
504 {
505  if ( ! x )
506  error(E_NULL,"zv_rand");
507 
508  mrandlist((Real *)(x->ve),2*x->dim);
509 
510  return x;
511 }
#define PNULL
Definition: matrix.h:633
PERM * px_inv(PERM *px, PERM *out)
Real im
Definition: zmatrix.h:40
#define E_SING
Definition: err.h:98
u_int dim
Definition: zmatrix.h:45
#define ZVNULL
Definition: zmatrix.h:57
#define min(a, b)
Definition: matrix.h:157
ZVEC * pxinv_zvec(PERM *px, ZVEC *x, ZVEC *out)
Definition: zvecop.c:466
ZVEC * zv_mlt(complex scalar, ZVEC *vector, ZVEC *out)
Definition: zvecop.c:54
#define Real
Definition: machine.h:189
void __zmlt__(complex *zp, complex s, complex *out, int len)
Definition: zmachine.c:117
#define TRUE
Definition: err.c:57
ZVEC * zv_star(ZVEC *x1, ZVEC *x2, ZVEC *out)
Definition: zvecop.c:319
#define v
Definition: md1redef.h:4
void __zmltadd__(complex *zp1, complex *zp2, complex s, int len, int flag)
Definition: zmachine.c:87
static char rcsid[]
Definition: zvecop.c:31
complex __zip__(complex *zp1, complex *zp2, int len, int flag)
Definition: zmachine.c:56
complex zv_sum(ZVEC *x)
Definition: zvecop.c:377
Definition: zmatrix.h:44
void start()
Definition: hel2mos.cpp:205
ZVEC * zv_sub(ZVEC *vec1, ZVEC *vec2, ZVEC *out)
Definition: zvecop.c:128
ZVEC * zv_mltadd(ZVEC *v1, ZVEC *v2, complex scale, ZVEC *out)
Definition: zvecop.c:95
#define E_SIZES
Definition: err.h:95
uint32_t u_int
Definition: machine.h:38
int const size_t const size_t n
Definition: nrngsl.h:12
ZVEC * zv_rand(ZVEC *x)
Definition: zvecop.c:502
complex * ve
Definition: zmatrix.h:46
Real re
Definition: zmatrix.h:40
#define zv_copy(x, y)
Definition: zmatrix.h:263
#define tracecatch(ok_part, function)
Definition: err.h:166
#define E_BOUNDS
Definition: err.h:96
ZVEC * zv_slash(ZVEC *x1, ZVEC *x2, ZVEC *out)
Definition: zvecop.c:347
#define E_NULL
Definition: err.h:102
void __zsub__(complex *zp1, complex *zp2, complex *out, int len)
Definition: zmachine.c:147
ZVEC * zv_zero(ZVEC *x)
Definition: zmemory.c:39
void __zadd__(complex *zp1, complex *zp2, complex *out, int len)
Definition: zmachine.c:134
ZVEC * zv_add(ZVEC *vec1, ZVEC *vec2, ZVEC *out)
Definition: zvecop.c:76
ZVEC * zv_resize(ZVEC *x, int new_dim)
Definition: zmemory.c:362
complex _zin_prod(ZVEC *a, ZVEC *b, u_int i0, u_int flag)
Definition: zvecop.c:38
#define i
Definition: md1redef.h:12
ZVEC * _zv_map(complex(*f)(), void *params, ZVEC *x, ZVEC *out)
Definition: zvecop.c:171
#define error(err_num, fn_name)
Definition: err.h:73
ZVEC * zv_map(complex(*f)(), ZVEC *x, ZVEC *out)
Definition: zvecop.c:148
ZVEC * zv_lincomb(int n, v, a, *out)
Definition: zvecop.c:196
Definition: matrix.h:87
ZVEC * px_zvec(PERM *px, ZVEC *vector, ZVEC *out)
Definition: zvecop.c:397
void mrandlist(a, int len)
Definition: init.c:171
ZVEC * zv_linlist(ZVEC *out, ZVEC *v1, complex a1,...)
Definition: zvecop.c:235
#define E_INSITU
Definition: err.h:106