Beispiel #1
0
            private uint GetOptimum(uint position, out uint backRes)
            {
                OptimumReps reps = new OptimumReps();
                P<uint> matches;
                uint numAvail;
                uint lenEnd;

                {
                    if (mOptimumEndIndex != mOptimumCurrentIndex)
                    {
                        COptimal opt = mOpt[mOptimumCurrentIndex];
                        uint lenRes = opt.mPosPrev - mOptimumCurrentIndex;
                        backRes = opt.mBackPrev;
                        mOptimumCurrentIndex = opt.mPosPrev;
                        return lenRes;
                    }

                    mOptimumCurrentIndex = 0;
                    mOptimumEndIndex = 0;

                    uint mainLen, numPairs;
                    if (mAdditionalOffset == 0)
                    {
                        mainLen = ReadMatchDistances(out numPairs);
                    }
                    else
                    {
                        mainLen = mLongestMatchLength;
                        numPairs = mNumPairs;
                    }

                    numAvail = mNumAvail;
                    if (numAvail < 2)
                    {
                        backRes = ~0u;
                        return 1;
                    }
                    if (numAvail > LZMA_MATCH_LEN_MAX)
                        numAvail = LZMA_MATCH_LEN_MAX;

                    P<byte> data = mMatchFinder.GetPointerToCurrentPos(mMatchFinderObj) - 1;
                    OptimumReps repLens = new OptimumReps();
                    uint repMaxIndex = 0;
                    for (uint i = 0; i < LZMA_NUM_REPS; i++)
                    {
                        reps[i] = mReps[i];
                        TR("GetOptimum:reps[i]", reps[i]);
                        P<byte> data2 = data - (reps[i] + 1);
                        if (data[0] != data2[0] || data[1] != data2[1])
                        {
                            repLens[i] = 0;
                            continue;
                        }

                        uint lenTest = 2;
                        while (lenTest < numAvail && data[lenTest] == data2[lenTest])
                            lenTest++;

                        repLens[i] = lenTest;
                        if (lenTest > repLens[repMaxIndex])
                            repMaxIndex = i;
                    }

                    if (repLens[repMaxIndex] >= mNumFastBytes)
                    {
                        uint lenRes;
                        backRes = repMaxIndex;
                        lenRes = repLens[repMaxIndex];
                        MovePos(lenRes - 1);
                        return lenRes;
                    }

                    matches = mMatches;
                    if (mainLen >= mNumFastBytes)
                    {
                        backRes = matches[numPairs - 1] + LZMA_NUM_REPS;
                        MovePos(mainLen - 1);
                        return mainLen;
                    }

                    byte curByte = data[0];
                    byte matchByte = (data - (reps._0 + 1))[0];

                    if (mainLen < 2 && curByte != matchByte && repLens[repMaxIndex] < 2)
                    {
                        backRes = ~0u;
                        return 1;
                    }

                    mOpt[0].mState = mState;

                    uint posState = (position & mPbMask);

                    {
                        P<ushort> probs = LIT_PROBS(position, (data - 1)[0]);
                        mOpt[1].mPrice = GET_PRICE_0(mIsMatch[mState][posState]) +
                            (!IsCharState(mState) ?
                              LitEnc_GetPriceMatched(probs, curByte, matchByte, mProbPrices) :
                              LitEnc_GetPrice(probs, curByte, mProbPrices));
                    }

                    mOpt[1].MakeAsChar();

                    uint matchPrice = GET_PRICE_1(mIsMatch[mState][posState]);
                    uint repMatchPrice = matchPrice + GET_PRICE_1(mIsRep[mState]);

                    if (matchByte == curByte)
                    {
                        uint shortRepPrice = repMatchPrice + GetRepLen1Price(mState, posState);
                        if (shortRepPrice < mOpt[1].mPrice)
                        {
                            mOpt[1].mPrice = shortRepPrice;
                            mOpt[1].MakeAsShortRep();
                        }
                    }
                    lenEnd = ((mainLen >= repLens[repMaxIndex]) ? mainLen : repLens[repMaxIndex]);

                    if (lenEnd < 2)
                    {
                        backRes = mOpt[1].mBackPrev;
                        return 1;
                    }

                    mOpt[1].mPosPrev = 0;
                    mOpt[0].mBacks = reps;

                    uint len = lenEnd;
                    do { mOpt[len--].mPrice = kInfinityPrice; }
                    while (len >= 2);

                    for (uint i = 0; i < LZMA_NUM_REPS; i++)
                    {
                        uint repLen = repLens[i];
                        if (repLen < 2)
                            continue;
                        uint price = repMatchPrice + GetPureRepPrice(i, mState, posState);
                        do
                        {
                            uint curAndLenPrice = price + mRepLenEnc.mPrices[posState][repLen - 2];
                            COptimal opt = mOpt[repLen];
                            if (curAndLenPrice < opt.mPrice)
                            {
                                opt.mPrice = curAndLenPrice;
                                opt.mPosPrev = 0;
                                opt.mBackPrev = i;
                                opt.mPrev1IsChar = false;
                            }
                        }
                        while (--repLen >= 2);
                    }

                    uint normalMatchPrice = matchPrice + GET_PRICE_0(mIsRep[mState]);

                    len = ((repLens._0 >= 2) ? repLens._0 + 1 : 2);
                    if (len <= mainLen)
                    {
                        uint offs = 0;
                        while (len > matches[offs])
                            offs += 2;
                        for (; ; len++)
                        {
                            uint distance = matches[offs + 1];

                            uint curAndLenPrice = normalMatchPrice + mLenEnc.mPrices[posState][len - LZMA_MATCH_LEN_MIN];
                            uint lenToPosState = GetLenToPosState(len);
                            if (distance < kNumFullDistances)
                            {
                                curAndLenPrice += mDistancesPrices[lenToPosState][distance];
                            }
                            else
                            {
                                uint slot = GetPosSlot2(distance);
                                curAndLenPrice += mAlignPrices[distance & kAlignMask] + mPosSlotPrices[lenToPosState][slot];
                            }

                            COptimal opt = mOpt[len];
                            if (curAndLenPrice < opt.mPrice)
                            {
                                opt.mPrice = curAndLenPrice;
                                opt.mPosPrev = 0;
                                opt.mBackPrev = distance + LZMA_NUM_REPS;
                                opt.mPrev1IsChar = false;
                            }
                            if (len == matches[offs])
                            {
                                offs += 2;
                                if (offs == numPairs)
                                    break;
                            }
                        }
                    }
                }

                uint cur = 0;

#if SHOW_STAT2
                if(position >= 0)
                {
                    Print("\n pos = {0:X4}", position);
                    for(uint j = cur; j <= lenEnd; j++)
                        Print("\nprice[{0:X4}] = {1}", position - cur + j, mOpt[j].mPrice);
                }
#endif
                //TR("GetOptimum::pos", position);
                //if(position >= 0)
                //{
                //    TR("GetOptimum::cur", cur);
                //    for(uint j = cur; j <= lenEnd; j++)
                //        TR("GetOptimum::price[i]", mOpt[j].price);
                //}

                for (;;)
                {
                    cur++;
                    if (cur == lenEnd)
                        return Backward(out backRes, cur);

                    uint numPairs;
                    uint newLen = ReadMatchDistances(out numPairs);
                    if (newLen >= mNumFastBytes)
                    {
                        mNumPairs = numPairs;
                        mLongestMatchLength = newLen;
                        return Backward(out backRes, cur);
                    }
                    position++;

                    uint state;
                    COptimal curOpt = mOpt[cur];
                    uint posPrev = curOpt.mPosPrev;
                    if (curOpt.mPrev1IsChar)
                    {
                        posPrev--;
                        if (curOpt.mPrev2)
                        {
                            state = mOpt[curOpt.mPosPrev2].mState;
                            if (curOpt.mBackPrev2 < LZMA_NUM_REPS)
                                state = kRepNextStates[state];
                            else
                                state = kMatchNextStates[state];
                        }
                        else
                        {
                            state = mOpt[posPrev].mState;
                        }
                        state = kLiteralNextStates[state];
                    }
                    else
                    {
                        state = mOpt[posPrev].mState;
                    }
                    if (posPrev == cur - 1)
                    {
                        if (curOpt.IsShortRep())
                            state = kShortRepNextStates[state];
                        else
                            state = kLiteralNextStates[state];
                    }
                    else
                    {
                        uint pos;
                        if (curOpt.mPrev1IsChar && curOpt.mPrev2)
                        {
                            posPrev = curOpt.mPosPrev2;
                            pos = curOpt.mBackPrev2;
                            state = kRepNextStates[state];
                        }
                        else
                        {
                            pos = curOpt.mBackPrev;
                            if (pos < LZMA_NUM_REPS)
                                state = kRepNextStates[state];
                            else
                                state = kMatchNextStates[state];
                        }
                        COptimal prevOpt = mOpt[posPrev];
                        if (pos < LZMA_NUM_REPS)
                        {
                            reps._0 = prevOpt.mBacks[pos];
                            uint i = 1;
                            for (; i <= pos; i++)
                                reps[i] = prevOpt.mBacks[i - 1];
                            for (; i < LZMA_NUM_REPS; i++)
                                reps[i] = prevOpt.mBacks[i];
                        }
                        else
                        {
                            reps._0 = pos - LZMA_NUM_REPS;
                            reps._1 = prevOpt.mBacks._0;
                            reps._2 = prevOpt.mBacks._1;
                            reps._3 = prevOpt.mBacks._2;
                        }
                    }
                    curOpt.mState = state;
                    curOpt.mBacks = reps;

                    uint curPrice = curOpt.mPrice;
                    bool nextIsChar = false;
                    P<byte> data = mMatchFinder.GetPointerToCurrentPos(mMatchFinderObj) - 1;
                    byte curByte = data[0];
                    byte matchByte = (data - (reps._0 + 1))[0];

                    uint posState = (position & mPbMask);

                    uint curAnd1Price = curPrice + GET_PRICE_0(mIsMatch[state][posState]);
                    {
                        P<ushort> probs = LIT_PROBS(position, data[-1]);
                        if (!IsCharState(state))
                            curAnd1Price += LitEnc_GetPriceMatched(probs, curByte, matchByte, mProbPrices);
                        else
                            curAnd1Price += LitEnc_GetPrice(probs, curByte, mProbPrices);
                    }

                    COptimal nextOpt = mOpt[cur + 1];

                    if (curAnd1Price < nextOpt.mPrice)
                    {
                        nextOpt.mPrice = curAnd1Price;
                        nextOpt.mPosPrev = cur;
                        nextOpt.MakeAsChar();
                        nextIsChar = true;
                    }

                    uint matchPrice = curPrice + GET_PRICE_1(mIsMatch[state][posState]);
                    uint repMatchPrice = matchPrice + GET_PRICE_1(mIsRep[state]);

                    if (matchByte == curByte && !(nextOpt.mPosPrev < cur && nextOpt.mBackPrev == 0))
                    {
                        uint shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState);
                        if (shortRepPrice <= nextOpt.mPrice)
                        {
                            nextOpt.mPrice = shortRepPrice;
                            nextOpt.mPosPrev = cur;
                            nextOpt.MakeAsShortRep();
                            nextIsChar = true;
                        }
                    }

                    uint numAvailFull = Math.Min(mNumAvail, kNumOpts - 1 - cur);
                    if (numAvailFull < 2)
                        continue;

                    numAvail = (numAvailFull <= mNumFastBytes ? numAvailFull : mNumFastBytes);

                    if (!nextIsChar && matchByte != curByte) /* speed optimization */
                    {
                        /* try Literal + rep0 */
                        P<byte> data2 = data - (reps._0 + 1);
                        uint limit = mNumFastBytes + 1;
                        if (limit > numAvailFull)
                            limit = numAvailFull;

                        uint temp = 1;
                        while (temp < limit && data[temp] == data2[temp])
                            temp++;

                        uint lenTest2 = temp - 1;
                        if (lenTest2 >= 2)
                        {
                            uint state2 = kLiteralNextStates[state];
                            uint posStateNext = (position + 1) & mPbMask;
                            uint nextRepMatchPrice = curAnd1Price + GET_PRICE_1(mIsMatch[state2][posStateNext]) + GET_PRICE_1(mIsRep[state2]);
                            /* for (; lenTest2 >= 2; lenTest2--) */
                            {
                                uint offset = cur + 1 + lenTest2;
                                while (lenEnd < offset)
                                    mOpt[++lenEnd].mPrice = kInfinityPrice;
                                uint curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext);
                                COptimal opt = mOpt[offset];
                                if (curAndLenPrice < opt.mPrice)
                                {
                                    opt.mPrice = curAndLenPrice;
                                    opt.mPosPrev = cur + 1;
                                    opt.mBackPrev = 0;
                                    opt.mPrev1IsChar = true;
                                    opt.mPrev2 = false;
                                }
                            }
                        }
                    }

                    uint startLen = 2; /* speed optimization */

                    for (uint repIndex = 0; repIndex < LZMA_NUM_REPS; repIndex++)
                    {
                        P<byte> data2 = data - (reps[repIndex] + 1);
                        if (data[0] != data2[0] || data[1] != data2[1])
                            continue;

                        uint lenTest = 2;
                        while (lenTest < numAvail && data[lenTest] == data2[lenTest])
                            lenTest++;

                        while (lenEnd < cur + lenTest)
                            mOpt[++lenEnd].mPrice = kInfinityPrice;

                        uint lenTestTemp = lenTest;
                        uint price = repMatchPrice + GetPureRepPrice(repIndex, state, posState);
                        do
                        {
                            uint curAndLenPrice = price + mRepLenEnc.mPrices[posState][lenTest - 2];
                            COptimal opt = mOpt[cur + lenTest];
                            if (curAndLenPrice < opt.mPrice)
                            {
                                opt.mPrice = curAndLenPrice;
                                opt.mPosPrev = cur;
                                opt.mBackPrev = repIndex;
                                opt.mPrev1IsChar = false;
                            }
                        }
                        while (--lenTest >= 2);
                        lenTest = lenTestTemp;

                        if (repIndex == 0)
                            startLen = lenTest + 1;

                        {
                            uint lenTest2 = lenTest + 1;

                            uint limit = lenTest2 + mNumFastBytes;
                            if (limit > numAvailFull)
                                limit = numAvailFull;

                            while (lenTest2 < limit && data[lenTest2] == data2[lenTest2])
                                lenTest2++;

                            lenTest2 -= lenTest + 1;
                            if (lenTest2 >= 2)
                            {
                                uint state2 = kRepNextStates[state];
                                uint posStateNext = (position + lenTest) & mPbMask;
                                uint curAndLenCharPrice = price
                                    + mRepLenEnc.mPrices[posState][lenTest - 2]
                                    + GET_PRICE_0(mIsMatch[state2][posStateNext])
                                    + LitEnc_GetPriceMatched(
                                        LIT_PROBS(position + lenTest, data[lenTest - 1]),
                                        data[lenTest], data2[lenTest], mProbPrices);

                                state2 = kLiteralNextStates[state2];
                                posStateNext = (position + lenTest + 1) & mPbMask;
                                uint nextRepMatchPrice = curAndLenCharPrice
                                    + GET_PRICE_1(mIsMatch[state2][posStateNext])
                                    + GET_PRICE_1(mIsRep[state2]);

                                /* for (; lenTest2 >= 2; lenTest2--) */
                                {
                                    uint offset = cur + lenTest + 1 + lenTest2;
                                    while (lenEnd < offset)
                                        mOpt[++lenEnd].mPrice = kInfinityPrice;

                                    uint curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext);

                                    COptimal opt = mOpt[offset];
                                    if (curAndLenPrice < opt.mPrice)
                                    {
                                        opt.mPrice = curAndLenPrice;
                                        opt.mPosPrev = cur + lenTest + 1;
                                        opt.mBackPrev = 0;
                                        opt.mPrev1IsChar = true;
                                        opt.mPrev2 = true;
                                        opt.mPosPrev2 = cur;
                                        opt.mBackPrev2 = repIndex;
                                    }
                                }
                            }
                        }
                    }

                    /* for (uint lenTest = 2; lenTest <= newLen; lenTest++) */
                    if (newLen > numAvail)
                    {
                        newLen = numAvail;
                        numPairs = 0;
                        while (newLen > matches[numPairs])
                            numPairs += 2;
                        matches[numPairs] = newLen;
                        numPairs += 2;
                    }
                    if (newLen >= startLen)
                    {
                        uint normalMatchPrice = matchPrice + GET_PRICE_0(mIsRep[state]);

                        while (lenEnd < cur + newLen)
                            mOpt[++lenEnd].mPrice = kInfinityPrice;

                        uint offs = 0;
                        while (startLen > matches[offs])
                            offs += 2;

                        uint curBack = matches[offs + 1];
                        uint posSlot = GetPosSlot2(curBack);
                        for (uint lenTest = /*2*/ startLen; ; lenTest++)
                        {
                            uint curAndLenPrice = normalMatchPrice + mLenEnc.mPrices[posState][lenTest - LZMA_MATCH_LEN_MIN];
                            uint lenToPosState = GetLenToPosState(lenTest);
                            if (curBack < kNumFullDistances)
                                curAndLenPrice += mDistancesPrices[lenToPosState][curBack];
                            else
                                curAndLenPrice += mPosSlotPrices[lenToPosState][posSlot] + mAlignPrices[curBack & kAlignMask];

                            COptimal opt = mOpt[cur + lenTest];
                            if (curAndLenPrice < opt.mPrice)
                            {
                                opt.mPrice = curAndLenPrice;
                                opt.mPosPrev = cur;
                                opt.mBackPrev = curBack + LZMA_NUM_REPS;
                                opt.mPrev1IsChar = false;
                            }

                            if (lenTest == matches[offs])
                            {
                                /* Try Match + Literal + Rep0 */
                                P<byte> data2 = data - (curBack + 1);
                                uint lenTest2 = lenTest + 1;
                                uint limit = lenTest2 + mNumFastBytes;
                                uint nextRepMatchPrice;
                                if (limit > numAvailFull)
                                    limit = numAvailFull;

                                while (lenTest2 < limit && data[lenTest2] == data2[lenTest2])
                                    lenTest2++;

                                lenTest2 -= lenTest + 1;
                                if (lenTest2 >= 2)
                                {
                                    uint state2 = kMatchNextStates[state];
                                    uint posStateNext = (position + lenTest) & mPbMask;
                                    uint curAndLenCharPrice = curAndLenPrice
                                        + GET_PRICE_0(mIsMatch[state2][posStateNext])
                                        + LitEnc_GetPriceMatched(
                                            LIT_PROBS(position + lenTest, data[lenTest - 1]),
                                            data[lenTest], data2[lenTest], mProbPrices);

                                    state2 = kLiteralNextStates[state2];
                                    posStateNext = (posStateNext + 1) & mPbMask;
                                    nextRepMatchPrice = curAndLenCharPrice
                                        + GET_PRICE_1(mIsMatch[state2][posStateNext])
                                        + GET_PRICE_1(mIsRep[state2]);

                                    /* for (; lenTest2 >= 2; lenTest2--) */
                                    {
                                        uint offset = cur + lenTest + 1 + lenTest2;
                                        uint curAndLenPrice4;
                                        while (lenEnd < offset)
                                            mOpt[++lenEnd].mPrice = kInfinityPrice;
                                        curAndLenPrice4 = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext);
                                        COptimal opt4 = mOpt[offset];
                                        if (curAndLenPrice4 < opt4.mPrice)
                                        {
                                            opt4.mPrice = curAndLenPrice4;
                                            opt4.mPosPrev = cur + lenTest + 1;
                                            opt4.mBackPrev = 0;
                                            opt4.mPrev1IsChar = true;
                                            opt4.mPrev2 = true;
                                            opt4.mPosPrev2 = cur;
                                            opt4.mBackPrev2 = curBack + LZMA_NUM_REPS;
                                        }
                                    }
                                }

                                offs += 2;
                                if (offs == numPairs)
                                    break;

                                curBack = matches[offs + 1];
                                if (curBack >= kNumFullDistances)
                                    posSlot = GetPosSlot2(curBack);
                            }
                        }
                    }
                }
            }
