#pragma once #include namespace tf { // rounds the given 64-bit unsigned integer to the nearest power of 2 template > && sizeof(T) == 8) , void >* = nullptr> constexpr T next_pow2(T x) { if(x == 0) return 1; x--; x |= x>>1; x |= x>>2; x |= x>>4; x |= x>>8; x |= x>>16; x |= x>>32; x++; return x; } // rounds the given 32-bit unsigned integer to the nearest power of 2 template > && sizeof(T) == 4), void >* = nullptr> constexpr T next_pow2(T x) { if(x == 0) return 1; x--; x |= x>>1; x |= x>>2; x |= x>>4; x |= x>>8; x |= x>>16; x++; return x; } // checks if the given number if a power of 2 template >, void>* = nullptr > constexpr bool is_pow2(const T& x) { return x && (!(x&(x-1))); } //// finds the ceil of x divided by b //template >, void>* = nullptr //> //constexpr T ceil(const T& x, const T& y) { // //return (x + y - 1) / y; // return (x-1) / y + 1; //} /** @brief returns floor(log2(n)), assumes n > 0 */ template constexpr int log2(T n) { int log = 0; while (n >>= 1) { ++log; } return log; } /** @brief finds the median of three numbers of dereferenced iterators using the given comparator */ template RandItr median_of_three(RandItr l, RandItr m, RandItr r, C cmp) { return cmp(*l, *m) ? (cmp(*m, *r) ? m : (cmp(*l, *r) ? r : l )) : (cmp(*r, *m) ? m : (cmp(*r, *l) ? r : l )); } /** @brief finds the pseudo median of a range of items using a spread of nine numbers */ template RandItr pseudo_median_of_nine(RandItr beg, RandItr end, C cmp) { size_t N = std::distance(beg, end); size_t offset = N >> 3; return median_of_three( median_of_three(beg, beg+offset, beg+(offset*2), cmp), median_of_three(beg+(offset*3), beg+(offset*4), beg+(offset*5), cmp), median_of_three(beg+(offset*6), beg+(offset*7), end-1, cmp), cmp ); } /** @brief sorts two elements of dereferenced iterators using the given comparison function */ template void sort2(Iter a, Iter b, Compare comp) { if (comp(*b, *a)) std::iter_swap(a, b); } /** @brief sorts three elements of dereferenced iterators using the given comparison function */ template void sort3(Iter a, Iter b, Iter c, Compare comp) { sort2(a, b, comp); sort2(b, c, comp); sort2(a, b, comp); } /** @brief generates a program-wise unique id of the give type (thread-safe) */ template , void>* = nullptr> T unique_id() { static std::atomic counter{0}; return counter.fetch_add(1, std::memory_order_relaxed); } /** @brief updates an atomic variable with a maximum value */ template inline void atomic_max(std::atomic& v, const T& max_v) noexcept { T prev = v.load(std::memory_order_relaxed); while(prev < max_v && !v.compare_exchange_weak(prev, max_v, std::memory_order_relaxed, std::memory_order_relaxed)) { } } /** @brief updates an atomic variable with a minimum value */ template inline void atomic_min(std::atomic& v, const T& min_v) noexcept { T prev = v.load(std::memory_order_relaxed); while(prev > min_v && !v.compare_exchange_weak(prev, min_v, std::memory_order_relaxed, std::memory_order_relaxed)) { } } } // end of namespace tf -----------------------------------------------------