Add Fast LZMA2 codec

This commit is contained in:
conor42
2018-11-05 21:22:10 +10:00
parent ed069bab9e
commit ab10047253
41 changed files with 9060 additions and 8 deletions

View File

@@ -110,6 +110,7 @@ enum EMethodID
kLIZARD_M4,
kLZMA,
kLZMA2,
kFLZMA2,
kPPMd,
kBZip2,
kDeflate,
@@ -130,6 +131,7 @@ static LPCSTR const kMethodsLongnames[] =
, "Lizard, LIZv1 + Huffman"
, "LZMA"
, "LZMA2"
, "LZMA2, Fast"
, "PPMd"
, "BZip2"
, "Deflate"
@@ -150,6 +152,7 @@ static LPCSTR const kMethodsNames[] =
, "Lizard"
, "LZMA"
, "LZMA2"
, "FLZMA2"
, "PPMd"
, "BZip2"
, "Deflate"
@@ -195,6 +198,7 @@ static const EMethodID g_7zMethods[] =
kLIZARD_M2,
kLIZARD_M3,
kLIZARD_M4,
kFLZMA2,
kLZMA2,
kLZMA,
kPPMd,
@@ -209,6 +213,7 @@ static const EMethodID g_7zSfxMethods[] =
kZSTD,
kLZMA,
kLZMA2,
kFLZMA2,
kPPMd
};
@@ -978,6 +983,12 @@ bool CCompressDialog::OnCommand(int code, int itemID, LPARAM lParam)
case IDC_COMPRESS_LEVEL:
{
{
const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()];
int index = FindRegistryFormatAlways(ai.Name);
NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];
fo.ResetForLevelChange();
}
SetMethod(GetMethodID());
SetSolidBlockSize();
SetNumThreads();
@@ -1304,7 +1315,7 @@ void CCompressDialog::SetMethod(int keepMethodId)
}
}
if (!weUseSameMethod)
// if (!weUseSameMethod)
{
SetDictionary();
SetOrder();
@@ -1392,6 +1403,42 @@ void CCompressDialog::AddDictionarySize(UInt32 size)
m_Dictionary.SetItemData(index, size);
}
typedef enum {
FL2_fast,
FL2_opt,
FL2_ultra
} FL2_strategy;
typedef struct {
unsigned dictionaryLog; /* largest match distance : larger == more compression, more memory needed during decompression; >= 27 == more memory, slower */
unsigned overlapFraction; /* overlap between consecutive blocks in 1/16 units: larger == more compression, slower */
unsigned chainLog; /* fully searched segment : larger == more compression, slower, more memory; hybrid mode only (ultra) */
unsigned searchLog; /* nb of searches : larger == more compression, slower; hybrid mode only (ultra) */
unsigned searchDepth; /* maximum depth for resolving string matches : larger == more compression, slower; >= 64 == more memory, slower */
unsigned fastLength; /* acceptable match size for parser, not less than searchDepth : larger == more compression, slower; fast bytes parameter from 7-zip */
unsigned divideAndConquer; /* split long chains of 2-byte matches into shorter chains with a small overlap : faster, somewhat less compression; enabled by default */
unsigned bufferLog; /* buffer size for processing match chains is (dictionaryLog - bufferLog) : when divideAndConquer enabled, affects compression; */
/* when divideAndConquer disabled, affects speed in a hardware-dependent manner */
FL2_strategy strategy; /* encoder strategy : fast, optimized or ultra (hybrid) */
} FL2_compressionParameters;
#define FL2_MAX_7Z_CLEVEL 9
static const FL2_compressionParameters FL2_7zCParameters[FL2_MAX_7Z_CLEVEL + 1] = {
{ 0,0,0,0,0,0,0 },
{ 20, 1, 7, 0, 6, 32, 1, 8, FL2_fast }, /* 1 */
{ 20, 2, 7, 0, 12, 32, 1, 8, FL2_fast }, /* 2 */
{ 21, 2, 7, 0, 16, 32, 1, 8, FL2_fast }, /* 3 */
{ 20, 2, 7, 0, 16, 32, 1, 8, FL2_opt }, /* 4 */
{ 24, 2, 9, 0, 40, 48, 1, 8, FL2_ultra }, /* 5 */
{ 25, 2, 10, 0, 48, 64, 1, 8, FL2_ultra }, /* 6 */
{ 26, 2, 11, 1, 60, 96, 1, 9, FL2_ultra }, /* 7 */
{ 27, 2, 12, 2, 128, 128, 1, 10, FL2_ultra }, /* 8 */
{ 27, 3, 14, 3, 252, 160, 0, 10, FL2_ultra } /* 9 */
};
#define RMF_BUILDER_SIZE (8 * 0x40100U)
void CCompressDialog::SetDictionary()
{
m_Dictionary.ResetContent();
@@ -1458,6 +1505,39 @@ void CCompressDialog::SetDictionary()
break;
}
case kFLZMA2:
{
static const UInt32 kMinDicSize = (1 << 20);
level += !level;
if (level > FL2_MAX_7Z_CLEVEL)
level = FL2_MAX_7Z_CLEVEL;
if (defaultDict == (UInt32)(Int32)-1)
defaultDict = (UInt32)1 << FL2_7zCParameters[level].dictionaryLog;
m_Dictionary.SetCurSel(0);
for (unsigned i = 20; i <= 31; i++) {
UInt32 dict = (UInt32)1 << i;
if (dict >
#ifdef MY_CPU_64BIT
(1 << 30)
#else
(1 << 27)
#endif
)
continue;
AddDictionarySize(dict);
UInt64 decomprSize;
UInt64 requiredComprSize = GetMemoryUsage(dict, decomprSize);
if (dict <= defaultDict && (!maxRamSize_Defined || requiredComprSize <= maxRamSize))
m_Dictionary.SetCurSel(m_Dictionary.GetCount() - 1);
}
break;
}
case kPPMd:
{
if (defaultDict == (UInt32)(Int32)-1)
@@ -1598,9 +1678,14 @@ void CCompressDialog::SetOrder()
{
case kLZMA:
case kLZMA2:
case kFLZMA2:
{
if (defaultOrder == (UInt32)(Int32)-1)
defaultOrder = (level >= 7) ? 64 : 32;
if (defaultOrder == (UInt32)(Int32)-1) {
if (methodID == kFLZMA2)
defaultOrder = FL2_7zCParameters[level].fastLength;
else
defaultOrder = (level >= 7) ? 64 : 32;
}
for (unsigned i = 3; i <= 8; i++)
for (unsigned j = 0; j < 2; j++)
{
@@ -1820,6 +1905,7 @@ void CCompressDialog::SetNumThreads()
case kLIZARD_M4: numAlgoThreadsMax = 128; break;
case kLZMA: numAlgoThreadsMax = 2; break;
case kLZMA2: numAlgoThreadsMax = 32; break;
case kFLZMA2: numAlgoThreadsMax = 128; break;
case kBZip2: numAlgoThreadsMax = 32; break;
}
if (IsZipFormat())
@@ -1930,6 +2016,22 @@ UInt64 CCompressDialog::GetMemoryUsage(UInt32 dict, UInt64 &decompressMemory)
return size;
}
case kFLZMA2:
{
if (level > FL2_MAX_7Z_CLEVEL)
level = FL2_MAX_7Z_CLEVEL;
size += dict * 5 + (1UL << 18) * numThreads;
unsigned depth = FL2_7zCParameters[level].searchDepth;
UInt32 bufSize = UInt32(1) << (FL2_7zCParameters[level].dictionaryLog - FL2_7zCParameters[level].bufferLog);
size += (bufSize * 12 + RMF_BUILDER_SIZE) * numThreads;
if (dict > (UInt32(1) << 26) || depth > 63)
size += dict;
if (FL2_7zCParameters[level].strategy == FL2_ultra)
size += (UInt32(4) << 14) + (UInt32(4) << FL2_7zCParameters[level].chainLog);
decompressMemory = dict + (2 << 20);
return size;
}
case kPPMd:
{
decompressMemory = dict + (2 << 20);