You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1159 lines
41 KiB
C++
1159 lines
41 KiB
C++
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
|
|
// License: Boost Software License See LICENSE.txt for the full license.
|
|
|
|
#ifdef DLIB_ALL_SOURCE_END
|
|
#include "dlib_basic_cpp_build_tutorial.txt"
|
|
#endif
|
|
|
|
#ifndef DLIB_ALGs_
|
|
#define DLIB_ALGs_
|
|
|
|
// this file contains miscellaneous stuff
|
|
|
|
// Give people who forget the -std=c++11 option a reminder
|
|
#if (defined(__GNUC__) && ((__GNUC__ >= 4 && __GNUC_MINOR__ >= 8) || (__GNUC__ > 4))) || \
|
|
(defined(__clang__) && ((__clang_major__ >= 3 && __clang_minor__ >= 4) || (__clang_major__ >= 3)))
|
|
#if __cplusplus < 201103
|
|
#error "Dlib requires C++11 support. Give your compiler the -std=c++11 option to enable it."
|
|
#endif
|
|
#endif
|
|
|
|
#if defined __NVCC__
|
|
// Disable the "statement is unreachable" message since it will go off on code that is
|
|
// actually reachable but just happens to not be reachable sometimes during certain
|
|
// template instantiations.
|
|
#pragma diag_suppress code_is_unreachable
|
|
#endif
|
|
|
|
|
|
#ifdef _MSC_VER
|
|
|
|
#if _MSC_VER < 1900
|
|
#error "dlib versions newer than v19.1 use C++11 and therefore require Visual Studio 2015 or newer."
|
|
#endif
|
|
|
|
// Disable the following warnings for Visual Studio
|
|
|
|
// this is to disable the "'this' : used in base member initializer list"
|
|
// warning you get from some of the GUI objects since all the objects
|
|
// require that their parent class be passed into their constructor.
|
|
// In this case though it is totally safe so it is ok to disable this warning.
|
|
#pragma warning(disable : 4355)
|
|
|
|
// This is a warning you get sometimes when Visual Studio performs a Koenig Lookup.
|
|
// This is a bug in visual studio. It is a totally legitimate thing to
|
|
// expect from a compiler.
|
|
#pragma warning(disable : 4675)
|
|
|
|
// This is a warning you get from visual studio 2005 about things in the standard C++
|
|
// library being "deprecated." I checked the C++ standard and it doesn't say jack
|
|
// about any of them (I checked the searchable PDF). So this warning is total Bunk.
|
|
#pragma warning(disable : 4996)
|
|
|
|
// This is a warning you get from visual studio 2003:
|
|
// warning C4345: behavior change: an object of POD type constructed with an initializer
|
|
// of the form () will be default-initialized.
|
|
// I love it when this compiler gives warnings about bugs in previous versions of itself.
|
|
#pragma warning(disable : 4345)
|
|
|
|
|
|
// Disable warnings about conversion from size_t to unsigned long and long.
|
|
#pragma warning(disable : 4267)
|
|
|
|
// Disable warnings about conversion from double to float
|
|
#pragma warning(disable : 4244)
|
|
#pragma warning(disable : 4305)
|
|
|
|
// Disable "warning C4180: qualifier applied to function type has no meaning; ignored".
|
|
// This warning happens often in generic code that works with functions and isn't useful.
|
|
#pragma warning(disable : 4180)
|
|
|
|
// Disable "warning C4290: C++ exception specification ignored except to indicate a function is not __declspec(nothrow)"
|
|
#pragma warning(disable : 4290)
|
|
|
|
|
|
// DNN module uses template-based network declaration that leads to very long
|
|
// type names. Visual Studio will produce Warning C4503 in such cases. https://msdn.microsoft.com/en-us/library/074af4b6.aspx says
|
|
// that correct binaries are still produced even when this warning happens, but linker errors from visual studio, if they occur could be confusing.
|
|
#pragma warning( disable: 4503 )
|
|
|
|
|
|
#endif
|
|
|
|
#ifdef __BORLANDC__
|
|
// Disable the following warnings for the Borland Compilers
|
|
//
|
|
// These warnings just say that the compiler is refusing to inline functions with
|
|
// loops or try blocks in them.
|
|
//
|
|
#pragma option -w-8027
|
|
#pragma option -w-8026
|
|
#endif
|
|
|
|
#include <string> // for the exceptions
|
|
|
|
#ifdef __CYGWIN__
|
|
namespace std
|
|
{
|
|
typedef std::basic_string<wchar_t> wstring;
|
|
}
|
|
#endif
|
|
|
|
#include "platform.h"
|
|
#include "windows_magic.h"
|
|
|
|
|
|
#include <algorithm> // for std::swap
|
|
#include <new> // for std::bad_alloc
|
|
#include <cstdlib>
|
|
#include <stddef.h>
|
|
#include <limits> // for std::numeric_limits for is_finite()
|
|
#include "assert.h"
|
|
#include "error.h"
|
|
#include "noncopyable.h"
|
|
#include "enable_if.h"
|
|
#include "uintn.h"
|
|
#include "numeric_constants.h"
|
|
#include "memory_manager_stateless/memory_manager_stateless_kernel_1.h" // for the default memory manager
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
/*!A _dT !*/
|
|
|
|
template <typename charT>
|
|
inline charT _dTcast (const char a, const wchar_t b);
|
|
template <>
|
|
inline char _dTcast<char> (const char a, const wchar_t ) { return a; }
|
|
template <>
|
|
inline wchar_t _dTcast<wchar_t> (const char , const wchar_t b) { return b; }
|
|
|
|
template <typename charT>
|
|
inline const charT* _dTcast ( const char* a, const wchar_t* b);
|
|
template <>
|
|
inline const char* _dTcast<char> ( const char* a, const wchar_t* ) { return a; }
|
|
template <>
|
|
inline const wchar_t* _dTcast<wchar_t> ( const char* , const wchar_t* b) { return b; }
|
|
|
|
|
|
#define _dT(charT,str) _dTcast<charT>(str,L##str)
|
|
/*!
|
|
requires
|
|
- charT == char or wchar_t
|
|
- str == a string or character literal
|
|
ensures
|
|
- returns the literal in the form of a charT type literal.
|
|
!*/
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
namespace dlib
|
|
{
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
/*!A default_memory_manager
|
|
|
|
This memory manager just calls new and delete directly.
|
|
|
|
!*/
|
|
typedef memory_manager_stateless_kernel_1<char> default_memory_manager;
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
/*!A swap !*/
|
|
// make swap available in the dlib namespace
|
|
using std::swap;
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
/*!
|
|
Here is where I define my return codes. It is
|
|
important that they all be < 0.
|
|
!*/
|
|
|
|
enum general_return_codes
|
|
{
|
|
TIMEOUT = -1,
|
|
WOULDBLOCK = -2,
|
|
OTHER_ERROR = -3,
|
|
SHUTDOWN = -4,
|
|
PORTINUSE = -5
|
|
};
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
inline unsigned long square_root (
|
|
unsigned long value
|
|
)
|
|
/*!
|
|
requires
|
|
- value <= 2^32 - 1
|
|
ensures
|
|
- returns the square root of value. if the square root is not an
|
|
integer then it will be rounded up to the nearest integer.
|
|
!*/
|
|
{
|
|
unsigned long x;
|
|
|
|
// set the initial guess for what the root is depending on
|
|
// how big value is
|
|
if (value < 3)
|
|
return value;
|
|
else if (value < 4096) // 12
|
|
x = 45;
|
|
else if (value < 65536) // 16
|
|
x = 179;
|
|
else if (value < 1048576) // 20
|
|
x = 717;
|
|
else if (value < 16777216) // 24
|
|
x = 2867;
|
|
else if (value < 268435456) // 28
|
|
x = 11469;
|
|
else // 32
|
|
x = 45875;
|
|
|
|
|
|
|
|
// find the root
|
|
x = (x + value/x)>>1;
|
|
x = (x + value/x)>>1;
|
|
x = (x + value/x)>>1;
|
|
x = (x + value/x)>>1;
|
|
|
|
|
|
|
|
if (x*x < value)
|
|
return x+1;
|
|
else
|
|
return x;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
template <
|
|
typename T
|
|
>
|
|
void median (
|
|
T& one,
|
|
T& two,
|
|
T& three
|
|
);
|
|
/*!
|
|
requires
|
|
- T implements operator<
|
|
- T is swappable by a global swap()
|
|
ensures
|
|
- #one is the median
|
|
- #one, #two, and #three is some permutation of one, two, and three.
|
|
!*/
|
|
|
|
|
|
template <
|
|
typename T
|
|
>
|
|
void median (
|
|
T& one,
|
|
T& two,
|
|
T& three
|
|
)
|
|
{
|
|
using std::swap;
|
|
using dlib::swap;
|
|
|
|
if ( one < two )
|
|
{
|
|
// one < two
|
|
if ( two < three )
|
|
{
|
|
// one < two < three : two
|
|
swap(one,two);
|
|
|
|
}
|
|
else
|
|
{
|
|
// one < two >= three
|
|
if ( one < three)
|
|
{
|
|
// three
|
|
swap(three,one);
|
|
}
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
// one >= two
|
|
if ( three < one )
|
|
{
|
|
// three <= one >= two
|
|
if ( three < two )
|
|
{
|
|
// two
|
|
swap(two,one);
|
|
}
|
|
else
|
|
{
|
|
// three
|
|
swap(three,one);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
namespace relational_operators
|
|
{
|
|
template <
|
|
typename A,
|
|
typename B
|
|
>
|
|
constexpr bool operator> (
|
|
const A& a,
|
|
const B& b
|
|
) { return b < a; }
|
|
|
|
// ---------------------------------
|
|
|
|
template <
|
|
typename A,
|
|
typename B
|
|
>
|
|
constexpr bool operator!= (
|
|
const A& a,
|
|
const B& b
|
|
) { return !(a == b); }
|
|
|
|
// ---------------------------------
|
|
|
|
template <
|
|
typename A,
|
|
typename B
|
|
>
|
|
constexpr bool operator<= (
|
|
const A& a,
|
|
const B& b
|
|
) { return !(b < a); }
|
|
|
|
// ---------------------------------
|
|
|
|
template <
|
|
typename A,
|
|
typename B
|
|
>
|
|
constexpr bool operator>= (
|
|
const A& a,
|
|
const B& b
|
|
) { return !(a < b); }
|
|
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
template <
|
|
typename T
|
|
>
|
|
void exchange (
|
|
T& a,
|
|
T& b
|
|
)
|
|
/*!
|
|
This function does the exact same thing that global swap does and it does it by
|
|
just calling swap. But a lot of compilers have problems doing a Koenig Lookup
|
|
and the fact that this has a different name (global swap has the same name as
|
|
the member functions called swap) makes them compile right.
|
|
|
|
So this is a workaround but not too ugly of one. But hopefully I get get
|
|
rid of this in a few years. So this function is already deprecated.
|
|
|
|
This also means you should NOT use this function in your own code unless
|
|
you have to support an old buggy compiler that benefits from this hack.
|
|
!*/
|
|
{
|
|
using std::swap;
|
|
using dlib::swap;
|
|
swap(a,b);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
/*!A is_pointer_type
|
|
|
|
This is a template where is_pointer_type<T>::value == true when T is a pointer
|
|
type and false otherwise.
|
|
!*/
|
|
|
|
template <
|
|
typename T
|
|
>
|
|
class is_pointer_type
|
|
{
|
|
public:
|
|
enum { value = false };
|
|
private:
|
|
is_pointer_type();
|
|
};
|
|
|
|
template <
|
|
typename T
|
|
>
|
|
class is_pointer_type<T*>
|
|
{
|
|
public:
|
|
enum { value = true };
|
|
private:
|
|
is_pointer_type();
|
|
};
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
/*!A is_const_type
|
|
|
|
This is a template where is_const_type<T>::value == true when T is a const
|
|
type and false otherwise.
|
|
!*/
|
|
|
|
template <typename T>
|
|
struct is_const_type
|
|
{
|
|
static const bool value = false;
|
|
};
|
|
template <typename T>
|
|
struct is_const_type<const T>
|
|
{
|
|
static const bool value = true;
|
|
};
|
|
template <typename T>
|
|
struct is_const_type<const T&>
|
|
{
|
|
static const bool value = true;
|
|
};
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
/*!A is_reference_type
|
|
|
|
This is a template where is_reference_type<T>::value == true when T is a reference
|
|
type and false otherwise.
|
|
!*/
|
|
|
|
template <typename T>
|
|
struct is_reference_type
|
|
{
|
|
static const bool value = false;
|
|
};
|
|
|
|
template <typename T> struct is_reference_type<const T&> { static const bool value = true; };
|
|
template <typename T> struct is_reference_type<T&> { static const bool value = true; };
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
/*!A is_same_type
|
|
|
|
This is a template where is_same_type<T,U>::value == true when T and U are the
|
|
same type and false otherwise.
|
|
!*/
|
|
|
|
template <
|
|
typename T,
|
|
typename U
|
|
>
|
|
class is_same_type
|
|
{
|
|
public:
|
|
enum {value = false};
|
|
private:
|
|
is_same_type();
|
|
};
|
|
|
|
template <typename T>
|
|
class is_same_type<T,T>
|
|
{
|
|
public:
|
|
enum {value = true};
|
|
private:
|
|
is_same_type();
|
|
};
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
/*!A is_float_type
|
|
|
|
This is a template that can be used to determine if a type is one of the built
|
|
int floating point types (i.e. float, double, or long double).
|
|
!*/
|
|
|
|
template < typename T > struct is_float_type { const static bool value = false; };
|
|
template <> struct is_float_type<float> { const static bool value = true; };
|
|
template <> struct is_float_type<double> { const static bool value = true; };
|
|
template <> struct is_float_type<long double> { const static bool value = true; };
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
/*!A is_convertible
|
|
|
|
This is a template that can be used to determine if one type is convertible
|
|
into another type.
|
|
|
|
For example:
|
|
is_convertible<int,float>::value == true // because ints are convertible to floats
|
|
is_convertible<int*,float>::value == false // because int pointers are NOT convertible to floats
|
|
!*/
|
|
|
|
template <typename from, typename to>
|
|
struct is_convertible
|
|
{
|
|
struct yes_type { char a; };
|
|
struct no_type { yes_type a[2]; };
|
|
static const from& from_helper();
|
|
static yes_type test(to);
|
|
static no_type test(...);
|
|
const static bool value = sizeof(test(from_helper())) == sizeof(yes_type);
|
|
};
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
struct general_ {};
|
|
struct special_ : general_ {};
|
|
template<typename> struct int_ { typedef int type; };
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
|
|
/*!A is_same_object
|
|
|
|
This is a templated function which checks if both of its arguments are actually
|
|
references to the same object. It returns true if they are and false otherwise.
|
|
|
|
!*/
|
|
|
|
// handle the case where T and U are unrelated types.
|
|
template < typename T, typename U >
|
|
typename disable_if_c<is_convertible<T*, U*>::value || is_convertible<U*,T*>::value, bool>::type
|
|
is_same_object (
|
|
const T& a,
|
|
const U& b
|
|
)
|
|
{
|
|
return ((void*)&a == (void*)&b);
|
|
}
|
|
|
|
// handle the case where T and U are related types because their pointers can be
|
|
// implicitly converted into one or the other. E.g. a derived class and its base class.
|
|
// Or where both T and U are just the same type. This way we make sure that if there is a
|
|
// valid way to convert between these two pointer types then we will take that route rather
|
|
// than the void* approach used otherwise.
|
|
template < typename T, typename U >
|
|
typename enable_if_c<is_convertible<T*, U*>::value || is_convertible<U*,T*>::value, bool>::type
|
|
is_same_object (
|
|
const T& a,
|
|
const U& b
|
|
)
|
|
{
|
|
return (&a == &b);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
/*!A is_unsigned_type
|
|
|
|
This is a template where is_unsigned_type<T>::value == true when T is an unsigned
|
|
scalar type and false when T is a signed scalar type.
|
|
!*/
|
|
template <
|
|
typename T
|
|
>
|
|
struct is_unsigned_type
|
|
{
|
|
static const bool value = static_cast<T>((static_cast<T>(0)-static_cast<T>(1))) > 0;
|
|
};
|
|
template <> struct is_unsigned_type<long double> { static const bool value = false; };
|
|
template <> struct is_unsigned_type<double> { static const bool value = false; };
|
|
template <> struct is_unsigned_type<float> { static const bool value = false; };
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
/*!A is_signed_type
|
|
|
|
This is a template where is_signed_type<T>::value == true when T is a signed
|
|
scalar type and false when T is an unsigned scalar type.
|
|
!*/
|
|
template <
|
|
typename T
|
|
>
|
|
struct is_signed_type
|
|
{
|
|
static const bool value = !is_unsigned_type<T>::value;
|
|
};
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
template <
|
|
typename T
|
|
>
|
|
class copy_functor
|
|
{
|
|
public:
|
|
void operator() (
|
|
const T& source,
|
|
T& destination
|
|
) const
|
|
{
|
|
destination = source;
|
|
}
|
|
};
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
/*!A static_switch
|
|
|
|
To use this template you give it some number of boolean expressions and it
|
|
tells you which one of them is true. If more than one of them is true then
|
|
it causes a compile time error.
|
|
|
|
for example:
|
|
static_switch<1 + 1 == 2, 4 - 1 == 4>::value == 1 // because the first expression is true
|
|
static_switch<1 + 1 == 3, 4 == 4>::value == 2 // because the second expression is true
|
|
static_switch<1 + 1 == 3, 4 == 5>::value == 0 // 0 here because none of them are true
|
|
static_switch<1 + 1 == 2, 4 == 4>::value == compiler error // because more than one expression is true
|
|
!*/
|
|
|
|
template < bool v1 = 0, bool v2 = 0, bool v3 = 0, bool v4 = 0, bool v5 = 0,
|
|
bool v6 = 0, bool v7 = 0, bool v8 = 0, bool v9 = 0, bool v10 = 0,
|
|
bool v11 = 0, bool v12 = 0, bool v13 = 0, bool v14 = 0, bool v15 = 0 >
|
|
struct static_switch;
|
|
|
|
template <> struct static_switch<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0> { const static int value = 0; };
|
|
template <> struct static_switch<1,0,0,0,0,0,0,0,0,0,0,0,0,0,0> { const static int value = 1; };
|
|
template <> struct static_switch<0,1,0,0,0,0,0,0,0,0,0,0,0,0,0> { const static int value = 2; };
|
|
template <> struct static_switch<0,0,1,0,0,0,0,0,0,0,0,0,0,0,0> { const static int value = 3; };
|
|
template <> struct static_switch<0,0,0,1,0,0,0,0,0,0,0,0,0,0,0> { const static int value = 4; };
|
|
template <> struct static_switch<0,0,0,0,1,0,0,0,0,0,0,0,0,0,0> { const static int value = 5; };
|
|
template <> struct static_switch<0,0,0,0,0,1,0,0,0,0,0,0,0,0,0> { const static int value = 6; };
|
|
template <> struct static_switch<0,0,0,0,0,0,1,0,0,0,0,0,0,0,0> { const static int value = 7; };
|
|
template <> struct static_switch<0,0,0,0,0,0,0,1,0,0,0,0,0,0,0> { const static int value = 8; };
|
|
template <> struct static_switch<0,0,0,0,0,0,0,0,1,0,0,0,0,0,0> { const static int value = 9; };
|
|
template <> struct static_switch<0,0,0,0,0,0,0,0,0,1,0,0,0,0,0> { const static int value = 10; };
|
|
template <> struct static_switch<0,0,0,0,0,0,0,0,0,0,1,0,0,0,0> { const static int value = 11; };
|
|
template <> struct static_switch<0,0,0,0,0,0,0,0,0,0,0,1,0,0,0> { const static int value = 12; };
|
|
template <> struct static_switch<0,0,0,0,0,0,0,0,0,0,0,0,1,0,0> { const static int value = 13; };
|
|
template <> struct static_switch<0,0,0,0,0,0,0,0,0,0,0,0,0,1,0> { const static int value = 14; };
|
|
template <> struct static_switch<0,0,0,0,0,0,0,0,0,0,0,0,0,0,1> { const static int value = 15; };
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
/*!A is_built_in_scalar_type
|
|
|
|
This is a template that allows you to determine if the given type is a built
|
|
in scalar type such as an int, char, float, short, etc.
|
|
|
|
For example, is_built_in_scalar_type<char>::value == true
|
|
For example, is_built_in_scalar_type<std::string>::value == false
|
|
!*/
|
|
|
|
template <typename T> struct is_built_in_scalar_type { const static bool value = false; };
|
|
|
|
template <> struct is_built_in_scalar_type<float> { const static bool value = true; };
|
|
template <> struct is_built_in_scalar_type<double> { const static bool value = true; };
|
|
template <> struct is_built_in_scalar_type<long double> { const static bool value = true; };
|
|
template <> struct is_built_in_scalar_type<short> { const static bool value = true; };
|
|
template <> struct is_built_in_scalar_type<int> { const static bool value = true; };
|
|
template <> struct is_built_in_scalar_type<long> { const static bool value = true; };
|
|
template <> struct is_built_in_scalar_type<unsigned short> { const static bool value = true; };
|
|
template <> struct is_built_in_scalar_type<unsigned int> { const static bool value = true; };
|
|
template <> struct is_built_in_scalar_type<unsigned long> { const static bool value = true; };
|
|
template <> struct is_built_in_scalar_type<uint64> { const static bool value = true; };
|
|
template <> struct is_built_in_scalar_type<int64> { const static bool value = true; };
|
|
template <> struct is_built_in_scalar_type<char> { const static bool value = true; };
|
|
template <> struct is_built_in_scalar_type<signed char> { const static bool value = true; };
|
|
template <> struct is_built_in_scalar_type<unsigned char> { const static bool value = true; };
|
|
// Don't define one for wchar_t when using a version of visual studio
|
|
// older than 8.0 (visual studio 2005) since before then they improperly set
|
|
// wchar_t to be a typedef rather than its own type as required by the C++
|
|
// standard.
|
|
#if !defined(_MSC_VER) || _NATIVE_WCHAR_T_DEFINED
|
|
template <> struct is_built_in_scalar_type<wchar_t> { const static bool value = true; };
|
|
#endif
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
template <
|
|
typename T
|
|
>
|
|
typename enable_if<is_built_in_scalar_type<T>,bool>::type is_finite (
|
|
const T& value
|
|
)
|
|
/*!
|
|
requires
|
|
- value must be some kind of scalar type such as int or double
|
|
ensures
|
|
- returns true if value is a finite value (e.g. not infinity or NaN) and false
|
|
otherwise.
|
|
!*/
|
|
{
|
|
if (is_float_type<T>::value)
|
|
return -std::numeric_limits<T>::infinity() < value && value < std::numeric_limits<T>::infinity();
|
|
else
|
|
return true;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
/*!A promote
|
|
|
|
This is a template that takes one of the built in scalar types and gives you another
|
|
scalar type that should be big enough to hold sums of values from the original scalar
|
|
type. The new scalar type will also always be signed.
|
|
|
|
For example, promote<uint16>::type == int32
|
|
!*/
|
|
|
|
template <typename T, size_t s = sizeof(T)> struct promote;
|
|
template <typename T> struct promote<T,1> { typedef int32 type; };
|
|
template <typename T> struct promote<T,2> { typedef int32 type; };
|
|
template <typename T> struct promote<T,4> { typedef int64 type; };
|
|
template <typename T> struct promote<T,8> { typedef int64 type; };
|
|
|
|
template <> struct promote<float,sizeof(float)> { typedef double type; };
|
|
template <> struct promote<double,sizeof(double)> { typedef double type; };
|
|
template <> struct promote<long double,sizeof(long double)> { typedef long double type; };
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
/*!A assign_zero_if_built_in_scalar_type
|
|
|
|
This function assigns its argument the value of 0 if it is a built in scalar
|
|
type according to the is_built_in_scalar_type<> template. If it isn't a
|
|
built in scalar type then it does nothing.
|
|
!*/
|
|
|
|
template <typename T> inline typename disable_if<is_built_in_scalar_type<T>,void>::type assign_zero_if_built_in_scalar_type (T&){}
|
|
template <typename T> inline typename enable_if<is_built_in_scalar_type<T>,void>::type assign_zero_if_built_in_scalar_type (T& a){a=0;}
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
/*!A basic_type
|
|
|
|
This is a template that takes a type and strips off any const, volatile, or reference
|
|
qualifiers and gives you back the basic underlying type. So for example:
|
|
|
|
basic_type<const int&>::type == int
|
|
!*/
|
|
|
|
template <typename T> struct basic_type { typedef T type; };
|
|
template <typename T> struct basic_type<const T> { typedef T type; };
|
|
template <typename T> struct basic_type<const T&> { typedef T type; };
|
|
template <typename T> struct basic_type<volatile const T&> { typedef T type; };
|
|
template <typename T> struct basic_type<T&> { typedef T type; };
|
|
template <typename T> struct basic_type<volatile T&> { typedef T type; };
|
|
template <typename T> struct basic_type<volatile T> { typedef T type; };
|
|
template <typename T> struct basic_type<volatile const T> { typedef T type; };
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
template <typename T>
|
|
T put_in_range (
|
|
const T& a,
|
|
const T& b,
|
|
const T& val
|
|
)
|
|
/*!
|
|
requires
|
|
- T is a type that looks like double, float, int, or so forth
|
|
ensures
|
|
- if (val is within the range [a,b]) then
|
|
- returns val
|
|
- else
|
|
- returns the end of the range [a,b] that is closest to val
|
|
!*/
|
|
{
|
|
if (a < b)
|
|
{
|
|
if (val < a)
|
|
return a;
|
|
else if (val > b)
|
|
return b;
|
|
}
|
|
else
|
|
{
|
|
if (val < b)
|
|
return b;
|
|
else if (val > a)
|
|
return a;
|
|
}
|
|
|
|
return val;
|
|
}
|
|
|
|
// overload for double
|
|
inline double put_in_range(const double& a, const double& b, const double& val)
|
|
{ return put_in_range<double>(a,b,val); }
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
/*!A tabs
|
|
|
|
This is a template to compute the absolute value a number at compile time.
|
|
|
|
For example,
|
|
abs<-4>::value == 4
|
|
abs<4>::value == 4
|
|
!*/
|
|
|
|
template <long x, typename enabled=void>
|
|
struct tabs { const static long value = x; };
|
|
template <long x>
|
|
struct tabs<x,typename enable_if_c<(x < 0)>::type> { const static long value = -x; };
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
/*!A tmax
|
|
|
|
This is a template to compute the max of two values at compile time
|
|
|
|
For example,
|
|
abs<4,7>::value == 7
|
|
!*/
|
|
|
|
template <long x, long y, typename enabled=void>
|
|
struct tmax { const static long value = x; };
|
|
template <long x, long y>
|
|
struct tmax<x,y,typename enable_if_c<(y > x)>::type> { const static long value = y; };
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
/*!A tmin
|
|
|
|
This is a template to compute the min of two values at compile time
|
|
|
|
For example,
|
|
abs<4,7>::value == 4
|
|
!*/
|
|
|
|
template <long x, long y, typename enabled=void>
|
|
struct tmin { const static long value = x; };
|
|
template <long x, long y>
|
|
struct tmin<x,y,typename enable_if_c<(y < x)>::type> { const static long value = y; };
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
#define DLIB_MAKE_HAS_MEMBER_FUNCTION_TEST(testname, returnT, funct_name, args) \
|
|
struct _two_bytes_##testname { char a[2]; }; \
|
|
template < typename T, returnT (T::*funct)args > \
|
|
struct _helper_##testname { typedef char type; }; \
|
|
template <typename T> \
|
|
static char _has_##testname##_helper( typename _helper_##testname<T,&T::funct_name >::type ) { return 0;} \
|
|
template <typename T> \
|
|
static _two_bytes_##testname _has_##testname##_helper(int) { return _two_bytes_##testname();} \
|
|
template <typename T> struct _##testname##workaroundbug { \
|
|
const static unsigned long U = sizeof(_has_##testname##_helper<T>('a')); }; \
|
|
template <typename T, unsigned long U = _##testname##workaroundbug<T>::U > \
|
|
struct testname { static const bool value = false; }; \
|
|
template <typename T> \
|
|
struct testname<T,1> { static const bool value = true; };
|
|
/*!A DLIB_MAKE_HAS_MEMBER_FUNCTION_TEST
|
|
|
|
The DLIB_MAKE_HAS_MEMBER_FUNCTION_TEST() macro is used to define traits templates
|
|
that tell you if a class has a certain member function. For example, to make a
|
|
test to see if a class has a public method with the signature void print(int) you
|
|
would say:
|
|
DLIB_MAKE_HAS_MEMBER_FUNCTION_TEST(has_print, void, print, (int))
|
|
|
|
Then you can check if a class, T, has this method by looking at the boolean value:
|
|
has_print<T>::value
|
|
which will be true if the member function is in the T class.
|
|
|
|
Note that you can test for member functions taking no arguments by simply passing
|
|
in empty () like so:
|
|
DLIB_MAKE_HAS_MEMBER_FUNCTION_TEST(has_print, void, print, ())
|
|
This would test for a member of the form:
|
|
void print().
|
|
|
|
To test for const member functions you would use a statement such as this:
|
|
DLIB_MAKE_HAS_MEMBER_FUNCTION_TEST(has_print, void, print, ()const)
|
|
This would test for a member of the form:
|
|
void print() const.
|
|
|
|
To test for const templated member functions you would use a statement such as this:
|
|
DLIB_MAKE_HAS_MEMBER_FUNCTION_TEST(has_print, void, template print<int>, ())
|
|
This would test for a member of the form:
|
|
template <typename T> void print().
|
|
!*/
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
/*!A is_function
|
|
|
|
This is a template that allows you to determine if the given type is a function.
|
|
|
|
For example,
|
|
void funct();
|
|
|
|
is_built_in_scalar_type<funct>::value == true
|
|
is_built_in_scalar_type<int>::value == false
|
|
!*/
|
|
|
|
template <typename T> struct is_function { static const bool value = false; };
|
|
template <typename T>
|
|
struct is_function<T (void)> { static const bool value = true; };
|
|
template <typename T, typename A0>
|
|
struct is_function<T (A0)> { static const bool value = true; };
|
|
template <typename T, typename A0, typename A1>
|
|
struct is_function<T (A0, A1)> { static const bool value = true; };
|
|
template <typename T, typename A0, typename A1, typename A2>
|
|
struct is_function<T (A0, A1, A2)> { static const bool value = true; };
|
|
template <typename T, typename A0, typename A1, typename A2, typename A3>
|
|
struct is_function<T (A0, A1, A2, A3)> { static const bool value = true; };
|
|
template <typename T, typename A0, typename A1, typename A2, typename A3, typename A4>
|
|
struct is_function<T (A0, A1, A2, A3, A4)> { static const bool value = true; };
|
|
template <typename T, typename A0, typename A1, typename A2, typename A3, typename A4,
|
|
typename A5>
|
|
struct is_function<T (A0,A1,A2,A3,A4,A5)> { static const bool value = true; };
|
|
template <typename T, typename A0, typename A1, typename A2, typename A3, typename A4,
|
|
typename A5, typename A6>
|
|
struct is_function<T (A0,A1,A2,A3,A4,A5,A6)> { static const bool value = true; };
|
|
template <typename T, typename A0, typename A1, typename A2, typename A3, typename A4,
|
|
typename A5, typename A6, typename A7>
|
|
struct is_function<T (A0,A1,A2,A3,A4,A5,A6,A7)> { static const bool value = true; };
|
|
template <typename T, typename A0, typename A1, typename A2, typename A3, typename A4,
|
|
typename A5, typename A6, typename A7, typename A8>
|
|
struct is_function<T (A0,A1,A2,A3,A4,A5,A6,A7,A8)> { static const bool value = true; };
|
|
template <typename T, typename A0, typename A1, typename A2, typename A3, typename A4,
|
|
typename A5, typename A6, typename A7, typename A8, typename A9>
|
|
struct is_function<T (A0,A1,A2,A3,A4,A5,A6,A7,A8,A9)> { static const bool value = true; };
|
|
|
|
|
|
template <typename T> class funct_wrap0
|
|
{
|
|
public:
|
|
funct_wrap0(T (&f_)()):f(f_){}
|
|
T operator()() const { return f(); }
|
|
private:
|
|
T (&f)();
|
|
};
|
|
template <typename T, typename A0> class funct_wrap1
|
|
{
|
|
public:
|
|
funct_wrap1(T (&f_)(A0)):f(f_){}
|
|
T operator()(A0 a0) const { return f(a0); }
|
|
private:
|
|
T (&f)(A0);
|
|
};
|
|
template <typename T, typename A0, typename A1> class funct_wrap2
|
|
{
|
|
public:
|
|
funct_wrap2(T (&f_)(A0,A1)):f(f_){}
|
|
T operator()(A0 a0, A1 a1) const { return f(a0,a1); }
|
|
private:
|
|
T (&f)(A0,A1);
|
|
};
|
|
template <typename T, typename A0, typename A1, typename A2> class funct_wrap3
|
|
{
|
|
public:
|
|
funct_wrap3(T (&f_)(A0,A1,A2)):f(f_){}
|
|
T operator()(A0 a0, A1 a1, A2 a2) const { return f(a0,a1,a2); }
|
|
private:
|
|
T (&f)(A0,A1,A2);
|
|
};
|
|
template <typename T, typename A0, typename A1, typename A2, typename A3> class funct_wrap4
|
|
{
|
|
public:
|
|
funct_wrap4(T (&f_)(A0,A1,A2,A3)):f(f_){}
|
|
T operator()(A0 a0, A1 a1, A2 a2, A3 a3) const { return f(a0,a1,a2,a3); }
|
|
private:
|
|
T (&f)(A0,A1,A2,A3);
|
|
};
|
|
template <typename T, typename A0, typename A1, typename A2, typename A3, typename A4> class funct_wrap5
|
|
{
|
|
public:
|
|
funct_wrap5(T (&f_)(A0,A1,A2,A3,A4)):f(f_){}
|
|
T operator()(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) const { return f(a0,a1,a2,a3,a4); }
|
|
private:
|
|
T (&f)(A0,A1,A2,A3,A4);
|
|
};
|
|
|
|
/*!A wrap_function
|
|
|
|
This is a template that allows you to turn a global function into a
|
|
function object. The reason for this template's existence is so you can
|
|
do stuff like this:
|
|
|
|
template <typename T>
|
|
void call_funct(const T& funct)
|
|
{ cout << funct(); }
|
|
|
|
std::string test() { return "asdfasf"; }
|
|
|
|
int main()
|
|
{
|
|
call_funct(wrap_function(test));
|
|
}
|
|
|
|
The above code doesn't work right on some compilers if you don't
|
|
use wrap_function.
|
|
!*/
|
|
|
|
template <typename T>
|
|
funct_wrap0<T> wrap_function(T (&f)()) { return funct_wrap0<T>(f); }
|
|
template <typename T, typename A0>
|
|
funct_wrap1<T,A0> wrap_function(T (&f)(A0)) { return funct_wrap1<T,A0>(f); }
|
|
template <typename T, typename A0, typename A1>
|
|
funct_wrap2<T,A0,A1> wrap_function(T (&f)(A0, A1)) { return funct_wrap2<T,A0,A1>(f); }
|
|
template <typename T, typename A0, typename A1, typename A2>
|
|
funct_wrap3<T,A0,A1,A2> wrap_function(T (&f)(A0, A1, A2)) { return funct_wrap3<T,A0,A1,A2>(f); }
|
|
template <typename T, typename A0, typename A1, typename A2, typename A3>
|
|
funct_wrap4<T,A0,A1,A2,A3> wrap_function(T (&f)(A0, A1, A2, A3)) { return funct_wrap4<T,A0,A1,A2,A3>(f); }
|
|
template <typename T, typename A0, typename A1, typename A2, typename A3, typename A4>
|
|
funct_wrap5<T,A0,A1,A2,A3,A4> wrap_function(T (&f)(A0, A1, A2, A3, A4)) { return funct_wrap5<T,A0,A1,A2,A3,A4>(f); }
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
template <unsigned long bSIZE>
|
|
class stack_based_memory_block : noncopyable
|
|
{
|
|
/*!
|
|
WHAT THIS OBJECT REPRESENTS
|
|
This object is a simple container for a block of memory
|
|
of bSIZE bytes. This memory block is located on the stack
|
|
and properly aligned to hold any kind of object.
|
|
!*/
|
|
public:
|
|
static const unsigned long size = bSIZE;
|
|
|
|
stack_based_memory_block(): data(mem.data) {}
|
|
|
|
void* get () { return data; }
|
|
/*!
|
|
ensures
|
|
- returns a pointer to the block of memory contained in this object
|
|
!*/
|
|
|
|
const void* get () const { return data; }
|
|
/*!
|
|
ensures
|
|
- returns a pointer to the block of memory contained in this object
|
|
!*/
|
|
|
|
private:
|
|
|
|
// You obviously can't have a block of memory that has zero bytes in it.
|
|
COMPILE_TIME_ASSERT(bSIZE > 0);
|
|
|
|
union mem_block
|
|
{
|
|
// All of this garbage is to make sure this union is properly aligned
|
|
// (a union is always aligned such that everything in it would be properly
|
|
// aligned. So the assumption here is that one of these objects has
|
|
// a large enough alignment requirement to satisfy any object this
|
|
// block of memory might be cast into).
|
|
void* void_ptr;
|
|
int integer;
|
|
struct {
|
|
void (stack_based_memory_block::*callback)();
|
|
stack_based_memory_block* o;
|
|
} stuff;
|
|
long double more_stuff;
|
|
|
|
uint64 var1;
|
|
uint32 var2;
|
|
double var3;
|
|
|
|
char data[size];
|
|
} mem;
|
|
|
|
// The reason for having this variable is that doing it this way avoids
|
|
// warnings from gcc about violations of strict-aliasing rules.
|
|
void* const data;
|
|
};
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
template <
|
|
typename T,
|
|
typename F
|
|
>
|
|
auto max_scoring_element(
|
|
const T& container,
|
|
F score_func
|
|
) -> decltype(std::make_pair(*container.begin(), 0.0))
|
|
/*!
|
|
requires
|
|
- container has .begin() and .end(), allowing it to be enumerated.
|
|
- score_func() is a function that takes an element of the container and returns a double.
|
|
ensures
|
|
- This function finds the element of container that has the largest score,
|
|
according to score_func(), and returns a std::pair containing that maximal
|
|
element along with the score.
|
|
- If the container is empty then make_pair(a default initialized object, -infinity) is returned.
|
|
!*/
|
|
{
|
|
double best_score = -std::numeric_limits<double>::infinity();
|
|
auto best_i = container.begin();
|
|
for (auto i = container.begin(); i != container.end(); ++i)
|
|
{
|
|
auto score = score_func(*i);
|
|
if (score > best_score)
|
|
{
|
|
best_score = score;
|
|
best_i = i;
|
|
}
|
|
}
|
|
|
|
using item_type = typename std::remove_reference<decltype(*best_i)>::type;
|
|
|
|
if (best_i == container.end())
|
|
return std::make_pair(item_type(), best_score);
|
|
else
|
|
return std::make_pair(*best_i, best_score);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
template <
|
|
typename T,
|
|
typename F
|
|
>
|
|
auto min_scoring_element(
|
|
const T& container,
|
|
F score_func
|
|
) -> decltype(std::make_pair(*container.begin(), 0.0))
|
|
/*!
|
|
requires
|
|
- container has .begin() and .end(), allowing it to be enumerated.
|
|
- score_func() is a function that takes an element of the container and returns a double.
|
|
ensures
|
|
- This function finds the element of container that has the smallest score,
|
|
according to score_func(), and returns a std::pair containing that minimal
|
|
element along with the score.
|
|
- If the container is empty then make_pair(a default initialized object, infinity) is returned.
|
|
!*/
|
|
{
|
|
double best_score = std::numeric_limits<double>::infinity();
|
|
auto best_i = container.begin();
|
|
for (auto i = container.begin(); i != container.end(); ++i)
|
|
{
|
|
auto score = score_func(*i);
|
|
if (score < best_score)
|
|
{
|
|
best_score = score;
|
|
best_i = i;
|
|
}
|
|
}
|
|
|
|
using item_type = typename std::remove_reference<decltype(*best_i)>::type;
|
|
|
|
if (best_i == container.end())
|
|
return std::make_pair(item_type(), best_score);
|
|
else
|
|
return std::make_pair(*best_i, best_score);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
}
|
|
|
|
#endif // DLIB_ALGs_
|
|
|