private byte[] PatternCompress(byte[] data)
        {
            for (int i=0;i<data.Length;i++)
            {
                UInt16 matchCount=0;
                int current = data[i];
                int lookupPos = 0;
                UInt16 bestMatchCount = 0;
                int bestMatchPos = 0;

                if (i<data.Length-2)
                {
                    byte current2 = data[i+1];
                    byte current3 = data[i+2];

                    ulong key = (ulong)current << 16;
                    key |= (ulong)current2 << 8;
                    key |= (ulong)current3 ;

                    int prevIndex = (int)patternHashArray[key];

                    int currentPrevIndex = prevIndex;

                    bestMatchCount = 0;
                    bestMatchPos = 0;
                    if (prevIndex != 0)
                    {

                        do
                        {
                            matchCount = 0;
                            PatternLink link = patternLinkArray[currentPrevIndex];
                            lookupPos = (int)link.FilePosition;

                        while (matchCount+i < data.Length && matchCount < UInt16.MaxValue &&  data[i+matchCount] == data[lookupPos+matchCount])
                            matchCount++;

                            //matchCount --;

                            if (matchCount > bestMatchCount)
                            {
                                bestMatchCount = matchCount;
                                bestMatchPos = lookupPos;
                            }

                            currentPrevIndex = link.NextMatch;

                        }while (currentPrevIndex != 0);
                    }

                    patternHashArray[key] = (ulong)i+1;
                    PatternLink newLink = new PatternLink() ;
                    newLink.FilePosition = (ulong)i;
                    newLink.NextMatch = prevIndex;
                    patternLinkArray[i+1]=newLink;
                }

                int relativeLookupPos = i-bestMatchPos;

                if (bestMatchCount > 4 && relativeLookupPos < 0x100 && bestMatchCount < 0x100)
                {
                    WriteBytes (escapeByte,1);
                    WriteBytes (0u,1); // 0 = short relative
                    WriteBytes((ulong)bestMatchCount,1);
                    WriteBytes((ulong)relativeLookupPos,1);
                    i += bestMatchCount-1;
                }
                else if (bestMatchCount > 5 && relativeLookupPos < 0x10000 && bestMatchCount <0x100)
                {
                    WriteBytes (escapeByte,1);
                    WriteBytes (1u,1); // 1 = 65k range relative
                    WriteBytes((ulong)bestMatchCount,1);
                    WriteBytes((ulong)relativeLookupPos,2);

                    i += bestMatchCount-1;
                }
                else
                    if (bestMatchCount > 8 )
                {

                    WriteBytes (escapeByte,1);
                    WriteBytes (2u,1); // long lookup
                    WriteBytes((ulong)bestMatchCount,2);
                    WriteBytes((ulong)bestMatchPos,4);
                    i += bestMatchCount-1;
                }
                else
                {
                    WriteBytes((ulong)current,1);
                }
            }

            byte[] compressedBytes = new byte[compressedStream.Length] ;
            compressedStream.Position = 0;
            compressedStream.Read(compressedBytes,0,compressedBytes.Length);
            return compressedBytes;
        }
        private byte[] PatternCompress(byte[] data)
        {
            for (int i = 0; i < data.Length; i++)
            {
                UInt16 matchCount     = 0;
                int    current        = data[i];
                int    lookupPos      = 0;
                UInt16 bestMatchCount = 0;
                int    bestMatchPos   = 0;

                if (i < data.Length - 2)
                {
                    byte current2 = data[i + 1];
                    byte current3 = data[i + 2];

                    ulong key = (ulong)current << 16;
                    key |= (ulong)current2 << 8;
                    key |= (ulong)current3;

                    int prevIndex = (int)patternHashArray[key];

                    int currentPrevIndex = prevIndex;


                    bestMatchCount = 0;
                    bestMatchPos   = 0;
                    if (prevIndex != 0)
                    {
                        do
                        {
                            matchCount = 0;
                            PatternLink link = patternLinkArray[currentPrevIndex];
                            lookupPos = (int)link.FilePosition;

                            while (matchCount + i < data.Length && matchCount < UInt16.MaxValue && data[i + matchCount] == data[lookupPos + matchCount])
                            {
                                matchCount++;
                            }

                            //matchCount --;

                            if (matchCount > bestMatchCount)
                            {
                                bestMatchCount = matchCount;
                                bestMatchPos   = lookupPos;
                            }

                            currentPrevIndex = link.NextMatch;
                        }while (currentPrevIndex != 0);
                    }


                    patternHashArray[key] = (ulong)i + 1;
                    PatternLink newLink = new PatternLink();
                    newLink.FilePosition    = (ulong)i;
                    newLink.NextMatch       = prevIndex;
                    patternLinkArray[i + 1] = newLink;
                }

                int relativeLookupPos = i - bestMatchPos;

                if (bestMatchCount > 4 && relativeLookupPos < 0x100 && bestMatchCount < 0x100)
                {
                    WriteBytes(escapeByte, 1);
                    WriteBytes(0u, 1);                     // 0 = short relative
                    WriteBytes((ulong)bestMatchCount, 1);
                    WriteBytes((ulong)relativeLookupPos, 1);
                    i += bestMatchCount - 1;
                }
                else if (bestMatchCount > 5 && relativeLookupPos < 0x10000 && bestMatchCount < 0x100)
                {
                    WriteBytes(escapeByte, 1);
                    WriteBytes(1u, 1);                     // 1 = 65k range relative
                    WriteBytes((ulong)bestMatchCount, 1);
                    WriteBytes((ulong)relativeLookupPos, 2);

                    i += bestMatchCount - 1;
                }
                else
                if (bestMatchCount > 8)
                {
                    WriteBytes(escapeByte, 1);
                    WriteBytes(2u, 1);                     // long lookup
                    WriteBytes((ulong)bestMatchCount, 2);
                    WriteBytes((ulong)bestMatchPos, 4);
                    i += bestMatchCount - 1;
                }
                else
                {
                    WriteBytes((ulong)current, 1);
                }
            }



            byte[] compressedBytes = new byte[compressedStream.Length];
            compressedStream.Position = 0;
            compressedStream.Read(compressedBytes, 0, compressedBytes.Length);
            return(compressedBytes);
        }