
#include "TComDictCoder.h"
#include <string.h>
#include <math.h>

#if DUAL_CODER

CDictEncoder::CDictEncoder()
{
  m_uCurrPackSize = 0;
  m_bFirst = true;
  m_bFirstInit = true;
  m_iDictCoderLevel = 4;
  m_uDictSize = 0;
  m_bIsLastCuRollBack = 0; //ZF initialize
#if TRY_BACK_UP_HASHBASETABLE
  m_pHashBaseBak = NULL;
#endif
#if DEBUG_DICTCODER
  m_pLenPos = NULL;
#endif
  m_iHashLength = 8;
  m_iHashMethod = 0;
}
//int CDictEncoder::ReadBlockData(void *pp, void *data, UInt *size) //ZF original
int CDictEncoder::ReadBlockData(CSeqInStreamBuf *pp, UChar*data, size_t *size)
{
  size_t curSize = *size;
  CSeqInStreamBuf *p = (CSeqInStreamBuf *)pp;
  if (p->rem < curSize)
    curSize = p->rem;
  memcpy(data, p->data, curSize);
  p->rem -= curSize;
  p->data += curSize;
  *size = curSize;
  return 0;
}
UChar * CDictEncoder::MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) 
{
  return p->buffer;
}

UInt CDictEncoder::MatchFinder_GetNumAvailableBytes(CMatchFinder *p)
{ 
  return p->streamPos - p->pos; 
}

void CDictEncoder::MatchFinder_Init(CMatchFinder *p)
{
  UInt i;
#if RESET_FIX
  for (i = 0; i < (p->hashSizeSum +p->numSons); i++)
#else
  for (i = 0; i < p->hashSizeSum; i++)
#endif
    p->m_pHash[i] = 0;
  p->cyclicBufferPos = 0;
  p->buffer = p->bufferBase;
  p->pos = p->streamPos = p->cyclicBufferSize;
  p->result = 0;
  MatchFinder_ReadBlock(p);
  MatchFinder_SetLimits(p);
}


void CDictEncoder::MatchFinder_MoveBlock(CMatchFinder *p)
{
#if TRY_LOSSY_MATCH
  int addOffset = 0;
  if (p->keepSizeBefore < m_uCuLen)
  {
    addOffset = m_uCuLen - p->keepSizeBefore;
    if (addOffset < MATCH_LEN_MAX)
    {
      addOffset = MATCH_LEN_MAX;
    }    
  }
  else
    addOffset = MATCH_LEN_MAX;

  memmove(p->bufferBase,
    p->buffer - p->keepSizeBefore - addOffset,
    (size_t)(p->streamPos - p->pos + p->keepSizeBefore + addOffset));
  p->buffer = p->bufferBase + p->keepSizeBefore + addOffset;
#else
  memmove(p->bufferBase,
    p->buffer - p->keepSizeBefore,
    (size_t)(p->streamPos - p->pos + p->keepSizeBefore));
  p->buffer = p->bufferBase + p->keepSizeBefore;
#endif
}


int CDictEncoder::MatchFinder_NeedMove(CMatchFinder *p)
{
  return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter);
}

void CDictEncoder::MatchFinder_CheckAndMoveAndRead(CMatchFinder *p)
{
  if (MatchFinder_NeedMove(p))
    MatchFinder_MoveBlock(p);
  MatchFinder_ReadBlock(p);
}

void CDictEncoder::MatchFinder_ReduceOffsets(CMatchFinder *p, UInt subValue)
{
  p->posLimit -= subValue;
  p->pos -= subValue;
  p->streamPos -= subValue;
}


void CDictEncoder::MatchFinder_Normalize3(UInt subValue, UInt *items, UInt numItems)
{
  UInt i;
  for (i = 0; i < numItems; i++)
  {
    UInt value = items[i];
    if (value <= subValue)
      value = 0;
    else
      value -= subValue;
    items[i] = value;
  }
}

UInt CDictEncoder::MatchFinder_GetSubValue(CMatchFinder *p)
{
  return (p->pos - p->historySize - 1) & kNormalizeMask;
}

void CDictEncoder::MatchFinder_Normalize(CMatchFinder *p)
{
  UInt subValue = MatchFinder_GetSubValue(p);
  MatchFinder_Normalize3(subValue, p->m_pHash, p->hashSizeSum + p->numSons);
  MatchFinder_ReduceOffsets(p, subValue);
}

void CDictEncoder::MatchFinder_SetLimits(CMatchFinder *p)
{
  UInt limit = kMaxValForNormalize - p->pos;
#if PIXEL_BUFFER
  UInt limit2 = (p->cyclicBufferSize - p->cyclicBufferPos)*3;
#else
  UInt limit2 = p->cyclicBufferSize - p->cyclicBufferPos;
#endif
  if (limit2 < limit)
    limit = limit2;
  limit2 = p->streamPos - p->pos;
  if (limit2 <= p->keepSizeAfter)
  {
    if (limit2 > 0)
      limit2 = 3;
  }
  else
    limit2 -= p->keepSizeAfter;
  if (limit2 < limit)
    limit = limit2;
  {
    UInt lenLimit = p->streamPos - p->pos;
    if (lenLimit > p->matchMaxLen)
      lenLimit = p->matchMaxLen;
    p->lenLimit = lenLimit;
  }
  p->posLimit = p->pos + limit;
}

void CDictEncoder::MatchFinder_CheckLimits(CMatchFinder *p)
{
  if (p->pos == kMaxValForNormalize)
    MatchFinder_Normalize(p);

  if (p->keepSizeAfter >= (p->streamPos - p->pos))
  {
    MatchFinder_CheckAndMoveAndRead(p);
  }
#if PIXEL_BUFFER
  if (p->cyclicBufferSize <= (p->cyclicBufferPos +1))
    p->cyclicBufferPos = 0;
#else
  if (p->cyclicBufferSize <= (p->cyclicBufferPos+3))
    p->cyclicBufferPos = 0;
#endif

  MatchFinder_SetLimits(p);
}

UInt * CDictEncoder::Hc_GetMatchesSpec(UInt lenLimit, UInt curMatch, UInt pos, const UChar *cur, UInt *son,
  UInt _cyclicBufferPos, UInt _cyclicBufferSize, UInt cutValue,
  UInt *distances, UInt maxLen)
{
#if TRY_LOSSY_MATCH
  int result = 0;
  UChar pCurTmpBuf[MATCH_LEN_MAX];
#endif
#if ADD_ENCODER_RD_ESCAPE_OR_RUN
  Int iCostAllEscapeCoded = 0;
  Int iCostRunCoded = 0;
  Int iBitsLen = 0, iBitsPos = 0;
  Int posSlot = 0, footerBits = 0;
  UInt* tempDistances = distances; //store the initial state of distances
  Int bestDelta = 1;
#endif

  son[_cyclicBufferPos] = curMatch;
  for (;;) //find max match len from all history match candidates
  {
    UInt delta = pos - curMatch;
    if (delta == 0)
    {	
      delta = 1;
    }

    if (cutValue-- == 0 || delta >= _cyclicBufferSize)
      return distances;

    {
      const UChar *pb = cur - delta;
#if PIXEL_BUFFER
      assert((_cyclicBufferPos - (delta/3) + (((delta /3) > _cyclicBufferPos) ? _cyclicBufferSize : 0)) >= 0);
      curMatch = son[_cyclicBufferPos - (delta/3) + (((delta/3) > _cyclicBufferPos) ? _cyclicBufferSize : 0)];
#else
      assert((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) >= 0);
      curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)];
#endif
#if TRY_LOSSY_MATCH
      memcpy(pCurTmpBuf,cur, MATCH_LEN_MAX);
      if (IS_LOSSY_EQUAL_COPY(pb[maxLen],pCurTmpBuf[maxLen],m_uiMatchDiffAllow) && IS_LOSSY_EQUAL_COPY(*pb , *pCurTmpBuf,m_uiMatchDiffAllow))
#else
      if (pb[maxLen] == cur[maxLen] && *pb == *cur)
#endif
      {
        UInt len = 0;
        while (++len != lenLimit) //find the max len from history match points
#if TRY_LOSSY_MATCH
          if (!IS_LOSSY_EQUAL_COPY(pb[len] , pCurTmpBuf[len],m_uiMatchDiffAllow))
#else
          if (pb[len] != cur[len])
#endif
            break;
        len = len / 3 * 3;
        if (maxLen < len)
        {
          *distances++ = maxLen = len;
          *distances++ = delta - 1;
#if ADD_ENCODER_RD_ESCAPE_OR_RUN
          bestDelta = delta;
#endif
          if (len == lenLimit)
            return distances;
        }   
#if ADD_ENCODER_RD_ESCAPE_OR_RUN
        //calculate the escape coded cost
        iCostAllEscapeCoded = maxLen * (8 + 1 + 1); //1bit flag, 8 bits escape pixel difference, 1 bit one sign 
        //calculate the run coded cost
        iBitsLen = maxLen < 8 ? 4 : (maxLen < 16 ? 5 : 10);
        posSlot = GetPosSlotFunc(bestDelta - 1);
        if (posSlot >= 4)
          footerBits = ((posSlot >> 1) - 1);

        iBitsPos = 6 + footerBits;
        iCostRunCoded = iBitsLen + iBitsPos + 1; //1 bit flag

        if (iCostAllEscapeCoded < iCostRunCoded)
        {
          distances = tempDistances; //reset
        }
#endif
      }
    }
  }
}

