corrade-vassal – Rev 1

Subversion Repositories:
Rev:
/*
* CVS identifier:
*
* $Id: MQDecoder.java,v 1.32 2001/10/17 16:58:00 grosbois Exp $
*
* Class:                   MQDecoder
*
* Description:             Class that encodes a number of bits using the
*                          MQ arithmetic decoder
*
*
*
* COPYRIGHT:
* 
* This software module was originally developed by Raphaël Grosbois and
* Diego Santa Cruz (Swiss Federal Institute of Technology-EPFL); Joel
* Askelöf (Ericsson Radio Systems AB); and Bertrand Berthelot, David
* Bouchard, Félix Henry, Gerard Mozelle and Patrice Onno (Canon Research
* Centre France S.A) in the course of development of the JPEG2000
* standard as specified by ISO/IEC 15444 (JPEG 2000 Standard). This
* software module is an implementation of a part of the JPEG 2000
* Standard. Swiss Federal Institute of Technology-EPFL, Ericsson Radio
* Systems AB and Canon Research Centre France S.A (collectively JJ2000
* Partners) agree not to assert against ISO/IEC and users of the JPEG
* 2000 Standard (Users) any of their rights under the copyright, not
* including other intellectual property rights, for this software module
* with respect to the usage by ISO/IEC and Users of this software module
* or modifications thereof for use in hardware or software products
* claiming conformance to the JPEG 2000 Standard. Those intending to use
* this software module in hardware or software products are advised that
* their use may infringe existing patents. The original developers of
* this software module, JJ2000 Partners and ISO/IEC assume no liability
* for use of this software module or modifications thereof. No license
* or right to this software module is granted for non JPEG 2000 Standard
* conforming products. JJ2000 Partners have full right to use this
* software module for his/her own purpose, assign or donate this
* software module to any third party and to inhibit third parties from
* using this software module for non JPEG 2000 Standard conforming
* products. This copyright notice must be included in all copies or
* derivative works of this software module.
* 
* Copyright (c) 1999/2000 JJ2000 Partners.
* */
using System;
using CSJ2K.j2k.entropy.decoder;
using CSJ2K.j2k.entropy;
using CSJ2K.j2k.io;
using CSJ2K.j2k.util;
namespace CSJ2K.j2k.entropy.decoder
{
        
        /// <summary> This class implements the MQ arithmetic decoder. It is implemented using
        /// the software conventions decoder for better performance (i.e. execution
        /// time performance). The initial states for each context of the MQ-coder are
        /// specified in the constructor.
        /// 
        /// </summary>
        
        // A trick to test for increased speed: merge the Qe and mPS into 1 thing by
        // using the sign bit of Qe to signal mPS (positive-or-0 is 0, negative is 1),
        // and doubling the Qe, nMPS and nLPS tables. This gets rid of the swicthLM
        // table since it can be integrated as special cases in the doubled nMPS and
        // nLPS tables. See the JPEG book, chapter 13. The decoded decision can be
        // calculated as (q>>>31).
        
        public class MQDecoder
        {
                /// <summary> Returns the number of contexts in the arithmetic coder.
                /// 
                /// </summary>
                /// <returns> The number of contexts
                /// 
                /// </returns>
                virtual public int NumCtxts
                {
                        get
                        {
                                return I.Length;
                        }
                        
                }
                /// <summary> Returns the underlying 'ByteInputBuffer' from where the MQ coded input
                /// bytes are read.
                /// 
                /// </summary>
                /// <returns> The underlying ByteInputBuffer.
                /// 
                /// </returns>
                virtual public ByteInputBuffer ByteInputBuffer
                {
                        get
                        {
                                return in_Renamed;
                        }
                        
                }
                
