[xiph-cvs] cvs commit: w3d wavelet_coeff2.c zpcoder.c zpcoder.h Makefile bitcoder.h rle.h wavelet_coeff.c

Holger Waechtler holger at xiph.org
Tue Jul 31 01:07:02 PDT 2001



holger      01/07/31 01:07:01

  Modified:    .        Makefile bitcoder.h rle.h wavelet_coeff.c
  Added:       .        wavelet_coeff2.c zpcoder.c zpcoder.h
  Log:
   - the skip-0coeff logic seems to work, the encoder is pretty fast now ...
   - some experiments with an octree coefficient encoder, inspired by SPECK
   - initial attempt to port the ZP coder

Revision  Changes    Path
1.12      +2 -2      w3d/Makefile

Index: Makefile
===================================================================
RCS file: /usr/local/cvsroot/w3d/Makefile,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- Makefile	2001/07/09 08:17:01	1.11
+++ Makefile	2001/07/31 08:07:00	1.12
@@ -4,8 +4,8 @@
 CFLAGS = -g -O0 -Wall -DTYPE=int16_t -DRLECODER -DDBG_XFORM -DDBG_MEMLEAKS
 LFLAGS = -g #-lefence
 
-OBJS = mem.o pnm.o wavelet.o wavelet_xform.o wavelet_coeff.o yuv.o \
-	tarkin.o tarkin-io.o
+OBJS = mem.o pnm.o wavelet.o wavelet_xform.o wavelet_coeff.o wavelet_coeff2.o \
+	yuv.o tarkin.o tarkin-io.o
 
 TEST_TARGETS = _test_bitcoder _test_rle _test_huffman
 

1.7       +1 -1      w3d/bitcoder.h

Index: bitcoder.h
===================================================================
RCS file: /usr/local/cvsroot/w3d/bitcoder.h,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- bitcoder.h	2001/07/11 14:25:23	1.6
+++ bitcoder.h	2001/07/31 08:07:00	1.7
@@ -80,7 +80,7 @@
 {
    if (!s->bitstream || s->byte_count >= s->limit)
 {
-printf ("bitcoder empty !!!\n");
+//printf ("bitcoder empty !!!\n");
       return 1;
 }
 

1.8       +2 -5      w3d/rle.h

Index: rle.h
===================================================================
RCS file: /usr/local/cvsroot/w3d/rle.h,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- rle.h	2001/07/11 14:25:23	1.7
+++ rle.h	2001/07/31 08:07:00	1.8
@@ -21,10 +21,8 @@
 #define ENTROPY_CODER_BITSTREAM(coder)    ((coder)->bitcoder.bitstream)
 
 #define ENTROPY_CODER_MPS(coder)          ((coder)->mps)
-#define ENTROPY_CODER_RUNLENGTH(coder)    ((coder)->count)
-//#define ENTROPY_CODER_SKIP(coder,skip)    printf ("coder->count == %u ->", (coder)->count); (coder)->count -= skip; printf ("%u\n", (coder)->count);
-#define ENTROPY_CODER_SKIP(coder,skip)    (coder)->count -= skip
-
+#define ENTROPY_CODER_RUNLENGTH(coder)    ((coder)->count+1)
+#define ENTROPY_CODER_SKIP(coder,skip)    do { (coder)->count -= skip-1; } while (0)
 #endif
 
 
@@ -189,7 +187,6 @@
    s->count--;
    return (s->mps);
 }
-
 
 
 static inline

1.3       +82 -56    w3d/wavelet_coeff.c

Index: wavelet_coeff.c
===================================================================
RCS file: /usr/local/cvsroot/w3d/wavelet_coeff.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- wavelet_coeff.c	2001/07/11 14:25:23	1.2
+++ wavelet_coeff.c	2001/07/31 08:07:00	1.3
@@ -54,8 +54,43 @@
 
 
 
-#if 0
+
 static inline