UInt CDictEncoder::createHashValue (CMatchFinder *p, const UChar *pCurSample )
{
  UInt temp, hashV =0;
  UInt uiHashMask = (1<<m_iHashLength)-1;

  switch(m_iHashMethod)
  {
  case 0:
    temp  = p->crc[pCurSample[0]] ^ pCurSample[1]; 
    hashV = (temp ^ ((UInt)pCurSample[2] << 8)) & uiHashMask; 
    break;
  case 1:
    hashV = (p->crc[pCurSample[0] ^ pCurSample[1] ^ pCurSample[2]] ^ (pCurSample[0] + pCurSample[1] + pCurSample[2])) & uiHashMask;
    break;
  case 2: 
    temp    = (pCurSample[0]>>3)<<6;
    temp   += (pCurSample[1]>>2);
    temp  <<= 5;
    temp   +=(pCurSample[2]>>3);
    hashV   = temp& uiHashMask;
    break;
  case 3:
    temp    = (pCurSample[0])<<8;
    temp   += pCurSample[1];
    temp  <<= 8;
    temp   += pCurSample[2];
    hashV   = temp& uiHashMask;
    break;
  case 4:
    temp = p->crc[pCurSample[0]] ^ p->crc[pCurSample[1]]; 
    hashV = (p->crc[pCurSample[0]] ^ p->crc[pCurSample[1] ^ pCurSample[2]]) & uiHashMask; 
    break;
#if CRC_24_to_16
   case 5:
    temp    = (pCurSample[0])<<8;
    temp   += pCurSample[1];
    temp  <<= 8;
    temp   += pCurSample[2];
    hashV   = m_pCRC[temp]& uiHashMask;
    break;
#endif
#if MORE_NEW_HASH
  case 6:
    temp    = (pCurSample[0]>>(8-m_iHashBitDis[0]))<<m_iHashBitDis[1];
    temp   += (pCurSample[1]>>(8-m_iHashBitDis[1]));
    temp  <<= m_iHashBitDis[2];
    temp   +=(pCurSample[2]>>(8-m_iHashBitDis[2]));
    hashV   = temp; //& uiHashMask;
    break;

#endif 
  default:
    hashV = pCurSample[0]& uiHashMask;
    break;
  }

  return hashV; 
}
UInt CDictEncoder::Hc3_MatchFinder_GetMatches(CMatchFinder *p, UInt *distances)
{
  UInt delta3, maxLen, offset;

  UInt lenLimit;  
  const UChar *cur;
  UInt curMatch; 
  UInt hashValue;

  UInt minLen = 3;

#if ADD_ENCODER_RD_ESCAPE_OR_RUN
  Int iCostAllEscapeCoded = 0;
  Int iCostRunCoded = 0;
  Int iBitsLen = 0, iBitsPos = 0;
  Int posSlot = 0, footerBits = 0;
#endif

  lenLimit = p->lenLimit; 
  {
    if (lenLimit < minLen) 
    {
      ++p->cyclicBufferPos; 
      p->buffer++; 
      if (++p->pos == p->posLimit) 
        MatchFinder_CheckLimits(p);
      return 0; 
    }
  }
  cur = p->buffer;
  

#if TRY_LOSSY_MATCH
  int result = 0;
  UChar pCurTmpBuf[MATCH_LEN_MAX];
  memcpy(pCurTmpBuf,cur, MATCH_LEN_MAX);
#endif

  { 
    hashValue = createHashValue(p,cur);
  }


  delta3 = p->pos - p->m_pHash[hashValue];
  curMatch = p->m_pHash[hashValue];
  //ZF test code
  //assert(delta3 % 3 == 0);

  p->m_pHash[ hashValue] =p->pos;
  
  // cy: kHash2Size should be set to 0
  //it's not necessary for search when the source is rec data of HM
  if (!p->m_bEncOrg)
  {
    offset = 0;
#if TRY_BACK_UP_HASHBASETABLE
    p->m_pSon[p->cyclicBufferPos] = curMatch;
#endif

#if PIXEL_BUFFER
    p->cyclicBufferPos += 1;
#else
    p->cyclicBufferPos += 3;// next sample cyclic pos of the same channel
#endif
    p->buffer += 3;         // next sample buffer of the same channel
    p->pos += 3;            // next sample pos of the same channel
    if (Int(p->posLimit - p->pos) <= 3)
      MatchFinder_CheckLimits(p);

    return offset;
  }

  if (delta3 == 0)
  {
    delta3 = 1;
  }

  maxLen = 1;
  offset = 0;// matching candidate information index

#if TRY_LOSSY_MATCH
  if (delta3 < p->cyclicBufferSize && IS_LOSSY_EQUAL_COPY(*(cur - delta3), *pCurTmpBuf, m_uiMatchDiffAllow))
#else
#if PIXEL_BUFFER
  if (curMatch != 0 && (delta3/3) < p->cyclicBufferSize && *(cur - delta3) == *cur)
#else
  if (delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur)
#endif
#endif
  {
    distances[0] = maxLen = 1; //only initialize match len, will be set later
    distances[1] = delta3 - 1; //relative match pos
    offset = 2;
  }

  if (offset != 0) //if found match, test how long the match could be
  {
    for (; maxLen != lenLimit; maxLen++) //find the maximum matching len
#if TRY_LOSSY_MATCH
    if (!IS_LOSSY_EQUAL_COPY(cur[(ptrdiff_t)maxLen - delta2], pCurTmpBuf[maxLen], m_uiMatchDiffAllow))
#else
    if (cur[(ptrdiff_t)maxLen - delta3] != cur[maxLen])
#endif
      break;
    maxLen = maxLen / 3 * 3;

#if ADD_ENCODER_RD_ESCAPE_OR_RUN
      //calculate the escape coded cost
      iCostAllEscapeCoded = maxLen * (8+1+1); //1bit flag, 8 bits escape pixel difference, 1 bit one sign 
      //calculate the run coded cost
      iBitsLen = maxLen < 8 ? 4 : (maxLen < 16 ? 5 : 10);
      posSlot = GetPosSlotFunc(delta2-1);
      if (posSlot >= 4)
        footerBits = ((posSlot >> 1) - 1);

      iBitsPos = 6 + footerBits;
      iCostRunCoded = iBitsLen + iBitsPos + 1; //1 bit flag

      if (iCostAllEscapeCoded < iCostRunCoded)
      {
        distances[offset - 2] = 1;
      }
      else
      {
        distances[offset - 2] = maxLen;
      }
#else
    distances[offset - 2] = maxLen;
#endif
    if (maxLen == lenLimit)
    {
      p->m_pSon[p->cyclicBufferPos] = curMatch;
#if PIXEL_BUFFER
      p->cyclicBufferPos += 1;
#else
      p->cyclicBufferPos += 3;
#endif
      p->buffer +=3;
      p->pos +=3;
      if (p->posLimit <= (p->pos+ 3))
        MatchFinder_CheckLimits(p);

      return offset;
    }
  }
  if (maxLen < 3)
    maxLen = 3;
  offset = (UInt)(Hc_GetMatchesSpec(lenLimit, curMatch, p->pos, p->buffer, p->m_pSon, p->cyclicBufferPos, p->cyclicBufferSize, p->m_uCutValue,distances + offset, maxLen) - (distances));
#if PIXEL_BUFFER
  p->cyclicBufferPos += 1;
#else
  p->cyclicBufferPos += 3;
#endif
  p->buffer += 3;
  p->pos +=3;
  if (p->posLimit <= (p->pos+ 3))
    MatchFinder_CheckLimits(p);

  return offset;
}

void CDictEncoder::MatchFinder_ReadBlock(CMatchFinder *p)
{
  for (;;)
  {
    UChar *dest = p->buffer + (p->streamPos - p->pos);
    size_t size = (p->bufferBase + p->blockSize - dest);
    if (size == 0)
      return;
    //p->result = ReadBlockData(p->stream, dest, &size);
    //p->result = ReadBlockData((void *)p->stream, (void *)dest, (UInt *)(&size)); // ZF Original
    p->result = ReadBlockData(p->stream, dest, (&size));
    if (p->result != 0)
      return;
    if (size == 0)
    {
      return;
    }
    p->streamPos += (UInt)size;

    if (p->streamPos - p->pos > p->keepSizeAfter)
      return;

  }
}

void CDictEncoder::MatchFinder_ReadIfRequired(CMatchFinder *p)
{
  if (p->keepSizeAfter >= p->streamPos - p->pos)
    MatchFinder_ReadBlock(p);

  if (p->pos == p->posLimit) 
    MatchFinder_CheckLimits(p);
}


UInt CDictEncoder::ReadMatchDistances(UInt *numDistancePairsRes)
{
  UInt lenRes = 0, numPairs;
  m_uNumAvail = MatchFinder_GetNumAvailableBytes(&m_matchFinderBase);
  numPairs = Hc3_MatchFinder_GetMatches(&m_matchFinderBase, m_uMatches); //numPairs 即 len ?
#if TRY_LOSSY_MATCH
  int result = 0;
  UChar *cur = MatchFinder_GetPointerToCurrentPos(&m_matchFinderBase) - 1;
  UChar pCurTmpBuf[MATCH_LEN_MAX];
  memcpy(pCurTmpBuf,cur, MATCH_LEN_MAX);
#endif
  if (numPairs > 0) //if there is a history match
  { //ZF should not change 
    lenRes = m_uMatches[numPairs - 2];
    if (lenRes == m_uNumFastBytes)
    {
      const UChar *pby = MatchFinder_GetPointerToCurrentPos(&m_matchFinderBase) - 3;
      UInt distance = m_uMatches[numPairs - 1] + 1;

      UInt numAvail = m_uNumAvail;

      if (distance == 0)
      {
        distance = 1;
      }

      if (numAvail > (MATCH_LEN_MAX*3))
        numAvail = MATCH_LEN_MAX *3;
      {
        const UChar *pby2 = pby - distance;
        lenRes = 0;
#if TRY_LOSSY_MATCH
        for (; lenRes < numAvail && IS_LOSSY_EQUAL_COPY(pby2[lenRes] , pCurTmpBuf[lenRes],m_uiMatchDiffAllow); lenRes++);
#else
        for (; lenRes < numAvail && pby[lenRes] == pby2[lenRes]; lenRes++);
#endif

//#if FORCE_PIXEL_MATCH
//        lenRes = (lenRes / 3) * 3; // not sure why the above function is recalled
//#endif
      }
    }
  }

  m_uAdditionalOffset += 3; // current sample pointer shift after this function

  *numDistancePairsRes = numPairs;
#if FORCE_PIXEL_MATCH
  assert((lenRes % 3) == 0);
#endif
  return lenRes;
}

#if EXTEND_RUN
void CDictEncoder::WriteBits(int64_t& uiDst, int64_t value, UInt numBits, UInt uiStartPos)
#else
void CDictEncoder::WriteBits(UInt & uiDst,UInt value, UInt numBits, UInt uiStartPos)
#endif
{
#if EXTEND_RUN
  value = value << (40 - uiStartPos - numBits + 1);
  uiDst=uiDst|value;
#else
  value=value<<(32-uiStartPos-numBits+1);
  uiDst=uiDst|value;
#endif
}

void CDictEncoder::WriteStrMapResult(int len, int pos,const UChar * pCurBuf)
{
#if EXTEND_RUN
  int64_t iDst = 0;
#else
  UInt iDst = 0;
#endif
  UInt c = 0;
  //   UInt tmp,rLen,rPos;

#if FORCE_PIXEL_MATCH
  if (len == 3 && pos == (UInt)-1)
#else
  if (len == 1 && pos == (UInt)-1)
#endif
  {
    // escape flag
    WriteBits(iDst, 0, 1, 1); 

    // first sample
    c = (UInt)pCurBuf[0];
    WriteBits(iDst, c, 8, 2);

    //second sample
    c = (UInt)pCurBuf[1];
    WriteBits(iDst, c, 8, 10);

    //third sample
    c = (UInt)pCurBuf[2];
    WriteBits(iDst, c, 8, 18);
  }
  else
  {
    WriteBits(iDst,1,1,1);
#if FORCE_PIXEL_MATCH
    assert(len % 3 == 0);
    len =len/3;
#endif

#if SUPER_EXTEND_RUN
    assert(len >= 0 && len <= 4096);
    WriteBits(iDst, len, 14, 2);//ZF note extend run
#if LARGE_DICT
    WriteBits(iDst, pos, 24, 16);
#else
    WriteBits(iDst, pos, 22,16);
#endif
#else
#if EXTEND_RUN
    assert(len >= 0 && len <= 528);
    WriteBits(iDst, len, 10, 2);//ZF note extend run
    WriteBits(iDst, pos, 22,12);
#else
    WriteBits(iDst,len,9,2);
    WriteBits(iDst,pos,22,11);
#endif
#endif
  }
  m_pStrMapBufList.push_back(iDst);
  m_uCurrPackSize++;
}


void CDictEncoder::Hc3_MatchFinder_Skip(CMatchFinder *p, UInt num) //ZF, num is sample number not pixel number
{
  do
  {
    UInt lenLimit,hashValue,curMatch; 
    const UChar *cur; 
    lenLimit = p->lenLimit; 
    { 
#if FORCE_PIXEL_MATCH
      assert(lenLimit % 3 == 0);
#endif
      if (lenLimit < 3) 
      {
        ++p->cyclicBufferPos; 
        p->buffer++; 
        if (++p->pos == p->posLimit) 
          MatchFinder_CheckLimits(p);
        continue; 
      }
    } 
    cur = p->buffer;


    hashValue = createHashValue(p,cur);

    curMatch = p->m_pHash[hashValue];

    p->m_pHash[hashValue] = p->pos;
    p->m_pSon[p->cyclicBufferPos] = curMatch;

#if FORCE_PIXEL_MATCH
#if PIXEL_BUFFER
    p->cyclicBufferPos += 1;// next sample cyclic pos of the same channel
#else
    p->cyclicBufferPos += 3;// next sample cyclic pos of the same channel
#endif
    p->buffer += 3;         // next sample buffer of the same channel
    p->pos += 3;            // next sample pos of the same channel
    if (Int(p->posLimit - p->pos) <= 3)
      MatchFinder_CheckLimits(p);
#else
    ++p->cyclicBufferPos; 
    p->buffer++; 
    if (++p->pos == p->posLimit) 
      MatchFinder_CheckLimits(p);
#endif
  }
  while (--num != 0);
}


void CDictEncoder::MovePos(UInt num)
{
  if (num != 0)
  {
    m_uAdditionalOffset += num;
#if FORCE_PIXEL_MATCH
    assert(num % 3 == 0);
    num = num / 3; //update the skip full pixels
#endif
    Hc3_MatchFinder_Skip(&m_matchFinderBase, num);
  }
}


UInt CDictEncoder::GetOptimumFast(UInt *backRes)
{
  UInt numAvail, mainLen, mainDist, numPairs, repIndex, repLen, i;
  const UChar *data;
  const UInt *matches;

  m_uNumAvail = MatchFinder_GetNumAvailableBytes(&m_matchFinderBase);

  if (m_uAdditionalOffset == 0)
    mainLen = ReadMatchDistances(&numPairs);
  else
  {
    mainLen = m_uLongestMatchLength;
    numPairs = m_uNumPairs;
  }

  numAvail = m_uNumAvail;
  *backRes = (UInt)-1;

  if (!m_matchFinderBase.m_bEncOrg)
  {
    return 1;
  }

#if FORCE_PIXEL_MATCH
  if (numAvail < 3)
    return 3;
#else
  if (numAvail < 2)
    return 1;
#endif

#if FORCE_PIXEL_MATCH
  if (numAvail > (MATCH_LEN_MAX *3))
    numAvail = MATCH_LEN_MAX*3;
#else
  if (numAvail > MATCH_LEN_MAX)
    numAvail = MATCH_LEN_MAX;
#endif
#if FORCE_PIXEL_MATCH
  data = MatchFinder_GetPointerToCurrentPos(&m_matchFinderBase) - 3; // shift back to the current sample 
#else
  data = MatchFinder_GetPointerToCurrentPos(&m_matchFinderBase) - 1;
#endif

#if TRY_LOSSY_MATCH
  int result = 0;
  UChar pCurTmpBuf[MATCH_LEN_MAX];
#endif

  repLen = repIndex = 0;
  for (i = 0; i < NUM_REPS; i++) // try the recent match distances
  {
    UInt len;
#if FORCE_PIXEL_FIX
    const UChar *data2 = data - (m_uReps[i] + 1) *3; //m_uReps is in unit of pixel
#else
    const UChar *data2 = data - (m_uReps[i] + 1);
#if FORCE_PIXEL_MATCH// ZF important to performance
   if ((m_uReps[i] + 1) % 3 != 0)
      continue;
#endif
#endif
#if TRY_LOSSY_MATCH
    memcpy(pCurTmpBuf,data, MATCH_LEN_MAX);
    if (!IS_LOSSY_EQUAL_COPY(data2[0] ,pCurTmpBuf[0],m_uiMatchDiffAllow) || !IS_LOSSY_EQUAL_COPY(data2[1] , pCurTmpBuf[1],m_uiMatchDiffAllow))
      continue;
    for (len = 2; len < numAvail && IS_LOSSY_EQUAL_COPY(data2[len] , pCurTmpBuf[len],m_uiMatchDiffAllow); len++);
#else
    if (data[0] != data2[0] || data[1] != data2[1])
      continue;
    for (len = 2; len < numAvail && data[len] == data2[len]; len++);
#endif

#if FORCE_PIXEL_MATCH
    len = UInt(len / 3) * 3;
#endif

    if (len >= m_uNumFastBytes)
    {
      *backRes = i;
#if FORCE_PIXEL_MATCH  
      MovePos(len - 3);
#else
      MovePos(len - 1);
#endif
      return len;
    }

    if (len > repLen)
    {
      repIndex = i;
      repLen = len;
    }
  }

  matches = m_uMatches;
  if (mainLen >= m_uNumFastBytes)
  {
    *backRes = matches[numPairs - 1] + NUM_REPS; //calculate the relative position, NUM_REPS is a temporal offset, which is not coded
#if FORCE_PIXEL_MATCH
    MovePos(mainLen - 3); // one pixel already updated to hash table
#else
    MovePos(mainLen - 1);
#endif
    return mainLen;
  }

  mainDist = 0;
#if FORCE_PIXEL_MATCH
  //assert(mainLen % 3 == 0);
  if (mainLen >= 3) //ZF not sure
#else
  if (mainLen >= 2)
#endif
  {
    mainDist = matches[numPairs - 1];
    while (numPairs > 2 && mainLen == matches[numPairs - 4] + 1)
    {
      if (!ChangePair(matches[numPairs - 3], mainDist))
        break;
      numPairs -= 2;
      mainLen = matches[numPairs - 2];
      mainDist = matches[numPairs - 1];
    }
    if (mainLen == 2 && mainDist >= 0x80)//ZF not sure
      mainLen = 1;
  }

#if FORCE_PIXEL_MATCH
  if (repLen >= 3 && (
    (repLen + 3 >= mainLen) ||
    (repLen + 6 >= mainLen && mainDist >= (1 << 9)) ||
    (repLen + 9 >= mainLen && mainDist >= (1 << 15))))
#else
  if (repLen >= 2 && ( 
    (repLen + 1 >= mainLen) ||
    (repLen + 2 >= mainLen && mainDist >= (1 << 9)) ||
    (repLen + 3 >= mainLen && mainDist >= (1 << 15))))
#endif
  {
    *backRes = repIndex;
#if FORCE_PIXEL_MATCH
    MovePos(repLen - 3);
#else
    MovePos(repLen - 1);
#endif
    return repLen;
  }

#if FORCE_PIXEL_MATCH
  if (mainLen <= 3 || numAvail <= 3)
    return 3; //current three samples do not have a match, then current three samples are escape coded
#else
  if (mainLen < 2 || numAvail <= 2)
    return 1;
#endif

  m_uLongestMatchLength = ReadMatchDistances(&m_uNumPairs);
#if FORCE_PIXEL_MATCH
  if (m_uLongestMatchLength >= 3)//not sure
#else
  if (m_uLongestMatchLength >= 2)//not sure
#endif
  {
    UInt newDistance = matches[m_uNumPairs - 1];
#if FORCE_PIXEL_MATCH
    if ((m_uLongestMatchLength >= mainLen && newDistance < mainDist) ||
      (m_uLongestMatchLength == mainLen + 3 && !ChangePair(mainDist, newDistance)) ||
      (m_uLongestMatchLength > mainLen + 3) ||
      (m_uLongestMatchLength + 3 >= mainLen && mainLen >= 3 && ChangePair(newDistance, mainDist)))
#else
    if ((m_uLongestMatchLength >= mainLen && newDistance < mainDist) ||
      (m_uLongestMatchLength == mainLen + 1 && !ChangePair(mainDist, newDistance)) ||
      (m_uLongestMatchLength > mainLen + 1) ||
      (m_uLongestMatchLength + 1 >= mainLen && mainLen >= 3 && ChangePair(newDistance, mainDist)))
#endif
#if FORCE_PIXEL_MATCH
      return 3; //if the next pixel match results are better, the current pixel (3 samples) are escape coded
#else
      return 1;
#endif
  }


#if FORCE_PIXEL_MATCH
  data = MatchFinder_GetPointerToCurrentPos(&m_matchFinderBase) - 3;//back to current sample //current match is better
#else
  data = MatchFinder_GetPointerToCurrentPos(&m_matchFinderBase) - 1;
#endif

  for (i = 0; i < NUM_REPS; i++)
  {
    UInt len, limit;
#if FORCE_PIXEL_FIX
    const UChar *data2 = data - (m_uReps[i] + 1) * 3;
#else
    const UChar *data2 = data - (m_uReps[i] + 1);
#if FORCE_PIXEL_MATCH
    if ((m_uReps[i] + 1) % 3 != 0)//ZF important to performance
      continue;
#endif
#endif

#if TRY_LOSSY_MATCH
    memcpy(pCurTmpBuf,data, MATCH_LEN_MAX);
    if (!IS_LOSSY_EQUAL_COPY(data2[0] ,pCurTmpBuf[0],m_uiMatchDiffAllow) || !IS_LOSSY_EQUAL_COPY(data2[1] , pCurTmpBuf[1],m_uiMatchDiffAllow))
#else
    if (data[0] != data2[0] || data[1] != data2[1])
#endif
      continue;
    limit = mainLen - 1;
#if TRY_LOSSY_MATCH
    for (len = 2; len < limit && IS_LOSSY_EQUAL_COPY(data2[len] , pCurTmpBuf[len],m_uiMatchDiffAllow); len++);
#else
    for (len = 2; len < limit && data[len] == data2[len]; len++);
#endif

    if (len >= limit)
#if FORCE_PIXEL_MATCH
      return 3;
#else
      return 1;
#endif
  }
  *backRes = mainDist + NUM_REPS;
#if FORCE_PIXEL_MATCH
  //assert(mainLen >= 6);
  MovePos(mainLen - 6);
#else
  MovePos(mainLen - 2);
#endif
  return mainLen;
}

void CDictEncoder::MatchFinder_Construct(CMatchFinder *p)
{
  UInt i;
  p->bufferBase = 0;
  p->m_pHash = 0;
  p->m_bEncOrg = 0;
  for (i = 0; i < 256; i++)
  {
    UInt r = i;
    int j;
    for (j = 0; j < 8; j++)
      r = (r >> 1) ^ (K_CRC_POLY & ~((r & 1) - 1));
    p->crc[i] = r;
  }
}

void CDictEncoder::MatchFinder_Free(CMatchFinder *p)
{
  if(p->bufferBase)
  {
    delete[] p->bufferBase;
    p->bufferBase = NULL;
  }
  if (p->m_pHash)
  {
    delete[] p->m_pHash;
    p->m_pHash = NULL;
  }
#if TRY_BACK_UP_HASHBASETABLE
  if (m_pHashBaseBak)
  {
    delete[] m_pHashBaseBak;  //ZF delete operator
    m_pHashBaseBak = NULL;
  }
#endif
}

int CDictEncoder::DictInWindow_Create(CMatchFinder *p, UInt keepSizeReserv)
{
#if PIXEL_BUFFER
  UInt blockSize = p->keepSizeBefore * 3 + p->keepSizeAfter + keepSizeReserv;
#else
  UInt blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv;
#endif

  if (p->bufferBase == 0 || p->blockSize != blockSize)
  {
    p->blockSize = blockSize;
    p->bufferBase = new UChar[blockSize*sizeof(UChar)];
  }
  return (p->bufferBase != 0);
}

