Example #1
0
static mem_stat_t update_total_allocated(int block_delta, mem_stat_t byte_delta)
{
    atomic32_t cur_total_blocks;
    for ( ; ; )
    {
        cur_total_blocks = g_total_blocks;
        atomic32_t new_total_blocks = static_cast<atomic32_t>(cur_total_blocks + block_delta);
        LZHAM_ASSERT(new_total_blocks >= 0);
        if (atomic_compare_exchange32(&g_total_blocks, new_total_blocks, cur_total_blocks) == cur_total_blocks)
            break;
    }

    mem_stat_t cur_total_allocated, new_total_allocated;
    for ( ; ; )
    {
        cur_total_allocated = g_total_allocated;
        new_total_allocated = static_cast<mem_stat_t>(cur_total_allocated + byte_delta);
        LZHAM_ASSERT(new_total_allocated >= 0);
        if (LZHAM_MEM_COMPARE_EXCHANGE(&g_total_allocated, new_total_allocated, cur_total_allocated) == cur_total_allocated)
            break;
    }
    for ( ; ; )
    {
        mem_stat_t cur_max_allocated = g_max_allocated;
        mem_stat_t new_max_allocated = LZHAM_MAX(new_total_allocated, cur_max_allocated);
        if (LZHAM_MEM_COMPARE_EXCHANGE(&g_max_allocated, new_max_allocated, cur_max_allocated) == cur_max_allocated)
            break;
    }
    return new_total_allocated;
}
   bool task_pool::init(uint num_threads)
   {
      LZHAM_ASSERT(num_threads <= cMaxThreads);
      num_threads = math::minimum<uint>(num_threads, cMaxThreads);

      deinit();

      bool succeeded = true;

      m_num_threads = 0;
      while (m_num_threads < num_threads)
      {
         m_threads[m_num_threads] = (HANDLE)_beginthreadex(NULL, 32768, thread_func, this, 0, NULL);
         LZHAM_ASSERT(m_threads[m_num_threads] != 0);

         if (!m_threads[m_num_threads])
         {
            succeeded = false;
            break;
         }

         m_num_threads++;
      }

      if (!succeeded)
      {
         deinit();
         return false;
      }

      return true;
   }
   void CLZDecompBase::init_position_slots(uint dict_size_log2)
   {
		LZHAM_ASSERT(dict_size_log2 >= LZHAM_MIN_DICT_SIZE_LOG2);
		LZHAM_ASSERT(dict_size_log2 <= LZHAM_MAX_DICT_SIZE_LOG2_X64);
		LZHAM_ASSERT((sizeof(g_table_update_settings) / sizeof(g_table_update_settings[0])) == LZHAM_FASTEST_TABLE_UPDATE_RATE);

		//for (dict_size_log2 = LZHAM_MIN_DICT_SIZE_LOG2; dict_size_log2 <= LZHAM_MAX_DICT_SIZE_LOG2_X64; dict_size_log2++) {

      m_dict_size_log2 = dict_size_log2;
      m_dict_size = 1U << dict_size_log2;
		m_num_lzx_slots = g_num_lzx_position_slots[dict_size_log2  - LZHAM_MIN_DICT_SIZE_LOG2];

#if 0
		int i, j;
      for (i = 0, j = 0; i < cLZXMaxPositionSlots; i += 2) 
      {
         m_lzx_position_extra_bits[i] = (uint8)j;
         m_lzx_position_extra_bits[i + 1] = (uint8)j; 

         if ((i != 0) && (j < 25))  
            j++; 
      }

      for (i = 0, j = 0; i < cLZXMaxPositionSlots; i++) 
      {
         m_lzx_position_base[i] = j;
         m_lzx_position_extra_mask[i] = (1 << m_lzx_position_extra_bits[i]) - 1;
         j += (1 << m_lzx_position_extra_bits[i]);
      }

		for (uint i = 0; i < cLZXMaxPositionSlots; i++)
		{
			printf("0x%X, ", m_lzx_position_base[i]);
			if ((i & 15) == 15) printf("\n");
		}
#endif

#if 0
      m_num_lzx_slots = 0;         
      
      const uint largest_dist = m_dict_size - 1;
      for (i = 0; i < cLZXMaxPositionSlots; i++)
      {
         if ( (largest_dist >= m_lzx_position_base[i]) &&
              (largest_dist < (m_lzx_position_base[i] + (1 << m_lzx_position_extra_bits[i])) ) )
         {
            m_num_lzx_slots = i + 1;
            break;
         }              
      }
      
      LZHAM_VERIFY(m_num_lzx_slots);
#endif

		//printf("%u, ", m_num_lzx_slots); }
   }
Example #4
0
static void* lzham_default_realloc(void* p, size_t size, size_t* pActual_size, lzham_bool movable, void* pUser_data)
{
    LZHAM_NOTE_UNUSED(pUser_data);

    void* p_new;

    if (!p)
    {
        p_new = malloc(size);
        LZHAM_ASSERT( (reinterpret_cast<ptr_bits_t>(p_new) & (LZHAM_MIN_ALLOC_ALIGNMENT - 1)) == 0 );

        if (pActual_size)
            *pActual_size = p_new ? _msize(p_new) : 0;
    }
    else if (!size)
    {
        free(p);
        p_new = NULL;

        if (pActual_size)
            *pActual_size = 0;
    }
    else
    {
        void* p_final_block = p;
#ifdef WIN32
        p_new = _expand(p, size);
#else

        p_new = NULL;
#endif

        if (p_new)
        {
            LZHAM_ASSERT( (reinterpret_cast<ptr_bits_t>(p_new) & (LZHAM_MIN_ALLOC_ALIGNMENT - 1)) == 0 );
            p_final_block = p_new;
        }
        else if (movable)
        {
            p_new = realloc(p, size);

            if (p_new)
            {
                LZHAM_ASSERT( (reinterpret_cast<ptr_bits_t>(p_new) & (LZHAM_MIN_ALLOC_ALIGNMENT - 1)) == 0 );
                p_final_block = p_new;
            }
        }

        if (pActual_size)
            *pActual_size = _msize(p_final_block);
    }

    return p_new;
}
      bool generate_codes(uint num_syms, const uint8* pCodesizes, uint16* pCodes)
      {
         uint num_codes[cMaxExpectedHuffCodeSize + 1];
         utils::zero_object(num_codes);

         for (uint i = 0; i < num_syms; i++)
         {
            uint c = pCodesizes[i];
            LZHAM_ASSERT(c <= cMaxExpectedHuffCodeSize);
            num_codes[c]++;
         }

         uint code = 0;

         uint next_code[cMaxExpectedHuffCodeSize + 1];
         next_code[0] = 0;
         
         for (uint i = 1; i <= cMaxExpectedHuffCodeSize; i++)
         {
            next_code[i] = code;
            
            code = (code + num_codes[i]) << 1;
         }

         if (code != (1 << (cMaxExpectedHuffCodeSize + 1)))
         {
            uint t = 0;
            for (uint i = 1; i <= cMaxExpectedHuffCodeSize; i++)
            {
               t += num_codes[i];
               if (t > 1)
               {
                  LZHAM_LOG_ERROR(3003);
                  return false;
               }
            }
         }

         for (uint i = 0; i < num_syms; i++)
         {
            uint c = pCodesizes[i];
            
            LZHAM_ASSERT(!c || (next_code[c] <= cUINT16_MAX));
            
            pCodes[i] = static_cast<uint16>(next_code[c]++);
            
            LZHAM_ASSERT(!c || (math::total_bits(pCodes[i]) <= pCodesizes[i]));
         }
         
         return true;
      }
Example #6
0
void* lzham_malloc(size_t size, size_t* pActual_size)
{
    size = (size + sizeof(uint32) - 1U) & ~(sizeof(uint32) - 1U);
    if (!size)
        size = sizeof(uint32);

    if (size > MAX_POSSIBLE_BLOCK_SIZE)
    {
        lzham_mem_error("lzham_malloc: size too big");
        return NULL;
    }

    size_t actual_size = size;
    uint8* p_new = static_cast<uint8*>((*g_pRealloc)(NULL, size, &actual_size, true, g_pUser_data));

    if (pActual_size)
        *pActual_size = actual_size;

    if ((!p_new) || (actual_size < size))
    {
        lzham_mem_error("lzham_malloc: out of memory");
        return NULL;
    }

    LZHAM_ASSERT((reinterpret_cast<ptr_bits_t>(p_new) & (LZHAM_MIN_ALLOC_ALIGNMENT - 1)) == 0);

#if LZHAM_MEM_STATS
    update_total_allocated(1, static_cast<mem_stat_t>(actual_size));
#endif

    return p_new;
}
   bool task_pool::init(uint num_threads)
   {
      LZHAM_ASSERT(num_threads <= cMaxThreads);
      num_threads = math::minimum<uint>(num_threads, cMaxThreads);

      deinit();

      bool succeeded = true;

      m_num_threads = 0;
      while (m_num_threads < num_threads)
      {
         int status = pthread_create(&m_threads[m_num_threads], NULL, thread_func, this);
         if (status)
         {
            succeeded = false;
            break;
         }

         m_num_threads++;
      }

      if (!succeeded)
      {
         deinit();
         return false;
      }

      return true;
   }
