26 #ifndef TILEDARRAY_TENSOR_UTILITY_H__INCLUDED 27 #define TILEDARRAY_TENSOR_UTILITY_H__INCLUDED 45 typename std::enable_if<is_contiguous_tensor<T>::value>::type* =
nullptr>
47 {
return tensor.range(); }
56 typename std::enable_if<! is_contiguous_tensor<T>::value>::type* =
nullptr>
58 return Range(tensor.range().lobound(), tensor.range().upbound());
68 template <
typename Range>
91 template <
typename Range>
104 template <
typename Range>
119 template <
typename T1,
typename T2,
120 typename std::enable_if<! (is_shifted<T1>::value
121 || is_shifted<T2>::value)>::type* =
nullptr>
137 template <
typename T1,
typename T2,
138 typename std::enable_if<! (is_shifted<T1>::value
139 || is_shifted<T2>::value)>::type* =
nullptr>
143 return is_congruent(tensor1.range(), perm*tensor2.range());
156 template <
typename T1,
typename T2,
157 typename std::enable_if<is_shifted<T1>::value
158 || is_shifted<T2>::value>::type* =
nullptr>
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);
177 template <
typename T>
178 inline constexpr
bool 194 template <
typename T1,
typename T2,
typename... Ts>
196 const T1& tensor1,
const T2& tensor2,
const Ts&... tensors)
211 template <
typename T>
226 template <
typename T1,
typename T2,
typename... Ts>
228 const Ts&... tensors)
243 template <
typename T>
245 const auto* MADNESS_RESTRICT
const stride = tensor.range().stride_data();
246 const auto* MADNESS_RESTRICT
const size = tensor.range().extent_data();
248 int i = int(tensor.range().rank()) - 1;
249 auto volume =
size[i];
251 for(--i; i >= 0; --i) {
252 const auto stride_i = stride[i];
253 const auto size_i =
size[i];
255 if(volume != stride_i)
273 template <
typename T1,
typename T2>
274 inline typename T1::size_type
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();
282 int i = int(tensor1.range().rank()) - 1;
283 auto volume1 = size1[i];
284 auto volume2 = size2[i];
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];
292 if((volume1 != stride1_i) || (volume2 != stride2_i))
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&) {
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) {
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) {
361 template <
typename T,
362 typename std::enable_if<! is_contiguous_tensor<T>::value>::type* =
nullptr>
374 inline constexpr
bool empty() {
return true; }
383 template <
typename T1,
typename... Ts>
384 inline bool empty(
const T1& tensor1,
const Ts&... tensors) {
385 return tensor1.empty() &&
empty(tensors...);
391 #endif // TILEDARRAY_TENSOR_UTILITY_H__INCLUDED A (hyperrectangular) interval on , space of integer n-indices.
const size_type * extent_data() const
Range extent data accessor.
bool is_congruent(const Range &r1, const Range &r2)
Test the two ranges are congruent.
constexpr bool is_range_set_congruent(const Permutation &perm, const T &tensor)
Test that the ranges of a permuted tensor is congruent with itself.
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.
auto clone_range(const T &tensor)
Create a copy of the range of the tensor.
unsigned int rank() const
Rank accessor.
T1::size_type inner_size(const T1 &tensor1, const T2 &)
Get the inner size of two tensors.
constexpr std::size_t size(T(&)[N])
Array size accessor.
constexpr bool empty()
Test for empty tensors in an empty list.
Permutation of a sequence of objects indexed by base-0 indices.
Range that references a subblock of another range.