int CDictEncoder::MatchFinder_Create(CMatchFinder *p, UInt historySize, UInt matchMaxLen, UInt keepAddBufferAfter)
{
  UInt sizeReserv;

  sizeReserv = m_uCuLen*2;
#if PIXEL_BUFFER
  historySize = historySize / 3;
#endif
  p->keepSizeBefore = historySize+1;

#if FORCE_PIXEL_MATCH
  p->keepSizeAfter = keepAddBufferAfter * 3;
#else
  p->keepSizeAfter = keepAddBufferAfter;
#endif


  /* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */
  if (DictInWindow_Create(p, sizeReserv))
  {
    UInt newCyclicBufferSize;
    UInt prevSize = p->hashSizeSum + p->numSons;
    UInt newSize;



    p->historySize = historySize;


    newCyclicBufferSize = (historySize /* >> p->skipModeBits */) + 1;

    p->matchMaxLen = matchMaxLen;
    /*
    switch(p->level)
    {
    case 1:
      bitsHash3 = 8;
      break;
    case 2:
      bitsHash3 = 9;
      break;
    case 3: 
      bitsHash3 = 10;
      break;
    case 4:
      bitsHash3 = 12;
      break;
    case 5:
      bitsHash3 = 14;
      break;
    default:
      bitsHash3 = 16;
      break;
    }
    */

    p->hashSizeSum = (1<< m_iHashLength);


    p->cyclicBufferSize = newCyclicBufferSize;
    p->numSons = newCyclicBufferSize;

    newSize = p->hashSizeSum + p->numSons;
    if (p->m_pHash != 0 && prevSize == newSize)
      return 1;

    p->m_pHash = new UInt[newSize*sizeof(UInt)];
    if (p->m_pHash != 0)
    {
      p->m_pSon = p->m_pHash + p->hashSizeSum;
      return 1; 
    }
  }
  MatchFinder_Free(p);
  return 0;
}

void CDictEncoder::DictEnc_FastPosInit()
{
  int c = 2, slotFast;
  int kNumLogBits = 11;
  m_pbFastPos[0] = 0;
  m_pbFastPos[1] = 1;


  for (slotFast = 2; slotFast < kNumLogBits*2; slotFast++)
  {
    UInt k = (1 << ((slotFast >> 1) - 1));
    UInt j;
    for (j = 0; j < k; j++, c++)
      m_pbFastPos[c] = (UChar)slotFast;
  } 
}

void CDictEncoder::DictEnc_Construct()
{
  MatchFinder_Construct(&m_matchFinderBase);
  DictEnc_FastPosInit();
}


int CDictEncoder::DictEnc_Alloc()
{

  if (!MatchFinder_Create(&m_matchFinderBase, m_uDictSize, m_uNumFastBytes, MATCH_LEN_MAX))
      return 1;
 
  return 0;
}

int CDictEncoder::DictEnc_AllocAndInit()
{
  UInt i,result;
  result = DictEnc_Alloc();
  if(result)
  {
    return result;
  }
  for (i = 0 ; i < NUM_REPS; i++)
    m_uReps[i] = 0;
  m_uAdditionalOffset = 0;

  m_uNowPos64 = 0;
  return 0;
} 

void CDictEncoder::Init(UChar * pSrcBuf)
{

  if (m_bFirstInit)
  {
    DictEnc_Construct();
    m_bFirstInit = false;
  }

  int level = m_iDictCoderLevel;

  if (m_uDictSize==0)
  {
#if LARGE_DICT
    if (level < 1 || level >8)
#else
    if (level < 1 || level >7)
#endif
    {
      printf("level must between 1~9\n");
      return;
    }
    else if (level == 1)
    {
      m_uDictSize = (1<<12);
    }
    else if (level == 2)
    {
      m_uDictSize = (1<<13);
    }
    else if (level > 2)
    {
      m_uDictSize = 1 << (level * 2 + 8);
    }
  } 
  m_uDictSize -= 2;



#if FORCE_PIXEL_MATCH
  m_uNumFastBytes = MATCH_LEN_MAX *3;
#else
  m_uNumFastBytes = MATCH_LEN_MAX;
#endif

  m_matchFinderBase.m_uCutValue = MATCH_FINDER_CUT_VALUE;
 
  m_cSeqBufInStream.data = pSrcBuf;

  m_uPrevPackSize = 0;
  m_bFirst = true;

  m_matchFinderBase.level = level;
    
  DictEnc_AllocAndInit();

#if TRY_BACK_UP_HASHBASETABLE
  if (m_pHashBaseBak == NULL)
  {
    m_pHashBaseBak = new UInt[m_matchFinderBase.hashSizeSum * sizeof(UInt)];//ZF buffer size
  }
#endif

#if DEBUG_DICTCODER
  if(m_pLenPos == NULL)
	m_pLenPos = fopen("Len&Pos.txt","wt");
#endif
   
}

void CDictEncoder::DictCodeOneBlock()
{
   UInt nowPos32, startPos32;
   UChar * pCurBuf;
   int i;

   if (m_bFirst)
  { 
    m_matchFinderBase.stream = &m_cSeqBufInStream;
    MatchFinder_Init(&m_matchFinderBase);
    m_bFirst = false;
  }

  MatchFinder_ReadIfRequired(&m_matchFinderBase);

  nowPos32 = (UInt)m_uNowPos64;
  startPos32 = nowPos32;

#if DEBUG_DICTCODER
  if (m_matchFinderBase.m_bEncOrg)
  {
	  fprintf(m_pLenPos,"#%d\n",m_uCuIdx+1);
  }
#endif

  m_uCurrPackSize = 0;

  if (m_uNowPos64 == 0)
  {
    UInt numPairs;
    if (MatchFinder_GetNumAvailableBytes(&m_matchFinderBase) == 0)
          return ;
    ReadMatchDistances(&numPairs);
#if FORCE_PIXEL_MATCH
    m_uAdditionalOffset -= 3; // shift back the current sample
    nowPos32 += 3;
#else
    m_uAdditionalOffset--;
    nowPos32++;
#endif
    if (m_matchFinderBase.m_bEncOrg)
    {
#if DEBUG_DICTCODER
	  fprintf(m_pLenPos,"%d\t%d\t%d\t\n",0,1,-1);
#endif


#if FORCE_PIXEL_MATCH
    WriteStrMapResult(3, -1, m_matchFinderBase.bufferBase);
#else
    WriteStrMapResult(1,-1,m_matchFinderBase.bufferBase);
#endif
    }
  }

  if (MatchFinder_GetNumAvailableBytes(&m_matchFinderBase) != 0)
    for (;;)
    {
      UInt pos, len;

      //if last cu roll back(coded by HM),then reset m_uReps[] to zero, otherwise decode error will happen.

      if (m_matchFinderBase.m_bEncOrg && m_bIsLastCuRollBack)
      {
        for (i = 0; i< NUM_REPS; i++)
        {
          m_uReps[i] = 0;
        }
       m_bIsLastCuRollBack = 0;
      }

      len = GetOptimumFast(&pos);

      if (!m_matchFinderBase.m_bEncOrg)
      {

        m_uAdditionalOffset -= len;

        if ((m_uAdditionalOffset == 0) && (MatchFinder_GetNumAvailableBytes(&m_matchFinderBase) == 0))
        {
          m_bIsLastCuRollBack = 1;
          break;
        }
        continue;
      }


      if (m_matchFinderBase.m_bEncOrg)
      {
        int dis = -1 ;
#if DEBUG_DICTCODER

        fprintf(m_pLenPos,"%d\t%d\t%d\t\n",nowPos32,len,pos);
#endif
        pCurBuf = MatchFinder_GetPointerToCurrentPos(&m_matchFinderBase) - m_uAdditionalOffset;


#if FORCE_PIXEL_MATCH
        if (len == 3 && pos == (UInt)-1)
#else
 				if(len == 1 && pos == (UInt)-1)
#endif
        {
        }
        else if (pos < NUM_REPS)
        {
          dis = m_uReps[pos];//pixel unit, starting from 0
          for (i=pos;i>0;i--)
          {
            m_uReps[i] = m_uReps[i-1];
          }

          m_uReps[0] = dis;

//#if FORCE_PIXEL_MATCH
//          assert((dis + 1) % 3 == 0);
//#endif
        }
        else
        {
          int posEnc = pos - NUM_REPS;
          for (i=NUM_REPS-1;i>0;i--)
          {
            m_uReps[i] = m_uReps[i-1];
          }
#if FORCE_PIXEL_FIX
          m_uReps[0] = UInt((posEnc + 1) / 3) - 1; //in pixel unit
#else
          m_uReps[0] = posEnc;
#endif
          dis = posEnc;
#if FORCE_PIXEL_MATCH
          assert((dis + 1) % 3 == 0);
          pos = NUM_REPS + UInt((posEnc + 1) / 3) - 1;// ZF pos shift// delta no need -1
#endif 
        }

#if TRY_LOSSY_MATCH   
        if (len != 1 && pos != (UInt)-1)
        {
          UInt  uLenTmp = len;
          UChar *pSrc, *pDst;
          pSrc = pCurBuf-dis-1;;
          pDst = pCurBuf;
          do 
          {
            *pDst++ = *pSrc++;
            uLenTmp--;
          } while (uLenTmp);
        }
#endif
#if SUPER_EXTEND_RUN
       assert(len >= 3 && len <= 4096 *3);
#endif
       WriteStrMapResult(len,pos,pCurBuf);


        m_uAdditionalOffset -= len;
        nowPos32 += len;

        if ((m_uAdditionalOffset == 0) && (MatchFinder_GetNumAvailableBytes(&m_matchFinderBase) == 0))
        {
          break;
        }
        continue;
      }
    }

    m_uNowPos64 += nowPos32 - startPos32;
    return ;
}
TComDictEnc::TComDictEnc()
{
  m_pDictEncoder = NULL;
  m_pReOrder = NULL;
  m_pCuBuf = NULL;
  m_pPackSizeBuf = NULL;
  m_bNeedRollBack = false; 
  m_bIsFirstRollBack = true;
#if MV_CODING
  m_bNeedResetEncoder = true;
#endif
  m_iDictCoderLevel = 4;
  m_iHashTableLevel = 8;
  m_iHashMethod = 0;
  m_uiStartPackPos = 0;
}

void CDictEncoder::DictEnc_SaveState()
{
//   CDictEncoder *p = (CDictEncoder *)pp;
  CSaveState *dest = &m_cSaveState;

  dest->mf = *(GetMatchFinderObj());
//   dest->m_uNowPos64 = m_uNowPos64;

  memcpy(dest->m_uReps, m_uReps, sizeof(m_uReps));
#if TRY_BACK_UP_HASHBASETABLE
  memcpy(m_pHashBaseBak,GetMatchFinderObj()->m_pHash,GetMatchFinderObj()->hashSizeSum*sizeof(UInt));
#endif

} 

void CDictEncoder::DictEnc_RestoreState()
{
	UChar * bufferBak;
// 	CDictEncoder *dest = (CDictEncoder *)pp;
	const CSaveState *p = &m_cSaveState;


	bufferBak = GetMatchFinderObj()->buffer; 
	SetMatchFinderObj(p->mf);
// 	m_uNowPos64 = p->m_uNowPos64;

	if (bufferBak < p->mf.buffer)
	{
		GetMatchFinderObj()->buffer = bufferBak - m_uCuLen;
	}
  memcpy(m_uReps, p->m_uReps, sizeof(p->m_uReps));

#if TRY_BACK_UP_HASHBASETABLE
  memcpy(GetMatchFinderObj()->m_pHash,m_pHashBaseBak,GetMatchFinderObj()->hashSizeSum*sizeof(UInt));
#endif
}

