|
||||
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
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |