Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 09:25:18

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 #include <boost/test/unit_test.hpp>
0010 
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Definitions/Common.hpp"
0013 #include "Acts/Definitions/TrackParametrization.hpp"
0014 #include "Acts/Utilities/AlgebraHelpers.hpp"
0015 #include "Acts/Utilities/Helpers.hpp"
0016 #include "Acts/Utilities/StringHelpers.hpp"
0017 #include "Acts/Utilities/VectorHelpers.hpp"
0018 #include "ActsTests/CommonHelpers/FloatComparisons.hpp"
0019 
0020 #include <algorithm>
0021 #include <bitset>
0022 #include <cmath>
0023 #include <cstddef>
0024 #include <limits>
0025 #include <memory>
0026 #include <numbers>
0027 #include <string>
0028 #include <tuple>
0029 #include <utility>
0030 #include <variant>
0031 #include <vector>
0032 
0033 using namespace Acts;
0034 using namespace Acts::VectorHelpers;
0035 
0036 namespace ActsTests {
0037 
0038 BOOST_AUTO_TEST_SUITE(UtilitiesSuite)
0039 
0040 BOOST_AUTO_TEST_CASE(bitset_to_matrix_to_bitset) {
0041   Eigen::Matrix<int, 4, 3> mat;
0042   mat << 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0;
0043 
0044   std::bitset<4 * 3> act = matrixToBitset(mat);
0045   std::bitset<4 * 3> exp{"101001011010"};
0046 
0047   BOOST_CHECK_EQUAL(exp, act);
0048 
0049   Eigen::Matrix<int, 4, 3> cnv;
0050   cnv = bitsetToMatrix<decltype(cnv)>(act);
0051 
0052   BOOST_CHECK_EQUAL(mat, cnv);
0053 }
0054 
0055 struct MyStruct {
0056   double phi() const { return 42; }
0057 };
0058 
0059 BOOST_AUTO_TEST_CASE(phi_helper_test) {
0060   Vector3 v(0, 1, 0);
0061   CHECK_CLOSE_ABS(phi(v), std::numbers::pi / 2., 1e-9);
0062 
0063   MyStruct s;
0064   BOOST_CHECK_EQUAL(phi(s), 42u);
0065 }
0066 
0067 BOOST_AUTO_TEST_CASE(perp_helper_test) {
0068   Vector3 v(1, 2, 3);
0069   CHECK_CLOSE_ABS(perp(v), std::sqrt(1 + 2 * 2), 1e-9);
0070 }
0071 
0072 BOOST_AUTO_TEST_CASE(theta_eta_test_helper) {
0073   Vector3 v(1, 2, 3);
0074   CHECK_CLOSE_ABS(theta(v), 0.640522, 1e-5);
0075   CHECK_CLOSE_ABS(eta(v), 1.10359, 1e-5);
0076 }
0077 
0078 BOOST_AUTO_TEST_CASE(cross_test_helper) {
0079   {
0080     Vector3 v(1, 2, 3);
0081     SquareMatrix3 mat;
0082     mat << 1, 2, 3, 4, 5, 6, 7, 8, 9;
0083 
0084     SquareMatrix3 act = cross(mat, v);
0085     SquareMatrix3 exp;
0086     exp << -2, -1, 0, 4, 2, 0, -2, -1, 0;
0087 
0088     CHECK_CLOSE_ABS(act, exp, 1e-9);
0089   }
0090 }
0091 
0092 BOOST_AUTO_TEST_CASE(toString_test_helper) {
0093   SquareMatrix3 mat;
0094   mat << 1, 2, 3, 4, 5, 6, 7, 8, 9;
0095   std::string out;
0096   out = toString(mat);
0097   BOOST_CHECK(!out.empty());
0098 
0099   Translation3 trl{Vector3{1, 2, 3}};
0100   out = toString(trl);
0101   BOOST_CHECK(!out.empty());
0102 
0103   Transform3 trf;
0104   trf = trl;
0105   out = toString(trf);
0106   BOOST_CHECK(!out.empty());
0107 }
0108 
0109 BOOST_AUTO_TEST_CASE(shared_vector_helper_test) {
0110   {
0111     std::vector<std::shared_ptr<int>> vec;
0112     vec = {std::make_shared<int>(5), std::make_shared<int>(9),
0113            std::make_shared<int>(26), std::make_shared<int>(18473)};
0114 
0115     std::vector<int*> unpacked = unpackSmartPointers(vec);
0116 
0117     std::vector<int*> exp = {
0118         vec[0].get(),
0119         vec[1].get(),
0120         vec[2].get(),
0121         vec[3].get(),
0122     };
0123 
0124     BOOST_CHECK_EQUAL_COLLECTIONS(unpacked.begin(), unpacked.end(), exp.begin(),
0125                                   exp.end());
0126   }
0127 
0128   // same for const
0129   {
0130     std::vector<std::shared_ptr<const int>> vec;
0131     vec = {std::make_shared<const int>(5), std::make_shared<const int>(9),
0132            std::make_shared<const int>(26), std::make_shared<const int>(18473)};
0133 
0134     std::vector<const int*> unpacked = unpackSmartPointers(vec);
0135 
0136     std::vector<const int*> exp = {
0137         vec[0].get(),
0138         vec[1].get(),
0139         vec[2].get(),
0140         vec[3].get(),
0141     };
0142 
0143     BOOST_CHECK_EQUAL_COLLECTIONS(unpacked.begin(), unpacked.end(), exp.begin(),
0144                                   exp.end());
0145   }
0146 }
0147 
0148 BOOST_AUTO_TEST_CASE(VectorHelpersPosition) {
0149   Vector4 pos4 = Vector4::Constant(-1);
0150   pos4[ePos0] = 1;
0151   pos4[ePos1] = 2;
0152   pos4[ePos2] = 3;
0153   BOOST_CHECK_EQUAL(position(pos4), Vector3(1, 2, 3));
0154 
0155   FreeVector params = FreeVector::Constant(-1);
0156   params[eFreePos0] = 1;
0157   params[eFreePos1] = 2;
0158   params[eFreePos2] = 3;
0159   BOOST_CHECK_EQUAL(position(params), Vector3(1, 2, 3));
0160 }
0161 
0162 template <std::size_t I>
0163 struct functor {
0164   static constexpr std::size_t invoke() { return I * I * I; }
0165 };
0166 
0167 BOOST_AUTO_TEST_CASE(test_matrix_dimension_switch) {
0168   constexpr std::size_t imax = 20;
0169   for (std::size_t i = 0; i < imax; i++) {
0170     std::size_t val = template_switch<functor, 0, imax>(i);
0171     BOOST_CHECK_EQUAL(val, i * i * i);
0172   }
0173 }
0174 
0175 using MatrixProductTypes =
0176     std::tuple<std::pair<SquareMatrix3, SquareMatrix3>,
0177                std::pair<SquareMatrix4, SquareMatrix4>,
0178                std::pair<ActsMatrix<8, 8>, ActsMatrix<8, 8>>,
0179                std::pair<ActsMatrix<8, 7>, ActsMatrix<7, 4>>>;
0180 
0181 BOOST_AUTO_TEST_CASE_TEMPLATE(BlockedMatrixMultiplication, Matrices,
0182                               MatrixProductTypes) {
0183   using A = typename Matrices::first_type;
0184   using B = typename Matrices::second_type;
0185   using C = ActsMatrix<A::RowsAtCompileTime, B::ColsAtCompileTime>;
0186 
0187   for (std::size_t i = 0; i < 100; ++i) {
0188     A a = A::Random();
0189     B b = B::Random();
0190 
0191     C ref = a * b;
0192     C res = blockedMult(a, b);
0193 
0194     BOOST_CHECK(ref.isApprox(res));
0195     BOOST_CHECK(res.isApprox(ref));
0196   }
0197 }
0198 
0199 BOOST_AUTO_TEST_CASE(range_medium) {
0200   std::vector<double> ordered = {-3., -2., -1., 0., 1., 2., 3.};
0201   auto [range0, medium0] = Acts::range_medium(ordered);
0202 
0203   CHECK_CLOSE_ABS(range0, 6., std::numeric_limits<double>::epsilon());
0204   CHECK_CLOSE_ABS(medium0, 0., std::numeric_limits<double>::epsilon());
0205 
0206   std::vector<double> unordered = {-2., -1., 0., 1., 2., 3., -3.};
0207   auto [range1, medium1] = Acts::range_medium(unordered);
0208 
0209   CHECK_CLOSE_ABS(range1, 6., std::numeric_limits<double>::epsilon());
0210   CHECK_CLOSE_ABS(medium1, 0., std::numeric_limits<double>::epsilon());
0211 }
0212 
0213 BOOST_AUTO_TEST_CASE(safeInverse) {
0214   {
0215     auto m = Eigen::Matrix3d::Zero().eval();
0216     BOOST_CHECK(!Acts::safeInverse(m));
0217   }
0218 
0219   {
0220     auto m = Eigen::Matrix3d::Identity().eval();
0221     BOOST_CHECK(Acts::safeInverse(m));
0222   }
0223 }
0224 
0225 BOOST_AUTO_TEST_CASE(incidentAnglesTest) {
0226   RotationMatrix3 ref = RotationMatrix3::Identity();
0227 
0228   // Right angle in both planes
0229   for (std::size_t i = 0; i < 3; i++) {
0230     Vector3 dir = Vector3::Zero();
0231     dir[i] = 1;
0232     std::pair<double, double> angles = incidentAngles(dir, ref);
0233     double expect = (i < 2) ? 0 : std::numbers::pi / 2.;
0234     CHECK_CLOSE_ABS(angles.first, expect,
0235                     std::numeric_limits<double>::epsilon());
0236     CHECK_CLOSE_ABS(angles.second, expect,
0237                     std::numeric_limits<double>::epsilon());
0238   }
0239 
0240   // 45 degree on both axes
0241   {
0242     Vector3 dir = Vector3({1, 1, 1}).normalized();
0243     auto [a0, a1] = incidentAngles(dir, ref);
0244     CHECK_CLOSE_ABS(a0, std::numbers::pi / 4.,
0245                     std::numeric_limits<double>::epsilon());
0246     CHECK_CLOSE_ABS(a1, std::numbers::pi / 4.,
0247                     std::numeric_limits<double>::epsilon());
0248   }
0249 
0250   // 45 degree on first axis
0251   {
0252     Vector3 dir = Vector3({1, 0, 1}).normalized();
0253     auto [a0, a1] = incidentAngles(dir, ref);
0254     CHECK_CLOSE_ABS(a0, std::numbers::pi / 4.,
0255                     std::numeric_limits<double>::epsilon());
0256     CHECK_CLOSE_ABS(a1, std::numbers::pi / 2.,
0257                     std::numeric_limits<double>::epsilon());
0258   }
0259 
0260   // 45 degree on second axis
0261   {
0262     Vector3 dir = Vector3({0, 1, 1}).normalized();
0263     auto [a0, a1] = incidentAngles(dir, ref);
0264     CHECK_CLOSE_ABS(a0, std::numbers::pi / 2.,
0265                     std::numeric_limits<double>::epsilon());
0266     CHECK_CLOSE_ABS(a1, std::numbers::pi / 4.,
0267                     std::numeric_limits<double>::epsilon());
0268   }
0269 
0270   // Reverse crossing
0271   {
0272     Vector3 dir = {0, 0, -1};
0273     auto [a0, a1] = incidentAngles(dir, ref);
0274     CHECK_CLOSE_ABS(a0, -std::numbers::pi / 2.,
0275                     std::numeric_limits<double>::epsilon());
0276     CHECK_CLOSE_ABS(a1, -std::numbers::pi / 2.,
0277                     std::numeric_limits<double>::epsilon());
0278   }
0279 
0280   // 45 degree but different quadrant
0281   {
0282     Vector3 dir = {-1, -1, 1};
0283     auto [a0, a1] = incidentAngles(dir, ref);
0284     CHECK_CLOSE_ABS(a0, 3 * std::numbers::pi / 4.,
0285                     std::numeric_limits<double>::epsilon());
0286     CHECK_CLOSE_ABS(a1, 3 * std::numbers::pi / 4.,
0287                     std::numeric_limits<double>::epsilon());
0288   }
0289 
0290   // 45 degree but different quadrant & other side
0291   {
0292     Vector3 dir = {-1, -1, -1};
0293     auto [a0, a1] = incidentAngles(dir, ref);
0294     CHECK_CLOSE_ABS(a0, -3 * std::numbers::pi / 4.,
0295                     std::numeric_limits<double>::epsilon());
0296     CHECK_CLOSE_ABS(a1, -3 * std::numbers::pi / 4.,
0297                     std::numeric_limits<double>::epsilon());
0298   }
0299 
0300   // Rotate the reference frame instead
0301   {
0302     double s45 = std::sin(std::numbers::pi / 4.);
0303     double c45 = std::cos(std::numbers::pi / 4.);
0304     RotationMatrix3 ref45;
0305     ref45 << c45, 0, s45, 0, 1, 0, -s45, 0, c45;
0306     Vector3 dir = {0, 0, 1};
0307     auto [a0, a1] = incidentAngles(dir, ref45);
0308     CHECK_CLOSE_ABS(a0, std::numbers::pi / 4.,
0309                     std::numeric_limits<double>::epsilon());
0310     CHECK_CLOSE_ABS(a1, std::numbers::pi / 2.,
0311                     std::numeric_limits<double>::epsilon());
0312   }
0313 }
0314 
0315 BOOST_AUTO_TEST_CASE(Overloaded) {
0316   struct A {};
0317   std::variant<int, double, A> var;
0318 
0319   var = 42;
0320 
0321   std::visit(overloaded{
0322                  [](int) { BOOST_CHECK(true); },
0323                  [](double) { BOOST_CHECK(false); },
0324                  [](A) { BOOST_CHECK(false); },
0325              },
0326              var);
0327 }
0328 
0329 BOOST_AUTO_TEST_SUITE_END()
0330 
0331 }  // namespace ActsTests