void ACSequentialScan::EncodeBlock(const LONG *block,
                                   LONG &prevdc,LONG &prevdiff,
                                   UBYTE small,UBYTE large,UBYTE kx,UBYTE dc,UBYTE ac)
{
  // DC coding
  if (m_ucScanStart == 0 && m_bResidual == false) {
    struct QMContextSet::DCContextZeroSet &cz = m_Context[dc].Classify(prevdiff,small,large);
    LONG diff;
    // DPCM coding of the DC coefficient.
    diff   = block[0] >> m_ucLowBit; // only correct for two's completement machines
    diff  -= prevdc;
    if (m_bDifferential) {
      prevdc = 0;
    } else {
      prevdc = block[0] >> m_ucLowBit;
    }

    if (diff) {
      LONG sz;
      //
      // Nonzero, encode a one in context zero.
      m_Coder.Put(cz.S0,true);
      //
      // Sign coding. Encode a zero for positive and a 1 for
      // negative.
      if (diff < 0) {
        m_Coder.Put(cz.SS,true);
        sz = -diff - 1;
      } else {
        m_Coder.Put(cz.SS,false);
        sz = diff - 1;
      }
      //
      // Code the magnitude.
      if (sz >= 1) {
        int  i = 0;
        LONG m = 2;
        m_Coder.Put((diff > 0)?(cz.SP):(cz.SN),true);
        //
        // Magnitude category coding.
        while(sz >= m) {
          m_Coder.Put(m_Context[dc].DCMagnitude.X[i],true);
          m <<= 1;
          i++;
        } 
        // Terminate magnitude cathegory coding.
        m_Coder.Put(m_Context[dc].DCMagnitude.X[i],false);
        //
        // Get the MSB to code.
        m >>= 1;
        // Refinement bits: Depend on the magnitude category.
        while((m >>= 1)) {
          m_Coder.Put(m_Context[dc].DCMagnitude.M[i],(m & sz)?(true):(false));
        }
      } else {
        m_Coder.Put((diff > 0)?(cz.SP):(cz.SN),false);
      }
    } else {
      // Difference is zero. Encode a zero in context zero.
      m_Coder.Put(cz.S0,false);
    }
    // Keep the difference for the next block.
    prevdiff = diff;
  }

  if (m_ucScanStop) {
    LONG data;
    int eob,k;
    // AC coding. Part one. Find the end of block.
    // eob is the index of the first zero coefficient from
    // which point on this, and all following coefficients
    // up to coefficient with index 63 are zero.
    eob = m_ucScanStop;
    k   = (m_ucScanStart)?(m_ucScanStart):((m_bResidual)?0:1);
    //
    while(eob >= k) {
      data = block[DCT::ScanOrder[eob]];
      if ((data >= 0)?(data >> m_ucLowBit):((-data) >> m_ucLowBit))
        break;
      eob--;
    }
    // The coefficient at eob is now nonzero, but eob+1 is
    // a zero coefficient or beyond the block end.
    eob++; // the first coefficient *not* to code.

    do {
      LONG data,sz;
      //
      if (k == eob) {
        m_Coder.Put(m_Context[ac].ACZero[k-1].SE,true); // Code EOB.
        break;
      }
      // Not EOB.
      m_Coder.Put(m_Context[ac].ACZero[k-1].SE,false);
      //
      // Run coding in S0. Since k is not the eob, at least
      // one non-zero coefficient must follow, so we cannot
      // run over the end of the block.
      do {
        data = block[DCT::ScanOrder[k]];
        data = (data >= 0)?(data >> m_ucLowBit):(-((-data) >> m_ucLowBit));
        if (data == 0) {
          m_Coder.Put(m_Context[ac].ACZero[k-1].S0,false);
          k++;
        }
      } while(data == 0);
      m_Coder.Put(m_Context[ac].ACZero[k-1].S0,true);
      //
      // The coefficient at k is now nonzero. First code
      // the sign. This context is the uniform.
      if (data < 0) {
        m_Coder.Put(m_Context[ac].Uniform,true);
        sz = -data - 1;
      } else {
        m_Coder.Put(m_Context[ac].Uniform,false);
        sz =  data - 1;
      }
      //
      // Code the magnitude category. 
      if (sz >= 1) {
        m_Coder.Put(m_Context[ac].ACZero[k-1].SP,true); // SP or SN coding.
        if (sz >= 2) {
          int  i = 0;
          LONG m = 4;
          struct QMContextSet::ACContextMagnitudeSet &acm = (k > kx)?(m_Context[ac].ACMagnitudeHigh):(m_Context[ac].ACMagnitudeLow);
          //
          m_Coder.Put(m_Context[ac].ACZero[k-1].SP,true); // X1 coding, identical to SN and SP.
          // Note that AC_SN,AC_SP and AC_X1 are all the same context
          // all following decisions are not conditioned on k directly.
          while(sz >= m) {
            m_Coder.Put(acm.X[i],true);
            m <<= 1;
            i++;
          }
          m_Coder.Put(acm.X[i],false);
          //
          // Get the MSB to code.
          m >>= 1;
          //
          // Magnitude refinement coding.
          while((m >>= 1)) {
            m_Coder.Put(acm.M[i],(m & sz)?true:false);
          }
        } else {
          m_Coder.Put(m_Context[ac].ACZero[k-1].SP,false);
        }
      } else {
        m_Coder.Put(m_Context[ac].ACZero[k-1].SP,false);
      }
      //
      // Encode the next coefficient. Note that this bails out early without an
      // S0 encoding if the end is reached.
    } while(++k <= m_ucScanStop);
  }
}
void ACSequentialScan::EncodeBlock(const LONG *block,
                                   LONG &prevdc,LONG &prevdiff,
                                   UBYTE small,UBYTE large,UBYTE kx,UBYTE dc,UBYTE ac)
{
   
  if (m_ucScanStart == 0 && m_bResidual == false) {
    struct QMContextSet::DCContextZeroSet &cz = m_Context[dc].Classify(prevdiff,small,large);
    LONG diff;
     
    diff   = block[0] >> m_ucLowBit;  
    diff  -= prevdc;
    if (m_bDifferential) {
      prevdc = 0;
    } else {
      prevdc = block[0] >> m_ucLowBit;
    }

    if (diff) {
      LONG sz;
       
       
      m_Coder.Put(cz.S0,true);
       
       
       
      if (diff < 0) {
        m_Coder.Put(cz.SS,true);
        sz = -diff - 1;
      } else {
        m_Coder.Put(cz.SS,false);
        sz = diff - 1;
      }
       
       
      if (sz >= 1) {
        int  i = 0;
        LONG m = 2;
        m_Coder.Put((diff > 0)?(cz.SP):(cz.SN),true);
         
         
        while(sz >= m) {
          m_Coder.Put(m_Context[dc].DCMagnitude.X[i],true);
          m <<= 1;
          i++;
        } 
         
        m_Coder.Put(m_Context[dc].DCMagnitude.X[i],false);
         
         
        m >>= 1;
         
        while((m >>= 1)) {
          m_Coder.Put(m_Context[dc].DCMagnitude.M[i],(m & sz)?(true):(false));
        }
      } else {
        m_Coder.Put((diff > 0)?(cz.SP):(cz.SN),false);
      }
    } else {
       
      m_Coder.Put(cz.S0,false);
    }
     
    prevdiff = diff;
  }

  if (m_ucScanStop) {
    LONG data;
    int eob,k;
     
     
     
     
    eob = m_ucScanStop;
    k   = (m_ucScanStart)?(m_ucScanStart):((m_bResidual)?0:1);
     
    while(eob >= k) {
      data = block[DCT::ScanOrder[eob]];
      if ((data >= 0)?(data >> m_ucLowBit):((-data) >> m_ucLowBit))
        break;
      eob--;
    }
     
     
    eob++;  

    do {
      LONG data,sz;
       
      if (k == eob) {
        m_Coder.Put(m_Context[ac].ACZero[k-1].SE,true);  
        break;
      }
       
      m_Coder.Put(m_Context[ac].ACZero[k-1].SE,false);
       
       
       
       
      do {
        data = block[DCT::ScanOrder[k]];
        data = (data >= 0)?(data >> m_ucLowBit):(-((-data) >> m_ucLowBit));
        if (data == 0) {
          m_Coder.Put(m_Context[ac].ACZero[k-1].S0,false);
          k++;
        }
      } while(data == 0);
      m_Coder.Put(m_Context[ac].ACZero[k-1].S0,true);
       
       
       
      if (data < 0) {
        m_Coder.Put(m_Context[ac].Uniform,true);
        sz = -data - 1;
      } else {
        m_Coder.Put(m_Context[ac].Uniform,false);
        sz =  data - 1;
      }
       
       
      if (sz >= 1) {
        m_Coder.Put(m_Context[ac].ACZero[k-1].SP,true);  
        if (sz >= 2) {
          int  i = 0;
          LONG m = 4;
          struct QMContextSet::ACContextMagnitudeSet &acm = (k > kx)?(m_Context[ac].ACMagnitudeHigh):(m_Context[ac].ACMagnitudeLow);
           
          m_Coder.Put(m_Context[ac].ACZero[k-1].SP,true);  
           
           
          while(sz >= m) {
            m_Coder.Put(acm.X[i],true);
            m <<= 1;
            i++;
          }
          m_Coder.Put(acm.X[i],false);
           
           
          m >>= 1;
           
           
          while((m >>= 1)) {
            m_Coder.Put(acm.M[i],(m & sz)?true:false);
          }
        } else {
          m_Coder.Put(m_Context[ac].ACZero[k-1].SP,false);
        }
      } else {
        m_Coder.Put(m_Context[ac].ACZero[k-1].SP,false);
      }
       
       
       
    } while(++k <= m_ucScanStop);
  }
}