Blob Blame History Raw
//C-  -*- C++ -*-
//C- -------------------------------------------------------------------
//C- DjVuLibre-3.5
//C- Copyright (c) 2002  Leon Bottou and Yann Le Cun.
//C- Copyright (c) 2001  AT&T
//C-
//C- This software is subject to, and may be distributed under, the
//C- GNU General Public License, either Version 2 of the license,
//C- or (at your option) any later version. The license should have
//C- accompanied the software or you may obtain a copy of the license
//C- from the Free Software Foundation at http://www.fsf.org .
//C-
//C- This program is distributed in the hope that it will be useful,
//C- but WITHOUT ANY WARRANTY; without even the implied warranty of
//C- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//C- GNU General Public License for more details.
//C- 
//C- DjVuLibre-3.5 is derived from the DjVu(r) Reference Library from
//C- Lizardtech Software.  Lizardtech Software has authorized us to
//C- replace the original DjVu(r) Reference Library notice by the following
//C- text (see doc/lizard2002.djvu and doc/lizardtech2007.djvu):
//C-
//C-  ------------------------------------------------------------------
//C- | DjVu (r) Reference Library (v. 3.5)
//C- | Copyright (c) 1999-2001 LizardTech, Inc. All Rights Reserved.
//C- | The DjVu Reference Library is protected by U.S. Pat. No.
//C- | 6,058,214 and patents pending.
//C- |
//C- | This software is subject to, and may be distributed under, the
//C- | GNU General Public License, either Version 2 of the license,
//C- | or (at your option) any later version. The license should have
//C- | accompanied the software or you may obtain a copy of the license
//C- | from the Free Software Foundation at http://www.fsf.org .
//C- |
//C- | The computer code originally released by LizardTech under this
//C- | license and unmodified by other parties is deemed "the LIZARDTECH
//C- | ORIGINAL CODE."  Subject to any third party intellectual property
//C- | claims, LizardTech grants recipient a worldwide, royalty-free, 
//C- | non-exclusive license to make, use, sell, or otherwise dispose of 
//C- | the LIZARDTECH ORIGINAL CODE or of programs derived from the 
//C- | LIZARDTECH ORIGINAL CODE in compliance with the terms of the GNU 
//C- | General Public License.   This grant only confers the right to 
//C- | infringe patent claims underlying the LIZARDTECH ORIGINAL CODE to 
//C- | the extent such infringement is reasonably necessary to enable 
//C- | recipient to make, have made, practice, sell, or otherwise dispose 
//C- | of the LIZARDTECH ORIGINAL CODE (or portions thereof) and not to 
//C- | any greater extent that may be necessary to utilize further 
//C- | modifications or combinations.
//C- |
//C- | The LIZARDTECH ORIGINAL CODE is provided "AS IS" WITHOUT WARRANTY
//C- | OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
//C- | TO ANY WARRANTY OF NON-INFRINGEMENT, OR ANY IMPLIED WARRANTY OF
//C- | MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
//C- +------------------------------------------------------------------

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#if NEED_GNUG_PRAGMAS
# pragma implementation
#endif

// From: Leon Bottou, 1/31/2002
// Almost equal to my initial code.

#include "ZPCodec.h"
#include "ByteStream.h"
#include "GException.h"

#include <stddef.h>
#include <stdlib.h>
#include <assert.h>
#include <math.h>
#include <stdio.h>


#ifdef HAVE_NAMESPACES
namespace DJVU {
# ifdef NOT_DEFINED // Just to fool emacs c++ mode
}
#endif
#endif

////////////////////////////////////////////////////////////////
// CODER SPECIFICATION
////////////////////////////////////////////////////////////////


#ifndef ZPCODER
#ifndef ZCODER
#define ZPCODER
#endif
#endif
#ifdef ZCODER

// The ZCODER option is provided for documentation purposes only. The ZCODER
// might come dangerously close to U.S. patent 5059976 (Mitsubishi).  This is
// why we always use the ZPCODER, although it usually produces 1% larger files.
#warning "The ZCODER may infringe non-LizardTech patent(s)."
#warning "You should use the ZPCODER instead."
#endif


////////////////////////////////////////////////////////////////
// ZP CODER DEFAULT ADAPTATION TABLE
////////////////////////////////////////////////////////////////


// See ZPCodec::ZPCodec to see how this
// default table is modified when not
// using the DjVu compatibility mode.


