Commit 754da0ef authored by Davis King's avatar Davis King
Browse files

Properly organized the svn repository. Finally.

--HG--
extra : convert_revision : svn%3Afdd8eb12-d10e-0410-9acb-85c331704f74/trunk%402199
parent 49388714
// Copyright (C) 2007 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_DIRECTED_GRAPh_
#define DLIB_DIRECTED_GRAPh_
#include "directed_graph/directed_graph_kernel_1.h"
#include "memory_manager.h"
namespace dlib
{
template <
typename T,
typename E = char,
typename mem_manager = memory_manager<char>::kernel_1a
>
class directed_graph
{
directed_graph() {}
public:
//----------- kernels ---------------
// kernel_1a
typedef directed_graph_kernel_1<T,E,mem_manager,false>
kernel_1a;
typedef directed_graph_kernel_1<T,E,mem_manager,true>
kernel_1a_c;
};
}
#endif // DLIB_DIRECTED_GRAPh_
// Copyright (C) 2007 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_DIRECTED_GRAPH_KERNEl_1_
#define DLIB_DIRECTED_GRAPH_KERNEl_1_
#include "../serialize.h"
#include "../noncopyable.h"
#include "../std_allocator.h"
#include "../smart_pointers.h"
#include "../algs.h"
#include <vector>
#include "../memory_manager.h"
#include "directed_graph_kernel_abstract.h"
#include "../is_kind.h"
namespace dlib
{
// ----------------------------------------------------------------------------------------
template <typename node_type, typename directed_graph, bool is_checked>
struct directed_graph_checker_helper
{
/*!
This object is used to check preconditions based on the value of is_checked
!*/
static void check_parent_edge (
unsigned long edge_index,
const node_type& self
)
{
// make sure requires clause is not broken
DLIB_CASSERT(edge_index < self.number_of_parents(),
"\tnode_type& directed_graph::node_type::parent_edge(edge_index)"
<< "\n\tYou have specified an invalid index"
<< "\n\tedge_index: " << edge_index
<< "\n\tnumber_of_parents(): " << self.number_of_parents()
<< "\n\tthis: " << &self
);
}
static void check_child_edge (
unsigned long edge_index,
const node_type& self
)
{
// make sure requires clause is not broken
DLIB_CASSERT(edge_index < self.number_of_children(),
"\tnode_type& directed_graph::node_type::child_edge(edge_index)"
<< "\n\tYou have specified an invalid index"
<< "\n\tedge_index: " << edge_index
<< "\n\tnumber_of_children(): " << self.number_of_children()
<< "\n\tthis: " << &self
);
}
static void check_parent (
unsigned long edge_index,
const node_type& self
)
{
// make sure requires clause is not broken
DLIB_CASSERT(edge_index < self.number_of_parents(),
"\tnode_type& directed_graph::node_type::parent(edge_index)"
<< "\n\tYou have specified an invalid index"
<< "\n\tedge_index: " << edge_index
<< "\n\tnumber_of_parents(): " << self.number_of_parents()
<< "\n\tthis: " << &self
);
}
static void check_child (
unsigned long edge_index,
const node_type& self
)
{
// make sure requires clause is not broken
DLIB_CASSERT(edge_index < self.number_of_children(),
"\tnode_type& directed_graph::node_type::child(edge_index)"
<< "\n\tYou have specified an invalid index"
<< "\n\tedge_index: " << edge_index
<< "\n\tnumber_of_children(): " << self.number_of_children()
<< "\n\tthis: " << &self
);
}
static void check_node (
unsigned long index,
const directed_graph& self
)
{
// make sure requires clause is not broken
DLIB_CASSERT(index < self.number_of_nodes(),
"\tnode_type& directed_graph::node(index)"
<< "\n\tYou have specified an invalid index"
<< "\n\tindex: " << index
<< "\n\tnumber_of_nodes(): " << self.number_of_nodes()
<< "\n\tthis: " << &self
);
}
static void check_has_edge (
unsigned long parent_node_index,
unsigned long child_node_index,
const directed_graph& self
)
{
// make sure requires clause is not broken
DLIB_CASSERT(parent_node_index < self.number_of_nodes() &&
child_node_index < self.number_of_nodes(),
"\tvoid directed_graph::has_edge(parent_node_index, child_node_index)"
<< "\n\tYou have specified an invalid index"
<< "\n\tparent_node_index: " << parent_node_index
<< "\n\tchild_node_index: " << child_node_index
<< "\n\tnumber_of_nodes(): " << self.number_of_nodes()
<< "\n\tthis: " << &self
);
}
static void check_add_edge (
unsigned long parent_node_index,
unsigned long child_node_index,
const directed_graph& self
)
{
DLIB_CASSERT(parent_node_index < self.number_of_nodes() &&
child_node_index < self.number_of_nodes(),
"\tvoid directed_graph::add_edge(parent_node_index, child_node_index)"
<< "\n\tYou have specified an invalid index"
<< "\n\tparent_node_index: " << parent_node_index
<< "\n\tchild_node_index: " << child_node_index
<< "\n\tnumber_of_nodes(): " << self.number_of_nodes()
<< "\n\tthis: " << &self
);
DLIB_CASSERT( self.has_edge(parent_node_index, child_node_index) == false,
"\tvoid directed_graph::add_edge(parent_node_index, child_node_index)"
<< "\n\tYou can't add an edge if it already exists in the graph"
<< "\n\tparent_node_index: " << parent_node_index
<< "\n\tchild_node_index: " << child_node_index
<< "\n\tnumber_of_nodes(): " << self.number_of_nodes()
<< "\n\tthis: " << &self
);
}
static void check_remove_edge (
unsigned long parent_node_index,
unsigned long child_node_index,
const directed_graph& self
)
{
DLIB_CASSERT(parent_node_index < self.number_of_nodes() &&
child_node_index < self.number_of_nodes(),
"\tvoid directed_graph::remove_edge(parent_node_index, child_node_index)"
<< "\n\tYou have specified an invalid index"
<< "\n\tparent_node_index: " << parent_node_index
<< "\n\tchild_node_index: " << child_node_index
<< "\n\tnumber_of_nodes(): " << self.number_of_nodes()
<< "\n\tthis: " << &self
);
DLIB_CASSERT( self.has_edge(parent_node_index, child_node_index) == true,
"\tvoid directed_graph::remove_edge(parent_node_index, child_node_index)"
<< "\n\tYou can't remove an edge if it isn't in the graph"
<< "\n\tparent_node_index: " << parent_node_index
<< "\n\tchild_node_index: " << child_node_index
<< "\n\tnumber_of_nodes(): " << self.number_of_nodes()
<< "\n\tthis: " << &self
);
}
static void check_remove_node (
unsigned long index,
const directed_graph& self
)
{
// make sure requires clause is not broken
DLIB_CASSERT(index < self.number_of_nodes(),
"\tvoid directed_graph::remove_node(index)"
<< "\n\tYou have specified an invalid index"
<< "\n\tindex: " << index
<< "\n\tnumber_of_nodes(): " << self.number_of_nodes()
<< "\n\tthis: " << &self
);
}
};
template <typename node_type, typename directed_graph>
struct directed_graph_checker_helper <node_type, directed_graph, false>
{
static inline void check_parent ( unsigned long edge_index, const node_type& self) { }
static inline void check_child ( unsigned long edge_index, const node_type& self) { }
static inline void check_parent_edge ( unsigned long edge_index, const node_type& self) { }
static inline void check_child_edge ( unsigned long edge_index, const node_type& self) { }
static inline void check_node ( unsigned long index, const directed_graph& self) { }
static inline void check_has_edge ( unsigned long , unsigned long , const directed_graph& ) { }
static inline void check_add_edge ( unsigned long , unsigned long , const directed_graph& ) { }
static inline void check_remove_edge ( unsigned long , unsigned long , const directed_graph& ) { }
static inline void check_remove_node ( unsigned long index, const directed_graph& self) { }
};
// ----------------------------------------------------------------------------------------
template <
typename T,
typename E = char,
typename mem_manager = memory_manager<char>::kernel_1a,
bool is_checked = true
>
class directed_graph_kernel_1 : noncopyable
{
/*!
INITIAL VALUE
- nodes.size() == 0
CONVENTION
- nodes.size() == number_of_nodes()
- for all valid i:
- *nodes[i] == node(i)
- nodes[i]->parents.size() == nodes[i]->number_of_parents(i)
- nodes[i]->children.size() == nodes[i]->number_of_children(i)
- nodes[i]->edge_parents.size() == nodes[i]->number_of_parents(i)
- nodes[i]->edge_children.size() == nodes[i]->number_of_children(i)
- nodes[i]->idx == i == nodes[i]->index()
- for all valid p:
- nodes[i]->parents[p] == pointer to the p'th parent node of i
- *nodes[i]->parents[p] == nodes[i]->parent(p)
- *nodes[i]->edge_parents[p] == nodes[i]->parent_edge(p)
- for all valid c:
- nodes[i]->children[c] == pointer to the c'th child node of i
- *nodes[i]->children[c] == nodes[i]->child(c)
- *nodes[i]->edge_children[c] == nodes[i]->child_edge(c)
!*/
public:
struct node_type;
private:
typedef directed_graph_checker_helper<node_type, directed_graph_kernel_1, is_checked> checker;
public:
typedef T type;
typedef E edge_type;
typedef mem_manager mem_manager_type;
template <typename Tr, typename Er, typename MMr>
struct rebind {
typedef directed_graph_kernel_1<Tr,Er,MMr> other;
};
directed_graph_kernel_1(
) {}
virtual ~directed_graph_kernel_1(
) {}
void clear(
) { nodes.clear(); }
void set_number_of_nodes (
unsigned long new_size
);
unsigned long number_of_nodes (
) const { return nodes.size(); }
node_type& node (
unsigned long index
) { checker::check_node(index,*this); return *nodes[index]; }
const node_type& node (
unsigned long index
) const { checker::check_node(index,*this); return *nodes[index]; }
bool has_edge (
unsigned long parent_node_index,
unsigned long child_node_index
) const;
void add_edge (
unsigned long parent_node_index,
unsigned long child_node_index
);
void remove_edge (
unsigned long parent_node_index,
unsigned long child_node_index
);
unsigned long add_node (
);
void remove_node (
unsigned long index
);
void swap (
directed_graph_kernel_1& item
) { nodes.swap(item.nodes); }
private:
public:
struct node_type
{
T data;
typedef directed_graph_kernel_1 graph_type;
unsigned long index(
) const { return idx; }
unsigned long number_of_parents (
) const { return parents.size(); }
unsigned long number_of_children (
) const { return children.size(); }
const node_type& parent (
unsigned long edge_index
) const { checker::check_parent(edge_index,*this); return *parents[edge_index]; }
node_type& parent (
unsigned long edge_index
) { checker::check_parent(edge_index,*this); return *parents[edge_index]; }
const node_type& child (
unsigned long edge_index
) const { checker::check_child(edge_index,*this); return *children[edge_index]; }
node_type& child (
unsigned long edge_index
) { checker::check_child(edge_index,*this); return *children[edge_index]; }
const E& parent_edge (
unsigned long edge_index
) const { checker::check_parent_edge(edge_index,*this); return *edge_parents[edge_index]; }
E& parent_edge (
unsigned long edge_index
) { checker::check_parent_edge(edge_index,*this); return *edge_parents[edge_index]; }
const E& child_edge (
unsigned long edge_index
) const { checker::check_child_edge(edge_index,*this); return *edge_children[edge_index]; }
E& child_edge (
unsigned long edge_index
) { checker::check_child_edge(edge_index,*this); return *edge_children[edge_index]; }
private:
friend class directed_graph_kernel_1;
typedef std_allocator<node_type*,mem_manager> alloc_type;
typedef std_allocator<shared_ptr<E>,mem_manager> alloc_edge_type;
std::vector<node_type*,alloc_type> parents;
std::vector<node_type*,alloc_type> children;
std::vector<shared_ptr<E>,alloc_edge_type> edge_parents;
std::vector<shared_ptr<E>,alloc_edge_type> edge_children;
unsigned long idx;
};
private:
typedef std_allocator<shared_ptr<node_type>,mem_manager> alloc_type;
typedef std::vector<shared_ptr<node_type>, alloc_type> vector_type;
vector_type nodes;
};
// ----------------------------------------------------------------------------------------
template <
typename T,
typename E,
typename mem_manager,
bool is_checked
>
struct is_directed_graph<directed_graph_kernel_1<T,E,mem_manager, is_checked> >
{
static const bool value = true;
};
// ----------------------------------------------------------------------------------------
template <
typename T,
typename E,
typename mem_manager,
bool is_checked
>
inline void swap (
directed_graph_kernel_1<T,E,mem_manager,is_checked>& a,
directed_graph_kernel_1<T,E,mem_manager,is_checked>& b
) { a.swap(b); }
// ----------------------------------------------------------------------------------------
template <
typename T,
typename E,
typename mem_manager,
bool is_checked
>
void serialize (
const directed_graph_kernel_1<T,E,mem_manager,is_checked>& item,
std::ostream& out
)
{
try
{
serialize(item.number_of_nodes(), out);
// serialize each node
for (unsigned long i = 0; i < item.number_of_nodes(); ++i)
{
serialize(item.node(i).data, out);
// serialize all the child edges
serialize(item.node(i).number_of_children(), out);
for (unsigned long c = 0; c < item.node(i).number_of_children(); ++c)
{
serialize(item.node(i).child(c).index(), out);
serialize(item.node(i).child_edge(c), out);
}
}
}
catch (serialization_error& e)
{
throw serialization_error(e.info + "\n while serializing object of type directed_graph_kernel_1");
}
}
// ----------------------------------------------------------------------------------------
template <
typename T,
typename E,
typename mem_manager,
bool is_checked
>
void deserialize (
directed_graph_kernel_1<T,E,mem_manager,is_checked>& item,
std::istream& in
)
{
try
{
unsigned long size;
deserialize(size, in);
item.clear();
item.set_number_of_nodes(size);
// deserialize each node
for (unsigned long i = 0; i < item.number_of_nodes(); ++i)
{
deserialize(item.node(i).data, in);
unsigned long num_children;
deserialize(num_children, in);
// Add all the edges going to this nodes children nodes
for (unsigned long c = 0; c < num_children; ++c)
{
unsigned long child_index;
deserialize(child_index, in);
item.add_edge(i, child_index);
// find the edge we just added
for (unsigned long j = 0; j < item.node(i).number_of_children(); ++j)
{
if (item.node(i).child(j).index() == child_index)
{
deserialize(item.node(i).child_edge(j), in);
break;
}
}
}
}
}
catch (serialization_error& e)
{
throw serialization_error(e.info + "\n while deserializing object of type directed_graph_kernel_1");
}
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename T,
typename E,
typename mem_manager,
bool is_checked
>
void directed_graph_kernel_1<T,E,mem_manager,is_checked>::
set_number_of_nodes (
unsigned long new_size
)
{
try
{
nodes.resize(new_size);
for (unsigned long i = 0; i < nodes.size(); ++i)
{
nodes[i].reset(new node_type);
nodes[i]->idx = i;
}
}
catch (...)
{
clear();
throw;
}
}
// ----------------------------------------------------------------------------------------
template <
typename T,
typename E,
typename mem_manager,
bool is_checked
>
bool directed_graph_kernel_1<T,E,mem_manager,is_checked>::
has_edge (
unsigned long parent_node_index,
unsigned long child_node_index
) const
{
checker::check_has_edge(parent_node_index, child_node_index, *this);
node_type& n = *nodes[parent_node_index];
// search all the child nodes to see if there is a link to the right node
for (unsigned long i = 0; i < n.children.size(); ++i)
{
if (n.children[i]->idx == child_node_index)
return true;
}
return false;
}
// ----------------------------------------------------------------------------------------
template <
typename T,
typename E,
typename mem_manager,
bool is_checked
>
void directed_graph_kernel_1<T,E,mem_manager,is_checked>::
add_edge (
unsigned long parent_node_index,
unsigned long child_node_index
)
{
checker::check_add_edge(parent_node_index, child_node_index, *this);
try
{
node_type& p = *nodes[parent_node_index];
node_type& c = *nodes[child_node_index];
p.children.push_back(&c);
c.parents.push_back(&p);
p.edge_children.push_back(shared_ptr<E>(new E));
c.edge_parents.push_back(p.edge_children.back());
}
catch (...)
{
clear();
throw;
}
}
// ----------------------------------------------------------------------------------------
template <
typename T,
typename E,
typename mem_manager,
bool is_checked
>
void directed_graph_kernel_1<T,E,mem_manager,is_checked>::
remove_edge (
unsigned long parent_node_index,
unsigned long child_node_index
)
{
checker::check_remove_edge(parent_node_index, child_node_index, *this);
node_type& p = *nodes[parent_node_index];
node_type& c = *nodes[child_node_index];
// remove the record of the link from the parent node
unsigned long pos = find( p.children.begin(),
p.children.end(),
&c) - p.children.begin();
p.children.erase(p.children.begin()+pos);
p.edge_children.erase(p.edge_children.begin()+pos);
// remove the record of the link from the child node
pos = find( c.parents.begin(),
c.parents.end(),
&p) - c.parents.begin();
c.parents.erase(c.parents.begin() + pos);
c.edge_parents.erase(c.edge_parents.begin() + pos);
}
// ----------------------------------------------------------------------------------------
template <
typename T,
typename E,
typename mem_manager,
bool is_checked
>
unsigned long directed_graph_kernel_1<T,E,mem_manager,is_checked>::
add_node (
)
{
try
{
shared_ptr<node_type> n(new node_type);
n->idx = nodes.size();
nodes.push_back(n);
return n->idx;
}
catch (...)
{
clear();
throw;
}
}
// ----------------------------------------------------------------------------------------
template <
typename T,
typename E,
typename mem_manager,
bool is_checked
>
void directed_graph_kernel_1<T,E,mem_manager,is_checked>::
remove_node (
unsigned long index
)
{
checker::check_remove_node(index,*this);
node_type& n = *nodes[index];
// remove all edges pointing to this node from its parents
for (unsigned long i = 0; i < n.parents.size(); ++i)
{
// remove the edge from this specific parent
unsigned long pos = find(n.parents[i]->children.begin(),
n.parents[i]->children.end(),
&n) - n.parents[i]->children.begin();
n.parents[i]->children.erase(n.parents[i]->children.begin() + pos);
n.parents[i]->edge_children.erase(n.parents[i]->edge_children.begin() + pos);
}
// remove all edges pointing to this node from its children
for (unsigned long i = 0; i < n.children.size(); ++i)
{
// remove the edge from this specific child
unsigned long pos = find(n.children[i]->parents.begin(),
n.children[i]->parents.end(),
&n) - n.children[i]->parents.begin();
n.children[i]->parents.erase(n.children[i]->parents.begin() + pos);
n.children[i]->edge_parents.erase(n.children[i]->edge_parents.begin() + pos);
}
// now remove this node by replacing it with the last node in the nodes vector
nodes[index] = nodes[nodes.size()-1];
// update the index for the node we just moved
nodes[index]->idx = index;
// now remove the duplicated node at the end of the vector
nodes.pop_back();
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_DIRECTED_GRAPH_KERNEl_1_
// Copyright (C) 2007 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_DIRECTED_GRAPH_KERNEl_ABSTRACT_
#ifdef DLIB_DIRECTED_GRAPH_KERNEl_ABSTRACT_
#include "../serialize.h"
#include "../memory_manager/memory_manager_kernel_abstract.h"
#include "../noncopyable.h"
namespace dlib
{
template <
typename T,
typename E = char,
typename mem_manager = memory_manager<char>::kernel_1a
>
class directed_graph : noncopyable
{
/*!
REQUIREMENTS ON T
T must be swappable by a global swap() and
T must have a default constructor
REQUIREMENTS ON E
E must be swappable by a global swap() and
E must have a default constructor
REQUIREMENTS ON mem_manager
must be an implementation of memory_manager/memory_manager_kernel_abstract.h or
must be an implementation of memory_manager_global/memory_manager_global_kernel_abstract.h or
must be an implementation of memory_manager_stateless/memory_manager_stateless_kernel_abstract.h
mem_manager::type can be set to anything.
POINTERS AND REFERENCES TO INTERNAL DATA
The only functions that invalidate pointers or references to internal data are
clear(), remove_node(), add_node(), set_number_of_nodes(), and the object's destructor.
INITIAL VALUE
number_of_nodes() == 0
WHAT THIS OBJECT REPRESENTS
This object represents a directed graph which is a set of nodes with directed
edges connecting various nodes.
In this object if there is a directed edge from a node A to a node B then I say
that A is the parent of B and B is the child of A.
!*/
public:
typedef T type;
typedef E edge_type;
typedef mem_manager mem_manager_type;
template <typename Tr, typename Er, typename MMr>
struct rebind {
typedef directed_graph<Tr,Er,MMr> other;
};
directed_graph(
);
/*!
ensures
- #*this is properly initialized
throws
- std::bad_alloc or any exception thrown by T's constructor.
!*/
virtual ~directed_graph(
);
/*!
ensures
- all resources associated with *this has been released
!*/
void clear(
);
/*!
ensures
- #*this has its initial value
throws
- std::bad_alloc or any exception thrown by T's constructor.
If this exception is thrown then *this is unusable
until clear() is called and succeeds
!*/
void set_number_of_nodes (
unsigned long new_size
);
/*!
ensures
- #number_of_nodes() == new_size
- for all i < new_size:
- number_of_parents(i) == 0
- number_of_children(i) == 0
throws
- std::bad_alloc or any exception thrown by T's constructor.
If this exception is thrown then this object reverts back
to its initial state.
!*/
unsigned long number_of_nodes (
) const;
/*!
ensures
- returns the number of nodes in this graph
!*/
struct node_type
{
T data;
typedef directed_graph graph_type;
unsigned long index(
) const;
/*!
ensures
- let G be the graph that contains the node *this
- returns a number N such that G.node(N) == *this
(i.e. returns the index of this node in the graph)
!*/
unsigned long number_of_parents (
) const;
/*!
ensures
- returns the number of parents of this node
!*/
unsigned long number_of_children (
) const;
/*!
ensures
- returns the number of children of this node
!*/
const node_type& parent (
unsigned long edge_index
) const;
/*!
requires
- edge_index < number_of_parents()
ensures
- returns a const reference to the edge_index'th parent of *this
!*/
node_type& parent (
unsigned long edge_index
);
/*!
requires
- edge_index < number_of_parents()
ensures
- returns a non-const reference to the edge_index'th parent of *this
!*/
const node_type& child (
unsigned long edge_index
) const;
/*!
requires
- edge_index < number_of_children()
ensures
- returns a const reference to the edge_index'th child of *this
!*/
node_type& child (
unsigned long edge_index
);
/*!
requires
- edge_index < number_of_children()
ensures
- returns a non-const reference to the edge_index'th child of *this
!*/
const E& parent_edge (
unsigned long edge_index
) const;
/*!
requires
- edge_index < number_of_parents()
ensures
- returns a const reference to the edge_index'th edge data for the
edge connecting to node this->parent(edge_index)
!*/
E& parent_edge (
unsigned long edge_index
);
/*!
requires
- edge_index < number_of_parents()
ensures
- returns a non-const reference to the edge_index'th edge data for the
edge connecting to node this->parent(edge_index)
!*/
const E& child_edge (
unsigned long edge_index
) const;
/*!
requires
- edge_index < number_of_children()
ensures
- returns a const reference to the edge_index'th edge data for the
edge connecting to node this->child(edge_index)
!*/
E& child_edge (
unsigned long edge_index
);
/*!
requires
- edge_index < number_of_children()
ensures
- returns a non-const reference to the edge_index'th edge data for the
edge connecting to node this->child(edge_index)
!*/
};
node_type& node (
unsigned long index
);
/*!
requires
- index < number_of_nodes()
ensures
- returns a non-const reference to the node with the given index
!*/
const node_type& node (
unsigned long index
) const;
/*!
requires
- index < number_of_nodes()
ensures
- returns a const reference to the node with the given index
!*/
bool has_edge (
unsigned long parent_node_index,
unsigned long child_node_index
) const;
/*!
requires
- parent_node_index < number_of_nodes()
- child_node_index < number_of_nodes()
ensures
- if (there is an edge leading from node(parent_node_index) to
node(child_node_index)) then
- returns true
- else
- returns false
!*/
void add_edge (
unsigned long parent_node_index,
unsigned long child_node_index
);
/*!
requires
- parent_node_index < number_of_nodes()
- child_node_index < number_of_nodes()
- has_edge(parent_node_index, child_node_index) == false
ensures
- #has_edge(parent_node_index, child_node_index) == true
throws
- std::bad_alloc
If this exception is thrown then this object reverts back
to its initial state.
!*/
void remove_edge (
unsigned long parent_node_index,
unsigned long child_node_index
);
/*!
requires
- parent_node_index < number_of_nodes()
- child_node_index < number_of_nodes()
- has_edge(parent_node_index, child_node_index) == true
ensures
- #has_edge(parent_node_index, child_node_index) == false
throws
- std::bad_alloc
If this exception is thrown then this object reverts back
to its initial state.
!*/
unsigned long add_node (
);
/*!
ensures
- adds a node with index N == number_of_nodes() such that:
- #node(N).number_of_parents() == 0
- #node(N).number_of_children() == 0
- #number_of_nodes() == number_of_nodes() + 1
- returns N
throws
- std::bad_alloc or any exception thrown by T's constructor.
If this exception is thrown then this object reverts back
to its initial state.
!*/
void remove_node (
unsigned long index
);
/*!
requires
- index < number_of_nodes()
ensures
- removes the node with the given index from the graph.
- removes all edges linking the removed node to the rest
of the graph.
- the remaining node indexes are remapped so that they remain
contiguous. (This means that for all valid N, node(N) doesn't
necessarily reference the same node as #node(N))
- #number_of_nodes() == number_of_nodes() - 1
throws
- std::bad_alloc or any exception thrown by T's constructor.
If this exception is thrown then this object reverts back
to its initial state.
!*/
void swap (
directed_graph& item
);
/*!
ensures
- swaps *this and item
!*/
};
template <
typename T,
typename mem_manager
>
inline void swap (
directed_graph<T,mem_manager>& a,
directed_graph<T,mem_manager>& b
) { a.swap(b); }
/*!
provides a global swap function
!*/
template <
typename T,
typename mem_manager
>
void serialize (
const directed_graph<T,mem_manager>& item,
std::ostream& out
);
/*!
provides deserialization support
!*/
template <
typename T,
typename mem_manager
>
void deserialize (
directed_graph<T,mem_manager>& item,
std::istream& in
);
/*!
provides deserialization support
!*/
}
#endif // DLIB_DIRECTED_GRAPH_KERNEl_ABSTRACT_
#error "Don't put the dlib folder in your include path"
/*
You are getting this error because you have added the dlib folder to your
compiler's include search path.
You should *NOT* add the dlib folder itself to your compiler's include path.
Doing so will cause the build to fail because of name collisions (such as
dlib/string.h and string.h from the standard library). Instead you should
add the folder that contains the dlib folder to your include search path
and then use include statements of the form #include <dlib/queue.h>.
This will ensure that everything builds correctly.
XCode:
The XCode IDE often puts all folders that it knows about into
the compiler search path. So if you are using XCode then don't
drag the dlib folder into the project (or modify your XCode project
settings to not auto-add all folders to the include path.
Instead just make sure that the dlib folder is itself inside
a folder in your include path.
*/
// Boost enable_if library
// Copyright 2003 (C) The Trustees of Indiana University.
// Use, modification, and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Authors: Jaakko Jarvi (jajarvi at osl.iu.edu)
// Jeremiah Willcock (jewillco at osl.iu.edu)
// Andrew Lumsdaine (lums at osl.iu.edu)
#ifndef DLIB_BOOST_UTILITY_ENABLE_IF_HPP
#define DLIB_BOOST_UTILITY_ENABLE_IF_HPP
#ifndef BOOST_UTILITY_ENABLE_IF_HPP
#define BOOST_UTILITY_ENABLE_IF_HPP
// Even the definition of enable_if causes problems on some compilers,
// so it's macroed out for all compilers that do not support SFINAE
#ifndef BOOST_NO_SFINAE
namespace boost
{
template <bool B, class T = void>
struct enable_if_c {
typedef T type;
};
template <class T>
struct enable_if_c<false, T> {};
template <class Cond, class T = void>
struct enable_if : public enable_if_c<Cond::value, T> {};
template <bool B, class T>
struct lazy_enable_if_c {
typedef typename T::type type;
};
template <class T>
struct lazy_enable_if_c<false, T> {};
template <class Cond, class T>
struct lazy_enable_if : public lazy_enable_if_c<Cond::value, T> {};
template <bool B, class T = void>
struct disable_if_c {
typedef T type;
};
template <class T>
struct disable_if_c<true, T> {};
template <class Cond, class T = void>
struct disable_if : public disable_if_c<Cond::value, T> {};
template <bool B, class T>
struct lazy_disable_if_c {
typedef typename T::type type;
};
template <class T>
struct lazy_disable_if_c<true, T> {};
template <class Cond, class T>
struct lazy_disable_if : public lazy_disable_if_c<Cond::value, T> {};
} // namespace boost
#else
namespace boost
{
namespace detail { typedef void enable_if_default_T; }
template <typename T>
struct enable_if_does_not_work_on_this_compiler;
template <bool B, class T = detail::enable_if_default_T>
struct enable_if_c : enable_if_does_not_work_on_this_compiler<T>
{ };
template <bool B, class T = detail::enable_if_default_T>
struct disable_if_c : enable_if_does_not_work_on_this_compiler<T>
{ };
template <bool B, class T = detail::enable_if_default_T>
struct lazy_enable_if_c : enable_if_does_not_work_on_this_compiler<T>
{ };
template <bool B, class T = detail::enable_if_default_T>
struct lazy_disable_if_c : enable_if_does_not_work_on_this_compiler<T>
{ };
template <class Cond, class T = detail::enable_if_default_T>
struct enable_if : enable_if_does_not_work_on_this_compiler<T>
{ };
template <class Cond, class T = detail::enable_if_default_T>
struct disable_if : enable_if_does_not_work_on_this_compiler<T>
{ };
template <class Cond, class T = detail::enable_if_default_T>
struct lazy_enable_if : enable_if_does_not_work_on_this_compiler<T>
{ };
template <class Cond, class T = detail::enable_if_default_T>
struct lazy_disable_if : enable_if_does_not_work_on_this_compiler<T>
{ };
} // namespace boost
#endif // BOOST_NO_SFINAE
#endif // BOOST_UTILITY_ENABLE_IF_HPP
namespace dlib
{
using boost::enable_if_c;
using boost::enable_if_c;
using boost::enable_if;
using boost::lazy_enable_if_c;
using boost::lazy_enable_if_c;
using boost::lazy_enable_if;
using boost::disable_if_c;
using boost::disable_if_c;
using boost::disable_if;
using boost::lazy_disable_if_c;
using boost::lazy_disable_if_c;
using boost::lazy_disable_if;
}
#endif // DLIB_BOOST_UTILITY_ENABLE_IF_HPP
// Copyright (C) 2003 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_ENTROPY_DECODEr_
#define DLIB_ENTROPY_DECODEr_
#include "entropy_decoder/entropy_decoder_kernel_1.h"
#include "entropy_decoder/entropy_decoder_kernel_2.h"
#include "entropy_decoder/entropy_decoder_kernel_c.h"
namespace dlib
{
class entropy_decoder
{
entropy_decoder() {}
public:
//----------- kernels ---------------
// kernel_1a
typedef entropy_decoder_kernel_1
kernel_1a;
typedef entropy_decoder_kernel_c<kernel_1a>
kernel_1a_c;
// kernel_2a
typedef entropy_decoder_kernel_2
kernel_2a;
typedef entropy_decoder_kernel_c<kernel_2a>
kernel_2a_c;
};
}
#endif // DLIB_ENTROPY_DECODEr_
// Copyright (C) 2003 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_ENTROPY_DECODER_KERNEL_1_CPp_
#define DLIB_ENTROPY_DECODER_KERNEL_1_CPp_
#include "entropy_decoder_kernel_1.h"
#include <iostream>
#include <streambuf>
#include <sstream>
#include "../assert.h"
namespace dlib
{
// ----------------------------------------------------------------------------------------
entropy_decoder_kernel_1::
entropy_decoder_kernel_1(
) :
initial_low(0x00000001),
initial_high(0xffffffff),
in(0),
low(initial_low),
high(initial_high),
buf(0),
buf_used(0),
target(0x00000000),
r(0)
{
}
// ----------------------------------------------------------------------------------------
entropy_decoder_kernel_1::
~entropy_decoder_kernel_1 (
)
{
}
// ----------------------------------------------------------------------------------------
void entropy_decoder_kernel_1::
clear(
)
{
in = 0;
buf_used = 0;
buf = 0;
r = 0;
low = initial_low;
high = initial_high;
target = 0x00000000;
}
// ----------------------------------------------------------------------------------------
void entropy_decoder_kernel_1::
set_stream (
std::istream& in_
)
{
buf_used = 0;
buf = 0;
r = 0;
low = initial_low;
high = initial_high;
target = 0x00000000;
in = &in_;
streambuf = in_.rdbuf();
unsigned char ch;
streambuf->sgetn((char*)&ch,1);
target = ch;
target <<= 8;
if (streambuf->sgetn((char*)&ch,1))
target += ch;
target <<= 8;
if (streambuf->sgetn((char*)&ch,1))
target += ch;
target <<= 8;
if (streambuf->sgetn((char*)&ch,1))
target += ch;
}
// ----------------------------------------------------------------------------------------
bool entropy_decoder_kernel_1::
stream_is_set (
) const
{
if (in != 0)
return true;
else
return false;
}
// ----------------------------------------------------------------------------------------
std::istream& entropy_decoder_kernel_1::
get_stream (
) const
{
return *in;
}
// ----------------------------------------------------------------------------------------
void entropy_decoder_kernel_1::
decode (
uint32 low_count,
uint32 high_count
)
{
// 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;
r = 0;
while (true)
{
// if the highest order bit in high and low is the same
if ( low >= 0x80000000 || high < 0x80000000)
{
// make sure buf isn't empty
if (buf_used == 0)
{
buf_used = 8;
if (streambuf->sgetn(reinterpret_cast<char*>(&buf),1)==0)
{
// if there isn't anything else in the streambuffer then just
// make buf zero.
buf = 0;
}
}
// we will be taking one bit from buf to replace the one we threw away
--buf_used;
// roll off the bit in target
target <<= 1;
// roll off the bit
high <<= 1;
low <<= 1;
high |= 1; // note that it is ok to add one 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;
// take a bit from buf to fill in the one we threw away
target += (buf>>buf_used)&0x01;
}
// if the distance between high and low is small and there aren't
// any bits we can roll off then round low up or high down.
else if (high-low < 0x10000)
{
if (high == 0x80000000)
high = 0x7fffffff;
else
low = 0x80000000;
}
else
{
break;
}
} // while (true)
}
// ----------------------------------------------------------------------------------------
bool entropy_decoder_kernel_1::
get_target_called (
) const
{
return (r != 0);
}
// ----------------------------------------------------------------------------------------
uint32 entropy_decoder_kernel_1::
get_target (
uint32 total
)
{
// note that we must add one because of the convention that
// high == the real upper range minus 1
r = (high-low+1)/total;
uint32 temp = (target-low)/r;
if (temp < total)
return temp;
else
return total-1;
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_ENTROPY_DECODER_KERNEL_1_CPp_
// Copyright (C) 2003 Davis E. King (davisking@users.sourceforge.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_
// Copyright (C) 2004 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_ENTROPY_DECODER_KERNEL_2_CPp_
#define DLIB_ENTROPY_DECODER_KERNEL_2_CPp_
#include "entropy_decoder_kernel_2.h"
#include <iostream>
#include <streambuf>
#include <sstream>
#include "../assert.h"
namespace dlib
{
// ----------------------------------------------------------------------------------------
entropy_decoder_kernel_2::
entropy_decoder_kernel_2(
) :
initial_low(0x00000001),
initial_high(0xffffffff),
in(0),
low(initial_low),
high(initial_high),
target(0x00000000),
r(0)
{
}
// ----------------------------------------------------------------------------------------
entropy_decoder_kernel_2::
~entropy_decoder_kernel_2 (
)
{
}
// ----------------------------------------------------------------------------------------
void entropy_decoder_kernel_2::
clear(
)
{
in = 0;
r = 0;
low = initial_low;
high = initial_high;
target = 0x00000000;
}
// ----------------------------------------------------------------------------------------
void entropy_decoder_kernel_2::
set_stream (
std::istream& in_
)
{
r = 0;
low = initial_low;
high = initial_high;
target = 0x00000000;
in = &in_;
streambuf = in_.rdbuf();
unsigned char ch;
streambuf->sgetn((char*)&ch,1);
target = ch;
target <<= 8;
if (streambuf->sgetn((char*)&ch,1))
target += ch;
target <<= 8;
if (streambuf->sgetn((char*)&ch,1))
target += ch;
target <<= 8;
if (streambuf->sgetn((char*)&ch,1))
target += ch;
}
// ----------------------------------------------------------------------------------------
bool entropy_decoder_kernel_2::
stream_is_set (
) const
{
if (in != 0)
return true;
else
return false;
}
// ----------------------------------------------------------------------------------------
std::istream& entropy_decoder_kernel_2::
get_stream (
) const
{
return *in;
}
// ----------------------------------------------------------------------------------------
void entropy_decoder_kernel_2::
decode (
uint32 low_count,
uint32 high_count
)
{
// 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;
r = 0;
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
{
unsigned char buf;
if (streambuf->sgetn(reinterpret_cast<char*>(&buf),1)==0)
{
// if there isn't anything else in the streambuffer then just
// make buf zero.
buf = 0;
}
// also roll off the bits in target
target <<= 8;
// roll off the bits
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;
// put the new bits into target
target |= static_cast<uint32>(buf);
}
} // while (true)
}
// ----------------------------------------------------------------------------------------
bool entropy_decoder_kernel_2::
get_target_called (
) const
{
return (r != 0);
}
// ----------------------------------------------------------------------------------------
uint32 entropy_decoder_kernel_2::
get_target (
uint32 total
)
{
// note that we must add one because of the convention that
// high == the real upper range minus 1
r = (high-low+1)/total;
uint32 temp = (target-low)/r;
if (temp < total)
return temp;
else
return total-1;
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_ENTROPY_DECODER_KERNEL_2_CPp_
// Copyright (C) 2004 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_ENTROPY_DECODER_KERNEl_2_
#define DLIB_ENTROPY_DECODER_KERNEl_2_
#include "../algs.h"
#include "entropy_decoder_kernel_abstract.h"
#include <iosfwd>
#include "../uintn.h"
namespace dlib
{
class entropy_decoder_kernel_2
{
/*!
GENERAL NOTES
this decoder is implemented using "range" coding
INITIAL VALUE
in == 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()
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_2 (
);
virtual ~entropy_decoder_kernel_2 (
);
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_2(entropy_decoder_kernel_2&); // copy constructor
entropy_decoder_kernel_2& operator=(entropy_decoder_kernel_2&); // assignment operator
// data members
const uint32 initial_low;
const uint32 initial_high;
std::istream* in;
uint32 low;
uint32 high;
uint32 target;
uint32 r;
std::streambuf* streambuf;
};
}
#ifdef NO_MAKEFILE
#include "entropy_decoder_kernel_2.cpp"
#endif
#endif // DLIB_ENTROPY_DECODER_KERNEl_2_
// Copyright (C) 2003 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_ENTROPY_DECODER_KERNEl_ABSTRACT_
#ifdef DLIB_ENTROPY_DECODER_KERNEl_ABSTRACT_
#include "../algs.h"
#include <iosfwd>
#include "../uintn.h"
namespace dlib
{
class entropy_decoder
{
/*!
INITIAL VALUE
stream_is_set() == false
get_target_called() == false
WHAT THIS OBJECT REPRESENTS
This object represents an entropy decoder (could be implemented as an
arithmetic decoder 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.
WHERE IS EOF?
It is important to note that this object will not give any indication
that is has hit the end of the input stream when it occurs. It is
up to you to use some kind of coding scheme to detect this in the
compressed data stream.
Another important thing to know is that decode() must be called
exactly the same number of times as encode() and with the same values
supplied for TOTAL, high_count, and low_count. Doing this ensures
that the decoder consumes exactly all the bytes from the input
stream that were written by the entropy_encoder.
NOTATION:
At any moment each symbol has a certain probability of appearing in
the input stream. These probabilities may change as each symbol is
decoded and the probability model is updated accordingly.
- Before considering current symbol:
let P(i) be a function which gives the probability of seeing the ith
symbol of an N symbol alphabet. Note that P(i) refers to the probability
of seeing the ith symbol WITHOUT considering the symbol currently given
by get_target(TOTAL). ( 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
- After considering current symbol:
let #P(i) be a function which gives the probability of seeing the ith
symbol after we have updated our probability model to take the symbol
given by get_target(TOTAL) into account.
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.
!*/
public:
entropy_decoder (
);
/*!
ensures
- #*this is properly initialized
throws
- std::bad_alloc
!*/
virtual ~entropy_decoder (
);
/*!
ensures
- all memory associated with *this has been released
!*/
void clear(
);
/*!
ensures
- #*this has its initial value
- if (stream_is_set())
- clears any state accumulated in *this from decoding data from
the stream get_stream()
throws
- any exception
if this exception is thrown then #*this is unusable
until clear() is called and succeeds
!*/
void set_stream (
std::istream& in
);
/*!
ensures
- #*this will read data from in and decode it
- #stream_is_set() == true
- #get_target() == a number representing the first symbol from in
- #get_target_called() == false
- if (stream_is_set())
- clears any state accumulated in *this from decoding data from
the stream get_stream()
throws
- any 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::istream& get_stream (
) const;
/*!
requires
- stream_is_set() == true
ensures
- returns a reference to the istream object that *this is reading
encoded data from
!*/
void decode (
uint32 low_count,
uint32 high_count
);
/*!
requires
- get_target_called() == true
- stream_is_set() == true
- low_count == LOW_COUNT(S) where S is the symbol represented
by get_target(TOTAL)
- high_count == HIGH_COUNT(S) where S is the symbol represented
by get_target(TOTAL)
- low_count <= get_target(TOTAL) < high_count <= TOTAL
ensures
- #get_target(#TOTAL) == a number which represents the next symbol
- #get_target_called() == false
throws
- any exception
if this exception is thrown then #*this is unusable
until clear() is called and succeeds
!*/
bool get_target_called (
) const;
/*!
ensures
- returns true if get_target() has been called and since then decode()
and set_stream() have not been called
- returns false otherwise
!*/
uint32 get_target (
uint32 total
);
/*!
requires
- 0 < total < 65536 (2^16)
- total == TOTAL
- stream_is_set() == true
ensures
- in the next call to decode() the value of TOTAL will be
considered to be total
- #get_target_called() == true
- returns a number N such that:
- N is in the range 0 to total - 1
- N represents a symbol S where
LOW_COUNT(S) <= N < HIGH_COUNT(S)
throws
- any exception
if this exception is thrown then #*this is unusable
until clear() is called and succeeds
!*/
private:
// restricted functions
entropy_decoder(entropy_decoder&); // copy constructor
entropy_decoder& operator=(entropy_decoder&); // assignment operator
};
}
#endif // DLIB_ENTROPY_DECODER_KERNEl_ABSTRACT_
// Copyright (C) 2003 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_ENTROPY_DECODER_KERNEl_C_
#define DLIB_ENTROPY_DECODER_KERNEl_C_
#include "entropy_decoder_kernel_abstract.h"
#include "../algs.h"
#include "../assert.h"
#include <iostream>
namespace dlib
{
template <
typename decoder
>
class entropy_decoder_kernel_c : public decoder
{
public:
std::istream& get_stream (
) const;
void decode (
uint32 low_count,
uint32 high_count
);
uint32 get_target (
uint32 total
);
private:
uint32 _get_target;
uint32 TOTAL;
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename decoder
>
std::istream& entropy_decoder_kernel_c<decoder>::
get_stream (
) const
{
// make sure requires clause is not broken
DLIB_CASSERT( this->stream_is_set() == true,
"\tstd::istream& entropy_decoder::get_stream()"
<< "\n\tyou must set a stream for this object before you can get it"
<< "\n\tthis: " << this
);
// call the real function
return decoder::get_stream();
}
// ----------------------------------------------------------------------------------------
template <
typename decoder
>
void entropy_decoder_kernel_c<decoder>::
decode (
uint32 low_count,
uint32 high_count
)
{
// make sure requires clause is not broken
DLIB_CASSERT( (low_count <= _get_target) && (_get_target < high_count) &&
(high_count <= TOTAL) &&
(this->stream_is_set() == true) && (this->get_target_called() == true),
"\tvoid entropy_decoder::decode()"
<< "\n\tRefer to the ensures clause for this function for further information."
<< "\n\tNote that _get_target refers to get_target(TOTAL)"
<< "\n\tthis: " << this
<< "\n\tlow_count: " << low_count
<< "\n\thigh_count: " << high_count
<< "\n\tTOTAL: " << TOTAL
<< "\n\tget_target(TOTAL): " << _get_target
<< "\n\tis_stream_set(): " << (this->stream_is_set() ? "true" : "false" )
<< "\n\tget_target_called(): " << (this->get_target_called() ? "true" : "false" )
);
// call the real function
decoder::decode(low_count,high_count);
}
// ----------------------------------------------------------------------------------------
template <
typename decoder
>
uint32 entropy_decoder_kernel_c<decoder>::
get_target (
uint32 total
)
{
// make sure requires clause is not broken
DLIB_CASSERT( (total > 0) && (total < 65536) && (this->stream_is_set() == true),
"\tvoid entropy_decoder::get_target()"
<< "\n\tyou must set a stream for this object before you can get the "
<< "\n\rnext target."
<< "\n\tthis: " << this
<< "\n\ttotal: " << total
);
// call the real function
_get_target = decoder::get_target(total);
TOTAL = total;
return _get_target;
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_ENTROPY_ENCODER_KERNEl_C_
// Copyright (C) 2004 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_ENTROPY_DECODER_MODEl_
#define DLIB_ENTROPY_DECODER_MODEl_
#include "entropy_decoder_model/entropy_decoder_model_kernel_1.h"
#include "entropy_decoder_model/entropy_decoder_model_kernel_2.h"
#include "entropy_decoder_model/entropy_decoder_model_kernel_3.h"
#include "entropy_decoder_model/entropy_decoder_model_kernel_4.h"
#include "entropy_decoder_model/entropy_decoder_model_kernel_5.h"
#include "entropy_decoder_model/entropy_decoder_model_kernel_6.h"
#include "conditioning_class.h"
#include "memory_manager.h"
namespace dlib
{
template <
unsigned long alphabet_size,
typename entropy_decoder
>
class entropy_decoder_model
{
entropy_decoder_model() {}
typedef typename conditioning_class<alphabet_size+1>::kernel_1a cc1;
typedef typename conditioning_class<alphabet_size+1>::kernel_2a cc2;
typedef typename conditioning_class<alphabet_size+1>::kernel_3a cc3;
typedef typename conditioning_class<alphabet_size+1>::kernel_4a cc4a;
typedef typename conditioning_class<alphabet_size+1>::kernel_4b cc4b;
typedef typename conditioning_class<alphabet_size+1>::kernel_4c cc4c;
typedef typename conditioning_class<alphabet_size+1>::kernel_4d cc4d;
public:
//----------- kernels ---------------
// kernel_1
typedef entropy_decoder_model_kernel_1<alphabet_size,entropy_decoder,cc1>
kernel_1a;
typedef entropy_decoder_model_kernel_1<alphabet_size,entropy_decoder,cc2>
kernel_1b;
typedef entropy_decoder_model_kernel_1<alphabet_size,entropy_decoder,cc3>
kernel_1c;
// --------------------
// kernel_2
typedef entropy_decoder_model_kernel_2<alphabet_size,entropy_decoder,cc1,cc1>
kernel_2a;
typedef entropy_decoder_model_kernel_2<alphabet_size,entropy_decoder,cc2,cc2>
kernel_2b;
typedef entropy_decoder_model_kernel_2<alphabet_size,entropy_decoder,cc3,cc3>
kernel_2c;
typedef entropy_decoder_model_kernel_2<alphabet_size,entropy_decoder,cc2,cc4b>
kernel_2d;
// --------------------
// kernel_3
typedef entropy_decoder_model_kernel_3<alphabet_size,entropy_decoder,cc1,cc4b>
kernel_3a;
typedef entropy_decoder_model_kernel_3<alphabet_size,entropy_decoder,cc2,cc4b>
kernel_3b;
typedef entropy_decoder_model_kernel_3<alphabet_size,entropy_decoder,cc3,cc4b>
kernel_3c;
// --------------------
// kernel_4
typedef entropy_decoder_model_kernel_4<alphabet_size,entropy_decoder,200000,4>
kernel_4a;
typedef entropy_decoder_model_kernel_4<alphabet_size,entropy_decoder,1000000,5>
kernel_4b;
// --------------------
// kernel_5
typedef entropy_decoder_model_kernel_5<alphabet_size,entropy_decoder,200000,4>
kernel_5a;
typedef entropy_decoder_model_kernel_5<alphabet_size,entropy_decoder,1000000,5>
kernel_5b;
typedef entropy_decoder_model_kernel_5<alphabet_size,entropy_decoder,2500000,7>
kernel_5c;
// --------------------
// kernel_6
typedef entropy_decoder_model_kernel_6<alphabet_size,entropy_decoder>
kernel_6a;
};
}
#endif // DLIB_ENTROPY_DECODER_MODEl_
// Copyright (C) 2004 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_ENTROPY_DECODER_MODEL_KERNEl_1_
#define DLIB_ENTROPY_DECODER_MODEL_KERNEl_1_
#include "../algs.h"
#include "entropy_decoder_model_kernel_abstract.h"
#include "../assert.h"
namespace dlib
{
template <
unsigned long alphabet_size,
typename entropy_decoder,
typename cc
>
class entropy_decoder_model_kernel_1
{
/*!
REQUIREMENTS ON cc
cc is an implementation of conditioning_class/conditioning_class_kernel_abstract.h
cc::get_alphabet_size() == alphabet_size+1
INITIAL VALUE
Initially this object's finite context model is empty
CONVENTION
&get_entropy_decoder() == coder
&order_0.get_global_state() == &gs
This is an order-0 model. The last symbol in the order-0 context is
an escape into the order minus 1 context.
!*/
public:
typedef entropy_decoder entropy_decoder_type;
entropy_decoder_model_kernel_1 (
entropy_decoder& coder
);
virtual ~entropy_decoder_model_kernel_1 (
);
inline void clear(
);
inline void decode (
unsigned long& symbol
);
entropy_decoder& get_entropy_decoder (
) { return coder; }
static unsigned long get_alphabet_size (
) { return alphabet_size; }
private:
entropy_decoder& coder;
typename cc::global_state_type gs;
cc order_0;
// restricted functions
entropy_decoder_model_kernel_1(entropy_decoder_model_kernel_1<alphabet_size,entropy_decoder,cc>&); // copy constructor
entropy_decoder_model_kernel_1<alphabet_size,entropy_decoder,cc>& operator=(entropy_decoder_model_kernel_1<alphabet_size,entropy_decoder,cc>&); // assignment operator
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
unsigned long alphabet_size,
typename entropy_decoder,
typename cc
>
entropy_decoder_model_kernel_1<alphabet_size,entropy_decoder,cc>::
entropy_decoder_model_kernel_1 (
entropy_decoder& coder_
) :
coder(coder_),
order_0(gs)
{
COMPILE_TIME_ASSERT( 1 < alphabet_size && alphabet_size < 65535 );
}
// ----------------------------------------------------------------------------------------
template <
unsigned long alphabet_size,
typename entropy_decoder,
typename cc
>
entropy_decoder_model_kernel_1<alphabet_size,entropy_decoder,cc>::
~entropy_decoder_model_kernel_1 (
)
{
}
// ----------------------------------------------------------------------------------------
template <
unsigned long alphabet_size,
typename entropy_decoder,
typename cc
>
void entropy_decoder_model_kernel_1<alphabet_size,entropy_decoder,cc>::
clear(
)
{
order_0.clear();
}
// ----------------------------------------------------------------------------------------
template <
unsigned long alphabet_size,
typename entropy_decoder,
typename cc
>
void entropy_decoder_model_kernel_1<alphabet_size,entropy_decoder,cc>::
decode (
unsigned long& symbol
)
{
unsigned long current_symbol, low_count, high_count, target;
// look in the order-0 context
target = coder.get_target(order_0.get_total());
order_0.get_symbol(target,current_symbol,low_count,high_count);
// have coder decode the next symbol
coder.decode(low_count,high_count);
// if current_symbol is not an escape from the order-0 context
if (current_symbol != alphabet_size)
{
// update the count for this symbol
order_0.increment_count(current_symbol,2);
symbol = current_symbol;
return;
}
// update the count for the escape symbol
order_0.increment_count(alphabet_size);
// go into the order minus one context
target = coder.get_target(alphabet_size);
coder.decode(target,target+1);
// update the count for this symbol in the order-0 context
order_0.increment_count(target,2);
symbol = target;
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_ENTROPY_DECODER_MODEL_KERNEl_1_
// Copyright (C) 2004 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_ENTROPY_DECODER_MODEL_KERNEl_2_
#define DLIB_ENTROPY_DECODER_MODEL_KERNEl_2_
#include "../algs.h"
#include "entropy_decoder_model_kernel_abstract.h"
#include "../assert.h"
namespace dlib
{
template <
unsigned long alphabet_size,
typename entropy_decoder,
typename cc,
typename ccbig
>
class entropy_decoder_model_kernel_2
{
/*!
REQUIREMENTS ON cc
cc is an implementation of conditioning_class/conditioning_class_kernel_abstract.h
cc::get_alphabet_size() == alphabet_size+1
this will be used for the order-0 context
REQUIREMENTS ON ccbig
ccbig is an implementation of conditioning_class/conditioning_class_kernel_abstract.h
ccbig::get_alphabet_size() == alphabet_size+1
this will be used for the order-1 context
INITIAL VALUE
Initially this object's finite context model is empty
previous_symbol == 0
CONVENTION
&get_entropy_decoder() == coder
&order_0.get_global_state() == &gs
&order_1[i]->get_global_state() == &gsbig
This is an order-1-0 model. The last symbol in the order-0 and order-1
context is an escape into the lower context.
previous_symbol == the last symbol seen
!*/
public:
typedef entropy_decoder entropy_decoder_type;
entropy_decoder_model_kernel_2 (
entropy_decoder& coder
);
virtual ~entropy_decoder_model_kernel_2 (
);
inline void clear(
);
inline void decode (
unsigned long& symbol
);
entropy_decoder& get_entropy_decoder (
) { return coder; }
static unsigned long get_alphabet_size (
) { return alphabet_size; }
private:
entropy_decoder& coder;
typename cc::global_state_type gs;
typename ccbig::global_state_type gsbig;
cc order_0;
ccbig* order_1[alphabet_size];
unsigned long previous_symbol;
// restricted functions
entropy_decoder_model_kernel_2(entropy_decoder_model_kernel_2<alphabet_size,entropy_decoder,cc,ccbig>&); // copy constructor
entropy_decoder_model_kernel_2<alphabet_size,entropy_decoder,cc,ccbig>& operator=(entropy_decoder_model_kernel_2<alphabet_size,entropy_decoder,cc,ccbig>&); // assignment operator
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
unsigned long alphabet_size,
typename entropy_decoder,
typename cc,
typename ccbig
>
entropy_decoder_model_kernel_2<alphabet_size,entropy_decoder,cc,ccbig>::
entropy_decoder_model_kernel_2 (
entropy_decoder& coder_
) :
coder(coder_),
order_0(gs),
previous_symbol(0)
{
COMPILE_TIME_ASSERT( 1 < alphabet_size && alphabet_size < 65535);
unsigned long i;
try
{
for (i = 0; i < alphabet_size; ++i)
{
order_1[i] = new ccbig(gsbig);
}
}
catch (...)
{
for (unsigned long j = 0; j < i; ++j)
{
delete order_1[j];
}
throw;
}
}
// ----------------------------------------------------------------------------------------
template <
unsigned long alphabet_size,
typename entropy_decoder,
typename cc,
typename ccbig
>
entropy_decoder_model_kernel_2<alphabet_size,entropy_decoder,cc,ccbig>::
~entropy_decoder_model_kernel_2 (
)
{
for (unsigned long i = 0; i < alphabet_size; ++i)
{
delete order_1[i];
}
}
// ----------------------------------------------------------------------------------------
template <
unsigned long alphabet_size,
typename entropy_decoder,
typename cc,
typename ccbig
>
void entropy_decoder_model_kernel_2<alphabet_size,entropy_decoder,cc,ccbig>::
clear(
)
{
previous_symbol = 0;
order_0.clear();
for (unsigned long i = 0; i < alphabet_size; ++i)
{
order_1[i]->clear();
}
}
// ----------------------------------------------------------------------------------------
template <
unsigned long alphabet_size,
typename entropy_decoder,
typename cc,
typename ccbig
>
void entropy_decoder_model_kernel_2<alphabet_size,entropy_decoder,cc,ccbig>::
decode (
unsigned long& symbol
)
{
unsigned long current_symbol, low_count, high_count, target;
// look in the order-1 context
target = coder.get_target(order_1[previous_symbol]->get_total());
order_1[previous_symbol]->get_symbol(target,current_symbol,low_count,high_count);
// have the coder decode the next symbol
coder.decode(low_count,high_count);
// if the current_symbol is not an escape from the order-1 context
if (current_symbol != alphabet_size)
{
symbol = current_symbol;
order_1[previous_symbol]->increment_count(current_symbol,2);
previous_symbol = current_symbol;
return;
}
// since this is an escape to order-0 we should increment
// the escape symbol
order_1[previous_symbol]->increment_count(alphabet_size);
// look in the order-0 context
target = coder.get_target(order_0.get_total());
order_0.get_symbol(target,current_symbol,low_count,high_count);
// have coder decode the next symbol
coder.decode(low_count,high_count);
// if current_symbol is not an escape from the order-0 context
if (current_symbol != alphabet_size)
{
// update the count for this symbol
order_1[previous_symbol]->increment_count(current_symbol,2);
order_0.increment_count(current_symbol,2);
symbol = current_symbol;
previous_symbol = current_symbol;
return;
}
// update the count for the escape symbol
order_0.increment_count(current_symbol);
// go into the order minus one context
target = coder.get_target(alphabet_size);
coder.decode(target,target+1);
// update the count for this symbol
order_1[previous_symbol]->increment_count(target,2);
order_0.increment_count(target,2);
symbol = target;
previous_symbol = target;
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_ENTROPY_DECODER_MODEL_KERNEl_2_
// Copyright (C) 2004 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_ENTROPY_DECODER_MODEL_KERNEl_3_
#define DLIB_ENTROPY_DECODER_MODEL_KERNEl_3_
#include "../algs.h"
#include "entropy_decoder_model_kernel_abstract.h"
#include "../assert.h"
namespace dlib
{
template <
unsigned long alphabet_size,
typename entropy_decoder,
typename cc,
typename cc_high
>
class entropy_decoder_model_kernel_3
{
/*!
REQUIREMENTS ON cc
cc is an implementation of conditioning_class/conditioning_class_kernel_abstract.h
cc::get_alphabet_size() == alphabet_size+1
REQUIREMENTS ON cc_high
cc_high is an implementation of conditioning_class/conditioning_class_kernel_abstract.h
cc_high::get_alphabet_size() == alphabet_size+1
INITIAL VALUE
- Initially this object's finite context model is empty
- previous_symbol == 0
- previous_symbol2 == 0
- order_1 == pointer to an array of alphabet_size elements
- order_2 == pointer to an array of alphabet_size*alphabet_size elements
- for all values of i: order_2[i] == 0
CONVENTION
&get_entropy_encoder() == coder
&order_0.get_global_state() == &gs
&order_1[i]->get_global_state() == &gs
if (order_2[i] != 0) then
&order_2[i]->get_global_state() == &gs_high
This is an order-2-1-0 model. The last symbol in the order-2, order-1 and
order-0 contexts is an escape into the lower context.
previous_symbol == the last symbol seen
previous_symbol2 == the symbol we saw before previous_symbol
!*/
public:
typedef entropy_decoder entropy_decoder_type;
entropy_decoder_model_kernel_3 (
entropy_decoder& coder
);
virtual ~entropy_decoder_model_kernel_3 (
);
inline void clear(
);
inline void decode (
unsigned long& symbol
);
entropy_decoder& get_entropy_decoder (
) { return coder; }
static unsigned long get_alphabet_size (
) { return alphabet_size; }
private:
entropy_decoder& coder;
typename cc::global_state_type gs;
typename cc_high::global_state_type gs_high;
cc order_0;
cc** order_1;
unsigned long previous_symbol;
cc_high** order_2;
unsigned long previous_symbol2;
// restricted functions
entropy_decoder_model_kernel_3(entropy_decoder_model_kernel_3&); // copy constructor
entropy_decoder_model_kernel_3& operator=(entropy_decoder_model_kernel_3&); // assignment operator
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
unsigned long alphabet_size,
typename entropy_decoder,
typename cc,
typename cc_high
>
entropy_decoder_model_kernel_3<alphabet_size,entropy_decoder,cc,cc_high>::
entropy_decoder_model_kernel_3 (
entropy_decoder& coder_
) :
coder(coder_),
order_0(gs),
order_1(0),
previous_symbol(0),
order_2(0),
previous_symbol2(0)
{
COMPILE_TIME_ASSERT( 1 < alphabet_size && alphabet_size < 65535);
try
{
order_1 = new cc*[alphabet_size];
order_2 = new cc_high*[alphabet_size*alphabet_size];
}
catch (...)
{
if (order_1) delete [] order_1;
if (order_2) delete [] order_2;
throw;
}
unsigned long i;
for (i = 0; i < alphabet_size*alphabet_size; ++i)
{
order_2[i] = 0;
}
try
{
for (i = 0; i < alphabet_size; ++i)
{
order_1[i] = new cc(gs);
}
}
catch (...)
{
for (unsigned long j = 0; j < i; ++j)
{
delete order_1[j];
}
throw;
}
}
// ----------------------------------------------------------------------------------------
template <
unsigned long alphabet_size,
typename entropy_decoder,
typename cc,
typename cc_high
>
entropy_decoder_model_kernel_3<alphabet_size,entropy_decoder,cc,cc_high>::
~entropy_decoder_model_kernel_3 (
)
{
for (unsigned long i = 0; i < alphabet_size; ++i)
{
delete order_1[i];
}
for (unsigned long i = 0; i < alphabet_size*alphabet_size; ++i)
{
if (order_2[i] != 0)
delete order_2[i];
}
delete [] order_1;
delete [] order_2;
}
// ----------------------------------------------------------------------------------------
template <
unsigned long alphabet_size,
typename entropy_decoder,
typename cc,
typename cc_high
>
void entropy_decoder_model_kernel_3<alphabet_size,entropy_decoder,cc,cc_high>::
clear(
)
{
previous_symbol = 0;
previous_symbol2 = 0;
order_0.clear();
for (unsigned long i = 0; i < alphabet_size; ++i)
{
order_1[i]->clear();
}
for (unsigned long i = 0; i < alphabet_size*alphabet_size; ++i)
{
if (order_2[i] != 0)
{
delete order_2[i];
order_2[i] = 0;
}
}
}
// ----------------------------------------------------------------------------------------
template <
unsigned long alphabet_size,
typename entropy_decoder,
typename cc,
typename cc_high
>
void entropy_decoder_model_kernel_3<alphabet_size,entropy_decoder,cc,cc_high>::
decode (
unsigned long& symbol
)
{
unsigned long current_symbol, low_count, high_count, target;
// look in the order-2 context
unsigned long temp = previous_symbol + (previous_symbol2 * alphabet_size);
if (order_2[temp] != 0)
{
target = coder.get_target(order_2[temp]->get_total());
order_2[temp]->get_symbol(target,current_symbol,low_count,high_count);
// have the coder decode the next symbol
coder.decode(low_count,high_count);
// if the current_symbol is not an escape from the order-2 context
if (current_symbol != alphabet_size)
{
symbol = current_symbol;
order_2[temp]->increment_count(current_symbol,2);
previous_symbol2 = previous_symbol;
previous_symbol = current_symbol;
return;
}
// since this is an escape to order-1 we should increment
// the escape symbol
order_2[temp]->increment_count(alphabet_size);
}
else
{
order_2[temp] = new cc_high(gs_high);
}
// look in the order-1 context
target = coder.get_target(order_1[previous_symbol]->get_total());
order_1[previous_symbol]->get_symbol(target,current_symbol,low_count,high_count);
// have the coder decode the next symbol
coder.decode(low_count,high_count);
// if the current_symbol is not an escape from the order-1 context
if (current_symbol != alphabet_size)
{
symbol = current_symbol;
order_2[temp]->increment_count(current_symbol,2);
order_1[previous_symbol]->increment_count(current_symbol,2);
previous_symbol2 = previous_symbol;
previous_symbol = current_symbol;
return;
}
// since this is an escape to order-0 we should increment
// the escape symbol
order_1[previous_symbol]->increment_count(alphabet_size);
// look in the order-0 context
target = coder.get_target(order_0.get_total());
order_0.get_symbol(target,current_symbol,low_count,high_count);
// have coder decode the next symbol
coder.decode(low_count,high_count);
// if current_symbol is not an escape from the order-0 context
if (current_symbol != alphabet_size)
{
// update the count for this symbol
order_2[temp]->increment_count(current_symbol,2);
order_1[previous_symbol]->increment_count(current_symbol,2);
order_0.increment_count(current_symbol,2);
symbol = current_symbol;
previous_symbol2 = previous_symbol;
previous_symbol = current_symbol;
return;
}
// update the count for the escape symbol
order_0.increment_count(current_symbol);
// go into the order minus one context
target = coder.get_target(alphabet_size);
coder.decode(target,target+1);
// update the count for this symbol
order_2[temp]->increment_count(target,2);
order_1[previous_symbol]->increment_count(target,2);
order_0.increment_count(target,2);
symbol = target;
previous_symbol2 = previous_symbol;
previous_symbol = target;
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_ENTROPY_DECODER_MODEL_KERNEl_3_
// Copyright (C) 2005 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_ENTROPY_DECODER_MODEL_KERNEl_4_
#define DLIB_ENTROPY_DECODER_MODEL_KERNEl_4_
#include "../algs.h"
#include "entropy_decoder_model_kernel_abstract.h"
#include "../assert.h"
namespace dlib
{
namespace edmk4
{
struct node
{
node* next;
node* child_context;
node* parent_context;
unsigned short symbol;
unsigned short count;
unsigned short total;
unsigned short escapes;
};
}
template <
unsigned long alphabet_size,
typename entropy_decoder,
unsigned long total_nodes,
unsigned long order
>
class entropy_decoder_model_kernel_4
{
/*!
REQUIREMENTS ON total_nodes
- 4096 < total_nodes
- this is the total number of nodes that we will use in the tree
REQUIREMENTS ON order
- 0 <= order
- this is the maximum depth-1 the tree will be allowed to go (note
that the root level is depth 0).
GENERAL NOTES
This implementation follows more or less the implementation
strategy laid out by Alistair Moffat in his paper
Implementing the PPM data compression scheme. Published in IEEE
Transactions on Communications, 38(11):1917-1921, 1990.
The escape method used will be method D.
INITIAL VALUE
- root == pointer to an array of total_nodes nodes
- next_node == 1
- cur == root
- cur_order = 0
- root->next == 0
- root->parent_context == 0
- root->child_context == 0
- root->escapes == 0
- root->total == 0
- stack_size == 0
CONVENTION
- pop() == stack[stack_size-1]
- &get_entropy_decoder() == coder
- root == pointer to an array of total_nodes nodes.
this is also the root of the tree.
- if (next_node < total_nodes) then
- next_node == the next node in root that has not yet been allocated
- root->next == 0
- root->parent_context == 0
- for every node in the tree:
{
- NOTATION:
- The "context" of a node is the string of symbols seen
when you go from the root of the tree down (down though
child context pointers) to the node, including the symbol at
the node itself. (note that the context of the root node
is "" or the empty string)
- A set of nodes is in the same "context set" if all the node's
contexts are of length n and all the node's contexts share
the same prefix of length n-1.
- The "child context set" of a node is a set of nodes with
contexts that are one symbol longer and prefixed by the node's
context. For example, if a node has a context "abc" then the
nodes for contexts "abca", "abcb", "abcc", etc... are all in
the child context set of the node.
- The "parent context" of a node is the context that is one
symbol shorter than the node's context and includes the
symbol in the node. So the parent context of a node with
context "abcd" would be the context "bcd".
- if (next != 0) then
- next == pointer to the next node in the same context set
- if (child_context != 0) then
- child_context == pointer to the first node of the child
context set for this node.
- if (parent_context != 0) then
- parent_context == pointer to the parent context of this node.
- else
- this node is the root node of the tree
- if (this is not the root node) then
- symbol == the symbol represented with this node
- count == the number of times this symbol has been seen in its
parent context.
- else
- the root doesn't have a symbol. i.e. the context for the
root node is "" or the empty string.
- total == The sum of the counts of all the nodes
in the child context set + escapes.
- escapes == the escape count for the context represented
by the node.
}
- cur_order < order
- cur_order == the depth of the node cur in the tree.
(note that the root node has depth 0)
- cur == pointer to the node in the tree who's context matches
the most recent symbols we have seen.
!*/
typedef edmk4::node node;
public:
typedef entropy_decoder entropy_decoder_type;
entropy_decoder_model_kernel_4 (
entropy_decoder& coder
);
virtual ~entropy_decoder_model_kernel_4 (
);
inline void clear(
);
inline void decode (
unsigned long& symbol
);
entropy_decoder& get_entropy_decoder (
) { return coder; }
static unsigned long get_alphabet_size (
) { return alphabet_size; }
private:
inline void push (
edmk4::node* n
);
/*!
requires
- stack_size <= order
ensures
- #pop() == n
!*/
inline edmk4::node* pop (
);
/*!
requires
- stack_size > 0
ensures
- returns the node at the top of the stack
!*/
inline edmk4::node* allocate_node (
);
/*!
requires
- space_left() == true
ensures
- returns a pointer to a new node
!*/
inline void destroy_tree (
);
/*!
ensures
- deallocates all nodes except the root
- #root->child_context == 0
- #root->escapes == 0
- #root->total == 0
- #cur == root
- #cur_order == 0
- #stack_size == 0
!*/
inline bool space_left (
) const;
/*!
ensures
- returns true if there is at least 1 free node left.
- returns false otherwise
!*/
inline void scale_counts (
node* n
);
/*!
ensures
- divides all the counts in the child context set of n by 2.
- none of the nodes in the child context set will have a count of 0
!*/
entropy_decoder& coder;
unsigned long next_node;
node* root;
node* cur;
unsigned long cur_order;
node* stack[order+1];
unsigned long stack_size;
// restricted functions
entropy_decoder_model_kernel_4(entropy_decoder_model_kernel_4<alphabet_size,entropy_decoder,total_nodes,order>&); // copy constructor
entropy_decoder_model_kernel_4<alphabet_size,entropy_decoder,total_nodes,order>& operator=(entropy_decoder_model_kernel_4<alphabet_size,entropy_decoder,total_nodes,order>&); // assignment operator
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
unsigned long alphabet_size,
typename entropy_decoder,
unsigned long total_nodes,
unsigned long order
>
entropy_decoder_model_kernel_4<alphabet_size,entropy_decoder,total_nodes,order>::
entropy_decoder_model_kernel_4 (
entropy_decoder& coder_
) :
coder(coder_),
next_node(1),
cur_order(0),
stack_size(0)
{
COMPILE_TIME_ASSERT( 1 < alphabet_size && alphabet_size < 65535);
COMPILE_TIME_ASSERT( 4096 < total_nodes );
root = new node[total_nodes];
cur = root;
root->child_context = 0;
root->escapes = 0;
root->next = 0;
root->parent_context = 0;
root->total = 0;
}
// ----------------------------------------------------------------------------------------
template <
unsigned long alphabet_size,
typename entropy_decoder,
unsigned long total_nodes,
unsigned long order
>
entropy_decoder_model_kernel_4<alphabet_size,entropy_decoder,total_nodes,order>::
~entropy_decoder_model_kernel_4 (
)
{
delete [] root;
}
// ----------------------------------------------------------------------------------------
template <
unsigned long alphabet_size,
typename entropy_decoder,
unsigned long total_nodes,
unsigned long order
>
void entropy_decoder_model_kernel_4<alphabet_size,entropy_decoder,total_nodes,order>::
clear(
)
{
destroy_tree();
}
// ----------------------------------------------------------------------------------------
template <
unsigned long alphabet_size,
typename entropy_decoder,
unsigned long total_nodes,
unsigned long order
>
void entropy_decoder_model_kernel_4<alphabet_size,entropy_decoder,total_nodes,order>::
decode (
unsigned long& symbol
)
{
node* temp = cur;
cur = 0;
unsigned long low_count, high_count, total_count;
unsigned long target;
node* new_node = 0;
// local_order will track the level of temp in the tree
unsigned long local_order = cur_order;
while (true)
{
high_count = 0;
if (space_left())
{
total_count = temp->total;
if (total_count > 0)
{
// check if we need to scale the counts
if (total_count > 10000)
{
scale_counts(temp);
total_count = temp->total;
}
target = coder.get_target(total_count);
// find either the symbol we are looking for or the
// end of the context set
node* n = temp->child_context;
node* last = 0;
while (true)
{
high_count += n->count;
if (high_count > target || n->next == 0)
break;
last = n;
n = n->next;
}
low_count = high_count - n->count;
// if we found the symbol
if (high_count > target)
{
if (new_node != 0)
{
new_node->parent_context = n;
}
symbol = n->symbol;
coder.decode(low_count,high_count);
n->count += 8;
temp->total += 8;
// move this node to the front
if (last)
{
last->next = n->next;
n->next = temp->child_context;
temp->child_context = n;
}
if (cur == 0)
{
if (local_order < order)
{
cur_order = local_order+1;
cur = n;
}
else
{
cur = n->parent_context;
cur_order = local_order;
}
}
break;
}
// if we hit the end of the context set without finding the symbol
else
{
if (new_node != 0)
{
new_node->parent_context = allocate_node();
new_node = new_node->parent_context;
}
else
{
new_node = allocate_node();
}
n->next = new_node;
// get the escape code
coder.decode(high_count,total_count);
}
}
else // if (total_count == 0)
{
// this means that temp->child_context == 0 so we should make
// a new node here.
if (new_node != 0)
{
new_node->parent_context = allocate_node();
new_node = new_node->parent_context;
}
else
{
new_node = allocate_node();
}
temp->child_context = new_node;
}
if (cur == 0 && local_order < order)
{
cur = new_node;
cur_order = local_order+1;
}
// fill out the new node
new_node->child_context = 0;
new_node->count = 4;
new_node->escapes = 0;
new_node->next = 0;
push(new_node);
new_node->total = 0;
temp->escapes += 4;
temp->total += 8;
if (temp != root)
{
temp = temp->parent_context;
--local_order;
continue;
}
// since this is the root we are going to the order-(-1) context
// so we can just take care of that here.
target = coder.get_target(alphabet_size);
new_node->parent_context = root;
coder.decode(target,target+1);
symbol = target;
if (cur == 0)
{
cur = root;
cur_order = 0;
}
break;
}
else
{
// there isn't enough space so we should rebuild the tree
destroy_tree();
temp = cur;
local_order = cur_order;
cur = 0;
new_node = 0;
}
} // while (true)
while (stack_size > 0)
{
pop()->symbol = static_cast<unsigned short>(symbol);
}
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// private member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
unsigned long alphabet_size,
typename entropy_decoder,
unsigned long total_nodes,
unsigned long order
>
edmk4::node* entropy_decoder_model_kernel_4<alphabet_size,entropy_decoder,total_nodes,order>::
allocate_node (
)
{
node* temp;
temp = root + next_node;
++next_node;
return temp;
}
// ----------------------------------------------------------------------------------------
template <
unsigned long alphabet_size,
typename entropy_decoder,
unsigned long total_nodes,
unsigned long order
>
void entropy_decoder_model_kernel_4<alphabet_size,entropy_decoder,total_nodes,order>::
destroy_tree (
)
{
next_node = 1;
root->child_context = 0;
root->escapes = 0;
root->total = 0;
cur = root;
cur_order = 0;
stack_size = 0;
}
// ----------------------------------------------------------------------------------------
template <
unsigned long alphabet_size,
typename entropy_decoder,
unsigned long total_nodes,
unsigned long order
>
bool entropy_decoder_model_kernel_4<alphabet_size,entropy_decoder,total_nodes,order>::
space_left (
) const
{
return (next_node < total_nodes);
}
// ----------------------------------------------------------------------------------------
template <
unsigned long alphabet_size,
typename entropy_decoder,
unsigned long total_nodes,
unsigned long order
>
void entropy_decoder_model_kernel_4<alphabet_size,entropy_decoder,total_nodes,order>::
push (
edmk4::node* n
)
{
stack[stack_size] = n;
++stack_size;
}
// ----------------------------------------------------------------------------------------
template <
unsigned long alphabet_size,
typename entropy_decoder,
unsigned long total_nodes,
unsigned long order
>
edmk4::node* entropy_decoder_model_kernel_4<alphabet_size,entropy_decoder,total_nodes,order>::
pop (
)
{
--stack_size;
return stack[stack_size];
}
// ----------------------------------------------------------------------------------------
template <
unsigned long alphabet_size,
typename entropy_decoder,
unsigned long total_nodes,
unsigned long order
>
void entropy_decoder_model_kernel_4<alphabet_size,entropy_decoder,total_nodes,order>::
scale_counts (
node* temp
)
{
if (temp->escapes > 1)
temp->escapes >>= 1;
temp->total = temp->escapes;
node* n = temp->child_context;
while (n != 0)
{
if (n->count > 1)
n->count >>= 1;
temp->total += n->count;
n = n->next;
}
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_ENTROPY_DECODER_MODEL_KERNEl_4_
// Copyright (C) 2005 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_ENTROPY_DECODER_MODEL_KERNEl_5_
#define DLIB_ENTROPY_DECODER_MODEL_KERNEl_5_
#include "../algs.h"
#include "entropy_decoder_model_kernel_abstract.h"
#include "../assert.h"
namespace dlib
{
namespace edmk5
{
struct node
{
node* next;
node* child_context;
node* parent_context;
unsigned short symbol;
unsigned short count;
unsigned short total;
unsigned short escapes;
};
}
template <
unsigned long alphabet_size,
typename entropy_decoder,
unsigned long total_nodes,
unsigned long order
>
class entropy_decoder_model_kernel_5
{
/*!
REQUIREMENTS ON total_nodes
- 4096 < total_nodes
- this is the total number of nodes that we will use in the tree
REQUIREMENTS ON order
- 0 <= order
- this is the maximum depth-1 the tree will be allowed to go (note
that the root level is depth 0).
GENERAL NOTES
This implementation follows more or less the implementation
strategy laid out by Alistair Moffat in his paper
Implementing the PPM data compression scheme. Published in IEEE
Transactions on Communications, 38(11):1917-1921, 1990.
The escape method used will be method D.
This also uses Dmitry Shkarin's Information Inheritance scheme.
(described in "PPM: one step to practicality" and "Improving the
Efficiency of the PPM Algorithm")
INITIAL VALUE
- root == pointer to an array of total_nodes nodes
- next_node == 1
- cur == root
- cur_order = 0
- root->next == 0
- root->parent_context == 0
- root->child_context == 0
- root->escapes == 0
- root->total == 0
- stack_size == 0
- exc_used == false
- for all i: exc[i] == 0
CONVENTION
- exc_used == something_is_excluded()
- pop() == stack[stack_size-1].n and stack[stack_size-1].nc
- is_excluded(symbol) == bit symbol&0x1F from exc[symbol>>5]
- &get_entropy_decoder() == coder
- root == pointer to an array of total_nodes nodes.
this is also the root of the tree.
- if (next_node < total_nodes) then
- next_node == the next node in root that has not yet been allocated
- root->next == 0
- root->parent_context == 0
- for every node in the tree:
{
- NOTATION:
- The "context" of a node is the string of symbols seen
when you go from the root of the tree down (down though
child context pointers) to the node, including the symbol at
the node itself. (note that the context of the root node
is "" or the empty string)
- A set of nodes is in the same "context set" if all the node's
contexts are of length n and all the node's contexts share
the same prefix of length n-1.
- The "child context set" of a node is a set of nodes with
contexts that are one symbol longer and prefixed by the node's
context. For example, if a node has a context "abc" then the
nodes for contexts "abca", "abcb", "abcc", etc... are all in
the child context set of the node.
- The "parent context" of a node is the context that is one
symbol shorter than the node's context and includes the
symbol in the node. So the parent context of a node with
context "abcd" would be the context "bcd".
- if (next != 0) then
- next == pointer to the next node in the same context set
- if (child_context != 0) then
- child_context == pointer to the first node of the child
context set for this node.
- escapes > 0
- if (parent_context != 0) then
- parent_context == pointer to the parent context of this node.
- else
- this node is the root node of the tree
- if (this is not the root node) then
- symbol == the symbol represented with this node
- count == the number of times this symbol has been seen in its
parent context.
- else
- the root doesn't have a symbol. i.e. the context for the
root node is "" or the empty string.
- total == The sum of the counts of all the nodes
in the child context set + escapes.
- escapes == the escape count for the context represented
by the node.
- count > 0
}
- cur_order < order
- cur_order == the depth of the node cur in the tree.
(note that the root node has depth 0)
- cur == pointer to the node in the tree who's context matches
the most recent symbols we have seen.
!*/
typedef edmk5::node node;
public:
typedef entropy_decoder entropy_decoder_type;
entropy_decoder_model_kernel_5 (
entropy_decoder& coder
);
virtual ~entropy_decoder_model_kernel_5 (
);
inline void clear(
);
inline void decode (
unsigned long& symbol
);
entropy_decoder& get_entropy_decoder (
) { return coder; }
static unsigned long get_alphabet_size (
) { return alphabet_size; }
private:
inline void push (
node* n,
node* nc
);
/*!
requires
- stack_size < order
ensures
- #pop(a,b): a == n && b == nc
!*/
inline void pop (
node*& n,
node*& nc
);
/*!
requires
- stack_size > 0
ensures
- returns the two nodes at the top of the stack
!*/
inline edmk5::node* allocate_node (
);
/*!
requires
- space_left() == true
ensures
- returns a pointer to a new node
!*/
inline bool space_left (
) const;
/*!
ensures
- returns true if there is at least 1 free node left.
- returns false otherwise
!*/
inline void exclude (
unsigned short symbol
);
/*!
ensures
- #is_excluded(symbol) == true
- #something_is_excluded() == true
!*/
inline bool is_excluded (
unsigned short symbol
);
/*!
ensures
- if (symbol has been excluded) then
- returns true
- else
- returns false
!*/
inline bool something_is_excluded (
);
/*!
ensures
- returns true if some symbol has been excluded.
returns false otherwise
!*/
inline void clear_exclusions (
);
/*!
ensures
- for all symbols #is_excluded(symbol) == false
- #something_is_excluded() == false
!*/
inline void scale_counts (
node* n
);
/*!
ensures
- divides all the counts in the child context set of n by 2.
- none of the nodes in the child context set will have a count of 0
!*/
struct nodes
{
node* n;
node* nc;
};
entropy_decoder& coder;
unsigned long next_node;
node* root;
node* cur;
unsigned long cur_order;
unsigned long exc[alphabet_size/32+1];
nodes stack[order+1];
unsigned long stack_size;
bool exc_used;
// restricted functions
entropy_decoder_model_kernel_5(entropy_decoder_model_kernel_5<alphabet_size,entropy_decoder,total_nodes,order>&); // copy constructor
entropy_decoder_model_kernel_5<alphabet_size,entropy_decoder,total_nodes,order>& operator=(entropy_decoder_model_kernel_5<alphabet_size,entropy_decoder,total_nodes,order>&); // assignment operator
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
unsigned long alphabet_size,
typename entropy_decoder,
unsigned long total_nodes,
unsigned long order
>
entropy_decoder_model_kernel_5<alphabet_size,entropy_decoder,total_nodes,order>::
entropy_decoder_model_kernel_5 (
entropy_decoder& coder_
) :
coder(coder_),
next_node(1),
cur_order(0),
stack_size(0)
{
COMPILE_TIME_ASSERT( 1 < alphabet_size && alphabet_size < 65535);
COMPILE_TIME_ASSERT( 4096 < total_nodes );
root = new node[total_nodes];
cur = root;
root->child_context = 0;
root->escapes = 0;
root->next = 0;
root->parent_context = 0;
root->total = 0;
clear_exclusions();
}
// ----------------------------------------------------------------------------------------
template <
unsigned long alphabet_size,
typename entropy_decoder,
unsigned long total_nodes,
unsigned long order
>
entropy_decoder_model_kernel_5<alphabet_size,entropy_decoder,total_nodes,order>::
~entropy_decoder_model_kernel_5 (
)
{
delete [] root;
}
// ----------------------------------------------------------------------------------------
template <
unsigned long alphabet_size,
typename entropy_decoder,
unsigned long total_nodes,
unsigned long order
>
void entropy_decoder_model_kernel_5<alphabet_size,entropy_decoder,total_nodes,order>::
clear(
)
{
next_node = 1;
root->child_context = 0;
root->escapes = 0;
root->total = 0;
cur = root;
cur_order = 0;
stack_size = 0;
clear_exclusions();
}
// ----------------------------------------------------------------------------------------
template <
unsigned long alphabet_size,
typename entropy_decoder,
unsigned long total_nodes,
unsigned long order
>
void entropy_decoder_model_kernel_5<alphabet_size,entropy_decoder,total_nodes,order>::
decode (
unsigned long& symbol
)
{
node* temp = cur;
cur = 0;
unsigned long low_count, high_count, total_count;
unsigned long target;
node* new_node = 0;
// local_order will track the level of temp in the tree
unsigned long local_order = cur_order;
unsigned short c; // c == t(a|sk)
unsigned short t; // t == T(sk)
if (something_is_excluded())
clear_exclusions();
while (true)
{
high_count = 0;
if (space_left())
{
total_count = temp->total;
if (total_count > 0)
{
// check if we need to scale the counts
if (total_count > 10000)
{
scale_counts(temp);
total_count = temp->total;
}
if (something_is_excluded())
{
node* n = temp->child_context;
total_count = temp->escapes;
while (true)
{
if (is_excluded(n->symbol) == false)
{
total_count += n->count;
}
if (n->next == 0)
break;
n = n->next;
}
}
target = coder.get_target(total_count);
// find either the symbol we are looking for or the
// end of the context set
node* n = temp->child_context;
node* last = 0;
while (true)
{
if (is_excluded(n->symbol) == false)
{
high_count += n->count;
exclude(n->symbol);
}
if (high_count > target || n->next == 0)
break;
last = n;
n = n->next;
}
// if we found the symbol
if (high_count > target)
{
low_count = high_count - n->count;
if (new_node != 0)
{
new_node->parent_context = n;
}
symbol = n->symbol;
coder.decode(low_count,high_count);
c = n->count += 8;
t = temp->total += 8;
// move this node to the front
if (last)
{
last->next = n->next;
n->next = temp->child_context;
temp->child_context = n;
}
if (cur == 0)
{
if (local_order < order)
{
cur_order = local_order+1;
cur = n;
}
else
{
cur = n->parent_context;
cur_order = local_order;
}
}
break;
}
// if we hit the end of the context set without finding the symbol
else
{
if (new_node != 0)
{
new_node->parent_context = allocate_node();
new_node = new_node->parent_context;
}
else
{
new_node = allocate_node();
}
n->next = new_node;
// get the escape code
coder.decode(high_count,total_count);
}
}
else // if (total_count == 0)
{
// this means that temp->child_context == 0 so we should make
// a new node here.
if (new_node != 0)
{
new_node->parent_context = allocate_node();
new_node = new_node->parent_context;
}
else
{
new_node = allocate_node();
}
temp->child_context = new_node;
}
if (cur == 0 && local_order < order)
{
cur = new_node;
cur_order = local_order+1;
}
// fill out the new node
new_node->child_context = 0;
new_node->escapes = 0;
new_node->next = 0;
push(new_node,temp);
new_node->total = 0;
if (temp != root)
{
temp = temp->parent_context;
--local_order;
continue;
}
t = 2056;
c = 8;
// since this is the root we are going to the order-(-1) context
// so we can just take care of that here.
target = coder.get_target(alphabet_size);
new_node->parent_context = root;
coder.decode(target,target+1);
symbol = target;
if (cur == 0)
{
cur = root;
cur_order = 0;
}
break;
}
else
{
// there isn't enough space so we should rebuild the tree
clear();
temp = cur;
local_order = cur_order;
cur = 0;
new_node = 0;
}
} // while (true)
// initialize the counts and symbol for any new nodes we have added
// to the tree.
node* n, *nc;
while (stack_size > 0)
{
pop(n,nc);
n->symbol = static_cast<unsigned short>(symbol);
// if nc is not a determnistic context
if (nc->total)
{
unsigned long temp2 = t-c+nc->total - nc->escapes - nc->escapes;
unsigned long temp = nc->total;
temp *= c;
temp /= (temp2|1); // this oring by 1 is just to make sure that temp2 is never zero
temp += 2;
if (temp > 50000) temp = 50000;
n->count = static_cast<unsigned short>(temp);
nc->escapes += 4;
nc->total += static_cast<unsigned short>(temp) + 4;
}
else
{
n->count = 3 + 5*(c)/(t-c);
nc->escapes = 4;
nc->total = n->count + 4;
}
while (nc->total > 10000)
{
scale_counts(nc);
}
}
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// private member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
unsigned long alphabet_size,
typename entropy_decoder,
unsigned long total_nodes,
unsigned long order
>
edmk5::node* entropy_decoder_model_kernel_5<alphabet_size,entropy_decoder,total_nodes,order>::
allocate_node (
)
{
node* temp;
temp = root + next_node;
++next_node;
return temp;
}
// ----------------------------------------------------------------------------------------
template <
unsigned long alphabet_size,
typename entropy_decoder,
unsigned long total_nodes,
unsigned long order
>
bool entropy_decoder_model_kernel_5<alphabet_size,entropy_decoder,total_nodes,order>::
space_left (
) const
{
return (next_node < total_nodes);
}
// ----------------------------------------------------------------------------------------
template <
unsigned long alphabet_size,
typename entropy_decoder,
unsigned long total_nodes,
unsigned long order
>
void entropy_decoder_model_kernel_5<alphabet_size,entropy_decoder,total_nodes,order>::
exclude (
unsigned short symbol
)
{
exc_used = true;
unsigned long temp = 1;
temp <<= symbol&0x1F;
exc[symbol>>5] |= temp;
}
// ----------------------------------------------------------------------------------------
template <
unsigned long alphabet_size,
typename entropy_decoder,
unsigned long total_nodes,
unsigned long order
>
bool entropy_decoder_model_kernel_5<alphabet_size,entropy_decoder,total_nodes,order>::
is_excluded (
unsigned short symbol
)
{
unsigned long temp = 1;
temp <<= symbol&0x1F;
return ((exc[symbol>>5]&temp) != 0);
}
// ----------------------------------------------------------------------------------------
template <
unsigned long alphabet_size,
typename entropy_decoder,
unsigned long total_nodes,
unsigned long order
>
void entropy_decoder_model_kernel_5<alphabet_size,entropy_decoder,total_nodes,order>::
clear_exclusions (
)
{
exc_used = false;
for (unsigned long i = 0; i < alphabet_size/32+1; ++i)
{
exc[i] = 0;
}
}
// ----------------------------------------------------------------------------------------
template <
unsigned long alphabet_size,
typename entropy_decoder,
unsigned long total_nodes,
unsigned long order
>
void entropy_decoder_model_kernel_5<alphabet_size,entropy_decoder,total_nodes,order>::
push (
node* n,
node* nc
)
{
stack[stack_size].n = n;
stack[stack_size].nc = nc;
++stack_size;
}
// ----------------------------------------------------------------------------------------
template <
unsigned long alphabet_size,
typename entropy_decoder,
unsigned long total_nodes,
unsigned long order
>
void entropy_decoder_model_kernel_5<alphabet_size,entropy_decoder,total_nodes,order>::
pop (
node*& n,
node*& nc
)
{
--stack_size;
n = stack[stack_size].n;
nc = stack[stack_size].nc;
}
// ----------------------------------------------------------------------------------------
template <
unsigned long alphabet_size,
typename entropy_decoder,
unsigned long total_nodes,
unsigned long order
>
bool entropy_decoder_model_kernel_5<alphabet_size,entropy_decoder,total_nodes,order>::
something_is_excluded (
)
{
return exc_used;
}
// ----------------------------------------------------------------------------------------
template <
unsigned long alphabet_size,
typename entropy_decoder,
unsigned long total_nodes,
unsigned long order
>
void entropy_decoder_model_kernel_5<alphabet_size,entropy_decoder,total_nodes,order>::
scale_counts (
node* temp
)
{
if (temp->escapes > 1)
temp->escapes >>= 1;
temp->total = temp->escapes;
node* n = temp->child_context;
while (n != 0)
{
if (n->count > 1)
n->count >>= 1;
temp->total += n->count;
n = n->next;
}
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_ENTROPY_DECODER_MODEL_KERNEl_5_
// Copyright (C) 2005 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_ENTROPY_DECODER_MODEL_KERNEl_6_
#define DLIB_ENTROPY_DECODER_MODEL_KERNEl_6_
#include "../algs.h"
#include "entropy_decoder_model_kernel_abstract.h"
#include "../assert.h"
namespace dlib
{
template <
unsigned long alphabet_size,
typename entropy_decoder
>
class entropy_decoder_model_kernel_6
{
/*!
INITIAL VALUE
This object has no state
CONVENTION
&get_entropy_decoder() == coder
This is an order-(-1) model. So it doesn't really do anything.
Every symbol has the same probability.
!*/
public:
typedef entropy_decoder entropy_decoder_type;
entropy_decoder_model_kernel_6 (
entropy_decoder& coder
);
virtual ~entropy_decoder_model_kernel_6 (
);
inline void clear(
);
inline void decode (
unsigned long& symbol
);
entropy_decoder& get_entropy_decoder (
) { return coder; }
static unsigned long get_alphabet_size (
) { return alphabet_size; }
private:
entropy_decoder& coder;
// restricted functions
entropy_decoder_model_kernel_6(entropy_decoder_model_kernel_6<alphabet_size,entropy_decoder>&); // copy constructor
entropy_decoder_model_kernel_6<alphabet_size,entropy_decoder>& operator=(entropy_decoder_model_kernel_6<alphabet_size,entropy_decoder>&); // assignment operator
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
unsigned long alphabet_size,
typename entropy_decoder
>
entropy_decoder_model_kernel_6<alphabet_size,entropy_decoder>::
entropy_decoder_model_kernel_6 (
entropy_decoder& coder_
) :
coder(coder_)
{
COMPILE_TIME_ASSERT( 1 < alphabet_size && alphabet_size < 65535 );
}
// ----------------------------------------------------------------------------------------
template <
unsigned long alphabet_size,
typename entropy_decoder
>
entropy_decoder_model_kernel_6<alphabet_size,entropy_decoder>::
~entropy_decoder_model_kernel_6 (
)
{
}
// ----------------------------------------------------------------------------------------
template <
unsigned long alphabet_size,
typename entropy_decoder
>
void entropy_decoder_model_kernel_6<alphabet_size,entropy_decoder>::
clear(
)
{
}
// ----------------------------------------------------------------------------------------
template <
unsigned long alphabet_size,
typename entropy_decoder
>
void entropy_decoder_model_kernel_6<alphabet_size,entropy_decoder>::
decode (
unsigned long& symbol
)
{
unsigned long target;
target = coder.get_target(alphabet_size);
coder.decode(target,target+1);
symbol = target;
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_ENTROPY_DECODER_MODEL_KERNEl_6_
// Copyright (C) 2004 Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_ENTROPY_DECODER_MODEL_KERNEl_ABSTRACT_
#ifdef DLIB_ENTROPY_DECODER_MODEL_KERNEl_ABSTRACT_
#include "../algs.h"
namespace dlib
{
template <
unsigned long alphabet_size,
typename entropy_decoder
>
class entropy_decoder_model
{
/*!
REQUIREMENTS ON alphabet_size
1 < alphabet_size < 65535
REQUIREMENTS ON entropy_decoder
is an implementation of entropy_decoder/entropy_decoder_kernel_abstract.h
INITIAL VALUE
Initially this object is at some predefined empty or ground state.
WHAT THIS OBJECT REPRESENTS
This object represents some kind of statistical model. You
can use it to read symbols from an entropy_decoder and it will calculate
the cumulative counts/probabilities and manage contexts for you.
Note that all implementations of entropy_encoder_model and
entropy_decoder_model are paired. This means that if you use
entropy_encoder_model_kernel_n to encode something then you must
use the corresponding entropy_decoder_model_kernel_n to decode it.
Also note that this object does not perform any buffering of symbols. It
reads them from its associated entropy_decoder simply as it needs them.
This makes it safe to use multiple entropy_decoder_model objects with
a single entropy_decoder without them trampling each other.
!*/
public:
typedef entropy_decoder entropy_decoder_type;
entropy_decoder_model (
entropy_decoder& coder
);
/*!
ensures
- #*this is properly initialized
- &#get_entropy_decoder() == &coder
throws
- any exception
!*/
virtual ~entropy_decoder_model (
);
/*!
ensures
- all memory associated with *this has been released
!*/
void clear(
);
/*!
ensures
- #*this has its initial value
- does not modify get_entropy_decoder()
throws
- any exception
if this exception is thrown then *this is unusable
until clear() is called and succeeds
!*/
void decode (
unsigned long& symbol
);
/*!
ensures
- decodes the next symbol
- #symbol == the next symbol
- #symbol < alphabet_size
throws
- any exception
If this exception is thrown then #*this is unusable until
clear() is called and succeeds.
!*/
entropy_decoder& get_entropy_decoder (
);
/*!
ensures
- returns a reference to the entropy_decoder used by *this
!*/
static unsigned long get_alphabet_size (
);
/*!
ensures
- returns alphabet_size
!*/
private:
// restricted functions
entropy_decoder_model(entropy_decoder_model<alphabet_size>&); // copy constructor
entropy_decoder_model<alphabet_size>& operator=(entropy_decoder_model<alphabet_size>&); // assignment operator
};
}
#endif // DLIB_ENTROPY_DECODER_MODEL_KERNEl_ABSTRACT_
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment