misc/libphysfs/lzma/C/Compress/Huffman/HuffmanEncode.c
author nemo
Mon, 10 Apr 2017 12:06:43 -0400
changeset 12213 bb5522e88ab2
permissions -rw-r--r--
bulk copy of latest physfs to our misc/libphysfs since this seems to fix an off-by-1 error reliably hit in readln read of 1 byte probably introduced in the addition of the buffered read. Whether this is excessive or whether libphysfs should even be maintained by us is another matter. But at least we shouldn't crash

/* Compress/HuffmanEncode.c */

#include "HuffmanEncode.h"
#include "../../Sort.h"

#define kMaxLen 16
#define NUM_BITS 10
#define MASK ((1 << NUM_BITS) - 1)

#define NUM_COUNTERS 64

/* use BLOCK_SORT_EXTERNAL_FLAGS if blockSize > 1M */
#define HUFFMAN_SPEED_OPT

void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 numSymbols, UInt32 maxLen)
{
  UInt32 num = 0;
  /* if (maxLen > 10) maxLen = 10; */
  {
    UInt32 i;
    
    #ifdef HUFFMAN_SPEED_OPT
    
    UInt32 counters[NUM_COUNTERS];
    for (i = 0; i < NUM_COUNTERS; i++) 
      counters[i] = 0;
    for (i = 0; i < numSymbols; i++) 
    {
      UInt32 freq = freqs[i];
      counters[(freq < NUM_COUNTERS - 1) ? freq : NUM_COUNTERS - 1]++;
    }
 
    for (i = 1; i < NUM_COUNTERS; i++) 
    {
      UInt32 temp = counters[i];
      counters[i] = num;
      num += temp;
    }

    for (i = 0; i < numSymbols; i++) 
    {
      UInt32 freq = freqs[i];
      if (freq == 0)
        lens[i] = 0;
      else
        p[counters[((freq < NUM_COUNTERS - 1) ? freq : NUM_COUNTERS - 1)]++] = i | (freq << NUM_BITS);
    }
    counters[0] = 0;
    HeapSort(p + counters[NUM_COUNTERS - 2], counters[NUM_COUNTERS - 1] - counters[NUM_COUNTERS - 2]);
    
    #else

    for (i = 0; i < numSymbols; i++) 
    {
      UInt32 freq = freqs[i];
      if (freq == 0)
        lens[i] = 0;
      else
        p[num++] = i | (freq << NUM_BITS);
    }
    HeapSort(p, num);

    #endif
  }

  if (num < 2) 
  {
    int minCode = 0;
    int maxCode = 1;
    if (num == 1)
    {
      maxCode = p[0] & MASK;
      if (maxCode == 0)
        maxCode++;
    }
    p[minCode] = 0;
    p[maxCode] = 1;
    lens[minCode] = lens[maxCode] = 1;
    return;
  }
  
  {
    UInt32 b, e, i;
  
    i = b = e = 0;
    do 
    {
      UInt32 n, m, freq;
      n = (i != num && (b == e || (p[i] >> NUM_BITS) <= (p[b] >> NUM_BITS))) ? i++ : b++;
      freq = (p[n] & ~MASK);
      p[n] = (p[n] & MASK) | (e << NUM_BITS);
      m = (i != num && (b == e || (p[i] >> NUM_BITS) <= (p[b] >> NUM_BITS))) ? i++ : b++;
      freq += (p[m] & ~MASK);
      p[m] = (p[m] & MASK) | (e << NUM_BITS);
      p[e] = (p[e] & MASK) | freq;
      e++;
    } 
    while (num - e > 1);
    
    {
      UInt32 lenCounters[kMaxLen + 1];
      for (i = 0; i <= kMaxLen; i++) 
        lenCounters[i] = 0;
      
      p[--e] &= MASK;
      lenCounters[1] = 2;
      while (e > 0) 
      {
        UInt32 len = (p[p[--e] >> NUM_BITS] >> NUM_BITS) + 1;
        p[e] = (p[e] & MASK) | (len << NUM_BITS);
        if (len >= maxLen) 
          for (len = maxLen - 1; lenCounters[len] == 0; len--);
        lenCounters[len]--;
        lenCounters[len + 1] += 2;
      }
      
      {
        UInt32 len;
        i = 0;
        for (len = maxLen; len != 0; len--) 
        {
          UInt32 num;
          for (num = lenCounters[len]; num != 0; num--) 
            lens[p[i++] & MASK] = (Byte)len;
        }
      }
      
      {
        UInt32 nextCodes[kMaxLen + 1];
        {
          UInt32 code = 0;
          UInt32 len;
          for (len = 1; len <= kMaxLen; len++) 
            nextCodes[len] = code = (code + lenCounters[len - 1]) << 1;
        }
        /* if (code + lenCounters[kMaxLen] - 1 != (1 << kMaxLen) - 1) throw 1; */

        {
          UInt32 i;
          for (i = 0; i < numSymbols; i++) 
            p[i] = nextCodes[lens[i]]++;
        }
      }
    }
  }
}