tiled_range1.h
Go to the documentation of this file.
1 /*
2  * This file is a part of TiledArray.
3  * Copyright (C) 2013 Virginia Tech
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  *
18  */
19 
20 #ifndef TILEDARRAY_TILED_RANGE1_H__INCLUDED
21 #define TILEDARRAY_TILED_RANGE1_H__INCLUDED
22 
23 #include <TiledArray/error.h>
24 #include <TiledArray/type_traits.h>
25 #include <TiledArray/utility.h>
26 #include <cassert>
27 #include <initializer_list>
28 #include <mutex>
29 #include <vector>
30 
31 // Forward declaration of MADNESS archive type traits
32 namespace madness {
33 namespace archive {
34 
35 template <typename>
36 struct is_output_archive;
37 template <typename>
38 struct is_input_archive;
39 
40 } // namespace archive
41 } // namespace madness
42 
43 namespace TiledArray {
44 
50 class TiledRange1 {
51  private:
52  struct Enabler {};
53 
54  public:
55  typedef TA_1INDEX_TYPE index1_type;
56  typedef std::pair<index1_type, index1_type> range_type;
57  typedef std::vector<range_type>::const_iterator const_iterator;
58 
67  : range_(0, 0), elements_range_(0, 0), tiles_ranges_(), elem2tile_() {}
68 
73  template <typename RandIter,
74  typename std::enable_if<
76  explicit TiledRange1(RandIter first, RandIter last)
77  : range_(), elements_range_(), tiles_ranges_(), elem2tile_() {
78  init_tiles_(first, last, 0);
79  }
80 
82  TiledRange1(const TiledRange1& rng) = default;
83 
85  TiledRange1(TiledRange1&& rng) = default;
86 
88 
97  template <typename... _sizes>
98  explicit TiledRange1(const index1_type& t0, const _sizes&... t_rest) {
99  const auto n = sizeof...(_sizes) + 1;
100  index1_type tile_boundaries[n] = {t0, static_cast<index1_type>(t_rest)...};
101  init_tiles_(tile_boundaries, tile_boundaries + n, 0);
102  }
103 
105 
115  template <typename Integer,
116  typename = std::enable_if_t<std::is_integral_v<Integer>>>
117  explicit TiledRange1(const std::initializer_list<Integer>& list) {
118  init_tiles_(list.begin(), list.end(), 0);
119  }
120 
122  TiledRange1& operator=(const TiledRange1& rng) = default;
123 
125  TiledRange1& operator=(TiledRange1&& rng) = default;
126 
128  const_iterator begin() const { return tiles_ranges_.begin(); }
129 
131  const_iterator end() const { return tiles_ranges_.end(); }
132 
134  bool empty() const { return tiles_ranges_.empty(); }
135 
137  const_iterator find(const index1_type& e) const {
138  if (!includes(elements_range_, e)) return tiles_ranges_.end();
139  const_iterator result = tiles_ranges_.begin();
140  result += element_to_tile(e);
141  return result;
142  }
143 
145  [[deprecated]] const range_type& tiles() const { return range_; }
146 
148 
150  const range_type& tiles_range() const { return range_; }
151 
153  const range_type& elements() const { return elements_range_; }
154 
156 
158  const range_type& elements_range() const { return elements_range_; }
159 
161  index1_type tile_extent() const { return range_.second - range_.first; }
162 
164  index1_type extent() const {
165  return elements_range_.second - elements_range_.first;
166  }
167 
169 
176  const range_type& tile(const index1_type i) const {
177  TA_ASSERT(includes(range_, i));
178  return tiles_ranges_[i - range_.first];
179  }
180 
182 
194  const index1_type& element_to_tile(const index1_type& i) const {
195  TA_ASSERT(includes(elements_range_, i));
196  if (elem2tile_.empty()) {
197  init_elem2tile_();
198  }
199  return elem2tile_[i - elements_range_.first];
200  }
201 
203  [[deprecated]] const index1_type& element2tile(const index1_type& i) const {
204  return element_to_tile(i);
205  }
206 
208 
211  void swap(TiledRange1& other) { // no throw
212  std::swap(range_, other.range_);
213  std::swap(elements_range_, other.elements_range_);
214  std::swap(tiles_ranges_, other.tiles_ranges_);
215  std::swap(elem2tile_, other.elem2tile_);
216  }
217 
218  template <typename Archive,
219  typename std::enable_if<madness::archive::is_input_archive<
220  Archive>::value>::type* = nullptr>
221  void serialize(const Archive& ar) {
222  ar& range_& elements_range_& tiles_ranges_& elem2tile_;
223  }
224 
225  template <typename Archive,
226  typename std::enable_if<madness::archive::is_output_archive<
227  Archive>::value>::type* = nullptr>
228  void serialize(const Archive& ar) const {
229  ar& range_& elements_range_& tiles_ranges_& elem2tile_;
230  }
231 
232  private:
233  static bool includes(const range_type& r, index1_type i) {
234  return (i >= r.first) && (i < r.second);
235  }
236 
238  template <typename RandIter>
239  static void valid_(RandIter first, RandIter last) {
240  // Verify at least 2 elements are present if the vector is not empty.
241  TA_ASSERT((std::distance(first, last) >= 2) &&
242  "TiledRange1 construction failed: You need at least 2 "
243  "elements in the tile boundary list.");
244  // Verify the requirement that a0 < a1 < a2 < ...
245  for (; first != (last - 1); ++first) {
246  TA_ASSERT(
247  *first < *(first + 1) &&
248  "TiledRange1 construction failed: Invalid tile boundary, tile "
249  "boundary i must be greater than tile boundary i+1 for all i. ");
250  TA_ASSERT(
251  static_cast<index1_type>(*first) <
252  static_cast<index1_type>(*(first + 1)) &&
253  "TiledRange1 construction failed: Invalid tile boundary, tile "
254  "boundary i must be greater than tile boundary i+1 for all i. ");
255  }
256  }
257 
259  template <typename RandIter>
260  void init_tiles_(RandIter first, RandIter last,
261  index1_type start_tile_index) {
262 #ifndef NDEBUG
263  valid_(first, last);
264 #endif // NDEBUG
265  range_.first = start_tile_index;
266  range_.second = start_tile_index + last - first - 1;
267  elements_range_.first = *first;
268  elements_range_.second = *(last - 1);
269  for (; first != (last - 1); ++first)
270  tiles_ranges_.emplace_back(*first, *(first + 1));
271  }
272 
274  void init_elem2tile_() const {
275  // check for 0 size range.
276  if ((elements_range_.second - elements_range_.first) == 0) return;
277 
278  static std::mutex mtx;
279  {
280  std::lock_guard<std::mutex> lock(mtx);
281  if (elem2tile_.empty()) {
282  // initialize elem2tile map
283  elem2tile_.resize(elements_range_.second - elements_range_.first);
284  const auto end = range_.second - range_.first;
285  for (index1_type t = 0; t < end; ++t)
286  for (index1_type e = tiles_ranges_[t].first;
287  e < tiles_ranges_[t].second; ++e)
288  elem2tile_[e - elements_range_.first] = t + range_.first;
289  }
290  }
291  }
292 
293  friend std::ostream& operator<<(std::ostream&, const TiledRange1&);
294 
295  // TiledRange1 data
296  range_type range_;
297  range_type elements_range_;
298  std::vector<range_type>
299  tiles_ranges_;
300  mutable std::vector<index1_type>
301  elem2tile_;
302 
303 }; // class TiledRange1
304 
306 inline void swap(TiledRange1& r0, TiledRange1& r1) { // no throw
307  r0.swap(r1);
308 }
309 
311 inline bool operator==(const TiledRange1& r1, const TiledRange1& r2) {
312  return std::equal(r1.begin(), r1.end(), r2.begin()) &&
313  (r1.tiles_range() == r2.tiles_range()) &&
314  (r1.elements_range() == r2.elements_range());
315 }
316 
318 inline bool operator!=(const TiledRange1& r1, const TiledRange1& r2) {
319  return !operator==(r1, r2);
320 }
321 
323 inline std::ostream& operator<<(std::ostream& out, const TiledRange1& rng) {
324  out << "( tiles = [ " << rng.tiles_range().first << ", "
325  << rng.tiles_range().second << " ), elements = [ "
326  << rng.elements_range().first << ", " << rng.elements_range().second
327  << " ) )";
328  return out;
329 }
330 
332 
339 inline TiledRange1 concat(const TiledRange1& r1, const TiledRange1& r2) {
340  std::vector<TiledRange1::index1_type> hashmarks;
341  hashmarks.reserve(r1.tile_extent() + r2.tile_extent() + 1);
342  if (!r1.empty()) {
343  hashmarks.push_back(r1.tile(0).first);
344  for (const auto& tile : r1) {
345  hashmarks.push_back(tile.second);
346  }
347  for (const auto& tile : r2) {
348  hashmarks.push_back(hashmarks.back() + tile.second - tile.first);
349  }
350  return TiledRange1(hashmarks.begin(), hashmarks.end());
351  } else {
352  return r2;
353  }
354 }
355 
357 
362 inline bool is_congruent(const TiledRange1& r1, const TiledRange1& r2) {
363  return std::equal(r1.begin(), r1.end(), r2.begin(),
364  [](const auto& tile1, const auto& tile2) {
365  return (tile1.second - tile1.first) ==
366  (tile2.second - tile2.first);
367  });
368 }
369 
370 } // namespace TiledArray
371 
372 #endif // TILEDARRAY_TILED_RANGE1_H__INCLUDED
bool operator==(const BlockRange &r1, const BlockRange &r2)
BlockRange equality comparison.
Definition: block_range.h:433
index1_type extent() const
Elements range extent accessor.
Definition: tiled_range1.h:164
TiledRange1 & operator=(TiledRange1 &&rng)=default
Move assignment operator.
const_iterator end() const
Returns an iterator to the end of the range.
Definition: tiled_range1.h:131
bool empty() const
Returns true if this range is empty (i.e. has no tiles)
Definition: tiled_range1.h:134
const_iterator find(const index1_type &e) const
Return tile iterator associated with ordinal_index.
Definition: tiled_range1.h:137
constexpr bool operator!=(const DenseShape &a, const DenseShape &b)
Definition: dense_shape.h:382
TiledRange1 & operator=(const TiledRange1 &rng)=default
Copy assignment operator.
void swap(TiledRange1 &r0, TiledRange1 &r1)
Exchange the data of the two given ranges.
Definition: tiled_range1.h:306
const index1_type & element_to_tile(const index1_type &i) const
Maps element index to tile index.
Definition: tiled_range1.h:194
TiledRange1(const std::initializer_list< Integer > &list)
Construct a 1D tiled range.
Definition: tiled_range1.h:117
TiledRange1(TiledRange1 &&rng)=default
Move constructor.
const range_type & tiles() const
Definition: tiled_range1.h:145
const range_type & elements() const
Definition: tiled_range1.h:153
index1_type tile_extent() const
Tile range extent accessor.
Definition: tiled_range1.h:161
const range_type & elements_range() const
Elements range accessor.
Definition: tiled_range1.h:158
#define TA_ASSERT(EXPR,...)
Definition: error.h:39
std::pair< index1_type, index1_type > range_type
Definition: tiled_range1.h:56
TiledRange1(RandIter first, RandIter last)
Definition: tiled_range1.h:76
void serialize(const Archive &ar) const
Definition: tiled_range1.h:228
std::vector< range_type >::const_iterator const_iterator
Definition: tiled_range1.h:57
friend std::ostream & operator<<(std::ostream &, const TiledRange1 &)
TiledRange1 ostream operator.
Definition: tiled_range1.h:323
bool is_congruent(const BlockRange &r1, const BlockRange &r2)
Test that two BlockRange objects are congruent.
Definition: block_range.h:400
std::ostream & operator<<(std::ostream &os, const DistArray< Tile, Policy > &a)
Add the tensor to an output stream.
Definition: dist_array.h:1602
const range_type & tiles_range() const
Tile range accessor.
Definition: tiled_range1.h:150
void swap(TiledRange1 &other)
swapper
Definition: tiled_range1.h:211
const range_type & tile(const index1_type i) const
Tile range accessor.
Definition: tiled_range1.h:176
const_iterator begin() const
Returns an iterator to the first tile in the range.
Definition: tiled_range1.h:128
void serialize(const Archive &ar)
Definition: tiled_range1.h:221
const index1_type & element2tile(const index1_type &i) const
Definition: tiled_range1.h:203
TiledRange1(const TiledRange1 &rng)=default
Copy constructor.
TiledRange1 concat(const TiledRange1 &r1, const TiledRange1 &r2)
Concatenates two ranges.
Definition: tiled_range1.h:339
void swap(Range &r0, Range &r1)
Exchange the values of the give two ranges.
Definition: range.h:1233
TiledRange1(const index1_type &t0, const _sizes &... t_rest)
Construct a 1D tiled range.
Definition: tiled_range1.h:98
TA_1INDEX_TYPE index1_type
Definition: tiled_range1.h:55