Beispiel #2
0
            internal void LzmaEnc_Init()
            {
                TR("LzmaEnc_Init", 0);

                mState = 0;
                mReps = new OptimumReps();

                mRC.RangeEnc_Init();

                for (uint i = 0; i < kNumStates; i++)
                {
                    for (uint j = 0; j < LZMA_NUM_PB_STATES_MAX; j++)
                    {
                        mIsMatch[i][j] = kProbInitValue;
                        mIsRep0Long[i][j] = kProbInitValue;
                    }

                    mIsRep[i] = kProbInitValue;
                    mIsRepG0[i] = kProbInitValue;
                    mIsRepG1[i] = kProbInitValue;
                    mIsRepG2[i] = kProbInitValue;
                }

                uint n = 0x300u << (mLP + mLC);
                for (uint i = 0; i < n; i++)
                    mLitProbs[i] = kProbInitValue;

                for (uint i = 0; i < kNumLenToPosStates; i++)
                {
                    P<ushort> probs = mPosSlotEncoder[i];
                    for (uint j = 0; j < (1 << kNumPosSlotBits); j++)
                        probs[j] = kProbInitValue;
                }

                for (uint i = 0; i < kNumFullDistances - kEndPosModelIndex; i++)
                    mPosEncoders[i] = kProbInitValue;

                mLenEnc.LenEnc_Init();
                mRepLenEnc.LenEnc_Init();

                for (uint i = 0; i < (1 << kNumAlignBits); i++)
                    mPosAlignEncoder[i] = kProbInitValue;

                mOptimumEndIndex = 0;
                mOptimumCurrentIndex = 0;
                mAdditionalOffset = 0;

                mPbMask = (1u << mPB) - 1;
                mLpMask = (1u << mLP) - 1;
            }