+uint32_t skip_0coeffs (Wavelet3DBuf* buf,
+                       ENTROPY_CODER s_stream [],
+                       ENTROPY_CODER i_stream [],
+                       uint32_t limit)
+{
+   int i;
+   uint32_t min = limit;
+
+   for (i=0; i<10; i++) {
+      if (ENTROPY_CODER_MPS(&s_stream[i]) == 0) {
+         uint32_t runlength = ENTROPY_CODER_RUNLENGTH(&s_stream[i]);
+         if (min > runlength)
+            min = runlength;
+         if (min <= 2)
+            return 0;
+      } else {
+         return 0;
+      }
+   }
+
+   if (min > limit)
+      min = limit;
+
+   for (i=0; i<10; i++) {
+      ENTROPY_CODER_SKIP(&s_stream[i], min);
+      ENTROPY_CODER_SKIP(&i_stream[i], min);
+   }
+
+   return min;
+}
+
+
+
+#if 1
+static inline
 void encode_quadrant (const Wavelet3DBuf* buf,
                       int level, int quadrant, uint32_t w, uint32_t h, uint32_t f,
                       ENTROPY_CODER significand_bitstream [],
@@ -112,23 +147,43 @@
 static inline
 void decode_quadrant (Wavelet3DBuf* buf,
                       int level, int quadrant, uint32_t w, uint32_t h, uint32_t f,
-                      ENTROPY_CODER significand_bitstream [],
-                      ENTROPY_CODER insignificand_bitstream [])
+                      ENTROPY_CODER s_stream [],
+                      ENTROPY_CODER i_stream [])
 {
    uint32_t x, y, z;
 
-   for (z=0; z<f; z++) {
-      for (y=0; y<h; y++) {
-         for (x=0; x<w; x++) {
-            unsigned int index = buf->offset [level] [quadrant]
-                                   + z * buf->width * buf->height
-                                   + y * buf->width + x;
-
-            buf->data [index] = decode_coeff (significand_bitstream,
-                                              insignificand_bitstream);
-         }
-      }
-   }
+   z = 0;
+   do {
+      y = 0;
+      do {
+         x = 0;
+         do {
+            uint32_t skip;
+            uint32_t index = buf->offset [level] [quadrant]
+                               + z * buf->width * buf->height
+                               + y * buf->width + x;
+
+            buf->data [index] = decode_coeff (s_stream, i_stream);
+
+            skip = skip_0coeffs (buf, s_stream, i_stream,
+                                 (w-x-1)+(h-y-1)*w+(f-z-1)*w*h);
+            if (skip > 0) {
+               x += skip;
+               while (x >= w) {
+                  y++; x -= w;
+                  while (y >= h) {
+                     z++; y -= h;
+                     if (z >= f)
+                        return;
+                  }
+               }
+            } else
+               x++;
+         } while (x < w);
+         y++;
+      } while (y < h);
+      z++;
+   } while (z < f);
 }
 
 
@@ -175,36 +230,6 @@
 }
 
 
-static inline
-uint32_t skip_0coeffs (Wavelet3DBuf* buf,
-                       ENTROPY_CODER s_stream [],
-                       ENTROPY_CODER i_stream [],
-                       uint32_t start)
-{
-   int i;
-   uint32_t min = ~0;
-
-   for (i=0; i<10; i++) {
-      if (ENTROPY_CODER_MPS(&s_stream[i]) != 0) {
-         return 0;
-      } else {
-         uint32_t runlength = ENTROPY_CODER_RUNLENGTH(&s_stream[i]);
-
-         if (min > runlength)
-            min = runlength;
-      }
-   }
-
-   if (min > 0 && min != ~0) {
-min = 0;
-      for (i=0; i<10; i++) {
-         ENTROPY_CODER_SKIP(&s_stream[i], min);
-         ENTROPY_CODER_SKIP(&i_stream[i], min);
-      }
-   }
-
-   return min;
-}
 
 
 static