Example #8
0
 void lzham_timer::stop()
 {
    LZHAM_ASSERT(m_started);
                
    query_counter(&m_stop_time);
    
    m_stopped = true;
 }
   // It's the object's responsibility to delete pObj within the execute_task() method, if needed!
   bool task_pool::queue_task(executable_task* pObj, uint64 data, void* pData_ptr)
   {
      LZHAM_ASSERT(m_num_threads);
      LZHAM_ASSERT(pObj);

      task tsk;
      tsk.m_pObj = pObj;
      tsk.m_data = data;
      tsk.m_pData_ptr = pData_ptr;
      tsk.m_flags = cTaskFlagObject;

      if (!m_task_stack.try_push(tsk))
         return false;

      atomic_increment32(&m_num_outstanding_tasks);

      m_tasks_available.release(1);

      return true;
   }
   bool task_pool::queue_task(task_callback_func pFunc, uint64 data, void* pData_ptr)
   {
      LZHAM_ASSERT(m_num_threads);
      LZHAM_ASSERT(pFunc);

      task tsk;
      tsk.m_callback = pFunc;
      tsk.m_data = data;
      tsk.m_pData_ptr = pData_ptr;
      tsk.m_flags = 0;

      if (!m_task_stack.try_push(tsk))
         return false;

      atomic_increment32(&m_num_outstanding_tasks);

      m_tasks_available.release(1);

      return true;
   }
Example #11
0
 timer_ticks lzham_timer::get_elapsed_us() const
 {
    LZHAM_ASSERT(m_started);
    if (!m_started)
       return 0;
       
    timer_ticks stop_time = m_stop_time;
    if (!m_stopped)
       query_counter(&stop_time);
    
    timer_ticks delta = stop_time - m_start_time;
    return (delta * 1000000ULL + (g_freq >> 1U)) / g_freq;      
 }
Example #12
0
 double lzham_timer::get_elapsed_secs() const
 {
    LZHAM_ASSERT(m_started);
    if (!m_started)
       return 0;
    
    timer_ticks stop_time = m_stop_time;
    if (!m_stopped)
       query_counter(&stop_time);
       
    timer_ticks delta = stop_time - m_start_time;
    return delta * g_inv_freq;
 }
Example #13
0
void* lzham_realloc(void* p, size_t size, size_t* pActual_size, bool movable)
{
    if ((ptr_bits_t)p & (LZHAM_MIN_ALLOC_ALIGNMENT - 1))
    {
        lzham_mem_error("lzham_realloc: bad ptr");
        return NULL;
    }

    if (size > MAX_POSSIBLE_BLOCK_SIZE)
    {
        lzham_mem_error("lzham_malloc: size too big");
        return NULL;
    }

#if LZHAM_MEM_STATS
    size_t cur_size = p ? (*g_pMSize)(p, g_pUser_data) : 0;
#endif

    size_t actual_size = size;
    void* p_new = (*g_pRealloc)(p, size, &actual_size, movable, g_pUser_data);

    if (pActual_size)
        *pActual_size = actual_size;

    LZHAM_ASSERT((reinterpret_cast<ptr_bits_t>(p_new) & (LZHAM_MIN_ALLOC_ALIGNMENT - 1)) == 0);

#if LZHAM_MEM_STATS
    int num_new_blocks = 0;
    if (p)
    {
        if (!p_new)
            num_new_blocks = -1;
    }
    else if (p_new)
    {
        num_new_blocks = 1;
    }
    update_total_allocated(num_new_blocks, static_cast<mem_stat_t>(actual_size) - static_cast<mem_stat_t>(cur_size));
#endif

    return p_new;
}
Example #14
0
   bool elemental_vector::increase_capacity(uint min_new_capacity, bool grow_hint, uint element_size, object_mover pMover, bool nofail)
   {
      LZHAM_ASSERT(m_size <= m_capacity);
      
#if LZHAM_64BIT_POINTERS
      LZHAM_ASSUME(sizeof(void*) == sizeof(uint64));
      LZHAM_ASSERT(min_new_capacity < (0x400000000ULL / element_size));
#else      
      LZHAM_ASSUME(sizeof(void*) == sizeof(uint32));
      LZHAM_ASSERT(min_new_capacity < (0x7FFF0000U / element_size));
#endif      

      if (m_capacity >= min_new_capacity)
         return true;

      // new_capacity must be 64-bit when compiling on x64.
		size_t new_capacity = (size_t)min_new_capacity;
      if ((grow_hint) && (!math::is_power_of_2(static_cast<uint64>(new_capacity))))
         new_capacity = static_cast<uint>(math::next_pow2(static_cast<uint64>(new_capacity)));

      LZHAM_ASSERT(new_capacity && (new_capacity > m_capacity));

      const size_t desired_size = element_size * new_capacity;
      size_t actual_size;
      if (!pMover)
      {
         void* new_p = lzham_realloc(m_malloc_context, m_p, desired_size, &actual_size, true);
         if (!new_p)
         {
            if (nofail)
            {
               LZHAM_LOG_ERROR(5000);
               return false;
            }
               
            char buf[256];
            sprintf_s(buf, sizeof(buf), "vector: lzham_realloc() failed allocating %u bytes", desired_size);
            LZHAM_FAIL(buf);
         }
         m_p = new_p;
      }
      else
      {
         void* new_p = lzham_malloc(m_malloc_context, desired_size, &actual_size);
         if (!new_p)
         {
            if (nofail)
            {
               LZHAM_LOG_ERROR(5001);
               return false;
            }
               
            LZHAM_LOG_ERROR(5002);

            char buf[256];
            sprintf_s(buf, sizeof(buf), "vector: lzham_malloc() failed allocating %u bytes", desired_size);
            LZHAM_FAIL(buf);
         }
         
         (*pMover)(new_p, m_p, m_size);
         
         if (m_p)
            lzham_free(m_malloc_context, m_p);

         m_p = new_p;
      }            
      
      if (actual_size > desired_size)
         m_capacity = static_cast<uint>(actual_size / element_size);
      else
         m_capacity = static_cast<uint>(new_capacity);
    
      return true;
   }
