Hammer  1.0.0
Helicity Amplitude Module for Matrix Element Reweighting
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
BinnedIndexingDefs.hh
Go to the documentation of this file.
1 #pragma clang diagnostic push
2 #pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
3 ///
4 /// @file BinnedIndexingDefs.hh
5 /// @brief Binned tensor (histogram) indexer template method definitions
6 ///
7 #pragma clang diagnostic pop
8 
9 //**** This file is a part of the HAMMER library
10 //**** Copyright (C) 2016 - 2020 The HAMMER Collaboration
11 //**** HAMMER is licensed under version 3 of the GPL; see COPYING for details
12 //**** Please note the MCnet academic guidelines; see GUIDELINES for details
13 
14 // -*- C++ -*-
15 
16 #include <utility>
17 
18 #include "Hammer/Exceptions.hh"
20 #include "Hammer/Math/Utils.hh"
21 
22 namespace Hammer {
23 
24  namespace MultiDimensional {
25 
26  template <class BasicIndexing>
27  BinnedIndexing<BasicIndexing>::BinnedIndexing() : BasicIndexing{}, _edges{}, _hasUnderOverFlow{false} {
28 
29  }
30 
31  template <class BasicIndexing>
32  BinnedIndexing<BasicIndexing>::BinnedIndexing(IndexList dimensions, BinEdgeList edges, bool hasUnderOverFlow)
33  : BasicIndexing{dimensions},
34  _edges{edges},
35  _hasUnderOverFlow{hasUnderOverFlow} {
36  if (!isValid()) {
37  throw RangeError("Length of list of bin edges is incompatible with length of dimensions: " +
38  std::to_string(edges.size()) + " vs " + std::to_string(dimensions.size()) +
39  " -> all your base are belong to us.");
40  }
41  }
42 
43  template <class BasicIndexing>
44  BinnedIndexing<BasicIndexing>::BinnedIndexing(IndexList dimensions, BinRangeList ranges, bool hasUnderOverFlow)
45  : BasicIndexing{BinnedIndexing<BasicIndexing>::processRanges(dimensions, hasUnderOverFlow)},
46  _hasUnderOverFlow{hasUnderOverFlow} {
47  fillEdges(ranges);
48  }
49 
50  template <class BasicIndexing>
53  _edges{edges},
54  _hasUnderOverFlow{hasUnderOverFlow} {
55  }
56 
57  template <class BasicIndexing>
59  return _edges;
60  }
61 
62  template <class BasicIndexing>
64  ASSERT(pos < _edges.size());
65  return _edges[pos];
66  }
67 
68  template <class BasicIndexing>
70  auto itv = point.begin();
71  auto itb = _edges.begin();
72  IndexList result;
73  int delta = _hasUnderOverFlow ? 0 : -1;
74  for (; itb != _edges.end(); ++itv, ++itb) {
75  auto itp = lower_bound(itb->begin(), itb->end(), *itv);
76  result.push_back(static_cast<IndexType>(distance(itb->begin(), itp) + delta));
77  }
78  return result;
79  }
80 
81  template <class BasicIndexing>
83  return (_hasUnderOverFlow ||
84  this->checkValidIndices(valueToPos(point)));
85  }
86 
87  template <class BasicIndexing>
89  ASSERT(this->checkValidIndices(position));
90  BinRangeList result;
91  result.reserve(position.size());
92  auto itp = position.begin();
93  auto itd = this->dims().begin();
94  auto ite = _edges.begin();
95  int delta = _hasUnderOverFlow ? -1 : 0;
96  for(; itp != position.end(); ++itp, ++ite, ++itd) {
97  if (_hasUnderOverFlow && *itp == 0) {
98  result.push_back({-std::numeric_limits<double>::max(),(*ite)[0]});
99  }
100  else if (_hasUnderOverFlow && *itp == ((*itd) - 1)) {
101  result.push_back({ite->back(), std::numeric_limits<double>::max()});
102  }
103  else {
104  result.push_back({(*ite)[*itp + delta], (*ite)[*itp + delta + 1]});
105  }
106  }
107  return result;
108  }
109 
110  template <class BasicIndexing>
112  ASSERT(coord < this->rank());
113  ASSERT(position < this->dims(coord));
114  auto& binnings = _edges[coord];
115  int delta = _hasUnderOverFlow ? -1 : 0;
116  if (_hasUnderOverFlow && position == 0) {
117  return {-std::numeric_limits<double>::max(), binnings[0]};
118  }
119  else if (_hasUnderOverFlow && position == (this->dims(coord) - 1)) {
120  return {binnings.back(), std::numeric_limits<double>::max()};
121  }
122  else {
123  return {binnings[position + delta], binnings[position + delta + 1]};
124  }
125  }
126 
127 
128  template <class BasicIndexing>
129  bool BinnedIndexing<BasicIndexing>::isSameBinShape(const BinEdgeList& otherEdges, const IndexList& otherIndices,
130  bool otherUnderOverFlow) const {
131  bool result = (_hasUnderOverFlow == otherUnderOverFlow);
132  if(!result)
133  return false;
134  result = this->isSameShape(otherIndices);
135  if (!result)
136  return false;
137  result &= equal(_edges.begin(), _edges.end(), otherEdges.begin());
138  return result;
139  }
140 
141  template <class BasicIndexing>
143  const IndexList& otherIndices,
144  bool otherUnderOverFlow) const {
145  bool result = (_hasUnderOverFlow == otherUnderOverFlow);
146  if (!result)
147  return false;
148  result = this->isSameShape(otherIndices);
149  if(!result) return false;
150  auto ite = _edges.begin();
151  auto itr = otherRanges.begin();
152  for(; ite != _edges.end() && itr != otherRanges.end(); ++ite, ++itr) {
153  result &= isZero(ite->front() - itr->first) && isZero(ite->back() - itr->second);
154  if(!result) break;
155  }
156  return result;
157  }
158 
159  template <class BasicIndexing>
160  template <typename S>
162  bool result = (_hasUnderOverFlow == other._hasUnderOverFlow);
163  if (!result)
164  return false;
165  result = this->isSameShape(other);
166  if(!result) return false;
167  result &= equal(_edges.begin(), _edges.end(), other._edges.begin());
168  return result;
169  }
170 
171  template <class BasicIndexing>
173  bool valid = (_edges.size() == this->rank());
174  for (IndexType i = 0; i < _edges.size(); ++i) {
175  valid &= ((_hasUnderOverFlow && (_edges[i].size() + 1u == dim(i))) ||
176  (!_hasUnderOverFlow && (_edges[i].size() == dim(i) + 1u)));
177  }
178  return valid;
179  }
180 
181  template <class BasicIndexing>
183  int deltaIdx = _hasUnderOverFlow ? -1 : 1;
184  if (ranges.size() > 0) {
185  ASSERT(ranges.size() == this->rank());
186  auto itr = ranges.begin();
187  auto itn = this->dims().begin();
188  for (; itn != this->dims().end(); ++itr, ++itn) {
189  std::vector<double> tmpvec(static_cast<size_t>(*itn + deltaIdx));
190  const double delta = (itr->second - itr->first) / (1. * (*itn + deltaIdx - 1));
191  generate(tmpvec.begin(), tmpvec.end(), [&, n = itr->first]() mutable {
192  double tmp = n;
193  n += delta;
194  return tmp;
195  });
196  _edges.push_back(tmpvec);
197  }
198  } else {
199  for (auto itn = this->dims().begin(); itn != this->dims().end(); ++itn) {
200  std::vector<double> tmpvec(static_cast<size_t>(*itn + deltaIdx));
201  generate(tmpvec.begin(), tmpvec.end(), [n = 0]() mutable { return n++; });
202  _edges.push_back(tmpvec);
203  }
204  }
205  }
206 
207  template <class BasicIndexing>
209  IndexList result;
210  result.reserve(edges.size());
211  int delta = hasUnderOverFlow ? 1 : -1;
212  for (auto& elem : edges) {
213  ASSERT(static_cast<int>(elem.size()) + delta > 0);
214  result.push_back(static_cast<IndexType>(static_cast<int>(elem.size()) + delta));
215  }
216  return result;
217  }
218 
219  template <class BasicIndexing>
220  IndexList BinnedIndexing<BasicIndexing>::processRanges(const IndexList& dimensions, bool hasUnderOverFlow) {
221  IndexList result;
222  result.reserve(dimensions.size());
223  int delta = hasUnderOverFlow ? 2 : 0;
224  for (auto& elem : dimensions) {
225  ASSERT(elem + delta > 0);
226  result.push_back(static_cast<IndexType>(elem + delta));
227  }
228  return result;
229  }
230 
231 
232  template <class BasicIndexing>
234  return _hasUnderOverFlow;
235  }
236 
237  template <class BasicIndexing>
238  typename BasicIndexing::StrideMap BinnedIndexing<BasicIndexing>::getBinStrides(const UniqueIndexList& positions) const {
239  std::map<IndexType, long> innerStrides;
240  for(auto& elem: positions) {
241  innerStrides.insert({elem, 0});
242  }
243  return this->buildStrideMap(innerStrides);
244  }
245 
246  } // namespace MultiDimensional
247 
248 } // namespace Hammer
BasicIndexing::StrideMap getBinStrides(const UniqueIndexList &positions) const
#define ASSERT(x)
Definition: Exceptions.hh:95
const BinEdgeList & edges() const
get the labels of all the indices at once
std::vector< std::vector< double >> BinEdgeList
bool isSameBinShape(const BinEdgeList &otherEdges, const IndexList &otherIndices, bool otherUnderOverFlow) const
BinRangeList binEdges(IndexList position) const
uint16_t IndexType
auto begin(reversion_wrapper< T > w)
Definition: Tools/Utils.hh:79
Hammer exception definitions.
IndexList valueToPos(const BinValue &point) const
Interface class for tensor container data structure.
std::vector< IndexType > IndexList
const BinValue & edge(IndexType pos) const
BinEdgeList _edges
the labels of each tensor index
bool isZero(const std::complex< double > val)
Definition: Math/Utils.hh:25
std::set< IndexType > UniqueIndexList
static IndexList processEdges(const BinEdgeList &edges, bool hasUnderOverFlow)
void fillEdges(const BinRangeList &ranges)
std::vector< BinRange > BinRangeList
BinRange binEdge(IndexType position, IndexType coord) const
std::pair< double, double > BinRange
std::vector< double > BinValue
static IndexList processRanges(const IndexList &dimensions, bool hasUnderOverFlow)