File indexing completed on 2026-05-08 07:59:31
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Utilities/ArrayHelpers.hpp"
0013 #include "Acts/Utilities/MathHelpers.hpp"
0014
0015 #include <bitset>
0016 #include <cassert>
0017 #include <optional>
0018
0019 #include "Eigen/Dense"
0020
0021 namespace Acts {
0022
0023
0024
0025
0026
0027
0028
0029
0030 template <typename MatrixType>
0031 MatrixType bitsetToMatrix(const std::bitset<MatrixType::RowsAtCompileTime *
0032 MatrixType::ColsAtCompileTime>
0033 bs) {
0034 constexpr int rows = MatrixType::RowsAtCompileTime;
0035 constexpr int cols = MatrixType::ColsAtCompileTime;
0036
0037 static_assert(rows != -1 && cols != -1,
0038 "bitsetToMatrix does not support dynamic matrices");
0039
0040 MatrixType m;
0041 auto* p = m.data();
0042 for (std::size_t i = 0; i < rows * cols; i++) {
0043 p[i] = bs[rows * cols - 1 - i];
0044 }
0045 return m;
0046 }
0047
0048
0049
0050
0051
0052
0053
0054 template <typename Derived>
0055 auto matrixToBitset(const Eigen::PlainObjectBase<Derived>& m) {
0056 using MatrixType = Eigen::PlainObjectBase<Derived>;
0057 constexpr std::size_t rows = MatrixType::RowsAtCompileTime;
0058 constexpr std::size_t cols = MatrixType::ColsAtCompileTime;
0059
0060 std::bitset<rows * cols> res;
0061
0062 auto* p = m.data();
0063 for (std::size_t i = 0; i < rows * cols; i++) {
0064 res[rows * cols - 1 - i] = static_cast<bool>(p[i]);
0065 }
0066
0067 return res;
0068 }
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080 template <typename A, typename B>
0081 inline Matrix<A::RowsAtCompileTime, B::ColsAtCompileTime> blockedMult(
0082 const A& a, const B& b) {
0083
0084
0085 constexpr int M = A::RowsAtCompileTime;
0086 constexpr int N = A::ColsAtCompileTime;
0087 constexpr int P = B::ColsAtCompileTime;
0088
0089
0090
0091 static_assert(N == B::RowsAtCompileTime);
0092
0093 if constexpr (M <= 4 && N <= 4 && P <= 4) {
0094
0095
0096 return a * b;
0097 } else {
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130 constexpr int M1 = M / 2;
0131 constexpr int M2 = (M + 1) / 2;
0132 constexpr int N1 = N / 2;
0133 constexpr int N2 = (N + 1) / 2;
0134 constexpr int P1 = P / 2;
0135 constexpr int P2 = (P + 1) / 2;
0136
0137
0138
0139 Matrix<M, P> r;
0140
0141
0142 r.template topLeftCorner<M1, P1>().noalias() =
0143 a.template topLeftCorner<M1, N1>() *
0144 b.template topLeftCorner<N1, P1>() +
0145 a.template topRightCorner<M1, N2>() *
0146 b.template bottomLeftCorner<N2, P1>();
0147
0148
0149 r.template topRightCorner<M1, P2>().noalias() =
0150 a.template topLeftCorner<M1, N1>() *
0151 b.template topRightCorner<N1, P2>() +
0152 a.template topRightCorner<M1, N2>() *
0153 b.template bottomRightCorner<N2, P2>();
0154
0155
0156 r.template bottomLeftCorner<M2, P1>().noalias() =
0157 a.template bottomLeftCorner<M2, N1>() *
0158 b.template topLeftCorner<N1, P1>() +
0159 a.template bottomRightCorner<M2, N2>() *
0160 b.template bottomLeftCorner<N2, P1>();
0161
0162
0163 r.template bottomRightCorner<M2, P2>().noalias() =
0164 a.template bottomLeftCorner<M2, N1>() *
0165 b.template topRightCorner<N1, P2>() +
0166 a.template bottomRightCorner<M2, N2>() *
0167 b.template bottomRightCorner<N2, P2>();
0168
0169 return r;
0170 }
0171 }
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192 template <typename MatrixType, typename ResultType = MatrixType>
0193 std::optional<ResultType> safeInverse(const MatrixType& m) noexcept {
0194 constexpr int rows = MatrixType::RowsAtCompileTime;
0195 constexpr int cols = MatrixType::ColsAtCompileTime;
0196
0197 static_assert(rows == cols);
0198
0199 ResultType result;
0200 bool invertible = false;
0201
0202 if constexpr (rows > 4 || rows == -1) {
0203 Eigen::FullPivLU<MatrixType> mFullPivLU(m);
0204 if (mFullPivLU.isInvertible()) {
0205 invertible = true;
0206 result = mFullPivLU.inverse();
0207 }
0208 } else {
0209 m.computeInverseWithCheck(result, invertible);
0210 }
0211
0212 if (invertible) {
0213 return result;
0214 }
0215
0216 return std::nullopt;
0217 }
0218
0219
0220
0221
0222 template <typename T>
0223 struct ExpSafeLimit {};
0224
0225 template <>
0226 struct ExpSafeLimit<double> {
0227
0228 constexpr static double value = 500.0;
0229 };
0230
0231 template <>
0232 struct ExpSafeLimit<float> {
0233
0234 constexpr static float value = 50.0;
0235 };
0236
0237
0238
0239
0240
0241
0242
0243 template <typename T>
0244 constexpr T safeExp(T val) noexcept {
0245 constexpr T maxExponent = ExpSafeLimit<T>::value;
0246 constexpr T minExponent = -maxExponent;
0247 if (val < minExponent) {
0248 return 0.0;
0249 }
0250
0251 if (val > maxExponent) {
0252 return std::numeric_limits<T>::infinity();
0253 }
0254
0255 return std::exp(val);
0256 }
0257
0258
0259
0260
0261
0262
0263 template <std::size_t N>
0264 constexpr std::size_t vecIdxFromSymMat(const std::size_t i, const std::size_t k)
0265 requires(N > 0)
0266 {
0267 assert(i < N);
0268 assert(k < N);
0269 if (k > i) {
0270 return vecIdxFromSymMat<N>(k, i);
0271 }
0272 return sumUpToN(i) + k;
0273 }
0274
0275
0276
0277
0278
0279
0280 template <std::size_t N>
0281 constexpr std::array<std::size_t, 2> symMatIndices(const std::size_t k)
0282 requires(N > 1)
0283 {
0284 assert(k < sumUpToN(N));
0285 constexpr std::size_t bound = sumUpToN(N - 1);
0286 if (k >= bound) {
0287 return std::array<std::size_t, 2>{N - 1, k - bound};
0288 }
0289 if constexpr (N > 2) {
0290 return symMatIndices<N - 1>(k);
0291 }
0292 return filledArray<std::size_t, 2>(0);
0293 }
0294
0295 }