static ZPCodec::Table default_ztable[256] = 
{
#ifdef ZPCODER
  /* This table has been designed for the ZPCoder
   * by running the following command in file 'zptable.sn':
   * (fast-crude (steady-mat 0.0035  0.0002) 260)))
   */
  { 0x8000,  0x0000,  84, 145 },    /* 000: p=0.500000 (    0,    0) */
  { 0x8000,  0x0000,   3,   4 },    /* 001: p=0.500000 (    0,    0) */
  { 0x8000,  0x0000,   4,   3 },    /* 002: p=0.500000 (    0,    0) */
  { 0x6bbd,  0x10a5,   5,   1 },    /* 003: p=0.465226 (    0,    0) */
  { 0x6bbd,  0x10a5,   6,   2 },    /* 004: p=0.465226 (    0,    0) */
  { 0x5d45,  0x1f28,   7,   3 },    /* 005: p=0.430708 (    0,    0) */
  { 0x5d45,  0x1f28,   8,   4 },    /* 006: p=0.430708 (    0,    0) */
  { 0x51b9,  0x2bd3,   9,   5 },    /* 007: p=0.396718 (    0,    0) */
  { 0x51b9,  0x2bd3,  10,   6 },    /* 008: p=0.396718 (    0,    0) */
  { 0x4813,  0x36e3,  11,   7 },    /* 009: p=0.363535 (    0,    0) */
  { 0x4813,  0x36e3,  12,   8 },    /* 010: p=0.363535 (    0,    0) */
  { 0x3fd5,  0x408c,  13,   9 },    /* 011: p=0.331418 (    0,    0) */
  { 0x3fd5,  0x408c,  14,  10 },    /* 012: p=0.331418 (    0,    0) */
  { 0x38b1,  0x48fd,  15,  11 },    /* 013: p=0.300585 (    0,    0) */
  { 0x38b1,  0x48fd,  16,  12 },    /* 014: p=0.300585 (    0,    0) */
  { 0x3275,  0x505d,  17,  13 },    /* 015: p=0.271213 (    0,    0) */
  { 0x3275,  0x505d,  18,  14 },    /* 016: p=0.271213 (    0,    0) */
  { 0x2cfd,  0x56d0,  19,  15 },    /* 017: p=0.243438 (    0,    0) */
  { 0x2cfd,  0x56d0,  20,  16 },    /* 018: p=0.243438 (    0,    0) */
  { 0x2825,  0x5c71,  21,  17 },    /* 019: p=0.217391 (    0,    0) */
  { 0x2825,  0x5c71,  22,  18 },    /* 020: p=0.217391 (    0,    0) */
  { 0x23ab,  0x615b,  23,  19 },    /* 021: p=0.193150 (    0,    0) */
  { 0x23ab,  0x615b,  24,  20 },    /* 022: p=0.193150 (    0,    0) */
  { 0x1f87,  0x65a5,  25,  21 },    /* 023: p=0.170728 (    0,    0) */
  { 0x1f87,  0x65a5,  26,  22 },    /* 024: p=0.170728 (    0,    0) */
  { 0x1bbb,  0x6962,  27,  23 },    /* 025: p=0.150158 (    0,    0) */
  { 0x1bbb,  0x6962,  28,  24 },    /* 026: p=0.150158 (    0,    0) */
  { 0x1845,  0x6ca2,  29,  25 },    /* 027: p=0.131418 (    0,    0) */
  { 0x1845,  0x6ca2,  30,  26 },    /* 028: p=0.131418 (    0,    0) */
  { 0x1523,  0x6f74,  31,  27 },    /* 029: p=0.114460 (    0,    0) */
  { 0x1523,  0x6f74,  32,  28 },    /* 030: p=0.114460 (    0,    0) */
  { 0x1253,  0x71e6,  33,  29 },    /* 031: p=0.099230 (    0,    0) */
  { 0x1253,  0x71e6,  34,  30 },    /* 032: p=0.099230 (    0,    0) */
  { 0x0fcf,  0x7404,  35,  31 },    /* 033: p=0.085611 (    0,    0) */
  { 0x0fcf,  0x7404,  36,  32 },    /* 034: p=0.085611 (    0,    0) */
  { 0x0d95,  0x75d6,  37,  33 },    /* 035: p=0.073550 (    0,    0) */
  { 0x0d95,  0x75d6,  38,  34 },    /* 036: p=0.073550 (    0,    0) */
  { 0x0b9d,  0x7768,  39,  35 },    /* 037: p=0.062888 (    0,    0) */
  { 0x0b9d,  0x7768,  40,  36 },    /* 038: p=0.062888 (    0,    0) */
  { 0x09e3,  0x78c2,  41,  37 },    /* 039: p=0.053539 (    0,    0) */
  { 0x09e3,  0x78c2,  42,  38 },    /* 040: p=0.053539 (    0,    0) */
  { 0x0861,  0x79ea,  43,  39 },    /* 041: p=0.045365 (    0,    0) */
  { 0x0861,  0x79ea,  44,  40 },    /* 042: p=0.045365 (    0,    0) */
  { 0x0711,  0x7ae7,  45,  41 },    /* 043: p=0.038272 (    0,    0) */
  { 0x0711,  0x7ae7,  46,  42 },    /* 044: p=0.038272 (    0,    0) */
  { 0x05f1,  0x7bbe,  47,  43 },    /* 045: p=0.032174 (    0,    0) */
  { 0x05f1,  0x7bbe,  48,  44 },    /* 046: p=0.032174 (    0,    0) */
  { 0x04f9,  0x7c75,  49,  45 },    /* 047: p=0.026928 (    0,    0) */
  { 0x04f9,  0x7c75,  50,  46 },    /* 048: p=0.026928 (    0,    0) */
  { 0x0425,  0x7d0f,  51,  47 },    /* 049: p=0.022444 (    0,    0) */
  { 0x0425,  0x7d0f,  52,  48 },    /* 050: p=0.022444 (    0,    0) */
  { 0x0371,  0x7d91,  53,  49 },    /* 051: p=0.018636 (    0,    0) */
  { 0x0371,  0x7d91,  54,  50 },    /* 052: p=0.018636 (    0,    0) */
  { 0x02d9,  0x7dfe,  55,  51 },    /* 053: p=0.015421 (    0,    0) */
  { 0x02d9,  0x7dfe,  56,  52 },    /* 054: p=0.015421 (    0,    0) */
  { 0x0259,  0x7e5a,  57,  53 },    /* 055: p=0.012713 (    0,    0) */
  { 0x0259,  0x7e5a,  58,  54 },    /* 056: p=0.012713 (    0,    0) */
  { 0x01ed,  0x7ea6,  59,  55 },    /* 057: p=0.010419 (    0,    0) */
  { 0x01ed,  0x7ea6,  60,  56 },    /* 058: p=0.010419 (    0,    0) */
  { 0x0193,  0x7ee6,  61,  57 },    /* 059: p=0.008525 (    0,    0) */
  { 0x0193,  0x7ee6,  62,  58 },    /* 060: p=0.008525 (    0,    0) */
  { 0x0149,  0x7f1a,  63,  59 },    /* 061: p=0.006959 (    0,    0) */
  { 0x0149,  0x7f1a,  64,  60 },    /* 062: p=0.006959 (    0,    0) */
  { 0x010b,  0x7f45,  65,  61 },    /* 063: p=0.005648 (    0,    0) */
  { 0x010b,  0x7f45,  66,  62 },    /* 064: p=0.005648 (    0,    0) */
  { 0x00d5,  0x7f6b,  67,  63 },    /* 065: p=0.004506 (    0,    0) */
  { 0x00d5,  0x7f6b,  68,  64 },    /* 066: p=0.004506 (    0,    0) */
  { 0x00a5,  0x7f8d,  69,  65 },    /* 067: p=0.003480 (    0,    0) */
  { 0x00a5,  0x7f8d,  70,  66 },    /* 068: p=0.003480 (    0,    0) */
  { 0x007b,  0x7faa,  71,  67 },    /* 069: p=0.002602 (    0,    0) */
  { 0x007b,  0x7faa,  72,  68 },    /* 070: p=0.002602 (    0,    0) */
  { 0x0057,  0x7fc3,  73,  69 },    /* 071: p=0.001843 (    0,    0) */
  { 0x0057,  0x7fc3,  74,  70 },    /* 072: p=0.001843 (    0,    0) */
  { 0x003b,  0x7fd7,  75,  71 },    /* 073: p=0.001248 (    0,    0) */
  { 0x003b,  0x7fd7,  76,  72 },    /* 074: p=0.001248 (    0,    0) */
  { 0x0023,  0x7fe7,  77,  73 },    /* 075: p=0.000749 (    0,    0) */
  { 0x0023,  0x7fe7,  78,  74 },    /* 076: p=0.000749 (    0,    0) */
  { 0x0013,  0x7ff2,  79,  75 },    /* 077: p=0.000402 (    0,    0) */
  { 0x0013,  0x7ff2,  80,  76 },    /* 078: p=0.000402 (    0,    0) */
  { 0x0007,  0x7ffa,  81,  77 },    /* 079: p=0.000153 (    0,    0) */
  { 0x0007,  0x7ffa,  82,  78 },    /* 080: p=0.000153 (    0,    0) */
  { 0x0001,  0x7fff,  81,  79 },    /* 081: p=0.000027 (    0,    0) */
  { 0x0001,  0x7fff,  82,  80 },    /* 082: p=0.000027 (    0,    0) */
  { 0x5695,  0x0000,   9,  85 },    /* 083: p=0.411764 (    2,    3) */
  { 0x24ee,  0x0000,  86, 226 },    /* 084: p=0.199988 (    1,    0) */
  { 0x8000,  0x0000,   5,   6 },    /* 085: p=0.500000 (    3,    3) */
  { 0x0d30,  0x0000,  88, 176 },    /* 086: p=0.071422 (    4,    0) */
  { 0x481a,  0x0000,  89, 143 },    /* 087: p=0.363634 (    1,    2) */
  { 0x0481,  0x0000,  90, 138 },    /* 088: p=0.024388 (   13,    0) */
  { 0x3579,  0x0000,  91, 141 },    /* 089: p=0.285711 (    1,    3) */
  { 0x017a,  0x0000,  92, 112 },    /* 090: p=0.007999 (   41,    0) */
  { 0x24ef,  0x0000,  93, 135 },    /* 091: p=0.199997 (    1,    5) */
  { 0x007b,  0x0000,  94, 104 },    /* 092: p=0.002611 (  127,    0) */
  { 0x1978,  0x0000,  95, 133 },    /* 093: p=0.137929 (    1,    8) */
  { 0x0028,  0x0000,  96, 100 },    /* 094: p=0.000849 (  392,    0) */
  { 0x10ca,  0x0000,  97, 129 },    /* 095: p=0.090907 (    1,   13) */
  { 0x000d,  0x0000,  82,  98 },    /* 096: p=0.000276 ( 1208,    0) */
  { 0x0b5d,  0x0000,  99, 127 },    /* 097: p=0.061537 (    1,   20) */
  { 0x0034,  0x0000,  76,  72 },    /* 098: p=0.001102 ( 1208,    1) */
  { 0x078a,  0x0000, 101, 125 },    /* 099: p=0.040815 (    1,   31) */
  { 0x00a0,  0x0000,  70, 102 },    /* 100: p=0.003387 (  392,    1) */
  { 0x050f,  0x0000, 103, 123 },    /* 101: p=0.027397 (    1,   47) */
  { 0x0117,  0x0000,  66,  60 },    /* 102: p=0.005912 (  392,    2) */
  { 0x0358,  0x0000, 105, 121 },    /* 103: p=0.018099 (    1,   72) */
  { 0x01ea,  0x0000, 106, 110 },    /* 104: p=0.010362 (  127,    1) */
  { 0x0234,  0x0000, 107, 119 },    /* 105: p=0.011940 (    1,  110) */
  { 0x0144,  0x0000,  66, 108 },    /* 106: p=0.006849 (  193,    1) */
  { 0x0173,  0x0000, 109, 117 },    /* 107: p=0.007858 (    1,  168) */
  { 0x0234,  0x0000,  60,  54 },    /* 108: p=0.011925 (  193,    2) */
  { 0x00f5,  0x0000, 111, 115 },    /* 109: p=0.005175 (    1,  256) */
  { 0x0353,  0x0000,  56,  48 },    /* 110: p=0.017995 (  127,    2) */
  { 0x00a1,  0x0000,  69, 113 },    /* 111: p=0.003413 (    1,  389) */
  { 0x05c5,  0x0000, 114, 134 },    /* 112: p=0.031249 (   41,    1) */
  { 0x011a,  0x0000,  65,  59 },    /* 113: p=0.005957 (    2,  389) */
  { 0x03cf,  0x0000, 116, 132 },    /* 114: p=0.020618 (   63,    1) */
  { 0x01aa,  0x0000,  61,  55 },    /* 115: p=0.009020 (    2,  256) */
  { 0x0285,  0x0000, 118, 130 },    /* 116: p=0.013652 (   96,    1) */
  { 0x0286,  0x0000,  57,  51 },    /* 117: p=0.013672 (    2,  168) */
  { 0x01ab,  0x0000, 120, 128 },    /* 118: p=0.009029 (  146,    1) */
  { 0x03d3,  0x0000,  53,  47 },    /* 119: p=0.020710 (    2,  110) */
  { 0x011a,  0x0000, 122, 126 },    /* 120: p=0.005961 (  222,    1) */
  { 0x05c5,  0x0000,  49,  41 },    /* 121: p=0.031250 (    2,   72) */
  { 0x00ba,  0x0000, 124,  62 },    /* 122: p=0.003925 (  338,    1) */
  { 0x08ad,  0x0000,  43,  37 },    /* 123: p=0.046979 (    2,   47) */
  { 0x007a,  0x0000,  72,  66 },    /* 124: p=0.002586 (  514,    1) */
  { 0x0ccc,  0x0000,  39,  31 },    /* 125: p=0.069306 (    2,   31) */
  { 0x01eb,  0x0000,  60,  54 },    /* 126: p=0.010386 (  222,    2) */
  { 0x1302,  0x0000,  33,  25 },    /* 127: p=0.102940 (    2,   20) */
  { 0x02e6,  0x0000,  56,  50 },    /* 128: p=0.015695 (  146,    2) */
  { 0x1b81,  0x0000,  29, 131 },    /* 129: p=0.148935 (    2,   13) */
  { 0x045e,  0x0000,  52,  46 },    /* 130: p=0.023648 (   96,    2) */
  { 0x24ef,  0x0000,  23,  17 },    /* 131: p=0.199999 (    3,   13) */
  { 0x0690,  0x0000,  48,  40 },    /* 132: p=0.035533 (   63,    2) */
  { 0x2865,  0x0000,  23,  15 },    /* 133: p=0.218748 (    2,    8) */
  { 0x09de,  0x0000,  42, 136 },    /* 134: p=0.053434 (   41,    2) */
  { 0x3987,  0x0000, 137,   7 },    /* 135: p=0.304346 (    2,    5) */
  { 0x0dc8,  0x0000,  38,  32 },    /* 136: p=0.074626 (   41,    3) */
  { 0x2c99,  0x0000,  21, 139 },    /* 137: p=0.241378 (    2,    7) */
  { 0x10ca,  0x0000, 140, 172 },    /* 138: p=0.090907 (   13,    1) */
  { 0x3b5f,  0x0000,  15,   9 },    /* 139: p=0.312499 (    3,    7) */
  { 0x0b5d,  0x0000, 142, 170 },    /* 140: p=0.061537 (   20,    1) */
  { 0x5695,  0x0000,   9,  85 },    /* 141: p=0.411764 (    2,    3) */
  { 0x078a,  0x0000, 144, 168 },    /* 142: p=0.040815 (   31,    1) */
  { 0x8000,  0x0000, 141, 248 },    /* 143: p=0.500000 (    2,    2) */
  { 0x050f,  0x0000, 146, 166 },    /* 144: p=0.027397 (   47,    1) */
  { 0x24ee,  0x0000, 147, 247 },    /* 145: p=0.199988 (    0,    1) */
  { 0x0358,  0x0000, 148, 164 },    /* 146: p=0.018099 (   72,    1) */
  { 0x0d30,  0x0000, 149, 197 },    /* 147: p=0.071422 (    0,    4) */
  { 0x0234,  0x0000, 150, 162 },    /* 148: p=0.011940 (  110,    1) */
  { 0x0481,  0x0000, 151,  95 },    /* 149: p=0.024388 (    0,   13) */
  { 0x0173,  0x0000, 152, 160 },    /* 150: p=0.007858 (  168,    1) */
  { 0x017a,  0x0000, 153, 173 },    /* 151: p=0.007999 (    0,   41) */
  { 0x00f5,  0x0000, 154, 158 },    /* 152: p=0.005175 (  256,    1) */
  { 0x007b,  0x0000, 155, 165 },    /* 153: p=0.002611 (    0,  127) */
  { 0x00a1,  0x0000,  70, 156 },    /* 154: p=0.003413 (  389,    1) */
  { 0x0028,  0x0000, 157, 161 },    /* 155: p=0.000849 (    0,  392) */
  { 0x011a,  0x0000,  66,  60 },    /* 156: p=0.005957 (  389,    2) */
  { 0x000d,  0x0000,  81, 159 },    /* 157: p=0.000276 (    0, 1208) */
  { 0x01aa,  0x0000,  62,  56 },    /* 158: p=0.009020 (  256,    2) */
  { 0x0034,  0x0000,  75,  71 },    /* 159: p=0.001102 (    1, 1208) */
  { 0x0286,  0x0000,  58,  52 },    /* 160: p=0.013672 (  168,    2) */
  { 0x00a0,  0x0000,  69, 163 },    /* 161: p=0.003387 (    1,  392) */
  { 0x03d3,  0x0000,  54,  48 },    /* 162: p=0.020710 (  110,    2) */
  { 0x0117,  0x0000,  65,  59 },    /* 163: p=0.005912 (    2,  392) */
  { 0x05c5,  0x0000,  50,  42 },    /* 164: p=0.031250 (   72,    2) */
  { 0x01ea,  0x0000, 167, 171 },    /* 165: p=0.010362 (    1,  127) */
  { 0x08ad,  0x0000,  44,  38 },    /* 166: p=0.046979 (   47,    2) */
  { 0x0144,  0x0000,  65, 169 },    /* 167: p=0.006849 (    1,  193) */
  { 0x0ccc,  0x0000,  40,  32 },    /* 168: p=0.069306 (   31,    2) */
  { 0x0234,  0x0000,  59,  53 },    /* 169: p=0.011925 (    2,  193) */
  { 0x1302,  0x0000,  34,  26 },    /* 170: p=0.102940 (   20,    2) */
  { 0x0353,  0x0000,  55,  47 },    /* 171: p=0.017995 (    2,  127) */
  { 0x1b81,  0x0000,  30, 174 },    /* 172: p=0.148935 (   13,    2) */
  { 0x05c5,  0x0000, 175, 193 },    /* 173: p=0.031249 (    1,   41) */
  { 0x24ef,  0x0000,  24,  18 },    /* 174: p=0.199999 (   13,    3) */
  { 0x03cf,  0x0000, 177, 191 },    /* 175: p=0.020618 (    1,   63) */
  { 0x2b74,  0x0000, 178, 222 },    /* 176: p=0.235291 (    4,    1) */
  { 0x0285,  0x0000, 179, 189 },    /* 177: p=0.013652 (    1,   96) */
  { 0x201d,  0x0000, 180, 218 },    /* 178: p=0.173910 (    6,    1) */
  { 0x01ab,  0x0000, 181, 187 },    /* 179: p=0.009029 (    1,  146) */
  { 0x1715,  0x0000, 182, 216 },    /* 180: p=0.124998 (    9,    1) */
  { 0x011a,  0x0000, 183, 185 },    /* 181: p=0.005961 (    1,  222) */
  { 0x0fb7,  0x0000, 184, 214 },    /* 182: p=0.085105 (   14,    1) */
  { 0x00ba,  0x0000,  69,  61 },    /* 183: p=0.003925 (    1,  338) */
  { 0x0a67,  0x0000, 186, 212 },    /* 184: p=0.056337 (   22,    1) */
  { 0x01eb,  0x0000,  59,  53 },    /* 185: p=0.010386 (    2,  222) */
  { 0x06e7,  0x0000, 188, 210 },    /* 186: p=0.037382 (   34,    1) */
  { 0x02e6,  0x0000,  55,  49 },    /* 187: p=0.015695 (    2,  146) */
  { 0x0496,  0x0000, 190, 208 },    /* 188: p=0.024844 (   52,    1) */
  { 0x045e,  0x0000,  51,  45 },    /* 189: p=0.023648 (    2,   96) */
  { 0x030d,  0x0000, 192, 206 },    /* 190: p=0.016529 (   79,    1) */
  { 0x0690,  0x0000,  47,  39 },    /* 191: p=0.035533 (    2,   63) */
  { 0x0206,  0x0000, 194, 204 },    /* 192: p=0.010959 (  120,    1) */
  { 0x09de,  0x0000,  41, 195 },    /* 193: p=0.053434 (    2,   41) */
  { 0x0155,  0x0000, 196, 202 },    /* 194: p=0.007220 (  183,    1) */
  { 0x0dc8,  0x0000,  37,  31 },    /* 195: p=0.074626 (    3,   41) */
  { 0x00e1,  0x0000, 198, 200 },    /* 196: p=0.004750 (  279,    1) */
  { 0x2b74,  0x0000, 199, 243 },    /* 197: p=0.235291 (    1,    4) */
  { 0x0094,  0x0000,  72,  64 },    /* 198: p=0.003132 (  424,    1) */
  { 0x201d,  0x0000, 201, 239 },    /* 199: p=0.173910 (    1,    6) */
  { 0x0188,  0x0000,  62,  56 },    /* 200: p=0.008284 (  279,    2) */
  { 0x1715,  0x0000, 203, 237 },    /* 201: p=0.124998 (    1,    9) */
  { 0x0252,  0x0000,  58,  52 },    /* 202: p=0.012567 (  183,    2) */
  { 0x0fb7,  0x0000, 205, 235 },    /* 203: p=0.085105 (    1,   14) */
  { 0x0383,  0x0000,  54,  48 },    /* 204: p=0.019021 (  120,    2) */
  { 0x0a67,  0x0000, 207, 233 },    /* 205: p=0.056337 (    1,   22) */
  { 0x0547,  0x0000,  50,  44 },    /* 206: p=0.028571 (   79,    2) */
  { 0x06e7,  0x0000, 209, 231 },    /* 207: p=0.037382 (    1,   34) */
  { 0x07e2,  0x0000,  46,  38 },    /* 208: p=0.042682 (   52,    2) */
  { 0x0496,  0x0000, 211, 229 },    /* 209: p=0.024844 (    1,   52) */
  { 0x0bc0,  0x0000,  40,  34 },    /* 210: p=0.063636 (   34,    2) */
  { 0x030d,  0x0000, 213, 227 },    /* 211: p=0.016529 (    1,   79) */
  { 0x1178,  0x0000,  36,  28 },    /* 212: p=0.094593 (   22,    2) */
  { 0x0206,  0x0000, 215, 225 },    /* 213: p=0.010959 (    1,  120) */
  { 0x19da,  0x0000,  30,  22 },    /* 214: p=0.139999 (   14,    2) */
  { 0x0155,  0x0000, 217, 223 },    /* 215: p=0.007220 (    1,  183) */
  { 0x24ef,  0x0000,  26,  16 },    /* 216: p=0.199998 (    9,    2) */
  { 0x00e1,  0x0000, 219, 221 },    /* 217: p=0.004750 (    1,  279) */
  { 0x320e,  0x0000,  20, 220 },    /* 218: p=0.269229 (    6,    2) */
  { 0x0094,  0x0000,  71,  63 },    /* 219: p=0.003132 (    1,  424) */
  { 0x432a,  0x0000,  14,   8 },    /* 220: p=0.344827 (    6,    3) */
  { 0x0188,  0x0000,  61,  55 },    /* 221: p=0.008284 (    2,  279) */
  { 0x447d,  0x0000,  14, 224 },    /* 222: p=0.349998 (    4,    2) */
  { 0x0252,  0x0000,  57,  51 },    /* 223: p=0.012567 (    2,  183) */
  { 0x5ece,  0x0000,   8,   2 },    /* 224: p=0.434782 (    4,    3) */
  { 0x0383,  0x0000,  53,  47 },    /* 225: p=0.019021 (    2,  120) */
  { 0x8000,  0x0000, 228,  87 },    /* 226: p=0.500000 (    1,    1) */
  { 0x0547,  0x0000,  49,  43 },    /* 227: p=0.028571 (    2,   79) */
  { 0x481a,  0x0000, 230, 246 },    /* 228: p=0.363634 (    2,    1) */
  { 0x07e2,  0x0000,  45,  37 },    /* 229: p=0.042682 (    2,   52) */
  { 0x3579,  0x0000, 232, 244 },    /* 230: p=0.285711 (    3,    1) */
  { 0x0bc0,  0x0000,  39,  33 },    /* 231: p=0.063636 (    2,   34) */
  { 0x24ef,  0x0000, 234, 238 },    /* 232: p=0.199997 (    5,    1) */
  { 0x1178,  0x0000,  35,  27 },    /* 233: p=0.094593 (    2,   22) */
  { 0x1978,  0x0000, 138, 236 },    /* 234: p=0.137929 (    8,    1) */
  { 0x19da,  0x0000,  29,  21 },    /* 235: p=0.139999 (    2,   14) */
  { 0x2865,  0x0000,  24,  16 },    /* 236: p=0.218748 (    8,    2) */
  { 0x24ef,  0x0000,  25,  15 },    /* 237: p=0.199998 (    2,    9) */
  { 0x3987,  0x0000, 240,   8 },    /* 238: p=0.304346 (    5,    2) */
  { 0x320e,  0x0000,  19, 241 },    /* 239: p=0.269229 (    2,    6) */
  { 0x2c99,  0x0000,  22, 242 },    /* 240: p=0.241378 (    7,    2) */
  { 0x432a,  0x0000,  13,   7 },    /* 241: p=0.344827 (    3,    6) */
  { 0x3b5f,  0x0000,  16,  10 },    /* 242: p=0.312499 (    7,    3) */
  { 0x447d,  0x0000,  13, 245 },    /* 243: p=0.349998 (    2,    4) */
  { 0x5695,  0x0000,  10,   2 },    /* 244: p=0.411764 (    3,    2) */
  { 0x5ece,  0x0000,   7,   1 },    /* 245: p=0.434782 (    3,    4) */
  { 0x8000,  0x0000, 244,  83 },    /* 246: p=0.500000 (    2,    2) */
  { 0x8000,  0x0000, 249, 250 },    /* 247: p=0.500000 (    1,    1) */
  { 0x5695,  0x0000,  10,   2 },    /* 248: p=0.411764 (    3,    2) */
  { 0x481a,  0x0000,  89, 143 },    /* 249: p=0.363634 (    1,    2) */
  { 0x481a,  0x0000, 230, 246 },    /* 250: p=0.363634 (    2,    1) */
#endif
#ifdef ZCODER
  /* This table has been designed for the ZCoder
   * by running the following command in file 'ztable2.sn':
   * (fast-crude (steady-mat 0.0035  0.0002) 260)))
   */
  { 0x8000,  0x0000,  84, 139 },    /* 000: p=0.500000 (    0,    0) */
  { 0x8000,  0x0000,   3,   4 },    /* 001: p=0.500000 (    0,    0) */
  { 0x8000,  0x0000,   4,   3 },    /* 002: p=0.500000 (    0,    0) */
  { 0x7399,  0x10a5,   5,   1 },    /* 003: p=0.465226 (    0,    0) */
  { 0x7399,  0x10a5,   6,   2 },    /* 004: p=0.465226 (    0,    0) */
  { 0x6813,  0x1f28,   7,   3 },    /* 005: p=0.430708 (    0,    0) */
  { 0x6813,  0x1f28,   8,   4 },    /* 006: p=0.430708 (    0,    0) */
  { 0x5d65,  0x2bd3,   9,   5 },    /* 007: p=0.396718 (    0,    0) */
  { 0x5d65,  0x2bd3,  10,   6 },    /* 008: p=0.396718 (    0,    0) */
  { 0x5387,  0x36e3,  11,   7 },    /* 009: p=0.363535 (    0,    0) */
  { 0x5387,  0x36e3,  12,   8 },    /* 010: p=0.363535 (    0,    0) */
  { 0x4a73,  0x408c,  13,   9 },    /* 011: p=0.331418 (    0,    0) */
  { 0x4a73,  0x408c,  14,  10 },    /* 012: p=0.331418 (    0,    0) */
  { 0x421f,  0x48fe,  15,  11 },    /* 013: p=0.300562 (    0,    0) */
  { 0x421f,  0x48fe,  16,  12 },    /* 014: p=0.300562 (    0,    0) */
  { 0x3a85,  0x5060,  17,  13 },    /* 015: p=0.271166 (    0,    0) */
  { 0x3a85,  0x5060,  18,  14 },    /* 016: p=0.271166 (    0,    0) */
  { 0x339b,  0x56d3,  19,  15 },    /* 017: p=0.243389 (    0,    0) */
  { 0x339b,  0x56d3,  20,  16 },    /* 018: p=0.243389 (    0,    0) */
  { 0x2d59,  0x5c73,  21,  17 },    /* 019: p=0.217351 (    0,    0) */
  { 0x2d59,  0x5c73,  22,  18 },    /* 020: p=0.217351 (    0,    0) */
  { 0x27b3,  0x615e,  23,  19 },    /* 021: p=0.193091 (    0,    0) */
  { 0x27b3,  0x615e,  24,  20 },    /* 022: p=0.193091 (    0,    0) */
  { 0x22a1,  0x65a7,  25,  21 },    /* 023: p=0.170683 (    0,    0) */
  { 0x22a1,  0x65a7,  26,  22 },    /* 024: p=0.170683 (    0,    0) */
  { 0x1e19,  0x6963,  27,  23 },    /* 025: p=0.150134 (    0,    0) */
  { 0x1e19,  0x6963,  28,  24 },    /* 026: p=0.150134 (    0,    0) */
  { 0x1a0f,  0x6ca3,  29,  25 },    /* 027: p=0.131397 (    0,    0) */
  { 0x1a0f,  0x6ca3,  30,  26 },    /* 028: p=0.131397 (    0,    0) */
  { 0x167b,  0x6f75,  31,  27 },    /* 029: p=0.114441 (    0,    0) */
  { 0x167b,  0x6f75,  32,  28 },    /* 030: p=0.114441 (    0,    0) */
  { 0x1353,  0x71e6,  33,  29 },    /* 031: p=0.099214 (    0,    0) */
  { 0x1353,  0x71e6,  34,  30 },    /* 032: p=0.099214 (    0,    0) */
  { 0x108d,  0x7403,  35,  31 },    /* 033: p=0.085616 (    0,    0) */
  { 0x108d,  0x7403,  36,  32 },    /* 034: p=0.085616 (    0,    0) */
  { 0x0e1f,  0x75d7,  37,  33 },    /* 035: p=0.073525 (    0,    0) */
  { 0x0e1f,  0x75d7,  38,  34 },    /* 036: p=0.073525 (    0,    0) */
  { 0x0c01,  0x7769,  39,  35 },    /* 037: p=0.062871 (    0,    0) */
  { 0x0c01,  0x7769,  40,  36 },    /* 038: p=0.062871 (    0,    0) */
  { 0x0a2b,  0x78c2,  41,  37 },    /* 039: p=0.053524 (    0,    0) */
  { 0x0a2b,  0x78c2,  42,  38 },    /* 040: p=0.053524 (    0,    0) */
  { 0x0895,  0x79ea,  43,  39 },    /* 041: p=0.045374 (    0,    0) */
  { 0x0895,  0x79ea,  44,  40 },    /* 042: p=0.045374 (    0,    0) */
  { 0x0737,  0x7ae7,  45,  41 },    /* 043: p=0.038280 (    0,    0) */
  { 0x0737,  0x7ae7,  46,  42 },    /* 044: p=0.038280 (    0,    0) */
  { 0x060b,  0x7bbe,  47,  43 },    /* 045: p=0.032175 (    0,    0) */
  { 0x060b,  0x7bbe,  48,  44 },    /* 046: p=0.032175 (    0,    0) */
  { 0x050b,  0x7c75,  49,  45 },    /* 047: p=0.026926 (    0,    0) */
  { 0x050b,  0x7c75,  50,  46 },    /* 048: p=0.026926 (    0,    0) */
  { 0x0431,  0x7d10,  51,  47 },    /* 049: p=0.022430 (    0,    0) */
  { 0x0431,  0x7d10,  52,  48 },    /* 050: p=0.022430 (    0,    0) */
  { 0x0379,  0x7d92,  53,  49 },    /* 051: p=0.018623 (    0,    0) */
  { 0x0379,  0x7d92,  54,  50 },    /* 052: p=0.018623 (    0,    0) */
  { 0x02dd,  0x7dff,  55,  51 },    /* 053: p=0.015386 (    0,    0) */
  { 0x02dd,  0x7dff,  56,  52 },    /* 054: p=0.015386 (    0,    0) */
  { 0x025b,  0x7e5b,  57,  53 },    /* 055: p=0.012671 (    0,    0) */
  { 0x025b,  0x7e5b,  58,  54 },    /* 056: p=0.012671 (    0,    0) */
  { 0x01ef,  0x7ea7,  59,  55 },    /* 057: p=0.010414 (    0,    0) */
  { 0x01ef,  0x7ea7,  60,  56 },    /* 058: p=0.010414 (    0,    0) */
  { 0x0195,  0x7ee6,  61,  57 },    /* 059: p=0.008529 (    0,    0) */
  { 0x0195,  0x7ee6,  62,  58 },    /* 060: p=0.008529 (    0,    0) */
  { 0x0149,  0x7f1b,  63,  59 },    /* 061: p=0.006935 (    0,    0) */
  { 0x0149,  0x7f1b,  64,  60 },    /* 062: p=0.006935 (    0,    0) */
  { 0x010b,  0x7f46,  65,  61 },    /* 063: p=0.005631 (    0,    0) */
  { 0x010b,  0x7f46,  66,  62 },    /* 064: p=0.005631 (    0,    0) */
  { 0x00d5,  0x7f6c,  67,  63 },    /* 065: p=0.004495 (    0,    0) */
  { 0x00d5,  0x7f6c,  68,  64 },    /* 066: p=0.004495 (    0,    0) */
  { 0x00a5,  0x7f8d,  69,  65 },    /* 067: p=0.003484 (    0,    0) */
  { 0x00a5,  0x7f8d,  70,  66 },    /* 068: p=0.003484 (    0,    0) */
  { 0x007b,  0x7faa,  71,  67 },    /* 069: p=0.002592 (    0,    0) */
  { 0x007b,  0x7faa,  72,  68 },    /* 070: p=0.002592 (    0,    0) */
  { 0x0057,  0x7fc3,  73,  69 },    /* 071: p=0.001835 (    0,    0) */
  { 0x0057,  0x7fc3,  74,  70 },    /* 072: p=0.001835 (    0,    0) */
  { 0x0039,  0x7fd8,  75,  71 },    /* 073: p=0.001211 (    0,    0) */
  { 0x0039,  0x7fd8,  76,  72 },    /* 074: p=0.001211 (    0,    0) */
  { 0x0023,  0x7fe7,  77,  73 },    /* 075: p=0.000740 (    0,    0) */
  { 0x0023,  0x7fe7,  78,  74 },    /* 076: p=0.000740 (    0,    0) */
  { 0x0013,  0x7ff2,  79,  75 },    /* 077: p=0.000402 (    0,    0) */
  { 0x0013,  0x7ff2,  80,  76 },    /* 078: p=0.000402 (    0,    0) */
  { 0x0007,  0x7ffa,  81,  77 },    /* 079: p=0.000153 (    0,    0) */
  { 0x0007,  0x7ffa,  82,  78 },    /* 080: p=0.000153 (    0,    0) */
  { 0x0001,  0x7fff,  81,  79 },    /* 081: p=0.000027 (    0,    0) */
  { 0x0001,  0x7fff,  82,  80 },    /* 082: p=0.000027 (    0,    0) */
  { 0x620b,  0x0000,   9,  85 },    /* 083: p=0.411764 (    2,    3) */
  { 0x294a,  0x0000,  86, 216 },    /* 084: p=0.199988 (    1,    0) */
  { 0x8000,  0x0000,   5,   6 },    /* 085: p=0.500000 (    3,    3) */
  { 0x0db3,  0x0000,  88, 168 },    /* 086: p=0.071422 (    4,    0) */
  { 0x538e,  0x0000,  89, 137 },    /* 087: p=0.363634 (    1,    2) */
  { 0x0490,  0x0000,  90, 134 },    /* 088: p=0.024388 (   13,    0) */
  { 0x3e3e,  0x0000,  91, 135 },    /* 089: p=0.285711 (    1,    3) */
  { 0x017c,  0x0000,  92, 112 },    /* 090: p=0.007999 (   41,    0) */
  { 0x294a,  0x0000,  93, 133 },    /* 091: p=0.199997 (    1,    5) */
  { 0x007c,  0x0000,  94, 104 },    /* 092: p=0.002611 (  127,    0) */
  { 0x1b75,  0x0000,  95, 131 },    /* 093: p=0.137929 (    1,    8) */
  { 0x0028,  0x0000,  96, 100 },    /* 094: p=0.000849 (  392,    0) */
  { 0x12fc,  0x0000,  97, 129 },    /* 095: p=0.097559 (    1,   12) */
  { 0x000d,  0x0000,  82,  98 },    /* 096: p=0.000276 ( 1208,    0) */
  { 0x0cfb,  0x0000,  99, 125 },    /* 097: p=0.067795 (    1,   18) */
  { 0x0034,  0x0000,  76,  72 },    /* 098: p=0.001102 ( 1208,    1) */
  { 0x08cd,  0x0000, 101, 123 },    /* 099: p=0.046511 (    1,   27) */
  { 0x00a0,  0x0000,  70, 102 },    /* 100: p=0.003387 (  392,    1) */
  { 0x05de,  0x0000, 103, 119 },    /* 101: p=0.031249 (    1,   41) */
  { 0x0118,  0x0000,  66,  60 },    /* 102: p=0.005912 (  392,    2) */
  { 0x03e9,  0x0000, 105, 117 },    /* 103: p=0.020942 (    1,   62) */
  { 0x01ed,  0x0000, 106, 110 },    /* 104: p=0.010362 (  127,    1) */
  { 0x0298,  0x0000, 107, 115 },    /* 105: p=0.013937 (    1,   94) */
  { 0x0145,  0x0000,  66, 108 },    /* 106: p=0.006849 (  193,    1) */
  { 0x01b6,  0x0000, 109, 113 },    /* 107: p=0.009216 (    1,  143) */
  { 0x0237,  0x0000,  60,  54 },    /* 108: p=0.011925 (  193,    2) */
  { 0x0121,  0x0000,  65, 111 },    /* 109: p=0.006097 (    1,  217) */
  { 0x035b,  0x0000,  56,  48 },    /* 110: p=0.017995 (  127,    2) */
  { 0x01f9,  0x0000,  59,  53 },    /* 111: p=0.010622 (    2,  217) */
  { 0x05de,  0x0000, 114, 130 },    /* 112: p=0.031249 (   41,    1) */
  { 0x02fc,  0x0000,  55,  49 },    /* 113: p=0.016018 (    2,  143) */
  { 0x03e9,  0x0000, 116, 128 },    /* 114: p=0.020942 (   62,    1) */
  { 0x0484,  0x0000,  51,  45 },    /* 115: p=0.024138 (    2,   94) */
  { 0x0298,  0x0000, 118, 126 },    /* 116: p=0.013937 (   94,    1) */
  { 0x06ca,  0x0000,  47,  39 },    /* 117: p=0.036082 (    2,   62) */
  { 0x01b6,  0x0000, 120, 124 },    /* 118: p=0.009216 (  143,    1) */
  { 0x0a27,  0x0000,  41, 121 },    /* 119: p=0.053434 (    2,   41) */
  { 0x0121,  0x0000,  66, 122 },    /* 120: p=0.006097 (  217,    1) */
  { 0x0e57,  0x0000,  37,  31 },    /* 121: p=0.074626 (    3,   41) */
  { 0x01f9,  0x0000,  60,  54 },    /* 122: p=0.010622 (  217,    2) */
  { 0x0f25,  0x0000,  37,  29 },    /* 123: p=0.078651 (    2,   27) */
  { 0x02fc,  0x0000,  56,  50 },    /* 124: p=0.016018 (  143,    2) */
  { 0x1629,  0x0000,  33, 127 },    /* 125: p=0.112902 (    2,   18) */
  { 0x0484,  0x0000,  52,  46 },    /* 126: p=0.024138 (   94,    2) */
  { 0x1ee8,  0x0000,  27,  21 },    /* 127: p=0.153845 (    3,   18) */
  { 0x06ca,  0x0000,  48,  40 },    /* 128: p=0.036082 (   62,    2) */
  { 0x200f,  0x0000,  27,  19 },    /* 129: p=0.159089 (    2,   12) */
  { 0x0a27,  0x0000,  42, 132 },    /* 130: p=0.053434 (   41,    2) */
  { 0x2dae,  0x0000,  21,  15 },    /* 131: p=0.218748 (    2,    8) */
  { 0x0e57,  0x0000,  38,  32 },    /* 132: p=0.074626 (   41,    3) */
  { 0x4320,  0x0000,  15,   7 },    /* 133: p=0.304346 (    2,    5) */
  { 0x11a0,  0x0000, 136, 164 },    /* 134: p=0.090907 (   13,    1) */
  { 0x620b,  0x0000,   9,  85 },    /* 135: p=0.411764 (    2,    3) */
  { 0x0bbe,  0x0000, 138, 162 },    /* 136: p=0.061537 (   20,    1) */
  { 0x8000,  0x0000, 135, 248 },    /* 137: p=0.500000 (    2,    2) */
  { 0x07f3,  0x0000, 140, 160 },    /* 138: p=0.042104 (   30,    1) */
  { 0x294a,  0x0000, 141, 247 },    /* 139: p=0.199988 (    0,    1) */
  { 0x053e,  0x0000, 142, 158 },    /* 140: p=0.027971 (   46,    1) */
  { 0x0db3,  0x0000, 143, 199 },    /* 141: p=0.071422 (    0,    4) */
  { 0x0378,  0x0000, 144, 156 },    /* 142: p=0.018604 (   70,    1) */
  { 0x0490,  0x0000, 145, 167 },    /* 143: p=0.024388 (    0,   13) */
  { 0x024d,  0x0000, 146, 154 },    /* 144: p=0.012384 (  106,    1) */
  { 0x017c,  0x0000, 147, 101 },    /* 145: p=0.007999 (    0,   41) */
  { 0x0185,  0x0000, 148, 152 },    /* 146: p=0.008197 (  161,    1) */
  { 0x007c,  0x0000, 149, 159 },    /* 147: p=0.002611 (    0,  127) */
  { 0x0100,  0x0000,  68, 150 },    /* 148: p=0.005405 (  245,    1) */
  { 0x0028,  0x0000, 151, 155 },    /* 149: p=0.000849 (    0,  392) */
  { 0x01c0,  0x0000,  62,  56 },    /* 150: p=0.009421 (  245,    2) */
  { 0x000d,  0x0000,  81, 153 },    /* 151: p=0.000276 (    0, 1208) */
  { 0x02a7,  0x0000,  58,  52 },    /* 152: p=0.014256 (  161,    2) */
  { 0x0034,  0x0000,  75,  71 },    /* 153: p=0.001102 (    1, 1208) */
  { 0x0403,  0x0000,  54,  46 },    /* 154: p=0.021472 (  106,    2) */
  { 0x00a0,  0x0000,  69, 157 },    /* 155: p=0.003387 (    1,  392) */
  { 0x0608,  0x0000,  48,  42 },    /* 156: p=0.032110 (   70,    2) */
  { 0x0118,  0x0000,  65,  59 },    /* 157: p=0.005912 (    2,  392) */
  { 0x0915,  0x0000,  44,  38 },    /* 158: p=0.047945 (   46,    2) */
  { 0x01ed,  0x0000, 161, 165 },    /* 159: p=0.010362 (    1,  127) */
  { 0x0db4,  0x0000,  40,  32 },    /* 160: p=0.071428 (   30,    2) */
  { 0x0145,  0x0000,  65, 163 },    /* 161: p=0.006849 (    1,  193) */
  { 0x1417,  0x0000,  34,  26 },    /* 162: p=0.102940 (   20,    2) */
  { 0x0237,  0x0000,  59,  53 },    /* 163: p=0.011925 (    2,  193) */
  { 0x1dd6,  0x0000,  30, 166 },    /* 164: p=0.148935 (   13,    2) */
  { 0x035b,  0x0000,  55,  47 },    /* 165: p=0.017995 (    2,  127) */
  { 0x294a,  0x0000,  24,  18 },    /* 166: p=0.199999 (   13,    3) */
  { 0x11a0,  0x0000, 169, 195 },    /* 167: p=0.090907 (    1,   13) */
  { 0x31a3,  0x0000, 170, 212 },    /* 168: p=0.235291 (    4,    1) */
  { 0x0bbe,  0x0000, 171, 193 },    /* 169: p=0.061537 (    1,   20) */
  { 0x235a,  0x0000, 172, 208 },    /* 170: p=0.173910 (    6,    1) */
  { 0x07f3,  0x0000, 173, 191 },    /* 171: p=0.042104 (    1,   30) */
  { 0x18b3,  0x0000, 174, 206 },    /* 172: p=0.124998 (    9,    1) */
  { 0x053e,  0x0000, 175, 189 },    /* 173: p=0.027971 (    1,   46) */
  { 0x1073,  0x0000, 176, 204 },    /* 174: p=0.085105 (   14,    1) */
  { 0x0378,  0x0000, 177, 187 },    /* 175: p=0.018604 (    1,   70) */
  { 0x0b35,  0x0000, 178, 200 },    /* 176: p=0.058822 (   21,    1) */
  { 0x024d,  0x0000, 179, 185 },    /* 177: p=0.012384 (    1,  106) */
  { 0x0778,  0x0000, 180, 198 },    /* 178: p=0.039603 (   32,    1) */
  { 0x0185,  0x0000, 181, 183 },    /* 179: p=0.008197 (    1,  161) */
  { 0x04ed,  0x0000, 182, 194 },    /* 180: p=0.026315 (   49,    1) */
  { 0x0100,  0x0000,  67,  59 },    /* 181: p=0.005405 (    1,  245) */
  { 0x0349,  0x0000, 184, 192 },    /* 182: p=0.017621 (   74,    1) */
  { 0x02a7,  0x0000,  57,  51 },    /* 183: p=0.014256 (    2,  161) */
  { 0x022e,  0x0000, 186, 190 },    /* 184: p=0.011730 (  112,    1) */
  { 0x0403,  0x0000,  53,  45 },    /* 185: p=0.021472 (    2,  106) */
  { 0x0171,  0x0000,  64, 188 },    /* 186: p=0.007767 (  170,    1) */
  { 0x0608,  0x0000,  47,  41 },    /* 187: p=0.032110 (    2,   70) */
  { 0x0283,  0x0000,  58,  52 },    /* 188: p=0.013513 (  170,    2) */
  { 0x0915,  0x0000,  43,  37 },    /* 189: p=0.047945 (    2,   46) */
  { 0x03cc,  0x0000,  54,  48 },    /* 190: p=0.020349 (  112,    2) */
  { 0x0db4,  0x0000,  39,  31 },    /* 191: p=0.071428 (    2,   30) */
  { 0x05b6,  0x0000,  50,  42 },    /* 192: p=0.030434 (   74,    2) */
  { 0x1417,  0x0000,  33,  25 },    /* 193: p=0.102940 (    2,   20) */
  { 0x088a,  0x0000,  44, 196 },    /* 194: p=0.045161 (   49,    2) */
  { 0x1dd6,  0x0000,  29, 197 },    /* 195: p=0.148935 (    2,   13) */
  { 0x0c16,  0x0000,  40,  34 },    /* 196: p=0.063291 (   49,    3) */
  { 0x294a,  0x0000,  23,  17 },    /* 197: p=0.199999 (    3,   13) */
  { 0x0ce2,  0x0000,  40,  32 },    /* 198: p=0.067307 (   32,    2) */
  { 0x31a3,  0x0000, 201, 243 },    /* 199: p=0.235291 (    1,    4) */
  { 0x1332,  0x0000,  36, 202 },    /* 200: p=0.098590 (   21,    2) */
  { 0x235a,  0x0000, 203, 239 },    /* 201: p=0.173910 (    1,    6) */
  { 0x1adc,  0x0000,  30,  24 },    /* 202: p=0.135134 (   21,    3) */
  { 0x18b3,  0x0000, 205, 237 },    /* 203: p=0.124998 (    1,    9) */
  { 0x1be7,  0x0000,  30,  22 },    /* 204: p=0.139999 (   14,    2) */
  { 0x1073,  0x0000, 207, 235 },    /* 205: p=0.085105 (    1,   14) */
  { 0x294a,  0x0000,  26,  16 },    /* 206: p=0.199998 (    9,    2) */
  { 0x0b35,  0x0000, 209, 231 },    /* 207: p=0.058822 (    1,   21) */
  { 0x3a07,  0x0000,  20, 210 },    /* 208: p=0.269229 (    6,    2) */
  { 0x0778,  0x0000, 211, 229 },    /* 209: p=0.039603 (    1,   32) */
  { 0x4e30,  0x0000,  14,   8 },    /* 210: p=0.344827 (    6,    3) */
  { 0x04ed,  0x0000, 213, 225 },    /* 211: p=0.026315 (    1,   49) */
  { 0x4fa6,  0x0000,  14, 214 },    /* 212: p=0.349998 (    4,    2) */
  { 0x0349,  0x0000, 215, 223 },    /* 213: p=0.017621 (    1,   74) */
  { 0x6966,  0x0000,   8,   2 },    /* 214: p=0.434782 (    4,    3) */
  { 0x022e,  0x0000, 217, 221 },    /* 215: p=0.011730 (    1,  112) */
  { 0x8000,  0x0000, 218,  87 },    /* 216: p=0.500000 (    1,    1) */
  { 0x0171,  0x0000,  63, 219 },    /* 217: p=0.007767 (    1,  170) */
  { 0x538e,  0x0000, 220, 246 },    /* 218: p=0.363634 (    2,    1) */
  { 0x0283,  0x0000,  57,  51 },    /* 219: p=0.013513 (    2,  170) */
  { 0x3e3e,  0x0000, 222, 244 },    /* 220: p=0.285711 (    3,    1) */
  { 0x03cc,  0x0000,  53,  47 },    /* 221: p=0.020349 (    2,  112) */
  { 0x294a,  0x0000, 224, 242 },    /* 222: p=0.199997 (    5,    1) */
  { 0x05b6,  0x0000,  49,  41 },    /* 223: p=0.030434 (    2,   74) */
  { 0x1b75,  0x0000, 226, 240 },    /* 224: p=0.137929 (    8,    1) */
  { 0x088a,  0x0000,  43, 227 },    /* 225: p=0.045161 (    2,   49) */
  { 0x12fc,  0x0000, 228, 238 },    /* 226: p=0.097559 (   12,    1) */
  { 0x0c16,  0x0000,  39,  33 },    /* 227: p=0.063291 (    3,   49) */
  { 0x0cfb,  0x0000, 230, 234 },    /* 228: p=0.067795 (   18,    1) */
  { 0x0ce2,  0x0000,  39,  31 },    /* 229: p=0.067307 (    2,   32) */
  { 0x08cd,  0x0000, 112, 232 },    /* 230: p=0.046511 (   27,    1) */
  { 0x1332,  0x0000,  35, 233 },    /* 231: p=0.098590 (    2,   21) */
  { 0x0f25,  0x0000,  38,  30 },    /* 232: p=0.078651 (   27,    2) */
  { 0x1adc,  0x0000,  29,  23 },    /* 233: p=0.135134 (    3,   21) */
  { 0x1629,  0x0000,  34, 236 },    /* 234: p=0.112902 (   18,    2) */
  { 0x1be7,  0x0000,  29,  21 },    /* 235: p=0.139999 (    2,   14) */
  { 0x1ee8,  0x0000,  28,  22 },    /* 236: p=0.153845 (   18,    3) */
  { 0x294a,  0x0000,  25,  15 },    /* 237: p=0.199998 (    2,    9) */
  { 0x200f,  0x0000,  28,  20 },    /* 238: p=0.159089 (   12,    2) */
  { 0x3a07,  0x0000,  19, 241 },    /* 239: p=0.269229 (    2,    6) */
  { 0x2dae,  0x0000,  22,  16 },    /* 240: p=0.218748 (    8,    2) */
  { 0x4e30,  0x0000,  13,   7 },    /* 241: p=0.344827 (    3,    6) */
  { 0x4320,  0x0000,  16,   8 },    /* 242: p=0.304346 (    5,    2) */
  { 0x4fa6,  0x0000,  13, 245 },    /* 243: p=0.349998 (    2,    4) */
  { 0x620b,  0x0000,  10,   2 },    /* 244: p=0.411764 (    3,    2) */
  { 0x6966,  0x0000,   7,   1 },    /* 245: p=0.434782 (    3,    4) */
  { 0x8000,  0x0000, 244,  83 },    /* 246: p=0.500000 (    2,    2) */
  { 0x8000,  0x0000, 249, 250 },    /* 247: p=0.500000 (    1,    1) */
  { 0x620b,  0x0000,  10,   2 },    /* 248: p=0.411764 (    3,    2) */
  { 0x538e,  0x0000,  89, 137 },    /* 249: p=0.363634 (    1,    2) */
  { 0x538e,  0x0000, 220, 246 },    /* 250: p=0.363634 (    2,    1) */
#endif
};



