Commit 0886042c authored by lishen's avatar lishen
Browse files

dlib from github, version=19.24

parent 5b127120
Pipeline #262 failed with stages
in 0 seconds
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_BIGINT_KERNEl_1_
#define DLIB_BIGINT_KERNEl_1_
#include "bigint_kernel_abstract.h"
#include "../algs.h"
#include "../serialize.h"
#include "../uintn.h"
#include <iosfwd>
namespace dlib
{
class bigint_kernel_1
{
/*!
INITIAL VALUE
slack == 25
data->number[0] == 0
data->size == slack
data->references == 1
data->digits_used == 1
CONVENTION
slack == the number of extra digits placed into the number when it is
created. the slack value should never be less than 1
data->number == pointer to an array of data->size uint16s.
data represents a string of base 65535 numbers with data[0] being
the least significant bit and data[data->digits_used-1] being the most
significant
NOTE: In the comments I will consider a word to be a 16 bit value
data->digits_used == the number of significant digits in the number.
data->digits_used tells us the number of used elements in the
data->number array so everything beyond data->number[data->digits_used-1]
is undefined
data->references == the number of bigint_kernel_1 objects which refer
to this data_record
!*/
struct data_record
{
explicit data_record(
uint32 size_
) :
size(size_),
number(new uint16[size_]),
references(1),
digits_used(1)
{*number = 0;}
/*!
ensures
- initializes *this to represent zero
!*/
data_record(
const data_record& item,
uint32 additional_size
) :
size(item.digits_used + additional_size),
number(new uint16[size]),
references(1),
digits_used(item.digits_used)
{
uint16* source = item.number;
uint16* dest = number;
uint16* end = source + digits_used;
while (source != end)
{
*dest = *source;
++dest;
++source;
}
}
/*!
ensures
- *this is a copy of item except with
size == item.digits_used + additional_size
!*/
~data_record(
)
{
delete [] number;
}
const uint32 size;
uint16* number;
uint32 references;
uint32 digits_used;
private:
// no copy constructor
data_record ( data_record&);
};
// note that the second parameter is just there
// to resolve the ambiguity between this constructor and
// bigint_kernel_1(uint32)
explicit bigint_kernel_1 (
data_record* data_, int
): slack(25),data(data_) {}
/*!
ensures
- *this is initialized with data_ as its data member
!*/
public:
bigint_kernel_1 (
);
bigint_kernel_1 (
uint32 value
);
bigint_kernel_1 (
const bigint_kernel_1& item
);
virtual ~bigint_kernel_1 (
);
const bigint_kernel_1 operator+ (
const bigint_kernel_1& rhs
) const;
bigint_kernel_1& operator+= (
const bigint_kernel_1& rhs
);
const bigint_kernel_1 operator- (
const bigint_kernel_1& rhs
) const;
bigint_kernel_1& operator-= (
const bigint_kernel_1& rhs
);
const bigint_kernel_1 operator* (
const bigint_kernel_1& rhs
) const;
bigint_kernel_1& operator*= (
const bigint_kernel_1& rhs
);
const bigint_kernel_1 operator/ (
const bigint_kernel_1& rhs
) const;
bigint_kernel_1& operator/= (
const bigint_kernel_1& rhs
);
const bigint_kernel_1 operator% (
const bigint_kernel_1& rhs
) const;
bigint_kernel_1& operator%= (
const bigint_kernel_1& rhs
);
bool operator < (
const bigint_kernel_1& rhs
) const;
bool operator == (
const bigint_kernel_1& rhs
) const;
bigint_kernel_1& operator= (
const bigint_kernel_1& rhs
);
friend std::ostream& operator<< (
std::ostream& out,
const bigint_kernel_1& rhs
);
friend std::istream& operator>> (
std::istream& in,
bigint_kernel_1& rhs
);
bigint_kernel_1& operator++ (
);
const bigint_kernel_1 operator++ (
int
);
bigint_kernel_1& operator-- (
);
const bigint_kernel_1 operator-- (
int
);
friend const bigint_kernel_1 operator+ (
uint16 lhs,
const bigint_kernel_1& rhs
);
friend const bigint_kernel_1 operator+ (
const bigint_kernel_1& lhs,
uint16 rhs
);
bigint_kernel_1& operator+= (
uint16 rhs
);
friend const bigint_kernel_1 operator- (
uint16 lhs,
const bigint_kernel_1& rhs
);
friend const bigint_kernel_1 operator- (
const bigint_kernel_1& lhs,
uint16 rhs
);
bigint_kernel_1& operator-= (
uint16 rhs
);
friend const bigint_kernel_1 operator* (
uint16 lhs,
const bigint_kernel_1& rhs
);
friend const bigint_kernel_1 operator* (
const bigint_kernel_1& lhs,
uint16 rhs
);
bigint_kernel_1& operator*= (
uint16 rhs
);
friend const bigint_kernel_1 operator/ (
uint16 lhs,
const bigint_kernel_1& rhs
);
friend const bigint_kernel_1 operator/ (
const bigint_kernel_1& lhs,
uint16 rhs
);
bigint_kernel_1& operator/= (
uint16 rhs
);
friend const bigint_kernel_1 operator% (
uint16 lhs,
const bigint_kernel_1& rhs
);
friend const bigint_kernel_1 operator% (
const bigint_kernel_1& lhs,
uint16 rhs
);
bigint_kernel_1& operator%= (
uint16 rhs
);
friend bool operator < (
uint16 lhs,
const bigint_kernel_1& rhs
);
friend bool operator < (
const bigint_kernel_1& lhs,
uint16 rhs
);
friend bool operator == (
const bigint_kernel_1& lhs,
uint16 rhs
);
friend bool operator == (
uint16 lhs,
const bigint_kernel_1& rhs
);
bigint_kernel_1& operator= (
uint16 rhs
);
void swap (
bigint_kernel_1& item
) { data_record* temp = data; data = item.data; item.data = temp; }
private:
void long_add (
const data_record* lhs,
const data_record* rhs,
data_record* result
) const;
/*!
requires
- result->size >= max(lhs->digits_used,rhs->digits_used) + 1
ensures
- result == lhs + rhs
!*/
void long_sub (
const data_record* lhs,
const data_record* rhs,
data_record* result
) const;
/*!
requires
- lhs >= rhs
- result->size >= lhs->digits_used
ensures
- result == lhs - rhs
!*/
void long_div (
const data_record* lhs,
const data_record* rhs,
data_record* result,
data_record* remainder
) const;
/*!
requires
- rhs != 0
- result->size >= lhs->digits_used
- remainder->size >= lhs->digits_used
- each parameter is unique (i.e. lhs != result, lhs != remainder, etc.)
ensures
- result == lhs / rhs
- remainder == lhs % rhs
!*/
void long_mul (
const data_record* lhs,
const data_record* rhs,
data_record* result
) const;
/*!
requires
- result->size >= lhs->digits_used + rhs->digits_used
- result != lhs
- result != rhs
ensures
- result == lhs * rhs
!*/
void short_add (
const data_record* data,
uint16 value,
data_record* result
) const;
/*!
requires
- result->size >= data->size + 1
ensures
- result == data + value
!*/
void short_sub (
const data_record* data,
uint16 value,
data_record* result
) const;
/*!
requires
- data >= value
- result->size >= data->digits_used
ensures
- result == data - value
!*/
void short_mul (
const data_record* data,
uint16 value,
data_record* result
) const;
/*!
requires
- result->size >= data->digits_used + 1
ensures
- result == data * value
!*/
void short_div (
const data_record* data,
uint16 value,
data_record* result,
uint16& remainder
) const;
/*!
requires
- value != 0
- result->size >= data->digits_used
ensures
- result = data*value
- remainder = data%value
!*/
void shift_left (
const data_record* data,
data_record* result,
uint32 shift_amount
) const;
/*!
requires
- result->size >= data->digits_used + shift_amount/8 + 1
ensures
- result == data << shift_amount
!*/
void shift_right (
const data_record* data,
data_record* result
) const;
/*!
requires
- result->size >= data->digits_used
ensures
- result == data >> 1
!*/
bool is_less_than (
const data_record* lhs,
const data_record* rhs
) const;
/*!
ensures
- returns true if lhs < rhs
- returns false otherwise
!*/
bool is_equal_to (
const data_record* lhs,
const data_record* rhs
) const;
/*!
ensures
- returns true if lhs == rhs
- returns false otherwise
!*/
void increment (
const data_record* source,
data_record* dest
) const;
/*!
requires
- dest->size >= source->digits_used + 1
ensures
- dest = source + 1
!*/
void decrement (
const data_record* source,
data_record* dest
) const;
/*!
requires
source != 0
ensuers
dest = source - 1
!*/
// member data
const uint32 slack;
data_record* data;
};
inline void swap (
bigint_kernel_1& a,
bigint_kernel_1& b
) { a.swap(b); }
inline void serialize (
const bigint_kernel_1& item,
std::ostream& out
)
{
std::ios::fmtflags oldflags = out.flags();
out << item << ' ';
out.flags(oldflags);
if (!out) throw serialization_error("Error serializing object of type bigint_kernel_c");
}
inline void deserialize (
bigint_kernel_1& item,
std::istream& in
)
{
std::ios::fmtflags oldflags = in.flags();
in >> item;
in.flags(oldflags);
if (in.get() != ' ')
{
item = 0;
throw serialization_error("Error deserializing object of type bigint_kernel_c");
}
}
inline bool operator> (const bigint_kernel_1& a, const bigint_kernel_1& b) { return b < a; }
inline bool operator!= (const bigint_kernel_1& a, const bigint_kernel_1& b) { return !(a == b); }
inline bool operator<= (const bigint_kernel_1& a, const bigint_kernel_1& b) { return !(b < a); }
inline bool operator>= (const bigint_kernel_1& a, const bigint_kernel_1& b) { return !(a < b); }
}
#ifdef NO_MAKEFILE
#include "bigint_kernel_1.cpp"
#endif
#endif // DLIB_BIGINT_KERNEl_1_
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_BIGINT_KERNEL_2_CPp_
#define DLIB_BIGINT_KERNEL_2_CPp_
#include "bigint_kernel_2.h"
#include <iostream>
#include <cmath>
namespace dlib
{
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// member/friend function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
bigint_kernel_2::
bigint_kernel_2 (
) :
slack(25),
data(new data_record(slack))
{}
// ----------------------------------------------------------------------------------------
bigint_kernel_2::
bigint_kernel_2 (
uint32 value
) :
slack(25),
data(new data_record(slack))
{
*(data->number) = static_cast<uint16>(value&0xFFFF);
*(data->number+1) = static_cast<uint16>((value>>16)&0xFFFF);
if (*(data->number+1) != 0)
data->digits_used = 2;
}
// ----------------------------------------------------------------------------------------
bigint_kernel_2::
bigint_kernel_2 (
const bigint_kernel_2& item
) :
slack(25),
data(item.data)
{
data->references += 1;
}
// ----------------------------------------------------------------------------------------
bigint_kernel_2::
~bigint_kernel_2 (
)
{
if (data->references == 1)
{
delete data;
}
else
{
data->references -= 1;
}
}
// ----------------------------------------------------------------------------------------
const bigint_kernel_2 bigint_kernel_2::
operator+ (
const bigint_kernel_2& rhs
) const
{
data_record* temp = new data_record (
std::max(rhs.data->digits_used,data->digits_used) + slack
);
long_add(data,rhs.data,temp);
return bigint_kernel_2(temp,0);
}
// ----------------------------------------------------------------------------------------
bigint_kernel_2& bigint_kernel_2::
operator+= (
const bigint_kernel_2& rhs
)
{
// if there are other references to our data
if (data->references != 1)
{
data_record* temp = new data_record(std::max(data->digits_used,rhs.data->digits_used)+slack);
data->references -= 1;
long_add(data,rhs.data,temp);
data = temp;
}
// if data is not big enough for the result
else if (data->size <= std::max(data->digits_used,rhs.data->digits_used))
{
data_record* temp = new data_record(std::max(data->digits_used,rhs.data->digits_used)+slack);
long_add(data,rhs.data,temp);
delete data;
data = temp;
}
// there is enough size and no references
else
{
long_add(data,rhs.data,data);
}
return *this;
}
// ----------------------------------------------------------------------------------------
const bigint_kernel_2 bigint_kernel_2::
operator- (
const bigint_kernel_2& rhs
) const
{
data_record* temp = new data_record (
data->digits_used + slack
);
long_sub(data,rhs.data,temp);
return bigint_kernel_2(temp,0);
}
// ----------------------------------------------------------------------------------------
bigint_kernel_2& bigint_kernel_2::
operator-= (
const bigint_kernel_2& rhs
)
{
// if there are other references to this data
if (data->references != 1)
{
data_record* temp = new data_record(data->digits_used+slack);
data->references -= 1;
long_sub(data,rhs.data,temp);
data = temp;
}
else
{
long_sub(data,rhs.data,data);
}
return *this;
}
// ----------------------------------------------------------------------------------------
const bigint_kernel_2 bigint_kernel_2::
operator* (
const bigint_kernel_2& rhs
) const
{
data_record* temp = new data_record (
data->digits_used + rhs.data->digits_used + slack
);
long_mul(data,rhs.data,temp);
return bigint_kernel_2(temp,0);
}
// ----------------------------------------------------------------------------------------
bigint_kernel_2& bigint_kernel_2::
operator*= (
const bigint_kernel_2& rhs
)
{
// create a data_record to store the result of the multiplication in
data_record* temp = new data_record(rhs.data->digits_used+data->digits_used+slack);
long_mul(data,rhs.data,temp);
// if there are other references to data
if (data->references != 1)
{
data->references -= 1;
}
else
{
delete data;
}
data = temp;
return *this;
}
// ----------------------------------------------------------------------------------------
const bigint_kernel_2 bigint_kernel_2::
operator/ (
const bigint_kernel_2& rhs
) const
{
data_record* temp = new data_record(data->digits_used+slack);
data_record* remainder;
try {
remainder = new data_record(data->digits_used+slack);
} catch (...) { delete temp; throw; }
long_div(data,rhs.data,temp,remainder);
delete remainder;
return bigint_kernel_2(temp,0);
}
// ----------------------------------------------------------------------------------------
bigint_kernel_2& bigint_kernel_2::
operator/= (
const bigint_kernel_2& rhs
)
{
data_record* temp = new data_record(data->digits_used+slack);
data_record* remainder;
try {
remainder = new data_record(data->digits_used+slack);
} catch (...) { delete temp; throw; }
long_div(data,rhs.data,temp,remainder);
// check if there are other references to data
if (data->references != 1)
{
data->references -= 1;
}
// if there are no references to data then it must be deleted
else
{
delete data;
}
data = temp;
delete remainder;
return *this;
}
// ----------------------------------------------------------------------------------------
const bigint_kernel_2 bigint_kernel_2::
operator% (
const bigint_kernel_2& rhs
) const
{
data_record* temp = new data_record(data->digits_used+slack);
data_record* remainder;
try {
remainder = new data_record(data->digits_used+slack);
} catch (...) { delete temp; throw; }
long_div(data,rhs.data,temp,remainder);
delete temp;
return bigint_kernel_2(remainder,0);
}
// ----------------------------------------------------------------------------------------
bigint_kernel_2& bigint_kernel_2::
operator%= (
const bigint_kernel_2& rhs
)
{
data_record* temp = new data_record(data->digits_used+slack);
data_record* remainder;
try {
remainder = new data_record(data->digits_used+slack);
} catch (...) { delete temp; throw; }
long_div(data,rhs.data,temp,remainder);
// check if there are other references to data
if (data->references != 1)
{
data->references -= 1;
}
// if there are no references to data then it must be deleted
else
{
delete data;
}
data = remainder;
delete temp;
return *this;
}
// ----------------------------------------------------------------------------------------
bool bigint_kernel_2::
operator < (
const bigint_kernel_2& rhs
) const
{
return is_less_than(data,rhs.data);
}
// ----------------------------------------------------------------------------------------
bool bigint_kernel_2::
operator == (
const bigint_kernel_2& rhs
) const
{
return is_equal_to(data,rhs.data);
}
// ----------------------------------------------------------------------------------------
bigint_kernel_2& bigint_kernel_2::
operator= (
const bigint_kernel_2& rhs
)
{
if (this == &rhs)
return *this;
// if we have the only reference to our data then delete it
if (data->references == 1)
{
delete data;
data = rhs.data;
data->references += 1;
}
else
{
data->references -= 1;
data = rhs.data;
data->references += 1;
}
return *this;
}
// ----------------------------------------------------------------------------------------
std::ostream& operator<< (
std::ostream& out_,
const bigint_kernel_2& rhs
)
{
std::ostream out(out_.rdbuf());
typedef bigint_kernel_2 bigint;
bigint::data_record* temp = new bigint::data_record(*rhs.data,0);
// get a char array big enough to hold the number in ascii format
char* str;
try {
str = new char[(rhs.data->digits_used)*5+10];
} catch (...) { delete temp; throw; }
char* str_start = str;
str += (rhs.data->digits_used)*5+9;
*str = 0; --str;
uint16 remainder;
rhs.short_div(temp,10000,temp,remainder);
// pull the digits out of remainder
char a = remainder % 10 + '0';
remainder /= 10;
char b = remainder % 10 + '0';
remainder /= 10;
char c = remainder % 10 + '0';
remainder /= 10;
char d = remainder % 10 + '0';
remainder /= 10;
*str = a; --str;
*str = b; --str;
*str = c; --str;
*str = d; --str;
// keep looping until temp represents zero
while (temp->digits_used != 1 || *(temp->number) != 0)
{
rhs.short_div(temp,10000,temp,remainder);
// pull the digits out of remainder
char a = remainder % 10 + '0';
remainder /= 10;
char b = remainder % 10 + '0';
remainder /= 10;
char c = remainder % 10 + '0';
remainder /= 10;
char d = remainder % 10 + '0';
remainder /= 10;
*str = a; --str;
*str = b; --str;
*str = c; --str;
*str = d; --str;
}
// throw away and extra leading zeros
++str;
if (*str == '0')
++str;
if (*str == '0')
++str;
if (*str == '0')
++str;
out << str;
delete [] str_start;
delete temp;
return out_;
}
// ----------------------------------------------------------------------------------------
std::istream& operator>> (
std::istream& in_,
bigint_kernel_2& rhs
)
{
std::istream in(in_.rdbuf());
// ignore any leading whitespaces
while (in.peek() == ' ' || in.peek() == '\t' || in.peek() == '\n')
{
in.get();
}
// if the first digit is not an integer then this is an error
if ( !(in.peek() >= '0' && in.peek() <= '9'))
{
in_.clear(std::ios::failbit);
return in_;
}
int num_read;
bigint_kernel_2 temp;
do
{
// try to get 4 chars from in
num_read = 1;
char a = 0;
char b = 0;
char c = 0;
char d = 0;
if (in.peek() >= '0' && in.peek() <= '9')
{
num_read *= 10;
a = in.get();
}
if (in.peek() >= '0' && in.peek() <= '9')
{
num_read *= 10;
b = in.get();
}
if (in.peek() >= '0' && in.peek() <= '9')
{
num_read *= 10;
c = in.get();
}
if (in.peek() >= '0' && in.peek() <= '9')
{
num_read *= 10;
d = in.get();
}
// merge the for digits into an uint16
uint16 num = 0;
if (a != 0)
{
num = a - '0';
}
if (b != 0)
{
num *= 10;
num += b - '0';
}
if (c != 0)
{
num *= 10;
num += c - '0';
}
if (d != 0)
{
num *= 10;
num += d - '0';
}
if (num_read != 1)
{
// shift the digits in temp left by the number of new digits we just read
temp *= num_read;
// add in new digits
temp += num;
}
} while (num_read == 10000);
rhs = temp;
return in_;
}
// ----------------------------------------------------------------------------------------
const bigint_kernel_2 operator+ (
uint16 lhs,
const bigint_kernel_2& rhs
)
{
typedef bigint_kernel_2 bigint;
bigint::data_record* temp = new bigint::data_record
(rhs.data->digits_used+rhs.slack);
rhs.short_add(rhs.data,lhs,temp);
return bigint_kernel_2(temp,0);
}
// ----------------------------------------------------------------------------------------
const bigint_kernel_2 operator+ (
const bigint_kernel_2& lhs,
uint16 rhs
)
{
typedef bigint_kernel_2 bigint;
bigint::data_record* temp = new bigint::data_record
(lhs.data->digits_used+lhs.slack);
lhs.short_add(lhs.data,rhs,temp);
return bigint_kernel_2(temp,0);
}
// ----------------------------------------------------------------------------------------
bigint_kernel_2& bigint_kernel_2::
operator+= (
uint16 rhs
)
{
// if there are other references to this data
if (data->references != 1)
{
data_record* temp = new data_record(data->digits_used+slack);
data->references -= 1;
short_add(data,rhs,temp);
data = temp;
}
// or if we need to enlarge data then do so
else if (data->digits_used == data->size)
{
data_record* temp = new data_record(data->digits_used+slack);
short_add(data,rhs,temp);
delete data;
data = temp;
}
// or if there is plenty of space and no references
else
{
short_add(data,rhs,data);
}
return *this;
}
// ----------------------------------------------------------------------------------------
const bigint_kernel_2 operator- (
uint16 lhs,
const bigint_kernel_2& rhs
)
{
typedef bigint_kernel_2 bigint;
bigint::data_record* temp = new bigint::data_record(rhs.slack);
*(temp->number) = lhs - *(rhs.data->number);
return bigint_kernel_2(temp,0);
}
// ----------------------------------------------------------------------------------------
const bigint_kernel_2 operator- (
const bigint_kernel_2& lhs,
uint16 rhs
)
{
typedef bigint_kernel_2 bigint;
bigint::data_record* temp = new bigint::data_record
(lhs.data->digits_used+lhs.slack);
lhs.short_sub(lhs.data,rhs,temp);
return bigint_kernel_2(temp,0);
}
// ----------------------------------------------------------------------------------------
bigint_kernel_2& bigint_kernel_2::
operator-= (
uint16 rhs
)
{
// if there are other references to this data
if (data->references != 1)
{
data_record* temp = new data_record(data->digits_used+slack);
data->references -= 1;
short_sub(data,rhs,temp);
data = temp;
}
else
{
short_sub(data,rhs,data);
}
return *this;
}
// ----------------------------------------------------------------------------------------
const bigint_kernel_2 operator* (
uint16 lhs,
const bigint_kernel_2& rhs
)
{
typedef bigint_kernel_2 bigint;
bigint::data_record* temp = new bigint::data_record
(rhs.data->digits_used+rhs.slack);
rhs.short_mul(rhs.data,lhs,temp);
return bigint_kernel_2(temp,0);
}
// ----------------------------------------------------------------------------------------
const bigint_kernel_2 operator* (
const bigint_kernel_2& lhs,
uint16 rhs
)
{
typedef bigint_kernel_2 bigint;
bigint::data_record* temp = new bigint::data_record
(lhs.data->digits_used+lhs.slack);
lhs.short_mul(lhs.data,rhs,temp);
return bigint_kernel_2(temp,0);
}
// ----------------------------------------------------------------------------------------
bigint_kernel_2& bigint_kernel_2::
operator*= (
uint16 rhs
)
{
// if there are other references to this data
if (data->references != 1)
{
data_record* temp = new data_record(data->digits_used+slack);
data->references -= 1;
short_mul(data,rhs,temp);
data = temp;
}
// or if we need to enlarge data
else if (data->digits_used == data->size)
{
data_record* temp = new data_record(data->digits_used+slack);
short_mul(data,rhs,temp);
delete data;
data = temp;
}
else
{
short_mul(data,rhs,data);
}
return *this;
}
// ----------------------------------------------------------------------------------------
const bigint_kernel_2 operator/ (
uint16 lhs,
const bigint_kernel_2& rhs
)
{
typedef bigint_kernel_2 bigint;
bigint::data_record* temp = new bigint::data_record(rhs.slack);
// if rhs might not be bigger than lhs
if (rhs.data->digits_used == 1)
{
*(temp->number) = lhs/ *(rhs.data->number);
}
return bigint_kernel_2(temp,0);
}
// ----------------------------------------------------------------------------------------
const bigint_kernel_2 operator/ (
const bigint_kernel_2& lhs,
uint16 rhs
)
{
typedef bigint_kernel_2 bigint;
bigint::data_record* temp = new bigint::data_record
(lhs.data->digits_used+lhs.slack);
uint16 remainder;
lhs.short_div(lhs.data,rhs,temp,remainder);
return bigint_kernel_2(temp,0);
}
// ----------------------------------------------------------------------------------------
bigint_kernel_2& bigint_kernel_2::
operator/= (
uint16 rhs
)
{
uint16 remainder;
// if there are other references to this data
if (data->references != 1)
{
data_record* temp = new data_record(data->digits_used+slack);
data->references -= 1;
short_div(data,rhs,temp,remainder);
data = temp;
}
else
{
short_div(data,rhs,data,remainder);
}
return *this;
}
// ----------------------------------------------------------------------------------------
const bigint_kernel_2 operator% (
uint16 lhs,
const bigint_kernel_2& rhs
)
{
typedef bigint_kernel_2 bigint;
// temp is zero by default
bigint::data_record* temp = new bigint::data_record(rhs.slack);
if (rhs.data->digits_used == 1)
{
// if rhs is just an uint16 inside then perform the modulus
*(temp->number) = lhs % *(rhs.data->number);
}
else
{
// if rhs is bigger than lhs then the answer is lhs
*(temp->number) = lhs;
}
return bigint_kernel_2(temp,0);
}
// ----------------------------------------------------------------------------------------
const bigint_kernel_2 operator% (
const bigint_kernel_2& lhs,
uint16 rhs
)
{
typedef bigint_kernel_2 bigint;
bigint::data_record* temp = new bigint::data_record(lhs.data->digits_used+lhs.slack);
uint16 remainder;
lhs.short_div(lhs.data,rhs,temp,remainder);
temp->digits_used = 1;
*(temp->number) = remainder;
return bigint_kernel_2(temp,0);
}
// ----------------------------------------------------------------------------------------
bigint_kernel_2& bigint_kernel_2::
operator%= (
uint16 rhs
)
{
uint16 remainder;
// if there are other references to this data
if (data->references != 1)
{
data_record* temp = new data_record(data->digits_used+slack);
data->references -= 1;
short_div(data,rhs,temp,remainder);
data = temp;
}
else
{
short_div(data,rhs,data,remainder);
}
data->digits_used = 1;
*(data->number) = remainder;
return *this;
}
// ----------------------------------------------------------------------------------------
bool operator < (
uint16 lhs,
const bigint_kernel_2& rhs
)
{
return (rhs.data->digits_used > 1 || lhs < *(rhs.data->number) );
}
// ----------------------------------------------------------------------------------------
bool operator < (
const bigint_kernel_2& lhs,
uint16 rhs
)
{
return (lhs.data->digits_used == 1 && *(lhs.data->number) < rhs);
}
// ----------------------------------------------------------------------------------------
bool operator == (
const bigint_kernel_2& lhs,
uint16 rhs
)
{
return (lhs.data->digits_used == 1 && *(lhs.data->number) == rhs);
}
// ----------------------------------------------------------------------------------------
bool operator == (
uint16 lhs,
const bigint_kernel_2& rhs
)
{
return (rhs.data->digits_used == 1 && *(rhs.data->number) == lhs);
}
// ----------------------------------------------------------------------------------------
bigint_kernel_2& bigint_kernel_2::
operator= (
uint16 rhs
)
{
// check if there are other references to our data
if (data->references != 1)
{
data->references -= 1;
try {
data = new data_record(slack);
} catch (...) { data->references += 1; throw; }
}
else
{
data->digits_used = 1;
}
*(data->number) = rhs;
return *this;
}
// ----------------------------------------------------------------------------------------
bigint_kernel_2& bigint_kernel_2::
operator++ (
)
{
// if there are other references to this data then make a copy of it
if (data->references != 1)
{
data_record* temp = new data_record(data->digits_used+slack);
data->references -= 1;
increment(data,temp);
data = temp;
}
// or if we need to enlarge data then do so
else if (data->digits_used == data->size)
{
data_record* temp = new data_record(data->digits_used+slack);
increment(data,temp);
delete data;
data = temp;
}
else
{
increment(data,data);
}
return *this;
}
// ----------------------------------------------------------------------------------------
const bigint_kernel_2 bigint_kernel_2::
operator++ (
int
)
{
data_record* temp; // this is the copy of temp we will return in the end
data_record* temp2 = new data_record(data->digits_used+slack);
increment(data,temp2);
temp = data;
data = temp2;
return bigint_kernel_2(temp,0);
}
// ----------------------------------------------------------------------------------------
bigint_kernel_2& bigint_kernel_2::
operator-- (
)
{
// if there are other references to this data
if (data->references != 1)
{
data_record* temp = new data_record(data->digits_used+slack);
data->references -= 1;
decrement(data,temp);
data = temp;
}
else
{
decrement(data,data);
}
return *this;
}
// ----------------------------------------------------------------------------------------
const bigint_kernel_2 bigint_kernel_2::
operator-- (
int
)
{
data_record* temp; // this is the copy of temp we will return in the end
data_record* temp2 = new data_record(data->digits_used+slack);
decrement(data,temp2);
temp = data;
data = temp2;
return bigint_kernel_2(temp,0);
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// private member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
void bigint_kernel_2::
short_add (
const data_record* data,
uint16 value,
data_record* result
) const
{
// put value into the carry part of temp
uint32 temp = value;
temp <<= 16;
const uint16* number = data->number;
const uint16* end = number + data->digits_used; // one past the end of number
uint16* r = result->number;
while (number != end)
{
// add *number and the current carry
temp = *number + (temp>>16);
// put the low word of temp into *r
*r = static_cast<uint16>(temp & 0xFFFF);
++number;
++r;
}
// if there is a final carry
if ((temp>>16) != 0)
{
result->digits_used = data->digits_used + 1;
// store the carry in the most significant digit of the result
*r = static_cast<uint16>(temp>>16);
}
else
{
result->digits_used = data->digits_used;
}
}
// ----------------------------------------------------------------------------------------
void bigint_kernel_2::
short_sub (
const data_record* data,
uint16 value,
data_record* result
) const
{
const uint16* number = data->number;
const uint16* end = number + data->digits_used - 1;
uint16* r = result->number;
uint32 temp = *number - value;
// put the low word of temp into *data
*r = static_cast<uint16>(temp & 0xFFFF);
while (number != end)
{
++number;
++r;
// subtract the carry from *number
temp = *number - (temp>>31);
// put the low word of temp into *r
*r = static_cast<uint16>(temp & 0xFFFF);
}
// if we lost a digit in the subtraction
if (*r == 0)
{
if (data->digits_used == 1)
result->digits_used = 1;
else
result->digits_used = data->digits_used - 1;
}
else
{
result->digits_used = data->digits_used;
}
}
// ----------------------------------------------------------------------------------------
void bigint_kernel_2::
short_mul (
const data_record* data,
uint16 value,
data_record* result
) const
{
uint32 temp = 0;
const uint16* number = data->number;
uint16* r = result->number;
const uint16* end = r + data->digits_used;
while ( r != end)
{
// multiply *data and value and add in the carry
temp = *number*(uint32)value + (temp>>16);
// put the low word of temp into *data
*r = static_cast<uint16>(temp & 0xFFFF);
++number;
++r;
}
// if there is a final carry
if ((temp>>16) != 0)
{
result->digits_used = data->digits_used + 1;
// put the final carry into the most significant digit of the result
*r = static_cast<uint16>(temp>>16);
}
else
{
result->digits_used = data->digits_used;
}
}
// ----------------------------------------------------------------------------------------
void bigint_kernel_2::
short_div (
const data_record* data,
uint16 value,
data_record* result,
uint16& rem
) const
{
uint16 remainder = 0;
uint32 temp;
const uint16* number = data->number + data->digits_used - 1;
const uint16* end = number - data->digits_used;
uint16* r = result->number + data->digits_used - 1;
// if we are losing a digit in this division
if (*number < value)
{
if (data->digits_used == 1)
result->digits_used = 1;
else
result->digits_used = data->digits_used - 1;
}
else
{
result->digits_used = data->digits_used;
}
// perform the actual division
while (number != end)
{
temp = *number + (((uint32)remainder)<<16);
*r = static_cast<uint16>(temp/value);
remainder = static_cast<uint16>(temp%value);
--number;
--r;
}
rem = remainder;
}
// ----------------------------------------------------------------------------------------
void bigint_kernel_2::
long_add (
const data_record* lhs,
const data_record* rhs,
data_record* result
) const
{
// put value into the carry part of temp
uint32 temp=0;
uint16* min_num; // the number with the least digits used
uint16* max_num; // the number with the most digits used
uint16* min_end; // one past the end of min_num
uint16* max_end; // one past the end of max_num
uint16* r = result->number;
uint32 max_digits_used;
if (lhs->digits_used < rhs->digits_used)
{
max_digits_used = rhs->digits_used;
min_num = lhs->number;
max_num = rhs->number;
min_end = min_num + lhs->digits_used;
max_end = max_num + rhs->digits_used;
}
else
{
max_digits_used = lhs->digits_used;
min_num = rhs->number;
max_num = lhs->number;
min_end = min_num + rhs->digits_used;
max_end = max_num + lhs->digits_used;
}
while (min_num != min_end)
{
// add *min_num, *max_num and the current carry
temp = *min_num + *max_num + (temp>>16);
// put the low word of temp into *r
*r = static_cast<uint16>(temp & 0xFFFF);
++min_num;
++max_num;
++r;
}
while (max_num != max_end)
{
// add *max_num and the current carry
temp = *max_num + (temp>>16);
// put the low word of temp into *r
*r = static_cast<uint16>(temp & 0xFFFF);
++max_num;
++r;
}
// check if there was a final carry
if ((temp>>16) != 0)
{
result->digits_used = max_digits_used + 1;
// put the carry into the most significant digit in the result
*r = static_cast<uint16>(temp>>16);
}
else
{
result->digits_used = max_digits_used;
}
}
// ----------------------------------------------------------------------------------------
void bigint_kernel_2::
long_sub (
const data_record* lhs,
const data_record* rhs,
data_record* result
) const
{
const uint16* number1 = lhs->number;
const uint16* number2 = rhs->number;
const uint16* end = number2 + rhs->digits_used;
uint16* r = result->number;
uint32 temp =0;
while (number2 != end)
{
// subtract *number2 from *number1 and then subtract any carry
temp = *number1 - *number2 - (temp>>31);
// put the low word of temp into *r
*r = static_cast<uint16>(temp & 0xFFFF);
++number1;
++number2;
++r;
}
end = lhs->number + lhs->digits_used;
while (number1 != end)
{
// subtract the carry from *number1
temp = *number1 - (temp>>31);
// put the low word of temp into *r
*r = static_cast<uint16>(temp & 0xFFFF);
++number1;
++r;
}
result->digits_used = lhs->digits_used;
// adjust the number of digits used appropriately
--r;
while (*r == 0 && result->digits_used > 1)
{
--r;
--result->digits_used;
}
}
// ----------------------------------------------------------------------------------------
void bigint_kernel_2::
long_div (
const data_record* lhs,
const data_record* rhs,
data_record* result,
data_record* remainder
) const
{
// zero result
result->digits_used = 1;
*(result->number) = 0;
uint16* a;
uint16* b;
uint16* end;
// copy lhs into remainder
remainder->digits_used = lhs->digits_used;
a = remainder->number;
end = a + remainder->digits_used;
b = lhs->number;
while (a != end)
{
*a = *b;
++a;
++b;
}
// if rhs is bigger than lhs then result == 0 and remainder == lhs
// so then we can quit right now
if (is_less_than(lhs,rhs))
{
return;
}
// make a temporary number
data_record temp(lhs->digits_used + slack);
// shift rhs left until it is one shift away from being larger than lhs and
// put the number of left shifts necessary into shifts
uint32 shifts;
shifts = (lhs->digits_used - rhs->digits_used) * 16;
shift_left(rhs,&temp,shifts);
// while (lhs > temp)
while (is_less_than(&temp,lhs))
{
shift_left(&temp,&temp,1);
++shifts;
}
// make sure lhs isn't smaller than temp
while (is_less_than(lhs,&temp))
{
shift_right(&temp,&temp);
--shifts;
}
// we want to execute the loop shifts +1 times
++shifts;
while (shifts != 0)
{
shift_left(result,result,1);
// if (temp <= remainder)
if (!is_less_than(remainder,&temp))
{
long_sub(remainder,&temp,remainder);
// increment result
uint16* r = result->number;
uint16* end = r + result->digits_used;
while (true)
{
++(*r);
// if there was no carry then we are done
if (*r != 0)
break;
++r;
// if we hit the end of r and there is still a carry then
// the next digit of r is 1 and there is one more digit used
if (r == end)
{
*r = 1;
++(result->digits_used);
break;
}
}
}
shift_right(&temp,&temp);
--shifts;
}
}
// ----------------------------------------------------------------------------------------
void bigint_kernel_2::
long_mul (
const data_record* lhs,
const data_record* rhs,
data_record* result
) const
{
// if one of the numbers is small then use this simple but O(n^2) algorithm
if (std::min(lhs->digits_used, rhs->digits_used) < 10)
{
// make result be zero
result->digits_used = 1;
*(result->number) = 0;
const data_record* aa;
const data_record* bb;
if (lhs->digits_used < rhs->digits_used)
{
// make copies of lhs and rhs and give them an appropriate amount of
// extra memory so there won't be any overflows
aa = lhs;
bb = rhs;
}
else
{
// make copies of lhs and rhs and give them an appropriate amount of
// extra memory so there won't be any overflows
aa = rhs;
bb = lhs;
}
// copy the larger(approximately) of lhs and rhs into b
data_record b(*bb,aa->digits_used+slack);
uint32 shift_value = 0;
uint16* anum = aa->number;
uint16* end = anum + aa->digits_used;
while (anum != end )
{
uint16 bit = 0x0001;
for (int i = 0; i < 16; ++i)
{
// if the specified bit of a is 1
if ((*anum & bit) != 0)
{
shift_left(&b,&b,shift_value);
shift_value = 0;
long_add(&b,result,result);
}
++shift_value;
bit <<= 1;
}
++anum;
}
}
else // else if both lhs and rhs are large then use the more complex
// O(n*logn) algorithm
{
uint32 size = 1;
// make size a power of 2
while (size < (lhs->digits_used + rhs->digits_used)*2)
{
size *= 2;
}
// allocate some temporary space so we can do the FFT
ct* a = new ct[size];
ct* b; try {b = new ct[size]; } catch (...) { delete [] a; throw; }
// load lhs into the a array. We are breaking the input number into
// 8bit chunks for the purpose of using this fft algorithm. The reason
// for this is so that we have smaller numbers coming out of the final
// ifft. This helps avoid overflow.
for (uint32 i = 0; i < lhs->digits_used; ++i)
{
a[i*2] = ct((t)(lhs->number[i]&0xFF),0);
a[i*2+1] = ct((t)(lhs->number[i]>>8),0);
}
for (uint32 i = lhs->digits_used*2; i < size; ++i)
{
a[i] = 0;
}
// load rhs into the b array
for (uint32 i = 0; i < rhs->digits_used; ++i)
{
b[i*2] = ct((t)(rhs->number[i]&0xFF),0);
b[i*2+1] = ct((t)(rhs->number[i]>>8),0);
}
for (uint32 i = rhs->digits_used*2; i < size; ++i)
{
b[i] = 0;
}
// perform the forward fft of a and b
fft(a,size);
fft(b,size);
const double l = 1.0/size;
// do the pointwise multiply of a and b and also apply the scale
// factor in this loop too.
for (unsigned long i = 0; i < size; ++i)
{
a[i] = l*a[i]*b[i];
}
// Now compute the inverse fft of the pointwise multiplication of a and b.
// This is basically the result. We just have to take care of any carries
// that should happen.
ifft(a,size);
// loop over the result and propagate any carries that need to take place.
// We will also be moving the resulting numbers into result->number at
// the same time.
uint64 carry = 0;
result->digits_used = 0;
int zeros = 0;
const uint32 len = lhs->digits_used + rhs->digits_used;
for (unsigned long i = 0; i < len; ++i)
{
uint64 num1 = static_cast<uint64>(std::round(a[i*2].real()));
num1 += carry;
carry = 0;
if (num1 > 255)
{
carry = num1 >> 8;
num1 = (num1&0xFF);
}
uint64 num2 = static_cast<uint64>(std::round(a[i*2+1].real()));
num2 += carry;
carry = 0;
if (num2 > 255)
{
carry = num2 >> 8;
num2 = (num2&0xFF);
}
// put the new number into its final place
num1 = (num2<<8) | num1;
result->number[i] = static_cast<uint16>(num1);
// keep track of the number of leading zeros
if (num1 == 0)
++zeros;
else
zeros = 0;
++(result->digits_used);
}
// adjust digits_used so that it reflects the actual number
// of non-zero digits in our representation.
result->digits_used -= zeros;
// if the result was zero then adjust the result accordingly
if (result->digits_used == 0)
{
// make result be zero
result->digits_used = 1;
*(result->number) = 0;
}
// free all the temporary buffers
delete [] a;
delete [] b;
}
}
// ----------------------------------------------------------------------------------------
void bigint_kernel_2::
shift_left (
const data_record* data,
data_record* result,
uint32 shift_amount
) const
{
uint32 offset = shift_amount/16;
shift_amount &= 0xf; // same as shift_amount %= 16;
uint16* r = result->number + data->digits_used + offset; // result
uint16* end = data->number;
uint16* s = end + data->digits_used; // source
const uint32 temp = 16 - shift_amount;
*r = (*(--s) >> temp);
// set the number of digits used in the result
// if the upper bits from *s were zero then don't count this first word
if (*r == 0)
{
result->digits_used = data->digits_used + offset;
}
else
{
result->digits_used = data->digits_used + offset + 1;
}
--r;
while (s != end)
{
*r = ((*s << shift_amount) | ( *(s-1) >> temp));
--r;
--s;
}
*r = *s << shift_amount;
// now zero the rest of the result
end = result->number;
while (r != end)
*(--r) = 0;
}
// ----------------------------------------------------------------------------------------
void bigint_kernel_2::
shift_right (
const data_record* data,
data_record* result
) const
{
uint16* r = result->number; // result
uint16* s = data->number; // source
uint16* end = s + data->digits_used - 1;
while (s != end)
{
*r = (*s >> 1) | (*(s+1) << 15);
++r;
++s;
}
*r = *s >> 1;
// calculate the new number for digits_used
if (*r == 0)
{
if (data->digits_used != 1)
result->digits_used = data->digits_used - 1;
else
result->digits_used = 1;
}
else
{
result->digits_used = data->digits_used;
}
}
// ----------------------------------------------------------------------------------------
bool bigint_kernel_2::
is_less_than (
const data_record* lhs,
const data_record* rhs
) const
{
uint32 lhs_digits_used = lhs->digits_used;
uint32 rhs_digits_used = rhs->digits_used;
// if lhs is definitely less than rhs
if (lhs_digits_used < rhs_digits_used )
return true;
// if lhs is definitely greater than rhs
else if (lhs_digits_used > rhs_digits_used)
return false;
else
{
uint16* end = lhs->number;
uint16* l = end + lhs_digits_used;
uint16* r = rhs->number + rhs_digits_used;
while (l != end)
{
--l;
--r;
if (*l < *r)
return true;
else if (*l > *r)
return false;
}
// at this point we know that they are equal
return false;
}
}
// ----------------------------------------------------------------------------------------
bool bigint_kernel_2::
is_equal_to (
const data_record* lhs,
const data_record* rhs
) const
{
// if lhs and rhs are definitely not equal
if (lhs->digits_used != rhs->digits_used )
{
return false;
}
else
{
uint16* l = lhs->number;
uint16* r = rhs->number;
uint16* end = l + lhs->digits_used;
while (l != end)
{
if (*l != *r)
return false;
++l;
++r;
}
// at this point we know that they are equal
return true;
}
}
// ----------------------------------------------------------------------------------------
void bigint_kernel_2::
increment (
const data_record* source,
data_record* dest
) const
{
uint16* s = source->number;
uint16* d = dest->number;
uint16* end = s + source->digits_used;
while (true)
{
*d = *s + 1;
// if there was no carry then break out of the loop
if (*d != 0)
{
dest->digits_used = source->digits_used;
// copy the rest of the digits over to d
++d; ++s;
while (s != end)
{
*d = *s;
++d;
++s;
}
break;
}
++s;
// if we have hit the end of s and there was a carry up to this point
// then just make the next digit 1 and add one to the digits used
if (s == end)
{
++d;
dest->digits_used = source->digits_used + 1;
*d = 1;
break;
}
++d;
}
}
// ----------------------------------------------------------------------------------------
void bigint_kernel_2::
decrement (
const data_record* source,
data_record* dest
) const
{
uint16* s = source->number;
uint16* d = dest->number;
uint16* end = s + source->digits_used;
while (true)
{
*d = *s - 1;
// if there was no carry then break out of the loop
if (*d != 0xFFFF)
{
// if we lost a digit in the subtraction
if (*d == 0 && s+1 == end)
{
if (source->digits_used == 1)
dest->digits_used = 1;
else
dest->digits_used = source->digits_used - 1;
}
else
{
dest->digits_used = source->digits_used;
}
break;
}
else
{
++d;
++s;
}
}
// copy the rest of the digits over to d
++d;
++s;
while (s != end)
{
*d = *s;
++d;
++s;
}
}
// ----------------------------------------------------------------------------------------
void bigint_kernel_2::
fft (
ct* data,
unsigned long len
) const
{
const t pi2 = -2.0*3.1415926535897932384626433832795028841971693993751;
const unsigned long half = len/2;
std::vector<ct> twiddle_factors;
twiddle_factors.resize(half);
// compute the complex root of unity w
const t temp = pi2/len;
ct w = ct(std::cos(temp),std::sin(temp));
ct w_pow = 1;
// compute the twiddle factors
for (std::vector<ct>::size_type j = 0; j < twiddle_factors.size(); ++j)
{
twiddle_factors[j] = w_pow;
w_pow *= w;
}
ct a, b;
// now compute the decimation in frequency. This first
// outer loop loops log2(len) number of times
unsigned long skip = 1;
for (unsigned long step = half; step != 0; step >>= 1)
{
// do blocks of butterflies in this loop
for (unsigned long j = 0; j < len; j += step*2)
{
// do step butterflies
for (unsigned long k = 0; k < step; ++k)
{
const unsigned long a_idx = j+k;
const unsigned long b_idx = j+k+step;
a = data[a_idx] + data[b_idx];
b = (data[a_idx] - data[b_idx])*twiddle_factors[k*skip];
data[a_idx] = a;
data[b_idx] = b;
}
}
skip *= 2;
}
}
// ----------------------------------------------------------------------------------------
void bigint_kernel_2::
ifft(
ct* data,
unsigned long len
) const
{
const t pi2 = 2.0*3.1415926535897932384626433832795028841971693993751;
const unsigned long half = len/2;
std::vector<ct> twiddle_factors;
twiddle_factors.resize(half);
// compute the complex root of unity w
const t temp = pi2/len;
ct w = ct(std::cos(temp),std::sin(temp));
ct w_pow = 1;
// compute the twiddle factors
for (std::vector<ct>::size_type j = 0; j < twiddle_factors.size(); ++j)
{
twiddle_factors[j] = w_pow;
w_pow *= w;
}
ct a, b;
// now compute the inverse decimation in frequency. This first
// outer loop loops log2(len) number of times
unsigned long skip = half;
for (unsigned long step = 1; step <= half; step <<= 1)
{
// do blocks of butterflies in this loop
for (unsigned long j = 0; j < len; j += step*2)
{
// do step butterflies
for (unsigned long k = 0; k < step; ++k)
{
const unsigned long a_idx = j+k;
const unsigned long b_idx = j+k+step;
data[b_idx] *= twiddle_factors[k*skip];
a = data[a_idx] + data[b_idx];
b = data[a_idx] - data[b_idx];
data[a_idx] = a;
data[b_idx] = b;
}
}
skip /= 2;
}
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_BIGINT_KERNEL_2_CPp_
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_BIGINT_KERNEl_2_
#define DLIB_BIGINT_KERNEl_2_
#include "bigint_kernel_abstract.h"
#include "../algs.h"
#include "../serialize.h"
#include "../uintn.h"
#include <iosfwd>
#include <cmath>
#include <complex>
#include <vector>
namespace dlib
{
class bigint_kernel_2
{
/*!
INITIAL VALUE
slack == 25
data->number[0] == 0
data->size == slack
data->references == 1
data->digits_used == 1
CONVENTION
slack == the number of extra digits placed into the number when it is
created. the slack value should never be less than 1
data->number == pointer to an array of data->size uint16s.
data represents a string of base 65535 numbers with data[0] being
the least significant bit and data[data->digits_used-1] being the most
significant
NOTE: In the comments I will consider a word to be a 16 bit value
data->digits_used == the number of significant digits in the number.
data->digits_used tells us the number of used elements in the
data->number array so everything beyond data->number[data->digits_used-1]
is undefined
data->references == the number of bigint_kernel_2 objects which refer
to this data_record
!*/
struct data_record
{
explicit data_record(
uint32 size_
) :
size(size_),
number(new uint16[size_]),
references(1),
digits_used(1)
{*number = 0;}
/*!
ensures
- initializes *this to represent zero
!*/
data_record(
const data_record& item,
uint32 additional_size
) :
size(item.digits_used + additional_size),
number(new uint16[size]),
references(1),
digits_used(item.digits_used)
{
uint16* source = item.number;
uint16* dest = number;
uint16* end = source + digits_used;
while (source != end)
{
*dest = *source;
++dest;
++source;
}
}
/*!
ensures
- *this is a copy of item except with
size == item.digits_used + additional_size
!*/
~data_record(
)
{
delete [] number;
}
const uint32 size;
uint16* number;
uint32 references;
uint32 digits_used;
private:
// no copy constructor
data_record ( data_record&);
};
// note that the second parameter is just there
// to resolve the ambiguity between this constructor and
// bigint_kernel_2(uint32)
explicit bigint_kernel_2 (
data_record* data_, int
): slack(25),data(data_) {}
/*!
ensures
- *this is initialized with data_ as its data member
!*/
public:
bigint_kernel_2 (
);
bigint_kernel_2 (
uint32 value
);
bigint_kernel_2 (
const bigint_kernel_2& item
);
virtual ~bigint_kernel_2 (
);
const bigint_kernel_2 operator+ (
const bigint_kernel_2& rhs
) const;
bigint_kernel_2& operator+= (
const bigint_kernel_2& rhs
);
const bigint_kernel_2 operator- (
const bigint_kernel_2& rhs
) const;
bigint_kernel_2& operator-= (
const bigint_kernel_2& rhs
);
const bigint_kernel_2 operator* (
const bigint_kernel_2& rhs
) const;
bigint_kernel_2& operator*= (
const bigint_kernel_2& rhs
);
const bigint_kernel_2 operator/ (
const bigint_kernel_2& rhs
) const;
bigint_kernel_2& operator/= (
const bigint_kernel_2& rhs
);
const bigint_kernel_2 operator% (
const bigint_kernel_2& rhs
) const;
bigint_kernel_2& operator%= (
const bigint_kernel_2& rhs
);
bool operator < (
const bigint_kernel_2& rhs
) const;
bool operator == (
const bigint_kernel_2& rhs
) const;
bigint_kernel_2& operator= (
const bigint_kernel_2& rhs
);
friend std::ostream& operator<< (
std::ostream& out,
const bigint_kernel_2& rhs
);
friend std::istream& operator>> (
std::istream& in,
bigint_kernel_2& rhs
);
bigint_kernel_2& operator++ (
);
const bigint_kernel_2 operator++ (
int
);
bigint_kernel_2& operator-- (
);
const bigint_kernel_2 operator-- (
int
);
friend const bigint_kernel_2 operator+ (
uint16 lhs,
const bigint_kernel_2& rhs
);
friend const bigint_kernel_2 operator+ (
const bigint_kernel_2& lhs,
uint16 rhs
);
bigint_kernel_2& operator+= (
uint16 rhs
);
friend const bigint_kernel_2 operator- (
uint16 lhs,
const bigint_kernel_2& rhs
);
friend const bigint_kernel_2 operator- (
const bigint_kernel_2& lhs,
uint16 rhs
);
bigint_kernel_2& operator-= (
uint16 rhs
);
friend const bigint_kernel_2 operator* (
uint16 lhs,
const bigint_kernel_2& rhs
);
friend const bigint_kernel_2 operator* (
const bigint_kernel_2& lhs,
uint16 rhs
);
bigint_kernel_2& operator*= (
uint16 rhs
);
friend const bigint_kernel_2 operator/ (
uint16 lhs,
const bigint_kernel_2& rhs
);
friend const bigint_kernel_2 operator/ (
const bigint_kernel_2& lhs,
uint16 rhs
);
bigint_kernel_2& operator/= (
uint16 rhs
);
friend const bigint_kernel_2 operator% (
uint16 lhs,
const bigint_kernel_2& rhs
);
friend const bigint_kernel_2 operator% (
const bigint_kernel_2& lhs,
uint16 rhs
);
bigint_kernel_2& operator%= (
uint16 rhs
);
friend bool operator < (
uint16 lhs,
const bigint_kernel_2& rhs
);
friend bool operator < (
const bigint_kernel_2& lhs,
uint16 rhs
);
friend bool operator == (
const bigint_kernel_2& lhs,
uint16 rhs
);
friend bool operator == (
uint16 lhs,
const bigint_kernel_2& rhs
);
bigint_kernel_2& operator= (
uint16 rhs
);
void swap (
bigint_kernel_2& item
) { data_record* temp = data; data = item.data; item.data = temp; }
private:
typedef double t;
typedef std::complex<t> ct;
void fft(
ct* data,
unsigned long len
) const;
/*!
requires
- len == x^n for some integer n (i.e. len is a power of 2)
- len > 0
ensures
- #data == the FT decimation in frequency of data
!*/
void ifft(
ct* data,
unsigned long len
) const;
/*!
requires
- len == x^n for some integer n (i.e. len is a power of 2)
- len > 0
ensures
- #data == the inverse decimation in frequency of data.
(i.e. the inverse of what fft(data,len,-1) does to data)
!*/
void long_add (
const data_record* lhs,
const data_record* rhs,
data_record* result
) const;
/*!
requires
- result->size >= max(lhs->digits_used,rhs->digits_used) + 1
ensures
- result == lhs + rhs
!*/
void long_sub (
const data_record* lhs,
const data_record* rhs,
data_record* result
) const;
/*!
requires
- lhs >= rhs
- result->size >= lhs->digits_used
ensures
- result == lhs - rhs
!*/
void long_div (
const data_record* lhs,
const data_record* rhs,
data_record* result,
data_record* remainder
) const;
/*!
requires
- rhs != 0
- result->size >= lhs->digits_used
- remainder->size >= lhs->digits_used
- each parameter is unique (i.e. lhs != result, lhs != remainder, etc.)
ensures
- result == lhs / rhs
- remainder == lhs % rhs
!*/
void long_mul (
const data_record* lhs,
const data_record* rhs,
data_record* result
) const;
/*!
requires
- result->size >= lhs->digits_used + rhs->digits_used
- result != lhs
- result != rhs
ensures
- result == lhs * rhs
!*/
void short_add (
const data_record* data,
uint16 value,
data_record* result
) const;
/*!
requires
- result->size >= data->size + 1
ensures
- result == data + value
!*/
void short_sub (
const data_record* data,
uint16 value,
data_record* result
) const;
/*!
requires
- data >= value
- result->size >= data->digits_used
ensures
- result == data - value
!*/
void short_mul (
const data_record* data,
uint16 value,
data_record* result
) const;
/*!
requires
- result->size >= data->digits_used + 1
ensures
- result == data * value
!*/
void short_div (
const data_record* data,
uint16 value,
data_record* result,
uint16& remainder
) const;
/*!
requires
- value != 0
- result->size >= data->digits_used
ensures
- result = data*value
- remainder = data%value
!*/
void shift_left (
const data_record* data,
data_record* result,
uint32 shift_amount
) const;
/*!
requires
- result->size >= data->digits_used + shift_amount/8 + 1
ensures
- result == data << shift_amount
!*/
void shift_right (
const data_record* data,
data_record* result
) const;
/*!
requires
- result->size >= data->digits_used
ensures
- result == data >> 1
!*/
bool is_less_than (
const data_record* lhs,
const data_record* rhs
) const;
/*!
ensures
- returns true if lhs < rhs
- returns false otherwise
!*/
bool is_equal_to (
const data_record* lhs,
const data_record* rhs
) const;
/*!
ensures
- returns true if lhs == rhs
- returns false otherwise
!*/
void increment (
const data_record* source,
data_record* dest
) const;
/*!
requires
- dest->size >= source->digits_used + 1
ensures
- dest = source + 1
!*/
void decrement (
const data_record* source,
data_record* dest
) const;
/*!
requires
source != 0
ensuers
dest = source - 1
!*/
// member data
const uint32 slack;
data_record* data;
};
inline void swap (
bigint_kernel_2& a,
bigint_kernel_2& b
) { a.swap(b); }
inline void serialize (
const bigint_kernel_2& item,
std::ostream& out
)
{
std::ios::fmtflags oldflags = out.flags();
out << item << ' ';
out.flags(oldflags);
if (!out) throw serialization_error("Error serializing object of type bigint_kernel_c");
}
inline void deserialize (
bigint_kernel_2& item,
std::istream& in
)
{
std::ios::fmtflags oldflags = in.flags();
in >> item;
in.flags(oldflags);
if (in.get() != ' ')
{
item = 0;
throw serialization_error("Error deserializing object of type bigint_kernel_c");
}
}
inline bool operator> (const bigint_kernel_2& a, const bigint_kernel_2& b) { return b < a; }
inline bool operator!= (const bigint_kernel_2& a, const bigint_kernel_2& b) { return !(a == b); }
inline bool operator<= (const bigint_kernel_2& a, const bigint_kernel_2& b) { return !(b < a); }
inline bool operator>= (const bigint_kernel_2& a, const bigint_kernel_2& b) { return !(a < b); }
}
#ifdef NO_MAKEFILE
#include "bigint_kernel_2.cpp"
#endif
#endif // DLIB_BIGINT_KERNEl_2_
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_BIGINT_KERNEl_ABSTRACT_
#ifdef DLIB_BIGINT_KERNEl_ABSTRACT_
#include <iosfwd>
#include "../algs.h"
#include "../serialize.h"
#include "../uintn.h"
namespace dlib
{
class bigint
{
/*!
INITIAL VALUE
*this == 0
WHAT THIS OBJECT REPRESENTS
This object represents an arbitrary precision unsigned integer
the following operators are supported:
operator +
operator +=
operator -
operator -=
operator *
operator *=
operator /
operator /=
operator %
operator %=
operator ==
operator <
operator =
operator << (for writing to ostreams)
operator >> (for reading from istreams)
operator++ // pre increment
operator++(int) // post increment
operator-- // pre decrement
operator--(int) // post decrement
the other comparison operators(>, !=, <=, and >=) are
available and come from the templates in dlib::relational_operators
THREAD SAFETY
bigint may be reference counted so it is very unthread safe.
use with care in a multithreaded program
!*/
public:
bigint (
);
/*!
ensures
- #*this is properly initialized
throws
- std::bad_alloc
if this is thrown the bigint will be unusable but
will not leak memory
!*/
bigint (
uint32 value
);
/*!
requires
- value <= (2^32)-1
ensures
- #*this is properly initialized
- #*this == value
throws
- std::bad_alloc
if this is thrown the bigint will be unusable but
will not leak memory
!*/
bigint (
const bigint& item
);
/*!
ensures
- #*this is properly initialized
- #*this == value
throws
- std::bad_alloc
if this is thrown the bigint will be unusable but
will not leak memory
!*/
virtual ~bigint (
);
/*!
ensures
- all resources associated with #*this have been released
!*/
const bigint operator+ (
const bigint& rhs
) const;
/*!
ensures
- returns the result of adding rhs to *this
throws
- std::bad_alloc
if this function throws then it has no effect
!*/
bigint& operator+= (
const bigint& rhs
);
/*!
ensures
- #*this == *this + rhs
- returns #*this
throws
- std::bad_alloc
if this function throws then it has no effect
!*/
const bigint operator- (
const bigint& rhs
) const;
/*!
requires
- *this >= rhs
ensures
- returns the result of subtracting rhs from *this
throws
- std::bad_alloc
if this function throws then it has no effect
!*/
bigint& operator-= (
const bigint& rhs
);
/*!
requires
- *this >= rhs
ensures
- #*this == *this - rhs
- returns #*this
throws
- std::bad_alloc
if this function throws then it has no effect
!*/
const bigint operator* (
const bigint& rhs
) const;
/*!
ensures
- returns the result of multiplying *this and rhs
throws
- std::bad_alloc
if this function throws then it has no effect
!*/
bigint& operator*= (
const bigint& rhs
);
/*!
ensures
- #*this == *this * rhs
- returns #*this
throws
- std::bad_alloc
if this function throws then it has no effect
!*/
const bigint operator/ (
const bigint& rhs
) const;
/*!
requires
- rhs != 0
ensures
- returns the result of dividing *this by rhs
throws
- std::bad_alloc
if this function throws then it has no effect
!*/
bigint& operator/= (
const bigint& rhs
);
/*!
requires
- rhs != 0
ensures
- #*this == *this / rhs
- returns #*this
throws
- std::bad_alloc
if this function throws then it has no effect
!*/
const bigint operator% (
const bigint& rhs
) const;
/*!
requires
- rhs != 0
ensures
- returns the result of *this mod rhs
throws
- std::bad_alloc
if this function throws then it has no effect
!*/
bigint& operator%= (
const bigint& rhs
);
/*!
requires
- rhs != 0
ensures
- #*this == *this % rhs
- returns #*this
throws
- std::bad_alloc
if this function throws then it has no effect
!*/
bool operator < (
const bigint& rhs
) const;
/*!
ensures
- returns true if *this is less than rhs
- returns false otherwise
!*/
bool operator == (
const bigint& rhs
) const;
/*!
ensures
- returns true if *this and rhs represent the same number
- returns false otherwise
!*/
bigint& operator= (
const bigint& rhs
);
/*!
ensures
- #*this == rhs
throws
- std::bad_alloc
if this function throws then it has no effect
!*/
friend std::ostream& operator<< (
std::ostream& out,
const bigint& rhs
);
/*!
ensures
- the number in *this has been written to #out as a base ten number
throws
- std::bad_alloc
if this function throws then it has no effect (nothing
is written to out)
!*/
friend std::istream& operator>> (
std::istream& in,
bigint& rhs
);
/*!
ensures
- reads a number from in and puts it into #*this
- if (there is no positive base ten number on the input stream ) then
- #in.fail() == true
throws
- std::bad_alloc
if this function throws the value in rhs is undefined and some
characters may have been read from in. rhs is still usable though,
its value is just unknown.
!*/
bigint& operator++ (
);
/*!
ensures
- #*this == *this + 1
- returns #*this
throws
- std::bad_alloc
if this function throws then it has no effect
!*/
const bigint operator++ (
int
);
/*!
ensures
- #*this == *this + 1
- returns *this
throws
- std::bad_alloc
if this function throws then it has no effect
!*/
bigint& operator-- (
);
/*!
requires
- *this != 0
ensures
- #*this == *this - 1
- returns #*this
throws
- std::bad_alloc
if this function throws then it has no effect
!*/
const bigint operator-- (
int
);
/*!
requires
- *this != 0
ensures
- #*this == *this - 1
- returns *this
throws
- std::bad_alloc
if this function throws then it has no effect
!*/
void swap (
bigint& item
);
/*!
ensures
- swaps *this and item
!*/
// ------------------------------------------------------------------
// ---- The following functions are identical to the above -----
// ---- but take uint16 as one of their arguments. They ---
// ---- exist only to allow for a more efficient implementation ---
// ------------------------------------------------------------------
friend const bigint operator+ (
uint16 lhs,
const bigint& rhs
);
/*!
requires
- lhs <= 65535
ensures
- returns the result of adding rhs to lhs
throws
- std::bad_alloc
if this function throws then it has no effect
!*/
friend const bigint operator+ (
const bigint& lhs,
uint16 rhs
);
/*!
requires
- rhs <= 65535
ensures
- returns the result of adding rhs to lhs
throws
- std::bad_alloc
if this function throws then it has no effect
!*/
bigint& operator+= (
uint16 rhs
);
/*!
requires
- rhs <= 65535
ensures
- #*this == *this + rhs
- returns #this
throws
- std::bad_alloc
if this function throws then it has no effect
!*/
friend const bigint operator- (
uint16 lhs,
const bigint& rhs
);
/*!
requires
- lhs >= rhs
- lhs <= 65535
ensures
- returns the result of subtracting rhs from lhs
throws
- std::bad_alloc
if this function throws then it has no effect
!*/
friend const bigint operator- (
const bigint& lhs,
uint16 rhs
);
/*!
requires
- lhs >= rhs
- rhs <= 65535
ensures
- returns the result of subtracting rhs from lhs
throws
- std::bad_alloc
if this function throws then it has no effect
!*/
bigint& operator-= (
uint16 rhs
);
/*!
requires
- *this >= rhs
- rhs <= 65535
ensures
- #*this == *this - rhs
- returns #*this
throws
- std::bad_alloc
if this function throws then it has no effect
!*/
friend const bigint operator* (
uint16 lhs,
const bigint& rhs
);
/*!
requires
- lhs <= 65535
ensures
- returns the result of multiplying lhs and rhs
throws
- std::bad_alloc
if this function throws then it has no effect
!*/
friend const bigint operator* (
const bigint& lhs,
uint16 rhs
);
/*!
requires
- rhs <= 65535
ensures
- returns the result of multiplying lhs and rhs
throws
- std::bad_alloc
if this function throws then it has no effect
!*/
bigint& operator*= (
uint16 rhs
);
/*!
requires
- rhs <= 65535
ensures
- #*this == *this * rhs
- returns #*this
throws
- std::bad_alloc
if this function throws then it has no effect
!*/
friend const bigint operator/ (
uint16 lhs,
const bigint& rhs
);
/*!
requires
- rhs != 0
- lhs <= 65535
ensures
- returns the result of dividing lhs by rhs
throws
- std::bad_alloc
if this function throws then it has no effect
!*/
friend const bigint operator/ (
const bigint& lhs,
uint16 rhs
);
/*!
requires
- rhs != 0
- rhs <= 65535
ensures
- returns the result of dividing lhs by rhs
throws
- std::bad_alloc
if this function throws then it has no effect
!*/
bigint& operator/= (
uint16 rhs
);
/*!
requires
- rhs != 0
- rhs <= 65535
ensures
- #*this == *this / rhs
- returns #*this
throws
- std::bad_alloc
if this function throws then it has no effect
!*/
friend const bigint operator% (
uint16 lhs,
const bigint& rhs
);
/*!
requires
- rhs != 0
- lhs <= 65535
ensures
- returns the result of lhs mod rhs
throws
- std::bad_alloc
if this function throws then it has no effect
!*/
friend const bigint operator% (
const bigint& lhs,
uint16 rhs
);
/*!
requires
- rhs != 0
- rhs <= 65535
ensures
- returns the result of lhs mod rhs
throws
- std::bad_alloc
if this function throws then it has no effect
!*/
bigint& operator%= (
uint16 rhs
);
/*!
requires
- rhs != 0
- rhs <= 65535
ensures
- #*this == *this % rhs
- returns #*this
throws
- std::bad_alloc
if this function throws then it has no effect
!*/
friend bool operator < (
uint16 lhs,
const bigint& rhs
);
/*!
requires
- lhs <= 65535
ensures
- returns true if lhs is less than rhs
- returns false otherwise
!*/
friend bool operator < (
const bigint& lhs,
uint16 rhs
);
/*!
requires
- rhs <= 65535
ensures
- returns true if lhs is less than rhs
- returns false otherwise
!*/
friend bool operator == (
const bigint& lhs,
uint16 rhs
);
/*!
requires
- rhs <= 65535
ensures
- returns true if lhs and rhs represent the same number
- returns false otherwise
!*/
friend bool operator == (
uint16 lhs,
const bigint& rhs
);
/*!
requires
- lhs <= 65535
ensures
- returns true if lhs and rhs represent the same number
- returns false otherwise
!*/
bigint& operator= (
uint16 rhs
);
/*!
requires
- rhs <= 65535
ensures
- #*this == rhs
- returns #*this
throws
- std::bad_alloc
if this function throws then it has no effect
!*/
};
inline void swap (
bigint& a,
bigint& b
) { a.swap(b); }
/*!
provides a global swap function
!*/
void serialize (
const bigint& item,
std::istream& in
);
/*!
provides serialization support
!*/
void deserialize (
bigint& item,
std::istream& in
);
/*!
provides deserialization support
!*/
inline bool operator> (const bigint& a, const bigint& b) { return b < a; }
inline bool operator!= (const bigint& a, const bigint& b) { return !(a == b); }
inline bool operator<= (const bigint& a, const bigint& b) { return !(b < a); }
inline bool operator>= (const bigint& a, const bigint& b) { return !(a < b); }
}
#endif // DLIB_BIGINT_KERNEl_ABSTRACT_
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_BIGINT_KERNEl_C_
#define DLIB_BIGINT_KERNEl_C_
#include "bigint_kernel_abstract.h"
#include "../algs.h"
#include "../assert.h"
#include <iostream>
namespace dlib
{
// ----------------------------------------------------------------------------------------
template <
typename bigint_base
>
class bigint_kernel_c
{
bigint_base data;
explicit bigint_kernel_c (
const bigint_base& item
) : data(item) {}
public:
bigint_kernel_c (
);
bigint_kernel_c (
uint32 value
);
bigint_kernel_c (
const bigint_kernel_c<bigint_base>& item
);
~bigint_kernel_c (
);
const bigint_kernel_c<bigint_base> operator+ (
const bigint_kernel_c<bigint_base>& rhs
) const;
bigint_kernel_c<bigint_base>& operator+= (
const bigint_kernel_c<bigint_base>& rhs
);
const bigint_kernel_c<bigint_base> operator- (
const bigint_kernel_c<bigint_base>& rhs
) const;
bigint_kernel_c<bigint_base>& operator-= (
const bigint_kernel_c<bigint_base>& rhs
);
const bigint_kernel_c<bigint_base> operator* (
const bigint_kernel_c<bigint_base>& rhs
) const;
bigint_kernel_c<bigint_base>& operator*= (
const bigint_kernel_c<bigint_base>& rhs
);
const bigint_kernel_c<bigint_base> operator/ (
const bigint_kernel_c<bigint_base>& rhs
) const;
bigint_kernel_c<bigint_base>& operator/= (
const bigint_kernel_c<bigint_base>& rhs
);
const bigint_kernel_c<bigint_base> operator% (
const bigint_kernel_c<bigint_base>& rhs
) const;
bigint_kernel_c<bigint_base>& operator%= (
const bigint_kernel_c<bigint_base>& rhs
);
bool operator < (
const bigint_kernel_c<bigint_base>& rhs
) const;
bool operator == (
const bigint_kernel_c<bigint_base>& rhs
) const;
bigint_kernel_c<bigint_base>& operator= (
const bigint_kernel_c<bigint_base>& rhs
);
template <typename T>
friend std::ostream& operator<< (
std::ostream& out,
const bigint_kernel_c<T>& rhs
);
template <typename T>
friend std::istream& operator>> (
std::istream& in,
bigint_kernel_c<T>& rhs
);
bigint_kernel_c<bigint_base>& operator++ (
);
const bigint_kernel_c<bigint_base> operator++ (
int
);
bigint_kernel_c<bigint_base>& operator-- (
);
const bigint_kernel_c<bigint_base> operator-- (
int
);
template <typename T>
friend const bigint_kernel_c<T> operator+ (
uint16 lhs,
const bigint_kernel_c<T>& rhs
);
template <typename T>
friend const bigint_kernel_c<T> operator+ (
const bigint_kernel_c<T>& lhs,
uint16 rhs
);
bigint_kernel_c<bigint_base>& operator+= (
uint16 rhs
);
template <typename T>
friend const bigint_kernel_c<T> operator- (
uint16 lhs,
const bigint_kernel_c<T>& rhs
);
template <typename T>
friend const bigint_kernel_c<T> operator- (
const bigint_kernel_c<T>& lhs,
uint16 rhs
);
bigint_kernel_c<bigint_base>& operator-= (
uint16 rhs
);
template <typename T>
friend const bigint_kernel_c<T> operator* (
uint16 lhs,
const bigint_kernel_c<T>& rhs
);
template <typename T>
friend const bigint_kernel_c<T> operator* (
const bigint_kernel_c<T>& lhs,
uint16 rhs
);
bigint_kernel_c<bigint_base>& operator*= (
uint16 rhs
);
template <typename T>
friend const bigint_kernel_c<T> operator/ (
uint16 lhs,
const bigint_kernel_c<T>& rhs
);
template <typename T>
friend const bigint_kernel_c<T> operator/ (
const bigint_kernel_c<T>& lhs,
uint16 rhs
);
bigint_kernel_c<bigint_base>& operator/= (
uint16 rhs
);
template <typename T>
friend const bigint_kernel_c<T> operator% (
uint16 lhs,
const bigint_kernel_c<T>& rhs
);
template <typename T>
friend const bigint_kernel_c<T> operator% (
const bigint_kernel_c<T>& lhs,
uint16 rhs
);
bigint_kernel_c<bigint_base>& operator%= (
uint16 rhs
);
template <typename T>
friend bool operator < (
uint16 lhs,
const bigint_kernel_c<T>& rhs
);
template <typename T>
friend bool operator < (
const bigint_kernel_c<T>& lhs,
uint16 rhs
);
template <typename T>
friend bool operator == (
const bigint_kernel_c<T>& lhs,
uint16 rhs
);
template <typename T>
friend bool operator == (
uint16 lhs,
const bigint_kernel_c<T>& rhs
);
bigint_kernel_c<bigint_base>& operator= (
uint16 rhs
);
void swap (
bigint_kernel_c<bigint_base>& item
) { data.swap(item.data); }
};
template <
typename bigint_base
>
void swap (
bigint_kernel_c<bigint_base>& a,
bigint_kernel_c<bigint_base>& b
) { a.swap(b); }
// ----------------------------------------------------------------------------------------
template <
typename bigint_base
>
inline void serialize (
const bigint_kernel_c<bigint_base>& item,
std::ostream& out
)
{
std::ios::fmtflags oldflags = out.flags();
out << item << ' ';
out.flags(oldflags);
if (!out) throw serialization_error("Error serializing object of type bigint_kernel_c");
}
template <
typename bigint_base
>
inline void deserialize (
bigint_kernel_c<bigint_base>& item,
std::istream& in
)
{
std::ios::fmtflags oldflags = in.flags();
in >> item;
in.flags(oldflags);
if (in.get() != ' ')
{
item = 0;
throw serialization_error("Error deserializing object of type bigint_kernel_c");
}
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename bigint_base
>
bigint_kernel_c<bigint_base>::
bigint_kernel_c (
)
{}
// ----------------------------------------------------------------------------------------
template <
typename bigint_base
>
bigint_kernel_c<bigint_base>::
bigint_kernel_c (
uint32 value
) :
data(value)
{
// make sure requires clause is not broken
DLIB_CASSERT( value <= 0xFFFFFFFF ,
"\tbigint::bigint(uint16)"
<< "\n\t value must be <= (2^32)-1"
<< "\n\tthis: " << this
<< "\n\tvalue: " << value
);
}
// ----------------------------------------------------------------------------------------
template <
typename bigint_base
>
bigint_kernel_c<bigint_base>::
bigint_kernel_c (
const bigint_kernel_c<bigint_base>& item
) :
data(item.data)
{}
// ----------------------------------------------------------------------------------------
template <
typename bigint_base
>
bigint_kernel_c<bigint_base>::
~bigint_kernel_c (
)
{}
// ----------------------------------------------------------------------------------------
template <
typename bigint_base
>
const bigint_kernel_c<bigint_base> bigint_kernel_c<bigint_base>::
operator+ (
const bigint_kernel_c<bigint_base>& rhs
) const
{
return bigint_kernel_c<bigint_base>(data + rhs.data);
}
// ----------------------------------------------------------------------------------------
template <
typename bigint_base
>
bigint_kernel_c<bigint_base>& bigint_kernel_c<bigint_base>::
operator+= (
const bigint_kernel_c<bigint_base>& rhs
)
{
data += rhs.data;
return *this;
}
// ----------------------------------------------------------------------------------------
template <
typename bigint_base
>
const bigint_kernel_c<bigint_base> bigint_kernel_c<bigint_base>::
operator- (
const bigint_kernel_c<bigint_base>& rhs
) const
{
// make sure requires clause is not broken
DLIB_CASSERT( !(*this < rhs),
"\tconst bigint bigint::operator-(const bigint&)"
<< "\n\t *this should not be less than rhs"
<< "\n\tthis: " << this
<< "\n\t*this: " << *this
<< "\n\trhs: " << rhs
);
// call the real function
return bigint_kernel_c<bigint_base>(data-rhs.data);
}
// ----------------------------------------------------------------------------------------
template <
typename bigint_base
>
bigint_kernel_c<bigint_base>& bigint_kernel_c<bigint_base>::
operator-= (
const bigint_kernel_c<bigint_base>& rhs
)
{
// make sure requires clause is not broken
DLIB_CASSERT( !(*this < rhs),
"\tbigint& bigint::operator-=(const bigint&)"
<< "\n\t *this should not be less than rhs"
<< "\n\tthis: " << this
<< "\n\t*this: " << *this
<< "\n\trhs: " << rhs
);
// call the real function
data -= rhs.data;
return *this;
}
// ----------------------------------------------------------------------------------------
template <
typename bigint_base
>
const bigint_kernel_c<bigint_base> bigint_kernel_c<bigint_base>::
operator* (
const bigint_kernel_c<bigint_base>& rhs
) const
{
return bigint_kernel_c<bigint_base>(data * rhs.data );
}
// ----------------------------------------------------------------------------------------
template <
typename bigint_base
>
bigint_kernel_c<bigint_base>& bigint_kernel_c<bigint_base>::
operator*= (
const bigint_kernel_c<bigint_base>& rhs
)
{
data *= rhs.data;
return *this;
}
// ----------------------------------------------------------------------------------------
template <
typename bigint_base
>
const bigint_kernel_c<bigint_base> bigint_kernel_c<bigint_base>::
operator/ (
const bigint_kernel_c<bigint_base>& rhs
) const
{
//make sure requires clause is not broken
DLIB_CASSERT( !(rhs == 0),
"\tconst bigint bigint::operator/(const bigint&)"
<< "\n\t can't divide by zero"
<< "\n\tthis: " << this
);
// call the real function
return bigint_kernel_c<bigint_base>(data/rhs.data);
}
// ----------------------------------------------------------------------------------------
template <
typename bigint_base
>
bigint_kernel_c<bigint_base>& bigint_kernel_c<bigint_base>::
operator/= (
const bigint_kernel_c<bigint_base>& rhs
)
{
// make sure requires clause is not broken
DLIB_CASSERT( !(rhs == 0),
"\tbigint& bigint::operator/=(const bigint&)"
<< "\n\t can't divide by zero"
<< "\n\tthis: " << this
);
// call the real function
data /= rhs.data;
return *this;
}
// ----------------------------------------------------------------------------------------
template <
typename bigint_base
>
const bigint_kernel_c<bigint_base> bigint_kernel_c<bigint_base>::
operator% (
const bigint_kernel_c<bigint_base>& rhs
) const
{
// make sure requires clause is not broken
DLIB_CASSERT( !(rhs == 0),
"\tconst bigint bigint::operator%(const bigint&)"
<< "\n\t can't divide by zero"
<< "\n\tthis: " << this
);
// call the real function
return bigint_kernel_c<bigint_base>(data%rhs.data);
}
// ----------------------------------------------------------------------------------------
template <
typename bigint_base
>
bigint_kernel_c<bigint_base>& bigint_kernel_c<bigint_base>::
operator%= (
const bigint_kernel_c<bigint_base>& rhs
)
{
// make sure requires clause is not broken
DLIB_CASSERT( !(rhs == 0),
"\tbigint& bigint::operator%=(const bigint&)"
<< "\n\t can't divide by zero"
<< "\n\tthis: " << this
);
// call the real function
data %= rhs.data;
return *this;
}
// ----------------------------------------------------------------------------------------
template <
typename bigint_base
>
bool bigint_kernel_c<bigint_base>::
operator < (
const bigint_kernel_c<bigint_base>& rhs
) const
{
return data < rhs.data;
}
// ----------------------------------------------------------------------------------------
template <
typename bigint_base
>
bool bigint_kernel_c<bigint_base>::
operator == (
const bigint_kernel_c<bigint_base>& rhs
) const
{
return data == rhs.data;
}
// ----------------------------------------------------------------------------------------
template <
typename bigint_base
>
bigint_kernel_c<bigint_base>& bigint_kernel_c<bigint_base>::
operator= (
const bigint_kernel_c<bigint_base>& rhs
)
{
data = rhs.data;
return *this;
}
// ----------------------------------------------------------------------------------------
template <
typename bigint_base
>
std::ostream& operator<< (
std::ostream& out,
const bigint_kernel_c<bigint_base>& rhs
)
{
out << rhs.data;
return out;
}
// ----------------------------------------------------------------------------------------
template <
typename bigint_base
>
std::istream& operator>> (
std::istream& in,
bigint_kernel_c<bigint_base>& rhs
)
{
in >> rhs.data;
return in;
}
// ----------------------------------------------------------------------------------------
template <
typename bigint_base
>
bigint_kernel_c<bigint_base>& bigint_kernel_c<bigint_base>::
operator++ (
)
{
++data;
return *this;
}
// ----------------------------------------------------------------------------------------
template <
typename bigint_base
>
const bigint_kernel_c<bigint_base> bigint_kernel_c<bigint_base>::
operator++ (
int
)
{
return bigint_kernel_c<bigint_base>(data++);
}
// ----------------------------------------------------------------------------------------
template <
typename bigint_base
>
bigint_kernel_c<bigint_base>& bigint_kernel_c<bigint_base>::
operator-- (
)
{
// make sure requires clause is not broken
DLIB_CASSERT( !(*this == 0),
"\tbigint& bigint::operator--()"
<< "\n\t *this to subtract from *this it must not be zero to begin with"
<< "\n\tthis: " << this
);
// call the real function
--data;
return *this;
}
// ----------------------------------------------------------------------------------------
template <
typename bigint_base
>
const bigint_kernel_c<bigint_base> bigint_kernel_c<bigint_base>::
operator-- (
int
)
{
// make sure requires clause is not broken
DLIB_CASSERT( !(*this == 0),
"\tconst bigint bigint::operator--(int)"
<< "\n\t *this to subtract from *this it must not be zero to begin with"
<< "\n\tthis: " << this
);
// call the real function
return bigint_kernel_c<bigint_base>(data--);
}
// ----------------------------------------------------------------------------------------
template <
typename bigint_base
>
const bigint_kernel_c<bigint_base> operator+ (
uint16 l,
const bigint_kernel_c<bigint_base>& rhs
)
{
uint32 lhs = l;
// make sure requires clause is not broken
DLIB_CASSERT( lhs <= 65535,
"\tconst bigint operator+(uint16, const bigint&)"
<< "\n\t lhs must be <= 65535"
<< "\n\trhs: " << rhs
<< "\n\tlhs: " << lhs
);
return bigint_kernel_c<bigint_base>(static_cast<uint16>(lhs)+rhs.data);
}
// ----------------------------------------------------------------------------------------
template <
typename bigint_base
>
const bigint_kernel_c<bigint_base> operator+ (
const bigint_kernel_c<bigint_base>& lhs,
uint16 r
)
{
uint32 rhs = r;
// make sure requires clause is not broken
DLIB_CASSERT( rhs <= 65535,
"\tconst bigint operator+(const bigint&, uint16)"
<< "\n\t rhs must be <= 65535"
<< "\n\trhs: " << rhs
<< "\n\tlhs: " << lhs
);
return bigint_kernel_c<bigint_base>(lhs.data+static_cast<uint16>(rhs));
}
// ----------------------------------------------------------------------------------------
template <
typename bigint_base
>
bigint_kernel_c<bigint_base>& bigint_kernel_c<bigint_base>::
operator+= (
uint16 r
)
{
uint32 rhs = r;
// make sure requires clause is not broken
DLIB_CASSERT( rhs <= 65535,
"\tbigint& bigint::operator+=(uint16)"
<< "\n\t rhs must be <= 65535"
<< "\n\tthis: " << this
<< "\n\t*this: " << *this
<< "\n\trhs: " << rhs
);
data += rhs;
return *this;
}
// ----------------------------------------------------------------------------------------
template <
typename bigint_base
>
const bigint_kernel_c<bigint_base> operator- (
uint16 l,
const bigint_kernel_c<bigint_base>& rhs
)
{
uint32 lhs = l;
// make sure requires clause is not broken
DLIB_CASSERT( !(static_cast<uint16>(lhs) < rhs) && lhs <= 65535,
"\tconst bigint operator-(uint16,const bigint&)"
<< "\n\t lhs must be greater than or equal to rhs and lhs <= 65535"
<< "\n\tlhs: " << lhs
<< "\n\trhs: " << rhs
<< "\n\t&lhs: " << &lhs
<< "\n\t&rhs: " << &rhs
);
// call the real function
return bigint_kernel_c<bigint_base>(static_cast<uint16>(lhs)-rhs.data);
}
// ----------------------------------------------------------------------------------------
template <
typename bigint_base
>
const bigint_kernel_c<bigint_base> operator- (
const bigint_kernel_c<bigint_base>& lhs,
uint16 r
)
{
uint32 rhs = r;
// make sure requires clause is not broken
DLIB_CASSERT( !(lhs < static_cast<uint16>(rhs)) && rhs <= 65535,
"\tconst bigint operator-(const bigint&,uint16)"
<< "\n\t lhs must be greater than or equal to rhs and rhs <= 65535"
<< "\n\tlhs: " << lhs
<< "\n\trhs: " << rhs
<< "\n\t&lhs: " << &lhs
<< "\n\t&rhs: " << &rhs
);
// call the real function
return bigint_kernel_c<bigint_base>(lhs.data-static_cast<uint16>(rhs));
}
// ----------------------------------------------------------------------------------------
template <
typename bigint_base
>
bigint_kernel_c<bigint_base>& bigint_kernel_c<bigint_base>::
operator-= (
uint16 r
)
{
uint32 rhs = r;
// make sure requires clause is not broken
DLIB_CASSERT( !(*this < static_cast<uint16>(rhs)) && rhs <= 65535,
"\tbigint& bigint::operator-=(uint16)"
<< "\n\t *this must not be less than rhs and rhs <= 65535"
<< "\n\tthis: " << this
<< "\n\t*this: " << *this
<< "\n\trhs: " << rhs
);
// call the real function
data -= static_cast<uint16>(rhs);
return *this;
}
// ----------------------------------------------------------------------------------------
template <
typename bigint_base
>
const bigint_kernel_c<bigint_base> operator* (
uint16 l,
const bigint_kernel_c<bigint_base>& rhs
)
{
uint32 lhs = l;
// make sure requires clause is not broken
DLIB_CASSERT( lhs <= 65535,
"\tconst bigint operator*(uint16, const bigint&)"
<< "\n\t lhs must be <= 65535"
<< "\n\trhs: " << rhs
<< "\n\tlhs: " << lhs
);
return bigint_kernel_c<bigint_base>(lhs*rhs.data);
}
// ----------------------------------------------------------------------------------------
template <
typename bigint_base
>
const bigint_kernel_c<bigint_base> operator* (
const bigint_kernel_c<bigint_base>& lhs,
uint16 r
)
{
uint32 rhs = r;
// make sure requires clause is not broken
DLIB_CASSERT( rhs <= 65535,
"\tconst bigint operator*(const bigint&, uint16)"
<< "\n\t rhs must be <= 65535"
<< "\n\trhs: " << rhs
<< "\n\tlhs: " << lhs
);
return bigint_kernel_c<bigint_base>(lhs.data*rhs);
}
// ----------------------------------------------------------------------------------------
template <
typename bigint_base
>
bigint_kernel_c<bigint_base>& bigint_kernel_c<bigint_base>::
operator*= (
uint16 r
)
{
uint32 rhs = r;
// make sure requires clause is not broken
DLIB_CASSERT( rhs <= 65535,
"\t bigint bigint::operator*=(uint16)"
<< "\n\t rhs must be <= 65535"
<< "\n\tthis: " << this
<< "\n\t*this: " << *this
<< "\n\trhs: " << rhs
);
data *= static_cast<uint16>(rhs);
return *this;
}
// ----------------------------------------------------------------------------------------
template <
typename bigint_base
>
const bigint_kernel_c<bigint_base> operator/ (
uint16 l,
const bigint_kernel_c<bigint_base>& rhs
)
{
uint32 lhs = l;
// make sure requires clause is not broken
DLIB_CASSERT( !(rhs == 0) && lhs <= 65535,
"\tconst bigint operator/(uint16,const bigint&)"
<< "\n\t you can't divide by zero and lhs <= 65535"
<< "\n\t&lhs: " << &lhs
<< "\n\t&rhs: " << &rhs
<< "\n\tlhs: " << lhs
);
// call the real function
return bigint_kernel_c<bigint_base>(lhs/rhs.data);
}
// ----------------------------------------------------------------------------------------
template <
typename bigint_base
>
const bigint_kernel_c<bigint_base> operator/ (
const bigint_kernel_c<bigint_base>& lhs,
uint16 r
)
{
uint32 rhs = r;
// make sure requires clause is not broken
DLIB_CASSERT( !(rhs == 0) && rhs <= 65535,
"\tconst bigint operator/(const bigint&,uint16)"
<< "\n\t you can't divide by zero and rhs <= 65535"
<< "\n\t&lhs: " << &lhs
<< "\n\t&rhs: " << &rhs
<< "\n\trhs: " << rhs
);
// call the real function
return bigint_kernel_c<bigint_base>(lhs.data/static_cast<uint16>(rhs));
}
// ----------------------------------------------------------------------------------------
template <
typename bigint_base
>
bigint_kernel_c<bigint_base>& bigint_kernel_c<bigint_base>::
operator/= (
uint16 rhs
)
{
// make sure requires clause is not broken
DLIB_CASSERT( !(rhs == 0) && static_cast<uint32>(rhs) <= 65535,
"\tbigint& bigint::operator/=(uint16)"
<< "\n\t you can't divide by zero and rhs must be <= 65535"
<< "\n\tthis: " << this
<< "\n\trhs: " << rhs
);
// call the real function
data /= rhs;
return *this;
}
// ----------------------------------------------------------------------------------------
template <
typename bigint_base
>
const bigint_kernel_c<bigint_base> operator% (
uint16 lhs,
const bigint_kernel_c<bigint_base>& rhs
)
{
// make sure requires clause is not broken
DLIB_CASSERT( !(rhs == 0) && static_cast<uint32>(lhs) <= 65535,
"\tconst bigint operator%(uint16,const bigint&)"
<< "\n\t you can't divide by zero and lhs must be <= 65535"
<< "\n\t&lhs: " << &lhs
<< "\n\t&rhs: " << &rhs
<< "\n\tlhs: " << lhs
);
// call the real function
return bigint_kernel_c<bigint_base>(lhs%rhs.data);
}
// ----------------------------------------------------------------------------------------
template <
typename bigint_base
>
const bigint_kernel_c<bigint_base> operator% (
const bigint_kernel_c<bigint_base>& lhs,
uint16 r
)
{
uint32 rhs = r;
// make sure requires clause is not broken
DLIB_CASSERT( !(rhs == 0) && rhs <= 65535,
"\tconst bigint operator%(const bigint&,uint16)"
<< "\n\t you can't divide by zero and rhs must be <= 65535"
<< "\n\t&lhs: " << &lhs
<< "\n\t&rhs: " << &rhs
<< "\n\trhs: " << rhs
);
// call the real function
return bigint_kernel_c<bigint_base>(lhs.data%static_cast<uint16>(rhs));
}
// ----------------------------------------------------------------------------------------
template <
typename bigint_base
>
bigint_kernel_c<bigint_base>& bigint_kernel_c<bigint_base>::
operator%= (
uint16 r
)
{
uint32 rhs = r;
// make sure requires clause is not broken
DLIB_CASSERT( !(rhs == 0) && rhs <= 65535,
"\tbigint& bigint::operator%=(uint16)"
<< "\n\t you can't divide by zero and rhs must be <= 65535"
<< "\n\tthis: " << this
<< "\n\trhs: " << rhs
);
// call the real function
data %= rhs;
return *this;
}
// ----------------------------------------------------------------------------------------
template <
typename bigint_base
>
bool operator < (
uint16 l,
const bigint_kernel_c<bigint_base>& rhs
)
{
uint32 lhs = l;
// make sure requires clause is not broken
DLIB_CASSERT( lhs <= 65535,
"\tbool operator<(uint16, const bigint&)"
<< "\n\t lhs must be <= 65535"
<< "\n\trhs: " << rhs
<< "\n\tlhs: " << lhs
);
return static_cast<uint16>(lhs) < rhs.data;
}
// ----------------------------------------------------------------------------------------
template <
typename bigint_base
>
bool operator < (
const bigint_kernel_c<bigint_base>& lhs,
uint16 r
)
{
uint32 rhs = r;
// make sure requires clause is not broken
DLIB_CASSERT( rhs <= 65535,
"\tbool operator<(const bigint&, uint16)"
<< "\n\t rhs must be <= 65535"
<< "\n\trhs: " << rhs
<< "\n\tlhs: " << lhs
);
return lhs.data < static_cast<uint16>(rhs);
}
// ----------------------------------------------------------------------------------------
template <
typename bigint_base
>
bool operator == (
const bigint_kernel_c<bigint_base>& lhs,
uint16 r
)
{
uint32 rhs = r;
// make sure requires clause is not broken
DLIB_CASSERT( rhs <= 65535,
"\tbool operator==(const bigint&, uint16)"
<< "\n\t rhs must be <= 65535"
<< "\n\trhs: " << rhs
<< "\n\tlhs: " << lhs
);
return lhs.data == static_cast<uint16>(rhs);
}
// ----------------------------------------------------------------------------------------
template <
typename bigint_base
>
bool operator == (
uint16 l,
const bigint_kernel_c<bigint_base>& rhs
)
{
uint32 lhs = l;
// make sure requires clause is not broken
DLIB_CASSERT( lhs <= 65535,
"\tbool operator==(uint16, const bigint&)"
<< "\n\t lhs must be <= 65535"
<< "\n\trhs: " << rhs
<< "\n\tlhs: " << lhs
);
return static_cast<uint16>(lhs) == rhs.data;
}
// ----------------------------------------------------------------------------------------
template <
typename bigint_base
>
bigint_kernel_c<bigint_base>& bigint_kernel_c<bigint_base>::
operator= (
uint16 r
)
{
uint32 rhs = r;
// make sure requires clause is not broken
DLIB_CASSERT( rhs <= 65535,
"\tbigint bigint::operator=(uint16)"
<< "\n\t rhs must be <= 65535"
<< "\n\t*this: " << *this
<< "\n\tthis: " << this
<< "\n\tlhs: " << rhs
);
data = static_cast<uint16>(rhs);
return *this;
}
// ----------------------------------------------------------------------------------------
template < typename bigint_base >
inline bool operator> (const bigint_kernel_c<bigint_base>& a, const bigint_kernel_c<bigint_base>& b) { return b < a; }
template < typename bigint_base >
inline bool operator!= (const bigint_kernel_c<bigint_base>& a, const bigint_kernel_c<bigint_base>& b) { return !(a == b); }
template < typename bigint_base >
inline bool operator<= (const bigint_kernel_c<bigint_base>& a, const bigint_kernel_c<bigint_base>& b) { return !(b < a); }
template < typename bigint_base >
inline bool operator>= (const bigint_kernel_c<bigint_base>& a, const bigint_kernel_c<bigint_base>& b) { return !(a < b); }
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_BIGINT_KERNEl_C_
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_BINARY_SEARCH_TREe_
#define DLIB_BINARY_SEARCH_TREe_
#include "binary_search_tree/binary_search_tree_kernel_1.h"
#include "binary_search_tree/binary_search_tree_kernel_2.h"
#include "binary_search_tree/binary_search_tree_kernel_c.h"
#include "algs.h"
#include <functional>
namespace dlib
{
template <
typename domain,
typename range,
typename mem_manager = default_memory_manager,
typename compare = std::less<domain>
>
class binary_search_tree
{
binary_search_tree() {}
public:
//----------- kernels ---------------
// kernel_1a
typedef binary_search_tree_kernel_1<domain,range,mem_manager,compare>
kernel_1a;
typedef binary_search_tree_kernel_c<kernel_1a>
kernel_1a_c;
// kernel_2a
typedef binary_search_tree_kernel_2<domain,range,mem_manager,compare>
kernel_2a;
typedef binary_search_tree_kernel_c<kernel_2a>
kernel_2a_c;
};
}
#endif // DLIB_BINARY_SEARCH_TREe_
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_BINARY_SEARCH_TREE_KERNEl_1_
#define DLIB_BINARY_SEARCH_TREE_KERNEl_1_
#include "binary_search_tree_kernel_abstract.h"
#include "../algs.h"
#include "../interfaces/map_pair.h"
#include "../interfaces/enumerable.h"
#include "../interfaces/remover.h"
#include "../serialize.h"
#include <cstdlib>
#include <functional>
namespace dlib
{
template <
typename domain,
typename range,
typename mem_manager,
typename compare = std::less<domain>
>
class binary_search_tree_kernel_1 : public enumerable<map_pair<domain,range> >,
public asc_pair_remover<domain,range,compare>
{
/*!
INITIAL VALUE
tree_size == 0
tree_root == 0
tree_height == 0
at_start_ == true
current_element == 0
stack == array of 50 node pointers
stack_pos == 0
CONVENTION
tree_size == size()
tree_height == height()
stack[stack_pos-1] == pop()
current_element_valid() == (current_element != 0)
if (current_element_valid()) then
element() == current_element->d and current_element->r
at_start_ == at_start()
if (current_element != 0 && current_element != tree_root) then
stack[stack_pos-1] == the parent of the node pointed to by current_element
if (tree_size != 0)
tree_root == pointer to the root node of the binary search tree
else
tree_root == 0
for all nodes:
{
left points to the left subtree or 0 if there is no left subtree and
right points to the right subtree or 0 if there is no right subtree and
all elements in a left subtree are <= the root and
all elements in a right subtree are >= the root and
d is the item in the domain of *this contained in the node
r is the item in the range of *this contained in the node
balance:
balance == 0 if both subtrees have the same height
balance == -1 if the left subtree has a height that is greater
than the height of the right subtree by 1
balance == 1 if the right subtree has a height that is greater
than the height of the left subtree by 1
for all trees:
the height of the left and right subtrees differ by at most one
}
!*/
class node
{
public:
node* left;
node* right;
domain d;
range r;
signed char balance;
};
class mpair : public map_pair<domain,range>
{
public:
const domain* d;
range* r;
const domain& key(
) const { return *d; }
const range& value(
) const { return *r; }
range& value(
) { return *r; }
};
public:
typedef domain domain_type;
typedef range range_type;
typedef compare compare_type;
typedef mem_manager mem_manager_type;
binary_search_tree_kernel_1(
) :
tree_size(0),
tree_root(0),
current_element(0),
tree_height(0),
at_start_(true),
stack_pos(0),
stack(ppool.allocate_array(50))
{
}
virtual ~binary_search_tree_kernel_1(
);
inline void clear(
);
inline short height (
) const;
inline unsigned long count (
const domain& item
) const;
inline void add (
domain& d,
range& r
);
void remove (
const domain& d,
domain& d_copy,
range& r
);
void destroy (
const domain& item
);
inline const range* operator[] (
const domain& item
) const;
inline range* operator[] (
const domain& item
);
inline void swap (
binary_search_tree_kernel_1& item
);
// function from the asc_pair_remover interface
void remove_any (
domain& d,
range& r
);
// functions from the enumerable interface
inline size_t size (
) const;
bool at_start (
) const;
inline void reset (
) const;
bool current_element_valid (
) const;
const map_pair<domain,range>& element (
) const;
map_pair<domain,range>& element (
);
bool move_next (
) const;
void remove_last_in_order (
domain& d,
range& r
);
void remove_current_element (
domain& d,
range& r
);
void position_enumerator (
const domain& d
) const;
private:
inline void rotate_left (
node*& t
);
/*!
requires
- t->balance == 2
- t->right->balance == 0 or 1
- t == reference to the pointer in t's parent node that points to t
ensures
- #t is still a binary search tree
- #t->balance is between 1 and -1
- #t now has a height smaller by 1 if #t->balance == 0
!*/
inline void rotate_right (
node*& t
);
/*!
requires
- t->balance == -2
- t->left->balance == 0 or -1
- t == reference to the pointer in t's parent node that points to t
ensures
- #t is still a binary search tree
- #t->balance is between 1 and -1
- #t now has a height smaller by 1 if #t->balance == 0
!*/
inline void double_rotate_right (
node*& t
);
/*!
requires
- t->balance == -2
- t->left->balance == 1
- t == reference to the pointer in t's parent node that points to t
ensures
- #t is still a binary search tree
- #t now has a balance of 0
- #t now has a height smaller by 1
!*/
inline void double_rotate_left (
node*& t
);
/*!
requires
- t->balance == 2
- t->right->balance == -1
- t == reference to the pointer in t's parent node that points to t
ensures
- #t is still a binary search tree
- #t now has a balance of 0
- #t now has a height smaller by 1
!*/
bool remove_biggest_element_in_tree (
node*& t,
domain& d,
range& r
);
/*!
requires
- t != 0 (i.e. there must be something in the tree to remove)
- t == reference to the pointer in t's parent node that points to t
ensures
- the biggest node in t has been removed
- the biggest node domain element in t has been put into #d
- the biggest node range element in t has been put into #r
- #t is still a binary search tree
- returns false if the height of the tree has not changed
- returns true if the height of the tree has shrunk by one
!*/
bool remove_least_element_in_tree (
node*& t,
domain& d,
range& r
);
/*!
requires
- t != 0 (i.e. there must be something in the tree to remove)
- t == reference to the pointer in t's parent node that points to t
ensures
- the least node in t has been removed
- the least node domain element in t has been put into #d
- the least node range element in t has been put into #r
- #t is still a binary search tree
- returns false if the height of the tree has not changed
- returns true if the height of the tree has shrunk by one
!*/
bool add_to_tree (
node*& t,
domain& d,
range& r
);
/*!
requires
- t == reference to the pointer in t's parent node that points to t
ensures
- the mapping (d --> r) has been added to #t
- #d and #r have initial values for their types
- #t is still a binary search tree
- returns false if the height of the tree has not changed
- returns true if the height of the tree has grown by one
!*/
bool remove_from_tree (
node*& t,
const domain& d,
domain& d_copy,
range& r
);
/*!
requires
- return_reference(t,d) != 0
- t == reference to the pointer in t's parent node that points to t
ensures
- #d_copy is equivalent to d
- an element in t equivalent to d has been removed and swapped
into #d_copy and its associated range object has been
swapped into #r
- #t is still a binary search tree
- returns false if the height of the tree has not changed
- returns true if the height of the tree has shrunk by one
!*/
bool remove_from_tree (
node*& t,
const domain& item
);
/*!
requires
- return_reference(t,item) != 0
- t == reference to the pointer in t's parent node that points to t
ensures
- an element in t equivalent to item has been removed
- #t is still a binary search tree
- returns false if the height of the tree has not changed
- returns true if the height of the tree has shrunk by one
!*/
const range* return_reference (
const node* t,
const domain& d
) const;
/*!
ensures
- if (there is a domain element equivalent to d in t) then
- returns a pointer to the element in the range equivalent to d
- else
- returns 0
!*/
range* return_reference (
node* t,
const domain& d
);
/*!
ensures
- if (there is a domain element equivalent to d in t) then
- returns a pointer to the element in the range equivalent to d
- else
- returns 0
!*/
inline bool keep_node_balanced (
node*& t
);
/*!
requires
- t != 0
- t == reference to the pointer in t's parent node that points to t
ensures
- if (t->balance is < 1 or > 1) then
- keep_node_balanced() will ensure that #t->balance == 0, -1, or 1
- #t is still a binary search tree
- returns true if it made the tree one height shorter
- returns false if it didn't change the height
!*/
unsigned long get_count (
const domain& item,
node* tree_root
) const;
/*!
requires
- tree_root == the root of a binary search tree or 0
ensures
- if (tree_root == 0) then
- returns 0
- else
- returns the number of elements in tree_root that are
equivalent to item
!*/
void delete_tree (
node* t
);
/*!
requires
- t != 0
ensures
- deallocates the node pointed to by t and all of t's left and right children
!*/
void push (
node* n
) const { stack[stack_pos] = n; ++stack_pos; }
/*!
ensures
- pushes n onto the stack
!*/
node* pop (
) const { --stack_pos; return stack[stack_pos]; }
/*!
ensures
- pops the top of the stack and returns it
!*/
bool fix_stack (
node* t,
unsigned char depth = 0
);
/*!
requires
- current_element != 0
- depth == 0
- t == tree_root
ensures
- makes the stack contain the correct set of parent pointers.
also adjusts stack_pos so it is correct.
- #t is still a binary search tree
!*/
bool remove_current_element_from_tree (
node*& t,
domain& d,
range& r,
unsigned long cur_stack_pos = 1
);
/*!
requires
- t == tree_root
- cur_stack_pos == 1
- current_element != 0
ensures
- removes the data in the node given by current_element and swaps it into
#d and #r.
- #t is still a binary search tree
- the enumerator is advances on to the next element but its stack is
potentially corrupted. so you must call fix_stack(tree_root) to fix
it.
- returns false if the height of the tree has not changed
- returns true if the height of the tree has shrunk by one
!*/
// data members
mutable mpair p;
unsigned long tree_size;
node* tree_root;
mutable node* current_element;
typename mem_manager::template rebind<node>::other pool;
typename mem_manager::template rebind<node*>::other ppool;
short tree_height;
mutable bool at_start_;
mutable unsigned char stack_pos;
mutable node** stack;
compare comp;
// restricted functions
binary_search_tree_kernel_1(binary_search_tree_kernel_1&);
binary_search_tree_kernel_1& operator=(binary_search_tree_kernel_1&);
};
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
inline void swap (
binary_search_tree_kernel_1<domain,range,mem_manager,compare>& a,
binary_search_tree_kernel_1<domain,range,mem_manager,compare>& b
) { a.swap(b); }
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
void deserialize (
binary_search_tree_kernel_1<domain,range,mem_manager,compare>& item,
std::istream& in
)
{
try
{
item.clear();
unsigned long size;
deserialize(size,in);
domain d;
range r;
for (unsigned long i = 0; i < size; ++i)
{
deserialize(d,in);
deserialize(r,in);
item.add(d,r);
}
}
catch (serialization_error& e)
{
item.clear();
throw serialization_error(e.info + "\n while deserializing object of type binary_search_tree_kernel_1");
}
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
binary_search_tree_kernel_1<domain,range,mem_manager,compare>::
~binary_search_tree_kernel_1 (
)
{
ppool.deallocate_array(stack);
if (tree_size != 0)
{
delete_tree(tree_root);
}
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
void binary_search_tree_kernel_1<domain,range,mem_manager,compare>::
clear (
)
{
if (tree_size > 0)
{
delete_tree(tree_root);
tree_root = 0;
tree_size = 0;
tree_height = 0;
}
// reset the enumerator
reset();
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
size_t binary_search_tree_kernel_1<domain,range,mem_manager,compare>::
size (
) const
{
return tree_size;
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
short binary_search_tree_kernel_1<domain,range,mem_manager,compare>::
height (
) const
{
return tree_height;
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
unsigned long binary_search_tree_kernel_1<domain,range,mem_manager,compare>::
count (
const domain& item
) const
{
return get_count(item,tree_root);
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
void binary_search_tree_kernel_1<domain,range,mem_manager,compare>::
add (
domain& d,
range& r
)
{
tree_height += add_to_tree(tree_root,d,r);
++tree_size;
// reset the enumerator
reset();
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
void binary_search_tree_kernel_1<domain,range,mem_manager,compare>::
remove (
const domain& d,
domain& d_copy,
range& r
)
{
tree_height -= remove_from_tree(tree_root,d,d_copy,r);
--tree_size;
// reset the enumerator
reset();
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
void binary_search_tree_kernel_1<domain,range,mem_manager,compare>::
destroy (
const domain& item
)
{
tree_height -= remove_from_tree(tree_root,item);
--tree_size;
// reset the enumerator
reset();
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
void binary_search_tree_kernel_1<domain,range,mem_manager,compare>::
remove_any (
domain& d,
range& r
)
{
tree_height -= remove_least_element_in_tree(tree_root,d,r);
--tree_size;
// reset the enumerator
reset();
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
range* binary_search_tree_kernel_1<domain,range,mem_manager,compare>::
operator[] (
const domain& item
)
{
return return_reference(tree_root,item);
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
const range* binary_search_tree_kernel_1<domain,range,mem_manager,compare>::
operator[] (
const domain& item
) const
{
return return_reference(tree_root,item);
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
void binary_search_tree_kernel_1<domain,range,mem_manager,compare>::
swap (
binary_search_tree_kernel_1<domain,range,mem_manager,compare>& item
)
{
pool.swap(item.pool);
ppool.swap(item.ppool);
exchange(p,item.p);
exchange(stack,item.stack);
exchange(stack_pos,item.stack_pos);
exchange(comp,item.comp);
node* tree_root_temp = item.tree_root;
unsigned long tree_size_temp = item.tree_size;
short tree_height_temp = item.tree_height;
node* current_element_temp = item.current_element;
bool at_start_temp = item.at_start_;
item.tree_root = tree_root;
item.tree_size = tree_size;
item.tree_height = tree_height;
item.current_element = current_element;
item.at_start_ = at_start_;
tree_root = tree_root_temp;
tree_size = tree_size_temp;
tree_height = tree_height_temp;
current_element = current_element_temp;
at_start_ = at_start_temp;
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
void binary_search_tree_kernel_1<domain,range,mem_manager,compare>::
remove_last_in_order (
domain& d,
range& r
)
{
tree_height -= remove_biggest_element_in_tree(tree_root,d,r);
--tree_size;
// reset the enumerator
reset();
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
void binary_search_tree_kernel_1<domain,range,mem_manager,compare>::
remove_current_element (
domain& d,
range& r
)
{
tree_height -= remove_current_element_from_tree(tree_root,d,r);
--tree_size;
// fix the enumerator stack if we need to
if (current_element)
fix_stack(tree_root);
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
void binary_search_tree_kernel_1<domain,range,mem_manager,compare>::
position_enumerator (
const domain& d
) const
{
// clear the enumerator state and make sure the stack is empty
reset();
at_start_ = false;
node* t = tree_root;
bool went_left = false;
while (t != 0)
{
if ( comp(d , t->d) )
{
push(t);
// if item is on the left then look in left
t = t->left;
went_left = true;
}
else if (comp(t->d , d))
{
push(t);
// if item is on the right then look in right
t = t->right;
went_left = false;
}
else
{
current_element = t;
return;
}
}
// if we didn't find any matches but there might be something after the
// d in this tree.
if (stack_pos > 0)
{
current_element = pop();
// if we went left from this node then this node is the next
// biggest.
if (went_left)
{
return;
}
else
{
move_next();
}
}
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// enumerable function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
bool binary_search_tree_kernel_1<domain,range,mem_manager,compare>::
at_start (
) const
{
return at_start_;
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
void binary_search_tree_kernel_1<domain,range,mem_manager,compare>::
reset (
) const
{
at_start_ = true;
current_element = 0;
stack_pos = 0;
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
bool binary_search_tree_kernel_1<domain,range,mem_manager,compare>::
current_element_valid (
) const
{
return (current_element != 0);
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
const map_pair<domain,range>& binary_search_tree_kernel_1<domain,range,mem_manager,compare>::
element (
) const
{
p.d = &(current_element->d);
p.r = &(current_element->r);
return p;
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
map_pair<domain,range>& binary_search_tree_kernel_1<domain,range,mem_manager,compare>::
element (
)
{
p.d = &(current_element->d);
p.r = &(current_element->r);
return p;
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
bool binary_search_tree_kernel_1<domain,range,mem_manager,compare>::
move_next (
) const
{
// if we haven't started iterating yet
if (at_start_)
{
at_start_ = false;
if (tree_size == 0)
{
return false;
}
else
{
// find the first element in the tree
current_element = tree_root;
node* temp = current_element->left;
while (temp != 0)
{
push(current_element);
current_element = temp;
temp = current_element->left;
}
return true;
}
}
else
{
if (current_element == 0)
{
return false;
}
else
{
node* temp;
bool went_up; // true if we went up the tree from a child node to parent
bool from_left = false; // true if we went up and were coming from a left child node
// find the next element in the tree
if (current_element->right != 0)
{
// go right and down
temp = current_element;
push(current_element);
current_element = temp->right;
went_up = false;
}
else
{
// go up to the parent if we can
if (current_element == tree_root)
{
// in this case we have iterated over all the element of the tree
current_element = 0;
return false;
}
went_up = true;
node* parent = pop();
from_left = (parent->left == current_element);
// go up to parent
current_element = parent;
}
while (true)
{
if (went_up)
{
if (from_left)
{
// in this case we have found the next node
break;
}
else
{
if (current_element == tree_root)
{
// in this case we have iterated over all the elements
// in the tree
current_element = 0;
return false;
}
// we should go up
node* parent = pop();
from_left = (parent->left == current_element);
current_element = parent;
}
}
else
{
// we just went down to a child node
if (current_element->left != 0)
{
// go left
went_up = false;
temp = current_element;
push(current_element);
current_element = temp->left;
}
else
{
// if there is no left child then we have found the next node
break;
}
}
}
return true;
}
}
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// private member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
void binary_search_tree_kernel_1<domain,range,mem_manager,compare>::
delete_tree (
node* t
)
{
if (t->left != 0)
delete_tree(t->left);
if (t->right != 0)
delete_tree(t->right);
pool.deallocate(t);
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
void binary_search_tree_kernel_1<domain,range,mem_manager,compare>::
rotate_left (
node*& t
)
{
// set the new balance numbers
if (t->right->balance == 1)
{
t->balance = 0;
t->right->balance = 0;
}
else
{
t->balance = 1;
t->right->balance = -1;
}
// perform the rotation
node* temp = t->right;
t->right = temp->left;
temp->left = t;
t = temp;
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
void binary_search_tree_kernel_1<domain,range,mem_manager,compare>::
rotate_right (
node*& t
)
{
// set the new balance numbers
if (t->left->balance == -1)
{
t->balance = 0;
t->left->balance = 0;
}
else
{
t->balance = -1;
t->left->balance = 1;
}
// preform the rotation
node* temp = t->left;
t->left = temp->right;
temp->right = t;
t = temp;
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
void binary_search_tree_kernel_1<domain,range,mem_manager,compare>::
double_rotate_right (
node*& t
)
{
node* temp = t;
t = t->left->right;
temp->left->right = t->left;
t->left = temp->left;
temp->left = t->right;
t->right = temp;
if (t->balance < 0)
{
t->left->balance = 0;
t->right->balance = 1;
}
else if (t->balance > 0)
{
t->left->balance = -1;
t->right->balance = 0;
}
else
{
t->left->balance = 0;
t->right->balance = 0;
}
t->balance = 0;
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
void binary_search_tree_kernel_1<domain,range,mem_manager,compare>::
double_rotate_left (
node*& t
)
{
node* temp = t;
t = t->right->left;
temp->right->left = t->right;
t->right = temp->right;
temp->right = t->left;
t->left = temp;
if (t->balance < 0)
{
t->left->balance = 0;
t->right->balance = 1;
}
else if (t->balance > 0)
{
t->left->balance = -1;
t->right->balance = 0;
}
else
{
t->left->balance = 0;
t->right->balance = 0;
}
t->balance = 0;
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
bool binary_search_tree_kernel_1<domain,range,mem_manager,compare>::
remove_biggest_element_in_tree (
node*& t,
domain& d,
range& r
)
{
// make a reference to the current node so we don't have to dereference a
// pointer a bunch of times
node& tree = *t;
// if the right tree is an empty tree
if ( tree.right == 0)
{
// swap nodes domain and range elements into d and r
exchange(d,tree.d);
exchange(r,tree.r);
// plug hole left by removing this node
t = tree.left;
// delete the node that was just removed
pool.deallocate(&tree);
// return that the height of this part of the tree has decreased
return true;
}
else
{
// keep going right
// if remove made the tree one height shorter
if ( remove_biggest_element_in_tree(tree.right,d,r) )
{
// if this caused the current tree to strink then report that
if ( tree.balance == 1)
{
--tree.balance;
return true;
}
else
{
--tree.balance;
return keep_node_balanced(t);
}
}
return false;
}
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
bool binary_search_tree_kernel_1<domain,range,mem_manager,compare>::
remove_least_element_in_tree (
node*& t,
domain& d,
range& r
)
{
// make a reference to the current node so we don't have to dereference a
// pointer a bunch of times
node& tree = *t;
// if the left tree is an empty tree
if ( tree.left == 0)
{
// swap nodes domain and range elements into d and r
exchange(d,tree.d);
exchange(r,tree.r);
// plug hole left by removing this node
t = tree.right;
// delete the node that was just removed
pool.deallocate(&tree);
// return that the height of this part of the tree has decreased
return true;
}
else
{
// keep going left
// if remove made the tree one height shorter
if ( remove_least_element_in_tree(tree.left,d,r) )
{
// if this caused the current tree to strink then report that
if ( tree.balance == -1)
{
++tree.balance;
return true;
}
else
{
++tree.balance;
return keep_node_balanced(t);
}
}
return false;
}
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
bool binary_search_tree_kernel_1<domain,range,mem_manager,compare>::
add_to_tree (
node*& t,
domain& d,
range& r
)
{
// if found place to add
if (t == 0)
{
// create a node to add new item into
t = pool.allocate();
// make a reference to the current node so we don't have to dereference a
// pointer a bunch of times
node& tree = *t;
// set left and right pointers to NULL to indicate that there are no
// left or right subtrees
tree.left = 0;
tree.right = 0;
tree.balance = 0;
// put d and r into t
exchange(tree.d,d);
exchange(tree.r,r);
// indicate that the height of this tree has increased
return true;
}
else // keep looking for a place to add the new item
{
// make a reference to the current node so we don't have to dereference
// a pointer a bunch of times
node& tree = *t;
signed char old_balance = tree.balance;
// add the new item to whatever subtree it should go into
if (comp( d , tree.d) )
tree.balance -= add_to_tree(tree.left,d,r);
else
tree.balance += add_to_tree(tree.right,d,r);
// if the tree was balanced to start with
if (old_balance == 0)
{
// if its not balanced anymore then it grew in height
if (tree.balance != 0)
return true;
else
return false;
}
else
{
// if the tree is now balanced then it didn't grow
if (tree.balance == 0)
{
return false;
}
else
{
// if the tree needs to be balanced
if (tree.balance != old_balance)
{
return !keep_node_balanced(t);
}
// if there has been no change in the heights
else
{
return false;
}
}
}
}
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
bool binary_search_tree_kernel_1<domain,range,mem_manager,compare>::
fix_stack (
node* t,
unsigned char depth
)
{
// if we found the node we were looking for
if (t == current_element)
{
stack_pos = depth;
return true;
}
else if (t == 0)
{
return false;
}
if (!( comp(t->d , current_element->d)))
{
// go left
if (fix_stack(t->left,depth+1))
{
stack[depth] = t;
return true;
}
}
if (!(comp(current_element->d , t->d)))
{
// go right
if (fix_stack(t->right,depth+1))
{
stack[depth] = t;
return true;
}
}
return false;
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
bool binary_search_tree_kernel_1<domain,range,mem_manager,compare>::
remove_current_element_from_tree (
node*& t,
domain& d,
range& r,
unsigned long cur_stack_pos
)
{
// make a reference to the current node so we don't have to dereference
// a pointer a bunch of times
node& tree = *t;
// if we found the node we were looking for
if (t == current_element)
{
// swap nodes domain and range elements into d_copy and r
exchange(d,tree.d);
exchange(r,tree.r);
// if there is no left node
if (tree.left == 0)
{
// move the enumerator on to the next element before we mess with the
// tree
move_next();
// plug hole left by removing this node and free memory
t = tree.right; // plug hole with right subtree
// delete old node
pool.deallocate(&tree);
// indicate that the height has changed
return true;
}
// if there is no right node
else if (tree.right == 0)
{
// move the enumerator on to the next element before we mess with the
// tree
move_next();
// plug hole left by removing this node and free memory
t = tree.left; // plug hole with left subtree
// delete old node
pool.deallocate(&tree);
// indicate that the height of this tree has changed
return true;
}
// if there are both a left and right sub node
else
{
// in this case the next current element is going to get swapped back
// into this t node.
current_element = t;
// get an element that can replace the one being removed and do this
// if it made the right subtree shrink by one
if (remove_least_element_in_tree(tree.right,tree.d,tree.r))
{
// adjust the tree height
--tree.balance;
// if the height of the current tree has dropped by one
if (tree.balance == 0)
{
return true;
}
else
{
return keep_node_balanced(t);
}
}
// else this remove did not effect the height of this tree
else
{
return false;
}
}
}
else if ( (cur_stack_pos < stack_pos && stack[cur_stack_pos] == tree.left) ||
tree.left == current_element )
{
// go left
if (tree.balance == -1)
{
int balance = tree.balance;
balance += remove_current_element_from_tree(tree.left,d,r,cur_stack_pos+1);
tree.balance = balance;
return !tree.balance;
}
else
{
int balance = tree.balance;
balance += remove_current_element_from_tree(tree.left,d,r,cur_stack_pos+1);
tree.balance = balance;
return keep_node_balanced(t);
}
}
else if ( (cur_stack_pos < stack_pos && stack[cur_stack_pos] == tree.right) ||
tree.right == current_element )
{
// go right
if (tree.balance == 1)
{
int balance = tree.balance;
balance -= remove_current_element_from_tree(tree.right,d,r,cur_stack_pos+1);
tree.balance = balance;
return !tree.balance;
}
else
{
int balance = tree.balance;
balance -= remove_current_element_from_tree(tree.right,d,r,cur_stack_pos+1);
tree.balance = balance;
return keep_node_balanced(t);
}
}
// this return should never happen but do it anyway to suppress compiler warnings
return false;
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
bool binary_search_tree_kernel_1<domain,range,mem_manager,compare>::
remove_from_tree (
node*& t,
const domain& d,
domain& d_copy,
range& r
)
{
// make a reference to the current node so we don't have to dereference
// a pointer a bunch of times
node& tree = *t;
// if item is on the left
if (comp(d , tree.d))
{
// if the left side of the tree has the greatest height
if (tree.balance == -1)
{
int balance = tree.balance;
balance += remove_from_tree(tree.left,d,d_copy,r);
tree.balance = balance;
return !tree.balance;
}
else
{
int balance = tree.balance;
balance += remove_from_tree(tree.left,d,d_copy,r);
tree.balance = balance;
return keep_node_balanced(t);
}
}
// if item is on the right
else if (comp(tree.d , d))
{
// if the right side of the tree has the greatest height
if (tree.balance == 1)
{
int balance = tree.balance;
balance -= remove_from_tree(tree.right,d,d_copy,r);
tree.balance = balance;
return !tree.balance;
}
else
{
int balance = tree.balance;
balance -= remove_from_tree(tree.right,d,d_copy,r);
tree.balance = balance;
return keep_node_balanced(t);
}
}
// if item is found
else
{
// swap nodes domain and range elements into d_copy and r
exchange(d_copy,tree.d);
exchange(r,tree.r);
// if there is no left node
if (tree.left == 0)
{
// plug hole left by removing this node and free memory
t = tree.right; // plug hole with right subtree
// delete old node
pool.deallocate(&tree);
// indicate that the height has changed
return true;
}
// if there is no right node
else if (tree.right == 0)
{
// plug hole left by removing this node and free memory
t = tree.left; // plug hole with left subtree
// delete old node
pool.deallocate(&tree);
// indicate that the height of this tree has changed
return true;
}
// if there are both a left and right sub node
else
{
// get an element that can replace the one being removed and do this
// if it made the right subtree shrink by one
if (remove_least_element_in_tree(tree.right,tree.d,tree.r))
{
// adjust the tree height
--tree.balance;
// if the height of the current tree has dropped by one
if (tree.balance == 0)
{
return true;
}
else
{
return keep_node_balanced(t);
}
}
// else this remove did not effect the height of this tree
else
{
return false;
}
}
}
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
bool binary_search_tree_kernel_1<domain,range,mem_manager,compare>::
remove_from_tree (
node*& t,
const domain& d
)
{
// make a reference to the current node so we don't have to dereference
// a pointer a bunch of times
node& tree = *t;
// if item is on the left
if (comp(d , tree.d))
{
// if the left side of the tree has the greatest height
if (tree.balance == -1)
{
int balance = tree.balance;
balance += remove_from_tree(tree.left,d);
tree.balance = balance;
return !tree.balance;
}
else
{
int balance = tree.balance;
balance += remove_from_tree(tree.left,d);
tree.balance = balance;
return keep_node_balanced(t);
}
}
// if item is on the right
else if (comp(tree.d , d))
{
// if the right side of the tree has the greatest height
if (tree.balance == 1)
{
int balance = tree.balance;
balance -= remove_from_tree(tree.right,d);
tree.balance = balance;
return !tree.balance;
}
else
{
int balance = tree.balance;
balance -= remove_from_tree(tree.right,d);
tree.balance = balance;
return keep_node_balanced(t);
}
}
// if item is found
else
{
// if there is no left node
if (tree.left == 0)
{
// plug hole left by removing this node and free memory
t = tree.right; // plug hole with right subtree
// delete old node
pool.deallocate(&tree);
// indicate that the height has changed
return true;
}
// if there is no right node
else if (tree.right == 0)
{
// plug hole left by removing this node and free memory
t = tree.left; // plug hole with left subtree
// delete old node
pool.deallocate(&tree);
// indicate that the height of this tree has changed
return true;
}
// if there are both a left and right sub node
else
{
// get an element that can replace the one being removed and do this
// if it made the right subtree shrink by one
if (remove_least_element_in_tree(tree.right,tree.d,tree.r))
{
// adjust the tree height
--tree.balance;
// if the height of the current tree has dropped by one
if (tree.balance == 0)
{
return true;
}
else
{
return keep_node_balanced(t);
}
}
// else this remove did not effect the height of this tree
else
{
return false;
}
}
}
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
range* binary_search_tree_kernel_1<domain,range,mem_manager,compare>::
return_reference (
node* t,
const domain& d
)
{
while (t != 0)
{
if ( comp(d , t->d ))
{
// if item is on the left then look in left
t = t->left;
}
else if (comp(t->d , d))
{
// if item is on the right then look in right
t = t->right;
}
else
{
// if it's found then return a reference to it
return &(t->r);
}
}
return 0;
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
const range* binary_search_tree_kernel_1<domain,range,mem_manager,compare>::
return_reference (
const node* t,
const domain& d
) const
{
while (t != 0)
{
if ( comp(d , t->d) )
{
// if item is on the left then look in left
t = t->left;
}
else if (comp(t->d , d))
{
// if item is on the right then look in right
t = t->right;
}
else
{
// if it's found then return a reference to it
return &(t->r);
}
}
return 0;
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
bool binary_search_tree_kernel_1<domain,range,mem_manager,compare>::
keep_node_balanced (
node*& t
)
{
// make a reference to the current node so we don't have to dereference
// a pointer a bunch of times
node& tree = *t;
// if tree does not need to be balanced then return false
if (tree.balance == 0)
return false;
// if tree needs to be rotated left
if (tree.balance == 2)
{
if (tree.right->balance >= 0)
rotate_left(t);
else
double_rotate_left(t);
}
// else if the tree needs to be rotated right
else if (tree.balance == -2)
{
if (tree.left->balance <= 0)
rotate_right(t);
else
double_rotate_right(t);
}
if (t->balance == 0)
return true;
else
return false;
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
unsigned long binary_search_tree_kernel_1<domain,range,mem_manager,compare>::
get_count (
const domain& d,
node* tree_root
) const
{
if (tree_root != 0)
{
if (comp(d , tree_root->d))
{
// go left
return get_count(d,tree_root->left);
}
else if (comp(tree_root->d , d))
{
// go right
return get_count(d,tree_root->right);
}
else
{
// go left and right to look for more matches
return get_count(d,tree_root->left)
+ get_count(d,tree_root->right)
+ 1;
}
}
return 0;
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_BINARY_SEARCH_TREE_KERNEl_1_
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_BINARY_SEARCH_TREE_KERNEl_2_
#define DLIB_BINARY_SEARCH_TREE_KERNEl_2_
#include "binary_search_tree_kernel_abstract.h"
#include "../algs.h"
#include "../interfaces/map_pair.h"
#include "../interfaces/enumerable.h"
#include "../interfaces/remover.h"
#include "../serialize.h"
#include <functional>
namespace dlib
{
template <
typename domain,
typename range,
typename mem_manager,
typename compare = std::less<domain>
>
class binary_search_tree_kernel_2 : public enumerable<map_pair<domain,range> >,
public asc_pair_remover<domain,range,compare>
{
/*!
INITIAL VALUE
NIL == pointer to a node that represents a leaf
tree_size == 0
tree_root == NIL
at_start == true
current_element == 0
CONVENTION
current_element_valid() == (current_element != 0)
if (current_element_valid()) then
element() == current_element->d and current_element->r
at_start_ == at_start()
tree_size == size()
NIL == pointer to a node that represents a leaf
if (tree_size != 0)
tree_root == pointer to the root node of the binary search tree
else
tree_root == NIL
tree_root->color == black
Every leaf is black and all leafs are the NIL node.
The number of black nodes in any path from the root to a leaf is the
same.
for all nodes:
{
- left points to the left subtree or NIL if there is no left subtree
- right points to the right subtree or NIL if there is no right
subtree
- parent points to the parent node or NIL if the node is the root
- ordering of nodes is determined by comparing each node's d member
- all elements in a left subtree are <= the node
- all elements in a right subtree are >= the node
- color == red or black
- if (color == red)
- the node's children are black
}
!*/
class node
{
public:
node* left;
node* right;
node* parent;
domain d;
range r;
char color;
};
class mpair : public map_pair<domain,range>
{
public:
const domain* d;
range* r;
const domain& key(
) const { return *d; }
const range& value(
) const { return *r; }
range& value(
) { return *r; }
};
const static char red = 0;
const static char black = 1;
public:
typedef domain domain_type;
typedef range range_type;
typedef compare compare_type;
typedef mem_manager mem_manager_type;
binary_search_tree_kernel_2(
) :
NIL(pool.allocate()),
tree_size(0),
tree_root(NIL),
current_element(0),
at_start_(true)
{
NIL->color = black;
NIL->left = 0;
NIL->right = 0;
NIL->parent = 0;
}
virtual ~binary_search_tree_kernel_2(
);
inline void clear(
);
inline short height (
) const;
inline unsigned long count (
const domain& d
) const;
inline void add (
domain& d,
range& r
);
void remove (
const domain& d,
domain& d_copy,
range& r
);
void destroy (
const domain& d
);
void remove_any (
domain& d,
range& r
);
inline const range* operator[] (
const domain& item
) const;
inline range* operator[] (
const domain& item
);
inline void swap (
binary_search_tree_kernel_2& item
);
// functions from the enumerable interface
inline size_t size (
) const;
bool at_start (
) const;
inline void reset (
) const;
bool current_element_valid (
) const;
const map_pair<domain,range>& element (
) const;
map_pair<domain,range>& element (
);
bool move_next (
) const;
void remove_last_in_order (
domain& d,
range& r
);
void remove_current_element (
domain& d,
range& r
);
void position_enumerator (
const domain& d
) const;
private:
inline void rotate_left (
node* t
);
/*!
requires
- t != NIL
- t->right != NIL
ensures
- performs a left rotation around t and its right child
!*/
inline void rotate_right (
node* t
);
/*!
requires
- t != NIL
- t->left != NIL
ensures
- performs a right rotation around t and its left child
!*/
inline void double_rotate_right (
node* t
);
/*!
requires
- t != NIL
- t->left != NIL
- t->left->right != NIL
- double_rotate_right() is only called in fix_after_add()
ensures
- performs a left rotation around t->left
- then performs a right rotation around t
!*/
inline void double_rotate_left (
node* t
);
/*!
requires
- t != NIL
- t->right != NIL
- t->right->left != NIL
- double_rotate_left() is only called in fix_after_add()
ensures
- performs a right rotation around t->right
- then performs a left rotation around t
!*/
void remove_biggest_element_in_tree (
node* t,
domain& d,
range& r
);
/*!
requires
- t != NIL (i.e. there must be something in the tree to remove)
ensures
- the biggest node in t has been removed
- the biggest node element in t has been put into #d and #r
- #t is still a binary search tree
!*/
bool remove_least_element_in_tree (
node* t,
domain& d,
range& r
);
/*!
requires
- t != NIL (i.e. there must be something in the tree to remove)
ensures
- the least node in t has been removed
- the least node element in t has been put into #d and #r
- #t is still a binary search tree
- if (the node that was removed was the one pointed to by current_element) then
- returns true
- else
- returns false
!*/
void add_to_tree (
node* t,
domain& d,
range& r
);
/*!
requires
- t != NIL
ensures
- d and r are now in #t
- there is a mapping from d to r in #t
- #d and #r have initial values for their types
- #t is still a binary search tree
!*/
void remove_from_tree (
node* t,
const domain& d,
domain& d_copy,
range& r
);
/*!
requires
- return_reference(t,d) != 0
ensures
- #d_copy is equivalent to d
- the first element in t equivalent to d that is encountered when searching down the tree
from t has been removed and swapped into #d_copy. Also, the associated range element
has been removed and swapped into #r.
- if (the node that got removed wasn't current_element) then
- adjusts the current_element pointer if the data in the node that it points to gets moved.
- else
- the value of current_element is now invalid
- #t is still a binary search tree
!*/
void remove_from_tree (
node* t,
const domain& d
);
/*!
requires
- return_reference(t,d) != 0
ensures
- an element in t equivalent to d has been removed
- #t is still a binary search tree
!*/
const range* return_reference (
const node* t,
const domain& d
) const;
/*!
ensures
- if (there is a domain element equivalent to d in t) then
- returns a pointer to the element in the range equivalent to d
- else
- returns 0
!*/
range* return_reference (
node* t,
const domain& d
);
/*!
ensures
- if (there is a domain element equivalent to d in t) then
- returns a pointer to the element in the range equivalent to d
- else
- returns 0
!*/
void fix_after_add (
node* t
);
/*!
requires
- t == pointer to the node just added
- t->color == red
- t->parent != NIL (t must not be the root)
- fix_after_add() is only called after a new node has been added
to t
ensures
- fixes any deviations from the CONVENTION caused by adding a node
!*/
void fix_after_remove (
node* t
);
/*!
requires
- t == pointer to the only child of the node that was spliced out
- fix_after_remove() is only called after a node has been removed
from t
- the color of the spliced out node was black
ensures
- fixes any deviations from the CONVENTION causes by removing a node
!*/
short tree_height (
node* t
) const;
/*!
ensures
- returns the number of nodes in the longest path from the root of the
tree to a leaf
!*/
void delete_tree (
node* t
);
/*!
requires
- t == root of binary search tree
- t != NIL
ensures
- deletes all nodes in t except for NIL
!*/
unsigned long get_count (
const domain& item,
node* tree_root
) const;
/*!
requires
- tree_root == the root of a binary search tree or NIL
ensures
- if (tree_root == NIL) then
- returns 0
- else
- returns the number of elements in tree_root that are
equivalent to item
!*/
// data members
typename mem_manager::template rebind<node>::other pool;
node* NIL;
unsigned long tree_size;
node* tree_root;
mutable node* current_element;
mutable bool at_start_;
mutable mpair p;
compare comp;
// restricted functions
binary_search_tree_kernel_2(binary_search_tree_kernel_2&);
binary_search_tree_kernel_2& operator=(binary_search_tree_kernel_2&);
};
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
inline void swap (
binary_search_tree_kernel_2<domain,range,mem_manager,compare>& a,
binary_search_tree_kernel_2<domain,range,mem_manager,compare>& b
) { a.swap(b); }
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
void deserialize (
binary_search_tree_kernel_2<domain,range,mem_manager,compare>& item,
std::istream& in
)
{
try
{
item.clear();
unsigned long size;
deserialize(size,in);
domain d;
range r;
for (unsigned long i = 0; i < size; ++i)
{
deserialize(d,in);
deserialize(r,in);
item.add(d,r);
}
}
catch (serialization_error& e)
{
item.clear();
throw serialization_error(e.info + "\n while deserializing object of type binary_search_tree_kernel_2");
}
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
binary_search_tree_kernel_2<domain,range,mem_manager,compare>::
~binary_search_tree_kernel_2 (
)
{
if (tree_root != NIL)
delete_tree(tree_root);
pool.deallocate(NIL);
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
void binary_search_tree_kernel_2<domain,range,mem_manager,compare>::
clear (
)
{
if (tree_size > 0)
{
delete_tree(tree_root);
tree_root = NIL;
tree_size = 0;
}
// reset the enumerator
reset();
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
size_t binary_search_tree_kernel_2<domain,range,mem_manager,compare>::
size (
) const
{
return tree_size;
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
short binary_search_tree_kernel_2<domain,range,mem_manager,compare>::
height (
) const
{
return tree_height(tree_root);
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
unsigned long binary_search_tree_kernel_2<domain,range,mem_manager,compare>::
count (
const domain& item
) const
{
return get_count(item,tree_root);
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
void binary_search_tree_kernel_2<domain,range,mem_manager,compare>::
add (
domain& d,
range& r
)
{
if (tree_size == 0)
{
tree_root = pool.allocate();
tree_root->color = black;
tree_root->left = NIL;
tree_root->right = NIL;
tree_root->parent = NIL;
exchange(tree_root->d,d);
exchange(tree_root->r,r);
}
else
{
add_to_tree(tree_root,d,r);
}
++tree_size;
// reset the enumerator
reset();
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
void binary_search_tree_kernel_2<domain,range,mem_manager,compare>::
remove (
const domain& d,
domain& d_copy,
range& r
)
{
remove_from_tree(tree_root,d,d_copy,r);
--tree_size;
// reset the enumerator
reset();
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
void binary_search_tree_kernel_2<domain,range,mem_manager,compare>::
destroy (
const domain& item
)
{
remove_from_tree(tree_root,item);
--tree_size;
// reset the enumerator
reset();
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
void binary_search_tree_kernel_2<domain,range,mem_manager,compare>::
remove_any (
domain& d,
range& r
)
{
remove_least_element_in_tree(tree_root,d,r);
--tree_size;
// reset the enumerator
reset();
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
range* binary_search_tree_kernel_2<domain,range,mem_manager,compare>::
operator[] (
const domain& d
)
{
return return_reference(tree_root,d);
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
const range* binary_search_tree_kernel_2<domain,range,mem_manager,compare>::
operator[] (
const domain& d
) const
{
return return_reference(tree_root,d);
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
void binary_search_tree_kernel_2<domain,range,mem_manager,compare>::
swap (
binary_search_tree_kernel_2<domain,range,mem_manager,compare>& item
)
{
pool.swap(item.pool);
exchange(p,item.p);
exchange(comp,item.comp);
node* tree_root_temp = item.tree_root;
unsigned long tree_size_temp = item.tree_size;
node* const NIL_temp = item.NIL;
node* current_element_temp = item.current_element;
bool at_start_temp = item.at_start_;
item.tree_root = tree_root;
item.tree_size = tree_size;
item.NIL = NIL;
item.current_element = current_element;
item.at_start_ = at_start_;
tree_root = tree_root_temp;
tree_size = tree_size_temp;
NIL = NIL_temp;
current_element = current_element_temp;
at_start_ = at_start_temp;
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
void binary_search_tree_kernel_2<domain,range,mem_manager,compare>::
remove_last_in_order (
domain& d,
range& r
)
{
remove_biggest_element_in_tree(tree_root,d,r);
--tree_size;
// reset the enumerator
reset();
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
void binary_search_tree_kernel_2<domain,range,mem_manager,compare>::
remove_current_element (
domain& d,
range& r
)
{
node* t = current_element;
move_next();
remove_from_tree(t,t->d,d,r);
--tree_size;
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
void binary_search_tree_kernel_2<domain,range,mem_manager,compare>::
position_enumerator (
const domain& d
) const
{
// clear the enumerator state and make sure the stack is empty
reset();
at_start_ = false;
node* t = tree_root;
node* parent = NIL;
bool went_left = false;
while (t != NIL)
{
if ( comp(d , t->d ))
{
// if item is on the left then look in left
parent = t;
t = t->left;
went_left = true;
}
else if (comp(t->d , d))
{
// if item is on the right then look in right
parent = t;
t = t->right;
went_left = false;
}
else
{
current_element = t;
return;
}
}
// if we didn't find any matches but there might be something after the
// d in this tree.
if (parent != NIL)
{
current_element = parent;
// if we went left from this node then this node is the next
// biggest.
if (went_left)
{
return;
}
else
{
move_next();
}
}
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// enumerable function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
bool binary_search_tree_kernel_2<domain,range,mem_manager,compare>::
at_start (
) const
{
return at_start_;
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
void binary_search_tree_kernel_2<domain,range,mem_manager,compare>::
reset (
) const
{
at_start_ = true;
current_element = 0;
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
bool binary_search_tree_kernel_2<domain,range,mem_manager,compare>::
current_element_valid (
) const
{
return (current_element != 0);
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
const map_pair<domain,range>& binary_search_tree_kernel_2<domain,range,mem_manager,compare>::
element (
) const
{
p.d = &(current_element->d);
p.r = &(current_element->r);
return p;
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
map_pair<domain,range>& binary_search_tree_kernel_2<domain,range,mem_manager,compare>::
element (
)
{
p.d = &(current_element->d);
p.r = &(current_element->r);
return p;
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
bool binary_search_tree_kernel_2<domain,range,mem_manager,compare>::
move_next (
) const
{
// if we haven't started iterating yet
if (at_start_)
{
at_start_ = false;
if (tree_size == 0)
{
return false;
}
else
{
// find the first element in the tree
current_element = tree_root;
node* temp = current_element->left;
while (temp != NIL)
{
current_element = temp;
temp = current_element->left;
}
return true;
}
}
else
{
if (current_element == 0)
{
return false;
}
else
{
bool went_up; // true if we went up the tree from a child node to parent
bool from_left = false; // true if we went up and were coming from a left child node
// find the next element in the tree
if (current_element->right != NIL)
{
// go right and down
current_element = current_element->right;
went_up = false;
}
else
{
went_up = true;
node* parent = current_element->parent;
if (parent == NIL)
{
// in this case we have iterated over all the element of the tree
current_element = 0;
return false;
}
from_left = (parent->left == current_element);
// go up to parent
current_element = parent;
}
while (true)
{
if (went_up)
{
if (from_left)
{
// in this case we have found the next node
break;
}
else
{
// we should go up
node* parent = current_element->parent;
from_left = (parent->left == current_element);
current_element = parent;
if (current_element == NIL)
{
// in this case we have iterated over all the elements
// in the tree
current_element = 0;
return false;
}
}
}
else
{
// we just went down to a child node
if (current_element->left != NIL)
{
// go left
went_up = false;
current_element = current_element->left;
}
else
{
// if there is no left child then we have found the next node
break;
}
}
}
return true;
}
}
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// private member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
void binary_search_tree_kernel_2<domain,range,mem_manager,compare>::
delete_tree (
node* t
)
{
if (t->left != NIL)
delete_tree(t->left);
if (t->right != NIL)
delete_tree(t->right);
pool.deallocate(t);
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
void binary_search_tree_kernel_2<domain,range,mem_manager,compare>::
rotate_left (
node* t
)
{
// perform the rotation
node* temp = t->right;
t->right = temp->left;
if (temp->left != NIL)
temp->left->parent = t;
temp->left = t;
temp->parent = t->parent;
if (t == tree_root)
tree_root = temp;
else
{
// if t was on the left
if (t->parent->left == t)
t->parent->left = temp;
else
t->parent->right = temp;
}
t->parent = temp;
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
void binary_search_tree_kernel_2<domain,range,mem_manager,compare>::
rotate_right (
node* t
)
{
// perform the rotation
node* temp = t->left;
t->left = temp->right;
if (temp->right != NIL)
temp->right->parent = t;
temp->right = t;
temp->parent = t->parent;
if (t == tree_root)
tree_root = temp;
else
{
// if t is a left child
if (t->parent->left == t)
t->parent->left = temp;
else
t->parent->right = temp;
}
t->parent = temp;
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
void binary_search_tree_kernel_2<domain,range,mem_manager,compare>::
double_rotate_right (
node* t
)
{
// preform the rotation
node& temp = *(t->left->right);
t->left = temp.right;
temp.right->parent = t;
temp.left->parent = temp.parent;
temp.parent->right = temp.left;
temp.parent->parent = &temp;
temp.right = t;
temp.left = temp.parent;
temp.parent = t->parent;
if (tree_root == t)
tree_root = &temp;
else
{
// t is a left child
if (t->parent->left == t)
t->parent->left = &temp;
else
t->parent->right = &temp;
}
t->parent = &temp;
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
void binary_search_tree_kernel_2<domain,range,mem_manager,compare>::
double_rotate_left (
node* t
)
{
// preform the rotation
node& temp = *(t->right->left);
t->right = temp.left;
temp.left->parent = t;
temp.right->parent = temp.parent;
temp.parent->left = temp.right;
temp.parent->parent = &temp;
temp.left = t;
temp.right = temp.parent;
temp.parent = t->parent;
if (tree_root == t)
tree_root = &temp;
else
{
// t is a left child
if (t->parent->left == t)
t->parent->left = &temp;
else
t->parent->right = &temp;
}
t->parent = &temp;
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
void binary_search_tree_kernel_2<domain,range,mem_manager,compare>::
remove_biggest_element_in_tree (
node* t,
domain& d,
range& r
)
{
node* next = t->right;
node* child; // the child node of the one we will slice out
if (next == NIL)
{
// need to determine if t is a right or left child
if (t->parent->right == t)
child = t->parent->right = t->left;
else
child = t->parent->left = t->left;
// update tree_root if necessary
if (t == tree_root)
tree_root = child;
}
else
{
// find the least node
do
{
t = next;
next = next->right;
} while (next != NIL);
// t is a right child
child = t->parent->right = t->left;
}
// swap the item from this node into d and r
exchange(d,t->d);
exchange(r,t->r);
// plug hole right by removing this node
child->parent = t->parent;
// keep the red-black properties true
if (t->color == black)
fix_after_remove(child);
// free the memory for this removed node
pool.deallocate(t);
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
bool binary_search_tree_kernel_2<domain,range,mem_manager,compare>::
remove_least_element_in_tree (
node* t,
domain& d,
range& r
)
{
node* next = t->left;
node* child; // the child node of the one we will slice out
if (next == NIL)
{
// need to determine if t is a left or right child
if (t->parent->left == t)
child = t->parent->left = t->right;
else
child = t->parent->right = t->right;
// update tree_root if necessary
if (t == tree_root)
tree_root = child;
}
else
{
// find the least node
do
{
t = next;
next = next->left;
} while (next != NIL);
// t is a left child
child = t->parent->left = t->right;
}
// swap the item from this node into d and r
exchange(d,t->d);
exchange(r,t->r);
// plug hole left by removing this node
child->parent = t->parent;
// keep the red-black properties true
if (t->color == black)
fix_after_remove(child);
bool rvalue = (t == current_element);
// free the memory for this removed node
pool.deallocate(t);
return rvalue;
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
void binary_search_tree_kernel_2<domain,range,mem_manager,compare>::
add_to_tree (
node* t,
domain& d,
range& r
)
{
// parent of the current node
node* parent;
// find a place to add node
while (true)
{
parent = t;
// if item should be put on the left then go left
if (comp(d , t->d))
{
t = t->left;
if (t == NIL)
{
t = parent->left = pool.allocate();
break;
}
}
// if item should be put on the right then go right
else
{
t = t->right;
if (t == NIL)
{
t = parent->right = pool.allocate();
break;
}
}
}
// t is now the node where we will add item and
// parent is the parent of t
t->parent = parent;
t->left = NIL;
t->right = NIL;
t->color = red;
exchange(t->d,d);
exchange(t->r,r);
// keep the red-black properties true
fix_after_add(t);
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
void binary_search_tree_kernel_2<domain,range,mem_manager,compare>::
remove_from_tree (
node* t,
const domain& d,
domain& d_copy,
range& r
)
{
while (true)
{
if ( comp(d , t->d) )
{
// if item is on the left then look in left
t = t->left;
}
else if (comp(t->d , d))
{
// if item is on the right then look in right
t = t->right;
}
else
{
// found the node we want to remove
// swap out the item into d_copy and r
exchange(d_copy,t->d);
exchange(r,t->r);
if (t->left == NIL)
{
// if there is no left subtree
node* parent = t->parent;
// plug hole with right subtree
// if t is on the left
if (parent->left == t)
parent->left = t->right;
else
parent->right = t->right;
t->right->parent = parent;
// update tree_root if necessary
if (t == tree_root)
tree_root = t->right;
if (t->color == black)
fix_after_remove(t->right);
// delete old node
pool.deallocate(t);
}
else if (t->right == NIL)
{
// if there is no right subtree
node* parent = t->parent;
// plug hole with left subtree
if (parent->left == t)
parent->left = t->left;
else
parent->right = t->left;
t->left->parent = parent;
// update tree_root if necessary
if (t == tree_root)
tree_root = t->left;
if (t->color == black)
fix_after_remove(t->left);
// delete old node
pool.deallocate(t);
}
else
{
// if there is both a left and right subtree
// get an element to fill this node now that its been swapped into
// item_copy
if (remove_least_element_in_tree(t->right,t->d,t->r))
{
// the node removed was the one pointed to by current_element so we
// need to update it so that it points to the right spot.
current_element = t;
}
}
// quit loop
break;
}
}
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
void binary_search_tree_kernel_2<domain,range,mem_manager,compare>::
remove_from_tree (
node* t,
const domain& d
)
{
while (true)
{
if ( comp(d , t->d) )
{
// if item is on the left then look in left
t = t->left;
}
else if (comp(t->d , d))
{
// if item is on the right then look in right
t = t->right;
}
else
{
// found the node we want to remove
if (t->left == NIL)
{
// if there is no left subtree
node* parent = t->parent;
// plug hole with right subtree
if (parent->left == t)
parent->left = t->right;
else
parent->right = t->right;
t->right->parent = parent;
// update tree_root if necessary
if (t == tree_root)
tree_root = t->right;
if (t->color == black)
fix_after_remove(t->right);
// delete old node
pool.deallocate(t);
}
else if (t->right == NIL)
{
// if there is no right subtree
node* parent = t->parent;
// plug hole with left subtree
if (parent->left == t)
parent->left = t->left;
else
parent->right = t->left;
t->left->parent = parent;
// update tree_root if necessary
if (t == tree_root)
tree_root = t->left;
if (t->color == black)
fix_after_remove(t->left);
// delete old node
pool.deallocate(t);
}
else
{
// if there is both a left and right subtree
// get an element to fill this node now that its been swapped into
// item_copy
remove_least_element_in_tree(t->right,t->d,t->r);
}
// quit loop
break;
}
}
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
range* binary_search_tree_kernel_2<domain,range,mem_manager,compare>::
return_reference (
node* t,
const domain& d
)
{
while (t != NIL)
{
if ( comp(d , t->d ))
{
// if item is on the left then look in left
t = t->left;
}
else if (comp(t->d , d))
{
// if item is on the right then look in right
t = t->right;
}
else
{
// if it's found then return a reference to it
return &(t->r);
}
}
return 0;
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
const range* binary_search_tree_kernel_2<domain,range,mem_manager,compare>::
return_reference (
const node* t,
const domain& d
) const
{
while (t != NIL)
{
if ( comp(d , t->d) )
{
// if item is on the left then look in left
t = t->left;
}
else if (comp(t->d , d))
{
// if item is on the right then look in right
t = t->right;
}
else
{
// if it's found then return a reference to it
return &(t->r);
}
}
return 0;
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
void binary_search_tree_kernel_2<domain,range,mem_manager,compare>::
fix_after_add (
node* t
)
{
while (t->parent->color == red)
{
node& grandparent = *(t->parent->parent);
// if both t's parent and its sibling are red
if (grandparent.left->color == grandparent.right->color)
{
grandparent.color = red;
grandparent.left->color = black;
grandparent.right->color = black;
t = &grandparent;
}
else
{
// if t is a left child
if (t == t->parent->left)
{
// if t's parent is a left child
if (t->parent == grandparent.left)
{
grandparent.color = red;
grandparent.left->color = black;
rotate_right(&grandparent);
}
// if t's parent is a right child
else
{
t->color = black;
grandparent.color = red;
double_rotate_left(&grandparent);
}
}
// if t is a right child
else
{
// if t's parent is a left child
if (t->parent == grandparent.left)
{
t->color = black;
grandparent.color = red;
double_rotate_right(&grandparent);
}
// if t's parent is a right child
else
{
grandparent.color = red;
grandparent.right->color = black;
rotate_left(&grandparent);
}
}
break;
}
}
tree_root->color = black;
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
void binary_search_tree_kernel_2<domain,range,mem_manager,compare>::
fix_after_remove (
node* t
)
{
while (t != tree_root && t->color == black)
{
if (t->parent->left == t)
{
node* sibling = t->parent->right;
if (sibling->color == red)
{
sibling->color = black;
t->parent->color = red;
rotate_left(t->parent);
sibling = t->parent->right;
}
if (sibling->left->color == black && sibling->right->color == black)
{
sibling->color = red;
t = t->parent;
}
else
{
if (sibling->right->color == black)
{
sibling->left->color = black;
sibling->color = red;
rotate_right(sibling);
sibling = t->parent->right;
}
sibling->color = t->parent->color;
t->parent->color = black;
sibling->right->color = black;
rotate_left(t->parent);
t = tree_root;
}
}
else
{
node* sibling = t->parent->left;
if (sibling->color == red)
{
sibling->color = black;
t->parent->color = red;
rotate_right(t->parent);
sibling = t->parent->left;
}
if (sibling->left->color == black && sibling->right->color == black)
{
sibling->color = red;
t = t->parent;
}
else
{
if (sibling->left->color == black)
{
sibling->right->color = black;
sibling->color = red;
rotate_left(sibling);
sibling = t->parent->left;
}
sibling->color = t->parent->color;
t->parent->color = black;
sibling->left->color = black;
rotate_right(t->parent);
t = tree_root;
}
}
}
t->color = black;
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
short binary_search_tree_kernel_2<domain,range,mem_manager,compare>::
tree_height (
node* t
) const
{
if (t == NIL)
return 0;
short height1 = tree_height(t->left);
short height2 = tree_height(t->right);
if (height1 > height2)
return height1 + 1;
else
return height2 + 1;
}
// ----------------------------------------------------------------------------------------
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
unsigned long binary_search_tree_kernel_2<domain,range,mem_manager,compare>::
get_count (
const domain& d,
node* tree_root
) const
{
if (tree_root != NIL)
{
if (comp(d , tree_root->d))
{
// go left
return get_count(d,tree_root->left);
}
else if (comp(tree_root->d , d))
{
// go right
return get_count(d,tree_root->right);
}
else
{
// go left and right to look for more matches
return get_count(d,tree_root->left)
+ get_count(d,tree_root->right)
+ 1;
}
}
return 0;
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_BINARY_SEARCH_TREE_KERNEl_2_
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_BINARY_SEARCH_TREE_KERNEl_ABSTRACT_
#ifdef DLIB_BINARY_SEARCH_TREE_KERNEl_ABSTRACT_
#include "../interfaces/map_pair.h"
#include "../interfaces/enumerable.h"
#include "../interfaces/remover.h"
#include "../serialize.h"
#include "../algs.h"
#include <functional>
namespace dlib
{
template <
typename domain,
typename range,
typename mem_manager = default_memory_manager,
typename compare = std::less<domain>
>
class binary_search_tree : public enumerable<map_pair<domain,range> >,
public asc_pair_remover<domain,range,compare>
{
/*!
REQUIREMENTS ON domain
domain must be comparable by compare where compare is a functor compatible with std::less and
domain is swappable by a global swap() and
domain must have a default constructor
REQUIREMENTS ON range
range is swappable by a global swap() and
range 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
swap(), count(), height(), and operator[] functions
do not invalidate pointers or references to internal data.
position_enumerator() invalidates pointers or references to
data returned by element() and only by element() (i.e. pointers and
references returned by operator[] are still valid).
All other functions have no such guarantees.
INITIAL VALUE
size() == 0
height() == 0
ENUMERATION ORDER
The enumerator will iterate over the domain (and each associated
range element) elements in ascending order according to the compare functor.
(i.e. the elements are enumerated in sorted order)
WHAT THIS OBJECT REPRESENTS
this object represents a data dictionary that is built on top of some
kind of binary search tree. It maps objects of type domain to objects
of type range.
Also note that unless specified otherwise, no member functions
of this object throw exceptions.
NOTE:
definition of equivalent:
a is equivalent to b if
a < b == false and
b < a == false
!*/
public:
typedef domain domain_type;
typedef range range_type;
typedef compare compare_type;
typedef mem_manager mem_manager_type;
binary_search_tree(
);
/*!
ensures
- #*this is properly initialized
throws
- std::bad_alloc or any exception thrown by domain's or range's
constructor.
!*/
virtual ~binary_search_tree(
);
/*!
ensures
- all memory associated with *this has been released
!*/
void clear(
);
/*!
ensures
- #*this has its initial value
throws
- std::bad_alloc or any exception thrown by domain's or range's
constructor.
if this exception is thrown then *this is unusable
until clear() is called and succeeds
!*/
short height (
) const;
/*!
ensures
- returns the number of elements in the longest path from the root
of the tree to a leaf
!*/
unsigned long count (
const domain& d
) const;
/*!
ensures
- returns the number of elements in the domain of *this that are
equivalent to d
!*/
void add (
domain& d,
range& r
);
/*!
requires
- &d != &r (i.e. d and r cannot be the same variable)
ensures
- adds a mapping between d and r to *this
- if (count(d) == 0) then
- #*(*this)[d] == r
- else
- #(*this)[d] != 0
- #d and #r have initial values for their types
- #count(d) == count(d) + 1
- #at_start() == true
- #size() == size() + 1
throws
- std::bad_alloc or any exception thrown by domain's or range's
constructor.
if add() throws then it has no effect
!*/
void remove (
const domain& d,
domain& d_copy,
range& r
);
/*!
requires
- (*this)[d] != 0
- &d != &r (i.e. d and r cannot be the same variable)
- &d != &d_copy (i.e. d and d_copy cannot be the same variable)
- &r != &d_copy (i.e. r and d_copy cannot be the same variable)
ensures
- some element in the domain of *this that is equivalent to d has
been removed and swapped into #d_copy. Additionally, its
associated range element has been removed and swapped into #r.
- #count(d) == count(d) - 1
- #size() == size() - 1
- #at_start() == true
!*/
void destroy (
const domain& d
);
/*!
requires
- (*this)[d] != 0
ensures
- an element in the domain of *this equivalent to d has been removed.
The element in the range of *this associated with d has also been
removed.
- #count(d) == count(d) - 1
- #size() == size() - 1
- #at_start() == true
!*/
void remove_last_in_order (
domain& d,
range& r
);
/*!
requires
- size() > 0
ensures
- the last/biggest (according to the compare functor) element in the domain of *this has
been removed and swapped into #d. The element in the range of *this
associated with #d has also been removed and swapped into #r.
- #count(#d) == count(#d) - 1
- #size() == size() - 1
- #at_start() == true
!*/
void remove_current_element (
domain& d,
range& r
);
/*!
requires
- current_element_valid() == true
ensures
- the current element given by element() has been removed and swapped into d and r.
- #d == element().key()
- #r == element().value()
- #count(#d) == count(#d) - 1
- #size() == size() - 1
- moves the enumerator to the next element. If element() was the last
element in enumeration order then #current_element_valid() == false
and #at_start() == false.
!*/
void position_enumerator (
const domain& d
) const;
/*!
ensures
- #at_start() == false
- if (count(d) > 0) then
- #element().key() == d
- else if (there are any items in the domain of *this that are bigger than
d according to the compare functor) then
- #element().key() == the smallest item in the domain of *this that is
bigger than d according to the compare functor.
- else
- #current_element_valid() == false
!*/
const range* operator[] (
const domain& d
) const;
/*!
ensures
- if (there is an element in the domain equivalent to d) then
- returns a pointer to an element in the range of *this that
is associated with an element in the domain of *this
equivalent to d.
- else
- returns 0
!*/
range* operator[] (
const domain& d
);
/*!
ensures
- if (there is an element in the domain equivalent to d) then
- returns a pointer to an element in the range of *this that
is associated with an element in the domain of *this
equivalent to d.
- else
- returns 0
!*/
void swap (
binary_search_tree& item
);
/*!
ensures
- swaps *this and item
!*/
private:
// restricted functions
binary_search_tree(binary_search_tree&);
binary_search_tree& operator=(binary_search_tree&);
};
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
inline void swap (
binary_search_tree<domain,range,mem_manager,compare>& a,
binary_search_tree<domain,range,mem_manager,compare>& b
) { a.swap(b); }
/*!
provides a global swap function
!*/
template <
typename domain,
typename range,
typename mem_manager,
typename compare
>
void deserialize (
binary_search_tree<domain,range,mem_manager,compare>& item,
std::istream& in
);
/*!
provides deserialization support
!*/
}
#endif // DLIB_BINARY_SEARCH_TREE_KERNEl_ABSTRACT_
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_BINARY_SEARCH_TREE_KERNEl_C_
#define DLIB_BINARY_SEARCH_TREE_KERNEl_C_
#include "../interfaces/map_pair.h"
#include "binary_search_tree_kernel_abstract.h"
#include "../algs.h"
#include "../assert.h"
namespace dlib
{
template <
typename bst_base
>
class binary_search_tree_kernel_c : public bst_base
{
typedef typename bst_base::domain_type domain;
typedef typename bst_base::range_type range;
public:
binary_search_tree_kernel_c () {}
void remove (
const domain& d,
domain& d_copy,
range& r
);
void destroy (
const domain& d
);
void add (
domain& d,
range& r
);
void remove_any (
domain& d,
range& r
);
const map_pair<domain, range>& element(
) const
{
DLIB_CASSERT(this->current_element_valid() == true,
"\tconst map_pair<domain,range>& binary_search_tree::element() const"
<< "\n\tyou can't access the current element if it doesn't exist"
<< "\n\tthis: " << this
);
return bst_base::element();
}
map_pair<domain, range>& element(
)
{
DLIB_CASSERT(this->current_element_valid() == true,
"\tmap_pair<domain,range>& binary_search_tree::element()"
<< "\n\tyou can't access the current element if it doesn't exist"
<< "\n\tthis: " << this
);
return bst_base::element();
}
void remove_last_in_order (
domain& d,
range& r
);
void remove_current_element (
domain& d,
range& r
);
};
template <
typename bst_base
>
inline void swap (
binary_search_tree_kernel_c<bst_base>& a,
binary_search_tree_kernel_c<bst_base>& b
) { a.swap(b); }
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename bst_base
>
void binary_search_tree_kernel_c<bst_base>::
add (
domain& d,
range& r
)
{
DLIB_CASSERT( static_cast<const void*>(&d) != static_cast<void*>(&r),
"\tvoid binary_search_tree::add"
<< "\n\tyou can't call add() and give the same object to both parameters."
<< "\n\tthis: " << this
<< "\n\t&d: " << &d
<< "\n\t&r: " << &r
<< "\n\tsize(): " << this->size()
);
bst_base::add(d,r);
}
// ----------------------------------------------------------------------------------------
template <
typename bst_base
>
void binary_search_tree_kernel_c<bst_base>::
destroy (
const domain& d
)
{
DLIB_CASSERT(this->operator[](d) != 0,
"\tvoid binary_search_tree::destroy"
<< "\n\tthe element must be in the tree for it to be removed"
<< "\n\tthis: " << this
<< "\n\t&d: " << &d
);
bst_base::destroy(d);
}
// ----------------------------------------------------------------------------------------
template <
typename bst_base
>
void binary_search_tree_kernel_c<bst_base>::
remove (
const domain& d,
domain& d_copy,
range& r
)
{
DLIB_CASSERT(this->operator[](d) != 0 &&
(static_cast<const void*>(&d) != static_cast<void*>(&d_copy)) &&
(static_cast<const void*>(&d) != static_cast<void*>(&r)) &&
(static_cast<const void*>(&r) != static_cast<void*>(&d_copy)),
"\tvoid binary_search_tree::remove"
<< "\n\tthe element must be in the tree for it to be removed"
<< "\n\tthis: " << this
<< "\n\t&d: " << &d
<< "\n\t&d_copy: " << &d_copy
<< "\n\t&r: " << &r
);
bst_base::remove(d,d_copy,r);
}
// ----------------------------------------------------------------------------------------
template <
typename bst_base
>
void binary_search_tree_kernel_c<bst_base>::
remove_any(
domain& d,
range& r
)
{
DLIB_CASSERT(this->size() != 0 &&
(static_cast<const void*>(&d) != static_cast<void*>(&r)),
"\tvoid binary_search_tree::remove_any"
<< "\n\ttree must not be empty if something is going to be removed"
<< "\n\tthis: " << this
<< "\n\t&d: " << &d
<< "\n\t&r: " << &r
);
bst_base::remove_any(d,r);
}
// ----------------------------------------------------------------------------------------
template <
typename bst_base
>
void binary_search_tree_kernel_c<bst_base>::
remove_last_in_order (
domain& d,
range& r
)
{
DLIB_CASSERT(this->size() > 0,
"\tvoid binary_search_tree::remove_last_in_order()"
<< "\n\tyou can't remove an element if it doesn't exist"
<< "\n\tthis: " << this
);
bst_base::remove_last_in_order(d,r);
}
// ----------------------------------------------------------------------------------------
template <
typename bst_base
>
void binary_search_tree_kernel_c<bst_base>::
remove_current_element (
domain& d,
range& r
)
{
DLIB_CASSERT(this->current_element_valid() == true,
"\tvoid binary_search_tree::remove_current_element()"
<< "\n\tyou can't remove the current element if it doesn't exist"
<< "\n\tthis: " << this
);
bst_base::remove_current_element(d,r);
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_BINARY_SEARCH_TREE_KERNEl_C_
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_BIT_STREAm_
#define DLIB_BIT_STREAm_
#include "bit_stream/bit_stream_kernel_1.h"
#include "bit_stream/bit_stream_kernel_c.h"
#include "bit_stream/bit_stream_multi_1.h"
#include "bit_stream/bit_stream_multi_c.h"
namespace dlib
{
class bit_stream
{
bit_stream() {}
public:
//----------- kernels ---------------
// kernel_1a
typedef bit_stream_kernel_1
kernel_1a;
typedef bit_stream_kernel_c<kernel_1a >
kernel_1a_c;
//---------- extensions ------------
// multi_1 extend kernel_1a
typedef bit_stream_multi_1<kernel_1a>
multi_1a;
typedef bit_stream_multi_c<bit_stream_multi_1<kernel_1a_c> >
multi_1a_c;
};
}
#endif // DLIB_BIT_STREAm_
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_BIT_STREAM_KERNEL_1_CPp_
#define DLIB_BIT_STREAM_KERNEL_1_CPp_
#include "bit_stream_kernel_1.h"
#include "../algs.h"
#include <iostream>
namespace dlib
{
inline void swap (
bit_stream_kernel_1& a,
bit_stream_kernel_1& b
) { a.swap(b); }
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
void bit_stream_kernel_1::
clear (
)
{
if (write_mode)
{
write_mode = false;
// flush output buffer
if (buffer_size > 0)
{
buffer <<= 8 - buffer_size;
osp->write(reinterpret_cast<char*>(&buffer),1);
}
}
else
read_mode = false;
}
// ----------------------------------------------------------------------------------------
void bit_stream_kernel_1::
set_input_stream (
std::istream& is
)
{
isp = &is;
read_mode = true;
buffer_size = 0;
}
// ----------------------------------------------------------------------------------------
void bit_stream_kernel_1::
set_output_stream (
std::ostream& os
)
{
osp = &os;
write_mode = true;
buffer_size = 0;
}
// ----------------------------------------------------------------------------------------
void bit_stream_kernel_1::
close (
)
{
if (write_mode)
{
write_mode = false;
// flush output buffer
if (buffer_size > 0)
{
buffer <<= 8 - buffer_size;
osp->write(reinterpret_cast<char*>(&buffer),1);
}
}
else
read_mode = false;
}
// ----------------------------------------------------------------------------------------
bool bit_stream_kernel_1::
is_in_write_mode (
) const
{
return write_mode;
}
// ----------------------------------------------------------------------------------------
bool bit_stream_kernel_1::
is_in_read_mode (
) const
{
return read_mode;
}
// ----------------------------------------------------------------------------------------
void bit_stream_kernel_1::
write (
int bit
)
{
// flush buffer if necessary
if (buffer_size == 8)
{
buffer <<= 8 - buffer_size;
if (osp->rdbuf()->sputn(reinterpret_cast<char*>(&buffer),1) == 0)
{
throw std::ios_base::failure("error occurred in the bit_stream object");
}
buffer_size = 0;
}
++buffer_size;
buffer <<= 1;
buffer += static_cast<unsigned char>(bit);
}
// ----------------------------------------------------------------------------------------
bool bit_stream_kernel_1::
read (
int& bit
)
{
// get new byte if necessary
if (buffer_size == 0)
{
if (isp->rdbuf()->sgetn(reinterpret_cast<char*>(&buffer), 1) == 0)
{
// if we didn't read anything then return false
return false;
}
buffer_size = 8;
}
// put the most significant bit from buffer into bit
bit = static_cast<int>(buffer >> 7);
// shift out the bit that was just read
buffer <<= 1;
--buffer_size;
return true;
}
// ----------------------------------------------------------------------------------------
void bit_stream_kernel_1::
swap (
bit_stream_kernel_1& item
)
{
std::istream* isp_temp = item.isp;
std::ostream* osp_temp = item.osp;
bool write_mode_temp = item.write_mode;
bool read_mode_temp = item.read_mode;
unsigned char buffer_temp = item.buffer;
unsigned short buffer_size_temp = item.buffer_size;
item.isp = isp;
item.osp = osp;
item.write_mode = write_mode;
item.read_mode = read_mode;
item.buffer = buffer;
item.buffer_size = buffer_size;
isp = isp_temp;
osp = osp_temp;
write_mode = write_mode_temp;
read_mode = read_mode_temp;
buffer = buffer_temp;
buffer_size = buffer_size_temp;
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_BIT_STREAM_KERNEL_1_CPp_
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_BIT_STREAM_KERNEl_1_
#define DLIB_BIT_STREAM_KERNEl_1_
#include "bit_stream_kernel_abstract.h"
#include <iosfwd>
namespace dlib
{
class bit_stream_kernel_1
{
/*!
INITIAL VALUE
write_mode == false
read_mode == false
CONVENTION
write_mode == is_in_write_mode()
read_mode == is_in_read_mode()
if (write_mode)
{
osp == pointer to an ostream object
buffer == the low order bits of buffer are the bits to be
written
buffer_size == the number of low order bits in buffer that are
bits that should be written
the lowest order bit is the last bit entered by the user
}
if (read_mode)
{
isp == pointer to an istream object
buffer == the high order bits of buffer are the bits
waiting to be read by the user
buffer_size == the number of high order bits in buffer that
are bits that are waiting to be read
the highest order bit is the next bit to give to the user
}
!*/
public:
bit_stream_kernel_1 (
) :
write_mode(false),
read_mode(false)
{}
virtual ~bit_stream_kernel_1 (
)
{}
void clear (
);
void set_input_stream (
std::istream& is
);
void set_output_stream (
std::ostream& os
);
void close (
);
inline bool is_in_write_mode (
) const;
inline bool is_in_read_mode (
) const;
inline void write (
int bit
);
bool read (
int& bit
);
void swap (
bit_stream_kernel_1& item
);
private:
// member data
std::istream* isp;
std::ostream* osp;
bool write_mode;
bool read_mode;
unsigned char buffer;
unsigned short buffer_size;
// restricted functions
bit_stream_kernel_1(bit_stream_kernel_1&); // copy constructor
bit_stream_kernel_1& operator=(bit_stream_kernel_1&); // assignment operator
};
inline void swap (
bit_stream_kernel_1& a,
bit_stream_kernel_1& b
);
// ----------------------------------------------------------------------------------------
}
#ifdef NO_MAKEFILE
#include "bit_stream_kernel_1.cpp"
#endif
#endif // DLIB_BIT_STREAM_KERNEl_1_
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_BIT_STREAM_KERNEl_ABSTRACT_
#ifdef DLIB_BIT_STREAM_KERNEl_ABSTRACT_
#include <iosfwd>
namespace dlib
{
class bit_stream
{
/*!
INITIAL VALUE
is_in_write_mode() == false
is_in_read_mode() == false
WHAT THIS OBJECT REPRESENTS
this object is a middle man between a user and the iostream classes.
it allows single bits to be read/written easily to/from
the iostream classes
BUFFERING:
This object will only read/write single bytes at a time from/to the
iostream objects. Any buffered bits still in the bit_stream object
when it is closed or destructed are lost if it is in read mode. If
it is in write mode then any remaining bits are guaranteed to be
written to the output stream by the time it is closed or destructed.
!*/
public:
bit_stream (
);
/*!
ensures
- #*this is properly initialized
throws
- std::bad_alloc
!*/
virtual ~bit_stream (
);
/*!
ensures
- all memory associated with *this has been released
!*/
void clear (
);
/*!
ensures
- #*this has its initial value
throws
- std::bad_alloc
if this exception is thrown then *this is unusable
until clear() is called and succeeds
!*/
void set_input_stream (
std::istream& is
);
/*!
requires
- is_in_write_mode() == false
- is_in_read_mode() == false
- is is ready to give input
ensures
- #is_in_write_mode() == false
- #is_in_read_mode() == true
- #*this will now be reading from is
throws
- std::bad_alloc
!*/
void set_output_stream (
std::ostream& os
);
/*!
requires
- is_in_write_mode() == false
- is_in_read_mode() == false
- os is ready to take output
ensures
- #is_in_write_mode() == true
- #is_in_read_mode() == false
- #*this will now write to os
throws
- std::bad_alloc
!*/
void close (
);
/*!
requires
- is_in_write_mode() == true || is_in_read_mode() == true
ensures
- #is_in_write_mode() == false
- #is_in_read_mode() == false
!*/
bool is_in_write_mode (
) const;
/*!
ensures
- returns true if *this is associated with an output stream object
- returns false otherwise
!*/
bool is_in_read_mode (
) const;
/*!
ensures
- returns true if *this is associated with an input stream object
- returns false otherwise
!*/
void write (
int bit
);
/*!
requires
- is_in_write_mode() == true
- bit == 0 || bit == 1
ensures
- bit will be written to the ostream object associated with *this
throws
- std::ios_base::failure
if (there was a problem writing to the output stream) then
this exception will be thrown. #*this will be unusable until
clear() is called and succeeds
- any other exception
if this exception is thrown then #*this is unusable
until clear() is called and succeeds
!*/
bool read (
int& bit
);
/*!
requires
- is_in_read_mode() == true
ensures
- the next bit has been read and placed into #bit
- returns true if the read was successful, else false
(ex. false if EOF has been reached)
throws
- any exception
if this exception is thrown then #*this is unusable
until clear() is called and succeeds
!*/
void swap (
bit_stream& item
);
/*!
ensures
- swaps *this and item
!*/
private:
// restricted functions
bit_stream(bit_stream&); // copy constructor
bit_stream& operator=(bit_stream&); // assignment operator
};
inline void swap (
bit_stream& a,
bit_stream& b
) { a.swap(b); }
/*!
provides a global swap function
!*/
}
#endif // DLIB_BIT_STREAM_KERNEl_ABSTRACT_
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_BIT_STREAM_KERNEl_C_
#define DLIB_BIT_STREAM_KERNEl_C_
#include "bit_stream_kernel_abstract.h"
#include "../algs.h"
#include "../assert.h"
#include <iosfwd>
namespace dlib
{
template <
typename bit_stream_base // implements bit_stream/bit_stream_kernel_abstract.h
>
class bit_stream_kernel_c : public bit_stream_base
{
public:
void set_input_stream (
std::istream& is
);
void set_output_stream (
std::ostream& os
);
void close (
);
void write (
int bit
);
bool read (
int& bit
);
};
template <
typename bit_stream_base
>
inline void swap (
bit_stream_kernel_c<bit_stream_base>& a,
bit_stream_kernel_c<bit_stream_base>& b
) { a.swap(b); }
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename bit_stream_base
>
void bit_stream_kernel_c<bit_stream_base>::
set_input_stream (
std::istream& is
)
{
// make sure requires clause is not broken
DLIB_CASSERT(( this->is_in_write_mode() == false ) && ( this->is_in_read_mode() == false ),
"\tvoid bit_stream::set_intput_stream"
<< "\n\tbit_stream must not be in write or read mode"
<< "\n\tthis: " << this
);
// call the real function
bit_stream_base::set_input_stream(is);
}
// ----------------------------------------------------------------------------------------
template <
typename bit_stream_base
>
void bit_stream_kernel_c<bit_stream_base>::
set_output_stream (
std::ostream& os
)
{
// make sure requires clause is not broken
DLIB_CASSERT(( this->is_in_write_mode() == false ) && ( this->is_in_read_mode() == false ),
"\tvoid bit_stream::set_output_stream"
<< "\n\tbit_stream must not be in write or read mode"
<< "\n\tthis: " << this
);
// call the real function
bit_stream_base::set_output_stream(os);
}
// ----------------------------------------------------------------------------------------
template <
typename bit_stream_base
>
void bit_stream_kernel_c<bit_stream_base>::
close (
)
{
// make sure requires clause is not broken
DLIB_CASSERT(( this->is_in_write_mode() == true ) || ( this->is_in_read_mode() == true ),
"\tvoid bit_stream::close"
<< "\n\tyou can't close a bit_stream that isn't open"
<< "\n\tthis: " << this
);
// call the real function
bit_stream_base::close();
}
// ----------------------------------------------------------------------------------------
template <
typename bit_stream_base
>
void bit_stream_kernel_c<bit_stream_base>::
write (
int bit
)
{
// make sure requires clause is not broken
DLIB_CASSERT(( this->is_in_write_mode() == true ) && ( bit == 0 || bit == 1 ),
"\tvoid bit_stream::write"
<< "\n\tthe bit stream bust be in write mode and bit must be either 1 or 0"
<< "\n\tis_in_write_mode() == " << this->is_in_write_mode()
<< "\n\tbit == " << bit
<< "\n\tthis: " << this
);
// call the real function
bit_stream_base::write(bit);
}
// ----------------------------------------------------------------------------------------
template <
typename bit_stream_base
>
bool bit_stream_kernel_c<bit_stream_base>::
read (
int& bit
)
{
// make sure requires clause is not broken
DLIB_CASSERT(( this->is_in_read_mode() == true ),
"\tbool bit_stream::read"
<< "\n\tyou can't read from a bit_stream that isn't in read mode"
<< "\n\tthis: " << this
);
// call the real function
return bit_stream_base::read(bit);
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_BIT_STREAM_KERNEl_C_
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_BIT_STREAM_MULTi_1_
#define DLIB_BIT_STREAM_MULTi_1_
#include "bit_stream_multi_abstract.h"
namespace dlib
{
template <
typename bit_stream_base
>
class bit_stream_multi_1 : public bit_stream_base
{
public:
void multi_write (
unsigned long data,
int num_to_write
);
int multi_read (
unsigned long& data,
int num_to_read
);
};
template <
typename bit_stream_base
>
inline void swap (
bit_stream_multi_1<bit_stream_base>& a,
bit_stream_multi_1<bit_stream_base>& b
) { a.swap(b); }
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename bit_stream_base
>
void bit_stream_multi_1<bit_stream_base>::
multi_write (
unsigned long data,
int num_to_write
)
{
// move the first bit into the most significant position
data <<= 32 - num_to_write;
for (int i = 0; i < num_to_write; ++i)
{
// write the first bit from data
this->write(static_cast<char>(data >> 31));
// shift the next bit into position
data <<= 1;
}
}
// ----------------------------------------------------------------------------------------
template <
typename bit_stream_base
>
int bit_stream_multi_1<bit_stream_base>::
multi_read (
unsigned long& data,
int num_to_read
)
{
int bit, i;
data = 0;
for (i = 0; i < num_to_read; ++i)
{
// get a bit
if (this->read(bit) == false)
break;
// shift data to make room for this new bit
data <<= 1;
// put bit into the least significant position in data
data += static_cast<unsigned long>(bit);
}
return i;
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_BIT_STREAM_MULTi_1_
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_BIT_STREAM_MULTi_ABSTRACT_
#ifdef DLIB_BIT_STREAM_MULTi_ABSTRACT_
#include "bit_stream_kernel_abstract.h"
namespace dlib
{
template <
typename bit_stream_base
>
class bit_stream_multi : public bit_stream_base
{
/*!
REQUIREMENTS ON BIT_STREAM_BASE
it is an implementation of bit_stream/bit_stream_kernel_abstract.h
WHAT THIS EXTENSION DOES FOR BIT_STREAM
this gives a bit_stream object the ability to read/write multible bits
at a time
!*/
public:
void multi_write (
unsigned long data,
int num_to_write
);
/*!
requires
- is_in_write_mode() == true
- 0 <= num_to_write <= 32
ensures
- num_to_write low order bits from data will be written to the ostream
- object associated with *this
example: if data is 10010 then the bits will be written in the
order 1,0,0,1,0
!*/
int multi_read (
unsigned long& data,
int num_to_read
);
/*!
requires
- is_in_read_mode() == true
- 0 <= num_to_read <= 32
ensures
- tries to read num_to_read bits into the low order end of #data
example: if the incoming bits were 10010 then data would end
up with 10010 as its low order bits
- all of the bits in #data not filled in by multi_read() are zero
- returns the number of bits actually read into #data
!*/
};
template <
typename bit_stream_base
>
inline void swap (
bit_stream_multi<bit_stream_base>& a,
bit_stream_multi<bit_stream_base>& b
) { a.swap(b); }
/*!
provides a global swap function
!*/
}
#endif // DLIB_BIT_STREAM_MULTi_ABSTRACT_
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_BIT_STREAM_MULTi_C_
#define DLIB_BIT_STREAM_MULTi_C_
#include "bit_stream_multi_abstract.h"
#include "../algs.h"
#include "../assert.h"
namespace dlib
{
template <
typename bit_stream_base // implements bit_stream/bit_stream_multi_abstract.h
>
class bit_stream_multi_c : public bit_stream_base
{
public:
void multi_write (
unsigned long data,
int num_to_write
);
int multi_read (
unsigned long& data,
int num_to_read
);
};
template <
typename bit_stream_base
>
inline void swap (
bit_stream_multi_c<bit_stream_base>& a,
bit_stream_multi_c<bit_stream_base>& b
) { a.swap(b); }
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename bit_stream_base
>
void bit_stream_multi_c<bit_stream_base>::
multi_write (
unsigned long data,
int num_to_write
)
{
// make sure requires clause is not broken
DLIB_CASSERT( (this->is_in_write_mode() == true) && (num_to_write >= 0 && num_to_write <=32),
"\tvoid bit_stream::write"
<< "\n\tthe bit stream bust be in write mode and"
<< "\n\tnum_to_write must be between 0 and 32 inclusive"
<< "\n\tnum_to_write == " << num_to_write
<< "\n\tis_in_write_mode() == " << this->is_in_write_mode()
<< "\n\tthis: " << this
);
// call the real function
bit_stream_base::multi_write(data,num_to_write);
}
// ----------------------------------------------------------------------------------------
template <
typename bit_stream_base
>
int bit_stream_multi_c<bit_stream_base>::
multi_read (
unsigned long& data,
int num_to_read
)
{
// make sure requires clause is not broken
DLIB_CASSERT(( this->is_in_read_mode() == true && ( num_to_read >= 0 && num_to_read <=32 ) ),
"\tvoid bit_stream::read"
<< "\n\tyou can't read from a bit_stream that isn't in read mode and"
<< "\n\tnum_to_read must be between 0 and 32 inclusive"
<< "\n\tnum_to_read == " << num_to_read
<< "\n\tis_in_read_mode() == " << this->is_in_read_mode()
<< "\n\tthis: " << this
);
// call the real function
return bit_stream_base::multi_read(data,num_to_read);
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_BIT_STREAM_MULTi_C_
#include "../dlib_include_path_tutorial.txt"
// Copyright (C) 2008 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_BOUND_FUNCTION_POINTEr_
#define DLIB_BOUND_FUNCTION_POINTEr_
#include "bound_function_pointer/bound_function_pointer_kernel_1.h"
#endif // DLIB_BOUND_FUNCTION_POINTEr_
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