NEURON
ivocvect.cpp
Go to the documentation of this file.
1 #include <../../nrnconf.h>
2 
3 #if defined(__GO32__)
4 #define HAVE_IV 0
5 #endif
6 
7 //#include <string.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <ivstream.h>
11 #include <math.h>
12 #include <errno.h>
13 #include <numeric>
14 #include <functional>
15 
16 #include <OS/math.h>
17 #include "fourier.h"
18 
19 #if HAVE_IV
20 #include <InterViews/glyph.h>
21 #include <InterViews/hit.h>
22 #include <InterViews/event.h>
23 #include <InterViews/color.h>
24 #include <InterViews/brush.h>
25 #include <InterViews/window.h>
26 #include <InterViews/printer.h>
27 #include <InterViews/label.h>
28 #include <InterViews/font.h>
29 #include <InterViews/background.h>
30 #include <InterViews/style.h>
31 //#include <OS/string.h>
32 
33 #include <IV-look/kit.h>
34 #else
35 #include <InterViews/resource.h>
36 #include <OS/list.h>
37 #endif
38 
39 #if defined(SVR4)
40 extern void exit(int status);
41 #endif
42 
43 #include "classreg.h"
44 #if HAVE_IV
45 #include "apwindow.h"
46 #include "ivoc.h"
47 #include "graph.h"
48 #endif
49 
50 #include "gui-redirect.h"
51 
52 extern Object** (*nrnpy_gui_helper_)(const char* name, Object* obj);
53 extern double (*nrnpy_object_to_double_)(Object*);
54 
55 #ifndef PI
56 #ifndef M_PI
57 #define M_PI 3.14159265358979323846
58 #endif
59 #define PI M_PI
60 #endif
61 #define BrainDamaged 0 // The Sun CC compiler but it doesn't hurt to leave it in
62 #if BrainDamaged
63 #define FWrite(arg1, arg2, arg3, arg4) \
64  if (fwrite((arg1), arg2, arg3, arg4) != arg3) { \
65  hoc_execerror("fwrite error", 0); \
66  }
67 #define FRead(arg1, arg2, arg3, arg4) \
68  if (fread((arg1), arg2, arg3, arg4) != arg3) { \
69  hoc_execerror("fread error", 0); \
70  }
71 #else
72 #define FWrite(arg1, arg2, arg3, arg4) \
73  if (fwrite(arg1, arg2, arg3, arg4) != arg3) { \
74  }
75 #define FRead(arg1, arg2, arg3, arg4) \
76  if (fread(arg1, arg2, arg3, arg4) != arg3) { \
77  }
78 #endif
79 
80 /**
81  * As all parameters are passed from hoc as double, we need
82  * to calculate max integer that can fit into double variable.
83  *
84  * With IEEE 64-bit double has 52 bits of mantissa, so it's 2^53.
85  * calculating it with approach `while (dbl + 1 != dbl) dbl++;`
86  * has issues with SSE and other 32 bits platform. So we are using
87  * direct value here.
88  *
89  * The maximum mantissa 0xFFFFFFFFFFFFF which is 52 bits all 1.
90  * In Python it's:
91  *
92  * >>> (2.**53).hex()
93  * '0x1.0000000000000p+53'
94  * >>> (2.**53)
95  * 9007199254740992.0
96  *
97  * See https://stackoverflow.com/questions/1848700/biggest-integer-that-can-be-stored-in-a-double
98  */
99 static double dmaxint_ = 9007199254740992;
100 
101 // Definitions allow machine independent write and read
102 // note that must include BYTEHEADER at head of routine
103 // The policy is that each machine vwrite binary information in
104 // without swapping, ie. native endian.
105 // On reading, the type is checked to decide whether
106 // byteswapping should be performed
107 
108 #define BYTEHEADER \
109  int _II__; \
110  char* _IN__; \
111  char _OUT__[16]; \
112  int BYTESWAP_FLAG = 0;
113 #define BYTESWAP(_X__, _TYPE__) \
114  if (BYTESWAP_FLAG == 1) { \
115  _IN__ = (char*) &(_X__); \
116  for (_II__ = 0; _II__ < sizeof(_TYPE__); _II__++) { \
117  _OUT__[_II__] = _IN__[sizeof(_TYPE__) - _II__ - 1]; \
118  } \
119  (_X__) = *((_TYPE__*) &_OUT__); \
120  }
121 
122 #include "ivocvect.h"
123 
124 // definition of random numer generator
125 #include "random1.h"
126 #include <Uniform.h>
127 
128 #if HAVE_IV
129 #include "utility.h"
130 #endif
131 #include "oc2iv.h"
132 #include "parse.hpp"
133 #include "ocfile.h"
134 
135 extern Object* hoc_thisobject;
137 extern "C" void nrn_exit(int);
138 IvocVect* (*nrnpy_vec_from_python_p_)(void*);
139 Object** (*nrnpy_vec_to_python_p_)(void*);
140 Object** (*nrnpy_vec_as_numpy_helper_)(int, double*);
141 
142 // math functions with error checking defined in oc/SRC/math.cpp
143 extern double hoc_Log(double x), hoc_Log10(double x), /*hoc_Exp(double x), */ hoc_Sqrt(double x);
144 extern double hoc_scan(FILE*);
145 
146 extern "C" {
147 extern double hoc_Exp(double);
148 } // extern "C"
149 
150 static int narg() {
151  int i = 0;
152  while (ifarg(i++))
153  ;
154  return i - 2;
155 }
156 
157 #define MAX_FIT_PARAMS 20
158 
159 #define TWO_BYTE_HIGH 65535.
160 #define ONE_BYTE_HIGH 255.
161 #define ONE_BYTE_HALF 128.
162 
163 #define EPSILON 1e-9
164 
165 
166 int cmpfcn(double a, double b) {
167  return ((a) <= (b)) ? (((a) == (b)) ? 0 : -1) : 1;
168 }
169 typedef int (*doubleComparator)(double, double);
170 
171 extern "C" {
172 extern void install_vector_method(const char* name, Pfrd_vp);
173 extern int vector_instance_px(void*, double**);
174 extern int nrn_mlh_gsort(double* vec, int* base_ptr, int total_elems, doubleComparator cmp);
175 } // extern "C"
176 
177 extern int vector_arg_px(int, double**);
178 extern void notify_freed_val_array(double*, size_t);
179 
180 extern int hoc_return_type_code;
181 
183  obj_ = o;
184  label_ = NULL;
185  MUTCONSTRUCT(0)
186 }
188  : vec_(l) {
189  obj_ = o;
190  label_ = NULL;
191  MUTCONSTRUCT(0)
192 }
193 IvocVect::IvocVect(int l, double fill_value, Object* o)
194  : vec_(l, fill_value) {
195  obj_ = o;
196  label_ = NULL;
197  MUTCONSTRUCT(0)
198 }
200  : vec_(v.vec_) {
201  obj_ = o;
202  label_ = NULL;
203  MUTCONSTRUCT(0)
204 }
205 
208  if (label_) {
209  delete[] label_;
210  }
211  notify_freed_val_array(vec_.data(), vec_.capacity());
212 }
213 
214 void IvocVect::label(const char* label) {
215  if (label_) {
216  delete[] label_;
217  label_ = NULL;
218  }
219  if (label) {
220  label_ = new char[strlen(label) + 1];
221  strcpy(label_, label);
222  }
223 }
224 
225 static const char* nullstr = "";
226 
227 static const char** v_label(void* v) {
228  Vect* x = (Vect*) v;
229  if (ifarg(1)) {
230  x->label(gargstr(1));
231  }
232  if (x->label_) {
233  return (const char**) &x->label_;
234  }
235  return &nullstr;
236 }
237 
238 static void same_err(const char* s, Vect* x, Vect* y) {
239  if (x == y) {
240  hoc_execerror(s, " argument needs to be copied first");
241  }
242 }
243 
244 /* the Vect->elem(start, end) function was used in about a dozen places
245 for the purpose of dealing with a subrange of elements. However that
246 function clones the subrange and returns a new Vect. This caused a
247 memory leak and was needlessly inefficient for those functions.
248 To fix both problems for these specific functions
249 we use a special vector which does not have
250 it's own space but merely a pointer and capacity to the right space of
251 the original vector. The usage is restricted to only once at a time, i.e.
252 can't use two subvecs at once and never do anything which affects the
253 memory space.
254 */
255 
256 #if HAVE_IV
257 /*static*/ class GraphMarkItem: public GraphItem {
258  public:
259  GraphMarkItem(Glyph* g)
260  : GraphItem(g) {}
261  virtual ~GraphMarkItem(){};
262  virtual void erase(Scene* s, GlyphIndex i, int type) {
263  if (type & GraphItem::ERASE_LINE) {
264  s->remove(i);
265  }
266  }
267 };
268 #endif
269 
270 static void* v_cons(Object* o) {
271  double fill_value = 0.;
272  int n = 0;
273  Vect* vec;
274  if (ifarg(1)) {
275  if (hoc_is_double_arg(1)) {
276  n = int(chkarg(1, 0, 1e10));
277  if (ifarg(2))
278  fill_value = *getarg(2);
279  vec = new Vect(n, fill_value, o);
280  } else {
282  hoc_execerror("Python not available", 0);
283  }
284  vec = (*nrnpy_vec_from_python_p_)(new Vect(0, 0, o));
285  }
286  } else {
287  vec = new Vect(0, 0, o);
288  }
289  return vec;
290 }
291 
292 
293 static void v_destruct(void* v) {
294  delete (Vect*) v;
295 }
296 
297 static Symbol* svec_;
298 
299 // extern "C" vector functions used by ocmatrix.dll
300 // can also be used in mod files
302  return new Vect(n, o);
303 }
305  return new Vect();
306 }
308  return new Vect(n);
309 }
311  return new Vect(*v);
312 }
314  delete v;
315 }
317  return v->buffer_size();
318 }
320  return v->size();
321 }
322 void vector_resize(Vect* v, int n) {
323  v->resize(n);
324 }
326  return v->temp_objvar();
327 }
328 double* vector_vec(Vect* v) {
329  return v->data();
330 }
332  return &v->obj_;
333 }
335  return v->label_;
336 }
337 void vector_set_label(Vect* v, char* s) {
338  v->label(s);
339 }
340 void vector_append(Vect* v, double x) {
341  v->push_back(x);
342 }
343 
344 #ifdef WIN32
345 #if !defined(USEMATRIX) || USEMATRIX == 0
346 #include "../windll/dll.h"
347 extern char* neuron_home;
348 
349 void load_ocmatrix() {
350  struct DLL* dll = NULL;
351  char buf[256];
352  sprintf(buf, "%s\\lib\\ocmatrix.dll", neuron_home);
353  dll = dll_load(buf);
354  if (dll) {
355  Pfri mreg = (Pfri) dll_lookup(dll, "_Matrix_reg");
356  if (mreg) {
357  (*mreg)();
358  }
359  } else {
360  printf("No Matrix class.\n");
361  }
362 }
363 #endif
364 #endif
365 
367  IvocVect* v = (IvocVect*) this;
368  Object** po;
369  if (v->obj_) {
370  po = hoc_temp_objptr(v->obj_);
371  } else {
372  po = hoc_temp_objvar(svec_, (void*) v);
373  obj_ = *po;
374  }
375  return po;
376 }
377 
378 extern "C" { // bug in cray compiler requires this
379 void install_vector_method(const char* name, double (*f)(void*)) {
380  Symbol* s_meth;
382  hoc_execerror(name, " already a method in the Vector class");
383  }
384  s_meth = hoc_install(name, FUNCTION, 0.0, &svec_->u.ctemplate->symtable);
385  s_meth->u.u_proc->defn.pfd = (Pfrd) f;
386 #define PUBLIC_TYPE 1
387  s_meth->cpublic = PUBLIC_TYPE;
388 }
389 } // extern "C"
390 
391 extern "C" int vector_instance_px(void* v, double** px) {
392  Vect* x = (Vect*) v;
393  *px = x->data();
394  return x->size();
395 }
396 
397 extern "C" Vect* vector_arg(int i) {
398  Object* ob = *hoc_objgetarg(i);
399  if (!ob || ob->ctemplate != svec_->u.ctemplate) {
400  check_obj_type(ob, "Vector");
401  }
402  return (Vect*) (ob->u.this_pointer);
403 }
404 
405 int is_vector_arg(int i) {
406  Object* ob = *hoc_objgetarg(i);
407  if (!ob || ob->ctemplate != svec_->u.ctemplate) {
408  return 0;
409  }
410  return 1;
411 }
412 
413 int vector_arg_px(int i, double** px) {
414  Vect* x = vector_arg(i);
415  *px = x->data();
416  return x->size();
417 }
418 
419 extern void nrn_vecsim_add(void*, bool);
420 extern void nrn_vecsim_remove(void*);
421 
422 static int possible_destvec(int arg, Vect*& dest) {
423  if (ifarg(arg) && hoc_is_object_arg(arg)) {
424  dest = vector_arg(arg);
425  return arg + 1;
426  } else {
427  dest = new Vect();
428  return arg;
429  }
430 }
431 
432 static double v_play_remove(void* v) {
434  return 1.;
435 }
436 
437 static double v_fwrite(void* v) {
438  Vect* vp = (Vect*) v;
439  void* s;
440  int x_max = vp->size() - 1;
441  int start = 0;
442  int end = x_max;
443  hoc_return_type_code = 1; // integer
444  if (ifarg(2)) {
445  start = int(chkarg(2, 0, x_max));
446  end = int(chkarg(3, start, x_max));
447  }
448  s = (void*) (&vp->elem(start));
449  const char* x = (const char*) s;
450 
451  Object* ob = *hoc_objgetarg(1);
452  check_obj_type(ob, "File");
453  OcFile* f = (OcFile*) (ob->u.this_pointer);
454  FILE* fp = f->file();
455  if (!fp) {
456  return 0.;
457  }
458  int n = end - start + 1;
459  BinaryMode(f);
460  return (double) fwrite(x, sizeof(double), n, fp);
461 }
462 
463 static double v_fread(void* v) {
464  Vect* vp = (Vect*) v;
465 
466  Object* ob = *hoc_objgetarg(1);
467 
468  check_obj_type(ob, "File");
469  OcFile* f = (OcFile*) (ob->u.this_pointer);
470 
471  if (ifarg(2))
472  vp->resize(int(chkarg(2, 0, 1e10)));
473  int n = vp->size();
474 
475  int type = 4;
476  if (ifarg(3)) {
477  type = int(chkarg(3, 1, 5));
478  }
479 
480  FILE* fp = f->file();
481  if (!fp) {
482  return 0.;
483  }
484 
485  int i;
486  BinaryMode(f) if (n > 0) switch (type) {
487  case 5: // short ints
488  {
489  short* xs = (short*) malloc(n * (unsigned) sizeof(short));
490  FRead(xs, sizeof(short), n, fp);
491  for (i = 0; i < n; ++i) {
492  vp->elem(i) = double(xs[i]);
493  }
494  free((char*) xs);
495  break;
496  }
497 
498  case 4: // doubles
499  FRead(&(vp->elem(0)), sizeof(double), n, fp);
500  break;
501 
502  case 3: // floats
503  {
504  float* xf = (float*) malloc(n * (unsigned) sizeof(float));
505  FRead(xf, sizeof(float), n, fp);
506  for (i = 0; i < n; ++i) {
507  vp->elem(i) = double(xf[i]);
508  }
509  free((char*) xf);
510  break;
511  }
512 
513  case 2: // unsigned short ints
514  {
515  unsigned short* xi = (unsigned short*) malloc(n * (unsigned) sizeof(unsigned short));
516  FRead(xi, sizeof(unsigned short), n, fp);
517  for (i = 0; i < n; ++i) {
518  vp->elem(i) = double(xi[i]);
519  }
520  free((char*) xi);
521  break;
522  }
523 
524  case 1: // char
525  {
526  char* xc = (char*) malloc(n * (unsigned) sizeof(char));
527  FRead(xc, sizeof(char), n, fp);
528  for (i = 0; i < n; ++i) {
529  vp->elem(i) = double(xc[i]);
530  }
531  free(xc);
532  break;
533  }
534  }
535  return 1;
536 }
537 
538 static double v_vwrite(void* v) {
539  Vect* vp = (Vect*) v;
540 
541  Object* ob = *hoc_objgetarg(1);
542  check_obj_type(ob, "File");
543  OcFile* f = (OcFile*) (ob->u.this_pointer);
544 
545  FILE* fp = f->file();
546  if (!fp) {
547  return 0.;
548  }
549 
550  BinaryMode(f)
551  // first, write the size of the vector
552  int n = vp->size();
553  FWrite(&n, sizeof(int), 1, fp);
554 
555  // next, write the type of elements
556  int type = 4;
557  if (ifarg(2)) {
558  type = int(chkarg(2, 1, 5));
559  }
560  FWrite(&type, sizeof(int), 1, fp);
561 
562  // convert the data if necessary
563  int i;
564  void* s;
565  const char* x;
566 
567  double min, max, r, sf, sub, intermed;
568  switch (type) {
569  case 5: // integers as ints (no scaling)
570  {
571  int* xi = (int*) malloc(n * sizeof(int));
572  for (i = 0; i < n; ++i) {
573  xi[i] = (int) (vp->elem(i));
574  }
575  FWrite(xi, sizeof(int), n, fp);
576  free((char*) xi);
577  break;
578  }
579 
580  case 4: // doubles (no conversion unless BYTESWAP used and needed)
581  {
582  s = (void*) (&(vp->elem(0)));
583  x = (const char*) s;
584  FWrite(x, sizeof(double), n, fp);
585  break;
586  }
587 
588  case 3: // float (simple automatic type conversion)
589  {
590  float* xf = (float*) malloc(n * (unsigned) sizeof(float));
591  for (i = 0; i < n; ++i) {
592  xf[i] = float(vp->elem(i));
593  }
594  FWrite(xf, sizeof(float), n, fp);
595  free((char*) xf);
596  break;
597  }
598 
599 
600  case 2: // short ints (scale to 16 bits with compression)
601  {
602  auto minmax = std::minmax_element(vp->begin(), vp->end());
603  min = *minmax.first;
604  max = *minmax.second;
605  r = max - min;
606  if (r > 0) {
607  sf = TWO_BYTE_HIGH / r;
608  } else {
609  sf = 1.;
610  }
611  unsigned short* xi = (unsigned short*) malloc(n * (unsigned) sizeof(unsigned short));
612  for (i = 0; i < n; ++i) {
613  intermed = (vp->elem(i) - min) * sf;
614  xi[i] = (unsigned short) intermed;
615  }
616  s = (void*) xi;
617  x = (const char*) s;
618  // store the info needed to reconvert
619  FWrite(&sf, sizeof(double), 1, fp);
620  FWrite(&min, sizeof(double), 1, fp);
621  // store the actual data
622  FWrite(x, sizeof(unsigned short), n, fp);
623  free((char*) xi);
624  break;
625  }
626 
627  case 1: // char (scale to 8 bits with compression)
628  {
629  sub = ONE_BYTE_HALF;
630  auto minmax = std::minmax_element(vp->begin(), vp->end());
631  min = *minmax.first;
632  max = *minmax.second;
633  r = max - min;
634  if (r > 0) {
635  sf = ONE_BYTE_HIGH / r;
636  } else {
637  sf = 1.;
638  }
639 
640  char* xc = (char*) malloc(n * (unsigned) sizeof(char));
641  for (i = 0; i < n; ++i) {
642  xc[i] = char(((vp->elem(i) - min) * sf) - sub);
643  }
644  s = (void*) xc;
645  x = (const char*) s;
646  // store the info needed to reconvert
647  FWrite(&sf, sizeof(double), 1, fp);
648  FWrite(&min, sizeof(double), 1, fp);
649  FWrite(x, sizeof(char), n, fp);
650  free(xc);
651  break;
652  }
653  }
654  return 1;
655 }
656 
657 
658 static double v_vread(void* v) {
659  Vect* vp = (Vect*) v;
660  void* s = (void*) (vp->data());
661 
662  Object* ob = *hoc_objgetarg(1);
663  check_obj_type(ob, "File");
664  OcFile* f = (OcFile*) (ob->u.this_pointer);
665  BYTEHEADER
666 
667  FILE* fp = f->file();
668  if (!fp) {
669  return 0.;
670  }
671 
672  BinaryMode(f) int n;
673  FRead(&n, sizeof(int), 1, fp);
674 
675  int type = 0;
676  FRead(&type, sizeof(int), 1, fp);
677 
678  // since the type ranges from 1 to 5 (very important that it not be 0)
679  // we can check the type and decide if it needs to be byteswapped
680  if (type < 1 || type > 5) {
681  BYTESWAP_FLAG = 1;
682  } else {
683  BYTESWAP_FLAG = 0;
684  }
685 
686  BYTESWAP(n, int)
687  BYTESWAP(type, int)
688  if (type < 1 || type > 5) {
689  return 0.;
690  }
691  if (vp->size() != n)
692  vp->resize(n);
693 
694  // read as appropriate type and convert to doubles
695 
696  int i;
697  double sf = 1.;
698  double min = 0.;
699  double add;
700 
701  switch (type) {
702  case 5: // ints; no conversion
703  {
704  int* xi = (int*) malloc(n * sizeof(int));
705  FRead(xi, sizeof(int), n, fp);
706  for (i = 0; i < n; ++i) {
707  BYTESWAP(xi[i], int)
708  vp->elem(i) = double(xi[i]);
709  }
710  free((char*) xi);
711  break;
712  }
713 
714  case 4: // doubles
715  FRead(&(vp->elem(0)), sizeof(double), n, fp);
716  if (BYTESWAP_FLAG == 1) {
717  for (i = 0; i < n; ++i) {
718  BYTESWAP(vp->elem(i), double)
719  }
720  }
721  break;
722 
723  case 3: // floats
724  {
725  float* xf = (float*) malloc(n * (unsigned) sizeof(float));
726  FRead(xf, sizeof(float), n, fp);
727  for (i = 0; i < n; ++i) {
728  BYTESWAP(xf[i], float)
729  vp->elem(i) = double(xf[i]);
730  }
731  free((char*) xf);
732  break;
733  }
734 
735  case 2: // unsigned short ints
736  { // convert back to double
737  FRead(&sf, sizeof(double), 1, fp);
738  FRead(&min, sizeof(double), 1, fp);
739  BYTESWAP(sf, double)
740  BYTESWAP(min, double)
741 
742  unsigned short* xi = (unsigned short*) malloc(n * (unsigned) sizeof(unsigned short));
743  FRead(xi, sizeof(unsigned short), n, fp);
744  for (i = 0; i < n; ++i) {
745  BYTESWAP(xi[i], short)
746  vp->elem(i) = double(xi[i] / sf + min);
747  }
748  free((char*) xi);
749  break;
750  }
751 
752  case 1: // char
753  { // convert back to double
754  FRead(&sf, sizeof(double), 1, fp);
755  FRead(&min, sizeof(double), 1, fp);
756  BYTESWAP(sf, double)
757  BYTESWAP(min, double)
758  char* xc = (char*) malloc(n * (unsigned) sizeof(char));
759  FRead(xc, sizeof(char), n, fp);
760  add = ONE_BYTE_HALF;
761  for (i = 0; i < n; ++i) {
762  vp->elem(i) = double((xc[i] + add) / sf + min);
763  }
764  free(xc);
765  break;
766  }
767  }
768  return 1;
769 }
770 
771 
772 static double v_printf(void* v) {
773  Vect* x = (Vect*) v;
774 
775  int top = x->size() - 1;
776  int start = 0;
777  int end = top;
778  int next_arg = 1;
779  const char* format = "%g\t";
780  int print_file = 0;
781  int extra_newline = 1; // when no File
782  OcFile* f;
783 
784  if (ifarg(next_arg) && (hoc_is_object_arg(next_arg))) {
785  Object* ob = *hoc_objgetarg(1);
786  check_obj_type(ob, "File");
787  f = (OcFile*) (ob->u.this_pointer);
788  format = "%g\n";
789  next_arg++;
790  print_file = 1;
791  }
792  if (ifarg(next_arg) && (hoc_argtype(next_arg) == STRING)) {
793  format = gargstr(next_arg);
794  next_arg++;
795  extra_newline = 0;
796  }
797  if (ifarg(next_arg)) {
798  start = int(chkarg(next_arg, 0, top));
799  end = int(chkarg(next_arg + 1, start, top));
800  }
801 
802  if (print_file) {
803  for (int i = start; i <= end; i++) {
804  fprintf(f->file(), format, x->elem(i));
805  }
806  fprintf(f->file(), "\n");
807  } else {
808  for (int i = start; i <= end; i++) {
809  Printf(format, x->elem(i));
810  if (extra_newline && !((i - start + 1) % 5)) {
811  Printf("\n");
812  }
813  }
814  if (extra_newline) {
815  Printf("\n");
816  }
817  }
818  hoc_return_type_code = 1; // integer
819  return double(end - start + 1);
820 }
821 
822 
823 static double v_scanf(void* v) {
824  Vect* x = (Vect*) v;
825 
826  int n = -1;
827  int c = 1;
828  int nc = 1;
829  Object* ob = *hoc_objgetarg(1);
830  check_obj_type(ob, "File");
831  OcFile* f = (OcFile*) (ob->u.this_pointer);
832 
833  hoc_return_type_code = 1; // integer
834 
835  if (ifarg(4)) {
836  n = int(*getarg(2));
837  c = int(*getarg(3));
838  nc = int(*getarg(4));
839  } else if (ifarg(3)) {
840  c = int(*getarg(2));
841  nc = int(*getarg(3));
842  } else if (ifarg(2)) {
843  n = int(*getarg(2));
844  }
845 
846  if (n >= 0) {
847  x->resize(n);
848  } else if (x->size()) { // gnuvec legacy handling
849  x->resize(0);
850  }
851 
852  // start at the right column
853 
854  int i = 0;
855 
856  while ((n < 0 || i < n) && !f->eof()) {
857  // skip unwanted columns before
858  int j;
859  for (j = 1; j < c; j++) {
860  if (!f->eof())
861  hoc_scan(f->file());
862  }
863 
864  // read data
865  if (!f->eof()) {
866  if (n >= 0)
867  x->elem(i) = hoc_scan(f->file());
868  else
869  x->push_back(hoc_scan(f->file()));
870  }
871 
872  // skip unwanted columns after
873  for (j = c; j < nc; j++) {
874  if (!f->eof())
875  hoc_scan(f->file());
876  }
877 
878  i++;
879  }
880 
881  if (x->size() != i)
882  x->resize(i);
883 
884  return double(i);
885 }
886 
887 static double v_scantil(void* v) {
888  Vect* x = (Vect*) v;
889  double val, til;
890 
891  int c = 1;
892  int nc = 1;
893  Object* ob = *hoc_objgetarg(1);
894  check_obj_type(ob, "File");
895  OcFile* f = (OcFile*) (ob->u.this_pointer);
896  // old gnuvec compatibility: clear vector if not empty()
897  if (x->size() > 0) {
898  x->resize(0);
899  }
900 
901  hoc_return_type_code = 1; // integer
902  til = *getarg(2);
903  if (ifarg(4)) {
904  c = int(*getarg(3));
905  nc = int(*getarg(4));
906  }
907 
908  // start at the right column
909 
910  int i = 0;
911 
912  for (;;) {
913  // skip unwanted columns before
914  int j;
915  for (j = 1; j < c; j++) {
916  if (hoc_scan(f->file()) == til) {
917  return double(i);
918  }
919  }
920 
921  // read data
922  val = hoc_scan(f->file());
923  if (val == til) {
924  break;
925  }
926  x->push_back(val);
927 
928  // skip unwanted columns after
929  for (j = c; j < nc; j++) {
930  hoc_scan(f->file());
931  }
932 
933  i++;
934  }
935  return double(i);
936 }
937 
938 
939 static Object** v_record(void* v) {
940  if (hoc_is_double_arg(1)) {
941  hoc_execerror("Vector.record:",
942  "A number was provided instead of a pointer.\nDid you forget an _ref_ "
943  "(Python) or an & (HOC)?");
944  }
945  Vect* vp = (Vect*) v;
946  nrn_vecsim_add(v, true);
947  return vp->temp_objvar();
948 }
949 
950 static Object** v_play(void* v) {
951  Vect* vp = (Vect*) v;
952  nrn_vecsim_add(v, false);
953  return vp->temp_objvar();
954 }
955 
956 /*ARGSUSED*/
957 static Object** v_plot(void* v) {
958  TRY_GUI_REDIRECT_METHOD_ACTUAL_OBJ("Vector.plot", svec_, v);
959  Vect* vp = (Vect*) v;
960 #if HAVE_IV
961  IFGUI
962  int i;
963  double* y = vp->data();
964  auto n = vp->size();
965 
966  Object* ob1 = *hoc_objgetarg(1);
967  check_obj_type(ob1, "Graph");
968  Graph* g = (Graph*) (ob1->u.this_pointer);
969 
970  GraphVector* gv = new GraphVector("");
971 
972  if (ifarg(5)) {
973  hoc_execerror("Vector.line:", "too many arguments");
974  }
975  if (narg() == 3) {
976  gv->color((colors->color(int(*getarg(2)))));
977  gv->brush((brushes->brush(int(*getarg(3)))));
978  } else if (narg() == 4) {
979  gv->color((colors->color(int(*getarg(3)))));
980  gv->brush((brushes->brush(int(*getarg(4)))));
981  }
982 
983  if (narg() == 2 || narg() == 4) {
984  // passed a vector or xinterval and possibly line attributes
985  if (hoc_is_object_arg(2)) {
986  // passed a vector
987  Vect* vp2 = vector_arg(2);
988  n = std::min(n, vp2->size());
989  for (i = 0; i < n; ++i)
990  gv->add(vp2->elem(i), y + i);
991  } else {
992  // passed xinterval
993  double interval = *getarg(2);
994  for (i = 0; i < n; ++i)
995  gv->add(i * interval, y + i);
996  }
997  } else {
998  // passed line attributes or nothing
999  for (i = 0; i < n; ++i)
1000  gv->add(i, y + i);
1001  }
1002 
1003  if (vp->label_) {
1004  GLabel* glab = g->label(vp->label_);
1005  gv->label(glab);
1006  ((GraphItem*) g->component(g->glyph_index(glab)))->save(false);
1007  }
1008  g->append(new GPolyLineItem(gv));
1009 
1010  g->flush();
1011  ENDGUI
1012 #endif
1013  return vp->temp_objvar();
1014 }
1015 
1016 static Object** v_ploterr(void* v) {
1017  TRY_GUI_REDIRECT_METHOD_ACTUAL_OBJ("Vector.ploterr", svec_, v);
1018  Vect* vp = (Vect*) v;
1019 #if HAVE_IV
1020  IFGUI
1021  int n = vp->size();
1022 
1023  Object* ob1 = *hoc_objgetarg(1);
1024  check_obj_type(ob1, "Graph");
1025  Graph* g = (Graph*) (ob1->u.this_pointer);
1026 
1027  char style = '-';
1028  double size = 4;
1029  if (ifarg(4))
1030  size = chkarg(4, 0.1, 100.);
1031  const ivColor* color = g->color();
1032  const ivBrush* brush = g->brush();
1033  if (ifarg(5)) {
1034  color = colors->color(int(*getarg(5)));
1035  brush = brushes->brush(int(*getarg(6)));
1036  }
1037 
1038  Vect* vp2 = vector_arg(2);
1039  if (vp2->size() < n)
1040  n = vp2->size();
1041 
1042  Vect* vp3 = vector_arg(3);
1043  if (vp3->size() < n)
1044  n = vp3->size();
1045 
1046  for (int i = 0; i < n; ++i) {
1047  g->begin_line();
1048 
1049  g->line(vp2->elem(i), vp->elem(i) - vp3->elem(i));
1050  g->line(vp2->elem(i), vp->elem(i) + vp3->elem(i));
1051  g->mark(vp2->elem(i), vp->elem(i) - vp3->elem(i), style, size, color, brush);
1052  g->mark(vp2->elem(i), vp->elem(i) + vp3->elem(i), style, size, color, brush);
1053  }
1054 
1055  g->flush();
1056  ENDGUI
1057 #endif
1058  return vp->temp_objvar();
1059 }
1060 
1061 static Object** v_line(void* v) {
1062  TRY_GUI_REDIRECT_METHOD_ACTUAL_OBJ("Vector.line", svec_, v);
1063  Vect* vp = (Vect*) v;
1064 #if HAVE_IV
1065  IFGUI
1066  int i;
1067  auto n = vp->size();
1068 
1069  Object* ob1 = *hoc_objgetarg(1);
1070  check_obj_type(ob1, "Graph");
1071  Graph* g = (Graph*) (ob1->u.this_pointer);
1072  char* s = vp->label_;
1073 
1074  if (ifarg(5)) {
1075  hoc_execerror("Vector.line:", "too many arguments");
1076  }
1077  if (narg() == 3) {
1078  g->begin_line(colors->color(int(*getarg(2))), brushes->brush(int(*getarg(3))), s);
1079  } else if (narg() == 4) {
1080  g->begin_line(colors->color(int(*getarg(3))), brushes->brush(int(*getarg(4))), s);
1081  } else {
1082  g->begin_line(s);
1083  }
1084 
1085  if (narg() == 2 || narg() == 4) {
1086  // passed a vector or xinterval and possibly line attributes
1087  if (hoc_is_object_arg(2)) {
1088  // passed a vector
1089  Vect* vp2 = vector_arg(2);
1090  n = std::min(n, vp2->size());
1091  for (i = 0; i < n; ++i)
1092  g->line(vp2->elem(i), vp->elem(i));
1093  } else {
1094  // passed xinterval
1095  double interval = *getarg(2);
1096  for (i = 0; i < n; ++i)
1097  g->line(i * interval, vp->elem(i));
1098  }
1099  } else {
1100  // passed line attributes or nothing
1101  for (i = 0; i < n; ++i)
1102  g->line(i, vp->elem(i));
1103  }
1104 
1105  g->flush();
1106  ENDGUI
1107 #endif
1108  return vp->temp_objvar();
1109 }
1110 
1111 
1112 static Object** v_mark(void* v) {
1113  TRY_GUI_REDIRECT_METHOD_ACTUAL_OBJ("Vector.mark", svec_, v);
1114  Vect* vp = (Vect*) v;
1115 #if HAVE_IV
1116  IFGUI
1117  int i;
1118  int n = vp->size();
1119 
1120  Object* ob1 = *hoc_objgetarg(1);
1121  check_obj_type(ob1, "Graph");
1122  Graph* g = (Graph*) (ob1->u.this_pointer);
1123 
1124  char style = '+';
1125  if (ifarg(3)) {
1126  if (hoc_is_str_arg(3)) {
1127  style = *gargstr(3);
1128  } else {
1129  style = char(chkarg(3, 0, 10));
1130  }
1131  }
1132  double size = 12;
1133  if (ifarg(4))
1134  size = chkarg(4, 0.1, 100.);
1135  const ivColor* color = g->color();
1136  if (ifarg(5))
1137  color = colors->color(int(*getarg(5)));
1138  const ivBrush* brush = g->brush();
1139  if (ifarg(6))
1140  brush = brushes->brush(int(*getarg(6)));
1141 
1142  if (hoc_is_object_arg(2)) {
1143  // passed a vector
1144  Vect* vp2 = vector_arg(2);
1145 
1146  for (i = 0; i < n; ++i) {
1147  g->mark(vp2->elem(i), vp->elem(i), style, size, color, brush);
1148  }
1149 
1150  } else {
1151  // passed xinterval
1152  double interval = *getarg(2);
1153  for (i = 0; i < n; ++i) {
1154  g->mark(i * interval, vp->elem(i), style, size, color, brush);
1155  }
1156  }
1157  ENDGUI
1158 #endif
1159  return vp->temp_objvar();
1160 }
1161 
1162 static Object** v_histogram(void* v) {
1163  Vect* x = (Vect*) v;
1164 
1165  double low = *getarg(1);
1166  double high = chkarg(2, low, 1e99);
1167  double width = chkarg(3, 0, high - low);
1168 
1169  // SampleHistogram h(low,high,width);
1170  int i;
1171  // for (i=0; i< x->size(); i++) h += x->elem(i);
1172 
1173  // int n = h.buckets();
1174  // analogous to howManyBuckets in gnu/SamplHist.cpp
1175  int n = int(floor((high - low) / width)) + 2;
1176  Vect* y = new Vect(n);
1177  std::fill(y->begin(), y->end(), 0.);
1178  // for (i=0; i< n; i++) y->elem(i) = h.inBucket(i);
1179 
1180  for (i = 0; i < x->size(); ++i) {
1181  int ind = int(floor((x->elem(i) - low) / width)) + 1;
1182  if (ind >= 0 && ind < y->size()) {
1183  y->elem(ind) += 1.0;
1184  }
1185  }
1186  return y->temp_objvar();
1187 }
1188 
1189 static Object** v_hist(void* v) {
1190  Vect* hv = (Vect*) v;
1191 
1192  Vect* data = vector_arg(1);
1193  same_err("hist", hv, data);
1194  double start = *getarg(2);
1195  int size = int(*getarg(3));
1196  double step = chkarg(4, 1.e-99, 1.e99);
1197  double high = start + step * size;
1198 
1199  // SampleHistogram h(start,high,step);
1200  // for (int i=0; i< data->size(); i++) h += data->elem(i);
1201 
1202  if (hv->size() != size)
1203  hv->resize(size);
1204  std::fill(hv->begin(), hv->end(), 0.);
1205  for (int i = 0; i < data->size(); i++) {
1206  int ind = int(floor((data->elem(i) - start) / step));
1207  if (ind >= 0 && ind < hv->size())
1208  hv->elem(ind) += 1;
1209  }
1210 
1211  // for (i=0; i< size; i++) hv->elem(i) = h.inBucket(i);
1212 
1213  return hv->temp_objvar();
1214 }
1215 
1216 
1217 static Object** v_sumgauss(void* v) {
1218  Vect* x = (Vect*) v;
1219 
1220  double low = *getarg(1);
1221  double high = chkarg(2, low, 1e99);
1222  double step = chkarg(3, 1.e-99, 1.e99);
1223  double var = chkarg(4, 0, 1.e99);
1224  Vect* w;
1225  bool d = false;
1226  if (ifarg(5)) {
1227  w = vector_arg(5);
1228  } else {
1229  w = new Vect(x->size());
1230  std::fill(w->begin(), w->end(), 1);
1231  d = true;
1232  }
1233 
1234  int points = int((high - low) / step + .5);
1235  Vect* sum = new Vect(points, 0.);
1236 
1237  double svar = var / (step * step);
1238 
1239  // 4/28/93 ZFM: corrected bug: replaced svar w/ var in line below
1240  double scale = 1. / hoc_Sqrt(2. * PI * var);
1241 
1242  for (int i = 0; i < x->size(); i++) {
1243  double xv = int((x->elem(i) - low) / step);
1244  for (int j = 0; j < points; j++) {
1245  double arg = -(j - xv) * (j - xv) / (2. * svar);
1246  if (arg > -20.)
1247  sum->elem(j) += hoc_Exp(arg) * scale * w->elem(i);
1248  }
1249  }
1250  if (d) {
1251  delete w;
1252  }
1253  return sum->temp_objvar();
1254 }
1255 
1256 static Object** v_smhist(void* v) {
1257  Vect* v1 = (Vect*) v;
1258 
1259  Vect* data = vector_arg(1);
1260 
1261  double start = *getarg(2);
1262  int size = int(*getarg(3));
1263  double step = chkarg(4, 1.e-99, 1.e99);
1264  double var = chkarg(5, 0, 1.e99);
1265 
1266  int weight, i;
1267  Vect* w;
1268 
1269  if (ifarg(6)) {
1270  w = vector_arg(6);
1271  if (w->size() != data->size()) {
1272  hoc_execerror("Vector.smhist: weight Vector must be same size as source Vector.", 0);
1273  }
1274  weight = 1;
1275  } else {
1276  weight = 0;
1277  }
1278 
1279 
1280  // ready a gaussian to convolve
1281  double svar = 2 * var / (step * step);
1282  double scale = 1 / hoc_Sqrt(2. * PI * var);
1283 
1284  int g2 = int(sqrt(10 * svar));
1285  int g = g2 * 2 + 1;
1286 
1287  int n = 1;
1288  while (n < size + g)
1289  n *= 2;
1290 
1291  double* gauss = (double*) calloc(n, (unsigned) sizeof(double));
1292 
1293  for (i = 0; i <= g2; i++)
1294  gauss[i] = scale * hoc_Exp(-i * i / svar);
1295  for (i = 1; i <= g2; i++)
1296  gauss[g - i] = scale * hoc_Exp(-i * i / svar);
1297 
1298  // put the data into a time series
1299  double* series = (double*) calloc(n, (unsigned) sizeof(double));
1300 
1301  double high = start + n * step;
1302  if (weight) {
1303  for (i = 0; i < data->size(); i++) {
1304  if (data->elem(i) >= start && data->elem(i) < high) {
1305  series[int((data->elem(i) - start) / step)] += w->elem(i);
1306  }
1307  }
1308  } else {
1309  for (i = 0; i < data->size(); i++) {
1310  if (data->elem(i) >= start && data->elem(i) < high) {
1311  series[int((data->elem(i) - start) / step)] += 1.;
1312  }
1313  }
1314  }
1315 
1316  // ready the answer vector
1317  double* ans = (double*) calloc(2 * n, (unsigned) sizeof(double));
1318 
1319  // convolve
1320  nrn_convlv(series, n, gauss, g, 1, ans);
1321 
1322  // put the answer in the vector
1323  if (v1->size() != size)
1324  v1->resize(size);
1325  std::fill(v1->begin(), v1->end(), 0.);
1326  for (i = 0; i < size; i++)
1327  if (ans[i] > EPSILON)
1328  v1->elem(i) = ans[i];
1329 
1330  free(series);
1331  free(gauss);
1332  free(ans);
1333 
1334  return v1->temp_objvar();
1335 }
1336 
1337 
1338 static Object** v_ind(void* v) {
1339  Vect* x = (Vect*) v;
1340  Vect* y = vector_arg(1);
1341  Vect* z = new Vect();
1342 
1343  int yv;
1344  int ztop = 0;
1345  int top = x->size();
1346  z->resize(y->size());
1347  z->resize(0);
1348  for (int i = 0; i < y->size(); i++) {
1349  yv = int(y->elem(i));
1350  if ((yv < top) && (yv >= 0)) {
1351  z->resize(++ztop);
1352  z->elem(ztop - 1) = x->elem(yv);
1353  }
1354  }
1355  return z->temp_objvar();
1356 }
1357 
1358 
1359 static double v_size(void* v) {
1360  Vect* x = (Vect*) v;
1362  return double(x->size());
1363 }
1364 
1365 static double v_buffer_size(void* v) {
1366  Vect* x = (Vect*) v;
1367  if (ifarg(1)) {
1368  int n = (int) chkarg(1, (double) x->size(), dmaxint_);
1369  x->buffer_size(n);
1370  }
1372  return x->buffer_size();
1373 }
1374 
1376  return vec_.capacity();
1377 }
1378 
1380  vec_.reserve(n);
1381 }
1382 
1383 static Object** v_resize(void* v) {
1384  Vect* x = (Vect*) v;
1385  x->resize(int(chkarg(1, 0, dmaxint_)));
1386  return x->temp_objvar();
1387 }
1388 
1389 static Object** v_clear(void* v) {
1390  Vect* x = (Vect*) v;
1391  x->resize(0);
1392  return x->temp_objvar();
1393 }
1394 
1395 static double v_get(void* v) {
1396  Vect* x = (Vect*) v;
1397  return x->elem(int(chkarg(1, 0, x->size() - 1)));
1398 }
1399 
1400 static Object** v_set(void* v) {
1401  Vect* x = (Vect*) v;
1402  x->elem(int(chkarg(1, 0, x->size() - 1))) = *getarg(2);
1403  return x->temp_objvar();
1404 }
1405 
1406 
1407 static Object** v_append(void* v) {
1408  Vect* x = (Vect*) v;
1409  int j, i = 1;
1410  while (ifarg(i)) {
1411  if (hoc_argtype(i) == NUMBER) {
1412  x->push_back(*getarg(i));
1413  } else if (hoc_is_object_arg(i)) {
1414  Vect* y = vector_arg(i);
1415  same_err("append", x, y);
1416  x->buffer_size(x->size() + y->size());
1417  x->vec().insert(x->end(), y->begin(), y->end());
1418  }
1419  i++;
1420  }
1421  return x->temp_objvar();
1422 }
1423 
1424 static Object** v_insert(void* v) {
1425  // insert all before indx (first arg)
1426  Vect* x = (Vect*) v;
1427  int n, j, m, i = 2;
1428  int indx = (int) chkarg(1, 0, x->size());
1429  m = x->size() - indx;
1430  double* z;
1431  if (m) {
1432  z = new double[m];
1433  for (j = 0; j < m; ++j) {
1434  z[j] = x->elem(indx + j);
1435  }
1436  }
1437  x->resize(indx);
1438  while (ifarg(i)) {
1439  if (hoc_argtype(i) == NUMBER) {
1440  x->push_back(*getarg(i));
1441  } else if (hoc_is_object_arg(i)) {
1442  Vect* y = vector_arg(i);
1443  same_err("insrt", x, y);
1444  n = x->size();
1445  x->buffer_size(n + y->size());
1446  x->vec().insert(x->end(), y->begin(), y->end());
1447  }
1448  i++;
1449  }
1450  if (m) {
1451  n = x->size();
1452  x->resize(n + m);
1453  for (j = 0; j < m; ++j) {
1454  x->elem(n + j) = z[j];
1455  }
1456  delete[] z;
1457  }
1458  return x->temp_objvar();
1459 }
1460 
1461 static Object** v_remove(void* v) {
1462  Vect* x = (Vect*) v;
1463  int i, j, n, start, end;
1464  start = (int) chkarg(1, 0, x->size() - 1);
1465  if (ifarg(2)) {
1466  end = (int) chkarg(2, start, x->size() - 1);
1467  } else {
1468  end = start;
1469  }
1470  n = x->size();
1471  for (i = start, j = end + 1; j < n; ++i, ++j) {
1472  x->elem(i) = x->elem(j);
1473  }
1474  x->resize(i);
1475  return x->temp_objvar();
1476 }
1477 
1478 static double v_contains(void* v) {
1479  Vect* x = (Vect*) v;
1480  double g = *getarg(1);
1482  for (int i = 0; i < x->size(); i++) {
1483  if (Math::equal(x->elem(i), g, hoc_epsilon))
1484  return 1.;
1485  }
1486  return 0.;
1487 }
1488 
1489 
1490 static Object** v_copy(void* v) {
1491  Vect* y = (Vect*) v;
1492 
1493  Vect* x = vector_arg(1);
1494 
1495  int top = x->size() - 1;
1496  int srcstart = 0;
1497  int srcend = top;
1498  int srcinc = 1;
1499 
1500  int deststart = 0;
1501  int destinc = 1;
1502 
1503  if (ifarg(2) && hoc_is_object_arg(2)) {
1504  Vect* srcind = vector_arg(2);
1505  int ns = srcind->size();
1506  int nx = x->size();
1507  if (ifarg(3)) {
1508  Vect* destind = vector_arg(3);
1509  if (destind->size() < ns) {
1510  ns = destind->size();
1511  }
1512  int ny = y->size();
1513  for (int i = 0; i < ns; ++i) {
1514  int ix = (int) (srcind->elem(i) + hoc_epsilon);
1515  int iy = (int) (destind->elem(i) + hoc_epsilon);
1516  if (ix >= 0 && iy >= 0 && ix < nx && iy < ny) {
1517  y->elem(iy) = x->elem(ix);
1518  }
1519  }
1520  } else {
1521  if (y->size() < nx) {
1522  nx = y->size();
1523  }
1524  for (int i = 0; i < ns; ++i) {
1525  int ii = (int) (srcind->elem(i) + hoc_epsilon);
1526  if (ii >= 0 && ii < nx) {
1527  y->elem(ii) = x->elem(ii);
1528  }
1529  }
1530  }
1531  return y->temp_objvar();
1532  }
1533 
1534  if (ifarg(2) && !(ifarg(3))) {
1535  deststart = int(*getarg(2));
1536  } else {
1537  if (ifarg(4)) {
1538  deststart = int(*getarg(2));
1539  srcstart = int(chkarg(3, 0, top));
1540  srcend = int(chkarg(4, -1, top));
1541  if (ifarg(5)) {
1542  destinc = int(chkarg(5, 1, dmaxint_));
1543  srcinc = int(chkarg(6, 1, dmaxint_));
1544  }
1545  } else if (ifarg(3)) {
1546  srcstart = int(chkarg(2, 0, top));
1547  srcend = int(chkarg(3, -1, top));
1548  }
1549  }
1550  if (srcend == -1) {
1551  srcend = top;
1552  } else if (srcend < srcstart) {
1553  hoc_execerror("Vector.copy: src_end arg smaller than src_start", 0);
1554  }
1555  int size = (srcend - srcstart) / srcinc;
1556  size *= destinc;
1557  size += deststart + 1;
1558  if (y->size() < size) {
1559  y->resize(size);
1560  } else if (y->size() > size && !ifarg(2)) {
1561  y->resize(size);
1562  }
1563  int i, j;
1564  for (i = srcstart, j = deststart; i <= srcend; i += srcinc, j += destinc) {
1565  y->elem(j) = x->elem(i);
1566  }
1567 
1568  return y->temp_objvar();
1569 }
1570 
1571 
1572 static Object** v_at(void* v) {
1573  auto* x = static_cast<Vect*>(v);
1574  std::size_t start{};
1575  std::size_t end{x->size()};
1576  if (ifarg(1)) {
1577  start = chkarg(1, 0, x->size() - 1);
1578  }
1579  if (ifarg(2)) {
1580  end = chkarg(2, start, x->size() - 1) + 1.0;
1581  }
1582  std::size_t size{end - start};
1583  auto* y = new Vect(size);
1584  // ZFM: fixed bug -- i<size, not i<=size
1585  for (std::size_t i = 0; i < size; ++i) {
1586  y->elem(i) = x->elem(i + start);
1587  }
1588  return y->temp_objvar();
1589 }
1590 
1591 typedef struct {
1592  double x;
1593  int i;
1594 } SortIndex;
1595 
1596 static int sort_index_cmp(const void* a, const void* b) {
1597  double x = ((SortIndex*) a)->x;
1598  double y = ((SortIndex*) b)->x;
1599  if (x > y)
1600  return (1);
1601  if (x < y)
1602  return (-1);
1603  return (0);
1604 }
1605 
1606 static Object** v_sortindex(void* v) {
1607  // v.index(vsrc, vsrc.sortindex) sorts vsrc into v
1608  int i, n;
1609  Vect* x = (Vect*) v;
1610  n = x->size();
1611  Vect* y;
1612  possible_destvec(1, y);
1613  y->resize(n);
1614 
1615  SortIndex* si = new SortIndex[n];
1616  for (i = 0; i < n; ++i) {
1617  si[i].i = i;
1618  si[i].x = x->elem(i);
1619  }
1620 
1621  // On BlueGene
1622  // qsort apparently can generate errno 38 "Function not implemented"
1623  qsort((void*) si, n, sizeof(SortIndex), sort_index_cmp);
1624  errno = 0;
1625  for (i = 0; i < n; i++)
1626  y->elem(i) = (double) si[i].i;
1627 
1628  delete[] si;
1629  return y->temp_objvar();
1630 }
1631 
1632 static Object** v_c(void* v) {
1633  return v_at(v);
1634 }
1635 
1636 static Object** v_cl(void* v) {
1637  Object** r = v_at(v);
1638  ((Vect*) ((*r)->u.this_pointer))->label(((Vect*) v)->label_);
1639  return r;
1640 }
1641 
1642 static Object** v_interpolate(void* v) {
1643  Vect* yd = (Vect*) v;
1644  Vect* xd = vector_arg(1);
1645  Vect* xs = vector_arg(2);
1646  Vect* ys;
1647  int flag, is, id, nd, ns;
1648  double thet;
1649  ns = xs->size();
1650  nd = xd->size();
1651  if (ifarg(3)) {
1652  ys = vector_arg(3);
1653  flag = 0;
1654  } else {
1655  ys = new Vect(*yd);
1656  flag = 1;
1657  }
1658  yd->resize(nd);
1659  // before domain
1660  for (id = 0; id < nd && xd->elem(id) <= xs->elem(0); ++id) {
1661  yd->elem(id) = ys->elem(0);
1662  }
1663  // in domain
1664  for (is = 1; is < ns && id < nd; ++is) {
1665  if (xs->elem(is) <= xs->elem(is - 1)) {
1666  continue;
1667  }
1668  while (xd->elem(id) <= xs->elem(is)) {
1669  thet = (xd->elem(id) - xs->elem(is - 1)) / (xs->elem(is) - xs->elem(is - 1));
1670  yd->elem(id) = (1. - thet) * (ys->elem(is - 1)) + thet * (ys->elem(is));
1671  ++id;
1672  if (id >= nd) {
1673  break;
1674  }
1675  }
1676  }
1677  // after domain
1678  for (; id < nd; ++id) {
1679  yd->elem(id) = ys->elem(ns - 1);
1680  }
1681 
1682  if (flag) {
1683  delete ys;
1684  }
1685 
1686  return yd->temp_objvar();
1687 }
1688 
1689 static int possible_srcvec(Vect*& src, Vect* dest, int& flag) {
1690  if (ifarg(1) && hoc_is_object_arg(1)) {
1691  src = vector_arg(1);
1692  flag = 0;
1693  return 2;
1694  } else {
1695  src = new Vect(*dest);
1696  flag = 1;
1697  return 1;
1698  }
1699 }
1700 
1701 static Object** v_where(void* v) {
1702  Vect* y = (Vect*) v;
1703  Vect* x;
1704  int iarg, flag;
1705 
1706  iarg = possible_srcvec(x, y, flag);
1707 
1708  int n = x->size();
1709  int m = 0;
1710  int i;
1711 
1712  char* op = gargstr(iarg++);
1713  double value = *getarg(iarg++);
1714  double value2;
1715 
1716  y->resize(0);
1717 
1718  if (!strcmp(op, "==")) {
1719  for (i = 0; i < n; i++) {
1720  if (Math::equal(x->elem(i), value, hoc_epsilon)) {
1721  // y->resize_chunk(++m);
1722  // y->elem(m-1) = x->elem(i);
1723  y->push_back(x->elem(i));
1724  }
1725  }
1726  } else if (!strcmp(op, "!=")) {
1727  for (i = 0; i < n; i++) {
1728  if (!Math::equal(x->elem(i), value, hoc_epsilon)) {
1729  y->push_back(x->elem(i));
1730  }
1731  }
1732  } else if (!strcmp(op, ">")) {
1733  for (i = 0; i < n; i++) {
1734  if (x->elem(i) > value + hoc_epsilon) {
1735  y->push_back(x->elem(i));
1736  }
1737  }
1738  } else if (!strcmp(op, "<")) {
1739  for (i = 0; i < n; i++) {
1740  if (x->elem(i) < value - hoc_epsilon) {
1741  y->push_back(x->elem(i));
1742  }
1743  }
1744  } else if (!strcmp(op, ">=")) {
1745  for (i = 0; i < n; i++) {
1746  if (x->elem(i) >= value - hoc_epsilon) {
1747  y->push_back(x->elem(i));
1748  }
1749  }
1750  } else if (!strcmp(op, "<=")) {
1751  for (i = 0; i < n; i++) {
1752  if (x->elem(i) <= value + hoc_epsilon) {
1753  y->push_back(x->elem(i));
1754  }
1755  }
1756  } else if (!strcmp(op, "()")) {
1757  value2 = *getarg(iarg);
1758  for (i = 0; i < n; i++) {
1759  if ((x->elem(i) > value + hoc_epsilon) && (x->elem(i) < value2 - hoc_epsilon)) {
1760  y->push_back(x->elem(i));
1761  }
1762  }
1763  } else if (!strcmp(op, "[]")) {
1764  value2 = *getarg(iarg);
1765  for (i = 0; i < n; i++) {
1766  if ((x->elem(i) >= value - hoc_epsilon) && (x->elem(i) <= value2 + hoc_epsilon)) {
1767  y->push_back(x->elem(i));
1768  }
1769  }
1770  } else if (!strcmp(op, "[)")) {
1771  value2 = *getarg(iarg);
1772  for (i = 0; i < n; i++) {
1773  if ((x->elem(i) >= value - hoc_epsilon) && (x->elem(i) < value2 - hoc_epsilon)) {
1774  y->push_back(x->elem(i));
1775  }
1776  }
1777  } else if (!strcmp(op, "(]")) {
1778  value2 = *getarg(iarg);
1779  for (i = 0; i < n; i++) {
1780  if ((x->elem(i) > value + hoc_epsilon) && (x->elem(i) <= value2 + hoc_epsilon)) {
1781  y->push_back(x->elem(i));
1782  }
1783  }
1784  } else {
1785  hoc_execerror("Vector", "Invalid comparator in .where()\n");
1786  }
1787  if (flag) {
1788  delete x;
1789  }
1790  return y->temp_objvar();
1791 }
1792 
1793 static double v_indwhere(void* v) {
1794  Vect* x = (Vect*) v;
1795  int i, iarg, m = 0;
1796  char* op;
1797  double value, value2;
1799  op = gargstr(1);
1800  value = *getarg(2);
1801  iarg = 3;
1802 
1803  int n = x->size();
1804 
1805 
1806  if (!strcmp(op, "==")) {
1807  for (i = 0; i < n; i++) {
1808  if (Math::equal(x->elem(i), value, hoc_epsilon)) {
1809  return i;
1810  }
1811  }
1812  } else if (!strcmp(op, "!=")) {
1813  for (i = 0; i < n; i++) {
1814  if (!Math::equal(x->elem(i), value, hoc_epsilon)) {
1815  return i;
1816  }
1817  }
1818  } else if (!strcmp(op, ">")) {
1819  for (i = 0; i < n; i++) {
1820  if (x->elem(i) > value + hoc_epsilon) {
1821  return i;
1822  }
1823  }
1824  } else if (!strcmp(op, "<")) {
1825  for (i = 0; i < n; i++) {
1826  if (x->elem(i) < value - hoc_epsilon) {
1827  return i;
1828  }
1829  }
1830  } else if (!strcmp(op, ">=")) {
1831  for (i = 0; i < n; i++) {
1832  if (x->elem(i) >= value - hoc_epsilon) {
1833  return i;
1834  }
1835  }
1836  } else if (!strcmp(op, "<=")) {
1837  for (i = 0; i < n; i++) {
1838  if (x->elem(i) <= value + hoc_epsilon) {
1839  return i;
1840  }
1841  }
1842  } else if (!strcmp(op, "()")) {
1843  value2 = *getarg(iarg);
1844  for (i = 0; i < n; i++) {
1845  if ((x->elem(i) > value + hoc_epsilon) && (x->elem(i) < value2 - hoc_epsilon)) {
1846  return i;
1847  }
1848  }
1849  } else if (!strcmp(op, "[]")) {
1850  value2 = *getarg(iarg);
1851  for (i = 0; i < n; i++) {
1852  if ((x->elem(i) >= value - hoc_epsilon) && (x->elem(i) <= value2 + hoc_epsilon)) {
1853  return i;
1854  }
1855  }
1856  } else if (!strcmp(op, "[)")) {
1857  value2 = *getarg(iarg);
1858  for (i = 0; i < n; i++) {
1859  if ((x->elem(i) >= value - hoc_epsilon) && (x->elem(i) < value2 - hoc_epsilon)) {
1860  return i;
1861  }
1862  }
1863  } else if (!strcmp(op, "(]")) {
1864  value2 = *getarg(iarg);
1865  for (i = 0; i < n; i++) {
1866  if ((x->elem(i) > value + hoc_epsilon) && (x->elem(i) <= value2 + hoc_epsilon)) {
1867  return i;
1868  }
1869  }
1870  } else {
1871  hoc_execerror("Vector", "Invalid comparator in .indwhere()\n");
1872  }
1873 
1874  return -1.;
1875 }
1876 
1877 static Object** v_indvwhere(void* v) {
1878  Vect* y = (Vect*) v;
1879  Vect* x;
1880  int i, iarg, m = 0, flag;
1881  char* op;
1882  double value, value2;
1883 
1884  iarg = possible_srcvec(x, y, flag);
1885  op = gargstr(iarg++);
1886  value = *getarg(iarg++);
1887  y->resize(0);
1888 
1889  int n = x->size();
1890 
1891 
1892  if (!strcmp(op, "==")) {
1893  for (i = 0; i < n; i++) {
1894  if (Math::equal(x->elem(i), value, hoc_epsilon)) {
1895  y->push_back(i);
1896  }
1897  }
1898  } else if (!strcmp(op, "!=")) {
1899  for (i = 0; i < n; i++) {
1900  if (!Math::equal(x->elem(i), value, hoc_epsilon)) {
1901  y->push_back(i);
1902  }
1903  }
1904  } else if (!strcmp(op, ">")) {
1905  for (i = 0; i < n; i++) {
1906  if (x->elem(i) > value + hoc_epsilon) {
1907  y->push_back(i);
1908  }
1909  }
1910  } else if (!strcmp(op, "<")) {
1911  for (i = 0; i < n; i++) {
1912  if (x->elem(i) < value - hoc_epsilon) {
1913  y->push_back(i);
1914  }
1915  }
1916  } else if (!strcmp(op, ">=")) {
1917  for (i = 0; i < n; i++) {
1918  if (x->elem(i) >= value - hoc_epsilon) {
1919  y->push_back(i);
1920  }
1921  }
1922  } else if (!strcmp(op, "<=")) {
1923  for (i = 0; i < n; i++) {
1924  if (x->elem(i) <= value + hoc_epsilon) {
1925  y->push_back(i);
1926  }
1927  }
1928  } else if (!strcmp(op, "()")) {
1929  value2 = *getarg(iarg);
1930  for (i = 0; i < n; i++) {
1931  if ((x->elem(i) > value + hoc_epsilon) && (x->elem(i) < value2 - hoc_epsilon)) {
1932  y->push_back(i);
1933  }
1934  }
1935  } else if (!strcmp(op, "[]")) {
1936  value2 = *getarg(iarg);
1937  for (i = 0; i < n; i++) {
1938  if ((x->elem(i) >= value - hoc_epsilon) && (x->elem(i) <= value2 + hoc_epsilon)) {
1939  y->push_back(i);
1940  }
1941  }
1942  } else if (!strcmp(op, "[)")) {
1943  value2 = *getarg(iarg);
1944  for (i = 0; i < n; i++) {
1945  if ((x->elem(i) >= value - hoc_epsilon) && (x->elem(i) < value2 - hoc_epsilon)) {
1946  y->push_back(i);
1947  }
1948  }
1949  } else if (!strcmp(op, "(]")) {
1950  value2 = *getarg(iarg);
1951  for (i = 0; i < n; i++) {
1952  if ((x->elem(i) > value + hoc_epsilon) && (x->elem(i) <= value2 + hoc_epsilon)) {
1953  y->push_back(i);
1954  }
1955  }
1956  } else {
1957  hoc_execerror("Vector", "Invalid comparator in .indvwhere()\n");
1958  }
1959 
1960  if (flag) {
1961  delete x;
1962  }
1963  return y->temp_objvar();
1964 }
1965 
1966 static Object** v_fill(void* v) {
1967  auto* x = static_cast<Vect*>(v);
1968  std::size_t start{};
1969  std::size_t end{x->size()};
1970  if (ifarg(2)) {
1971  start = chkarg(2, 0, x->size() - 1);
1972  end = chkarg(3, start, x->size() - 1) + 1.0;
1973  }
1974  std::fill(x->begin() + start, x->begin() + end, *getarg(1));
1975  return x->temp_objvar();
1976 }
1977 
1978 static Object** v_indgen(void* v) {
1979  Vect* x = (Vect*) v;
1980 
1981  int n = x->size();
1982 
1983  double start = 0.;
1984  double step = 1.;
1985  double end = double(n - 1);
1986 
1987  if (ifarg(1)) {
1988  if (ifarg(3)) {
1989  start = *getarg(1);
1990  end = *getarg(2);
1991  step =
1992  chkarg(3, Math::min(start - end, end - start), Math::max(start - end, end - start));
1993  double xn = floor((end - start) / step + EPSILON) + 1.;
1994  if (xn > dmaxint_) {
1995  hoc_execerror("size too large", 0);
1996  } else if (xn < 0) {
1997  hoc_execerror("empty set", 0);
1998  }
1999  n = int(xn);
2000  if (n != x->size())
2001  x->resize(n);
2002  } else if (ifarg(2)) {
2003  start = *getarg(1);
2004  step = chkarg(2, -dmaxint_, dmaxint_);
2005  } else {
2006  step = chkarg(1, -dmaxint_, dmaxint_);
2007  }
2008  }
2009  for (int i = 0; i < n; i++) {
2010  x->elem(i) = double(i) * step + start;
2011  }
2012  return x->temp_objvar();
2013 }
2014 
2015 static Object** v_addrand(void* v) {
2016  Vect* x = (Vect*) v;
2017  Object* ob = *hoc_objgetarg(1);
2018  check_obj_type(ob, "Random");
2019  Rand* r = (Rand*) (ob->u.this_pointer);
2020  int top = x->size() - 1;
2021  int start = 0;
2022  int end = top;
2023  if (ifarg(2)) {
2024  start = int(chkarg(2, 0, top));
2025  end = int(chkarg(3, start, top));
2026  }
2027  for (int i = start; i <= end; i++)
2028  x->elem(i) += (*(r->rand))();
2029  return x->temp_objvar();
2030 }
2031 
2032 static Object** v_setrand(void* v) {
2033  Vect* x = (Vect*) v;
2034  Object* ob = *hoc_objgetarg(1);
2035  check_obj_type(ob, "Random");
2036  Rand* r = (Rand*) (ob->u.this_pointer);
2037  int top = x->size() - 1;
2038  int start = 0;
2039  int end = top;
2040  if (ifarg(2)) {
2041  start = int(chkarg(2, 0, top));
2042  end = int(chkarg(3, start, top));
2043  }
2044  for (int i = start; i <= end; i++)
2045  x->elem(i) = (*(r->rand))();
2046  return x->temp_objvar();
2047 }
2048 
2049 
2050 static Object** v_apply(void* v) {
2051  Vect* x = (Vect*) v;
2052  char* func = gargstr(1);
2053  int top = x->size() - 1;
2054  int start = 0;
2055  int end = top;
2056  Object* ob;
2057  if (ifarg(2)) {
2058  start = int(chkarg(2, 0, top));
2059  end = int(chkarg(3, start, top));
2060  }
2061  Symbol* s = hoc_lookup(func);
2062  ob = hoc_thisobject;
2063  if (!s) {
2064  ob = NULL;
2066  if (!s) {
2067  hoc_execerror(func, " is undefined");
2068  }
2069  }
2070  for (int i = start; i <= end; i++) {
2071  hoc_pushx(x->elem(i));
2072  x->elem(i) = hoc_call_objfunc(s, 1, ob);
2073  }
2074  return x->temp_objvar();
2075 }
2076 
2077 static double v_reduce(void* v) {
2078  Vect* x = (Vect*) v;
2079  double base = 0;
2080  int top = x->size() - 1;
2081  int start = 0;
2082  int end = top;
2083  if (ifarg(3)) {
2084  start = int(chkarg(3, 0, top));
2085  end = int(chkarg(4, start, top));
2086  }
2087  char* func = gargstr(1);
2088  if (ifarg(2))
2089  base = *getarg(2);
2090  Symbol* s = hoc_lookup(func);
2091  if (!s) {
2092  hoc_execerror(func, " is undefined");
2093  }
2094  for (int i = start; i <= end; i++) {
2095  hoc_pushx(x->elem(i));
2096  base += hoc_call_func(s, 1);
2097  }
2098  return base;
2099 }
2100 
2101 
2102 static double v_min(void* v) {
2103  Vect* x = (Vect*) v;
2104  if (x->size() == 0) {
2105  return 0.0;
2106  }
2107  int x_max = x->size() - 1;
2108  if (ifarg(1)) {
2109  int start = int(chkarg(1, 0, x_max));
2110  int end = int(chkarg(2, start, x_max));
2111  return *std::min_element(x->begin() + start, x->begin() + end + 1);
2112  } else {
2113  return *std::min_element(x->begin(), x->end());
2114  }
2115 }
2116 
2117 static double v_min_ind(void* v) {
2118  Vect* x = (Vect*) v;
2119  if (x->size() == 0) {
2120  return -1.0;
2121  }
2122  int x_max = x->size() - 1;
2123  hoc_return_type_code = 1; // integer
2124  if (ifarg(1)) {
2125  int start = int(chkarg(1, 0, x_max));
2126  int end = int(chkarg(2, start, x_max));
2127  return std::min_element(x->begin() + start, x->begin() + end + 1) - x->begin() + start;
2128  } else {
2129  return std::min_element(x->begin(), x->end()) - x->begin();
2130  }
2131 }
2132 
2133 static double v_max(void* v) {
2134  Vect* x = (Vect*) v;
2135  if (x->size() == 0) {
2136  return 0.0;
2137  }
2138  int x_max = x->size() - 1;
2139  if (ifarg(1)) {
2140  int start = int(chkarg(1, 0, x_max));
2141  int end = int(chkarg(2, start, x_max));
2142  return *std::max_element(x->begin() + start, x->begin() + end + 1);
2143  } else {
2144  return *std::max_element(x->begin(), x->end());
2145  }
2146 }
2147 
2148 static double v_max_ind(void* v) {
2149  Vect* x = (Vect*) v;
2150  if (x->size() == 0) {
2151  return -1.0;
2152  }
2153  int x_max = x->size() - 1;
2154  hoc_return_type_code = 1; // integer
2155  if (ifarg(1)) {
2156  int start = int(chkarg(1, 0, x_max));
2157  int end = int(chkarg(2, start, x_max));
2158  return std::max_element(x->begin() + start, x->begin() + end + 1) - x->begin() + start;
2159  } else {
2160  return std::max_element(x->begin(), x->end()) - x->begin();
2161  }
2162 }
2163 
2164 static double v_sum(void* v) {
2165  Vect* x = (Vect*) v;
2166  int x_max = x->size() - 1;
2167  if (ifarg(1)) {
2168  int start = int(chkarg(1, 0, x_max));
2169  int end = int(chkarg(2, start, x_max));
2170  return std::accumulate(x->begin() + start, x->begin() + end + 1, 0.);
2171  } else {
2172  return std::accumulate(x->begin(), x->end(), 0.);
2173  }
2174 }
2175 
2176 static double v_sumsq(void* v) {
2177  Vect* x = (Vect*) v;
2178  int x_max = x->size() - 1;
2179  if (ifarg(1)) {
2180  int start = int(chkarg(1, 0, x_max));
2181  int end = int(chkarg(2, start, x_max));
2182  return std::inner_product(x->begin() + start, x->begin() + end + 1, x->begin() + start, 0.);
2183  } else {
2184  return std::inner_product(x->begin(), x->end(), x->begin(), 0.);
2185  }
2186 }
2187 
2188 static double v_mean(void* v) {
2189  Vect* x = (Vect*) v;
2190  int x_max = x->size() - 1;
2191  if (ifarg(1)) {
2192  int start = int(chkarg(1, 0, x_max));
2193  int end = int(chkarg(2, start, x_max));
2194  if (end - start < 1) {
2195  hoc_execerror("end - start", "must be > 0");
2196  }
2197  const double sum = std::accumulate(x->begin() + start, x->begin() + end + 1, 0.0);
2198  return sum / end - start + 1;
2199  } else {
2200  if (x->size() < 1) {
2201  hoc_execerror("Vector", "must have size > 0");
2202  }
2203  const double sum = std::accumulate(x->begin(), x->end(), 0.0);
2204  return sum / x->size();
2205  }
2206 }
2207 
2208 static double v_var(void* v) {
2209  Vect* x = (Vect*) v;
2210  int x_max = x->size() - 1;
2211  if (ifarg(1)) {
2212  int start = int(chkarg(1, 0, x_max));
2213  int end = int(chkarg(2, start, x_max));
2214  if (end - start < 1) {
2215  hoc_execerror("end - start", "must be > 1");
2216  }
2217  return var(x->begin() + start, x->begin() + end + 1);
2218  } else {
2219  if (x->size() < 2) {
2220  hoc_execerror("Vector", "must have size > 1");
2221  }
2222  return var(x->begin(), x->end());
2223  }
2224 }
2225 
2226 static double v_stdev(void* v) {
2227  Vect* x = (Vect*) v;
2228  int x_max = x->size() - 1;
2229  if (ifarg(1)) {
2230  int start = int(chkarg(1, 0, x_max));
2231  int end = int(chkarg(2, start, x_max));
2232  if (end - start < 1) {
2233  hoc_execerror("end - start", "must be > 1");
2234  }
2235  return stdDev(x->begin() + start, x->begin() + end + 1);
2236  } else {
2237  if (x->size() < 2) {
2238  hoc_execerror("Vector", "must have size > 1");
2239  }
2240  return stdDev(x->begin(), x->end());
2241  }
2242 }
2243 
2244 static double v_stderr(void* v) {
2245  Vect* x = (Vect*) v;
2246  int x_max = x->size() - 1;
2247  if (ifarg(1)) {
2248  int start = int(chkarg(1, 0, x_max));
2249  int end = int(chkarg(2, start, x_max));
2250  if (end - start < 1) {
2251  hoc_execerror("end - start", "must be > 1");
2252  }
2253  return stdDev(x->begin() + start, x->begin() + end + 1) / hoc_Sqrt(double(end - start + 1));
2254  } else {
2255  if (x->size() < 2) {
2256  hoc_execerror("Vector", "must have size > 1");
2257  }
2258  return stdDev(x->begin(), x->end()) / hoc_Sqrt((double) x_max + 1.);
2259  }
2260 }
2261 
2262 static double v_meansqerr(void* v1) {
2263  Vect* x = (Vect*) v1;
2264 
2265  Vect* y = vector_arg(1);
2266  Vect* w = NULL;
2267 
2268  if (ifarg(2)) {
2269  w = vector_arg(2);
2270  }
2271  double err = 0.;
2272  int size = x->size();
2273  if (size > y->size() || !size) {
2274  hoc_execerror("Vector", "Vector argument too small\n");
2275  } else {
2276  if (w) {
2277  if (size > w->size()) {
2278  hoc_execerror("Vector", "second Vector size too small\n");
2279  }
2280  for (int i = 0; i < size; i++) {
2281  double diff = x->elem(i) - y->elem(i);
2282  err += diff * diff * w->elem(i);
2283  }
2284  } else {
2285  for (int i = 0; i < size; i++) {
2286  double diff = x->elem(i) - y->elem(i);
2287  err += diff * diff;
2288  }
2289  }
2290  }
2291  return err / size;
2292 }
2293 
2294 static double v_dot(void* v1) {
2295  Vect* x = (Vect*) v1;
2296  Vect* y = vector_arg(1);
2297  return std::inner_product(x->begin(), x->end(), y->begin(), 0.);
2298 }
2299 
2300 static double v_mag(void* v1) {
2301  Vect* x = (Vect*) v1;
2302  return hoc_Sqrt(std::inner_product(x->begin(), x->end(), x->begin(), 0.));
2303 }
2304 
2305 static Object** v_from_double(void* v) {
2306  Vect* x = (Vect*) v;
2307  int i;
2308  int n = (int) *getarg(1);
2309  double* px = hoc_pgetarg(2);
2310  x->resize(n);
2311  for (i = 0; i < n; ++i) {
2312  x->elem(i) = px[i];
2313  }
2314  return x->temp_objvar();
2315 }
2316 
2317 static Object** v_add(void* v1) {
2318  Vect* x = (Vect*) v1;
2319  if (hoc_argtype(1) == NUMBER) {
2320  std::for_each(x->begin(), x->end(), [](double& d) { d += *getarg(1); });
2321  }
2322  if (hoc_is_object_arg(1)) {
2323  Vect* y = vector_arg(1);
2324  if (x->size() != y->size()) {
2325  hoc_execerror("Vector", "Vector argument to .add() wrong size\n");
2326  } else {
2327  std::transform(x->begin(), x->end(), y->begin(), x->begin(), std::plus<double>());
2328  }
2329  }
2330  return x->temp_objvar();
2331 }
2332 
2333 
2334 static Object** v_sub(void* v1) {
2335  Vect* x = (Vect*) v1;
2336  if (hoc_argtype(1) == NUMBER) {
2337  std::for_each(x->begin(), x->end(), [](double& d) { d -= *getarg(1); });
2338  }
2339  if (hoc_is_object_arg(1)) {
2340  Vect* y = vector_arg(1);
2341  if (x->size() != y->size()) {
2342  hoc_execerror("Vector", "Vector argument to .sub() wrong size\n");
2343  } else {
2344  std::transform(x->begin(), x->end(), y->begin(), x->begin(), std::minus<double>());
2345  }
2346  }
2347  return x->temp_objvar();
2348 }
2349 
2350 static Object** v_mul(void* v1) {
2351  Vect* x = (Vect*) v1;
2352  if (hoc_argtype(1) == NUMBER) {
2353  std::for_each(x->begin(), x->end(), [](double& d) { d *= *getarg(1); });
2354  }
2355  if (hoc_is_object_arg(1)) {
2356  Vect* y = vector_arg(1);
2357  if (x->size() != y->size()) {
2358  hoc_execerror("Vector", "Vector argument to .mult() wrong size\n");
2359  } else {
2360  std::transform(x->begin(), x->end(), y->begin(), x->begin(), std::multiplies<double>());
2361  }
2362  }
2363  return x->temp_objvar();
2364 }
2365 
2366 
2367 static Object** v_div(void* v1) {
2368  Vect* x = (Vect*) v1;
2369  if (hoc_argtype(1) == NUMBER) {
2370  std::for_each(x->begin(), x->end(), [](double& d) { d /= *getarg(1); });
2371  }
2372  if (hoc_is_object_arg(1)) {
2373  Vect* y = vector_arg(1);
2374  if (x->size() != y->size()) {
2375  hoc_execerror("Vector", "Vector argument to .div() wrong size\n");
2376  } else {
2377  std::transform(x->begin(), x->end(), y->begin(), x->begin(), std::divides<double>());
2378  }
2379  }
2380  return x->temp_objvar();
2381 }
2382 
2383 static double v_scale(void* v1) {
2384  Vect* x = (Vect*) v1;
2385 
2386  double a = *getarg(1);
2387  double b = *getarg(2);
2388  double sf;
2389  auto minmax = std::minmax_element(x->begin(), x->end());
2390  double min = *minmax.first;
2391  double max = *minmax.second;
2392  double r = max - min;
2393  if (r > 0) {
2394  sf = (b - a) / r;
2395  std::for_each(x->begin(), x->end(), [&](double& d) {
2396  d -= min;
2397  d *= sf;
2398  d += a;
2399  });
2400  } else {
2401  sf = 0.;
2402  }
2403  return sf;
2404 }
2405 
2406 static double v_eq(void* v1) {
2407  Vect* x = (Vect*) v1;
2408  Vect* y = vector_arg(1);
2409  int i, n = x->size();
2410  if (n != y->size()) {
2411  return false;
2412  }
2413  for (i = 0; i < n; ++i) {
2414  if (!Math::equal(x->elem(i), y->elem(i), hoc_epsilon)) {
2415  return false;
2416  }
2417  }
2418  return true;
2419 }
2420 
2421 
2422 /*=============================================================================
2423 
2424  FITTING A MULTIVARIABLE FUNCTION FROM DATA -- SIMPLEX METHOD
2425 
2426  double simplex( p,n,trial,a,b,c,d )
2427  double *p;
2428  vector of dimension n, containing variables
2429  int n;
2430  number of variables of the function to fit
2431  int trial;
2432  number of trials of simplex loop
2433  trial = 0: do simplex until the minimum pole has found
2434  trial > 0: do simplex [trial] times.
2435  double a,b,c,d
2436  values of contraction/expansion of the simplex;
2437  control the rate of the search in multidim variable space
2438  must be chosen by trial and error
2439  2.0, 1.4, 0.7, 0.3 -> standard values
2440 
2441  return most optimized eval value
2442  (negative if error occured)
2443 
2444  A function must be supplied by the user:
2445 
2446  external function DOUBLE EVAL(double *p);
2447 
2448  This function evaluates the mean square error between the
2449  the data and the multivariable function with the values of
2450  variables in vector p.
2451 
2452 =============================================================================*/
2453 
2454 
2455 #define SIMPLEX_MAXN 1e+300
2456 #define SIMPLEX_INORM 1.2
2457 
2458 /* 1.2: normal,
2459  1.3: extensive search,
2460  1.1: final adjustments
2461 */
2462 
2463 
2464 #define SIMPLEX_ALPHA 2.0
2465 #define SIMPLEX_BETA 1.4
2466 #define SIMPLEX_GAMMA 0.7
2467 #define SIMPLEX_DELTA 0.3
2468 
2469 /*
2470  values of contraction/expansion of the simplex;
2471  control the rate of the search in multidim variable space
2472  must be chosen by trial and error
2473  2.0, 1.4, 0.7, 0.3 -> standard values
2474 */
2475 
2476 static double splx_evl_;
2477 static int renew_;
2478 
2479 
2480 static double eval(double* p, int n, Vect* x, Vect* y, char* fcn) {
2481  double sq_err = 0.;
2482  double guess;
2483  int i;
2484  double dexp, t, amp1, tau1, amp2, tau2;
2485 
2486  if (!strcmp(fcn, "exp2")) {
2487  if (n < 4)
2488  hoc_execerror("Vector", ".fit(\"exp2\") requires amp1,tau1,amp2,tau2");
2489  amp1 = p[0];
2490  tau1 = p[1];
2491  amp2 = p[2];
2492  tau2 = p[3];
2493 
2494  for (i = 0; i < x->size(); i++) {
2495  t = x->elem(i);
2496  dexp = amp1 * hoc_Exp(-t / tau1) + amp2 * hoc_Exp(-t / tau2);
2497  guess = dexp - y->elem(i);
2498  sq_err += guess * guess;
2499  }
2500  } else if (!strcmp(fcn, "charging")) {
2501  if (n < 4)
2502  hoc_execerror("Vector", ".fit(\"charging\") requires amp1,tau1,amp2,tau2");
2503  amp1 = p[0];
2504  tau1 = p[1];
2505  amp2 = p[2];
2506  tau2 = p[3];
2507 
2508  for (i = 0; i < x->size(); i++) {
2509  t = x->elem(i);
2510  dexp = amp1 * (1 - hoc_Exp(-t / tau1)) + amp2 * (1 - hoc_Exp(-t / tau2));
2511  guess = dexp - y->elem(i);
2512  sq_err += guess * guess;
2513  }
2514  } else if (!strcmp(fcn, "exp1")) {
2515  if (n < 2)
2516  hoc_execerror("Vector", ".fit(\"exp1\") requires amp,tau");
2517  amp1 = p[0];
2518  tau1 = p[1];
2519 
2520 
2521  for (i = 0; i < x->size(); i++) {
2522  t = x->elem(i);
2523  dexp = amp1 * hoc_Exp(-t / tau1);
2524  guess = dexp - y->elem(i);
2525  sq_err += guess * guess;
2526  }
2527  } else if (!strcmp(fcn, "line")) {
2528  if (n < 2)
2529  hoc_execerror("Vector", ".fit(\"line\") requires slope,intercept");
2530 
2531  for (i = 0; i < x->size(); i++) {
2532  guess = (p[0] * x->elem(i) + p[1]) - y->elem(i);
2533  sq_err += guess * guess;
2534  }
2535  } else if (!strcmp(fcn, "quad")) {
2536  if (n < 3)
2537  hoc_execerror("Vector", ".fit(\"quad\") requires ax^2+bx+c");
2538 
2539  for (i = 0; i < x->size(); i++) {
2540  guess = (p[0] * x->elem(i) * x->elem(i) + p[1] * x->elem(i) + p[2]) - y->elem(i);
2541  sq_err += guess * guess;
2542  }
2543  } else {
2544  for (i = 0; i < x->size(); i++) {
2545  // first the independent variable
2546  hoc_pushx(x->elem(i));
2547  // then other parameters
2548  for (int j = 0; j < n; j++)
2549  hoc_pushx(p[j]);
2550 
2551  guess = hoc_call_func(hoc_lookup(fcn), n + 1) - y->elem(i);
2552  sq_err += guess * guess;
2553  }
2554  }
2555  return sq_err / x->size();
2556 }
2557 
2558 
2559 static double eval_error(double* p, int n, Vect* x, Vect* y, char* fcn) {
2560  double retval;
2561 
2562  if (renew_ > 3 * (n + 1)) {
2563  retval = eval(p, n, x, y, fcn);
2564  if (retval == splx_evl_)
2565  return (splx_evl_);
2566  else
2567  return (SIMPLEX_MAXN);
2568  } else {
2569  retval = eval(p, n, x, y, fcn);
2570  if (splx_evl_ > retval)
2571  splx_evl_ = retval;
2572  return (retval);
2573  }
2574 }
2575 
2576 static double simplex(double* p, int n, Vect* x, Vect* y, char* fcn) {
2577  int i, j;
2578  int emaxp; /* max position */
2579  int eminp;
2580  int ptr;
2581 
2582  double* evortex; /* eval value of votexes */
2583  double* gvortex; /* the vector of gravity */
2584  double* vortex; /* parameter matrix */
2585  double* nvortex; /* new vortex */
2586  double emax;
2587  double emin;
2588  double fv1;
2589 
2590  evortex = (double*) calloc(n + 1, (unsigned) sizeof(double));
2591  gvortex = (double*) calloc(n, (unsigned) sizeof(double));
2592  vortex = (double*) calloc(n * (n + 1), (unsigned) sizeof(double));
2593  nvortex = (double*) calloc(n * 4, (unsigned) sizeof(double));
2594 
2595  if (0 == evortex || 0 == gvortex || 0 == vortex || 0 == nvortex) {
2596  Printf("allocation error in simplex()\n");
2597  nrn_exit(1);
2598  }
2599 
2600 
2601  // NEXT:;
2602  /* make the initial vortex matrix */
2603  for (i = 0; i < n + 1; i++) {
2604  for (j = 0; j < n; j++) {
2605  vortex[i * n + j] = p[j];
2606  if (i == j)
2607  vortex[i * n + j] *= SIMPLEX_INORM;
2608  }
2609  }
2610 
2611  /* evaluate the n+1 of vortexes and make the maximal one
2612  to be pointed out by emaxp */
2613  for (i = 0; i < n + 1; i++)
2614  evortex[i] = eval_error(&vortex[i * n], n, x, y, fcn);
2615 
2616 Label2:;
2617  emin = emax = evortex[0];
2618  emaxp = eminp = 0;
2619  for (i = 0; i < n + 1; i++) {
2620  fv1 = evortex[i];
2621  if (fv1 > emax) {
2622  emax = fv1;
2623  emaxp = i;
2624  }
2625  if (fv1 < emin) {
2626  emin = fv1;
2627  eminp = i;
2628  }
2629  }
2630  /* calculate the center of gravity */
2631  for (i = 0; i < n; i++)
2632  gvortex[i] = 0.0;
2633  for (i = 0; i < n + 1; i++)
2634  for (j = 0; j < n; j++)
2635  gvortex[j] += vortex[i * n + j];
2636  for (i = 0; i < n; i++)
2637  gvortex[i] = (gvortex[i] - vortex[emaxp * n + i]) / n;
2638 
2639  /* calculate the new vortexes */
2640 
2641  for (i = 0; i < n; i++)
2642  nvortex[i] = (1.0 - SIMPLEX_ALPHA) * vortex[emaxp * n + i] + SIMPLEX_ALPHA * gvortex[i];
2643  fv1 = eval_error(&nvortex[0], n, x, y, fcn);
2644  if (fv1 < evortex[emaxp]) {
2645  ptr = 0;
2646  goto UPDATE;
2647  }
2648 
2649  for (i = 0; i < n; i++)
2650  nvortex[1 * n + i] = (1.0 - SIMPLEX_BETA) * vortex[emaxp * n + i] +
2651  SIMPLEX_BETA * gvortex[i];
2652  fv1 = eval_error(&nvortex[1 * n], n, x, y, fcn);
2653  if (fv1 < evortex[emaxp]) {
2654  ptr = 1;
2655  goto UPDATE;
2656  }
2657 
2658  for (i = 0; i < n; i++)
2659  nvortex[2 * n + i] = (1.0 - SIMPLEX_GAMMA) * vortex[emaxp * n + i] +
2660  SIMPLEX_GAMMA * gvortex[i];
2661  fv1 = eval_error(&nvortex[2 * n], n, x, y, fcn);
2662  if (fv1 < evortex[emaxp]) {
2663  ptr = 2;
2664  goto UPDATE;
2665  }
2666 
2667  for (i = 0; i < n; i++)
2668  nvortex[3 * n + i] = (1.0 - SIMPLEX_DELTA) * vortex[emaxp * n + i] +
2669  SIMPLEX_DELTA * gvortex[i];
2670  fv1 = eval_error(&nvortex[3 * n], n, x, y, fcn);
2671  if (fv1 < evortex[emaxp]) {
2672  ptr = 3;
2673  goto UPDATE;
2674  }
2675 
2676  goto Label3;
2677 
2678 
2679 UPDATE:;
2680  /* update the vortex matrix */
2681  if (splx_evl_ == fv1)
2682  renew_++;
2683  for (i = 0; i < n; i++)
2684  vortex[emaxp * n + i] = nvortex[ptr * n + i];
2685  evortex[emaxp] = fv1;
2686  goto Label2;
2687 
2688 
2689 Label3:;
2690  /*
2691  ** search for the vortex that represents smallest eval vaule
2692  */
2693  emin = evortex[0];
2694  eminp = 0;
2695  for (i = 0; i < n + 1; i++) {
2696  if (evortex[i] < emin) {
2697  emin = evortex[i];
2698  eminp = i;
2699  }
2700  }
2701 
2702  for (i = 0; i < n; i++)
2703  p[i] = vortex[eminp * n + i];
2704  free(gvortex);
2705  free(evortex);
2706  free(vortex);
2707  free(nvortex);
2708  return (emin);
2709 }
2710 
2711 
2712 double call_simplex(double* p, int n, Vect* x, Vect* y, char* fcn, int trial) {
2713  double retval;
2714 
2715  if (!trial) {
2716  while (1) {
2717  renew_ = 0;
2719  retval = simplex(p, n, x, y, fcn);
2720  if (!renew_ || splx_evl_ <= retval)
2721  break;
2722  }
2723  } else {
2724  for (int i = 0; i < trial; i++) {
2725  renew_ = 0;
2727  retval = simplex(p, n, x, y, fcn);
2728  if (!renew_ || splx_evl_ <= retval)
2729  break;
2730  }
2731  }
2732  return (retval);
2733 }
2734 
2735 static double v_fit(void* v) {
2736  int trial = 0;
2737  /* number of trials of simplex loop
2738  trial = 0: do simplex until the minimum pole has found
2739  trial > 0: do simplex [trial] times.
2740  */
2741 
2742 
2743  // get the data vector
2744  Vect* y = (Vect*) v;
2745 
2746  // get a vector to place the fitted function
2747  Vect* fitted = vector_arg(1);
2748  if (fitted->size() != y->size())
2749  fitted->resize(y->size());
2750 
2751  // get a function to fit
2752  char* fcn;
2753  fcn = gargstr(2);
2754 
2755  // get the independent variable
2756 
2757  Vect* x = vector_arg(3);
2758  if (x->size() != y->size()) {
2759  hoc_execerror("Vector", "Indep argument to .fit() wrong size\n");
2760  }
2761 
2762  // get the parameters of the function
2763 
2764  double* p_ptr[MAX_FIT_PARAMS];
2765  double p[MAX_FIT_PARAMS];
2766 
2767  if (ifarg(MAX_FIT_PARAMS)) {
2768  hoc_execerror("Vector", "Too many parameters to fit()\n");
2769  }
2770  int n = 0;
2771  while (ifarg(4 + n)) {
2772  // pointer to parameter
2773  p_ptr[n] = hoc_pgetarg(4 + n);
2774  // parameter value
2775  p[n] = *(p_ptr[n]);
2776  n++;
2777  }
2778 
2779  double meansqerr = call_simplex(p, n, x, y, fcn, trial);
2780 
2781  // assign data to pointers where they came from;
2782  int i;
2783  for (i = 0; i < n; i++) {
2784  *(p_ptr[i]) = p[i];
2785  }
2786 
2787  if (!strcmp(fcn, "exp2")) {
2788  for (i = 0; i < x->size(); i++) {
2789  fitted->elem(i) = p[0] * hoc_Exp(-(x->elem(i) / p[1])) +
2790  p[2] * hoc_Exp(-(x->elem(i) / p[3]));
2791  }
2792  } else if (!strcmp(fcn, "charging")) {
2793  for (i = 0; i < x->size(); i++) {
2794  fitted->elem(i) = p[0] * (1 - hoc_Exp(-(x->elem(i) / p[1]))) +
2795  p[2] * (1 - hoc_Exp(-(x->elem(i) / p[3])));
2796  }
2797  } else if (!strcmp(fcn, "exp1")) {
2798  for (i = 0; i < x->size(); i++) {
2799  fitted->elem(i) = p[0] * hoc_Exp(-(x->elem(i) / p[1]));
2800  }
2801  } else if (!strcmp(fcn, "line")) {
2802  for (i = 0; i < x->size(); i++) {
2803  fitted->elem(i) = p[0] * x->elem(i) + p[1];
2804  }
2805  } else if (!strcmp(fcn, "quad")) {
2806  for (i = 0; i < x->size(); i++) {
2807  fitted->elem(i) = p[0] * x->elem(i) * x->elem(i) + p[1] * x->elem(i) + p[2];
2808  }
2809  } else {
2810  for (i = 0; i < x->size(); i++) {
2811  hoc_pushx(x->elem(i));
2812  for (int j = 0; j < n; j++)
2813  hoc_pushx(p[j]);
2814  fitted->elem(i) = hoc_call_func(hoc_lookup(fcn), n + 1);
2815  }
2816  }
2817 
2818  return meansqerr;
2819 }
2820 
2821 
2822 // FOURIER analysis
2823 
2824 
2825 static Object** v_correl(void* v) {
2826  Vect* v3 = (Vect*) v;
2827 
2828  Vect* v1;
2829  Vect* v2;
2830 
2831  // first data set
2832  v1 = vector_arg(1);
2833 
2834  // second data set
2835  if (ifarg(2)) {
2836  v2 = vector_arg(2);
2837  } else {
2838  v2 = v1;
2839  }
2840 
2841  // make both data sets equal integer power of 2
2842  int v1n = v1->size();
2843  int v2n = v2->size();
2844  int m = (v1n > v2n) ? v1n : v2n;
2845  int n = 1;
2846  while (n < m)
2847  n *= 2;
2848 
2849  double* d1 = (double*) calloc(n, (unsigned) sizeof(double));
2850  int i;
2851  for (i = 0; i < v1n; ++i)
2852  d1[i] = v1->elem(i);
2853  double* d2 = (double*) calloc(n, (unsigned) sizeof(double));
2854  for (i = 0; i < v2n; ++i)
2855  d2[i] = v2->elem(i);
2856  double* ans = (double*) calloc(n, (unsigned) sizeof(double));
2857 
2858  nrn_correl(d1, d2, n, ans);
2859 
2860  if (v3->size() != n)
2861  v3->resize(n);
2862  for (i = 0; i < n; ++i)
2863  v3->elem(i) = ans[i];
2864  free((char*) d1);
2865  free((char*) d2);
2866  free((char*) ans);
2867 
2868  return v3->temp_objvar();
2869 }
2870 
2871 static Object** v_convlv(void* v) {
2872  Vect* v3 = (Vect*) v;
2873 
2874  Vect *v1, *v2;
2875 
2876  // data set
2877  v1 = vector_arg(1);
2878 
2879 
2880  // filter
2881  v2 = vector_arg(2);
2882 
2883  // convolve unless isign is -1, then deconvolve!
2884  int isign;
2885  if (ifarg(3))
2886  isign = (int) (*getarg(3));
2887  else
2888  isign = 1;
2889 
2890  // make both data sets equal integer power of 2
2891  int v1n = v1->size();
2892  int v2n = v2->size();
2893  int m = (v1n > v2n) ? v1n : v2n;
2894  int n = 1;
2895  while (n < m)
2896  n *= 2;
2897 
2898  double* data = (double*) calloc(n, (unsigned) sizeof(double));
2899  int i;
2900  for (i = 0; i < v1n; ++i)
2901  data[i] = v1->elem(i);
2902 
2903  // assume respns is given in "wrap-around" order,
2904  // with countup t=0..t=n/2 followed by countdown t=n..t=n/2
2905  // v2n should be an odd <= n
2906 
2907  double* respns = (double*) calloc(n, (unsigned) sizeof(double));
2908  for (i = 0; i < v2n; i++)
2909  respns[i] = v2->elem(i);
2910 
2911  double* ans = (double*) calloc(2 * n, (unsigned) sizeof(double));
2912 
2913  nrn_convlv(data, n, respns, v2n, isign, ans);
2914 
2915  if (v3->size() != n)
2916  v3->resize(n);
2917  for (i = 0; i < n; ++i)
2918  v3->elem(i) = ans[i];
2919 
2920  free((char*) data);
2921  free((char*) respns);
2922  free((char*) ans);
2923 
2924  return v3->temp_objvar();
2925 }
2926 
2927 
2928 static Object** v_spctrm(void* v) {
2929  Vect* ans = (Vect*) v;
2930 
2931  // n data pts will be divided into k partitions of size m
2932  // the spectrum will have m values from 0 to m/2 cycles/dt.
2933  // n = (2*k+1)*m
2934 
2935  // data set
2936  Vect* v1 = vector_arg(1);
2937 
2938  int dc = v1->size();
2939  int mr;
2940  if (ifarg(2))
2941  mr = (int) (*getarg(2));
2942  else
2943  mr = dc / 8;
2944 
2945  // make sure the length of partitions is integer power of 2
2946  int m = 1;
2947  while (m < mr)
2948  m *= 2;
2949 
2950  int k = int(ceil((double(dc) / m - 1.) / 2.));
2951  int n = (2 * k + 1) * m;
2952 
2953  double* data = (double*) calloc(n, (unsigned) sizeof(double));
2954  for (int i = 0; i < dc; ++i)
2955  data[i] = v1->elem(i);
2956 
2957  if (ans->size() < m)
2958  ans->resize(m);
2959  nrn_spctrm(data, &ans->elem(0), m, k);
2960 
2961  free((char*) data);
2962 
2963  return ans->temp_objvar();
2964 }
2965 
2966 static Object** v_filter(void* v) {
2967  Vect* v3 = (Vect*) v;
2968  Vect* v1;
2969  Vect* v2;
2970  int iarg = 1;
2971 
2972  // data set
2973  if (hoc_is_object_arg(iarg)) {
2974  v1 = vector_arg(iarg++);
2975  } else {
2976  v1 = v3;
2977  }
2978 
2979  // filter
2980  v2 = vector_arg(iarg);
2981 
2982  // make both data sets equal integer power of 2
2983  int v1n = v1->size();
2984  int v2n = v2->size();
2985  int m = (v1n > v2n) ? v1n : v2n;
2986  int n = 1;
2987  while (n < m)
2988  n *= 2;
2989 
2990  double* data = (double*) calloc(n, (unsigned) sizeof(double));
2991  int i;
2992  for (i = 0; i < v1n; ++i)
2993  data[i] = v1->elem(i);
2994 
2995  double* filter = (double*) calloc(n, (unsigned) sizeof(double));
2996  for (i = 0; i < v2n; i++)
2997  filter[i] = v2->elem(i);
2998 
2999  double* ans = (double*) calloc(2 * n, (unsigned) sizeof(double));
3000 
3001  nrngsl_realft(filter, n, 1);
3002 
3003  nrn_convlv(data, n, filter, v2n, 1, ans);
3004 
3005  if (v3->size() != n)
3006  v3->resize(n);
3007  for (i = 0; i < n; ++i)
3008  v3->elem(i) = ans[i];
3009 
3010  free((char*) data);
3011  free((char*) filter);
3012  free((char*) ans);
3013 
3014  return v3->temp_objvar();
3015 }
3016 
3017 
3018 static Object** v_fft(void* v) {
3019  Vect* v3 = (Vect*) v;
3020  Vect* v1;
3021  int iarg = 1;
3022 
3023  // data set
3024  if (hoc_is_object_arg(iarg)) {
3025  v1 = vector_arg(iarg++);
3026  } else {
3027  v1 = v3;
3028  }
3029 
3030  // inverse = -1, regular = 1
3031 
3032  int inv = 1;
3033  if (ifarg(iarg))
3034  inv = int(chkarg(iarg, -1, 1));
3035 
3036  // make data set integer power of 2
3037  int v1n = v1->size();
3038  int n = 1;
3039  while (n < v1n)
3040  n *= 2;
3041 
3042  double* data = (double*) calloc(n, (unsigned) sizeof(double));
3043  int i;
3044  for (i = 0; i < v1n; ++i)
3045  data[i] = v1->elem(i);
3046  if (v3->size() != n)
3047  v3->resize(n);
3048 
3049  if (inv == -1) {
3050  nrn_nrc2gsl(data, &v3->elem(0), n);
3051  nrngsl_realft(&v3->elem(0), n, -1);
3052  } else {
3053  nrngsl_realft(data, n, 1);
3054  nrn_gsl2nrc(data, &v3->elem(0), n);
3055  }
3056  free((char*) data);
3057 
3058  return v3->temp_objvar();
3059 }
3060 
3061 static Object** v_spikebin(void* v) {
3062  Vect* ans = (Vect*) v;
3063 
3064  // data set
3065  Vect* v1 = vector_arg(1);
3066 
3067  double thresh = *getarg(2);
3068 
3069  int bin = 1;
3070  if (ifarg(3))
3071  bin = int(chkarg(3, 0, 1e6));
3072 
3073  int n = v1->size() / bin;
3074  if (ans->size() != n)
3075  ans->resize(n);
3076  std::fill(ans->begin(), ans->end(), 0.);
3077 
3078  int firing = 0;
3079  int k;
3080 
3081  for (int i = 0; i < n; i++) {
3082  for (int j = 0; j < bin; j++) {
3083  k = i * bin + j;
3084  if (v1->elem(k) >= thresh && !firing) {
3085  firing = 1;
3086  ans->elem(i) = 1;
3087  } else if (firing && v1->elem(k) < thresh) {
3088  firing = 0;
3089  }
3090  }
3091  }
3092 
3093  return ans->temp_objvar();
3094 }
3095 
3096 static Object** v_rotate(void* v) {
3097  Vect* a = (Vect*) v;
3098 
3099  int wrap = 1;
3100  int rev = 0;
3101 
3102  int n = a->size();
3103  int r = int(*getarg(1));
3104  if (ifarg(2))
3105  wrap = 0;
3106 
3107  if (r > n)
3108  r = r % n;
3109  if (r < 0) {
3110  r = n - (Math::abs(r) % n);
3111  rev = 1;
3112  }
3113 
3114  if (r > 0) {
3115  int rc = n - r;
3116 
3117  double* hold = (double*) calloc(n, (unsigned) sizeof(double));
3118 
3119  int i;
3120  if (wrap) {
3121  for (i = 0; i < rc; i++)
3122  hold[i + r] = a->elem(i);
3123  for (i = 0; i < r; i++)
3124  hold[i] = a->elem(i + rc);
3125  } else {
3126  if (rev == 0) {
3127  for (i = 0; i < rc; i++)
3128  hold[i + r] = a->elem(i);
3129  for (i = 0; i < r; i++)
3130  hold[i] = 0.;
3131  } else {
3132  for (i = 0; i < r; i++)
3133  hold[i] = a->elem(i + rc);
3134  for (i = r; i < n; i++)
3135  hold[i] = 0.;
3136  }
3137  }
3138  for (i = 0; i < n; i++)
3139  a->elem(i) = hold[i];
3140 
3141 
3142  free((char*) hold);
3143  }
3144 
3145  return a->temp_objvar();
3146 }
3147 
3148 static Object** v_deriv(void* v) {
3149  Vect* ans = (Vect*) v;
3150  Vect* v1;
3151  int flag, iarg = 1;
3152 
3153  // data set
3154  iarg = possible_srcvec(v1, ans, flag);
3155 
3156  int n = v1->size();
3157  if (n < 2) {
3158  hoc_execerror("Can't take derivative of Vector with less than two points", 0);
3159  }
3160  if (ans->size() != n)
3161  ans->resize(n);
3162 
3163  double dx = 1;
3164  if (ifarg(iarg))
3165  dx = *getarg(iarg++);
3166 
3167  int sym = 2;
3168  if (ifarg(iarg))
3169  sym = int(chkarg(iarg++, 1, 2));
3170 
3171 
3172  if (sym == 2) {
3173  // use symmetrical form -- see NumRcpC p. 187.
3174  // at boundaries use single-sided form
3175 
3176  ans->elem(0) = (v1->elem(1) - v1->elem(0)) / dx;
3177  ans->elem(n - 1) = (v1->elem(n - 1) - v1->elem(n - 2)) / dx;
3178  dx = dx * 2;
3179  for (int i = 1; i < n - 1; i++) {
3180  ans->elem(i) = (v1->elem(i + 1) - v1->elem(i - 1)) / dx;
3181  }
3182  } else {
3183  // use single-sided form
3184  ans->resize(n - 1);
3185  for (int i = 0; i < n - 1; i++) {
3186  ans->elem(i) = (v1->elem(i + 1) - v1->elem(i)) / dx;
3187  }
3188  }
3189  if (flag) {
3190  delete v1;
3191  }
3192  return ans->temp_objvar();
3193 }
3194 
3195 static Object** v_integral(void* v) {
3196  Vect* ans = (Vect*) v;
3197  Vect* v1;
3198  int iarg = 1;
3199 
3200  // data set
3201  if (ifarg(iarg) && hoc_is_object_arg(iarg)) {
3202  v1 = vector_arg(iarg++);
3203  } else {
3204  v1 = ans;
3205  }
3206 
3207  int n = v1->size();
3208  if (ans->size() != n)
3209  ans->resize(n);
3210 
3211  double dx = 1.;
3212  if (ifarg(iarg))
3213  dx = *getarg(iarg++);
3214 
3215  ans->elem(0) = v1->elem(0);
3216  for (int i = 1; i < n; i++) {
3217  ans->elem(i) = ans->elem(i - 1) + v1->elem(i) * dx;
3218  }
3219  return ans->temp_objvar();
3220 }
3221 
3222 static double v_trigavg(void* v) {
3223  Vect* avg = (Vect*) v;
3224 
3225  // continuous data(t)
3226  Vect* data = vector_arg(1);
3227 
3228  // trigger times
3229  Vect* trig = vector_arg(2);
3230 
3231  int n = data->size();
3232  int pre = int(chkarg(3, 0, n - 1));
3233  int post = int(chkarg(4, 0, n - 1));
3234  int m = pre + post;
3235  if (avg->size() != m)
3236  avg->resize(m);
3237  int l = trig->size();
3238  int trcount = 0;
3239 
3240  std::fill(avg->begin(), avg->end(), 0.);
3241 
3242  for (int i = 0; i < l; i++) {
3243  int tr = int(trig->elem(i));
3244 
3245  // throw out events within the window size of the edges
3246  if (tr >= pre && tr < n - post) {
3247  trcount++;
3248  for (int j = -pre; j < post; j++) {
3249  avg->elem(j + pre) += data->elem(tr + j);
3250  }
3251  }
3252  }
3253  std::for_each(avg->begin(), avg->end(), [&](double& d) { d /= trcount; });
3254 
3255  return trcount;
3256 }
3257 
3258 
3259 static Object** v_medfltr(void* v) {
3260  Vect* ans = (Vect*) v;
3261  Vect* v1;
3262  int w0, w1, wlen, i, flag, iarg = 1;
3263 
3264  // data set
3265  iarg = possible_srcvec(v1, ans, flag);
3266 
3267  int n = v1->size();
3268  if (ans->size() != n)
3269  ans->resize(n);
3270 
3271  int points = 3;
3272  if (ifarg(iarg))
3273  points = int(chkarg(iarg, 1, n / 2));
3274 
3275  double* res = (double*) calloc(n, (unsigned) sizeof(double));
3276  for (i = 0; i < n; i++) {
3277  w0 = (i >= points) ? i - points : 0;
3278  w1 = (i < n - points) ? i + points : n - 1;
3279  wlen = w1 - w0;
3280 
3281  std::vector<double> window(v1->begin() + w0, v1->begin() + wlen);
3282  std::sort(window.begin(), window.end());
3283  res[i] = window[wlen / 2];
3284  }
3285 
3286  if (ans->size() != n)
3287  ans->resize(n);
3288  for (i = 0; i < n; i++) {
3289  ans->elem(i) = res[i];
3290  }
3291  free(res);
3292  if (flag) {
3293  delete v1;
3294  }
3295  return ans->temp_objvar();
3296 }
3297 
3298 static double v_median(void* v) {
3299  Vect* ans = (Vect*) v;
3300 
3301  int n = ans->size();
3302  if (n == 0) {
3303  hoc_execerror("Vector", "must have size > 0");
3304  }
3305 
3306  Vect* sorted = new Vect(*ans);
3307  std::sort(sorted->begin(), sorted->end());
3308 
3309  int n2 = n / 2;
3310 
3311  double median;
3312  if (2 * n2 == n) {
3313  median = (sorted->elem(n2 - 1) + sorted->elem(n2)) / 2.;
3314  } else {
3315  median = sorted->elem(n2);
3316  }
3317  delete sorted;
3318 
3319  return median;
3320 }
3321 
3322 static Object** v_sort(void* v) {
3323  Vect* ans = (Vect*) v;
3324  std::sort(ans->begin(), ans->end());
3325  return ans->temp_objvar();
3326 }
3327 
3328 static Object** v_reverse(void* v) {
3329  Vect* ans = (Vect*) v;
3330  std::reverse(ans->begin(), ans->end());
3331  return ans->temp_objvar();
3332 }
3333 
3334 
3335 static Object** v_sin(void* v) {
3336  Vect* ans = (Vect*) v;
3337 
3338  int n = ans->size();
3339  double freq = *getarg(1);
3340  double phase = *getarg(2);
3341  double dx = 1;
3342  if (ifarg(3))
3343  dx = *getarg(3);
3344 
3345  double period = 2 * PI / 1000 * freq * dx;
3346 
3347  for (int i = 0; i < n; i++) {
3348  ans->elem(i) = sin(period * i + phase);
3349  }
3350  return ans->temp_objvar();
3351 }
3352 
3353 static Object** v_log(void* v) {
3354  Vect* ans = (Vect*) v;
3355  Vect* v1;
3356  // data set
3357  if (ifarg(1)) {
3358  v1 = vector_arg(1);
3359  } else {
3360  v1 = ans;
3361  }
3362 
3363  int n = v1->size();
3364  if (ans->size() != n)
3365  ans->resize(n);
3366 
3367  for (int i = 0; i < n; i++) {
3368  ans->elem(i) = log(v1->elem(i));
3369  }
3370  return ans->temp_objvar();
3371 }
3372 
3373 static Object** v_log10(void* v) {
3374  Vect* ans = (Vect*) v;
3375  Vect* v1;
3376  // data set
3377  if (ifarg(1)) {
3378  v1 = vector_arg(1);
3379  } else {
3380  v1 = ans;
3381  }
3382 
3383  int n = v1->size();
3384  if (ans->size() != n)
3385  ans->resize(n);
3386 
3387  for (int i = 0; i < n; i++) {
3388  ans->elem(i) = log10(v1->elem(i));
3389  }
3390  return ans->temp_objvar();
3391 }
3392 
3393 static Object** v_rebin(void* v) {
3394  Vect* ans = (Vect*) v;
3395  Vect* v1;
3396  int flag, iarg = 1;
3397 
3398  // data set
3399  iarg = possible_srcvec(v1, ans, flag);
3400 
3401  int f = int(*getarg(iarg));
3402  int n = v1->size() / f;
3403  if (ans->size() != n)
3404  ans->resize(n);
3405 
3406  for (int i = 0; i < n; i++) {
3407  ans->elem(i) = 0.;
3408  for (int j = 0; j < f; j++) {
3409  ans->elem(i) += v1->elem(i * f + j);
3410  }
3411  }
3412 
3413  if (flag) {
3414  delete v1;
3415  }
3416  return ans->temp_objvar();
3417 }
3418 
3419 static Object** v_resample(void* v) {
3420  Vect* ans = (Vect*) v;
3421 
3422  // data set
3423  Vect* v1 = vector_arg(1);
3424 
3425  double f = chkarg(2, 0, v1->size() / 2);
3426  int n = int(v1->size() * f);
3427 
3428  Vect* temp = new Vect(n);
3429 
3430  for (int i = 0; i < n; i++)
3431  temp->elem(i) = v1->elem(int(i / f));
3432  ans->vec().swap(temp->vec());
3433 
3434  delete temp;
3435 
3436  return ans->temp_objvar();
3437 }
3438 
3439 static Object** v_psth(void* v) {
3440  Vect* ans = (Vect*) v;
3441 
3442  // data set
3443  Vect* v1 = vector_arg(1);
3444 
3445  double dt = chkarg(2, 0, 9e99);
3446  double trials = chkarg(3, 0, 9e99);
3447  double size = chkarg(4, 0, v1->size() / 2);
3448  int n = int(v1->size());
3449 
3450  Vect* temp = new Vect(n);
3451 
3452  for (int i = 0; i < n; i++) {
3453  int fj = 0;
3454  int bj = 0;
3455  double integral = v1->elem(i);
3456  while (integral < size) {
3457  if (i + fj < n - 1) {
3458  fj++;
3459  integral += v1->elem(i + fj);
3460  }
3461  if (i - bj > 0 && integral < size) {
3462  bj++;
3463  integral += v1->elem(i - bj);
3464  }
3465  }
3466  temp->elem(i) = integral / trials * 1000. / ((fj + bj + 1) * dt);
3467  }
3468 
3469  ans->vec().swap(temp->vec());
3470 
3471  delete temp;
3472 
3473  return ans->temp_objvar();
3474 }
3475 
3476 static Object** v_inf(void* x) {
3477  Vect* V = (Vect*) x;
3478 
3479  // data set
3480  Vect* stim = vector_arg(1);
3481  int n = stim->size();
3482 
3483  double dt = chkarg(2, 1e-99, 9e99);
3484  double gl = *getarg(3);
3485  double el = *getarg(4);
3486  double cm = *getarg(5) / dt;
3487  double th = *getarg(6);
3488  double res = *getarg(7);
3489  double refp = 0;
3490  if (ifarg(8))
3491  refp = *getarg(8);
3492 
3493  if (V->size() != n)
3494  V->resize(n);
3495 
3496  double i = 0, v, ref = 0;
3497 
3498  V->elem(0) = el;
3499 
3500  for (int t = 0; t < n - 1; t++) {
3501  i = -gl * (V->elem(t) - el) + stim->elem(t);
3502  v = V->elem(t) + i / cm;
3503  if (v >= th && ref <= 0) {
3504  V->elem(t + 1) = 0;
3505  t = t + 1;
3506  V->elem(t + 1) = res;
3507  ref = refp;
3508  } else {
3509  ref = ref - dt;
3510  V->elem(t + 1) = v;
3511  }
3512  }
3513  return V->temp_objvar();
3514 }
3515 
3516 static Object** v_pow(void* v) {
3517  Vect* ans = (Vect*) v;
3518  Vect* v1;
3519  int iarg = 1;
3520 
3521  // data set
3522  if (hoc_is_object_arg(iarg)) {
3523  v1 = vector_arg(iarg++);
3524  } else {
3525  v1 = ans;
3526  }
3527 
3528  double p = *getarg(iarg);
3529  int n = v1->size();
3530  if (ans->size() != n)
3531  ans->resize(n);
3532 
3533  if (p == -1) {
3534  for (int i = 0; i < n; i++) {
3535  if (ans->elem(i) == 0) {
3536  hoc_execerror("Vector", "Invalid comparator in .where()\n");
3537  } else {
3538  ans->elem(i) = 1 / v1->elem(i);
3539  }
3540  }
3541  } else if (p == 0) {
3542  for (int i = 0; i < n; i++) {
3543  ans->elem(i) = 1;
3544  }
3545  } else if (p == 0.5) {
3546  for (int i = 0; i < n; i++) {
3547  ans->elem(i) = hoc_Sqrt(v1->elem(i));
3548  }
3549  } else if (p == 1) {
3550  for (int i = 0; i < n; i++) {
3551  ans->elem(i) = v1->elem(i);
3552  }
3553  } else if (p == 2) {
3554  for (int i = 0; i < n; i++) {
3555  ans->elem(i) = v1->elem(i) * v1->elem(i);
3556  }
3557  } else {
3558  for (int i = 0; i < n; i++) {
3559  ans->elem(i) = pow(v1->elem(i), p);
3560  }
3561  }
3562  return ans->temp_objvar();
3563 }
3564 
3565 static Object** v_sqrt(void* v) {
3566  Vect* ans = (Vect*) v;
3567  Vect* v1;
3568  // data set
3569  if (ifarg(1)) {
3570  v1 = vector_arg(1);
3571  } else {
3572  v1 = ans;
3573  }
3574 
3575  int n = v1->size();
3576  if (ans->size() != n)
3577  ans->resize(n);
3578 
3579  for (int i = 0; i < n; i++) {
3580  ans->elem(i) = hoc_Sqrt(v1->elem(i));
3581  }
3582  return ans->temp_objvar();
3583 }
3584 
3585 static Object** v_abs(void* v) {
3586  Vect* ans = (Vect*) v;
3587  Vect* v1;
3588  // data set
3589  if (ifarg(1)) {
3590  v1 = vector_arg(1);
3591  } else {
3592  v1 = ans;
3593  }
3594 
3595  int n = v1->size();
3596  if (ans->size() != n)
3597  ans->resize(n);
3598 
3599  for (int i = 0; i < n; i++) {
3600  ans->elem(i) = Math::abs(v1->elem(i));
3601  }
3602  return ans->temp_objvar();
3603 }
3604 
3605 static Object** v_floor(void* v) {
3606  Vect* ans = (Vect*) v;
3607  Vect* v1;
3608  // data set
3609  if (ifarg(1)) {
3610  v1 = vector_arg(1);
3611  } else {
3612  v1 = ans;
3613  }
3614 
3615  int n = v1->size();
3616  if (ans->size() != n)
3617  ans->resize(n);
3618 
3619  for (int i = 0; i < n; i++) {
3620  ans->elem(i) = floor(v1->elem(i));
3621  }
3622  return ans->temp_objvar();
3623 }
3624 
3625 static Object** v_tanh(void* v) {
3626  Vect* ans = (Vect*) v;
3627  Vect* v1;
3628  // data set
3629  if (ifarg(1)) {
3630  v1 = vector_arg(1);
3631  } else {
3632  v1 = ans;
3633  }
3634 
3635  int n = v1->size();
3636  if (ans->size() != n)
3637  ans->resize(n);
3638 
3639  for (int i = 0; i < n; i++) {
3640  ans->elem(i) = tanh(v1->elem(i));
3641  }
3642  return ans->temp_objvar();
3643 }
3644 
3645 static Object** v_index(void* v) {
3646  Vect* ans = (Vect*) v;
3647  Vect* data;
3648  Vect* index;
3649  bool del = false;
3650 
3651  if (ifarg(2)) {
3652  data = vector_arg(1);
3653  index = vector_arg(2);
3654  } else {
3655  data = ans;
3656  index = vector_arg(1);
3657  }
3658  if (data == ans) {
3659  data = new Vect(*data);
3660  del = true;
3661  }
3662 
3663  int n = data->size();
3664  int m = index->size();
3665  if (ans->size() != m)
3666  ans->resize(m);
3667 
3668  for (int i = 0; i < m; i++) {
3669  int j = int(index->elem(i));
3670  if (j >= 0 && j < n) {
3671  ans->elem(i) = data->elem(j);
3672  } else {
3673  ans->elem(i) = 0.;
3674  }
3675  }
3676 
3677  if (del) {
3678  delete data;
3679  }
3680 
3681  return ans->temp_objvar();
3682 }
3683 
3685  if (!nrnpy_vec_from_python_p_) {
3686  hoc_execerror("Python not available", 0);
3687  }
3688  Vect* vec = (*nrnpy_vec_from_python_p_)(v);
3689  return vec->temp_objvar();
3690 }
3691 
3693  if (!nrnpy_vec_to_python_p_) {
3694  hoc_execerror("Python not available", 0);
3695  }
3696  return (*nrnpy_vec_to_python_p_)(v);
3697 }
3698 
3699 Object** v_as_numpy(void* v) {
3701  hoc_execerror("Python not available", 0);
3702  }
3703  Vect* vec = (Vect*) v;
3704  // not a copy, shares the data! So do not change the size while
3705  // the python numpy array is in use.
3706  return (*nrnpy_vec_as_numpy_helper_)(vec->size(), vec->data());
3707 }
3708 
3709 
3711 
3712  "x",
3713  v_size, // will be changed below
3714  "size",
3715  v_size,
3716  "buffer_size",
3717  v_buffer_size,
3718  "get",
3719  v_get,
3720  "reduce",
3721  v_reduce,
3722  "min",
3723  v_min,
3724  "max",
3725  v_max,
3726  "min_ind",
3727  v_min_ind,
3728  "max_ind",
3729  v_max_ind,
3730  "sum",
3731  v_sum,
3732  "sumsq",
3733  v_sumsq,
3734  "mean",
3735  v_mean,
3736  "var",
3737  v_var,
3738  "stdev",
3739  v_stdev,
3740  "stderr",
3741  v_stderr,
3742  "meansqerr",
3743  v_meansqerr,
3744  "mag",
3745  v_mag,
3746  "contains",
3747  v_contains,
3748  "median",
3749  v_median,
3750 
3751  "dot",
3752  v_dot,
3753  "eq",
3754  v_eq,
3755 
3756  "play_remove",
3757  v_play_remove,
3758 
3759  "fwrite",
3760  v_fwrite,
3761  "fread",
3762  v_fread,
3763  "vwrite",
3764  v_vwrite,
3765  "vread",
3766  v_vread,
3767  "printf",
3768  v_printf,
3769  "scanf",
3770  v_scanf,
3771  "scantil",
3772  v_scantil,
3773 
3774  "fit",
3775  v_fit,
3776  "trigavg",
3777  v_trigavg,
3778  "indwhere",
3779  v_indwhere,
3780 
3781  "scale",
3782  v_scale,
3783 
3784  0,
3785  0};
3786 
3788  v_c,
3789  "cl",
3790  v_cl,
3791  "at",
3792  v_at,
3793  "ind",
3794  v_ind,
3795  "histogram",
3796  v_histogram,
3797  "sumgauss",
3798  v_sumgauss,
3799 
3800  "resize",
3801  v_resize,
3802  "clear",
3803  v_clear,
3804  "set",
3805  v_set,
3806  "append",
3807  v_append,
3808  "copy",
3809  v_copy,
3810  "insrt",
3811  v_insert,
3812  "remove",
3813  v_remove,
3814  "interpolate",
3815  v_interpolate,
3816  "from_double",
3817  v_from_double,
3818 
3819  "index",
3820  v_index,
3821  "apply",
3822  v_apply,
3823  "add",
3824  v_add,
3825  "sub",
3826  v_sub,
3827  "mul",
3828  v_mul,
3829  "div",
3830  v_div,
3831  "fill",
3832  v_fill,
3833  "indgen",
3834  v_indgen,
3835  "addrand",
3836  v_addrand,
3837  "setrand",
3838  v_setrand,
3839  "deriv",
3840  v_deriv,
3841  "integral",
3842  v_integral,
3843 
3844  "sqrt",
3845  v_sqrt,
3846  "abs",
3847  v_abs,
3848  "floor",
3849  v_floor,
3850  "sin",
3851  v_sin,
3852  "pow",
3853  v_pow,
3854  "log",
3855  v_log,
3856  "log10",
3857  v_log10,
3858  "tanh",
3859  v_tanh,
3860 
3861  "correl",
3862  v_correl,
3863  "convlv",
3864  v_convlv,
3865  "spctrm",
3866  v_spctrm,
3867  "filter",
3868  v_filter,
3869  "fft",
3870  v_fft,
3871  "rotate",
3872  v_rotate,
3873  "smhist",
3874  v_smhist,
3875  "hist",
3876  v_hist,
3877  "spikebin",
3878  v_spikebin,
3879  "rebin",
3880  v_rebin,
3881  "medfltr",
3882  v_medfltr,
3883  "sort",
3884  v_sort,
3885  "sortindex",
3886  v_sortindex,
3887  "reverse",
3888  v_reverse,
3889  "resample",
3890  v_resample,
3891  "psth",
3892  v_psth,
3893  "inf",
3894  v_inf,
3895 
3896  "index",
3897  v_index,
3898  "indvwhere",
3899  v_indvwhere,
3900 
3901  "where",
3902  v_where,
3903 
3904  "plot",
3905  v_plot,
3906  "line",
3907  v_line,
3908  "mark",
3909  v_mark,
3910  "ploterr",
3911  v_ploterr,
3912 
3913  "record",
3914  v_record,
3915  "play",
3916  v_play,
3917 
3918  "from_python",
3919  v_from_python,
3920  "to_python",
3921  v_to_python,
3922  "as_numpy",
3923  v_as_numpy,
3924 
3925  0,
3926  0};
3927 
3929  v_label,
3930 
3931  0,
3932  0};
3933 
3934 extern int hoc_araypt(Symbol*, int);
3935 
3937  Vect* vp = (Vect*) o->u.this_pointer;
3938  return vp->size();
3939 }
3940 
3941 double* ivoc_vector_ptr(Object* o, int index) {
3942  check_obj_type(o, "Vector");
3943  Vect* vp = (Vect*) o->u.this_pointer;
3944  return vp->data() + index;
3945 }
3946 
3947 static void steer_x(void* v) {
3948  Vect* vp = (Vect*) v;
3949  int index;
3950  Symbol* s = hoc_spop();
3951  // if you don't want to test then you could get the index off the stack
3952  s->arayinfo->sub[0] = vp->size();
3953  index = hoc_araypt(s, SYMBOL);
3954  hoc_pushpx(vp->data() + index);
3955 }
3956 
3957 void Vector_reg() {
3959  svec_ = hoc_lookup("Vector");
3960  // now make the x variable an actual double
3961  Symbol* sv = hoc_lookup("Vector");
3962  Symbol* sx = hoc_table_lookup("x", sv->u.ctemplate->symtable);
3963  sx->type = VAR;
3964  sx->arayinfo = new Arrayinfo;
3965  sx->arayinfo->refcount = 1;
3966  sx->arayinfo->a_varn = NULL;
3967  sx->arayinfo->nsub = 1;
3968  sx->arayinfo->sub[0] = 1;
3969  sv->u.ctemplate->steer = steer_x;
3970 #if defined(WIN32) && !defined(USEMATRIX)
3971  load_ocmatrix();
3972 #endif
3973 }
3974 
3975 // hacked version of gsort from ../gnu/d_vec.cpp
3976 // the transformation is that everything that used to be a double* becomes
3977 // an int* and cmp(*arg1, *arg2) becomes cmp(vec[*arg1], vec[*arg2])
3978 // I am not sure what to do about the BYTES_PER_WORD
3979 
3980 // An adaptation of Schmidt's new quicksort
3981 
3982 static inline void SWAP(int* A, int* B) {
3983  int tmp = *A;
3984  *A = *B;
3985  *B = tmp;
3986 }
3987 
3988 /* This should be replaced by a standard ANSI macro. */
3989 #define BYTES_PER_WORD 8
3990 #define BYTES_PER_LONG 4
3991 
3992 /* The next 4 #defines implement a very fast in-line stack abstraction. */
3993 
3994 #define STACK_SIZE (BYTES_PER_WORD * BYTES_PER_LONG)
3995 #define PUSH(LOW, HIGH) \
3996  do { \
3997  top->lo = LOW; \
3998  top++->hi = HIGH; \
3999  } while (0)
4000 #define POP(LOW, HIGH) \
4001  do { \
4002  LOW = (--top)->lo; \
4003  HIGH = top->hi; \
4004  } while (0)
4005 #define STACK_NOT_EMPTY (stack < top)
4006 
4007 /* Discontinue quicksort algorithm when partition gets below this size.
4008  This particular magic number was chosen to work best on a Sun 4/260. */
4009 #define MAX_THRESH 4
4010 
4011 
4012 /* Order size using quicksort. This implementation incorporates
4013  four optimizations discussed in Sedgewick:
4014 
4015  1. Non-recursive, using an explicit stack of pointer that
4016  store the next array partition to sort. To save time, this
4017  maximum amount of space required to store an array of
4018  MAX_INT is allocated on the stack. Assuming a 32-bit integer,
4019  this needs only 32 * sizeof (stack_node) == 136 bits. Pretty
4020  cheap, actually.
4021 
4022  2. Chose the pivot element using a median-of-three decision tree.
4023  This reduces the probability of selecting a bad pivot value and
4024  eliminates certain extraneous comparisons.
4025 
4026  3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving
4027  insertion sort to order the MAX_THRESH items within each partition.
4028  This is a big win, since insertion sort is faster for small, mostly
4029  sorted array segements.
4030 
4031  4. The larger of the two sub-partitions is always pushed onto the
4032  stack first, with the algorithm then concentrating on the
4033  smaller partition. This *guarantees* no more than log (n)
4034  stack size is needed! */
4035 
4036 extern "C" int nrn_mlh_gsort(double* vec, int* base_ptr, int total_elems, doubleComparator cmp) {
4037  /* Stack node declarations used to store unfulfilled partition obligations. */
4038  struct stack_node {
4039  int* lo;
4040  int* hi;
4041  };
4042  int pivot_buffer;
4043  int max_thresh = MAX_THRESH;
4044 
4045  if (total_elems > MAX_THRESH) {
4046  int* lo = base_ptr;
4047  int* hi = lo + (total_elems - 1);
4048  int* left_ptr;
4049  int* right_ptr;
4050  stack_node stack[STACK_SIZE]; /* Largest size needed for 32-bit int!!! */
4051  stack_node* top = stack + 1;
4052 
4053  while (STACK_NOT_EMPTY) {
4054  {
4055  int* pivot = &pivot_buffer;
4056  {
4057  /* Select median value from among LO, MID, and HI. Rearrange
4058  LO and HI so the three values are sorted. This lowers the
4059  probability of picking a pathological pivot value and
4060  skips a comparison for both the LEFT_PTR and RIGHT_PTR. */
4061 
4062  int* mid = lo + ((hi - lo) >> 1);
4063 
4064  if (cmp(vec[*mid], vec[*lo]) < 0)
4065  SWAP(mid, lo);
4066  if (cmp(vec[*hi], vec[*mid]) < 0) {
4067  SWAP(mid, hi);
4068  if (cmp(vec[*mid], vec[*lo]) < 0)
4069  SWAP(mid, lo);
4070  }
4071  *pivot = *mid;
4072  pivot = &pivot_buffer;
4073  }
4074  left_ptr = lo + 1;
4075  right_ptr = hi - 1;
4076 
4077  /* Here's the famous ``collapse the walls'' section of quicksort.
4078  Gotta like those tight inner loops! They are the main reason
4079  that this algorithm runs much faster than others. */
4080  do {
4081  while (cmp(vec[*left_ptr], vec[*pivot]) < 0)
4082  left_ptr += 1;
4083 
4084  while (cmp(vec[*pivot], vec[*right_ptr]) < 0)
4085  right_ptr -= 1;
4086 
4087  if (left_ptr < right_ptr) {
4088  SWAP(left_ptr, right_ptr);
4089  left_ptr += 1;
4090  right_ptr -= 1;
4091  } else if (left_ptr == right_ptr) {
4092  left_ptr += 1;
4093  right_ptr -= 1;
4094  break;
4095  }
4096  } while (left_ptr <= right_ptr);
4097  }
4098 
4099  /* Set up pointers for next iteration. First determine whether
4100  left and right partitions are below the threshold size. If so,
4101  ignore one or both. Otherwise, push the larger partition's
4102  bounds on the stack and continue sorting the smaller one. */
4103 
4104  if ((right_ptr - lo) <= max_thresh) {
4105  if ((hi - left_ptr) <= max_thresh) /* Ignore both small partitions. */
4106  POP(lo, hi);
4107  else /* Ignore small left partition. */
4108  lo = left_ptr;
4109  } else if ((hi - left_ptr) <= max_thresh) /* Ignore small right partition. */
4110  hi = right_ptr;
4111  else if ((right_ptr - lo) > (hi - left_ptr)) /* Push larger left partition indices. */
4112  {
4113  PUSH(lo, right_ptr);
4114  lo = left_ptr;
4115  } else /* Push larger right partition indices. */
4116  {
4117  PUSH(left_ptr, hi);
4118  hi = right_ptr;
4119  }
4120  }
4121  }
4122 
4123  /* Once the BASE_PTR array is partially sorted by quicksort the rest
4124  is completely sorted using insertion sort, since this is efficient
4125  for partitions below MAX_THRESH size. BASE_PTR points to the beginning
4126  of the array to sort, and END_PTR points at the very last element in
4127  the array (*not* one beyond it!). */
4128 
4129 
4130  {
4131  int* end_ptr = base_ptr + 1 * (total_elems - 1);
4132  int* run_ptr;
4133  int* tmp_ptr = base_ptr;
4134  int* thresh = (end_ptr < (base_ptr + max_thresh)) ? end_ptr : (base_ptr + max_thresh);
4135 
4136  /* Find smallest element in first threshold and place it at the
4137  array's beginning. This is the smallest array element,
4138  and the operation speeds up insertion sort's inner loop. */
4139 
4140  for (run_ptr = tmp_ptr + 1; run_ptr <= thresh; run_ptr += 1)
4141  if (cmp(vec[*run_ptr], vec[*tmp_ptr]) < 0)
4142  tmp_ptr = run_ptr;
4143 
4144  if (tmp_ptr != base_ptr)
4145  SWAP(tmp_ptr, base_ptr);
4146 
4147  /* Insertion sort, running from left-hand-side up to `right-hand-side.'
4148  Pretty much straight out of the original GNU qsort routine. */
4149 
4150  for (run_ptr = base_ptr + 1; (tmp_ptr = run_ptr += 1) <= end_ptr;) {
4151  while (cmp(vec[*run_ptr], vec[*(tmp_ptr -= 1)]) < 0)
4152  ;
4153 
4154  if ((tmp_ptr += 1) != run_ptr) {
4155  int* trav;
4156 
4157  for (trav = run_ptr + 1; --trav >= run_ptr;) {
4158  int c = *trav;
4159  int *hi, *lo;
4160 
4161  for (hi = lo = trav; (lo -= 1) >= tmp_ptr; hi = lo)
4162  *hi = *lo;
4163  *hi = c;
4164  }
4165  }
4166  }
4167  }
4168  return 1;
4169 }
#define GlyphIndex
Definition: _defines.h:23
#define Glyph
Definition: _defines.h:132
static void del(int *a)
Definition: bgpdmasetup.cpp:99
short index
Definition: cabvars.h:10
short type
Definition: cabvars.h:9
const Brush * brush(int) const
const Color * color(int) const
Definition: graph.h:424
virtual void save(std::ostream &, Coord, Coord)
void brush(const Brush *)
void color(const Color *)
GLabel * label() const
Definition: graph.h:302
Definition: graph.h:57
virtual void erase(Scene *, GlyphIndex, int erase_type)
@ ERASE_LINE
Definition: graph.h:31
void add(float, double *)
IvocVect(Object *obj=NULL)
Definition: ivocvect.cpp:182
char * label_
Definition: ivocvect.h:95
std::vector< double > vec_
Definition: ivocvect.h:96
int buffer_size()
Definition: ivocvect.cpp:1375
Object ** temp_objvar()
Definition: ivocvect.cpp:366
void label(const char *)
Definition: ivocvect.cpp:214
Object * obj_
Definition: ivocvect.h:94
static bool equal(float x, float y, float e)
Definition: math.h:108
static int abs(int)
Definition: math.cpp:43
Definition: ocfile.h:9
bool eof()
Definition: ocfile.cpp:374
FILE * file()
Definition: ocfile.cpp:367
Definition: random1.h:9
Random * rand
Definition: random1.h:14
virtual void remove(GlyphIndex)
Symbol * hoc_table_lookup(const char *, Symlist *)
Definition: symbol.cpp:61
static Frame * fp
Definition: code.cpp:161
#define stack
Definition: code.cpp:135
double cm
Definition: coord.h:49
double points
Definition: coord.h:49
double dt
Definition: netcvode.cpp:76
double t
Definition: cvodeobj.cpp:59
sprintf(buf, " if (secondorder) {\n" " int _i;\n" " for (_i = 0; _i < %d; ++_i) {\n" " _p[_slist%d[_i]] += dt*_p[_dlist%d[_i]];\n" " }}\n", numeqn, listnum, listnum)
static int indx
Definition: deriv.cpp:294
#define dc
double chkarg(int, double low, double high)
Definition: code2.cpp:638
#define c
#define xc
Definition: extcelln.cpp:87
double hoc_epsilon
Definition: hoc_init.cpp:396
void nrngsl_realft(double *data, unsigned long n, int direction)
Definition: fourier.cpp:43
void hoc_execerror(const char *, const char *)
Definition: hoc.cpp:754
void nrn_correl(double *x, double *y, unsigned long n, double *z)
Definition: fourier.cpp:131
void nrn_nrc2gsl(double *x, double *y, unsigned long n)
Definition: fourier.cpp:70
void nrn_convlv(double *data, unsigned long n, double *respns, unsigned long m, int isign, double *ans)
Definition: fourier.cpp:87
void nrn_spctrm(double *data, double *psd, int setsize, int numsegpairs)
Definition: fourier.cpp:154
void nrn_gsl2nrc(double *x, double *y, unsigned long n)
Definition: fourier.cpp:57
BrushPalette * brushes
ColorPalette * colors
char buf[512]
Definition: init.cpp:13
int hoc_is_object_arg(int narg)
Definition: code.cpp:756
double hoc_call_func(Symbol *s, int narg)
Definition: code.cpp:1462
Object ** hoc_temp_objvar(Symbol *symtemp, void *v)
Definition: hoc_oop.cpp:491
int vector_instance_px(void *, double **)
Definition: ivocvect.cpp:391
void hoc_pushpx(double *d)
Definition: code.cpp:716
int vector_arg_px(int, double **)
Definition: ivocvect.cpp:413
Symbol * hoc_install(const char *, int, double, Symlist **)
int hoc_is_str_arg(int narg)
Definition: code.cpp:752
Vect * vector_new(int n, Object *o)
Definition: ivocvect.cpp:301
int hoc_argtype(int narg)
Definition: code.cpp:738
double hoc_call_objfunc(Symbol *s, int narg, Object *ob)
Definition: hoc_oop.cpp:389
void install_vector_method(const char *name, Pfrd_vp)
Definition: ivocvect.cpp:379
int hoc_is_double_arg(int narg)
Definition: code.cpp:744
Vect * vector_arg(int i)
Definition: ivocvect.cpp:397
Vect * vector_new0()
Definition: ivocvect.cpp:304
int is_vector_arg(int i)
Definition: ivocvect.cpp:405
Symbol * hoc_lookup(const char *)
Vect * vector_new1(int n)
Definition: ivocvect.cpp:307
double * hoc_pgetarg(int narg)
Definition: code.cpp:1623
int nrn_mlh_gsort(double *vec, int *base_ptr, int total_elems, doubleComparator cmp)
Definition: ivocvect.cpp:4036
Symbol * hoc_spop(void)
#define TRY_GUI_REDIRECT_METHOD_ACTUAL_OBJ(name, sym, v)
Definition: gui-redirect.h:35
void start()
Definition: hel2mos.cpp:204
double(* func)(double)
Definition: hoc_init.cpp:164
#define IFGUI
Definition: hocdec.h:372
double(* Pfrd)(void)
Definition: hocdec.h:41
#define getarg
Definition: hocdec.h:15
#define gargstr
Definition: hocdec.h:14
struct Arrayinfo Arrayinfo
#define ENDGUI
Definition: hocdec.h:373
double(* Pfrd_vp)(void *)
Definition: hocdec.h:47
int(* Pfri)(void)
Definition: hocdec.h:39
Object ** hoc_objgetarg(int)
Definition: code.cpp:1587
#define ind(mm, x)
Definition: isaac64.cpp:18
const char * neuron_home
Definition: hoc_init.cpp:404
int ifarg(int)
Definition: code.cpp:1581
void hoc_pushx(double)
#define EPSILON
Definition: ivocvect.cpp:163
double * ivoc_vector_ptr(Object *o, int index)
Definition: ivocvect.cpp:3941
#define ONE_BYTE_HALF
Definition: ivocvect.cpp:161
static Object ** v_c(void *v)
Definition: ivocvect.cpp:1632
static Object ** v_append(void *v)
Definition: ivocvect.cpp:1407
static double v_scale(void *v1)
Definition: ivocvect.cpp:2383
static Object ** v_sort(void *v)
Definition: ivocvect.cpp:3322
static Object ** v_record(void *v)
Definition: ivocvect.cpp:939
static void SWAP(int *A, int *B)
Definition: ivocvect.cpp:3982
static Object ** v_ploterr(void *v)
Definition: ivocvect.cpp:1016
static double v_contains(void *v)
Definition: ivocvect.cpp:1478
static Object ** v_sqrt(void *v)
Definition: ivocvect.cpp:3565
static Object ** v_indgen(void *v)
Definition: ivocvect.cpp:1978
static Object ** v_resample(void *v)
Definition: ivocvect.cpp:3419
static Object ** v_sortindex(void *v)
Definition: ivocvect.cpp:1606
static Object ** v_deriv(void *v)
Definition: ivocvect.cpp:3148
#define FWrite(arg1, arg2, arg3, arg4)
Definition: ivocvect.cpp:72
static Member_func v_members[]
Definition: ivocvect.cpp:3710
static double v_fwrite(void *v)
Definition: ivocvect.cpp:437
void vector_append(Vect *v, double x)
Definition: ivocvect.cpp:340
static void steer_x(void *v)
Definition: ivocvect.cpp:3947
Object ** vector_temp_objvar(Vect *v)
Definition: ivocvect.cpp:325
int cmpfcn(double a, double b)
Definition: ivocvect.cpp:166
static double v_fit(void *v)
Definition: ivocvect.cpp:2735
Object ** v_as_numpy(void *v)
Definition: ivocvect.cpp:3699
static Object ** v_fft(void *v)
Definition: ivocvect.cpp:3018
#define BYTEHEADER
Definition: ivocvect.cpp:108
int vector_capacity(Vect *v)
Definition: ivocvect.cpp:319
static double v_stderr(void *v)
Definition: ivocvect.cpp:2244
static Object ** v_index(void *v)
Definition: ivocvect.cpp:3645
int(* doubleComparator)(double, double)
Definition: ivocvect.cpp:169
static Object ** v_line(void *v)
Definition: ivocvect.cpp:1061
static int possible_srcvec(Vect *&src, Vect *dest, int &flag)
Definition: ivocvect.cpp:1689
Symlist * hoc_top_level_symlist
Definition: symdir.cpp:23
static Object ** v_at(void *v)
Definition: ivocvect.cpp:1572
static Object ** v_ind(void *v)
Definition: ivocvect.cpp:1338
static double v_buffer_size(void *v)
Definition: ivocvect.cpp:1365
int ivoc_vector_size(Object *o)
Definition: ivocvect.cpp:3936
void vector_resize(Vect *v, int n)
Definition: ivocvect.cpp:322
static double v_eq(void *v1)
Definition: ivocvect.cpp:2406
static Object ** v_insert(void *v)
Definition: ivocvect.cpp:1424
static double v_sum(void *v)
Definition: ivocvect.cpp:2164
static Object ** v_tanh(void *v)
Definition: ivocvect.cpp:3625
static Object ** v_hist(void *v)
Definition: ivocvect.cpp:1189
static double splx_evl_
Definition: ivocvect.cpp:2476
static Object ** v_set(void *v)
Definition: ivocvect.cpp:1400
#define MAX_THRESH
Definition: ivocvect.cpp:4009
static Object ** v_smhist(void *v)
Definition: ivocvect.cpp:1256
double hoc_Sqrt(double x)
Vect * vector_new2(Vect *v)
Definition: ivocvect.cpp:310
static Object ** v_medfltr(void *v)
Definition: ivocvect.cpp:3259
static double v_sumsq(void *v)
Definition: ivocvect.cpp:2176
#define SIMPLEX_INORM
Definition: ivocvect.cpp:2456
static double v_trigavg(void *v)
Definition: ivocvect.cpp:3222
static const char ** v_label(void *v)
Definition: ivocvect.cpp:227
#define PI
Definition: ivocvect.cpp:59
double(* nrnpy_object_to_double_)(Object *)
Definition: xmenu.cpp:14
static Object ** v_mark(void *v)
Definition: ivocvect.cpp:1112
static Object ** v_sumgauss(void *v)
Definition: ivocvect.cpp:1217
static double v_max(void *v)
Definition: ivocvect.cpp:2133
#define FRead(arg1, arg2, arg3, arg4)
Definition: ivocvect.cpp:75
void notify_freed_val_array(double *, size_t)
Definition: ivoc.cpp:101
static Object ** v_integral(void *v)
Definition: ivocvect.cpp:3195
char * vector_get_label(Vect *v)
Definition: ivocvect.cpp:334
#define STACK_SIZE
Definition: ivocvect.cpp:3994
static Object ** v_add(void *v1)
Definition: ivocvect.cpp:2317
static Object ** v_sub(void *v1)
Definition: ivocvect.cpp:2334
static double simplex(double *p, int n, Vect *x, Vect *y, char *fcn)
Definition: ivocvect.cpp:2576
static Object ** v_correl(void *v)
Definition: ivocvect.cpp:2825
static double dmaxint_
As all parameters are passed from hoc as double, we need to calculate max integer that can fit into d...
Definition: ivocvect.cpp:99
double hoc_Log10(double x)
static Symbol * svec_
Definition: ivocvect.cpp:297
#define SIMPLEX_GAMMA
Definition: ivocvect.cpp:2466
static Object ** v_pow(void *v)
Definition: ivocvect.cpp:3516
Object **(* nrnpy_vec_as_numpy_helper_)(int, double *)
Definition: ivocvect.cpp:140
static double v_min(void *v)
Definition: ivocvect.cpp:2102
static double v_size(void *v)
Definition: ivocvect.cpp:1359
static double v_meansqerr(void *v1)
Definition: ivocvect.cpp:2262
void nrn_exit(int)
Definition: hoc.cpp:219
static int sort_index_cmp(const void *a, const void *b)
Definition: ivocvect.cpp:1596
static double eval_error(double *p, int n, Vect *x, Vect *y, char *fcn)
Definition: ivocvect.cpp:2559
static Object ** v_spctrm(void *v)
Definition: ivocvect.cpp:2928
static double v_median(void *v)
Definition: ivocvect.cpp:3298
static Object ** v_fill(void *v)
Definition: ivocvect.cpp:1966
static double v_dot(void *v1)
Definition: ivocvect.cpp:2294
static double v_var(void *v)
Definition: ivocvect.cpp:2208
void Vector_reg()
Definition: ivocvect.cpp:3957
static Object ** v_plot(void *v)
Definition: ivocvect.cpp:957
Object ** vector_pobj(Vect *v)
Definition: ivocvect.cpp:331
static double eval(double *p, int n, Vect *x, Vect *y, char *fcn)
Definition: ivocvect.cpp:2480
static double v_indwhere(void *v)
Definition: ivocvect.cpp:1793
static Object ** v_abs(void *v)
Definition: ivocvect.cpp:3585
#define SIMPLEX_ALPHA
Definition: ivocvect.cpp:2464
int vector_buffer_size(Vect *v)
Definition: ivocvect.cpp:316
static double v_vread(void *v)
Definition: ivocvect.cpp:658
double * vector_vec(Vect *v)
Definition: ivocvect.cpp:328
Object **(* nrnpy_vec_to_python_p_)(void *)
Definition: ivocvect.cpp:139
static Object ** v_rebin(void *v)
Definition: ivocvect.cpp:3393
#define TWO_BYTE_HIGH
Definition: ivocvect.cpp:159
double hoc_Log(double x)
static Object ** v_reverse(void *v)
Definition: ivocvect.cpp:3328
double hoc_Exp(double)
Definition: math.cpp:44
static const char * nullstr
Definition: ivocvect.cpp:225
void vector_set_label(Vect *v, char *s)
Definition: ivocvect.cpp:337
#define MAX_FIT_PARAMS
Definition: ivocvect.cpp:157
static int narg()
Definition: ivocvect.cpp:150
static double v_scantil(void *v)
Definition: ivocvect.cpp:887
static double v_get(void *v)
Definition: ivocvect.cpp:1395
int hoc_return_type_code
Definition: code.cpp:42
#define SIMPLEX_DELTA
Definition: ivocvect.cpp:2467
#define PUBLIC_TYPE
Object ** v_from_python(void *v)
Definition: ivocvect.cpp:3684
static Object ** v_log(void *v)
Definition: ivocvect.cpp:3353
void nrn_vecsim_remove(void *)
Definition: datapath.cpp:21
#define SIMPLEX_MAXN
Definition: ivocvect.cpp:2455
#define POP(LOW, HIGH)
Definition: ivocvect.cpp:4000
static int renew_
Definition: ivocvect.cpp:2477
static Object ** v_copy(void *v)
Definition: ivocvect.cpp:1490
double call_simplex(double *p, int n, Vect *x, Vect *y, char *fcn, int trial)
Definition: ivocvect.cpp:2712
static double v_min_ind(void *v)
Definition: ivocvect.cpp:2117
void vector_delete(Vect *v)
Definition: ivocvect.cpp:313
static Object ** v_setrand(void *v)
Definition: ivocvect.cpp:2032
static double v_stdev(void *v)
Definition: ivocvect.cpp:2226
static Object ** v_addrand(void *v)
Definition: ivocvect.cpp:2015
static double v_fread(void *v)
Definition: ivocvect.cpp:463
static Object ** v_cl(void *v)
Definition: ivocvect.cpp:1636
static Object ** v_play(void *v)
Definition: ivocvect.cpp:950
static double v_reduce(void *v)
Definition: ivocvect.cpp:2077
static Object ** v_sin(void *v)
Definition: ivocvect.cpp:3335
static Object ** v_apply(void *v)
Definition: ivocvect.cpp:2050
static Object ** v_convlv(void *v)
Definition: ivocvect.cpp:2871
static void same_err(const char *s, Vect *x, Vect *y)
Definition: ivocvect.cpp:238
#define PUSH(LOW, HIGH)
Definition: ivocvect.cpp:3995
void nrn_vecsim_add(void *, bool)
Definition: datapath.cpp:18
int hoc_araypt(Symbol *, int)
static int possible_destvec(int arg, Vect *&dest)
Definition: ivocvect.cpp:422
static Object ** v_psth(void *v)
Definition: ivocvect.cpp:3439
static double v_scanf(void *v)
Definition: ivocvect.cpp:823
static Object ** v_remove(void *v)
Definition: ivocvect.cpp:1461
static Object ** v_from_double(void *v)
Definition: ivocvect.cpp:2305
static Object ** v_filter(void *v)
Definition: ivocvect.cpp:2966
static double v_max_ind(void *v)
Definition: ivocvect.cpp:2148
static Object ** v_div(void *v1)
Definition: ivocvect.cpp:2367
static double v_mag(void *v1)
Definition: ivocvect.cpp:2300
static Object ** v_inf(void *x)
Definition: ivocvect.cpp:3476
static Object ** v_resize(void *v)
Definition: ivocvect.cpp:1383
static Object ** v_floor(void *v)
Definition: ivocvect.cpp:3605
static double v_printf(void *v)
Definition: ivocvect.cpp:772
static Member_ret_obj_func v_retobj_members[]
Definition: ivocvect.cpp:3787
static Object ** v_mul(void *v1)
Definition: ivocvect.cpp:2350
static Object ** v_spikebin(void *v)
Definition: ivocvect.cpp:3061
static double v_mean(void *v)
Definition: ivocvect.cpp:2188
static Object ** v_log10(void *v)
Definition: ivocvect.cpp:3373
static Object ** v_where(void *v)
Definition: ivocvect.cpp:1701
#define SIMPLEX_BETA
Definition: ivocvect.cpp:2465
static Object ** v_clear(void *v)
Definition: ivocvect.cpp:1389
double hoc_scan(FILE *)
Definition: fileio.cpp:339
static Object ** v_histogram(void *v)
Definition: ivocvect.cpp:1162
#define BYTESWAP(_X__, _TYPE__)
Definition: ivocvect.cpp:113
Object ** v_to_python(void *v)
Definition: ivocvect.cpp:3692
static Object ** v_interpolate(void *v)
Definition: ivocvect.cpp:1642
static void * v_cons(Object *o)
Definition: ivocvect.cpp:270
Object * hoc_thisobject
Definition: hoc_oop.cpp:122
IvocVect *(* nrnpy_vec_from_python_p_)(void *)
Definition: ivocvect.cpp:138
static Member_ret_str_func v_retstr_members[]
Definition: ivocvect.cpp:3928
static double v_play_remove(void *v)
Definition: ivocvect.cpp:432
#define STACK_NOT_EMPTY
Definition: ivocvect.cpp:4005
static Object ** v_indvwhere(void *v)
Definition: ivocvect.cpp:1877
static Object ** v_rotate(void *v)
Definition: ivocvect.cpp:3096
#define ONE_BYTE_HIGH
Definition: ivocvect.cpp:160
static void v_destruct(void *v)
Definition: ivocvect.cpp:293
static double v_vwrite(void *v)
Definition: ivocvect.cpp:538
double var(InputIterator begin, InputIterator end)
Definition: ivocvect.h:101
#define Vect
Definition: ivocvect.h:14
double stdDev(InputIterator begin, InputIterator end)
Definition: ivocvect.h:113
Object ** hoc_temp_objptr(Object *)
Definition: code.cpp:216
#define min(a, b)
Definition: matrix.h:157
#define max(a, b)
Definition: matrix.h:154
static char * format
Definition: matrixio.c:386
#define v
Definition: md1redef.h:4
#define id
Definition: md1redef.h:33
#define i
Definition: md1redef.h:12
#define SYMBOL
Definition: model.h:102
#define Printf
Definition: model.h:237
tanh
Definition: extdef.h:4
ceil
Definition: extdef.h:4
sqrt
Definition: extdef.h:3
floor
Definition: extdef.h:4
log10
Definition: extdef.h:4
sin
Definition: extdef.h:3
gauss
Definition: extdef.h:8
pow
Definition: extdef.h:4
log
Definition: extdef.h:4
step
Definition: extdef.h:7
char * name
Definition: init.cpp:16
#define A(i)
Definition: multisplit.cpp:63
#define B(i)
Definition: multisplit.cpp:64
#define printf
Definition: mwprefix.h:26
#define fprintf
Definition: mwprefix.h:30
int const size_t const size_t n
Definition: nrngsl.h:11
#define FUNCTION(a, b)
Definition: nrngsl.h:6
return status
size_t p
size_t j
#define MUTCONSTRUCT(mkmut)
Definition: nrnmutdec.h:70
#define MUTDESTRUCT
Definition: nrnmutdec.h:71
void class2oc(const char *, void *(*cons)(Object *), void(*destruct)(void *), Member_func *, int(*checkpoint)(void **), Member_ret_obj_func *, Member_ret_str_func *)
Definition: hoc_oop.cpp:1560
static philox4x32_key_t k
Definition: nrnran123.cpp:11
static realtype retval
static double ref(void *v)
Definition: ocbox.cpp:383
#define BinaryMode(ocfile)
Definition: ocfile.h:61
#define STRING
Definition: bbslsrv.cpp:9
static double post(void *v)
Definition: ocbbs.cpp:319
#define g
Definition: passive0.cpp:21
#define e
Definition: passive0.cpp:22
#define data
Definition: rbtqueue.cpp:49
#define color
Definition: rbtqueue.cpp:50
#define arg
Definition: redef.h:28
#define add
Definition: redef.h:24
static uint32_t value
Definition: scoprand.cpp:25
check_obj_type(o, "SectionList")
o
Definition: seclist.cpp:175
#define NULL
Definition: sptree.h:16
unsigned * a_varn
Definition: hocdec.h:69
int nsub
Definition: hocdec.h:70
int refcount
Definition: hocdec.h:71
int sub[1]
Definition: hocdec.h:72
Definition: hocdec.h:227
void * this_pointer
Definition: hocdec.h:232
union Object::@39 u
Inst defn
Definition: hocdec.h:76
double x
Definition: ivocvect.cpp:1592
Definition: model.h:57
Proc * u_proc
Definition: hocdec.h:145
short cpublic
Note: public is a reserved keyword.
Definition: hocdec.h:125
short type
Definition: model.h:58
union Symbol::@18 u
HocStruct cTemplate * ctemplate
Definition: hocdec.h:152
Arrayinfo * arayinfo
Definition: hocdec.h:159
Definition: hocdec.h:84
Symlist * symtable
Definition: hocdec.h:197
void(* steer)(void *)
Definition: hocdec.h:209
Pfrd pfd
Definition: hocdec.h:53