////////////////////////////////////////////////////////////////
// CONSTRUCTOR/DESTRUCTOR
////////////////////////////////////////////////////////////////

class ZPCodec::Encode : public ZPCodec
{
public:
  Encode(GP<ByteStream> gbs, const bool djvucompat);
  virtual ~Encode();
private:
  void init(void); 
};

ZPCodec::Encode::Encode(GP<ByteStream> gbs, const bool djvucompat)
: ZPCodec(gbs,true,djvucompat)
{
  init();
  // Codebit counter
#ifdef ZPCODEC_BITCOUNT
  bitcount = 0;
#endif
}

ZPCodec::Encode::~Encode()
{
  eflush();
}
 
class ZPCodec::Decode : public ZPCodec
{
public:
  Decode(GP<ByteStream> gbs, const bool djvucompat);
  virtual ~Decode();
private:
  void init(void); 
};

ZPCodec::Decode::Decode(GP<ByteStream> gbs, const bool djvucompat)
: ZPCodec(gbs,false,djvucompat)
{
  init();
  // Codebit counter
#ifdef ZPCODEC_BITCOUNT
  bitcount = 0;
#endif
}
 
ZPCodec::Decode::~Decode() {}

ZPCodec::ZPCodec(GP<ByteStream> xgbs, const bool xencoding, const bool djvucompat)
: gbs(xgbs), bs(xgbs), encoding(xencoding), fence(0), subend(0), buffer(0), nrun(0)
{
  // Create machine independent ffz table
  for (int i=0; i<256; i++)
    {
      ffzt[i]=0;
      for (int j=i; j&0x80; j<<=1)
        ffzt[i] += 1;
    }
  // Initialize table
  newtable(default_ztable);
  // Patch table table (and lose DjVu compatibility).
  if (!djvucompat)
    {
      for (int j=0; j<256; j++)
        {
          unsigned short a = 0x10000-p[j];
          while (a>=0x8000)  a=(unsigned short)(a<<1);
          if (m[j]>0 && a+p[j]>=0x8000 && a>=m[j])
            {
              BitContext x = default_ztable[j].dn;
              BitContext y = default_ztable[x].dn;
              dn[j] = y;
            }
        }
    }
}

