RLPark 1.0.0
Reinforcement Learning Framework in Java
|
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 }