misc.hpp
1 
5 #pragma once
6 
7 #include <chrono>
8 #include <cmath>
9 #include <cstdlib>
10 #include <functional>
11 #include <memory>
12 #include <ranges>
13 #include <source_location>
14 #include <stdexcept>
15 #include <type_traits>
16 #include <utility>
17 #include <vector>
18 
19 #include <cuda_runtime_api.h>
20 
21 namespace rapidsmpf {
22 
28 #define RAPIDSMPF_CUDA_VERSION_AT_LEAST(version) (CUDART_VERSION >= version)
29 
31 using Clock = std::chrono::high_resolution_clock;
33 using Duration = std::chrono::duration<double>;
35 using TimePoint = std::chrono::time_point<Clock, Duration>;
36 
49 template <typename MapType>
50 std::pair<typename MapType::key_type, typename MapType::mapped_type> extract_item(
51  MapType& map, typename MapType::const_iterator position
52 ) {
53  auto node = map.extract(position);
54  if (!node) {
55  throw std::out_of_range("Invalid iterator passed to extract");
56  }
57  return {std::move(node.key()), std::move(node.mapped())};
58 }
59 
70 template <typename MapType>
71 std::pair<typename MapType::key_type, typename MapType::mapped_type> extract_item(
72  MapType& map, typename MapType::key_type const& key
73 ) {
74  auto node = map.extract(key);
75  if (!node) {
76  throw std::out_of_range("Invalid key passed to extract");
77  }
78  return {std::move(node.key()), std::move(node.mapped())};
79 }
80 
92 template <typename MapType>
93 typename MapType::mapped_type extract_value(
94  MapType& map, typename MapType::key_type const& key
95 ) {
96  return std::move(extract_item(map, key).second);
97 }
98 
112 template <typename MapType>
113 typename MapType::mapped_type extract_value(
114  MapType& map, typename MapType::const_iterator position
115 ) {
116  return std::move(extract_item(map, position).second);
117 }
118 
129 template <typename MapType>
130 typename MapType::key_type extract_key(
131  MapType& map, typename MapType::key_type const& key
132 ) {
133  return std::move(extract_item(map, key).first);
134 }
135 
148 template <typename MapType>
149 typename MapType::key_type extract_key(
150  MapType& map, typename MapType::const_iterator position
151 ) {
152  return std::move(extract_item(map, position).first);
153 }
154 
165 template <typename MapType>
166 auto to_vector(MapType&& map) {
167  using ValueType = typename std::remove_reference_t<MapType>::mapped_type;
168  std::vector<ValueType> vec;
169  vec.reserve(map.size());
170  for (auto&& [key, value] : map) {
171  vec.push_back(std::move(value));
172  }
173  return vec;
174 }
175 
182 
191 template <typename T>
192 constexpr T safe_div(T x, T y) {
193  return (y == 0) ? 0 : x / y;
194 }
195 
196 // Macro to concatenate two tokens x and y.
197 #define RAPIDSMPF_CONCAT_DETAIL_(x, y) x##y
198 #define RAPIDSMPF_CONCAT(x, y) RAPIDSMPF_CONCAT_DETAIL_(x, y)
199 
200 // Stringify a macro argument.
201 #define RAPIDSMPF_STRINGIFY_DETAIL_(x) #x
202 #define RAPIDSMPF_STRINGIFY(x) RAPIDSMPF_STRINGIFY_DETAIL_(x)
203 
220 #define RAPIDSMPF_OVERLOAD_BY_ARG_COUNT(_1, _2, NAME, ...) NAME
221 
222 namespace detail {
223 
233 template <typename T>
234 constexpr T* to_pointer(T* ptr) noexcept {
235  return ptr;
236 }
237 
239 template <typename T>
240 constexpr T* to_pointer(T& ptr) noexcept {
241  return std::addressof(ptr);
242 }
243 
245 template <typename T>
246 constexpr T* to_pointer(std::unique_ptr<T>& ptr) noexcept {
247  return ptr.get();
248 }
249 
251 template <typename T>
252 constexpr T* to_pointer(std::shared_ptr<T>& ptr) noexcept {
253  return ptr.get();
254 }
255 
256 } // namespace detail
257 
259 template <class... Ts>
260 struct overloaded : Ts... {
261  using Ts::operator()...;
262 };
263 
280 template <std::ranges::input_range R, typename T, typename Proj = std::identity>
281 [[nodiscard]] constexpr bool contains(R&& range, T const& value, Proj proj = {}) {
282  for (auto const& elem : range) {
283  if (std::invoke(proj, elem) == value) {
284  return true;
285  }
286  }
287  return false;
288 }
289 
309 template <typename To, typename From>
310  requires std::is_arithmetic_v<To> && std::is_arithmetic_v<From>
311 constexpr To safe_cast(
312  From value, std::source_location const& loc = std::source_location::current()
313 ) {
314  if constexpr (std::is_same_v<From, To>) {
315  // Same type, no-op.
316  return value;
317  } else if constexpr (std::is_integral_v<From> && std::is_integral_v<To>) {
318  // Integer to integer.
319  if (!std::in_range<To>(value)) {
320  throw std::overflow_error(
321  "RapidsMPF cast error at: " + std::string(loc.file_name()) + ":"
322  + std::to_string(loc.line()) + ", value out of range"
323  );
324  }
325  return static_cast<To>(value);
326  } else {
327  // Floating point conversions: direct cast (well-defined overflow behavior).
328  return static_cast<To>(value);
329  }
330 }
331 
332 } // namespace rapidsmpf
constexpr T * to_pointer(T *ptr) noexcept
Returns the raw pointer from a pointer, reference, or smart pointer.
Definition: misc.hpp:234
RAPIDS Multi-Processor interfaces.
Definition: backend.hpp:13
std::chrono::duration< double > Duration
Alias for a duration type representing time in seconds as a double.
Definition: misc.hpp:33
std::chrono::time_point< Clock, Duration > TimePoint
Alias for a time point with double precision in seconds.
Definition: misc.hpp:35
MapType::mapped_type extract_value(MapType &map, typename MapType::key_type const &key)
Extracts the value associated with a specific key from a map, removing the key-value pair.
Definition: misc.hpp:93
MapType::key_type extract_key(MapType &map, typename MapType::key_type const &key)
Extracts a key from a map, removing the key-value pair.
Definition: misc.hpp:130
bool is_running_under_valgrind()
Checks whether the application is running under Valgrind.
std::pair< typename MapType::key_type, typename MapType::mapped_type > extract_item(MapType &map, typename MapType::const_iterator position)
Extracts a key-value pair from a map, removing it from the map.
Definition: misc.hpp:50
constexpr T safe_div(T x, T y)
Performs safe division, returning 0 if the denominator is zero.
Definition: misc.hpp:192
std::chrono::high_resolution_clock Clock
Alias for high-resolution clock from the chrono library.
Definition: misc.hpp:31
constexpr bool contains(R &&range, T const &value, Proj proj={})
Backport of std::ranges::contains from C++23 for C++20.
Definition: misc.hpp:281
requires std::is_arithmetic_v< To > &&constexpr std::is_arithmetic_v< From > To safe_cast(From value, std::source_location const &loc=std::source_location::current())
Safely casts a numeric value to another type with overflow checking.
Definition: misc.hpp:311
auto to_vector(MapType &&map)
Converts a map-like associative container to a vector by moving the values and discarding the keys.
Definition: misc.hpp:166
Helper for overloaded lambdas using std::visit.
Definition: misc.hpp:260