
git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@6720 212acab6-be3b-0410-9dea-997c60f758d6
135 lines
3.4 KiB
C++
135 lines
3.4 KiB
C++
/*
|
|
* RangeCoderBit.h
|
|
*
|
|
* This file is a part of LZMA compression module for NSIS.
|
|
*
|
|
* Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov
|
|
* Modifications Copyright (C) 2003-2016 Amir Szekely <kichik@netvision.net.il>
|
|
*
|
|
* Licensed under the Common Public License version 1.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
*
|
|
* Licence details can be found in the file COPYING.
|
|
*
|
|
* This software is provided 'as-is', without any express or implied
|
|
* warranty.
|
|
*/
|
|
|
|
#ifndef __COMPRESS_RANGECODER_BIT_H
|
|
#define __COMPRESS_RANGECODER_BIT_H
|
|
|
|
#include "RangeCoder.h"
|
|
|
|
namespace NCompress {
|
|
namespace NRangeCoder {
|
|
|
|
const int kNumBitModelTotalBits = 11;
|
|
const UInt32 kBitModelTotal = (1 << kNumBitModelTotalBits);
|
|
|
|
const int kNumMoveReducingBits = 2;
|
|
|
|
const int kNumBitPriceShiftBits = 6;
|
|
const UInt32 kBitPrice = 1 << kNumBitPriceShiftBits;
|
|
|
|
class CPriceTables
|
|
{
|
|
public:
|
|
static UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits];
|
|
static void Init();
|
|
CPriceTables();
|
|
};
|
|
|
|
template <int numMoveBits>
|
|
class CBitModel
|
|
{
|
|
public:
|
|
UInt32 Prob;
|
|
void UpdateModel(UInt32 symbol)
|
|
{
|
|
/*
|
|
Prob -= (Prob + ((symbol - 1) & ((1 << numMoveBits) - 1))) >> numMoveBits;
|
|
Prob += (1 - symbol) << (kNumBitModelTotalBits - numMoveBits);
|
|
*/
|
|
if (symbol == 0)
|
|
Prob += (kBitModelTotal - Prob) >> numMoveBits;
|
|
else
|
|
Prob -= (Prob) >> numMoveBits;
|
|
}
|
|
public:
|
|
void Init() { Prob = kBitModelTotal / 2; }
|
|
};
|
|
|
|
template <int numMoveBits>
|
|
class CBitEncoder: public CBitModel<numMoveBits>
|
|
{
|
|
public:
|
|
void Encode(CEncoder *encoder, UInt32 symbol)
|
|
{
|
|
/*
|
|
encoder->EncodeBit(this->Prob, kNumBitModelTotalBits, symbol);
|
|
this->UpdateModel(symbol);
|
|
*/
|
|
UInt32 newBound = (encoder->Range >> kNumBitModelTotalBits) * this->Prob;
|
|
if (symbol == 0)
|
|
{
|
|
encoder->Range = newBound;
|
|
this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits;
|
|
}
|
|
else
|
|
{
|
|
encoder->Low += newBound;
|
|
encoder->Range -= newBound;
|
|
this->Prob -= (this->Prob) >> numMoveBits;
|
|
}
|
|
if (encoder->Range < kTopValue)
|
|
{
|
|
encoder->Range <<= 8;
|
|
encoder->ShiftLow();
|
|
}
|
|
}
|
|
UInt32 GetPrice(UInt32 symbol) const
|
|
{
|
|
return CPriceTables::ProbPrices[
|
|
(((this->Prob - symbol) ^ ((-(int)symbol))) & (kBitModelTotal - 1)) >> kNumMoveReducingBits];
|
|
}
|
|
UInt32 GetPrice0() const { return CPriceTables::ProbPrices[this->Prob >> kNumMoveReducingBits]; }
|
|
UInt32 GetPrice1() const { return CPriceTables::ProbPrices[(kBitModelTotal - this->Prob) >> kNumMoveReducingBits]; }
|
|
};
|
|
|
|
|
|
template <int numMoveBits>
|
|
class CBitDecoder: public CBitModel<numMoveBits>
|
|
{
|
|
public:
|
|
UInt32 Decode(CDecoder *decoder)
|
|
{
|
|
UInt32 newBound = (decoder->Range >> kNumBitModelTotalBits) * this->Prob;
|
|
if (decoder->Code < newBound)
|
|
{
|
|
decoder->Range = newBound;
|
|
this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits;
|
|
if (decoder->Range < kTopValue)
|
|
{
|
|
decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte();
|
|
decoder->Range <<= 8;
|
|
}
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
decoder->Range -= newBound;
|
|
decoder->Code -= newBound;
|
|
this->Prob -= (this->Prob) >> numMoveBits;
|
|
if (decoder->Range < kTopValue)
|
|
{
|
|
decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte();
|
|
decoder->Range <<= 8;
|
|
}
|
|
return 1;
|
|
}
|
|
}
|
|
};
|
|
|
|
}}
|
|
|
|
#endif
|