ZPCodec::~ZPCodec() {}

GP<ZPCodec>
ZPCodec::create(GP<ByteStream> gbs, const bool encoding, const bool djvucompat)
{
  GP<ZPCodec> retval;
  if(encoding)
  {
    retval=new ZPCodec::Encode(gbs,djvucompat);
  }else
  {
    retval=new ZPCodec::Decode(gbs,djvucompat);
  }
  return retval;
}

////////////////////////////////////////////////////////////////
// Z CODER DECODE ALGORITHM
////////////////////////////////////////////////////////////////



void 
ZPCodec::Decode::init(void)
{
  assert(sizeof(unsigned int)==4);
  assert(sizeof(unsigned short)==2);
  a = 0;
  /* Read first 16 bits of code */
  if (! bs->read((void*)&byte, 1))
    byte = 0xff;
  code = (byte<<8);
  if (! bs->read((void*)&byte, 1))
    byte = 0xff;
  code = code | byte;
  /* Preload buffer */
  delay = 25;
  scount = 0;
  preload();
  /* Compute initial fence */
  fence = code;
  if (code >= 0x8000)
    fence = 0x7fff;
}


void
ZPCodec::preload(void)
{
  while (scount<=24)
    {
      if (bs->read((void*)&byte, 1) < 1) 
        {
          byte = 0xff;
          if (--delay < 1)
            G_THROW( ByteStream::EndOfFile );
        }
      buffer = (buffer<<8) | byte;
      scount += 8;
    }
}


