Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-29 07:32:49

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
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 /// @brief Check subspace indices for consistency
0026 ///
0027 /// Indices must be unique and within the full size of the subspace
0028 ///
0029 /// @tparam index_range_t the type of the container of indices
0030 ///
0031 /// @param indexRange the range of indices
0032 /// @param fullSize the full size of the subspace
0033 /// @param subspaceSize the size of the subspace
0034 ///
0035 /// @return true if the indices are consistent
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 /// Serialize subspace indices to a single 64 bit integer
0061 ///
0062 /// @tparam FullSize the full size of the subspace
0063 ///
0064 /// @param indices the subspace indices
0065 ///
0066 /// @return the serialized subspace indices
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 /// Deserialize subspace indices from a single 64 bit integer
0081 ///
0082 /// @tparam FullSize the full size of the subspace
0083 ///
0084 /// @param serialized the serialized subspace indices
0085 ///
0086 /// @return the subspace indices
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 /// Helper base class for subspace operations which provides common
0102 /// functionality for fixed and variable subspace helpers
0103 ///
0104 /// @tparam Derived the derived type
0105 /// @tparam FullSize the full size of the subspace
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 }  // namespace detail
0184 
0185 /// Helper class for variable subspace operations
0186 ///
0187 /// @tparam FullSize the full size of the subspace
0188 /// @tparam index_t the index type
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   /// Size of the full parameter space
0195   static constexpr std::size_t kFullSize = FullSize;
0196 
0197   /// Type alias for index type
0198   using IndexType = index_t;
0199   /// Type alias for container holding subspace indices
0200   using Container = boost::container::static_vector<IndexType, FullSize>;
0201 
0202   /// Construct a variable subspace helper with specified indices
0203   ///
0204   /// @tparam other_index_range_t Type of the index range
0205   /// @param indices Range of indices defining the subspace
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   /// Check if the subspace is empty
0217   /// @return True if the subspace contains no indices
0218   bool empty() const { return m_indices.empty(); }
0219   /// Get the size of the subspace
0220   /// @return Number of indices in the subspace
0221   std::size_t size() const { return m_indices.size(); }
0222   /// Get the container of subspace indices
0223   /// @return Reference to the container holding the indices
0224   const Container& indices() const { return m_indices; }
0225 
0226   /// Access subspace index at position i
0227   /// @param i Position index
0228   /// @return The subspace index at position i
0229   IndexType operator[](std::size_t i) const { return m_indices[i]; }
0230 
0231   /// Get iterator to beginning of indices
0232   /// @return Iterator to the first index
0233   auto begin() const { return m_indices.begin(); }
0234   /// Get iterator to end of indices
0235   /// @return Iterator past the last index
0236   auto end() const { return m_indices.end(); }
0237 
0238  private:
0239   Container m_indices;
0240 };
0241 
0242 /// Helper class for fixed subspace operations
0243 ///
0244 /// @tparam FullSize the full size of the subspace
0245 /// @tparam SubspaceSize the size of the subspace
0246 /// @tparam index_t the index type
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   /// Size of the full parameter space
0254   static constexpr std::size_t kFullSize = FullSize;
0255   /// Size of the subspace parameter space
0256   static constexpr std::size_t kSubspaceSize = SubspaceSize;
0257   static_assert(kSubspaceSize <= kFullSize, "Invalid subspace size");
0258 
0259   /// Type alias for projection matrix (subspace x full)
0260   using Projector = Matrix<kSubspaceSize, kFullSize>;
0261   /// Type alias for expansion matrix (full x subspace)
0262   using Expander = Matrix<kFullSize, kSubspaceSize>;
0263   /// Type alias for subspace vector
0264   using VectorD = Vector<kSubspaceSize>;
0265   /// Type alias for subspace square matrix
0266   using SquareMatrixD = SquareMatrix<kSubspaceSize>;
0267   /// Type alias for left application result matrix
0268   template <std::size_t K>
0269   using ApplyLeftResult = Matrix<kSubspaceSize, kSubspaceSize>;
0270   /// Type alias for right application result matrix
0271   template <std::size_t N>
0272   using ApplyRightResult = Matrix<kSubspaceSize, kSubspaceSize>;
0273 
0274   /// Type alias for index type used to specify subspace indices
0275   using IndexType = index_t;
0276   /// Type alias for container storing subspace indices
0277   using Container = std::array<IndexType, kSubspaceSize>;
0278 
0279   /// Type alias for size type
0280   using size_type = std::size_t;
0281 
0282   /// Construct a fixed subspace helper with specified indices
0283   ///
0284   /// @tparam other_index_range_t Type of the index range
0285   /// @param indices Range of indices defining the subspace, must match SubspaceSize
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   /// Check if the subspace is empty
0296   /// @return True if the subspace contains no indices (always false for fixed subspaces)
0297   bool empty() const { return m_indices.empty(); }
0298   /// Get the size of the subspace
0299   /// @return Number of indices in the subspace (always SubspaceSize)
0300   std::size_t size() const { return m_indices.size(); }
0301   /// Get the container of subspace indices
0302   /// @return Reference to the array holding the indices
0303   const Container& indices() const { return m_indices; }
0304 
0305   /// Access subspace index at position i
0306   /// @param i Position index
0307   /// @return The subspace index at position i
0308   IndexType operator[](std::uint32_t i) const { return m_indices[i]; }
0309 
0310   /// Get iterator to beginning of indices
0311   /// @return Iterator to the first index
0312   auto begin() const { return m_indices.begin(); }
0313   /// Get iterator to end of indices
0314   /// @return Iterator past the last index
0315   auto end() const { return m_indices.end(); }
0316 
0317   /// Create a projection matrix from full space to subspace
0318   /// @return Matrix that projects from full space to subspace dimensions
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   /// Create an expansion matrix from subspace to full space
0328   /// @return Matrix that expands from subspace to full space dimensions
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   /// Apply subspace projection on the left side of a matrix
0338   /// @tparam K Number of columns in the input matrix
0339   /// @tparam Derived Eigen matrix type
0340   /// @param matrix Input matrix with rows matching full space size
0341   /// @return Matrix with subspace rows and K columns
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   /// Apply subspace projection on the right side of a matrix
0356   /// @tparam N Number of rows in the input matrix
0357   /// @tparam Derived Eigen matrix type
0358   /// @param matrix Input matrix with columns matching subspace size
0359   /// @return Matrix with N rows and subspace columns
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   /// Project a full-space vector to subspace
0374   /// @tparam Derived Eigen vector type
0375   /// @param fullVector Input vector with full space dimensions
0376   /// @return Vector projected to subspace dimensions
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   /// Project a full-space square matrix to subspace
0388   /// @tparam Derived Eigen matrix type
0389   /// @param fullMatrix Input square matrix with full space dimensions
0390   /// @return Square matrix projected to subspace dimensions
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 /// @brief Helper type for fixed-size bound parameter subspaces
0410 /// @details Provides utilities for working with fixed-size subspaces of bound track parameters
0411 template <std::size_t SubspaceSize>
0412 using FixedBoundSubspaceHelper =
0413     FixedSubspaceHelper<Acts::eBoundSize, SubspaceSize, std::uint8_t>;
0414 
0415 /// @typedef VariableBoundSubspaceHelper
0416 /// Helper type for variable-size bound parameter subspaces.
0417 /// Provides utilities for working with variable-size subspaces of bound track
0418 /// parameters.
0419 using VariableBoundSubspaceHelper =
0420     VariableSubspaceHelper<Acts::eBoundSize, std::uint8_t>;
0421 
0422 /// Convert a projector to subspace indices
0423 ///
0424 /// @tparam kFullSize the full size of the subspace
0425 /// @tparam Derived the derived type
0426 ///
0427 /// @param projector the projector
0428 ///
0429 /// @return the subspace indices
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 }  // namespace Acts