UInt TComDictEnc::xGetSSE()
{
  int i, iBlockLen;
  UChar* pOrg, * pCur;
  pOrg = m_pCuBuf;
  pCur = m_pDictEncoder->m_matchFinderBase.buffer - m_uCuLen;
  iBlockLen = m_uCuLen;

  UInt uiSum = 0;

  Int iTemp;

  for (i=0; i < iBlockLen; i++)
  {
    iTemp = pOrg[i] - pCur[i];
    uiSum += (iTemp * iTemp);
  }

  return ( uiSum );
}

void TComDictEnc::InitEncoder(TComSlice* pcSlice,UInt cuCnt)
{
  UInt frame_size;
  static int isFirst = 1;

  if (isFirst || m_bNeedResetEncoder)
  {
    isFirst = 0;
    m_bNeedResetEncoder = 0;
  }
  else 
  {
    return;
  }


  ChromaFormat chForm = pcSlice->getPic()->getChromaFormat();


  m_uCuWidth = pcSlice->getSPS()->getMaxCUWidth();
  m_uCuHeight = pcSlice->getSPS()->getMaxCUHeight();

  m_uPicWidth = pcSlice->getPic()->getPicYuvOrg()->getWidth(COMPONENT_Y);
  m_uPicHeight = pcSlice->getPic()->getPicYuvOrg()->getHeight(COMPONENT_Y);

  frame_size = m_uPicWidth*m_uPicHeight;

  if(chForm == CHROMA_444)
  {
    m_uCuLen = m_uCuWidth * m_uCuHeight * 3;
    m_uPicLen = frame_size*3;
  }
  else if (chForm == CHROMA_420)
  {
    m_uCuLen = m_uCuWidth * m_uCuHeight * 3 / 2;
    m_uPicLen = frame_size * 3 / 2;
  }
  else if(chForm == CHROMA_422)
  {
    m_uCuLen = m_uCuWidth * m_uCuHeight *  2;
    m_uPicLen = frame_size *  2;
  }
  else
  {
    printf("error chroma format!\n");
  }

  m_uPicLenPad = cuCnt * m_uCuLen;

  //input cu buffer
  if (m_pCuBuf == NULL)
  {
      m_pCuBuf = new UChar[m_uCuLen*sizeof(UChar)];
  }

  if (m_pPackSizeBuf == NULL)
  {
    m_pPackSizeBuf = new UInt[cuCnt*sizeof(UInt)];
  }
  memset(m_pPackSizeBuf,0,cuCnt*sizeof(int));

  if (m_pDictEncoder == NULL)
  {
      m_pDictEncoder = new CDictEncoder;
      m_pDictEncoder->m_uCuLen = m_uCuLen;
      m_pDictEncoder->m_iDictCoderLevel = m_iDictCoderLevel;
      m_pDictEncoder->m_iHashLength      = m_iHashTableLevel;
      m_pDictEncoder->m_iHashMethod      = m_iHashMethod;
      m_pDictEncoder->m_uiMatchDiffAllow = m_iP2MLossyLevel;
#if CRC_24_to_16
      m_pDictEncoder->m_pCRC             = m_pCRC;
#endif	  
#if MORE_NEW_HASH
      int i=0;
      for (i=0; i<3; i++)
        m_pDictEncoder->m_iHashBitDis[i]= m_iHashTableLevel<24 ? (m_pDictEncoder->m_iHashLength+2-i)/3 : 8;
#endif
  }

  m_pDictEncoder->Init(m_pCuBuf);

  if (m_pReOrder == NULL)
  {
    m_pReOrder = new TComReOrderData;
    m_pReOrder->InitPara(m_uCuWidth,m_uCuHeight,m_uCuLen,chForm);
  }
  
   m_uCuEncNumByLz = 0; //ZF no use
}

#if RESET_FIX
void TComDictEnc::ResetHash()
{
  //m_pDictEncoder->m_uNowPos64 = 0;
  //m_pDictEncoder->m_bFirst = true;
  if (m_pDictEncoder->m_matchFinderBase.m_pHash!= 0)
  {
    Int hashSize = m_pDictEncoder->m_matchFinderBase.hashSizeSum + m_pDictEncoder->m_matchFinderBase.numSons;
    memset(m_pDictEncoder->m_matchFinderBase.m_pHash, 0, sizeof(UInt)* hashSize);
  }
  //reset previous coded pos
  Int i = 0;
  for (i = 0; i < NUM_REPS; i++)
    m_pDictEncoder->m_uReps[i] = 0;

}
#endif


void TComDictEnc::CopyCuFromPicYuv(TComPic* pcPic,UChar* pDst ,UInt cuIdx,bool bEncOrg)
{
  int  i,j;
  int strideY, strideUV;
  UChar *pDstBase;

  Pel* pSrc;

  UInt cuYHeight = m_uCuHeight;
  UInt cuYWidth = m_uCuWidth;
  UInt cuUVHeight=0, cuUVWidth=0;
  //static UInt cuNumEncByLz = 0;

  UInt picWidth, picHeight, cuNumInWidth, cuNumInHeight;
  Double dBorderCuWidthScale,dBorderCuHeightScale;
  bool bBorderCuX = false,bBorderCuY = false;

  picWidth = pcPic->getPicYuvOrg()->getWidth(COMPONENT_Y);
  picHeight = pcPic->getPicYuvOrg()->getHeight(COMPONENT_Y);

  dBorderCuWidthScale = (Double)picWidth/(Double)m_uCuWidth - picWidth / m_uCuWidth;
  dBorderCuHeightScale  = (Double)picHeight / (Double)m_uCuHeight - picHeight/m_uCuHeight;

  cuNumInWidth = pcPic->getFrameWidthInCU();
  cuNumInHeight = pcPic->getFrameHeightInCU();

  bBorderCuX = (cuIdx % cuNumInWidth == (cuNumInWidth - 1)) ;
  bBorderCuY = (cuIdx / cuNumInWidth == (cuNumInHeight - 1));

  pDstBase = pDst;

  strideY = pcPic->getPicYuvOrg()->getStride(COMPONENT_Y);

  if (pcPic->getChromaFormat() == CHROMA_444)
  {
    cuUVWidth = cuYWidth;
    cuUVHeight = cuYHeight;
  }
  else if (pcPic->getChromaFormat() == CHROMA_420)
  {
    cuUVWidth = (cuYWidth>>1);
    cuUVHeight = (cuYHeight>>1);
  }
  else if (pcPic->getChromaFormat() == CHROMA_422)
  {
    cuUVWidth = (cuYWidth>>1);
    cuUVHeight = cuYHeight;
  }
  else
  {
    printf("error chroma format!\n");
  }
  
  strideUV = pcPic->getPicYuvOrg()->getStride(COMPONENT_Cb); 


  if (bEncOrg)
  {
    pSrc= pcPic->getPicYuvOrg()->getAddr(COMPONENT_Y,cuIdx);
  }
  else
  {
    pSrc= pcPic->getPicYuvRec()->getAddr(COMPONENT_Y,cuIdx);

  }



  for (i=0;i<cuYHeight;i++)
  {
    for (j=0;j<cuYWidth;j++)
    {
      *pDst++ = *(pSrc+j);
    }
    pSrc+=strideY;
  }
  if (bBorderCuX && dBorderCuWidthScale)
  {
    int padW = (int)(m_uCuWidth - m_uCuWidth*dBorderCuWidthScale);
    UChar * pTmp = pDst - cuYHeight*cuYWidth;
    for (i = 0 ;i < cuYHeight; i++)
    {
      memset(pTmp+(m_uCuWidth-padW),0,padW);
      pTmp += m_uCuWidth;
    }
    pTmp = NULL;
  }
  if (bBorderCuY && dBorderCuHeightScale)
  {
    int padH =(int)( m_uCuHeight - m_uCuHeight*dBorderCuHeightScale);
    UChar * pTmp = pDst - padH * m_uCuWidth;
    for (i=0;i<padH;i++)
    {
      memset(pTmp,0,m_uCuWidth);
      pTmp += m_uCuWidth;
    }
    pTmp = NULL;
  }

  //copy U data
  if (bEncOrg)
  {
    pSrc = pcPic->getPicYuvOrg()->getAddr(COMPONENT_Cb,cuIdx);	
  }
  else
  {
    pSrc = pcPic->getPicYuvRec()->getAddr(COMPONENT_Cb,cuIdx);	
  }

  for (i=0;i<cuUVHeight;i++)
  {
    for (j=0;j<cuUVWidth;j++)
    {
      *pDst++ = *(pSrc+j);
    }
    pSrc+=strideUV;
  }
  if (bBorderCuX && dBorderCuWidthScale)
  {
    int padW =(int)( cuUVWidth - cuUVWidth*dBorderCuWidthScale);
    UChar * pTmp = pDst - cuUVHeight*cuUVWidth;
    for (i = 0 ;i < cuUVHeight; i++)
    {
      memset(pTmp+(cuUVWidth-padW),0,padW);
      pTmp += cuUVWidth;
    }
    pTmp = NULL;
  }
  if (bBorderCuY && dBorderCuHeightScale)
  {
    int padH =(int)( cuUVHeight - cuUVHeight*dBorderCuHeightScale);
    UChar * pTmp = pDst - padH * cuUVWidth;
    for (i=0;i<padH;i++)
    {
      memset(pTmp,0,cuUVWidth);
      pTmp += cuUVWidth;
    }
    pTmp = NULL;
  }

  //copy V data
  if (bEncOrg)
  {
    pSrc = pcPic->getPicYuvOrg()->getAddr(COMPONENT_Cr,cuIdx);	
  }
  else
  {
    pSrc = pcPic->getPicYuvRec()->getAddr(COMPONENT_Cr,cuIdx);	
  }

  for (i=0;i<cuUVHeight;i++)
  {
    for (j=0;j<cuUVWidth;j++)
    {
      *pDst++ = *(pSrc+j);
    } 
    pSrc+=strideUV;
  } 

  if (bBorderCuX && dBorderCuWidthScale)
  {
    int padW =(int)( cuUVWidth - cuUVWidth*dBorderCuWidthScale);
    UChar * pTmp = pDst - cuUVHeight*cuUVWidth;
    for (i = 0 ;i < cuUVHeight; i++)
    {
      memset(pTmp+(cuUVWidth-padW),0,padW);
      pTmp += cuUVWidth;
    }
    pTmp = NULL;
  }
  if (bBorderCuY && dBorderCuHeightScale)
  {
    int padH =(int)( cuUVHeight - cuUVHeight*dBorderCuHeightScale);
    UChar * pTmp = pDst - padH * cuUVWidth;
    for (i=0;i<padH;i++)
    {
      memset(pTmp,0,cuUVWidth);
      pTmp += cuUVWidth;
    }
    pTmp = NULL;
  }
  //reorder data
#if REORDER_DATA
//   m_pReOrder->TranposeCu(m_pCuBuf);

  if (pcPic->getChromaFormat() == CHROMA_444)
  {
    m_pReOrder->ReOrderDataEncYuv444(m_pCuBuf);
  }
  else if (pcPic->getChromaFormat() == CHROMA_420)
  {
    m_pReOrder->ReOrderDataEncYuv420(m_pCuBuf,YUV420_REORDER_TYPE);
  }
  else if(pcPic->getChromaFormat() == CHROMA_422)
  {
    m_pReOrder->ReOrderDataEncYuv422(m_pCuBuf);
  }
  else
  {
    printf("error chroma format!\n");
  }
#endif

  m_pDictEncoder->m_cSeqBufInStream.data = m_pCuBuf;
  m_pDictEncoder->m_cSeqBufInStream.rem = m_uCuLen;

}

