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