Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:11:11

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 
0013 #include <algorithm>
0014 #include <array>
0015 #include <iostream>
0016 #include <limits>
0017 #include <memory>
0018 #include <type_traits>
0019 #include <vector>
0020 
0021 #define ACTS_CHECK_BIT(value, mask) ((value & mask) == mask)
0022 
0023 namespace Acts {
0024 
0025 /// Helper function to unpack a vector of @c shared_ptr into a vector of raw
0026 /// pointers
0027 /// @tparam T the stored type
0028 /// @param items The vector of @c shared_ptr
0029 /// @return The unpacked vector
0030 template <typename T>
0031 std::vector<T*> unpack_shared_vector(
0032     const std::vector<std::shared_ptr<T>>& items) {
0033   std::vector<T*> rawPtrs;
0034   rawPtrs.reserve(items.size());
0035   for (const std::shared_ptr<T>& item : items) {
0036     rawPtrs.push_back(item.get());
0037   }
0038   return rawPtrs;
0039 }
0040 
0041 /// Helper function to unpack a vector of @c shared_ptr into a vector of raw
0042 /// pointers (const version)
0043 /// @tparam T the stored type
0044 /// @param items The vector of @c shared_ptr
0045 /// @return The unpacked vector
0046 template <typename T>
0047 std::vector<const T*> unpack_shared_vector(
0048     const std::vector<std::shared_ptr<const T>>& items) {
0049   std::vector<const T*> rawPtrs;
0050   rawPtrs.reserve(items.size());
0051   for (const std::shared_ptr<const T>& item : items) {
0052     rawPtrs.push_back(item.get());
0053   }
0054   return rawPtrs;
0055 }
0056 
0057 /// Helper function to unpack a vector of @c shared_ptr into a vector of raw
0058 /// pointers
0059 /// @tparam T the stored type
0060 /// @param items The vector of @c shared_ptr
0061 /// @return The unpacked vector
0062 template <typename T>
0063 std::vector<const T*> unpack_shared_const_vector(
0064     const std::vector<std::shared_ptr<T>>& items) {
0065   std::vector<const T*> rawPtrs;
0066   rawPtrs.reserve(items.size());
0067   for (const std::shared_ptr<T>& item : items) {
0068     rawPtrs.push_back(item.get());
0069   }
0070   return rawPtrs;
0071 }
0072 
0073 /// @brief Converts a vector to a fixed-size array with truncating or padding.
0074 ///
0075 /// This function copies elements from the input vector into a fixed-size array.
0076 /// If the vector contains more than `kDIM` elements, the array is truncated to
0077 /// fit. If the vector contains fewer elements than `kDIM`, the remaining array
0078 /// elements are value-initialized (default-initialized, i.e., filled with zero
0079 /// or default values).
0080 ///
0081 /// @tparam kDIM The size of the resulting array.
0082 /// @tparam value_t The type of elements in the vector and the array.
0083 /// @param vecvals The input vector to be converted to an array.
0084 ///
0085 /// @return An array containing the first `kDIM` elements of the vector.
0086 template <std::size_t kDIM, typename value_t>
0087 std::array<value_t, kDIM> toArray(const std::vector<value_t>& vecvals) {
0088   std::array<value_t, kDIM> arr = {};
0089   std::copy_n(vecvals.begin(), std::min(vecvals.size(), kDIM), arr.begin());
0090   return arr;
0091 }
0092 
0093 /// @brief Dispatch a call based on a runtime value on a function taking the
0094 /// value at compile time.
0095 ///
0096 /// This function allows to write a templated functor, which accepts a @c std::size_t
0097 /// like parameter at compile time. It is then possible to make a call to the
0098 /// corresponding instance of the functor based on a runtime value. To achieve
0099 /// this, the function essentially created a if cascade between @c N and @c
0100 /// NMAX, attempting to find the right instance. Because the cascade is visible
0101 /// to the compiler entirely, it should be able to optimize.
0102 ///
0103 /// @tparam Callable Type which takes a std::size_t as a compile time param
0104 /// @tparam N Value from which to start the dispatch chain, i.e. 0 in most cases
0105 /// @tparam NMAX Maximum value up to which to attempt a dispatch
0106 /// @param v The runtime value to dispatch on
0107 /// @param args Additional arguments passed to @c Callable::invoke().
0108 /// @note @c Callable is expected to have a static member function @c invoke
0109 /// that is callable with @c Args
0110 template <template <std::size_t> class Callable, std::size_t N,
0111           std::size_t NMAX, typename... Args>
0112 auto template_switch(std::size_t v, Args&&... args) {
0113   if (v == N) {
0114     return Callable<N>::invoke(std::forward<Args>(args)...);
0115   }
0116   if (v == 0) {
0117     std::cerr << "template_switch<Fn, " << N << ", " << NMAX << ">(v=" << v
0118               << ") is not valid (v == 0 and N != 0)" << std::endl;
0119     std::abort();
0120   }
0121   if constexpr (N < NMAX) {
0122     return template_switch<Callable, N + 1, NMAX>(v,
0123                                                   std::forward<Args>(args)...);
0124   }
0125   std::cerr << "template_switch<Fn, " << N << ", " << NMAX << ">(v=" << v
0126             << ") is not valid (v > NMAX)" << std::endl;
0127   std::abort();
0128 }
0129 
0130 /// Alternative version of @c template_switch which accepts a generic
0131 /// lambda and communicates the dimension via an integral constant type
0132 /// @tparam N Value from which to start the dispatch chain, i.e. 0 in most cases
0133 /// @tparam NMAX Maximum value up to which to attempt a dispatch
0134 /// @param v The runtime value to dispatch on
0135 /// @param func The lambda to invoke
0136 /// @param args Additional arguments passed to @p func
0137 template <std::size_t N, std::size_t NMAX, typename Lambda, typename... Args>
0138 auto template_switch_lambda(std::size_t v, Lambda&& func, Args&&... args) {
0139   if (v == N) {
0140     return func(std::integral_constant<std::size_t, N>{},
0141                 std::forward<Args>(args)...);
0142   }
0143   if (v == 0) {
0144     std::cerr << "template_switch<Fn, " << N << ", " << NMAX << ">(v=" << v
0145               << ") is not valid (v == 0 and N != 0)" << std::endl;
0146     std::abort();
0147   }
0148   if constexpr (N < NMAX) {
0149     return template_switch_lambda<N + 1, NMAX>(v, func,
0150                                                std::forward<Args>(args)...);
0151   }
0152   std::cerr << "template_switch<Fn, " << N << ", " << NMAX << ">(v=" << v
0153             << ") is not valid (v > NMAX)" << std::endl;
0154   std::abort();
0155 }
0156 
0157 /// Clamp a numeric value to another type, respecting range of the target type
0158 /// @tparam T the target type
0159 /// @tparam U the source type
0160 /// @param value the value to clamp
0161 /// @return the clamped value
0162 template <typename T, typename U>
0163 T clampValue(U value) {
0164   return std::clamp(value, static_cast<U>(std::numeric_limits<T>::lowest()),
0165                     static_cast<U>(std::numeric_limits<T>::max()));
0166 }
0167 
0168 /// Return range and medium of an unsorted numeric series
0169 ///
0170 /// @tparam T a numeric series
0171 ///
0172 /// @param tseries is the number series
0173 ///
0174 /// @return [ range, medium ] in an tuple
0175 template <typename T>
0176 std::tuple<typename T::value_type, double> range_medium(const T& tseries) {
0177   auto [minIt, maxIt] = std::ranges::minmax_element(tseries);
0178   typename T::value_type range = (*maxIt - *minIt);
0179   double medium = static_cast<double>((*maxIt + *minIt) * 0.5);
0180   return {range, medium};
0181 }
0182 
0183 template <typename enum_t>
0184 constexpr std::underlying_type_t<enum_t> toUnderlying(enum_t value) {
0185   return static_cast<std::underlying_type_t<enum_t>>(value);
0186 }
0187 
0188 /// This can be replaced with C++23 to use the std::ranges::contains method
0189 ///
0190 /// This function searches through the given range for a specified value
0191 /// and returns `true` if the value is found, or `false` otherwise.
0192 ///
0193 /// @tparam R The type of the range (e.g., vector, list, array).
0194 /// @tparam T The type of the value to search for within the range.
0195 ///
0196 /// @param range The range to search within. This can be any range-compatible container.
0197 /// @param value The value to search for in the range.
0198 ///
0199 /// @return `true` if the value is found within the range, `false` otherwise.
0200 template <typename R, typename T>
0201 bool rangeContainsValue(const R& range, const T& value) {
0202   return std::ranges::find(range, value) != std::ranges::end(range);
0203 }
0204 
0205 /// Helper struct that can turn a set of lambdas into a single entity with
0206 /// overloaded call operator. This can be useful for example in a std::visit
0207 /// call.
0208 /// ```cpp
0209 /// std::visit(overloaded{
0210 ///  [](const int& i) { std::cout << "int: " << i << std::endl; },
0211 ///  [](const std::string& s) { std::cout << "string: " << s << std::endl; },
0212 /// }, variant);
0213 /// ```
0214 template <class... Ts>
0215 struct overloaded : Ts... {
0216   using Ts::operator()...;
0217 };
0218 
0219 template <class... Ts>
0220 overloaded(Ts...) -> overloaded<Ts...>;
0221 
0222 namespace detail {
0223 
0224 /// Computes the minimum, maximum, and bin count for a given vector of values.
0225 ///
0226 /// This function processes a vector of doubles to compute:
0227 /// - The minimum value (@c xMin)
0228 /// - The maximum value (@c xMax), adjusted to include an additional bin
0229 /// - The bin count (@c xBinCount) based on the number of unique values
0230 ///
0231 /// The computation is performed as follows:
0232 /// 1. Sorts the input vector using @c std::ranges::sort to prepare for uniqueness.
0233 /// 2. Determines the number of unique values using @c std::unique and calculates the bin count.
0234 /// 3. Calculates the minimum and maximum using @c std::ranges::minmax.
0235 /// 4. Adjusts the maximum to include an additional bin by adding the bin step
0236 /// size.
0237 ///
0238 /// @param xPos A reference to a vector of doubles.
0239 /// @return A tuple containing:
0240 ///         - The minimum value (double)
0241 ///         - The adjusted maximum value (double)
0242 ///         - The bin count (std::size_t)
0243 ///
0244 /// @note The vector xPos will be modified during the call.
0245 inline auto getMinMaxAndBinCount(std::vector<double>& xPos) {
0246   // sort the values for unique()
0247   std::ranges::sort(xPos);
0248 
0249   // get the number of bins over unique values
0250   auto it = std::unique(xPos.begin(), xPos.end());
0251   const std::size_t xBinCount = std::distance(xPos.begin(), it);
0252 
0253   // get the minimum and maximum
0254   auto [xMin, xMax] = std::ranges::minmax(xPos);
0255 
0256   // calculate maxima (add one last bin, because bin value always corresponds to
0257   // left boundary)
0258   const double stepX = (xMax - xMin) / static_cast<double>(xBinCount - 1);
0259   xMax += stepX;
0260 
0261   // Return all values as a tuple
0262   return std::make_tuple(xMin, xMax, xBinCount);
0263 }
0264 
0265 }  // namespace detail
0266 
0267 }  // namespace Acts