-
Notifications
You must be signed in to change notification settings - Fork 3
/
radix_sort_basic_kdf.hpp
48 lines (40 loc) · 1.38 KB
/
radix_sort_basic_kdf.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
/*
Key-Derivation Functions
See also: https://github.com/eloj/radix-sorting
*/
#pragma once
#include <type_traits>
#include <algorithm>
namespace basic_kdfs {
// Helper template to return an unsigned T with the MSB set.
template<typename T>
std::enable_if_t<std::is_integral_v<T>, typename std::make_unsigned_t<T>>
constexpr highbit(void) {
return 1ULL << ((sizeof(T) << 3) - 1);
}
template<typename T, typename KT=T>
std::enable_if_t<std::is_integral_v<T> && std::is_unsigned_v<T> && !std::is_same_v<T,bool>, KT>
kdf(const T& value) {
return value;
};
// The std::conditional is needed because std::make_unsigned<T> does not support non-integral types
template<typename T, typename KT=std::conditional<std::is_integral_v<T>,std::make_unsigned<T>,std::common_type<T>>>
std::enable_if_t<std::is_integral_v<T> && std::is_signed_v<T> && !std::is_same_v<T,bool>, typename KT::type::type>
kdf(const T& value) {
return value ^ highbit<T>();
}
template<typename T, typename KT=uint32_t>
std::enable_if_t<std::is_same_v<T,float>, KT>
kdf(const T& value) {
KT local;
std::memcpy(&local, &value, sizeof(local));
return local ^ (-(local >> 31UL) | (1UL << 31UL));
}
template<typename T, typename KT=uint64_t>
std::enable_if_t<std::is_same_v<T,double>, KT>
kdf(const T& value) {
KT local;
std::memcpy(&local, &value, sizeof(local));
return local ^ (-(local >> 63UL) | (1UL << 63UL));
}
} // namespace