inline int
ZPCodec::ffz(unsigned int x)
{
  // DO NOT DEFINE FASTBSR : 
  // Test shows that it hardly helps on a PPro,
  // and rumors are that BSR is very slow on PPlain.
#if defined(FASTBSR) && defined(_MSC_VER) && defined(_M_IX86)
  int r;
  __asm  { 
        mov  ebx, x
        xor  ebx, 0xffff
        mov  eax, -1
        bsr  eax, ebx
        mov  r, eax
  }
  return 15 - r;
#elif defined(FASTBSR) && defined(__GNUC__) && defined(__i386__)
  int r, dummy;
  __asm__ const ( "movl %2,%1\n\t"
                  "xorl $0xffff, %1\n\t"
                  "movl $-1, %0\n\t"
                  "bsrl %1, %0"
                  : "=&q" (r), "=q" (dummy) : "rm" (x) );
  return 15 - r;
#else
  return (x>=0xff00) ? (ffzt[x&0xff]+8) : (ffzt[(x>>8)&0xff]);
#endif
}


int 
ZPCodec::decode_sub(BitContext &ctx, unsigned int z)
{
  /* Save bit */
  int bit = (ctx & 1);
  /* Avoid interval reversion */
#ifdef ZPCODER
  unsigned int d = 0x6000 + ((z+a)>>2);
  if (z > d) 
    z = d;
#endif
#ifdef ZCODER
  if (z >= 0x8000)
    z = 0x4000 + (z>>1);
#endif
  /* Test MPS/LPS */
  if (z > code)
    {
      /* LPS branch */
      z = 0x10000 - z;
      a = a + z;
      code = code + z;
      /* LPS adaptation */
      ctx = dn[ctx];
      /* LPS renormalization */
      int shift = ffz(a);
      scount -= shift;
      a = (unsigned short)(a<<shift);
      code = (unsigned short)(code<<shift) | ((buffer>>scount) & ((1<<shift)-1));
#ifdef ZPCODEC_BITCOUNT
      bitcount += shift;
#endif
      if (scount<16) preload();
      /* Adjust fence */
      fence = code;
      if (code >= 0x8000)
        fence = 0x7fff;
      return bit ^ 1;
    }
  else
    {
      /* MPS adaptation */
      if (a >= m[ctx])
        ctx = up[ctx];
      /* MPS renormalization */
      scount -= 1;
      a = (unsigned short)(z<<1);
      code = (unsigned short)(code<<1) | ((buffer>>scount) & 1);
#ifdef ZPCODEC_BITCOUNT
      bitcount += 1;
#endif
      if (scount<16) preload();
      /* Adjust fence */
      fence = code;
      if (code >= 0x8000)
        fence = 0x7fff;
      return bit;
    }
}


