Hammer  1.0.0
Helicity Amplitude Module for Matrix Element Reweighting
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SequentialIndexing.cc
Go to the documentation of this file.
1 ///
2 /// @file SequentialIndexing.cc
3 /// @brief Non-sparse tensor indexer
4 ///
5 
6 //**** This file is a part of the HAMMER library
7 //**** Copyright (C) 2016 - 2020 The HAMMER Collaboration
8 //**** HAMMER is licensed under version 3 of the GPL; see COPYING for details
9 //**** Please note the MCnet academic guidelines; see GUIDELINES for details
10 
11 // -*- C++ -*-
12 #include <numeric>
13 #include <functional>
14 #include <iostream>
15 #include <cstdlib>
16 #include <tuple>
17 
19 #include "Hammer/Exceptions.hh"
20 #include "Hammer/Tools/Utils.hh"
21 
22 using namespace std;
23 
24 namespace Hammer {
25 
26  namespace MultiDimensional {
27 
28  SequentialIndexing::SequentialIndexing() : _dimensions{}, _strides{}, _maxIndex{0} {
29  }
30 
31  SequentialIndexing::SequentialIndexing(IndexList dimensions) : _dimensions{dimensions} {
32  calcPadding();
33  }
34 
35  size_t SequentialIndexing::rank() const {
36  return _dimensions.size();
37  }
38 
40  if (index < _dimensions.size()) {
41  return _dimensions[index];
42  }
43  throw Hammer::RangeError("Index out of range for multidimensional object of rank " +
44  to_string(_dimensions.size()) + ": all your base are belong to us.");
45  }
46 
48  return _dimensions;
49  }
50 
52  return _maxIndex + 1;
53  }
54 
55  bool SequentialIndexing::checkValidIndices(const IndexList& indices) const {
56  bool valid = (indices.size() == _dimensions.size());
57  if (!valid)
58  return false;
59  valid = inner_product(indices.begin(), indices.end(), _dimensions.begin(), valid, logical_and<bool>(),
60  less<uint8_t>());
61  return valid;
62  }
63 
64  bool SequentialIndexing::checkValidIndices(IndexList::const_iterator first,
65  IndexList::const_iterator last) const {
66  bool valid = (distance(first, last) == static_cast<ptrdiff_t>(_dimensions.size()));
67  if (!valid)
68  return false;
69  valid = inner_product(first, last, _dimensions.begin(), valid, logical_and<bool>(), less<IndexType>());
70  return valid;
71  }
72 
74  if(rank() == 1) {
75  return indices[0];
76  }
77  return indicesToPos(indices.begin(), indices.end());
78  }
79 
80  PositionType SequentialIndexing::indicesToPos(IndexList::const_iterator first,
81  IndexList::const_iterator last) const {
82  if (rank() == 1) {
83  return *first;
84  }
85  PositionType index = 0ul;
86  function<size_t(PositionType, IndexType)> opCombine = [](PositionType a, IndexType b) -> PositionType {
87  return a * b;
88  };
89  index = inner_product(first, last, _strides.begin(), index, plus<PositionType>(), opCombine);
90  return index;
91  }
92 
94  if(rank() == 1) {
95  result[0] = static_cast<IndexType>(position);
96  }
97  pair<IndexType, PositionType> current{'\0', position};
98  auto its = _strides.begin();
99  auto itd = _dimensions.begin();
100  auto itr = result.begin();
101  for (; its != _strides.end(); ++its, ++itd, ++itr) {
102  current = {static_cast<IndexType>(current.second / (*its)), current.second % (*its)};
103  if (static_cast<PositionType>(current.first) < *itd) {
104  *itr = current.first;
105  } else {
106  throw RangeError("Index #" + to_string(distance(itd, _dimensions.begin())) +
107  " for multidimensional object "
108  " of rank " +
109  to_string(_dimensions.size()) + " out of range (" + to_string(current.first) +
110  " vs " + to_string(*itd) + "): all your base are belong to us.");
111  }
112  }
113  }
114 
116  if (indexPosition == '\0') {
117  return static_cast<IndexType>(position / _strides[indexPosition]);
118  } else {
119  PositionType temp = position % _strides[indexPosition - 1];
120  return static_cast<IndexType>(temp / _strides[indexPosition]);
121  }
122  }
123 
125  IndexType indexValue) const {
126  PositionType stride = _strides[indexPosition];
127  auto res = div(static_cast<long>(position), static_cast<long>(stride));
128  return (static_cast<PositionType>(res.quot) * _dimensions[indexPosition] + indexValue) * stride + static_cast<PositionType>(res.rem);
129  }
130 
131 
133  const PositionPairList& conversion) const {
134  PositionType out = 0ul;
135  PositionType tmp = reducedPosition;
136  for (auto& elem : conversion) {
137  auto res = div(static_cast<long>(tmp), static_cast<long>(elem.first));
138  out += static_cast<PositionType>(res.quot) * elem.second;
139  tmp = static_cast<PositionType>(res.rem);
140  }
141  return out + innerPosition;
142  }
143 
145  auto& dims = _dimensions;
146  auto tmp = accumulate(indices.begin(), indices.end(), 1ul,
147  [dims](PositionType current, const IndexPair& elem) -> PositionType {
148  return current * dims[elem.second];
149  });
150  return numValues()/tmp;
151  }
152 
154  PositionType out = 0ul;
155  long in = 0ul;
156  PositionType tmp = position;
157  for(auto& elem: conversion) {
158  if(!get<2>(elem) && get<0>(elem) == 0) {
159  continue;
160  }
161  auto res = div(static_cast<long>(tmp), static_cast<long>(get<0>(elem)));
162  if(get<2>(elem)) {
163  in += res.quot * get<1>(elem);
164  }
165  else {
166  out += static_cast<PositionType>(res.quot * get<1>(elem));
167  }
168  tmp = static_cast<PositionType>(res.rem);
169  }
170  return make_pair(out, in);
171  }
172 
173  SequentialIndexing::StrideMap SequentialIndexing::getInnerOuterStrides(const IndexPairList& positions, const PositionList& secondStrides, bool flipSecond) const {
174  ASSERT(positions.size() > 0 && positions.size() <= _dimensions.size());
175  ASSERT(is_sorted(positions.begin(), positions.end(), [](const pair<IndexType, IndexType>& a,
176  const pair<IndexType, IndexType>& b) -> bool { return a.second < b.second;}));
177  map<IndexType, long> innerStrides;
178  for (auto& elem : positions) {
179  innerStrides.insert({elem.first, secondStrides[elem.second]});
180  if(flipSecond) {
181  innerStrides.insert({elem.second, -1 * static_cast<long>(secondStrides[elem.second])});
182  }
183  }
184  return buildStrideMap(innerStrides);
185  }
186 
187  SequentialIndexing::StrideMap SequentialIndexing::buildStrideMap(const map<IndexType, long> innerMap) const {
188  auto it = innerMap.end();
189  PositionType outerStride = 1ul;
190  StrideMap results;
191  results.reserve(_dimensions.size());
192  bool done = (it == innerMap.begin());
193  if (!done) {
194  --it;
195  }
196  for (IndexType i = static_cast<IndexType>(_dimensions.size()); i-- != 0; ) {
197  if (!done && i == it->first) {
198  results.push_back(make_tuple(_strides[i], it->second, true));
199  if(it == innerMap.begin()) {
200  done = true;
201  }
202  else {
203  --it;
204  }
205  } else {
206  results.push_back(make_tuple(_strides[i], outerStride, false));
207  outerStride *= _dimensions[i];
208  }
209  }
210  reverse(results.begin(), results.end());
211  for(size_t i=0; i< results.size()-1; ++i) {
212  if (!get<2>(results[i + 1]) && !get<2>(results[i])) {
213  results[i] = make_tuple(0,0,false);
214  }
215  }
216  return results;
217  }
218 
220  ASSERT(positions.size() > 0 && positions.size() <= _dimensions.size());
221  ASSERT(is_sorted(positions.begin(), positions.end(),
222  [](const IndexPair& a, const IndexPair& b) -> bool {
223  return a.second < b.second;
224  }));
225  auto it = positions.end();
226  PositionType outerStride = 1ul;
227  PositionPairList results;
228  results.reserve(_dimensions.size()-positions.size());
229  bool done = (it == positions.begin());
230  if (!done) {
231  --it;
232  }
233  for (IndexType i = static_cast<IndexType>(_dimensions.size()); i-- != 0;) {
234  if (!done && i == it->second) {
235  if (it == positions.begin()) {
236  done = true;
237  } else {
238  --it;
239  }
240  } else {
241  results.push_back(make_pair(outerStride, _strides[i]));
242  outerStride *= _dimensions[i];
243  }
244  }
245  reverse(results.begin(), results.end());
246  return results;
247  }
248 
249 
251  return _strides[index];
252  }
253 
255  return _strides;
256  }
257 
259  _strides.clear();
260  _strides.push_back(1);
261  partial_sum(_dimensions.rbegin(), _dimensions.rend(), back_inserter(_strides), multiplies<PositionType>());
262  _maxIndex = _strides.back() - 1;
263  _strides.pop_back();
264  reverse(_strides.begin(), _strides.end());
265  }
266 
267 
268  bool SequentialIndexing::isSameShape(const IndexList& indices) const {
269  if (rank() != indices.size())
270  return false;
271  return equal(_dimensions.begin(), _dimensions.end(), indices.begin());
272  }
273 
274  } // namespace MultiDimensional
275 
276 } // namespace Hammer
PositionPairList getOuterStrides2nd(const IndexPairList &positions) const
Get the Outer Strides2nd object.
std::pair< IndexType, IndexType > IndexPair
StrideMap buildStrideMap(const std::map< IndexType, long > innerMap) const
std::vector< IndexPair > IndexPairList
PositionList _strides
the strides for each tensor index (necessary to convert coordinates to position in _data) ...
size_t PositionType
#define ASSERT(x)
Definition: Exceptions.hh:95
const IndexList & dims() const
get the dimensions of all the indices at once
std::pair< PositionType, PositionType > PositionPair
Non-sparse tensor indexer.
PositionType extendPosition(PositionType position, IndexType indexPosition, IndexType indexValue) const
extends an absolute position from a rank N-1 tensor to the corresponding position for this rank N ten...
uint16_t IndexType
std::vector< std::tuple< PositionType, long, bool >> StrideMap
PositionPair splitPosition(PositionType position, const StrideMap &conversion) const
PositionType indicesToPos(const IndexList &indices) const
convert the indices into the position indicizing a sparse tensor container organized as row-major ...
void posToIndices(PositionType position, IndexList &result) const
convert the absolute position (in row-major convention) into the list of indices
Hammer exception definitions.
size_t rank() const
rank of the tensor
bool isSameShape(const BasicIndexing &other) const
PositionType reducedNumValues(const IndexPairList &indices) const
std::vector< IndexType > IndexList
IndexType ithIndexInPos(PositionType position, IndexType indexPosition) const
extract the value of the i-th index from an absolute position
IndexType dim(IndexType index) const
dimension of a specific component
PositionType numValues() const
the number of elements (product of all the dimensions)
std::vector< PositionPair > PositionPairList
const PositionList & strides() const
list of strides, i.e.
StrideMap getInnerOuterStrides(const IndexPairList &positions, const PositionList &secondStrides, bool flipSecond=false) const
Get the Inner Outer Strides object.
bool checkValidIndices(const IndexList &indices) const
check that the indices are within range for each component
PositionType build2ndPosition(PositionType reducedPosition, PositionType innerPosition, const PositionPairList &conversion) const
Out-of-range error class.
Definition: Exceptions.hh:49
PositionType stride(IndexType index) const
stride of a specific component, i.e.
IndexList _dimensions
the dimensions of each tensor index
std::vector< PositionType > PositionList