Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-20 07:36:12

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/data/test_case.hpp>
0010 #include <boost/test/unit_test.hpp>
0011 
0012 #include "Acts/Utilities/ArrayHelpers.hpp"
0013 #include "Acts/Utilities/MathHelpers.hpp"
0014 #include "ActsTests/CommonHelpers/FloatComparisons.hpp"
0015 
0016 #include <cmath>
0017 
0018 namespace bdata = boost::unit_test::data;
0019 
0020 const auto expDist = bdata::random(
0021     (bdata::engine = std::mt19937{}, bdata::seed = 0,
0022      bdata::distribution = std::uniform_real_distribution<double>(-4, 4)));
0023 
0024 namespace ActsTetsts {
0025 
0026 BOOST_AUTO_TEST_SUITE(UtilitiesSuite)
0027 
0028 BOOST_DATA_TEST_CASE(fastHypot, expDist ^ expDist ^ bdata::xrange(100), xExp,
0029                      yExp, i) {
0030   static_cast<void>(i);
0031 
0032   const double x = std::pow(10, xExp);
0033   const double y = std::pow(10, yExp);
0034 
0035   const float fastFloat =
0036       Acts::fastHypot(static_cast<float>(x), static_cast<float>(y));
0037   const double fastDouble = Acts::fastHypot(x, y);
0038 
0039   const float slowFloat =
0040       Acts::slowHypot(static_cast<float>(x), static_cast<float>(y));
0041   const double slowDouble = Acts::slowHypot(x, y);
0042 
0043   CHECK_CLOSE_REL(slowFloat, fastFloat, 1e-6);
0044   CHECK_CLOSE_REL(slowDouble, fastDouble, 1e-6);
0045 }
0046 
0047 BOOST_DATA_TEST_CASE(fastCathetus, expDist ^ expDist ^ bdata::xrange(100), xExp,
0048                      yExp, i) {
0049   static_cast<void>(i);
0050 
0051   const auto [y, x] = std::minmax({std::pow(10, xExp), std::pow(10, yExp)});
0052 
0053   const float fastFloat =
0054       Acts::fastCathetus(static_cast<float>(x), static_cast<float>(y));
0055   const double fastDouble = Acts::fastCathetus(x, y);
0056 
0057   const float slowFloat =
0058       Acts::slowCathetus(static_cast<float>(x), static_cast<float>(y));
0059   const double slowDouble = Acts::slowCathetus(x, y);
0060 
0061   CHECK_CLOSE_REL(fastFloat, slowFloat, 1e-6);
0062   CHECK_CLOSE_REL(fastDouble, slowDouble, 1e-6);
0063 }
0064 
0065 BOOST_AUTO_TEST_CASE(ProductTests) {
0066   static_assert(Acts::product(1u, 1u) == 1u);
0067   static_assert(Acts::product(2u, 2u) == 2u);
0068   static_assert(Acts::product(3u, 4u) == 12u);
0069   static_assert(Acts::product(1u, 5u) == 120u);
0070   static_assert(Acts::product(2u, 5u) == 120u);
0071   static_assert(Acts::product(3u, 5u) == 60u);
0072 
0073   static_assert(Acts::product(5u, 4u) == 1u);
0074 
0075   static_assert(Acts::product(0u, 0u) == 0u);
0076   static_assert(Acts::product(0u, 5u) == 0u);
0077 
0078   // These should fail at compile time
0079   // static_assert(Acts::product(std::uint8_t{1}, std::uint8_t{6}));
0080   // static_assert(Acts::product(std::uint16_t{1}, std::uint16_t{9}));
0081   // static_assert(Acts::product(std::uint32_t{1}, std::uint32_t{13}));
0082   // static_assert(Acts::product(std::uint64_t{1}, std::uint64_t{21}));
0083 
0084   // These expressions should fail at runtime
0085   // auto fail8  = Acts::product(std::uint8_t{1},  std::uint8_t{6});
0086   // auto fail16 = Acts::product(std::uint16_t{1}, std::uint16_t{9});
0087   // auto fail32 = Acts::product(std::uint32_t{1}, std::uint32_t{13});
0088   // auto fail64 = Acts::product(std::uint64_t{1}, std::uint64_t{21});
0089 
0090   const std::size_t zero{0};
0091   const std::size_t one{1};
0092   for (std::size_t k = 0; k <= 20; ++k) {
0093     BOOST_CHECK_EQUAL(Acts::product(zero, k), zero);
0094     BOOST_CHECK_EQUAL(Acts::product(one, k), Acts::factorial(k));
0095     BOOST_CHECK_EQUAL(Acts::product(k, k), k);
0096 
0097     for (std::size_t j = 1; j < k; ++j) {
0098       BOOST_CHECK_EQUAL(Acts::product(j, k), j * Acts::product(j + one, k));
0099       BOOST_CHECK_EQUAL(Acts::product(one, k),
0100                         Acts::product(one, j) * Acts::product(j + one, k));
0101     }
0102   }
0103 }
0104 
0105 BOOST_AUTO_TEST_CASE(FactorialTests) {
0106   static_assert(Acts::factorial(0u) == 1u);
0107   static_assert(Acts::factorial(1u) == 1u);
0108   static_assert(Acts::factorial(2u) == 2u);
0109   static_assert(Acts::factorial(5u) == 5u * Acts::factorial(4u));
0110 
0111   // These tests should fail at compile time
0112   // static_assert(Acts::factorial(std::uint8_t{6}));
0113   // static_assert(Acts::factorial(std::uint16_t{9}));
0114   // static_assert(Acts::factorial(std::uint32_t{13}));
0115   // static_assert(Acts::factorial(std::uint64_t{21}));
0116 
0117   // These expressions should fail at runtime
0118   // auto fail8 = Acts::factorial(std::uint8_t{6});
0119   // auto fail16 = Acts::factorial(std::uint16_t{9});
0120   // auto fail32 = Acts::factorial(std::uint32_t{13});
0121   // auto fail64 = Acts::factorial(std::uint64_t{21});
0122 
0123   const std::size_t one{1};
0124   for (std::size_t k = 1; k <= 20; ++k) {
0125     BOOST_CHECK_EQUAL(Acts::factorial(k), k * Acts::factorial(k - one));
0126     for (std::size_t j = 1; j <= k; ++j) {
0127       BOOST_CHECK_EQUAL(Acts::product(j, k),
0128                         Acts::factorial(k) / Acts::factorial(j - one));
0129     }
0130   }
0131 }
0132 
0133 BOOST_AUTO_TEST_CASE(PowerTests) {
0134   for (unsigned p = 0; p <= 15; ++p) {
0135     BOOST_CHECK_EQUAL(std::pow(2., p), Acts::pow(2., p));
0136     BOOST_CHECK_EQUAL(std::pow(0.5, p), Acts::pow(0.5, p));
0137     for (std::size_t k = 1; k <= 15; ++k) {
0138       BOOST_CHECK_EQUAL(std::pow(k, p), Acts::pow(k, p));
0139     }
0140   }
0141   for (int p = 0; p <= 15; ++p) {
0142     BOOST_CHECK_EQUAL(std::pow(2., p), Acts::pow(2., p));
0143     BOOST_CHECK_EQUAL(std::pow(2., -p), Acts::pow(2., -p));
0144     BOOST_CHECK_EQUAL(std::pow(0.5, p), Acts::pow(0.5, p));
0145 
0146     BOOST_CHECK_EQUAL(std::pow(0.5, -p), Acts::pow(0.5, -p));
0147   }
0148 }
0149 
0150 BOOST_AUTO_TEST_CASE(SumOfIntegers) {
0151   std::array<unsigned, 100> numberSeq{Acts::filledArray<unsigned, 100>(1)};
0152   std::iota(numberSeq.begin(), numberSeq.end(), 1);
0153   for (unsigned i = 1; i <= numberSeq.size(); ++i) {
0154     const unsigned sum =
0155         std::accumulate(numberSeq.begin(), numberSeq.begin() + i, 0);
0156     BOOST_CHECK_EQUAL(sum, Acts::sumUpToN(i));
0157   }
0158 }
0159 
0160 BOOST_AUTO_TEST_CASE(BinomialTests) {
0161   static_assert(Acts::binomial(0u, 0u) == 1u);
0162 
0163   static_assert(Acts::binomial(5u, 0u) == 1u);
0164   static_assert(Acts::binomial(5u, 1u) == 5u);
0165   static_assert(Acts::binomial(5u, 2u) == 10u);
0166   static_assert(Acts::binomial(5u, 3u) == 10u);
0167   static_assert(Acts::binomial(5u, 4u) == 5u);
0168   static_assert(Acts::binomial(5u, 5u) == 1u);
0169 
0170   static_assert(Acts::binomial(10u, 3u) == 120u);
0171   static_assert(Acts::binomial(10u, 7u) == 120u);
0172   static_assert(Acts::binomial(20ull, 10ull) == 184756ull);
0173 
0174   // This test should fail at compile time
0175   // static_assert(Acts::binomial(4u, 5u));
0176 
0177   BOOST_CHECK_EQUAL(Acts::binomial(1u, 1u), 1u);
0178   for (unsigned n = 1; n <= 10; ++n) {
0179     /// Check that the binomial of (n 0 is always 1)
0180     BOOST_CHECK_EQUAL(Acts::binomial(n, 0u), 1);
0181     BOOST_CHECK_EQUAL(Acts::binomial(n, n), 1);
0182 
0183     for (unsigned k = 1; k <= n - 1u; ++k) {
0184       /// Use recursive formula
0185       ///  n      n -1       n -1
0186       ///     =          +
0187       ///  k      k -1        k
0188       std::cout << "n: " << n << ", \tk: " << k
0189                 << ", \tbinom(n, k): " << Acts::binomial(n, k)
0190                 << ", \tbinom(n-1, k-1): " << Acts::binomial(n - 1, k - 1)
0191                 << ", \tbinom(n-1, k): " << Acts::binomial(n - 1, k)
0192                 << std::endl;
0193       BOOST_CHECK_EQUAL(Acts::binomial(n, k), Acts::binomial(n - 1, k - 1) +
0194                                                   Acts::binomial(n - 1, k));
0195       BOOST_CHECK_EQUAL(Acts::binomial(n, k), Acts::binomial(n, n - k));
0196     }
0197   }
0198 }
0199 
0200 BOOST_AUTO_TEST_CASE(CopySign) {
0201   BOOST_CHECK_EQUAL(Acts::copySign(5, -10), -5);
0202   BOOST_CHECK_EQUAL(Acts::copySign(5, 0), 5);
0203   BOOST_CHECK_EQUAL(Acts::copySign(5, 55), 5);
0204 
0205   static_assert(Acts::copySign(5, -10) == -5);
0206   static_assert(Acts::copySign(5, 0) == 5);
0207   static_assert(Acts::copySign(5, 55) == 5);
0208 
0209   BOOST_CHECK_EQUAL(Acts::copySign(5, -std::numeric_limits<double>::infinity()),
0210                     -5);
0211   BOOST_CHECK_EQUAL(Acts::copySign(5, std::numeric_limits<double>::infinity()),
0212                     5);
0213 
0214   static_assert(Acts::copySign(5., -std::numeric_limits<double>::infinity()) ==
0215                 -5.);
0216   static_assert(Acts::copySign(5., 0) == 5);
0217   static_assert(Acts::copySign(5., std::numeric_limits<double>::infinity()) ==
0218                 5.);
0219 
0220   BOOST_CHECK_EQUAL(Acts::copySign(5., -10.), -5.);
0221   BOOST_CHECK_EQUAL(Acts::copySign(5., 0.), 5.);
0222   BOOST_CHECK_EQUAL(Acts::copySign(5., 55.), 5.);
0223 
0224   enum class CopyEnum : int { b = 1, a = -1, c = 0 };
0225   BOOST_CHECK_EQUAL(Acts::copySign(5, CopyEnum::a), -5);
0226   BOOST_CHECK_EQUAL(Acts::copySign(5, CopyEnum::b), 5);
0227   BOOST_CHECK_EQUAL(Acts::copySign(5, CopyEnum::c), 5);
0228 
0229   const Acts::Vector3 v{Acts::Vector3::UnitZ()};
0230   CHECK_CLOSE_ABS(Acts::copySign(v, -1).dot(v), -1., 1.e-7);
0231   CHECK_CLOSE_ABS(Acts::copySign(v, 1).dot(v), 1., 1.e-7);
0232 }
0233 
0234 BOOST_AUTO_TEST_SUITE_END()
0235 
0236 }  // namespace ActsTetsts