p7zip-rar/CPP/7zip/Compress/Mtf8.h
2017-10-11 12:40:22 +02:00

192 lines
3.8 KiB
C++

// Mtf8.h
#ifndef __COMPRESS_MTF8_H
#define __COMPRESS_MTF8_H
#include "../../../C/CpuArch.h"
namespace NCompress {
struct CMtf8Encoder
{
Byte Buf[256];
unsigned FindAndMove(Byte v)
{
unsigned pos;
for (pos = 0; Buf[pos] != v; pos++);
unsigned resPos = pos;
for (; pos >= 8; pos -= 8)
{
Buf[pos] = Buf[pos - 1];
Buf[pos - 1] = Buf[pos - 2];
Buf[pos - 2] = Buf[pos - 3];
Buf[pos - 3] = Buf[pos - 4];
Buf[pos - 4] = Buf[pos - 5];
Buf[pos - 5] = Buf[pos - 6];
Buf[pos - 6] = Buf[pos - 7];
Buf[pos - 7] = Buf[pos - 8];
}
for (; pos != 0; pos--)
Buf[pos] = Buf[pos - 1];
Buf[0] = v;
return resPos;
}
};
/*
struct CMtf8Decoder
{
Byte Buf[256];
void Init(int) {};
Byte GetHead() const { return Buf[0]; }
Byte GetAndMove(int pos)
{
Byte res = Buf[pos];
for (; pos >= 8; pos -= 8)
{
Buf[pos] = Buf[pos - 1];
Buf[pos - 1] = Buf[pos - 2];
Buf[pos - 2] = Buf[pos - 3];
Buf[pos - 3] = Buf[pos - 4];
Buf[pos - 4] = Buf[pos - 5];
Buf[pos - 5] = Buf[pos - 6];
Buf[pos - 6] = Buf[pos - 7];
Buf[pos - 7] = Buf[pos - 8];
}
for (; pos > 0; pos--)
Buf[pos] = Buf[pos - 1];
Buf[0] = res;
return res;
}
};
*/
#ifdef MY_CPU_64BIT
typedef UInt64 CMtfVar;
#define MTF_MOVS 3
#else
typedef UInt32 CMtfVar;
#define MTF_MOVS 2
#endif
#define MTF_MASK ((1 << MTF_MOVS) - 1)
struct CMtf8Decoder
{
CMtfVar Buf[256 >> MTF_MOVS];
void StartInit() { memset(Buf, 0, sizeof(Buf)); }
void Add(unsigned pos, Byte val) { Buf[pos >> MTF_MOVS] |= ((CMtfVar)val << ((pos & MTF_MASK) << 3)); }
Byte GetHead() const { return (Byte)Buf[0]; }
Byte GetAndMove(unsigned pos)
{
UInt32 lim = ((UInt32)pos >> MTF_MOVS);
pos = (pos & MTF_MASK) << 3;
CMtfVar prev = (Buf[lim] >> pos) & 0xFF;
UInt32 i = 0;
if ((lim & 1) != 0)
{
CMtfVar next = Buf[0];
Buf[0] = (next << 8) | prev;
prev = (next >> (MTF_MASK << 3));
i = 1;
lim -= 1;
}
for (; i < lim; i += 2)
{
CMtfVar n0 = Buf[i];
CMtfVar n1 = Buf[i + 1];
Buf[i ] = (n0 << 8) | prev;
Buf[i + 1] = (n1 << 8) | (n0 >> (MTF_MASK << 3));
prev = (n1 >> (MTF_MASK << 3));
}
CMtfVar next = Buf[i];
CMtfVar mask = (((CMtfVar)0x100 << pos) - 1);
Buf[i] = (next & ~mask) | (((next << 8) | prev) & mask);
return (Byte)Buf[0];
}
};
/*
const int kSmallSize = 64;
class CMtf8Decoder
{
Byte SmallBuffer[kSmallSize];
int SmallSize;
Byte Counts[16];
int Size;
public:
Byte Buf[256];
Byte GetHead() const
{
if (SmallSize > 0)
return SmallBuffer[kSmallSize - SmallSize];
return Buf[0];
}
void Init(int size)
{
Size = size;
SmallSize = 0;
for (int i = 0; i < 16; i++)
{
Counts[i] = ((size >= 16) ? 16 : size);
size -= Counts[i];
}
}
Byte GetAndMove(int pos)
{
if (pos < SmallSize)
{
Byte *p = SmallBuffer + kSmallSize - SmallSize;
Byte res = p[pos];
for (; pos > 0; pos--)
p[pos] = p[pos - 1];
SmallBuffer[kSmallSize - SmallSize] = res;
return res;
}
if (SmallSize == kSmallSize)
{
int i = Size - 1;
int g = 16;
do
{
g--;
int offset = (g << 4);
for (int t = Counts[g] - 1; t >= 0; t--, i--)
Buf[i] = Buf[offset + t];
}
while (g != 0);
for (i = kSmallSize - 1; i >= 0; i--)
Buf[i] = SmallBuffer[i];
Init(Size);
}
pos -= SmallSize;
int g;
for (g = 0; pos >= Counts[g]; g++)
pos -= Counts[g];
int offset = (g << 4);
Byte res = Buf[offset + pos];
for (pos; pos < 16 - 1; pos++)
Buf[offset + pos] = Buf[offset + pos + 1];
SmallSize++;
SmallBuffer[kSmallSize - SmallSize] = res;
Counts[g]--;
return res;
}
};
*/
}
#endif