LArSoft  v06_85_00
Liquid Argon Software toolkit - http://larsoft.org/
TensorIndices.h
Go to the documentation of this file.
1 
15 #ifndef LARDATA_UTILITIES_TENSORINDICES_H
16 #define LARDATA_UTILITIES_TENSORINDICES_H
17 
18 
19 // C/C++ standard libraries
20 #include <cstddef> // std::size_t
21 #include <stdexcept> // std::out_of_range
22 #include <string> // std::to_string()
23 #include <type_traits> // std::enable_if
24 
25 
26 namespace util {
27 
28 
31 
33  using Index_t = std::ptrdiff_t;
34 
36  using DimSize_t = std::size_t;
37 
39  using LinIndex_t = std::size_t;
40 
41  }; // TensorIndicesBasicTypes
42 
43 
44  // This is the class declaration; it has a specialisation for rank 1 and
45  // a generic implementation (valid for rank larger than 1).
46  template <unsigned int RANK>
48 
49 
50  namespace details {
51  template <unsigned int RANK, unsigned int DIM>
53  } // namespace details
54 
55 
63  template <>
64  class TensorIndices<1U> {
65  public:
66 
68 
70 
72 
73  static constexpr unsigned int rank() { return 1U; }
74 
75 
76  TensorIndices(DimSize_t dim): dimSize(dim) {}
77 
78  template <
79  typename ITER,
80  typename = std::enable_if_t
82  >
83  TensorIndices(ITER dimIter): TensorIndices(*dimIter) {}
84 
85 
86  LinIndex_t operator() (Index_t index) const { return index; }
87 
88  template <typename ITER>
89  std::enable_if_t
90  <std::is_convertible<decltype(*(ITER())), DimSize_t>::value, LinIndex_t>
91  operator() (ITER indexIter) const { return *indexIter; }
92 
93  LinIndex_t at(Index_t index) const { return checkOuterIndex(index); }
94 
95  template <typename ITER>
96  std::enable_if_t
97  <std::is_convertible<decltype(*(ITER())), DimSize_t>::value, LinIndex_t>
98  at(ITER indexIter) const
99  { return checkOuterIndex(*indexIter); }
100 
101  bool has(Index_t index) const
102  { return (index >= 0) && ((DimSize_t) index < size()); }
103 
104  template <typename ITER>
105  std::enable_if_t
106  <std::is_convertible<decltype(*(ITER())), DimSize_t>::value, bool>
107  has(ITER indexIter) const
108  { return (*indexIter >= 0) && ((DimSize_t) *indexIter < size()); }
109 
110 
111  template <unsigned int DIM = 0>
112  DimSize_t size() const { return (DIM == 0)? totalSize(): dim<DIM>(); }
113 
114  template <unsigned int DIM>
115  DimSize_t dim() const
116  {
117  static_assert(DIM == 0, "Invalid dimension requested");
118  return dimSize;
119  } // dim()
120 
121  template <unsigned int DIM>
122  bool hasIndex(Index_t index) const
123  {
124  static_assert(DIM == 0, "Invalid dimension requested");
125  return has(index);
126  }
127 
128  bool hasLinIndex(LinIndex_t linIndex) const
129  { return has((Index_t) linIndex); }
130 
131  bool operator== (TensorIndices<1U> const& t) const
132  { return t.size() == size(); }
133  bool operator!= (TensorIndices<1U> const& t) const
134  { return t.size() != size(); }
135 
136  protected:
138  {
139  if (has(index)) return index; // good
140  throw std::out_of_range("Requested index " + std::to_string(index)
141  + " for a dimension of size " + std::to_string(size()));
142  }
143 
144  protected:
146  DimSize_t dim0() const { return dimSize; }
147 
148  private:
149  template <unsigned int R, unsigned int D>
151 
153 
155  DimSize_t totalSize() const { return dim0(); }
156 
157  }; // class TensorIndices<1>
158 
159 
174  template <unsigned int RANK>
175  class TensorIndices: private TensorIndices<1U> {
176  static_assert(RANK > 1, "TensorIndices must have rank 1 or higher");
177 
179 
180  public:
181 
184 
186  using DimSize_t = Base_t::DimSize_t ;
187 
190 
191 
193  static constexpr unsigned int rank() { return RANK; }
194 
196  using MinorTensor_t = TensorIndices<rank() - 1>;
197 
198 
211  template <typename... OTHERDIMS>
212  TensorIndices(DimSize_t first, OTHERDIMS... others)
213  : Base_t(first), m(others...), totSize(dim0() * m.size()) {}
214 
215 
235  // only if ITER can be dereferenced into something convertible to DimSize_t
236  template <
237  typename ITER,
238  typename = std::enable_if_t
240  >
241  TensorIndices(ITER dimIter)
242  : Base_t(dimIter), m(++dimIter), totSize(dim0() * m.size()) {}
243 
244 
265  template <typename... OTHERINDICES>
266  LinIndex_t operator() (Index_t first, OTHERINDICES... others) const
267  { return first * minor().size() + minor()(others...); }
268 
269 
289  template <typename ITER>
290  std::enable_if_t
291  <std::is_convertible<decltype(*(ITER())), DimSize_t>::value, LinIndex_t>
292  operator() (ITER indexIter) const
293  {
294  auto const baseSize = (*indexIter) * minor().size();
295  return baseSize + minor()(++indexIter);
296  }
297 
298 
321  template <typename... OTHERINDICES>
322  LinIndex_t at(Index_t first, OTHERINDICES... others) const
323  {
324  return Base_t::checkOuterIndex(first) * minor().size()
325  + minor().at(others...);
326  }
327 
349  template <typename ITER>
350  std::enable_if_t
351  <std::is_convertible<decltype(*(ITER())), DimSize_t>::value, LinIndex_t>
352  at(ITER indexIter) const
353  {
354  auto const baseSize
355  = Base_t::checkOuterIndex(*indexIter) * minor().size();
356  return baseSize + minor()(++indexIter);
357  }
358 
359 
384  template <typename... OTHERINDICES>
385  bool has(Index_t first, OTHERINDICES... others) const
386  { return Base_t::has(first) && minor().has(others...); }
387 
410  template <typename ITER>
411  std::enable_if_t
412  <std::is_convertible<decltype(*(ITER())), DimSize_t>::value, bool>
413  has(ITER indexIter) const
414  { return Base_t::has(*indexIter)? minor().has(++indexIter): false; }
415 
416 
424  template <unsigned int DIM>
425  DimSize_t dim() const
427 
428 
453  template <unsigned int DIM>
454  bool hasIndex(Index_t index) const
455  { return (index >= 0U) && ((DimSize_t) index < dim<DIM>()); }
456 
457 
471  template <unsigned int DIM = 0>
472  DimSize_t size() const
473  {
474  return (DIM == 0)? totalSize():
476  }
477 
479  bool hasLinIndex(LinIndex_t linIndex) const
480  { return (linIndex >= 0U) && ((DimSize_t) linIndex < size()); }
481 
482 
484  MinorTensor_t const& minor() const { return m; }
485 
487  bool operator== (TensorIndices<RANK> const& t) const
488  { return Base_t::operator==(t) && (minor() == t.minor()); }
489 
491  bool operator!= (TensorIndices<RANK> const& t) const
492  { return Base_t::operator!=(t) || (minor() != t.minor()); }
493 
494 
495 
496  protected:
497  // need to be friend of the dimension extractor
498  template <unsigned int R, unsigned int D>
500 
503 
505  DimSize_t totalSize() const { return totSize; }
506 
507  }; // class TensorIndices<>
508 
509 
510 
512  template <
513  unsigned int RANK1, unsigned int RANK2,
514  typename = std::enable_if_t<(RANK1 != RANK2), bool>
515  >
517  { return false; }
518 
520  template <
521  unsigned int RANK1, unsigned int RANK2,
522  typename = std::enable_if_t<(RANK1 != RANK2), bool>
523  >
525  { return true; }
526 
527 
541  template <typename... DIMS>
542  auto makeTensorIndices(DIMS... dims)
543  {
544  return TensorIndices<sizeof...(DIMS)>
546  }
547 
548 
551 
552 
553 } // namespace util
554 
555 
556 //------------------------------------------------------------------------------
557 //--- details implementation
558 //---
559 namespace util {
560  namespace details {
561 
578  template <unsigned int RANK, unsigned int DIM>
579  struct ExtractTensorDimension {
580  static_assert(RANK > DIM, "Invalid dimension requested");
584 
588 
589  }; // ExtractTensorDimension<>()
590 
591  template <unsigned int RANK>
592  struct ExtractTensorDimension<RANK, 0U> {
593  static_assert(RANK > 0, "Invalid rank 0 for TensorIndices");
596  { return t.dim0(); }
597 
600  { return t.size(); }
601 
602  }; // ExtractTensorDimension<RANK, 0>()
603 
604  } // namespace details
605 } // namespace util
606 
607 
608 
609 #endif // LARDATA_UTILITIES_TENSORINDICES_H
bool has(Index_t index) const
DimSize_t dim() const
std::enable_if_t< std::is_convertible< decltype(*(ITER())), DimSize_t >::value, LinIndex_t > at(ITER indexIter) const
Definition: TensorIndices.h:98
Base_t::LinIndex_t LinIndex_t
Type of the linear index.
Namespace for general, non-LArSoft-specific utilities.
Definition: PIDAAlg.h:17
std::ptrdiff_t Index_t
Type of a single index in the tensor.
Definition: TensorIndices.h:33
bool operator==(TensorIndices< RANK1 > const &a, TensorIndices< RANK2 > const &b)
Comparison operator with tensors of different rank.
bool hasIndex(Index_t index) const
Types for TensorIndices class.
Definition: TensorIndices.h:30
std::enable_if_t< std::is_convertible< decltype(*(ITER())), DimSize_t >::value, LinIndex_t > at(ITER indexIter) const
Returns the linear index corresponding to the tensor indices.
bool has(Index_t first, OTHERINDICES...others) const
Returns whether the specified set of indices is valid.
DimSize_t dimSize
size of the largest dimension
DimSize_t dim0() const
Returns the size of the outer dimension.
TensorIndices(ITER dimIter)
Definition: TensorIndices.h:83
Base_t::Index_t Index_t
Type of a single index in the tensor.
DimSize_t totalSize() const
Returns the total size of this tensor.
TensorIndices(DimSize_t first, OTHERDIMS...others)
Constructor: initialises the dimension of the tensor.
DimSize_t size() const
bool hasLinIndex(LinIndex_t linIndex) const
unsigned int Index_t
Type to denote the index of the flag.
Definition: BitMask.h:60
std::enable_if_t< std::is_convertible< decltype(*(ITER())), DimSize_t >::value, bool > has(ITER indexIter) const
DimSize_t dim() const
Returns the size of the specified dimension.
bool hasIndex(Index_t index) const
Returns whether a index is valid within a specified dimension.
DimSize_t totalSize() const
Returns the total size of this tensor (the same as size())
Index_t checkOuterIndex(Index_t index) const
Converts a tensor element specification into a linear index.
Definition: TensorIndices.h:47
TensorIndicesBasicTypes::LinIndex_t LinIndex_t
Definition: TensorIndices.h:71
std::size_t DimSize_t
Type of size of a dimension in the tensor.
Definition: TensorIndices.h:36
DimSize_t totSize
size of this tensor
TensorIndices(ITER dimIter)
Constructor: initialises the dimension of the tensor.
bool hasLinIndex(LinIndex_t linIndex) const
Returns whether the specified linear index is valid in this tensor.
TensorIndices(DimSize_t dim)
Definition: TensorIndices.h:76
TensorIndicesBasicTypes::Index_t Index_t
Definition: TensorIndices.h:67
MinorTensor_t m
the rest of the tensor indices
TensorIndicesBasicTypes::DimSize_t DimSize_t
Definition: TensorIndices.h:69
std::string value(boost::any const &)
static constexpr unsigned int rank()
Rank of this tensor.
std::string to_string(Flag_t< Storage > const flag)
Convert a flag into a stream (shows its index).
Definition: BitMask.h:187
MinorTensor_t const & minor() const
Returns the tensor of rank Rank-1 from stripping the first dimension.
static constexpr unsigned int rank()
Definition: TensorIndices.h:73
DimSize_t size() const
Returns the size of the minor tensor.
auto makeTensorIndices(DIMS...dims)
Instantiates a TensorIndices class with the specified dimensions.
bool operator!=(TensorIndices< RANK1 > const &a, TensorIndices< RANK2 > const &b)
Comparison operator with tensors of different rank.
std::size_t LinIndex_t
Type of the linear index.
Definition: TensorIndices.h:39
LinIndex_t at(Index_t first, OTHERINDICES...others) const
Returns the linear index corresponding to the tensor indices.
LinIndex_t at(Index_t index) const
Definition: TensorIndices.h:93
std::enable_if_t< std::is_convertible< decltype(*(ITER())), DimSize_t >::value, bool > has(ITER indexIter) const
Returns whether the specified set of indices is valid.
Base_t::DimSize_t DimSize_t
Type for the specification of a dimension size.