void TComDictEnc::WriteCu2RecYuv(TComDataCU* pcCU, UInt cuIdx) 
{  
  int i,j, cuSize,chromaCuWidth=0, chromaCuHeight=0;
  int strideY, strideUV=0;
  Pel  *pDstY=NULL, *pDstU=NULL, *pDstV=NULL;
//  Pel * pSrcY,*pSrcU,*pSrcV;

  cuSize = m_uCuLen;

  pDstY = pcCU->getPic()->getPicYuvRec()->getAddr(COMPONENT_Y,cuIdx);
  pDstU = pcCU->getPic()->getPicYuvRec()->getAddr(COMPONENT_Cb,cuIdx);
  pDstV = pcCU->getPic()->getPicYuvRec()->getAddr(COMPONENT_Cr,cuIdx);

#if TRY_LOSSY_MATCH
  UChar * pSrcY = NULL,*pSrcU= NULL,*pSrcV =NULL;
  memcpy(m_pCuBuf,m_pDictEncoder->m_matchFinderBase.buffer - m_uCuLen, m_uCuLen);

  if (pcCU->getPic()->getChromaFormat() == CHROMA_444)//yuv444
  {

#if REORDER_DATA
    m_pReOrder->ReOrderDataDecYuv444(m_pCuBuf);
#endif
    pSrcY = m_pCuBuf;
    pSrcU = pSrcY + m_uCuWidth * m_uCuHeight;
    pSrcV = pSrcU + m_uCuWidth * m_uCuHeight;
  }
  else	if (pcCU->getPic()->getChromaFormat() == CHROMA_420)//yuv420
  {
#if REORDER_DATA
    m_pReOrder->ReOrderDataDecYuv420(m_pCuBuf,YUV420_REORDER_TYPE);
#endif
    pSrcY = m_pCuBuf;
    pSrcU = pSrcY + m_uCuWidth * m_uCuHeight;
    pSrcV = pSrcU + m_uCuWidth * m_uCuHeight / 4;
  }
  else	if(pcCU->getPic()->getChromaFormat() == CHROMA_422)//yuv422 
  {
#if REORDER_DATA
    m_pReOrder->ReOrderDataDecYuv422(m_pCuBuf);
#endif
    pSrcY = m_pCuBuf;
    pSrcU = pSrcY + m_uCuWidth * m_uCuHeight;
    pSrcV = pSrcU + m_uCuWidth * m_uCuHeight / 2;
  }
  else
  {
    printf("error chroma format!\n");
  }
#else
    Pel * pSrcY,*pSrcU,*pSrcV;
  pSrcY =	pcCU->getPic()->getPicYuvOrg()->getAddr(COMPONENT_Y,cuIdx);
  pSrcU = pcCU->getPic()->getPicYuvOrg()->getAddr(COMPONENT_Cb,cuIdx);
  pSrcV = pcCU->getPic()->getPicYuvOrg()->getAddr(COMPONENT_Cr,cuIdx);
#endif

  strideY = pcCU->getPic()->getPicYuvRec()->getStride(COMPONENT_Y);

  if (pcCU->getPic()->getChromaFormat() == CHROMA_444)
  {
    strideUV = pcCU->getPic()->getPicYuvRec()->getStride(COMPONENT_Y);
    chromaCuWidth = m_uCuWidth;
    chromaCuHeight = m_uCuHeight; 
  }
  else if (pcCU->getPic()->getChromaFormat() == CHROMA_420)
  {
    strideUV = pcCU->getPic()->getPicYuvRec()->getStride(COMPONENT_Cb);
    chromaCuWidth = (m_uCuWidth>>1);
    chromaCuHeight = (m_uCuHeight>>1); 
  }
  else if (pcCU->getPic()->getChromaFormat() == CHROMA_422)
  {
    strideUV = pcCU->getPic()->getPicYuvRec()->getStride(COMPONENT_Cb);
    chromaCuWidth = (m_uCuWidth>>1);
    chromaCuHeight = m_uCuHeight; 
  }
  else
  {
    printf("error chroma format!\n");
  }
  


  //copy Y
  for (i=0;i<m_uCuWidth;i++)
  {
    for (j=0;j<m_uCuHeight;j++)
    {
      *pDstY++ = *pSrcY++;
    }
    pDstY += strideY - m_uCuWidth;
#if TRY_LOSSY_MATCH
#else
    pSrcY += strideY - m_uCuHeight;
#endif
  }

  //copy U
  for (i=0;i<chromaCuHeight;i++)
  {
    for(j=0;j<chromaCuWidth;j++)
    {
      *pDstU++ = *pSrcU++;
    }
    pDstU += strideUV - (chromaCuWidth);
#if TRY_LOSSY_MATCH
#else
    pSrcU += strideUV - (chromaCuWidth);
#endif
  }

  //copy V
  for (i=0;i<chromaCuHeight;i++)
  {
    for(j=0;j<chromaCuWidth;j++)
    {
      *pDstV++ = *pSrcV++;
    }
    pDstV += strideUV - (chromaCuWidth);
#if TRY_LOSSY_MATCH
#else
    pSrcV += strideUV - (chromaCuWidth);
#endif
  }
}

void TComDictEnc::destroy()
{
  if (m_pCuBuf)
  {
    delete[] m_pCuBuf;
    m_pCuBuf = NULL;
  }
  if(m_pPackSizeBuf)
  {
    delete[] m_pPackSizeBuf;
    m_pPackSizeBuf = NULL;
  }

  if (m_pDictEncoder)
  {
     m_pDictEncoder->MatchFinder_Free(&m_pDictEncoder->m_matchFinderBase);

     

    delete m_pDictEncoder;
    m_pDictEncoder = NULL;
  }

  if (m_pReOrder)
  {
    delete m_pReOrder;
    m_pReOrder = NULL;
  }
}

int CDictEncoder::GetPosSlotFunc(int pos)
{
  int posSlot;
  int kNumLogBits = 11;

  if (pos < 128)
    posSlot = m_pbFastPos[pos]; 
  else 
  {
    UInt i = 6 + ((kNumLogBits - 1) & (0 - (((((UInt)1 << (kNumLogBits + 6)) - 1) - pos) >> 31))); 
    posSlot = m_pbFastPos[pos >> i] + (i * 2); 

    /////////////////////////
    //FILE*fp;
    //fp = fopen("PosSlot.txt", "a");
    //for (Int k = 0; k < 128; k++)
    //{
    //  posSlot = m_pbFastPos[k];
    //  fprintf(fp, "%d %d\n", k, posSlot);
    //}
    //fclose(fp);
    /////////////////////

    /////////////////////////
    //FILE*fp;
    //fp = fopen("PosSlot.txt", "a");
    //for (Int k = 128; k < 4194304; k++)
    //{
    //  UInt t = 6 + ((kNumLogBits - 1) & (0 - (((((UInt)1 << (kNumLogBits + 6)) - 1) - k) >> 31)));
    // posSlot = m_pbFastPos[k >> t] + (t * 2);
    //  fprintf(fp, "%d %d\n", k, posSlot);
    //}
    //fclose(fp);
    /////////////////////
  }

 

  return posSlot;

}
#if MV_CODING
void TComDictEnc::WriteBitstreamDictEnc(UInt cuIdx, UInt cuEndIdx, TEncEntropy * pEncEty, UInt isLastCuRollBack, TComPic * rpcPic)
#else
#if POS_CODING
void TComDictEnc::WriteBitstreamDictEnc(UInt cuIdx, UInt cuEndIdx, TEncEntropy * pEncEty, UInt isLastCuRollBack, TComPic * rpcPic)
#else
void TComDictEnc::WriteBitstreamDictEnc( UInt cuIdx, UInt cuEndIdx, TEncEntropy * pEncEty, UInt isLastCuRollBack)
#endif
#endif
{

//#if Debug_Dict
//  Bool write_Flag = 1;
//  FILE*fp;
//  fp = fopen("Encoder_Syntax.txt", "a");
//  fprintf(fp, "LCU Addr: %4d \n", cuIdx);
//  fclose(fp);
//#endif
#if MV_CODING
  pEncEty->m_pcEntropyCoderIf->codeDictEnc(m_uiStartPackPos, m_uCuLen, m_pDictEncoder, cuIdx == cuEndIdx, isLastCuRollBack, cuIdx, rpcPic);
#else
#if POS_CODING
  pEncEty->m_pcEntropyCoderIf->codeDictEnc(m_uiStartPackPos, m_uCuLen, m_pDictEncoder, cuIdx == cuEndIdx, isLastCuRollBack, cuIdx, rpcPic/*, write_Flag*/);
#else
  pEncEty->m_pcEntropyCoderIf->codeDictEnc(m_uiStartPackPos, m_uCuLen, m_pDictEncoder, cuIdx == cuEndIdx, isLastCuRollBack);
#endif
#endif
   m_uiStartPackPos += m_pPackSizeBuf[cuIdx];

}

void TComDictEnc::DictCompressCu(UInt cuIdx, UInt cuEndIdx, bool bEncOrg, TComSlice* pcSlice)
{
  int idx,i;
  //int remained = 0;
  UInt frame_size;
  TComPic * pcPic = NULL;

  frame_size = m_uPicWidth * m_uPicHeight;

  pcPic = pcSlice->getPic();

 //  pcPic->getChromaFormat();

  if (m_bNeedRollBack)
  {
    if (bEncOrg)
    {
      idx = cuIdx;
    }
    else
    {
      idx = cuIdx+1;
    }
    m_pDictEncoder->DictEnc_RestoreState();

    m_pDictEncoder->m_uPrevPackSize -= m_pDictEncoder->m_uCurrPackSize;
    m_pPackSizeBuf[idx-1] = 0;

    for(i = 0 ;i < m_pDictEncoder->m_uCurrPackSize;i++)
    {
      m_pDictEncoder->m_pStrMapBufList.pop_back();
    }
    m_pDictEncoder->m_uCurrPackSize = 0;

  }
  if (m_pDictEncoder->m_uPrevPackSize)
  {
    m_pDictEncoder->m_bFirst = false;
  }	
  else if(m_bNeedRollBack)
  {
    if(m_bIsFirstRollBack)
    {
      m_bNeedResetEncoder = 1;
      InitEncoder(pcSlice, cuEndIdx+1);
      m_bIsFirstRollBack = false;
     }
  } 
  m_pDictEncoder->DictEnc_SaveState();

  CopyCuFromPicYuv(pcPic,m_pCuBuf, cuIdx,bEncOrg);

  m_pDictEncoder->m_matchFinderBase.m_bEncOrg = bEncOrg;

  m_pDictEncoder->m_uCuIdx = cuIdx;

  m_pDictEncoder->DictCodeOneBlock();

  m_pDictEncoder->m_uPrevPackSize += m_pDictEncoder->m_uCurrPackSize;
  m_pPackSizeBuf[cuIdx] = m_pDictEncoder->m_uCurrPackSize;
}
TComDictDec::TComDictDec()
{
  m_bFirst = true;
  m_pDecBuf = NULL;
  m_uNumUnitInCu = 0;
  m_pReOrder = NULL;
}

