File indexing completed on 2025-11-08 09:18:25
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include "Acts/Utilities/PointerTraits.hpp"
0012
0013 #include <algorithm>
0014 #include <array>
0015 #include <cmath>
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
0027
0028
0029
0030
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
0045
0046
0047
0048
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
0061
0062
0063
0064
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
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
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
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114 template <template <std::size_t> class Callable, std::size_t N,
0115 std::size_t NMAX, typename... Args>
0116 auto template_switch(std::size_t v, Args&&... args) {
0117 if (v == N) {
0118 return Callable<N>::invoke(std::forward<Args>(args)...);
0119 }
0120 if (v == 0) {
0121 std::cerr << "template_switch<Fn, " << N << ", " << NMAX << ">(v=" << v
0122 << ") is not valid (v == 0 and N != 0)" << std::endl;
0123 std::abort();
0124 }
0125 if constexpr (N < NMAX) {
0126 return template_switch<Callable, N + 1, NMAX>(v,
0127 std::forward<Args>(args)...);
0128 }
0129 std::cerr << "template_switch<Fn, " << N << ", " << NMAX << ">(v=" << v
0130 << ") is not valid (v > NMAX)" << std::endl;
0131 std::abort();
0132 }
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142 template <std::size_t N, std::size_t NMAX, typename Lambda, typename... Args>
0143 auto template_switch_lambda(std::size_t v, Lambda&& func, Args&&... args) {
0144 if (v == N) {
0145 return func(std::integral_constant<std::size_t, N>{},
0146 std::forward<Args>(args)...);
0147 }
0148 if (v == 0) {
0149 std::cerr << "template_switch<Fn, " << N << ", " << NMAX << ">(v=" << v
0150 << ") is not valid (v == 0 and N != 0)" << std::endl;
0151 std::abort();
0152 }
0153 if constexpr (N < NMAX) {
0154 return template_switch_lambda<N + 1, NMAX>(v, func,
0155 std::forward<Args>(args)...);
0156 }
0157 std::cerr << "template_switch<Fn, " << N << ", " << NMAX << ">(v=" << v
0158 << ") is not valid (v > NMAX)" << std::endl;
0159 std::abort();
0160 }
0161
0162
0163
0164
0165
0166
0167 template <typename T, typename U>
0168 T clampValue(U value) {
0169 if (std::numeric_limits<U>::has_infinity && std::isinf(value)) {
0170 if (!std::numeric_limits<T>::has_infinity) {
0171 throw std::logic_error(
0172 "Cannot convert infinite value to type without infinity support");
0173 }
0174 return (value > 0) ? std::numeric_limits<T>::infinity()
0175 : -std::numeric_limits<T>::infinity();
0176 }
0177 if (std::numeric_limits<U>::has_quiet_NaN && std::isnan(value)) {
0178 if (!std::numeric_limits<T>::has_quiet_NaN) {
0179 throw std::logic_error(
0180 "Cannot convert NaN value to type without NaN support");
0181 }
0182 return std::numeric_limits<T>::quiet_NaN();
0183 }
0184 return static_cast<T>(
0185 std::clamp(value, static_cast<U>(std::numeric_limits<T>::lowest()),
0186 static_cast<U>(std::numeric_limits<T>::max())));
0187 }
0188
0189
0190
0191
0192
0193
0194
0195
0196 template <typename T>
0197 std::tuple<typename T::value_type, double> range_medium(const T& tseries) {
0198 auto [minIt, maxIt] = std::ranges::minmax_element(tseries);
0199 typename T::value_type range = (*maxIt - *minIt);
0200 double medium = static_cast<double>((*maxIt + *minIt) * 0.5);
0201 return {range, medium};
0202 }
0203
0204
0205
0206
0207 template <typename enum_t>
0208 constexpr std::underlying_type_t<enum_t> toUnderlying(enum_t value) {
0209 return static_cast<std::underlying_type_t<enum_t>>(value);
0210 }
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224 template <typename R, typename T>
0225 bool rangeContainsValue(const R& range, const T& value) {
0226 return std::ranges::find(range, value) != std::ranges::end(range);
0227 }
0228
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238 template <class... Ts>
0239 struct overloaded : Ts... {
0240 using Ts::operator()...;
0241 };
0242
0243
0244 template <class... Ts>
0245 overloaded(Ts...) -> overloaded<Ts...>;
0246
0247 namespace detail {
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270 inline auto getMinMaxAndBinCount(std::vector<double>& xPos) {
0271
0272 std::ranges::sort(xPos);
0273
0274
0275 auto it = std::unique(xPos.begin(), xPos.end());
0276 const std::size_t xBinCount = std::distance(xPos.begin(), it);
0277
0278
0279 auto [xMin, xMax] = std::ranges::minmax(xPos);
0280
0281
0282
0283 const double stepX = (xMax - xMin) / static_cast<double>(xBinCount - 1);
0284 xMax += stepX;
0285
0286
0287 return std::make_tuple(xMin, xMax, xBinCount);
0288 }
0289
0290 }
0291
0292 }