#ifndef CPU_CLOG
#define CPU_CLOG
template <typename T>
static inline bool h_CLOG(int& csize, byte in [CS], byte out [CS])
{
assert(std::is_unsigned<T>::value);
const int TB = sizeof(T) * 8; const int SC = 32; const int CB = (32 - __builtin_clz(sizeof(T))) + 3; assert((1 << CB) > TB);
assert((1 << (CB - 1)) <= TB);
T* in_t = (T*)in;
T* out_t = (T*)out;
const int size = csize / sizeof(T);
byte ln [SC];
int bits = 0;
int end = 0;
for (int i = 0; i < SC; i++) {
const int beg = end;
end = (i + 1) * size / SC;
T max_val = 0;
for (int j = beg; j < end; j++) {
max_val = std::max(max_val, in_t[j]);
}
int cnt = 0;
if (max_val != 0) {
cnt = (sizeof(T) == 8) ? (sizeof(unsigned long long) * 8 - __builtin_clzll((unsigned long long)max_val)) : (sizeof(unsigned int) * 8 - __builtin_clz((unsigned int)max_val));
}
bits += cnt * (end - beg);
ln[i] = cnt;
}
const int extra = csize % sizeof(T);
const int newsize = (16 + CB * SC + bits + 7) / 8;
if (newsize + extra >= CS) return false;
memset(out_t, 0, newsize);
out[0] = csize & 0xFF;
out[1] = csize >> 8;
int loc = 16;
for (int i = 0; i < SC; i++) {
const T val = ln[i];
const int pos = loc / TB;
const int shift = loc % TB;
out_t[pos] |= val << shift;
if (TB - CB < shift) {
out_t[pos + 1] = val >> (TB - shift);
}
loc += CB;
}
end = 0;
for (int i = 0; i < SC; i++) {
const int logn = ln[i];
const int beg = end;
end = (i + 1) * size / SC;
for (int j = beg; j < end; j++) {
const T val = in_t[j];
const int pos = loc / TB;
const int shift = loc % TB;
out_t[pos] |= val << shift;
if (TB - logn < shift) {
out_t[pos + 1] = val >> (TB - shift);
}
loc += logn;
}
}
for (int i = 0; i < extra; i++) out[newsize + i] = in[csize - extra + i];
csize = newsize + extra;
return true;
}
template <typename T>
static inline void h_iCLOG(int& csize, byte in [CS], byte out [CS])
{
assert(std::is_unsigned<T>::value);
const int TB = sizeof(T) * 8; const int SC = 32; const int CB = (32 - __builtin_clz(sizeof(T))) + 3; assert((1 << CB) > TB);
assert((1 << (CB - 1)) <= TB);
T* in_t = (T*)in;
T* out_t = (T*)out;
byte ln [SC];
int loc = 16;
const T mask = ((1 << CB) - 1);
for (int i = 0; i < SC; i++) {
const int pos = loc / TB;
const int shift = loc % TB;
T res = in_t[pos] >> shift;
if (TB - CB < shift) {
res |= in_t[pos + 1] << (TB - shift);
}
ln[i] = res & mask;
loc += CB;
}
const int orig_csize = *((unsigned short*)in);
const int size = orig_csize / sizeof(T);
int end = 0;
for (int i = 0; i < SC; i++) {
const int logn = ln[i];
const int beg = end;
end = (i + 1) * size / SC;
const T mask = (sizeof(T) < 8) ? ((1ULL << logn) - 1) : ((logn == 64) ? (~0ULL) : ((1ULL << logn) - 1));
for (int j = beg; j < end; j++) {
const int pos = loc / TB;
const int shift = loc % TB;
T res = in_t[pos] >> shift;
if (TB - logn < shift) {
res |= in_t[pos + 1] << (TB - shift);
}
out_t[j] = res & mask;
loc += logn;
}
}
const int extra = orig_csize % sizeof(T);
for (int i = 0; i < extra; i++) out[orig_csize - extra + i] = in[csize - extra + i];
csize = orig_csize;
}
#endif