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