TiledArray  0.7.0
perm_index.h
Go to the documentation of this file.
1 /*
2  * This file is a part of TiledArray.
3  * Copyright (C) 2014 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  * perm_index.h
22  * Oct 10, 2014
23  *
24  */
25 
26 #ifndef TILEDARRAY_PERM_INDEX_H__INCLUDED
27 #define TILEDARRAY_PERM_INDEX_H__INCLUDED
28 
29 #include <TiledArray/range.h>
30 
31 namespace TiledArray {
32  namespace detail {
33 
34 
36 
39  class PermIndex {
40  std::size_t* weights_;
41  unsigned int ndim_;
43 
44  public:
45 
47  PermIndex() : weights_(NULL), ndim_(0) { }
48 
50 
52  PermIndex(const Range& range, const Permutation& perm) :
53  weights_(NULL), ndim_(perm.dim())
54  {
55  if(ndim_ > 0) {
56  // Check the input data
57  TA_ASSERT(range.rank() == perm.dim());
58 
59  // Construct the inverse permutation
60  const Permutation inv_perm_ = -perm;
61 
62  // Allocate memory for this object
63  weights_ = static_cast<std::size_t*>(malloc((ndim_ + ndim_) * sizeof(std::size_t)));
64  if(! weights_)
65  throw std::bad_alloc();
66 
67  // Construct MADNESS_RESTRICTed pointers to the input data
68  const auto* MADNESS_RESTRICT const inv_perm = & inv_perm_.data().front();
69  const auto* MADNESS_RESTRICT const range_size = range.extent_data();
70  const auto* MADNESS_RESTRICT const range_weight = range.stride_data();
71 
72  // Construct MADNESS_RESTRICTed pointers to the object data
73  std::size_t* MADNESS_RESTRICT const input_weight = weights_;
74  std::size_t* MADNESS_RESTRICT const output_weight = weights_ + ndim_;
75 
76  // Initialize input and output weights
77  std::size_t volume = 1ul;
78  for(int i = int(ndim_) - 1; i >= 0; --i) {
79  // Load input data for iteration i.
80  const auto inv_perm_i = inv_perm[i];
81  const auto weight = range_weight[i];
82  const auto size = range_size[inv_perm_i];
83 
84  // Store the input and output weights
85  output_weight[inv_perm_i] = volume;
86  volume *= size;
87  input_weight[i] = weight;
88  }
89  }
90  }
91 
92  PermIndex(const PermIndex& other) :
93  weights_(NULL), ndim_(other.ndim_)
94  {
95  if(ndim_) {
96  // Allocate memory for this object
97  weights_ = static_cast<std::size_t*>(malloc((ndim_ + ndim_) * sizeof(std::size_t)));
98  if(! weights_)
99  throw std::bad_alloc();
100 
101  // Copy data
102  memcpy(weights_, other.weights_, (ndim_ + ndim_) * sizeof(std::size_t));
103  }
104  }
105 
107  free(weights_);
108  weights_ = NULL;
109  }
110 
111  PermIndex& operator=(const PermIndex& other) {
112  // Deallocate memory
113  if(ndim_ && (ndim_ != other.ndim_)) {
114  free(weights_);
115  weights_ = NULL;
116  }
117 
118  const std::size_t bytes = (other.ndim_ + other.ndim_) * sizeof(std::size_t);
119 
120  if(! weights_ && bytes) {
121  // Allocate new memory
122  weights_ = static_cast<std::size_t*>(malloc(bytes));
123  if(! weights_)
124  throw std::bad_alloc();
125  }
126 
127  // copy the data (safe if ndim_ == 0)
128  ndim_ = other.ndim_;
129  memcpy(weights_, other.weights_, bytes);
130 
131  return *this;
132  }
133 
135 
137  int dim() const { return ndim_; }
138 
140 
142  const std::size_t* data() const { return weights_; }
143 
145  std::size_t operator()(std::size_t index) const {
146  TA_ASSERT(ndim_);
147  TA_ASSERT(weights_);
148 
149  // Construct MADNESS_RESTRICTed pointers to data
150  const std::size_t* MADNESS_RESTRICT const input_weight = weights_;
151  const std::size_t* MADNESS_RESTRICT const output_weight = weights_ + ndim_;
152 
153  // create result index
154  std::size_t perm_index = 0ul;
155 
156  for(unsigned int i = 0u; i < ndim_; ++i) {
157  const std::size_t input_weight_i = input_weight[i];
158  const std::size_t output_weight_i = output_weight[i];
159  perm_index += index / input_weight_i * output_weight_i;
160  index %= input_weight_i;
161  }
162 
163  return perm_index;
164  }
165 
166  // Check for valid permutation
167  operator bool() const { return ndim_; }
168  }; // class PermIndex
169 
170  } // namespace detail
171 } // namespace TiledArray
172 
173 #endif // MADNESS_PERM_INDEX_H__INCLUDED
174 TILEDARRAY_PERM_INDEX_H__INCLUDED
A functor that permutes ordinal indices.
Definition: perm_index.h:39
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
PermIndex(const Range &range, const Permutation &perm)
Construct permuting functor.
Definition: perm_index.h:52
const std::size_t * data() const
Data accessor.
Definition: perm_index.h:142
std::size_t operator()(std::size_t index) const
Compute the permuted index for the current block.
Definition: perm_index.h:145
unsigned int rank() const
Rank accessor.
Definition: range.h:542
const size_type * stride_data() const
Range stride data accessor.
Definition: range.h:618
PermIndex(const PermIndex &other)
Definition: perm_index.h:92
index_type dim() const
Domain size accessor.
Definition: permutation.h:206
constexpr std::size_t size(T(&)[N])
Array size accessor.
Definition: utility.h:47
#define TA_ASSERT(a)
Definition: error.h:107
Permutation of a sequence of objects indexed by base-0 indices.
Definition: permutation.h:119
PermIndex()
Default constructor.
Definition: perm_index.h:47
int dim() const
Dimension accessor.
Definition: perm_index.h:137
PermIndex & operator=(const PermIndex &other)
Definition: perm_index.h:111