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