File indexing completed on 2026-05-29 07:32:49
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Definitions/TrackParametrization.hpp"
0013 #include "Acts/EventData/Types.hpp"
0014 #include "Acts/Utilities/AlgebraHelpers.hpp"
0015 #include "Acts/Utilities/Enumerate.hpp"
0016
0017 #include <algorithm>
0018 #include <cstddef>
0019 #include <ranges>
0020
0021 #include <boost/container/static_vector.hpp>
0022
0023 namespace Acts {
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036 template <std::ranges::sized_range index_range_t>
0037 inline static bool checkSubspaceIndices(const index_range_t& indexRange,
0038 std::size_t fullSize,
0039 std::size_t subspaceSize) {
0040 if (subspaceSize > fullSize) {
0041 return false;
0042 }
0043 if (static_cast<std::size_t>(indexRange.size()) != subspaceSize) {
0044 return false;
0045 }
0046 for (auto it = indexRange.begin(); it != indexRange.end();) {
0047 auto index = *it;
0048 if (index >= fullSize) {
0049 return false;
0050 }
0051 ++it;
0052 if (const auto tail = std::ranges::subrange(it, indexRange.end());
0053 std::ranges::find(tail, index) != tail.end()) {
0054 return false;
0055 }
0056 }
0057 return true;
0058 }
0059
0060
0061
0062
0063
0064
0065
0066
0067 template <std::size_t FullSize>
0068 inline static SerializedSubspaceIndices serializeSubspaceIndices(
0069 const SubspaceIndices<FullSize>& indices)
0070 requires(FullSize <= 8)
0071 {
0072 SerializedSubspaceIndices result = 0;
0073 for (std::size_t i = 0; i < FullSize; ++i) {
0074 result |= static_cast<SerializedSubspaceIndices>(indices[i] & 0xFF)
0075 << (i * 8);
0076 }
0077 return result;
0078 }
0079
0080
0081
0082
0083
0084
0085
0086
0087 template <std::size_t FullSize>
0088 inline static SubspaceIndices<FullSize> deserializeSubspaceIndices(
0089 SerializedSubspaceIndices serialized)
0090 requires(FullSize <= 8)
0091 {
0092 SubspaceIndices<FullSize> result;
0093 for (std::size_t i = 0; i < FullSize; ++i) {
0094 result[i] = static_cast<std::uint8_t>((serialized >> (i * 8)) & 0xFF);
0095 }
0096 return result;
0097 }
0098
0099 namespace detail {
0100
0101
0102
0103
0104
0105
0106 template <typename Derived, std::size_t FullSize>
0107 class SubspaceHelperBase {
0108 public:
0109 static constexpr std::size_t kFullSize = FullSize;
0110
0111 using FullSquareMatrix = SquareMatrix<kFullSize>;
0112
0113 using size_type = std::size_t;
0114
0115 bool empty() const { return self().empty(); }
0116 std::size_t size() const { return self().size(); }
0117
0118 auto operator[](std::size_t i) const { return self()[i]; }
0119
0120 auto begin() const { return self().begin(); }
0121 auto end() const { return self().end(); }
0122
0123 bool contains(std::uint8_t index) const {
0124 const auto r = std::ranges::subrange(begin(), end());
0125 return std::ranges::find(r, index) != r.end();
0126 }
0127 std::size_t indexOf(std::uint8_t index) const {
0128 const auto r = std::ranges::subrange(begin(), end());
0129 const auto it = std::ranges::find(r, index);
0130 return it != r.end()
0131 ? static_cast<std::size_t>(std::ranges::distance(r.begin(), it))
0132 : kFullSize;
0133 }
0134
0135 template <typename EigenDerived>
0136 Vector<kFullSize> expandVector(
0137 const Eigen::DenseBase<EigenDerived>& vector) const {
0138 Vector<kFullSize> result = Vector<kFullSize>::Zero();
0139 for (auto [i, index] : enumerate(*this)) {
0140 result(index) = vector(i);
0141 }
0142 return result;
0143 }
0144
0145 template <typename EigenDerived>
0146 FullSquareMatrix expandMatrix(
0147 const Eigen::DenseBase<EigenDerived>& matrix) const {
0148 FullSquareMatrix result = FullSquareMatrix::Zero();
0149 for (auto [i, indexI] : enumerate(*this)) {
0150 for (auto [j, indexJ] : enumerate(*this)) {
0151 result(indexI, indexJ) = matrix(i, j);
0152 }
0153 }
0154 return result;
0155 }
0156
0157 FullSquareMatrix fullProjector() const {
0158 FullSquareMatrix result = FullSquareMatrix::Zero();
0159 for (auto [i, index] : enumerate(*this)) {
0160 result(i, index) = 1;
0161 }
0162 return result;
0163 }
0164
0165 FullSquareMatrix fullExpander() const {
0166 FullSquareMatrix result = FullSquareMatrix::Zero();
0167 for (auto [i, index] : enumerate(*this)) {
0168 result(index, i) = 1;
0169 }
0170 return result;
0171 }
0172
0173 ProjectorBitset projectorBitset() const
0174 requires(kFullSize <= 8)
0175 {
0176 return matrixToBitset(fullProjector()).to_ullong();
0177 }
0178
0179 private:
0180 const Derived& self() const { return static_cast<const Derived&>(*this); }
0181 };
0182
0183 }
0184
0185
0186
0187
0188
0189 template <std::size_t FullSize, typename index_t = std::uint8_t>
0190 class VariableSubspaceHelper
0191 : public detail::SubspaceHelperBase<
0192 VariableSubspaceHelper<FullSize, index_t>, FullSize> {
0193 public:
0194
0195 static constexpr std::size_t kFullSize = FullSize;
0196
0197
0198 using IndexType = index_t;
0199
0200 using Container = boost::container::static_vector<IndexType, FullSize>;
0201
0202
0203
0204
0205
0206 template <std::ranges::sized_range other_index_range_t>
0207 explicit VariableSubspaceHelper(const other_index_range_t& indices) {
0208 assert(checkSubspaceIndices(indices, kFullSize, indices.size()) &&
0209 "Invalid indices");
0210 m_indices.resize(indices.size());
0211 std::ranges::transform(indices, m_indices.begin(), [](auto index) {
0212 return static_cast<IndexType>(index);
0213 });
0214 }
0215
0216
0217
0218 bool empty() const { return m_indices.empty(); }
0219
0220
0221 std::size_t size() const { return m_indices.size(); }
0222
0223
0224 const Container& indices() const { return m_indices; }
0225
0226
0227
0228
0229 IndexType operator[](std::size_t i) const { return m_indices[i]; }
0230
0231
0232
0233 auto begin() const { return m_indices.begin(); }
0234
0235
0236 auto end() const { return m_indices.end(); }
0237
0238 private:
0239 Container m_indices;
0240 };
0241
0242
0243
0244
0245
0246
0247 template <std::size_t FullSize, std::size_t SubspaceSize,
0248 typename index_t = std::uint8_t>
0249 class FixedSubspaceHelper
0250 : public detail::SubspaceHelperBase<
0251 FixedSubspaceHelper<FullSize, SubspaceSize, index_t>, FullSize> {
0252 public:
0253
0254 static constexpr std::size_t kFullSize = FullSize;
0255
0256 static constexpr std::size_t kSubspaceSize = SubspaceSize;
0257 static_assert(kSubspaceSize <= kFullSize, "Invalid subspace size");
0258
0259
0260 using Projector = Matrix<kSubspaceSize, kFullSize>;
0261
0262 using Expander = Matrix<kFullSize, kSubspaceSize>;
0263
0264 using VectorD = Vector<kSubspaceSize>;
0265
0266 using SquareMatrixD = SquareMatrix<kSubspaceSize>;
0267
0268 template <std::size_t K>
0269 using ApplyLeftResult = Matrix<kSubspaceSize, kSubspaceSize>;
0270
0271 template <std::size_t N>
0272 using ApplyRightResult = Matrix<kSubspaceSize, kSubspaceSize>;
0273
0274
0275 using IndexType = index_t;
0276
0277 using Container = std::array<IndexType, kSubspaceSize>;
0278
0279
0280 using size_type = std::size_t;
0281
0282
0283
0284
0285
0286 template <std::ranges::sized_range other_index_range_t>
0287 explicit FixedSubspaceHelper(const other_index_range_t& indices) {
0288 assert(checkSubspaceIndices(indices, kFullSize, kSubspaceSize) &&
0289 "Invalid indices");
0290 std::ranges::transform(indices, m_indices.begin(), [](auto index) {
0291 return static_cast<IndexType>(index);
0292 });
0293 }
0294
0295
0296
0297 bool empty() const { return m_indices.empty(); }
0298
0299
0300 std::size_t size() const { return m_indices.size(); }
0301
0302
0303 const Container& indices() const { return m_indices; }
0304
0305
0306
0307
0308 IndexType operator[](std::uint32_t i) const { return m_indices[i]; }
0309
0310
0311
0312 auto begin() const { return m_indices.begin(); }
0313
0314
0315 auto end() const { return m_indices.end(); }
0316
0317
0318
0319 Projector projector() const {
0320 Projector result = Projector::Zero();
0321 for (auto [i, index] : enumerate(*this)) {
0322 result(i, index) = 1;
0323 }
0324 return result;
0325 }
0326
0327
0328
0329 Expander expander() const {
0330 Expander result = Expander::Zero();
0331 for (auto [i, index] : enumerate(*this)) {
0332 result(index, i) = 1;
0333 }
0334 return result;
0335 }
0336
0337
0338
0339
0340
0341
0342 template <std::size_t K, typename Derived>
0343 ApplyLeftResult<K> applyLeftOf(
0344 const Eigen::DenseBase<Derived>& matrix) const {
0345 assert(matrix.rows() == kFullSize && "Invalid matrix size");
0346 ApplyLeftResult<K> result = ApplyLeftResult<K>::Zero();
0347 for (auto [i, indexI] : enumerate(*this)) {
0348 for (std::size_t j = 0; j < K; ++j) {
0349 result(i, j) = matrix(indexI, j);
0350 }
0351 }
0352 return result;
0353 }
0354
0355
0356
0357
0358
0359
0360 template <std::size_t N, typename Derived>
0361 ApplyRightResult<N> applyRightOf(
0362 const Eigen::DenseBase<Derived>& matrix) const {
0363 assert(matrix.cols() == kSubspaceSize && "Invalid matrix size");
0364 ApplyRightResult<N> result = ApplyRightResult<N>::Zero();
0365 for (std::size_t i = 0; i < N; ++i) {
0366 for (auto [j, indexJ] : enumerate(*this)) {
0367 result(i, j) = matrix(i, indexJ);
0368 }
0369 }
0370 return result;
0371 }
0372
0373
0374
0375
0376
0377 template <typename Derived>
0378 VectorD projectVector(const Eigen::DenseBase<Derived>& fullVector) const {
0379 assert(fullVector.size() == kFullSize && "Invalid full vector size");
0380 VectorD result = VectorD::Zero();
0381 for (auto [i, index] : enumerate(*this)) {
0382 result(i) = fullVector(index);
0383 }
0384 return result;
0385 }
0386
0387
0388
0389
0390
0391 template <typename Derived>
0392 SquareMatrixD projectMatrix(
0393 const Eigen::DenseBase<Derived>& fullMatrix) const {
0394 assert(fullMatrix.rows() == kFullSize && fullMatrix.cols() == kFullSize &&
0395 "Invalid full matrix size");
0396 SquareMatrixD result = SquareMatrixD::Zero();
0397 for (auto [i, indexI] : enumerate(*this)) {
0398 for (auto [j, indexJ] : enumerate(*this)) {
0399 result(i, j) = fullMatrix(indexI, indexJ);
0400 }
0401 }
0402 return result;
0403 }
0404
0405 private:
0406 Container m_indices{};
0407 };
0408
0409
0410
0411 template <std::size_t SubspaceSize>
0412 using FixedBoundSubspaceHelper =
0413 FixedSubspaceHelper<Acts::eBoundSize, SubspaceSize, std::uint8_t>;
0414
0415
0416
0417
0418
0419 using VariableBoundSubspaceHelper =
0420 VariableSubspaceHelper<Acts::eBoundSize, std::uint8_t>;
0421
0422
0423
0424
0425
0426
0427
0428
0429
0430 template <std::size_t kFullSize, typename Derived>
0431 SubspaceIndices<kFullSize> projectorToSubspaceIndices(
0432 const Eigen::DenseBase<Derived>& projector) {
0433 auto rows = static_cast<std::size_t>(projector.rows());
0434 auto cols = static_cast<std::size_t>(projector.cols());
0435 assert(cols == kFullSize && rows <= kFullSize && "Invalid projector size");
0436 SubspaceIndices<kFullSize> result;
0437 result.fill(kFullSize);
0438 for (std::size_t i = 0; i < rows; ++i) {
0439 for (std::size_t j = 0; j < cols; ++j) {
0440 assert((projector(i, j) == 0 || projector(i, j) == 1) &&
0441 "Invalid projector value");
0442 if (projector(i, j) == 1) {
0443 result[i] = j;
0444 }
0445 }
0446 }
0447 return result;
0448 }
0449
0450 }