// Copyright (C) 2003  Davis E. King (davis@dlib.net)
// License: Boost Software License   See LICENSE.txt for the full license.
#undef DLIB_ENTROPY_ENCODER_KERNEl_ABSTRACT_
#ifdef DLIB_ENTROPY_ENCODER_KERNEl_ABSTRACT_

#include "../algs.h"
#include <iosfwd>
#include "../uintn.h"

namespace dlib
{

    class entropy_encoder 
    {
        /*!
            INITIAL VALUE
                stream_is_set() == false


            WHAT THIS OBJECT REPRESENTS
                This object represents an entropy encoder (could be implemented as an 
                arithmetic encoder for example).      
                
                Note that all implementations of entropy_encoder and entropy_decoder 
                are paired. This means that if you use entropy_encoder_kernel_n to 
                encode something then you must use the corresponding 
                entropy_decoder_kernel_n to decode it.

            NOTATION:              
                At any moment each symbol has a certain probability of appearing in 
                the input stream.  These probabilities may change as each symbol is 
                encountered and the probability model is updated accordingly.


                let P(i) be a function which gives the probability of seeing the ith 
                symbol of an N symbol alphabet BEFORE the probability model is updated
                to account for the current symbol.  ( The domain of P(i) is from 0 to N-1. )

                for each i: P(i) == COUNT/TOTAL where COUNT and TOTAL are integers.
                and TOTAL is the same number for all P(i) but COUNT may vary.
                   
                let LOW_COUNT(i)  be the sum of all P(x)*TOTAL from x == 0 to x == i-1
                  (note that LOW_COUNT(0) == 0)
                let HIGH_COUNT(i) be the sum of all P(x)*TOTAL from x == 0 to x == i
        !*/

    public:

        entropy_encoder (
        );
        /*!
            ensures
                - #*this is properly initialized
            throws
                - std::bad_alloc
        !*/

        virtual ~entropy_encoder (
        );
        /*!
            ensures
                - all memory associated with *this has been released
                - if (stream_is_set()) then
                    - any buffered data in *this will be written to get_stream() 
        !*/

        void clear(
        );
        /*!
            ensures
                - #*this has its initial value
                - if (stream_is_set()) then
                    - any buffered data in *this will be written to get_stream() 
                    - clears any memory of all previous calls to encode() from #*this
            throws
                - std::ios_base::failure
                    if (stream_is_set() && there was a problem writing to get_stream())
                    then this exception will be thrown.  #*this will be unusable until
                    clear() is called and succeeds
                - any other exception
                    if this exception is thrown then #*this is unusable 
                    until clear() is called and succeeds
        !*/


        void set_stream (
            std::ostream& out
        );
        /*!
            ensures
                - #get_stream()    == out
                - #stream_is_set() == true
                - if (stream_is_set()) then
                    - any buffered data in *this will be written to get_stream() 
                    - clears any memory of all previous calls to encode() from #*this
            throws
                - std::ios_base::failure
                    if (stream_is_set() && there was a problem writing to get_stream())
                    then this exception will be thrown.  #*this will be unusable until
                    clear() is called and succeeds
                - any other exception
                    if this exception is thrown then #*this is unusable 
                    until clear() is called and succeeds
        !*/

        bool stream_is_set (
        ) const;
        /*!
            ensures
                - returns true if a stream has been associated with *this by calling
                  set_stream()
        !*/

        std::ostream& get_stream (
        ) const;
        /*!
            requires
                - stream_is_set() == true
            ensures
                - returns a reference to the ostream object that *this writes its 
                  encoded data to
        !*/

        void encode (
            uint32 low_count,
            uint32 high_count,
            uint32 total
        );
        /*!
            requires
                - 0 < total <  65536 (2^16)
                - total == TOTAL
                - low_count < high_count <= total    
                - stream_is_set() == true
            ensures
                - encodes the symbol S where: 
                    - LOW_COUNT(S)  == low_count
                    - HIGH_COUNT(S) == high_count
            throws
                - std::ios_base::failure
                    if (there was a problem writing to get_stream()) then
                    this exception will be thrown.  #*this will be unusable until
                    clear() is called and succeeds
                - any other exception
                    if this exception is thrown then #*this is unusable 
                    until clear() is called and succeeds
        !*/


    private:

        // restricted functions
        entropy_encoder(entropy_encoder&);        // copy constructor
        entropy_encoder& operator=(entropy_encoder&);    // assignment operator

    };   
   
}

#endif // DLIB_ENTROPY_ENCODER_KERNEl_ABSTRACT_