Go to the documentation of this file.00001 #ifndef IZ_BITCODER_H
00002 #define IZ_BITCODER_H 1
00003
00004 #include "intmacros.h"
00005
00006 namespace IZ {
00007
00008
00009
00010
00011 #if defined(__LP64__) || defined(__L64__)
00012 typedef unsigned long U64;
00013 typedef unsigned int U32;
00014 #elif defined(__LLP64__) || defined(__LL64__) || defined(_WIN64)
00015 typedef unsigned long long U64;
00016 typedef unsigned int U32;
00017 #elif defined(__MMX__)
00018 #include <mmintrin.h>
00019 typedef __m64 U64;
00020 typedef unsigned int U32;
00021 #define USE_MMX
00022 #else
00023 typedef unsigned long long U64;
00024 typedef unsigned int U32;
00025 #endif
00026
00027 template<typename Code = U32>
00028 class BitCoderBase
00029 {
00030 protected:
00043 typedef U64 Cache;
00044
00045 enum Constants {
00046 CodeBits = sizeof(Code) * CHAR_BIT,
00047 CacheBits = sizeof(Cache) * CHAR_BIT
00048 };
00049
00050 protected:
00054 unsigned int len;
00055
00059 Cache bitcache;
00060 };
00061
00062 template<typename Code = U32>
00063 class BitDecoder : public BitCoderBase<Code>
00064 {
00065 using BitCoderBase<Code>::len;
00066 using BitCoderBase<Code>::bitcache;
00067 using BitCoderBase<Code>::CodeBits;
00068
00069 public:
00070 Code fetchCode() {
00071 return (*p++);
00072 }
00073
00074 void begin(const unsigned char *ptr) {
00075 p = (const Code *) ptr;
00076 #if defined(USE_MMX)
00077 bitcache = _mm_cvtsi32_si64(fetchCode());
00078 #else
00079 bitcache = fetchCode();
00080 #endif
00081 len = CodeBits;
00082 }
00083
00084 void fillCache() {
00085 if (len < CodeBits) {
00086 #if defined(USE_MMX)
00087 bitcache = _mm_slli_si64(bitcache, CodeBits);
00088 bitcache = _mm_or_si64(bitcache, _mm_cvtsi32_si64(fetchCode()));
00089 #else
00090 bitcache <<= CodeBits;
00091 bitcache += fetchCode();
00092 #endif
00093 len += CodeBits;
00094 }
00095 }
00096
00097 unsigned int peekBits(unsigned int count) const {
00098 #if defined(USE_MMX)
00099 return _mm_cvtsi64_si32(_mm_srli_si64(bitcache, len - count)) & bitMask(count);
00100 #else
00101 return (bitcache >> (len - count)) & bitMask(count);
00102 #endif
00103 }
00104
00105 void skipBits(unsigned int count) {
00106 len -= count;
00107 }
00108
00109 unsigned int cachedLength() const {
00110 return len;
00111 }
00112
00113 unsigned int readBits(unsigned int count) {
00114 len -= count;
00115 #if defined(USE_MMX)
00116 return _mm_cvtsi64_si32(_mm_srli_si64(bitcache, len)) & bitMask(count);
00117 #else
00118 return (bitcache >> len) & bitMask(count);
00119 #endif
00120 }
00121
00122 void align() {
00123 len = 0;
00124 }
00125
00126 const unsigned char *end() {
00127 #if defined(USE_MMX)
00128 _mm_empty();
00129 #endif
00130 return (const unsigned char *) (p - (len >= CodeBits));
00131 }
00132
00133 private:
00134 const Code *p;
00135 };
00136
00137 template<typename Code = U32>
00138 class BitEncoder : public BitCoderBase<Code>
00139 {
00140 using BitCoderBase<Code>::len;
00141 using BitCoderBase<Code>::bitcache;
00142 using BitCoderBase<Code>::CodeBits;
00143
00144 public:
00145 void storeCode(Code code) {
00146 *p++ = (code);
00147 }
00148
00149 void begin(unsigned char *ptr) {
00150 p = (Code *) ptr;
00151 len = 0;
00152 #if defined(USE_MMX)
00153 bitcache = _mm_cvtsi32_si64(0);
00154 #else
00155 bitcache = 0;
00156 #endif
00157 }
00158
00159 void flushCache() {
00160 if (len >= CodeBits) {
00161 len -= CodeBits;
00162 #if defined(USE_MMX)
00163 storeCode(_mm_cvtsi64_si32(_mm_srli_si64(bitcache, len)));
00164 #else
00165 storeCode(bitcache >> len);
00166 #endif
00167 }
00168 }
00169
00170 void writeBits(unsigned int bits, unsigned int count) {
00171 len += count;
00172 #if defined(USE_MMX)
00173 bitcache = _mm_slli_si64(bitcache, count);
00174 bitcache = _mm_or_si64(bitcache, _mm_cvtsi32_si64(bits));
00175 #else
00176 bitcache = (bitcache << count) + bits;
00177 #endif
00178 }
00179
00180 void align() {
00181 if (len > 0) {
00182 #if defined(USE_MMX)
00183 storeCode(_mm_cvtsi64_si32(_mm_slli_si64(bitcache, CodeBits - len)));
00184 _mm_empty();
00185 #else
00186 storeCode(bitcache << (CodeBits - len));
00187 #endif
00188 len = 0;
00189 }
00190 }
00191
00192 unsigned char *end() {
00193 align();
00194 return (unsigned char *) p;
00195 }
00196
00197 private:
00198 Code *p;
00199 };
00200
00201 }
00202
00203 #endif