Example #15
0
      bool generate_decoder_tables(uint num_syms, const uint8* pCodesizes, decoder_tables* pTables, uint table_bits, const code_size_histogram &code_size_histo, bool sym_freq_all_ones)
      {
         uint min_codes[cMaxExpectedHuffCodeSize];
         
         if ((!num_syms) || (table_bits > cMaxTableBits))
         {
            LZHAM_LOG_ERROR(3004);
            return false;
         }
            
         pTables->m_num_syms = num_syms;
      
         uint sorted_positions[cMaxExpectedHuffCodeSize + 1];
               
         uint next_code = 0;

         uint total_used_syms = 0;
         uint max_code_size = 0;
         uint min_code_size = UINT_MAX;
         for (uint i = 1; i <= cMaxExpectedHuffCodeSize; i++)
         {
            const uint n = code_size_histo.m_num_codes[i];
            
            if (!n)
               pTables->m_max_codes[i - 1] = 0;//UINT_MAX;
            else
            {
               min_code_size = math::minimum(min_code_size, i);
               max_code_size = math::maximum(max_code_size, i);
                  
               min_codes[i - 1] = next_code;
               
               pTables->m_max_codes[i - 1] = next_code + n - 1;
               pTables->m_max_codes[i - 1] = 1 + ((pTables->m_max_codes[i - 1] << (16 - i)) | ((1 << (16 - i)) - 1));
               
               pTables->m_val_ptrs[i - 1] = total_used_syms;
               
               sorted_positions[i] = total_used_syms;
               
               next_code += n;
               total_used_syms += n;
            }

            next_code <<= 1;
         }
         
         pTables->m_total_used_syms = total_used_syms;

         if (total_used_syms > pTables->m_cur_sorted_symbol_order_size)
         {
            pTables->m_cur_sorted_symbol_order_size = total_used_syms;
            
            if (!math::is_power_of_2(total_used_syms))
               pTables->m_cur_sorted_symbol_order_size = math::minimum<uint>(num_syms, math::next_pow2(total_used_syms));
            
            if (pTables->m_sorted_symbol_order)
            {
               lzham_delete_array(pTables->m_malloc_context, pTables->m_sorted_symbol_order);
               pTables->m_sorted_symbol_order = NULL;
            }
            
            pTables->m_sorted_symbol_order = lzham_new_array<uint16>(pTables->m_malloc_context, pTables->m_cur_sorted_symbol_order_size);
            if (!pTables->m_sorted_symbol_order)
            {
               LZHAM_LOG_ERROR(3005);
               return false;
            }
         }
         
         pTables->m_min_code_size = static_cast<uint8>(min_code_size);
         pTables->m_max_code_size = static_cast<uint8>(max_code_size);

         if (sym_freq_all_ones)
         {
            if (min_code_size == max_code_size)
            {
               memcpy(pTables->m_sorted_symbol_order, g_uint16_sequence, num_syms * sizeof(uint16));
            }
            else
            {
               LZHAM_ASSERT((min_code_size + 1) == max_code_size);
               LZHAM_ASSERT(pCodesizes[0] == max_code_size);
               LZHAM_ASSERT(pCodesizes[code_size_histo.m_num_codes[max_code_size]] == min_code_size);
                              
               memcpy(pTables->m_sorted_symbol_order + sorted_positions[max_code_size], g_uint16_sequence, code_size_histo.m_num_codes[max_code_size] * sizeof(uint16));
               
               memcpy(pTables->m_sorted_symbol_order + sorted_positions[min_code_size], g_uint16_sequence + code_size_histo.m_num_codes[max_code_size], code_size_histo.m_num_codes[min_code_size] * sizeof(uint16));
            }

#ifdef LZHAM_BUILD_DEBUG
            for (uint i = 0; i < num_syms; i++)
            {
               uint c = pCodesizes[i];
               LZHAM_ASSERT(code_size_histo.m_num_codes[c]);

               uint sorted_pos = sorted_positions[c]++;

               LZHAM_ASSERT(sorted_pos < total_used_syms);

               LZHAM_ASSERT(pTables->m_sorted_symbol_order[sorted_pos] == i);
            }
#endif
         }
         else
         {
            for (uint i = 0; i < num_syms; i++)
            {
               uint c = pCodesizes[i];
               LZHAM_ASSERT(code_size_histo.m_num_codes[c]);
               
               uint sorted_pos = sorted_positions[c]++;
               
               LZHAM_ASSERT(sorted_pos < total_used_syms);
               
               pTables->m_sorted_symbol_order[sorted_pos] = static_cast<uint16>(i);
            }
         }

         if (table_bits <= pTables->m_min_code_size)
            table_bits = 0;                                       
         pTables->m_table_bits = table_bits;
                  
         if (table_bits)
         {
            uint table_size = 1 << table_bits;
            if (table_size > pTables->m_cur_lookup_size)
            {
               pTables->m_cur_lookup_size = table_size;
               
               if (pTables->m_lookup)
               {
                  lzham_delete_array(pTables->m_malloc_context, pTables->m_lookup);
                  pTables->m_lookup = NULL;
               }
                  
               pTables->m_lookup = lzham_new_array<uint32>(pTables->m_malloc_context, table_size);
               if (!pTables->m_lookup)
               {
                  LZHAM_LOG_ERROR(3006);
                  return false;
               }
            }
                        
            memset(pTables->m_lookup, 0xFF, static_cast<uint>(sizeof(pTables->m_lookup[0])) * (1UL << table_bits));
            
            for (uint codesize = 1; codesize <= table_bits; codesize++)
            {
               if (!code_size_histo.m_num_codes[codesize])
                  continue;
               
               const uint fillsize = table_bits - codesize;
               const uint fillnum = 1 << fillsize;
               
               const uint min_code = min_codes[codesize - 1];
               const uint max_code = pTables->get_unshifted_max_code(codesize);
               const uint val_ptr = pTables->m_val_ptrs[codesize - 1];
                      
               for (uint code = min_code; code <= max_code; code++)
               {
                  const uint sym_index = pTables->m_sorted_symbol_order[ val_ptr + code - min_code ];
                  LZHAM_ASSERT( pCodesizes[sym_index] == codesize );
                  
                  for (uint j = 0; j < fillnum; j++)
                  {
                     const uint t = j + (code << fillsize);
                     
                     LZHAM_ASSERT(t < (1U << table_bits));
                     
                     LZHAM_ASSERT(pTables->m_lookup[t] == cUINT32_MAX);
                     
                     pTables->m_lookup[t] = sym_index | (codesize << 16U);
                  }
               }
            }
         }         
         
         for (uint i = 0; i < cMaxExpectedHuffCodeSize; i++)
            pTables->m_val_ptrs[i] -= min_codes[i];
         
         pTables->m_table_max_code = 0;
         pTables->m_decode_start_code_size = pTables->m_min_code_size;

         if (table_bits)
         {
            uint i;
            for (i = table_bits; i >= 1; i--)
            {
               if (code_size_histo.m_num_codes[i])
               {
                  pTables->m_table_max_code = pTables->m_max_codes[i - 1];
                  break;
               }
            }
            if (i >= 1)
            {
               pTables->m_decode_start_code_size = table_bits + 1;
               for (i = table_bits + 1; i <= max_code_size; i++)
               {
                  if (code_size_histo.m_num_codes[i])
                  {
                     pTables->m_decode_start_code_size = i;
                     break;
                  }
               }
            }
         }

         // sentinels
         pTables->m_max_codes[cMaxExpectedHuffCodeSize] = UINT_MAX;
         pTables->m_val_ptrs[cMaxExpectedHuffCodeSize] = 0xFFFFF;

         pTables->m_table_shift = 32 - pTables->m_table_bits;

         return true;
      }
