|
|
|
|
|
#ifndef DLIB_CONDITIONING_CLASS_KERNEl_3_ |
|
#define DLIB_CONDITIONING_CLASS_KERNEl_3_ |
|
|
|
#include "conditioning_class_kernel_abstract.h" |
|
#include "../assert.h" |
|
#include "../algs.h" |
|
|
|
|
|
namespace dlib |
|
{ |
|
|
|
template < |
|
unsigned long alphabet_size |
|
> |
|
class conditioning_class_kernel_3 |
|
{ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public: |
|
|
|
class global_state_type |
|
{ |
|
public: |
|
global_state_type () : memory_usage(0) {} |
|
private: |
|
unsigned long memory_usage; |
|
|
|
friend class conditioning_class_kernel_3<alphabet_size>; |
|
}; |
|
|
|
conditioning_class_kernel_3 ( |
|
global_state_type& global_state_ |
|
); |
|
|
|
~conditioning_class_kernel_3 ( |
|
); |
|
|
|
void clear( |
|
); |
|
|
|
bool increment_count ( |
|
unsigned long symbol, |
|
unsigned short amount = 1 |
|
); |
|
|
|
unsigned long get_count ( |
|
unsigned long symbol |
|
) const; |
|
|
|
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: |
|
|
|
|
|
conditioning_class_kernel_3(conditioning_class_kernel_3<alphabet_size>&); |
|
conditioning_class_kernel_3& operator=(conditioning_class_kernel_3<alphabet_size>&); |
|
|
|
struct data |
|
{ |
|
unsigned short count; |
|
unsigned short symbol; |
|
bool present; |
|
}; |
|
|
|
|
|
unsigned short total; |
|
data* counts; |
|
global_state_type& global_state; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template < |
|
unsigned long alphabet_size |
|
> |
|
conditioning_class_kernel_3<alphabet_size>:: |
|
conditioning_class_kernel_3 ( |
|
global_state_type& global_state_ |
|
) : |
|
total(1), |
|
counts(new data[alphabet_size]), |
|
global_state(global_state_) |
|
{ |
|
COMPILE_TIME_ASSERT( 1 < alphabet_size && alphabet_size < 65536 ); |
|
|
|
data* start = counts; |
|
data* end = counts+alphabet_size; |
|
start->count = 1; |
|
start->symbol = alphabet_size-1; |
|
start->present = false; |
|
++start; |
|
while (start != end) |
|
{ |
|
start->count = 0; |
|
start->present = false; |
|
++start; |
|
} |
|
counts[alphabet_size-1].present = true; |
|
|
|
|
|
global_state.memory_usage += sizeof(data)*alphabet_size + |
|
sizeof(conditioning_class_kernel_3); |
|
|
|
} |
|
|
|
|
|
|
|
template < |
|
unsigned long alphabet_size |
|
> |
|
conditioning_class_kernel_3<alphabet_size>:: |
|
~conditioning_class_kernel_3 ( |
|
) |
|
{ |
|
delete [] counts; |
|
|
|
global_state.memory_usage -= sizeof(data)*alphabet_size + |
|
sizeof(conditioning_class_kernel_3); |
|
} |
|
|
|
|
|
|
|
template < |
|
unsigned long alphabet_size |
|
> |
|
void conditioning_class_kernel_3<alphabet_size>:: |
|
clear( |
|
) |
|
{ |
|
total = 1; |
|
data* start = counts; |
|
data* end = counts+alphabet_size; |
|
start->count = 1; |
|
start->symbol = alphabet_size-1; |
|
start->present = false; |
|
++start; |
|
while (start != end) |
|
{ |
|
start->count = 0; |
|
start->present = false; |
|
++start; |
|
} |
|
counts[alphabet_size-1].present = true; |
|
|
|
} |
|
|
|
|
|
|
|
template < |
|
unsigned long alphabet_size |
|
> |
|
typename conditioning_class_kernel_3<alphabet_size>::global_state_type& conditioning_class_kernel_3<alphabet_size>:: |
|
get_global_state( |
|
) |
|
{ |
|
return global_state; |
|
} |
|
|
|
|
|
|
|
template < |
|
unsigned long alphabet_size |
|
> |
|
unsigned long conditioning_class_kernel_3<alphabet_size>:: |
|
get_memory_usage( |
|
) const |
|
{ |
|
return global_state.memory_usage; |
|
} |
|
|
|
|
|
|
|
template < |
|
unsigned long alphabet_size |
|
> |
|
bool conditioning_class_kernel_3<alphabet_size>:: |
|
increment_count ( |
|
unsigned long symbol, |
|
unsigned short amount |
|
) |
|
{ |
|
|
|
if (static_cast<unsigned long>(total)+static_cast<unsigned long>(amount) >= 65536) |
|
{ |
|
total = 0; |
|
data* start = counts; |
|
data* end = counts+alphabet_size; |
|
|
|
while (start != end) |
|
{ |
|
if (start->count == 1) |
|
{ |
|
if (start->symbol == alphabet_size-1) |
|
{ |
|
|
|
++total; |
|
} |
|
else |
|
{ |
|
start->count = 0; |
|
counts[start->symbol].present = false; |
|
} |
|
} |
|
else |
|
{ |
|
start->count >>= 1; |
|
total += start->count; |
|
} |
|
|
|
++start; |
|
} |
|
} |
|
|
|
|
|
data* start = counts; |
|
data* swap_spot = counts; |
|
|
|
if (counts[symbol].present) |
|
{ |
|
while (true) |
|
{ |
|
if (start->symbol == symbol && start->count!=0) |
|
{ |
|
unsigned short temp = start->count + amount; |
|
|
|
start->symbol = swap_spot->symbol; |
|
start->count = swap_spot->count; |
|
|
|
swap_spot->symbol = static_cast<unsigned short>(symbol); |
|
swap_spot->count = temp; |
|
break; |
|
} |
|
|
|
if ( (start->count) < (swap_spot->count)) |
|
{ |
|
swap_spot = start; |
|
} |
|
|
|
|
|
++start; |
|
} |
|
} |
|
else |
|
{ |
|
counts[symbol].present = true; |
|
while (true) |
|
{ |
|
if (start->count == 0) |
|
{ |
|
start->symbol = swap_spot->symbol; |
|
start->count = swap_spot->count; |
|
|
|
swap_spot->symbol = static_cast<unsigned short>(symbol); |
|
swap_spot->count = amount; |
|
break; |
|
} |
|
|
|
if ((start->count) < (swap_spot->count)) |
|
{ |
|
swap_spot = start; |
|
} |
|
|
|
++start; |
|
} |
|
} |
|
|
|
total += amount; |
|
|
|
return true; |
|
} |
|
|
|
|
|
|
|
template < |
|
unsigned long alphabet_size |
|
> |
|
unsigned long conditioning_class_kernel_3<alphabet_size>:: |
|
get_count ( |
|
unsigned long symbol |
|
) const |
|
{ |
|
if (counts[symbol].present == false) |
|
return 0; |
|
|
|
data* start = counts; |
|
while (start->symbol != symbol) |
|
{ |
|
++start; |
|
} |
|
return start->count; |
|
} |
|
|
|
|
|
|
|
template < |
|
unsigned long alphabet_size |
|
> |
|
unsigned long conditioning_class_kernel_3<alphabet_size>:: |
|
get_alphabet_size ( |
|
) |
|
{ |
|
return alphabet_size; |
|
} |
|
|
|
|
|
|
|
template < |
|
unsigned long alphabet_size |
|
> |
|
unsigned long conditioning_class_kernel_3<alphabet_size>:: |
|
get_total ( |
|
) const |
|
{ |
|
return total; |
|
} |
|
|
|
|
|
|
|
template < |
|
unsigned long alphabet_size |
|
> |
|
unsigned long conditioning_class_kernel_3<alphabet_size>:: |
|
get_range ( |
|
unsigned long symbol, |
|
unsigned long& low_count, |
|
unsigned long& high_count, |
|
unsigned long& total_count |
|
) const |
|
{ |
|
if (counts[symbol].present == false) |
|
return 0; |
|
|
|
total_count = total; |
|
unsigned long low_count_temp = 0; |
|
data* start = counts; |
|
while (start->symbol != symbol) |
|
{ |
|
low_count_temp += start->count; |
|
++start; |
|
} |
|
|
|
low_count = low_count_temp; |
|
high_count = low_count_temp + start->count; |
|
return start->count; |
|
} |
|
|
|
|
|
|
|
template < |
|
unsigned long alphabet_size |
|
> |
|
void conditioning_class_kernel_3<alphabet_size>:: |
|
get_symbol ( |
|
unsigned long target, |
|
unsigned long& symbol, |
|
unsigned long& low_count, |
|
unsigned long& high_count |
|
) const |
|
{ |
|
unsigned long high_count_temp = counts->count; |
|
const data* start = counts; |
|
while (target >= high_count_temp) |
|
{ |
|
++start; |
|
high_count_temp += start->count; |
|
} |
|
|
|
low_count = high_count_temp - start->count; |
|
high_count = high_count_temp; |
|
symbol = static_cast<unsigned long>(start->symbol); |
|
} |
|
|
|
|
|
|
|
} |
|
|
|
#endif |
|
|
|
|