38#include <boost/multi_array.hpp>
39#include <boost/numeric/ublas/matrix.hpp>
40#include <boost/numeric/ublas/matrix_proxy.hpp>
41#include <boost/numeric/ublas/storage.hpp>
45typedef unsigned int uint;
46typedef vector<int> iVec;
47typedef vector<double> dVec;
70template <
int N,
class T,
bool CopyData = true,
bool Continuous = true,
class ArrayRefCountT = EmptyClass,
class Gr
idRefCountT = EmptyClass>
74 typedef ArrayRefCountT array_ref_count_type;
75 typedef GridRefCountT grid_ref_count_type;
77 static const int m_N = N;
78 static const bool m_bCopyData = CopyData;
79 static const bool m_bContinuous = Continuous;
81 typedef boost::numeric::ublas::array_adaptor<T> grid_type;
82 typedef boost::const_multi_array_ref<T, N> array_type;
83 typedef std::unique_ptr<array_type> array_type_ptr;
86 ArrayRefCountT m_ref_F;
89 vector<grid_type> m_grid_list;
90 vector<GridRefCountT> m_grid_ref_list;
91 vector<vector<T> > m_grid_copy_list;
95 template <
class IterT1,
class IterT2,
class IterT3>
96 NDInterpolator(IterT1 grids_begin, IterT2 grids_len_begin, IterT3 f_begin, IterT3 f_end) {
97 init(grids_begin, grids_len_begin, f_begin, f_end);
101 template <
class IterT1,
class IterT2,
class IterT3,
class RefCountIterT>
102 NDInterpolator(IterT1 grids_begin, IterT2 grids_len_begin, IterT3 f_begin, IterT3 f_end, ArrayRefCountT &refF, RefCountIterT grid_refs_begin) {
103 init_refcount(grids_begin, grids_len_begin, f_begin, f_end, refF, grid_refs_begin);
106 template <
class IterT1,
class IterT2,
class IterT3>
107 void init(IterT1 grids_begin, IterT2 grids_len_begin, IterT3 f_begin, IterT3 f_end) {
108 set_grids(grids_begin, grids_len_begin, m_bCopyData);
109 set_f_array(f_begin, f_end, m_bCopyData);
111 template <
class IterT1,
class IterT2,
class IterT3,
class RefCountIterT>
112 void init_refcount(IterT1 grids_begin, IterT2 grids_len_begin, IterT3 f_begin, IterT3 f_end, ArrayRefCountT &refF, RefCountIterT grid_refs_begin) {
113 set_grids(grids_begin, grids_len_begin, m_bCopyData);
114 set_grids_refcount(grid_refs_begin, grid_refs_begin + N);
115 set_f_array(f_begin, f_end, m_bCopyData);
116 set_f_refcount(refF);
119 template <
class IterT1,
class IterT2>
120 void set_grids(IterT1 grids_begin, IterT2 grids_len_begin,
bool bCopy) {
122 m_grid_ref_list.clear();
123 m_grid_copy_list.clear();
124 for (
int i=0; i<N; i++) {
125 int gridLength = grids_len_begin[i];
126 if (bCopy ==
false) {
127 T
const *grid_ptr = &(*grids_begin[i]);
128 m_grid_list.push_back(grid_type(gridLength, (T*) grid_ptr ));
130 m_grid_copy_list.push_back( vector<T>(grids_begin[i], grids_begin[i] + grids_len_begin[i]) );
131 T *begin = &(m_grid_copy_list[i][0]);
132 m_grid_list.push_back(grid_type(gridLength, begin));
136 template <
class IterT1,
class RefCountIterT>
137 void set_grids_refcount(RefCountIterT refs_begin, RefCountIterT refs_end) {
138 assert(refs_end - refs_begin == N);
139 m_grid_ref_list.assign(refs_begin, refs_begin + N);
143 template <
class IterT>
144 void set_f_array(IterT f_begin, IterT f_end,
bool bCopy) {
145 unsigned int nGridPoints = 1;
147 for (
unsigned int i=0; i<m_grid_list.size(); i++) {
148 sizes[i] = m_grid_list[i].size();
149 nGridPoints *= sizes[i];
152 int f_len = f_end - f_begin;
153 if ( (m_bContinuous && f_len != nGridPoints) || (!m_bContinuous && f_len != 2 * nGridPoints) ) {
154 throw std::invalid_argument(
"f has wrong size");
156 for (
unsigned int i=0; i<m_grid_list.size(); i++) {
157 if (!m_bContinuous) { sizes[i] *= 2; }
161 if (bCopy ==
false) {
162 m_pF.reset(
new array_type(f_begin, sizes));
164 m_F_copy = vector<T>(f_begin, f_end);
165 m_pF.reset(
new array_type(&m_F_copy[0], sizes));
168 void set_f_refcount(ArrayRefCountT &refF) {
174 int find_cell(
int dim, T x)
const {
175 grid_type
const &grid(m_grid_list[dim]);
176 if (x < *(grid.begin()))
return -1;
177 else if (x >= *(grid.end()-1))
return grid.size()-1;
179 auto i_upper = std::upper_bound(grid.begin(), grid.end(), x);
180 return i_upper - grid.begin() - 1;
185 T get_f_val(array<int,N>
const &cell_index, array<int,N>
const &v_index)
const {
186 array<int,N> f_index;
189 for (
int i=0; i<N; i++) {
190 if (cell_index[i] < 0) {
192 }
else if (cell_index[i] >= m_grid_list[i].size()-1) {
193 f_index[i] = m_grid_list[i].size()-1;
195 f_index[i] = cell_index[i] + v_index[i];
199 for (
int i=0; i<N; i++) {
200 if (cell_index[i] < 0) {
202 }
else if (cell_index[i] >= m_grid_list[i].size()-1) {
203 f_index[i] = (2*m_grid_list[i].size())-1;
205 f_index[i] = 1 + (2*cell_index[i]) + v_index[i];
209 return (*m_pF)(f_index);
212 T get_f_val(array<int,N>
const &cell_index,
int v)
const {
213 array<int,N> v_index;
214 for (
int dim=0; dim<N; dim++) {
215 v_index[dim] = (v >> (N-dim-1)) & 1;
217 return get_f_val(cell_index, v_index);
221template <
int N,
class T,
bool CopyData = true,
bool Continuous = true,
class ArrayRefCountT = EmptyClass,
class Gr
idRefCountT = EmptyClass>
226 template <
class IterT1,
class IterT2,
class IterT3>
227 InterpSimplex(IterT1 grids_begin, IterT2 grids_len_begin, IterT3 f_begin, IterT3 f_end)
228 :
super(grids_begin, grids_len_begin, f_begin, f_end)
230 template <
class IterT1,
class IterT2,
class IterT3,
class RefCountIterT>
231 InterpSimplex(IterT1 grids_begin, IterT2 grids_len_begin, IterT3 f_begin, IterT3 f_end, ArrayRefCountT &refF, RefCountIterT ref_begins)
232 :
super(grids_begin, grids_len_begin, f_begin, f_end, refF, ref_begins)
235 template <
class IterT>
236 T interp(IterT x_begin)
const {
238 array< array<T,1>, N > coord_iter;
239 for (
int i=0; i<N; i++) {
240 coord_iter[i][0] = x_begin[i];
242 interp_vec(1, coord_iter.begin(), coord_iter.end(), result.begin());
246 template <
class IterT1,
class IterT2>
247 void interp_vec(
int n, IterT1 coord_iter_begin, IterT1 coord_iter_end, IterT2 i_result)
const {
248 assert(N == coord_iter_end - coord_iter_begin);
250 array<int,N> cell_index, v_index;
251 array<std::pair<T, int>,N> xipair;
255 for (
int i=0; i<n; i++) {
256 for (
int dim=0; dim<N; dim++) {
257 typename super::grid_type
const &grid(super::m_grid_list[dim]);
258 c = this->find_cell(dim, coord_iter_begin[dim][i]);
262 }
else if (c == grid.size()-1) {
266 y = (coord_iter_begin[dim][i] - grid[c]) / (grid[c + 1] - grid[c]);
268 else if (y > 1.0) y=1.0;
270 xipair[dim].first = y;
271 xipair[dim].second = dim;
275 std::sort(xipair.begin(), xipair.end(), [](std::pair<T, int>
const &a, std::pair<T, int>
const &b) {
276 return (a.first < b.first);
279 for (
int j=0; j<N; j++) {
282 v0 = this->get_f_val(cell_index, v_index);
284 for (
int j=0; j<N; j++) {
285 v_index[xipair[j].second]--;
286 v1 = this->get_f_val(cell_index, v_index);
287 y += (1.0 - xipair[j].first) * (v1-v0);
295template <
int N,
class T,
bool CopyData = true,
bool Continuous = true,
class ArrayRefCountT = EmptyClass,
class Gr
idRefCountT = EmptyClass>
300 template <
class IterT1,
class IterT2,
class IterT3>
301 InterpMultilinear(IterT1 grids_begin, IterT2 grids_len_begin, IterT3 f_begin, IterT3 f_end)
302 :
super(grids_begin, grids_len_begin, f_begin, f_end)
304 template <
class IterT1,
class IterT2,
class IterT3,
class RefCountIterT>
305 InterpMultilinear(IterT1 grids_begin, IterT2 grids_len_begin, IterT3 f_begin, IterT3 f_end, ArrayRefCountT &refF, RefCountIterT ref_begins)
306 :
super(grids_begin, grids_len_begin, f_begin, f_end, refF, ref_begins)
309 template <
class IterT1,
class IterT2>
310 static T linterp_nd_unitcube(IterT1 f_begin, IterT1 f_end, IterT2 xi_begin, IterT2 xi_end) {
311 int n = xi_end - xi_begin;
312 int f_len = f_end - f_begin;
313 assert(1 << n == f_len);
314 T sub_lower, sub_upper;
316 sub_lower = f_begin[0];
317 sub_upper = f_begin[1];
319 sub_lower = linterp_nd_unitcube(f_begin, f_begin + (f_len/2), xi_begin + 1, xi_end);
320 sub_upper = linterp_nd_unitcube(f_begin + (f_len/2), f_end, xi_begin + 1, xi_end);
322 T result = sub_lower + (*xi_begin)*(sub_upper - sub_lower);
326 template <
class IterT>
327 T interp(IterT x_begin)
const {
329 array< array<T,1>, N > coord_iter;
330 for (
int i=0; i<N; i++) {
331 coord_iter[i][0] = x_begin[i];
333 interp_vec(1, coord_iter.begin(), coord_iter.end(), result.begin());
337 template <
class IterT1,
class IterT2>
338 void interp_vec(
int n, IterT1 coord_iter_begin, IterT1 coord_iter_end, IterT2 i_result)
const {
339 assert(N == coord_iter_end - coord_iter_begin);
346 for (
int i=0; i<n; i++) {
347 for (
int dim=0; dim<N; dim++) {
348 auto const &grid(super::m_grid_list[dim]);
349 xi = coord_iter_begin[dim][i];
350 c = this->find_cell(dim, coord_iter_begin[dim][i]);
353 }
else if (c == grid.size()-1) {
356 y = (coord_iter_begin[dim][i] - grid[c]) / (grid[c + 1] - grid[c]);
358 else if (y > 1.0) y=1.0;
364 for (
int v=0; v < (1 << N); v++) {
365 f[v] = this->get_f_val(index, v);
367 *i_result++ = linterp_nd_unitcube(f.begin(), f.end(), x.begin(), x.end());
385 void linterp_simplex_1(
double **grids_begin,
int *grid_len_begin,
double *pF,
int xi_len,
double **xi_begin,
double *pResult);
386 void linterp_simplex_2(
double **grids_begin,
int *grid_len_begin,
double *pF,
int xi_len,
double **xi_begin,
double *pResult);
387 void linterp_simplex_3(
double **grids_begin,
int *grid_len_begin,
double *pF,
int xi_len,
double **xi_begin,
double *pResult);
390void inline linterp_simplex_1(
double **grids_begin,
int *grid_len_begin,
double *pF,
int xi_len,
double **xi_begin,
double *pResult) {
392 size_t total_size = 1;
393 for (
int i=0; i<N; i++) {
394 total_size *= grid_len_begin[i];
397 interp_obj.interp_vec(xi_len, xi_begin, xi_begin + N, pResult);
400void inline linterp_simplex_2(
double **grids_begin,
int *grid_len_begin,
double *pF,
int xi_len,
double **xi_begin,
double *pResult) {
402 size_t total_size = 1;
403 for (
int i=0; i<N; i++) {
404 total_size *= grid_len_begin[i];
407 interp_obj.interp_vec(xi_len, xi_begin, xi_begin + N, pResult);
410void inline linterp_simplex_3(
double **grids_begin,
int *grid_len_begin,
double *pF,
int xi_len,
double **xi_begin,
double *pResult) {
412 size_t total_size = 1;
413 for (
int i=0; i<N; i++) {
414 total_size *= grid_len_begin[i];
417 interp_obj.interp_vec(xi_len, xi_begin, xi_begin + N, pResult);
Definition: linterp.h:296
Definition: linterp.h:222