Example #16
0
      bool limit_max_code_size(uint num_syms, uint8* pCodesizes, uint max_code_size)
      {
         const uint cMaxEverCodeSize = 34;            
         
         if ((!num_syms) || (num_syms > cMaxSupportedSyms) || (max_code_size < 1) || (max_code_size > cMaxEverCodeSize))
         {
            LZHAM_LOG_ERROR(3000);
            return false;
         }
         
         uint num_codes[cMaxEverCodeSize + 1];
         utils::zero_object(num_codes);

         bool should_limit = false;
         
         for (uint i = 0; i < num_syms; i++)
         {
            uint c = pCodesizes[i];
            
            LZHAM_ASSERT(c <= cMaxEverCodeSize);
            
            num_codes[c]++;
            if (c > max_code_size)
               should_limit = true;
         }
         
         if (!should_limit)
            return true;
         
         uint ofs = 0;
         uint next_sorted_ofs[cMaxEverCodeSize + 1];
         for (uint i = 1; i <= cMaxEverCodeSize; i++)
         {
            next_sorted_ofs[i] = ofs;
            ofs += num_codes[i];
         }
            
         if ((ofs < 2) || (ofs > cMaxSupportedSyms))
            return true;
         
         if (ofs > (1U << max_code_size))
         {
            LZHAM_LOG_ERROR(3001);
            return false;
         }
                           
         for (uint i = max_code_size + 1; i <= cMaxEverCodeSize; i++)
            num_codes[max_code_size] += num_codes[i];
         
         // Technique of adjusting tree to enforce maximum code size from LHArc. 
			// (If you remember what LHArc was, you've been doing this for a LONG time.)
         
         uint total = 0;
         for (uint i = max_code_size; i; --i)
            total += (num_codes[i] << (max_code_size - i));

         if (total == (1U << max_code_size))  
            return true;
            
         do
         {
            num_codes[max_code_size]--;

            uint i;
            for (i = max_code_size - 1; i; --i)
            {
               if (!num_codes[i])
                  continue;
               num_codes[i]--;          
               num_codes[i + 1] += 2;   
               break;
            }
            if (!i)
            {
               LZHAM_LOG_ERROR(3002);
               return false;
            }

            total--;   
         } while (total != (1U << max_code_size));
         
         uint8 new_codesizes[cMaxSupportedSyms];
         uint8* p = new_codesizes;
         for (uint i = 1; i <= max_code_size; i++)
         {
            uint n = num_codes[i];
            if (n)
            {
               memset(p, i, n);
               p += n;
            }
         }
                                             
         for (uint i = 0; i < num_syms; i++)
         {
            const uint c = pCodesizes[i];
            if (c)
            {
               uint next_ofs = next_sorted_ofs[c];
               next_sorted_ofs[c] = next_ofs + 1;
            
               pCodesizes[i] = static_cast<uint8>(new_codesizes[next_ofs]);
            }
         }
            
         return true;
      }
      bool generate_decoder_tables(uint num_syms, const uint8* pCodesizes, decoder_tables* pTables, uint table_bits)
      {
         uint min_codes[cMaxExpectedCodeSize];
         
         if ((!num_syms) || (table_bits > cMaxTableBits))
            return false;
            
         pTables->m_num_syms = num_syms;
         
         uint num_codes[cMaxExpectedCodeSize + 1];
         utils::zero_object(num_codes);

         for (uint i = 0; i < num_syms; i++)
         {
            uint c = pCodesizes[i];
            num_codes[c]++;
         }

         uint sorted_positions[cMaxExpectedCodeSize + 1];
               
         uint code = 0;

         uint total_used_syms = 0;
         uint max_code_size = 0;
         uint min_code_size = UINT_MAX;
         for (uint i = 1; i <= cMaxExpectedCodeSize; i++)
         {
            const uint n = num_codes[i];
            
            if (!n)
               pTables->m_max_codes[i - 1] = 0;//UINT_MAX;
            else
            {
               min_code_size = math::minimum(min_code_size, i);
               max_code_size = math::maximum(max_code_size, i);
                  
               min_codes[i - 1] = code;
               
               pTables->m_max_codes[i - 1] = code + n - 1;
               pTables->m_max_codes[i - 1] = 1 + ((pTables->m_max_codes[i - 1] << (16 - i)) | ((1 << (16 - i)) - 1));
               
               pTables->m_val_ptrs[i - 1] = total_used_syms;
               
               sorted_positions[i] = total_used_syms;
               
               code += n;
               total_used_syms += n;
            }

            code <<= 1;
         }
         
         pTables->m_total_used_syms = total_used_syms;

         if (total_used_syms > pTables->m_cur_sorted_symbol_order_size)
         {
            pTables->m_cur_sorted_symbol_order_size = total_used_syms;
            
            if (!math::is_power_of_2(total_used_syms))
               pTables->m_cur_sorted_symbol_order_size = math::minimum<uint>(num_syms, math::next_pow2(total_used_syms));
            
            if (pTables->m_sorted_symbol_order)
            {
               lzham_delete_array(pTables->m_sorted_symbol_order);
               pTables->m_sorted_symbol_order = NULL;
            }
            
            pTables->m_sorted_symbol_order = lzham_new_array<uint16>(pTables->m_cur_sorted_symbol_order_size);
            if (!pTables->m_sorted_symbol_order)
               return false;
         }
         
         pTables->m_min_code_size = static_cast<uint8>(min_code_size);
         pTables->m_max_code_size = static_cast<uint8>(max_code_size);
                  
         for (uint i = 0; i < num_syms; i++)
         {
            uint c = pCodesizes[i];
            if (c)
            {
               LZHAM_ASSERT(num_codes[c]);
               
               uint sorted_pos = sorted_positions[c]++;
               
               LZHAM_ASSERT(sorted_pos < total_used_syms);
               
               pTables->m_sorted_symbol_order[sorted_pos] = static_cast<uint16>(i);
            }            
         }

         if (table_bits <= pTables->m_min_code_size)
            table_bits = 0;                                       
         pTables->m_table_bits = table_bits;
                  
         if (table_bits)
         {
            uint table_size = 1 << table_bits;
            if (table_size > pTables->m_cur_lookup_size)
            {
               pTables->m_cur_lookup_size = table_size;
               
               if (pTables->m_lookup)
               {
                  lzham_delete_array(pTables->m_lookup);
                  pTables->m_lookup = NULL;
               }
                  
               pTables->m_lookup = lzham_new_array<uint32>(table_size);
               if (!pTables->m_lookup)
                  return false;
            }
                        
            memset(pTables->m_lookup, 0xFF, static_cast<uint>(sizeof(pTables->m_lookup[0])) * (1UL << table_bits));
            
            for (uint codesize = 1; codesize <= table_bits; codesize++)
            {
               if (!num_codes[codesize])
                  continue;
               
               const uint fillsize = table_bits - codesize;
               const uint fillnum = 1 << fillsize;
               
               const uint min_code = min_codes[codesize - 1];
               const uint max_code = pTables->get_unshifted_max_code(codesize);
               const uint val_ptr = pTables->m_val_ptrs[codesize - 1];
                      
               for (uint code = min_code; code <= max_code; code++)
               {
                  const uint sym_index = pTables->m_sorted_symbol_order[ val_ptr + code - min_code ];
                  LZHAM_ASSERT( pCodesizes[sym_index] == codesize );
                  
                  for (uint j = 0; j < fillnum; j++)
                  {
                     const uint t = j + (code << fillsize);
                     
                     LZHAM_ASSERT(t < (1U << table_bits));
                     
                     LZHAM_ASSERT(pTables->m_lookup[t] == UINT32_MAX);
                     
                     pTables->m_lookup[t] = sym_index | (codesize << 16U);
                  }
               }
            }
         }         
         
         for (uint i = 0; i < cMaxExpectedCodeSize; i++)
            pTables->m_val_ptrs[i] -= min_codes[i];
         
         pTables->m_table_max_code = 0;
         pTables->m_decode_start_code_size = pTables->m_min_code_size;

         if (table_bits)
         {
            uint i;
            for (i = table_bits; i >= 1; i--)
            {
               if (num_codes[i])
               {
                  pTables->m_table_max_code = pTables->m_max_codes[i - 1];
                  break;
               }
            }
            if (i >= 1)
            {
               pTables->m_decode_start_code_size = table_bits + 1;
               for (uint i = table_bits + 1; i <= max_code_size; i++)
               {
                  if (num_codes[i])
                  {
                     pTables->m_decode_start_code_size = i;
                     break;
                  }
               }
            }
         }

         // sentinels
         pTables->m_max_codes[cMaxExpectedCodeSize] = UINT_MAX;
         pTables->m_val_ptrs[cMaxExpectedCodeSize] = 0xFFFFF;

         pTables->m_table_shift = 32 - pTables->m_table_bits;

         return true;
      }
Example #18
0
   bool generate_huffman_codes(void* pContext, uint num_syms, const uint16* pFreq, uint8* pCodesizes, uint& max_code_size, uint& total_freq_ret)
   {
      if ((!num_syms) || (num_syms > cHuffmanMaxSupportedSyms))
         return false;
                  
      huffman_work_tables& state = *static_cast<huffman_work_tables*>(pContext);;
            
      uint max_freq = 0;
      uint total_freq = 0;
      
      uint num_used_syms = 0;
      for (uint i = 0; i < num_syms; i++)
      {
         uint freq = pFreq[i];
         
         if (!freq)
            pCodesizes[i] = 0;
         else
         {
            total_freq += freq;
            max_freq = math::maximum(max_freq, freq);
            
            sym_freq& sf = state.syms0[num_used_syms];
            sf.m_left = (uint16)i;
            sf.m_right = LZHAM_UINT16_MAX;
            sf.m_freq = freq;
            num_used_syms++;
         }            
      }
      
      total_freq_ret = total_freq;

      if (num_used_syms == 1)
      {
         pCodesizes[state.syms0[0].m_left] = 1;
         return true;
      }

      sym_freq* syms = radix_sort_syms(num_used_syms, state.syms0, state.syms1);
      
#if USE_CALCULATE_MINIMUM_REDUNDANCY
      int x[cHuffmanMaxSupportedSyms];
      for (uint i = 0; i < num_used_syms; i++)
         x[i] = syms[i].m_freq;
      
      calculate_minimum_redundancy(x, num_used_syms);
      
      uint max_len = 0;
      for (uint i = 0; i < num_used_syms; i++)
      {
         uint len = x[i];
         max_len = math::maximum(len, max_len);
         pCodesizes[syms[i].m_left] = static_cast<uint8>(len);
      }
      max_code_size = max_len;
#else    
      // Computes Huffman codelengths in linear time. More readable than calculate_minimum_redundancy(), and approximately the same speed, but not in-place.
      
      // Dummy node
      sym_freq& sf = state.syms0[num_used_syms];
      sf.m_left = LZHAM_UINT16_MAX;
      sf.m_right = LZHAM_UINT16_MAX;
      sf.m_freq = UINT_MAX;
      
      uint next_internal_node = num_used_syms + 1;
            
      uint queue_front = 0;
      uint queue_end = 0;
            
      uint next_lowest_sym = 0;
      
      uint num_nodes_remaining = num_used_syms;
      do
      {
         uint left_freq = syms[next_lowest_sym].m_freq;
         uint left_child = next_lowest_sym;
         
         if ((queue_end > queue_front) && (syms[state.queue[queue_front]].m_freq < left_freq))
         {
            left_child = state.queue[queue_front];
            left_freq = syms[left_child].m_freq;
            
            queue_front++;
         }
         else
            next_lowest_sym++;
         
         uint right_freq = syms[next_lowest_sym].m_freq;
         uint right_child = next_lowest_sym;

         if ((queue_end > queue_front) && (syms[state.queue[queue_front]].m_freq < right_freq))
         {
            right_child = state.queue[queue_front];
            right_freq = syms[right_child].m_freq;
            
            queue_front++;
         }
         else
            next_lowest_sym++;
      
         LZHAM_ASSERT(next_internal_node < huffman_work_tables::cMaxInternalNodes);
         
         const uint internal_node_index = next_internal_node;
         next_internal_node++;
         
         syms[internal_node_index].m_freq = left_freq + right_freq;
         syms[internal_node_index].m_left = static_cast<uint16>(left_child);
         syms[internal_node_index].m_right = static_cast<uint16>(right_child);
         
         LZHAM_ASSERT(queue_end < huffman_work_tables::cMaxInternalNodes);
         state.queue[queue_end] = static_cast<uint16>(internal_node_index);
         queue_end++;
                  
         num_nodes_remaining--;
         
      } while (num_nodes_remaining > 1);
      
      LZHAM_ASSERT(next_lowest_sym == num_used_syms);
      LZHAM_ASSERT((queue_end - queue_front) == 1);
      
      uint cur_node_index = state.queue[queue_front];
      
      uint32* pStack = (syms == state.syms0) ? (uint32*)state.syms1 : (uint32*)state.syms0;
      uint32* pStack_top = pStack;

      uint max_level = 0;
      
      for ( ; ; ) 
      {
         uint level = cur_node_index >> 16;
         uint node_index = cur_node_index & 0xFFFF;
         
         uint left_child = syms[node_index].m_left;
         uint right_child = syms[node_index].m_right;
         
         uint next_level = (cur_node_index + 0x10000) & 0xFFFF0000;
                           
         if (left_child < num_used_syms)
         {
            max_level = math::maximum(max_level, level);
            
            pCodesizes[syms[left_child].m_left] = static_cast<uint8>(level + 1);
            
            if (right_child < num_used_syms)
            {
               pCodesizes[syms[right_child].m_left] = static_cast<uint8>(level + 1);
               
               if (pStack == pStack_top) break;
               cur_node_index = *--pStack;
            }
            else
            {
               cur_node_index = next_level | right_child;
            }
         }
         else
         {
            if (right_child < num_used_syms)
            {
               max_level = math::maximum(max_level, level);
               
               pCodesizes[syms[right_child].m_left] = static_cast<uint8>(level + 1);
                              
               cur_node_index = next_level | left_child;
            }
            else
            {
               *pStack++ = next_level | left_child;
                              
               cur_node_index = next_level | right_child;
            }
         }
      }
      
      max_code_size = max_level + 1;
#endif
                  
      return true;
   }