@@ -212,18 +237,19 @@
                           ENTROPY_CODER s_stream [],
                           ENTROPY_CODER i_stream [])
 {
-   uint32_t i;
+   uint32_t i = 0;
 
-   for (i=0; i<buf->width*buf->height*buf->frames; i++) {
-#if 0
-      int skip = skip_0coeffs (buf, s_stream, i_stream, i);
+   while (i < buf->width*buf->height*buf->frames) {
+      int skip;
 
-      if (skip >= buf->width*buf->height*buf->frames - i)
-         return;
-
-      i += skip;
-#endif
       buf->data[i] = decode_coeff(s_stream, i_stream);
+
+      skip = skip_0coeffs (buf, s_stream, i_stream,
+                           buf->width*buf->height*buf->frames - i);
+      if (skip > 0)
+         i += skip;
+      else
+         i++;
    }
 }
 #endif
@@ -436,8 +462,8 @@
    uint32_t insignificand_limittab [10];
    int i;
 
-   for (i=0; i<buf->width*buf->height*buf->frames; i++)
-      buf->data[i] = 0xff;
+   memset (buf->data, 0,
+           buf->width * buf->height * buf->frames * sizeof(TYPE));
 
    bitstream = read_limittabs (bitstream,
                                significand_limittab, insignificand_limittab);

1.1                  w3d/wavelet_coeff2.c

Index: wavelet_coeff2.c
===================================================================

#include <stdint.h>

#define width 0
#define height 0
#define GND 0 
#define SETCOEFF(x)
#define INPUT_8BIT(x) 0

static
void decode_8pixel (uint32_t x, uint32_t y, uint32_t z)
{
   uint8_t byte = INPUT_8BIT(x);
   uint32_t base;

   if (byte == 0)
      return;

   base = x + y * width + z * width * height;

   if (byte & 0x01)  SETCOEFF(base);
   if (byte & 0x02)  SETCOEFF(base+1);
   if (byte & 0x04)  SETCOEFF(base+width);
   if (byte & 0x08)  SETCOEFF(base+width+1);
   if (byte & 0x10)  SETCOEFF(base+width*height);
   if (byte & 0x20)  SETCOEFF(base+width*height+1);
   if (byte & 0x40)  SETCOEFF(base+width*height+width);
   if (byte & 0x80)  SETCOEFF(base+width*height+width+1);
}

#define DECODE_CHILD_CUBES(x,y,z,level)               \
   do {                                               \
      decode_cube (2*(x), 2*(y), 2*(z), level);       \
      decode_cube (2*(x)+1, 2*(y), 2*(z), level);     \
      decode_cube (2*(x), 2*(y)+1, 2*(z), level);     \
      decode_cube (2*(x), 2*(y), 2*(z)+1, level);     \
      decode_cube (2*(x)+1, 2*(y)+1, 2*(z), level);   \
      decode_cube (2*(x), 2*(y)+1, 2*(z)+1, level);   \
      decode_cube (2*(x)+1, 2*(y), 2*(z)+1, level);   \
      decode_cube (2*(x)+1, 2*(y)+1, 2*(z)+1, level); \
   } while (0)

static
void decode_cube (uint32_t x, uint32_t y, uint32_t z, uint32_t level)
{
   uint8_t byte = INPUT_8BIT(x);

   if (byte == 0)
      return;

   ++level;
   if (level == GND)
      decode_8pixel (x, y, z);

   if (byte & 0x01)  DECODE_CHILD_CUBES(x,y,z,level);
   if (byte & 0x02)  DECODE_CHILD_CUBES(x+1,y,z,level);
   if (byte & 0x04)  DECODE_CHILD_CUBES(x,y+1,z,level);
   if (byte & 0x08)  DECODE_CHILD_CUBES(x,y,z+1,level);
   if (byte & 0x10)  DECODE_CHILD_CUBES(x+1,y+1,z,level);
   if (byte & 0x20)  DECODE_CHILD_CUBES(x,y+1,z+1,level);
   if (byte & 0x40)  DECODE_CHILD_CUBES(x+1,y,z+1,level);
   if (byte & 0x80)  DECODE_CHILD_CUBES(x+1,y+1,z+1,level);
}

1.1                  w3d/zpcoder.c

Index: zpcoder.c
===================================================================
/**
 *   This file implements the ZPCoder, a very nice, fast and efficient binary
 *   entropy coder.
 * 
 *   It is a C++ to C port of AT&T's and  Lizardtech's DjVu sample
 *   implementation. The original sources were GPL'd, so Tarkin would have to
 *   get GPL'd too if we use it. This and some open patent issues are a real 
 *   problem for a compression codec. As soon we are sure we really want to
 *   use this entropy coder in Tarkin I'll contact Leon Bottou, the author
 *   of the original file to clear these questions.
 *
 *   Until then this file is provided for research and documentation purposes
 *   only. See the copyright notices on djvu.att.com and www.lizardtech.com
 *   for the original terms of distribution.
 */

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "zpcoder.h"
#include "bitcoder.h"

#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

typdef struct {
   unsigned short p;
   unsigned short m;
   BitContext up;
   BitContext dn;
} ZPCoderAdaptionTable;

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

static ZPCoderAdaptionTable 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
};

