```// Copyright (C) 2003  Davis E. King (davis@dlib.net)
#undef DLIB_CONDITIONING_CLASS_KERNEl_ABSTRACT_
#ifdef DLIB_CONDITIONING_CLASS_KERNEl_ABSTRACT_

#include "../algs.h"

namespace dlib
{

template <
unsigned long alphabet_size
>
class conditioning_class
{
/*!
REQUIREMENTS ON alphabet_size
1 < alphabet_size < 65536

INITIAL VALUE
get_total() == 1
get_count(X) == 0 : for all valid values of X except alphabet_size-1
get_count(alphabet_size-1) == 1

WHAT THIS OBJECT REPRESENTS
This object represents a conditioning class used for arithmetic style
compression.  It maintains the cumulative counts which are needed
by the entropy_coder and entropy_decoder objects.

At any moment a conditioning_class object represents a set of
alphabet_size symbols.  Each symbol is associated with an integer
called its count.

All symbols start out with a count of zero except for alphabet_size-1.
This last symbol will always have a count of at least one.  It is
intended to be used as an escape into a lower context when coding
and so it must never have a zero probability or the decoder won't
be able to identify the escape symbol.

NOTATION:
Let MAP(i) be a function which maps integers to symbols.  MAP(i) is
one to one and onto.  Its domain is 1 to alphabet_size inclusive.

Let RMAP(s) be the inverse of MAP(i).
( i.e.  RMAP(MAP(i)) == i  and  MAP(RMAP(s)) == s  )

Let COUNT(i) give the count for the symbol MAP(i).
( i.e.  COUNT(i) == get_count(MAP(i)) )

Let LOW_COUNT(s) == the sum of COUNT(x) for x == 1 to x == RMAP(s)-1
(note that the sum of COUNT(x) for x == 1 to x == 0 is 0)
Let HIGH_COUNT(s) == LOW_COUNT(s) + get_count(s)

Basically what this is saying is just that you shoudln't assume you know
what order the symbols are placed in when calculating the cumulative
sums.  The specific mapping provided by the MAP() function is unspecified.

This object can be used safely in a multithreaded program as long as the
global state is not shared between conditioning classes which run on

GLOBAL_STATE_TYPE
The global_state_type obejct allows instances of the conditioning_class
object to share any kind of global state the implementer desires.
However, the global_state_type object exists primarily to facilitate the
sharing of a memory pool between many instances of a conditioning_class
object.  But note that it is not required that there be any kind of
memory pool at all, it is just a possibility.
!*/

public:

class global_state_type
{
global_state_type (
);
/*!
ensures
- #*this is properly initialized
throws
!*/

// my contents are implementation specific.
};

conditioning_class (
global_state_type& global_state
);
/*!
ensures
- #*this is properly initialized
- &#get_global_state() == &global_state
throws
!*/

~conditioning_class (
);
/*!
ensures
- all memory associated with *this has been released
!*/

void clear(
);
/*!
ensures
- #*this has its initial value
throws
!*/

bool increment_count (
unsigned long symbol,
unsigned short amount = 1
);
/*!
requires
- 0 <= symbol < alphabet_size
- 0 < amount < 32768
ensures
- if (sufficient memory is available to complete this operation) then
- returns true
- if (get_total()+amount < 65536) then
- #get_count(symbol) == get_count(symbol) + amount
- else
- #get_count(symbol) == get_count(symbol)/2 + amount
- if (get_count(alphabet_size-1) == 1) then
- #get_count(alphabet_size-1) == 1
- else
- #get_count(alphabet_size-1) == get_count(alphabet_size-1)/2
- for all X where (X != symbol)&&(X != alpahbet_size-1):
#get_count(X) == get_count(X)/2
- else
- returns false
!*/

unsigned long get_count (
unsigned long symbol
) const;
/*!
requires
- 0 <= symbol < alphabet_size
ensures
- returns the count for the specified symbol
!*/

unsigned long get_total (
) const;
/*!
ensures
- returns the sum of get_count(X) for all valid values of X
(i.e. returns the sum of the counts for all the symbols)
!*/

unsigned long get_range (
unsigned long symbol,
unsigned long& low_count,
unsigned long& high_count,
unsigned long& total_count
) const;
/*!
requires
- 0 <= symbol < alphabet_size
ensures
- returns get_count(symbol)
- if (get_count(symbol) != 0) then
- #total_count == get_total()
- #low_count   == LOW_COUNT(symbol)
- #high_count  == HIGH_COUNT(symbol)
- #low_count < #high_count <= #total_count
!*/

void get_symbol (
unsigned long target,
unsigned long& symbol,
unsigned long& low_count,
unsigned long& high_count
) const;
/*!
requires
- 0 <= target < get_total()
ensures
- LOW_COUNT(#symbol) <= target < HIGH_COUNT(#symbol)
- #low_count   == LOW_COUNT(#symbol)
- #high_count  == HIGH_COUNT(#symbol)
- #low_count < #high_count <= get_total()
!*/

global_state_type& get_global_state (
);
/*!
ensures
- returns a reference to the global state used by *this
!*/

unsigned long get_memory_usage (
) const;
/*!
ensures
- returns the number of bytes of memory allocated by all conditioning_class
objects that share the global state given by get_global_state()
!*/

static unsigned long get_alphabet_size (
);
/*!
ensures
- returns alphabet_size
!*/

private:

// restricted functions
conditioning_class(conditioning_class<alphabet_size>&);        // copy constructor
conditioning_class<alphabet_size>& operator=(conditioning_class<alphabet_size>&);    // assignment operator

};

}

#endif // DLIB_CONDITIONING_CLASS_KERNEl_ABSTRACT_

```