diff options
author | Igor Pavlov <ipavlov@users.sourceforge.net> | 2007-01-20 03:00:00 +0300 |
---|---|---|
committer | Kornel LesiĆski <kornel@geekhood.net> | 2016-05-28 02:15:49 +0300 |
commit | d9666cf046a8453b33b3e2fbf4d82295a9f87df3 (patch) | |
tree | c722ed19b844b53042aec0c1d7d2f8381140a5ed /CPP/7zip/Compress/PPMD | |
parent | 804edc5756fede54dbb1aefda6d39d306111938d (diff) |
4.44 beta
Diffstat (limited to 'CPP/7zip/Compress/PPMD')
-rwxr-xr-x | CPP/7zip/Compress/PPMD/DllExports.cpp | 93 | ||||
-rwxr-xr-x | CPP/7zip/Compress/PPMD/PPMD.dsp | 229 | ||||
-rwxr-xr-x | CPP/7zip/Compress/PPMD/PPMD.dsw | 29 | ||||
-rwxr-xr-x | CPP/7zip/Compress/PPMD/PPMDContext.h | 489 | ||||
-rwxr-xr-x | CPP/7zip/Compress/PPMD/PPMDDecode.h | 154 | ||||
-rwxr-xr-x | CPP/7zip/Compress/PPMD/PPMDDecoder.cpp | 184 | ||||
-rwxr-xr-x | CPP/7zip/Compress/PPMD/PPMDDecoder.h | 89 | ||||
-rwxr-xr-x | CPP/7zip/Compress/PPMD/PPMDEncode.h | 142 | ||||
-rwxr-xr-x | CPP/7zip/Compress/PPMD/PPMDEncoder.cpp | 155 | ||||
-rwxr-xr-x | CPP/7zip/Compress/PPMD/PPMDEncoder.h | 81 | ||||
-rwxr-xr-x | CPP/7zip/Compress/PPMD/PPMDSubAlloc.h | 292 | ||||
-rwxr-xr-x | CPP/7zip/Compress/PPMD/PPMDType.h | 19 | ||||
-rwxr-xr-x | CPP/7zip/Compress/PPMD/StdAfx.cpp | 3 | ||||
-rwxr-xr-x | CPP/7zip/Compress/PPMD/StdAfx.h | 8 | ||||
-rwxr-xr-x | CPP/7zip/Compress/PPMD/makefile | 41 | ||||
-rwxr-xr-x | CPP/7zip/Compress/PPMD/resource.rc | 3 |
16 files changed, 2011 insertions, 0 deletions
diff --git a/CPP/7zip/Compress/PPMD/DllExports.cpp b/CPP/7zip/Compress/PPMD/DllExports.cpp new file mode 100755 index 00000000..8159a2f8 --- /dev/null +++ b/CPP/7zip/Compress/PPMD/DllExports.cpp @@ -0,0 +1,93 @@ +// DLLExports.cpp + +#include "StdAfx.h" + +#include "Common/MyInitGuid.h" +#include "Common/ComTry.h" +#ifdef _WIN32 +#include "Common/Alloc.h" +#endif + +#include "PPMDEncoder.h" +#include "PPMDDecoder.h" + +// {23170F69-40C1-278B-0304-010000000000} +DEFINE_GUID(CLSID_CCompressPPMDDecoder, +0x23170F69, 0x40C1, 0x278B, 0x03, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00); + +// {23170F69-40C1-278B-0304-010000000100} +DEFINE_GUID(CLSID_CCompressPPMDEncoder, +0x23170F69, 0x40C1, 0x278B, 0x03, 0x04, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00); + +extern "C" +BOOL WINAPI DllMain(HINSTANCE /* hInstance */, DWORD dwReason, LPVOID /*lpReserved*/) +{ + #ifdef _WIN32 + if (dwReason == DLL_PROCESS_ATTACH) + SetLargePageSize(); + #endif + return TRUE; +} + +STDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject) +{ + COM_TRY_BEGIN + *outObject = 0; + int correctInterface = (*iid == IID_ICompressCoder); + CMyComPtr<ICompressCoder> coder; + if (*clsid == CLSID_CCompressPPMDDecoder) + { + if (!correctInterface) + return E_NOINTERFACE; + coder = (ICompressCoder *)new NCompress::NPPMD::CDecoder(); + } + else if (*clsid == CLSID_CCompressPPMDEncoder) + { + if (!correctInterface) + return E_NOINTERFACE; + coder = (ICompressCoder *)new NCompress::NPPMD::CEncoder(); + } + else + return CLASS_E_CLASSNOTAVAILABLE; + *outObject = coder.Detach(); + COM_TRY_END + return S_OK; +} + +STDAPI GetNumberOfMethods(UINT32 *numMethods) +{ + *numMethods = 1; + return S_OK; +} + +STDAPI GetMethodProperty(UINT32 index, PROPID propID, PROPVARIANT *value) +{ + if (index != 0) + return E_INVALIDARG; + ::VariantClear((tagVARIANT *)value); + switch(propID) + { + case NMethodPropID::kID: + { + const char id[] = { 0x03, 0x04, 0x01 }; + if ((value->bstrVal = ::SysAllocStringByteLen(id, sizeof(id))) != 0) + value->vt = VT_BSTR; + return S_OK; + } + case NMethodPropID::kName: + if ((value->bstrVal = ::SysAllocString(L"PPMD")) != 0) + value->vt = VT_BSTR; + return S_OK; + case NMethodPropID::kDecoder: + if ((value->bstrVal = ::SysAllocStringByteLen( + (const char *)&CLSID_CCompressPPMDDecoder, sizeof(GUID))) != 0) + value->vt = VT_BSTR; + return S_OK; + case NMethodPropID::kEncoder: + if ((value->bstrVal = ::SysAllocStringByteLen( + (const char *)&CLSID_CCompressPPMDEncoder, sizeof(GUID))) != 0) + value->vt = VT_BSTR; + return S_OK; + } + return S_OK; +} diff --git a/CPP/7zip/Compress/PPMD/PPMD.dsp b/CPP/7zip/Compress/PPMD/PPMD.dsp new file mode 100755 index 00000000..9e512f6c --- /dev/null +++ b/CPP/7zip/Compress/PPMD/PPMD.dsp @@ -0,0 +1,229 @@ +# Microsoft Developer Studio Project File - Name="PPMD" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=PPMD - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "PPMD.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "PPMD.mak" CFG="PPMD - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "PPMD - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "PPMD - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "PPMD - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 1 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PPMD_EXPORTS" /YX /FD /c +# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PPMD_EXPORTS" /Yu"StdAfx.h" /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"C:\Program Files\7-Zip\Codecs\PPMd.dll" /opt:NOWIN98 +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "PPMD - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 1 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PPMD_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /Gz /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PPMD_EXPORTS" /Yu"StdAfx.h" /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"C:\Program Files\7-Zip\Codecs\PPMd.dll" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "PPMD - Win32 Release" +# Name "PPMD - Win32 Debug" +# Begin Group "Spec" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\Codec.def +# End Source File +# Begin Source File + +SOURCE=.\DllExports.cpp +# End Source File +# Begin Source File + +SOURCE=.\resource.rc +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.cpp +# ADD CPP /Yc +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.h +# End Source File +# End Group +# Begin Group "PPMD" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\PPMDContext.h +# End Source File +# Begin Source File + +SOURCE=.\PPMDDecode.h +# End Source File +# Begin Source File + +SOURCE=.\PPMDDecoder.cpp + +!IF "$(CFG)" == "PPMD - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "PPMD - Win32 Debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\PPMDDecoder.h +# End Source File +# Begin Source File + +SOURCE=.\PPMDEncode.h +# End Source File +# Begin Source File + +SOURCE=.\PPMDEncoder.cpp + +!IF "$(CFG)" == "PPMD - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "PPMD - Win32 Debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\PPMDEncoder.h +# End Source File +# Begin Source File + +SOURCE=.\PPMDSubAlloc.h +# End Source File +# Begin Source File + +SOURCE=.\PPMDType.h +# End Source File +# End Group +# Begin Group "7zip common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Common\InBuffer.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\InBuffer.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\OutBuffer.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\OutBuffer.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.h +# End Source File +# End Group +# Begin Group "RangeCoder" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\RangeCoder\RangeCoder.h +# End Source File +# End Group +# Begin Group "Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\..\Common\Alloc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\Alloc.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\Types.h +# End Source File +# End Group +# End Target +# End Project diff --git a/CPP/7zip/Compress/PPMD/PPMD.dsw b/CPP/7zip/Compress/PPMD/PPMD.dsw new file mode 100755 index 00000000..8032f3db --- /dev/null +++ b/CPP/7zip/Compress/PPMD/PPMD.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "PPMD"=.\PPMD.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/CPP/7zip/Compress/PPMD/PPMDContext.h b/CPP/7zip/Compress/PPMD/PPMDContext.h new file mode 100755 index 00000000..a6a8dd60 --- /dev/null +++ b/CPP/7zip/Compress/PPMD/PPMDContext.h @@ -0,0 +1,489 @@ +// Compress/PPMD/Context.h +// This code is based on Dmitry Shkarin's PPMdH code + +#ifndef __COMPRESS_PPMD_CONTEXT_H +#define __COMPRESS_PPMD_CONTEXT_H + +#include "../../../Common/Types.h" + +#include "../RangeCoder/RangeCoder.h" +#include "PPMDSubAlloc.h" + +namespace NCompress { +namespace NPPMD { + +const int INT_BITS=7, PERIOD_BITS=7, TOT_BITS=INT_BITS+PERIOD_BITS, + INTERVAL=1 << INT_BITS, BIN_SCALE=1 << TOT_BITS, MAX_FREQ=124; + +struct SEE2_CONTEXT +{ + // SEE-contexts for PPM-contexts with masked symbols + UInt16 Summ; + Byte Shift, Count; + void init(int InitVal) { Summ = (UInt16)(InitVal << (Shift=PERIOD_BITS-4)); Count=4; } + unsigned int getMean() + { + unsigned int RetVal=(Summ >> Shift); + Summ = (UInt16)(Summ - RetVal); + return RetVal+(RetVal == 0); + } + void update() + { + if (Shift < PERIOD_BITS && --Count == 0) + { + Summ <<= 1; + Count = (Byte)(3 << Shift++); + } + } +}; + +struct PPM_CONTEXT +{ + UInt16 NumStats; // sizeof(UInt16) > sizeof(Byte) + UInt16 SummFreq; + + struct STATE + { + Byte Symbol, Freq; + UInt16 SuccessorLow; + UInt16 SuccessorHigh; + + UInt32 GetSuccessor() const { return SuccessorLow | ((UInt32)SuccessorHigh << 16); } + void SetSuccessor(UInt32 v) + { + SuccessorLow = (UInt16)(v & 0xFFFF); + SuccessorHigh = (UInt16)((v >> 16) & 0xFFFF); + } + }; + + UInt32 Stats; + UInt32 Suffix; + + PPM_CONTEXT* createChild(CSubAllocator &subAllocator, STATE* pStats, STATE& FirstState) + { + PPM_CONTEXT* pc = (PPM_CONTEXT*) subAllocator.AllocContext(); + if (pc) + { + pc->NumStats = 1; + pc->oneState() = FirstState; + pc->Suffix = subAllocator.GetOffset(this); + pStats->SetSuccessor(subAllocator.GetOffsetNoCheck(pc)); + } + return pc; + } + + STATE& oneState() const { return (STATE&) SummFreq; } +}; + +///////////////////////////////// + +const UInt16 InitBinEsc[] = + {0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051}; + +struct CInfo +{ + CSubAllocator SubAllocator; + SEE2_CONTEXT SEE2Cont[25][16], DummySEE2Cont; + PPM_CONTEXT * MinContext, * MaxContext; + + PPM_CONTEXT::STATE* FoundState; // found next state transition + int NumMasked, InitEsc, OrderFall, RunLength, InitRL, MaxOrder; + Byte CharMask[256], NS2Indx[256], NS2BSIndx[256], HB2Flag[256]; + Byte EscCount, PrintCount, PrevSuccess, HiBitsFlag; + UInt16 BinSumm[128][64]; // binary SEE-contexts + + UInt16 &GetBinSumm(const PPM_CONTEXT::STATE &rs, int numStates) + { + HiBitsFlag = HB2Flag[FoundState->Symbol]; + return BinSumm[rs.Freq - 1][ + PrevSuccess + NS2BSIndx[numStates - 1] + + HiBitsFlag + 2 * HB2Flag[rs.Symbol] + + ((RunLength >> 26) & 0x20)]; + } + + PPM_CONTEXT *GetContext(UInt32 offset) const { return (PPM_CONTEXT *)SubAllocator.GetPtr(offset); } + PPM_CONTEXT *GetContextNoCheck(UInt32 offset) const { return (PPM_CONTEXT *)SubAllocator.GetPtrNoCheck(offset); } + PPM_CONTEXT::STATE *GetState(UInt32 offset) const { return (PPM_CONTEXT::STATE *)SubAllocator.GetPtr(offset); } + PPM_CONTEXT::STATE *GetStateNoCheck(UInt32 offset) const { return (PPM_CONTEXT::STATE *)SubAllocator.GetPtr(offset); } + + void RestartModelRare() + { + int i, k, m; + memset(CharMask,0,sizeof(CharMask)); + SubAllocator.InitSubAllocator(); + InitRL = -((MaxOrder < 12) ? MaxOrder : 12) - 1; + MinContext = MaxContext = (PPM_CONTEXT*) SubAllocator.AllocContext(); + MinContext->Suffix = 0; + OrderFall = MaxOrder; + MinContext->SummFreq = (UInt16)((MinContext->NumStats = 256) + 1); + FoundState = (PPM_CONTEXT::STATE*)SubAllocator.AllocUnits(256 / 2); + MinContext->Stats = SubAllocator.GetOffsetNoCheck(FoundState); + PrevSuccess = 0; + for (RunLength = InitRL, i = 0; i < 256; i++) + { + PPM_CONTEXT::STATE &state = FoundState[i]; + state.Symbol = (Byte)i; + state.Freq = 1; + state.SetSuccessor(0); + } + for (i = 0; i < 128; i++) + for (k = 0; k < 8; k++) + for ( m=0; m < 64; m += 8) + BinSumm[i][k + m] = (UInt16)(BIN_SCALE - InitBinEsc[k] / (i + 2)); + for (i = 0; i < 25; i++) + for (k = 0; k < 16; k++) + SEE2Cont[i][k].init(5*i+10); + } + + void StartModelRare(int MaxOrder) + { + int i, k, m ,Step; + EscCount=PrintCount=1; + if (MaxOrder < 2) + { + memset(CharMask,0,sizeof(CharMask)); + OrderFall = this->MaxOrder; + MinContext = MaxContext; + while (MinContext->Suffix != 0) + { + MinContext = GetContextNoCheck(MinContext->Suffix); + OrderFall--; + } + FoundState = GetState(MinContext->Stats); + MinContext = MaxContext; + } + else + { + this->MaxOrder = MaxOrder; + RestartModelRare(); + NS2BSIndx[0] = 2 * 0; + NS2BSIndx[1] = 2 * 1; + memset(NS2BSIndx + 2, 2 * 2, 9); + memset(NS2BSIndx + 11, 2 * 3, 256 - 11); + for (i = 0; i < 3; i++) + NS2Indx[i] = (Byte)i; + for (m = i, k = Step = 1; i < 256; i++) + { + NS2Indx[i] = (Byte)m; + if ( !--k ) + { + k = ++Step; + m++; + } + } + memset(HB2Flag, 0, 0x40); + memset(HB2Flag + 0x40, 0x08, 0x100 - 0x40); + DummySEE2Cont.Shift = PERIOD_BITS; + } + } + + PPM_CONTEXT* CreateSuccessors(bool skip, PPM_CONTEXT::STATE* p1) + { + // static UpState declaration bypasses IntelC bug + // static PPM_CONTEXT::STATE UpState; + PPM_CONTEXT::STATE UpState; + + PPM_CONTEXT *pc = MinContext; + PPM_CONTEXT *UpBranch = GetContext(FoundState->GetSuccessor()); + PPM_CONTEXT::STATE * p, * ps[MAX_O], ** pps = ps; + if ( !skip ) + { + *pps++ = FoundState; + if ( !pc->Suffix ) + goto NO_LOOP; + } + if ( p1 ) + { + p = p1; + pc = GetContext(pc->Suffix); + goto LOOP_ENTRY; + } + do + { + pc = GetContext(pc->Suffix); + if (pc->NumStats != 1) + { + if ((p = GetStateNoCheck(pc->Stats))->Symbol != FoundState->Symbol) + do { p++; } while (p->Symbol != FoundState->Symbol); + } + else + p = &(pc->oneState()); +LOOP_ENTRY: + if (GetContext(p->GetSuccessor()) != UpBranch) + { + pc = GetContext(p->GetSuccessor()); + break; + } + *pps++ = p; + } + while ( pc->Suffix ); +NO_LOOP: + if (pps == ps) + return pc; + UpState.Symbol = *(Byte*) UpBranch; + UpState.SetSuccessor(SubAllocator.GetOffset(UpBranch) + 1); + if (pc->NumStats != 1) + { + if ((p = GetStateNoCheck(pc->Stats))->Symbol != UpState.Symbol) + do { p++; } while (p->Symbol != UpState.Symbol); + unsigned int cf = p->Freq-1; + unsigned int s0 = pc->SummFreq - pc->NumStats - cf; + UpState.Freq = (Byte)(1 + ((2 * cf <= s0) ? (5 * cf > s0) : + ((2 * cf + 3 * s0 - 1) / (2 * s0)))); + } + else + UpState.Freq = pc->oneState().Freq; + do + { + pc = pc->createChild(SubAllocator, *--pps, UpState); + if ( !pc ) + return NULL; + } + while (pps != ps); + return pc; + } + + void UpdateModel() + { + PPM_CONTEXT::STATE fs = *FoundState, * p = NULL; + PPM_CONTEXT* pc, * Successor; + unsigned int ns1, ns, cf, sf, s0; + if (fs.Freq < MAX_FREQ / 4 && MinContext->Suffix != 0) + { + pc = GetContextNoCheck(MinContext->Suffix); + + if (pc->NumStats != 1) + { + if ((p = GetStateNoCheck(pc->Stats))->Symbol != fs.Symbol) + { + do { p++; } while (p->Symbol != fs.Symbol); + if (p[0].Freq >= p[-1].Freq) + { + _PPMD_SWAP(p[0],p[-1]); + p--; + } + } + if (p->Freq < MAX_FREQ-9) + { + p->Freq += 2; + pc->SummFreq += 2; + } + } + else + { + p = &(pc->oneState()); + p->Freq = (Byte)(p->Freq + ((p->Freq < 32) ? 1 : 0)); + } + } + if ( !OrderFall ) + { + MinContext = MaxContext = CreateSuccessors(true, p); + FoundState->SetSuccessor(SubAllocator.GetOffset(MinContext)); + if (MinContext == 0) + goto RESTART_MODEL; + return; + } + *SubAllocator.pText++ = fs.Symbol; + Successor = (PPM_CONTEXT*) SubAllocator.pText; + if (SubAllocator.pText >= SubAllocator.UnitsStart) + goto RESTART_MODEL; + if (fs.GetSuccessor() != 0) + { + if ((Byte *)GetContext(fs.GetSuccessor()) <= SubAllocator.pText) + { + PPM_CONTEXT* cs = CreateSuccessors(false, p); + fs.SetSuccessor(SubAllocator.GetOffset(cs)); + if (cs == NULL) + goto RESTART_MODEL; + } + if ( !--OrderFall ) + { + Successor = GetContext(fs.GetSuccessor()); + SubAllocator.pText -= (MaxContext != MinContext); + } + } + else + { + FoundState->SetSuccessor(SubAllocator.GetOffsetNoCheck(Successor)); + fs.SetSuccessor(SubAllocator.GetOffsetNoCheck(MinContext)); + } + s0 = MinContext->SummFreq - (ns = MinContext->NumStats) - (fs.Freq - 1); + for (pc = MaxContext; pc != MinContext; pc = GetContext(pc->Suffix)) + { + if ((ns1 = pc->NumStats) != 1) + { + if ((ns1 & 1) == 0) + { + void *ppp = SubAllocator.ExpandUnits(GetState(pc->Stats), ns1 >> 1); + pc->Stats = SubAllocator.GetOffset(ppp); + if (!ppp) + goto RESTART_MODEL; + } + pc->SummFreq = (UInt16)(pc->SummFreq + (2 * ns1 < ns) + 2 * ((4 * ns1 <= ns) & + (pc->SummFreq <= 8 * ns1))); + } + else + { + p = (PPM_CONTEXT::STATE*) SubAllocator.AllocUnits(1); + if ( !p ) + goto RESTART_MODEL; + *p = pc->oneState(); + pc->Stats = SubAllocator.GetOffsetNoCheck(p); + if (p->Freq < MAX_FREQ / 4 - 1) + p->Freq <<= 1; + else + p->Freq = MAX_FREQ - 4; + pc->SummFreq = (UInt16)(p->Freq + InitEsc + (ns > 3)); + } + cf = 2 * fs.Freq * (pc->SummFreq+6); + sf = s0 + pc->SummFreq; + if (cf < 6 * sf) + { + cf = 1 + (cf > sf)+(cf >= 4 * sf); + pc->SummFreq += 3; + } + else + { + cf = 4 + (cf >= 9 * sf) + (cf >= 12 * sf) + (cf >= 15 * sf); + pc->SummFreq = (UInt16)(pc->SummFreq + cf); + } + p = GetState(pc->Stats) + ns1; + p->SetSuccessor(SubAllocator.GetOffset(Successor)); + p->Symbol = fs.Symbol; + p->Freq = (Byte)cf; + pc->NumStats = (UInt16)++ns1; + } + MaxContext = MinContext = GetContext(fs.GetSuccessor()); + return; +RESTART_MODEL: + RestartModelRare(); + EscCount = 0; + PrintCount = 0xFF; + } + + void ClearMask() + { + EscCount = 1; + memset(CharMask, 0, sizeof(CharMask)); + // if (++PrintCount == 0) + // PrintInfo(DecodedFile,EncodedFile); + } + + void update1(PPM_CONTEXT::STATE* p) + { + (FoundState = p)->Freq += 4; + MinContext->SummFreq += 4; + if (p[0].Freq > p[-1].Freq) + { + _PPMD_SWAP(p[0],p[-1]); + FoundState = --p; + if (p->Freq > MAX_FREQ) + rescale(); + } + } + + + void update2(PPM_CONTEXT::STATE* p) + { + (FoundState = p)->Freq += 4; + MinContext->SummFreq += 4; + if (p->Freq > MAX_FREQ) + rescale(); + EscCount++; + RunLength = InitRL; + } + + SEE2_CONTEXT* makeEscFreq2(int Diff, UInt32 &scale) + { + SEE2_CONTEXT* psee2c; + if (MinContext->NumStats != 256) + { + psee2c = SEE2Cont[NS2Indx[Diff-1]] + + (Diff < (GetContext(MinContext->Suffix))->NumStats - MinContext->NumStats) + + 2 * (MinContext->SummFreq < 11 * MinContext->NumStats) + + 4 * (NumMasked > Diff) + + HiBitsFlag; + scale = psee2c->getMean(); + } + else + { + psee2c = &DummySEE2Cont; + scale = 1; + } + return psee2c; + } + + + + void rescale() + { + int OldNS = MinContext->NumStats, i = MinContext->NumStats - 1, Adder, EscFreq; + PPM_CONTEXT::STATE* p1, * p; + PPM_CONTEXT::STATE *stats = GetStateNoCheck(MinContext->Stats); + for (p = FoundState; p != stats; p--) + _PPMD_SWAP(p[0], p[-1]); + stats->Freq += 4; + MinContext->SummFreq += 4; + EscFreq = MinContext->SummFreq - p->Freq; + Adder = (OrderFall != 0); + p->Freq = (Byte)((p->Freq + Adder) >> 1); + MinContext->SummFreq = p->Freq; + do + { + EscFreq -= (++p)->Freq; + p->Freq = (Byte)((p->Freq + Adder) >> 1); + MinContext->SummFreq = (UInt16)(MinContext->SummFreq + p->Freq); + if (p[0].Freq > p[-1].Freq) + { + PPM_CONTEXT::STATE tmp = *(p1 = p); + do + { + p1[0] = p1[-1]; + } + while (--p1 != stats && tmp.Freq > p1[-1].Freq); + *p1 = tmp; + } + } + while ( --i ); + if (p->Freq == 0) + { + do { i++; } while ((--p)->Freq == 0); + EscFreq += i; + MinContext->NumStats = (UInt16)(MinContext->NumStats - i); + if (MinContext->NumStats == 1) + { + PPM_CONTEXT::STATE tmp = *stats; + do { tmp.Freq = (Byte)(tmp.Freq - (tmp.Freq >> 1)); EscFreq >>= 1; } while (EscFreq > 1); + SubAllocator.FreeUnits(stats, (OldNS+1) >> 1); + *(FoundState = &MinContext->oneState()) = tmp; return; + } + } + EscFreq -= (EscFreq >> 1); + MinContext->SummFreq = (UInt16)(MinContext->SummFreq + EscFreq); + int n0 = (OldNS+1) >> 1, n1 = (MinContext->NumStats + 1) >> 1; + if (n0 != n1) + MinContext->Stats = SubAllocator.GetOffset(SubAllocator.ShrinkUnits(stats, n0, n1)); + FoundState = GetState(MinContext->Stats); + } + + void NextContext() + { + PPM_CONTEXT *c = GetContext(FoundState->GetSuccessor()); + if (!OrderFall && (Byte *)c > SubAllocator.pText) + MinContext = MaxContext = c; + else + { + UpdateModel(); + if (EscCount == 0) + ClearMask(); + } + } +}; + +// Tabulated escapes for exponential symbol distribution +const Byte ExpEscape[16]={ 25,14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 }; +#define GET_MEAN(SUMM,SHIFT,ROUND) ((SUMM+(1 << (SHIFT-ROUND))) >> (SHIFT)) + +}} + +#endif diff --git a/CPP/7zip/Compress/PPMD/PPMDDecode.h b/CPP/7zip/Compress/PPMD/PPMDDecode.h new file mode 100755 index 00000000..b05d8ee0 --- /dev/null +++ b/CPP/7zip/Compress/PPMD/PPMDDecode.h @@ -0,0 +1,154 @@ +// PPMDDecode.h +// This code is based on Dmitry Shkarin's PPMdH code + +#ifndef __COMPRESS_PPMD_DECODE_H +#define __COMPRESS_PPMD_DECODE_H + +#include "PPMDContext.h" + +namespace NCompress { +namespace NPPMD { + +class CRangeDecoderVirt +{ +public: + virtual UInt32 GetThreshold(UInt32 total) = 0; + virtual void Decode(UInt32 start, UInt32 size) = 0; + virtual UInt32 DecodeBit(UInt32 size0, UInt32 numTotalBits) = 0; +}; + +typedef NRangeCoder::CDecoder CRangeDecoderMy; + +class CRangeDecoder:public CRangeDecoderVirt, public CRangeDecoderMy +{ + UInt32 GetThreshold(UInt32 total) { return CRangeDecoderMy::GetThreshold(total); } + void Decode(UInt32 start, UInt32 size) { CRangeDecoderMy::Decode(start, size); } + UInt32 DecodeBit(UInt32 size0, UInt32 numTotalBits) { return CRangeDecoderMy::DecodeBit(size0, numTotalBits); } +}; + +struct CDecodeInfo: public CInfo +{ + void DecodeBinSymbol(CRangeDecoderVirt *rangeDecoder) + { + PPM_CONTEXT::STATE& rs = MinContext->oneState(); + UInt16& bs = GetBinSumm(rs, GetContextNoCheck(MinContext->Suffix)->NumStats); + if (rangeDecoder->DecodeBit(bs, TOT_BITS) == 0) + { + FoundState = &rs; + rs.Freq = (Byte)(rs.Freq + (rs.Freq < 128 ? 1: 0)); + bs = (UInt16)(bs + INTERVAL - GET_MEAN(bs, PERIOD_BITS, 2)); + PrevSuccess = 1; + RunLength++; + } + else + { + bs = (UInt16)(bs - GET_MEAN(bs, PERIOD_BITS, 2)); + InitEsc = ExpEscape[bs >> 10]; + NumMasked = 1; + CharMask[rs.Symbol] = EscCount; + PrevSuccess = 0; + FoundState = NULL; + } + } + + void DecodeSymbol1(CRangeDecoderVirt *rangeDecoder) + { + PPM_CONTEXT::STATE* p = GetStateNoCheck(MinContext->Stats); + int i, count, hiCnt; + if ((count = rangeDecoder->GetThreshold(MinContext->SummFreq)) < (hiCnt = p->Freq)) + { + PrevSuccess = (2 * hiCnt > MinContext->SummFreq); + RunLength += PrevSuccess; + rangeDecoder->Decode(0, p->Freq); // MinContext->SummFreq); + (FoundState = p)->Freq = (Byte)(hiCnt += 4); + MinContext->SummFreq += 4; + if (hiCnt > MAX_FREQ) + rescale(); + return; + } + PrevSuccess = 0; + i = MinContext->NumStats - 1; + while ((hiCnt += (++p)->Freq) <= count) + if (--i == 0) + { + HiBitsFlag = HB2Flag[FoundState->Symbol]; + rangeDecoder->Decode(hiCnt, MinContext->SummFreq - hiCnt); // , MinContext->SummFreq); + CharMask[p->Symbol] = EscCount; + i = (NumMasked = MinContext->NumStats)-1; + FoundState = NULL; + do { CharMask[(--p)->Symbol] = EscCount; } while ( --i ); + return; + } + rangeDecoder->Decode(hiCnt - p->Freq, p->Freq); // , MinContext->SummFreq); + update1(p); + } + + + void DecodeSymbol2(CRangeDecoderVirt *rangeDecoder) + { + int count, hiCnt, i = MinContext->NumStats - NumMasked; + UInt32 freqSum; + SEE2_CONTEXT* psee2c = makeEscFreq2(i, freqSum); + PPM_CONTEXT::STATE* ps[256], ** pps = ps, * p = GetStateNoCheck(MinContext->Stats)-1; + hiCnt = 0; + do + { + do { p++; } while (CharMask[p->Symbol] == EscCount); + hiCnt += p->Freq; + *pps++ = p; + } + while ( --i ); + + freqSum += hiCnt; + count = rangeDecoder->GetThreshold(freqSum); + + p = *(pps = ps); + if (count < hiCnt) + { + hiCnt = 0; + while ((hiCnt += p->Freq) <= count) + p=*++pps; + rangeDecoder->Decode(hiCnt - p->Freq, p->Freq); // , freqSum); + + psee2c->update(); + update2(p); + } + else + { + rangeDecoder->Decode(hiCnt, freqSum - hiCnt); // , freqSum); + + i = MinContext->NumStats - NumMasked; + pps--; + do { CharMask[(*++pps)->Symbol] = EscCount; } while ( --i ); + psee2c->Summ = (UInt16)(psee2c->Summ + freqSum); + NumMasked = MinContext->NumStats; + } + } + + int DecodeSymbol(CRangeDecoderVirt *rangeDecoder) + { + if (MinContext->NumStats != 1) + DecodeSymbol1(rangeDecoder); + else + DecodeBinSymbol(rangeDecoder); + while ( !FoundState ) + { + do + { + OrderFall++; + MinContext = GetContext(MinContext->Suffix); + if (MinContext == 0) + return -1; + } + while (MinContext->NumStats == NumMasked); + DecodeSymbol2(rangeDecoder); + } + Byte symbol = FoundState->Symbol; + NextContext(); + return symbol; + } +}; + +}} + +#endif diff --git a/CPP/7zip/Compress/PPMD/PPMDDecoder.cpp b/CPP/7zip/Compress/PPMD/PPMDDecoder.cpp new file mode 100755 index 00000000..2d0a2f52 --- /dev/null +++ b/CPP/7zip/Compress/PPMD/PPMDDecoder.cpp @@ -0,0 +1,184 @@ +// PPMDDecoder.cpp + +#include "StdAfx.h" + +#include "Common/Defs.h" +#include "Windows/Defs.h" + +#include "PPMDDecoder.h" + +namespace NCompress { +namespace NPPMD { + +const int kLenIdFinished = -1; +const int kLenIdNeedInit = -2; + +STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *properties, UInt32 size) +{ + if (size < 5) + return E_INVALIDARG; + _order = properties[0]; + _usedMemorySize = 0; + for (int i = 0; i < 4; i++) + _usedMemorySize += ((UInt32)(properties[1 + i])) << (i * 8); + + if (_usedMemorySize > kMaxMemBlockSize) + return E_NOTIMPL; + + if (!_rangeDecoder.Create(1 << 20)) + return E_OUTOFMEMORY; + if (!_info.SubAllocator.StartSubAllocator(_usedMemorySize)) + return E_OUTOFMEMORY; + + return S_OK; +} + +class CDecoderFlusher +{ + CDecoder *_coder; +public: + bool NeedFlush; + CDecoderFlusher(CDecoder *coder): _coder(coder), NeedFlush(true) {} + ~CDecoderFlusher() + { + if (NeedFlush) + _coder->Flush(); + _coder->ReleaseStreams(); + } +}; + +HRESULT CDecoder::CodeSpec(UInt32 size, Byte *memStream) +{ + if (_outSizeDefined) + { + const UInt64 rem = _outSize - _processedSize; + if (size > rem) + size = (UInt32)rem; + } + const UInt32 startSize = size; + + if (_remainLen == kLenIdFinished) + return S_OK; + if (_remainLen == kLenIdNeedInit) + { + _rangeDecoder.Init(); + _remainLen = 0; + _info.MaxOrder = 0; + _info.StartModelRare(_order); + } + while (size != 0) + { + int symbol = _info.DecodeSymbol(&_rangeDecoder); + if (symbol < 0) + { + _remainLen = kLenIdFinished; + break; + } + if (memStream != 0) + *memStream++ = (Byte)symbol; + else + _outStream.WriteByte((Byte)symbol); + size--; + } + _processedSize += startSize - size; + return S_OK; +} + +STDMETHODIMP CDecoder::CodeReal(ISequentialInStream *inStream, + ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize, + ICompressProgressInfo *progress) +{ + if (!_outStream.Create(1 << 20)) + return E_OUTOFMEMORY; + + SetInStream(inStream); + _outStream.SetStream(outStream); + SetOutStreamSize(outSize); + CDecoderFlusher flusher(this); + + for (;;) + { + _processedSize = _outStream.GetProcessedSize(); + UInt32 curSize = (1 << 18); + RINOK(CodeSpec(curSize, NULL)); + if (_remainLen == kLenIdFinished) + break; + if (progress != NULL) + { + UInt64 inSize = _rangeDecoder.GetProcessedSize(); + RINOK(progress->SetRatioInfo(&inSize, &_processedSize)); + } + if (_outSizeDefined) + if (_outStream.GetProcessedSize() >= _outSize) + break; + } + flusher.NeedFlush = false; + return Flush(); +} + +#ifdef _NO_EXCEPTIONS + +#define PPMD_TRY_BEGIN +#define PPMD_TRY_END + +#else + +#define PPMD_TRY_BEGIN try { +#define PPMD_TRY_END } \ + catch(const CInBufferException &e) { return e.ErrorCode; } \ + catch(const COutBufferException &e) { return e.ErrorCode; } \ + catch(...) { return S_FALSE; } + +#endif + + +STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, + ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, + ICompressProgressInfo *progress) +{ + PPMD_TRY_BEGIN + return CodeReal(inStream, outStream, inSize, outSize, progress); + PPMD_TRY_END +} + +STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) +{ + _rangeDecoder.SetStream(inStream); + return S_OK; +} + +STDMETHODIMP CDecoder::ReleaseInStream() +{ + _rangeDecoder.ReleaseStream(); + return S_OK; +} + +STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize) +{ + _outSizeDefined = (outSize != NULL); + if (_outSizeDefined) + _outSize = *outSize; + _processedSize = 0; + _remainLen = kLenIdNeedInit; + _outStream.Init(); + return S_OK; +} + +#ifdef _ST_MODE + +STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + PPMD_TRY_BEGIN + if (processedSize) + *processedSize = 0; + const UInt64 startPos = _processedSize; + RINOK(CodeSpec(size, (Byte *)data)); + if (processedSize) + *processedSize = (UInt32)(_processedSize - startPos); + return Flush(); + PPMD_TRY_END +} + +#endif + +}} diff --git a/CPP/7zip/Compress/PPMD/PPMDDecoder.h b/CPP/7zip/Compress/PPMD/PPMDDecoder.h new file mode 100755 index 00000000..8e30c35c --- /dev/null +++ b/CPP/7zip/Compress/PPMD/PPMDDecoder.h @@ -0,0 +1,89 @@ +// Compress/PPM/PPMDDecoder.h + +#ifndef __COMPRESS_PPMD_DECODER_H +#define __COMPRESS_PPMD_DECODER_H + +#include "../../../Common/MyCom.h" + +#include "../../ICoder.h" +#include "../../Common/OutBuffer.h" +#include "../RangeCoder/RangeCoder.h" + +#include "PPMDDecode.h" + +namespace NCompress { +namespace NPPMD { + +class CDecoder : + public ICompressCoder, + public ICompressSetDecoderProperties2, + #ifdef _ST_MODE + public ICompressSetInStream, + public ICompressSetOutStreamSize, + public ISequentialInStream, + #endif + public CMyUnknownImp +{ + CRangeDecoder _rangeDecoder; + + COutBuffer _outStream; + + CDecodeInfo _info; + + Byte _order; + UInt32 _usedMemorySize; + + int _remainLen; + UInt64 _outSize; + bool _outSizeDefined; + UInt64 _processedSize; + + HRESULT CodeSpec(UInt32 num, Byte *memStream); +public: + + #ifdef _ST_MODE + MY_UNKNOWN_IMP4( + ICompressSetDecoderProperties2, + ICompressSetInStream, + ICompressSetOutStreamSize, + ISequentialInStream) + #else + MY_UNKNOWN_IMP1( + ICompressSetDecoderProperties2) + #endif + + void ReleaseStreams() + { + ReleaseInStream(); + _outStream.ReleaseStream(); + } + + HRESULT Flush() { return _outStream.Flush(); } + + STDMETHOD(CodeReal)(ISequentialInStream *inStream, + ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, + ICompressProgressInfo *progress); + + STDMETHOD(Code)(ISequentialInStream *inStream, + ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, + ICompressProgressInfo *progress); + + + STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); + + STDMETHOD(SetInStream)(ISequentialInStream *inStream); + STDMETHOD(ReleaseInStream)(); + STDMETHOD(SetOutStreamSize)(const UInt64 *outSize); + + #ifdef _ST_MODE + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + #endif + + CDecoder(): _outSizeDefined(false) {} + +}; + +}} + +#endif diff --git a/CPP/7zip/Compress/PPMD/PPMDEncode.h b/CPP/7zip/Compress/PPMD/PPMDEncode.h new file mode 100755 index 00000000..6a720cac --- /dev/null +++ b/CPP/7zip/Compress/PPMD/PPMDEncode.h @@ -0,0 +1,142 @@ +// PPMDEncode.h +// This code is based on Dmitry Shkarin's PPMdH code + +#ifndef __COMPRESS_PPMD_ENCODE_H +#define __COMPRESS_PPMD_ENCODE_H + +#include "PPMDContext.h" + +namespace NCompress { +namespace NPPMD { + +struct CEncodeInfo: public CInfo +{ + + void EncodeBinSymbol(int symbol, NRangeCoder::CEncoder *rangeEncoder) + { + PPM_CONTEXT::STATE& rs = MinContext->oneState(); + UInt16 &bs = GetBinSumm(rs, GetContextNoCheck(MinContext->Suffix)->NumStats); + if (rs.Symbol == symbol) + { + FoundState = &rs; + rs.Freq = (Byte)(rs.Freq + (rs.Freq < 128 ? 1: 0)); + rangeEncoder->EncodeBit(bs, TOT_BITS, 0); + bs = (UInt16)(bs + INTERVAL - GET_MEAN(bs, PERIOD_BITS, 2)); + PrevSuccess = 1; + RunLength++; + } + else + { + rangeEncoder->EncodeBit(bs, TOT_BITS, 1); + bs = (UInt16)(bs - GET_MEAN(bs, PERIOD_BITS, 2)); + InitEsc = ExpEscape[bs >> 10]; + NumMasked = 1; + CharMask[rs.Symbol] = EscCount; + PrevSuccess = 0; + FoundState = NULL; + } + } + + void EncodeSymbol1(int symbol, NRangeCoder::CEncoder *rangeEncoder) + { + PPM_CONTEXT::STATE* p = GetStateNoCheck(MinContext->Stats); + if (p->Symbol == symbol) + { + PrevSuccess = (2 * (p->Freq) > MinContext->SummFreq); + RunLength += PrevSuccess; + rangeEncoder->Encode(0, p->Freq, MinContext->SummFreq); + (FoundState = p)->Freq += 4; + MinContext->SummFreq += 4; + if (p->Freq > MAX_FREQ) + rescale(); + return; + } + PrevSuccess = 0; + int LoCnt = p->Freq, i = MinContext->NumStats - 1; + while ((++p)->Symbol != symbol) + { + LoCnt += p->Freq; + if (--i == 0) + { + HiBitsFlag = HB2Flag[FoundState->Symbol]; + CharMask[p->Symbol] = EscCount; + i=(NumMasked = MinContext->NumStats)-1; + FoundState = NULL; + do { CharMask[(--p)->Symbol] = EscCount; } while ( --i ); + rangeEncoder->Encode(LoCnt, MinContext->SummFreq - LoCnt, MinContext->SummFreq); + return; + } + } + rangeEncoder->Encode(LoCnt, p->Freq, MinContext->SummFreq); + update1(p); + } + + void EncodeSymbol2(int symbol, NRangeCoder::CEncoder *rangeEncoder) + { + int hiCnt, i = MinContext->NumStats - NumMasked; + UInt32 scale; + SEE2_CONTEXT* psee2c = makeEscFreq2(i, scale); + PPM_CONTEXT::STATE* p = GetStateNoCheck(MinContext->Stats) - 1; + hiCnt = 0; + do + { + do { p++; } while (CharMask[p->Symbol] == EscCount); + hiCnt += p->Freq; + if (p->Symbol == symbol) + goto SYMBOL_FOUND; + CharMask[p->Symbol] = EscCount; + } + while ( --i ); + + rangeEncoder->Encode(hiCnt, scale, hiCnt + scale); + scale += hiCnt; + + psee2c->Summ = (UInt16)(psee2c->Summ + scale); + NumMasked = MinContext->NumStats; + return; +SYMBOL_FOUND: + + UInt32 highCount = hiCnt; + UInt32 lowCount = highCount - p->Freq; + if ( --i ) + { + PPM_CONTEXT::STATE* p1 = p; + do + { + do { p1++; } while (CharMask[p1->Symbol] == EscCount); + hiCnt += p1->Freq; + } + while ( --i ); + } + // SubRange.scale += hiCnt; + scale += hiCnt; + rangeEncoder->Encode(lowCount, highCount - lowCount, scale); + psee2c->update(); + update2(p); + } + + void EncodeSymbol(int c, NRangeCoder::CEncoder *rangeEncoder) + { + if (MinContext->NumStats != 1) + EncodeSymbol1(c, rangeEncoder); + else + EncodeBinSymbol(c, rangeEncoder); + while ( !FoundState ) + { + do + { + OrderFall++; + MinContext = GetContext(MinContext->Suffix); + if (MinContext == 0) + return; // S_OK; + } + while (MinContext->NumStats == NumMasked); + EncodeSymbol2(c, rangeEncoder); + } + NextContext(); + } + +}; +}} + +#endif diff --git a/CPP/7zip/Compress/PPMD/PPMDEncoder.cpp b/CPP/7zip/Compress/PPMD/PPMDEncoder.cpp new file mode 100755 index 00000000..fe99ea5a --- /dev/null +++ b/CPP/7zip/Compress/PPMD/PPMDEncoder.cpp @@ -0,0 +1,155 @@ +// Compress/Associative/Encoder.h + +#include "StdAfx.h" + +#include "Windows/Defs.h" + +// #include <fstream.h> +// #include <iomanip.h> + +#include "Common/Defs.h" + +#include "../../Common/StreamUtils.h" + +#include "PPMDEncoder.h" + +namespace NCompress { +namespace NPPMD { + +const UInt32 kMinMemSize = (1 << 11); +const UInt32 kMinOrder = 2; + +/* +UInt32 g_NumInner = 0; +UInt32 g_InnerCycles = 0; + +UInt32 g_Encode2 = 0; +UInt32 g_Encode2Cycles = 0; +UInt32 g_Encode2Cycles2 = 0; + +class CCounter +{ +public: + CCounter() {} + ~CCounter() + { + ofstream ofs("Res.dat"); + ofs << "innerEncode1 = " << setw(10) << g_NumInner << endl; + ofs << "g_InnerCycles = " << setw(10) << g_InnerCycles << endl; + ofs << "g_Encode2 = " << setw(10) << g_Encode2 << endl; + ofs << "g_Encode2Cycles = " << setw(10) << g_Encode2Cycles << endl; + ofs << "g_Encode2Cycles2= " << setw(10) << g_Encode2Cycles2 << endl; + + } +}; +CCounter g_Counter; +*/ + +STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, + const PROPVARIANT *properties, UInt32 numProperties) +{ + for (UInt32 i = 0; i < numProperties; i++) + { + const PROPVARIANT &prop = properties[i]; + switch(propIDs[i]) + { + case NCoderPropID::kUsedMemorySize: + if (prop.vt != VT_UI4) + return E_INVALIDARG; + if (prop.ulVal < kMinMemSize || prop.ulVal > kMaxMemBlockSize) + return E_INVALIDARG; + _usedMemorySize = (UInt32)prop.ulVal; + break; + case NCoderPropID::kOrder: + if (prop.vt != VT_UI4) + return E_INVALIDARG; + if (prop.ulVal < kMinOrder || prop.ulVal > kMaxOrderCompress) + return E_INVALIDARG; + _order = (Byte)prop.ulVal; + break; + default: + return E_INVALIDARG; + } + } + return S_OK; +} + +STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream) +{ + const UInt32 kPropSize = 5; + Byte properties[kPropSize]; + properties[0] = _order; + for (int i = 0; i < 4; i++) + properties[1 + i] = Byte(_usedMemorySize >> (8 * i)); + return WriteStream(outStream, properties, kPropSize, NULL); +} + +const UInt32 kUsedMemorySizeDefault = (1 << 24); +const int kOrderDefault = 6; + +CEncoder::CEncoder(): + _usedMemorySize(kUsedMemorySizeDefault), + _order(kOrderDefault) +{ +} + + +HRESULT CEncoder::CodeReal(ISequentialInStream *inStream, + ISequentialOutStream *outStream, + const UInt64 * /* inSize */, const UInt64 * /* outSize */, + ICompressProgressInfo *progress) +{ + if (!_inStream.Create(1 << 20)) + return E_OUTOFMEMORY; + if (!_rangeEncoder.Create(1 << 20)) + return E_OUTOFMEMORY; + if (!_info.SubAllocator.StartSubAllocator(_usedMemorySize)) + return E_OUTOFMEMORY; + + _inStream.SetStream(inStream); + _inStream.Init(); + + _rangeEncoder.SetStream(outStream); + _rangeEncoder.Init(); + + CEncoderFlusher flusher(this); + + _info.MaxOrder = 0; + _info.StartModelRare(_order); + + for (;;) + { + UInt32 size = (1 << 18); + do + { + Byte symbol; + if (!_inStream.ReadByte(symbol)) + { + // here we can write End Mark for stream version. + // In current version this feature is not used. + // _info.EncodeSymbol(-1, &_rangeEncoder); + return S_OK; + } + _info.EncodeSymbol(symbol, &_rangeEncoder); + } + while (--size != 0); + if (progress != NULL) + { + UInt64 inSize = _inStream.GetProcessedSize(); + UInt64 outSize = _rangeEncoder.GetProcessedSize(); + RINOK(progress->SetRatioInfo(&inSize, &outSize)); + } + } +} + +STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, + ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, + ICompressProgressInfo *progress) +{ + try { return CodeReal(inStream, outStream, inSize, outSize, progress); } + catch(const COutBufferException &e) { return e.ErrorCode; } + catch(const CInBufferException &e) { return e.ErrorCode; } + catch(...) { return E_FAIL; } +} + +}} diff --git a/CPP/7zip/Compress/PPMD/PPMDEncoder.h b/CPP/7zip/Compress/PPMD/PPMDEncoder.h new file mode 100755 index 00000000..915180b9 --- /dev/null +++ b/CPP/7zip/Compress/PPMD/PPMDEncoder.h @@ -0,0 +1,81 @@ +// Compress/PPMD/Encoder.h + +#ifndef __COMPRESS_PPMD_ENCODER_H +#define __COMPRESS_PPMD_ENCODER_H + +#include "../../../Common/MyCom.h" + +#include "../../ICoder.h" +#include "../../Common/InBuffer.h" +#include "../RangeCoder/RangeCoder.h" + +#include "PPMDEncode.h" + +namespace NCompress { +namespace NPPMD { + +class CEncoder : + public ICompressCoder, + public ICompressSetCoderProperties, + public ICompressWriteCoderProperties, + public CMyUnknownImp +{ +public: + CInBuffer _inStream; + + NRangeCoder::CEncoder _rangeEncoder; + + CEncodeInfo _info; + UInt32 _usedMemorySize; + Byte _order; + + HRESULT Flush() + { + _rangeEncoder.FlushData(); + return _rangeEncoder.FlushStream(); + } + + void ReleaseStreams() + { + _inStream.ReleaseStream(); + _rangeEncoder.ReleaseStream(); + } + + HRESULT CodeReal(ISequentialInStream *inStream, + ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, + ICompressProgressInfo *progress); + + class CEncoderFlusher + { + CEncoder *_encoder; + public: + CEncoderFlusher(CEncoder *encoder): _encoder(encoder) {} + ~CEncoderFlusher() + { + _encoder->Flush(); + _encoder->ReleaseStreams(); + } + }; + +public: + + MY_UNKNOWN_IMP2( + ICompressSetCoderProperties, + ICompressWriteCoderProperties) + + STDMETHOD(Code)(ISequentialInStream *inStream, + ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, + ICompressProgressInfo *progress); + + STDMETHOD(SetCoderProperties)(const PROPID *propIDs, + const PROPVARIANT *properties, UInt32 numProperties); + + STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream); + + CEncoder(); + +}; + +}} + +#endif diff --git a/CPP/7zip/Compress/PPMD/PPMDSubAlloc.h b/CPP/7zip/Compress/PPMD/PPMDSubAlloc.h new file mode 100755 index 00000000..dce765d6 --- /dev/null +++ b/CPP/7zip/Compress/PPMD/PPMDSubAlloc.h @@ -0,0 +1,292 @@ +// PPMDSubAlloc.h +// This code is based on Dmitry Shkarin's PPMdH code + +#ifndef __PPMD_SUBALLOC_H +#define __PPMD_SUBALLOC_H + +#include "PPMDType.h" + +#include "../../../Common/Alloc.h" + +const UINT N1=4, N2=4, N3=4, N4=(128+3-1*N1-2*N2-3*N3)/4; +const UINT UNIT_SIZE=12, N_INDEXES=N1+N2+N3+N4; + +// Extra 1 * UNIT_SIZE for NULL support +// Extra 2 * UNIT_SIZE for s0 in GlueFreeBlocks() +const UInt32 kExtraSize = (UNIT_SIZE * 3); +const UInt32 kMaxMemBlockSize = 0xFFFFFFFF - kExtraSize; + +struct MEM_BLK +{ + UInt16 Stamp, NU; + UInt32 Next, Prev; + void InsertAt(Byte *Base, UInt32 p) + { + Prev = p; + MEM_BLK *pp = (MEM_BLK *)(Base + p); + Next = pp->Next; + pp->Next = ((MEM_BLK *)(Base + Next))->Prev = (UInt32)((Byte *)this - Base); + } + void Remove(Byte *Base) + { + ((MEM_BLK *)(Base + Prev))->Next = Next; + ((MEM_BLK *)(Base + Next))->Prev = Prev; + } +}; + + +class CSubAllocator +{ + UInt32 SubAllocatorSize; + Byte Indx2Units[N_INDEXES], Units2Indx[128], GlueCount; + UInt32 FreeList[N_INDEXES]; + + Byte *Base; + Byte *HeapStart, *LoUnit, *HiUnit; +public: + Byte *pText, *UnitsStart; + CSubAllocator(): + SubAllocatorSize(0), + GlueCount(0), + LoUnit(0), + HiUnit(0), + pText(0), + UnitsStart(0) + { + memset(Indx2Units, 0, sizeof(Indx2Units)); + memset(FreeList, 0, sizeof(FreeList)); + } + ~CSubAllocator() + { + StopSubAllocator(); + }; + + void *GetPtr(UInt32 offset) const { return (offset == 0) ? 0 : (void *)(Base + offset); } + void *GetPtrNoCheck(UInt32 offset) const { return (void *)(Base + offset); } + UInt32 GetOffset(void *ptr) const { return (ptr == 0) ? 0 : (UInt32)((Byte *)ptr - Base); } + UInt32 GetOffsetNoCheck(void *ptr) const { return (UInt32)((Byte *)ptr - Base); } + MEM_BLK *GetBlk(UInt32 offset) const { return (MEM_BLK *)(Base + offset); } + UInt32 *GetNode(UInt32 offset) const { return (UInt32 *)(Base + offset); } + + void InsertNode(void* p, int indx) + { + *(UInt32 *)p = FreeList[indx]; + FreeList[indx] = GetOffsetNoCheck(p); + } + + void* RemoveNode(int indx) + { + UInt32 offset = FreeList[indx]; + UInt32 *p = GetNode(offset); + FreeList[indx] = *p; + return (void *)p; + } + + UINT U2B(int NU) const { return (UINT)(NU) * UNIT_SIZE; } + + void SplitBlock(void* pv, int oldIndx, int newIndx) + { + int i, UDiff = Indx2Units[oldIndx] - Indx2Units[newIndx]; + Byte* p = ((Byte*)pv) + U2B(Indx2Units[newIndx]); + if (Indx2Units[i = Units2Indx[UDiff-1]] != UDiff) + { + InsertNode(p, --i); + p += U2B(i = Indx2Units[i]); + UDiff -= i; + } + InsertNode(p, Units2Indx[UDiff - 1]); + } + + UInt32 GetUsedMemory() const + { + UInt32 RetVal = SubAllocatorSize - (UInt32)(HiUnit - LoUnit) - (UInt32)(UnitsStart - pText); + for (UInt32 i = 0; i < N_INDEXES; i++) + for (UInt32 pn = FreeList[i]; pn != 0; RetVal -= (UInt32)Indx2Units[i] * UNIT_SIZE) + pn = *GetNode(pn); + return (RetVal >> 2); + } + + UInt32 GetSubAllocatorSize() const { return SubAllocatorSize; } + + void StopSubAllocator() + { + if (SubAllocatorSize != 0) + { + BigFree(Base); + SubAllocatorSize = 0; + Base = 0; + } + } + + bool StartSubAllocator(UInt32 size) + { + if (SubAllocatorSize == size) + return true; + StopSubAllocator(); + if (size == 0) + Base = 0; + else + { + if ((Base = (Byte *)::BigAlloc(size + kExtraSize)) == 0) + return false; + HeapStart = Base + UNIT_SIZE; // we need such code to support NULL; + } + SubAllocatorSize = size; + return true; + } + + void InitSubAllocator() + { + int i, k; + memset(FreeList, 0, sizeof(FreeList)); + HiUnit = (pText = HeapStart) + SubAllocatorSize; + UINT Diff = UNIT_SIZE * (SubAllocatorSize / 8 / UNIT_SIZE * 7); + LoUnit = UnitsStart = HiUnit - Diff; + for (i = 0, k=1; i < N1 ; i++, k += 1) Indx2Units[i] = (Byte)k; + for (k++; i < N1 + N2 ;i++, k += 2) Indx2Units[i] = (Byte)k; + for (k++; i < N1 + N2 + N3 ;i++,k += 3) Indx2Units[i] = (Byte)k; + for (k++; i < N1 + N2 + N3 + N4; i++, k += 4) Indx2Units[i] = (Byte)k; + GlueCount = 0; + for (k = i = 0; k < 128; k++) + { + i += (Indx2Units[i] < k+1); + Units2Indx[k] = (Byte)i; + } + } + + void GlueFreeBlocks() + { + UInt32 s0 = (UInt32)(HeapStart + SubAllocatorSize - Base); + + // We need add exta MEM_BLK with Stamp=0 + GetBlk(s0)->Stamp = 0; + s0 += UNIT_SIZE; + MEM_BLK *ps0 = GetBlk(s0); + + UInt32 p; + int i; + if (LoUnit != HiUnit) + *LoUnit=0; + ps0->Next = ps0->Prev = s0; + + for (i = 0; i < N_INDEXES; i++) + while (FreeList[i] != 0) + { + MEM_BLK *pp = (MEM_BLK *)RemoveNode(i); + pp->InsertAt(Base, s0); + pp->Stamp = 0xFFFF; + pp->NU = Indx2Units[i]; + } + for (p = ps0->Next; p != s0; p = GetBlk(p)->Next) + { + for (;;) + { + MEM_BLK *pp = GetBlk(p); + MEM_BLK *pp1 = GetBlk(p + pp->NU * UNIT_SIZE); + if (pp1->Stamp != 0xFFFF || int(pp->NU) + pp1->NU >= 0x10000) + break; + pp1->Remove(Base); + pp->NU = (UInt16)(pp->NU + pp1->NU); + } + } + while ((p = ps0->Next) != s0) + { + MEM_BLK *pp = GetBlk(p); + pp->Remove(Base); + int sz; + for (sz = pp->NU; sz > 128; sz -= 128, p += 128 * UNIT_SIZE) + InsertNode(Base + p, N_INDEXES - 1); + if (Indx2Units[i = Units2Indx[sz-1]] != sz) + { + int k = sz - Indx2Units[--i]; + InsertNode(Base + p + (sz - k) * UNIT_SIZE, k - 1); + } + InsertNode(Base + p, i); + } + } + void* AllocUnitsRare(int indx) + { + if ( !GlueCount ) + { + GlueCount = 255; + GlueFreeBlocks(); + if (FreeList[indx] != 0) + return RemoveNode(indx); + } + int i = indx; + do + { + if (++i == N_INDEXES) + { + GlueCount--; + i = U2B(Indx2Units[indx]); + return (UnitsStart - pText > i) ? (UnitsStart -= i) : (NULL); + } + } while (FreeList[i] == 0); + void* RetVal = RemoveNode(i); + SplitBlock(RetVal, i, indx); + return RetVal; + } + + void* AllocUnits(int NU) + { + int indx = Units2Indx[NU - 1]; + if (FreeList[indx] != 0) + return RemoveNode(indx); + void* RetVal = LoUnit; + LoUnit += U2B(Indx2Units[indx]); + if (LoUnit <= HiUnit) + return RetVal; + LoUnit -= U2B(Indx2Units[indx]); + return AllocUnitsRare(indx); + } + + void* AllocContext() + { + if (HiUnit != LoUnit) + return (HiUnit -= UNIT_SIZE); + if (FreeList[0] != 0) + return RemoveNode(0); + return AllocUnitsRare(0); + } + + void* ExpandUnits(void* oldPtr, int oldNU) + { + int i0=Units2Indx[oldNU - 1], i1=Units2Indx[oldNU - 1 + 1]; + if (i0 == i1) + return oldPtr; + void* ptr = AllocUnits(oldNU + 1); + if (ptr) + { + memcpy(ptr, oldPtr, U2B(oldNU)); + InsertNode(oldPtr, i0); + } + return ptr; + } + + void* ShrinkUnits(void* oldPtr, int oldNU, int newNU) + { + int i0 = Units2Indx[oldNU - 1], i1 = Units2Indx[newNU - 1]; + if (i0 == i1) + return oldPtr; + if (FreeList[i1] != 0) + { + void* ptr = RemoveNode(i1); + memcpy(ptr, oldPtr, U2B(newNU)); + InsertNode(oldPtr,i0); + return ptr; + } + else + { + SplitBlock(oldPtr, i0, i1); + return oldPtr; + } + } + + void FreeUnits(void* ptr, int oldNU) + { + InsertNode(ptr, Units2Indx[oldNU - 1]); + } +}; + +#endif diff --git a/CPP/7zip/Compress/PPMD/PPMDType.h b/CPP/7zip/Compress/PPMD/PPMDType.h new file mode 100755 index 00000000..5200fa54 --- /dev/null +++ b/CPP/7zip/Compress/PPMD/PPMDType.h @@ -0,0 +1,19 @@ +/**************************************************************************** + * This file is part of PPMd project * + * Written and distributed to public domain by Dmitry Shkarin 1997, * + * 1999-2001 * + * Contents: compilation parameters and miscelaneous definitions * + * Comments: system & compiler dependent file + + * modified by Igor Pavlov (2004-08-29). + ****************************************************************************/ +#ifndef __PPMD_TYPE_H +#define __PPMD_TYPE_H + +const int kMaxOrderCompress = 32; +const int MAX_O = 255; /* maximum allowed model order */ + +template <class T> +inline void _PPMD_SWAP(T& t1,T& t2) { T tmp = t1; t1 = t2; t2 = tmp; } + +#endif diff --git a/CPP/7zip/Compress/PPMD/StdAfx.cpp b/CPP/7zip/Compress/PPMD/StdAfx.cpp new file mode 100755 index 00000000..d0feea85 --- /dev/null +++ b/CPP/7zip/Compress/PPMD/StdAfx.cpp @@ -0,0 +1,3 @@ +// StdAfx.cpp + +#include "StdAfx.h" diff --git a/CPP/7zip/Compress/PPMD/StdAfx.h b/CPP/7zip/Compress/PPMD/StdAfx.h new file mode 100755 index 00000000..e7fb6986 --- /dev/null +++ b/CPP/7zip/Compress/PPMD/StdAfx.h @@ -0,0 +1,8 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../../Common/MyWindows.h" + +#endif diff --git a/CPP/7zip/Compress/PPMD/makefile b/CPP/7zip/Compress/PPMD/makefile new file mode 100755 index 00000000..2e687a70 --- /dev/null +++ b/CPP/7zip/Compress/PPMD/makefile @@ -0,0 +1,41 @@ +PROG = PPMd.dll +DEF_FILE = ../Codec.def +CFLAGS = $(CFLAGS) -I ../../../ +LIBS = $(LIBS) oleaut32.lib + +PPMD_OBJS = \ + $O\DllExports.obj \ + +PPMD_OPT_OBJS = \ + $O\PPMDDecoder.obj \ + $O\PPMDEncoder.obj \ + +COMMON_OBJS = \ + $O\Alloc.obj \ + +7ZIP_COMMON_OBJS = \ + $O\InBuffer.obj \ + $O\OutBuffer.obj \ + $O\StreamUtils.obj \ + + +OBJS = \ + $O\StdAfx.obj \ + $(PPMD_OBJS) \ + $(PPMD_OPT_OBJS) \ + $(COMMON_OBJS) \ + $(7ZIP_COMMON_OBJS) \ + $O\resource.res + + +!include "../../../Build.mak" + +$(PPMD_OBJS): $(*B).cpp + $(COMPL) +$(PPMD_OPT_OBJS): $(*B).cpp + $(COMPL_O2) +$(COMMON_OBJS): ../../../Common/$(*B).cpp + $(COMPL) +$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp + $(COMPL) + diff --git a/CPP/7zip/Compress/PPMD/resource.rc b/CPP/7zip/Compress/PPMD/resource.rc new file mode 100755 index 00000000..fed98e19 --- /dev/null +++ b/CPP/7zip/Compress/PPMD/resource.rc @@ -0,0 +1,3 @@ +#include "../../MyVersionInfo.rc" + +MY_VERSION_INFO_DLL("PPMd Codec", "PPMd") |