DIY  3.0
data-parallel out-of-core C++ library
 All Classes Namespaces Functions Typedefs Groups Pages
grid.hpp
1 #ifndef DIY_GRID_HPP
2 #define DIY_GRID_HPP
3 
4 #include "point.hpp"
5 
6 namespace diy
7 {
8 
9 template<class C, unsigned D>
10 struct Grid;
11 
12 template<class C, unsigned D>
13 struct GridRef
14 {
15  public:
16  typedef C Value;
17 
18  typedef Point<int, D> Vertex;
19  typedef size_t Index;
20 
21  public:
22  template<class Int>
23  GridRef(C* data, const Point<Int,D>& shape, bool c_order = true):
24  data_(data), shape_(shape), c_order_(c_order) { set_stride(); }
25 
26  GridRef(Grid<C,D>& g):
27  data_(g.data()), shape_(g.shape()),
28  c_order_(g.c_order()) { set_stride(); }
29 
30  template<class Int>
31  C operator()(const Point<Int, D>& v) const { return (*this)(index(v)); }
32 
33  template<class Int>
34  C& operator()(const Point<Int, D>& v) { return (*this)(index(v)); }
35 
36  C operator()(Index i) const { return data_[i]; }
37  C& operator()(Index i) { return data_[i]; }
38 
39  const Vertex&
40  shape() const { return shape_; }
41 
42  const C*
43  data() const { return data_; }
44  C* data() { return data_; }
45 
46  // Set every element to the given value
47  GridRef& operator=(C value) { Index s = size(); for (Index i = 0; i < s; ++i) data_[i] = value; return *this; }
48  GridRef& operator/=(C value) { Index s = size(); for (Index i = 0; i < s; ++i) data_[i] /= value; return *this; }
49 
50  Vertex vertex(Index idx) const { Vertex v; for (unsigned i = 0; i < D; ++i) { v[i] = idx / stride_[i]; idx %= stride_[i]; } return v; }
51  Index index(const Vertex& v) const { Index idx = 0; for (unsigned i = 0; i < D; ++i) { idx += ((Index) v[i]) * ((Index) stride_[i]); } return idx; }
52 
53  Index size() const { return size(shape()); }
54  void swap(GridRef& other) { std::swap(data_, other.data_); std::swap(shape_, other.shape_); std::swap(stride_, other.stride_); std::swap(c_order_, other.c_order_); }
55 
56  bool c_order() const { return c_order_; }
57 
58  static constexpr
59  unsigned dimension() { return D; }
60 
61  protected:
62  static Index
63  size(const Vertex& v) { Index res = 1; for (unsigned i = 0; i < D; ++i) res *= v[i]; return res; }
64 
65  void set_stride()
66  {
67  Index cur = 1;
68  if (c_order_)
69  for (unsigned i = D; i > 0; --i) { stride_[i-1] = cur; cur *= shape_[i-1]; }
70  else
71  for (unsigned i = 0; i < D; ++i) { stride_[i] = cur; cur *= shape_[i]; }
72 
73  }
74  void set_shape(const Vertex& v) { shape_ = v; set_stride(); }
75  void set_data(C* data) { data_ = data; }
76  void set_c_order(bool order) { c_order_ = order; }
77 
78  private:
79  C* data_;
80  Vertex shape_;
81  Vertex stride_;
82  bool c_order_;
83 };
84 
85 
86 template<class C, unsigned D>
87 struct Grid: public GridRef<C,D>
88 {
89  public:
90  typedef GridRef<C,D> Parent;
91  typedef typename Parent::Value Value;
92  typedef typename Parent::Index Index;
93  typedef typename Parent::Vertex Vertex;
94  typedef Parent Reference;
95 
96  template<class U>
97  struct rebind { typedef Grid<U,D> type; };
98 
99  public:
100  Grid():
101  Parent(new C[0], Vertex::zero()) {}
102  template<class Int>
103  Grid(const Point<Int, D>& shape, bool c_order = true):
104  Parent(new C[size(shape)], shape, c_order)
105  {}
106 
107  Grid(Grid&& g): Grid() { Parent::swap(g); }
108 
109  Grid(const Parent& g):
110  Parent(new C[size(g.shape())], g.shape(),
111  g.c_order()) { copy_data(g.data()); }
112 
113  template<class OtherGrid>
114  Grid(const OtherGrid& g):
115  Parent(new C[size(g.shape())],
116  g.shape(),
117  g.c_order()) { copy_data(g.data()); }
118 
119  ~Grid() { delete[] Parent::data(); }
120 
121  template<class OC>
122  Grid& operator=(const GridRef<OC, D>& other)
123  {
124  delete[] Parent::data();
125  Parent::set_c_order(other.c_order()); // NB: order needs to be set before the shape, to set the stride correctly
126  Parent::set_shape(other.shape());
127  Index s = size(shape());
128  Parent::set_data(new C[s]);
129  copy_data(other.data());
130  return *this;
131  }
132 
133  Grid& operator=(Grid&& g) { Parent::swap(g); return *this; }
134 
135  using Parent::data;
136  using Parent::shape;
137  using Parent::operator();
138  using Parent::operator=;
139  using Parent::size;
140 
141  private:
142  template<class OC>
143  void copy_data(const OC* data)
144  {
145  Index s = size(shape());
146  for (Index i = 0; i < s; ++i)
147  Parent::data()[i] = data[i];
148  }
149 };
150 
151 }
152 
153 #endif
Definition: grid.hpp:13
Definition: grid.hpp:10
Definition: grid.hpp:97