RLPark 1.0.0
Reinforcement Learning Framework in Java

CBZip2OutputStream.java

Go to the documentation of this file.
00001 /*
00002  * The Apache Software License, Version 1.1
00003  *
00004  * Copyright (c) 2001-2003 The Apache Software Foundation.  All rights
00005  * reserved.
00006  *
00007  * Redistribution and use in source and binary forms, with or without
00008  * modification, are permitted provided that the following conditions
00009  * are met:
00010  *
00011  * 1. Redistributions of source code must retain the above copyright
00012  *    notice, this list of conditions and the following disclaimer.
00013  *
00014  * 2. Redistributions in binary form must reproduce the above copyright
00015  *    notice, this list of conditions and the following disclaimer in
00016  *    the documentation and/or other materials provided with the
00017  *    distribution.
00018  *
00019  * 3. The end-user documentation included with the redistribution, if
00020  *    any, must include the following acknowlegement:
00021  *       "This product includes software developed by the
00022  *        Apache Software Foundation (http://www.apache.org/)."
00023  *    Alternately, this acknowlegement may appear in the software itself,
00024  *    if and wherever such third-party acknowlegements normally appear.
00025  *
00026  * 4. The names "Ant" and "Apache Software
00027  *    Foundation" must not be used to endorse or promote products derived
00028  *    from this software without prior written permission. For written
00029  *    permission, please contact apache@apache.org.
00030  *
00031  * 5. Products derived from this software may not be called "Apache"
00032  *    nor may "Apache" appear in their names without prior written
00033  *    permission of the Apache Group.
00034  *
00035  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
00036  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00037  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00038  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
00039  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00040  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00041  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
00042  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00043  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00044  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
00045  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00046  * SUCH DAMAGE.
00047  * ====================================================================
00048  *
00049  * This software consists of voluntary contributions made by many
00050  * individuals on behalf of the Apache Software Foundation.  For more
00051  * information on the Apache Software Foundation, please see
00052  * <http://www.apache.org/>.
00053  */
00054 
00055 /*
00056  * This package is based on the work done by Keiron Liddle, Aftex Software
00057  * <keiron@aftexsw.com> to whom the Ant project is very grateful for his
00058  * great code.
00059  */
00060 
00061 package zephyr.plugin.core.api.internal.bz2;
00062 
00063 import static zephyr.plugin.core.api.internal.bz2.BZip2Constants.G_SIZE;
00064 import static zephyr.plugin.core.api.internal.bz2.BZip2Constants.MAX_ALPHA_SIZE;
00065 import static zephyr.plugin.core.api.internal.bz2.BZip2Constants.MAX_SELECTORS;
00066 import static zephyr.plugin.core.api.internal.bz2.BZip2Constants.NUM_OVERSHOOT_BYTES;
00067 import static zephyr.plugin.core.api.internal.bz2.BZip2Constants.N_GROUPS;
00068 import static zephyr.plugin.core.api.internal.bz2.BZip2Constants.N_ITERS;
00069 import static zephyr.plugin.core.api.internal.bz2.BZip2Constants.RUNA;
00070 import static zephyr.plugin.core.api.internal.bz2.BZip2Constants.RUNB;
00071 import static zephyr.plugin.core.api.internal.bz2.BZip2Constants.baseBlockSize;
00072 import static zephyr.plugin.core.api.internal.bz2.BZip2Constants.rNums;
00073 import java.io.IOException;
00074 import java.io.OutputStream;
00075 
00083 public class CBZip2OutputStream extends OutputStream {
00084   protected static final int SETMASK = 1 << 21;
00085   protected static final int CLEARMASK = ~SETMASK;
00086   protected static final int GREATER_ICOST = 15;
00087   protected static final int LESSER_ICOST = 0;
00088   protected static final int SMALL_THRESH = 20;
00089   protected static final int DEPTH_THRESH = 10;
00090 
00091   /*
00092    * If you are ever unlucky/improbable enough to get a stack overflow whilst
00093    * sorting, increase the following constant and try again. In practice I have
00094    * never seen the stack go above 27 elems, so the following limit seems very
00095    * generous.
00096    */
00097   protected static final int QSORT_STACK_SIZE = 1000;
00098 
00099   private static void panic() {
00100     System.out.println("panic");
00101     // throw new CError();
00102   }
00103 
00104   private void makeMaps() {
00105     int i;
00106     nInUse = 0;
00107     for (i = 0; i < 256; i++)
00108       if (inUse[i]) {
00109         seqToUnseq[nInUse] = (char) i;
00110         unseqToSeq[i] = (char) nInUse;
00111         nInUse++;
00112       }
00113   }
00114 
00115   protected static void hbMakeCodeLengths(char[] len, int[] freq, int alphaSize, int maxLen) {
00116     /*
00117      * Nodes and heap entries run from 1. Entry 0 for both the heap and nodes is
00118      * a sentinel.
00119      */
00120     int nNodes, nHeap, n1, n2, i, j, k;
00121     boolean tooLong;
00122 
00123     int[] heap = new int[MAX_ALPHA_SIZE + 2];
00124     int[] weight = new int[MAX_ALPHA_SIZE * 2];
00125     int[] parent = new int[MAX_ALPHA_SIZE * 2];
00126 
00127     for (i = 0; i < alphaSize; i++)
00128       weight[i + 1] = (freq[i] == 0 ? 1 : freq[i]) << 8;
00129 
00130     while (true) {
00131       nNodes = alphaSize;
00132       nHeap = 0;
00133 
00134       heap[0] = 0;
00135       weight[0] = 0;
00136       parent[0] = -2;
00137 
00138       for (i = 1; i <= alphaSize; i++) {
00139         parent[i] = -1;
00140         nHeap++;
00141         heap[nHeap] = i;
00142         {
00143           int zz, tmp;
00144           zz = nHeap;
00145           tmp = heap[zz];
00146           while (weight[tmp] < weight[heap[zz >> 1]]) {
00147             heap[zz] = heap[zz >> 1];
00148             zz >>= 1;
00149           }
00150           heap[zz] = tmp;
00151         }
00152       }
00153       if (!(nHeap < MAX_ALPHA_SIZE + 2))
00154         panic();
00155 
00156       while (nHeap > 1) {
00157         n1 = heap[1];
00158         heap[1] = heap[nHeap];
00159         nHeap--;
00160         {
00161           int zz = 0, yy = 0, tmp = 0;
00162           zz = 1;
00163           tmp = heap[zz];
00164           while (true) {
00165             yy = zz << 1;
00166             if (yy > nHeap)
00167               break;
00168             if (yy < nHeap && weight[heap[yy + 1]] < weight[heap[yy]])
00169               yy++;
00170             if (weight[tmp] < weight[heap[yy]])
00171               break;
00172             heap[zz] = heap[yy];
00173             zz = yy;
00174           }
00175           heap[zz] = tmp;
00176         }
00177         n2 = heap[1];
00178         heap[1] = heap[nHeap];
00179         nHeap--;
00180         {
00181           int zz = 0, yy = 0, tmp = 0;
00182           zz = 1;
00183           tmp = heap[zz];
00184           while (true) {
00185             yy = zz << 1;
00186             if (yy > nHeap)
00187               break;
00188             if (yy < nHeap && weight[heap[yy + 1]] < weight[heap[yy]])
00189               yy++;
00190             if (weight[tmp] < weight[heap[yy]])
00191               break;
00192             heap[zz] = heap[yy];
00193             zz = yy;
00194           }
00195           heap[zz] = tmp;
00196         }
00197         nNodes++;
00198         parent[n1] = parent[n2] = nNodes;
00199 
00200         weight[nNodes] = (weight[n1] & 0xffffff00)
00201             + (weight[n2] & 0xffffff00)
00202             | 1
00203             + ((weight[n1] & 0x000000ff) > (weight[n2] & 0x000000ff) ? weight[n1] & 0x000000ff
00204                 : weight[n2] & 0x000000ff);
00205 
00206         parent[nNodes] = -1;
00207         nHeap++;
00208         heap[nHeap] = nNodes;
00209         {
00210           int zz = 0, tmp = 0;
00211           zz = nHeap;
00212           tmp = heap[zz];
00213           while (weight[tmp] < weight[heap[zz >> 1]]) {
00214             heap[zz] = heap[zz >> 1];
00215             zz >>= 1;
00216           }
00217           heap[zz] = tmp;
00218         }
00219       }
00220       if (!(nNodes < MAX_ALPHA_SIZE * 2))
00221         panic();
00222 
00223       tooLong = false;
00224       for (i = 1; i <= alphaSize; i++) {
00225         j = 0;
00226         k = i;
00227         while (parent[k] >= 0) {
00228           k = parent[k];
00229           j++;
00230         }
00231         len[i - 1] = (char) j;
00232         if (j > maxLen)
00233           tooLong = true;
00234       }
00235 
00236       if (!tooLong)
00237         break;
00238 
00239       for (i = 1; i < alphaSize; i++) {
00240         j = weight[i] >> 8;
00241         j = 1 + j / 2;
00242         weight[i] = j << 8;
00243       }
00244     }
00245   }
00246 
00247   /*
00248    * index of the last char in the block, so the block size == last + 1.
00249    */
00250   int last;
00251 
00252   /*
00253    * index in zptr[] of original string after sorting.
00254    */
00255   int origPtr;
00256 
00257   /*
00258    * always: in the range 0 .. 9. The current block size is 100000 * this
00259    * number.
00260    */
00261   int blockSize100k;
00262 
00263   boolean blockRandomised;
00264 
00265   int bytesOut;
00266   int bsBuff;
00267   int bsLive;
00268   CRC mCrc = new CRC();
00269 
00270   private final boolean[] inUse = new boolean[256];
00271   private int nInUse;
00272 
00273   private final char[] seqToUnseq = new char[256];
00274   private final char[] unseqToSeq = new char[256];
00275 
00276   private final char[] selector = new char[MAX_SELECTORS];
00277   private final char[] selectorMtf = new char[MAX_SELECTORS];
00278 
00279   private char[] block;
00280   private int[] quadrant;
00281   private int[] zptr;
00282   private short[] szptr;
00283   private int[] ftab;
00284 
00285   private int nMTF;
00286 
00287   private final int[] mtfFreq = new int[MAX_ALPHA_SIZE];
00288 
00289   /*
00290    * Used when sorting. If too many long comparisons happen, we stop sorting,
00291    * randomise the block slightly, and try again.
00292    */
00293   private final int workFactor;
00294   private int workDone;
00295   private int workLimit;
00296   private boolean firstAttempt;
00297   private int currentChar = -1;
00298   private int runLength = 0;
00299 
00300   public CBZip2OutputStream(OutputStream inStream) throws IOException {
00301     this(inStream, 9);
00302   }
00303 
00304   public CBZip2OutputStream(OutputStream inStream, int p_inBlockSize) throws IOException {
00305     block = null;
00306     quadrant = null;
00307     zptr = null;
00308     ftab = null;
00309 
00310     bsSetStream(inStream);
00311 
00312     workFactor = 50;
00313     int inBlockSize = p_inBlockSize;
00314     if (inBlockSize > 9)
00315       inBlockSize = 9;
00316     if (inBlockSize < 1)
00317       inBlockSize = 1;
00318     blockSize100k = inBlockSize;
00319     allocateCompressStructures();
00320     initialize();
00321     initBlock();
00322   }
00323 
00329   @Override
00330   public void write(int bv) throws IOException {
00331     int b = (256 + bv) % 256;
00332     if (currentChar != -1) {
00333       if (currentChar == b) {
00334         runLength++;
00335         if (runLength > 254) {
00336           writeRun();
00337           currentChar = -1;
00338           runLength = 0;
00339         }
00340       } else {
00341         writeRun();
00342         runLength = 1;
00343         currentChar = b;
00344       }
00345     } else {
00346       currentChar = b;
00347       runLength++;
00348     }
00349   }
00350 
00351   private void writeRun() throws IOException {
00352     if (last < allowableBlockSize) {
00353       inUse[currentChar] = true;
00354       for (int i = 0; i < runLength; i++)
00355         mCrc.updateCRC((char) currentChar);
00356       switch (runLength) {
00357       case 1:
00358         last++;
00359         block[last + 1] = (char) currentChar;
00360         break;
00361       case 2:
00362         last++;
00363         block[last + 1] = (char) currentChar;
00364         last++;
00365         block[last + 1] = (char) currentChar;
00366         break;
00367       case 3:
00368         last++;
00369         block[last + 1] = (char) currentChar;
00370         last++;
00371         block[last + 1] = (char) currentChar;
00372         last++;
00373         block[last + 1] = (char) currentChar;
00374         break;
00375       default:
00376         inUse[runLength - 4] = true;
00377         last++;
00378         block[last + 1] = (char) currentChar;
00379         last++;
00380         block[last + 1] = (char) currentChar;
00381         last++;
00382         block[last + 1] = (char) currentChar;
00383         last++;
00384         block[last + 1] = (char) currentChar;
00385         last++;
00386         block[last + 1] = (char) (runLength - 4);
00387         break;
00388       }
00389     } else {
00390       endBlock();
00391       initBlock();
00392       writeRun();
00393     }
00394   }
00395 
00396   boolean closed = false;
00397 
00398   @Override
00399   protected void finalize() throws Throwable {
00400     close();
00401     super.finalize();
00402   }
00403 
00404   @Override
00405   public void close() throws IOException {
00406     if (closed)
00407       return;
00408 
00409     if (runLength > 0)
00410       writeRun();
00411     currentChar = -1;
00412     endBlock();
00413     endCompression();
00414     closed = true;
00415     super.close();
00416     bsStream.close();
00417   }
00418 
00419   @Override
00420   public void flush() throws IOException {
00421     super.flush();
00422     bsStream.flush();
00423   }
00424 
00425   private int blockCRC, combinedCRC;
00426 
00427   private void initialize() throws IOException {
00428     bytesOut = 0;
00429     /*
00430      * Write `magic' bytes h indicating file-format == huffmanised, followed by
00431      * a digit indicating blockSize100k.
00432      */
00433     bsPutUChar('h');
00434     bsPutUChar('0' + blockSize100k);
00435 
00436     combinedCRC = 0;
00437   }
00438 
00439   private int allowableBlockSize;
00440 
00441   private void initBlock() {
00442     // blockNo++;
00443     mCrc.initialiseCRC();
00444     last = -1;
00445     // ch = 0;
00446 
00447     for (int i = 0; i < 256; i++)
00448       inUse[i] = false;
00449 
00450     /* 20 is just a paranoia constant */
00451     allowableBlockSize = baseBlockSize * blockSize100k - 20;
00452   }
00453 
00454   private void endBlock() throws IOException {
00455     blockCRC = mCrc.getFinalCRC();
00456     combinedCRC = combinedCRC << 1 | combinedCRC >>> 31;
00457     combinedCRC ^= blockCRC;
00458 
00459     /* sort the block and establish posn of original string */
00460     doReversibleTransformation();
00461 
00462     /*
00463      * A 6-byte block header, the value chosen arbitrarily as 0x314159265359
00464      * :-). A 32 bit value does not really give a strong enough guarantee that
00465      * the value will not appear by chance in the compressed datastream.
00466      * Worst-case probability of this event, for a 900k block, is about 2.0e-3
00467      * for 32 bits, 1.0e-5 for 40 bits and 4.0e-8 for 48 bits. For a compressed
00468      * file of size 100Gb -- about 100000 blocks -- only a 48-bit marker will
00469      * do. NB: normal compression/ decompression do *not* rely on these
00470      * statistical properties. They are only important when trying to recover
00471      * blocks from damaged files.
00472      */
00473     bsPutUChar(0x31);
00474     bsPutUChar(0x41);
00475     bsPutUChar(0x59);
00476     bsPutUChar(0x26);
00477     bsPutUChar(0x53);
00478     bsPutUChar(0x59);
00479 
00480     /* Now the block's CRC, so it is in a known place. */
00481     bsPutint(blockCRC);
00482 
00483     /* Now a single bit indicating randomisation. */
00484     if (blockRandomised) {
00485       bsW(1, 1);
00486     } else
00487       bsW(1, 0);
00488 
00489     /* Finally, block's contents proper. */
00490     moveToFrontCodeAndSend();
00491   }
00492 
00493   private void endCompression() throws IOException {
00494     /*
00495      * Now another magic 48-bit number, 0x177245385090, to indicate the end of
00496      * the last block. (sqrt(pi), if you want to know. I did want to use e, but
00497      * it contains too much repetition -- 27 18 28 18 28 46 -- for me to feel
00498      * statistically comfortable. Call me paranoid.)
00499      */
00500     bsPutUChar(0x17);
00501     bsPutUChar(0x72);
00502     bsPutUChar(0x45);
00503     bsPutUChar(0x38);
00504     bsPutUChar(0x50);
00505     bsPutUChar(0x90);
00506 
00507     bsPutint(combinedCRC);
00508 
00509     bsFinishedWithStream();
00510   }
00511 
00512   private static void hbAssignCodes(int[] code, char[] length, int minLen, int maxLen, int alphaSize) {
00513     int n, vec, i;
00514     vec = 0;
00515     for (n = minLen; n <= maxLen; n++) {
00516       for (i = 0; i < alphaSize; i++)
00517         if (length[i] == n) {
00518           code[i] = vec;
00519           vec++;
00520         }
00521       ;
00522       vec <<= 1;
00523     }
00524   }
00525 
00526   private void bsSetStream(OutputStream f) {
00527     bsStream = f;
00528     bsLive = 0;
00529     bsBuff = 0;
00530     bytesOut = 0;
00531   }
00532 
00533   private void bsFinishedWithStream() throws IOException {
00534     while (bsLive > 0) {
00535       int ch = bsBuff >> 24;
00536       try {
00537         bsStream.write(ch); // write 8-bit
00538       } catch (IOException e) {
00539         throw e;
00540       }
00541       bsBuff <<= 8;
00542       bsLive -= 8;
00543       bytesOut++;
00544     }
00545   }
00546 
00547   private void bsW(int n, int v) throws IOException {
00548     while (bsLive >= 8) {
00549       int ch = bsBuff >> 24;
00550       try {
00551         bsStream.write(ch); // write 8-bit
00552       } catch (IOException e) {
00553         throw e;
00554       }
00555       bsBuff <<= 8;
00556       bsLive -= 8;
00557       bytesOut++;
00558     }
00559     bsBuff |= v << 32 - bsLive - n;
00560     bsLive += n;
00561   }
00562 
00563   private void bsPutUChar(int c) throws IOException {
00564     bsW(8, c);
00565   }
00566 
00567   private void bsPutint(int u) throws IOException {
00568     bsW(8, u >> 24 & 0xff);
00569     bsW(8, u >> 16 & 0xff);
00570     bsW(8, u >> 8 & 0xff);
00571     bsW(8, u & 0xff);
00572   }
00573 
00574   private void bsPutIntVS(int numBits, int c) throws IOException {
00575     bsW(numBits, c);
00576   }
00577 
00578   private void sendMTFValues() throws IOException {
00579     char len[][] = new char[N_GROUPS][MAX_ALPHA_SIZE];
00580 
00581     int v, t, i, j, gs, ge, bt, bc, iter;
00582     int nSelectors = 0, alphaSize, minLen, maxLen, selCtr;
00583     @SuppressWarnings("unused")
00584     int nGroups, nBytes;
00585 
00586     alphaSize = nInUse + 2;
00587     for (t = 0; t < N_GROUPS; t++)
00588       for (v = 0; v < alphaSize; v++)
00589         len[t][v] = (char) GREATER_ICOST;
00590 
00591     /* Decide how many coding tables to use */
00592     if (nMTF <= 0)
00593       panic();
00594 
00595     if (nMTF < 200)
00596       nGroups = 2;
00597     else if (nMTF < 600)
00598       nGroups = 3;
00599     else if (nMTF < 1200)
00600       nGroups = 4;
00601     else if (nMTF < 2400)
00602       nGroups = 5;
00603     else
00604       nGroups = 6;
00605 
00606     /* Generate an initial set of coding tables */{
00607       int nPart, remF, tFreq, aFreq;
00608 
00609       nPart = nGroups;
00610       remF = nMTF;
00611       gs = 0;
00612       while (nPart > 0) {
00613         tFreq = remF / nPart;
00614         ge = gs - 1;
00615         aFreq = 0;
00616         while (aFreq < tFreq && ge < alphaSize - 1) {
00617           ge++;
00618           aFreq += mtfFreq[ge];
00619         }
00620 
00621         if (ge > gs && nPart != nGroups && nPart != 1 && ((nGroups - nPart) & 1) == 1) {
00622           aFreq -= mtfFreq[ge];
00623           ge--;
00624         }
00625 
00626         for (v = 0; v < alphaSize; v++)
00627           if (v >= gs && v <= ge)
00628             len[nPart - 1][v] = (char) LESSER_ICOST;
00629           else
00630             len[nPart - 1][v] = (char) GREATER_ICOST;
00631 
00632         nPart--;
00633         gs = ge + 1;
00634         remF -= aFreq;
00635       }
00636     }
00637 
00638     int[][] rfreq = new int[N_GROUPS][MAX_ALPHA_SIZE];
00639     int[] fave = new int[N_GROUPS];
00640     short[] cost = new short[N_GROUPS];
00641     /*
00642      * Iterate up to N_ITERS times to improve the tables.
00643      */
00644     for (iter = 0; iter < N_ITERS; iter++) {
00645       for (t = 0; t < nGroups; t++)
00646         fave[t] = 0;
00647 
00648       for (t = 0; t < nGroups; t++)
00649         for (v = 0; v < alphaSize; v++)
00650           rfreq[t][v] = 0;
00651 
00652       nSelectors = 0;
00653       gs = 0;
00654       while (true) {
00655 
00656         /* Set group start & end marks. */
00657         if (gs >= nMTF)
00658           break;
00659         ge = gs + G_SIZE - 1;
00660         if (ge >= nMTF)
00661           ge = nMTF - 1;
00662 
00663         /*
00664          * Calculate the cost of this group as coded by each of the coding
00665          * tables.
00666          */
00667         for (t = 0; t < nGroups; t++)
00668           cost[t] = 0;
00669 
00670         if (nGroups == 6) {
00671           short cost0, cost1, cost2, cost3, cost4, cost5;
00672           cost0 = cost1 = cost2 = cost3 = cost4 = cost5 = 0;
00673           for (i = gs; i <= ge; i++) {
00674             short icv = szptr[i];
00675             cost0 += len[0][icv];
00676             cost1 += len[1][icv];
00677             cost2 += len[2][icv];
00678             cost3 += len[3][icv];
00679             cost4 += len[4][icv];
00680             cost5 += len[5][icv];
00681           }
00682           cost[0] = cost0;
00683           cost[1] = cost1;
00684           cost[2] = cost2;
00685           cost[3] = cost3;
00686           cost[4] = cost4;
00687           cost[5] = cost5;
00688         } else
00689           for (i = gs; i <= ge; i++) {
00690             short icv = szptr[i];
00691             for (t = 0; t < nGroups; t++)
00692               cost[t] += len[t][icv];
00693           }
00694 
00695         /*
00696          * Find the coding table which is best for this group, and record its
00697          * identity in the selector table.
00698          */
00699         bc = 999999999;
00700         bt = -1;
00701         for (t = 0; t < nGroups; t++)
00702           if (cost[t] < bc) {
00703             bc = cost[t];
00704             bt = t;
00705           }
00706         ;
00707         fave[bt]++;
00708         selector[nSelectors] = (char) bt;
00709         nSelectors++;
00710 
00711         /*
00712          * Increment the symbol frequencies for the selected table.
00713          */
00714         for (i = gs; i <= ge; i++)
00715           rfreq[bt][szptr[i]]++;
00716 
00717         gs = ge + 1;
00718       }
00719 
00720       /*
00721        * Recompute the tables based on the accumulated frequencies.
00722        */
00723       for (t = 0; t < nGroups; t++)
00724         hbMakeCodeLengths(len[t], rfreq[t], alphaSize, 20);
00725     }
00726 
00727     rfreq = null;
00728     fave = null;
00729     cost = null;
00730 
00731     if (!(nGroups < 8))
00732       panic();
00733     if (!(nSelectors < 32768 && nSelectors <= 2 + 900000 / G_SIZE))
00734       panic();
00735 
00736 
00737     /* Compute MTF values for the selectors. */
00738     {
00739       char[] pos = new char[N_GROUPS];
00740       char ll_i, tmp2, tmp;
00741       for (i = 0; i < nGroups; i++)
00742         pos[i] = (char) i;
00743       for (i = 0; i < nSelectors; i++) {
00744         ll_i = selector[i];
00745         j = 0;
00746         tmp = pos[j];
00747         while (ll_i != tmp) {
00748           j++;
00749           tmp2 = tmp;
00750           tmp = pos[j];
00751           pos[j] = tmp2;
00752         }
00753         pos[0] = tmp;
00754         selectorMtf[i] = (char) j;
00755       }
00756     }
00757 
00758     int[][] code = new int[N_GROUPS][MAX_ALPHA_SIZE];
00759 
00760     /* Assign actual codes for the tables. */
00761     for (t = 0; t < nGroups; t++) {
00762       minLen = 32;
00763       maxLen = 0;
00764       for (i = 0; i < alphaSize; i++) {
00765         if (len[t][i] > maxLen)
00766           maxLen = len[t][i];
00767         if (len[t][i] < minLen)
00768           minLen = len[t][i];
00769       }
00770       if (maxLen > 20)
00771         panic();
00772       if (minLen < 1)
00773         panic();
00774       hbAssignCodes(code[t], len[t], minLen, maxLen, alphaSize);
00775     }
00776 
00777     /* Transmit the mapping table. */
00778     {
00779       boolean[] inUse16 = new boolean[16];
00780       for (i = 0; i < 16; i++) {
00781         inUse16[i] = false;
00782         for (j = 0; j < 16; j++)
00783           if (inUse[i * 16 + j])
00784             inUse16[i] = true;
00785       }
00786 
00787       nBytes = bytesOut;
00788       for (i = 0; i < 16; i++)
00789         if (inUse16[i])
00790           bsW(1, 1);
00791         else
00792           bsW(1, 0);
00793 
00794       for (i = 0; i < 16; i++)
00795         if (inUse16[i])
00796           for (j = 0; j < 16; j++)
00797             if (inUse[i * 16 + j])
00798               bsW(1, 1);
00799             else
00800               bsW(1, 0);
00801 
00802     }
00803 
00804     /* Now the selectors. */
00805     nBytes = bytesOut;
00806     bsW(3, nGroups);
00807     bsW(15, nSelectors);
00808     for (i = 0; i < nSelectors; i++) {
00809       for (j = 0; j < selectorMtf[i]; j++)
00810         bsW(1, 1);
00811       bsW(1, 0);
00812     }
00813 
00814     /* Now the coding tables. */
00815     nBytes = bytesOut;
00816 
00817     for (t = 0; t < nGroups; t++) {
00818       int curr = len[t][0];
00819       bsW(5, curr);
00820       for (i = 0; i < alphaSize; i++) {
00821         while (curr < len[t][i]) {
00822           bsW(2, 2);
00823           curr++; /* 10 */
00824         }
00825         while (curr > len[t][i]) {
00826           bsW(2, 3);
00827           curr--; /* 11 */
00828         }
00829         bsW(1, 0);
00830       }
00831     }
00832 
00833     /* And finally, the block data proper */
00834     nBytes = bytesOut;
00835     selCtr = 0;
00836     gs = 0;
00837     while (true) {
00838       if (gs >= nMTF)
00839         break;
00840       ge = gs + G_SIZE - 1;
00841       if (ge >= nMTF)
00842         ge = nMTF - 1;
00843       for (i = gs; i <= ge; i++)
00844         bsW(len[selector[selCtr]][szptr[i]], code[selector[selCtr]][szptr[i]]);
00845 
00846       gs = ge + 1;
00847       selCtr++;
00848     }
00849     if (!(selCtr == nSelectors))
00850       panic();
00851   }
00852 
00853   private void moveToFrontCodeAndSend() throws IOException {
00854     bsPutIntVS(24, origPtr);
00855     generateMTFValues();
00856     sendMTFValues();
00857   }
00858 
00859   private OutputStream bsStream;
00860 
00861   private void simpleSort(int lo, int hi, int d) {
00862     int i, j, h, bigN, hp;
00863     int v;
00864 
00865     bigN = hi - lo + 1;
00866     if (bigN < 2)
00867       return;
00868 
00869     hp = 0;
00870     while (incs[hp] < bigN)
00871       hp++;
00872     hp--;
00873 
00874     for (; hp >= 0; hp--) {
00875       h = incs[hp];
00876 
00877       i = lo + h;
00878       while (true) {
00879         /* copy 1 */
00880         if (i > hi)
00881           break;
00882         v = zptr[i];
00883         j = i;
00884         while (fullGtU(zptr[j - h] + d, v + d)) {
00885           zptr[j] = zptr[j - h];
00886           j = j - h;
00887           if (j <= lo + h - 1)
00888             break;
00889         }
00890         zptr[j] = v;
00891         i++;
00892 
00893         /* copy 2 */
00894         if (i > hi)
00895           break;
00896         v = zptr[i];
00897         j = i;
00898         while (fullGtU(zptr[j - h] + d, v + d)) {
00899           zptr[j] = zptr[j - h];
00900           j = j - h;
00901           if (j <= lo + h - 1)
00902             break;
00903         }
00904         zptr[j] = v;
00905         i++;
00906 
00907         /* copy 3 */
00908         if (i > hi)
00909           break;
00910         v = zptr[i];
00911         j = i;
00912         while (fullGtU(zptr[j - h] + d, v + d)) {
00913           zptr[j] = zptr[j - h];
00914           j = j - h;
00915           if (j <= lo + h - 1)
00916             break;
00917         }
00918         zptr[j] = v;
00919         i++;
00920 
00921         if (workDone > workLimit && firstAttempt)
00922           return;
00923       }
00924     }
00925   }
00926 
00927   private void vswap(int p_p1, int p_p2, int p_n) {
00928     int p1 = p_p1, p2 = p_p2, n = p_n;
00929     int temp = 0;
00930     while (n > 0) {
00931       temp = zptr[p1];
00932       zptr[p1] = zptr[p2];
00933       zptr[p2] = temp;
00934       p1++;
00935       p2++;
00936       n--;
00937     }
00938   }
00939 
00940   private static char med3(char p_a, char p_b, char p_c) {
00941     char a = p_a, b = p_b, c = p_c;
00942     char t;
00943     if (a > b) {
00944       t = a;
00945       a = b;
00946       b = t;
00947     }
00948     if (b > c)
00949       b = c;
00950     if (a > b)
00951       b = a;
00952     return b;
00953   }
00954 
00955   private static class StackElem {
00956     int ll;
00957     int hh;
00958     int dd;
00959   }
00960 
00961   @SuppressWarnings("synthetic-access")
00962   private void qSort3(int loSt, int hiSt, int dSt) {
00963     int unLo, unHi, ltLo, gtHi, med, n, m;
00964     int sp, lo, hi, d;
00965     StackElem[] stack = new StackElem[QSORT_STACK_SIZE];
00966     for (int count = 0; count < QSORT_STACK_SIZE; count++)
00967       stack[count] = new StackElem();
00968 
00969     sp = 0;
00970 
00971     stack[sp].ll = loSt;
00972     stack[sp].hh = hiSt;
00973     stack[sp].dd = dSt;
00974     sp++;
00975 
00976     while (sp > 0) {
00977       if (sp >= QSORT_STACK_SIZE)
00978         panic();
00979 
00980       sp--;
00981       lo = stack[sp].ll;
00982       hi = stack[sp].hh;
00983       d = stack[sp].dd;
00984 
00985       if (hi - lo < SMALL_THRESH || d > DEPTH_THRESH) {
00986         simpleSort(lo, hi, d);
00987         if (workDone > workLimit && firstAttempt)
00988           return;
00989         continue;
00990       }
00991 
00992       med = med3(block[zptr[lo] + d + 1], block[zptr[hi] + d + 1], block[zptr[lo + hi >>> 1] + d + 1]);
00993 
00994       unLo = ltLo = lo;
00995       unHi = gtHi = hi;
00996 
00997       while (true) {
00998         while (true) {
00999           if (unLo > unHi)
01000             break;
01001           n = block[zptr[unLo] + d + 1] - med;
01002           if (n == 0) {
01003             int temp = 0;
01004             temp = zptr[unLo];
01005             zptr[unLo] = zptr[ltLo];
01006             zptr[ltLo] = temp;
01007             ltLo++;
01008             unLo++;
01009             continue;
01010           }
01011           ;
01012           if (n > 0)
01013             break;
01014           unLo++;
01015         }
01016         while (true) {
01017           if (unLo > unHi)
01018             break;
01019           n = block[zptr[unHi] + d + 1] - med;
01020           if (n == 0) {
01021             int temp = 0;
01022             temp = zptr[unHi];
01023             zptr[unHi] = zptr[gtHi];
01024             zptr[gtHi] = temp;
01025             gtHi--;
01026             unHi--;
01027             continue;
01028           }
01029           ;
01030           if (n < 0)
01031             break;
01032           unHi--;
01033         }
01034         if (unLo > unHi)
01035           break;
01036         int temp = 0;
01037         temp = zptr[unLo];
01038         zptr[unLo] = zptr[unHi];
01039         zptr[unHi] = temp;
01040         unLo++;
01041         unHi--;
01042       }
01043 
01044       if (gtHi < ltLo) {
01045         stack[sp].ll = lo;
01046         stack[sp].hh = hi;
01047         stack[sp].dd = d + 1;
01048         sp++;
01049         continue;
01050       }
01051 
01052       n = ltLo - lo < unLo - ltLo ? ltLo - lo : unLo - ltLo;
01053       vswap(lo, unLo - n, n);
01054       m = hi - gtHi < gtHi - unHi ? hi - gtHi : gtHi - unHi;
01055       vswap(unLo, hi - m + 1, m);
01056 
01057       n = lo + unLo - ltLo - 1;
01058       m = hi - (gtHi - unHi) + 1;
01059 
01060       stack[sp].ll = lo;
01061       stack[sp].hh = n;
01062       stack[sp].dd = d;
01063       sp++;
01064 
01065       stack[sp].ll = n + 1;
01066       stack[sp].hh = m - 1;
01067       stack[sp].dd = d + 1;
01068       sp++;
01069 
01070       stack[sp].ll = m;
01071       stack[sp].hh = hi;
01072       stack[sp].dd = d;
01073       sp++;
01074     }
01075   }
01076 
01077   private void mainSort() {
01078     int i, j, ss, sb;
01079     int[] runningOrder = new int[256];
01080     int[] copy = new int[256];
01081     boolean[] bigDone = new boolean[256];
01082     int c1, c2;
01083 
01084 
01085     /*
01086      * In the various block-sized structures, live data runs from 0 to
01087      * last+NUM_OVERSHOOT_BYTES inclusive. First, set up the overshoot area for
01088      * block.
01089      */
01090 
01091     // if (verbosity >= 4) fprintf ( stderr, "   sort initialise ...\n" );
01092     for (i = 0; i < NUM_OVERSHOOT_BYTES; i++)
01093       block[last + i + 2] = block[i % (last + 1) + 1];
01094     for (i = 0; i <= last + NUM_OVERSHOOT_BYTES; i++)
01095       quadrant[i] = 0;
01096 
01097     block[0] = block[last + 1];
01098 
01099     if (last < 4000) {
01100       /*
01101        * Use simpleSort(), since the full sorting mechanism has quite a large
01102        * constant overhead.
01103        */
01104       for (i = 0; i <= last; i++)
01105         zptr[i] = i;
01106       firstAttempt = false;
01107       workDone = workLimit = 0;
01108       simpleSort(0, last, 0);
01109     } else {
01110       for (i = 0; i <= 255; i++)
01111         bigDone[i] = false;
01112 
01113       for (i = 0; i <= 65536; i++)
01114         ftab[i] = 0;
01115 
01116       c1 = block[0];
01117       for (i = 0; i <= last; i++) {
01118         c2 = block[i + 1];
01119         ftab[(c1 << 8) + c2]++;
01120         c1 = c2;
01121       }
01122 
01123       for (i = 1; i <= 65536; i++)
01124         ftab[i] += ftab[i - 1];
01125 
01126       c1 = block[1];
01127       for (i = 0; i < last; i++) {
01128         c2 = block[i + 2];
01129         j = (c1 << 8) + c2;
01130         c1 = c2;
01131         ftab[j]--;
01132         zptr[ftab[j]] = i;
01133       }
01134 
01135       j = (block[last + 1] << 8) + block[1];
01136       ftab[j]--;
01137       zptr[ftab[j]] = last;
01138 
01139       /*
01140        * Now ftab contains the first loc of every small bucket. Calculate the
01141        * running order, from smallest to largest big bucket.
01142        */
01143 
01144       for (i = 0; i <= 255; i++)
01145         runningOrder[i] = i;
01146 
01147       {
01148         int vv;
01149         int h = 1;
01150         do
01151           h = 3 * h + 1;
01152         while (h <= 256);
01153         do {
01154           h = h / 3;
01155           for (i = h; i <= 255; i++) {
01156             vv = runningOrder[i];
01157             j = i;
01158             while (ftab[runningOrder[j - h] + 1 << 8] - ftab[runningOrder[j - h] << 8] > ftab[vv + 1 << 8]
01159                 - ftab[vv << 8]) {
01160               runningOrder[j] = runningOrder[j - h];
01161               j = j - h;
01162               if (j <= h - 1)
01163                 break;
01164             }
01165             runningOrder[j] = vv;
01166           }
01167         } while (h != 1);
01168       }
01169 
01170       /*
01171        * The main sorting loop.
01172        */
01173       for (i = 0; i <= 255; i++) {
01174 
01175         /*
01176          * Process big buckets, starting with the least full.
01177          */
01178         ss = runningOrder[i];
01179 
01180         /*
01181          * Complete the big bucket [ss] by quicksorting any unsorted small
01182          * buckets [ss, j]. Hopefully previous pointer-scanning phases have
01183          * already completed many of the small buckets [ss, j], so we don't have
01184          * to sort them at all.
01185          */
01186         for (j = 0; j <= 255; j++) {
01187           sb = (ss << 8) + j;
01188           if (!((ftab[sb] & SETMASK) == SETMASK)) {
01189             int lo = ftab[sb] & CLEARMASK;
01190             int hi = (ftab[sb + 1] & CLEARMASK) - 1;
01191             if (hi > lo) {
01192               qSort3(lo, hi, 2);
01193               if (workDone > workLimit && firstAttempt)
01194                 return;
01195             }
01196             ftab[sb] |= SETMASK;
01197           }
01198         }
01199 
01200         /*
01201          * The ss big bucket is now done. Record this fact, and update the
01202          * quadrant descriptors. Remember to update quadrants in the overshoot
01203          * area too, if necessary. The "if (i < 255)" test merely skips this
01204          * updating for the last bucket processed, since updating for the last
01205          * bucket is pointless.
01206          */
01207         bigDone[ss] = true;
01208 
01209         if (i < 255) {
01210           int bbStart = ftab[ss << 8] & CLEARMASK;
01211           int bbSize = (ftab[ss + 1 << 8] & CLEARMASK) - bbStart;
01212           int shifts = 0;
01213 
01214           while (bbSize >> shifts > 65534)
01215             shifts++;
01216 
01217           for (j = 0; j < bbSize; j++) {
01218             int a2update = zptr[bbStart + j];
01219             int qVal = j >> shifts;
01220             quadrant[a2update] = qVal;
01221             if (a2update < NUM_OVERSHOOT_BYTES)
01222               quadrant[a2update + last + 1] = qVal;
01223           }
01224 
01225           if (!(bbSize - 1 >> shifts <= 65535))
01226             panic();
01227         }
01228 
01229         /*
01230          * Now scan this big bucket so as to synthesise the sorted order for
01231          * small buckets [t, ss] for all t != ss.
01232          */
01233         for (j = 0; j <= 255; j++)
01234           copy[j] = ftab[(j << 8) + ss] & CLEARMASK;
01235 
01236         for (j = ftab[ss << 8] & CLEARMASK; j < (ftab[ss + 1 << 8] & CLEARMASK); j++) {
01237           c1 = block[zptr[j]];
01238           if (!bigDone[c1]) {
01239             zptr[copy[c1]] = zptr[j] == 0 ? last : zptr[j] - 1;
01240             copy[c1]++;
01241           }
01242         }
01243 
01244         for (j = 0; j <= 255; j++)
01245           ftab[(j << 8) + ss] |= SETMASK;
01246       }
01247     }
01248   }
01249 
01250   private void randomiseBlock() {
01251     int i;
01252     int rNToGo = 0;
01253     int rTPos = 0;
01254     for (i = 0; i < 256; i++)
01255       inUse[i] = false;
01256 
01257     for (i = 0; i <= last; i++) {
01258       if (rNToGo == 0) {
01259         rNToGo = (char) rNums[rTPos];
01260         rTPos++;
01261         if (rTPos == 512)
01262           rTPos = 0;
01263       }
01264       rNToGo--;
01265       block[i + 1] ^= rNToGo == 1 ? 1 : 0;
01266       // handle 16 bit signed numbers
01267       block[i + 1] &= 0xFF;
01268 
01269       inUse[block[i + 1]] = true;
01270     }
01271   }
01272 
01273   private void doReversibleTransformation() {
01274     int i;
01275 
01276     workLimit = workFactor * last;
01277     workDone = 0;
01278     blockRandomised = false;
01279     firstAttempt = true;
01280 
01281     mainSort();
01282 
01283     if (workDone > workLimit && firstAttempt) {
01284       randomiseBlock();
01285       workLimit = workDone = 0;
01286       blockRandomised = true;
01287       firstAttempt = false;
01288       mainSort();
01289     }
01290 
01291     origPtr = -1;
01292     for (i = 0; i <= last; i++)
01293       if (zptr[i] == 0) {
01294         origPtr = i;
01295         break;
01296       }
01297     ;
01298 
01299     if (origPtr == -1)
01300       panic();
01301   }
01302 
01303   private boolean fullGtU(int p_i1, int p_i2) {
01304     int i1 = p_i1, i2 = p_i2;
01305     int k;
01306     char c1, c2;
01307     int s1, s2;
01308 
01309     c1 = block[i1 + 1];
01310     c2 = block[i2 + 1];
01311     if (c1 != c2)
01312       return c1 > c2;
01313     i1++;
01314     i2++;
01315 
01316     c1 = block[i1 + 1];
01317     c2 = block[i2 + 1];
01318     if (c1 != c2)
01319       return c1 > c2;
01320     i1++;
01321     i2++;
01322 
01323     c1 = block[i1 + 1];
01324     c2 = block[i2 + 1];
01325     if (c1 != c2)
01326       return c1 > c2;
01327     i1++;
01328     i2++;
01329 
01330     c1 = block[i1 + 1];
01331     c2 = block[i2 + 1];
01332     if (c1 != c2)
01333       return c1 > c2;
01334     i1++;
01335     i2++;
01336 
01337     c1 = block[i1 + 1];
01338     c2 = block[i2 + 1];
01339     if (c1 != c2)
01340       return c1 > c2;
01341     i1++;
01342     i2++;
01343 
01344     c1 = block[i1 + 1];
01345     c2 = block[i2 + 1];
01346     if (c1 != c2)
01347       return c1 > c2;
01348     i1++;
01349     i2++;
01350 
01351     k = last + 1;
01352 
01353     do {
01354       c1 = block[i1 + 1];
01355       c2 = block[i2 + 1];
01356       if (c1 != c2)
01357         return c1 > c2;
01358       s1 = quadrant[i1];
01359       s2 = quadrant[i2];
01360       if (s1 != s2)
01361         return s1 > s2;
01362       i1++;
01363       i2++;
01364 
01365       c1 = block[i1 + 1];
01366       c2 = block[i2 + 1];
01367       if (c1 != c2)
01368         return c1 > c2;
01369       s1 = quadrant[i1];
01370       s2 = quadrant[i2];
01371       if (s1 != s2)
01372         return s1 > s2;
01373       i1++;
01374       i2++;
01375 
01376       c1 = block[i1 + 1];
01377       c2 = block[i2 + 1];
01378       if (c1 != c2)
01379         return c1 > c2;
01380       s1 = quadrant[i1];
01381       s2 = quadrant[i2];
01382       if (s1 != s2)
01383         return s1 > s2;
01384       i1++;
01385       i2++;
01386 
01387       c1 = block[i1 + 1];
01388       c2 = block[i2 + 1];
01389       if (c1 != c2)
01390         return c1 > c2;
01391       s1 = quadrant[i1];
01392       s2 = quadrant[i2];
01393       if (s1 != s2)
01394         return s1 > s2;
01395       i1++;
01396       i2++;
01397 
01398       if (i1 > last) {
01399         i1 -= last;
01400         i1--;
01401       }
01402       ;
01403       if (i2 > last) {
01404         i2 -= last;
01405         i2--;
01406       }
01407       ;
01408 
01409       k -= 4;
01410       workDone++;
01411     } while (k >= 0);
01412 
01413     return false;
01414   }
01415 
01416   /*
01417    * Knuth's increments seem to work better than Incerpi-Sedgewick here.
01418    * Possibly because the number of elems to sort is usually small, typically <=
01419    * 20.
01420    */
01421   private final int[] incs = { 1, 4, 13, 40, 121, 364, 1093, 3280, 9841, 29524, 88573, 265720, 797161, 2391484 };
01422 
01423   private void allocateCompressStructures() {
01424     int n = baseBlockSize * blockSize100k;
01425     block = new char[(n + 1 + NUM_OVERSHOOT_BYTES)];
01426     quadrant = new int[(n + NUM_OVERSHOOT_BYTES)];
01427     zptr = new int[n];
01428     ftab = new int[65537];
01429 
01430     if (block == null || quadrant == null || zptr == null || ftab == null) {
01431       // int totalDraw = (n + 1 + NUM_OVERSHOOT_BYTES) + (n +
01432       // NUM_OVERSHOOT_BYTES) + n + 65537;
01433       // compressOutOfMemory ( totalDraw, n );
01434     }
01435 
01436     /*
01437      * The back end needs a place to store the MTF values whilst it calculates
01438      * the coding tables. We could put them in the zptr array. However, these
01439      * values will fit in a short, so we overlay szptr at the start of zptr, in
01440      * the hope of reducing the number of cache misses induced by the multiple
01441      * traversals of the MTF values when calculating coding tables. Seems to
01442      * improve compression speed by about 1%.
01443      */
01444     // szptr = zptr;
01445 
01446 
01447     szptr = new short[2 * n];
01448   }
01449 
01450   private void generateMTFValues() {
01451     char[] yy = new char[256];
01452     int i, j;
01453     char tmp;
01454     char tmp2;
01455     int zPend;
01456     int wr;
01457     int EOB;
01458 
01459     makeMaps();
01460     EOB = nInUse + 1;
01461 
01462     for (i = 0; i <= EOB; i++)
01463       mtfFreq[i] = 0;
01464 
01465     wr = 0;
01466     zPend = 0;
01467     for (i = 0; i < nInUse; i++)
01468       yy[i] = (char) i;
01469 
01470 
01471     for (i = 0; i <= last; i++) {
01472       char ll_i;
01473 
01474       ll_i = unseqToSeq[block[zptr[i]]];
01475 
01476       j = 0;
01477       tmp = yy[j];
01478       while (ll_i != tmp) {
01479         j++;
01480         tmp2 = tmp;
01481         tmp = yy[j];
01482         yy[j] = tmp2;
01483       }
01484       ;
01485       yy[0] = tmp;
01486 
01487       if (j == 0)
01488         zPend++;
01489       else {
01490         if (zPend > 0) {
01491           zPend--;
01492           while (true) {
01493             switch (zPend % 2) {
01494             case 0:
01495               szptr[wr] = (short) RUNA;
01496               wr++;
01497               mtfFreq[RUNA]++;
01498               break;
01499             case 1:
01500               szptr[wr] = (short) RUNB;
01501               wr++;
01502               mtfFreq[RUNB]++;
01503               break;
01504             }
01505             ;
01506             if (zPend < 2)
01507               break;
01508             zPend = (zPend - 2) / 2;
01509           }
01510           ;
01511           zPend = 0;
01512         }
01513         szptr[wr] = (short) (j + 1);
01514         wr++;
01515         mtfFreq[j + 1]++;
01516       }
01517     }
01518 
01519     if (zPend > 0) {
01520       zPend--;
01521       while (true) {
01522         switch (zPend % 2) {
01523         case 0:
01524           szptr[wr] = (short) RUNA;
01525           wr++;
01526           mtfFreq[RUNA]++;
01527           break;
01528         case 1:
01529           szptr[wr] = (short) RUNB;
01530           wr++;
01531           mtfFreq[RUNB]++;
01532           break;
01533         }
01534         if (zPend < 2)
01535           break;
01536         zPend = (zPend - 2) / 2;
01537       }
01538     }
01539 
01540     szptr[wr] = (short) EOB;
01541     wr++;
01542     mtfFreq[EOB]++;
01543 
01544     nMTF = wr;
01545   }
01546 }
 All Classes Namespaces Files Functions Variables Enumerations
Zephyr
RLPark