NEURON
vecop.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 /* vecop.c 1.3 8/18/87 */
29 
30 #include <stdio.h>
31 #include "matrix.h"
32 
33 static char rcsid[] = "vecop.c,v 1.1 1997/12/04 17:56:02 hines Exp";
34 
35 
36 /* _in_prod -- inner product of two vectors from i0 downwards */
37 double _in_prod(a,b,i0)
38 VEC *a,*b;
39 u_int i0;
40 {
41  u_int limit;
42  /* Real *a_v, *b_v; */
43  /* register Real sum; */
44 
45  if ( a==(VEC *)NULL || b==(VEC *)NULL )
46  error(E_NULL,"_in_prod");
47  limit = min(a->dim,b->dim);
48  if ( i0 > limit )
49  error(E_BOUNDS,"_in_prod");
50 
51  return __ip__(&(a->ve[i0]),&(b->ve[i0]),(int)(limit-i0));
52  /*****************************************
53  a_v = &(a->ve[i0]); b_v = &(b->ve[i0]);
54  for ( i=i0; i<limit; i++ )
55  sum += a_v[i]*b_v[i];
56  sum += (*a_v++)*(*b_v++);
57 
58  return (double)sum;
59  ******************************************/
60 }
61 
62 /* sv_mlt -- scalar-vector multiply -- may be in-situ */
63 VEC *sv_mlt(scalar,vector,out)
64 double scalar;
65 VEC *vector,*out;
66 {
67  /* u_int dim, i; */
68  /* Real *out_ve, *vec_ve; */
69 
70  if ( vector==(VEC *)NULL )
71  error(E_NULL,"sv_mlt");
72  if ( out==(VEC *)NULL || out->dim != vector->dim )
73  out = v_resize(out,vector->dim);
74  if ( scalar == 0.0 )
75  return v_zero(out);
76  if ( scalar == 1.0 )
77  return v_copy(vector,out);
78 
79  __smlt__(vector->ve,(double)scalar,out->ve,(int)(vector->dim));
80  /**************************************************
81  dim = vector->dim;
82  out_ve = out->ve; vec_ve = vector->ve;
83  for ( i=0; i<dim; i++ )
84  out->ve[i] = scalar*vector->ve[i];
85  (*out_ve++) = scalar*(*vec_ve++);
86  **************************************************/
87  return (out);
88 }
89 
90 /* v_add -- vector addition -- may be in-situ */
91 VEC *v_add(vec1,vec2,out)
92 VEC *vec1,*vec2,*out;
93 {
94  u_int dim;
95  /* Real *out_ve, *vec1_ve, *vec2_ve; */
96 
97  if ( vec1==(VEC *)NULL || vec2==(VEC *)NULL )
98  error(E_NULL,"v_add");
99  if ( vec1->dim != vec2->dim )
100  error(E_SIZES,"v_add");
101  if ( out==(VEC *)NULL || out->dim != vec1->dim )
102  out = v_resize(out,vec1->dim);
103  dim = vec1->dim;
104  __add__(vec1->ve,vec2->ve,out->ve,(int)dim);
105  /************************************************************
106  out_ve = out->ve; vec1_ve = vec1->ve; vec2_ve = vec2->ve;
107  for ( i=0; i<dim; i++ )
108  out->ve[i] = vec1->ve[i]+vec2->ve[i];
109  (*out_ve++) = (*vec1_ve++) + (*vec2_ve++);
110  ************************************************************/
111 
112  return (out);
113 }
114 
115 /* v_mltadd -- scalar/vector multiplication and addition
116  -- out = v1 + scale.v2 */
117 VEC *v_mltadd(v1,v2,scale,out)
118 VEC *v1,*v2,*out;
119 double scale;
120 {
121  /* register u_int dim, i; */
122  /* Real *out_ve, *v1_ve, *v2_ve; */
123 
124  if ( v1==(VEC *)NULL || v2==(VEC *)NULL )
125  error(E_NULL,"v_mltadd");
126  if ( v1->dim != v2->dim )
127  error(E_SIZES,"v_mltadd");
128  if ( scale == 0.0 )
129  return v_copy(v1,out);
130  if ( scale == 1.0 )
131  return v_add(v1,v2,out);
132 
133  if ( v2 != out )
134  {
135  tracecatch(out = v_copy(v1,out),"v_mltadd");
136 
137  /* dim = v1->dim; */
138  __mltadd__(out->ve,v2->ve,scale,(int)(v1->dim));
139  }
140  else
141  {
142  tracecatch(out = sv_mlt(scale,v2,out),"v_mltadd");
143  out = v_add(v1,out,out);
144  }
145  /************************************************************
146  out_ve = out->ve; v1_ve = v1->ve; v2_ve = v2->ve;
147  for ( i=0; i < dim ; i++ )
148  out->ve[i] = v1->ve[i] + scale*v2->ve[i];
149  (*out_ve++) = (*v1_ve++) + scale*(*v2_ve++);
150  ************************************************************/
151 
152  return (out);
153 }
154 
155 /* v_sub -- vector subtraction -- may be in-situ */
156 VEC *v_sub(vec1,vec2,out)
157 VEC *vec1,*vec2,*out;
158 {
159  /* u_int i, dim; */
160  /* Real *out_ve, *vec1_ve, *vec2_ve; */
161 
162  if ( vec1==(VEC *)NULL || vec2==(VEC *)NULL )
163  error(E_NULL,"v_sub");
164  if ( vec1->dim != vec2->dim )
165  error(E_SIZES,"v_sub");
166  if ( out==(VEC *)NULL || out->dim != vec1->dim )
167  out = v_resize(out,vec1->dim);
168 
169  __sub__(vec1->ve,vec2->ve,out->ve,(int)(vec1->dim));
170  /************************************************************
171  dim = vec1->dim;
172  out_ve = out->ve; vec1_ve = vec1->ve; vec2_ve = vec2->ve;
173  for ( i=0; i<dim; i++ )
174  out->ve[i] = vec1->ve[i]-vec2->ve[i];
175  (*out_ve++) = (*vec1_ve++) - (*vec2_ve++);
176  ************************************************************/
177 
178  return (out);
179 }
180 
181 /* v_map -- maps function f over components of x: out[i] = f(x[i])
182  -- _v_map sets out[i] = f(params,x[i]) */
183 VEC *v_map(f,x,out)
184 #ifdef PROTOTYPES_IN_STRUCT
185 double (*f)(double);
186 #else
187 double (*f)();
188 #endif
189 VEC *x, *out;
190 {
191  Real *x_ve, *out_ve;
192  int i, dim;
193 
194  if ( ! x || ! f )
195  error(E_NULL,"v_map");
196  if ( ! out || out->dim != x->dim )
197  out = v_resize(out,x->dim);
198 
199  dim = x->dim; x_ve = x->ve; out_ve = out->ve;
200  for ( i = 0; i < dim; i++ )
201  *out_ve++ = (*f)(*x_ve++);
202 
203  return out;
204 }
205 
206 VEC *_v_map(f,params,x,out)
207 #ifdef PROTOTYPES_IN_STRUCT
208 double (*f)(void *,double);
209 #else
210 double (*f)();
211 #endif
212 VEC *x, *out;
213 void *params;
214 {
215  Real *x_ve, *out_ve;
216  int i, dim;
217 
218  if ( ! x || ! f )
219  error(E_NULL,"_v_map");
220  if ( ! out || out->dim != x->dim )
221  out = v_resize(out,x->dim);
222 
223  dim = x->dim; x_ve = x->ve; out_ve = out->ve;
224  for ( i = 0; i < dim; i++ )
225  *out_ve++ = (*f)(params,*x_ve++);
226 
227  return out;
228 }
229 
230 /* v_lincomb -- returns sum_i a[i].v[i], a[i] real, v[i] vectors */
231 VEC *v_lincomb(n,v,a,out)
232 int n; /* number of a's and v's */
233 Real a[];
234 VEC *v[], *out;
235 {
236  int i;
237 
238  if ( ! a || ! v )
239  error(E_NULL,"v_lincomb");
240  if ( n <= 0 )
241  return VNULL;
242 
243  for ( i = 1; i < n; i++ )
244  if ( out == v[i] )
245  error(E_INSITU,"v_lincomb");
246 
247  out = sv_mlt(a[0],v[0],out);
248  for ( i = 1; i < n; i++ )
249  {
250  if ( ! v[i] )
251  error(E_NULL,"v_lincomb");
252  if ( v[i]->dim != out->dim )
253  error(E_SIZES,"v_lincomb");
254  out = v_mltadd(out,v[i],a[i],out);
255  }
256 
257  return out;
258 }
259 
260 
261 
262 #ifdef ANSI_C
263 
264 /* v_linlist -- linear combinations taken from a list of arguments;
265  calling:
266  v_linlist(out,v1,a1,v2,a2,...,vn,an,NULL);
267  where vi are vectors (VEC *) and ai are numbers (double)
268 */
269 VEC *v_linlist(VEC *out,VEC *v1,double a1,...)
270 {
271  va_list ap;
272  VEC *par;
273  double a_par;
274 
275  if ( ! v1 )
276  return VNULL;
277 
278  va_start(ap, a1);
279  out = sv_mlt(a1,v1,out);
280 
281  while ((par = va_arg(ap,VEC *))) { /* NULL ends the list*/
282  a_par = va_arg(ap,double);
283  if (a_par == 0.0) continue;
284  if ( out == par )
285  error(E_INSITU,"v_linlist");
286  if ( out->dim != par->dim )
287  error(E_SIZES,"v_linlist");
288 
289  if (a_par == 1.0)
290  out = v_add(out,par,out);
291  else if (a_par == -1.0)
292  out = v_sub(out,par,out);
293  else
294  out = v_mltadd(out,par,a_par,out);
295  }
296 
297  va_end(ap);
298  return out;
299 }
300 
301 #elif VARARGS
302 
303 
304 /* v_linlist -- linear combinations taken from a list of arguments;
305  calling:
306  v_linlist(out,v1,a1,v2,a2,...,vn,an,NULL);
307  where vi are vectors (VEC *) and ai are numbers (double)
308 */
309 VEC *v_linlist(va_alist) va_dcl
310 {
311  va_list ap;
312  VEC *par, *out;
313  double a_par;
314 
315  va_start(ap);
316  out = va_arg(ap,VEC *);
317  par = va_arg(ap,VEC *);
318  if ( ! par ) {
319  va_end(ap);
320  return VNULL;
321  }
322 
323  a_par = va_arg(ap,double);
324  out = sv_mlt(a_par,par,out);
325 
326  while ((par = va_arg(ap,VEC *))) { /* NULL ends the list*/
327  a_par = va_arg(ap,double);
328  if (a_par == 0.0) continue;
329  if ( out == par )
330  error(E_INSITU,"v_linlist");
331  if ( out->dim != par->dim )
332  error(E_SIZES,"v_linlist");
333 
334  if (a_par == 1.0)
335  out = v_add(out,par,out);
336  else if (a_par == -1.0)
337  out = v_sub(out,par,out);
338  else
339  out = v_mltadd(out,par,a_par,out);
340  }
341 
342  va_end(ap);
343  return out;
344 }
345 
346 #endif
347 
348 
349 
350 
351 
352 /* v_star -- computes componentwise (Hadamard) product of x1 and x2
353  -- result out is returned */
354 VEC *v_star(x1, x2, out)
355 VEC *x1, *x2, *out;
356 {
357  int i;
358 
359  if ( ! x1 || ! x2 )
360  error(E_NULL,"v_star");
361  if ( x1->dim != x2->dim )
362  error(E_SIZES,"v_star");
363  out = v_resize(out,x1->dim);
364 
365  for ( i = 0; i < x1->dim; i++ )
366  out->ve[i] = x1->ve[i] * x2->ve[i];
367 
368  return out;
369 }
370 
371 /* v_slash -- computes componentwise ratio of x2 and x1
372  -- out[i] = x2[i] / x1[i]
373  -- if x1[i] == 0 for some i, then raise E_SING error
374  -- result out is returned */
375 VEC *v_slash(x1, x2, out)
376 VEC *x1, *x2, *out;
377 {
378  int i;
379  Real tmp;
380 
381  if ( ! x1 || ! x2 )
382  error(E_NULL,"v_slash");
383  if ( x1->dim != x2->dim )
384  error(E_SIZES,"v_slash");
385  out = v_resize(out,x1->dim);
386 
387  for ( i = 0; i < x1->dim; i++ )
388  {
389  tmp = x1->ve[i];
390  if ( tmp == 0.0 )
391  error(E_SING,"v_slash");
392  out->ve[i] = x2->ve[i] / tmp;
393  }
394 
395  return out;
396 }
397 
398 /* v_min -- computes minimum component of x, which is returned
399  -- also sets min_idx to the index of this minimum */
400 double v_min(x, min_idx)
401 VEC *x;
402 int *min_idx;
403 {
404  int i, i_min;
405  Real min_val, tmp;
406 
407  if ( ! x )
408  error(E_NULL,"v_min");
409  if ( x->dim <= 0 )
410  error(E_SIZES,"v_min");
411  i_min = 0;
412  min_val = x->ve[0];
413  for ( i = 1; i < x->dim; i++ )
414  {
415  tmp = x->ve[i];
416  if ( tmp < min_val )
417  {
418  min_val = tmp;
419  i_min = i;
420  }
421  }
422 
423  if ( min_idx != NULL )
424  *min_idx = i_min;
425  return min_val;
426 }
427 
428 /* v_max -- computes maximum component of x, which is returned
429  -- also sets max_idx to the index of this maximum */
430 double v_max(x, max_idx)
431 VEC *x;
432 int *max_idx;
433 {
434  int i, i_max;
435  Real max_val, tmp;
436 
437  if ( ! x )
438  error(E_NULL,"v_max");
439  if ( x->dim <= 0 )
440  error(E_SIZES,"v_max");
441  i_max = 0;
442  max_val = x->ve[0];
443  for ( i = 1; i < x->dim; i++ )
444  {
445  tmp = x->ve[i];
446  if ( tmp > max_val )
447  {
448  max_val = tmp;
449  i_max = i;
450  }
451  }
452 
453  if ( max_idx != NULL )
454  *max_idx = i_max;
455  return max_val;
456 }
457 
458 #define MAX_STACK 60
459 
460 
461 /* v_sort -- sorts vector x, and generates permutation that gives the order
462  of the components; x = [1.3, 3.7, 0.5] -> [0.5, 1.3, 3.7] and
463  the permutation is order = [2, 0, 1].
464  -- if order is NULL on entry then it is ignored
465  -- the sorted vector x is returned */
467 VEC *x;
468 PERM *order;
469 {
470  Real *x_ve, tmp, v;
471  /* int *order_pe; */
472  int dim, i, j, l, r, tmp_i;
473  int stack[MAX_STACK], sp;
474 
475  if ( ! x )
476  error(E_NULL,"v_sort");
477  if ( order != PNULL && order->size != x->dim )
478  order = px_resize(order, x->dim);
479 
480  x_ve = x->ve;
481  dim = x->dim;
482  if ( order != PNULL )
483  px_ident(order);
484 
485  if ( dim <= 1 )
486  return x;
487 
488  /* using quicksort algorithm in Sedgewick,
489  "Algorithms in C", Ch. 9, pp. 118--122 (1990) */
490  sp = 0;
491  l = 0; r = dim-1; v = x_ve[0];
492  for ( ; ; )
493  {
494  while ( r > l )
495  {
496  /* "i = partition(x_ve,l,r);" */
497  v = x_ve[r];
498  i = l-1;
499  j = r;
500  for ( ; ; )
501  {
502  while ( x_ve[++i] < v )
503  ;
504  while ( x_ve[--j] > v )
505  ;
506  if ( i >= j ) break;
507 
508  tmp = x_ve[i];
509  x_ve[i] = x_ve[j];
510  x_ve[j] = tmp;
511  if ( order != PNULL )
512  {
513  tmp_i = order->pe[i];
514  order->pe[i] = order->pe[j];
515  order->pe[j] = tmp_i;
516  }
517  }
518  tmp = x_ve[i];
519  x_ve[i] = x_ve[r];
520  x_ve[r] = tmp;
521  if ( order != PNULL )
522  {
523  tmp_i = order->pe[i];
524  order->pe[i] = order->pe[r];
525  order->pe[r] = tmp_i;
526  }
527 
528  if ( i-l > r-i )
529  { stack[sp++] = l; stack[sp++] = i-1; l = i+1; }
530  else
531  { stack[sp++] = i+1; stack[sp++] = r; r = i-1; }
532  }
533 
534  /* recursion elimination */
535  if ( sp == 0 )
536  break;
537  r = stack[--sp];
538  l = stack[--sp];
539  }
540 
541  return x;
542 }
543 
544 /* v_sum -- returns sum of entries of a vector */
545 double v_sum(x)
546 VEC *x;
547 {
548  int i;
549  Real sum;
550 
551  if ( ! x )
552  error(E_NULL,"v_sum");
553 
554  sum = 0.0;
555  for ( i = 0; i < x->dim; i++ )
556  sum += x->ve[i];
557 
558  return sum;
559 }
560 
561 /* v_conv -- computes convolution product of two vectors */
562 VEC *v_conv(x1, x2, out)
563 VEC *x1, *x2, *out;
564 {
565  int i;
566 
567  if ( ! x1 || ! x2 )
568  error(E_NULL,"v_conv");
569  if ( x1 == out || x2 == out )
570  error(E_INSITU,"v_conv");
571  if ( x1->dim == 0 || x2->dim == 0 )
572  return out = v_resize(out,0);
573 
574  out = v_resize(out,x1->dim + x2->dim - 1);
575  v_zero(out);
576  for ( i = 0; i < x1->dim; i++ )
577  __mltadd__(&(out->ve[i]),x2->ve,x1->ve[i],x2->dim);
578 
579  return out;
580 }
581 
582 /* v_pconv -- computes a periodic convolution product
583  -- the period is the dimension of x2 */
584 VEC *v_pconv(x1, x2, out)
585 VEC *x1, *x2, *out;
586 {
587  int i;
588 
589  if ( ! x1 || ! x2 )
590  error(E_NULL,"v_pconv");
591  if ( x1 == out || x2 == out )
592  error(E_INSITU,"v_pconv");
593  out = v_resize(out,x2->dim);
594  if ( x2->dim == 0 )
595  return out;
596 
597  v_zero(out);
598  for ( i = 0; i < x1->dim; i++ )
599  {
600  __mltadd__(&(out->ve[i]),x2->ve,x1->ve[i],x2->dim - i);
601  if ( i > 0 )
602  __mltadd__(out->ve,&(x2->ve[x2->dim - i]),x1->ve[i],i);
603  }
604 
605  return out;
606 }
#define PNULL
Definition: matrix.h:633
VEC * v_slash(VEC *x1, VEC *x2, VEC *out)
Definition: vecop.c:375
VEC * _v_map(double(*f)(), void *params, VEC *x, VEC *out)
Definition: vecop.c:206
#define E_SING
Definition: err.h:98
order
Definition: multicore.cpp:886
double _in_prod(VEC *a, VEC *b, u_int i0)
Definition: vecop.c:37
VEC * v_add(VEC *vec1, VEC *vec2, VEC *out)
Definition: vecop.c:91
#define min(a, b)
Definition: matrix.h:157
#define MAX_STACK
Definition: vecop.c:458
#define Real
Definition: machine.h:189
static Object ** v_resize(void *v)
Definition: ivocvect.cpp:1297
#define v
Definition: md1redef.h:4
VEC * v_map(double(*f)(), VEC *x, VEC *out)
Definition: vecop.c:183
#define stack
Definition: code.cpp:128
VEC * v_star(VEC *x1, VEC *x2, VEC *out)
Definition: vecop.c:354
VEC * v_lincomb(int n, v, a, *out)
Definition: vecop.c:231
VEC * v_mltadd(VEC *v1, VEC *v2, double scale, VEC *out)
Definition: vecop.c:117
Real * ve
Definition: matrix.h:69
VEC * v_sort(VEC *x, PERM *order)
Definition: vecop.c:466
Definition: matrix.h:67
#define v_copy(in, out)
Definition: matrix.h:404
u_int size
Definition: matrix.h:88
#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
static char rcsid[]
Definition: vecop.c:33
void __mltadd__(Real *dp1, Real *dp2, double s, int len)
Definition: machine.c:76
PERM * px_resize(PERM *, int)
Definition: memory.c:399
u_int dim
Definition: matrix.h:68
double v_sum(VEC *x)
Definition: vecop.c:545
#define tracecatch(ok_part, function)
Definition: err.h:166
#define E_BOUNDS
Definition: err.h:96
#define E_NULL
Definition: err.h:102
size_t j
void __add__(Real *dp1, Real *dp2, Real *out, int len)
Definition: machine.c:113
double __ip__(Real *dp1, Real *dp2, int len)
Definition: machine.c:40
double v_min(VEC *x, int *min_idx)
Definition: vecop.c:400
VEC * v_zero(VEC *x)
Definition: init.c:40
VEC * v_conv(VEC *x1, VEC *x2, VEC *out)
Definition: vecop.c:562
VEC * sv_mlt(double scalar, VEC *vector, VEC *out)
Definition: vecop.c:63
#define i
Definition: md1redef.h:12
#define error(err_num, fn_name)
Definition: err.h:73
void __sub__(Real *dp1, Real *dp2, Real *out, int len)
Definition: machine.c:123
VEC * v_linlist(VEC *out, VEC *v1, double a1,...)
Definition: vecop.c:269
#define VNULL
Definition: matrix.h:631
double v_max(VEC *x, int *max_idx)
Definition: vecop.c:430
VEC * v_sub(VEC *vec1, VEC *vec2, VEC *out)
Definition: vecop.c:156
VEC * v_pconv(VEC *x1, VEC *x2, VEC *out)
Definition: vecop.c:584
void __smlt__(Real *dp, double s, Real *out, int len)
Definition: machine.c:102
Definition: matrix.h:87
PERM * px_ident(PERM *px)
Definition: init.c:108
return NULL
Definition: cabcode.cpp:461
u_int * pe
Definition: matrix.h:88
#define E_INSITU
Definition: err.h:106