utility.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  * untility.h
22  * Jun 1, 2015
23  *
24  */
25 
26 #ifndef TILEDARRAY_TENSOR_UTILITY_H__INCLUDED
27 #define TILEDARRAY_TENSOR_UTILITY_H__INCLUDED
28 
29 #include <TiledArray/block_range.h>
30 #include <TiledArray/range.h>
31 #include <TiledArray/size_array.h>
34 #include <TiledArray/utility.h>
35 
36 namespace TiledArray {
37 namespace detail {
38 
40 
45 template <typename T, typename std::enable_if<
46  is_contiguous_tensor<T>::value>::type* = nullptr>
47 inline auto clone_range(const T& tensor) {
48  return tensor.range();
49 }
50 
52 
57 template <typename T, typename std::enable_if<
58  !is_contiguous_tensor<T>::value>::type* = nullptr>
59 inline Range clone_range(const T& tensor) {
60  return Range(tensor.range().lobound(), tensor.range().upbound());
61 }
62 
64 
73 template <typename T1, typename T2,
74  typename std::enable_if<!(is_shifted<T1>::value ||
75  is_shifted<T2>::value)>::type* = nullptr>
76 inline bool is_range_congruent(const T1& tensor1, const T2& tensor2) {
77  return is_congruent(tensor1.range(), tensor2.range());
78 }
79 
81 
91 template <typename T1, typename T2,
92  typename std::enable_if<!(is_shifted<T1>::value ||
93  is_shifted<T2>::value)>::type* = nullptr>
94 inline bool is_range_congruent(const T1& tensor1, const T2& tensor2,
95  const Permutation& perm) {
96  return is_congruent(tensor1.range(), perm * tensor2.range());
97 }
98 
100 
109 template <typename T1, typename T2,
110  typename std::enable_if<is_shifted<T1>::value ||
111  is_shifted<T2>::value>::type* = nullptr>
112 inline bool is_range_congruent(const T1& tensor1, const T2& tensor2) {
113  const auto rank1 = tensor1.range().rank();
114  const auto rank2 = tensor2.range().rank();
115  const auto* const extent1 = tensor1.range().extent_data();
116  const auto* const extent2 = tensor2.range().extent_data();
117  return (rank1 == rank2) && std::equal(extent1, extent1 + rank1, extent2);
118 }
119 
121 
129 template <typename T>
130 inline constexpr bool is_range_set_congruent(const Permutation& perm,
131  const T& tensor) {
132  return true;
133 }
134 
136 
146 template <typename T1, typename T2, typename... Ts>
147 inline bool is_range_set_congruent(const Permutation& perm, const T1& tensor1,
148  const T2& tensor2, const Ts&... tensors) {
149  return is_range_congruent(tensor1, tensor2, perm) &&
150  is_range_set_congruent(perm, tensor1, tensors...);
151 }
152 
154 
161 template <typename T>
162 inline constexpr bool is_range_set_congruent(const T& tensor) {
163  return true;
164 }
165 
167 
176 template <typename T1, typename T2, typename... Ts>
177 inline bool is_range_set_congruent(const T1& tensor1, const T2& tensor2,
178  const Ts&... tensors) {
179  return is_range_congruent(tensor1, tensor2) &&
180  is_range_set_congruent(tensor1, tensors...);
181 }
182 
184 
191 template <typename T>
192 inline typename T::size_type inner_size_helper(const T& tensor) {
193  const auto* MADNESS_RESTRICT const stride = tensor.range().stride_data();
194  const auto* MADNESS_RESTRICT const size = tensor.range().extent_data();
195 
196  int i = int(tensor.range().rank()) - 1;
197  auto volume = size[i];
198 
199  for (--i; i >= 0; --i) {
200  const auto stride_i = stride[i];
201  const auto size_i = size[i];
202 
203  if (volume != stride_i) break;
204  volume *= size_i;
205  }
206 
207  return volume;
208 }
209 
211 
220 template <typename T1, typename T2>
221 inline typename T1::size_type inner_size_helper(const T1& tensor1,
222  const T2& tensor2) {
223  TA_ASSERT(is_range_congruent(tensor1, tensor2));
224  const auto* MADNESS_RESTRICT const size1 = tensor1.range().extent_data();
225  const auto* MADNESS_RESTRICT const stride1 = tensor1.range().stride_data();
226  const auto* MADNESS_RESTRICT const size2 = tensor2.range().extent_data();
227  const auto* MADNESS_RESTRICT const stride2 = tensor2.range().stride_data();
228 
229  int i = int(tensor1.range().rank()) - 1;
230  auto volume1 = size1[i];
231  auto volume2 = size2[i];
232 
233  for (--i; i >= 0; --i) {
234  const auto stride1_i = stride1[i];
235  const auto stride2_i = stride2[i];
236  const auto size1_i = size1[i];
237  const auto size2_i = size2[i];
238 
239  if ((volume1 != stride1_i) || (volume2 != stride2_i)) break;
240  volume1 *= size1_i;
241  volume2 *= size2_i;
242  }
243 
244  return volume1;
245 }
246 
248 
256 template <
257  typename T1, typename T2,
258  typename std::enable_if<!is_contiguous_tensor<T1>::value &&
259  is_contiguous_tensor<T2>::value>::type* = nullptr>
260 inline typename T1::size_type inner_size(const T1& tensor1, const T2&) {
261  return inner_size_helper(tensor1);
262 }
263 
265 
273 template <
274  typename T1, typename T2,
275  typename std::enable_if<is_contiguous_tensor<T1>::value &&
276  !is_contiguous_tensor<T2>::value>::type* = nullptr>
277 inline typename T1::size_type inner_size(const T1&, const T2& tensor2) {
278  return inner_size_helper(tensor2);
279 }
280 
282 
292 template <
293  typename T1, typename T2,
294  typename std::enable_if<!is_contiguous_tensor<T1>::value &&
295  !is_contiguous_tensor<T2>::value>::type* = nullptr>
296 inline typename T1::size_type inner_size(const T1& tensor1, const T2& tensor2) {
297  return inner_size_helper(tensor1, tensor2);
298 }
299 
301 
308 template <typename T, typename std::enable_if<
309  !is_contiguous_tensor<T>::value>::type* = nullptr>
310 inline typename T::size_type inner_size(const T& tensor) {
311  return inner_size_helper(tensor);
312 }
313 
315 
320 inline constexpr bool empty() { return true; }
321 
323 
329 template <typename T1, typename... Ts>
330 inline bool empty(const T1& tensor1, const Ts&... tensors) {
331  return tensor1.empty() || empty(tensors...);
332 }
333 
334 } // namespace detail
335 } // namespace TiledArray
336 
337 #endif // TILEDARRAY_TENSOR_UTILITY_H__INCLUDED
auto clone_range(const T &tensor)
Create a copy of the range of the tensor.
Definition: utility.h:47
constexpr bool is_range_set_congruent(const Permutation &perm, const T &tensor)
Test that the ranges of a permuted tensor is congruent with itself.
Definition: utility.h:130
bool is_range_congruent(const Left &left, const ShiftWrapper< Right > &right)
Check for congruent range objects with a shifted tensor.
Permutation of a sequence of objects indexed by base-0 indices.
Definition: permutation.h:130
T1::size_type inner_size(const T1 &tensor1, const T2 &)
Get the inner size of two tensors.
Definition: utility.h:260
#define TA_ASSERT(EXPR,...)
Definition: error.h:39
T::size_type inner_size_helper(const T &tensor)
Get the inner size.
Definition: utility.h:192
bool is_congruent(const BlockRange &r1, const BlockRange &r2)
Test that two BlockRange objects are congruent.
Definition: block_range.h:400
constexpr bool empty()
Test for empty tensors in an empty list.
Definition: utility.h:320
size_t volume(const DistArray< Tile, Policy > &a)
Definition: dist_array.h:1622
A (hyperrectangular) interval on , space of integer -indices.
Definition: range.h:46