NEURON
functabl.cpp
Go to the documentation of this file.
1 #include <../../nrnconf.h>
2 #include "hoc.h"
3 
4 #define INTERPOLATE 1
5 
6 typedef struct TableArg {
7  int nsize;
8  double* argvec; /* if nil use min,max */
9  double min;
10  double max;
11 #if INTERPOLATE
12  double frac; /* temporary storage */
13 #endif
14 } TableArg;
15 
16 typedef struct FuncTable {
17  double* table;
19  double value; /* if constant this is it */
20 } FuncTable;
21 
22 static int arg_index(TableArg* ta, double x)
23 {
24  int j;
25 
26  if (ta->argvec) {
27  int t0, t1;
28 #if INTERPOLATE
29  ta->frac = 0.;
30 #endif
31  t0 = 0;
32  t1 = ta->nsize-1;
33  if (x <= ta->argvec[t0]) {
34  j = 0;
35  }else if (x >= ta->argvec[t1]) {
36  j = t1;
37  }else{
38  while (t0 < (t1-1)) {
39  j = (t0 + t1)/2;
40 #if 0
41 printf("x[%d]=%g x[%d]=%g x[%d]=%g\n", t0, ta->argvec[t0], j, ta->argvec[j], t1, ta->argvec[t1]);
42 #endif
43  if (ta->argvec[j] <= x) {
44  t0 = j;
45  }else{
46  t1 = j;
47  }
48  }
49  j = t0;
50 #if INTERPOLATE
51 ta->frac = (x - ta->argvec[j])/(ta->argvec[j+1] - ta->argvec[j]);
52 #if 0
53 printf("x[%d]=%g frac=%g x=%g\n", j, ta->argvec[j], ta->frac, x);
54 #endif
55 #endif
56  }
57  }else{
58 #if INTERPOLATE
59  ta->frac = 0.;
60 #endif
61  if (x <= ta->min) {
62  j = 0;
63  }else if (x >= ta->max) {
64  j = ta->nsize -1;
65  }else{
66  double d, x1;
67  d = (ta->max - ta->min)/((double)(ta->nsize - 1));
68  x1 = (x - ta->min)/d;
69  j = (int)x1;
70 #if INTERPOLATE
71  ta->frac = x1 - (double)j;
72 #endif
73  }
74  }
75  return j;
76 }
77 
78 static double inter(double frac, double* tab, int j)
79 {
80  if (frac > 0.) {
81  return (1. - frac)*tab[j] + frac*tab[j+1];
82  }else{
83  return tab[j];
84  }
85 }
86 
87 static double interp(double frac, double x1, double x2)
88 {
89  if (frac > 0.) {
90  return (1. - frac)*x1 + frac*x2;
91  }else{
92  return x1;
93  }
94 }
95 
96 double hoc_func_table(void* vpft, int n, double* args)
97 {
98  int i, j;
99  double* tab;
100  FuncTable* ft = (FuncTable*)vpft;
101  if (!ft) {
102  hoc_execerror("table not specified in hoc_func_table", (char*)0);
103  }
104  tab = ft->table;
105  j = 0;
106  for (i=0; i < n; ++i) {
107  j = (j * ft->targs[i].nsize) + arg_index(ft->targs + i, args[i]);
108 /*
109 printf("calculating j: i=%d args=%g j=%d frac=%g\n", i, args[i], j, ft->targs[i].frac);
110 */
111  }
112 #if INTERPOLATE
113  if (n == 1) {
114  return inter(ft->targs[0].frac, tab, j);
115  }else if (n == 2) {
116  /* adjacent indices ar adjacent values of y dimension */
117  double y1, y2;
118  double fy = ft->targs[1].frac;
119  y1 = inter(fy, tab, j);
120 /*
121 printf("calculating y1: fy=%g j=%d y1=%g, tabj=%g\n", fy, j, y1, tab[j]);
122 */
123  if (ft->targs[0].frac) { /* x dimension fraction */
124  int j1 = j + ft->targs[1].nsize;
125  y2 = inter(fy, tab, j1);
126 /*
127 printf("calculating y2: fx=%g fy=%g j1=%d y2=%g tabj1=%g\n", ft->targs[0].frac, fy, j1, y2, tab[j1]);
128 */
129  return interp(ft->targs[0].frac, y1, y2);
130  }else{
131  return y1;
132  }
133  }else{
134  return tab[j];
135  }
136 #else
137  return tab[j];
138 #endif
139 }
140 
141 void hoc_spec_table(void** vppt, int n)
142 {
143  int i, argcnt;
144  FuncTable** ppt = (FuncTable**)vppt;
145  FuncTable* ft;
146  TableArg* ta;
147  if (!*ppt) {
148  *ppt = (FuncTable*) ecalloc(1, sizeof(FuncTable));
149  (*ppt)->targs = (TableArg*) ecalloc(n, sizeof(TableArg));
150  }
151  ft = *ppt;
152  ta = ft->targs;
153  argcnt = 2;
154  if (!ifarg(2)) { /* set to constant */
155  ft->value = *getarg(1);
156  ft->table = &ft->value;
157  for (i=0; i < n; ++i) {
158  ta[i].nsize = 1;
159  ta[i].argvec = (double*)0;
160  ta[i].min = 1e20;
161  ta[i].max = 1e20;
162  }
163  return;
164  }
165  if (hoc_is_object_arg(1)) {
166  int ns;
167  if (n > 1) {
168 hoc_execerror("Vector arguments allowed only for functions", "of one variable");
169  }
170  ns = vector_arg_px(1, &ft->table);
171  ta[0].nsize = vector_arg_px(2, &ta[0].argvec);
172  if (ns != ta[0].nsize) {
173  hoc_execerror("Vector arguments not same size", (char*)0);
174  }
175  }else{
176  for (i = 0; i < n; ++i) {
177  ta[i].nsize = *getarg(argcnt++);
178  if (ta[i].nsize < 1) {
179  hoc_execerror("size arg < 1 in hoc_spec_table", (char*)0);
180  }
181  if (hoc_is_double_arg(argcnt)) {
182  ta[i].min = *getarg(argcnt++);
183  ta[i].max = *getarg(argcnt++);
184  if (ta[i].max < ta[i].min) {
185  hoc_execerror("min > max in hoc_spec_table", (char*)0);
186  }
187  ta[i].argvec = (double*)0;
188  }else{
189  ta[i].argvec = hoc_pgetarg(argcnt++);
190  }
191  }
192  ft->table = hoc_pgetarg(1);
193  }
194 }
void * ecalloc(size_t n, size_t size)
Definition: symbol.cpp:221
struct FuncTable FuncTable
double max
Definition: functabl.cpp:10
int hoc_is_double_arg(int narg)
Definition: code.cpp:733
static int arg_index(TableArg *ta, double x)
Definition: functabl.cpp:22
static double interp(double frac, double x1, double x2)
Definition: functabl.cpp:87
double min
Definition: functabl.cpp:9
double * hoc_pgetarg(int narg)
Definition: code.cpp:1604
double hoc_func_table(void *vpft, int n, double *args)
Definition: functabl.cpp:96
int const size_t const size_t n
Definition: nrngsl.h:12
#define printf
Definition: mwprefix.h:26
struct TableArg TableArg
int
Definition: nrnmusic.cpp:71
void hoc_execerror(const char *, const char *)
Definition: hoc.cpp:741
double * table
Definition: functabl.cpp:17
double * argvec
Definition: functabl.cpp:8
size_t j
double value
Definition: functabl.cpp:19
int ifarg(int)
Definition: code.cpp:1562
double frac
Definition: functabl.cpp:12
void hoc_spec_table(void **vppt, int n)
Definition: functabl.cpp:141
#define getarg
Definition: hocdec.h:15
#define i
Definition: md1redef.h:12
int nsize
Definition: functabl.cpp:7
TableArg * targs
Definition: functabl.cpp:18
static double inter(double frac, double *tab, int j)
Definition: functabl.cpp:78
int hoc_is_object_arg(int narg)
Definition: code.cpp:745
int vector_arg_px(int, double **)
Definition: ivocvect.cpp:348