void zpcoder_init (ByteStream &bs, bool encoding, bool djvucompat)
{
   int i, j;

   // Create machine independent ffz table
   for (i=0; i<256; i++) {
      s->ffzt[i]=0;
      for (j=i; j&0x80; j<<=1)
         s->ffzt[i] += 1;
   }

   // Initialize table
   newtable (default_ztable);

   // Patch table table (and lose DjVu compatibility).
   if (!djvucompat) {
      for (j=0; j<256; j++) {
         unsigned short s->a = 0x10000 - s->p[j];

         while (s->a >= 0x8000)
            a = (unsigned short) (s->a << 1);

         if (s->m[j]>0 && s->a + s->p[j] >= 0x8000 && s->a >= s->m[j]) {
             BitContext x = default_ztable[j].dn;
             BitContext y = default_ztable[x].dn;
             s->dn[j] = y;
         }
      }
   }

   // Initialize encoder or decoder
   s->encoding = encoding;
   if (encoding) 
      zpcoder_einit (s);
   else
      zpcoder_dinit (s);
}

zpoder_done (ZPCoderState *s)
{
   if (s->encoding)
      zpcoder_eflush(s);
}

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

void zpcoder_dinit (ZPCoderState *s)
{
   s->a = 0;

   /* Read first 16 bits of code */
   if (! bs->read((void*)&s->byte, 1))
      s->byte = 0xff;
   s->code = (s->byte << 8);

   if (! bs->read((void*)&s->byte, 1))
      s->byte = 0xff;
   s->code = s->code | s->byte;

   /* Preload buffer */
   s->delay = 25;
   s->scount = 0;
   zpcoder_preload (s);

   /* Compute initial fence */
   s->fence = s->code;
   if (s->code >= 0x8000)
      s->fence = 0x7fff;
}

static
void zpcoder_preload (ZPCoderState *s)
{
   while (s->scount <= 24) {
      if (bs->read((void*)&s->byte, 1) < 1) {
         s->byte = 0xff;
         if (--s->delay < 1)
            G_THROW("EOF");
      }
      s->buffer = (s->buffer<<8) | s->byte;
      s->scount += 8;
   }
}

static inline
int zpcoder_ffz (ZPCoderState *s, uint32_t x)
{
   return (x >= 0xff00) ? (s->ffzt[x&0xff] + 8) : (s->ffzt[(x >> 8) & 0xff]);
}

int zpcoder_decode_sub(ZPCoderState *s, BitContext *ctx, uint32_t z)
{
   /* Save bit */
   int bit = (*ctx & 1);

   /* Avoid interval reversion */
#ifdef ZPCODER
   uint32_t 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 > s->code) {
      int shift;

      /* LPS branch */
      z = 0x10000 - z;
      s->a = a->a + z;
      s->code = s->code + z;

      /* LPS adaptation */
      *ctx = dn[*ctx];

      /* LPS renormalization */
      shift = ffz(s->a);
      s->scount -= shift;
      s->a = (uint16_t) (s->a << shift);
      s->code = (uint16_t) (s->code << shift) |
                            ((s->buffer >> s->scount) & ((1 << shift)-1));
      if (s->scount < 16)
         zpcoder_preload (s);

      /* Adjust fence */
      s->fence = s->code;
      if (s->code >= 0x8000)
         s->fence = 0x7fff;
      return bit ^ 1;
   } else {
      /* MPS adaptation */
      if (s->a >= m[*ctx])
         *ctx = up[*ctx];

      /* MPS renormalization */
      s->scount -= 1;
      s->a = (uint16_t) (z<<1);
      s->code = (uint16_t) (s->code<<1) | ((s->buffer >> s->scount) & 1);

      if (s->scount < 16)
         zpcoer_preload (s);

      /* Adjust fence */
      s->fence = s->code;
      if (s->code >= 0x8000)
         s->fence = 0x7fff;

      return bit;
   }
}

