PageRenderTime 221ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 0ms

/src/ivoc/ivocvect.cpp

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