#ifndef CPU_RLE
#define CPU_RLE
template <typename T>
static inline bool h_RLE(int& csize, byte in [CS], byte out [CS])
{
T* const in_t = (T*)in;
T* const out_t = (T*)out;
byte counts [CS / sizeof(T)]; const int elems = csize / sizeof(T);
const int extra = csize % sizeof(T);
int cpos = 0; int vpos = 0;
T prev = ~in_t[0];
int repeat = 0;
int nrepeat = 0;
for (int i = 0; i < elems; i++) {
const T curr = in_t[i];
if (prev != curr) { prev = curr;
out_t[vpos++] = curr; nrepeat++;
while (repeat > 0) {
const int rep = std::min(128, repeat);
counts[cpos++] = 0x80 | (rep - 1);
repeat -= rep;
}
} else { repeat++;
while (nrepeat > 0) {
const int nrep = std::min(128, nrepeat);
counts[cpos++] = nrep - 1;
nrepeat -= nrep;
}
}
}
while (repeat > 0) {
const int rep = std::min(128, repeat);
counts[cpos++] = 0x80 | (rep - 1);
repeat -= rep;
}
while (nrepeat > 0) {
const int nrep = std::min(128, nrepeat);
counts[cpos++] = nrep - 1;
nrepeat -= nrep;
}
int wpos = vpos * sizeof(T);
const int newsize = wpos + cpos + extra + 2;
if (newsize >= CS) return false;
for (int j = 0; j < extra; j++) {
out[wpos++] = in[csize - extra + j];
}
for (int j = 0; j < cpos; j++) {
out[wpos + j] = counts[j];
}
out[newsize - 2] = wpos & 0xff;
out[newsize - 1] = (wpos >> 8) & 0xff;
csize = newsize;
return true;
}
template <typename T>
static inline void h_iRLE(int& csize, byte in [CS], byte out[CS])
{
T* const in_t = (T*)in;
T* const out_t = (T*)out;
const int cpos = (((int)in[csize - 1]) << 8) | in[csize - 2];
const int extra = cpos % sizeof(T);
int wpos = 0; int vpos = 0; T val = 0;
for (int i = cpos; i < csize - 2; i++) {
const int rep = in[i]; if (rep & 0x80) {
const int repeat = (rep & 0x7f) + 1;
for (int j = 0; j < repeat; j++) {
out_t[wpos++] = val;
}
} else {
const int nrepeat = rep + 1;
for (int j = 0; j < nrepeat; j++) {
val = in_t[vpos++];
out_t[wpos++] = val;
}
}
}
wpos *= sizeof(T);
for (int j = 0; j < extra; j++) {
out[wpos++] = in[cpos - extra + j];
}
csize = wpos;
}
#endif