int 
ZPCodec::decode_sub_simple(int mps, unsigned int z)
{
  /* Test MPS/LPS */
  if (z > code)
    {
      /* LPS branch */
      z = 0x10000 - z;
      a = a + z;
      code = code + z;
      /* LPS renormalization */
      int shift = ffz(a);
      scount -= shift;
      a = (unsigned short)(a<<shift);
      code = (unsigned short)(code<<shift) | ((buffer>>scount) & ((1<<shift)-1));
#ifdef ZPCODEC_BITCOUNT
      bitcount += shift;
#endif
      if (scount<16) preload();
      /* Adjust fence */
      fence = code;
      if (code >= 0x8000)
        fence = 0x7fff;
      return mps ^ 1;
    }
  else
    {
      /* MPS renormalization */
      scount -= 1;
      a = (unsigned short)(z<<1);
      code = (unsigned short)(code<<1) | ((buffer>>scount) & 1);
#ifdef ZPCODEC_BITCOUNT
      bitcount += 1;
#endif
      if (scount<16) preload();
      /* Adjust fence */
      fence = code;
      if (code >= 0x8000)
        fence = 0x7fff;
      return mps;
    }
}


int  
ZPCodec::decode_sub_nolearn(int mps, unsigned int z)
{
#ifdef ZPCODER
  unsigned int d = 0x6000 + ((z+a)>>2);
  if (z > d) 
        z = d;
#endif
#ifdef ZCODER
  if (z >= 0x8000)
    z = 0x4000 + (z>>1);
#endif
  /* Test MPS/LPS */
  if (z > code)
    {
      /* LPS branch */
      z = 0x10000 - z;
      a = a + z;
      code = code + z;
      /* LPS renormalization */
      int shift = ffz(a);
      scount -= shift;
      a = (unsigned short)(a<<shift);
      code = (unsigned short)(code<<shift) | ((buffer>>scount) & ((1<<shift)-1));
#ifdef ZPCODEC_BITCOUNT
      bitcount += shift;
#endif
      if (scount<16) preload();
      /* Adjust fence */
      fence = code;
      if (code >= 0x8000)
        fence = 0x7fff;
      return mps ^ 1;
    }
  else
    {
      /* MPS renormalization */
      scount -= 1;
      a = (unsigned short)(z<<1);
      code = (unsigned short)(code<<1) | ((buffer>>scount) & 1);
#ifdef ZPCODEC_BITCOUNT
      bitcount += 1;
#endif
      if (scount<16) preload();
      /* Adjust fence */
      fence = code;
      if (code >= 0x8000)
        fence = 0x7fff;
      return mps;
    }
}