Beispiel #3
0
            internal void LzmaEnc_RestoreState()
            {
                TR("LzmaEnc_RestoreState", 0);

                mLenEnc = new CLenPriceEnc(mSaveState.mLenEnc);
                mRepLenEnc = new CLenPriceEnc(mSaveState.mRepLenEnc);
                mState = mSaveState.mState;

                for (int i = 0; i < kNumStates; i++)
                {
                    memcpy(mIsMatch[i], mSaveState.mIsMatch[i], LZMA_NUM_PB_STATES_MAX * 2);
                    memcpy(mIsRep0Long[i], mSaveState.mIsRep0Long[i], LZMA_NUM_PB_STATES_MAX * 2);
                }

                for (int i = 0; i < kNumLenToPosStates; i++)
                    memcpy(mPosSlotEncoder[i], mSaveState.mPosSlotEncoder[i], (1 << kNumPosSlotBits) * 2);

                memcpy(mIsRep, mSaveState.mIsRep, kNumStates * 2);
                memcpy(mIsRepG0, mSaveState.mIsRepG0, kNumStates * 2);
                memcpy(mIsRepG1, mSaveState.mIsRepG1, kNumStates * 2);
                memcpy(mIsRepG2, mSaveState.mIsRepG2, kNumStates * 2);
                memcpy(mPosEncoders, mSaveState.mPosEncoders, (kNumFullDistances - kEndPosModelIndex) * 2);
                memcpy(mPosAlignEncoder, mSaveState.mPosAlignEncoder, (1 << kNumAlignBits) * 2);
                mReps = mSaveState.mReps;
                memcpy(mLitProbs, mSaveState.mLitProbs, (0x300 << mLcLp) * 2);
            }