// Copyright (C) 2003  Davis E. King (davis@dlib.net)
// License: Boost Software License   See LICENSE.txt for the full license.
#ifndef DLIB_ENTROPY_DECODER_KERNEl_1_
#define DLIB_ENTROPY_DECODER_KERNEl_1_
#include "../algs.h"
#include "entropy_decoder_kernel_abstract.h"
#include <iosfwd>
#include "../uintn.h"
namespace dlib
{
    class entropy_decoder_kernel_1 
    {
        /*!
            GENERAL NOTES
                this decoder is implemented using arithmetic coding
            INITIAL VALUE
                in       == 0
                buf_used == 0
                buf      == 0
                initial_low      == 0x00000001  (slightly more than zero)
                initial_high     == 0xffffffff  (slightly less than one, 0.99999999976717)
                target   == 0x00000000  (zero)
                low      == initial_low
                high     == initial_high
                r        == 0
            CONVENTION
                if (in != 0)
                    *in       == get_stream()
                    true      == stream_is_set()
                    streambuf == in->rdbuf()
                else
                    false   == stream_is_set()
                buf      == used to hold fractional byte values which are fed to target.  
                buf_used == the number of low order bits in buf that are currently 
                            in use
                low      == the low end of the range used for arithmetic encoding.
                            this number is used as a 32bit fixed point real number. 
                            the point is fixed just before the first bit, so it is
                            always in the range [0,1)
                            low is also never allowed to be zero to avoid overflow
                            in the calculation (high-low+1)/total.
                high     == the high end of the range - 1 used for arithmetic encoding.
                            this number is used as a 32bit fixed point real number. 
                            the point is fixed just before the first bit, so when we
                            interpret high as a real number then it is always in the
                            range [0,1)
                            the range for arithmetic encoding is always 
                            [low,high + 0.9999999...)   the 0.9999999... is why
                            high == real upper range - 1
                target  ==  32 bits of the fraction produced from an arithmetic encoder.
                            this number is used as a 32bit fixed point real number. 
                            the point is fixed just before the first bit, so it is
                            always in the range [0,1)      
                r       ==  the value (high-low+1)/total from the last call to 
                            get_target() or 0 if get_target_called() should be false
                get_target_called() == (r != 0)
        !*/
    public:
        entropy_decoder_kernel_1 (
        );
        virtual ~entropy_decoder_kernel_1 (
        );
        void clear(
        );
        void set_stream (
            std::istream& in
        );
        bool stream_is_set (
        ) const;
        std::istream& get_stream (
        ) const;
        void decode (
            uint32 low_count,
            uint32 high_count
        );
        bool get_target_called (
        ) const;
        uint32 get_target (
            uint32 total
        );
    private:
        // restricted functions
        entropy_decoder_kernel_1(entropy_decoder_kernel_1&);        // copy constructor
        entropy_decoder_kernel_1& operator=(entropy_decoder_kernel_1&);    // assignment operator
        // data members
        const uint32 initial_low;
        const uint32 initial_high;
        std::istream* in;
        uint32 low;
        uint32 high;
        unsigned char buf; 
        uint32 buf_used; 
        uint32 target;
        uint32 r;
        std::streambuf* streambuf;
    };   
}
#ifdef NO_MAKEFILE
#include "entropy_decoder_kernel_1.cpp"
#endif
#endif // DLIB_ENTROPY_DECODER_KERNEl_1_