void TComDictDec::InitDecoder(TComSlice* pcSlice)
{
  int frame_size = 0;
  int cuCnt;
  if (m_bFirst)
  {
    m_bFirst = false;
  }
  else
    return;

  m_uPicWidth = pcSlice->getSPS()->getPicWidthInLumaSamples();
  m_uPicHeight = pcSlice->getSPS()->getPicHeightInLumaSamples();

  m_uCuWidth = pcSlice->getSPS()->getMaxCUWidth();
  m_uCuHeight = pcSlice->getSPS()->getMaxCUHeight();

  frame_size = m_uPicWidth * m_uPicHeight;

  ChromaFormat chForm = pcSlice->getPic()->getChromaFormat();
  if (chForm == CHROMA_444)
  {
    m_uCuLen = m_uCuWidth * m_uCuHeight * 3;
  }
  else if (chForm == CHROMA_420)
  {
    m_uCuLen = m_uCuWidth * m_uCuHeight * 3 / 2;
  }
  else if (chForm == CHROMA_422)
  {
    m_uCuLen = m_uCuWidth * m_uCuHeight *  2;
  }
  else
  {
    printf("error chroma format!\n");
  }

  cuCnt = pcSlice->getPic()->getPicSym()->getNumberOfCUsInFrame();

  m_uPicLenPad = cuCnt * m_uCuLen;
#if LARGE_DICT
  m_uNumUnitInCu = (1 << 24) / m_uCuLen + 1;
#else
  m_uNumUnitInCu = (1 << 22) / m_uCuLen + 1;
#endif
  if (m_pDecBuf == NULL)
  {
    m_pDecBuf = new UChar[m_uNumUnitInCu*m_uCuLen*2*sizeof(UChar)];
    memset(m_pDecBuf,0,m_uNumUnitInCu*m_uCuLen*2*sizeof(UChar));
  }
  if (m_pReOrder == NULL)
  {
    m_pReOrder = new TComReOrderData;
    m_pReOrder->InitPara(m_uCuWidth,m_uCuHeight,m_uCuLen,chForm);
  }
  

}
#if POS_CODING
void TComDictDec::DictDec_FastPosInit()
{
  int c = 2, slotFast;
  int kNumLogBits = 11;
  m_pbFastPos[0] = 0;
  m_pbFastPos[1] = 1;


  for (slotFast = 2; slotFast < kNumLogBits * 2; slotFast++)
  {
    UInt k = (1 << ((slotFast >> 1) - 1));
    UInt j;
    for (j = 0; j < k; j++, c++)
      m_pbFastPos[c] = (UChar)slotFast;
  }
}

int TComDictDec::GetPosSlotFunc(int pos)
{
  int posSlot;
  int kNumLogBits = 11;

  if (pos < 128)
    posSlot = m_pbFastPos[pos];
  else
  {
    UInt i = 6 + ((kNumLogBits - 1) & (0 - (((((UInt)1 << (kNumLogBits + 6)) - 1) - pos) >> 31)));
    posSlot = m_pbFastPos[pos >> i] + (i * 2);
  }

  return posSlot;
}
#endif

void TComDictDec::destroy()
{
  if (m_pDecBuf)
  {
    delete[] m_pDecBuf;
    m_pDecBuf = NULL;
  }
  if (m_pReOrder)
  {
    delete m_pReOrder;
    m_pReOrder = NULL;
  }
  

}

void TComReOrderData::ReOrderDataEncYuv422(UChar * pCuBuf)
{
  int i,j;
  UChar * pTmp;
  UChar * pY, *tY, *tU, *tV;
  bool bRowFirst = false;
  pTmp = new UChar[m_uCuLen*sizeof(UChar)];
  memcpy(pTmp,pCuBuf,m_uCuLen*sizeof(UChar));
  tY = pTmp;
  tU = tY + m_uCuWidth * m_uCuHeight;
  tV = tU + m_uCuWidth * m_uCuHeight / 2;

  pY = pCuBuf;

  if (bRowFirst)
  {
    //行序优先
    for (i = 0; i< m_uCuWidth*m_uCuHeight/2;i++)
    {
      *pY++ = *tY++;
      *pY++ = *tY++;
      *pY++ = *tU++;
      *pY++ = *tV++;
    }
  }
  else
  {
    //列序优先
    for (i = 0; i < m_uCuWidth/2; i++)
    {
      tY = pTmp+i*2;
      tU = pTmp + m_uCuWidth * m_uCuHeight+i;
      tV = pTmp + m_uCuWidth * m_uCuHeight * 3 / 2 + i;
      for (j = 0; j < m_uCuHeight; j++)
      {
        *pY++ = *tY;
        *pY++ = *(tY+1);
        *pY++ = *tU;
        *pY++ = *tV;
  
        tY += m_uCuWidth;
        tU += m_uCuWidth/2;
        tV += m_uCuWidth/2;
      }
    }
  }
  if(pTmp)
  {
    delete[] pTmp;
    pTmp = NULL;
  }
}
void TComReOrderData::ReOrderDataDecYuv422(UChar * pcuBuf)
{
  int i,j;
  UChar * pTmp;
  UChar * pY, *pU, *pV, *tY;
  bool bRowFirst = false;
  pTmp = new UChar[m_uCuLen*sizeof(UChar)];
  memcpy(pTmp,pcuBuf,m_uCuLen*sizeof(UChar));
  tY = pTmp;

  pY = pcuBuf;
  pU = pY + m_uCuWidth * m_uCuHeight;
  pV = pU + m_uCuWidth * m_uCuHeight/2;

  if(bRowFirst)
  {
    // 行序优先
    for (i = 0; i< m_uCuWidth*m_uCuHeight/2;i++)
    {
      *pY++ = *tY++;
      *pY++ = *tY++;
      *pU++ = *tY++;
      *pV++ = *tY++;
    }
  }
  else
  {
    //列序优先
    for (i = 0; i < m_uCuWidth/2; i++)
    {
      pY = pcuBuf + i*2;
      pU = pcuBuf + m_uCuWidth * m_uCuHeight + i;
      pV = pcuBuf + m_uCuWidth * m_uCuHeight * 3 / 2 + i;
      for (j = 0; j < m_uCuHeight; j++)
      {
        *pY = *tY++;
        *(pY+1) = *tY++;
        *pU = *tY++;
        *pV = *tY++;

        pY += m_uCuWidth;
        pU += m_uCuWidth/2;
        pV += m_uCuWidth/2;
      }
    }
  }
  

  if(pTmp)
  {
    delete[] pTmp;
    pTmp = NULL;
  }
}
void TComReOrderData::ReOrderDataEncYuv444(UChar * pCuBuf)
{
  int i;
  UChar * pTmp;
  UChar * pY, *tY, *tU, *tV;
#if !QC_Raster_Scan
  TranposeCu(pCuBuf);
#endif
  pTmp = new UChar[m_uCuLen*sizeof(UChar)];
  memcpy(pTmp,pCuBuf,m_uCuLen*sizeof(UChar));
  tY = pTmp;
  tU = tY + m_uCuWidth * m_uCuHeight;
  tV = tU + m_uCuWidth * m_uCuHeight;

  pY = pCuBuf;

  for (i = 0; i< m_uCuWidth*m_uCuHeight;i++)
  {
    *pY++ = *tY++;
    *pY++ = *tU++;
    *pY++ = *tV++;
  }

  if(pTmp)
  {
    delete[] pTmp;
    pTmp = NULL;
  }
}

void TComReOrderData::ReOrderDataDecYuv444(UChar * pcuBuf)
{
  int i;
  UChar * pTmp;
  UChar * pY, *pU, *pV, *tY, *tU, *tV;
  pTmp = new UChar[m_uCuLen*sizeof(UChar)];
  memcpy(pTmp,pcuBuf,m_uCuLen*sizeof(UChar));
  tY = pTmp;
  tU = tY+1;
  tV = tY+2;

  pY = pcuBuf;
  pU = pY + m_uCuWidth * m_uCuHeight;
  pV = pU + m_uCuWidth * m_uCuHeight;


  for (i = 0; i< m_uCuWidth*m_uCuHeight;i++)
  {
    *pY++ = *tY;
    *pU++ = *tU;
    *pV++ = *tV;
    tY += 3;
    tU += 3;
    tV += 3;
  }
#if ! QC_Raster_Scan
  TranposeCu(pcuBuf);
#endif
  if(pTmp)
  {
    delete[] pTmp;
    pTmp = NULL;
  }
}
void TComReOrderData::InitPara(UInt cuWidth, UInt cuHeight, UInt cuLen, ChromaFormat chForm)
{
  m_uCuWidth = cuWidth;
  m_uCuHeight = cuHeight;
  m_uCuLen = cuLen;
  m_eChForm = chForm;
}
void TComReOrderData::TranposeCu(UChar * pCuBuf)
{
  int wdt,hgt,i,j;
  UChar *pY = NULL;//ZF
  UChar *pU = NULL; 
  UChar *pV = NULL;
  UChar *pTmp=NULL,*tY=NULL,*tU=NULL,*tV=NULL;
  UInt cuSizeY = m_uCuWidth * m_uCuHeight;
  pTmp = new UChar[m_uCuLen*sizeof(UChar)];
  memcpy(pTmp,pCuBuf,m_uCuLen*sizeof(UChar));


  pY = pCuBuf;
  pU = pY + cuSizeY;
  if (m_eChForm == CHROMA_444)
  {
    pV = pU + cuSizeY;
  }
  else if(m_eChForm == CHROMA_420)
  {
    pV = pU + (cuSizeY>>2);
  }
  else
  {
    printf("error chroma format!\n");
  }



  wdt = hgt = m_uCuWidth;
  
  for (i=0;i<wdt;i++)
  {
    tY = pTmp + i;
    for (j=0;j<hgt;j++)
    {
      *pY++ = *tY;
      tY += wdt;
    }
  }

  if (m_eChForm == CHROMA_420)
  {
    wdt >>= 1;
    hgt >>= 1;
  }

  for (i=0;i<wdt;i++)
  {
    tU = pTmp + cuSizeY + i;
    for (j=0;j<hgt;j++)
    {
      *pU++ = *tU;
      tU += wdt;
    } 
  }
  for (i=0;i<wdt;i++)
  {
    if (m_eChForm == CHROMA_444)
    {
          tV = pTmp + cuSizeY*2  + i;
    }
    else if (m_eChForm == CHROMA_420)
    {
          tV = pTmp + cuSizeY + cuSizeY/4 + i;
    }
    else
    {
      printf("error chroma format!\n");
    }

    for (j=0;j<hgt;j++)
    {
      *pV++ = *tV;
      tV += wdt;
    }
  }
  if (pTmp)
  {
    delete[] pTmp;
    pTmp = NULL;
  }
}