int zpcoder_decode_sub_simple (ZPCoderState *s, int mps, uint32_t z)
{
   /* Test MPS/LPS */
   if (z > s->code) {
      int shift;

      /* LPS branch */
      z = 0x10000 - z;
      s->a = s->a + z;
      s->code = s->code + z;

      /* LPS renormalization */
      shift = ffz (s->a);
      s->scount -= shift;
      s->a = (uint16_t) (s->a << shift);
      code = (uint16_t) (s->code << shift) |
                        ((s->buffer >> s->scount) & ((1 << shift)-1));

      if (s->scount < 16)
         zpcoder_preload (s);

      /* Adjust fence */
      s->fence = s->code;
      if (s->code >= 0x8000)
        s->fence = 0x7fff;

      return mps ^ 1;
   } else {
      /* MPS renormalization */
      s->scount -= 1;
      s->a = (uint16_t) (z << 1);
      code = (uint16_t) (s->code << 1) | ((buffer >> scount) & 1);
      if (s->scount < 16)
         zpcoder_preload (s);

      /* Adjust fence */
      s->fence = s->code;
      if (s->code >= 0x8000)
        s->fence = 0x7fff;

      return mps;
   }
}

int zpcoder_decode_sub_nolearn (ZPCoderState *s, int mps, uint32_t z)
{
#ifdef ZPCODER
   uint32_t d = 0x6000 + ((z + s->a) >> 2);
   if (z > d) 
      z = d;
#endif
#ifdef ZCODER
   if (z >= 0x8000)
      z = 0x4000 + (z>>1);
#endif

   /* Test MPS/LPS */
   if (z > s->code) {
      int shift;

      /* LPS branch */
      z = 0x10000 - z;
      s->a = s->a + z;
      s->code = s->code + z;

      /* LPS renormalization */
      shift = ffz(s->a);
      s->scount -= shift;
      s->a = (uint16_t) (s->a << shift);
      s->code = (uint16_t) (s->code << shift) |
                           ((s->buffer >> s->scount) & ((1 << shift)-1));
      if (s->scount < 16)
         zpcoder_preload (s);

      /* Adjust fence */
      s->fence = s->code;
      if (s->code >= 0x8000)
         s->fence = 0x7fff;

      return mps ^ 1;
   } else {
      /* MPS renormalization */
      s->scount -= 1;
      s->a = (uint16_t) (z << 1);
      code = (uint16_t) (s->code << 1) | ((s->buffer >> s->scount) & 1);
      if (scount < 16)
         zpcoder_preload (s);

      /* Adjust fence */
      s->fence = s->code;
      if (s->code >= 0x8000)
         s->fence = 0x7fff;

      return mps;
   }
}

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

void zpcoder_einit (ZPCoderState *s)
{
   s->a = 0;
   s->scount = 0;
   s->byte = 0;
   s->delay = 25;
   s->subend = 0;
   s->buffer = 0xffffff;
   s->nrun = 0;
}

static
void zpcoder_outbit (ZPCoderState *s, int bit)
{
   if (s->delay > 0) {
      if (s->delay < 0xff) // delay=0xff suspends emission forever
        s->delay -= 1;
   } else {
      /* Insert a bit */
      s->byte = (s->byte<<1) | bit;

      /* Output a byte */
      if (++s->scount == 8) {
         if (!s->encoding)
            G_THROW("ZPCodec.no_encoding");
         if (bs->write((void*)&s->byte, 1) != 1)
            G_THROW("ZPCodec.write_error");
         s->scount = 0;
         s->byte = 0;
      }
   }
}

void zpcoder_zemit (ZPCoderState *s, int b)
{
  /* Shift new bit into 3bytes buffer */
   s->buffer = (s->buffer << 1) + b;

  /* Examine bit going out of the 3bytes buffer */
   b = (s->buffer >> 24);
   s->buffer = (s->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) {
   case 1:                   /* Similar to WN&C upper renormalization */
      zpcoder_outbit(s, 1);
      while (s->nrun-- > 0)
         zpcoder_outbit(s, 0);
      s->nrun = 0;
      break;
   case 0xff:                /* Similar to WN&C lower renormalization */
      zpcoder_outbit(s, 0);
      while (s->nrun-- > 0)
         zpcoder_outbit(s, 1);
      s->nrun = 0;
      break;
   case 0:                   /* Similar to WN&C central renormalization */
      s->nrun += 1;
      break;
   }
}

