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