bitcoder.h
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 /* 64 bit unsigned datatype. On x86-32, the 64 bit datatypes are slow, so
00009  * use MMX if available.
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 /*__builtin_bswap32*/(*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++ = /*__builtin_bswap32*/(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; // silence compiler
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 } // namespace IZ
00202 
00203 #endif


imagezero
Author(s):
autogenerated on Thu Jun 6 2019 21:34:51