                /// <summary>The data structures containing the probabilities for the LPS </summary>
                //UPGRADE_NOTE: Final was removed from the declaration of 'qe'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
                internal static readonly uint[] qe = new uint[]{0x5601, 0x3401, 0x1801, 0x0ac1, 0x0521, 0x0221, 0x5601, 0x5401, 0x4801, 0x3801, 0x3001, 0x2401, 0x1c01, 0x1601, 0x5601, 0x5401, 0x5101, 0x4801, 0x3801, 0x3401, 0x3001, 0x2801, 0x2401, 0x2201, 0x1c01, 0x1801, 0x1601, 0x1401, 0x1201, 0x1101, 0x0ac1, 0x09c1, 0x08a1, 0x0521, 0x0441, 0x02a1, 0x0221, 0x0141, 0x0111, 0x0085, 0x0049, 0x0025, 0x0015, 0x0009, 0x0005, 0x0001, 0x5601};
                
                /// <summary>The indexes of the next MPS </summary>
                //UPGRADE_NOTE: Final was removed from the declaration of 'nMPS'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
                internal static readonly int[] nMPS = new int[]{1, 2, 3, 4, 5, 38, 7, 8, 9, 10, 11, 12, 13, 29, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 45, 46};
                
                /// <summary>The indexes of the next LPS </summary>
                //UPGRADE_NOTE: Final was removed from the declaration of 'nLPS'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
                internal static readonly int[] nLPS = new int[]{1, 6, 9, 12, 29, 33, 6, 14, 14, 14, 17, 18, 20, 21, 14, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 46};
                
