TiledArray  0.7.0
block_range.h
Go to the documentation of this file.
1 /*
2  * This file is a part of TiledArray.
3  * Copyright (C) 2015 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  * Justus Calvin
19  * Department of Chemistry, Virginia Tech
20  *
21  * block_range.h
22  * May 29, 2015
23  *
24  */
25 
26 #ifndef TILEDARRAY_BLOCK_RANGE_H__INCLUDED
27 #define TILEDARRAY_BLOCK_RANGE_H__INCLUDED
28 
29 #include <TiledArray/range.h>
30 
31 namespace TiledArray {
32 
34  class BlockRange : public Range {
35  private:
36  using Range::data_;
37  using Range::offset_;
38  using Range::volume_;
39  using Range::rank_;
40 
41  Range::ordinal_type block_offset_ = 0ul;
42 
43 
44  template <typename Index>
45  void init(const Range& range, const Index& lower_bound, const Index& upper_bound) {
46  TA_ASSERT(range.rank());
47  // Check for valid lower and upper bounds
48  TA_ASSERT(std::equal(lower_bound.begin(), lower_bound.end(), range.lobound_data(),
49  [](const size_type l, const size_type r) { return l >= r; }));
50  TA_ASSERT(std::equal(upper_bound.begin(), upper_bound.end(), lower_bound.begin(),
51  [](const size_type l, const size_type r) { return l > r; }));
52  TA_ASSERT(std::equal(upper_bound.begin(), upper_bound.end(), range.upbound_data(),
53  [](const size_type l, const size_type r) { return l <= r; }));
54 
55  // Initialize the block range data members
56  data_ = new size_type[range.rank() << 2];
57  offset_ = range.offset();
58  volume_ = 1ul;
59  rank_ = range.rank();
60  block_offset_ = 0ul;
61 
62  // Construct temp pointers
63  const auto* MADNESS_RESTRICT const range_stride = range.stride_data();
64  const auto* MADNESS_RESTRICT const lower_bound_ptr = detail::data(lower_bound);
65  const auto* MADNESS_RESTRICT const upper_bound_ptr = detail::data(upper_bound);
66  auto* MADNESS_RESTRICT const lower = data_;
67  auto* MADNESS_RESTRICT const upper = lower + rank_;
68  auto* MADNESS_RESTRICT const extent = upper + rank_;
69  auto* MADNESS_RESTRICT const stride = extent + rank_;
70 
71  // Compute range data
72  for(int i = int(rank_) - 1; i >= 0; --i) {
73  // Compute data for element i of lower, upper, and extent
74  const auto lower_bound_i = lower_bound_ptr[i];
75  const auto upper_bound_i = upper_bound_ptr[i];
76  const auto range_stride_i = range_stride[i];
77  const auto extent_i = upper_bound_i - lower_bound_i;
78 
79  // Check input dimensions
80  TA_ASSERT(lower_bound_i >= range.lobound(i));
81  TA_ASSERT(lower_bound_i < upper_bound_i);
82  TA_ASSERT(upper_bound_i <= range.upbound(i));
83 
84  // Set the block range data
85  lower[i] = lower_bound_i;
86  upper[i] = upper_bound_i;
87  extent[i] = extent_i;
88  stride[i] = range_stride_i;
89  block_offset_ += lower_bound_i * range_stride_i;
90  volume_ *= extent_i;
91  }
92  }
93 
94  public:
95 
96  // Compiler generated functions
97  BlockRange() = default;
98  BlockRange(const BlockRange&) = default;
99  BlockRange(BlockRange&&) = default;
100  ~BlockRange() = default;
101  BlockRange& operator=(const BlockRange&) = default;
102  BlockRange& operator=(BlockRange&&) = default;
103 
104  template <typename Index>
105  BlockRange(const Range& range, const Index& lower_bound,
106  const Index& upper_bound) :
107  Range()
108  {
109  init(range, lower_bound, upper_bound);
110  }
111 
112 
113  BlockRange(const Range& range, const std::initializer_list<size_type>& lower_bound,
114  const std::initializer_list<size_type>& upper_bound) :
115  Range()
116  {
117  init(range, lower_bound, upper_bound);
118  }
119 
120 
122 
128  template <typename Index,
129  typename std::enable_if<! std::is_integral<Index>::value>::type* = nullptr>
130  ordinal_type ordinal(const Index& index) const {
131  return Range::ordinal(index);
132  }
133 
134  template <typename... Index,
135  typename std::enable_if<(sizeof...(Index) > 1ul)>::type* = nullptr>
136  ordinal_type ordinal(const Index&... index) const {
137  return Range::ordinal(index...);
138  }
139 
141 
148  // Check that index is contained by range.
150 
151  // Construct result coordinate index object and allocate its memory.
152  ordinal_type result = 0ul;
153 
154  // Get pointers to the data
155  const auto * MADNESS_RESTRICT const size = data_ + rank_ + rank_;
156  const auto * MADNESS_RESTRICT const stride = size + rank_;
157 
158  // Compute the coordinate index of o in range.
159  for(int i = int(rank_) - 1; i >= 0; --i) {
160  const auto size_i = size[i];
161  const auto stride_i = stride[i];
162 
163  // Compute result index element i
164  result += (index % size_i) * stride_i;
165  index /= size_i;
166  }
167 
168  return result + block_offset_ - offset_;
169  }
170 
172  template <typename Index>
173  BlockRange& resize(const Index&, const Index&) {
174  // This function is here to shadow the base class resize function
175  TA_EXCEPTION("BlockRange::resize() is not supported");
176  return *this;
177  }
178 
179 
181 
184  template <typename Index>
185  Range_& inplace_shift(const Index&) {
186  TA_EXCEPTION("BlockRange::inplace_shift() is not supported");
187  return *this;
188  }
189 
191 
194  template <typename Index>
195  Range_ shift(const Index&) {
196  TA_EXCEPTION("BlockRange::shift() is not supported");
197  return *this;
198  }
199 
200  void swap(BlockRange& other) {
201  Range::swap(other);
202  std::swap(block_offset_, other.block_offset_);
203  }
204 
206  template <typename Archive>
207  void serialize(const Archive& ar) const {
208  Range::serialize(ar);
209  ar & block_offset_;
210  }
211  }; // BlockRange
212 
213 
214 } // namespace TiledArray
215 
216 #endif // TILEDARRAY_BLOCK_RANGE_H__INCLUDED
std::vector< size_type > index
Coordinate index type.
Definition: range.h:43
size_type volume_
Total number of elements.
Definition: range.h:63
A (hyperrectangular) interval on , space of integer n-indices.
Definition: range.h:39
size_array lobound() const
Range lower bound accessor.
Definition: range.h:555
auto data(T &t)
Container data pointer accessor.
Definition: utility.h:89
ordinal_type ordinal(const Index &index) const
calculate the ordinal index of i
Definition: block_range.h:130
Range_ shift(const Index &)
Shift the lower and upper bound of this range.
Definition: block_range.h:195
void swap(Bitset< B > &b0, Bitset< B > &b1)
Definition: bitset.h:593
std::size_t ordinal_type
Ordinal type, to conform Tensor Working Group spec.
Definition: range.h:47
void swap(Range_ &other)
Definition: range.h:943
BlockRange & resize(const Index &, const Index &)
Resize of block range is not supported.
Definition: block_range.h:173
BlockRange & operator=(const BlockRange &)=default
void swap(BlockRange &other)
Definition: block_range.h:200
unsigned int rank() const
Rank accessor.
Definition: range.h:542
const size_type * stride_data() const
Range stride data accessor.
Definition: range.h:618
size_t size(const DistArray< Tile, Policy > &a)
Definition: utils.h:49
const size_type * upbound_data() const
Range upper bound data accessor.
Definition: range.h:570
ordinal_type ordinal(const Index &... index) const
Definition: block_range.h:136
#define TA_ASSERT(a)
Definition: error.h:107
size_type offset_
Ordinal index offset correction.
Definition: range.h:62
unsigned int rank_
The rank (or number of dimensions) in the range.
Definition: range.h:64
void serialize(const Archive &ar) const
Serialization Block range.
Definition: block_range.h:207
ordinal_type ordinal(ordinal_type index) const
calculate the coordinate index of the ordinal index, index.
Definition: block_range.h:147
Range_ & inplace_shift(const Index &)
Shift the lower and upper bound of this range.
Definition: block_range.h:185
size_array upbound() const
Range upper bound accessor.
Definition: range.h:577
bool includes(const Index &index) const
Check the coordinate to make sure it is within the range.
Definition: range.h:682
std::size_t size_type
Size type.
Definition: range.h:42
const size_type * lobound_data() const
Range lower bound data accessor.
Definition: range.h:548
Range that references a subblock of another range.
Definition: block_range.h:34
#define TA_EXCEPTION(m)
Definition: error.h:72
size_type * data_
Definition: range.h:53
BlockRange(const Range &range, const std::initializer_list< size_type > &lower_bound, const std::initializer_list< size_type > &upper_bound)
Definition: block_range.h:113
ordinal_type ordinal(const ordinal_type index) const
calculate the ordinal index of i
Definition: range.h:826
void serialize(const Archive &ar)
Definition: range.h:920
extent_type extent() const
Range extent accessor.
Definition: range.h:601
ordinal_type offset() const
Range offset.
Definition: range.h:654
BlockRange(const Range &range, const Index &lower_bound, const Index &upper_bound)
Definition: block_range.h:105
size_array stride() const
Range stride accessor.
Definition: range.h:625