Loading...
Searching...
No Matches
math.hpp
1#pragma once
2
3#include <algorithm>
4#include <atomic>
5#include <chrono>
6#include <concepts>
7#include <numeric>
8
9namespace tf {
10
14template <typename T>
15requires (std::is_unsigned_v<std::decay_t<T>> && sizeof(T) == 8)
16constexpr T next_pow2(T x) {
17 if(x == 0) return 1;
18 x--;
19 x |= x >> 1;
20 x |= x >> 2;
21 x |= x >> 4;
22 x |= x >> 8;
23 x |= x >> 16;
24 x |= x >> 32;
25 x++;
26 return x;
27}
28
32template <typename T>
33requires (std::is_unsigned_v<std::decay_t<T>> && sizeof(T) == 4)
34constexpr T next_pow2(T y) {
35 if(y == 0) return 1;
36 y--;
37 y |= y >> 1;
38 y |= y >> 2;
39 y |= y >> 4;
40 y |= y >> 8;
41 y |= y >> 16;
42 y++;
43 return y;
44}
45
58template <std::integral T>
59constexpr bool is_pow2(const T& x) {
60 return x && (!(x&(x-1)));
61}
62
66template <size_t N>
67constexpr size_t static_floor_log2() {
68 return (N < 2) ? 0 : 1 + static_floor_log2<N / 2>();
69 //auto log = 0;
70 //while (N >>= 1) {
71 // ++log;
72 //}
73 //return log;
74}
75
76
92template <typename RandItr, typename C>
93RandItr median_of_three(RandItr l, RandItr m, RandItr r, C cmp) {
94 return cmp(*l, *m) ? (cmp(*m, *r) ? m : (cmp(*l, *r) ? r : l ))
95 : (cmp(*r, *m) ? m : (cmp(*r, *l) ? r : l ));
96}
97
116template <typename RandItr, typename C>
117RandItr pseudo_median_of_nine(RandItr beg, RandItr end, C cmp) {
118 size_t N = std::distance(beg, end);
119 size_t offset = N >> 3;
120 return median_of_three(
121 median_of_three(beg, beg+offset, beg+(offset*2), cmp),
122 median_of_three(beg+(offset*3), beg+(offset*4), beg+(offset*5), cmp),
123 median_of_three(beg+(offset*6), beg+(offset*7), end-1, cmp),
124 cmp
125 );
126}
127
141template<typename Iter, typename Compare>
142void sort2(Iter a, Iter b, Compare comp) {
143 if (comp(*b, *a)) std::iter_swap(a, b);
144}
145
161template<typename Iter, typename Compare>
162void sort3(Iter a, Iter b, Iter c, Compare comp) {
163 sort2(a, b, comp);
164 sort2(b, c, comp);
165 sort2(a, b, comp);
166}
167
182template <std::integral T>
184 static std::atomic<T> counter{0};
185 return counter.fetch_add(1, std::memory_order_relaxed);
186}
187
203template <typename T>
204inline void atomic_max(std::atomic<T>& v, const T& max_v) noexcept {
205 T prev = v.load(std::memory_order_relaxed);
206 while(prev < max_v &&
207 !v.compare_exchange_weak(prev, max_v, std::memory_order_relaxed,
208 std::memory_order_relaxed)) {
209 }
210}
211
227template <typename T>
228inline void atomic_min(std::atomic<T>& v, const T& min_v) noexcept {
229 T prev = v.load(std::memory_order_relaxed);
230 while(prev > min_v &&
231 !v.compare_exchange_weak(prev, min_v, std::memory_order_relaxed,
232 std::memory_order_relaxed)) {
233 }
234}
235
247template <typename T>
248inline T seed() noexcept {
249 return std::chrono::system_clock::now().time_since_epoch().count();
250}
251
252// ------------------------------------------------------------------------------------------------
253// coprime
254// ------------------------------------------------------------------------------------------------
255
265constexpr size_t coprime(size_t N) {
266 if(N < 3) {
267 return 1;
268 }
269 for (size_t x = N; --x > 0;) {
270 if (std::gcd(x, N) == 1) {
271 return x;
272 }
273 }
274 return 1;
275}
276
286template <size_t N>
287constexpr std::array<size_t, N> make_coprime_lut() {
288 static_assert(N>0, "N must be greater than 0");
289 std::array<size_t, N> coprimes{};
290 for (size_t n = 0; n < N; ++n) {
291 coprimes[n] = coprime(n);
292 }
293 return coprimes;
294}
295
296//template <typename T>
297//constexpr T lemire_range(T x, T range) {
298// return (uint32_t)(((uint64_t)x * (uint64_t)range) >> 32);
299//}
300
301
319template <typename T>
320class Xorshift {
321 static_assert(std::is_unsigned<T>::value, "Xorshift requires an unsigned integral type.");
322
323 public:
324
331 Xorshift() = default;
332
340 Xorshift(T value) : _state(value) {}
341
350 void seed(T value) {
351 _state = value;
352 }
353
368 if constexpr (sizeof(T) == 8) {
369 // Xorshift64 constants
370 _state ^= _state << 13;
371 _state ^= _state >> 7;
372 _state ^= _state << 17;
373 return _state * 0x2545F4914F6CDD1DULL;
374 }
375 else if constexpr (sizeof(T) == 4) {
376 // Xorshift32 constants
377 _state ^= _state << 13;
378 _state ^= _state >> 17;
379 _state ^= _state << 5;
380 return _state;
381 }
382 else {
383 static_assert(sizeof(T) == 0, "Unsupported bit-width for Xorshift. Use uint32_t or uint64_t.");
384 }
385 }
386
387 private:
388
389 T _state; // must be initialized with non-zero
390};
391
392} // end of namespace tf -----------------------------------------------------
void seed(T value)
seeds the generator with a new value
Definition math.hpp:350
T operator()()
generates the next pseudo-random value
Definition math.hpp:367
Xorshift(T value)
constructs a xor-shift generator with the given seed
Definition math.hpp:340
Xorshift()=default
constructs an uninitialized xor-shift generator
taskflow namespace
Definition small_vector.hpp:20
RandItr median_of_three(RandItr l, RandItr m, RandItr r, C cmp)
finds the median of three numbers pointed to by iterators using the given comparator
Definition math.hpp:93
T unique_id()
generates a program-wide unique ID of the given type in a thread-safe manner
Definition math.hpp:183
constexpr size_t coprime(size_t N)
computes a coprime of a given number
Definition math.hpp:265
T seed() noexcept
generates a random seed based on the current system clock
Definition math.hpp:248
constexpr T next_pow2(T x)
rounds the given 64-bit unsigned integer to the nearest power of 2
Definition math.hpp:16
void atomic_max(std::atomic< T > &v, const T &max_v) noexcept
updates an atomic variable with the maximum value
Definition math.hpp:204
void atomic_min(std::atomic< T > &v, const T &min_v) noexcept
updates an atomic variable with the minimum value
Definition math.hpp:228
constexpr std::array< size_t, N > make_coprime_lut()
generates a compile-time array of coprimes for numbers from 0 to N-1
Definition math.hpp:287
RandItr pseudo_median_of_nine(RandItr beg, RandItr end, C cmp)
finds the pseudo median of a range of items using a spread of nine numbers
Definition math.hpp:117
void sort3(Iter a, Iter b, Iter c, Compare comp)
Sorts three elements of dereferenced iterators using the given comparison function.
Definition math.hpp:162
void sort2(Iter a, Iter b, Compare comp)
sorts two elements of dereferenced iterators using the given comparison function
Definition math.hpp:142
constexpr size_t static_floor_log2()
returns the floor of log2(N) at compile time
Definition math.hpp:67
constexpr bool is_pow2(const T &x)
checks if the given number is a power of 2
Definition math.hpp:59