TiledArray  0.7.0
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/utility.h>
30 #include <TiledArray/range.h>
31 #include <TiledArray/block_range.h>
32 #include <TiledArray/size_array.h>
34 
35 namespace TiledArray {
36  namespace detail {
37 
39 
44  template <typename T,
45  typename std::enable_if<is_contiguous_tensor<T>::value>::type* = nullptr>
46  inline auto clone_range(const T& tensor)
47  { return tensor.range(); }
48 
50 
55  template <typename T,
56  typename std::enable_if<! is_contiguous_tensor<T>::value>::type* = nullptr>
57  inline Range clone_range(const T& tensor) {
58  return Range(tensor.range().lobound(), tensor.range().upbound());
59  }
60 
62 
68  template <typename Range>
69  inline bool is_congruent(const Range& r1, const Range& r2){
70  return r1 == r2;
71  }
72 
74 
78  template <>
79  inline bool is_congruent(const BlockRange& r1, const BlockRange& r2){
80  return (r1.rank() == r2.rank()) &&
81  std::equal(r1.extent_data(),
82  r1.extent_data() + r1.rank(), r2.extent_data());
83  }
84 
86 
91  template <typename Range>
92  inline bool is_congruent(const BlockRange& r1, const Range& r2){
93  return (r1.rank() == r2.rank()) &&
94  std::equal(r1.extent_data(),
95  r1.extent_data() + r1.rank(), r2.extent_data());
96  }
97 
99 
104  template <typename Range>
105  inline bool is_congruent(const Range& r1, const BlockRange& r2){
106  return is_congruent(r2,r1);
107  }
108 
110 
119  template <typename T1, typename T2,
120  typename std::enable_if<! (is_shifted<T1>::value
121  || is_shifted<T2>::value)>::type* = nullptr>
122  inline bool is_range_congruent(const T1& tensor1, const T2& tensor2) {
123  return is_congruent(tensor1.range(), tensor2.range());
124  }
125 
127 
137  template <typename T1, typename T2,
138  typename std::enable_if<! (is_shifted<T1>::value
139  || is_shifted<T2>::value)>::type* = nullptr>
140  inline bool is_range_congruent(const T1& tensor1, const T2& tensor2,
141  const Permutation& perm)
142  {
143  return is_congruent(tensor1.range(), perm*tensor2.range());
144  }
145 
147 
156  template <typename T1, typename T2,
157  typename std::enable_if<is_shifted<T1>::value
158  || is_shifted<T2>::value>::type* = nullptr>
159  inline bool is_range_congruent(const T1& tensor1, const T2& tensor2) {
160  const auto rank1 = tensor1.range().rank();
161  const auto rank2 = tensor2.range().rank();
162  const auto* const extent1 = tensor1.range().extent_data();
163  const auto* const extent2 = tensor2.range().extent_data();
164  return (rank1 == rank2) && std::equal(extent1, extent1 + rank1, extent2);
165  }
166 
167 
169 
177  template <typename T>
178  inline constexpr bool
179  is_range_set_congruent(const Permutation& perm, const T& tensor) {
180  return true;
181  }
182 
184 
194  template <typename T1, typename T2, typename... Ts>
195  inline bool is_range_set_congruent(const Permutation& perm,
196  const T1& tensor1, const T2& tensor2, const Ts&... tensors)
197  {
198  return is_range_congruent(tensor1, tensor2, perm)
199  && is_range_set_congruent(perm, tensor1, tensors...);
200  }
201 
202 
204 
211  template <typename T>
212  inline constexpr bool is_range_set_congruent(const T& tensor) {
213  return true;
214  }
215 
217 
226  template <typename T1, typename T2, typename... Ts>
227  inline bool is_range_set_congruent(const T1& tensor1, const T2& tensor2,
228  const Ts&... tensors)
229  {
230  return is_range_congruent(tensor1, tensor2)
231  && is_range_set_congruent(tensor1, tensors...);
232  }
233 
234 
236 
243  template <typename T>
244  inline typename T::size_type inner_size_helper(const T& tensor) {
245  const auto* MADNESS_RESTRICT const stride = tensor.range().stride_data();
246  const auto* MADNESS_RESTRICT const size = tensor.range().extent_data();
247 
248  int i = int(tensor.range().rank()) - 1;
249  auto volume = size[i];
250 
251  for(--i; i >= 0; --i) {
252  const auto stride_i = stride[i];
253  const auto size_i = size[i];
254 
255  if(volume != stride_i)
256  break;
257  volume *= size_i;
258  }
259 
260  return volume;
261  }
262 
264 
273  template <typename T1, typename T2>
274  inline typename T1::size_type
275  inner_size_helper(const T1& tensor1, const T2& tensor2) {
276  TA_ASSERT(is_range_congruent(tensor1, tensor2));
277  const auto* MADNESS_RESTRICT const size1 = tensor1.range().extent_data();
278  const auto* MADNESS_RESTRICT const stride1 = tensor1.range().stride_data();
279  const auto* MADNESS_RESTRICT const size2 = tensor2.range().extent_data();
280  const auto* MADNESS_RESTRICT const stride2 = tensor2.range().stride_data();
281 
282  int i = int(tensor1.range().rank()) - 1;
283  auto volume1 = size1[i];
284  auto volume2 = size2[i];
285 
286  for(--i; i >= 0; --i) {
287  const auto stride1_i = stride1[i];
288  const auto stride2_i = stride2[i];
289  const auto size1_i = size1[i];
290  const auto size2_i = size2[i];
291 
292  if((volume1 != stride1_i) || (volume2 != stride2_i))
293  break;
294  volume1 *= size1_i;
295  volume2 *= size2_i;
296  }
297 
298  return volume1;
299  }
300 
302 
310  template <typename T1, typename T2,
311  typename std::enable_if<! is_contiguous_tensor<T1>::value
312  && is_contiguous_tensor<T2>::value>::type* = nullptr>
313  inline typename T1::size_type inner_size(const T1& tensor1, const T2&) {
314  return inner_size_helper(tensor1);
315  }
316 
317 
319 
327  template <typename T1, typename T2,
328  typename std::enable_if<is_contiguous_tensor<T1>::value
329  && ! is_contiguous_tensor<T2>::value>::type* = nullptr>
330  inline typename T1::size_type inner_size(const T1&, const T2& tensor2) {
331  return inner_size_helper(tensor2);
332  }
333 
335 
345  template <typename T1, typename T2,
346  typename std::enable_if<! is_contiguous_tensor<T1>::value
347  && ! is_contiguous_tensor<T2>::value>::type* = nullptr>
348  inline typename T1::size_type inner_size(const T1& tensor1, const T2& tensor2) {
349  return inner_size_helper(tensor1, tensor2);
350  }
351 
352 
354 
361  template <typename T,
362  typename std::enable_if<! is_contiguous_tensor<T>::value>::type* = nullptr>
363  inline typename T::size_type inner_size(const T& tensor) {
364  return inner_size_helper(tensor);
365  }
366 
367 
369 
374  inline constexpr bool empty() { return true; }
375 
377 
383  template <typename T1, typename... Ts>
384  inline bool empty(const T1& tensor1, const Ts&... tensors) {
385  return tensor1.empty() && empty(tensors...);
386  }
387 
388  } // namespace detail
389 } // namespace TiledArray
390 
391 #endif // TILEDARRAY_TENSOR_UTILITY_H__INCLUDED
A (hyperrectangular) interval on , space of integer n-indices.
Definition: range.h:39
const size_type * extent_data() const
Range extent data accessor.
Definition: range.h:594
bool is_congruent(const Range &r1, const Range &r2)
Test the two ranges are congruent.
Definition: utility.h:69
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:179
bool is_range_congruent(const Left &left, const ShiftWrapper< Right > &right)
Check for congruent range objects with a shifted tensor.
T::size_type inner_size_helper(const T &tensor)
Get the inner size.
Definition: utility.h:244
auto clone_range(const T &tensor)
Create a copy of the range of the tensor.
Definition: utility.h:46
unsigned int rank() const
Rank accessor.
Definition: range.h:542
T1::size_type inner_size(const T1 &tensor1, const T2 &)
Get the inner size of two tensors.
Definition: utility.h:313
constexpr std::size_t size(T(&)[N])
Array size accessor.
Definition: utility.h:47
constexpr bool empty()
Test for empty tensors in an empty list.
Definition: utility.h:374
#define TA_ASSERT(a)
Definition: error.h:107
Permutation of a sequence of objects indexed by base-0 indices.
Definition: permutation.h:119
Range that references a subblock of another range.
Definition: block_range.h:34