|
|
|
|
|
#ifndef DLIB_CONDITIONING_CLASS_KERNEl_4_ |
|
#define DLIB_CONDITIONING_CLASS_KERNEl_4_ |
|
|
|
#include "conditioning_class_kernel_abstract.h" |
|
#include "../assert.h" |
|
#include "../algs.h" |
|
|
|
namespace dlib |
|
{ |
|
template < |
|
unsigned long alphabet_size, |
|
unsigned long pool_size, |
|
typename mem_manager |
|
> |
|
class conditioning_class_kernel_4 |
|
{ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct node |
|
{ |
|
unsigned short symbol; |
|
unsigned short count; |
|
node* next; |
|
}; |
|
|
|
public: |
|
|
|
class global_state_type |
|
{ |
|
public: |
|
global_state_type ( |
|
) : |
|
memory_usage(pool_size*sizeof(node)+sizeof(global_state_type)) |
|
{} |
|
private: |
|
unsigned long memory_usage; |
|
|
|
typename mem_manager::template rebind<node>::other pool; |
|
|
|
friend class conditioning_class_kernel_4<alphabet_size,pool_size,mem_manager>; |
|
}; |
|
|
|
conditioning_class_kernel_4 ( |
|
global_state_type& global_state_ |
|
); |
|
|
|
~conditioning_class_kernel_4 ( |
|
); |
|
|
|
void clear( |
|
); |
|
|
|
bool increment_count ( |
|
unsigned long symbol, |
|
unsigned short amount = 1 |
|
); |
|
|
|
unsigned long get_count ( |
|
unsigned long symbol |
|
) const; |
|
|
|
inline unsigned long get_total ( |
|
) const; |
|
|
|
unsigned long get_range ( |
|
unsigned long symbol, |
|
unsigned long& low_count, |
|
unsigned long& high_count, |
|
unsigned long& total_count |
|
) const; |
|
|
|
void get_symbol ( |
|
unsigned long target, |
|
unsigned long& symbol, |
|
unsigned long& low_count, |
|
unsigned long& high_count |
|
) const; |
|
|
|
unsigned long get_memory_usage ( |
|
) const; |
|
|
|
global_state_type& get_global_state ( |
|
); |
|
|
|
static unsigned long get_alphabet_size ( |
|
); |
|
|
|
|
|
private: |
|
|
|
void half_counts ( |
|
); |
|
|
|
|
|
|
|
|
|
|
|
|
|
conditioning_class_kernel_4(conditioning_class_kernel_4<alphabet_size,pool_size,mem_manager>&); |
|
conditioning_class_kernel_4& operator=(conditioning_class_kernel_4<alphabet_size,pool_size,mem_manager>&); |
|
|
|
|
|
unsigned short total; |
|
unsigned short escapes; |
|
node* next; |
|
global_state_type& global_state; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template < |
|
unsigned long alphabet_size, |
|
unsigned long pool_size, |
|
typename mem_manager |
|
> |
|
conditioning_class_kernel_4<alphabet_size,pool_size,mem_manager>:: |
|
conditioning_class_kernel_4 ( |
|
global_state_type& global_state_ |
|
) : |
|
total(1), |
|
escapes(1), |
|
next(0), |
|
global_state(global_state_) |
|
{ |
|
COMPILE_TIME_ASSERT( 1 < alphabet_size && alphabet_size < 65536 ); |
|
|
|
|
|
global_state.memory_usage += sizeof(conditioning_class_kernel_4); |
|
} |
|
|
|
|
|
|
|
template < |
|
unsigned long alphabet_size, |
|
unsigned long pool_size, |
|
typename mem_manager |
|
> |
|
conditioning_class_kernel_4<alphabet_size,pool_size,mem_manager>:: |
|
~conditioning_class_kernel_4 ( |
|
) |
|
{ |
|
clear(); |
|
|
|
global_state.memory_usage -= sizeof(conditioning_class_kernel_4); |
|
} |
|
|
|
|
|
|
|
template < |
|
unsigned long alphabet_size, |
|
unsigned long pool_size, |
|
typename mem_manager |
|
> |
|
void conditioning_class_kernel_4<alphabet_size,pool_size,mem_manager>:: |
|
clear( |
|
) |
|
{ |
|
total = 1; |
|
escapes = 1; |
|
while (next) |
|
{ |
|
node* temp = next; |
|
next = next->next; |
|
global_state.pool.deallocate(temp); |
|
} |
|
} |
|
|
|
|
|
|
|
template < |
|
unsigned long alphabet_size, |
|
unsigned long pool_size, |
|
typename mem_manager |
|
> |
|
unsigned long conditioning_class_kernel_4<alphabet_size,pool_size,mem_manager>:: |
|
get_memory_usage( |
|
) const |
|
{ |
|
return global_state.memory_usage; |
|
} |
|
|
|
|
|
|
|
template < |
|
unsigned long alphabet_size, |
|
unsigned long pool_size, |
|
typename mem_manager |
|
> |
|
typename conditioning_class_kernel_4<alphabet_size,pool_size,mem_manager>::global_state_type& conditioning_class_kernel_4<alphabet_size,pool_size,mem_manager>:: |
|
get_global_state( |
|
) |
|
{ |
|
return global_state; |
|
} |
|
|
|
|
|
|
|
template < |
|
unsigned long alphabet_size, |
|
unsigned long pool_size, |
|
typename mem_manager |
|
> |
|
bool conditioning_class_kernel_4<alphabet_size,pool_size,mem_manager>:: |
|
increment_count ( |
|
unsigned long symbol, |
|
unsigned short amount |
|
) |
|
{ |
|
if (symbol == alphabet_size-1) |
|
{ |
|
|
|
if (total >= 65536 - amount ) |
|
half_counts(); |
|
|
|
escapes += amount; |
|
total += amount; |
|
return true; |
|
} |
|
|
|
|
|
|
|
if (next) |
|
{ |
|
node* temp = next; |
|
node* previous = 0; |
|
while (true) |
|
{ |
|
if (temp->symbol == static_cast<unsigned short>(symbol)) |
|
{ |
|
|
|
if (total >= 65536 - amount ) |
|
half_counts(); |
|
|
|
|
|
total += amount; |
|
temp->count += amount; |
|
|
|
|
|
if (previous && temp->count > previous->count) |
|
{ |
|
|
|
swap(temp->count,previous->count); |
|
swap(temp->symbol,previous->symbol); |
|
} |
|
return true; |
|
} |
|
else if (temp->next == 0) |
|
{ |
|
|
|
if (global_state.pool.get_number_of_allocations() < pool_size) |
|
{ |
|
|
|
if (total >= 65536 - amount ) |
|
half_counts(); |
|
|
|
node* t = global_state.pool.allocate(); |
|
t->next = 0; |
|
t->symbol = static_cast<unsigned short>(symbol); |
|
t->count = amount; |
|
temp->next = t; |
|
total += amount; |
|
return true; |
|
} |
|
else |
|
{ |
|
|
|
return false; |
|
} |
|
} |
|
else if (temp->count == 0) |
|
{ |
|
|
|
if (previous) |
|
{ |
|
previous->next = temp->next; |
|
node* t = temp; |
|
temp = temp->next; |
|
global_state.pool.deallocate(t); |
|
} |
|
else |
|
{ |
|
next = temp->next; |
|
node* t = temp; |
|
temp = temp->next; |
|
global_state.pool.deallocate(t); |
|
} |
|
} |
|
else |
|
{ |
|
previous = temp; |
|
temp = temp->next; |
|
} |
|
} |
|
} |
|
|
|
else |
|
{ |
|
if (global_state.pool.get_number_of_allocations() < pool_size) |
|
{ |
|
|
|
if (total >= 65536 - amount ) |
|
half_counts(); |
|
|
|
next = global_state.pool.allocate(); |
|
next->next = 0; |
|
next->symbol = static_cast<unsigned short>(symbol); |
|
next->count = amount; |
|
total += amount; |
|
return true; |
|
} |
|
else |
|
{ |
|
|
|
return false; |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
template < |
|
unsigned long alphabet_size, |
|
unsigned long pool_size, |
|
typename mem_manager |
|
> |
|
unsigned long conditioning_class_kernel_4<alphabet_size,pool_size,mem_manager>:: |
|
get_count ( |
|
unsigned long symbol |
|
) const |
|
{ |
|
if (symbol == alphabet_size-1) |
|
{ |
|
return escapes; |
|
} |
|
else |
|
{ |
|
node* temp = next; |
|
while (temp) |
|
{ |
|
if (temp->symbol == symbol) |
|
return temp->count; |
|
temp = temp->next; |
|
} |
|
return 0; |
|
} |
|
} |
|
|
|
|
|
|
|
template < |
|
unsigned long alphabet_size, |
|
unsigned long pool_size, |
|
typename mem_manager |
|
> |
|
unsigned long conditioning_class_kernel_4<alphabet_size,pool_size,mem_manager>:: |
|
get_alphabet_size ( |
|
) |
|
{ |
|
return alphabet_size; |
|
} |
|
|
|
|
|
|
|
template < |
|
unsigned long alphabet_size, |
|
unsigned long pool_size, |
|
typename mem_manager |
|
> |
|
unsigned long conditioning_class_kernel_4<alphabet_size,pool_size,mem_manager>:: |
|
get_total ( |
|
) const |
|
{ |
|
return total; |
|
} |
|
|
|
|
|
|
|
template < |
|
unsigned long alphabet_size, |
|
unsigned long pool_size, |
|
typename mem_manager |
|
> |
|
unsigned long conditioning_class_kernel_4<alphabet_size,pool_size,mem_manager>:: |
|
get_range ( |
|
unsigned long symbol, |
|
unsigned long& low_count, |
|
unsigned long& high_count, |
|
unsigned long& total_count |
|
) const |
|
{ |
|
if (symbol != alphabet_size-1) |
|
{ |
|
node* temp = next; |
|
unsigned long low = 0; |
|
while (temp) |
|
{ |
|
if (temp->symbol == static_cast<unsigned short>(symbol)) |
|
{ |
|
high_count = temp->count + low; |
|
low_count = low; |
|
total_count = total; |
|
return temp->count; |
|
} |
|
low += temp->count; |
|
temp = temp->next; |
|
} |
|
return 0; |
|
} |
|
else |
|
{ |
|
total_count = total; |
|
high_count = total; |
|
low_count = total-escapes; |
|
return escapes; |
|
} |
|
} |
|
|
|
|
|
|
|
template < |
|
unsigned long alphabet_size, |
|
unsigned long pool_size, |
|
typename mem_manager |
|
> |
|
void conditioning_class_kernel_4<alphabet_size,pool_size,mem_manager>:: |
|
get_symbol ( |
|
unsigned long target, |
|
unsigned long& symbol, |
|
unsigned long& low_count, |
|
unsigned long& high_count |
|
) const |
|
{ |
|
node* temp = next; |
|
unsigned long high = 0; |
|
while (true) |
|
{ |
|
if (temp != 0) |
|
{ |
|
high += temp->count; |
|
if (target < high) |
|
{ |
|
symbol = temp->symbol; |
|
high_count = high; |
|
low_count = high - temp->count; |
|
return; |
|
} |
|
temp = temp->next; |
|
} |
|
else |
|
{ |
|
|
|
symbol = alphabet_size-1; |
|
low_count = total-escapes; |
|
high_count = total; |
|
return; |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template < |
|
unsigned long alphabet_size, |
|
unsigned long pool_size, |
|
typename mem_manager |
|
> |
|
void conditioning_class_kernel_4<alphabet_size,pool_size,mem_manager>:: |
|
half_counts ( |
|
) |
|
{ |
|
total = 0; |
|
if (escapes > 1) |
|
escapes >>= 1; |
|
|
|
|
|
node* temp = next; |
|
while (temp) |
|
{ |
|
temp->count >>= 1; |
|
total += temp->count; |
|
temp = temp->next; |
|
} |
|
total += escapes; |
|
} |
|
|
|
|
|
|
|
} |
|
|
|
#endif |
|
|
|
|