void TComReOrderData::ReOrderDataEncYuv420(UChar * pcuBuf, UInt flag)
{
  int i,j,k;
  UChar * pY,*pU,*pV;
  UChar * pTmp, *tY, *tY1, *tY2, *tU,*tV;
  UInt cuSizeY = m_uCuWidth*m_uCuHeight;

  TranposeCu(pcuBuf);

  pTmp = new UChar[m_uCuLen*sizeof(UChar)];
  pY = pcuBuf;
  pU = pY + cuSizeY;
  pV = pU + (cuSizeY>>2);

  tY = pTmp;
  tU = pTmp + cuSizeY;
  tV = tU + (cuSizeY>>2);

  memcpy(tY, pY, cuSizeY*3/2);

  switch(flag)
  {
  case 1:
    for (i=0;i<cuSizeY/4;i++)
    {
      *pU++ = *tU++;
      *pU++ = *tV++;
    }
    break;
  case 2:
    tY1 = tY;
    tY2 = tY + m_uCuWidth;

    for (i=0;i<cuSizeY/4;i++)
    {
      *pY++ = *tY1++;
      *pY++ = *tY1++;
      *pY++ = *tY2++;
      *pY++ = *tY2++;

      *pY++ = *tU++;
      *pY++ = *tV++;

      if ((i+1)%(m_uCuWidth/2)  == 0)
      {
        tY1 += m_uCuWidth;
        tY2 += m_uCuWidth;
      }
    }
    break;
  case 3:
    tY1 = tY;
    tY2 = tY + m_uCuWidth;

    for (i=0;i<cuSizeY/4;i++)
    {
      *pY++ = *tY1++;
      *pY++ = *tU;
      *pY++ = *tV;

      *pY++ = *tY1++;
      *pY++ = *tU;
      *pY++ = *tV;

      *pY++ = *tY2++;
      *pY++ = *tU;
      *pY++ = *tV;

      *pY++ = *tY2++;
      *pY++ = *tU++;
      *pY++ = *tV++;

      if ((i+1)%(m_uCuWidth/2)  == 0)
      {
        tY1 += m_uCuWidth;
        tY2 += m_uCuWidth;
      }
    }
    break;
  case 4:
    tY1 = tY;
    for (i=0;i<m_uCuWidth/2;i++)
    {
      for (j=0;j<m_uCuWidth/2;j++)
      {
        *pY++ = *tY1++;
        *pY++ = *tY1++;
        *pY++ = *tU++;
        *pY++ = *tV++;
      }
      for (k=0;k<m_uCuWidth/2;k++)
      {
        *pY++ = *tY1++;
        *pY++ = *tY1++;
      }
    }
    break;
  default:
    break;
  }
  if (pTmp)
  {
    delete[] pTmp;
    pTmp = NULL;
  }
}

void TComReOrderData::ReOrderDataDecYuv420(UChar * pcuBuf, UInt flag)
{
  int i,j,k;
  UChar * pY,*pU,*pV;
  UChar *pTmp, *tY,*tY1,*tY2,*tU,*tV;
  UInt cuSizeY = m_uCuWidth*m_uCuHeight;
  pTmp = new UChar[m_uCuLen*sizeof(UChar)];
  pY = pcuBuf;
  pU = pY + cuSizeY;
  pV = pU + (cuSizeY>>2);

  tY = pTmp;
  tU = tY + cuSizeY;
  tV = tU + (cuSizeY>>2);

  switch(flag)
  {
  case 1:
    for (i=0;i<cuSizeY/4;i++)
    {
      *tU++ = *pU++;
      *tV++ = *pU++;
    }
    memcpy(pY+cuSizeY,tY+cuSizeY,cuSizeY/2);
    break;
  case 2:
    tY1 = tY;
    tY2 = tY + m_uCuWidth;

    for (i=0;i<cuSizeY/4;i++)
    {
      *tY1++ = *pY++;
      *tY1++ = *pY++ ;
      *tY2++ = *pY++ ;
      *tY2++ = *pY++;

      *tU++ = *pY++ ;
      *tV++ = *pY++ ;

      if ((i+1)%(m_uCuWidth/2) == 0)
      {
        tY1 += m_uCuWidth;
        tY2 += m_uCuWidth;
      }

    }
    memcpy(pcuBuf,tY,cuSizeY*3/2);
    break;
  case 3:
    tY1 = tY;
    tY2 = tY + m_uCuWidth;

    for (i=0;i<cuSizeY/4;i++)
    {
      *tY1++ = *pY++;
      *tU = *pY++;
      *tV = *pY++;

      *tY1++ = *pY++;
      *tU = *pY++;
      *tV = *pY++;

      *tY2++ = *pY++;
      *tU = *pY++;
      *tV = *pY++;

      *tY2++ = *pY++;
      *tU++ = *pY++;
      *tV++ = *pY++;

      if ((i+1)%(m_uCuWidth/2)  == 0)
      {
        tY1 += m_uCuWidth;
        tY2 += m_uCuWidth;
      }
    }
    memcpy(pcuBuf,tY,cuSizeY*3/2);
    break;
  case 4:
    tY1 = tY;
    for (i=0;i<m_uCuWidth/2;i++)
    {
      for (j=0;j<m_uCuWidth/2;j++)
      {
        *tY1++ = *pY++ ;
        *tY1++ = *pY++;
        *tU++ = *pY++;
        *tV++ = *pY++;
      }
      for (k=0;k<m_uCuWidth/2;k++)
      {
        *tY1++ = *pY++;
        *tY1++ = *pY++;
      }
    }
    memcpy(pcuBuf,tY,cuSizeY*3/2);
    break;
  default:
    break;
  }

  TranposeCu(pcuBuf);

  if (pTmp)
  {
    delete[] pTmp;
    pTmp = NULL;
  }
}

void TComDictDec::CopyCu2Dic(TComPic * pcPic, UInt cuIdx, UInt cuIdxDic, UChar * dstBase)
{
  Pel * pSrcY, *pSrcU, *pSrcV;
  UInt strideY, strideUV, i, j, cuSizeY,uvCuWidth=0, uvCuHeight=0;
  UChar * pDst=NULL, *pDstY=NULL, *pDstU=NULL, *pDstV=NULL;

  cuSizeY = m_uCuWidth * m_uCuHeight;
  
  pSrcY = pcPic->getPicYuvRec()->getAddr(COMPONENT_Y,cuIdx);
  pSrcU = pcPic->getPicYuvRec()->getAddr(COMPONENT_Cb,cuIdx);
  pSrcV = pcPic->getPicYuvRec()->getAddr(COMPONENT_Cr,cuIdx);

  strideY = pcPic->getPicYuvRec()->getStride(COMPONENT_Y);
  strideUV = pcPic->getPicYuvRec()->getStride(COMPONENT_Cb);

  pDst = dstBase + cuIdxDic * m_uCuLen;
  pDstY = pDst;
  pDstU = pDstY + cuSizeY;

  if (pcPic->getChromaFormat() == CHROMA_444)
  {
    pDstV = pDstU + cuSizeY;
    uvCuWidth = uvCuHeight = m_uCuWidth;
  }
  else if (pcPic->getChromaFormat() == CHROMA_420)
  {
    pDstV = pDstU + (cuSizeY>>2);
    uvCuWidth = uvCuHeight = (m_uCuWidth>>1);
  }
  else if (pcPic->getChromaFormat() == CHROMA_422)
  {
    pDstV = pDstU + (cuSizeY>>1);
    uvCuWidth = (m_uCuWidth>>1);
    uvCuHeight = m_uCuHeight;
  }
  else
  {
    printf("error chroma format!\n");
  }


  for (i=0;i<m_uCuHeight;i++)
  {
    for (j=0;j<m_uCuWidth;j++)
    {
      *pDstY++ = *pSrcY++;
    }
    pSrcY += strideY - m_uCuWidth;
  }

  for (i=0;i<uvCuHeight;i++)
  {
    for (j=0;j<uvCuWidth;j++)
    {
      *pDstU++ = *pSrcU++;
    }
    pSrcU += strideUV - uvCuWidth;
  }

  for (i=0;i<uvCuHeight;i++)
  {
    for (j=0;j<uvCuWidth;j++)
    {
      *pDstV++ = *pSrcV++;
    }
    pSrcV += strideUV - uvCuWidth;
  }
      
#if REORDER_DATA

//   m_pReOrder->TranposeCu(pDst);

  if (pcPic->getChromaFormat() == CHROMA_444)
  {
    m_pReOrder->ReOrderDataEncYuv444(pDst);
  }
  else if (pcPic->getChromaFormat() == CHROMA_420)
  {
    m_pReOrder->ReOrderDataEncYuv420(pDst,YUV420_REORDER_TYPE);
  }
  else if (pcPic->getChromaFormat() == CHROMA_422)
  {
    m_pReOrder->ReOrderDataEncYuv422(pDst);
  }
  else
  {
    printf("error chroma format!\n");
  }
#endif
  
}

void TComDictEnc::ResetForNewPic(int cuCnt)
{
  m_pDictEncoder->m_uPrevPackSize = 0;
  m_pDictEncoder->m_pStrMapBufList.clear();
  m_uiStartPackPos = 0;
}

void TComDictDec::WriteCu2Pic(TComPic* pcPic, UInt cuIdx, UInt cuIdxDic, UChar * pDecBuf) 
{ 
  int i,j, cuSizeY,uvCuWidth=0,uvCuHeight=0;
  int strideY, strideUV=0;
  Pel  *pDstY, *pDstU, *pDstV;
  UChar * pSrcY=NULL,*pSrcU=NULL,*pSrcV=NULL, *pTmp=NULL;

  cuSizeY = m_uCuWidth*m_uCuHeight;

  pDstY = pcPic->getPicYuvRec()->getAddr(COMPONENT_Y,cuIdx);
  pDstU = pcPic->getPicYuvRec()->getAddr(COMPONENT_Cb,cuIdx);
  pDstV = pcPic->getPicYuvRec()->getAddr(COMPONENT_Cr,cuIdx);

  strideY = pcPic->getPicYuvRec()->getStride(COMPONENT_Y);

  pSrcY = pDecBuf + cuIdxDic*m_uCuLen;

  pTmp = new UChar[m_uCuLen*sizeof(UChar)];
  memcpy(pTmp,pSrcY,m_uCuLen);

#if REORDER_DATA

  if (pcPic->getChromaFormat() == CHROMA_444)
  {
      m_pReOrder->ReOrderDataDecYuv444(pTmp);
  }
  else if (pcPic->getChromaFormat() == CHROMA_420)
  {
      m_pReOrder->ReOrderDataDecYuv420(pTmp,2);
  }
  else if (pcPic->getChromaFormat() == CHROMA_422)
  {
    m_pReOrder->ReOrderDataDecYuv422(pTmp);
  }
  else
  {
    printf("error chroma format!\n");
  }

//   m_pReOrder->TranposeCu(pTmp);
#endif

  pSrcY = pTmp;

  pSrcU = pSrcY + cuSizeY;

  if (pcPic->getChromaFormat() == CHROMA_444)
  {
    pSrcV = pSrcU + cuSizeY;
    uvCuWidth = uvCuHeight = m_uCuWidth;
    strideUV = pcPic->getPicYuvRec()->getStride(COMPONENT_Y);
  }
  else if (pcPic->getChromaFormat() == CHROMA_420)
  {
    pSrcV = pSrcU + (cuSizeY>>2);
    uvCuWidth = uvCuHeight = (m_uCuWidth>>1);
    strideUV = pcPic->getPicYuvRec()->getStride(COMPONENT_Cb);
  }
  else if (pcPic->getChromaFormat() == CHROMA_422)
  {
    pSrcV = pSrcU + (cuSizeY>>1);
    uvCuWidth = (m_uCuWidth>>1);
    uvCuHeight = m_uCuHeight;
    strideUV = pcPic->getPicYuvRec()->getStride(COMPONENT_Cb);
  }

  //copy Y
  for (i=0;i<m_uCuHeight;i++)
  {
    for (j=0;j<m_uCuWidth;j++)
    {
      *pDstY++ = *pSrcY++;
    }
    pDstY += strideY - m_uCuWidth;
  } 

  //copy U
  for (i=0;i<uvCuHeight;i++)
  {
    for(j=0;j<uvCuWidth;j++)
    {
      *pDstU++ = *pSrcU++;
    }
    pDstU += strideUV - uvCuWidth;
  }

  //copy V
  for (i=0;i<uvCuHeight;i++)
  {
    for(j=0;j<uvCuWidth;j++)
    {
      *pDstV++ = *pSrcV++;
    }
    pDstV += strideUV - uvCuWidth;
  } 

  //release temp buffer
  if (pTmp)
  {
    delete[] pTmp;
    pTmp = NULL;
  }
}  
#endif
