xref: /aosp_15_r20/external/lzma/C/Ppmd.h (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1*f6dc9357SAndroid Build Coastguard Worker /* Ppmd.h -- PPMD codec common code
2*f6dc9357SAndroid Build Coastguard Worker 2023-03-05 : Igor Pavlov : Public domain
3*f6dc9357SAndroid Build Coastguard Worker This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */
4*f6dc9357SAndroid Build Coastguard Worker 
5*f6dc9357SAndroid Build Coastguard Worker #ifndef ZIP7_INC_PPMD_H
6*f6dc9357SAndroid Build Coastguard Worker #define ZIP7_INC_PPMD_H
7*f6dc9357SAndroid Build Coastguard Worker 
8*f6dc9357SAndroid Build Coastguard Worker #include "CpuArch.h"
9*f6dc9357SAndroid Build Coastguard Worker 
10*f6dc9357SAndroid Build Coastguard Worker EXTERN_C_BEGIN
11*f6dc9357SAndroid Build Coastguard Worker 
12*f6dc9357SAndroid Build Coastguard Worker #if defined(MY_CPU_SIZEOF_POINTER) && (MY_CPU_SIZEOF_POINTER == 4)
13*f6dc9357SAndroid Build Coastguard Worker /*
14*f6dc9357SAndroid Build Coastguard Worker    PPMD code always uses 32-bit internal fields in PPMD structures to store internal references in main block.
15*f6dc9357SAndroid Build Coastguard Worker    if (PPMD_32BIT is     defined), the PPMD code stores internal pointers to 32-bit reference fields.
16*f6dc9357SAndroid Build Coastguard Worker    if (PPMD_32BIT is NOT defined), the PPMD code stores internal UInt32 offsets to reference fields.
17*f6dc9357SAndroid Build Coastguard Worker    if (pointer size is 64-bit), then (PPMD_32BIT) mode is not allowed,
18*f6dc9357SAndroid Build Coastguard Worker    if (pointer size is 32-bit), then (PPMD_32BIT) mode is optional,
19*f6dc9357SAndroid Build Coastguard Worker      and it's allowed to disable PPMD_32BIT mode even if pointer is 32-bit.
20*f6dc9357SAndroid Build Coastguard Worker    PPMD code works slightly faster in (PPMD_32BIT) mode.
21*f6dc9357SAndroid Build Coastguard Worker */
22*f6dc9357SAndroid Build Coastguard Worker   #define PPMD_32BIT
23*f6dc9357SAndroid Build Coastguard Worker #endif
24*f6dc9357SAndroid Build Coastguard Worker 
25*f6dc9357SAndroid Build Coastguard Worker #define PPMD_INT_BITS 7
26*f6dc9357SAndroid Build Coastguard Worker #define PPMD_PERIOD_BITS 7
27*f6dc9357SAndroid Build Coastguard Worker #define PPMD_BIN_SCALE (1 << (PPMD_INT_BITS + PPMD_PERIOD_BITS))
28*f6dc9357SAndroid Build Coastguard Worker 
29*f6dc9357SAndroid Build Coastguard Worker #define PPMD_GET_MEAN_SPEC(summ, shift, round) (((summ) + (1 << ((shift) - (round)))) >> (shift))
30*f6dc9357SAndroid Build Coastguard Worker #define PPMD_GET_MEAN(summ) PPMD_GET_MEAN_SPEC((summ), PPMD_PERIOD_BITS, 2)
31*f6dc9357SAndroid Build Coastguard Worker #define PPMD_UPDATE_PROB_0(prob) ((prob) + (1 << PPMD_INT_BITS) - PPMD_GET_MEAN(prob))
32*f6dc9357SAndroid Build Coastguard Worker #define PPMD_UPDATE_PROB_1(prob) ((prob) - PPMD_GET_MEAN(prob))
33*f6dc9357SAndroid Build Coastguard Worker 
34*f6dc9357SAndroid Build Coastguard Worker #define PPMD_N1 4
35*f6dc9357SAndroid Build Coastguard Worker #define PPMD_N2 4
36*f6dc9357SAndroid Build Coastguard Worker #define PPMD_N3 4
37*f6dc9357SAndroid Build Coastguard Worker #define PPMD_N4 ((128 + 3 - 1 * PPMD_N1 - 2 * PPMD_N2 - 3 * PPMD_N3) / 4)
38*f6dc9357SAndroid Build Coastguard Worker #define PPMD_NUM_INDEXES (PPMD_N1 + PPMD_N2 + PPMD_N3 + PPMD_N4)
39*f6dc9357SAndroid Build Coastguard Worker 
40*f6dc9357SAndroid Build Coastguard Worker MY_CPU_pragma_pack_push_1
41*f6dc9357SAndroid Build Coastguard Worker /* Most compilers works OK here even without #pragma pack(push, 1), but some GCC compilers need it. */
42*f6dc9357SAndroid Build Coastguard Worker 
43*f6dc9357SAndroid Build Coastguard Worker /* SEE-contexts for PPM-contexts with masked symbols */
44*f6dc9357SAndroid Build Coastguard Worker typedef struct
45*f6dc9357SAndroid Build Coastguard Worker {
46*f6dc9357SAndroid Build Coastguard Worker   UInt16 Summ; /* Freq */
47*f6dc9357SAndroid Build Coastguard Worker   Byte Shift;  /* Speed of Freq change; low Shift is for fast change */
48*f6dc9357SAndroid Build Coastguard Worker   Byte Count;  /* Count to next change of Shift */
49*f6dc9357SAndroid Build Coastguard Worker } CPpmd_See;
50*f6dc9357SAndroid Build Coastguard Worker 
51*f6dc9357SAndroid Build Coastguard Worker #define Ppmd_See_UPDATE(p) \
52*f6dc9357SAndroid Build Coastguard Worker   { if ((p)->Shift < PPMD_PERIOD_BITS && --(p)->Count == 0) \
53*f6dc9357SAndroid Build Coastguard Worker     { (p)->Summ = (UInt16)((p)->Summ << 1); \
54*f6dc9357SAndroid Build Coastguard Worker       (p)->Count = (Byte)(3 << (p)->Shift++); }}
55*f6dc9357SAndroid Build Coastguard Worker 
56*f6dc9357SAndroid Build Coastguard Worker 
57*f6dc9357SAndroid Build Coastguard Worker typedef struct
58*f6dc9357SAndroid Build Coastguard Worker {
59*f6dc9357SAndroid Build Coastguard Worker   Byte Symbol;
60*f6dc9357SAndroid Build Coastguard Worker   Byte Freq;
61*f6dc9357SAndroid Build Coastguard Worker   UInt16 Successor_0;
62*f6dc9357SAndroid Build Coastguard Worker   UInt16 Successor_1;
63*f6dc9357SAndroid Build Coastguard Worker } CPpmd_State;
64*f6dc9357SAndroid Build Coastguard Worker 
65*f6dc9357SAndroid Build Coastguard Worker typedef struct CPpmd_State2_
66*f6dc9357SAndroid Build Coastguard Worker {
67*f6dc9357SAndroid Build Coastguard Worker   Byte Symbol;
68*f6dc9357SAndroid Build Coastguard Worker   Byte Freq;
69*f6dc9357SAndroid Build Coastguard Worker } CPpmd_State2;
70*f6dc9357SAndroid Build Coastguard Worker 
71*f6dc9357SAndroid Build Coastguard Worker typedef struct CPpmd_State4_
72*f6dc9357SAndroid Build Coastguard Worker {
73*f6dc9357SAndroid Build Coastguard Worker   UInt16 Successor_0;
74*f6dc9357SAndroid Build Coastguard Worker   UInt16 Successor_1;
75*f6dc9357SAndroid Build Coastguard Worker } CPpmd_State4;
76*f6dc9357SAndroid Build Coastguard Worker 
77*f6dc9357SAndroid Build Coastguard Worker MY_CPU_pragma_pop
78*f6dc9357SAndroid Build Coastguard Worker 
79*f6dc9357SAndroid Build Coastguard Worker /*
80*f6dc9357SAndroid Build Coastguard Worker    PPMD code can write full CPpmd_State structure data to CPpmd*_Context
81*f6dc9357SAndroid Build Coastguard Worker       at (byte offset = 2) instead of some fields of original CPpmd*_Context structure.
82*f6dc9357SAndroid Build Coastguard Worker 
83*f6dc9357SAndroid Build Coastguard Worker    If we use pointers to different types, but that point to shared
84*f6dc9357SAndroid Build Coastguard Worker    memory space, we can have aliasing problem (strict aliasing).
85*f6dc9357SAndroid Build Coastguard Worker 
86*f6dc9357SAndroid Build Coastguard Worker    XLC compiler in -O2 mode can change the order of memory write instructions
87*f6dc9357SAndroid Build Coastguard Worker    in relation to read instructions, if we have use pointers to different types.
88*f6dc9357SAndroid Build Coastguard Worker 
89*f6dc9357SAndroid Build Coastguard Worker    To solve that aliasing problem we use combined CPpmd*_Context structure
90*f6dc9357SAndroid Build Coastguard Worker    with unions that contain the fields from both structures:
91*f6dc9357SAndroid Build Coastguard Worker    the original CPpmd*_Context and CPpmd_State.
92*f6dc9357SAndroid Build Coastguard Worker    So we can access the fields from both structures via one pointer,
93*f6dc9357SAndroid Build Coastguard Worker    and the compiler doesn't change the order of write instructions
94*f6dc9357SAndroid Build Coastguard Worker    in relation to read instructions.
95*f6dc9357SAndroid Build Coastguard Worker 
96*f6dc9357SAndroid Build Coastguard Worker    If we don't use memory write instructions to shared memory in
97*f6dc9357SAndroid Build Coastguard Worker    some local code, and we use only reading instructions (read only),
98*f6dc9357SAndroid Build Coastguard Worker    then probably it's safe to use pointers to different types for reading.
99*f6dc9357SAndroid Build Coastguard Worker */
100*f6dc9357SAndroid Build Coastguard Worker 
101*f6dc9357SAndroid Build Coastguard Worker 
102*f6dc9357SAndroid Build Coastguard Worker 
103*f6dc9357SAndroid Build Coastguard Worker #ifdef PPMD_32BIT
104*f6dc9357SAndroid Build Coastguard Worker 
105*f6dc9357SAndroid Build Coastguard Worker   #define Ppmd_Ref_Type(type)   type *
106*f6dc9357SAndroid Build Coastguard Worker   #define Ppmd_GetRef(p, ptr)   (ptr)
107*f6dc9357SAndroid Build Coastguard Worker   #define Ppmd_GetPtr(p, ptr)   (ptr)
108*f6dc9357SAndroid Build Coastguard Worker   #define Ppmd_GetPtr_Type(p, ptr, note_type) (ptr)
109*f6dc9357SAndroid Build Coastguard Worker 
110*f6dc9357SAndroid Build Coastguard Worker #else
111*f6dc9357SAndroid Build Coastguard Worker 
112*f6dc9357SAndroid Build Coastguard Worker   #define Ppmd_Ref_Type(type)   UInt32
113*f6dc9357SAndroid Build Coastguard Worker   #define Ppmd_GetRef(p, ptr)   ((UInt32)((Byte *)(ptr) - (p)->Base))
114*f6dc9357SAndroid Build Coastguard Worker   #define Ppmd_GetPtr(p, offs)  ((void *)((p)->Base + (offs)))
115*f6dc9357SAndroid Build Coastguard Worker   #define Ppmd_GetPtr_Type(p, offs, type) ((type *)Ppmd_GetPtr(p, offs))
116*f6dc9357SAndroid Build Coastguard Worker 
117*f6dc9357SAndroid Build Coastguard Worker #endif // PPMD_32BIT
118*f6dc9357SAndroid Build Coastguard Worker 
119*f6dc9357SAndroid Build Coastguard Worker 
120*f6dc9357SAndroid Build Coastguard Worker typedef Ppmd_Ref_Type(CPpmd_State) CPpmd_State_Ref;
121*f6dc9357SAndroid Build Coastguard Worker typedef Ppmd_Ref_Type(void)        CPpmd_Void_Ref;
122*f6dc9357SAndroid Build Coastguard Worker typedef Ppmd_Ref_Type(Byte)        CPpmd_Byte_Ref;
123*f6dc9357SAndroid Build Coastguard Worker 
124*f6dc9357SAndroid Build Coastguard Worker 
125*f6dc9357SAndroid Build Coastguard Worker /*
126*f6dc9357SAndroid Build Coastguard Worker #ifdef MY_CPU_LE_UNALIGN
127*f6dc9357SAndroid Build Coastguard Worker // the unaligned 32-bit access latency can be too large, if the data is not in L1 cache.
128*f6dc9357SAndroid Build Coastguard Worker #define Ppmd_GET_SUCCESSOR(p) ((CPpmd_Void_Ref)*(const UInt32 *)(const void *)&(p)->Successor_0)
129*f6dc9357SAndroid Build Coastguard Worker #define Ppmd_SET_SUCCESSOR(p, v) *(UInt32 *)(void *)(void *)&(p)->Successor_0 = (UInt32)(v)
130*f6dc9357SAndroid Build Coastguard Worker 
131*f6dc9357SAndroid Build Coastguard Worker #else
132*f6dc9357SAndroid Build Coastguard Worker */
133*f6dc9357SAndroid Build Coastguard Worker 
134*f6dc9357SAndroid Build Coastguard Worker /*
135*f6dc9357SAndroid Build Coastguard Worker    We can write 16-bit halves to 32-bit (Successor) field in any selected order.
136*f6dc9357SAndroid Build Coastguard Worker    But the native order is more consistent way.
137*f6dc9357SAndroid Build Coastguard Worker    So we use the native order, if LE/BE order can be detected here at compile time.
138*f6dc9357SAndroid Build Coastguard Worker */
139*f6dc9357SAndroid Build Coastguard Worker 
140*f6dc9357SAndroid Build Coastguard Worker #ifdef MY_CPU_BE
141*f6dc9357SAndroid Build Coastguard Worker 
142*f6dc9357SAndroid Build Coastguard Worker   #define Ppmd_GET_SUCCESSOR(p) \
143*f6dc9357SAndroid Build Coastguard Worker     ( (CPpmd_Void_Ref) (((UInt32)(p)->Successor_0 << 16) | (p)->Successor_1) )
144*f6dc9357SAndroid Build Coastguard Worker 
145*f6dc9357SAndroid Build Coastguard Worker   #define Ppmd_SET_SUCCESSOR(p, v) { \
146*f6dc9357SAndroid Build Coastguard Worker     (p)->Successor_0 = (UInt16)(((UInt32)(v) >> 16) /* & 0xFFFF */); \
147*f6dc9357SAndroid Build Coastguard Worker     (p)->Successor_1 = (UInt16)((UInt32)(v) /* & 0xFFFF */); }
148*f6dc9357SAndroid Build Coastguard Worker 
149*f6dc9357SAndroid Build Coastguard Worker #else
150*f6dc9357SAndroid Build Coastguard Worker 
151*f6dc9357SAndroid Build Coastguard Worker   #define Ppmd_GET_SUCCESSOR(p) \
152*f6dc9357SAndroid Build Coastguard Worker     ( (CPpmd_Void_Ref) ((p)->Successor_0 | ((UInt32)(p)->Successor_1 << 16)) )
153*f6dc9357SAndroid Build Coastguard Worker 
154*f6dc9357SAndroid Build Coastguard Worker   #define Ppmd_SET_SUCCESSOR(p, v) { \
155*f6dc9357SAndroid Build Coastguard Worker     (p)->Successor_0 = (UInt16)((UInt32)(v) /* & 0xFFFF */); \
156*f6dc9357SAndroid Build Coastguard Worker     (p)->Successor_1 = (UInt16)(((UInt32)(v) >> 16) /* & 0xFFFF */); }
157*f6dc9357SAndroid Build Coastguard Worker 
158*f6dc9357SAndroid Build Coastguard Worker #endif
159*f6dc9357SAndroid Build Coastguard Worker 
160*f6dc9357SAndroid Build Coastguard Worker // #endif
161*f6dc9357SAndroid Build Coastguard Worker 
162*f6dc9357SAndroid Build Coastguard Worker 
163*f6dc9357SAndroid Build Coastguard Worker #define PPMD_SetAllBitsIn256Bytes(p) \
164*f6dc9357SAndroid Build Coastguard Worker   { size_t z; for (z = 0; z < 256 / sizeof(p[0]); z += 8) { \
165*f6dc9357SAndroid Build Coastguard Worker   p[z+7] = p[z+6] = p[z+5] = p[z+4] = p[z+3] = p[z+2] = p[z+1] = p[z+0] = ~(size_t)0; }}
166*f6dc9357SAndroid Build Coastguard Worker 
167*f6dc9357SAndroid Build Coastguard Worker EXTERN_C_END
168*f6dc9357SAndroid Build Coastguard Worker 
169*f6dc9357SAndroid Build Coastguard Worker #endif
170