                /// <summary>Whether LPS and MPS should be switched </summary>
                //UPGRADE_NOTE: Final was removed from the declaration of 'switchLM'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
                internal static readonly int[] switchLM = new int[]{1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
                
                /// <summary>The ByteInputBuffer used to read the compressed bit stream. </summary>
                internal ByteInputBuffer in_Renamed;
                
                /// <summary>The current most probable signal for each context </summary>
                internal int[] mPS;
                
                /// <summary>The current index of each context </summary>
                internal int[] I;
                
                /// <summary>The current bit code </summary>
                internal uint c;
                
                /// <summary>The bit code counter </summary>
                internal uint cT;
                
                /// <summary>The current interval </summary>
                internal uint a;
                
                /// <summary>The last byte read </summary>
                internal uint b;
                
                /// <summary>Flag indicating if a marker has been found </summary>
                internal bool markerFound;
                
                /// <summary>The initial state of each context </summary>
                //UPGRADE_NOTE: Final was removed from the declaration of 'initStates '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"
                internal int[] initStates;
                
                /// <summary> Instantiates a new MQ-decoder, with the specified number of contexts
                /// and initial states. The compressed bytestream is read from the
                /// 'iStream' object.
                /// 
                /// </summary>
                /// <param name="iStream">the stream that contains the coded bits 
                /// 
                /// </param>
                /// <param name="nrOfContexts">The number of contexts used
                /// 
                /// </param>
                /// <param name="initStates">The initial state for each context. A reference is
                /// kept to this array to reinitialize the contexts whenever 'reset()' or
                /// 'resetCtxts()' is called.
                /// 
                /// </param>
                public MQDecoder(ByteInputBuffer iStream, int nrOfContexts, int[] initStates)
                {
                        in_Renamed = iStream;
                        
                        // Default initialization of the statistics bins is MPS=0 and
                        // I=0
                        I = new int[nrOfContexts];
                        mPS = new int[nrOfContexts];
                        // Save the initial states
                        this.initStates = initStates;
                        
                        // Initialize
                        init();
                        
                        // Set the contexts
                        resetCtxts();
                }
                
                /// <summary> Decodes 'n' symbols from the bit stream using the same context
                /// 'ctxt'. If possible the MQ-coder speedup mode will be used to speed up
                /// decoding. The speedup mode is used if Q (the LPS probability for 'ctxt'
                /// is low enough) and the A and C registers permit decoding several MPS
                /// symbols without renormalization.
                /// 
                /// <P>Speedup mode should be used when decoding long runs of MPS with high
                /// probability with the same context.
                /// 
                /// <P>This methiod will return the decoded symbols differently if speedup 
                /// mode was used or not. If true is returned, then speedup mode was used
                /// and the 'n' decoded symbols are all the same and it is returned ain
                /// bits[0] only. If false is returned then speedup mode was not used, the
                /// decoded symbols are probably not all the same and they are returned in
                /// bits[0], bits[1], ... bits[n-1].
                /// 
                /// </summary>
                /// <param name="bits">The array where to put the decoded symbols. Must be of
                /// length 'n' or more.
                /// 
                /// </param>
                /// <param name="ctxt">The context to use in decoding the symbols.
                /// 
                /// </param>
                /// <param name="n">The number of symbols to decode.
                /// 
                /// </param>
                /// <returns> True if speedup mode was used, false if not. If speedup mode
                /// was used then all the decoded symbols are the same and its value is
                /// returned in 'bits[0]' only (not in bits[1], bits[2], etc.).
                /// 
                /// </returns>
                internal bool fastDecodeSymbols(int[] bits, int ctxt, uint n)
                {
                        uint q; // LPS probability for context
                        int idx; // Index of current state
                        uint la; // cache for A register
                        int i; // counter
                        
                        idx = I[ctxt];
                        q = qe[idx];
                        
                        // This is a first attempt to implement speedup mode, it is probably
                        // not the most efficient way of doing it.
                        
                        if ((q < 0x4000) && (n <= (a - (c >> 16) - 1) / q) && (n <= (a - 0x8000) / q + 1))
                        {
                                // Q is small enough. There will be no modification of C that
                                // affects decoding, and Q can be substracted from A several
                                // times. We will decode all MPS.
                                a -= n * q;
                                if (a >= 0x8000)
                                {
                                        // No renormalization needed
                                        bits[0] = mPS[ctxt];
                                        return true; // Done, used speedup mode
                                }
                                else
                                {
                                        // renormalization needed
                                        I[ctxt] = nMPS[idx];
                                        // Renormalize (MPS: no need for while loop)
                                        if (cT == 0)
                                                byteIn();
                                        a <<= 1;
                                        c <<= 1;
                                        cT--;
                                        // End renormalization
                                        bits[0] = mPS[ctxt];
                                        return true; // Done, used speedup mode
                                }
                        }
                        else
                        {
                                // Normal mode
                                la = a; // cache A register
                                for (i = 0; i < n; i++)
                                {
                                        la -= q;
                                        if ((c >> 16) < la)
                                        {
                                                if (la >= 0x8000)
                                                {
                                                        bits[i] = mPS[ctxt];
                                                }
                                                else
                                                {
                                                        // -- MPS Exchange
                                                        if (la >= q)
                                                        {
                                                                bits[i] = mPS[ctxt];
                                                                idx = nMPS[idx];
                                                                q = qe[idx];
                                                                // I[ctxt] set at end of loop
                                                                // -- Renormalize (MPS: no need for while loop)
                                                                if (cT == 0)
                                                                        byteIn();
                                                                la <<= 1;
                                                                c <<= 1;
                                                                cT--;
                                                                // -- End renormalization
                                                        }
                                                        else
                                                        {
                                                                bits[i] = 1 - mPS[ctxt];
                                                                if (switchLM[idx] == 1)
                                                                        mPS[ctxt] = 1 - mPS[ctxt];
                                                                idx = nLPS[idx];
                                                                q = qe[idx];
                                                                // I[ctxt] set at end of loop
                                                                // -- Renormalize
                                                                do 
                                                                {
                                                                        if (cT == 0)
                                                                                byteIn();
                                                                        la <<= 1;
                                                                        c <<= 1;
                                                                        cT--;
                                                                }
                                                                while (la < 0x8000);
                                                                // -- End renormalization
                                                        }
                                                        // -- End MPS Exchange
                                                }
                                        }
                                        else
                                        {
                                                c -= (la << 16);
                                                // -- LPS Exchange
                                                if (la < q)
                                                {
                                                        la = q;
                                                        bits[i] = mPS[ctxt];
                                                        idx = nMPS[idx];
                                                        q = qe[idx];
                                                        // I[ctxt] set at end of loop
                                                        // -- Renormalize (MPS: no need for while loop)
                                                        if (cT == 0)
                                                                byteIn();
                                                        la <<= 1;
                                                        c <<= 1;
                                                        cT--;
                                                        // -- End renormalization
                                                }
                                                else
                                                {
                                                        la = q;
                                                        bits[i] = 1 - mPS[ctxt];
                                                        if (switchLM[idx] == 1)
                                                                mPS[ctxt] = 1 - mPS[ctxt];
                                                        idx = nLPS[idx];
                                                        q = qe[idx];
                                                        // I[ctxt] set at end of loop
                                                        // -- Renormalize
                                                        do 
                                                        {
                                                                if (cT == 0)
                                                                        byteIn();
                                                                la <<= 1;
                                                                c <<= 1;
                                                                cT--;
                                                        }
                                                        while (la < 0x8000);
                                                        // -- End renormalization
                                                }
                                                // -- End LPS Exchange
                                        }
                                }
                                a = la; // save cached A register
                                I[ctxt] = idx; // save current index for context
                                return false; // done, did not use speedup mode
                        } // End normal mode
                }
                
                /// <summary> This function performs the arithmetic decoding. The function receives 
                /// an array in which to put the decoded symbols and an array of contexts 
                /// with which to decode them. 
                /// 
                /// <P>Each context has a current MPS and an index describing what the
                /// current probability is for the LPS. Each bit is decoded and if the
                /// probability of the LPS exceeds .5, the MPS and LPS are switched.
                /// 
                /// </summary>
                /// <param name="bits">The array where to place the decoded symbols. It should be
                /// long enough to contain 'n' elements.
                /// 
                /// </param>
                /// <param name="cX">The context to use in decoding each symbol.
                /// 
                /// </param>
                /// <param name="n">The number of symbols to decode
                /// 
                /// </param>
                public void  decodeSymbols(int[] bits, int[] cX, int n)
                {
                        uint q;
                        int ctxt;
                        uint la; // cache for A register value
                        int index;
                        int i;
                        
                        // NOTE: (a < 0x8000) is equivalent to ((a & 0x8000)==0)
                        // since 'a' is always less than or equal to 0xFFFF
                        
                        // NOTE: conditional exchange guarantees that A for MPS is
                        // always greater than 0x4000 (i.e. 0.375)
                        // => one renormalization shift is enough for MPS
                        // => no need to do a renormalization while loop for MPS
                        
                        for (i = 0; i < n; i++)
                        {
                                ctxt = cX[i];
                                
                                index = I[ctxt];
                                q = qe[index];
                                
                                a -= q;
                                if ((c >> 16) < a)
                                {
                                        if (a >= 0x8000)
                                        {
                                                bits[i] = mPS[ctxt];
                                        }
                                        else
                                        {
                                                la = a;
                                                // -- MPS Exchange
                                                if (la >= q)
                                                {
                                                        bits[i] = mPS[ctxt];
                                                        I[ctxt] = nMPS[index];
                                                        // -- Renormalize (MPS: no need for while loop)
                                                        if (cT == 0)
                                                                byteIn();
                                                        la <<= 1;
                                                        c <<= 1;
                                                        cT--;
                                                        // -- End renormalization
                                                }
                                                else
                                                {
                                                        bits[i] = 1 - mPS[ctxt];
                                                        if (switchLM[index] == 1)
                                                                mPS[ctxt] = 1 - mPS[ctxt];
                                                        I[ctxt] = nLPS[index];
                                                        // -- Renormalize
                                                        do 
                                                        {
                                                                if (cT == 0)
                                                                        byteIn();
                                                                la <<= 1;
                                                                c <<= 1;
                                                                cT--;
                                                        }
                                                        while (la < 0x8000);
                                                        // -- End renormalization
                                                }
                                                // -- End MPS Exchange
                                                a = la;
                                        }
                                }
                                else
                                {
                                        la = a;
                                        c -= (la << 16);
                                        // -- LPS Exchange
                                        if (la < q)
                                        {
                                                la = q;
                                                bits[i] = mPS[ctxt];
                                                I[ctxt] = nMPS[index];
                                                // -- Renormalize (MPS: no need for while loop)
                                                if (cT == 0)
                                                        byteIn();
                                                la <<= 1;
                                                c <<= 1;
                                                cT--;
                                                // -- End renormalization
                                        }
                                        else
                                        {
                                                la = q;
                                                bits[i] = 1 - mPS[ctxt];
                                                if (switchLM[index] == 1)
                                                        mPS[ctxt] = 1 - mPS[ctxt];
                                                I[ctxt] = nLPS[index];
                                                // -- Renormalize
                                                do 
                                                {
                                                        if (cT == 0)
                                                                byteIn();
                                                        la <<= 1;
                                                        c <<= 1;
                                                        cT--;
                                                }
                                                while (la < 0x8000);
                                                // -- End renormalization
                                        }
                                        // -- End LPS Exchange
                                        
                                        a = la;
                                }
                        }
                }
                
                
                /// <summary> Arithmetically decodes one symbol from the bit stream with the given
                /// context and returns its decoded value.
                /// 
                /// <P>Each context has a current MPS and an index describing what the
                /// current probability is for the LPS. Each bit is encoded and if the
                /// probability of the LPS exceeds .5, the MPS and LPS are switched.
                /// 
                /// </summary>
                /// <param name="context">The context to use in decoding the symbol
                /// 
                /// </param>
                /// <returns> The decoded symbol, 0 or 1.
                /// 
                /// </returns>
                public int decodeSymbol(int context)
                {
                        uint q;
                        uint la;
                        int index;
                        int decision;
                        
                        index = I[context];
                        q = qe[index];
                        
                        // NOTE: (a < 0x8000) is equivalent to ((a & 0x8000)==0)
                        // since 'a' is always less than or equal to 0xFFFF
                        
                        // NOTE: conditional exchange guarantees that A for MPS is
                        // always greater than 0x4000 (i.e. 0.375)
                        // => one renormalization shift is enough for MPS
                        // => no need to do a renormalization while loop for MPS
                        
                        a -= q;
            if ((c >> 16) < a)
                        {
                                if (a >= 0x8000)
                                {
                                        decision = mPS[context];
                                }
                                else
                                {
                                        la = a;
                                        // -- MPS Exchange
                                        if (la >= q)
                                        {
                                                decision = mPS[context];
                                                I[context] = nMPS[index];
                                                // -- Renormalize (MPS: no need for while loop)
                                                if (cT == 0)
                                                        byteIn();
                                                la <<= 1;
                                                c <<= 1;
                                                cT--;
                                                // -- End renormalization
                                        }
                                        else
                                        {
                                                decision = 1 - mPS[context];
                                                if (switchLM[index] == 1)
                                                        mPS[context] = 1 - mPS[context];
                                                I[context] = nLPS[index];
                                                // -- Renormalize
                                                do 
                                                {
                                                        if (cT == 0)
                                                                byteIn();
                                                        la <<= 1;
                                                        c <<= 1;
                                                        cT--;
                                                }
                                                while (la < 0x8000);
                                                // -- End renormalization
                                        }
                                        // -- End MPS Exchange
                                        a = la;
                                }
                        }
                        else
                        {
                                la = a;
                                c -= (la << 16);
                                // -- LPS Exchange
                                if (la < q)
                                {
                                        la = q;
                                        decision = mPS[context];
                                        I[context] = nMPS[index];
                                        // -- Renormalize (MPS: no need for while loop)
                                        if (cT == 0)
                                                byteIn();
                                        la <<= 1;
                                        c <<= 1;
                                        cT--;
                                        // -- End renormalization
                                }
                                else
                                {
                                        la = q;
                                        decision = 1 - mPS[context];
                                        if (switchLM[index] == 1)
                                                mPS[context] = 1 - mPS[context];
                                        I[context] = nLPS[index];
                                        // -- Renormalize
                                        do 
                                        {
                                                if (cT == 0)
                                                        byteIn();
                                                la <<= 1;
                                                c <<= 1;
                                                cT--;
                                        }
                                        while (la < 0x8000);
                                        // -- End renormalization
                                }
                                // -- End LPS Exchange
                                
                                a = la;
                        }
                        return decision;
                }
                
                /// <summary> Checks for past errors in the decoding process using the predictable
                /// error resilient termination. This works only if the encoder used the
                /// predictable error resilient MQ termination, otherwise it reports wrong
                /// results. If an error is detected it means that the MQ bit stream has
                /// been wrongly decoded or that the MQ terminated segment length is too
                /// long. If no errors are detected it does not necessarily mean that the
                /// MQ bit stream has been correctly decoded.
                /// 
                /// </summary>
                /// <returns> True if errors are found, false otherwise.
                /// 
                /// </returns>
                public virtual bool checkPredTerm()
                {
                        int k; // Number of bits that where added in the termination process
                        uint q;
                        
                        // 1) if everything has been OK, 'b' must be 0xFF if a terminating
                        // marker has not yet been found
                        if (b != 0xFF && !markerFound)
                                return true;
                        
                        // 2) if cT is not 0, we must have already reached the terminating
                        // marker
                        if (cT != 0 && !markerFound)
                                return true;
                        
                        // 3) If cT is 1 there where no spare bits at the encoder, this is all
                        // that we can check
                        if (cT == 1)
                                return false;
                        
                        // 4) if cT is 0, then next byte must be the second byte of a
                        // terminating marker (i.e. larger than 0x8F) if the terminating
                        // marker has not been reached yet
                        if (cT == 0)
                        {
                                if (!markerFound)
                                {
                                        // Get next byte and check
                                        b = (uint)in_Renamed.read() & 0xFF;
                                        if (b <= 0x8F)
                                                return true;
                                }
                                // Adjust cT for last byte
                                cT = 8;
                        }
                        
                        // 5) Now we can calculate the number 'k' of bits having error
                        // resilience information, which is the number of bits left to
                        // normalization in the C register, minus 1.
                        k = (int)(cT - 1);
                        
                        // 6) The predictable termination policy is as if an LPS interval was
                        // coded that caused a renormalization of 'k' bits, before the
                        // termination marker started
                        
                        // We first check if an LPS is decoded, that causes a renormalization
                        // of 'k' bits. Worst case is smallest LPS probability 'q' that causes
                        // a renormalization of 'k' bits.
                        q = ((uint)0x8000) >> k;
                        
                        // Check that we can decode an LPS interval of probability 'q'
                        a -= q;
                        if ((c >> 16) < a)
                        {
                                // Error: MPS interval decoded
                                return true;
                        }
                        // OK: LPS interval decoded
                        c -= (a << 16);
                        // -- LPS Exchange
                        // Here 'a' can not be smaller than 'q' because the minimum value
                        // for 'a' is 0x8000-0x4000=0x4000 and 'q' is set to a value equal
                        // to or smaller than that.
                        a = q;
                        // -- Renormalize
                        do 
                        {
                                if (cT == 0)
                                        byteIn();
                                a <<= 1;
                                c <<= 1;
                                cT--;
                        }
                        while (a < 0x8000);
                        // -- End renormalization
                        // -- End LPS Exchange
                        
                        // 7) Everything seems OK, we have checked the C register for the LPS
                        // symbols and ensured that it is followed by bits synthetized by the
                        // termination marker.
                        return false;
                }
                
                /// <summary> This function gets one byte of compressed bits from the in-stream.  the
                /// byte is added to c. If the byte is 0xFF and the next byte is greater
                /// than 0x8F, the byte after 0xFF is a marker.
                /// 
                /// </summary>
                private void  byteIn()
                {
                        if (!markerFound)
                        {
                                if (b == 0xFF)
                                {
                                        b = ((uint)in_Renamed.read()) & 0xFF; // Convert EOFs (-1) to 0xFF
                                        
                                        if (b > 0x8F)
                                        {
                                                markerFound = true;
                                                // software-convention decoder: c unchanged
                                                cT = 8;
                                        }
                                        else
                                        {
                                                c += 0xFE00 - (b << 9);
                                                cT = 7;
                                        }
                                }
                                else
                                {
                                        b = ((uint)in_Renamed.read()) & 0xFF; // Convert EOFs (-1) to 0xFF
                                        c += 0xFF00 - (b << 8);
                                        cT = 8;
                                }
                        }
                        else
                        {
                                // software-convention decoder: c unchanged
                                cT = 8;
                        }
                }
                
                /// <summary> Resets a context to the original probability distribution.
                /// 
                /// </summary>
                /// <param name="c">The number of the context (it starts at 0).
                /// 
                /// </param>
                public void  resetCtxt(int c)
                {
                        I[c] = initStates[c];
                        mPS[c] = 0;
                }
                
                /// <summary> Resets a context to the original probability distribution. The original
                /// probability distribution depends on the actual implementation of the
                /// arithmetic coder or decoder.
                /// 
                /// </summary>
                /// <param name="c">The index of the context (it starts at 0).
                /// 
                /// </param>
                public void  resetCtxts()
                {
                        Array.Copy(initStates, 0, I, 0, I.Length);
                        ArrayUtil.intArraySet(mPS, 0);
                }
                
                /// <summary> Resets the MQ decoder to start a new segment. This is like recreating a
                /// new MQDecoder object with new input data.
                /// 
                /// </summary>
                /// <param name="buf">The byte array containing the MQ encoded data. If null the
                /// current byte array is assumed.
                /// 
                /// </param>
                /// <param name="off">The index of the first element in 'buf' to be decoded. If
                /// negative the byte just after the previous segment is assumed, only
                /// valid if 'buf' is null.
                /// 
                /// </param>
                /// <param name="len">The number of bytes in 'buf' to be decoded. Any subsequent
                /// bytes are taken to be 0xFF.
                /// 
                /// </param>
                public void  nextSegment(byte[] buf, int off, int len)
                {
                        // Set the new input
                        in_Renamed.setByteArray(buf, off, len);
                        // Reinitialize MQ
                        init();
                }
                
                /// <summary> Initializes the state of the MQ coder, without modifying the current
                /// context states. It sets the registers (A,C,B) and the "marker found"
                /// state to the initial state, to start the decoding of a new segment.
                /// 
                /// <P>To have a complete reset of the MQ (as if a new MQDecoder object was
                /// created) 'resetCtxts()' should be called after this method.
                /// 
                /// </summary>
                private void  init()
                {
                        // --- INITDEC
                        markerFound = false;
                        
                        // Read first byte
                        b = ((uint)in_Renamed.read()) & 0xFF;
                        
                        // Software conventions decoder
                        c = (b ^ 0xFF) << 16;
                        byteIn();
                        c = c << 7;
                        cT = cT - 7;
                        a = 0x8000;
                        
                        // End of INITDEC ---
                }
        }
}

Generated by GNU Enscript 1.6.5.90.