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