void zpcoder_eflush (ZPCoderState *s)
{
   /* adjust subend */
   if (s->subend > 0x8000)
      s->subend = 0x10000;
   else if (s->subend > 0)
      s->subend = 0x8000;

   /* zemit many mps bits */
   while (s->buffer != 0xffffff  || s->subend ) {
      zemit(1 - (s->subend >> 15) );
      s->subend = (uint16_t) (s->subend << 1);
   }

   /* zemit pending run */
   zpcoder_outbit(s, 1);
   while (s->nrun-- > 0)
      zpcoder_outbit(s, 0);
   nrun = 0;

   /* zemit 1 until full byte */
   while (s->scount > 0)
      zpcoder_outbit(s, 1);

   /* prevent further emission */
   s->delay = 0xff;
}

void zpcoder_encode_mps (ZPCoderState *s, BitContext *ctx, uint32_t z)
{
   /* Avoid interval reversion */
#ifdef ZPCODER
   uint32_t d = 0x6000 + ((z + s->a) >> 2);
   if (z > d) 
      z = d;
#endif
#ifdef ZCODER
   if (z >= 0x8000)
      z = 0x4000 + (z >> 1);
#endif
   /* Adaptation */
   if (s->a >= s->m[*ctx])
      *ctx = s->up[*ctx];

   /* Code MPS */
   s->a = z;

   /* Export bits */
   if (s->a >= 0x8000) {
      zemit(1 - (s->subend >> 15) );
      subend = (uint16_t) (s->subend << 1);
      s->a = (uint16_t) (s->a << 1);
   }
}

void zpcoder_encode_lps (ZPCoderState *s, BitContext *ctx, uint32_t z)
{
   /* Avoid interval reversion */
#ifdef ZPCODER
   uint32_t d = 0x6000 + ((z + s->a) >> 2);
   if (z > d) 
      z = d;
#endif
#ifdef ZCODER
   if (z >= 0x8000)
      z = 0x4000 + (z >> 1);
#endif

   /* Adaptation */
   *ctx = s->dn[*ctx];

   /* Code LPS */
   z = 0x10000 - z;
   s->subend += z;
   s->a += z;

   /* Export bits */
   while (s->a >= 0x8000) {
      zemit(1 - (s->subend >> 15) );
      subend = (uint16_t) (s->subend<<1);
      s->a = (uint16_t) (s->a << 1);
   }
}

void zpcoder_encode_mps_simple (ZPCoderState *s, uint32_t z)
{
   /* Code MPS */
   s->a = z;

   /* Export bits */
   if (s->a >= 0x8000) {
      zemit(1 - (s->subend >> 15) );
      s->subend = (uint16_t) (s->subend << 1);
      s->a = (uint16_t) (a << 1);
   }
}

void zpcoder_encode_lps_simple (ZPCoderState *s, uint32_t z)
{
   /* Code LPS */
   z = 0x10000 - z;
   s->subend += z;
   s->a += z;

   /* Export bits */
   while (s->a >= 0x8000) {
      zemit(1 - (s->subend >> 15));
      subend = (uint16_t) (s->subend << 1);
      s->a = (uint16_t) (s->a << 1);
   }
}

void zpcoder_encode_mps_nolearn (ZPCoderState *s, uint32_t z)
{
#ifdef ZPCODER
   uint32_t d = 0x6000 + ((z + s->a) >> 2);
   if (z > d) 
      z = d;
#endif
#ifdef ZCODER
   if (z >= 0x8000)
      z = 0x4000 + (z>>1);
#endif

   /* Code MPS */
   s->a = z;

   /* Export bits */
   if (a >= 0x8000) {
      zemit(1 - (s->subend >> 15));
      subend = (uint16_t) (s->subend << 1);
      s->a = (uint16_t) (s->a << 1);
   }
}

void zpcoder_encode_lps_nolearn (ZPCoderState *s, uint32_t z)
{
#ifdef ZPCODER
   uint32_t d = 0x6000 + ((z + s->a) >> 2);
   if (z > d) 
      z = d;
#endif
#ifdef ZCODER
   if (z >= 0x8000)
      z = 0x4000 + (z>>1);
#endif

   /* Code LPS */
   z = 0x10000 - z;
   s->subend += z;
   s->a += z;

   /* Export bits */
   while (s->a >= 0x8000) {
      zemit(1 - (s->subend >> 15) );
      subend = (unsigned short) (s->subend << 1);
      s->a = (unsigned short) (s->a << 1);
   }
}

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

