MP-Gadget  5.0.1.dev1-76bc7d4726-dirty
interp.c
Go to the documentation of this file.
1 #include <stdio.h>
2 #include <stddef.h>
3 #include <stdlib.h>
4 #include <math.h>
5 
6 #include "interp.h"
7 #include "mymalloc.h"
8 
9 void interp_init(Interp * obj, int Ndim, int64_t * dims) {
10  ptrdiff_t N = 1;
11  int d;
12  for(d = 0 ; d < Ndim; d ++) {
13  N *= dims[d];
14  }
15 
16  /* alloc memory */
17  obj->Ndim = Ndim;
18  obj->data = mymalloc("interp_data", 0
19  + sizeof(double) * Ndim * 3
20  + sizeof(ptrdiff_t) * Ndim
21  + sizeof(int) * Ndim);
22 
23  obj->dims = (int *) obj->data;
24  obj->strides = (ptrdiff_t*) (obj->dims + Ndim);
25  obj->Min = (double*) (obj->strides + Ndim);
26  obj->Step = obj->Min + Ndim;
27  obj->Max = obj->Step + Ndim;
28 
29  /* fillin strides */
30  N = 1;
31  for(d = Ndim - 1 ; d >= 0; d --) {
32  obj->dims[d] = dims[d];
33  /* column first, C ordering */
34  obj->strides[d] = N;
35  N *= dims[d];
36  }
37 
38  int fsize = 1;
39  for(d = 0; d < obj->Ndim; d++) {
40  fsize *= 2;
41  }
42  obj->fsize = fsize;
43 }
44 
45 /* set up an interpolation dimension.
46  * Max is inclusive. aka if dims[d] == 2, Min = 0, Max = 1
47  * then the steps are 0, 1.
48  *
49  **/
50 void interp_init_dim(Interp * obj, int d, double Min, double Max) {
51  obj->Min[d] = Min;
52  obj->Max[d] = Max;
53  obj->Step[d] = (Max - Min) / (obj->dims[d] - 1);
54 }
55 
56 
57 static ptrdiff_t linearindex(ptrdiff_t * strides, int * xi, int Ndim) {
58  int d;
59  ptrdiff_t rt = 0;
60  for(d = 0; d < Ndim; d++) {
61  rt += strides[d] * xi[d] ;
62  }
63  return rt;
64 }
65 
66 /* status:
67  * 0 if interplation is good on that axis
68  * -1 below
69  * +1 above
70  * status needs to be array of Ndim
71  * */
72 double interp_eval(Interp * obj, double * x, double * ydata, int * status) {
73  int d;
74  if(status == NULL) {
75  status = (int *) alloca(sizeof(int) * obj->Ndim);
76  }
77  int * xi = (int *) alloca(sizeof(int) * obj->Ndim);
78  double * f = (double *) alloca(sizeof(double) * obj->Ndim);
79 
80  for(d = 0; d < obj->Ndim; d++) {
81  double xd = (x[d] - obj->Min[d]) / obj->Step[d];
82  if (x[d] < obj->Min[d]) {
83  status[d] = -1;
84  xi[d] = 0;
85  f[d] = 0;
86  } else
87  if (x[d] > obj->Max[d]) {
88  status[d] = 1;
89  xi[d] = obj->dims[d] - 1;
90  f[d] = 0;
91  } else {
92  xi[d] = floor(xd);
93  f[d] = xd - xi[d];
94  status[d] = 0;
95  }
96  }
97 
98  double ret = 0;
99  /* the origin, "this point" */
100  ptrdiff_t l0 = linearindex(obj->strides, xi, obj->Ndim);
101 
102  int i;
103  /* for each point covered by the filter */
104  for(i = 0; i < obj->fsize; i ++) {
105  double filter = 1.0;
106  ptrdiff_t l = l0;
107  int skip = 0;
108  for(d = 0; d < obj->Ndim; d++ ) {
109  int foffset = (i & (1 << d))?1:0;
110  if(f[d] == 0 && foffset == 1) {
111  /* on this dimension the second data point
112  * is not needed */
113  skip = 1;
114  break;
115  }
116 
117  /*
118  * are we on this point or next point?
119  *
120  * weight on next point is f[d]
121  * weight on this point is 1 - f[d]
122  * */
123  filter *= foffset?f[d] : (1 - f[d]);
124  l += foffset * obj->strides[d];
125  }
126  if(!skip) {
127  ret += ydata[l] * filter;
128  }
129  }
130  return ret;
131 }
132 
133 /* interpolation assuming periodic boundary */
134 double interp_eval_periodic(Interp * obj, double * x, double * ydata) {
135  int * xi = (int *) alloca(sizeof(int) * obj->Ndim);
136  int * xi1 = (int *) alloca(sizeof(int) * obj->Ndim);
137  double * f = (double *) alloca(sizeof(double) * obj->Ndim);
138 
139  int d;
140  for(d = 0; d < obj->Ndim; d++) {
141  double xd = (x[d] - obj->Min[d]) / obj->Step[d];
142  xi[d] = floor(xd);
143  f[d] = xd - xi[d];
144  }
145 
146  double ret = 0;
147  /* the origin, "this point" */
148 
149  int i;
150  /* for each point covered by the filter */
151  for(i = 0; i < obj->fsize; i ++) {
152  double filter = 1.0;
153  for(d = 0; d < obj->Ndim; d++ ) {
154  int foffset = (i & (1 << d))?1:0;
155  xi1[d] = xi[d] + foffset;
156  while(xi1[d] >= obj->dims[d]) xi1[d] -= obj->dims[d];
157  while(xi1[d] < 0 ) xi1[d] += obj->dims[d];
158  /*
159  * are we on this point or next point?
160  *
161  * weight on next point is f[d]
162  * weight on this point is 1 - f[d]
163  * */
164  filter *= foffset?f[d] : (1 - f[d]);
165  }
166  ptrdiff_t l = linearindex(obj->strides, xi1, obj->Ndim);
167  ret += ydata[l] * filter;
168  }
169  return ret;
170 }
171 
172 void interp_destroy(Interp * obj) {
173  myfree(obj->data);
174 }
175 
double interp_eval(Interp *obj, double *x, double *ydata, int *status)
Definition: interp.c:72
void interp_init(Interp *obj, int Ndim, int64_t *dims)
Definition: interp.c:9
void interp_destroy(Interp *obj)
Definition: interp.c:172
static ptrdiff_t linearindex(ptrdiff_t *strides, int *xi, int Ndim)
Definition: interp.c:57
void interp_init_dim(Interp *obj, int d, double Min, double Max)
Definition: interp.c:50
double interp_eval_periodic(Interp *obj, double *x, double *ydata)
Definition: interp.c:134
#define mymalloc(name, size)
Definition: mymalloc.h:15
#define myfree(x)
Definition: mymalloc.h:19
Definition: interp.h:6
int Ndim
Definition: interp.h:7
ptrdiff_t * strides
Definition: interp.h:9
void * data
Definition: interp.h:14
double * Max
Definition: interp.h:12
double * Step
Definition: interp.h:11
int * dims
Definition: interp.h:8
int fsize
Definition: interp.h:15
double * Min
Definition: interp.h:10