http://nishi.dreamhosters.com/u/rc_v0.rar

fpaq0p is based on Matt's coder and is somewhat hard to find these days anyway,

so I decided to post a new incarnation.

So here we have:

fpaq0p_mm.cpp - 88 lines, 242226 on book1bwt (SClog=15), 243048 (SClog=12)

fpaq0p_sh.cpp - 88 lines, 241455 on book1bwt (SClog=15), 242947 (SClog=12)

For reference:

fpaq0p.cpp - 190 lines, 244093 on book1bwt (SClog=12)

(redundancy is due to EOF flags)

Code:#include <stdio.h> enum { SCALElog=15, SCALE=1<<SCALElog, mSCALE=SCALE-1, hSCALE=SCALE/2 }; template< int DECODE > struct Rangecoder { enum { NUM=4, sTOP=0x01000000U, Thres=0xFF000000U }; typedef unsigned long long int qword; unsigned range, code, FFNum, Cache; qword lowc; FILE* f; void Init( FILE* _f ) { f = _f; range = 0xFFFFFFFF; lowc = 0; FFNum = 0; Cache = 0; if( DECODE==1 ) for( unsigned _=0; _<NUM+1; _++ ) (code<<=8)+=getc(f); } void Quit( void ) { if( DECODE==0 ) for( unsigned _=0; _<NUM+1; _++ ) ShiftLow(); } unsigned Process( unsigned freq, unsigned bit ) { unsigned rnew = (qword(range)*(freq<<(32-SCALElog)))>>32; if( DECODE ) bit = (code>=rnew); bit ? range-=rnew, (DECODE ? code-=rnew : lowc+=rnew) : range=rnew; while( range<sTOP ) range<<=8, (DECODE ? (code<<=8)+=getc(f) : ShiftLow()); return bit; } unsigned ShiftLow( void ) { unsigned Carry = unsigned(lowc>>32), low = unsigned(lowc); if( low<Thres || Carry ) { putc( Cache+Carry, f ); for (;FFNum != 0;FFNum--) putc( Carry-1, f ); Cache = low>>24; } else FFNum++; return lowc = (low<<8); } }; struct Predictor { short cxt; short p[256-1]; Predictor() { for( unsigned i=0; i<sizeof(p)/sizeof(p[0]); i++ ) p[i]=hSCALE; byte(); } int P() const { return p[cxt-1]; } unsigned byte( void ) { unsigned c=cxt; cxt=1; return c; } void update( unsigned y ) { if( y ) p[cxt-1] -= ( p[cxt-1] >> 5), cxt+=cxt+1; else p[cxt-1] += ((SCALE - p[cxt-1]) >> 5), cxt+=cxt+0; } }; template< class Predictor, class Rangecoder > void proc( Predictor& p, Rangecoder& rc, unsigned y=0 ) { p.update( rc.Process( p.P(), y ) ); } unsigned flen( FILE* f ) { fseek( f, 0, SEEK_END ); unsigned len = ftell(f); fseek( f, 0, SEEK_SET ); return len; } int main( int argc, char** argv ) { unsigned i,c,f_len = 0; if( argc<4 ) return 1; FILE* f = fopen( argv[2], "rb" ); if( f==0 ) return 2; FILE* g = fopen( argv[3], "wb" ); if( g==0 ) return 3; Predictor p; if( argv[1][0]=='c' ) { f_len = flen( f ); fwrite( &f_len, 1,4, g ); Rangecoder<0> rc; rc.Init(g); for( i=0; i<f_len; i++ ) { c = getc(f); p.byte(); proc(p,rc,c&0x80); proc(p,rc,c&0x40); proc(p,rc,c&0x20); proc(p,rc,c&0x10); proc(p,rc,c&0x08); proc(p,rc,c&0x04); proc(p,rc,c&0x02); proc(p,rc,c&0x01); } rc.Quit(); } else { fread( &f_len, 1,4, f ); Rangecoder<1> rc; rc.Init(f); for( i=0; i<f_len; i++ ) { proc(p,rc); proc(p,rc); proc(p,rc); proc(p,rc); proc(p,rc); proc(p,rc); proc(p,rc); proc(p,rc); putc( p.byte(), g ); } } fclose( f ); fclose( g ); return 0; }