////////////////////////////////////////////////////////////////
// Z CODER ENCODE ALGORITHM
////////////////////////////////////////////////////////////////




void 
ZPCodec::Encode::init(void)
{
  assert(sizeof(unsigned int)==4);
  assert(sizeof(unsigned short)==2);
  a = 0;
  scount = 0;
  byte = 0;
  delay = 25;
  subend = 0;
  buffer = 0xffffff;
  nrun = 0;
}

void
ZPCodec::outbit(int bit)
{
  if (delay > 0)
    {
      if (delay < 0xff) // delay=0xff suspends emission forever
        delay -= 1;
    }
  else
    {
      /* Insert a bit */
      byte = (byte<<1) | bit;
      /* Output a byte */
      if (++scount == 8)
        {
          if (!encoding)
            G_THROW( ERR_MSG("ZPCodec.no_encoding") );
          if (bs->write((void*)&byte, 1) != 1)
            G_THROW( ERR_MSG("ZPCodec.write_error") );
          scount = 0;
          byte = 0;
        }
    }
}

void 
ZPCodec::zemit(int b)
{
  /* Shift new bit into 3bytes buffer */
  buffer = (buffer<<1) + b;
  /* Examine bit going out of the 3bytes buffer */
  b = (buffer >> 24);
  buffer = (buffer & 0xffffff);
  /* The following lines have been changed in order to emphazise the
   * similarity between this bit counting and the scheme of Witten, Neal & Cleary
   * (WN&C).  Corresponding changes have been made in outbit and eflush.
   * Variable 'nrun' is similar to the 'bits_to_follow' in the W&N code.
   */
  switch(b)
    {
      /* Similar to WN&C upper renormalization */
    case 1:
      outbit(1);
      while (nrun-- > 0)
        outbit(0);
      nrun = 0;
      break;
      /* Similar to WN&C lower renormalization */
    case 0xff:
      outbit(0);
      while (nrun-- > 0)
        outbit(1);
      nrun = 0;
      break;
      /* Similar to WN&C central renormalization */
    case 0:
      nrun += 1;
      break;
    default:
      assert(0);
    }
  /* Code bit counter */
#ifdef ZPCODEC_BITCOUNT
  bitcount += 1;
#endif
}

