TensorIndices.h
Go to the documentation of this file.
1 /**
2  * @file TensorIndices.h
3  * @brief TensorIndices class to flatten multi-dimension indices into linear
4  * @author Gianluca Petrillo (petrillo@fnal.gov)
5  * @date June 28, 2016
6  *
7  * This header provides:
8  *
9  * * util::TensorIndices: general template
10  * * util::MatrixIndices: alias for 2D tensors
11  *
12  * This is a pure header that contains only template classes.
13  */
14 
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 namespace util {
26 
27 
28  /// Types for TensorIndices class
30 
31  /// Type of a single index in the tensor
32  using Index_t = std::ptrdiff_t;
33 
34  /// Type of size of a dimension in the tensor
35  using DimSize_t = std::size_t;
36 
37  /// Type of the linear index
38  using LinIndex_t = std::size_t;
39 
40  }; // TensorIndicesBasicTypes
41 
42 
43  // This is the class declaration; it has a specialisation for rank 1 and
44  // a generic implementation (valid for rank larger than 1).
45  template <unsigned int RANK>
47 
48 
49  namespace details {
50  template <unsigned int RANK, unsigned int DIM>
52  } // namespace details
53 
54 
55  /**
56  * Specialisation for vector index (rank 1).
57  *
58  * Documentation is in the general template.
59  * No public methods are added respect to it (but the `minor()` method is
60  * removed).
61  */
62  template <>
63  class TensorIndices<1U> {
64  public:
65 
67 
69 
71 
72  static constexpr unsigned int rank() { return 1U; }
73 
74 
75  TensorIndices(DimSize_t dim): dimSize(dim) {}
76 
77  template <
78  typename ITER,
79  typename = std::enable_if_t
81  >
82  TensorIndices(ITER dimIter): TensorIndices(*dimIter) {}
83 
84 
85  LinIndex_t operator() (Index_t index) const { return index; }
86 
87  template <typename ITER>
88  std::enable_if_t
89  <std::is_convertible<decltype(*(ITER())), DimSize_t>::value, LinIndex_t>
90  operator() (ITER indexIter) const { return *indexIter; }
91 
92  LinIndex_t at(Index_t index) const { return checkOuterIndex(index); }
93 
94  template <typename ITER>
95  std::enable_if_t
96  <std::is_convertible<decltype(*(ITER())), DimSize_t>::value, LinIndex_t>
97  at(ITER indexIter) const
98  { return checkOuterIndex(*indexIter); }
99 
100  bool has(Index_t index) const
101  { return (index >= 0) && ((DimSize_t) index < size()); }
102 
103  template <typename ITER>
104  std::enable_if_t
105  <std::is_convertible<decltype(*(ITER())), DimSize_t>::value, bool>
106  has(ITER indexIter) const
107  { return (*indexIter >= 0) && ((DimSize_t) *indexIter < size()); }
108 
109 
110  template <unsigned int DIM = 0>
111  DimSize_t size() const { return (DIM == 0)? totalSize(): dim<DIM>(); }
112 
113  template <unsigned int DIM>
114  DimSize_t dim() const
115  {
116  static_assert(DIM == 0, "Invalid dimension requested");
117  return dimSize;
118  } // dim()
119 
120  template <unsigned int DIM>
121  bool hasIndex(Index_t index) const
122  {
123  static_assert(DIM == 0, "Invalid dimension requested");
124  return has(index);
125  }
126 
127  bool hasLinIndex(LinIndex_t linIndex) const
128  { return has((Index_t) linIndex); }
129 
130  bool operator== (TensorIndices<1U> const& t) const
131  { return t.size() == size(); }
132  bool operator!= (TensorIndices<1U> const& t) const
133  { return t.size() != size(); }
134 
135  protected:
137  {
138  if (has(index)) return index; // good
139  throw std::out_of_range("Requested index " + std::to_string(index)
140  + " for a dimension of size " + std::to_string(size()));
141  }
142 
143  protected:
144  /// Returns the size of the outer dimension
145  DimSize_t dim0() const { return dimSize; }
146 
147  private:
148  template <unsigned int R, unsigned int D>
150 
151  DimSize_t dimSize; ///< size of the largest dimension
152 
153  /// Returns the total size of this tensor
154  DimSize_t totalSize() const { return dim0(); }
155 
156  }; // class TensorIndices<1>
157 
158 
159  /**
160  * @brief Converts a tensor element specification into a linear index
161  *
162  * Example to use a 6 x 3 x 2 x 4 tensor of rank 4:
163  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
164  * TensorIndices<4> indices(6, 3, 2, 4);
165  *
166  * std::vector<double> v(indices.size(), 0.);
167  * std::cout << v[indices(4, 1, 1, 0)] << std::endl;
168  *
169  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
170  * This will map the content of the vector `v` as a tensor of rank 4.
171  *
172  */
173  template <unsigned int RANK>
174  class TensorIndices: private TensorIndices<1U> {
175  static_assert(RANK > 1, "TensorIndices must have rank 1 or higher");
176 
177  using Base_t = TensorIndices<1U>; ///< type of base class
178 
179  public:
180 
181  /// Type of a single index in the tensor
183 
184  /// Type for the specification of a dimension size
186 
187  /// Type of the linear index
189 
190 
191  /// Rank of this tensor
192  static constexpr unsigned int rank() { return RANK; }
193 
194  /// Type of the tensor indices with rank smaller by one
195  using MinorTensor_t = TensorIndices<rank() - 1>;
196 
197 
198  /**
199  * @brief Constructor: initialises the dimension of the tensor
200  * @tparam OTHERINDICES types of the other index values
201  * @param first the size of the first dimension
202  * @param others size of each of the other dimensions
203  *
204  * Example to initialise indices for a 6 x 3 x 2 x 4 tensor of rank 4:
205  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
206  * TensorIndices<4> indices(6, 3, 2, 4);
207  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
208  *
209  */
210  template <typename... OTHERDIMS>
211  TensorIndices(DimSize_t first, OTHERDIMS... others)
212  : Base_t(first), m(others...), totSize(dim0() * m.size()) {}
213 
214 
215  /**
216  * @brief Constructor: initialises the dimension of the tensor
217  * @tparam ITER type of iterator to dimension sizes
218  * @param dimIter iterator pointing to the first dimension size
219  *
220  * Dimensions are initialised from the values pointed by the specified
221  * iterator. The iterator is required to be a forward iterator pointing to
222  * a type convertible to a `DimSize_t` type.
223  * The iterator must be valid when increased up to `rank() - 1` times, so
224  * that all the `rank()` dimensions can be extracted.
225  *
226  * Example to initialise indices for a 6 x 3 x 2 x 4 tensor of rank 4:
227  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
228  * std::array<size_t, 4> dims { 6, 3, 2, 4 };
229  * TensorIndices<4> indices(dims.begin());
230  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
231  * Note that no `end` iterator is required.
232  *
233  */
234  // only if ITER can be dereferenced into something convertible to DimSize_t
235  template <
236  typename ITER,
237  typename = std::enable_if_t
239  >
240  TensorIndices(ITER dimIter)
241  : Base_t(dimIter), m(++dimIter), totSize(dim0() * m.size()) {}
242 
243 
244  /**
245  * @brief Returns the linear index corresponding to the tensor indices
246  * @tparam OTHERINDICES types of the other index values
247  * @param first the index of the first dimension
248  * @param others the indices of the other dimensions
249  * @return the offset of the specified element with respect to the first one
250  * @see at(), has()
251  *
252  * No check is performed on the validity of the indices (that is, whether
253  * they fall within the dimension range).
254  *
255  * Use it as:
256  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
257  * TensorIndices<4> indices(6, 3, 2, 4);
258  * auto validIndex = indices(4, 2, 0, 1);
259  * auto invalidIndex = indices(4, 3, 2, 1); // invalid index is returned!
260  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
261  * (in the example, note that the last line has two indices out of range and
262  * the return value will not be valid!).
263  */
264  template <typename... OTHERINDICES>
265  LinIndex_t operator() (Index_t first, OTHERINDICES... others) const
266  { return first * minorTensor().size() + minorTensor()(others...); }
267 
268 
269  /**
270  * @brief Returns the linear index corresponding to the tensor indices
271  * @tparam ITER type of iterator to dimension sizes
272  * @param indexIter iterator pointing to the first dimension size
273  * @return the offset of the specified element with respect to the first one
274  * @see at(), has()
275  *
276  * No check is performed on the validity of the indices (that is, whether
277  * they fall within the dimension range).
278  *
279  * Use it as:
280  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
281  * TensorIndices<4> indices(6, 3, 2, 4);
282  * std::array<int, 4> ix { 4, 2, 0, 1 };
283  * auto validIndex = indices(ix.begin());
284  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
285  * The behaviour is the same as in
286  * `operator()(Index_t first, OTHERINDICES... others)`.
287  */
288  template <typename ITER>
289  std::enable_if_t
290  <std::is_convertible<decltype(*(ITER())), DimSize_t>::value, LinIndex_t>
291  operator() (ITER indexIter) const
292  {
293  auto const baseSize = (*indexIter) * minorTensor().size();
294  return baseSize + minorTensor()(++indexIter);
295  }
296 
297 
298  /**
299  * @brief Returns the linear index corresponding to the tensor indices
300  * @tparam OTHERINDICES types of the other index values
301  * @param first the index of the first dimension
302  * @param others the indices of the other dimensions
303  * @throw std::out_of_range if any of the indices is not valid
304  * @return the offset of the specified element with respect to the first one
305  * @see operator()(), has()
306  *
307  * If any of the index values is not in the valid index range, an exception
308  * is thrown.
309  *
310  * Use it as:
311  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
312  * TensorIndices<4> indices(6, 3, 2, 4);
313  * auto validIndex = indices.at(4, 2, 0, 1);
314  * auto invalidIndex = indices.at(4, 3, 2, 1); // throws std::out_of_range
315  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
316  * (in the example, note that the last line has two indices out of range and
317  * an exception will be thrown).
318  *
319  */
320  template <typename... OTHERINDICES>
321  LinIndex_t at(Index_t first, OTHERINDICES... others) const
322  {
323  return Base_t::checkOuterIndex(first) * minorTensor().size()
324  + minorTensor().at(others...);
325  }
326 
327  /**
328  * @brief Returns the linear index corresponding to the tensor indices
329  * @tparam ITER type of iterator to dimension sizes
330  * @param indexIter iterator pointing to the first dimension size
331  * @throw std::out_of_range if any of the indices is not valid
332  * @return the offset of the specified element with respect to the first one
333  * @see operator()(), has()
334  *
335  * If any of the index values is not in the valid index range, an exception
336  * is thrown.
337  *
338  * Use it as:
339  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
340  * TensorIndices<4> indices(6, 3, 2, 4);
341  * std::array<int, 4> ix { 4, 2, 0, 1 };
342  * auto validIndex = indices.at(ix.begin());
343  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
344  * The behaviour is the same as in
345  * `at()(Index_t first, OTHERINDICES... others)`.
346  *
347  */
348  template <typename ITER>
349  std::enable_if_t
350  <std::is_convertible<decltype(*(ITER())), DimSize_t>::value, LinIndex_t>
351  at(ITER indexIter) const
352  {
353  auto const baseSize
354  = Base_t::checkOuterIndex(*indexIter) * minorTensor().size();
355  return baseSize + minorTensor()(++indexIter);
356  }
357 
358 
359  /**
360  * @brief Returns whether the specified set of indices is valid
361  * @tparam OTHERINDICES types of the other index values
362  * @param first the index of the first dimension
363  * @param others the indices of the other dimensions
364  * @return whether the specified set of indices is valid
365  * @see operator(), at()
366  *
367  * If any of the index values is not in the valid index range, an exception
368  * is thrown.
369  *
370  * Use it as:
371  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
372  * TensorIndices<4> indices(6, 3, 2, 4);
373  * if (indices.has(4, 2, 0, 1)) {
374  * // ...
375  * }
376  * if (indices.has(4, 3, 2, 1)) {
377  * // ... (won't be executed)
378  * }
379  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
380  * (in the example, note that the last line has two indices out of range and
381  * an exception will be thrown).
382  */
383  template <typename... OTHERINDICES>
384  bool has(Index_t first, OTHERINDICES... others) const
385  { return Base_t::has(first) && minorTensor().has(others...); }
386 
387  /**
388  * @brief Returns whether the specified set of indices is valid
389  * @tparam ITER type of iterator to dimension sizes
390  * @param indexIter iterator pointing to the first dimension size
391  * @return whether the specified set of indices is valid
392  * @see operator(), at()
393  *
394  * If any of the index values is not in the valid index range, an exception
395  * is thrown.
396  *
397  * Use it as:
398  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
399  * TensorIndices<4> indices(6, 3, 2, 4);
400  * std::array<int, 4> ix { 4, 2, 0, 1 };
401  * if (indices.has(ix.begin())) {
402  * // ...
403  * }
404  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
405  * The behaviour is the same as in
406  * `has()(Index_t first, OTHERINDICES... others)`.
407 
408  */
409  template <typename ITER>
410  std::enable_if_t
411  <std::is_convertible<decltype(*(ITER())), DimSize_t>::value, bool>
412  has(ITER indexIter) const
413  { return Base_t::has(*indexIter)? minorTensor().has(++indexIter): false; }
414 
415 
416  /**
417  * @brief Returns the size of the specified dimension
418  * @tparam DIM the dimension (0 is the first one)
419  * @return the size of the specified dimension
420  *
421  * Code won't compile for DIM larger than the tensor rank.
422  */
423  template <unsigned int DIM>
424  DimSize_t dim() const
426 
427 
428  /**
429  * @brief Returns whether a index is valid within a specified dimension
430  * @tparam DIM the dimension (0 is the first one)
431  * @param index the value of the index to be tested
432  * @return whether a index is valid within a specified dimension
433  *
434  * Use it as:
435  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
436  * TensorIndices<4> indices(6, 3, 2, 4);
437  * if (indices.hasIndex<0>(2)) { // dimension #0 has 6 indices, [ 0 ; 5 ]
438  * // ... (will be executed)
439  * }
440  * if (indices.hasIndex<0>(6)) {
441  * // ... (will not be executed)
442  * }
443  * if (indices.hasIndex<2>(0)) { // dimension #2 has 2 indices, { 0 , 1 }
444  * // ... (will be executed)
445  * }
446  * if (indices.hasIndex<3>(6)) {// dimension #3 has 4 indices, [ 0 ; 3 ]
447  * // ... (will not be executed)
448  * }
449  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
450  *
451  */
452  template <unsigned int DIM>
453  bool hasIndex(Index_t index) const
454  { return (index >= 0U) && ((DimSize_t) index < dim<DIM>()); }
455 
456 
457  /**
458  * @brief Returns the size of the minor tensor
459  * @tparam DIM the index of the outer dimension of the minor tensor
460  * @return the size of the specified tensor
461  *
462  * The total size of the tensor obtained after stripping the DIM most outer
463  * dimensions if returned. Therefore, `size<0>()` is the size of the full
464  * tensor, while `size<1>()` is the size of the tensor obtained by stripping
465  * the first dimension (that is, the tensor returned by `minor()`), and so
466  * on.
467  *
468  * Code won't compile for DIM larger than the tensor rank.
469  */
470  template <unsigned int DIM = 0>
471  DimSize_t size() const
472  {
473  return (DIM == 0)? totalSize():
475  }
476 
477  /// Returns whether the specified linear index is valid in this tensor
478  bool hasLinIndex(LinIndex_t linIndex) const
479  { return (linIndex >= 0U) && ((DimSize_t) linIndex < size()); }
480 
481 
482  /// Returns the tensor of rank `Rank-1` from stripping the first dimension
483  /// Note that the minorTensor variable was previously named "minor".
484  /// However, minor is also defined in sys/types.h to mean something completely different.
485  MinorTensor_t const& minorTensor() const { return m; }
486 
487  /// Returns whether all sizes of the tensor t are the same as this one
488  bool operator== (TensorIndices<RANK> const& t) const
489  { return Base_t::operator==(t) && (minorTensor() == t.minorTensor()); }
490 
491  /// Returns whether any size of the tensor t is different from this one
492  bool operator!= (TensorIndices<RANK> const& t) const
493  { return Base_t::operator!=(t) || (minorTensor() != t.minorTensor()); }
494 
495 
496 
497  protected:
498  // need to be friend of the dimension extractor
499  template <unsigned int R, unsigned int D>
501 
502  MinorTensor_t m; ///< the rest of the tensor indices
503  DimSize_t totSize; ///< size of this tensor
504 
505  /// Returns the total size of this tensor (the same as `size()`)
506  DimSize_t totalSize() const { return totSize; }
507 
508  }; // class TensorIndices<>
509 
510 
511 
512  /// Comparison operator with tensors of different rank
513  template <
514  unsigned int RANK1, unsigned int RANK2,
515  typename = std::enable_if_t<(RANK1 != RANK2), bool>
516  >
518  { return false; }
519 
520  /// Comparison operator with tensors of different rank
521  template <
522  unsigned int RANK1, unsigned int RANK2,
523  typename = std::enable_if_t<(RANK1 != RANK2), bool>
524  >
526  { return true; }
527 
528 
529  /**
530  * @brief Instantiates a TensorIndices class with the specified dimensions
531  * @tparam DIMS types for each of the arguments
532  * @param dims size of each of the dimensions
533  * @return a TensorIndices object with properly initialised dimensions
534  *
535  * The rank of the tensor is determined by the number of arguments; example:
536  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
537  * auto indices = util::makeTensorIndices(3, 4);
538  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
539  * will initialise a `TensorIndices<2>` (that's matrix indices), for a 3 x 4
540  * (3 rows, 4 columns) disposition.
541  */
542  template <typename... DIMS>
543  auto makeTensorIndices(DIMS... dims)
544  {
545  return TensorIndices<sizeof...(DIMS)>
547  }
548 
549 
550  /// Type for indexing a 2D-tensor (matrix)
552 
553 
554 } // namespace util
555 
556 
557 //------------------------------------------------------------------------------
558 //--- details implementation
559 //---
560 namespace util {
561  namespace details {
562 
563  /**
564  * @tparam RANK rank of the TensorIndices to be queried
565  * @tparam DIM the dimension to ask about (0 is the most outer one)
566  *
567  * Helper to recourse tensor dimensions with C++ metaprogramming.
568  * Currently supported:
569  *
570  * * `dim(t)`: if `DIM` is 0, the request is for the outer dimension of `t`,
571  * which is immediately returned; otherwise, another extractor is queried
572  * on the `minor()` of `t`, decreasing `DIM` by 1
573  *
574  * * `size(t)`: if `DIM` is 0, the request is for the outer dimension of `t`,
575  * which is immediately returned; otherwise, another extractor is queried
576  * on the `minor()` of `t`, decreasing `DIM` by 1
577  *
578  */
579  template <unsigned int RANK, unsigned int DIM>
580  struct ExtractTensorDimension {
581  static_assert(RANK > DIM, "Invalid dimension requested");
585 
589 
590  }; // ExtractTensorDimension<>()
591 
592  template <unsigned int RANK>
593  struct ExtractTensorDimension<RANK, 0U> {
594  static_assert(RANK > 0, "Invalid rank 0 for TensorIndices");
597  { return t.dim0(); }
598 
601  { return t.size(); }
602 
603  }; // ExtractTensorDimension<RANK, 0>()
604 
605  } // namespace details
606 } // namespace util
607 
608 
609 
610 #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:97
Base_t::LinIndex_t LinIndex_t
Type of the linear index.
Namespace for general, non-LArSoft-specific utilities.
std::ptrdiff_t Index_t
Type of a single index in the tensor.
Definition: TensorIndices.h:32
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:29
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:82
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.
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
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:46
TensorIndicesBasicTypes::LinIndex_t LinIndex_t
Definition: TensorIndices.h:70
const double a
std::size_t DimSize_t
Type of size of a dimension in the tensor.
Definition: TensorIndices.h:35
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:75
TensorIndicesBasicTypes::Index_t Index_t
Definition: TensorIndices.h:66
MinorTensor_t m
the rest of the tensor indices
TensorIndicesBasicTypes::DimSize_t DimSize_t
Definition: TensorIndices.h:68
static constexpr unsigned int rank()
Rank of this tensor.
static constexpr unsigned int rank()
Definition: TensorIndices.h:72
DimSize_t size() const
Returns the size of the minor tensor.
static bool * b
Definition: config.cpp:1043
auto makeTensorIndices(DIMS...dims)
Instantiates a TensorIndices class with the specified dimensions.
MinorTensor_t const & minorTensor() const
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:38
std::string to_string(ModuleType const mt)
Definition: ModuleType.h:34
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:92
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.