00001 #include "vliCodec.h"
00002
00003 using namespace std;
00004
00006 class VLI {
00008 static int toPositive(int value)
00009 { return value>=0 ? value*2 : value*(-2)-1 ; }
00011 static int fromPositive(int value) {
00012 int res= value/2;
00013 return value%2 ? -res-1 : res ;
00014 }
00016 static int getLevel(int posValue,int expAdd)
00017 { return log2ceil(posValue+powers[expAdd]+1) -expAdd -1; }
00018
00020 int getBase(int level) const {
00021 ASSERT( level>=0 && level<=maxLevel );
00022 return powers[level+expAdd] -powers[expAdd];
00023 }
00024 public:
00026 struct Type {
00027 int level, data;
00028 };
00029
00030
00031 const int expAdd
00032 , maxLevel
00033 #ifndef NDEBUG
00034 , possib
00035 #endif
00036 , maxLevel_Bits;
00037
00038 public:
00040 VLI(int possibilities,int exponentAddition)
00041 : expAdd(exponentAddition), maxLevel(getLevel( possibilities-1 , exponentAddition ))
00042 #ifndef NDEBUG
00043 , possib(possibilities)
00044 #endif
00045 , maxLevel_Bits(log2ceil( possibilities-getBase(maxLevel) ))
00046 { ASSERT( possibilities>0 && exponentAddition>=0 ); }
00048 int bitsForLevel(int level) const {
00049 ASSERT( level>=0 && level<=maxLevel );
00050 return level==maxLevel ? maxLevel_Bits : level+expAdd ;
00051 }
00052
00054 Type toVLI(int value) const {
00055 value= toPositive(value);
00056 ASSERT( value>=0 && value<possib );
00057 Type result;
00058 result.level= getLevel(value,expAdd);
00059 result.data= value -getBase(result.level);
00060 return result;
00061 }
00063 int fromVLI(int level,int data) const
00064 { return fromPositive( getBase(level) +data ); }
00065 int fromVLI(Type vli) const
00066 { return fromVLI(vli.level,vli.data); }
00067 };
00068
00069
00070
00071 void MDifferentialVLICodec::encode(vector<int> &data,ostream &file) {
00072
00073 VLI vli( possib, settingsInt(VLIExponent) );
00074 vector<VLI::Type> vlis;
00075 vlis.reserve( data.size() );
00076 int posHalf= possib/2;
00077 for (vector<int>::iterator it=data.begin(); it!=data.end(); ++it) {
00078 int diff= *it -lastSymbol;
00079 if (diff < -posHalf)
00080 diff+= possib; else
00081 if (diff >= posHalf)
00082 diff-= possib;
00083
00084 lastSymbol= *it;
00085 vlis.push_back( vli.toVLI(diff) );
00086 }
00087
00088 BitWriter out(file);
00089 int bits= log2ceil(vli.maxLevel+1);
00090 for (vector<VLI::Type>::iterator it=vlis.begin(); it!=vlis.end(); ++it)
00091 out.putBits( it->level, bits );
00092 for (vector<VLI::Type>::iterator it=vlis.begin(); it!=vlis.end(); ++it)
00093 out.putBits( it->data, vli.bitsForLevel(it->level) );
00094 }
00095
00096 void MDifferentialVLICodec::decode(istream &file,int count,vector<int> &data) {
00097 VLI vli( possib, settingsInt(VLIExponent) );
00098 vector<int> levels;
00099 levels.resize(count);
00100
00101 BitReader in(file);
00102 int bits= log2ceil(vli.maxLevel+1);
00103 for (int i=0; i<count; ++i)
00104 if ( (levels[i]= in.getBits(bits)) > vli.maxLevel )
00105 throw exception();
00106
00107 for (int i=0; i<count; ++i) {
00108 int level= levels[i];
00109 lastSymbol+= vli.fromVLI( level, in.getBits(vli.bitsForLevel(level)) );
00110
00111 if (lastSymbol<0)
00112 lastSymbol+= possib; else
00113 if (lastSymbol>=possib)
00114 lastSymbol-= possib;
00115
00116 levels[i]= lastSymbol;
00117 }
00118
00119 swap(levels,data);
00120 }