Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
utils.h
Go to the documentation of this file.
1#ifndef BVH_V2_UTILS_H
2#define BVH_V2_UTILS_H
3
4#include "bvh/v2/platform.h"
5
6#include <limits>
7#include <climits>
8#include <cstdint>
9#include <cstring>
10#include <cmath>
11#include <atomic>
12
13namespace bvh::v2 {
14
15/// Helper type that gives an unsigned integer type with the given number of bits.
16template <size_t Bits>
17struct UnsignedInt {};
18
19template <> struct UnsignedInt< 8> { using Type = uint8_t ; };
20template <> struct UnsignedInt<16> { using Type = uint16_t; };
21template <> struct UnsignedInt<32> { using Type = uint32_t; };
22template <> struct UnsignedInt<64> { using Type = uint64_t; };
23
24template <size_t Bits>
26
27/// Helper callable object that just ignores its arguments and returns nothing.
28struct IgnoreArgs {
29 template <typename... Args>
30 void operator () (Args&&...) const {}
31};
32
33/// Generates a bitmask with the given number of bits.
34template <typename T, std::enable_if_t<std::is_unsigned_v<T>, bool> = true>
35BVH_ALWAYS_INLINE constexpr T make_bitmask(size_t bits) {
36 return bits >= std::numeric_limits<T>::digits ? static_cast<T>(-1) : (static_cast<T>(1) << bits) - 1;
37}
38
39// These two functions are designed to return the second argument if the first one is a NaN.
40template <typename T, std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
41BVH_ALWAYS_INLINE T robust_min(T a, T b) { return a < b ? a : b; }
42template <typename T, std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
43BVH_ALWAYS_INLINE T robust_max(T a, T b) { return a > b ? a : b; }
44
45/// Adds the given number of ULPs (Units in the Last Place) to the given floating-point number.
46template <typename T, std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
48 if (!std::isfinite(t))
49 return t;
50 UnsignedIntType<sizeof(T) * CHAR_BIT> u;
51 std::memcpy(&u, &t, sizeof(T));
52 u += ulp;
53 std::memcpy(&t, &u, sizeof(T));
54 return t;
55}
56
57/// Computes the inverse of the given value, always returning a finite value.
58template <typename T, std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
60 return std::fabs(x) <= std::numeric_limits<T>::epsilon()
61 ? std::copysign(std::numeric_limits<T>::max(), x)
62 : static_cast<T>(1.) / x;
63}
64
65/// Fast multiply-add operation. Should translate into an FMA for architectures that support it. On
66/// architectures which do not support FMA in hardware, or on which FMA is slow, this defaults to a
67/// regular multiplication followed by an addition.
68#if defined(_MSC_VER) && !defined(__clang__)
69#pragma float_control(push)
70#pragma float_control(precise, off)
71#pragma fp_contract(on)
72#endif
73template <typename T, std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
75#ifdef FP_FAST_FMAF
76 return std::fma(a, b, c);
77#elif defined(__clang__)
79#endif
80 return a * b + c;
81}
82#if defined(_MSC_VER) && !defined(__clang__)
83#pragma float_control(pop)
84#endif
85
86/// Executes the given function once for every integer in the range `[Begin, End)`.
87template <size_t Begin, size_t End, typename F>
89 if constexpr (Begin < End) {
90 f(Begin);
91 static_for<Begin + 1, End>(std::forward<F>(f));
92 }
93}
94
95/// Computes the (rounded-up) compile-time log in base-2 of an unsigned integer.
96template <typename T, std::enable_if_t<std::is_unsigned_v<T>, bool> = true>
97inline constexpr T round_up_log2(T i, T p = 0) {
98 return (static_cast<T>(1) << p) >= i ? p : round_up_log2(i, p + 1);
99}
100
101/// Split an unsigned integer such that its bits are spaced by 2 zeros.
102/// For instance, split_bits(0b00110010) = 0b000000001001000000001000.
103template <typename T, std::enable_if_t<std::is_unsigned_v<T>, bool> = true>
105 constexpr size_t bit_count = sizeof(T) * CHAR_BIT;
106 constexpr size_t log_bits = round_up_log2(bit_count);
107 auto mask = static_cast<T>(-1) >> (bit_count / 2);
108 x &= mask;
109 for (size_t i = log_bits - 1, n = size_t{1} << i; i > 0; --i, n >>= 1) {
110 mask = (mask | (mask << n)) & ~(mask << (n / 2));
111 x = (x | (x << n)) & mask;
112 }
113 return x;
114}
115
116/// Morton-encode three unsigned integers into one.
117template <typename T, std::enable_if_t<std::is_unsigned_v<T>, bool> = true>
119 return split_bits(x) | (split_bits(y) << 1) | (split_bits(z) << 2);
120}
121
122/// Computes the maximum between an atomic variable and a value, and returns the value previously
123/// held by the atomic variable.
124template <typename T>
125BVH_ALWAYS_INLINE T atomic_max(std::atomic<T>& atomic, const T& value) {
126 auto prev_value = atomic;
127 while (prev_value < value && !atomic.compare_exchange_weak(prev_value, value));
128 return prev_value;
129}
130
131} // namespace bvh::v2
132
133#endif
#define b(i)
Definition RSha256.hxx:100
#define f(i)
Definition RSha256.hxx:104
#define c(i)
Definition RSha256.hxx:101
#define a(i)
Definition RSha256.hxx:99
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t mask
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
Double_t y[n]
Definition legend1.C:17
Double_t x[n]
Definition legend1.C:17
const Int_t n
Definition legend1.C:16
#define F(x, y, z)
Definition bbox.h:9
BVH_ALWAYS_INLINE T split_bits(T x)
Split an unsigned integer such that its bits are spaced by 2 zeros.
Definition utils.h:104
constexpr T round_up_log2(T i, T p=0)
Computes the (rounded-up) compile-time log in base-2 of an unsigned integer.
Definition utils.h:97
typename UnsignedInt< Bits >::Type UnsignedIntType
Definition utils.h:25
BVH_ALWAYS_INLINE T safe_inverse(T x)
Computes the inverse of the given value, always returning a finite value.
Definition utils.h:59
BVH_ALWAYS_INLINE T morton_encode(T x, T y, T z)
Morton-encode three unsigned integers into one.
Definition utils.h:118
BVH_ALWAYS_INLINE T add_ulp_magnitude(T t, unsigned ulp)
Adds the given number of ULPs (Units in the Last Place) to the given floating-point number.
Definition utils.h:47
BVH_ALWAYS_INLINE T robust_max(T a, T b)
Definition utils.h:43
BVH_ALWAYS_INLINE T atomic_max(std::atomic< T > &atomic, const T &value)
Computes the maximum between an atomic variable and a value, and returns the value previously held by...
Definition utils.h:125
BVH_ALWAYS_INLINE T fast_mul_add(T a, T b, T c)
Fast multiply-add operation.
Definition utils.h:74
BVH_ALWAYS_INLINE void static_for(F &&f)
Executes the given function once for every integer in the range [Begin, End).
Definition utils.h:88
BVH_ALWAYS_INLINE T robust_min(T a, T b)
Definition utils.h:41
BVH_ALWAYS_INLINE constexpr T make_bitmask(size_t bits)
Generates a bitmask with the given number of bits.
Definition utils.h:35
#define BVH_CLANG_ENABLE_FP_CONTRACT
Definition platform.h:11
#define BVH_ALWAYS_INLINE
Definition platform.h:19
Helper callable object that just ignores its arguments and returns nothing.
Definition utils.h:28
void operator()(Args &&...) const
Definition utils.h:30
Helper type that gives an unsigned integer type with the given number of bits.
Definition utils.h:17