summaryrefslogtreecommitdiffstats
path: root/private/windows/diamond/quantum/lz.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/windows/diamond/quantum/lz.c')
-rw-r--r--private/windows/diamond/quantum/lz.c719
1 files changed, 719 insertions, 0 deletions
diff --git a/private/windows/diamond/quantum/lz.c b/private/windows/diamond/quantum/lz.c
new file mode 100644
index 000000000..4d91da0a0
--- /dev/null
+++ b/private/windows/diamond/quantum/lz.c
@@ -0,0 +1,719 @@
+// LZ.C
+//
+// Quantum file archiver and compressor
+// Advanced data compression
+//
+// Copyright (c) 1993,1994 Cinematronics
+// All rights reserved.
+//
+// This file contains trade secrets of Cinematronics.
+// Do NOT distribute!
+
+
+#ifdef STAFFORD
+#define ASM asm
+#else
+#define ASM __asm
+#endif
+
+
+#ifndef __PCC__
+ #pragma auto_inline(on)
+#endif
+
+#include <stdlib.h>
+#include "arith.h"
+#include "quantum.h" //msliger
+#include "lz.h"
+#include "comp.h"
+#include "dcomp.h"
+
+#ifdef __PCC__ //msliger
+#include "log.h"
+#endif //msliger
+
+typedef struct
+ {
+ unsigned Freq;
+ unsigned Symbol;
+ } COUNT;
+
+
+typedef struct
+ {
+ int Num; // Number of symbols in this table, max of 64
+#ifdef PAQ
+ int Lookup[ 65 ]; // Given a symbol identifies its index
+#endif
+ int SortCountdown;
+ COUNT Table[ 65 ]; // Yucky but 64+1 is the largest we ever need...
+ } COUNT_RECORD;
+
+
+struct
+ {
+ COUNT_RECORD TokenType;
+ COUNT_RECORD Literal1;
+ COUNT_RECORD Literal2;
+ COUNT_RECORD Literal3;
+ COUNT_RECORD Literal4;
+
+ COUNT_RECORD MatchCode;
+
+ COUNT_RECORD WindowCode;
+ COUNT_RECORD TinyWindowCode;
+ COUNT_RECORD ShortWindowCode;
+ } Count;
+
+
+typedef struct
+ {
+#ifdef PAQ
+ unsigned MatchCodeTrans[ MATCH_NUM ];
+#endif
+ unsigned MatchCodeBase[ MATCH_CODES ];
+
+#ifdef PAQ
+ unsigned WindowCodeTrans[ 2048 + (1 << (WINDOW_MAX-10)) ];
+#endif
+ long WindowCodeBase[ WINDOW_CODES ];
+
+#ifdef DEBUG
+ long Stat[ 7 ];
+#endif
+ } LZ;
+
+LZ Lz;
+
+// Extra bits for each match length code
+
+unsigned MatchCodeExtra[ MATCH_CODES ] =
+ { 0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0 };
+
+// Extra bits for each distance code
+
+unsigned WindowCodeExtra[ WINDOW_CODES ] =
+ { 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,
+ 12,12,13,13,14,14,15,15,16,16,17,17,18,18,19,19 };
+
+
+extern LONGDOUBLE FAST MYLOG( LONGDOUBLE x );
+
+
+void FAST Lz_Init( BYTE WindowBits ) //msliger
+ {
+ int i, k;
+ long Base, WindowSize;
+
+ WindowSize = 1L << WindowBits; //msliger
+
+ for( Base = i = 0; i < MATCH_CODES; i++ )
+ {
+ Lz.MatchCodeBase[ i ] = (unsigned) Base;
+
+ for( k = 0; k < (1 << MatchCodeExtra[ i ]); k++ )
+ {
+#ifdef PAQ
+ Lz.MatchCodeTrans[ Base++ ] = i;
+#else
+ Base++;
+#endif
+ }
+ }
+
+ for( Base = i = 0; i < WINDOW_CODES; i++ )
+ {
+ if( Base < WindowSize )
+ {
+ Count.WindowCode.Num = i + 1;
+
+ if( Base < 1 << (TINY_WINDOW_MAX) )
+ {
+ Count.TinyWindowCode.Num = i + 1;
+ }
+
+ if( Base < 1L << (SHORT_WINDOW_MAX) )
+ {
+ Count.ShortWindowCode.Num = i + 1;
+ }
+ }
+
+ Lz.WindowCodeBase[ i ] = Base;
+
+ Base += (1L << WindowCodeExtra[ i ]);
+ }
+
+#ifdef PAQ
+ for( i = 0; i < 2048; i++ )
+ {
+ for( k = 0; Lz.WindowCodeBase[ k ] <= i; k++ )
+ ;
+
+ Lz.WindowCodeTrans[ i ] = k - 1;
+ }
+
+ Base = 2;
+
+ for( k = k - 1; k < WINDOW_CODES; k++ )
+ {
+ for( i = 0; i < (1 << (WindowCodeExtra[ k ] - 10)); i++ )
+ {
+ Lz.WindowCodeTrans[ 2048 + Base++ ] = k;
+ }
+ }
+#endif
+
+ Count.TokenType.Num = 7;
+ Count.TokenType.SortCountdown = 4;
+
+ for( i = 0; i <= 7; i++ )
+ {
+ Count.TokenType.Table[ i ].Freq = 7 - i;
+ Count.TokenType.Table[ i ].Symbol = i;
+
+#ifdef PAQ
+ Count.TokenType.Lookup[ i ] = i;
+#endif
+ }
+
+ Count.Literal1.Num =
+ Count.Literal2.Num =
+ Count.Literal3.Num =
+ Count.Literal4.Num = 64;
+
+ Count.Literal1.SortCountdown =
+ Count.Literal2.SortCountdown =
+ Count.Literal3.SortCountdown =
+ Count.Literal4.SortCountdown = 4;
+
+ for( i = 0; i <= 64; i++ )
+ {
+ Count.Literal1.Table[ i ].Freq = 64 - i;
+ Count.Literal2.Table[ i ].Freq = 64 - i;
+ Count.Literal3.Table[ i ].Freq = 64 - i;
+ Count.Literal4.Table[ i ].Freq = 64 - i;
+
+ Count.Literal1.Table[ i ].Symbol = i;
+ Count.Literal2.Table[ i ].Symbol = i;
+ Count.Literal3.Table[ i ].Symbol = i;
+ Count.Literal4.Table[ i ].Symbol = i;
+
+#ifdef PAQ
+ Count.Literal1.Lookup[ i ] = i;
+ Count.Literal2.Lookup[ i ] = i;
+ Count.Literal3.Lookup[ i ] = i;
+ Count.Literal4.Lookup[ i ] = i;
+#endif
+ }
+
+ Count.MatchCode.Num = MATCH_CODES;
+ Count.MatchCode.SortCountdown = 4;
+
+ for( i = 0; i <= MATCH_CODES; i++ )
+ {
+ Count.MatchCode.Table[ i ].Freq = MATCH_CODES - i;
+ Count.MatchCode.Table[ i ].Symbol = i;
+
+#ifdef PAQ
+ Count.MatchCode.Lookup[ i ] = i;
+#endif
+ }
+
+ Count.WindowCode.SortCountdown = 4;
+ Count.TinyWindowCode.SortCountdown = 4;
+ Count.ShortWindowCode.SortCountdown = 4;
+
+ for( i = 0; i <= WINDOW_CODES; i++ )
+ {
+ Count.WindowCode.Table[ i ].Freq = Count.WindowCode.Num - i;
+ Count.TinyWindowCode.Table[ i ].Freq = Count.TinyWindowCode.Num - i;
+ Count.ShortWindowCode.Table[ i ].Freq = Count.ShortWindowCode.Num - i;
+
+ Count.WindowCode.Table[ i ].Symbol = i;
+ Count.TinyWindowCode.Table[ i ].Symbol = i;
+ Count.ShortWindowCode.Table[ i ].Symbol = i;
+
+#ifdef PAQ
+ Count.WindowCode.Lookup[ i ] = i;
+ Count.TinyWindowCode.Lookup[ i ] = i;
+ Count.ShortWindowCode.Lookup[ i ] = i;
+#endif
+ }
+
+#ifndef UNPAQLIB //msliger
+ Arith_Init();
+#endif //msliger
+ }
+
+
+void FAST Lz_Close( void )
+ {
+ #ifdef DEBUG
+ #ifdef PAQ
+ printf( "\n\n" );
+ printf( "Stats:\n" );
+ printf( "Literal 0 = %ld\n", Lz.Stat[ 0 ] );
+ printf( "Literal 1 = %ld\n", Lz.Stat[ 1 ] );
+ printf( "Literal 2 = %ld\n", Lz.Stat[ 2 ] );
+ printf( "Literal 3 = %ld\n", Lz.Stat[ 3 ] );
+ printf( "Match 3 = %ld\n", Lz.Stat[ 4 ] );
+ printf( "Match 4 = %ld\n", Lz.Stat[ 5 ] );
+ printf( "Match 5+ = %ld\n", Lz.Stat[ 6 ] );
+ #endif
+ #endif
+
+#ifndef PAQLIB //msliger
+#ifndef UNPAQLIB //msliger
+ Arith_Close();
+#endif //msliger
+#endif //msliger
+ }
+
+
+void FAST Lz_Bump( COUNT_RECORD NEAR *Rec )
+ {
+ COUNT NEAR *pTab;
+ int Num;
+ int i, j;
+ COUNT Scratch;
+
+ pTab = Rec->Table;
+ Num = Rec->Num;
+
+ if( --Rec->SortCountdown == 0 )
+ {
+ Rec->SortCountdown = 50;
+
+ // Change all the frequencies to their absolute values divided by two.
+
+ for( i = 0; i < Num; i++ )
+ {
+ pTab[ i ].Freq -= pTab[ i + 1 ].Freq;
+
+ pTab[ i ].Freq++;
+ pTab[ i ].Freq >>= 1;
+ }
+
+ // Sort them.
+ // Yes, this could be a faster sort but the list is never
+ // more than 64 items and it spends very little time here.
+
+ for( i = 0; i < Num; i++ )
+ {
+ for( j = i + 1; j < Num; j++ )
+ {
+ if( pTab[ j ].Freq > pTab[ i ].Freq )
+ {
+ Scratch = pTab[ i ];
+ pTab[ i ] = pTab[ j ];
+ pTab[ j ] = Scratch;
+ }
+ }
+ }
+
+ // Recreate the relative frequencies.
+
+ for( i = Num - 1; i >= 0; i-- )
+ {
+ pTab[ i ].Freq += pTab[ i + 1 ].Freq;
+ }
+
+#ifdef PAQ
+ // Rebuild the lookup table.
+
+ for( i = 0; i < Num; i++ )
+ {
+ Rec->Lookup[ pTab[ i ].Symbol ] = i;
+ }
+#endif
+ }
+ else /* SortCountDown != 0 */
+ {
+ for( i = Num - 1; i >= 0; i-- )
+ {
+ pTab[ i ].Freq >>= 1;
+
+ if( pTab[ i ].Freq <= pTab[ i + 1 ].Freq )
+ {
+ pTab[ i ].Freq = pTab[ i + 1 ].Freq + 1;
+ }
+ }
+ }
+ }
+
+
+#ifdef PAQ
+
+// Maps a distance into a window code
+
+int FAST Lz_MapDistanceToWindowCode( long Distance )
+ {
+ if( Distance < 2048 )
+ {
+ return( Lz.WindowCodeTrans[ Distance ] );
+ }
+ else
+ {
+ return( Lz.WindowCodeTrans[ 2048 + (Distance >> 10) ] );
+ }
+ }
+
+
+LONGDOUBLE FAST EstimateBits( long Occur, long Total )
+ {
+ #ifdef DEBUG
+ if( Occur <= 0 || Total <= 0 )
+ {
+ puts( "ERR: Domain" );
+ exit( -1 );
+ }
+ #endif
+
+ return( MYLOG( (LONGDOUBLE)Total / (LONGDOUBLE)Occur ) );
+ }
+
+
+void FAST Lz_Encode_Symbol( COUNT_RECORD *Rec, int Sym )
+ {
+ register COUNT NEAR *pTab;
+ SYMBOL Symbol;
+ int Index = Rec->Lookup[ Sym ];
+
+ Symbol.High = Rec->Table[ Index ].Freq;
+ Symbol.Low = Rec->Table[ Index + 1 ].Freq;
+ Symbol.Scale = Rec->Table[ 0 ].Freq;
+
+ Arith_Encode_Symbol( &Symbol );
+
+ pTab = (COUNT NEAR *) Rec->Table;
+
+ do
+ {
+ pTab->Freq += MAGIC_INC;
+ pTab++;
+ }
+ while( Index-- );
+
+ if( Rec->Table[ 0 ].Freq > MAGIC_MAX )
+ {
+ Lz_Bump( Rec );
+ }
+ }
+
+
+LONGDOUBLE FAST Lz_Encode_Symbol_Cost( COUNT_RECORD *Rec, int Sym )
+ {
+ int Index = Rec->Lookup[ Sym ];
+
+ return( EstimateBits(
+ Rec->Table[ Index ].Freq - Rec->Table[ Index + 1 ].Freq,
+ Rec->Table[ 0 ].Freq ) );
+ }
+
+
+LONGDOUBLE FAST Lz_Encode_Match_Cost( MATCH *Match )
+ {
+ int Code;
+ LONGDOUBLE Total;
+
+ switch( Match->Len )
+ {
+ case 3:
+ Total = Lz_Encode_Symbol_Cost( &Count.TokenType, 4 );
+ Code = Lz_MapDistanceToWindowCode( Match->Dist - 1 );
+ Total += Lz_Encode_Symbol_Cost( &Count.TinyWindowCode, Code );
+ break;
+ case 4:
+ Total = Lz_Encode_Symbol_Cost( &Count.TokenType, 5 );
+ Code = Lz_MapDistanceToWindowCode( Match->Dist - 1 );
+ Total += Lz_Encode_Symbol_Cost( &Count.ShortWindowCode, Code );
+ break;
+ default:
+ Total = Lz_Encode_Symbol_Cost( &Count.TokenType, 6 );
+ Code = Lz.MatchCodeTrans[ Match->Len - 5 ];
+ Total += Lz_Encode_Symbol_Cost( &Count.MatchCode, Code );
+ Total += MatchCodeExtra[ Code ];
+ Code = Lz_MapDistanceToWindowCode( Match->Dist - 1 );
+ Total += Lz_Encode_Symbol_Cost( &Count.WindowCode, Code );
+ }
+
+ Total += WindowCodeExtra[ Code ];
+
+ return( Total );
+ }
+
+
+void FAST Lz_Encode_Match( MATCH *Match )
+ {
+ int Code;
+
+ switch( Match->Len )
+ {
+ case 3:
+ #ifdef DEBUG
+ Lz.Stat[ 4 ]++;
+ #endif
+
+ Lz_Encode_Symbol( &Count.TokenType, 4 );
+ Code = Lz_MapDistanceToWindowCode( Match->Dist - 1 );
+ Lz_Encode_Symbol( &Count.TinyWindowCode, Code );
+ break;
+
+ case 4:
+ #ifdef DEBUG
+ Lz.Stat[ 5 ]++;
+ #endif
+
+ Lz_Encode_Symbol( &Count.TokenType, 5 );
+ Code = Lz_MapDistanceToWindowCode( Match->Dist - 1 );
+ Lz_Encode_Symbol( &Count.ShortWindowCode, Code );
+ break;
+
+ default:
+ #ifdef DEBUG
+ Lz.Stat[ 6 ]++;
+ #endif
+
+ Lz_Encode_Symbol( &Count.TokenType, 6 );
+ Code = Lz.MatchCodeTrans[ Match->Len - 5 ];
+ Lz_Encode_Symbol( &Count.MatchCode, Code );
+ Arith_Encode_Bits( Match->Len - 5 - Lz.MatchCodeBase[ Code ],
+ MatchCodeExtra[ Code ] );
+ Code = Lz_MapDistanceToWindowCode( Match->Dist - 1 );
+ Lz_Encode_Symbol( &Count.WindowCode, Code );
+ }
+
+ Arith_Encode_Bits( Match->Dist - 1 - Lz.WindowCodeBase[ Code ],
+ WindowCodeExtra[ Code ] );
+ }
+
+
+LONGDOUBLE FAST Lz_Encode_Literal_Cost( int Chr )
+ {
+ LONGDOUBLE Total;
+
+ if( Chr < 64 )
+ {
+ Total = Lz_Encode_Symbol_Cost( &Count.TokenType, 0 ) +
+ Lz_Encode_Symbol_Cost( &Count.Literal1, Chr );
+ }
+ else
+ {
+ if( Chr < 128 )
+ {
+ Total = Lz_Encode_Symbol_Cost( &Count.TokenType, 1 ) +
+ Lz_Encode_Symbol_Cost( &Count.Literal2, Chr - 64 );
+ }
+ else
+ {
+ if( Chr < 192 )
+ {
+ Total = Lz_Encode_Symbol_Cost( &Count.TokenType, 2 ) +
+ Lz_Encode_Symbol_Cost( &Count.Literal3, Chr - 128 );
+ }
+ else
+ {
+ Total = Lz_Encode_Symbol_Cost( &Count.TokenType, 3 ) +
+ Lz_Encode_Symbol_Cost( &Count.Literal4, Chr - 192 );
+ }
+ }
+ }
+
+ return( Total );
+ }
+
+
+void FAST Lz_Encode_Literal( int Chr )
+ {
+ if( Chr < 64 )
+ {
+ #ifdef DEBUG
+ Lz.Stat[ 0 ]++;
+ #endif
+ Lz_Encode_Symbol( &Count.TokenType, 0 );
+ Lz_Encode_Symbol( &Count.Literal1, Chr );
+ }
+ else
+ {
+ if( Chr < 128 )
+ {
+ #ifdef DEBUG
+ Lz.Stat[ 1 ]++;
+ #endif
+ Lz_Encode_Symbol( &Count.TokenType, 1 );
+ Lz_Encode_Symbol( &Count.Literal2, Chr - 64 );
+ }
+ else
+ {
+ if( Chr < 192 )
+ {
+ #ifdef DEBUG
+ Lz.Stat[ 2 ]++;
+ #endif
+ Lz_Encode_Symbol( &Count.TokenType, 2 );
+ Lz_Encode_Symbol( &Count.Literal3, Chr - 128 );
+ }
+ else
+ {
+ #ifdef DEBUG
+ Lz.Stat[ 3 ]++;
+ #endif
+ Lz_Encode_Symbol( &Count.TokenType, 3 );
+ Lz_Encode_Symbol( &Count.Literal4, Chr - 192 );
+ }
+ }
+ }
+ }
+
+
+#else //UNPAQ
+
+#define LZ_DECODE_SYMBOL(Rec,Sym) \
+ { \
+/* SYMBOL Symbol; / I defined these at the top of */ \
+/* unsigned Counter; / the calling function because */ \
+/* int Index; / the compiler wasn't re-using */ \
+/* register COUNT NEAR *pTab; / the local variable space. */ \
+ \
+ Symbol.Scale = Rec.Table[ 0 ].Freq; \
+ \
+ Counter = Arith_GetCount( Symbol.Scale ); \
+ \
+ Index = 0; \
+ \
+ while ( Rec.Table[ Index + 1 ].Freq > Counter ) \
+ { \
+ Index++; \
+ } \
+ \
+ Sym = Rec.Table[ Index ].Symbol; \
+ \
+ Symbol.High = Rec.Table[ Index ].Freq; \
+ Symbol.Low = Rec.Table[ Index + 1 ].Freq; \
+ \
+ Arith_Remove_Symbol( Symbol ); \
+ \
+ pTab = (COUNT NEAR *) &Rec.Table; \
+ \
+ do \
+ { \
+ pTab->Freq += MAGIC_INC; \
+ pTab++; \
+ } \
+ while( Index-- ); \
+ \
+ if( Rec.Table[ 0 ].Freq > MAGIC_MAX ) \
+ { \
+ Lz_Bump((COUNT_RECORD NEAR *)&Rec ); \
+ } \
+ }
+
+
+void FAST Lz_NextToken( void )
+ {
+ int Code;
+ MATCH Match;
+ SYMBOL Symbol; /* ref'd from macro */
+ unsigned Counter; /* ref'd from macro */
+ int Index; /* ref'd from macro */
+ register COUNT NEAR *pTab; /* ref'd from macro */
+
+ LZ_DECODE_SYMBOL(Count.TokenType,Code);
+
+ switch( Code )
+ {
+ case 0:
+ LZ_DECODE_SYMBOL(Count.Literal1,Code);
+ DComp_Token_Literal( Code );
+ break;
+
+ case 1:
+ LZ_DECODE_SYMBOL(Count.Literal2,Code);
+ DComp_Token_Literal( Code + 64 );
+ break;
+
+ case 2:
+ LZ_DECODE_SYMBOL(Count.Literal3,Code);
+ DComp_Token_Literal( Code + 128 );
+ break;
+
+ case 3:
+ LZ_DECODE_SYMBOL(Count.Literal4,Code);
+ DComp_Token_Literal( Code + 192 );
+ break;
+
+ case 4:
+ Match.Len = 3;
+ LZ_DECODE_SYMBOL(Count.TinyWindowCode,Code);
+ Match.Dist = Lz.WindowCodeBase[ Code ] +
+ Arith_Decode_Bits( WindowCodeExtra[ Code ] ) + 1;
+ DComp_Token_Match( Match );
+ break;
+
+ case 5:
+ Match.Len = 4;
+ LZ_DECODE_SYMBOL(Count.ShortWindowCode,Code);
+ Match.Dist = Lz.WindowCodeBase[ Code ] +
+ Arith_Decode_Bits( WindowCodeExtra[ Code ] ) + 1;
+ DComp_Token_Match( Match );
+ break;
+
+ case 6:
+ LZ_DECODE_SYMBOL(Count.MatchCode,Code);
+ Match.Len = Lz.MatchCodeBase[ Code ] +
+ (short) Arith_Decode_Bits( MatchCodeExtra[ Code ] ) + 5;
+ LZ_DECODE_SYMBOL(Count.WindowCode,Code);
+ Match.Dist = Lz.WindowCodeBase[ Code ] +
+ Arith_Decode_Bits( WindowCodeExtra[ Code ] ) + 1;
+ DComp_Token_Match( Match );
+ break;
+ }
+ }
+
+#endif
+
+
+#ifdef PAQ
+
+// Estimates the number of bits required to represent a symbol
+// given the total number of occurances of this symbol and the
+// total number of occurances of all symbols (an order-0 probability).
+
+#ifndef __PCC__
+
+#undef HUGE /* defined by MATH.H */
+
+#include <math.h>
+
+//#if defined(_MIPS_) || defined(_ALPHA_)
+#ifndef _X86_
+#ifndef logl
+#define logl(x) ((LONGDOUBLE)log((double)(x)))
+#endif
+#ifndef M_LN2
+#define M_LN2 0.6931471805599
+#endif
+#endif
+
+LONGDOUBLE FAST MYLOG( LONGDOUBLE x )
+ {
+//#if defined(_MIPS_) || defined(_ALPHA_)
+#ifndef _X86_
+ return( logl( x ) / M_LN2 );
+#else
+
+ ASM fldln2 // st(0) = log( x )
+ ASM fld x
+ ASM fyl2x
+
+ ASM fldln2 // st(0) = st(0) / log( 2 )
+ ASM fdivp st(1),st
+
+ ASM fstp x
+
+ return( x );
+#endif /* 0 */
+ }
+#endif /* ! PCC */
+
+#endif /* PAQ */