cr88192

Range-Coder post-compressor for RP2.

Feb 4th, 2026
192
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 10.31 KB | None | 0 0
  1. /*
  2.  * Bitwise Range Coder
  3.  *
  4.  * Can be bolted on top of RP2 as an optional post-compressor, with some
  5.  * gains seen for compression ratio. Doesn't currently support the
  6.  * "Long Match" case.
  7.  *
  8.  * RP2 (Transposed, LE):
  9.  *                        dddddddd-dlllrrr0 (l=3..10, d=0..511, r=0..7)
  10.  *               dddddddd-dddddlll-lllrrr01 (l=4..67, d=0..8191)
  11.  *      dddddddd-dddddddd-dlllllll-llrrr011 (l=4..515, d=0..131071)
  12.  *                                 rrrr0111 (Raw Bytes, r=(r+1)*8, 8..128)
  13.  *                               * rrr01111 (Long Match)
  14.  *                                 rr011111 (r=1..3 bytes, 0=EOB)
  15.  *                        rrrrrrrr-r0111111  (Long Raw, r=(r+1)*8, 8..4096)
  16.  *                        lllllll0-01111111  (RP2B, l=4..131, d=1, r=0)
  17.  * 2x D-ddddddll-llllllll-llllrrr1-01111111  (RP2B, l=4..16K, d=0..4M, r=0..7)
  18.  *
  19.  ** d: Distance
  20.  ** l: Match Length
  21.  ** r: Literal Length
  22.  *
  23.  * Will use 3 contexts:
  24.  * One for Tag Bytes (the first byte in the match pattern).
  25.  * One for Length/Distance Bytes (any secondary bytes in the match).
  26.  * One for raw/literal bytes.
  27.  *
  28.  * This will use a shared bit history between symbols,
  29.  * with each symbol being encoded with 11 bits of context
  30.  *   As history and bit position within the byte.
  31.  * Symbols will be encoded in LSB first order in this case.
  32.  *   LSB first is a slightly better fit for the data being encoded.
  33.  *
  34.  * This will use 30-00 as an escape pattern.
  35.  *   This will otherwise be invalid at the start of an RP2 encoded blob.
  36.  * Apart from this (and a few other escape patterns), could assume normal RP2.
  37.  *   Here, entropy coding is regarded as an optional special case.
  38.  *   Entropy coding is then only used if it brings sufficient benefit.
  39.  *   Otherwise, the high CPU cost of Range Coding is undesirable.
  40.  *
  41.  * Here, it is assumed that this will be used on relatively short data blobs.
  42.  *   Something more normal, like Deflate, making more sense for larger blobs.
  43.  *   But, Deflate being mostly ineffective with small data blobs.
  44.  *     Also, initializing Huffman tables is very expensive for small blobs.
  45.  * Huffman quickly becomes faster than Range-Coding as symbol counts increase.
  46.  *   STF+AdRice was another option for fast and OK at small blob sizes.
  47.  *   But, for small blobs, STF+AdRice was seeing little compression vs plain RP2.
  48.  *     So, Range Coding was the only option that "actually did something" here.
  49.  *
  50.  */
  51.  
  52. typedef struct BTM_BitRcCtx_s BTM_BitRcCtx;
  53.  
  54. struct BTM_BitRcCtx_s {
  55. u32 w_lo;   //lower bound of range
  56. u32 w_rn;   //range
  57. u32 w_in;   //reference input
  58. byte *cst;  //entropy-coded stream
  59. };
  60.  
  61. static const u16 btm_bitrc_padjusttab[256]={
  62. 0xA05F, 0x0301, 0x0501, 0x0702, 0x0803, 0x0A04, 0x0B05, 0x0C06,
  63. 0x0E07, 0x0F08, 0x1109, 0x120A, 0x130B, 0x140C, 0x160D, 0x170E,
  64. 0x180F, 0x1910, 0x1A11, 0x1C12, 0x1D13, 0x1E14, 0x1F15, 0x2016,
  65. 0x2117, 0x2318, 0x2419, 0x251A, 0x261A, 0x271B, 0x281C, 0x291D,
  66. 0x2A1E, 0x2B1F, 0x2C20, 0x2E21, 0x2F22, 0x3023, 0x3124, 0x3225,
  67. 0x3326, 0x3426, 0x3527, 0x3628, 0x3729, 0x382A, 0x392B, 0x3A2C,
  68. 0x3B2D, 0x3C2E, 0x3D2F, 0x3E30, 0x3F31, 0x4031, 0x4132, 0x4233,
  69. 0x4334, 0x4435, 0x4536, 0x4637, 0x4738, 0x4839, 0x493A, 0x4A3B,
  70. 0x4B3C, 0x4C3D, 0x4D3D, 0x4E3E, 0x4F3F, 0x5040, 0x5141, 0x5242,
  71. 0x5343, 0x5444, 0x5545, 0x5646, 0x5747, 0x5848, 0x5949, 0x5A49,
  72. 0x5B4A, 0x5C4B, 0x5D4C, 0x5E4D, 0x5F4E, 0x604F, 0x6150, 0x6251,
  73. 0x6352, 0x6453, 0x6554, 0x6655, 0x6755, 0x6856, 0x6957, 0x6A58,
  74. 0x6B59, 0x6C5A, 0x6D5B, 0x6E5C, 0x6F5D, 0x705E, 0x705F, 0x7160,
  75. 0x7261, 0x7362, 0x7462, 0x7563, 0x7664, 0x7765, 0x7866, 0x7967,
  76. 0x7A68, 0x7B69, 0x7C6A, 0x7D6B, 0x7E6C, 0x7F6D, 0x806E, 0x816F,
  77. 0x816F, 0x8270, 0x8371, 0x8472, 0x8573, 0x8674, 0x8775, 0x8876,
  78. 0x8977, 0x8A78, 0x8B79, 0x8C7A, 0x8D7B, 0x8E7C, 0x8F7D, 0x907E,
  79. 0x907E, 0x917F, 0x9280, 0x9381, 0x9482, 0x9583, 0x9684, 0x9785,
  80. 0x9886, 0x9987, 0x9A88, 0x9B89, 0x9C8A, 0x9D8B, 0x9D8C, 0x9E8D,
  81. 0x9F8E, 0xA08F, 0xA18F, 0xA290, 0xA391, 0xA492, 0xA593, 0xA694,
  82. 0xA795, 0xA896, 0xA997, 0xAA98, 0xAA99, 0xAB9A, 0xAC9B, 0xAD9C,
  83. 0xAE9D, 0xAF9E, 0xB09F, 0xB1A0, 0xB2A1, 0xB3A2, 0xB4A3, 0xB5A4,
  84. 0xB6A5, 0xB6A6, 0xB7A7, 0xB8A8, 0xB9A9, 0xBAAA, 0xBBAB, 0xBCAC,
  85. 0xBDAD, 0xBEAE, 0xBFAF, 0xC0B0, 0xC1B1, 0xC2B2, 0xC2B3, 0xC3B4,
  86. 0xC4B5, 0xC5B6, 0xC6B7, 0xC7B8, 0xC8B9, 0xC9BA, 0xCABB, 0xCBBC,
  87. 0xCCBD, 0xCDBE, 0xCEBF, 0xCEC0, 0xCFC1, 0xD0C2, 0xD1C3, 0xD2C4,
  88. 0xD3C5, 0xD4C6, 0xD5C7, 0xD6C8, 0xD7C9, 0xD8CA, 0xD9CB, 0xD9CC,
  89. 0xDACD, 0xDBCE, 0xDCCF, 0xDDD0, 0xDED1, 0xDFD3, 0xE0D4, 0xE1D5,
  90. 0xE2D6, 0xE3D7, 0xE4D8, 0xE5D9, 0xE5DA, 0xE6DB, 0xE7DC, 0xE8DE,
  91. 0xE9DF, 0xEAE0, 0xEBE1, 0xECE2, 0xEDE3, 0xEEE5, 0xEFE6, 0xF0E7,
  92. 0xF1E8, 0xF2E9, 0xF3EB, 0xF4EC, 0xF5ED, 0xF6EE, 0xF7F0, 0xF8F1,
  93. 0xF9F3, 0xFAF4, 0xFBF5, 0xFCF7, 0xFDF8, 0xFEFA, 0xFEFC, 0xA05F,
  94. };
  95.  
  96. int BTM_BItRc_EncodeFlush(BTM_BitRcCtx *ctx)
  97. {
  98.     int prb, mid, rng, low;
  99.     int i;
  100.    
  101.     rng=ctx->w_rn;
  102.     low=ctx->w_lo;
  103.    
  104.     while(low)
  105.     {
  106.         *ctx->cst++=low>>24;
  107.         low=low<<8;
  108.         rng=(rng<<8);
  109.     }
  110.    
  111.     ctx->w_lo=low;
  112.     ctx->w_rn=rng;
  113.     return(0);
  114. }
  115.  
  116.  
  117. int BTM_BItRc_EncodeBit(BTM_BitRcCtx *ctx, byte *rprb, int bit)
  118. {
  119.     u16 prbi;
  120.     u32 prb, mid, rng, low, low0;
  121.     int i, j, k;
  122.    
  123.     prb=*rprb;
  124.  
  125.     rng=ctx->w_rn;
  126.     low=ctx->w_lo;
  127.     prbi=btm_bitrc_padjusttab[prb];
  128.     low0=low;
  129.    
  130.     mid=(rng>>8)*prb;
  131.     if(bit)
  132.     {
  133.         low=low+mid;
  134.         rng=rng-mid;
  135.         prb=prbi&255;
  136.     }else
  137.     {
  138.         rng=mid;
  139.         prb=prbi>>8;
  140.     }
  141.    
  142.     /* if value has overflowed, we need to adjust prior bytes... */
  143.     if(low<low0)
  144.     {
  145.         i=-1;
  146.         while(1)
  147.         {
  148.             j=ctx->cst[i];
  149.             k=j+1;
  150.             ctx->cst[i]=k;
  151.             if((k&255)>j)
  152.                 break;
  153.             i--;
  154.         }
  155.     }
  156.    
  157.     if(rng<0x01000000)
  158.     {
  159.         *ctx->cst++=low>>24;
  160.         low=low<<8;
  161.         rng=(rng<<8);
  162.     }
  163.    
  164.     ctx->w_lo=low;
  165.     ctx->w_rn=rng;
  166.     *rprb=prb;
  167.     return(0);
  168. }
  169.  
  170. int BTM_BItRc_DecodeBit(BTM_BitRcCtx *ctx, byte *rprb)
  171. {
  172.     u16 prbi;
  173.     u32 prb, mid, rng, bit, win;
  174.    
  175.     prb=*rprb;
  176.  
  177.     rng=ctx->w_rn;
  178.     win=ctx->w_in;
  179.     prbi=btm_bitrc_padjusttab[prb];
  180.     mid=(rng>>8)*prb;
  181.  
  182.     bit=win>=mid;
  183.  
  184.     if(bit)
  185.     {
  186.         win-=mid;
  187.         rng-=mid;
  188.         prb=prbi&255;
  189.     }else
  190.     {
  191.         rng=mid;
  192.         prb=prbi>>8;
  193.     }
  194.    
  195.     if(rng<0x01000000)
  196.     {
  197.         win=(win<<8)|(*ctx->cst++);
  198.         rng=(rng<<8);
  199.     }
  200.    
  201.     ctx->w_rn=rng;
  202.     ctx->w_in=win;
  203.     *rprb=prb;
  204.    
  205.     return(bit);
  206. }
  207.  
  208. int BTM_BItRc_DecodeInit(BTM_BitRcCtx *ctx, byte *ibuf)
  209. {
  210.     ctx->w_lo=0x00000000;
  211.     ctx->w_rn=0xFFFFFFFF;
  212.     ctx->cst=ibuf;
  213.  
  214.     ctx->w_in=(ctx->w_in<<8)|(*ctx->cst++);
  215.     ctx->w_in=(ctx->w_in<<8)|(*ctx->cst++);
  216.     ctx->w_in=(ctx->w_in<<8)|(*ctx->cst++);
  217.     ctx->w_in=(ctx->w_in<<8)|(*ctx->cst++);
  218.  
  219.     return(0);
  220. }
  221.  
  222. int BTM_BItRc_EncodeInit(BTM_BitRcCtx *ctx, byte *ibuf)
  223. {
  224.     ctx->w_lo=0x00000000;
  225.     ctx->w_rn=0xFFFFFFFF;
  226.     ctx->cst=ibuf;
  227.     return(0);
  228. }
  229.  
  230. int BTM_BItRc_DecodeByteLeCtx8B(BTM_BitRcCtx *ctx,
  231.     byte *probtab, int *rhist)
  232. {
  233.     int b, v, h, ix;
  234.     int i, j, k;
  235.    
  236.     v=0;
  237.     h=*rhist;
  238.     for(i=0; i<8; i++)
  239.     {
  240.         j=((h&255)<<3)|(i&7);
  241.         b=BTM_BItRc_DecodeBit(ctx, probtab+j);
  242.         h=(h<<1)|b;
  243.         v=(v>>1)|(b<<7);
  244.     }
  245.     *rhist=h;
  246.     return(v);
  247. }
  248.  
  249. int BTM_BItRc_EncodeByteLeCtx8B(BTM_BitRcCtx *ctx,
  250.     byte *probtab, int *rhist, int val)
  251. {
  252.     int b, v, h, ix;
  253.     int i, j, k;
  254.    
  255.     h=*rhist;
  256.     for(i=0; i<8; i++)
  257.     {
  258.         b=(val>>i)&1;
  259.         j=((h&255)<<3)|(i&7);
  260.         BTM_BItRc_EncodeBit(ctx, probtab+j, b);
  261.         h=(h<<1)|b;
  262.     }
  263.     *rhist=h;
  264.     return(0);
  265. }
  266.  
  267. int BTM_BItRc_CheckPostRp2Blob(byte *ibuf)
  268. {
  269.     if((ibuf[0]==0x30) && (ibuf[1]==0x00))
  270.         return(1);
  271.     return(0);
  272. }
  273.  
  274. int BTM_BItRc_EncodeBufferPostRp2(byte *obuf, byte *ibuf, int ibsz)
  275. {
  276.     byte prbtab_t[2048];
  277.     byte prbtab_d[2048];
  278.     byte prbtab_l[2048];
  279.     BTM_BitRcCtx t_ctx;
  280.     BTM_BitRcCtx *ctx;
  281.     byte *cs, *cse, *cs1, *csr, *ct;
  282.     u32 tag;
  283.     int lc, tsz, nr;
  284.     int i, j, k;
  285.  
  286.     ctx=&t_ctx;
  287.  
  288.     ct=obuf;
  289.     *ct++=0x30;
  290.     *ct++=0x00;
  291.  
  292.     BTM_BItRc_EncodeInit(ctx, ct);
  293.  
  294.     memset(prbtab_t, 0x80, 2048);
  295.     memset(prbtab_d, 0x80, 2048);
  296.     memset(prbtab_l, 0x80, 2048);
  297.     lc=0;
  298.    
  299.     cs=ibuf;
  300.     cse=ibuf+ibsz;
  301.     while(cs<cse)
  302.     {
  303.         tag=*(u32 *)cs;
  304.         if(!(tag&0x01))         { tsz=2; nr=(tag>>1)&7; }
  305.         else if(!(tag&0x02))    { tsz=3; nr=(tag>>2)&7; }
  306.         else if(!(tag&0x04))    { tsz=4; nr=(tag>>3)&7; }
  307.         else if(!(tag&0x08))    { tsz=1; nr=(((tag>>4)&15)+1)*8; }
  308.         else if(!(tag&0x10))    { tsz=-1; nr=(tag>>5)&7; }
  309.         else if(!(tag&0x20))    { tsz=1; nr=(tag>>6)&3; }
  310.         else if(!(tag&0x40))    { tsz=2; nr=(((tag>>7)&511)+1)*8; }
  311.         else if(!(tag&0x80))
  312.         {
  313.             if(tag&0x100)
  314.                 { tsz=6; nr=(tag>>9)&7; }
  315.             else
  316.                 { tsz=2; nr=0; }
  317.         }
  318.         else { tsz=-1; }
  319.        
  320.         if(tsz<1)
  321.             return(-1);
  322.        
  323.         BTM_BItRc_EncodeByteLeCtx8B(ctx, prbtab_t, &lc, *cs++);
  324.         for(i=1; i<tsz; i++)
  325.             BTM_BItRc_EncodeByteLeCtx8B(ctx, prbtab_d, &lc, *cs++);
  326.         for(i=0; i<nr; i++)
  327.             BTM_BItRc_EncodeByteLeCtx8B(ctx, prbtab_l, &lc, *cs++);
  328.     }
  329.     BTM_BItRc_EncodeFlush(ctx);
  330.     return(ctx->cst-obuf);
  331. }
  332.  
  333. int BTM_BItRc_DecodeBufferPostRp2(byte *obuf, byte *ibuf, int ibsz)
  334. {
  335.     byte prbtab_t[2048];
  336.     byte prbtab_d[2048];
  337.     byte prbtab_l[2048];
  338.     BTM_BitRcCtx t_ctx;
  339.     BTM_BitRcCtx *ctx;
  340.     byte *cs, *cse, *cs1, *csr, *ct;
  341.     u32 tag;
  342.     int lc, tsz, tsi, nr, tg;
  343.     int i, j, k;
  344.  
  345.     if((ibuf[0]!=0x30) || (ibuf[1]!=0x00))
  346.         return(-1);
  347.  
  348.     ctx=&t_ctx;
  349.     BTM_BItRc_DecodeInit(ctx, ibuf+2);
  350.    
  351.     ct=obuf;
  352.  
  353.     memset(prbtab_t, 0x80, 2048);
  354.     memset(prbtab_d, 0x80, 2048);
  355.     memset(prbtab_l, 0x80, 2048);
  356.     lc=0;
  357.    
  358.     while(1)
  359.     {
  360.         tg=BTM_BItRc_DecodeByteLeCtx8B(ctx, prbtab_t, &lc);
  361.         if(!(tg&0x01))          { tsz=2; }
  362.         else if(!(tg&0x02)) { tsz=3; }
  363.         else if(!(tg&0x04)) { tsz=4; }
  364.         else if(!(tg&0x08)) { tsz=1; }
  365.         else if(!(tg&0x10)) { tsz=1; }
  366.         else if(!(tg&0x20)) { tsz=1; }
  367.         else if(!(tg&0x40)) { tsz=2; }
  368.         else if(!(tg&0x80)) { tsz=2; }
  369.         tsi=1;
  370.        
  371.         *ct++=tg;
  372.         if(tg==0x1F)
  373.             break;
  374.        
  375.         if(tg==0x7F)
  376.         {
  377.             j=BTM_BItRc_DecodeByteLeCtx8B(ctx, prbtab_d, &lc);
  378.             *ct++=j;
  379.             tag|=j<<8;
  380.             tsi=2;
  381.             if(tag&0x0100)
  382.                 tsz=6;
  383.         }
  384.        
  385.         tag=tg;
  386.         for(i=tsi; i<tsz; i++)
  387.         {
  388.             j=BTM_BItRc_DecodeByteLeCtx8B(ctx, prbtab_d, &lc);
  389.             *ct++=j;
  390.             tag|=j<<(i*8);
  391.         }
  392.        
  393.         if(!tag)
  394.             break;
  395.        
  396.         if(!(tag&0x01))         { tsz=2; nr=(tag>>1)&7; }
  397.         else if(!(tag&0x02))    { tsz=3; nr=(tag>>2)&7; }
  398.         else if(!(tag&0x04))    { tsz=4; nr=(tag>>3)&7; }
  399.         else if(!(tag&0x08))    { tsz=1; nr=(((tag>>4)&15)+1)*8; }
  400.         else if(!(tag&0x10))    { tsz=1; nr=(tag>>5)&7; }
  401.         else if(!(tag&0x20))    { tsz=1; nr=(tag>>6)&3; }
  402.         else if(!(tag&0x40))    { tsz=2; nr=(((tag>>7)&511)+1)*8; }
  403.         else if(!(tag&0x80))    { nr=(tag&0x0100)?((tag>>9)&7):0; }
  404.         for(i=0; i<nr; i++)
  405.             { *ct++=BTM_BItRc_DecodeByteLeCtx8B(ctx, prbtab_l, &lc); }
  406.     }
  407.     return(ct-obuf);
  408. }
  409.  
Tags: range coder
Advertisement
Add Comment
Please, Sign In to add comment