Octane v1.01.20 - The Open Compression Toolkit for C++ | http://octane.sourceforge.net/ |
00001 00002 00003 00004 00005 00006 00007 00008 00009 00010 00011 00012 00013 00014 //--------------------------------------------------------------------------- 00015 00016 //--------------------------------------------------------------------------- 00017 // recursive header protection 00018 #ifndef Coder_HuffmanNodesH 00019 #define Coder_HuffmanNodesH 00020 //--------------------------------------------------------------------------- 00021 00022 00023 //--------------------------------------------------------------------------- 00024 // application includes 00025 #include "../../bitio/bitio.hpp" 00026 // system includes 00027 #include <string> 00028 #include <iostream> 00029 #include <iomanip> 00030 #include <vector> 00031 #include <queue> 00032 #include <set> 00033 #include <bitset> 00034 using namespace std; 00035 //--------------------------------------------------------------------------- 00036 00037 00038 //--------------------------------------------------------------------------- 00039 // forward declarations 00040 class HuffNode; 00041 class HuffNode_Middle; 00042 class HuffNode_Leaf; 00043 //--------------------------------------------------------------------------- 00044 00045 00046 //--------------------------------------------------------------------------- 00047 // jibz modified huffman pq weight comparisn, 00048 #define OCTANE_USEJIBZHUFFMANPQGREATER 00049 // <mouser> so if left is a leaf and right is not a leaf, then you treat right as if it has lower weight 00050 // <mouser> (on ties) 00051 // <Jibz> yes .. that was what I was going for .. making internal nodes seem slightly smaller than leafs with the same weight 00052 // <mouser> now why is this good? 00053 // <Jibz> I don't know .. it may even be bad ;) 00054 // <mouser> hehehehe 00055 // <Jibz> but it seems like it might be better to make a choice, than to pick at random (or whatever the pq gives you) 00056 // COMPARISON SHOWS -> no perceivable difference. 00057 //--------------------------------------------------------------------------- 00058 00059 00060 00061 //--------------------------------------------------------------------------- 00062 // TypeDefs and Defines 00063 // 00064 // what kind of precision should we use for the weights? 00065 // note that because of the way trees are built, this values needs to store 00066 // the SUM of all weights in the tree, not just the maximum frequency of 00067 // any leaf(!). 00068 00069 // We could use a typedef here but it can cause warnings on type conversions 00070 // //typedef unsigned long THuffmanNodeWeight; 00071 // #define THuffmanNodeWeight unsigned long 00072 // #define THuffmanNodeWeight_MAX ULONGMAX 00073 // typedef unsigned long THuffmanNodeWeight; 00074 00076 #define THuffmanNodeWeight float 00077 00078 #define THuffmanNodeWeight_MAX FLOATMAX 00079 00091 #define DEF_HUFFMANPQ_MAXIMUM_CODEBITDEPTH 160 00092 00096 #define DEF_HUFFMANPQ_MAXFUNCBITS 200 00097 //--------------------------------------------------------------------------- 00098 00099 00100 00101 00102 00103 00104 //--------------------------------------------------------------------------- 00110 class HuffNode { 00111 protected: 00113 THuffmanNodeWeight weight; 00114 public: 00116 HuffNode() { ; } 00118 virtual ~HuffNode() { ; } 00119 public: 00121 bool operator>( const HuffNode* &a ) const {return weight > (a->get_weight());} 00122 public: 00124 virtual void traverse_buildbitcodes(std::bitset<DEF_HUFFMANPQ_MAXFUNCBITS> ¤t_bitset, int bitsetlength); 00125 public: 00127 virtual void recursive_freechildren() { ; } 00128 public: 00130 THuffmanNodeWeight get_weight() const {return weight;} 00132 void increment_weight(int increment) {weight+=increment;} 00134 void set_weight(THuffmanNodeWeight val) {weight=val;} 00136 virtual unsigned int get_memoryused() const {return sizeof(this);} 00138 virtual HuffNode *get_child0() {return 0;} 00140 virtual HuffNode *get_child1() {return 0;} 00141 public: 00143 virtual bool isleaf() {return false;} 00144 }; 00145 //--------------------------------------------------------------------------- 00146 00147 00148 //--------------------------------------------------------------------------- 00151 class HuffNode_Middle : public HuffNode { 00152 protected: 00154 HuffNode *child0; 00156 HuffNode *child1; 00157 public: 00159 HuffNode_Middle(HuffNode* c0, HuffNode *c1 ) {weight=c0->get_weight()+c1->get_weight(); child0=c0; child1=c1;} 00162 virtual ~HuffNode_Middle() { ; } 00163 public: 00164 void recursive_freechildren() {child0->recursive_freechildren(); delete child0; child1->recursive_freechildren(); delete child1;} 00165 public: 00166 virtual void traverse_buildbitcodes(std::bitset<DEF_HUFFMANPQ_MAXFUNCBITS> ¤t_bitset, int bitsetlength); 00167 public: 00168 virtual unsigned int get_memoryused() const {return sizeof(this)+(child0->get_memoryused())+(child1->get_memoryused());} 00169 virtual HuffNode *get_child0() {return child0;} 00170 virtual HuffNode *get_child1() {return child1;} 00171 public: 00172 bool isleaf() {return false;} 00173 }; 00174 //--------------------------------------------------------------------------- 00175 00176 00177 //--------------------------------------------------------------------------- 00183 class HuffNode_Leaf : public HuffNode { 00184 protected: 00185 // length of the bitcode for this symbol 00186 unsigned char code_bitsetlength; 00188 std::bitset<DEF_HUFFMANPQ_MAXIMUM_CODEBITDEPTH> code_bitset; 00190 int symbolid; 00191 public: 00193 HuffNode_Leaf(int insymbolid, THuffmanNodeWeight inweight) {symbolid=insymbolid; weight=inweight;} 00195 virtual ~HuffNode_Leaf() { ; } 00196 public: 00197 void recursive_freechildren() { ; } 00198 public: 00199 virtual void traverse_buildbitcodes(std::bitset<DEF_HUFFMANPQ_MAXFUNCBITS> ¤t_bitset, int bitsetlength); 00200 public: 00202 int get_symbolid() {return symbolid;} 00204 void set_symbolid(int val) {symbolid=val;} 00206 unsigned char get_bitcode_length() {return code_bitsetlength;}; 00208 std::string get_bitcode_string(); 00209 public: 00212 virtual unsigned int get_memoryused() const {return (unsigned int)(sizeof(this)+sizeof(code_bitset));} 00213 public: 00214 virtual bool isleaf() {return true;} 00215 public: 00217 virtual bool AddBitsToBitWriter(bitwriter &bw); 00218 }; 00219 //--------------------------------------------------------------------------- 00220 00221 00222 //--------------------------------------------------------------------------- 00226 00227 template< class T > 00228 class PQWeightGreater 00229 { 00230 public: 00231 bool operator() (const T& pLeft, const T& pRight) const 00232 { 00233 #ifdef OCTANE_USEJIBZHUFFMANPQGREATER 00234 if (pLeft->get_weight()==pRight->get_weight()) return (pLeft->isleaf() && !pRight->isleaf()); 00235 //if (pLeft->get_weight()==pRight->get_weight()) return (!pLeft->isleaf() && pRight->isleaf()); 00236 #endif 00237 return pLeft->get_weight()>pRight->get_weight(); 00238 } 00239 }; 00240 //--------------------------------------------------------------------------- 00241 00242 00243 //--------------------------------------------------------------------------- 00244 // typedef for priority queue of HuffNodes, which we use in huffman coding and in DictionarySet 00245 typedef std::priority_queue< HuffNode*, std::vector< HuffNode* >, PQWeightGreater<HuffNode*> > THuffmanNodePriorityQueue; 00246 //--------------------------------------------------------------------------- 00247 00248 00249 00250 00251 00252 00253 //--------------------------------------------------------------------------- 00254 #endif 00255 //--------------------------------------------------------------------------- 00256 00257