1 #ifndef VTESTBED_CORE_GRID_HH 2 #define VTESTBED_CORE_GRID_HH 8 #include <vtestbed/base/blitz.hh> 9 #include <vtestbed/base/bstream.hh> 10 #include <vtestbed/base/for_loop.hh> 24 template <
class T,
int N>
28 typedef blitz::TinyVector<T,N> vec;
29 typedef blitz::TinyVector<int,N> int_n;
34 int_n _begin_index{blitz::const_vector<int,N>(0)};
35 int_n _end_index{blitz::const_vector<int,N>(0)};
42 Grid& operator=(
const Grid&) =
default;
49 this->_lbound = rhs.
lbound();
50 this->_ubound = rhs.
ubound();
51 this->_begin_index = rhs.
begin();
52 this->_end_index = rhs.
end();
59 const int_n& begin_index,
60 const int_n& end_index
64 _begin_index(begin_index),
65 _end_index(end_index) {
66 #if defined(VTB_DEBUG) 67 for (
int i=0; i<N; ++i) {
70 "vtb::core::Grid: bad begin/end index" 84 blitz::const_vector<T,N>(T{0}),
86 blitz::const_vector<int,N>(0),
94 template <
class ... Tail>
97 const Grid<T,1>* grids[N] = {&head, &(tail)...};
98 for (
int i=0; i<N; ++i) {
99 this->_lbound(i) = grids[i]->
lbound(0);
100 this->_ubound(i) = grids[i]->
ubound(0);
101 this->_begin_index(i) = grids[i]->
begin(0);
102 this->_end_index(i) = grids[i]->
end(0);
115 return this->
end(i) - this->
begin(i);
121 return this->_begin_index;
127 return this->_begin_index;
133 return this->_begin_index(i);
139 return this->_begin_index(i);
145 return this->_end_index;
151 return this->_end_index;
157 return this->_end_index(i);
162 end(
int i)
const noexcept {
163 return this->_end_index(i);
169 return this->_lbound;
175 return this->_lbound;
179 lbound(
int i)
const noexcept {
180 return this->_lbound(i);
185 return this->_lbound(i);
191 return this->_ubound;
197 return this->_ubound;
201 ubound(
int i)
const noexcept {
202 return this->_ubound(i);
207 return this->_ubound(i);
213 return std::max(this->
extent(i)-1, 1);
219 return blitz::max(this->
shape()-1, 1);
241 return npatches == 0 ? T(0) : (this->
length(i) / npatches);
249 return where(npatches == 0, T(0), this->
size() / npatches);
265 operator()(
const int i,
const int dim)
const noexcept {
266 return this->
lbound(dim) +
271 index(
const vec& x)
const noexcept {
274 return this->
begin() + where(
282 index(T x,
const int dim)
const noexcept {
284 return this->
begin(dim) +
285 (npatches == 0 ? T(0)
290 operator()(
const blitz::RectDomain<N>& domain)
const {
292 for (
int i=0; i<N; ++i) {
293 auto start = domain.lbound(i);
294 auto end = domain.ubound(i);
295 result._begin_index[i] = start;
296 result._end_index[i] =
end+1;
297 result._lbound[i] = (*this)(start, i);
298 result._ubound[i] = (*this)(
end, i);
303 template <
class ... Tail>
305 operator()(
const blitz::Range& head,
const Tail& ... tail)
const {
306 const blitz::Range* ranges[N] = {&head, &(tail)...};
308 for (
int i=0; i<N; ++i) {
309 const auto& r = *ranges[i];
310 auto start = r.first(this->_begin_index[i]);
311 auto end = r.last(this->_end_index[i]-1);
312 result._begin_index[i] = start;
313 result._end_index[i] =
end+1;
314 result._lbound[i] = (*this)(start, i);
315 result._ubound[i] = (*this)(
end, i);
320 template <
class ... Tail>
322 select(
int head, Tail ... tail)
const -> Grid<T,
sizeof...(tail)+1> {
323 const int dimensions[] = {head, tail...};
324 Grid<T,
sizeof...(tail)+1> result;
325 for (
size_t i=0; i<
sizeof...(tail)+1; ++i) {
326 const auto dim = dimensions[i];
328 result.begin(i) = this->_begin_index[dim],
329 result.end(i) = this->_end_index[dim],
330 result.lbound(i) = this->_lbound[dim],
331 result.ubound(i) = this->_ubound[dim];
340 this->_lbound = T(0);
341 this->_ubound = T(0);
342 this->_begin_index = 0;
343 this->_end_index = 1;
347 within_bounds(T x,
int dim)
const noexcept {
348 return !(x < this->_lbound(dim) || x > this->_ubound(dim));
352 contains(
const vec& x)
const noexcept {
353 return !blitz::any(x < this->
lbound() || x > this->
ubound());
356 template <
class ... Args>
358 contains(
const vec& x ,
const Args& ... tail)
const noexcept {
359 return this->contains(x) && contains(tail...);
363 near(
const Grid& rhs, T eps) {
367 all(rhs.begin() == this->
begin()) &&
368 all(rhs.end() == this->
end()) &&
369 near(rhs.lbound(), this->
lbound(), eps) &&
370 near(rhs.ubound(), this->
ubound(), eps);
379 inline friend bstream&
380 operator<<(bstream& out,
const Grid& rhs) {
383 out << rhs._begin_index;
384 out << rhs._end_index;
388 inline friend bstream&
389 operator>>(bstream& in, Grid& rhs) {
392 in >> rhs._begin_index;
393 in >> rhs._end_index;
400 <<
"from" <<
' ' << rhs._lbound <<
' ' 401 <<
"to" <<
' ' << rhs._ubound <<
' ' 402 <<
"start" <<
' ' << rhs._begin_index <<
' ' 403 <<
"end" <<
' ' << rhs._end_index;
412 template <
class T,
int N>
413 inline blitz::TinyVector<T,N>
414 clamp(
const blitz::TinyVector<T,N> x,
const Grid<T,N>& grid) {
417 return max(grid.lbound(),
min(grid.ubound(), x));
420 template <
class T,
int N,
class Function>
423 const Grid<T,N>& grid,
424 blitz::Array<T,N>& result,
427 #if defined(VTB_DEBUG) 428 if (!all(result.shape() <= grid.end())) {
430 "vtb::core::generate: bad result shape" 434 const auto delta{grid.delta()};
435 parallel_for_loop<N>(
438 [&](
const blitz::TinyVector<int,N>& idx) {
439 result(idx) = func(grid(idx, delta));
444 template <
class T,
int N,
class Function>
445 inline blitz::Array<T,N>
447 const Grid<T,N>& grid,
450 blitz::Array<T,N> result(grid.shape());
451 generate<T,N,Function>(grid, result, func);
459 #endif // vim:filetype=cpp const T length(int i) const noexcept
The size of the region for dimension i.
int extent(int i) const noexcept
The number of points for dimension i.
int num_patches(int i) const
The number of patches (intervals) for dimension i.
const int_n & end() const noexcept
End indices (exclusive).
size_t num_elements() const
Total number of grid points.
const vec & lbound() const noexcept
Lower bound of the region.
const int_n shape() const noexcept
The number of points for all dimensions.
const vec size() const noexcept
The size of the region.
const T delta(int i) const
The size of the patch (interval) for dimension i.
A region defined by start and end index and lower and upper bound for each dimension.
int & end(int i) noexcept
End index for dimension i (exclusive).
int end(int i) const noexcept
End index for dimension i (exclusive).
const int_n & begin() const noexcept
Start indices (inclusive).
const vec operator()(const int_n &i) const noexcept
Point inside the region specified by index i.
int & begin(int i) noexcept
Start index for dimension i (inclusive).
vec delta() const
The size of the patch (interval) for all dimensions.
int_n & end() noexcept
End indices (exclusive).
vec & lbound() noexcept
Lower bound of the region.
const vec & ubound() const noexcept
Upper bound of the region.
const int_n num_patches() const
The number of patches (intervals) for all dimensions.
int begin(int i) const noexcept
Start index for dimension i (inclusive).
int_n & begin() noexcept
Start indices (inclusive).
vec & ubound() noexcept
Upper bound of the region.
const vec operator()(const int_n &i, const vec &delta) const noexcept
Point inside the region specified by index i and delta.