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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111 | #pragma once
#include <limits><--- Include file: not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <concepts><--- Include file: not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <cstdint><--- Include file: not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include "internal/dev_env.hpp"
#include "internal/types.hpp"
#include "numeric/bit.hpp"
namespace uni {
template<std::unsigned_integral R, std::integral T>
constexpr R shrink(T x) noexcept(NO_EXCEPT) {
constexpr int DIGITS_R = std::numeric_limits<R>::digits;<--- 'DIGITS_R' is assigned value 'std::numeric_limits::digits' here.
constexpr int DIGITS_T = std::numeric_limits<R>::digits;<--- 'DIGITS_T' is assigned value 'std::numeric_limits::digits' here.
REPD(digits, DIGITS_R, DIGITS_T, DIGITS_R) {<--- Same expression on both sides of '-'. [+]Finding the same expression on both sides of an operator is suspicious and might indicate a cut and paste or logic error. Please examine this code carefully to determine if it is correct.
x = (x >> digits) ^ uni::lower_bits(x, digits);
}
return x;
}
// Thanks to: https://gist.github.com/badboy/6267743
template<class T>
constexpr u32 hash32(T x) {
if constexpr(std::integral<T>) {
if constexpr(std::signed_integral<T>) return hash32(to_unsigned(x));
constexpr int DIGITS_T = std::numeric_limits<T>::digits;
if constexpr(DIGITS_T <= 32) {
auto h = static_cast<u32>(x);
h = ~h + (h << 15);
h ^= (h >> 12);
h += (h << 2);
h ^= (h >> 4);
h *= 2057;
h ^= (h >> 16);
return h;
}
else if constexpr(DIGITS_T <= 64) {
auto h = static_cast<u64>(x);
h = (~h) + (h << 18);
h ^= (h >> 31);
h *= 21;
h ^= (h >> 11);
h += (h << 6);
h ^= (h >> 22);
return static_cast<u32>(h);
}
else {
return hash32(hash64(x));
}
}
else {
return hash32(std::hash<T>{}(x));
}
}
template<class T>
constexpr u64 hash64(T x) {
if constexpr(std::integral<T>) {
if constexpr(std::signed_integral<T>) return hash64(to_unsigned(x));
constexpr int DIGITS_T = std::numeric_limits<T>::digits;
if constexpr(DIGITS_T <= 64) {
auto h = static_cast<u64>(x);
h = (~h) + (h << 21);
h ^= (h >> 24);
h *= 265;
h ^= (h >> 14);
h *= 21;
h ^= (h >> 28);
h += h << 31;
return h;
}
else {
return hash64(shrink<u64>(x));
}
}
else {
return hash64(std::hash<T>{}(x));
}
}
template<class T>
struct hash {
inline constexpr auto operator()(const T& key) const noexcept(NO_EXCEPT) {
return static_cast<std::size_t>(uni::hash64(key));
}
};
} // namespace uni
|