xref: /aosp_15_r20/external/lzma/CPP/7zip/Compress/Mtf8.h (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1*f6dc9357SAndroid Build Coastguard Worker // Mtf8.h
2*f6dc9357SAndroid Build Coastguard Worker 
3*f6dc9357SAndroid Build Coastguard Worker #ifndef ZIP7_INC_COMPRESS_MTF8_H
4*f6dc9357SAndroid Build Coastguard Worker #define ZIP7_INC_COMPRESS_MTF8_H
5*f6dc9357SAndroid Build Coastguard Worker 
6*f6dc9357SAndroid Build Coastguard Worker #include "../../../C/CpuArch.h"
7*f6dc9357SAndroid Build Coastguard Worker 
8*f6dc9357SAndroid Build Coastguard Worker namespace NCompress {
9*f6dc9357SAndroid Build Coastguard Worker 
10*f6dc9357SAndroid Build Coastguard Worker struct CMtf8Encoder
11*f6dc9357SAndroid Build Coastguard Worker {
12*f6dc9357SAndroid Build Coastguard Worker   Byte Buf[256];
13*f6dc9357SAndroid Build Coastguard Worker 
FindAndMoveCMtf8Encoder14*f6dc9357SAndroid Build Coastguard Worker   unsigned FindAndMove(Byte v) throw()
15*f6dc9357SAndroid Build Coastguard Worker   {
16*f6dc9357SAndroid Build Coastguard Worker     size_t pos;
17*f6dc9357SAndroid Build Coastguard Worker     for (pos = 0; Buf[pos] != v; pos++);
18*f6dc9357SAndroid Build Coastguard Worker     const unsigned resPos = (unsigned)pos;
19*f6dc9357SAndroid Build Coastguard Worker     for (; pos >= 8; pos -= 8)
20*f6dc9357SAndroid Build Coastguard Worker     {
21*f6dc9357SAndroid Build Coastguard Worker       Buf[pos] = Buf[pos - 1];
22*f6dc9357SAndroid Build Coastguard Worker       Buf[pos - 1] = Buf[pos - 2];
23*f6dc9357SAndroid Build Coastguard Worker       Buf[pos - 2] = Buf[pos - 3];
24*f6dc9357SAndroid Build Coastguard Worker       Buf[pos - 3] = Buf[pos - 4];
25*f6dc9357SAndroid Build Coastguard Worker       Buf[pos - 4] = Buf[pos - 5];
26*f6dc9357SAndroid Build Coastguard Worker       Buf[pos - 5] = Buf[pos - 6];
27*f6dc9357SAndroid Build Coastguard Worker       Buf[pos - 6] = Buf[pos - 7];
28*f6dc9357SAndroid Build Coastguard Worker       Buf[pos - 7] = Buf[pos - 8];
29*f6dc9357SAndroid Build Coastguard Worker     }
30*f6dc9357SAndroid Build Coastguard Worker     for (; pos != 0; pos--)
31*f6dc9357SAndroid Build Coastguard Worker       Buf[pos] = Buf[pos - 1];
32*f6dc9357SAndroid Build Coastguard Worker     Buf[0] = v;
33*f6dc9357SAndroid Build Coastguard Worker     return resPos;
34*f6dc9357SAndroid Build Coastguard Worker   }
35*f6dc9357SAndroid Build Coastguard Worker };
36*f6dc9357SAndroid Build Coastguard Worker 
37*f6dc9357SAndroid Build Coastguard Worker /*
38*f6dc9357SAndroid Build Coastguard Worker struct CMtf8Decoder
39*f6dc9357SAndroid Build Coastguard Worker {
40*f6dc9357SAndroid Build Coastguard Worker   Byte Buf[256];
41*f6dc9357SAndroid Build Coastguard Worker 
42*f6dc9357SAndroid Build Coastguard Worker   void StartInit() { memset(Buf, 0, sizeof(Buf)); }
43*f6dc9357SAndroid Build Coastguard Worker   void Add(unsigned pos, Byte val) { Buf[pos] = val;  }
44*f6dc9357SAndroid Build Coastguard Worker   Byte GetHead() const { return Buf[0]; }
45*f6dc9357SAndroid Build Coastguard Worker   Byte GetAndMove(unsigned pos)
46*f6dc9357SAndroid Build Coastguard Worker   {
47*f6dc9357SAndroid Build Coastguard Worker     Byte res = Buf[pos];
48*f6dc9357SAndroid Build Coastguard Worker     for (; pos >= 8; pos -= 8)
49*f6dc9357SAndroid Build Coastguard Worker     {
50*f6dc9357SAndroid Build Coastguard Worker       Buf[pos] = Buf[pos - 1];
51*f6dc9357SAndroid Build Coastguard Worker       Buf[pos - 1] = Buf[pos - 2];
52*f6dc9357SAndroid Build Coastguard Worker       Buf[pos - 2] = Buf[pos - 3];
53*f6dc9357SAndroid Build Coastguard Worker       Buf[pos - 3] = Buf[pos - 4];
54*f6dc9357SAndroid Build Coastguard Worker       Buf[pos - 4] = Buf[pos - 5];
55*f6dc9357SAndroid Build Coastguard Worker       Buf[pos - 5] = Buf[pos - 6];
56*f6dc9357SAndroid Build Coastguard Worker       Buf[pos - 6] = Buf[pos - 7];
57*f6dc9357SAndroid Build Coastguard Worker       Buf[pos - 7] = Buf[pos - 8];
58*f6dc9357SAndroid Build Coastguard Worker     }
59*f6dc9357SAndroid Build Coastguard Worker     for (; pos > 0; pos--)
60*f6dc9357SAndroid Build Coastguard Worker       Buf[pos] = Buf[pos - 1];
61*f6dc9357SAndroid Build Coastguard Worker     Buf[0] = res;
62*f6dc9357SAndroid Build Coastguard Worker     return res;
63*f6dc9357SAndroid Build Coastguard Worker   }
64*f6dc9357SAndroid Build Coastguard Worker };
65*f6dc9357SAndroid Build Coastguard Worker */
66*f6dc9357SAndroid Build Coastguard Worker 
67*f6dc9357SAndroid Build Coastguard Worker #ifdef MY_CPU_64BIT
68*f6dc9357SAndroid Build Coastguard Worker   typedef UInt64 CMtfVar;
69*f6dc9357SAndroid Build Coastguard Worker   #define Z7_MTF_MOVS 3
70*f6dc9357SAndroid Build Coastguard Worker #else
71*f6dc9357SAndroid Build Coastguard Worker   typedef UInt32 CMtfVar;
72*f6dc9357SAndroid Build Coastguard Worker   #define Z7_MTF_MOVS 2
73*f6dc9357SAndroid Build Coastguard Worker #endif
74*f6dc9357SAndroid Build Coastguard Worker 
75*f6dc9357SAndroid Build Coastguard Worker #define Z7_MTF_MASK ((1 << Z7_MTF_MOVS) - 1)
76*f6dc9357SAndroid Build Coastguard Worker 
77*f6dc9357SAndroid Build Coastguard Worker 
78*f6dc9357SAndroid Build Coastguard Worker struct CMtf8Decoder
79*f6dc9357SAndroid Build Coastguard Worker {
80*f6dc9357SAndroid Build Coastguard Worker   CMtfVar Buf[256 >> Z7_MTF_MOVS];
81*f6dc9357SAndroid Build Coastguard Worker 
StartInitCMtf8Decoder82*f6dc9357SAndroid Build Coastguard Worker   void StartInit() { memset(Buf, 0, sizeof(Buf)); }
AddCMtf8Decoder83*f6dc9357SAndroid Build Coastguard Worker   void Add(unsigned pos, Byte val) { Buf[pos >> Z7_MTF_MOVS] |= ((CMtfVar)val << ((pos & Z7_MTF_MASK) << 3));  }
GetHeadCMtf8Decoder84*f6dc9357SAndroid Build Coastguard Worker   Byte GetHead() const { return (Byte)Buf[0]; }
85*f6dc9357SAndroid Build Coastguard Worker 
86*f6dc9357SAndroid Build Coastguard Worker   Z7_FORCE_INLINE
GetAndMoveCMtf8Decoder87*f6dc9357SAndroid Build Coastguard Worker   Byte GetAndMove(unsigned pos) throw()
88*f6dc9357SAndroid Build Coastguard Worker   {
89*f6dc9357SAndroid Build Coastguard Worker     const UInt32 lim = ((UInt32)pos >> Z7_MTF_MOVS);
90*f6dc9357SAndroid Build Coastguard Worker     pos = (pos & Z7_MTF_MASK) << 3;
91*f6dc9357SAndroid Build Coastguard Worker     CMtfVar prev = (Buf[lim] >> pos) & 0xFF;
92*f6dc9357SAndroid Build Coastguard Worker 
93*f6dc9357SAndroid Build Coastguard Worker     UInt32 i = 0;
94*f6dc9357SAndroid Build Coastguard Worker 
95*f6dc9357SAndroid Build Coastguard Worker 
96*f6dc9357SAndroid Build Coastguard Worker     /*
97*f6dc9357SAndroid Build Coastguard Worker     if ((lim & 1) != 0)
98*f6dc9357SAndroid Build Coastguard Worker     {
99*f6dc9357SAndroid Build Coastguard Worker       CMtfVar next = Buf[0];
100*f6dc9357SAndroid Build Coastguard Worker       Buf[0] = (next << 8) | prev;
101*f6dc9357SAndroid Build Coastguard Worker       prev = (next >> (Z7_MTF_MASK << 3));
102*f6dc9357SAndroid Build Coastguard Worker       i = 1;
103*f6dc9357SAndroid Build Coastguard Worker       lim -= 1;
104*f6dc9357SAndroid Build Coastguard Worker     }
105*f6dc9357SAndroid Build Coastguard Worker     for (; i < lim; i += 2)
106*f6dc9357SAndroid Build Coastguard Worker     {
107*f6dc9357SAndroid Build Coastguard Worker       CMtfVar n0 = Buf[i];
108*f6dc9357SAndroid Build Coastguard Worker       CMtfVar n1 = Buf[i + 1];
109*f6dc9357SAndroid Build Coastguard Worker       Buf[i    ] = (n0 << 8) | prev;
110*f6dc9357SAndroid Build Coastguard Worker       Buf[i + 1] = (n1 << 8) | (n0 >> (Z7_MTF_MASK << 3));
111*f6dc9357SAndroid Build Coastguard Worker       prev = (n1 >> (Z7_MTF_MASK << 3));
112*f6dc9357SAndroid Build Coastguard Worker     }
113*f6dc9357SAndroid Build Coastguard Worker     */
114*f6dc9357SAndroid Build Coastguard Worker 
115*f6dc9357SAndroid Build Coastguard Worker     for (; i < lim; i++)
116*f6dc9357SAndroid Build Coastguard Worker     {
117*f6dc9357SAndroid Build Coastguard Worker       const CMtfVar n0 = Buf[i];
118*f6dc9357SAndroid Build Coastguard Worker       Buf[i    ] = (n0 << 8) | prev;
119*f6dc9357SAndroid Build Coastguard Worker       prev = (n0 >> (Z7_MTF_MASK << 3));
120*f6dc9357SAndroid Build Coastguard Worker     }
121*f6dc9357SAndroid Build Coastguard Worker 
122*f6dc9357SAndroid Build Coastguard Worker 
123*f6dc9357SAndroid Build Coastguard Worker     const CMtfVar next = Buf[i];
124*f6dc9357SAndroid Build Coastguard Worker     const CMtfVar mask = (((CMtfVar)0x100 << pos) - 1);
125*f6dc9357SAndroid Build Coastguard Worker     Buf[i] = (next & ~mask) | (((next << 8) | prev) & mask);
126*f6dc9357SAndroid Build Coastguard Worker     return (Byte)Buf[0];
127*f6dc9357SAndroid Build Coastguard Worker   }
128*f6dc9357SAndroid Build Coastguard Worker };
129*f6dc9357SAndroid Build Coastguard Worker 
130*f6dc9357SAndroid Build Coastguard Worker /*
131*f6dc9357SAndroid Build Coastguard Worker const int kSmallSize = 64;
132*f6dc9357SAndroid Build Coastguard Worker class CMtf8Decoder
133*f6dc9357SAndroid Build Coastguard Worker {
134*f6dc9357SAndroid Build Coastguard Worker   Byte SmallBuffer[kSmallSize];
135*f6dc9357SAndroid Build Coastguard Worker   int SmallSize;
136*f6dc9357SAndroid Build Coastguard Worker   int Counts[16];
137*f6dc9357SAndroid Build Coastguard Worker   int Size;
138*f6dc9357SAndroid Build Coastguard Worker public:
139*f6dc9357SAndroid Build Coastguard Worker   Byte Buf[256];
140*f6dc9357SAndroid Build Coastguard Worker 
141*f6dc9357SAndroid Build Coastguard Worker   Byte GetHead() const
142*f6dc9357SAndroid Build Coastguard Worker   {
143*f6dc9357SAndroid Build Coastguard Worker     if (SmallSize > 0)
144*f6dc9357SAndroid Build Coastguard Worker       return SmallBuffer[kSmallSize - SmallSize];
145*f6dc9357SAndroid Build Coastguard Worker     return Buf[0];
146*f6dc9357SAndroid Build Coastguard Worker   }
147*f6dc9357SAndroid Build Coastguard Worker 
148*f6dc9357SAndroid Build Coastguard Worker   void Init(int size)
149*f6dc9357SAndroid Build Coastguard Worker   {
150*f6dc9357SAndroid Build Coastguard Worker     Size = size;
151*f6dc9357SAndroid Build Coastguard Worker     SmallSize = 0;
152*f6dc9357SAndroid Build Coastguard Worker     for (int i = 0; i < 16; i++)
153*f6dc9357SAndroid Build Coastguard Worker     {
154*f6dc9357SAndroid Build Coastguard Worker       Counts[i] = ((size >= 16) ? 16 : size);
155*f6dc9357SAndroid Build Coastguard Worker       size -= Counts[i];
156*f6dc9357SAndroid Build Coastguard Worker     }
157*f6dc9357SAndroid Build Coastguard Worker   }
158*f6dc9357SAndroid Build Coastguard Worker 
159*f6dc9357SAndroid Build Coastguard Worker   void Add(unsigned pos, Byte val)
160*f6dc9357SAndroid Build Coastguard Worker   {
161*f6dc9357SAndroid Build Coastguard Worker     Buf[pos] = val;
162*f6dc9357SAndroid Build Coastguard Worker   }
163*f6dc9357SAndroid Build Coastguard Worker 
164*f6dc9357SAndroid Build Coastguard Worker   Byte GetAndMove(int pos)
165*f6dc9357SAndroid Build Coastguard Worker   {
166*f6dc9357SAndroid Build Coastguard Worker     if (pos < SmallSize)
167*f6dc9357SAndroid Build Coastguard Worker     {
168*f6dc9357SAndroid Build Coastguard Worker       Byte *p = SmallBuffer + kSmallSize - SmallSize;
169*f6dc9357SAndroid Build Coastguard Worker       Byte res = p[pos];
170*f6dc9357SAndroid Build Coastguard Worker       for (; pos > 0; pos--)
171*f6dc9357SAndroid Build Coastguard Worker         p[pos] = p[pos - 1];
172*f6dc9357SAndroid Build Coastguard Worker       SmallBuffer[kSmallSize - SmallSize] = res;
173*f6dc9357SAndroid Build Coastguard Worker       return res;
174*f6dc9357SAndroid Build Coastguard Worker     }
175*f6dc9357SAndroid Build Coastguard Worker     if (SmallSize == kSmallSize)
176*f6dc9357SAndroid Build Coastguard Worker     {
177*f6dc9357SAndroid Build Coastguard Worker       int i = Size - 1;
178*f6dc9357SAndroid Build Coastguard Worker       int g = 16;
179*f6dc9357SAndroid Build Coastguard Worker       do
180*f6dc9357SAndroid Build Coastguard Worker       {
181*f6dc9357SAndroid Build Coastguard Worker         g--;
182*f6dc9357SAndroid Build Coastguard Worker         int offset = (g << 4);
183*f6dc9357SAndroid Build Coastguard Worker         for (int t = Counts[g] - 1; t >= 0; t--, i--)
184*f6dc9357SAndroid Build Coastguard Worker           Buf[i] = Buf[offset + t];
185*f6dc9357SAndroid Build Coastguard Worker       }
186*f6dc9357SAndroid Build Coastguard Worker       while (g != 0);
187*f6dc9357SAndroid Build Coastguard Worker 
188*f6dc9357SAndroid Build Coastguard Worker       for (i = kSmallSize - 1; i >= 0; i--)
189*f6dc9357SAndroid Build Coastguard Worker         Buf[i] = SmallBuffer[i];
190*f6dc9357SAndroid Build Coastguard Worker       Init(Size);
191*f6dc9357SAndroid Build Coastguard Worker     }
192*f6dc9357SAndroid Build Coastguard Worker     pos -= SmallSize;
193*f6dc9357SAndroid Build Coastguard Worker     int g;
194*f6dc9357SAndroid Build Coastguard Worker     for (g = 0; pos >= Counts[g]; g++)
195*f6dc9357SAndroid Build Coastguard Worker       pos -= Counts[g];
196*f6dc9357SAndroid Build Coastguard Worker     int offset = (g << 4);
197*f6dc9357SAndroid Build Coastguard Worker     Byte res = Buf[offset + pos];
198*f6dc9357SAndroid Build Coastguard Worker     for (pos; pos < 16 - 1; pos++)
199*f6dc9357SAndroid Build Coastguard Worker       Buf[offset + pos] = Buf[offset + pos + 1];
200*f6dc9357SAndroid Build Coastguard Worker 
201*f6dc9357SAndroid Build Coastguard Worker     SmallSize++;
202*f6dc9357SAndroid Build Coastguard Worker     SmallBuffer[kSmallSize - SmallSize] = res;
203*f6dc9357SAndroid Build Coastguard Worker 
204*f6dc9357SAndroid Build Coastguard Worker     Counts[g]--;
205*f6dc9357SAndroid Build Coastguard Worker     return res;
206*f6dc9357SAndroid Build Coastguard Worker   }
207*f6dc9357SAndroid Build Coastguard Worker };
208*f6dc9357SAndroid Build Coastguard Worker */
209*f6dc9357SAndroid Build Coastguard Worker 
210*f6dc9357SAndroid Build Coastguard Worker }
211*f6dc9357SAndroid Build Coastguard Worker 
212*f6dc9357SAndroid Build Coastguard Worker #endif
213