Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Subspace.hpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file Subspace.hpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2020 CERN for the benefit of the Acts project
4 //
5 // This Source Code Form is subject to the terms of the Mozilla Public
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
7 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 
9 #pragma once
10 
12 
13 #include <array>
14 #include <cassert>
15 #include <cstddef>
16 #include <cstdint>
17 
18 namespace Acts {
19 namespace detail {
20 
58 
63 template <size_t kFullSize, size_t kSize>
65  static_assert(kFullSize <= static_cast<size_t>(UINT8_MAX),
66  "Full vector space size is larger than the supported range");
67  static_assert(1u <= kSize, "Subspace size must be at least 1");
68  static_assert(kSize <= kFullSize,
69  "Subspace can only be as large as the full space");
70 
71  template <typename source_t>
72  using SubspaceVectorFor = Eigen::Matrix<typename source_t::Scalar, kSize, 1>;
73  template <typename source_t>
74  using FullspaceVectorFor =
75  Eigen::Matrix<typename source_t::Scalar, kFullSize, 1>;
76  template <typename scalar_t>
77  using ProjectionMatrix = Eigen::Matrix<scalar_t, kSize, kFullSize>;
78  template <typename scalar_t>
79  using ExpansionMatrix = Eigen::Matrix<scalar_t, kFullSize, kSize>;
80 
81  // the functionality could also be implemented using a std::bitset where each
82  // bit corresponds to an axis in the fullspace and set bits indicate which
83  // bits make up the subspace. this would be a more compact representation but
84  // complicates the implementation since we can not easily iterate over the
85  // indices of the subspace. storing the subspace indices directly requires a
86  // bit more memory but is easier to work with. for our typical use cases with
87  // n<=8, this still takes only 64bit of memory.
88  std::array<uint8_t, kSize> m_axes;
89 
90  public:
95  template <typename index_t>
96  constexpr FixedSizeSubspace(const std::array<index_t, kSize>& indices) {
97  for (size_t i = 0u; i < kSize; ++i) {
98  assert((indices[i] < kFullSize) and
99  "Axis indices must be within the full space");
100  if (0u < i) {
101  assert((indices[i - 1u] < indices[i]) and
102  "Axis indices must be unique and ordered");
103  }
104  }
105  for (size_t i = 0; i < kSize; ++i) {
106  m_axes[i] = static_cast<uint8_t>(indices[i]);
107  }
108  }
109  // The subset can not be constructed w/o defining its axis indices.
110  FixedSizeSubspace() = delete;
111  FixedSizeSubspace(const FixedSizeSubspace&) = default;
113  FixedSizeSubspace& operator=(const FixedSizeSubspace&) = default;
115 
117  static constexpr size_t size() { return kSize; }
119  static constexpr size_t fullSize() { return kFullSize; }
120 
126  constexpr const std::array<uint8_t, kSize>& indices() const { return m_axes; }
127 
129  constexpr bool contains(size_t index) const {
130  bool isContained = false;
131  // always iterate over all elements to avoid branching and hope the compiler
132  // can optimise this for us.
133  for (auto a : m_axes) {
134  isContained = (isContained or (a == index));
135  }
136  return isContained;
137  }
138 
146  template <typename fullspace_vector_t>
147  auto projectVector(const Eigen::MatrixBase<fullspace_vector_t>& full) const
149  EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(fullspace_vector_t, kFullSize);
150 
152  for (auto i = 0u; i < kSize; ++i) {
153  sub[i] = full[m_axes[i]];
154  }
155  return sub;
156  }
157 
165  template <typename subspace_vector_t>
166  auto expandVector(const Eigen::MatrixBase<subspace_vector_t>& sub) const
168  EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(subspace_vector_t, kSize);
169 
171  full.setZero();
172  for (auto i = 0u; i < kSize; ++i) {
173  full[m_axes[i]] = sub[i];
174  }
175  return full;
176  }
177 
181  template <typename scalar_t>
182  auto projector() const -> ProjectionMatrix<scalar_t> {
184  proj.setZero();
185  for (auto i = 0u; i < kSize; ++i) {
186  proj(i, m_axes[i]) = 1;
187  }
188  return proj;
189  }
190 
194  template <typename scalar_t>
195  auto expander() const -> ExpansionMatrix<scalar_t> {
197  expn.setZero();
198  for (auto i = 0u; i < kSize; ++i) {
199  expn(m_axes[i], i) = 1;
200  }
201  return expn;
202  }
203 };
204 
206 
207 } // namespace detail
208 } // namespace Acts