void 
ZPCodec::eflush()
{
  /* adjust subend */
  if (subend > 0x8000)
    subend = 0x10000;
  else if (subend > 0)
    subend = 0x8000;
  /* zemit many mps bits */
  while (buffer != 0xffffff  || subend )
    {
      zemit(1 - (subend>>15) );
      subend = (unsigned short)(subend<<1);
    }
  /* zemit pending run */
  outbit(1);
  while (nrun-- > 0)
    outbit(0);
  nrun = 0;
  /* zemit 1 until full byte */
  while (scount > 0)
    outbit(1);
  /* prevent further emission */
  delay = 0xff;
}

void 
ZPCodec::encode_mps(BitContext &ctx, unsigned int z)
{
  /* Avoid interval reversion */
#ifdef ZPCODER
  unsigned int d = 0x6000 + ((z+a)>>2);
  if (z > d) 
    z = d;
#endif
#ifdef ZCODER
  if (z >= 0x8000)
    z = 0x4000 + (z>>1);
#endif
  /* Adaptation */
  if (a >= m[ctx])
    ctx = up[ctx];
  /* Code MPS */
  a = z;
  /* Export bits */
  if (a >= 0x8000)
    {
      zemit(1 - (subend>>15) );
      subend = (unsigned short)(subend<<1);
      a = (unsigned short)(a<<1);
    }
}


void 
ZPCodec::encode_lps(BitContext &ctx, unsigned int z)
{
  /* Avoid interval reversion */
#ifdef ZPCODER
  unsigned int d = 0x6000 + ((z+a)>>2);
  if (z > d) 
    z = d;
#endif
#ifdef ZCODER
  if (z >= 0x8000)
    z = 0x4000 + (z>>1);
#endif
  /* Adaptation */
  ctx = dn[ctx];
  /* Code LPS */
  z = 0x10000 - z;
  subend += z;
  a += z;
  /* Export bits */
  while (a >= 0x8000)
    {
      zemit(1 - (subend>>15) );
      subend = (unsigned short)(subend<<1);
      a = (unsigned short)(a<<1);
    }
}


void 
ZPCodec::encode_mps_simple(unsigned int z)
{
  /* Code MPS */
  a = z;
  /* Export bits */
  if (a >= 0x8000)
    {
      zemit(1 - (subend>>15) );
      subend = (unsigned short)(subend<<1);
      a = (unsigned short)(a<<1);
    }
}

void 
ZPCodec::encode_lps_simple(unsigned int z)
{
  /* Code LPS */
  z = 0x10000 - z;
  subend += z;
  a += z;
  /* Export bits */
  while (a >= 0x8000)
    {
      zemit(1 - (subend>>15) );
      subend = (unsigned short)(subend<<1);
      a = (unsigned short)(a<<1);
    }
}


void 
ZPCodec::encode_mps_nolearn(unsigned int z)
{
#ifdef ZPCODER
  unsigned int d = 0x6000 + ((z+a)>>2);
  if (z > d) 
    z = d;
#endif
#ifdef ZCODER
  if (z >= 0x8000)
    z = 0x4000 + (z>>1);
#endif
  /* Code MPS */
  a = z;
  /* Export bits */
  if (a >= 0x8000)
    {
      zemit(1 - (subend>>15) );
      subend = (unsigned short)(subend<<1);
      a = (unsigned short)(a<<1);
    }
}


void 
ZPCodec::encode_lps_nolearn(unsigned int z)
{
#ifdef ZPCODER
  unsigned int d = 0x6000 + ((z+a)>>2);
  if (z > d) 
    z = d;
#endif
#ifdef ZCODER
  if (z >= 0x8000)
    z = 0x4000 + (z>>1);
#endif
  /* Code LPS */
  z = 0x10000 - z;
  subend += z;
  a += z;
  /* Export bits */
  while (a >= 0x8000)
    {
      zemit(1 - (subend>>15) );
      subend = (unsigned short)(subend<<1);
      a = (unsigned short)(a<<1);
    }
}






////////////////////////////////////////////////////////////////
// TABLE AND PARAMETER MANAGEMENT
////////////////////////////////////////////////////////////////




void 
ZPCodec::newtable(ZPCodec::Table *table)
{
  for (int i=0; i<256; i++)
    {
      p[i]  = table[i].p;
      m[i]  = table[i].m;
      up[i] = table[i].up;
      dn[i] = table[i].dn;
    }
}

static float 
p_to_plps(unsigned short p)
{
  float fplps;
  float fp = (float)(p) / (float)(0x10000);
  const float log2 = (float)0.69314718055994530942;
#ifdef ZCODER
  fplps = fp - (fp+0.5) * log(fp+0.5) + (fp-0.5)*log2;
#endif
#ifdef ZPCODER
  if (fp <= (1.0/6.0) )
    fplps = fp * 2 * log2;
  else
    fplps = (float)((1.5*fp-0.25) - (1.5*fp+0.25)*log(1.5*fp+0.25) + (0.5*fp-0.25)*log2);
#endif
  return fplps;
}


BitContext 
ZPCodec::state(float prob1)
{
  // Return a state representing 'prob1' in the steady chain
  // FixMe: This is quite slow! 
  int mps = (prob1 <= 0.5 ? 0 : 1);
  float plps = (float)(mps ? 1.0 - prob1 : prob1);
  // Locate steady chain (ordered, decreasing)
  int sz = 0;
  int lo = (mps ? 1 : 2);
  while (p[lo+sz+sz+2] < p[lo+sz+sz]) sz+=1;
  // Bisection
  while (sz > 1)
    {
      int nsz = sz >> 1;
      float nplps = p_to_plps( p[lo+nsz+nsz] );
      if (nplps < plps)
        { sz=nsz; }
      else
        { lo=lo+nsz+nsz; sz=sz-nsz; }
    }
  // Choose closest one
  float f1 = p_to_plps(p[lo])-plps;
  float f2 = plps-p_to_plps(p[lo+2]);
  return (f1<f2) ? lo : lo+2;
}


#ifdef HAVE_NAMESPACES
}
# ifndef NOT_USING_DJVU_NAMESPACE
using namespace DJVU;
# endif
#endif