static
void newtable (ZPCoderState *s, ZPCoderAdaptionTable *table)
{
   int i;

   for (i=0; i<256; i++) {
      s->p[i]  = table[i].p;
      s->m[i]  = table[i].m;
      s->up[i] = table[i].up;
      s->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;
}

#if 0
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;
}
#endif

1.1                  w3d/zpcoder.h

Index: zpcoder.h
===================================================================
/**
 *   This file implements the ZPCoder, a very nice, fast and efficient binary
 *   entropy coder.
 *
 *   It is a C++ to C port of AT&T's and  Lizardtech's DjVu sample
 *   implementation. The original sources were GPL'd, so Tarkin would have to
 *   get GPL'd too if we use it. This and some open patent issues are a real
 *   problem for a compression codec. As soon we are sure we really want to
 *   use this entropy coder in Tarkin I'll contact Leon Bottou, the author
 *   of the original file to clear these questions.
 *
 *   Until then this file is provided for research and documentation purposes
 *   only. See the copyright notices on djvu.att.com and www.lizardtech.com
 *   for the original terms of distribution.
 */

#ifndef __ZPCODER_H
#define __ZPCODER_H

#include <stdint.h>
#include "bitcoder.h"

typedef uint8_t BitContext;

typedef struct {
   BitCoderState bitcoder;
   int encoding;                // Direction (0=decoding, 1=encoding)
   uint8_t byte;
   uint8_t scount;
   uint8_t delay;
   uint32_t a;
   uint32_t code;
   uint32_t fence;
   uint32_t subend;
   uint32_t buffer;
   uint32_t nrun;
   uint32_t p[256];
   uint32_t m[256];
   BitContext up[256];
   BitContext dn[256];
   int8_t ffzt[256];
} ZPCoderState;

static inline 
void zpcoder_encoder (ZPCoderState *s, int bit, BitContext *ctx) 
{
  uint32_t z = s->a + s->p[*ctx];

  if (bit != (*ctx & 1))
    encode_lps (s, ctx, z);
  else if (z >= 0x8000)
    encode_mps (s, ctx, z);
  else
    a = z;
}

static inline 
int zpcoder_IWdecoder (ZPCoderState *s)
{
  return decode_sub_simple (s, 0, 0x8000 + ((s->a + s->a + s->a) >> 3));
}

static inline
int zpcoder_decoder (ZPCoderState *s, BitContext *ctx)
{
   uint32_t z = s->a + s->p[*ctx];

   if (z <= s->fence) { 
      s->a = z;
      return (*ctx & 1);
   } 

   return decode_sub (s, ctx, z);
}

static inline
void zpcoder_encoder_nolearn (ZPCoderState *s, int bit, BitContext *ctx) 
{
   uint32_t z = s->a + s->p[*ctx];

   if (bit != (*ctx & 1))
      encode_lps_nolearn (s, z);
   else if (z >= 0x8000)
      encode_mps_nolearn (s, z);
   else
      s->a = z;
}

 
static inline
int zpcoder_decoder_nolearn (ZPCoderState *s, BitContext *ctx)
{
   uint32_t z = s->a + s->p[*ctx];

   if (z <= s->fence) {
      s->a = z;
      return (*ctx & 1);
   }

   return decode_sub_nolearn (s, *ctx & 1, z);
}

static inline
void zpcoder_encoder (ZPCoderState *s, int bit)
{
  if (bit)
    encode_lps_simple (s, 0x8000 + (s->a >> 1));
  else 
    encode_mps_simple (s, 0x8000 + (s->a >> 1));
}

static inline
int zpcoder_decoder (ZPCoderState *s)
{
  return decode_sub_simple (s, 0, 0x8000 + (s->a >> 1));
}

static inline
void zpcoder_IWencoder (ZPCoderState *s, const bool bit)
{
  const uint32_t z = 0x8000 + ((s->a + s->a + s->a) >> 3);

  if (bit)
    encode_lps_simple (s, z);
  else
    encode_mps_simple (s, z);
}

#endif

--- >8 ----
List archives:  http://www.xiph.org/archives/
Ogg project homepage: http://www.xiph.org/ogg/
To unsubscribe from this list, send a message to 'cvs-request at xiph.org'
containing only the word 'unsubscribe' in the body.  No subject is needed.
Unsubscribe messages sent to the list will be ignored/filtered.



More information about the commits mailing list