public static UrShift ( int number, int bits ) : int | ||
number | int | Number to operate on |
bits | int | Ammount of bits to shift |
return | int |
/// <param name="b"></param><param name="bindex"></param> <param name="n"></param><param name="s"></param> /// <param name="d"></param><param name="e"></param> <param name="t"></param><param name="m"></param> /// <param name="hp"></param><param name="hn"></param> <param name="v"></param><returns></returns> private int HuftBuild( int[] b, int bindex, int n, int s, int[] d, int[] e, int[] t, int[] m, int[] hp, int[] hn, int[] v) { // Given a list of code lengths and a maximum table size, make a set of // tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR // if the given code set is incomplete (the tables are still built in this case), Z_DATA_ERROR if the input // is invalid (an over-subscribed set of lengths), or Z_MEM_ERROR if not enough memory. int j; // counter int y; // number of dummy codes added // Generate counts for each bit length int p = 0; int i = n; do { this.bitLength[b[bindex + p]]++; p++; i--; // assume all entries <= BMAX }while (i != 0); if (this.bitLength[0] == n) { // null input--all zero length codes t[0] = -1; m[0] = 0; return(Zok); } // Find minimum and maximum length, bound *m by those int l = m[0]; for (j = 1; j <= Bmax; j++) { if (this.bitLength[j] != 0) { break; } } int k = j; if (l < j) { l = j; } for (i = Bmax; i != 0; i--) { if (this.bitLength[i] != 0) { break; } } int g = i; if (l > i) { l = i; } m[0] = l; // Adjust last length count to fill out codes, if needed for (y = 1 << j; j < i; j++, y <<= 1) { if ((y -= this.bitLength[j]) < 0) { return(ZDataError); } } if ((y -= this.bitLength[i]) < 0) { return(ZDataError); } this.bitLength[i] += y; // Generate starting offsets into the value table for each length this.bitOffsets[1] = j = 0; p = 1; int xp = 2; while (--i != 0) { // note that i == g from above this.bitOffsets[xp] = j += this.bitLength[p]; xp++; p++; } // Make a table of values in order of bit lengths i = 0; p = 0; do { if ((j = b[bindex + p]) != 0) { v[this.bitOffsets[j]++] = i; } p++; }while (++i < n); n = this.bitOffsets[g]; // set n to length of v // Generate the Huffman codes and for each, make the table entries this.bitOffsets[0] = i = 0; // first Huffman code is zero p = 0; // grab values in bit order int h = -1; int w = -l; this.tableStack[0] = 0; // just to keep compilers happy int q = 0; int z = 0; // go through the bit lengths (k already is bits in shortest code) for (; k <= g; k++) { int a = this.bitLength[k]; // counter for codes of length k while (a-- != 0) { // here i is the Huffman code of length k bits for value *p make tables up to required level int f; // i repeats in table every f entries while (k > w + l) { h++; w += l; // previous table always l bits // compute minimum size table less than or equal to l bits z = g - w; z = (z > l) ? l : z; // table size upper limit if ((f = 1 << (j = k - w)) > a + 1) { // try a k-w bit table too few codes for k-w bit table f -= a + 1; // deduct codes from patterns left xp = k; if (j < z) { while (++j < z) { // try smaller tables up to z bits if ((f <<= 1) <= this.bitLength[++xp]) { break; // enough codes to use up j bits } f -= this.bitLength[xp]; // else deduct codes from patterns } } } z = 1 << j; // table entries for j-bit table // allocate new table if (hn[0] + z > Many) { // (note: doesn't matter for fixed) return(ZDataError); // overflow of MANY } this.tableStack[h] = q = hn[0]; // DEBUG hn[0] += z; // connect to last table, if there is one if (h != 0) { this.bitOffsets[h] = i; // save pattern for backing up this.tableEntry[0] = (sbyte)j; // bits in this table this.tableEntry[1] = (sbyte)l; // bits to dump before this table j = SharedUtils.UrShift(i, w - l); this.tableEntry[2] = q - this.tableStack[h - 1] - j; // offset to this table Array.Copy(this.tableEntry, 0, hp, (this.tableStack[h - 1] + j) * 3, 3); // connect to last table } else { t[0] = q; // first table is returned result } } // set up table entry in r this.tableEntry[1] = (sbyte)(k - w); if (p >= n) { this.tableEntry[0] = 128 + 64; // out of values--invalid code } else if (v[p] < s) { this.tableEntry[0] = (sbyte)(v[p] < 256 ? 0 : 32 + 64); // 256 is end-of-block this.tableEntry[2] = v[p++]; // simple code is just the value } else { this.tableEntry[0] = (sbyte)(e[v[p] - s] + 16 + 64); // non-simple--look up in lists this.tableEntry[2] = d[v[p++] - s]; } // fill code-like entries with r f = 1 << (k - w); for (j = SharedUtils.UrShift(i, w); j < z; j += f) { Array.Copy(this.tableEntry, 0, hp, (q + j) * 3, 3); } // backwards increment the k-bit code i for (j = 1 << (k - 1); (i & j) != 0; j = SharedUtils.UrShift(j, 1)) { i ^= j; } i ^= j; // backup over finished tables int mask = (1 << w) - 1; // (1 << w) - 1, to avoid cc -O bug on HP while ((i & mask) != this.bitOffsets[h]) { h--; // don't need to update q w -= l; mask = (1 << w) - 1; } } } // Return Z_BUF_ERROR if we were given an incomplete table return(y != 0 && g != 1 ? ZBufError : Zok); }
/// <summary>Map from a distance to a distance code.</summary> /// <remarks>No side effects. _dist_code[256] and _dist_code[257] are never used.</remarks> internal static int DistanceCode(int dist) { return((dist < 256) ? DistCode[dist] : DistCode[256 + SharedUtils.UrShift(dist, 7)]); }