public static byte[] Encode(byte[] data, out ConcurrentDictionary <BitsWithLength, byte> decodeTable,
                                    out long bitsCount, int degreeOfParallelism)
        {
            var frequences = CalcFrequences(data, degreeOfParallelism);

            var root = BuildHuffmanTree(frequences);

            var encodeTable = new BitsWithLength[byte.MaxValue + 1];

            FillEncodeTable(root, encodeTable);

            var dataSize    = data.Length;
            var chunkLength = dataSize / degreeOfParallelism;

            ParallelEnumerable.Range(0, degreeOfParallelism + 1)
            .AsOrdered()
            .WithDegreeOfParallelism(degreeOfParallelism)
            .Select(
                i =>
            {
                var chunk = new BitsBuffer();
                var lower = chunkLength * i;
                var upper = Math.Min(chunkLength * (i + 1), dataSize);
                for (var j = lower; j < upper; j++)
                {
                    chunk.Add(encodeTable[data[j]]);
                }
                return(chunk);
            })
            .ForEach(AddRange);
            decodeTable = CreateDecodeTable(encodeTable, degreeOfParallelism);

            return(globalBuffer.ToArray(out bitsCount));
        }
 private static void AddRange(BitsBuffer chunk)
 {
     foreach (var b in chunk.buffer)
     {
         globalBuffer.Add(new BitsWithLength {
             Bits = b, BitsCount = 8
         }, 8);
     }
     globalBuffer.Add(chunk.unfinishedBits);
 }
        public static byte[] EncodeSequential(byte[] data, out ConcurrentDictionary <BitsWithLength, byte> decodeTable,
                                              out long bitsCount, int degreeOfParallelism)
        {
            var frequences = CalcFrequences(data, degreeOfParallelism);

            var root = BuildHuffmanTree(frequences);

            var encodeTable = new BitsWithLength[byte.MaxValue + 1];

            FillEncodeTable(root, encodeTable);

            var bitsBuffer = new BitsBuffer();

            foreach (var b in data)
            {
                bitsBuffer.Add(encodeTable[b]);
            }

            decodeTable = CreateDecodeTable(encodeTable, degreeOfParallelism);

            return(bitsBuffer.ToArray(out bitsCount));
        }