7 #ifndef _MINISKETCH_INT_UTILS_H_ 8 #define _MINISKETCH_INT_UTILS_H_ 14 #include <type_traits> 21 static constexpr
inline uint64_t
Rot(uint64_t x) {
return (x << bits) | (x >> (64 - bits)); }
23 static inline void SipHashRound(uint64_t& v0, uint64_t& v1, uint64_t& v2, uint64_t& v3) {
24 v0 += v1; v1 = Rot<13>(v1); v1 ^= v0;
26 v2 += v3; v3 = Rot<16>(v3); v3 ^= v2;
27 v0 += v3; v3 = Rot<21>(v3); v3 ^= v0;
28 v2 += v1; v1 = Rot<17>(v1); v1 ^= v2;
32 inline uint64_t
SipHash(uint64_t k0, uint64_t k1, uint64_t data) {
33 uint64_t v0 = 0x736f6d6570736575ULL ^ k0;
34 uint64_t v1 = 0x646f72616e646f6dULL ^ k1;
35 uint64_t v2 = 0x6c7967656e657261ULL ^ k0;
36 uint64_t v3 = 0x7465646279746573ULL ^ k1 ^ data;
40 v3 ^= 0x800000000000000ULL;
43 v0 ^= 0x800000000000000ULL;
49 return v0 ^ v1 ^ v2 ^ v3;
60 template<
int BITS,
typename I>
92 const unsigned char*
in;
97 template<
int BITS,
typename I>
108 while (
out + 8 <= bits) {
109 val |= ((I(*(
in++))) <<
out);
113 unsigned char c = *(
in++);
114 val |= (c & ((I(1) << (bits -
out)) - 1)) <<
out;
126 template<
int BITS,
typename I>
127 constexpr
inline I
Mask() {
return ((I((I(-1)) << (std::numeric_limits<I>::digits - BITS))) >> (std::numeric_limits<I>::digits - BITS)); }
136 if (std::numeric_limits<I>::digits <= 32) {
137 ret = _BitScanReverse(&index, val);
139 ret = _BitScanReverse64(&index, val);
145 if (val == 0)
return 0;
146 if (std::numeric_limits<unsigned>::digits >= std::numeric_limits<I>::digits) {
147 return std::numeric_limits<unsigned>::digits - __builtin_clz(val);
148 }
else if (std::numeric_limits<unsigned long>::digits >= std::numeric_limits<I>::digits) {
149 return std::numeric_limits<unsigned long>::digits - __builtin_clzl(val);
151 return std::numeric_limits<unsigned long long>::digits - __builtin_clzll(val);
154 while (max && (val >> (max - 1) == 0)) --max;
159 template<
typename I,
int BITS>
162 static_assert(std::is_integral<I>::value && std::is_unsigned<I>::value,
"BitsInt requires an unsigned integer type");
163 static_assert(BITS > 0 && BITS <= std::numeric_limits<I>::digits,
"BitsInt requires 1 <= Bits <= representation type size");
165 static constexpr I
MASK = Mask<BITS, I>();
171 static constexpr
int SIZE = BITS;
173 static void inline Swap(I& a, I& b) {
177 static constexpr
inline bool IsZero(I a) {
return a == 0; }
178 static constexpr
inline I
Mask(I val) {
return val &
MASK; }
179 static constexpr
inline I
Shift(I val,
int bits) {
return ((val << bits) &
MASK); }
180 static constexpr
inline I
UnsafeShift(I val,
int bits) {
return (val << bits); }
182 template<
int Offset,
int Count>
184 static_assert(Count > 0,
"BITSInt::MidBits needs Count > 0");
185 static_assert(Count + Offset <= BITS,
"BitsInt::MidBits overflow of Count+Offset");
186 return (val >> Offset) & ((I(1) << Count) - 1);
191 static_assert(Count > 0,
"BitsInt::TopBits needs Count > 0");
192 static_assert(Count <= BITS,
"BitsInt::TopBits needs Offset <= BITS");
193 return val >> (BITS - Count);
197 return val ^ (-I(cond) & v);
202 return val ^ (-I(cond) & MOD);
205 static inline int Bits(I val,
int max) {
return CountBits<I>(val, max); }
209 template<
typename F, u
int32_t MOD>
211 typedef typename F::Repr
I;
213 static inline constexpr
I Call(
const I& a) {
214 return F::template CondXorWith<MOD>(F::Shift(a, 1), F::template TopBits<1>(a));
219 template<
typename I,
int N,
typename L,
typename F,
int K>
struct GFMulHelper;
220 template<
typename I,
int N,
typename L,
typename F>
struct GFMulHelper<I, N, L, F, 0>
222 static inline constexpr I
Run(
const I& a,
const I& b) {
return I(0); }
224 template<
typename I,
int N,
typename L,
typename F,
int K>
struct GFMulHelper 233 template<
typename I,
typename F,
int BITS, u
int32_t MOD>
236 if (F::IsZero(x))
return x;
239 int rlen = BITS + 1, newrlen = F::Bits(newr, BITS);
241 int q = rlen - newrlen;
242 r ^= F::Shift(newr, q);
243 t ^= F::UnsafeShift(newt, q);
244 rlen = F::Bits(r, rlen - 1);
248 std::swap(rlen, newrlen);
259 template<
typename I,
typename F,
int BITS, I (*MUL)(I, I), I (*SQR)(I), I (*SQR2)(I), I(*SQR4)(I), I(*SQR8)(I), I(*SQR16)(I)>
262 static constexpr
int INV_EXP = BITS - 1;
263 I x2 = (INV_EXP >= 2) ? MUL(SQR(x1), x1) : I();
264 I x4 = (INV_EXP >= 4) ? MUL(SQR2(x2), x2) : I();
265 I x8 = (INV_EXP >= 8) ? MUL(SQR4(x4), x4) : I();
266 I x16 = (INV_EXP >= 16) ? MUL(SQR8(x8), x8) : I();
267 I x32 = (INV_EXP >= 32) ? MUL(SQR16(x16), x16) : I();
271 }
else if (INV_EXP >= 16) {
273 }
else if (INV_EXP >= 8) {
275 }
else if (INV_EXP >= 4) {
277 }
else if (INV_EXP >= 2) {
282 if (INV_EXP >= 32 && (INV_EXP & 16)) r = MUL(SQR16(r), x16);
283 if (INV_EXP >= 16 && (INV_EXP & 8)) r = MUL(SQR8(r), x8);
284 if (INV_EXP >= 8 && (INV_EXP & 4)) r = MUL(SQR4(r), x4);
285 if (INV_EXP >= 4 && (INV_EXP & 2)) r = MUL(SQR2(r), x2);
286 if (INV_EXP >= 2 && (INV_EXP & 1)) r = MUL(SQR(r), x1);
static constexpr I Run(const I &a, const I &b)
static constexpr I Call(const I &a)
Shift a value a up once, treating it as an N-bit LFSR, with pattern MOD.
static void SipHashRound(uint64_t &v0, uint64_t &v1, uint64_t &v2, uint64_t &v3)
I InvLadder(I x1)
Compute the inverse of x1 using an exponentiation ladder.
uint64_t SipHash(uint64_t k0, uint64_t k1, uint64_t data)
static constexpr I UnsafeShift(I val, int bits)
Helper class for carryless multiplications.
static constexpr bool IsZero(I a)
Class which implements a stateless LFSR for generic moduli.
I InvExtGCD(I x)
Compute the inverse of x using an extgcd algorithm.
constexpr I Mask()
Return a value of type I with its bits lowest bits set (bits must be > 0).
static constexpr I Shift(I val, int bits)
BitReader(const unsigned char *input)
constexpr I GFMul(const I &a, const I &b)
Compute the carry-less multiplication of a and b, with N bits, using L as LFSR type.
static void Swap(I &a, I &b)
BitWriter(unsigned char *output)
static constexpr int SIZE
static constexpr I CondXorWith(I val, bool cond, I v)
static int Bits(I val, int max)
static constexpr I Mask(I val)
static constexpr I CondXorWith(I val, bool cond)
static int CountBits(I val, int max)
Compute the smallest power of two that is larger than val.
static constexpr I Run(const I &a, const I &b)
static constexpr int MidBits(I val)
static constexpr int TopBits(I val)
static constexpr uint64_t Rot(uint64_t x)