[ create a new paste ] login | about

Link: http://codepad.org/Uspvykm9    [ raw code | output | fork ]

C++, pasted on Jan 15:
#include <stdio.h>

typedef unsigned int  uint;
typedef unsigned char uc;

#define  DO(n)     for (int _=0; _<n; _++)
#define  TOP       (1<<24)
#define  BOT       (1<<16)

struct RangeCoder {
 uint  low, code, range, passed;
 FILE  *f;

 void OutByte (uc c)           { passed++; /*fputc(c,f);*/ }
 uc   InByte ()                { passed++; return 0/*fgetc(f)*/; }

public:

 uint GetPassed ()             { return passed; }
 void StartEncode (FILE *F)    { f=F; passed=low=0;  range= (uint) -1; }
 void FinishEncode ()          { DO(4)  OutByte(low>>24), low<<=8; }
 void StartDecode (FILE *F)    { passed=low=code=0;  range= (uint) -1;
                                 f=F; DO(4) code= code<<8 | InByte();
                               }

 void Encode (uint cumFreq, uint freq, uint totFreq) {
//    assert(cumFreq+freq<totFreq && freq && totFreq<=BOT);
   low  += cumFreq * (range/= totFreq);
   range*= freq;

//   while( (low ^ low+range)<TOP || range<BOT && ((range= -low & BOT-1),1))
//     OutByte(low>>24), range<<=8, low<<=8;

   while( ((low ^ low+range)<TOP) || (range<BOT) ) { // true

     if( ((low ^ low+range)>=TOP) ) {  
       int above = ( low + range) & 0xFFFF; // (0xFFFFFFFF+0x0000FFFF)&0xFFFF = 0xFFFE
       int below = (~low) & 0xFFFF; // (~0xFFFFFFFF)&0xFFFF = 0x0000
       
       if( above > below ) { // true
         low += range - above; // 0xFFFFFFFF + 0xFFFF-0xFFFE = 0x00000000 !!! OVERFLOW !!!
         range = above; // 0xFFFE
       } else {
         range = below;
       }
     }
     
     OutByte( low>>24 );
     range <<= 8;
     low <<= 8;
   }
 }

 uint GetFreq (uint totFreq) {
   uint tmp= (code-low) / (range/= totFreq);
//   if (tmp >= totFreq)  throw ("Input data corrupt"); // or force it to return
   return tmp;                                         // a valid value :)
 }

 void Decode (uint cumFreq, uint freq, uint totFreq) {
//    assert(cumFreq+freq<totFreq && freq && totFreq<=BOT);
   low  += cumFreq*range;
   range*= freq;
   while ((low ^ low+range)<TOP || range<BOT && ((range= -low & BOT-1),1))
      code= code<<8 | InByte(), range<<=8, low<<=8;
 }
} rc;

int main( void ) {

  rc.StartEncode(0);

  for( int i=0; i<999999; i++ ) rc.Encode( 254,1,255 );

  printf( "output bytes = %i\n", rc.passed );
}


Output:
1
output bytes = 999294


Create a new paste based on this one


Comments: