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