summaryrefslogtreecommitdiffstats
path: root/ml/dlib/dlib/algs.h
diff options
context:
space:
mode:
Diffstat (limited to 'ml/dlib/dlib/algs.h')
-rw-r--r--ml/dlib/dlib/algs.h1157
1 files changed, 1157 insertions, 0 deletions
diff --git a/ml/dlib/dlib/algs.h b/ml/dlib/dlib/algs.h
new file mode 100644
index 00000000..d0f74b1f
--- /dev/null
+++ b/ml/dlib/dlib/algs.h
@@ -0,0 +1,1157 @@
+// 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 occurr 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 <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 existance 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_
+