summaryrefslogtreecommitdiffstats
path: root/ml/dlib/dlib/entropy_encoder/entropy_encoder_kernel_2.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ml/dlib/dlib/entropy_encoder/entropy_encoder_kernel_2.cpp')
-rw-r--r--ml/dlib/dlib/entropy_encoder/entropy_encoder_kernel_2.cpp233
1 files changed, 233 insertions, 0 deletions
diff --git a/ml/dlib/dlib/entropy_encoder/entropy_encoder_kernel_2.cpp b/ml/dlib/dlib/entropy_encoder/entropy_encoder_kernel_2.cpp
new file mode 100644
index 000000000..4f64a6155
--- /dev/null
+++ b/ml/dlib/dlib/entropy_encoder/entropy_encoder_kernel_2.cpp
@@ -0,0 +1,233 @@
+// Copyright (C) 2004 Davis E. King (davis@dlib.net)
+// License: Boost Software License See LICENSE.txt for the full license.
+#ifndef DLIB_ENTROPY_ENCODER_KERNEL_2_CPp_
+#define DLIB_ENTROPY_ENCODER_KERNEL_2_CPp_
+#include "entropy_encoder_kernel_2.h"
+#include <iostream>
+#include <streambuf>
+
+namespace dlib
+{
+
+
+// ----------------------------------------------------------------------------------------
+
+ entropy_encoder_kernel_2::
+ entropy_encoder_kernel_2(
+ ) :
+ initial_low(0x00000001),
+ initial_high(0xffffffff),
+ out(0),
+ low(initial_low),
+ high(initial_high)
+ {
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ entropy_encoder_kernel_2::
+ ~entropy_encoder_kernel_2 (
+ )
+ {
+ try {
+ if (out != 0)
+ {
+ flush();
+ }
+ } catch (...) {}
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ void entropy_encoder_kernel_2::
+ clear(
+ )
+ {
+ if (out != 0)
+ {
+ flush();
+ }
+ out = 0;
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ void entropy_encoder_kernel_2::
+ set_stream (
+ std::ostream& out_
+ )
+ {
+ if (out != 0)
+ {
+ // if a stream is currently set then flush the buffers to it before
+ // we switch to the new stream
+ flush();
+ }
+
+ out = &out_;
+ streambuf = out_.rdbuf();
+
+ // reset the encoder state
+ low = initial_low;
+ high = initial_high;
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ bool entropy_encoder_kernel_2::
+ stream_is_set (
+ ) const
+ {
+ if (out != 0)
+ return true;
+ else
+ return false;
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ std::ostream& entropy_encoder_kernel_2::
+ get_stream (
+ ) const
+ {
+ return *out;
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ void entropy_encoder_kernel_2::
+ encode (
+ uint32 low_count,
+ uint32 high_count,
+ uint32 total
+ )
+ {
+ // note that we must add one because of the convention that
+ // high == the real upper range minus 1
+ uint32 r = (high-low+1)/total;
+
+ // note that we must subtract 1 to preserve the convention that
+ // high == the real upper range - 1
+ high = low + r*high_count-1;
+ low = low + r*low_count;
+
+
+
+ while (true )
+ {
+
+ // if high and low don't have the same 8 high order bits
+ if ((high&0xFF000000) != (low&0xFF000000))
+ {
+ // if the distance between high and low is small and there aren't
+ // any bits we can roll off then force high and low to have common high
+ // order bits.
+ if ((high-low < 0x10000))
+ {
+ if (high-low > 0x1000)
+ {
+ high>>=1;
+ low>>=1;
+ high = low = high+low;
+ high += 0xFF;
+ low -= 0xFF;
+ }
+ else /**/
+ {
+ high>>=1;
+ low>>=1;
+ high = low = high+low;
+ }
+ }
+ else
+ {
+ // there are no bits to roll off and high and low are not
+ // too close so just quit the loop
+ break;
+ }
+
+ }
+ // else if there are 8 bits we can roll off
+ else
+ {
+ // write the 8 high order bits from low into buf
+ unsigned char buf = static_cast<unsigned char>(low>>24);
+
+
+ // roll off the bits we just wrote to buf
+ high <<= 8;
+ low <<= 8;
+ high |= 0xFF; // note that it is ok to add 0xFF to high here because
+ // of the convention that high == real upper range - 1.
+ // so that means that if we want to shift the upper range
+ // left by one then we must shift a one into high also
+ // since real upper range == high + 0.999999999...
+
+ // make sure low is never zero
+ if (low == 0)
+ low = 1;
+
+ // write buf to the output stream
+ if (streambuf->sputn(reinterpret_cast<char*>(&buf),1)==0)
+ {
+ throw std::ios_base::failure("error occurred in the entropy_encoder object");
+ }
+
+ }
+
+ } // while (true)
+
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ void entropy_encoder_kernel_2::
+ flush (
+ )
+ {
+
+ // flush low to the output stream
+
+
+ unsigned char buf;
+
+
+ buf = static_cast<unsigned char>((low >> 24)&0xFF);
+ if (streambuf->sputn(reinterpret_cast<char*>(&buf),1) == 0)
+ throw std::ios_base::failure("error occurred in the entropy_encoder object");
+
+
+
+
+ buf = static_cast<unsigned char>((low >> 16)&0xFF);
+ if (streambuf->sputn(reinterpret_cast<char*>(&buf),1)==0)
+ throw std::ios_base::failure("error occurred in the entropy_encoder object");
+
+
+
+ buf = static_cast<unsigned char>((low >> 8)&0xFF);
+ if (streambuf->sputn(reinterpret_cast<char*>(&buf),1)==0)
+ throw std::ios_base::failure("error occurred in the entropy_encoder object");
+
+
+ buf = static_cast<unsigned char>((low)&0xFF);
+ if (streambuf->sputn(reinterpret_cast<char*>(&buf),1)==0)
+ throw std::ios_base::failure("error occurred in the entropy_encoder object");
+
+
+
+
+ // make sure the stream buffer flushes to its I/O channel
+ streambuf->pubsync();
+
+
+ // reset the encoder state
+ low = initial_low;
+ high = initial_high;
+ }
+
+// ----------------------------------------------------------------------------------------
+
+}
+#endif // DLIB_ENTROPY_ENCODER_KERNEL_2_CPp_
+