7
7
#ifndef _MINISKETCH_INT_UTILS_H_
8
8
#define _MINISKETCH_INT_UTILS_H_
9
9
10
+ #include < stdint.h>
10
11
#include < stdlib.h>
11
12
12
13
#include < limits>
13
14
#include < algorithm>
14
15
#include < type_traits>
15
16
16
- #ifdef _MSC_VER
17
+ #if defined(__cpp_lib_int_pow2) && __cpp_lib_int_pow2 >= 202002L
18
+ # include < bit>
19
+ #elif defined(_MSC_VER)
17
20
# include < intrin.h>
18
21
#endif
19
22
@@ -54,11 +57,10 @@ class BitWriter {
54
57
int offset = 0 ;
55
58
unsigned char * out;
56
59
57
- public:
58
- BitWriter (unsigned char * output) : out(output) {}
59
-
60
60
template <int BITS, typename I>
61
- inline void Write (I val) {
61
+ inline void WriteInner (I val) {
62
+ // We right shift by up to 8 bits below. Verify that's well defined for the type I.
63
+ static_assert (std::numeric_limits<I>::digits > 8 , " BitWriter::WriteInner needs I > 8 bits" );
62
64
int bits = BITS;
63
65
if (bits + offset >= 8 ) {
64
66
state |= ((val & ((I (1 ) << (8 - offset)) - 1 )) << offset);
@@ -77,6 +79,19 @@ class BitWriter {
77
79
offset += bits;
78
80
}
79
81
82
+
83
+ public:
84
+ BitWriter (unsigned char * output) : out(output) {}
85
+
86
+ template <int BITS, typename I>
87
+ inline void Write (I val) {
88
+ // If I is smaller than an unsigned int, invoke WriteInner with argument converted to unsigned.
89
+ using compute_type = typename std::conditional<
90
+ (std::numeric_limits<I>::digits < std::numeric_limits<unsigned >::digits),
91
+ unsigned , I>::type;
92
+ return WriteInner<BITS, compute_type>(val);
93
+ }
94
+
80
95
inline void Flush () {
81
96
if (offset) {
82
97
*(out++) = state;
@@ -129,7 +144,11 @@ constexpr inline I Mask() { return ((I((I(-1)) << (std::numeric_limits<I>::digit
129
144
/* * Compute the smallest power of two that is larger than val. */
130
145
template <typename I>
131
146
static inline int CountBits (I val, int max) {
132
- #ifdef _MSC_VER
147
+ #if defined(__cpp_lib_int_pow2) && __cpp_lib_int_pow2 >= 202002L
148
+ // c++20 impl
149
+ (void )max;
150
+ return std::bit_width (val);
151
+ #elif defined(_MSC_VER)
133
152
(void )max;
134
153
unsigned long index ;
135
154
unsigned char ret;
@@ -175,6 +194,7 @@ class BitsInt {
175
194
}
176
195
177
196
static constexpr inline bool IsZero (I a) { return a == 0 ; }
197
+ static constexpr inline bool IsOne (I a) { return a == 1 ; }
178
198
static constexpr inline I Mask (I val) { return val & MASK; }
179
199
static constexpr inline I Shift (I val, int bits) { return ((val << bits) & MASK); }
180
200
static constexpr inline I UnsafeShift (I val, int bits) { return (val << bits); }
@@ -233,7 +253,7 @@ template<typename I, int N, typename L, typename F> inline constexpr I GFMul(con
233
253
template <typename I, typename F, int BITS, uint32_t MOD>
234
254
inline I InvExtGCD (I x)
235
255
{
236
- if (F::IsZero (x)) return x;
256
+ if (F::IsZero (x) || F::IsOne (x) ) return x;
237
257
I t (0 ), newt (1 );
238
258
I r (MOD), newr = x;
239
259
int rlen = BITS + 1 , newrlen = F::Bits (newr, BITS);
0 commit comments