#ifndef CPU_RAZE
#define CPU_RAZE
template <typename T>
static inline bool h_RAZE(int& csize, byte in [CS], byte out [CS])
{
const int size = csize / sizeof(T); const int extra = csize % sizeof(T); const int bits = 8 * sizeof(T); T* const in_t = (T*)in; T* const out_t = (T*)out;
int count [bits + 1]; for (int i = 0; i < bits; i++) count[i] = 0; int zeros = 0;
for (int i = 0; i < size; i++) {
const T val = in_t[i];
if (val == 0) zeros++;
const int keep = (val == 0) ? 0 : (64 - __builtin_clzll((long long)val));
count[keep]++;
}
if (zeros == size) {
if constexpr (sizeof(T) > 1) {
for (int i = 0; i < extra; i++) {
out[i] = in[csize - extra + i];
}
}
out[extra] = bits + 1; out[extra + 1] = csize; out[extra + 2] = csize >> 8; csize = extra + 3;
return true;
}
int pfs = count[0];
int saved = bits * pfs;
int keep = 0;
int countk = pfs;
for (int i = 1; i < bits; i++) { pfs += count[i];
const int sav = (bits - i) * pfs;
if (saved < sav) {
saved = sav;
keep = i;
countk = pfs;
}
}
if (saved == 0) {
if (csize + 3 >= CS) return false;
memcpy(out, in, csize);
out[csize] = bits; out[csize + 1] = csize; out[csize + 2] = csize >> 8; csize = csize + 3;
return true;
}
assert(CS == 16384);
const int num = (2048 + 256 + 32 + 4) / sizeof(T);
byte bitmap [num];
const T tmask = ~(T)0 << keep; const T bmask = ~tmask; int wpos1 = 0;
int wpos2 = size - countk;
int wloc2 = bits * wpos2;
T oval = 0;
byte bmp = 0;
for (int i = 0; i < size; i++) {
const T val = in_t[i];
if (0 != (val & tmask)) {
bmp |= 1 << (i % 8);
out_t[wpos1++] = val; } else {
if (keep != 0) {
const T bval = val & bmask;
const int shift = wloc2 % bits;
const int bms = bits - shift;
oval |= bval << shift;
if (bms <= keep) {
out_t[wpos2++] = oval;
oval = bval >> bms;
}
wloc2 += keep;
}
}
if ((i % 8) == 7) {
bitmap[i / 8] = bmp;
bmp = 0;
}
}
if ((wloc2 % bits) != 0) {
out_t[wpos2] = oval;
}
if ((size % 8) != 0) {
bitmap[size / 8] = bmp;
}
for (int i = (size + 7) / 8; i < CS / bits; i++) {
bitmap[i] = 0;
}
int wpos = (wloc2 + 7) / 8;
int base = 0;
int range = CS / bits;
while (range >= 8) { byte prev = 0;
for (int i = 0; i < range; i += 8) {
const long long lval = *((long long*)(&bitmap[base + i]));
byte bmp = 0;
for (int j = 0; j < 8; j++) {
const byte val = (lval >> (j * 8)) & 0xff;
if (val != prev) {
out[wpos++] = prev = val;
bmp |= 1 << j;
if (wpos >= CS - 3 - extra) return false;
}
}
bitmap[base + range + i / 8] = bmp;
}
base += range;
range /= 8;
}
if (wpos >= CS - 3 - extra - range) return false;
for (int i = 0; i < range; i++) {
out[wpos++] = bitmap[base + i];
}
if constexpr (sizeof(T) > 1) {
for (int i = 0; i < extra; i++) {
out[wpos++] = in[csize - extra + i];
}
}
out[wpos++] = keep; out[wpos++] = csize; out[wpos++] = csize >> 8; csize = wpos;
return true;
}
template <typename T>
static inline void h_iRAZE(int& csize, byte in [CS], byte out [CS])
{
const int oldsize = in[csize - 2] + ((int)in[csize - 1] << 8);
const int keep = in[csize - 3];
const int bits = 8 * sizeof(T); const int size = oldsize / sizeof(T); const int extra = oldsize % sizeof(T); T* const in_t = (T*)in; T* const out_t = (T*)out;
if (keep == bits + 1) { memset(out, 0, oldsize - extra);
} else if (keep == bits) { memcpy(out, in, oldsize - extra);
} else { int base = 0;
int range = CS / bits;
while (range >= 8) {
base += range;
range /= 8;
}
assert(CS == 16384);
const int num = (2048 + 256 + 32 + 4) / sizeof(T);
byte bitmap [num];
int count = 0;
int rpos = csize - 3 - extra - range;
for (int i = 0; i < range; i++) {
const T val = in[rpos + i];
bitmap[base + i] = val;
count += __builtin_popcount((int)val);
}
while (range < CS / bits) {
range *= 8;
base -= range;
rpos -= count;
int pos = rpos;
byte val = 0;
count = 0;
assert(range % 8 == 0);
for (int i = 0; i < range; i += 8) {
const byte bmp = bitmap[base + range + i / 8];
for (int j = 0; j < 8; j++) {
if ((bmp >> j) & 1) {
val = in[pos++];
}
bitmap[base + i + j] = val;
count += __builtin_popcount((int)val);
}
}
}
const T tmask = ~(T)0 << keep; const T bmask = ~tmask; int rpos1 = 0;
int rloc2 = bits * count;
int rpos2 = rloc2 / bits;
T ival = in_t[rpos2++];
byte bmp;
for (int i = 0; i < size; i++) {
T val = 0;
if ((i % 8) == 0) bmp = bitmap[i / 8];
if ((bmp >> (i % 8)) & 1) {
val = in_t[rpos1++]; } else {
if (keep != 0) {
const int shift = rloc2 % bits;
const int bms = bits - shift;
T res = ival >> shift;
if (bms <= keep) {
ival = in_t[rpos2++];
res |= ival << bms;
}
rloc2 += keep;
val = res & bmask;
}
}
out_t[i] = val;
}
}
if constexpr (sizeof(T) > 1) {
for (int i = 0; i < extra; i++) {
out[oldsize - extra + i] = in[csize - 3 - extra + i];
}
}
csize = oldsize;
}
#endif