AshanGimhana commited on
Commit
9375c9a
·
verified ·
1 Parent(s): 7087e43

Upload folder using huggingface_hub

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. dlibs/CMakeLists.txt +37 -0
  2. dlibs/ISSUE_TEMPLATE.md +31 -0
  3. dlibs/LICENSE.txt +23 -0
  4. dlibs/MANIFEST.in +17 -0
  5. dlibs/README.md +70 -0
  6. dlibs/dlib/CMakeLists.txt +1001 -0
  7. dlibs/dlib/LICENSE.txt +23 -0
  8. dlibs/dlib/algs.h +1158 -0
  9. dlibs/dlib/all/source.cpp +100 -0
  10. dlibs/dlib/any.h +13 -0
  11. dlibs/dlib/any/any.h +183 -0
  12. dlibs/dlib/any/any_abstract.h +210 -0
  13. dlibs/dlib/any/any_decision_function.h +209 -0
  14. dlibs/dlib/any/any_decision_function_abstract.h +224 -0
  15. dlibs/dlib/any/any_function.h +885 -0
  16. dlibs/dlib/any/any_function_abstract.h +292 -0
  17. dlibs/dlib/any/any_function_impl.h +516 -0
  18. dlibs/dlib/any/any_function_impl2.h +44 -0
  19. dlibs/dlib/any/any_trainer.h +217 -0
  20. dlibs/dlib/any/any_trainer_abstract.h +234 -0
  21. dlibs/dlib/appveyor/dtest.yml +19 -0
  22. dlibs/dlib/appveyor/dtest_vc2017.yml +21 -0
  23. dlibs/dlib/appveyor/examples.yml +16 -0
  24. dlibs/dlib/appveyor/python.yml +14 -0
  25. dlibs/dlib/array.h +10 -0
  26. dlibs/dlib/array/array_kernel.h +809 -0
  27. dlibs/dlib/array/array_kernel_abstract.h +360 -0
  28. dlibs/dlib/array/array_tools.h +38 -0
  29. dlibs/dlib/array/array_tools_abstract.h +33 -0
  30. dlibs/dlib/array2d.h +12 -0
  31. dlibs/dlib/array2d/array2d_generic_image.h +67 -0
  32. dlibs/dlib/array2d/array2d_kernel.h +522 -0
  33. dlibs/dlib/array2d/array2d_kernel_abstract.h +339 -0
  34. dlibs/dlib/array2d/serialize_pixel_overloads.h +371 -0
  35. dlibs/dlib/assert.h +217 -0
  36. dlibs/dlib/base64.h +9 -0
  37. dlibs/dlib/base64/base64_kernel_1.cpp +403 -0
  38. dlibs/dlib/base64/base64_kernel_1.h +92 -0
  39. dlibs/dlib/base64/base64_kernel_abstract.h +121 -0
  40. dlibs/dlib/bayes_utils.h +11 -0
  41. dlibs/dlib/bayes_utils/bayes_utils.h +1678 -0
  42. dlibs/dlib/bayes_utils/bayes_utils_abstract.h +1042 -0
  43. dlibs/dlib/bigint.h +43 -0
  44. dlibs/dlib/bigint/bigint_kernel_1.cpp +1720 -0
  45. dlibs/dlib/bigint/bigint_kernel_1.h +543 -0
  46. dlibs/dlib/bigint/bigint_kernel_2.cpp +1945 -0
  47. dlibs/dlib/bigint/bigint_kernel_2.h +569 -0
  48. dlibs/dlib/bigint/bigint_kernel_abstract.h +670 -0
  49. dlibs/dlib/bigint/bigint_kernel_c.h +1140 -0
  50. dlibs/dlib/binary_search_tree.h +50 -0
dlibs/CMakeLists.txt ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ cmake_minimum_required(VERSION 2.8.12)
2
+
3
+ project(dlib_project)
4
+
5
+
6
+
7
+ #############################################################################
8
+ # #
9
+ # READ examples/CMakeLists.txt TO SEE HOW TO USE DLIB FROM C++ WITH CMAKE #
10
+ # #
11
+ #############################################################################
12
+
13
+
14
+
15
+
16
+
17
+ get_directory_property(has_parent PARENT_DIRECTORY)
18
+ if(NOT has_parent)
19
+ # When you call add_subdirectory(dlib) from a parent CMake project dlib's
20
+ # CMake scripts will assume you want to statically compile dlib into
21
+ # whatever you are building rather than create a standalone copy of dlib.
22
+ # This means CMake will build dlib as a static library, disable dlib's
23
+ # install targets so they don't clutter your project, and adjust a few other
24
+ # minor things that are convenient when statically building dlib as part of
25
+ # your own projects.
26
+ #
27
+ # On the other hand, if there is no parent CMake project or if
28
+ # DLIB_IN_PROJECT_BUILD is set to false, CMake will compile dlib as a normal
29
+ # standalone library (either shared or static, based on the state of CMake's
30
+ # BUILD_SHARED_LIBS flag), and include the usual install targets so you can
31
+ # install dlib on your computer via `make install`. Since the only reason
32
+ # to build this CMakeLists.txt (the one you are reading right now) by itself
33
+ # is if you want to install dlib, we indicate as such by setting
34
+ # DLIB_IN_PROJECT_BUILD to false.
35
+ set(DLIB_IN_PROJECT_BUILD false)
36
+ endif()
37
+ add_subdirectory(dlib)
dlibs/ISSUE_TEMPLATE.md ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ IF YOU ARE REPORTING A BUG OR PROBLEM WITH DLIB THEN FILL OUT THE ENTIRE TEMPLATE BELOW. ISSUES ASKING QUESTIONS ABOUT WHY SOMETHING DOESN'T WORK THAT FAIL TO FILL OUT THE ENTIRE TEMPLATE WILL BE CLOSED.
2
+
3
+ It is OK to suggest interesting improvements to dlib, even if you are not volunteering to implement them. **However, the issue tracker is not a code writing service, do not ask for someone to write code for you.** E.g. Do not ask for feature improvements to the example programs. **If there is some feature improvement you want in an example program then it's up to you to write it**.
4
+
5
+ Before you ask a question, check Google for a solution, [the dlib FAQ](http://dlib.net/faq.html), or consult the dlib documentation. Every single function in dlib is documented in detail. If you obviously haven't read the documentation your issue will be closed.
6
+
7
+ If you aren't reporting a bug or problem with dlib then delete this template and write whatever you want here.
8
+
9
+ <!-- ================================================================== -->
10
+ <!-- ================== BUG/PROBLEM REPORT TEMPLATE ================== -->
11
+ <!-- ================================================================== -->
12
+
13
+
14
+ <!-- Delete the above instructions and then provide a general summary of the issue in the Title above. Then fill out the template below. FAILURE TO FILL OUT EVERY PART WILL RESULT IN YOUR ISSUE BEING CLOSED -->
15
+
16
+ ## Expected Behavior
17
+ <!--- Tell us what should happen. What were you doing? What part of dlib are you using? What do you think should happen? -->
18
+
19
+ ## Current Behavior
20
+ <!--- Tell us what happens instead of the expected behavior. If you get an error, include the entire error message in the bug report. DO NOT POST SCREEN SHOTS. Paste in the text instead. If the issue is some kind of build problem, include the entire CMake output along with the error message. -->
21
+
22
+ ## Steps to Reproduce
23
+ <!--- Provide an unambiguous set of steps to reproduce this problem. What exactly do I have to type to reproduce your error? If you don't post complete instructions you are much less likely to get help. -->
24
+
25
+
26
+
27
+ * **Version**: <!-- What version of dlib? -->
28
+ * **Where did you get dlib**: <!-- Did you get it from an official source like dlib.net, this github repo, or somewhere else? -->
29
+ * **Platform**: <!-- include something like `lsb_release -a` output, or if Windows, version and 32-bit or
30
+ 64-bit -->
31
+ * **Compiler**: <!-- What compiler are you using? What version of that compiler? -->
dlibs/LICENSE.txt ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Boost Software License - Version 1.0 - August 17th, 2003
2
+
3
+ Permission is hereby granted, free of charge, to any person or organization
4
+ obtaining a copy of the software and accompanying documentation covered by
5
+ this license (the "Software") to use, reproduce, display, distribute,
6
+ execute, and transmit the Software, and to prepare derivative works of the
7
+ Software, and to permit third-parties to whom the Software is furnished to
8
+ do so, all subject to the following:
9
+
10
+ The copyright notices in the Software and this entire statement, including
11
+ the above license grant, this restriction and the following disclaimer,
12
+ must be included in all copies of the Software, in whole or in part, and
13
+ all derivative works of the Software, unless such copies or derivative
14
+ works are solely in the form of machine-executable object code generated by
15
+ a source language processor.
16
+
17
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
20
+ SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
21
+ FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
22
+ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
+ DEALINGS IN THE SOFTWARE.
dlibs/MANIFEST.in ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # MANIFEST.in
3
+ #
4
+ # Manifest template for creating the dlib source distribution.
5
+
6
+
7
+ include MANIFEST.in
8
+ include setup.py
9
+ include README.md
10
+
11
+ # sources
12
+ recursive-include dlib **
13
+ recursive-include python_examples *.txt *.py
14
+ recursive-include tools/python **
15
+
16
+ prune tools/python/build*
17
+ prune dlib/test
dlibs/README.md ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # dlib C++ library [![Travis Status](https://travis-ci.org/davisking/dlib.svg?branch=master)](https://travis-ci.org/davisking/dlib)
2
+
3
+ Dlib is a modern C++ toolkit containing machine learning algorithms and tools for creating complex software in C++ to solve real world problems. See [http://dlib.net](http://dlib.net) for the main project documentation and API reference.
4
+
5
+
6
+
7
+ ## Compiling dlib C++ example programs
8
+
9
+ Go into the examples folder and type:
10
+
11
+ ```bash
12
+ mkdir build; cd build; cmake .. ; cmake --build .
13
+ ```
14
+
15
+ That will build all the examples.
16
+ If you have a CPU that supports AVX instructions then turn them on like this:
17
+
18
+ ```bash
19
+ mkdir build; cd build; cmake .. -DUSE_AVX_INSTRUCTIONS=1; cmake --build .
20
+ ```
21
+
22
+ Doing so will make some things run faster.
23
+
24
+ Finally, Visual Studio users should usually do everything in 64bit mode. By default Visual Studio is 32bit, both in its outputs and its own execution, so you have to explicitly tell it to use 64bits. Since it's not the 1990s anymore you probably want to use 64bits. Do that with a cmake invocation like this:
25
+ ```bash
26
+ cmake .. -G "Visual Studio 14 2015 Win64" -T host=x64
27
+ ```
28
+
29
+ ## Compiling your own C++ programs that use dlib
30
+
31
+ The examples folder has a [CMake tutorial](https://github.com/davisking/dlib/blob/master/examples/CMakeLists.txt) that tells you what to do. There are also additional instructions on the [dlib web site](http://dlib.net/compile.html).
32
+
33
+ Alternatively, if you are using the [vcpkg](https://github.com/Microsoft/vcpkg/) dependency manager you can download and install dlib with CMake integration in a single command:
34
+ ```bash
35
+ vcpkg install dlib
36
+ ```
37
+
38
+ ## Compiling dlib Python API
39
+
40
+ Before you can run the Python example programs you must compile dlib. Type:
41
+
42
+ ```bash
43
+ python setup.py install
44
+ ```
45
+
46
+
47
+ ## Running the unit test suite
48
+
49
+ Type the following to compile and run the dlib unit test suite:
50
+
51
+ ```bash
52
+ cd dlib/test
53
+ mkdir build
54
+ cd build
55
+ cmake ..
56
+ cmake --build . --config Release
57
+ ./dtest --runall
58
+ ```
59
+
60
+ Note that on windows your compiler might put the test executable in a subfolder called `Release`. If that's the case then you have to go to that folder before running the test.
61
+
62
+ This library is licensed under the Boost Software License, which can be found in [dlib/LICENSE.txt](https://github.com/davisking/dlib/blob/master/dlib/LICENSE.txt). The long and short of the license is that you can use dlib however you like, even in closed source commercial software.
63
+
64
+ ## dlib sponsors
65
+
66
+ This research is based in part upon work supported by the Office of the Director of National Intelligence (ODNI), Intelligence Advanced Research Projects Activity (IARPA) under contract number 2014-14071600010. The views and conclusions contained herein are those of the authors and should not be interpreted as necessarily representing the official policies or endorsements, either expressed or implied, of ODNI, IARPA, or the U.S. Government.
67
+
68
+ Version: 19.22
69
+ Date: Sun Mar 28 09:22:07 EDT 2021
70
+ Mercurial Revision ID: f152a78a56bce7a6603a247bea96f353e0662e63
dlibs/dlib/CMakeLists.txt ADDED
@@ -0,0 +1,1001 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # This is a CMake makefile. You can find the cmake utility and
3
+ # information about it at http://www.cmake.org
4
+ #
5
+
6
+
7
+ cmake_minimum_required(VERSION 2.8.12)
8
+
9
+ set(CMAKE_DISABLE_SOURCE_CHANGES ON)
10
+ set(CMAKE_DISABLE_IN_SOURCE_BUILD ON)
11
+
12
+ if(POLICY CMP0048)
13
+ cmake_policy(SET CMP0048 NEW)
14
+ endif()
15
+ if(POLICY CMP0077)
16
+ cmake_policy(SET CMP0077 NEW)
17
+ endif()
18
+
19
+ project(dlib)
20
+
21
+ set(CPACK_PACKAGE_NAME "dlib")
22
+ set(CPACK_PACKAGE_VERSION_MAJOR "19")
23
+ set(CPACK_PACKAGE_VERSION_MINOR "22")
24
+ set(CPACK_PACKAGE_VERSION_PATCH "0")
25
+ set(VERSION ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH})
26
+ # Only print these messages once, even if dlib is added multiple times via add_subdirectory()
27
+ if (NOT TARGET dlib)
28
+ message(STATUS "Using CMake version: ${CMAKE_VERSION}")
29
+ message(STATUS "Compiling dlib version: ${VERSION}")
30
+ endif()
31
+
32
+
33
+ include(cmake_utils/set_compiler_specific_options.cmake)
34
+
35
+
36
+ # Adhere to GNU filesystem layout conventions
37
+ include(GNUInstallDirs)
38
+
39
+ if (POLICY CMP0063)
40
+ # This policy tells cmake to really honor CXX_VISIBILITY_PRESET rather than
41
+ # ignore it for backwards compatibility.
42
+ cmake_policy(SET CMP0063 NEW)
43
+ endif()
44
+ if (POLICY CMP0075)
45
+ cmake_policy(SET CMP0075 NEW)
46
+ endif()
47
+
48
+ # default to a Release build (except if CMAKE_BUILD_TYPE is set)
49
+ include(cmake_utils/release_build_by_default)
50
+ include(cmake_utils/use_cpp_11.cmake)
51
+
52
+ # Set DLIB_VERSION in the including CMake file so they can use it to do whatever they want.
53
+ get_directory_property(has_parent PARENT_DIRECTORY)
54
+ if(has_parent)
55
+ set(DLIB_VERSION ${VERSION} PARENT_SCOPE)
56
+ if (NOT DEFINED DLIB_IN_PROJECT_BUILD)
57
+ set(DLIB_IN_PROJECT_BUILD true)
58
+ endif()
59
+ endif()
60
+
61
+ if (COMMAND pybind11_add_module AND MSVC)
62
+ # True when building a python extension module using Visual Studio. We care
63
+ # about this because a huge number of windows users have broken systems, and
64
+ # in particular, they have broken or incompatibly installed copies of things
65
+ # like libjpeg or libpng. So if we detect we are in this mode we will never
66
+ # ever link to those libraries. Instead, we link to the copy included with
67
+ # dlib.
68
+ set (BUILDING_PYTHON_IN_MSVC true)
69
+ else()
70
+ set (BUILDING_PYTHON_IN_MSVC false)
71
+ endif()
72
+
73
+ if (DLIB_IN_PROJECT_BUILD)
74
+
75
+ # Check if we are being built as part of a pybind11 module.
76
+ if (COMMAND pybind11_add_module)
77
+ set(CMAKE_POSITION_INDEPENDENT_CODE True)
78
+ if (CMAKE_COMPILER_IS_GNUCXX)
79
+ # Just setting CMAKE_POSITION_INDEPENDENT_CODE should be enough to set
80
+ # -fPIC for GCC but sometimes it still doesn't get set, so make sure it
81
+ # does.
82
+ add_definitions("-fPIC")
83
+ endif()
84
+ # Make DLIB_ASSERT statements not abort the python interpreter, but just return an error.
85
+ list(APPEND active_preprocessor_switches "-DDLIB_NO_ABORT_ON_2ND_FATAL_ERROR")
86
+ endif()
87
+
88
+ # DLIB_IN_PROJECT_BUILD==true means you are using dlib by invoking
89
+ # add_subdirectory(dlib) in the parent project. In this case, we always want
90
+ # to build dlib as a static library so the parent project doesn't need to
91
+ # deal with some random dlib shared library file. It is much better to
92
+ # statically compile dlib into the parent project. So the following bit of
93
+ # CMake ensures that happens. However, we have to take care to compile dlib
94
+ # with position independent code if appropriate (i.e. if the parent project
95
+ # is a shared library).
96
+ if (BUILD_SHARED_LIBS)
97
+ if (CMAKE_COMPILER_IS_GNUCXX)
98
+ # Just setting CMAKE_POSITION_INDEPENDENT_CODE should be enough to set
99
+ # -fPIC for GCC but sometimes it still doesn't get set, so make sure it
100
+ # does.
101
+ add_definitions("-fPIC")
102
+ endif()
103
+ set(CMAKE_POSITION_INDEPENDENT_CODE true)
104
+ endif()
105
+
106
+ # Tell cmake to build dlib as a static library
107
+ set(BUILD_SHARED_LIBS false)
108
+
109
+ elseif(BUILD_SHARED_LIBS)
110
+ if (MSVC)
111
+ message(FATAL_ERROR "Building dlib as a standalone dll is not supported when using Visual Studio. You are highly encouraged to use static linking instead. See https://github.com/davisking/dlib/issues/1483 for a discussion.")
112
+ endif()
113
+ endif()
114
+
115
+
116
+ if (CMAKE_VERSION VERSION_LESS "3.9.0")
117
+ # Set only because there are old target_link_libraries() statements in the
118
+ # FindCUDA.cmake file that comes with CMake that error out if the new behavior
119
+ # is used. In newer versions of CMake we can instead set CUDA_LINK_LIBRARIES_KEYWORD which fixes this issue.
120
+ cmake_policy(SET CMP0023 OLD)
121
+ else()
122
+ set(CUDA_LINK_LIBRARIES_KEYWORD PUBLIC)
123
+ endif()
124
+
125
+
126
+ macro (enable_preprocessor_switch option_name)
127
+ list(APPEND active_preprocessor_switches "-D${option_name}")
128
+ endmacro()
129
+
130
+ macro (disable_preprocessor_switch option_name)
131
+ if (active_preprocessor_switches)
132
+ list(REMOVE_ITEM active_preprocessor_switches "-D${option_name}")
133
+ endif()
134
+ endmacro()
135
+
136
+ macro (toggle_preprocessor_switch option_name)
137
+ if (${option_name})
138
+ enable_preprocessor_switch(${option_name})
139
+ else()
140
+ disable_preprocessor_switch(${option_name})
141
+ endif()
142
+ endmacro()
143
+
144
+
145
+
146
+ # Suppress superfluous randlib warnings about libdlib.a having no symbols on MacOSX.
147
+ if (APPLE)
148
+ set(CMAKE_C_ARCHIVE_CREATE "<CMAKE_AR> Scr <TARGET> <LINK_FLAGS> <OBJECTS>")
149
+ set(CMAKE_CXX_ARCHIVE_CREATE "<CMAKE_AR> Scr <TARGET> <LINK_FLAGS> <OBJECTS>")
150
+ set(CMAKE_C_ARCHIVE_FINISH "<CMAKE_RANLIB> -no_warning_for_no_symbols -c <TARGET>")
151
+ set(CMAKE_CXX_ARCHIVE_FINISH "<CMAKE_RANLIB> -no_warning_for_no_symbols -c <TARGET>")
152
+ endif()
153
+
154
+ # Don't try to call add_library(dlib) and setup dlib's stuff if it has already
155
+ # been done by some other part of the current cmake project. We do this
156
+ # because it avoids getting warnings/errors about cmake policy CMP0002. This
157
+ # happens when a project tries to call add_subdirectory() on dlib more than
158
+ # once. This most often happens when the top level of a project depends on two
159
+ # or more other things which both depend on dlib.
160
+ if (NOT TARGET dlib)
161
+
162
+ set (DLIB_ISO_CPP_ONLY_STR
163
+ "Enable this if you don't want to compile any non-ISO C++ code (i.e. you don't use any of the API Wrappers)" )
164
+ set (DLIB_NO_GUI_SUPPORT_STR
165
+ "Enable this if you don't want to compile any of the dlib GUI code" )
166
+ set (DLIB_ENABLE_STACK_TRACE_STR
167
+ "Enable this if you want to turn on the DLIB_STACK_TRACE macros" )
168
+ set (DLIB_USE_BLAS_STR
169
+ "Disable this if you don't want to use a BLAS library" )
170
+ set (DLIB_USE_LAPACK_STR
171
+ "Disable this if you don't want to use a LAPACK library" )
172
+ set (DLIB_USE_CUDA_STR
173
+ "Disable this if you don't want to use NVIDIA CUDA" )
174
+ set (DLIB_USE_MKL_SEQUENTIAL_STR
175
+ "Enable this if you have MKL installed and want to use the sequential version instead of the multi-core version." )
176
+ set (DLIB_USE_MKL_WITH_TBB_STR
177
+ "Enable this if you have MKL installed and want to use the tbb version instead of the openmp version." )
178
+ set (DLIB_PNG_SUPPORT_STR
179
+ "Disable this if you don't want to link against libpng" )
180
+ set (DLIB_GIF_SUPPORT_STR
181
+ "Disable this if you don't want to link against libgif" )
182
+ set (DLIB_JPEG_SUPPORT_STR
183
+ "Disable this if you don't want to link against libjpeg" )
184
+ set (DLIB_LINK_WITH_SQLITE3_STR
185
+ "Disable this if you don't want to link against sqlite3" )
186
+ #set (DLIB_USE_FFTW_STR "Disable this if you don't want to link against fftw" )
187
+ set (DLIB_USE_MKL_FFT_STR
188
+ "Disable this is you don't want to use the MKL DFTI FFT implementation" )
189
+ set (DLIB_ENABLE_ASSERTS_STR
190
+ "Enable this if you want to turn on the DLIB_ASSERT macro" )
191
+
192
+
193
+ option(DLIB_ENABLE_ASSERTS ${DLIB_ENABLE_ASSERTS_STR} OFF)
194
+ option(DLIB_ISO_CPP_ONLY ${DLIB_ISO_CPP_ONLY_STR} OFF)
195
+ toggle_preprocessor_switch(DLIB_ISO_CPP_ONLY)
196
+ option(DLIB_NO_GUI_SUPPORT ${DLIB_NO_GUI_SUPPORT_STR} OFF)
197
+ toggle_preprocessor_switch(DLIB_NO_GUI_SUPPORT)
198
+ option(DLIB_ENABLE_STACK_TRACE ${DLIB_ENABLE_STACK_TRACE_STR} OFF)
199
+ toggle_preprocessor_switch(DLIB_ENABLE_STACK_TRACE)
200
+ option(DLIB_USE_MKL_SEQUENTIAL ${DLIB_USE_MKL_SEQUENTIAL_STR} OFF)
201
+ option(DLIB_USE_MKL_WITH_TBB ${DLIB_USE_MKL_WITH_TBB_STR} OFF)
202
+
203
+ if(DLIB_ENABLE_ASSERTS)
204
+ # Set these variables so they are set in the config.h.in file when dlib
205
+ # is installed.
206
+ set (DLIB_DISABLE_ASSERTS false)
207
+ set (ENABLE_ASSERTS true)
208
+ enable_preprocessor_switch(ENABLE_ASSERTS)
209
+ disable_preprocessor_switch(DLIB_DISABLE_ASSERTS)
210
+ else()
211
+ # Set these variables so they are set in the config.h.in file when dlib
212
+ # is installed.
213
+ set (DLIB_DISABLE_ASSERTS true)
214
+ set (ENABLE_ASSERTS false)
215
+ disable_preprocessor_switch(ENABLE_ASSERTS)
216
+ # Never force the asserts off when doing an in project build. The only
217
+ # time this matters is when using visual studio. The visual studio IDE
218
+ # has a drop down that lets the user select either release or debug
219
+ # builds. The DLIB_ASSERT macro is setup to enable/disable automatically
220
+ # based on this drop down (via preprocessor magic). However, if
221
+ # DLIB_DISABLE_ASSERTS is defined it permanently disables asserts no
222
+ # matter what, which would defeat the visual studio drop down. So here
223
+ # we make a point to not do that kind of severe disabling when in a
224
+ # project build. It should also be pointed out that DLIB_DISABLE_ASSERTS
225
+ # is only needed when building and installing dlib as a separately
226
+ # installed library. It doesn't matter when doing an in project build.
227
+ if (NOT DLIB_IN_PROJECT_BUILD)
228
+ enable_preprocessor_switch(DLIB_DISABLE_ASSERTS)
229
+ endif()
230
+ endif()
231
+
232
+ if (DLIB_ISO_CPP_ONLY)
233
+ option(DLIB_JPEG_SUPPORT ${DLIB_JPEG_SUPPORT_STR} OFF)
234
+ option(DLIB_LINK_WITH_SQLITE3 ${DLIB_LINK_WITH_SQLITE3_STR} OFF)
235
+ option(DLIB_USE_BLAS ${DLIB_USE_BLAS_STR} OFF)
236
+ option(DLIB_USE_LAPACK ${DLIB_USE_LAPACK_STR} OFF)
237
+ option(DLIB_USE_CUDA ${DLIB_USE_CUDA_STR} OFF)
238
+ option(DLIB_PNG_SUPPORT ${DLIB_PNG_SUPPORT_STR} OFF)
239
+ option(DLIB_GIF_SUPPORT ${DLIB_GIF_SUPPORT_STR} OFF)
240
+ #option(DLIB_USE_FFTW ${DLIB_USE_FFTW_STR} OFF)
241
+ option(DLIB_USE_MKL_FFT ${DLIB_USE_MKL_FFT_STR} OFF)
242
+ else()
243
+ option(DLIB_JPEG_SUPPORT ${DLIB_JPEG_SUPPORT_STR} ON)
244
+ option(DLIB_LINK_WITH_SQLITE3 ${DLIB_LINK_WITH_SQLITE3_STR} ON)
245
+ option(DLIB_USE_BLAS ${DLIB_USE_BLAS_STR} ON)
246
+ option(DLIB_USE_LAPACK ${DLIB_USE_LAPACK_STR} ON)
247
+ option(DLIB_USE_CUDA ${DLIB_USE_CUDA_STR} ON)
248
+ option(DLIB_PNG_SUPPORT ${DLIB_PNG_SUPPORT_STR} ON)
249
+ option(DLIB_GIF_SUPPORT ${DLIB_GIF_SUPPORT_STR} ON)
250
+ #option(DLIB_USE_FFTW ${DLIB_USE_FFTW_STR} ON)
251
+ option(DLIB_USE_MKL_FFT ${DLIB_USE_MKL_FFT_STR} ON)
252
+ endif()
253
+ toggle_preprocessor_switch(DLIB_JPEG_SUPPORT)
254
+ toggle_preprocessor_switch(DLIB_USE_BLAS)
255
+ toggle_preprocessor_switch(DLIB_USE_LAPACK)
256
+ toggle_preprocessor_switch(DLIB_USE_CUDA)
257
+ toggle_preprocessor_switch(DLIB_PNG_SUPPORT)
258
+ toggle_preprocessor_switch(DLIB_GIF_SUPPORT)
259
+ #toggle_preprocessor_switch(DLIB_USE_FFTW)
260
+ toggle_preprocessor_switch(DLIB_USE_MKL_FFT)
261
+
262
+
263
+ set(source_files
264
+ base64/base64_kernel_1.cpp
265
+ bigint/bigint_kernel_1.cpp
266
+ bigint/bigint_kernel_2.cpp
267
+ bit_stream/bit_stream_kernel_1.cpp
268
+ entropy_decoder/entropy_decoder_kernel_1.cpp
269
+ entropy_decoder/entropy_decoder_kernel_2.cpp
270
+ entropy_encoder/entropy_encoder_kernel_1.cpp
271
+ entropy_encoder/entropy_encoder_kernel_2.cpp
272
+ gui_widgets/fonts.cpp
273
+ md5/md5_kernel_1.cpp
274
+ tokenizer/tokenizer_kernel_1.cpp
275
+ unicode/unicode.cpp
276
+ test_for_odr_violations.cpp
277
+ )
278
+
279
+
280
+ set(dlib_needed_libraries)
281
+ set(dlib_needed_includes)
282
+
283
+ if (DLIB_ISO_CPP_ONLY)
284
+ add_library(dlib ${source_files} )
285
+ else()
286
+
287
+ set(source_files ${source_files}
288
+ sockets/sockets_kernel_1.cpp
289
+ bsp/bsp.cpp
290
+ dir_nav/dir_nav_kernel_1.cpp
291
+ dir_nav/dir_nav_kernel_2.cpp
292
+ dir_nav/dir_nav_extensions.cpp
293
+ linker/linker_kernel_1.cpp
294
+ logger/extra_logger_headers.cpp
295
+ logger/logger_kernel_1.cpp
296
+ logger/logger_config_file.cpp
297
+ misc_api/misc_api_kernel_1.cpp
298
+ misc_api/misc_api_kernel_2.cpp
299
+ sockets/sockets_extensions.cpp
300
+ sockets/sockets_kernel_2.cpp
301
+ sockstreambuf/sockstreambuf.cpp
302
+ sockstreambuf/sockstreambuf_unbuffered.cpp
303
+ server/server_kernel.cpp
304
+ server/server_iostream.cpp
305
+ server/server_http.cpp
306
+ threads/multithreaded_object_extension.cpp
307
+ threads/threaded_object_extension.cpp
308
+ threads/threads_kernel_1.cpp
309
+ threads/threads_kernel_2.cpp
310
+ threads/threads_kernel_shared.cpp
311
+ threads/thread_pool_extension.cpp
312
+ threads/async.cpp
313
+ timer/timer.cpp
314
+ stack_trace.cpp
315
+ cuda/cpu_dlib.cpp
316
+ cuda/tensor_tools.cpp
317
+ data_io/image_dataset_metadata.cpp
318
+ data_io/mnist.cpp
319
+ data_io/cifar.cpp
320
+ global_optimization/global_function_search.cpp
321
+ filtering/kalman_filter.cpp
322
+ svm/auto.cpp
323
+ )
324
+
325
+ if(UNIX)
326
+ set(CMAKE_THREAD_PREFER_PTHREAD ON)
327
+ find_package(Threads REQUIRED)
328
+ set(dlib_needed_libraries ${dlib_needed_libraries} ${CMAKE_THREAD_LIBS_INIT})
329
+ endif()
330
+
331
+ # we want to link to the right stuff depending on our platform.
332
+ if (WIN32 AND NOT CYGWIN) ###############################################################################
333
+ if (DLIB_NO_GUI_SUPPORT)
334
+ set (dlib_needed_libraries ws2_32 winmm)
335
+ else()
336
+ set (dlib_needed_libraries ws2_32 winmm comctl32 gdi32 imm32)
337
+ endif()
338
+ elseif(APPLE) ############################################################################
339
+ set(CMAKE_MACOSX_RPATH 1)
340
+ if (NOT DLIB_NO_GUI_SUPPORT)
341
+ find_package(X11 QUIET)
342
+ if (X11_FOUND)
343
+ # If both X11 and anaconda are installed, it's possible for the
344
+ # anaconda path to appear before /opt/X11, so we remove anaconda.
345
+ foreach (ITR ${X11_INCLUDE_DIR})
346
+ if ("${ITR}" MATCHES "(.*)(Ana|ana|mini)conda(.*)")
347
+ list (REMOVE_ITEM X11_INCLUDE_DIR ${ITR})
348
+ endif ()
349
+ endforeach(ITR)
350
+ include_directories(${X11_INCLUDE_DIR})
351
+ set (dlib_needed_libraries ${dlib_needed_libraries} ${X11_LIBRARIES})
352
+ else()
353
+ find_library(xlib X11)
354
+ # Make sure X11 is in the include path. Note that we look for
355
+ # Xlocale.h rather than Xlib.h because it avoids finding a partial
356
+ # copy of the X11 headers on systems with anaconda installed.
357
+ find_path(xlib_path Xlocale.h
358
+ PATHS
359
+ /Developer/SDKs/MacOSX10.4u.sdk/usr/X11R6/include
360
+ /opt/local/include
361
+ PATH_SUFFIXES X11
362
+ )
363
+ if (xlib AND xlib_path)
364
+ get_filename_component(x11_path ${xlib_path} PATH CACHE)
365
+ include_directories(${x11_path})
366
+ set(dlib_needed_libraries ${dlib_needed_libraries} ${xlib} )
367
+ set(X11_FOUND 1)
368
+ endif()
369
+ endif()
370
+ if (NOT X11_FOUND)
371
+ message(" *****************************************************************************")
372
+ message(" *** DLIB GUI SUPPORT DISABLED BECAUSE X11 DEVELOPMENT LIBRARIES NOT FOUND ***")
373
+ message(" *** Make sure XQuartz is installed if you want GUI support. ***")
374
+ message(" *** You can download XQuartz from: https://www.xquartz.org/ ***")
375
+ message(" *****************************************************************************")
376
+ set(DLIB_NO_GUI_SUPPORT ON CACHE STRING ${DLIB_NO_GUI_SUPPORT_STR} FORCE )
377
+ enable_preprocessor_switch(DLIB_NO_GUI_SUPPORT)
378
+ endif()
379
+ endif()
380
+
381
+ mark_as_advanced(xlib xlib_path x11_path)
382
+ else () ##################################################################################
383
+ # link to the socket library if it exists. this is something you need on solaris
384
+ find_library(socketlib socket)
385
+ if (socketlib)
386
+ set (dlib_needed_libraries ${dlib_needed_libraries} ${socketlib})
387
+ endif ()
388
+
389
+ if (NOT DLIB_NO_GUI_SUPPORT)
390
+ include(FindX11)
391
+ if (X11_FOUND)
392
+ include_directories(${X11_INCLUDE_DIR})
393
+ set (dlib_needed_libraries ${dlib_needed_libraries} ${X11_LIBRARIES})
394
+ else()
395
+ message(" *****************************************************************************")
396
+ message(" *** DLIB GUI SUPPORT DISABLED BECAUSE X11 DEVELOPMENT LIBRARIES NOT FOUND ***")
397
+ message(" *** Make sure libx11-dev is installed if you want GUI support. ***")
398
+ message(" *** On Ubuntu run: sudo apt-get install libx11-dev ***")
399
+ message(" *****************************************************************************")
400
+ set(DLIB_NO_GUI_SUPPORT ON CACHE STRING ${DLIB_NO_GUI_SUPPORT_STR} FORCE )
401
+ enable_preprocessor_switch(DLIB_NO_GUI_SUPPORT)
402
+ endif()
403
+ endif()
404
+
405
+ mark_as_advanced(nsllib socketlib)
406
+ endif () ##################################################################################
407
+
408
+ if (NOT DLIB_NO_GUI_SUPPORT)
409
+ set(source_files ${source_files}
410
+ gui_widgets/widgets.cpp
411
+ gui_widgets/drawable.cpp
412
+ gui_widgets/canvas_drawing.cpp
413
+ gui_widgets/style.cpp
414
+ gui_widgets/base_widgets.cpp
415
+ gui_core/gui_core_kernel_1.cpp
416
+ gui_core/gui_core_kernel_2.cpp
417
+ )
418
+ endif()
419
+
420
+ INCLUDE (CheckFunctionExists)
421
+
422
+ if (DLIB_GIF_SUPPORT)
423
+ find_package(GIF QUIET)
424
+ if (GIF_FOUND)
425
+ set (dlib_needed_includes ${dlib_needed_includes} ${GIF_INCLUDE_DIR})
426
+ set (dlib_needed_libraries ${dlib_needed_libraries} ${GIF_LIBRARY})
427
+ else()
428
+ set(DLIB_GIF_SUPPORT OFF CACHE STRING ${DLIB_GIF_SUPPORT_STR} FORCE )
429
+ toggle_preprocessor_switch(DLIB_GIF_SUPPORT)
430
+ endif()
431
+ endif()
432
+
433
+ if (DLIB_PNG_SUPPORT)
434
+ include(cmake_utils/find_libpng.cmake)
435
+ if (PNG_FOUND)
436
+ include_directories(${PNG_INCLUDE_DIR})
437
+ set (dlib_needed_libraries ${dlib_needed_libraries} ${PNG_LIBRARIES})
438
+ else()
439
+ # If we can't find libpng then statically compile it in.
440
+ include_directories(external/libpng external/zlib)
441
+ set(source_files ${source_files}
442
+ external/libpng/arm/arm_init.c
443
+ external/libpng/arm/filter_neon_intrinsics.c
444
+ external/libpng/png.c
445
+ external/libpng/pngerror.c
446
+ external/libpng/pngget.c
447
+ external/libpng/pngmem.c
448
+ external/libpng/pngpread.c
449
+ external/libpng/pngread.c
450
+ external/libpng/pngrio.c
451
+ external/libpng/pngrtran.c
452
+ external/libpng/pngrutil.c
453
+ external/libpng/pngset.c
454
+ external/libpng/pngtrans.c
455
+ external/libpng/pngwio.c
456
+ external/libpng/pngwrite.c
457
+ external/libpng/pngwtran.c
458
+ external/libpng/pngwutil.c
459
+ external/zlib/adler32.c
460
+ external/zlib/compress.c
461
+ external/zlib/crc32.c
462
+ external/zlib/deflate.c
463
+ external/zlib/gzclose.c
464
+ external/zlib/gzlib.c
465
+ external/zlib/gzread.c
466
+ external/zlib/gzwrite.c
467
+ external/zlib/infback.c
468
+ external/zlib/inffast.c
469
+ external/zlib/inflate.c
470
+ external/zlib/inftrees.c
471
+ external/zlib/trees.c
472
+ external/zlib/uncompr.c
473
+ external/zlib/zutil.c
474
+ )
475
+
476
+ include(cmake_utils/check_if_neon_available.cmake)
477
+ if (ARM_NEON_IS_AVAILABLE)
478
+ message (STATUS "NEON instructions will be used for libpng.")
479
+ enable_language(ASM)
480
+ set(source_files ${source_files}
481
+ external/libpng/arm/arm_init.c
482
+ external/libpng/arm/filter_neon_intrinsics.c
483
+ external/libpng/arm/filter_neon.S
484
+ )
485
+ set_source_files_properties(external/libpng/arm/filter_neon.S PROPERTIES COMPILE_FLAGS "${CMAKE_ASM_FLAGS} ${CMAKE_CXX_FLAGS} -x assembler-with-cpp")
486
+ endif()
487
+ endif()
488
+ set(source_files ${source_files}
489
+ image_loader/png_loader.cpp
490
+ image_saver/save_png.cpp
491
+ )
492
+ endif()
493
+
494
+ if (DLIB_JPEG_SUPPORT)
495
+ include(cmake_utils/find_libjpeg.cmake)
496
+ if (JPEG_FOUND)
497
+ include_directories(${JPEG_INCLUDE_DIR})
498
+ set (dlib_needed_libraries ${dlib_needed_libraries} ${JPEG_LIBRARY})
499
+ else()
500
+ # If we can't find libjpeg then statically compile it in.
501
+ add_definitions(-DDLIB_JPEG_STATIC)
502
+ set(source_files ${source_files}
503
+ external/libjpeg/jaricom.c
504
+ external/libjpeg/jcapimin.c
505
+ external/libjpeg/jcapistd.c
506
+ external/libjpeg/jcarith.c
507
+ external/libjpeg/jccoefct.c
508
+ external/libjpeg/jccolor.c
509
+ external/libjpeg/jcdctmgr.c
510
+ external/libjpeg/jchuff.c
511
+ external/libjpeg/jcinit.c
512
+ external/libjpeg/jcmainct.c
513
+ external/libjpeg/jcmarker.c
514
+ external/libjpeg/jcmaster.c
515
+ external/libjpeg/jcomapi.c
516
+ external/libjpeg/jcparam.c
517
+ external/libjpeg/jcprepct.c
518
+ external/libjpeg/jcsample.c
519
+ external/libjpeg/jdapimin.c
520
+ external/libjpeg/jdapistd.c
521
+ external/libjpeg/jdarith.c
522
+ external/libjpeg/jdatadst.c
523
+ external/libjpeg/jdatasrc.c
524
+ external/libjpeg/jdcoefct.c
525
+ external/libjpeg/jdcolor.c
526
+ external/libjpeg/jddctmgr.c
527
+ external/libjpeg/jdhuff.c
528
+ external/libjpeg/jdinput.c
529
+ external/libjpeg/jdmainct.c
530
+ external/libjpeg/jdmarker.c
531
+ external/libjpeg/jdmaster.c
532
+ external/libjpeg/jdmerge.c
533
+ external/libjpeg/jdpostct.c
534
+ external/libjpeg/jdsample.c
535
+ external/libjpeg/jerror.c
536
+ external/libjpeg/jfdctflt.c
537
+ external/libjpeg/jfdctfst.c
538
+ external/libjpeg/jfdctint.c
539
+ external/libjpeg/jidctflt.c
540
+ external/libjpeg/jidctfst.c
541
+ external/libjpeg/jidctint.c
542
+ external/libjpeg/jmemmgr.c
543
+ external/libjpeg/jmemnobs.c
544
+ external/libjpeg/jquant1.c
545
+ external/libjpeg/jquant2.c
546
+ external/libjpeg/jutils.c
547
+ )
548
+ endif()
549
+ set(source_files ${source_files}
550
+ image_loader/jpeg_loader.cpp
551
+ image_saver/save_jpeg.cpp
552
+ )
553
+ endif()
554
+
555
+
556
+ if (DLIB_USE_BLAS OR DLIB_USE_LAPACK OR DLIB_USE_MKL_FFT)
557
+ if (DLIB_USE_MKL_WITH_TBB AND DLIB_USE_MKL_SEQUENTIAL)
558
+ set(DLIB_USE_MKL_SEQUENTIAL OFF CACHE STRING ${DLIB_USE_MKL_SEQUENTIAL_STR} FORCE )
559
+ toggle_preprocessor_switch(DLIB_USE_MKL_SEQUENTIAL)
560
+ message(STATUS "Disabling DLIB_USE_MKL_SEQUENTIAL. It cannot be used simultaneously with DLIB_USE_MKL_WITH_TBB.")
561
+ endif()
562
+
563
+
564
+ # Try to find BLAS, LAPACK and MKL
565
+ include(cmake_utils/find_blas.cmake)
566
+
567
+ if (DLIB_USE_BLAS)
568
+ if (blas_found)
569
+ set (dlib_needed_libraries ${dlib_needed_libraries} ${blas_libraries})
570
+ else()
571
+ set(DLIB_USE_BLAS OFF CACHE STRING ${DLIB_USE_BLAS_STR} FORCE )
572
+ toggle_preprocessor_switch(DLIB_USE_BLAS)
573
+ endif()
574
+ endif()
575
+
576
+ if (DLIB_USE_LAPACK)
577
+ if (lapack_found)
578
+ set (dlib_needed_libraries ${dlib_needed_libraries} ${lapack_libraries})
579
+ if (lapack_with_underscore)
580
+ set(LAPACK_FORCE_UNDERSCORE 1)
581
+ enable_preprocessor_switch(LAPACK_FORCE_UNDERSCORE)
582
+ elseif (lapack_without_underscore)
583
+ set(LAPACK_FORCE_NOUNDERSCORE 1)
584
+ enable_preprocessor_switch(LAPACK_FORCE_NOUNDERSCORE)
585
+ endif ()
586
+ else()
587
+ set(DLIB_USE_LAPACK OFF CACHE STRING ${DLIB_USE_LAPACK_STR} FORCE )
588
+ toggle_preprocessor_switch(DLIB_USE_LAPACK)
589
+ endif()
590
+ endif()
591
+
592
+ if (DLIB_USE_MKL_FFT)
593
+ if (found_intel_mkl AND found_intel_mkl_headers)
594
+ set (dlib_needed_includes ${dlib_needed_includes} ${mkl_include_dir})
595
+ set (dlib_needed_libraries ${dlib_needed_libraries} ${mkl_libraries})
596
+ else()
597
+ set(DLIB_USE_MKL_FFT OFF CACHE STRING ${DLIB_USE_MKL_FFT_STR} FORCE )
598
+ toggle_preprocessor_switch(DLIB_USE_MKL_FFT)
599
+ endif()
600
+ endif()
601
+ endif()
602
+
603
+
604
+ if (DLIB_USE_CUDA)
605
+ find_package(CUDA 7.5)
606
+
607
+ if (CUDA_VERSION VERSION_GREATER 9.1 AND CMAKE_VERSION VERSION_LESS 3.12.2)
608
+ # This bit of weirdness is to work around a bug in cmake
609
+ list(REMOVE_ITEM CUDA_CUBLAS_LIBRARIES "CUDA_cublas_device_LIBRARY-NOTFOUND")
610
+ endif()
611
+
612
+
613
+ if (CUDA_FOUND AND MSVC AND NOT CUDA_CUBLAS_LIBRARIES AND "${CMAKE_SIZEOF_VOID_P}" EQUAL "4")
614
+ message(WARNING "You have CUDA installed, but we can't use it unless you put visual studio in 64bit mode.")
615
+ set(CUDA_FOUND 0)
616
+ endif()
617
+
618
+ if (NOT CUDA_CUBLAS_LIBRARIES)
619
+ message(STATUS "Found CUDA, but CMake was unable to find the cuBLAS libraries that should be part of every basic CUDA "
620
+ "install. Your CUDA install is somehow broken or incomplete. Since cuBLAS is required for dlib to use CUDA we won't use CUDA.")
621
+ set(CUDA_FOUND 0)
622
+ endif()
623
+
624
+ if (CUDA_FOUND AND (NOT USING_OLD_VISUAL_STUDIO_COMPILER))
625
+
626
+ # There is some bug in cmake that causes it to mess up the
627
+ # -std=c++11 option if you let it propagate it to nvcc in some
628
+ # cases. So instead we disable this and manually include
629
+ # things from CMAKE_CXX_FLAGS in the CUDA_NVCC_FLAGS list below.
630
+ if (APPLE)
631
+ set(CUDA_PROPAGATE_HOST_FLAGS OFF)
632
+ # Grab all the -D flags from CMAKE_CXX_FLAGS so we can pass them
633
+ # to nvcc.
634
+ string(REGEX MATCHALL "-D[^ ]*" FLAGS_FOR_NVCC "${CMAKE_CXX_FLAGS}")
635
+
636
+ # Check if we are being built as part of a pybind11 module.
637
+ if (COMMAND pybind11_add_module)
638
+ # Don't export unnecessary symbols.
639
+ list(APPEND FLAGS_FOR_NVCC "-Xcompiler=-fvisibility=hidden")
640
+ endif()
641
+ endif()
642
+
643
+ set(CUDA_HOST_COMPILATION_CPP ON)
644
+ # Note that we add __STRICT_ANSI__ to avoid freaking out nvcc with gcc specific
645
+ # magic in the standard C++ header files (since nvcc uses gcc headers on
646
+ # linux).
647
+ list(APPEND CUDA_NVCC_FLAGS "-arch=sm_50;-D__STRICT_ANSI__;-D_MWAITXINTRIN_H_INCLUDED;-D_FORCE_INLINES;${FLAGS_FOR_NVCC}")
648
+ list(APPEND CUDA_NVCC_FLAGS ${active_preprocessor_switches})
649
+ if (NOT DLIB_IN_PROJECT_BUILD)
650
+ LIST(APPEND CUDA_NVCC_FLAGS -DDLIB__CMAKE_GENERATED_A_CONFIG_H_FILE)
651
+ endif()
652
+ if (NOT MSVC)
653
+ list(APPEND CUDA_NVCC_FLAGS "-std=c++11")
654
+ endif()
655
+ if (CMAKE_POSITION_INDEPENDENT_CODE)
656
+ # sometimes this setting isn't propagated to NVCC, which then causes the
657
+ # compile to fail. So make sure it's propagated.
658
+ if (NOT MSVC) # Visual studio doesn't have -fPIC so don't do it in that case.
659
+ list(APPEND CUDA_NVCC_FLAGS "-Xcompiler -fPIC")
660
+ endif()
661
+ endif()
662
+
663
+ include(cmake_utils/test_for_cudnn/find_cudnn.txt)
664
+
665
+ if (cudnn AND cudnn_include AND NOT DEFINED cuda_test_compile_worked AND NOT DEFINED cudnn_test_compile_worked)
666
+ # make sure cuda is really working by doing a test compile
667
+ message(STATUS "Building a CUDA test project to see if your compiler is compatible with CUDA...")
668
+
669
+ set(CUDA_TEST_CMAKE_FLAGS
670
+ "-DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH}"
671
+ "-DCMAKE_INCLUDE_PATH=${CMAKE_INCLUDE_PATH}"
672
+ "-DCMAKE_LIBRARY_PATH=${CMAKE_LIBRARY_PATH}")
673
+
674
+ if (NOT MSVC) # see https://github.com/davisking/dlib/issues/363
675
+ list(APPEND CUDA_TEST_CMAKE_FLAGS "-DCUDA_HOST_COMPILER=${CUDA_HOST_COMPILER}")
676
+ endif()
677
+
678
+ try_compile(cuda_test_compile_worked
679
+ ${PROJECT_BINARY_DIR}/cuda_test_build
680
+ ${PROJECT_SOURCE_DIR}/cmake_utils/test_for_cuda cuda_test
681
+ CMAKE_FLAGS ${CUDA_TEST_CMAKE_FLAGS}
682
+ OUTPUT_VARIABLE try_compile_output_message
683
+ )
684
+ if (NOT cuda_test_compile_worked)
685
+ string(REPLACE "\n" "\n *** " try_compile_output_message "${try_compile_output_message}")
686
+ message(STATUS "*****************************************************************************************************************")
687
+ message(STATUS "*** CUDA was found but your compiler failed to compile a simple CUDA program so dlib isn't going to use CUDA. ")
688
+ message(STATUS "*** The output of the failed CUDA test compile is shown below: ")
689
+ message(STATUS "*** ")
690
+ message(STATUS "*** ${try_compile_output_message}")
691
+ message(STATUS "*****************************************************************************************************************")
692
+ else()
693
+ message(STATUS "Building a cuDNN test project to check if you have the right version of cuDNN installed...")
694
+ try_compile(cudnn_test_compile_worked
695
+ ${PROJECT_BINARY_DIR}/cudnn_test_build
696
+ ${PROJECT_SOURCE_DIR}/cmake_utils/test_for_cudnn cudnn_test
697
+ CMAKE_FLAGS ${CUDA_TEST_CMAKE_FLAGS}
698
+ OUTPUT_VARIABLE try_compile_output_message
699
+ )
700
+ if (NOT cudnn_test_compile_worked)
701
+ string(REPLACE "\n" "\n *** " try_compile_output_message "${try_compile_output_message}")
702
+ message(STATUS "*****************************************************************************************************")
703
+ message(STATUS "*** Found cuDNN, but we failed to compile the dlib/cmake_utils/test_for_cudnn project. ")
704
+ message(STATUS "*** You either have an unsupported version of cuDNN or something is wrong with your cudDNN install.")
705
+ message(STATUS "*** Since a functional cuDNN is not found DLIB WILL NOT USE CUDA. ")
706
+ message(STATUS "*** The output of the failed test_for_cudnn build is: ")
707
+ message(STATUS "*** ")
708
+ message(STATUS "*** ${try_compile_output_message}")
709
+ message(STATUS "*****************************************************************************************************")
710
+ endif()
711
+ endif()
712
+ endif()
713
+
714
+ # Find where cuSOLVER is since the FindCUDA cmake package doesn't
715
+ # bother to look for it in older versions of cmake.
716
+ if (NOT CUDA_cusolver_LIBRARY)
717
+ get_filename_component(cuda_blas_path "${CUDA_CUBLAS_LIBRARIES}" DIRECTORY)
718
+ find_library(CUDA_cusolver_LIBRARY cusolver HINTS ${cuda_blas_path})
719
+ # CUDA 10.1 doesn't install symbolic links to libcusolver.so in
720
+ # the usual place. This is probably a bug in the cuda
721
+ # installer. In any case, If we haven't found cusolver yet go
722
+ # look in the cuda install folder for it. New versions of cmake
723
+ # do this correctly, but older versions need help.
724
+ if (NOT CUDA_cusolver_LIBRARY)
725
+ find_library(CUDA_cusolver_LIBRARY cusolver HINTS
726
+ /usr/local/cuda/lib64/
727
+ )
728
+ endif()
729
+ mark_as_advanced(CUDA_cusolver_LIBRARY)
730
+ endif()
731
+ # Also find OpenMP since cuSOLVER needs it. Importantly, we only
732
+ # look for one to link to if our use of BLAS, specifically the
733
+ # Intel MKL, hasn't already decided what to use. This is because
734
+ # it makes the MKL bug out if you link to another openmp lib other
735
+ # than Intel's when you use the MKL. I'm also not really sure when
736
+ # explicit linking to openmp became unnecessary, but for
737
+ # sufficiently older versions of cuda it was needed. Then in
738
+ # versions of cmake newer than 3.11 linking to openmp started to
739
+ # mess up the switches passed to nvcc, so you can't just leave
740
+ # these "try to link to openmp" statements here going forward. Fun
741
+ # times.
742
+ if (CUDA_VERSION VERSION_LESS "9.1" AND NOT openmp_libraries AND NOT MSVC AND NOT XCODE AND NOT APPLE)
743
+ find_package(OpenMP)
744
+ if (OPENMP_FOUND)
745
+ set(openmp_libraries ${OpenMP_CXX_FLAGS})
746
+ else()
747
+ message(STATUS "*** Didn't find OpenMP, which is required to use CUDA. ***")
748
+ set(CUDA_FOUND 0)
749
+ endif()
750
+ endif()
751
+ endif()
752
+
753
+ if (CUDA_FOUND AND cudnn AND (NOT USING_OLD_VISUAL_STUDIO_COMPILER) AND cuda_test_compile_worked AND cudnn_test_compile_worked AND cudnn_include)
754
+ set(source_files ${source_files}
755
+ cuda/cuda_dlib.cu
756
+ cuda/cudnn_dlibapi.cpp
757
+ cuda/cublas_dlibapi.cpp
758
+ cuda/cusolver_dlibapi.cu
759
+ cuda/curand_dlibapi.cpp
760
+ cuda/cuda_data_ptr.cpp
761
+ cuda/gpu_data.cpp
762
+ )
763
+ set(dlib_needed_libraries ${dlib_needed_libraries}
764
+ ${CUDA_CUBLAS_LIBRARIES}
765
+ ${cudnn}
766
+ ${CUDA_curand_LIBRARY}
767
+ ${CUDA_cusolver_LIBRARY}
768
+ ${CUDA_CUDART_LIBRARY}
769
+ )
770
+ if(openmp_libraries)
771
+ list(APPEND dlib_needed_libraries ${openmp_libraries})
772
+ endif()
773
+
774
+ include_directories(${cudnn_include})
775
+ message(STATUS "Enabling CUDA support for dlib. DLIB WILL USE CUDA")
776
+ else()
777
+ set(DLIB_USE_CUDA OFF CACHE STRING ${DLIB_USE_BLAS_STR} FORCE )
778
+ toggle_preprocessor_switch(DLIB_USE_CUDA)
779
+ if (USING_OLD_VISUAL_STUDIO_COMPILER)
780
+ message(STATUS "*** Dlib CUDA support requires C++11 but your compiler doesn't support it. ***")
781
+ endif()
782
+ if (NOT CUDA_FOUND)
783
+ message(STATUS "DID NOT FIND CUDA")
784
+ endif()
785
+ message(STATUS "Disabling CUDA support for dlib. DLIB WILL NOT USE CUDA")
786
+ endif()
787
+ endif()
788
+
789
+
790
+ if (DLIB_LINK_WITH_SQLITE3)
791
+ find_library(sqlite sqlite3)
792
+ # make sure sqlite3.h is in the include path
793
+ find_path(sqlite_path sqlite3.h)
794
+ if (sqlite AND sqlite_path)
795
+ set(dlib_needed_includes ${dlib_needed_includes} ${sqlite_path})
796
+ set(dlib_needed_libraries ${dlib_needed_libraries} ${sqlite} )
797
+ else()
798
+ set(DLIB_LINK_WITH_SQLITE3 OFF CACHE STRING ${DLIB_LINK_WITH_SQLITE3_STR} FORCE )
799
+ endif()
800
+ mark_as_advanced(sqlite sqlite_path)
801
+ endif()
802
+
803
+
804
+
805
+ if (DLIB_USE_FFTW)
806
+ find_library(fftw fftw3)
807
+ # make sure fftw3.h is in the include path
808
+ find_path(fftw_path fftw3.h)
809
+ if (fftw AND fftw_path)
810
+ set(dlib_needed_includes ${dlib_needed_includes} ${fftw_path})
811
+ set(dlib_needed_libraries ${dlib_needed_libraries} ${fftw} )
812
+ else()
813
+ set(DLIB_USE_FFTW OFF CACHE STRING ${DLIB_USE_FFTW_STR} FORCE )
814
+ toggle_preprocessor_switch(DLIB_USE_FFTW)
815
+ endif()
816
+ mark_as_advanced(fftw fftw_path)
817
+ endif()
818
+
819
+
820
+
821
+ # Tell CMake to build dlib via add_library()/cuda_add_library()
822
+ if (DLIB_USE_CUDA)
823
+ # The old cuda_add_library() command doesn't support CMake's newer dependency
824
+ # stuff, so we have to set the include path manually still, which we do here.
825
+ include_directories(${dlib_needed_includes})
826
+ cuda_add_library(dlib ${source_files} )
827
+ else()
828
+ add_library(dlib ${source_files} )
829
+ endif()
830
+
831
+ endif () ##### end of if NOT DLIB_ISO_CPP_ONLY ##########################################################
832
+
833
+
834
+ target_include_directories(dlib
835
+ INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..>
836
+ INTERFACE $<INSTALL_INTERFACE:include>
837
+ PUBLIC ${dlib_needed_includes}
838
+ )
839
+ target_link_libraries(dlib PUBLIC ${dlib_needed_libraries})
840
+ if (DLIB_IN_PROJECT_BUILD)
841
+ target_compile_options(dlib PUBLIC ${active_preprocessor_switches})
842
+ else()
843
+ # These are private in this case because they will be controlled by the
844
+ # contents of dlib/config.h once it's installed. But for in project
845
+ # builds, there is no real config.h so they are public in the above case.
846
+ target_compile_options(dlib PRIVATE ${active_preprocessor_switches})
847
+ # Do this so that dlib/config.h won't set DLIB_NOT_CONFIGURED. This will then allow
848
+ # the code in dlib/threads_kernel_shared.cpp to emit a linker error for users who
849
+ # don't use the configured config.h file generated by cmake.
850
+ target_compile_options(dlib PRIVATE -DDLIB__CMAKE_GENERATED_A_CONFIG_H_FILE)
851
+
852
+ # Do this so that dlib/config.h can record the version of dlib it's configured with
853
+ # and ultimately issue a linker error to people who try to use a binary dlib that is
854
+ # the wrong version.
855
+ set(DLIB_CHECK_FOR_VERSION_MISMATCH
856
+ DLIB_VERSION_MISMATCH_CHECK__EXPECTED_VERSION_${CPACK_PACKAGE_VERSION_MAJOR}_${CPACK_PACKAGE_VERSION_MINOR}_${CPACK_PACKAGE_VERSION_PATCH})
857
+ target_compile_options(dlib PRIVATE "-DDLIB_CHECK_FOR_VERSION_MISMATCH=${DLIB_CHECK_FOR_VERSION_MISMATCH}")
858
+ endif()
859
+
860
+
861
+ # Allow the unit tests to ask us to compile the all/source.cpp file just to make sure it compiles.
862
+ if (DLIB_TEST_COMPILE_ALL_SOURCE_CPP)
863
+ add_library(dlib_all_source_cpp STATIC all/source.cpp)
864
+ target_link_libraries(dlib_all_source_cpp dlib)
865
+ target_compile_options(dlib_all_source_cpp PUBLIC ${active_preprocessor_switches})
866
+ enable_cpp11_for_target(dlib_all_source_cpp)
867
+ endif()
868
+
869
+ enable_cpp11_for_target(dlib)
870
+ if((MSVC AND CMAKE_VERSION VERSION_LESS 3.11) OR CMAKE_VERSION VERSION_LESS 3.3)
871
+ target_compile_options(dlib PUBLIC ${active_compile_opts})
872
+ target_compile_options(dlib PRIVATE ${active_compile_opts_private})
873
+ else()
874
+ target_compile_options(dlib PUBLIC $<$<COMPILE_LANGUAGE:CXX>:${active_compile_opts}>)
875
+ target_compile_options(dlib PRIVATE $<$<COMPILE_LANGUAGE:CXX>:${active_compile_opts_private}>)
876
+ endif()
877
+
878
+ # Install the library
879
+ if (NOT DLIB_IN_PROJECT_BUILD)
880
+ string (REPLACE ";" " " pkg_config_dlib_needed_libraries "${dlib_needed_libraries}")
881
+ # Make the -I include options for pkg-config
882
+ foreach (ITR ${dlib_needed_includes})
883
+ set (pkg_config_dlib_needed_includes "${pkg_config_dlib_needed_includes} -I${ITR}")
884
+ endforeach()
885
+ set_target_properties(dlib PROPERTIES
886
+ VERSION ${VERSION})
887
+ install(TARGETS dlib
888
+ EXPORT dlib
889
+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} # Windows considers .dll to be runtime artifacts
890
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
891
+ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
892
+
893
+ install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dlib
894
+ FILES_MATCHING
895
+ PATTERN "*.h"
896
+ PATTERN "*.cmake"
897
+ PATTERN "*_tutorial.txt"
898
+ PATTERN "cassert"
899
+ PATTERN "cstring"
900
+ PATTERN "fstream"
901
+ PATTERN "iomanip"
902
+ PATTERN "iosfwd"
903
+ PATTERN "iostream"
904
+ PATTERN "istream"
905
+ PATTERN "locale"
906
+ PATTERN "ostream"
907
+ PATTERN "sstream"
908
+ REGEX "${CMAKE_CURRENT_BINARY_DIR}" EXCLUDE)
909
+
910
+
911
+ configure_file(${PROJECT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)
912
+ # overwrite config.h with the configured one
913
+ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/config.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dlib)
914
+
915
+ configure_file(${PROJECT_SOURCE_DIR}/revision.h.in ${CMAKE_CURRENT_BINARY_DIR}/revision.h)
916
+ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/revision.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dlib)
917
+
918
+ ## Config.cmake generation and installation
919
+
920
+ set(ConfigPackageLocation "${CMAKE_INSTALL_LIBDIR}/cmake/dlib")
921
+ install(EXPORT dlib
922
+ NAMESPACE dlib::
923
+ DESTINATION ${ConfigPackageLocation})
924
+
925
+ configure_file(cmake_utils/dlibConfig.cmake.in "${CMAKE_CURRENT_BINARY_DIR}/config/dlibConfig.cmake" @ONLY)
926
+
927
+ include(CMakePackageConfigHelpers)
928
+ write_basic_package_version_file(
929
+ "${CMAKE_CURRENT_BINARY_DIR}/config/dlibConfigVersion.cmake"
930
+ VERSION ${VERSION}
931
+ COMPATIBILITY AnyNewerVersion
932
+ )
933
+
934
+ install(FILES
935
+ "${CMAKE_CURRENT_BINARY_DIR}/config/dlibConfig.cmake"
936
+ "${CMAKE_CURRENT_BINARY_DIR}/config/dlibConfigVersion.cmake"
937
+ DESTINATION ${ConfigPackageLocation})
938
+
939
+ ## dlib-1.pc generation and installation
940
+
941
+ configure_file("cmake_utils/dlib.pc.in" "dlib-1.pc" @ONLY)
942
+ install(FILES "${CMAKE_CURRENT_BINARY_DIR}/dlib-1.pc"
943
+ DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
944
+
945
+ # Add a cpack "package" target. This will create an archive containing
946
+ # the built library file, the header files, and cmake and pkgconfig
947
+ # configuration files.
948
+ include(CPack)
949
+
950
+ endif()
951
+
952
+ endif()
953
+
954
+ if (MSVC)
955
+ # Give the output library files names that are unique functions of the
956
+ # visual studio mode that compiled them. We do this so that people who
957
+ # compile dlib and then copy the .lib files around (which they shouldn't be
958
+ # doing in the first place!) will hopefully be slightly less confused by
959
+ # what happens since, at the very least, the filenames will indicate what
960
+ # visual studio runtime they go with.
961
+ math(EXPR numbits ${CMAKE_SIZEOF_VOID_P}*8)
962
+ set_target_properties(dlib PROPERTIES DEBUG_POSTFIX "${VERSION}_debug_${numbits}bit_msvc${MSVC_VERSION}")
963
+ set_target_properties(dlib PROPERTIES RELEASE_POSTFIX "${VERSION}_release_${numbits}bit_msvc${MSVC_VERSION}")
964
+ set_target_properties(dlib PROPERTIES MINSIZEREL_POSTFIX "${VERSION}_minsizerel_${numbits}bit_msvc${MSVC_VERSION}")
965
+ set_target_properties(dlib PROPERTIES RELWITHDEBINFO_POSTFIX "${VERSION}_relwithdebinfo_${numbits}bit_msvc${MSVC_VERSION}")
966
+ endif()
967
+
968
+ # Check if we are being built as part of a pybind11 module.
969
+ if (COMMAND pybind11_add_module)
970
+ # Don't export unnecessary symbols.
971
+ set_target_properties(dlib PROPERTIES CXX_VISIBILITY_PRESET "hidden")
972
+ set_target_properties(dlib PROPERTIES CUDA_VISIBILITY_PRESET "hidden")
973
+ endif()
974
+
975
+ if (WIN32 AND mkl_iomp_dll)
976
+ # If we are using the Intel MKL on windows then try and copy the iomp dll
977
+ # file to the output folder. We do this since a very large number of
978
+ # windows users don't understand that they need to add the Intel MKL's
979
+ # folders to their PATH to use the Intel MKL. They then complain on the
980
+ # dlib forums. Copying the Intel MKL dlls to the output directory removes
981
+ # the need to add the Intel MKL to the PATH.
982
+ if (CMAKE_LIBRARY_OUTPUT_DIRECTORY)
983
+ add_custom_command(TARGET dlib POST_BUILD
984
+ # In some newer versions of windows/visual studio the output Config folder doesn't
985
+ # exist at first, so you can't copy to it unless you make it yourself. So make
986
+ # sure the target folder exists first.
987
+ COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/"
988
+ COMMAND ${CMAKE_COMMAND} -E copy "${mkl_iomp_dll}" "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/"
989
+ )
990
+ else()
991
+ add_custom_command(TARGET dlib POST_BUILD
992
+ # In some newer versions of windows/visual studio the output Config folder doesn't
993
+ # exist at first, so you can't copy to it unless you make it yourself. So make
994
+ # sure the target folder exists first.
995
+ COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_BINARY_DIR}/$<CONFIG>/"
996
+ COMMAND ${CMAKE_COMMAND} -E copy "${mkl_iomp_dll}" "${CMAKE_BINARY_DIR}/$<CONFIG>/"
997
+ )
998
+ endif()
999
+ endif()
1000
+
1001
+ add_library(dlib::dlib ALIAS dlib)
dlibs/dlib/LICENSE.txt ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Boost Software License - Version 1.0 - August 17th, 2003
2
+
3
+ Permission is hereby granted, free of charge, to any person or organization
4
+ obtaining a copy of the software and accompanying documentation covered by
5
+ this license (the "Software") to use, reproduce, display, distribute,
6
+ execute, and transmit the Software, and to prepare derivative works of the
7
+ Software, and to permit third-parties to whom the Software is furnished to
8
+ do so, all subject to the following:
9
+
10
+ The copyright notices in the Software and this entire statement, including
11
+ the above license grant, this restriction and the following disclaimer,
12
+ must be included in all copies of the Software, in whole or in part, and
13
+ all derivative works of the Software, unless such copies or derivative
14
+ works are solely in the form of machine-executable object code generated by
15
+ a source language processor.
16
+
17
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
20
+ SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
21
+ FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
22
+ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
+ DEALINGS IN THE SOFTWARE.
dlibs/dlib/algs.h ADDED
@@ -0,0 +1,1158 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (C) 2003 Davis E. King ([email protected])
2
+ // License: Boost Software License See LICENSE.txt for the full license.
3
+
4
+ #ifdef DLIB_ALL_SOURCE_END
5
+ #include "dlib_basic_cpp_build_tutorial.txt"
6
+ #endif
7
+
8
+ #ifndef DLIB_ALGs_
9
+ #define DLIB_ALGs_
10
+
11
+ // this file contains miscellaneous stuff
12
+
13
+ // Give people who forget the -std=c++11 option a reminder
14
+ #if (defined(__GNUC__) && ((__GNUC__ >= 4 && __GNUC_MINOR__ >= 8) || (__GNUC__ > 4))) || \
15
+ (defined(__clang__) && ((__clang_major__ >= 3 && __clang_minor__ >= 4) || (__clang_major__ >= 3)))
16
+ #if __cplusplus < 201103
17
+ #error "Dlib requires C++11 support. Give your compiler the -std=c++11 option to enable it."
18
+ #endif
19
+ #endif
20
+
21
+ #if defined __NVCC__
22
+ // Disable the "statement is unreachable" message since it will go off on code that is
23
+ // actually reachable but just happens to not be reachable sometimes during certain
24
+ // template instantiations.
25
+ #pragma diag_suppress code_is_unreachable
26
+ #endif
27
+
28
+
29
+ #ifdef _MSC_VER
30
+
31
+ #if _MSC_VER < 1900
32
+ #error "dlib versions newer than v19.1 use C++11 and therefore require Visual Studio 2015 or newer."
33
+ #endif
34
+
35
+ // Disable the following warnings for Visual Studio
36
+
37
+ // this is to disable the "'this' : used in base member initializer list"
38
+ // warning you get from some of the GUI objects since all the objects
39
+ // require that their parent class be passed into their constructor.
40
+ // In this case though it is totally safe so it is ok to disable this warning.
41
+ #pragma warning(disable : 4355)
42
+
43
+ // This is a warning you get sometimes when Visual Studio performs a Koenig Lookup.
44
+ // This is a bug in visual studio. It is a totally legitimate thing to
45
+ // expect from a compiler.
46
+ #pragma warning(disable : 4675)
47
+
48
+ // This is a warning you get from visual studio 2005 about things in the standard C++
49
+ // library being "deprecated." I checked the C++ standard and it doesn't say jack
50
+ // about any of them (I checked the searchable PDF). So this warning is total Bunk.
51
+ #pragma warning(disable : 4996)
52
+
53
+ // This is a warning you get from visual studio 2003:
54
+ // warning C4345: behavior change: an object of POD type constructed with an initializer
55
+ // of the form () will be default-initialized.
56
+ // I love it when this compiler gives warnings about bugs in previous versions of itself.
57
+ #pragma warning(disable : 4345)
58
+
59
+
60
+ // Disable warnings about conversion from size_t to unsigned long and long.
61
+ #pragma warning(disable : 4267)
62
+
63
+ // Disable warnings about conversion from double to float
64
+ #pragma warning(disable : 4244)
65
+ #pragma warning(disable : 4305)
66
+
67
+ // Disable "warning C4180: qualifier applied to function type has no meaning; ignored".
68
+ // This warning happens often in generic code that works with functions and isn't useful.
69
+ #pragma warning(disable : 4180)
70
+
71
+ // Disable "warning C4290: C++ exception specification ignored except to indicate a function is not __declspec(nothrow)"
72
+ #pragma warning(disable : 4290)
73
+
74
+
75
+ // DNN module uses template-based network declaration that leads to very long
76
+ // type names. Visual Studio will produce Warning C4503 in such cases. https://msdn.microsoft.com/en-us/library/074af4b6.aspx says
77
+ // that correct binaries are still produced even when this warning happens, but linker errors from visual studio, if they occur could be confusing.
78
+ #pragma warning( disable: 4503 )
79
+
80
+
81
+ #endif
82
+
83
+ #ifdef __BORLANDC__
84
+ // Disable the following warnings for the Borland Compilers
85
+ //
86
+ // These warnings just say that the compiler is refusing to inline functions with
87
+ // loops or try blocks in them.
88
+ //
89
+ #pragma option -w-8027
90
+ #pragma option -w-8026
91
+ #endif
92
+
93
+ #include <string> // for the exceptions
94
+
95
+ #ifdef __CYGWIN__
96
+ namespace std
97
+ {
98
+ typedef std::basic_string<wchar_t> wstring;
99
+ }
100
+ #endif
101
+
102
+ #include "platform.h"
103
+ #include "windows_magic.h"
104
+
105
+
106
+ #include <algorithm> // for std::swap
107
+ #include <new> // for std::bad_alloc
108
+ #include <cstdlib>
109
+ #include <stddef.h>
110
+ #include <limits> // for std::numeric_limits for is_finite()
111
+ #include "assert.h"
112
+ #include "error.h"
113
+ #include "noncopyable.h"
114
+ #include "enable_if.h"
115
+ #include "uintn.h"
116
+ #include "numeric_constants.h"
117
+ #include "memory_manager_stateless/memory_manager_stateless_kernel_1.h" // for the default memory manager
118
+
119
+
120
+
121
+ // ----------------------------------------------------------------------------------------
122
+ /*!A _dT !*/
123
+
124
+ template <typename charT>
125
+ inline charT _dTcast (const char a, const wchar_t b);
126
+ template <>
127
+ inline char _dTcast<char> (const char a, const wchar_t ) { return a; }
128
+ template <>
129
+ inline wchar_t _dTcast<wchar_t> (const char , const wchar_t b) { return b; }
130
+
131
+ template <typename charT>
132
+ inline const charT* _dTcast ( const char* a, const wchar_t* b);
133
+ template <>
134
+ inline const char* _dTcast<char> ( const char* a, const wchar_t* ) { return a; }
135
+ template <>
136
+ inline const wchar_t* _dTcast<wchar_t> ( const char* , const wchar_t* b) { return b; }
137
+
138
+
139
+ #define _dT(charT,str) _dTcast<charT>(str,L##str)
140
+ /*!
141
+ requires
142
+ - charT == char or wchar_t
143
+ - str == a string or character literal
144
+ ensures
145
+ - returns the literal in the form of a charT type literal.
146
+ !*/
147
+
148
+ // ----------------------------------------------------------------------------------------
149
+
150
+
151
+
152
+ namespace dlib
153
+ {
154
+
155
+ // ----------------------------------------------------------------------------------------
156
+
157
+ /*!A default_memory_manager
158
+
159
+ This memory manager just calls new and delete directly.
160
+
161
+ !*/
162
+ typedef memory_manager_stateless_kernel_1<char> default_memory_manager;
163
+
164
+ // ----------------------------------------------------------------------------------------
165
+
166
+ /*!A swap !*/
167
+ // make swap available in the dlib namespace
168
+ using std::swap;
169
+
170
+ // ----------------------------------------------------------------------------------------
171
+
172
+ /*!
173
+ Here is where I define my return codes. It is
174
+ important that they all be < 0.
175
+ !*/
176
+
177
+ enum general_return_codes
178
+ {
179
+ TIMEOUT = -1,
180
+ WOULDBLOCK = -2,
181
+ OTHER_ERROR = -3,
182
+ SHUTDOWN = -4,
183
+ PORTINUSE = -5
184
+ };
185
+
186
+ // ----------------------------------------------------------------------------------------
187
+
188
+ inline unsigned long square_root (
189
+ unsigned long value
190
+ )
191
+ /*!
192
+ requires
193
+ - value <= 2^32 - 1
194
+ ensures
195
+ - returns the square root of value. if the square root is not an
196
+ integer then it will be rounded up to the nearest integer.
197
+ !*/
198
+ {
199
+ unsigned long x;
200
+
201
+ // set the initial guess for what the root is depending on
202
+ // how big value is
203
+ if (value < 3)
204
+ return value;
205
+ else if (value < 4096) // 12
206
+ x = 45;
207
+ else if (value < 65536) // 16
208
+ x = 179;
209
+ else if (value < 1048576) // 20
210
+ x = 717;
211
+ else if (value < 16777216) // 24
212
+ x = 2867;
213
+ else if (value < 268435456) // 28
214
+ x = 11469;
215
+ else // 32
216
+ x = 45875;
217
+
218
+
219
+
220
+ // find the root
221
+ x = (x + value/x)>>1;
222
+ x = (x + value/x)>>1;
223
+ x = (x + value/x)>>1;
224
+ x = (x + value/x)>>1;
225
+
226
+
227
+
228
+ if (x*x < value)
229
+ return x+1;
230
+ else
231
+ return x;
232
+ }
233
+
234
+ // ----------------------------------------------------------------------------------------
235
+
236
+ template <
237
+ typename T
238
+ >
239
+ void median (
240
+ T& one,
241
+ T& two,
242
+ T& three
243
+ );
244
+ /*!
245
+ requires
246
+ - T implements operator<
247
+ - T is swappable by a global swap()
248
+ ensures
249
+ - #one is the median
250
+ - #one, #two, and #three is some permutation of one, two, and three.
251
+ !*/
252
+
253
+
254
+ template <
255
+ typename T
256
+ >
257
+ void median (
258
+ T& one,
259
+ T& two,
260
+ T& three
261
+ )
262
+ {
263
+ using std::swap;
264
+ using dlib::swap;
265
+
266
+ if ( one < two )
267
+ {
268
+ // one < two
269
+ if ( two < three )
270
+ {
271
+ // one < two < three : two
272
+ swap(one,two);
273
+
274
+ }
275
+ else
276
+ {
277
+ // one < two >= three
278
+ if ( one < three)
279
+ {
280
+ // three
281
+ swap(three,one);
282
+ }
283
+ }
284
+
285
+ }
286
+ else
287
+ {
288
+ // one >= two
289
+ if ( three < one )
290
+ {
291
+ // three <= one >= two
292
+ if ( three < two )
293
+ {
294
+ // two
295
+ swap(two,one);
296
+ }
297
+ else
298
+ {
299
+ // three
300
+ swap(three,one);
301
+ }
302
+ }
303
+ }
304
+ }
305
+
306
+ // ----------------------------------------------------------------------------------------
307
+
308
+ namespace relational_operators
309
+ {
310
+ template <
311
+ typename A,
312
+ typename B
313
+ >
314
+ constexpr bool operator> (
315
+ const A& a,
316
+ const B& b
317
+ ) { return b < a; }
318
+
319
+ // ---------------------------------
320
+
321
+ template <
322
+ typename A,
323
+ typename B
324
+ >
325
+ constexpr bool operator!= (
326
+ const A& a,
327
+ const B& b
328
+ ) { return !(a == b); }
329
+
330
+ // ---------------------------------
331
+
332
+ template <
333
+ typename A,
334
+ typename B
335
+ >
336
+ constexpr bool operator<= (
337
+ const A& a,
338
+ const B& b
339
+ ) { return !(b < a); }
340
+
341
+ // ---------------------------------
342
+
343
+ template <
344
+ typename A,
345
+ typename B
346
+ >
347
+ constexpr bool operator>= (
348
+ const A& a,
349
+ const B& b
350
+ ) { return !(a < b); }
351
+
352
+ }
353
+
354
+ // ----------------------------------------------------------------------------------------
355
+
356
+ template <
357
+ typename T
358
+ >
359
+ void exchange (
360
+ T& a,
361
+ T& b
362
+ )
363
+ /*!
364
+ This function does the exact same thing that global swap does and it does it by
365
+ just calling swap. But a lot of compilers have problems doing a Koenig Lookup
366
+ and the fact that this has a different name (global swap has the same name as
367
+ the member functions called swap) makes them compile right.
368
+
369
+ So this is a workaround but not too ugly of one. But hopefully I get get
370
+ rid of this in a few years. So this function is already deprecated.
371
+
372
+ This also means you should NOT use this function in your own code unless
373
+ you have to support an old buggy compiler that benefits from this hack.
374
+ !*/
375
+ {
376
+ using std::swap;
377
+ using dlib::swap;
378
+ swap(a,b);
379
+ }
380
+
381
+ // ----------------------------------------------------------------------------------------
382
+
383
+ /*!A is_pointer_type
384
+
385
+ This is a template where is_pointer_type<T>::value == true when T is a pointer
386
+ type and false otherwise.
387
+ !*/
388
+
389
+ template <
390
+ typename T
391
+ >
392
+ class is_pointer_type
393
+ {
394
+ public:
395
+ enum { value = false };
396
+ private:
397
+ is_pointer_type();
398
+ };
399
+
400
+ template <
401
+ typename T
402
+ >
403
+ class is_pointer_type<T*>
404
+ {
405
+ public:
406
+ enum { value = true };
407
+ private:
408
+ is_pointer_type();
409
+ };
410
+
411
+ // ----------------------------------------------------------------------------------------
412
+
413
+ /*!A is_const_type
414
+
415
+ This is a template where is_const_type<T>::value == true when T is a const
416
+ type and false otherwise.
417
+ !*/
418
+
419
+ template <typename T>
420
+ struct is_const_type
421
+ {
422
+ static const bool value = false;
423
+ };
424
+ template <typename T>
425
+ struct is_const_type<const T>
426
+ {
427
+ static const bool value = true;
428
+ };
429
+ template <typename T>
430
+ struct is_const_type<const T&>
431
+ {
432
+ static const bool value = true;
433
+ };
434
+
435
+ // ----------------------------------------------------------------------------------------
436
+
437
+ /*!A is_reference_type
438
+
439
+ This is a template where is_reference_type<T>::value == true when T is a reference
440
+ type and false otherwise.
441
+ !*/
442
+
443
+ template <typename T>
444
+ struct is_reference_type
445
+ {
446
+ static const bool value = false;
447
+ };
448
+
449
+ template <typename T> struct is_reference_type<const T&> { static const bool value = true; };
450
+ template <typename T> struct is_reference_type<T&> { static const bool value = true; };
451
+
452
+ // ----------------------------------------------------------------------------------------
453
+
454
+ /*!A is_same_type
455
+
456
+ This is a template where is_same_type<T,U>::value == true when T and U are the
457
+ same type and false otherwise.
458
+ !*/
459
+
460
+ template <
461
+ typename T,
462
+ typename U
463
+ >
464
+ class is_same_type
465
+ {
466
+ public:
467
+ enum {value = false};
468
+ private:
469
+ is_same_type();
470
+ };
471
+
472
+ template <typename T>
473
+ class is_same_type<T,T>
474
+ {
475
+ public:
476
+ enum {value = true};
477
+ private:
478
+ is_same_type();
479
+ };
480
+
481
+ // ----------------------------------------------------------------------------------------
482
+
483
+ /*!A is_float_type
484
+
485
+ This is a template that can be used to determine if a type is one of the built
486
+ int floating point types (i.e. float, double, or long double).
487
+ !*/
488
+
489
+ template < typename T > struct is_float_type { const static bool value = false; };
490
+ template <> struct is_float_type<float> { const static bool value = true; };
491
+ template <> struct is_float_type<double> { const static bool value = true; };
492
+ template <> struct is_float_type<long double> { const static bool value = true; };
493
+
494
+ // ----------------------------------------------------------------------------------------
495
+
496
+ /*!A is_convertible
497
+
498
+ This is a template that can be used to determine if one type is convertible
499
+ into another type.
500
+
501
+ For example:
502
+ is_convertible<int,float>::value == true // because ints are convertible to floats
503
+ is_convertible<int*,float>::value == false // because int pointers are NOT convertible to floats
504
+ !*/
505
+
506
+ template <typename from, typename to>
507
+ struct is_convertible
508
+ {
509
+ struct yes_type { char a; };
510
+ struct no_type { yes_type a[2]; };
511
+ static const from& from_helper();
512
+ static yes_type test(to);
513
+ static no_type test(...);
514
+ const static bool value = sizeof(test(from_helper())) == sizeof(yes_type);
515
+ };
516
+
517
+ // ----------------------------------------------------------------------------------------
518
+
519
+ struct general_ {};
520
+ struct special_ : general_ {};
521
+ template<typename> struct int_ { typedef int type; };
522
+
523
+ // ----------------------------------------------------------------------------------------
524
+
525
+
526
+ /*!A is_same_object
527
+
528
+ This is a templated function which checks if both of its arguments are actually
529
+ references to the same object. It returns true if they are and false otherwise.
530
+
531
+ !*/
532
+
533
+ // handle the case where T and U are unrelated types.
534
+ template < typename T, typename U >
535
+ typename disable_if_c<is_convertible<T*, U*>::value || is_convertible<U*,T*>::value, bool>::type
536
+ is_same_object (
537
+ const T& a,
538
+ const U& b
539
+ )
540
+ {
541
+ return ((void*)&a == (void*)&b);
542
+ }
543
+
544
+ // handle the case where T and U are related types because their pointers can be
545
+ // implicitly converted into one or the other. E.g. a derived class and its base class.
546
+ // Or where both T and U are just the same type. This way we make sure that if there is a
547
+ // valid way to convert between these two pointer types then we will take that route rather
548
+ // than the void* approach used otherwise.
549
+ template < typename T, typename U >
550
+ typename enable_if_c<is_convertible<T*, U*>::value || is_convertible<U*,T*>::value, bool>::type
551
+ is_same_object (
552
+ const T& a,
553
+ const U& b
554
+ )
555
+ {
556
+ return (&a == &b);
557
+ }
558
+
559
+ // ----------------------------------------------------------------------------------------
560
+
561
+ /*!A is_unsigned_type
562
+
563
+ This is a template where is_unsigned_type<T>::value == true when T is an unsigned
564
+ scalar type and false when T is a signed scalar type.
565
+ !*/
566
+ template <
567
+ typename T
568
+ >
569
+ struct is_unsigned_type
570
+ {
571
+ static const bool value = static_cast<T>((static_cast<T>(0)-static_cast<T>(1))) > 0;
572
+ };
573
+ template <> struct is_unsigned_type<long double> { static const bool value = false; };
574
+ template <> struct is_unsigned_type<double> { static const bool value = false; };
575
+ template <> struct is_unsigned_type<float> { static const bool value = false; };
576
+
577
+ // ----------------------------------------------------------------------------------------
578
+
579
+ /*!A is_signed_type
580
+
581
+ This is a template where is_signed_type<T>::value == true when T is a signed
582
+ scalar type and false when T is an unsigned scalar type.
583
+ !*/
584
+ template <
585
+ typename T
586
+ >
587
+ struct is_signed_type
588
+ {
589
+ static const bool value = !is_unsigned_type<T>::value;
590
+ };
591
+
592
+ // ----------------------------------------------------------------------------------------
593
+
594
+ template <
595
+ typename T
596
+ >
597
+ class copy_functor
598
+ {
599
+ public:
600
+ void operator() (
601
+ const T& source,
602
+ T& destination
603
+ ) const
604
+ {
605
+ destination = source;
606
+ }
607
+ };
608
+
609
+ // ----------------------------------------------------------------------------------------
610
+
611
+ /*!A static_switch
612
+
613
+ To use this template you give it some number of boolean expressions and it
614
+ tells you which one of them is true. If more than one of them is true then
615
+ it causes a compile time error.
616
+
617
+ for example:
618
+ static_switch<1 + 1 == 2, 4 - 1 == 4>::value == 1 // because the first expression is true
619
+ static_switch<1 + 1 == 3, 4 == 4>::value == 2 // because the second expression is true
620
+ static_switch<1 + 1 == 3, 4 == 5>::value == 0 // 0 here because none of them are true
621
+ static_switch<1 + 1 == 2, 4 == 4>::value == compiler error // because more than one expression is true
622
+ !*/
623
+
624
+ template < bool v1 = 0, bool v2 = 0, bool v3 = 0, bool v4 = 0, bool v5 = 0,
625
+ bool v6 = 0, bool v7 = 0, bool v8 = 0, bool v9 = 0, bool v10 = 0,
626
+ bool v11 = 0, bool v12 = 0, bool v13 = 0, bool v14 = 0, bool v15 = 0 >
627
+ struct static_switch;
628
+
629
+ template <> struct static_switch<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0> { const static int value = 0; };
630
+ template <> struct static_switch<1,0,0,0,0,0,0,0,0,0,0,0,0,0,0> { const static int value = 1; };
631
+ template <> struct static_switch<0,1,0,0,0,0,0,0,0,0,0,0,0,0,0> { const static int value = 2; };
632
+ template <> struct static_switch<0,0,1,0,0,0,0,0,0,0,0,0,0,0,0> { const static int value = 3; };
633
+ template <> struct static_switch<0,0,0,1,0,0,0,0,0,0,0,0,0,0,0> { const static int value = 4; };
634
+ template <> struct static_switch<0,0,0,0,1,0,0,0,0,0,0,0,0,0,0> { const static int value = 5; };
635
+ template <> struct static_switch<0,0,0,0,0,1,0,0,0,0,0,0,0,0,0> { const static int value = 6; };
636
+ template <> struct static_switch<0,0,0,0,0,0,1,0,0,0,0,0,0,0,0> { const static int value = 7; };
637
+ template <> struct static_switch<0,0,0,0,0,0,0,1,0,0,0,0,0,0,0> { const static int value = 8; };
638
+ template <> struct static_switch<0,0,0,0,0,0,0,0,1,0,0,0,0,0,0> { const static int value = 9; };
639
+ template <> struct static_switch<0,0,0,0,0,0,0,0,0,1,0,0,0,0,0> { const static int value = 10; };
640
+ template <> struct static_switch<0,0,0,0,0,0,0,0,0,0,1,0,0,0,0> { const static int value = 11; };
641
+ template <> struct static_switch<0,0,0,0,0,0,0,0,0,0,0,1,0,0,0> { const static int value = 12; };
642
+ template <> struct static_switch<0,0,0,0,0,0,0,0,0,0,0,0,1,0,0> { const static int value = 13; };
643
+ template <> struct static_switch<0,0,0,0,0,0,0,0,0,0,0,0,0,1,0> { const static int value = 14; };
644
+ template <> struct static_switch<0,0,0,0,0,0,0,0,0,0,0,0,0,0,1> { const static int value = 15; };
645
+
646
+ // ----------------------------------------------------------------------------------------
647
+ /*!A is_built_in_scalar_type
648
+
649
+ This is a template that allows you to determine if the given type is a built
650
+ in scalar type such as an int, char, float, short, etc.
651
+
652
+ For example, is_built_in_scalar_type<char>::value == true
653
+ For example, is_built_in_scalar_type<std::string>::value == false
654
+ !*/
655
+
656
+ template <typename T> struct is_built_in_scalar_type { const static bool value = false; };
657
+
658
+ template <> struct is_built_in_scalar_type<float> { const static bool value = true; };
659
+ template <> struct is_built_in_scalar_type<double> { const static bool value = true; };
660
+ template <> struct is_built_in_scalar_type<long double> { const static bool value = true; };
661
+ template <> struct is_built_in_scalar_type<short> { const static bool value = true; };
662
+ template <> struct is_built_in_scalar_type<int> { const static bool value = true; };
663
+ template <> struct is_built_in_scalar_type<long> { const static bool value = true; };
664
+ template <> struct is_built_in_scalar_type<unsigned short> { const static bool value = true; };
665
+ template <> struct is_built_in_scalar_type<unsigned int> { const static bool value = true; };
666
+ template <> struct is_built_in_scalar_type<unsigned long> { const static bool value = true; };
667
+ template <> struct is_built_in_scalar_type<uint64> { const static bool value = true; };
668
+ template <> struct is_built_in_scalar_type<int64> { const static bool value = true; };
669
+ template <> struct is_built_in_scalar_type<char> { const static bool value = true; };
670
+ template <> struct is_built_in_scalar_type<signed char> { const static bool value = true; };
671
+ template <> struct is_built_in_scalar_type<unsigned char> { const static bool value = true; };
672
+ // Don't define one for wchar_t when using a version of visual studio
673
+ // older than 8.0 (visual studio 2005) since before then they improperly set
674
+ // wchar_t to be a typedef rather than its own type as required by the C++
675
+ // standard.
676
+ #if !defined(_MSC_VER) || _NATIVE_WCHAR_T_DEFINED
677
+ template <> struct is_built_in_scalar_type<wchar_t> { const static bool value = true; };
678
+ #endif
679
+
680
+ // ----------------------------------------------------------------------------------------
681
+
682
+ template <
683
+ typename T
684
+ >
685
+ typename enable_if<is_built_in_scalar_type<T>,bool>::type is_finite (
686
+ const T& value
687
+ )
688
+ /*!
689
+ requires
690
+ - value must be some kind of scalar type such as int or double
691
+ ensures
692
+ - returns true if value is a finite value (e.g. not infinity or NaN) and false
693
+ otherwise.
694
+ !*/
695
+ {
696
+ if (is_float_type<T>::value)
697
+ return -std::numeric_limits<T>::infinity() < value && value < std::numeric_limits<T>::infinity();
698
+ else
699
+ return true;
700
+ }
701
+
702
+ // ----------------------------------------------------------------------------------------
703
+
704
+ /*!A promote
705
+
706
+ This is a template that takes one of the built in scalar types and gives you another
707
+ scalar type that should be big enough to hold sums of values from the original scalar
708
+ type. The new scalar type will also always be signed.
709
+
710
+ For example, promote<uint16>::type == int32
711
+ !*/
712
+
713
+ template <typename T, size_t s = sizeof(T)> struct promote;
714
+ template <typename T> struct promote<T,1> { typedef int32 type; };
715
+ template <typename T> struct promote<T,2> { typedef int32 type; };
716
+ template <typename T> struct promote<T,4> { typedef int64 type; };
717
+ template <typename T> struct promote<T,8> { typedef int64 type; };
718
+
719
+ template <> struct promote<float,sizeof(float)> { typedef double type; };
720
+ template <> struct promote<double,sizeof(double)> { typedef double type; };
721
+ template <> struct promote<long double,sizeof(long double)> { typedef long double type; };
722
+
723
+ // ----------------------------------------------------------------------------------------
724
+
725
+ /*!A assign_zero_if_built_in_scalar_type
726
+
727
+ This function assigns its argument the value of 0 if it is a built in scalar
728
+ type according to the is_built_in_scalar_type<> template. If it isn't a
729
+ built in scalar type then it does nothing.
730
+ !*/
731
+
732
+ template <typename T> inline typename disable_if<is_built_in_scalar_type<T>,void>::type assign_zero_if_built_in_scalar_type (T&){}
733
+ 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;}
734
+
735
+ // ----------------------------------------------------------------------------------------
736
+
737
+ /*!A basic_type
738
+
739
+ This is a template that takes a type and strips off any const, volatile, or reference
740
+ qualifiers and gives you back the basic underlying type. So for example:
741
+
742
+ basic_type<const int&>::type == int
743
+ !*/
744
+
745
+ template <typename T> struct basic_type { typedef T type; };
746
+ template <typename T> struct basic_type<const T> { typedef T type; };
747
+ template <typename T> struct basic_type<const T&> { typedef T type; };
748
+ template <typename T> struct basic_type<volatile const T&> { typedef T type; };
749
+ template <typename T> struct basic_type<T&> { typedef T type; };
750
+ template <typename T> struct basic_type<volatile T&> { typedef T type; };
751
+ template <typename T> struct basic_type<volatile T> { typedef T type; };
752
+ template <typename T> struct basic_type<volatile const T> { typedef T type; };
753
+
754
+ // ----------------------------------------------------------------------------------------
755
+
756
+ template <typename T>
757
+ T put_in_range (
758
+ const T& a,
759
+ const T& b,
760
+ const T& val
761
+ )
762
+ /*!
763
+ requires
764
+ - T is a type that looks like double, float, int, or so forth
765
+ ensures
766
+ - if (val is within the range [a,b]) then
767
+ - returns val
768
+ - else
769
+ - returns the end of the range [a,b] that is closest to val
770
+ !*/
771
+ {
772
+ if (a < b)
773
+ {
774
+ if (val < a)
775
+ return a;
776
+ else if (val > b)
777
+ return b;
778
+ }
779
+ else
780
+ {
781
+ if (val < b)
782
+ return b;
783
+ else if (val > a)
784
+ return a;
785
+ }
786
+
787
+ return val;
788
+ }
789
+
790
+ // overload for double
791
+ inline double put_in_range(const double& a, const double& b, const double& val)
792
+ { return put_in_range<double>(a,b,val); }
793
+
794
+ // ----------------------------------------------------------------------------------------
795
+
796
+ /*!A tabs
797
+
798
+ This is a template to compute the absolute value a number at compile time.
799
+
800
+ For example,
801
+ abs<-4>::value == 4
802
+ abs<4>::value == 4
803
+ !*/
804
+
805
+ template <long x, typename enabled=void>
806
+ struct tabs { const static long value = x; };
807
+ template <long x>
808
+ struct tabs<x,typename enable_if_c<(x < 0)>::type> { const static long value = -x; };
809
+
810
+ // ----------------------------------------------------------------------------------------
811
+
812
+ /*!A tmax
813
+
814
+ This is a template to compute the max of two values at compile time
815
+
816
+ For example,
817
+ abs<4,7>::value == 7
818
+ !*/
819
+
820
+ template <long x, long y, typename enabled=void>
821
+ struct tmax { const static long value = x; };
822
+ template <long x, long y>
823
+ struct tmax<x,y,typename enable_if_c<(y > x)>::type> { const static long value = y; };
824
+
825
+ // ----------------------------------------------------------------------------------------
826
+
827
+ /*!A tmin
828
+
829
+ This is a template to compute the min of two values at compile time
830
+
831
+ For example,
832
+ abs<4,7>::value == 4
833
+ !*/
834
+
835
+ template <long x, long y, typename enabled=void>
836
+ struct tmin { const static long value = x; };
837
+ template <long x, long y>
838
+ struct tmin<x,y,typename enable_if_c<(y < x)>::type> { const static long value = y; };
839
+
840
+ // ----------------------------------------------------------------------------------------
841
+
842
+ #define DLIB_MAKE_HAS_MEMBER_FUNCTION_TEST(testname, returnT, funct_name, args) \
843
+ struct _two_bytes_##testname { char a[2]; }; \
844
+ template < typename T, returnT (T::*funct)args > \
845
+ struct _helper_##testname { typedef char type; }; \
846
+ template <typename T> \
847
+ static char _has_##testname##_helper( typename _helper_##testname<T,&T::funct_name >::type ) { return 0;} \
848
+ template <typename T> \
849
+ static _two_bytes_##testname _has_##testname##_helper(int) { return _two_bytes_##testname();} \
850
+ template <typename T> struct _##testname##workaroundbug { \
851
+ const static unsigned long U = sizeof(_has_##testname##_helper<T>('a')); }; \
852
+ template <typename T, unsigned long U = _##testname##workaroundbug<T>::U > \
853
+ struct testname { static const bool value = false; }; \
854
+ template <typename T> \
855
+ struct testname<T,1> { static const bool value = true; };
856
+ /*!A DLIB_MAKE_HAS_MEMBER_FUNCTION_TEST
857
+
858
+ The DLIB_MAKE_HAS_MEMBER_FUNCTION_TEST() macro is used to define traits templates
859
+ that tell you if a class has a certain member function. For example, to make a
860
+ test to see if a class has a public method with the signature void print(int) you
861
+ would say:
862
+ DLIB_MAKE_HAS_MEMBER_FUNCTION_TEST(has_print, void, print, (int))
863
+
864
+ Then you can check if a class, T, has this method by looking at the boolean value:
865
+ has_print<T>::value
866
+ which will be true if the member function is in the T class.
867
+
868
+ Note that you can test for member functions taking no arguments by simply passing
869
+ in empty () like so:
870
+ DLIB_MAKE_HAS_MEMBER_FUNCTION_TEST(has_print, void, print, ())
871
+ This would test for a member of the form:
872
+ void print().
873
+
874
+ To test for const member functions you would use a statement such as this:
875
+ DLIB_MAKE_HAS_MEMBER_FUNCTION_TEST(has_print, void, print, ()const)
876
+ This would test for a member of the form:
877
+ void print() const.
878
+
879
+ To test for const templated member functions you would use a statement such as this:
880
+ DLIB_MAKE_HAS_MEMBER_FUNCTION_TEST(has_print, void, template print<int>, ())
881
+ This would test for a member of the form:
882
+ template <typename T> void print().
883
+ !*/
884
+
885
+ // ----------------------------------------------------------------------------------------
886
+
887
+ /*!A is_function
888
+
889
+ This is a template that allows you to determine if the given type is a function.
890
+
891
+ For example,
892
+ void funct();
893
+
894
+ is_built_in_scalar_type<funct>::value == true
895
+ is_built_in_scalar_type<int>::value == false
896
+ !*/
897
+
898
+ template <typename T> struct is_function { static const bool value = false; };
899
+ template <typename T>
900
+ struct is_function<T (void)> { static const bool value = true; };
901
+ template <typename T, typename A0>
902
+ struct is_function<T (A0)> { static const bool value = true; };
903
+ template <typename T, typename A0, typename A1>
904
+ struct is_function<T (A0, A1)> { static const bool value = true; };
905
+ template <typename T, typename A0, typename A1, typename A2>
906
+ struct is_function<T (A0, A1, A2)> { static const bool value = true; };
907
+ template <typename T, typename A0, typename A1, typename A2, typename A3>
908
+ struct is_function<T (A0, A1, A2, A3)> { static const bool value = true; };
909
+ template <typename T, typename A0, typename A1, typename A2, typename A3, typename A4>
910
+ struct is_function<T (A0, A1, A2, A3, A4)> { static const bool value = true; };
911
+ template <typename T, typename A0, typename A1, typename A2, typename A3, typename A4,
912
+ typename A5>
913
+ struct is_function<T (A0,A1,A2,A3,A4,A5)> { static const bool value = true; };
914
+ template <typename T, typename A0, typename A1, typename A2, typename A3, typename A4,
915
+ typename A5, typename A6>
916
+ struct is_function<T (A0,A1,A2,A3,A4,A5,A6)> { static const bool value = true; };
917
+ template <typename T, typename A0, typename A1, typename A2, typename A3, typename A4,
918
+ typename A5, typename A6, typename A7>
919
+ struct is_function<T (A0,A1,A2,A3,A4,A5,A6,A7)> { static const bool value = true; };
920
+ template <typename T, typename A0, typename A1, typename A2, typename A3, typename A4,
921
+ typename A5, typename A6, typename A7, typename A8>
922
+ struct is_function<T (A0,A1,A2,A3,A4,A5,A6,A7,A8)> { static const bool value = true; };
923
+ template <typename T, typename A0, typename A1, typename A2, typename A3, typename A4,
924
+ typename A5, typename A6, typename A7, typename A8, typename A9>
925
+ struct is_function<T (A0,A1,A2,A3,A4,A5,A6,A7,A8,A9)> { static const bool value = true; };
926
+
927
+
928
+ template <typename T> class funct_wrap0
929
+ {
930
+ public:
931
+ funct_wrap0(T (&f_)()):f(f_){}
932
+ T operator()() const { return f(); }
933
+ private:
934
+ T (&f)();
935
+ };
936
+ template <typename T, typename A0> class funct_wrap1
937
+ {
938
+ public:
939
+ funct_wrap1(T (&f_)(A0)):f(f_){}
940
+ T operator()(A0 a0) const { return f(a0); }
941
+ private:
942
+ T (&f)(A0);
943
+ };
944
+ template <typename T, typename A0, typename A1> class funct_wrap2
945
+ {
946
+ public:
947
+ funct_wrap2(T (&f_)(A0,A1)):f(f_){}
948
+ T operator()(A0 a0, A1 a1) const { return f(a0,a1); }
949
+ private:
950
+ T (&f)(A0,A1);
951
+ };
952
+ template <typename T, typename A0, typename A1, typename A2> class funct_wrap3
953
+ {
954
+ public:
955
+ funct_wrap3(T (&f_)(A0,A1,A2)):f(f_){}
956
+ T operator()(A0 a0, A1 a1, A2 a2) const { return f(a0,a1,a2); }
957
+ private:
958
+ T (&f)(A0,A1,A2);
959
+ };
960
+ template <typename T, typename A0, typename A1, typename A2, typename A3> class funct_wrap4
961
+ {
962
+ public:
963
+ funct_wrap4(T (&f_)(A0,A1,A2,A3)):f(f_){}
964
+ T operator()(A0 a0, A1 a1, A2 a2, A3 a3) const { return f(a0,a1,a2,a3); }
965
+ private:
966
+ T (&f)(A0,A1,A2,A3);
967
+ };
968
+ template <typename T, typename A0, typename A1, typename A2, typename A3, typename A4> class funct_wrap5
969
+ {
970
+ public:
971
+ funct_wrap5(T (&f_)(A0,A1,A2,A3,A4)):f(f_){}
972
+ T operator()(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) const { return f(a0,a1,a2,a3,a4); }
973
+ private:
974
+ T (&f)(A0,A1,A2,A3,A4);
975
+ };
976
+
977
+ /*!A wrap_function
978
+
979
+ This is a template that allows you to turn a global function into a
980
+ function object. The reason for this template's existence is so you can
981
+ do stuff like this:
982
+
983
+ template <typename T>
984
+ void call_funct(const T& funct)
985
+ { cout << funct(); }
986
+
987
+ std::string test() { return "asdfasf"; }
988
+
989
+ int main()
990
+ {
991
+ call_funct(wrap_function(test));
992
+ }
993
+
994
+ The above code doesn't work right on some compilers if you don't
995
+ use wrap_function.
996
+ !*/
997
+
998
+ template <typename T>
999
+ funct_wrap0<T> wrap_function(T (&f)()) { return funct_wrap0<T>(f); }
1000
+ template <typename T, typename A0>
1001
+ funct_wrap1<T,A0> wrap_function(T (&f)(A0)) { return funct_wrap1<T,A0>(f); }
1002
+ template <typename T, typename A0, typename A1>
1003
+ funct_wrap2<T,A0,A1> wrap_function(T (&f)(A0, A1)) { return funct_wrap2<T,A0,A1>(f); }
1004
+ template <typename T, typename A0, typename A1, typename A2>
1005
+ funct_wrap3<T,A0,A1,A2> wrap_function(T (&f)(A0, A1, A2)) { return funct_wrap3<T,A0,A1,A2>(f); }
1006
+ template <typename T, typename A0, typename A1, typename A2, typename A3>
1007
+ funct_wrap4<T,A0,A1,A2,A3> wrap_function(T (&f)(A0, A1, A2, A3)) { return funct_wrap4<T,A0,A1,A2,A3>(f); }
1008
+ template <typename T, typename A0, typename A1, typename A2, typename A3, typename A4>
1009
+ 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); }
1010
+
1011
+ // ----------------------------------------------------------------------------------------
1012
+
1013
+ template <unsigned long bSIZE>
1014
+ class stack_based_memory_block : noncopyable
1015
+ {
1016
+ /*!
1017
+ WHAT THIS OBJECT REPRESENTS
1018
+ This object is a simple container for a block of memory
1019
+ of bSIZE bytes. This memory block is located on the stack
1020
+ and properly aligned to hold any kind of object.
1021
+ !*/
1022
+ public:
1023
+ static const unsigned long size = bSIZE;
1024
+
1025
+ stack_based_memory_block(): data(mem.data) {}
1026
+
1027
+ void* get () { return data; }
1028
+ /*!
1029
+ ensures
1030
+ - returns a pointer to the block of memory contained in this object
1031
+ !*/
1032
+
1033
+ const void* get () const { return data; }
1034
+ /*!
1035
+ ensures
1036
+ - returns a pointer to the block of memory contained in this object
1037
+ !*/
1038
+
1039
+ private:
1040
+
1041
+ // You obviously can't have a block of memory that has zero bytes in it.
1042
+ COMPILE_TIME_ASSERT(bSIZE > 0);
1043
+
1044
+ union mem_block
1045
+ {
1046
+ // All of this garbage is to make sure this union is properly aligned
1047
+ // (a union is always aligned such that everything in it would be properly
1048
+ // aligned. So the assumption here is that one of these objects has
1049
+ // a large enough alignment requirement to satisfy any object this
1050
+ // block of memory might be cast into).
1051
+ void* void_ptr;
1052
+ int integer;
1053
+ struct {
1054
+ void (stack_based_memory_block::*callback)();
1055
+ stack_based_memory_block* o;
1056
+ } stuff;
1057
+ long double more_stuff;
1058
+
1059
+ uint64 var1;
1060
+ uint32 var2;
1061
+ double var3;
1062
+
1063
+ char data[size];
1064
+ } mem;
1065
+
1066
+ // The reason for having this variable is that doing it this way avoids
1067
+ // warnings from gcc about violations of strict-aliasing rules.
1068
+ void* const data;
1069
+ };
1070
+
1071
+ // ----------------------------------------------------------------------------------------
1072
+
1073
+ template <
1074
+ typename T,
1075
+ typename F
1076
+ >
1077
+ auto max_scoring_element(
1078
+ const T& container,
1079
+ F score_func
1080
+ ) -> decltype(std::make_pair(*container.begin(), 0.0))
1081
+ /*!
1082
+ requires
1083
+ - container has .begin() and .end(), allowing it to be enumerated.
1084
+ - score_func() is a function that takes an element of the container and returns a double.
1085
+ ensures
1086
+ - This function finds the element of container that has the largest score,
1087
+ according to score_func(), and returns a std::pair containing that maximal
1088
+ element along with the score.
1089
+ - If the container is empty then make_pair(a default initialized object, -infinity) is returned.
1090
+ !*/
1091
+ {
1092
+ double best_score = -std::numeric_limits<double>::infinity();
1093
+ auto best_i = container.begin();
1094
+ for (auto i = container.begin(); i != container.end(); ++i)
1095
+ {
1096
+ auto score = score_func(*i);
1097
+ if (score > best_score)
1098
+ {
1099
+ best_score = score;
1100
+ best_i = i;
1101
+ }
1102
+ }
1103
+
1104
+ using item_type = typename std::remove_reference<decltype(*best_i)>::type;
1105
+
1106
+ if (best_i == container.end())
1107
+ return std::make_pair(item_type(), best_score);
1108
+ else
1109
+ return std::make_pair(*best_i, best_score);
1110
+ }
1111
+
1112
+ // ----------------------------------------------------------------------------------------
1113
+
1114
+ template <
1115
+ typename T,
1116
+ typename F
1117
+ >
1118
+ auto min_scoring_element(
1119
+ const T& container,
1120
+ F score_func
1121
+ ) -> decltype(std::make_pair(*container.begin(), 0.0))
1122
+ /*!
1123
+ requires
1124
+ - container has .begin() and .end(), allowing it to be enumerated.
1125
+ - score_func() is a function that takes an element of the container and returns a double.
1126
+ ensures
1127
+ - This function finds the element of container that has the smallest score,
1128
+ according to score_func(), and returns a std::pair containing that minimal
1129
+ element along with the score.
1130
+ - If the container is empty then make_pair(a default initialized object, infinity) is returned.
1131
+ !*/
1132
+ {
1133
+ double best_score = std::numeric_limits<double>::infinity();
1134
+ auto best_i = container.begin();
1135
+ for (auto i = container.begin(); i != container.end(); ++i)
1136
+ {
1137
+ auto score = score_func(*i);
1138
+ if (score < best_score)
1139
+ {
1140
+ best_score = score;
1141
+ best_i = i;
1142
+ }
1143
+ }
1144
+
1145
+ using item_type = typename std::remove_reference<decltype(*best_i)>::type;
1146
+
1147
+ if (best_i == container.end())
1148
+ return std::make_pair(item_type(), best_score);
1149
+ else
1150
+ return std::make_pair(*best_i, best_score);
1151
+ }
1152
+
1153
+ // ----------------------------------------------------------------------------------------
1154
+
1155
+ }
1156
+
1157
+ #endif // DLIB_ALGs_
1158
+
dlibs/dlib/all/source.cpp ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (C) 2006 Davis E. King ([email protected])
2
+ // License: Boost Software License See LICENSE.txt for the full license.
3
+ #ifndef DLIB_ALL_SOURCe_
4
+ #define DLIB_ALL_SOURCe_
5
+
6
+ #if defined(DLIB_ALGs_) || defined(DLIB_PLATFORm_)
7
+ #include "../dlib_basic_cpp_build_tutorial.txt"
8
+ #endif
9
+
10
+ // ISO C++ code
11
+ #include "../base64/base64_kernel_1.cpp"
12
+ #include "../bigint/bigint_kernel_1.cpp"
13
+ #include "../bigint/bigint_kernel_2.cpp"
14
+ #include "../bit_stream/bit_stream_kernel_1.cpp"
15
+ #include "../entropy_decoder/entropy_decoder_kernel_1.cpp"
16
+ #include "../entropy_decoder/entropy_decoder_kernel_2.cpp"
17
+ #include "../entropy_encoder/entropy_encoder_kernel_1.cpp"
18
+ #include "../entropy_encoder/entropy_encoder_kernel_2.cpp"
19
+ #include "../md5/md5_kernel_1.cpp"
20
+ #include "../tokenizer/tokenizer_kernel_1.cpp"
21
+ #include "../unicode/unicode.cpp"
22
+ #include "../test_for_odr_violations.cpp"
23
+
24
+
25
+
26
+
27
+ #ifndef DLIB_ISO_CPP_ONLY
28
+ // Code that depends on OS specific APIs
29
+
30
+ // include this first so that it can disable the older version
31
+ // of the winsock API when compiled in windows.
32
+ #include "../sockets/sockets_kernel_1.cpp"
33
+ #include "../bsp/bsp.cpp"
34
+
35
+ #include "../dir_nav/dir_nav_kernel_1.cpp"
36
+ #include "../dir_nav/dir_nav_kernel_2.cpp"
37
+ #include "../dir_nav/dir_nav_extensions.cpp"
38
+ #include "../linker/linker_kernel_1.cpp"
39
+ #include "../logger/extra_logger_headers.cpp"
40
+ #include "../logger/logger_kernel_1.cpp"
41
+ #include "../logger/logger_config_file.cpp"
42
+ #include "../misc_api/misc_api_kernel_1.cpp"
43
+ #include "../misc_api/misc_api_kernel_2.cpp"
44
+ #include "../sockets/sockets_extensions.cpp"
45
+ #include "../sockets/sockets_kernel_2.cpp"
46
+ #include "../sockstreambuf/sockstreambuf.cpp"
47
+ #include "../sockstreambuf/sockstreambuf_unbuffered.cpp"
48
+ #include "../server/server_kernel.cpp"
49
+ #include "../server/server_iostream.cpp"
50
+ #include "../server/server_http.cpp"
51
+ #include "../threads/multithreaded_object_extension.cpp"
52
+ #include "../threads/threaded_object_extension.cpp"
53
+ #include "../threads/threads_kernel_1.cpp"
54
+ #include "../threads/threads_kernel_2.cpp"
55
+ #include "../threads/threads_kernel_shared.cpp"
56
+ #include "../threads/thread_pool_extension.cpp"
57
+ #include "../threads/async.cpp"
58
+ #include "../timer/timer.cpp"
59
+ #include "../stack_trace.cpp"
60
+
61
+ #ifdef DLIB_PNG_SUPPORT
62
+ #include "../image_loader/png_loader.cpp"
63
+ #include "../image_saver/save_png.cpp"
64
+ #endif
65
+
66
+ #ifdef DLIB_JPEG_SUPPORT
67
+ #include "../image_loader/jpeg_loader.cpp"
68
+ #include "../image_saver/save_jpeg.cpp"
69
+ #endif
70
+
71
+ #ifndef DLIB_NO_GUI_SUPPORT
72
+ #include "../gui_widgets/fonts.cpp"
73
+ #include "../gui_widgets/widgets.cpp"
74
+ #include "../gui_widgets/drawable.cpp"
75
+ #include "../gui_widgets/canvas_drawing.cpp"
76
+ #include "../gui_widgets/style.cpp"
77
+ #include "../gui_widgets/base_widgets.cpp"
78
+ #include "../gui_core/gui_core_kernel_1.cpp"
79
+ #include "../gui_core/gui_core_kernel_2.cpp"
80
+ #endif // DLIB_NO_GUI_SUPPORT
81
+
82
+ #include "../cuda/cpu_dlib.cpp"
83
+ #include "../cuda/tensor_tools.cpp"
84
+ #include "../data_io/image_dataset_metadata.cpp"
85
+ #include "../data_io/mnist.cpp"
86
+ #include "../data_io/cifar.cpp"
87
+ #include "../svm/auto.cpp"
88
+ #include "../global_optimization/global_function_search.cpp"
89
+ #include "../filtering/kalman_filter.cpp"
90
+
91
+ #endif // DLIB_ISO_CPP_ONLY
92
+
93
+
94
+
95
+
96
+
97
+ #define DLIB_ALL_SOURCE_END
98
+
99
+ #endif // DLIB_ALL_SOURCe_
100
+
dlibs/dlib/any.h ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (C) 2010 Davis E. King ([email protected])
2
+ // License: Boost Software License See LICENSE.txt for the full license.
3
+ #ifndef DLIB_AnY_
4
+ #define DLIB_AnY_
5
+
6
+ #include "any/any.h"
7
+ #include "any/any_trainer.h"
8
+ #include "any/any_decision_function.h"
9
+ #include "any/any_function.h"
10
+
11
+ #endif // DLIB_AnY_
12
+
13
+
dlibs/dlib/any/any.h ADDED
@@ -0,0 +1,183 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (C) 2010 Davis E. King ([email protected])
2
+ // License: Boost Software License See LICENSE.txt for the full license.
3
+ #ifndef DLIB_AnY_H_
4
+ #define DLIB_AnY_H_
5
+
6
+ #include "any_abstract.h"
7
+ #include "../algs.h"
8
+
9
+ #include <memory>
10
+ #include <typeinfo>
11
+
12
+ namespace dlib
13
+ {
14
+
15
+ // ----------------------------------------------------------------------------------------
16
+
17
+ class bad_any_cast : public std::bad_cast
18
+ {
19
+ public:
20
+ virtual const char * what() const throw()
21
+ {
22
+ return "bad_any_cast";
23
+ }
24
+ };
25
+
26
+ // ----------------------------------------------------------------------------------------
27
+
28
+ class any
29
+ {
30
+
31
+ public:
32
+
33
+ any()
34
+ {
35
+ }
36
+
37
+ any (
38
+ const any& item
39
+ )
40
+ {
41
+ if (item.data)
42
+ {
43
+ item.data->copy_to(data);
44
+ }
45
+ }
46
+
47
+ template <typename T>
48
+ any (
49
+ const T& item
50
+ )
51
+ {
52
+ typedef typename basic_type<T>::type U;
53
+ data.reset(new derived<U>(item));
54
+ }
55
+
56
+ void clear (
57
+ )
58
+ {
59
+ data.reset();
60
+ }
61
+
62
+ template <typename T>
63
+ bool contains (
64
+ ) const
65
+ {
66
+ typedef typename basic_type<T>::type U;
67
+ return dynamic_cast<derived<U>*>(data.get()) != 0;
68
+ }
69
+
70
+ bool is_empty(
71
+ ) const
72
+ {
73
+ return data.get() == 0;
74
+ }
75
+
76
+ template <typename T>
77
+ T& cast_to(
78
+ )
79
+ {
80
+ typedef typename basic_type<T>::type U;
81
+ derived<U>* d = dynamic_cast<derived<U>*>(data.get());
82
+ if (d == 0)
83
+ {
84
+ throw bad_any_cast();
85
+ }
86
+
87
+ return d->item;
88
+ }
89
+
90
+ template <typename T>
91
+ const T& cast_to(
92
+ ) const
93
+ {
94
+ typedef typename basic_type<T>::type U;
95
+ derived<U>* d = dynamic_cast<derived<U>*>(data.get());
96
+ if (d == 0)
97
+ {
98
+ throw bad_any_cast();
99
+ }
100
+
101
+ return d->item;
102
+ }
103
+
104
+ template <typename T>
105
+ T& get(
106
+ )
107
+ {
108
+ typedef typename basic_type<T>::type U;
109
+ derived<U>* d = dynamic_cast<derived<U>*>(data.get());
110
+ if (d == 0)
111
+ {
112
+ d = new derived<U>();
113
+ data.reset(d);
114
+ }
115
+
116
+ return d->item;
117
+ }
118
+
119
+ any& operator= (
120
+ const any& item
121
+ )
122
+ {
123
+ any(item).swap(*this);
124
+ return *this;
125
+ }
126
+
127
+ void swap (
128
+ any& item
129
+ )
130
+ {
131
+ data.swap(item.data);
132
+ }
133
+
134
+ private:
135
+
136
+ struct base
137
+ {
138
+ virtual ~base() {}
139
+
140
+ virtual void copy_to (
141
+ std::unique_ptr<base>& dest
142
+ ) const = 0;
143
+ };
144
+
145
+ template <typename T>
146
+ struct derived : public base
147
+ {
148
+ T item;
149
+ derived() {}
150
+ derived(const T& val) : item(val) {}
151
+
152
+ virtual void copy_to (
153
+ std::unique_ptr<base>& dest
154
+ ) const
155
+ {
156
+ dest.reset(new derived<T>(item));
157
+ }
158
+ };
159
+
160
+ std::unique_ptr<base> data;
161
+ };
162
+
163
+ // ----------------------------------------------------------------------------------------
164
+
165
+ inline void swap (
166
+ any& a,
167
+ any& b
168
+ ) { a.swap(b); }
169
+
170
+ // ----------------------------------------------------------------------------------------
171
+
172
+ template <typename T> T& any_cast(any& a) { return a.cast_to<T>(); }
173
+ template <typename T> const T& any_cast(const any& a) { return a.cast_to<T>(); }
174
+
175
+ // ----------------------------------------------------------------------------------------
176
+
177
+ }
178
+
179
+
180
+ #endif // DLIB_AnY_H_
181
+
182
+
183
+
dlibs/dlib/any/any_abstract.h ADDED
@@ -0,0 +1,210 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (C) 2010 Davis E. King ([email protected])
2
+ // License: Boost Software License See LICENSE.txt for the full license.
3
+ #undef DLIB_AnY_ABSTRACT_H_
4
+ #ifdef DLIB_AnY_ABSTRACT_H_
5
+
6
+ #include <typeinfo>
7
+
8
+ namespace dlib
9
+ {
10
+
11
+ // ----------------------------------------------------------------------------------------
12
+
13
+ class bad_any_cast : public std::bad_cast
14
+ {
15
+ /*!
16
+ WHAT THIS OBJECT REPRESENTS
17
+ This object is the exception class used by the any object.
18
+ It is used to indicate when someone attempts to cast an any
19
+ object into a type which isn't contained in the any object.
20
+ !*/
21
+
22
+ public:
23
+ virtual const char* what() const throw() { return "bad_any_cast"; }
24
+ };
25
+
26
+ // ----------------------------------------------------------------------------------------
27
+
28
+ class any
29
+ {
30
+ /*!
31
+ INITIAL VALUE
32
+ - is_empty() == true
33
+ - for all T: contains<T>() == false
34
+
35
+ WHAT THIS OBJECT REPRESENTS
36
+ This object is basically a type-safe version of a void*. In particular,
37
+ it is a container which can contain only one object but the object may
38
+ be of any type.
39
+
40
+ It is somewhat like the type_safe_union except you don't have to declare
41
+ the set of possible content types beforehand. So in some sense this is
42
+ like a less type-strict version of the type_safe_union.
43
+ !*/
44
+
45
+ public:
46
+
47
+ any(
48
+ );
49
+ /*!
50
+ ensures
51
+ - this object is properly initialized
52
+ !*/
53
+
54
+ any (
55
+ const any& item
56
+ );
57
+ /*!
58
+ ensures
59
+ - copies the state of item into *this.
60
+ - Note that *this and item will contain independent copies of the
61
+ contents of item. That is, this function performs a deep
62
+ copy and therefore does not result in *this containing
63
+ any kind of reference to item.
64
+ !*/
65
+
66
+ template < typename T >
67
+ any (
68
+ const T& item
69
+ );
70
+ /*!
71
+ ensures
72
+ - #contains<T>() == true
73
+ - #cast_to<T>() == item
74
+ (i.e. a copy of item will be stored in *this)
75
+ !*/
76
+
77
+ void clear (
78
+ );
79
+ /*!
80
+ ensures
81
+ - #*this will have its default value. I.e. #is_empty() == true
82
+ !*/
83
+
84
+ template <typename T>
85
+ bool contains (
86
+ ) const;
87
+ /*!
88
+ ensures
89
+ - if (this object currently contains an object of type T) then
90
+ - returns true
91
+ - else
92
+ - returns false
93
+ !*/
94
+
95
+ bool is_empty(
96
+ ) const;
97
+ /*!
98
+ ensures
99
+ - if (this object contains any kind of object) then
100
+ - returns false
101
+ - else
102
+ - returns true
103
+ !*/
104
+
105
+ template <typename T>
106
+ T& cast_to(
107
+ );
108
+ /*!
109
+ ensures
110
+ - if (contains<T>() == true) then
111
+ - returns a non-const reference to the object contained within *this
112
+ - else
113
+ - throws bad_any_cast
114
+ !*/
115
+
116
+ template <typename T>
117
+ const T& cast_to(
118
+ ) const;
119
+ /*!
120
+ ensures
121
+ - if (contains<T>() == true) then
122
+ - returns a const reference to the object contained within *this
123
+ - else
124
+ - throws bad_any_cast
125
+ !*/
126
+
127
+ template <typename T>
128
+ T& get(
129
+ );
130
+ /*!
131
+ ensures
132
+ - #is_empty() == false
133
+ - #contains<T>() == true
134
+ - if (contains<T>() == true)
135
+ - returns a non-const reference to the object contained in *this.
136
+ - else
137
+ - Constructs an object of type T inside *this
138
+ - Any previous object stored in this any object is destructed and its
139
+ state is lost.
140
+ - returns a non-const reference to the newly created T object.
141
+ !*/
142
+
143
+ any& operator= (
144
+ const any& item
145
+ );
146
+ /*!
147
+ ensures
148
+ - copies the state of item into *this.
149
+ - Note that *this and item will contain independent copies of the
150
+ contents of item. That is, this function performs a deep
151
+ copy and therefore does not result in *this containing
152
+ any kind of reference to item.
153
+ !*/
154
+
155
+ void swap (
156
+ any& item
157
+ );
158
+ /*!
159
+ ensures
160
+ - swaps *this and item
161
+ - does not invalidate pointers or references to the object contained
162
+ inside *this or item. Moreover, a pointer or reference to the object in
163
+ *this will now refer to the contents of #item and vice versa.
164
+ !*/
165
+
166
+ };
167
+
168
+ // ----------------------------------------------------------------------------------------
169
+
170
+ inline void swap (
171
+ any& a,
172
+ any& b
173
+ ) { a.swap(b); }
174
+ /*!
175
+ provides a global swap function
176
+ !*/
177
+
178
+ // ----------------------------------------------------------------------------------------
179
+
180
+ template <
181
+ typename T
182
+ >
183
+ T& any_cast(
184
+ any& a
185
+ ) { return a.cast_to<T>(); }
186
+ /*!
187
+ ensures
188
+ - returns a.cast_to<T>()
189
+ !*/
190
+
191
+ // ----------------------------------------------------------------------------------------
192
+
193
+ template <
194
+ typename T
195
+ >
196
+ const T& any_cast(
197
+ const any& a
198
+ ) { return a.cast_to<T>(); }
199
+ /*!
200
+ ensures
201
+ - returns a.cast_to<T>()
202
+ !*/
203
+
204
+ // ----------------------------------------------------------------------------------------
205
+
206
+ }
207
+
208
+ #endif // DLIB_AnY_ABSTRACT_H_
209
+
210
+
dlibs/dlib/any/any_decision_function.h ADDED
@@ -0,0 +1,209 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (C) 2010 Davis E. King ([email protected])
2
+ // License: Boost Software License See LICENSE.txt for the full license.
3
+ #ifndef DLIB_AnY_DECISION_FUNCTION_Hh_
4
+ #define DLIB_AnY_DECISION_FUNCTION_Hh_
5
+
6
+ #include "any.h"
7
+
8
+ #include "any_decision_function_abstract.h"
9
+
10
+ namespace dlib
11
+ {
12
+
13
+ // ----------------------------------------------------------------------------------------
14
+
15
+ template <
16
+ typename sample_type_,
17
+ typename result_type_ = double
18
+ >
19
+ class any_decision_function
20
+ {
21
+
22
+ public:
23
+
24
+ typedef sample_type_ sample_type;
25
+ typedef result_type_ result_type;
26
+ typedef default_memory_manager mem_manager_type;
27
+
28
+ any_decision_function()
29
+ {
30
+ }
31
+
32
+ any_decision_function (
33
+ const any_decision_function& item
34
+ )
35
+ {
36
+ if (item.data)
37
+ {
38
+ item.data->copy_to(data);
39
+ }
40
+ }
41
+
42
+ template <typename T>
43
+ any_decision_function (
44
+ const T& item
45
+ )
46
+ {
47
+ typedef typename basic_type<T>::type U;
48
+ data.reset(new derived<U>(item));
49
+ }
50
+
51
+ void clear (
52
+ )
53
+ {
54
+ data.reset();
55
+ }
56
+
57
+ template <typename T>
58
+ bool contains (
59
+ ) const
60
+ {
61
+ typedef typename basic_type<T>::type U;
62
+ return dynamic_cast<derived<U>*>(data.get()) != 0;
63
+ }
64
+
65
+ bool is_empty(
66
+ ) const
67
+ {
68
+ return data.get() == 0;
69
+ }
70
+
71
+ result_type operator() (
72
+ const sample_type& item
73
+ ) const
74
+ {
75
+ // make sure requires clause is not broken
76
+ DLIB_ASSERT(is_empty() == false,
77
+ "\t result_type any_decision_function::operator()"
78
+ << "\n\t You can't call operator() on an empty any_decision_function"
79
+ << "\n\t this: " << this
80
+ );
81
+
82
+ return data->evaluate(item);
83
+ }
84
+
85
+ template <typename T>
86
+ T& cast_to(
87
+ )
88
+ {
89
+ typedef typename basic_type<T>::type U;
90
+ derived<U>* d = dynamic_cast<derived<U>*>(data.get());
91
+ if (d == 0)
92
+ {
93
+ throw bad_any_cast();
94
+ }
95
+
96
+ return d->item;
97
+ }
98
+
99
+ template <typename T>
100
+ const T& cast_to(
101
+ ) const
102
+ {
103
+ typedef typename basic_type<T>::type U;
104
+ derived<U>* d = dynamic_cast<derived<U>*>(data.get());
105
+ if (d == 0)
106
+ {
107
+ throw bad_any_cast();
108
+ }
109
+
110
+ return d->item;
111
+ }
112
+
113
+ template <typename T>
114
+ T& get(
115
+ )
116
+ {
117
+ typedef typename basic_type<T>::type U;
118
+ derived<U>* d = dynamic_cast<derived<U>*>(data.get());
119
+ if (d == 0)
120
+ {
121
+ d = new derived<U>();
122
+ data.reset(d);
123
+ }
124
+
125
+ return d->item;
126
+ }
127
+
128
+ any_decision_function& operator= (
129
+ const any_decision_function& item
130
+ )
131
+ {
132
+ any_decision_function(item).swap(*this);
133
+ return *this;
134
+ }
135
+
136
+ void swap (
137
+ any_decision_function& item
138
+ )
139
+ {
140
+ data.swap(item.data);
141
+ }
142
+
143
+ private:
144
+
145
+ struct base
146
+ {
147
+ virtual ~base() {}
148
+
149
+ virtual void copy_to (
150
+ std::unique_ptr<base>& dest
151
+ ) const = 0;
152
+
153
+ virtual result_type evaluate (
154
+ const sample_type& samp
155
+ ) const = 0;
156
+ };
157
+
158
+ template <typename T>
159
+ struct derived : public base
160
+ {
161
+ T item;
162
+ derived() {}
163
+ derived(const T& val) : item(val) {}
164
+
165
+ virtual void copy_to (
166
+ std::unique_ptr<base>& dest
167
+ ) const
168
+ {
169
+ dest.reset(new derived<T>(item));
170
+ }
171
+
172
+ virtual result_type evaluate (
173
+ const sample_type& samp
174
+ ) const
175
+ {
176
+ return item(samp);
177
+ }
178
+ };
179
+
180
+ std::unique_ptr<base> data;
181
+ };
182
+
183
+ // ----------------------------------------------------------------------------------------
184
+
185
+ template <
186
+ typename sample_type,
187
+ typename result_type
188
+ >
189
+ inline void swap (
190
+ any_decision_function<sample_type, result_type>& a,
191
+ any_decision_function<sample_type, result_type>& b
192
+ ) { a.swap(b); }
193
+
194
+ // ----------------------------------------------------------------------------------------
195
+
196
+ template <typename T, typename U, typename V>
197
+ T& any_cast(any_decision_function<U,V>& a) { return a.template cast_to<T>(); }
198
+
199
+ template <typename T, typename U, typename V>
200
+ const T& any_cast(const any_decision_function<U,V>& a) { return a.template cast_to<T>(); }
201
+
202
+ // ----------------------------------------------------------------------------------------
203
+
204
+ }
205
+
206
+
207
+ #endif // DLIB_AnY_DECISION_FUNCTION_Hh_
208
+
209
+
dlibs/dlib/any/any_decision_function_abstract.h ADDED
@@ -0,0 +1,224 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (C) 2010 Davis E. King ([email protected])
2
+ // License: Boost Software License See LICENSE.txt for the full license.
3
+ #undef DLIB_AnY_DECISION_FUNCTION_ABSTRACT_H_
4
+ #ifdef DLIB_AnY_DECISION_FUNCTION_ABSTRACT_H_
5
+
6
+ #include "any_abstract.h"
7
+ #include "../algs.h"
8
+
9
+ namespace dlib
10
+ {
11
+
12
+ // ----------------------------------------------------------------------------------------
13
+
14
+ template <
15
+ typename sample_type_,
16
+ typename result_type_ = double
17
+ >
18
+ class any_decision_function
19
+ {
20
+ /*!
21
+ INITIAL VALUE
22
+ - is_empty() == true
23
+ - for all T: contains<T>() == false
24
+
25
+ WHAT THIS OBJECT REPRESENTS
26
+ This object is a version of dlib::any that is restricted to containing
27
+ elements which are some kind of function object with an operator() with
28
+ the following signature:
29
+ result_type operator()(const sample_type&) const
30
+
31
+ It is intended to be used to contain dlib::decision_function objects and
32
+ other types which represent learned decision functions. It allows you
33
+ to write code which contains and processes these decision functions
34
+ without needing to know the specific types of decision functions used.
35
+ !*/
36
+
37
+ public:
38
+
39
+ typedef sample_type_ sample_type;
40
+ typedef result_type_ result_type;
41
+ typedef default_memory_manager mem_manager_type;
42
+
43
+ any_decision_function(
44
+ );
45
+ /*!
46
+ ensures
47
+ - this object is properly initialized
48
+ !*/
49
+
50
+ any_decision_function (
51
+ const any_decision_function& item
52
+ );
53
+ /*!
54
+ ensures
55
+ - copies the state of item into *this.
56
+ - Note that *this and item will contain independent copies of the
57
+ contents of item. That is, this function performs a deep
58
+ copy and therefore does not result in *this containing
59
+ any kind of reference to item.
60
+ !*/
61
+
62
+ template < typename T >
63
+ any_decision_function (
64
+ const T& item
65
+ );
66
+ /*!
67
+ ensures
68
+ - #contains<T>() == true
69
+ - #cast_to<T>() == item
70
+ (i.e. a copy of item will be stored in *this)
71
+ !*/
72
+
73
+ void clear (
74
+ );
75
+ /*!
76
+ ensures
77
+ - #*this will have its default value. I.e. #is_empty() == true
78
+ !*/
79
+
80
+ template <typename T>
81
+ bool contains (
82
+ ) const;
83
+ /*!
84
+ ensures
85
+ - if (this object currently contains an object of type T) then
86
+ - returns true
87
+ - else
88
+ - returns false
89
+ !*/
90
+
91
+ bool is_empty(
92
+ ) const;
93
+ /*!
94
+ ensures
95
+ - if (this object contains any kind of object) then
96
+ - returns false
97
+ - else
98
+ - returns true
99
+ !*/
100
+
101
+ result_type operator() (
102
+ const sample_type& item
103
+ ) const;
104
+ /*!
105
+ requires
106
+ - is_empty() == false
107
+ ensures
108
+ - Let F denote the function object contained within *this. Then
109
+ this function performs:
110
+ return F(item)
111
+ !*/
112
+
113
+ template <typename T>
114
+ T& cast_to(
115
+ );
116
+ /*!
117
+ ensures
118
+ - if (contains<T>() == true) then
119
+ - returns a non-const reference to the object contained within *this
120
+ - else
121
+ - throws bad_any_cast
122
+ !*/
123
+
124
+ template <typename T>
125
+ const T& cast_to(
126
+ ) const;
127
+ /*!
128
+ ensures
129
+ - if (contains<T>() == true) then
130
+ - returns a const reference to the object contained within *this
131
+ - else
132
+ - throws bad_any_cast
133
+ !*/
134
+
135
+ template <typename T>
136
+ T& get(
137
+ );
138
+ /*!
139
+ ensures
140
+ - #is_empty() == false
141
+ - #contains<T>() == true
142
+ - if (contains<T>() == true)
143
+ - returns a non-const reference to the object contained in *this.
144
+ - else
145
+ - Constructs an object of type T inside *this
146
+ - Any previous object stored in this any_decision_function object is destructed and its
147
+ state is lost.
148
+ - returns a non-const reference to the newly created T object.
149
+ !*/
150
+
151
+ any_decision_function& operator= (
152
+ const any_decision_function& item
153
+ );
154
+ /*!
155
+ ensures
156
+ - copies the state of item into *this.
157
+ - Note that *this and item will contain independent copies of the
158
+ contents of item. That is, this function performs a deep
159
+ copy and therefore does not result in *this containing
160
+ any kind of reference to item.
161
+ !*/
162
+
163
+ void swap (
164
+ any_decision_function& item
165
+ );
166
+ /*!
167
+ ensures
168
+ - swaps *this and item
169
+ !*/
170
+
171
+ };
172
+
173
+ // ----------------------------------------------------------------------------------------
174
+
175
+ template <
176
+ typename sample_type,
177
+ typename result_type
178
+ >
179
+ inline void swap (
180
+ any_decision_function<sample_type,result_type>& a,
181
+ any_decision_function<sample_type,result_type>& b
182
+ ) { a.swap(b); }
183
+ /*!
184
+ provides a global swap function
185
+ !*/
186
+
187
+ // ----------------------------------------------------------------------------------------
188
+
189
+ template <
190
+ typename T,
191
+ typename sample_type,
192
+ typename result_type
193
+ >
194
+ T& any_cast(
195
+ any_decision_function<sample_type,result_type>& a
196
+ ) { return a.cast_to<T>(); }
197
+ /*!
198
+ ensures
199
+ - returns a.cast_to<T>()
200
+ !*/
201
+
202
+ // ----------------------------------------------------------------------------------------
203
+
204
+ template <
205
+ typename T,
206
+ typename sample_type,
207
+ typename result_type
208
+ >
209
+ const T& any_cast(
210
+ const any_decision_function<sample_type,result_type>& a
211
+ ) { return a.cast_to<T>(); }
212
+ /*!
213
+ ensures
214
+ - returns a.cast_to<T>()
215
+ !*/
216
+
217
+ // ----------------------------------------------------------------------------------------
218
+
219
+ }
220
+
221
+ #endif // DLIB_AnY_DECISION_FUNCTION_ABSTRACT_H_
222
+
223
+
224
+
dlibs/dlib/any/any_function.h ADDED
@@ -0,0 +1,885 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (C) 2011 Davis E. King ([email protected])
2
+ // License: Boost Software License See LICENSE.txt for the full license.
3
+ #ifndef DLIB_AnY_FUNCTION_Hh_
4
+ #define DLIB_AnY_FUNCTION_Hh_
5
+
6
+ #include "any.h"
7
+
8
+ #include "any_function_abstract.h"
9
+
10
+ namespace dlib
11
+ {
12
+
13
+ // ----------------------------------------------------------------------------------------
14
+
15
+ template <typename T>
16
+ struct sig_traits {};
17
+
18
+ template <
19
+ typename T
20
+ >
21
+ struct sig_traits<T ()>
22
+ {
23
+ typedef T result_type;
24
+ typedef void arg1_type;
25
+ typedef void arg2_type;
26
+ typedef void arg3_type;
27
+ typedef void arg4_type;
28
+ typedef void arg5_type;
29
+ typedef void arg6_type;
30
+ typedef void arg7_type;
31
+ typedef void arg8_type;
32
+ typedef void arg9_type;
33
+ typedef void arg10_type;
34
+ typedef void arg11_type;
35
+ typedef void arg12_type;
36
+ typedef void arg13_type;
37
+ typedef void arg14_type;
38
+ typedef void arg15_type;
39
+ typedef void arg16_type;
40
+ typedef void arg17_type;
41
+ typedef void arg18_type;
42
+ typedef void arg19_type;
43
+ typedef void arg20_type;
44
+
45
+ const static unsigned long num_args = 0;
46
+ };
47
+
48
+ template <
49
+ typename T,
50
+ typename A1
51
+ >
52
+ struct sig_traits<T (A1)>
53
+ {
54
+ typedef T result_type;
55
+ typedef A1 arg1_type;
56
+ typedef void arg2_type;
57
+ typedef void arg3_type;
58
+ typedef void arg4_type;
59
+ typedef void arg5_type;
60
+ typedef void arg6_type;
61
+ typedef void arg7_type;
62
+ typedef void arg8_type;
63
+ typedef void arg9_type;
64
+ typedef void arg10_type;
65
+ typedef void arg11_type;
66
+ typedef void arg12_type;
67
+ typedef void arg13_type;
68
+ typedef void arg14_type;
69
+ typedef void arg15_type;
70
+ typedef void arg16_type;
71
+ typedef void arg17_type;
72
+ typedef void arg18_type;
73
+ typedef void arg19_type;
74
+ typedef void arg20_type;
75
+
76
+ const static unsigned long num_args = 1;
77
+ };
78
+
79
+ template <
80
+ typename T,
81
+ typename A1, typename A2
82
+ >
83
+ struct sig_traits<T (A1,A2)>
84
+ {
85
+ typedef T result_type;
86
+ typedef A1 arg1_type;
87
+ typedef A2 arg2_type;
88
+ typedef void arg3_type;
89
+ typedef void arg4_type;
90
+ typedef void arg5_type;
91
+ typedef void arg6_type;
92
+ typedef void arg7_type;
93
+ typedef void arg8_type;
94
+ typedef void arg9_type;
95
+ typedef void arg10_type;
96
+ typedef void arg11_type;
97
+ typedef void arg12_type;
98
+ typedef void arg13_type;
99
+ typedef void arg14_type;
100
+ typedef void arg15_type;
101
+ typedef void arg16_type;
102
+ typedef void arg17_type;
103
+ typedef void arg18_type;
104
+ typedef void arg19_type;
105
+ typedef void arg20_type;
106
+
107
+ const static unsigned long num_args = 2;
108
+ };
109
+
110
+ template <
111
+ typename T,
112
+ typename A1, typename A2, typename A3
113
+ >
114
+ struct sig_traits<T (A1,A2,A3)>
115
+ {
116
+ typedef T result_type;
117
+ typedef A1 arg1_type;
118
+ typedef A2 arg2_type;
119
+ typedef A3 arg3_type;
120
+ typedef void arg4_type;
121
+ typedef void arg5_type;
122
+ typedef void arg6_type;
123
+ typedef void arg7_type;
124
+ typedef void arg8_type;
125
+ typedef void arg9_type;
126
+ typedef void arg10_type;
127
+ typedef void arg11_type;
128
+ typedef void arg12_type;
129
+ typedef void arg13_type;
130
+ typedef void arg14_type;
131
+ typedef void arg15_type;
132
+ typedef void arg16_type;
133
+ typedef void arg17_type;
134
+ typedef void arg18_type;
135
+ typedef void arg19_type;
136
+ typedef void arg20_type;
137
+
138
+ const static unsigned long num_args = 3;
139
+ };
140
+
141
+ template <
142
+ typename T,
143
+ typename A1, typename A2, typename A3,
144
+ typename A4
145
+ >
146
+ struct sig_traits<T (A1,A2,A3,A4)>
147
+ {
148
+ typedef T result_type;
149
+ typedef A1 arg1_type;
150
+ typedef A2 arg2_type;
151
+ typedef A3 arg3_type;
152
+ typedef A4 arg4_type;
153
+ typedef void arg5_type;
154
+ typedef void arg6_type;
155
+ typedef void arg7_type;
156
+ typedef void arg8_type;
157
+ typedef void arg9_type;
158
+ typedef void arg10_type;
159
+ typedef void arg11_type;
160
+ typedef void arg12_type;
161
+ typedef void arg13_type;
162
+ typedef void arg14_type;
163
+ typedef void arg15_type;
164
+ typedef void arg16_type;
165
+ typedef void arg17_type;
166
+ typedef void arg18_type;
167
+ typedef void arg19_type;
168
+ typedef void arg20_type;
169
+
170
+ const static unsigned long num_args = 4;
171
+ };
172
+
173
+ template <
174
+ typename T,
175
+ typename A1, typename A2, typename A3,
176
+ typename A4, typename A5
177
+ >
178
+ struct sig_traits<T (A1,A2,A3,A4,A5)>
179
+ {
180
+ typedef T result_type;
181
+ typedef A1 arg1_type;
182
+ typedef A2 arg2_type;
183
+ typedef A3 arg3_type;
184
+ typedef A4 arg4_type;
185
+ typedef A5 arg5_type;
186
+ typedef void arg6_type;
187
+ typedef void arg7_type;
188
+ typedef void arg8_type;
189
+ typedef void arg9_type;
190
+ typedef void arg10_type;
191
+ typedef void arg11_type;
192
+ typedef void arg12_type;
193
+ typedef void arg13_type;
194
+ typedef void arg14_type;
195
+ typedef void arg15_type;
196
+ typedef void arg16_type;
197
+ typedef void arg17_type;
198
+ typedef void arg18_type;
199
+ typedef void arg19_type;
200
+ typedef void arg20_type;
201
+
202
+ const static unsigned long num_args = 5;
203
+ };
204
+
205
+ template <
206
+ typename T,
207
+ typename A1, typename A2, typename A3,
208
+ typename A4, typename A5, typename A6
209
+ >
210
+ struct sig_traits<T (A1,A2,A3,A4,A5,A6)>
211
+ {
212
+ typedef T result_type;
213
+ typedef A1 arg1_type;
214
+ typedef A2 arg2_type;
215
+ typedef A3 arg3_type;
216
+ typedef A4 arg4_type;
217
+ typedef A5 arg5_type;
218
+ typedef A6 arg6_type;
219
+ typedef void arg7_type;
220
+ typedef void arg8_type;
221
+ typedef void arg9_type;
222
+ typedef void arg10_type;
223
+ typedef void arg11_type;
224
+ typedef void arg12_type;
225
+ typedef void arg13_type;
226
+ typedef void arg14_type;
227
+ typedef void arg15_type;
228
+ typedef void arg16_type;
229
+ typedef void arg17_type;
230
+ typedef void arg18_type;
231
+ typedef void arg19_type;
232
+ typedef void arg20_type;
233
+
234
+ const static unsigned long num_args = 6;
235
+ };
236
+
237
+ template <
238
+ typename T,
239
+ typename A1, typename A2, typename A3,
240
+ typename A4, typename A5, typename A6,
241
+ typename A7
242
+ >
243
+ struct sig_traits<T (A1,A2,A3,A4,A5,A6,A7)>
244
+ {
245
+ typedef T result_type;
246
+ typedef A1 arg1_type;
247
+ typedef A2 arg2_type;
248
+ typedef A3 arg3_type;
249
+ typedef A4 arg4_type;
250
+ typedef A5 arg5_type;
251
+ typedef A6 arg6_type;
252
+ typedef A7 arg7_type;
253
+ typedef void arg8_type;
254
+ typedef void arg9_type;
255
+ typedef void arg10_type;
256
+ typedef void arg11_type;
257
+ typedef void arg12_type;
258
+ typedef void arg13_type;
259
+ typedef void arg14_type;
260
+ typedef void arg15_type;
261
+ typedef void arg16_type;
262
+ typedef void arg17_type;
263
+ typedef void arg18_type;
264
+ typedef void arg19_type;
265
+ typedef void arg20_type;
266
+
267
+ const static unsigned long num_args = 7;
268
+ };
269
+
270
+ template <
271
+ typename T,
272
+ typename A1, typename A2, typename A3,
273
+ typename A4, typename A5, typename A6,
274
+ typename A7, typename A8
275
+ >
276
+ struct sig_traits<T (A1,A2,A3,A4,A5,A6,A7,A8)>
277
+ {
278
+ typedef T result_type;
279
+ typedef A1 arg1_type;
280
+ typedef A2 arg2_type;
281
+ typedef A3 arg3_type;
282
+ typedef A4 arg4_type;
283
+ typedef A5 arg5_type;
284
+ typedef A6 arg6_type;
285
+ typedef A7 arg7_type;
286
+ typedef A8 arg8_type;
287
+ typedef void arg9_type;
288
+ typedef void arg10_type;
289
+ typedef void arg11_type;
290
+ typedef void arg12_type;
291
+ typedef void arg13_type;
292
+ typedef void arg14_type;
293
+ typedef void arg15_type;
294
+ typedef void arg16_type;
295
+ typedef void arg17_type;
296
+ typedef void arg18_type;
297
+ typedef void arg19_type;
298
+ typedef void arg20_type;
299
+
300
+ const static unsigned long num_args = 8;
301
+ };
302
+
303
+ template <
304
+ typename T,
305
+ typename A1, typename A2, typename A3,
306
+ typename A4, typename A5, typename A6,
307
+ typename A7, typename A8, typename A9
308
+ >
309
+ struct sig_traits<T (A1,A2,A3,A4,A5,A6,A7,A8,A9)>
310
+ {
311
+ typedef T result_type;
312
+ typedef A1 arg1_type;
313
+ typedef A2 arg2_type;
314
+ typedef A3 arg3_type;
315
+ typedef A4 arg4_type;
316
+ typedef A5 arg5_type;
317
+ typedef A6 arg6_type;
318
+ typedef A7 arg7_type;
319
+ typedef A8 arg8_type;
320
+ typedef A9 arg9_type;
321
+ typedef void arg10_type;
322
+ typedef void arg11_type;
323
+ typedef void arg12_type;
324
+ typedef void arg13_type;
325
+ typedef void arg14_type;
326
+ typedef void arg15_type;
327
+ typedef void arg16_type;
328
+ typedef void arg17_type;
329
+ typedef void arg18_type;
330
+ typedef void arg19_type;
331
+ typedef void arg20_type;
332
+
333
+ const static unsigned long num_args = 9;
334
+ };
335
+
336
+ template <
337
+ typename T,
338
+ typename A1, typename A2, typename A3,
339
+ typename A4, typename A5, typename A6,
340
+ typename A7, typename A8, typename A9,
341
+ typename A10
342
+ >
343
+ struct sig_traits<T (A1,A2,A3,A4,A5,A6,A7,A8,A9,A10)>
344
+ {
345
+ typedef T result_type;
346
+ typedef A1 arg1_type;
347
+ typedef A2 arg2_type;
348
+ typedef A3 arg3_type;
349
+ typedef A4 arg4_type;
350
+ typedef A5 arg5_type;
351
+ typedef A6 arg6_type;
352
+ typedef A7 arg7_type;
353
+ typedef A8 arg8_type;
354
+ typedef A9 arg9_type;
355
+ typedef A10 arg10_type;
356
+ typedef void arg11_type;
357
+ typedef void arg12_type;
358
+ typedef void arg13_type;
359
+ typedef void arg14_type;
360
+ typedef void arg15_type;
361
+ typedef void arg16_type;
362
+ typedef void arg17_type;
363
+ typedef void arg18_type;
364
+ typedef void arg19_type;
365
+ typedef void arg20_type;
366
+
367
+ const static unsigned long num_args = 10;
368
+ };
369
+
370
+ template <
371
+ typename T,
372
+ typename A1, typename A2, typename A3,
373
+ typename A4, typename A5, typename A6,
374
+ typename A7, typename A8, typename A9,
375
+ typename A10,
376
+ typename A11
377
+ >
378
+ struct sig_traits<T (A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11)>
379
+ {
380
+ typedef T result_type;
381
+ typedef A1 arg1_type;
382
+ typedef A2 arg2_type;
383
+ typedef A3 arg3_type;
384
+ typedef A4 arg4_type;
385
+ typedef A5 arg5_type;
386
+ typedef A6 arg6_type;
387
+ typedef A7 arg7_type;
388
+ typedef A8 arg8_type;
389
+ typedef A9 arg9_type;
390
+ typedef A10 arg10_type;
391
+ typedef A11 arg11_type;
392
+ typedef void arg12_type;
393
+ typedef void arg13_type;
394
+ typedef void arg14_type;
395
+ typedef void arg15_type;
396
+ typedef void arg16_type;
397
+ typedef void arg17_type;
398
+ typedef void arg18_type;
399
+ typedef void arg19_type;
400
+ typedef void arg20_type;
401
+
402
+ const static unsigned long num_args = 11;
403
+ };
404
+
405
+ template <
406
+ typename T,
407
+ typename A1, typename A2, typename A3,
408
+ typename A4, typename A5, typename A6,
409
+ typename A7, typename A8, typename A9,
410
+ typename A10,
411
+ typename A11,
412
+ typename A12
413
+ >
414
+ struct sig_traits<T (A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12)>
415
+ {
416
+ typedef T result_type;
417
+ typedef A1 arg1_type;
418
+ typedef A2 arg2_type;
419
+ typedef A3 arg3_type;
420
+ typedef A4 arg4_type;
421
+ typedef A5 arg5_type;
422
+ typedef A6 arg6_type;
423
+ typedef A7 arg7_type;
424
+ typedef A8 arg8_type;
425
+ typedef A9 arg9_type;
426
+ typedef A10 arg10_type;
427
+ typedef A11 arg11_type;
428
+ typedef A12 arg12_type;
429
+ typedef void arg13_type;
430
+ typedef void arg14_type;
431
+ typedef void arg15_type;
432
+ typedef void arg16_type;
433
+ typedef void arg17_type;
434
+ typedef void arg18_type;
435
+ typedef void arg19_type;
436
+ typedef void arg20_type;
437
+
438
+ const static unsigned long num_args = 12;
439
+ };
440
+
441
+ template <
442
+ typename T,
443
+ typename A1, typename A2, typename A3,
444
+ typename A4, typename A5, typename A6,
445
+ typename A7, typename A8, typename A9,
446
+ typename A10,
447
+ typename A11,
448
+ typename A12,
449
+ typename A13
450
+ >
451
+ struct sig_traits<T (A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13)>
452
+ {
453
+ typedef T result_type;
454
+ typedef A1 arg1_type;
455
+ typedef A2 arg2_type;
456
+ typedef A3 arg3_type;
457
+ typedef A4 arg4_type;
458
+ typedef A5 arg5_type;
459
+ typedef A6 arg6_type;
460
+ typedef A7 arg7_type;
461
+ typedef A8 arg8_type;
462
+ typedef A9 arg9_type;
463
+ typedef A10 arg10_type;
464
+ typedef A11 arg11_type;
465
+ typedef A12 arg12_type;
466
+ typedef A13 arg13_type;
467
+ typedef void arg14_type;
468
+ typedef void arg15_type;
469
+ typedef void arg16_type;
470
+ typedef void arg17_type;
471
+ typedef void arg18_type;
472
+ typedef void arg19_type;
473
+ typedef void arg20_type;
474
+
475
+ const static unsigned long num_args = 13;
476
+ };
477
+
478
+ template <
479
+ typename T,
480
+ typename A1, typename A2, typename A3,
481
+ typename A4, typename A5, typename A6,
482
+ typename A7, typename A8, typename A9,
483
+ typename A10,
484
+ typename A11,
485
+ typename A12,
486
+ typename A13,
487
+ typename A14
488
+ >
489
+ struct sig_traits<T (A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13,A14)>
490
+ {
491
+ typedef T result_type;
492
+ typedef A1 arg1_type;
493
+ typedef A2 arg2_type;
494
+ typedef A3 arg3_type;
495
+ typedef A4 arg4_type;
496
+ typedef A5 arg5_type;
497
+ typedef A6 arg6_type;
498
+ typedef A7 arg7_type;
499
+ typedef A8 arg8_type;
500
+ typedef A9 arg9_type;
501
+ typedef A10 arg10_type;
502
+ typedef A11 arg11_type;
503
+ typedef A12 arg12_type;
504
+ typedef A13 arg13_type;
505
+ typedef A14 arg14_type;
506
+ typedef void arg15_type;
507
+ typedef void arg16_type;
508
+ typedef void arg17_type;
509
+ typedef void arg18_type;
510
+ typedef void arg19_type;
511
+ typedef void arg20_type;
512
+
513
+ const static unsigned long num_args = 14;
514
+ };
515
+
516
+ template <
517
+ typename T,
518
+ typename A1, typename A2, typename A3,
519
+ typename A4, typename A5, typename A6,
520
+ typename A7, typename A8, typename A9,
521
+ typename A10,
522
+ typename A11,
523
+ typename A12,
524
+ typename A13,
525
+ typename A14,
526
+ typename A15
527
+ >
528
+ struct sig_traits<T (A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13,A14,A15)>
529
+ {
530
+ typedef T result_type;
531
+ typedef A1 arg1_type;
532
+ typedef A2 arg2_type;
533
+ typedef A3 arg3_type;
534
+ typedef A4 arg4_type;
535
+ typedef A5 arg5_type;
536
+ typedef A6 arg6_type;
537
+ typedef A7 arg7_type;
538
+ typedef A8 arg8_type;
539
+ typedef A9 arg9_type;
540
+ typedef A10 arg10_type;
541
+ typedef A11 arg11_type;
542
+ typedef A12 arg12_type;
543
+ typedef A13 arg13_type;
544
+ typedef A14 arg14_type;
545
+ typedef A15 arg15_type;
546
+ typedef void arg16_type;
547
+ typedef void arg17_type;
548
+ typedef void arg18_type;
549
+ typedef void arg19_type;
550
+ typedef void arg20_type;
551
+
552
+ const static unsigned long num_args = 15;
553
+ };
554
+
555
+ template <
556
+ typename T,
557
+ typename A1, typename A2, typename A3,
558
+ typename A4, typename A5, typename A6,
559
+ typename A7, typename A8, typename A9,
560
+ typename A10,
561
+ typename A11,
562
+ typename A12,
563
+ typename A13,
564
+ typename A14,
565
+ typename A15,
566
+ typename A16
567
+ >
568
+ struct sig_traits<T (A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13,A14,A15,A16)>
569
+ {
570
+ typedef T result_type;
571
+ typedef A1 arg1_type;
572
+ typedef A2 arg2_type;
573
+ typedef A3 arg3_type;
574
+ typedef A4 arg4_type;
575
+ typedef A5 arg5_type;
576
+ typedef A6 arg6_type;
577
+ typedef A7 arg7_type;
578
+ typedef A8 arg8_type;
579
+ typedef A9 arg9_type;
580
+ typedef A10 arg10_type;
581
+ typedef A11 arg11_type;
582
+ typedef A12 arg12_type;
583
+ typedef A13 arg13_type;
584
+ typedef A14 arg14_type;
585
+ typedef A15 arg15_type;
586
+ typedef A16 arg16_type;
587
+ typedef void arg17_type;
588
+ typedef void arg18_type;
589
+ typedef void arg19_type;
590
+ typedef void arg20_type;
591
+
592
+ const static unsigned long num_args = 16;
593
+ };
594
+
595
+ template <
596
+ typename T,
597
+ typename A1, typename A2, typename A3,
598
+ typename A4, typename A5, typename A6,
599
+ typename A7, typename A8, typename A9,
600
+ typename A10,
601
+ typename A11,
602
+ typename A12,
603
+ typename A13,
604
+ typename A14,
605
+ typename A15,
606
+ typename A16,
607
+ typename A17
608
+ >
609
+ struct sig_traits<T (A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13,A14,A15,A16,A17)>
610
+ {
611
+ typedef T result_type;
612
+ typedef A1 arg1_type;
613
+ typedef A2 arg2_type;
614
+ typedef A3 arg3_type;
615
+ typedef A4 arg4_type;
616
+ typedef A5 arg5_type;
617
+ typedef A6 arg6_type;
618
+ typedef A7 arg7_type;
619
+ typedef A8 arg8_type;
620
+ typedef A9 arg9_type;
621
+ typedef A10 arg10_type;
622
+ typedef A11 arg11_type;
623
+ typedef A12 arg12_type;
624
+ typedef A13 arg13_type;
625
+ typedef A14 arg14_type;
626
+ typedef A15 arg15_type;
627
+ typedef A16 arg16_type;
628
+ typedef A17 arg17_type;
629
+ typedef void arg18_type;
630
+ typedef void arg19_type;
631
+ typedef void arg20_type;
632
+
633
+ const static unsigned long num_args = 17;
634
+ };
635
+
636
+ template <
637
+ typename T,
638
+ typename A1, typename A2, typename A3,
639
+ typename A4, typename A5, typename A6,
640
+ typename A7, typename A8, typename A9,
641
+ typename A10,
642
+ typename A11,
643
+ typename A12,
644
+ typename A13,
645
+ typename A14,
646
+ typename A15,
647
+ typename A16,
648
+ typename A17,
649
+ typename A18
650
+ >
651
+ struct sig_traits<T (A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13,A14,A15,A16,A17,A18)>
652
+ {
653
+ typedef T result_type;
654
+ typedef A1 arg1_type;
655
+ typedef A2 arg2_type;
656
+ typedef A3 arg3_type;
657
+ typedef A4 arg4_type;
658
+ typedef A5 arg5_type;
659
+ typedef A6 arg6_type;
660
+ typedef A7 arg7_type;
661
+ typedef A8 arg8_type;
662
+ typedef A9 arg9_type;
663
+ typedef A10 arg10_type;
664
+ typedef A11 arg11_type;
665
+ typedef A12 arg12_type;
666
+ typedef A13 arg13_type;
667
+ typedef A14 arg14_type;
668
+ typedef A15 arg15_type;
669
+ typedef A16 arg16_type;
670
+ typedef A17 arg17_type;
671
+ typedef A18 arg18_type;
672
+ typedef void arg19_type;
673
+ typedef void arg20_type;
674
+
675
+ const static unsigned long num_args = 18;
676
+ };
677
+
678
+ template <
679
+ typename T,
680
+ typename A1, typename A2, typename A3,
681
+ typename A4, typename A5, typename A6,
682
+ typename A7, typename A8, typename A9,
683
+ typename A10,
684
+ typename A11,
685
+ typename A12,
686
+ typename A13,
687
+ typename A14,
688
+ typename A15,
689
+ typename A16,
690
+ typename A17,
691
+ typename A18,
692
+ typename A19
693
+ >
694
+ struct sig_traits<T (A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13,A14,A15,A16,A17,A18,A19)>
695
+ {
696
+ typedef T result_type;
697
+ typedef A1 arg1_type;
698
+ typedef A2 arg2_type;
699
+ typedef A3 arg3_type;
700
+ typedef A4 arg4_type;
701
+ typedef A5 arg5_type;
702
+ typedef A6 arg6_type;
703
+ typedef A7 arg7_type;
704
+ typedef A8 arg8_type;
705
+ typedef A9 arg9_type;
706
+ typedef A10 arg10_type;
707
+ typedef A11 arg11_type;
708
+ typedef A12 arg12_type;
709
+ typedef A13 arg13_type;
710
+ typedef A14 arg14_type;
711
+ typedef A15 arg15_type;
712
+ typedef A16 arg16_type;
713
+ typedef A17 arg17_type;
714
+ typedef A18 arg18_type;
715
+ typedef A19 arg19_type;
716
+ typedef void arg20_type;
717
+
718
+ const static unsigned long num_args = 19;
719
+ };
720
+
721
+ template <
722
+ typename T,
723
+ typename A1, typename A2, typename A3,
724
+ typename A4, typename A5, typename A6,
725
+ typename A7, typename A8, typename A9,
726
+ typename A10,
727
+ typename A11,
728
+ typename A12,
729
+ typename A13,
730
+ typename A14,
731
+ typename A15,
732
+ typename A16,
733
+ typename A17,
734
+ typename A18,
735
+ typename A19,
736
+ typename A20
737
+ >
738
+ struct sig_traits<T (A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13,A14,A15,A16,A17,A18,A19,A20)>
739
+ {
740
+ typedef T result_type;
741
+ typedef A1 arg1_type;
742
+ typedef A2 arg2_type;
743
+ typedef A3 arg3_type;
744
+ typedef A4 arg4_type;
745
+ typedef A5 arg5_type;
746
+ typedef A6 arg6_type;
747
+ typedef A7 arg7_type;
748
+ typedef A8 arg8_type;
749
+ typedef A9 arg9_type;
750
+ typedef A10 arg10_type;
751
+ typedef A11 arg11_type;
752
+ typedef A12 arg12_type;
753
+ typedef A13 arg13_type;
754
+ typedef A14 arg14_type;
755
+ typedef A15 arg15_type;
756
+ typedef A16 arg16_type;
757
+ typedef A17 arg17_type;
758
+ typedef A18 arg18_type;
759
+ typedef A19 arg19_type;
760
+ typedef A20 arg20_type;
761
+
762
+ const static unsigned long num_args = 20;
763
+ };
764
+
765
+ // ----------------------------------------------------------------------------------------
766
+
767
+ template <
768
+ typename function_type,
769
+ // These arguments are used to control the overloading. A user should
770
+ // not mess with them.
771
+ typename Enabled = void,
772
+ unsigned long Num_args = sig_traits<function_type>::num_args
773
+ >
774
+ class any_function
775
+ {
776
+ private:
777
+ any_function() {}
778
+ /* !!!!!!!! ERRORS ON THE ABOVE LINE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
779
+ An error on this line means you are trying to use a function signature
780
+ with more than the supported number of arguments. The current version
781
+ of dlib only supports up to 10 arguments.
782
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
783
+ };
784
+
785
+
786
+ // The following preprocessor commands build the various overloaded versions
787
+ // of any_function for different numbers of commands and void vs. non-void return
788
+ // types.
789
+
790
+ // 0 arguments
791
+ #define DLIB_ANY_FUNCTION_ARG_LIST
792
+ #define DLIB_ANY_FUNCTION_ARGS
793
+ #define DLIB_ANY_FUNCTION_NUM_ARGS 0
794
+ #include "any_function_impl2.h"
795
+
796
+ // 1 argument
797
+ #define DLIB_ANY_FUNCTION_ARG_LIST arg1_type a1
798
+ #define DLIB_ANY_FUNCTION_ARGS a1
799
+ #define DLIB_ANY_FUNCTION_NUM_ARGS 1
800
+ #include "any_function_impl2.h"
801
+
802
+ // 2 arguments
803
+ #define DLIB_ANY_FUNCTION_ARG_LIST arg1_type a1, arg2_type a2
804
+ #define DLIB_ANY_FUNCTION_ARGS a1,a2
805
+ #define DLIB_ANY_FUNCTION_NUM_ARGS 2
806
+ #include "any_function_impl2.h"
807
+
808
+ // 3 arguments
809
+ #define DLIB_ANY_FUNCTION_ARG_LIST arg1_type a1, arg2_type a2, arg3_type a3
810
+ #define DLIB_ANY_FUNCTION_ARGS a1,a2,a3
811
+ #define DLIB_ANY_FUNCTION_NUM_ARGS 3
812
+ #include "any_function_impl2.h"
813
+
814
+ // 4 arguments
815
+ #define DLIB_ANY_FUNCTION_ARG_LIST arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4
816
+ #define DLIB_ANY_FUNCTION_ARGS a1,a2,a3,a4
817
+ #define DLIB_ANY_FUNCTION_NUM_ARGS 4
818
+ #include "any_function_impl2.h"
819
+
820
+ // 5 arguments
821
+ #define DLIB_ANY_FUNCTION_ARG_LIST arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, \
822
+ arg5_type a5
823
+ #define DLIB_ANY_FUNCTION_ARGS a1,a2,a3,a4,a5
824
+ #define DLIB_ANY_FUNCTION_NUM_ARGS 5
825
+ #include "any_function_impl2.h"
826
+
827
+ // 6 arguments
828
+ #define DLIB_ANY_FUNCTION_ARG_LIST arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, \
829
+ arg5_type a5, arg6_type a6
830
+ #define DLIB_ANY_FUNCTION_ARGS a1,a2,a3,a4,a5,a6
831
+ #define DLIB_ANY_FUNCTION_NUM_ARGS 6
832
+ #include "any_function_impl2.h"
833
+
834
+ // 7 arguments
835
+ #define DLIB_ANY_FUNCTION_ARG_LIST arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, \
836
+ arg5_type a5, arg6_type a6, arg7_type a7
837
+ #define DLIB_ANY_FUNCTION_ARGS a1,a2,a3,a4,a5,a6,a7
838
+ #define DLIB_ANY_FUNCTION_NUM_ARGS 7
839
+ #include "any_function_impl2.h"
840
+
841
+ // 8 arguments
842
+ #define DLIB_ANY_FUNCTION_ARG_LIST arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, \
843
+ arg5_type a5, arg6_type a6, arg7_type a7, arg8_type a8
844
+ #define DLIB_ANY_FUNCTION_ARGS a1,a2,a3,a4,a5,a6,a7,a8
845
+ #define DLIB_ANY_FUNCTION_NUM_ARGS 8
846
+ #include "any_function_impl2.h"
847
+
848
+ // 9 arguments
849
+ #define DLIB_ANY_FUNCTION_ARG_LIST arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, \
850
+ arg5_type a5, arg6_type a6, arg7_type a7, arg8_type a8, \
851
+ arg9_type a9
852
+ #define DLIB_ANY_FUNCTION_ARGS a1,a2,a3,a4,a5,a6,a7,a8,a9
853
+ #define DLIB_ANY_FUNCTION_NUM_ARGS 9
854
+ #include "any_function_impl2.h"
855
+
856
+ // 10 arguments
857
+ #define DLIB_ANY_FUNCTION_ARG_LIST arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, \
858
+ arg5_type a5, arg6_type a6, arg7_type a7, arg8_type a8, \
859
+ arg9_type a9, arg10_type a10
860
+ #define DLIB_ANY_FUNCTION_ARGS a1,a2,a3,a4,a5,a6,a7,a8,a9,a10
861
+ #define DLIB_ANY_FUNCTION_NUM_ARGS 10
862
+ #include "any_function_impl2.h"
863
+
864
+ // ----------------------------------------------------------------------------------------
865
+
866
+ template <typename function_type>
867
+ inline void swap (
868
+ any_function<function_type>& a,
869
+ any_function<function_type>& b
870
+ ) { a.swap(b); }
871
+
872
+ // ----------------------------------------------------------------------------------------
873
+
874
+ template <typename T, typename function_type>
875
+ T& any_cast(any_function<function_type>& a) { return a.template cast_to<T>(); }
876
+
877
+ template <typename T, typename function_type>
878
+ const T& any_cast(const any_function<function_type>& a) { return a.template cast_to<T>(); }
879
+
880
+ // ----------------------------------------------------------------------------------------
881
+
882
+ }
883
+
884
+ #endif // DLIB_AnY_FUNCTION_Hh_
885
+
dlibs/dlib/any/any_function_abstract.h ADDED
@@ -0,0 +1,292 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (C) 2011 Davis E. King ([email protected])
2
+ // License: Boost Software License See LICENSE.txt for the full license.
3
+ #undef DLIB_AnY_FUNCTION_ABSTRACT_H_
4
+ #ifdef DLIB_AnY_FUNCTION_ABSTRACT_H_
5
+
6
+ #include "any_abstract.h"
7
+ #include "../algs.h"
8
+
9
+ namespace dlib
10
+ {
11
+
12
+ // ----------------------------------------------------------------------------------------
13
+
14
+ template <
15
+ typename function_type
16
+ >
17
+ class any_function
18
+ {
19
+ /*!
20
+ REQUIREMENTS ON function_type
21
+ This type should be a function signature. Some examples are:
22
+ void (int,int) // a function returning nothing and taking two ints
23
+ void () // a function returning nothing and taking no arguments
24
+ char (double&) // a function returning a char and taking a reference to a double
25
+
26
+ The number of arguments in the function must be no greater than 10.
27
+
28
+ INITIAL VALUE
29
+ - is_empty() == true
30
+ - for all T: contains<T>() == false
31
+
32
+ WHAT THIS OBJECT REPRESENTS
33
+ This object is a version of dlib::any that is restricted to containing
34
+ elements which are some kind of function object with an operator() which
35
+ matches the function signature defined by function_type.
36
+
37
+
38
+ Here is an example:
39
+ #include <iostream>
40
+ #include <string>
41
+ #include "dlib/any.h"
42
+ using namespace std;
43
+ void print_message(string str) { cout << str << endl; }
44
+
45
+ int main()
46
+ {
47
+ dlib::any_function<void(string)> f;
48
+ f = print_message;
49
+ f("hello world"); // calls print_message("hello world")
50
+ }
51
+
52
+ Note that any_function objects can be used to store general function
53
+ objects (i.e. defined by a class with an overloaded operator()) in
54
+ addition to regular global functions.
55
+ !*/
56
+
57
+ public:
58
+
59
+ // This is the type of object returned by function_type functions.
60
+ typedef result_type_for_function_type result_type;
61
+ // Typedefs defining the argument types. If an argument does not exist
62
+ // then it is set to void.
63
+ typedef type_of_first_argument_in_funct_type arg1_type;
64
+ typedef type_of_second_argument_in_funct_type arg2_type;
65
+ ...
66
+ typedef type_of_last_argument_in_funct_type arg10_type;
67
+ const static unsigned long num_args = total_number_of_non_void_arguments;
68
+
69
+ any_function(
70
+ );
71
+ /*!
72
+ ensures
73
+ - this object is properly initialized
74
+ !*/
75
+
76
+ any_function (
77
+ const any_function& item
78
+ );
79
+ /*!
80
+ ensures
81
+ - copies the state of item into *this.
82
+ - Note that *this and item will contain independent copies of the
83
+ contents of item. That is, this function performs a deep
84
+ copy and therefore does not result in *this containing
85
+ any kind of reference to item.
86
+ !*/
87
+
88
+ template < typename T >
89
+ any_function (
90
+ const T& item
91
+ );
92
+ /*!
93
+ ensures
94
+ - #contains<T>() == true
95
+ - #cast_to<T>() == item
96
+ (i.e. a copy of item will be stored in *this)
97
+ !*/
98
+
99
+ void clear (
100
+ );
101
+ /*!
102
+ ensures
103
+ - #*this will have its default value. I.e. #is_empty() == true
104
+ !*/
105
+
106
+ template <typename T>
107
+ bool contains (
108
+ ) const;
109
+ /*!
110
+ ensures
111
+ - if (this object currently contains an object of type T) then
112
+ - returns true
113
+ - else
114
+ - returns false
115
+ !*/
116
+
117
+ bool is_empty(
118
+ ) const;
119
+ /*!
120
+ ensures
121
+ - if (this object contains any kind of object) then
122
+ - returns false
123
+ - else
124
+ - returns true
125
+ !*/
126
+
127
+ bool is_set (
128
+ ) const;
129
+ /*!
130
+ ensures
131
+ - returns !is_empty()
132
+ !*/
133
+
134
+ result_type operator() (
135
+ ) const;
136
+ /*!
137
+ requires
138
+ - is_empty() == false
139
+ - the signature defined by function_type takes no arguments
140
+ ensures
141
+ - Let F denote the function object contained within *this. Then
142
+ this function performs:
143
+ return F()
144
+ or if result_type is void then this function performs:
145
+ F()
146
+ !*/
147
+
148
+ result_type operator() (
149
+ const arg1_type& a1
150
+ ) const;
151
+ /*!
152
+ requires
153
+ - is_empty() == false
154
+ - the signature defined by function_type takes one argument
155
+ ensures
156
+ - Let F denote the function object contained within *this. Then
157
+ this function performs:
158
+ return F(a1)
159
+ or if result_type is void then this function performs:
160
+ F(a1)
161
+ !*/
162
+
163
+ result_type operator() (
164
+ const arg1_type& a1,
165
+ const arg2_type& a2
166
+ ) const;
167
+ /*!
168
+ requires
169
+ - is_empty() == false
170
+ - the signature defined by function_type takes two arguments
171
+ ensures
172
+ - Let F denote the function object contained within *this. Then
173
+ this function performs:
174
+ return F(a1,a2)
175
+ or if result_type is void then this function performs:
176
+ F(a1,a2)
177
+ !*/
178
+
179
+ /* !!!!!!!!! NOTE !!!!!!!!!
180
+
181
+ In addition to the above, operator() is defined for up to 10 arguments.
182
+ They are not listed here because it would clutter the documentation.
183
+
184
+ !!!!!!!!! NOTE !!!!!!!!! */
185
+
186
+ template <typename T>
187
+ T& cast_to(
188
+ );
189
+ /*!
190
+ ensures
191
+ - if (contains<T>() == true) then
192
+ - returns a non-const reference to the object contained within *this
193
+ - else
194
+ - throws bad_any_cast
195
+ !*/
196
+
197
+ template <typename T>
198
+ const T& cast_to(
199
+ ) const;
200
+ /*!
201
+ ensures
202
+ - if (contains<T>() == true) then
203
+ - returns a const reference to the object contained within *this
204
+ - else
205
+ - throws bad_any_cast
206
+ !*/
207
+
208
+ template <typename T>
209
+ T& get(
210
+ );
211
+ /*!
212
+ ensures
213
+ - #is_empty() == false
214
+ - #contains<T>() == true
215
+ - if (contains<T>() == true)
216
+ - returns a non-const reference to the object contained in *this.
217
+ - else
218
+ - Constructs an object of type T inside *this
219
+ - Any previous object stored in this any_function object is destructed and its
220
+ state is lost.
221
+ - returns a non-const reference to the newly created T object.
222
+ !*/
223
+
224
+ any_function& operator= (
225
+ const any_function& item
226
+ );
227
+ /*!
228
+ ensures
229
+ - copies the state of item into *this.
230
+ - Note that *this and item will contain independent copies of the
231
+ contents of item. That is, this function performs a deep
232
+ copy and therefore does not result in *this containing
233
+ any kind of reference to item.
234
+ !*/
235
+
236
+ void swap (
237
+ any_function& item
238
+ );
239
+ /*!
240
+ ensures
241
+ - swaps *this and item
242
+ !*/
243
+
244
+ };
245
+
246
+ // ----------------------------------------------------------------------------------------
247
+
248
+ template <
249
+ typename function_type
250
+ >
251
+ inline void swap (
252
+ any_function<function_type>& a,
253
+ any_function<function_type>& b
254
+ ) { a.swap(b); }
255
+ /*!
256
+ provides a global swap function
257
+ !*/
258
+
259
+ // ----------------------------------------------------------------------------------------
260
+
261
+ template <
262
+ typename T,
263
+ typename function_type
264
+ >
265
+ T& any_cast(
266
+ any_function<function_type>& a
267
+ ) { return a.cast_to<T>(); }
268
+ /*!
269
+ ensures
270
+ - returns a.cast_to<T>()
271
+ !*/
272
+
273
+ // ----------------------------------------------------------------------------------------
274
+
275
+ template <
276
+ typename T,
277
+ typename function_type
278
+ >
279
+ const T& any_cast(
280
+ const any_function<function_type>& a
281
+ ) { return a.cast_to<T>(); }
282
+ /*!
283
+ ensures
284
+ - returns a.cast_to<T>()
285
+ !*/
286
+
287
+ // ----------------------------------------------------------------------------------------
288
+
289
+ }
290
+
291
+ #endif // DLIB_AnY_FUNCTION_ABSTRACT_H_
292
+
dlibs/dlib/any/any_function_impl.h ADDED
@@ -0,0 +1,516 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (C) 2011 Davis E. King ([email protected])
2
+ // License: Boost Software License See LICENSE.txt for the full license.
3
+ #ifndef DLIB_ANY_FUNCTION_RETURN
4
+ #error "You aren't supposed to directly #include this file. #include <dlib/any.h> instead."
5
+ #endif
6
+
7
+ #ifdef _MSC_VER
8
+ // When using visual studio 2012, disable the warning "warning C4180: qualifier applied to function type has no meaning; ignored"
9
+ // that you get about some template expansions applying & to function types.
10
+ #pragma warning(disable : 4180)
11
+ #endif
12
+
13
+ #ifdef DLIB_ANY_FUNCTION_RETURN
14
+
15
+ // This file contains the body of the any_function class. We use the
16
+ // preprocessor to generate many different versions. There are
17
+ // versions which return a value and those which return void. For
18
+ // each of these types there are versions with differing numbers
19
+ // of arguments.
20
+
21
+ public:
22
+ typedef typename sig_traits<function_type>::result_type result_type;
23
+ typedef typename sig_traits<function_type>::arg1_type arg1_type;
24
+ typedef typename sig_traits<function_type>::arg2_type arg2_type;
25
+ typedef typename sig_traits<function_type>::arg3_type arg3_type;
26
+ typedef typename sig_traits<function_type>::arg4_type arg4_type;
27
+ typedef typename sig_traits<function_type>::arg5_type arg5_type;
28
+ typedef typename sig_traits<function_type>::arg6_type arg6_type;
29
+ typedef typename sig_traits<function_type>::arg7_type arg7_type;
30
+ typedef typename sig_traits<function_type>::arg8_type arg8_type;
31
+ typedef typename sig_traits<function_type>::arg9_type arg9_type;
32
+ typedef typename sig_traits<function_type>::arg10_type arg10_type;
33
+ const static unsigned long num_args = sig_traits<function_type>::num_args;
34
+
35
+ any_function()
36
+ {
37
+ }
38
+
39
+ any_function (
40
+ const any_function& item
41
+ )
42
+ {
43
+ if (item.data)
44
+ {
45
+ item.data->copy_to(data);
46
+ }
47
+ }
48
+
49
+ template <typename T>
50
+ any_function (
51
+ const T& item
52
+ )
53
+ {
54
+ typedef typename basic_type<T>::type U;
55
+ data.reset(new derived<U,function_type>(item));
56
+ }
57
+
58
+ void clear (
59
+ )
60
+ {
61
+ data.reset();
62
+ }
63
+
64
+ template <typename T>
65
+ bool contains (
66
+ ) const
67
+ {
68
+ typedef typename basic_type<T>::type U;
69
+ return dynamic_cast<derived<U,function_type>*>(data.get()) != 0;
70
+ }
71
+
72
+ bool is_empty(
73
+ ) const
74
+ {
75
+ return data.get() == 0;
76
+ }
77
+
78
+ bool is_set(
79
+ ) const
80
+ {
81
+ return !is_empty();
82
+ }
83
+
84
+ template <typename T>
85
+ T& cast_to(
86
+ )
87
+ {
88
+ typedef typename basic_type<T>::type U;
89
+ derived<U,function_type>* d = dynamic_cast<derived<U,function_type>*>(data.get());
90
+ if (d == 0)
91
+ {
92
+ throw bad_any_cast();
93
+ }
94
+
95
+ return d->item;
96
+ }
97
+
98
+ template <typename T>
99
+ const T& cast_to(
100
+ ) const
101
+ {
102
+ typedef typename basic_type<T>::type U;
103
+ derived<U,function_type>* d = dynamic_cast<derived<U,function_type>*>(data.get());
104
+ if (d == 0)
105
+ {
106
+ throw bad_any_cast();
107
+ }
108
+
109
+ return d->item;
110
+ }
111
+
112
+ template <typename T>
113
+ T& get(
114
+ )
115
+ {
116
+ typedef typename basic_type<T>::type U;
117
+ derived<U,function_type>* d = dynamic_cast<derived<U,function_type>*>(data.get());
118
+ if (d == 0)
119
+ {
120
+ d = new derived<U,function_type>();
121
+ data.reset(d);
122
+ }
123
+
124
+ return d->item;
125
+ }
126
+
127
+ any_function& operator= (
128
+ const any_function& item
129
+ )
130
+ {
131
+ any_function(item).swap(*this);
132
+ return *this;
133
+ }
134
+
135
+ void swap (
136
+ any_function& item
137
+ )
138
+ {
139
+ data.swap(item.data);
140
+ }
141
+
142
+ result_type operator()(DLIB_ANY_FUNCTION_ARG_LIST) const
143
+ { validate(); DLIB_ANY_FUNCTION_RETURN data->evaluate(DLIB_ANY_FUNCTION_ARGS); }
144
+ /* !!!!!!!! ERRORS ON THE ABOVE LINE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
145
+ If you are getting an error on the above line then it means you
146
+ have attempted to call a dlib::any_function but you have supplied
147
+ arguments which don't match the function signature used by the
148
+ dlib::any_function.
149
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
150
+
151
+ private:
152
+
153
+ void validate () const
154
+ {
155
+ // make sure requires clause is not broken
156
+ DLIB_ASSERT(is_empty() == false,
157
+ "\t result_type any_function::operator()"
158
+ << "\n\t You can't call operator() on an empty any_function"
159
+ << "\n\t this: " << this
160
+ );
161
+ }
162
+
163
+
164
+ template <typename FT>
165
+ struct Tbase
166
+ {
167
+ virtual ~Tbase() {}
168
+ virtual result_type evaluate () const = 0;
169
+ virtual void copy_to ( std::unique_ptr<Tbase>& dest) const = 0;
170
+ };
171
+
172
+ template <
173
+ typename T,
174
+ typename A1
175
+ >
176
+ struct Tbase<T (A1)>
177
+ {
178
+ virtual ~Tbase() {}
179
+ virtual T evaluate ( A1) const = 0;
180
+ virtual void copy_to ( std::unique_ptr<Tbase>& dest) const = 0;
181
+ };
182
+
183
+ template <
184
+ typename T,
185
+ typename A1, typename A2
186
+ >
187
+ struct Tbase<T (A1,A2)>
188
+ {
189
+ virtual ~Tbase() {}
190
+ virtual T evaluate (A1,A2) const = 0;
191
+ virtual void copy_to ( std::unique_ptr<Tbase>& dest) const = 0;
192
+ };
193
+
194
+ template <
195
+ typename T,
196
+ typename A1, typename A2, typename A3
197
+ >
198
+ struct Tbase<T (A1,A2,A3)>
199
+ {
200
+ virtual ~Tbase() {}
201
+ virtual T evaluate (A1,A2,A3) const = 0;
202
+ virtual void copy_to ( std::unique_ptr<Tbase>& dest) const = 0;
203
+ };
204
+
205
+ template <
206
+ typename T,
207
+ typename A1, typename A2, typename A3,
208
+ typename A4
209
+ >
210
+ struct Tbase<T (A1,A2,A3,A4)>
211
+ {
212
+ virtual ~Tbase() {}
213
+ virtual T evaluate (A1,A2,A3,A4) const = 0;
214
+ virtual void copy_to ( std::unique_ptr<Tbase>& dest) const = 0;
215
+ };
216
+
217
+ template <
218
+ typename T,
219
+ typename A1, typename A2, typename A3,
220
+ typename A4, typename A5
221
+ >
222
+ struct Tbase<T (A1,A2,A3,A4,A5)>
223
+ {
224
+ virtual ~Tbase() {}
225
+ virtual T evaluate (A1,A2,A3,A4,A5) const = 0;
226
+ virtual void copy_to ( std::unique_ptr<Tbase>& dest) const = 0;
227
+ };
228
+
229
+ template <
230
+ typename T,
231
+ typename A1, typename A2, typename A3,
232
+ typename A4, typename A5, typename A6
233
+ >
234
+ struct Tbase<T (A1,A2,A3,A4,A5,A6)>
235
+ {
236
+ virtual ~Tbase() {}
237
+ virtual T evaluate (A1,A2,A3,A4,A5,A6) const = 0;
238
+ virtual void copy_to ( std::unique_ptr<Tbase>& dest) const = 0;
239
+ };
240
+
241
+ template <
242
+ typename T,
243
+ typename A1, typename A2, typename A3,
244
+ typename A4, typename A5, typename A6,
245
+ typename A7
246
+ >
247
+ struct Tbase<T (A1,A2,A3,A4,A5,A6,A7)>
248
+ {
249
+ virtual ~Tbase() {}
250
+ virtual T evaluate (A1,A2,A3,A4,A5,A6,A7) const = 0;
251
+ virtual void copy_to ( std::unique_ptr<Tbase>& dest) const = 0;
252
+ };
253
+
254
+ template <
255
+ typename T,
256
+ typename A1, typename A2, typename A3,
257
+ typename A4, typename A5, typename A6,
258
+ typename A7, typename A8
259
+ >
260
+ struct Tbase<T (A1,A2,A3,A4,A5,A6,A7,A8)>
261
+ {
262
+ virtual ~Tbase() {}
263
+ virtual T evaluate (A1,A2,A3,A4,A5,A6,A7,A8) const = 0;
264
+ virtual void copy_to ( std::unique_ptr<Tbase>& dest) const = 0;
265
+ };
266
+
267
+ template <
268
+ typename T,
269
+ typename A1, typename A2, typename A3,
270
+ typename A4, typename A5, typename A6,
271
+ typename A7, typename A8, typename A9
272
+ >
273
+ struct Tbase<T (A1,A2,A3,A4,A5,A6,A7,A8,A9)>
274
+ {
275
+ virtual ~Tbase() {}
276
+ virtual T evaluate (A1,A2,A3,A4,A5,A6,A7,A8,A9) const = 0;
277
+ virtual void copy_to ( std::unique_ptr<Tbase>& dest) const = 0;
278
+ };
279
+
280
+ template <
281
+ typename T,
282
+ typename A1, typename A2, typename A3,
283
+ typename A4, typename A5, typename A6,
284
+ typename A7, typename A8, typename A9,
285
+ typename A10
286
+ >
287
+ struct Tbase<T (A1,A2,A3,A4,A5,A6,A7,A8,A9,A10)>
288
+ {
289
+ virtual ~Tbase() {}
290
+ virtual T evaluate (A1,A2,A3,A4,A5,A6,A7,A8,A9,A10) const = 0;
291
+ virtual void copy_to ( std::unique_ptr<Tbase>& dest) const = 0;
292
+ };
293
+
294
+ typedef Tbase<function_type> base;
295
+
296
+ // -----------------------------------------------
297
+
298
+ // Some templates to help deal with the weirdness of storing C function types (rather than pointer to functions).
299
+ // Basically, we make sure things always get turned into function pointers even if the user gives a function reference.
300
+ template <typename T, typename enabled = void>
301
+ struct funct_type { typedef T type; };
302
+ template <typename T>
303
+ struct funct_type<T, typename enable_if<is_function<T> >::type> { typedef T* type; };
304
+
305
+ template <typename T>
306
+ static typename enable_if<is_function<T>,const T*>::type copy (const T& item) { return &item; }
307
+ template <typename T>
308
+ static typename disable_if<is_function<T>,const T&>::type copy (const T& item) { return item; }
309
+
310
+ template <typename T, typename U>
311
+ static typename enable_if<is_function<T>,const T&>::type deref (const U& item) { return *item; }
312
+ template <typename T, typename U>
313
+ static typename disable_if<is_function<T>,const T&>::type deref (const U& item) { return item; }
314
+
315
+ // -----------------------------------------------
316
+
317
+ #define DLIB_ANY_FUNCTION_DERIVED_BOILERPLATE \
318
+ typename funct_type<T>::type item; \
319
+ derived() {} \
320
+ derived(const T& val) : item(copy(val)) {} \
321
+ virtual void copy_to ( std::unique_ptr<base>& dest) const \
322
+ { dest.reset(new derived(deref<T>(item))); }
323
+
324
+ template <typename T, typename FT>
325
+ struct derived : public base
326
+ {
327
+ DLIB_ANY_FUNCTION_DERIVED_BOILERPLATE
328
+
329
+ virtual result_type evaluate (
330
+ ) const { DLIB_ANY_FUNCTION_RETURN item(); }
331
+ /* !!!!!!!! ERRORS ON THE ABOVE LINE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
332
+ If you are getting an error on the above line then it means you
333
+ have attempted to assign a function or function object to a
334
+ dlib::any_function but the signatures of the source and
335
+ destination functions don't match.
336
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
337
+ };
338
+
339
+ template <typename T, typename A1>
340
+ struct derived<T,result_type (A1)> : public base
341
+ {
342
+ DLIB_ANY_FUNCTION_DERIVED_BOILERPLATE
343
+
344
+ virtual result_type evaluate (
345
+ A1 a1
346
+ ) const { DLIB_ANY_FUNCTION_RETURN item(a1); }
347
+ /* !!!!!!!! ERRORS ON THE ABOVE LINE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
348
+ If you are getting an error on the above line then it means you
349
+ have attempted to assign a function or function object to a
350
+ dlib::any_function but the signatures of the source and
351
+ destination functions don't match.
352
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
353
+ };
354
+
355
+ template <typename T, typename A1, typename A2>
356
+ struct derived<T,result_type (A1,A2)> : public base
357
+ {
358
+ DLIB_ANY_FUNCTION_DERIVED_BOILERPLATE
359
+
360
+ virtual result_type evaluate (
361
+ A1 a1, A2 a2
362
+ ) const { DLIB_ANY_FUNCTION_RETURN item(a1,a2); }
363
+ /* !!!!!!!! ERRORS ON THE ABOVE LINE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
364
+ If you are getting an error on the above line then it means you
365
+ have attempted to assign a function or function object to a
366
+ dlib::any_function but the signatures of the source and
367
+ destination functions don't match.
368
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
369
+ };
370
+
371
+ template <typename T, typename A1, typename A2, typename A3>
372
+ struct derived<T,result_type (A1,A2,A3)> : public base
373
+ {
374
+ DLIB_ANY_FUNCTION_DERIVED_BOILERPLATE
375
+
376
+ virtual result_type evaluate (
377
+ A1 a1, A2 a2, A3 a3
378
+ ) const { DLIB_ANY_FUNCTION_RETURN item(a1,a2,a3); }
379
+ /* !!!!!!!! ERRORS ON THE ABOVE LINE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
380
+ If you are getting an error on the above line then it means you
381
+ have attempted to assign a function or function object to a
382
+ dlib::any_function but the signatures of the source and
383
+ destination functions don't match.
384
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
385
+ };
386
+
387
+ template <typename T, typename A1, typename A2, typename A3,
388
+ typename A4>
389
+ struct derived<T,result_type (A1,A2,A3,A4)> : public base
390
+ {
391
+ DLIB_ANY_FUNCTION_DERIVED_BOILERPLATE
392
+
393
+ virtual result_type evaluate (
394
+ A1 a1, A2 a2, A3 a3, A4 a4
395
+ ) const { DLIB_ANY_FUNCTION_RETURN item(a1,a2,a3,a4); }
396
+ /* !!!!!!!! ERRORS ON THE ABOVE LINE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
397
+ If you are getting an error on the above line then it means you
398
+ have attempted to assign a function or function object to a
399
+ dlib::any_function but the signatures of the source and
400
+ destination functions don't match.
401
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
402
+ };
403
+
404
+ template <typename T, typename A1, typename A2, typename A3,
405
+ typename A4, typename A5>
406
+ struct derived<T,result_type (A1,A2,A3,A4,A5)> : public base
407
+ {
408
+ DLIB_ANY_FUNCTION_DERIVED_BOILERPLATE
409
+
410
+ virtual result_type evaluate (
411
+ A1 a1, A2 a2, A3 a3, A4 a4, A5 a5
412
+ ) const { DLIB_ANY_FUNCTION_RETURN item(a1,a2,a3,a4,a5); }
413
+ /* !!!!!!!! ERRORS ON THE ABOVE LINE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
414
+ If you are getting an error on the above line then it means you
415
+ have attempted to assign a function or function object to a
416
+ dlib::any_function but the signatures of the source and
417
+ destination functions don't match.
418
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
419
+ };
420
+
421
+ template <typename T, typename A1, typename A2, typename A3,
422
+ typename A4, typename A5, typename A6>
423
+ struct derived<T,result_type (A1,A2,A3,A4,A5,A6)> : public base
424
+ {
425
+ DLIB_ANY_FUNCTION_DERIVED_BOILERPLATE
426
+
427
+ virtual result_type evaluate (
428
+ A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6
429
+ ) const { DLIB_ANY_FUNCTION_RETURN item(a1,a2,a3,a4,a5,a6); }
430
+ /* !!!!!!!! ERRORS ON THE ABOVE LINE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
431
+ If you are getting an error on the above line then it means you
432
+ have attempted to assign a function or function object to a
433
+ dlib::any_function but the signatures of the source and
434
+ destination functions don't match.
435
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
436
+ };
437
+
438
+ template <typename T, typename A1, typename A2, typename A3,
439
+ typename A4, typename A5, typename A6,
440
+ typename A7>
441
+ struct derived<T,result_type (A1,A2,A3,A4,A5,A6,A7)> : public base
442
+ {
443
+ DLIB_ANY_FUNCTION_DERIVED_BOILERPLATE
444
+
445
+ virtual result_type evaluate (
446
+ A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7
447
+ ) const { DLIB_ANY_FUNCTION_RETURN item(a1,a2,a3,a4,a5,a6,a7); }
448
+ /* !!!!!!!! ERRORS ON THE ABOVE LINE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
449
+ If you are getting an error on the above line then it means you
450
+ have attempted to assign a function or function object to a
451
+ dlib::any_function but the signatures of the source and
452
+ destination functions don't match.
453
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
454
+ };
455
+
456
+ template <typename T, typename A1, typename A2, typename A3,
457
+ typename A4, typename A5, typename A6,
458
+ typename A7, typename A8>
459
+ struct derived<T,result_type (A1,A2,A3,A4,A5,A6,A7,A8)> : public base
460
+ {
461
+ DLIB_ANY_FUNCTION_DERIVED_BOILERPLATE
462
+
463
+ virtual result_type evaluate (
464
+ A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8
465
+ ) const { DLIB_ANY_FUNCTION_RETURN item(a1,a2,a3,a4,a5,a6,a7,a8); }
466
+ /* !!!!!!!! ERRORS ON THE ABOVE LINE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
467
+ If you are getting an error on the above line then it means you
468
+ have attempted to assign a function or function object to a
469
+ dlib::any_function but the signatures of the source and
470
+ destination functions don't match.
471
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
472
+ };
473
+
474
+ template <typename T, typename A1, typename A2, typename A3,
475
+ typename A4, typename A5, typename A6,
476
+ typename A7, typename A8, typename A9>
477
+ struct derived<T,result_type (A1,A2,A3,A4,A5,A6,A7,A8,A9)> : public base
478
+ {
479
+ DLIB_ANY_FUNCTION_DERIVED_BOILERPLATE
480
+
481
+ virtual result_type evaluate (
482
+ A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9
483
+ ) const { DLIB_ANY_FUNCTION_RETURN item(a1,a2,a3,a4,a5,a6,a7,a8,a9); }
484
+ /* !!!!!!!! ERRORS ON THE ABOVE LINE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
485
+ If you are getting an error on the above line then it means you
486
+ have attempted to assign a function or function object to a
487
+ dlib::any_function but the signatures of the source and
488
+ destination functions don't match.
489
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
490
+ };
491
+
492
+ template <typename T, typename A1, typename A2, typename A3,
493
+ typename A4, typename A5, typename A6,
494
+ typename A7, typename A8, typename A9,
495
+ typename A10>
496
+ struct derived<T,result_type (A1,A2,A3,A4,A5,A6,A7,A8,A9,A10)> : public base
497
+ {
498
+ DLIB_ANY_FUNCTION_DERIVED_BOILERPLATE
499
+
500
+ virtual result_type evaluate (
501
+ A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10
502
+ ) const { DLIB_ANY_FUNCTION_RETURN item(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10); }
503
+ /* !!!!!!!! ERRORS ON THE ABOVE LINE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
504
+ If you are getting an error on the above line then it means you
505
+ have attempted to assign a function or function object to a
506
+ dlib::any_function but the signatures of the source and
507
+ destination functions don't match.
508
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
509
+ };
510
+
511
+ std::unique_ptr<base> data;
512
+
513
+ #undef DLIB_ANY_FUNCTION_DERIVED_BOILERPLATE
514
+
515
+ #endif // DLIB_ANY_FUNCTION_RETURN
516
+
dlibs/dlib/any/any_function_impl2.h ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (C) 2011 Davis E. King ([email protected])
2
+ // License: Boost Software License See LICENSE.txt for the full license.
3
+ #ifndef DLIB_ANY_FUNCTION_ARG_LIST
4
+ #error "You aren't supposed to directly #include this file. #include <dlib/any.h> instead."
5
+ #endif
6
+
7
+ #ifdef DLIB_ANY_FUNCTION_ARG_LIST
8
+
9
+ // The case where function_type has a non-void return type
10
+ template <typename function_type, typename Enabled>
11
+ class any_function<function_type, Enabled, DLIB_ANY_FUNCTION_NUM_ARGS>
12
+ {
13
+ #define DLIB_ANY_FUNCTION_RETURN return
14
+ #include "any_function_impl.h"
15
+ #undef DLIB_ANY_FUNCTION_RETURN
16
+
17
+ private:
18
+ // You get a compiler error about this function being private if you try to assign
19
+ // or copy between any_functions with different types. You must only copy between
20
+ // any_functions that represent functions with the same signature.
21
+ template <typename T, typename U> any_function(const any_function<T,U>&);
22
+ };
23
+
24
+ // The case where function_type has a void return type
25
+ template <typename function_type>
26
+ class any_function<function_type, typename sig_traits<function_type>::type, DLIB_ANY_FUNCTION_NUM_ARGS>
27
+ {
28
+ #define DLIB_ANY_FUNCTION_RETURN
29
+ #include "any_function_impl.h"
30
+ #undef DLIB_ANY_FUNCTION_RETURN
31
+
32
+ private:
33
+ // You get a compiler error about this function being private if you try to assign
34
+ // or copy between any_functions with different types. You must only copy between
35
+ // any_functions that represent functions with the same signature.
36
+ template <typename T> any_function(const any_function<T>&);
37
+ };
38
+
39
+ #undef DLIB_ANY_FUNCTION_ARG_LIST
40
+ #undef DLIB_ANY_FUNCTION_ARGS
41
+ #undef DLIB_ANY_FUNCTION_NUM_ARGS
42
+
43
+ #endif // DLIB_ANY_FUNCTION_ARG_LIST
44
+
dlibs/dlib/any/any_trainer.h ADDED
@@ -0,0 +1,217 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (C) 2010 Davis E. King ([email protected])
2
+ // License: Boost Software License See LICENSE.txt for the full license.
3
+ #ifndef DLIB_AnY_TRAINER_H_
4
+ #define DLIB_AnY_TRAINER_H_
5
+
6
+ #include "any.h"
7
+
8
+ #include "any_decision_function.h"
9
+
10
+ #include "any_trainer_abstract.h"
11
+ #include <vector>
12
+
13
+ namespace dlib
14
+ {
15
+
16
+ // ----------------------------------------------------------------------------------------
17
+
18
+ template <
19
+ typename sample_type_,
20
+ typename scalar_type_ = double
21
+ >
22
+ class any_trainer
23
+ {
24
+ public:
25
+ typedef sample_type_ sample_type;
26
+ typedef scalar_type_ scalar_type;
27
+ typedef default_memory_manager mem_manager_type;
28
+ typedef any_decision_function<sample_type, scalar_type> trained_function_type;
29
+
30
+
31
+ any_trainer()
32
+ {
33
+ }
34
+
35
+ any_trainer (
36
+ const any_trainer& item
37
+ )
38
+ {
39
+ if (item.data)
40
+ {
41
+ item.data->copy_to(data);
42
+ }
43
+ }
44
+
45
+ template <typename T>
46
+ any_trainer (
47
+ const T& item
48
+ )
49
+ {
50
+ typedef typename basic_type<T>::type U;
51
+ data.reset(new derived<U>(item));
52
+ }
53
+
54
+ void clear (
55
+ )
56
+ {
57
+ data.reset();
58
+ }
59
+
60
+ template <typename T>
61
+ bool contains (
62
+ ) const
63
+ {
64
+ typedef typename basic_type<T>::type U;
65
+ return dynamic_cast<derived<U>*>(data.get()) != 0;
66
+ }
67
+
68
+ bool is_empty(
69
+ ) const
70
+ {
71
+ return data.get() == 0;
72
+ }
73
+
74
+ trained_function_type train (
75
+ const std::vector<sample_type>& samples,
76
+ const std::vector<scalar_type>& labels
77
+ ) const
78
+ {
79
+ // make sure requires clause is not broken
80
+ DLIB_ASSERT(is_empty() == false,
81
+ "\t trained_function_type any_trainer::train()"
82
+ << "\n\t You can't call train() on an empty any_trainer"
83
+ << "\n\t this: " << this
84
+ );
85
+
86
+ return data->train(samples, labels);
87
+ }
88
+
89
+ template <typename T>
90
+ T& cast_to(
91
+ )
92
+ {
93
+ typedef typename basic_type<T>::type U;
94
+ derived<U>* d = dynamic_cast<derived<U>*>(data.get());
95
+ if (d == 0)
96
+ {
97
+ throw bad_any_cast();
98
+ }
99
+
100
+ return d->item;
101
+ }
102
+
103
+ template <typename T>
104
+ const T& cast_to(
105
+ ) const
106
+ {
107
+ typedef typename basic_type<T>::type U;
108
+ derived<U>* d = dynamic_cast<derived<U>*>(data.get());
109
+ if (d == 0)
110
+ {
111
+ throw bad_any_cast();
112
+ }
113
+
114
+ return d->item;
115
+ }
116
+
117
+ template <typename T>
118
+ T& get(
119
+ )
120
+ {
121
+ typedef typename basic_type<T>::type U;
122
+ derived<U>* d = dynamic_cast<derived<U>*>(data.get());
123
+ if (d == 0)
124
+ {
125
+ d = new derived<U>();
126
+ data.reset(d);
127
+ }
128
+
129
+ return d->item;
130
+ }
131
+
132
+ any_trainer& operator= (
133
+ const any_trainer& item
134
+ )
135
+ {
136
+ any_trainer(item).swap(*this);
137
+ return *this;
138
+ }
139
+
140
+ void swap (
141
+ any_trainer& item
142
+ )
143
+ {
144
+ data.swap(item.data);
145
+ }
146
+
147
+ private:
148
+
149
+ struct base
150
+ {
151
+ virtual ~base() {}
152
+
153
+ virtual trained_function_type train (
154
+ const std::vector<sample_type>& samples,
155
+ const std::vector<scalar_type>& labels
156
+ ) const = 0;
157
+
158
+ virtual void copy_to (
159
+ std::unique_ptr<base>& dest
160
+ ) const = 0;
161
+ };
162
+
163
+ template <typename T>
164
+ struct derived : public base
165
+ {
166
+ T item;
167
+ derived() {}
168
+ derived(const T& val) : item(val) {}
169
+
170
+ virtual void copy_to (
171
+ std::unique_ptr<base>& dest
172
+ ) const
173
+ {
174
+ dest.reset(new derived<T>(item));
175
+ }
176
+
177
+ virtual trained_function_type train (
178
+ const std::vector<sample_type>& samples,
179
+ const std::vector<scalar_type>& labels
180
+ ) const
181
+ {
182
+ return item.train(samples, labels);
183
+ }
184
+ };
185
+
186
+ std::unique_ptr<base> data;
187
+ };
188
+
189
+ // ----------------------------------------------------------------------------------------
190
+
191
+ template <
192
+ typename sample_type,
193
+ typename scalar_type
194
+ >
195
+ inline void swap (
196
+ any_trainer<sample_type,scalar_type>& a,
197
+ any_trainer<sample_type,scalar_type>& b
198
+ ) { a.swap(b); }
199
+
200
+ // ----------------------------------------------------------------------------------------
201
+
202
+ template <typename T, typename U, typename V>
203
+ T& any_cast(any_trainer<U,V>& a) { return a.template cast_to<T>(); }
204
+
205
+ template <typename T, typename U, typename V>
206
+ const T& any_cast(const any_trainer<U,V>& a) { return a.template cast_to<T>(); }
207
+
208
+ // ----------------------------------------------------------------------------------------
209
+
210
+ }
211
+
212
+
213
+ #endif // DLIB_AnY_TRAINER_H_
214
+
215
+
216
+
217
+
dlibs/dlib/any/any_trainer_abstract.h ADDED
@@ -0,0 +1,234 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (C) 2010 Davis E. King ([email protected])
2
+ // License: Boost Software License See LICENSE.txt for the full license.
3
+ #undef DLIB_AnY_TRAINER_ABSTRACT_H_
4
+ #ifdef DLIB_AnY_TRAINER_ABSTRACT_H_
5
+
6
+ #include "any_abstract.h"
7
+ #include "../algs.h"
8
+ #include "any_decision_function_abstract.h"
9
+ #include <vector>
10
+
11
+ namespace dlib
12
+ {
13
+
14
+ // ----------------------------------------------------------------------------------------
15
+
16
+ template <
17
+ typename sample_type_,
18
+ typename scalar_type_ = double
19
+ >
20
+ class any_trainer
21
+ {
22
+ /*!
23
+ INITIAL VALUE
24
+ - is_empty() == true
25
+ - for all T: contains<T>() == false
26
+
27
+ WHAT THIS OBJECT REPRESENTS
28
+ This object is a version of dlib::any that is restricted to containing
29
+ elements which are some kind of object with a .train() method compatible
30
+ with the following signature:
31
+
32
+ decision_function train(
33
+ const std::vector<sample_type>& samples,
34
+ const std::vector<scalar_type>& labels
35
+ ) const
36
+
37
+ Where decision_function is a type capable of being stored in an
38
+ any_decision_function<sample_type,scalar_type> object.
39
+
40
+ any_trainer is intended to be used to contain objects such as the svm_nu_trainer
41
+ and other similar types which represent supervised machine learning algorithms.
42
+ It allows you to write code which contains and processes these trainer objects
43
+ without needing to know the specific types of trainer objects used.
44
+ !*/
45
+
46
+ public:
47
+
48
+ typedef sample_type_ sample_type;
49
+ typedef scalar_type_ scalar_type;
50
+ typedef default_memory_manager mem_manager_type;
51
+ typedef any_decision_function<sample_type, scalar_type> trained_function_type;
52
+
53
+ any_trainer(
54
+ );
55
+ /*!
56
+ ensures
57
+ - this object is properly initialized
58
+ !*/
59
+
60
+ any_trainer (
61
+ const any_trainer& item
62
+ );
63
+ /*!
64
+ ensures
65
+ - copies the state of item into *this.
66
+ - Note that *this and item will contain independent copies of the
67
+ contents of item. That is, this function performs a deep
68
+ copy and therefore does not result in *this containing
69
+ any kind of reference to item.
70
+ !*/
71
+
72
+ template < typename T >
73
+ any_trainer (
74
+ const T& item
75
+ );
76
+ /*!
77
+ ensures
78
+ - #contains<T>() == true
79
+ - #cast_to<T>() == item
80
+ (i.e. a copy of item will be stored in *this)
81
+ !*/
82
+
83
+ void clear (
84
+ );
85
+ /*!
86
+ ensures
87
+ - #*this will have its default value. I.e. #is_empty() == true
88
+ !*/
89
+
90
+ template <typename T>
91
+ bool contains (
92
+ ) const;
93
+ /*!
94
+ ensures
95
+ - if (this object currently contains an object of type T) then
96
+ - returns true
97
+ - else
98
+ - returns false
99
+ !*/
100
+
101
+ bool is_empty(
102
+ ) const;
103
+ /*!
104
+ ensures
105
+ - if (this object contains any kind of object) then
106
+ - returns false
107
+ - else
108
+ - returns true
109
+ !*/
110
+
111
+ trained_function_type train (
112
+ const std::vector<sample_type>& samples,
113
+ const std::vector<scalar_type>& labels
114
+ ) const
115
+ /*!
116
+ requires
117
+ - is_empty() == false
118
+ ensures
119
+ - Let TRAINER denote the object contained within *this. Then
120
+ this function performs:
121
+ return TRAINER.train(samples, labels)
122
+ !*/
123
+
124
+ template <typename T>
125
+ T& cast_to(
126
+ );
127
+ /*!
128
+ ensures
129
+ - if (contains<T>() == true) then
130
+ - returns a non-const reference to the object contained within *this
131
+ - else
132
+ - throws bad_any_cast
133
+ !*/
134
+
135
+ template <typename T>
136
+ const T& cast_to(
137
+ ) const;
138
+ /*!
139
+ ensures
140
+ - if (contains<T>() == true) then
141
+ - returns a const reference to the object contained within *this
142
+ - else
143
+ - throws bad_any_cast
144
+ !*/
145
+
146
+ template <typename T>
147
+ T& get(
148
+ );
149
+ /*!
150
+ ensures
151
+ - #is_empty() == false
152
+ - #contains<T>() == true
153
+ - if (contains<T>() == true)
154
+ - returns a non-const reference to the object contained in *this.
155
+ - else
156
+ - Constructs an object of type T inside *this
157
+ - Any previous object stored in this any_trainer object is destructed and its
158
+ state is lost.
159
+ - returns a non-const reference to the newly created T object.
160
+ !*/
161
+
162
+ any_trainer& operator= (
163
+ const any_trainer& item
164
+ );
165
+ /*!
166
+ ensures
167
+ - copies the state of item into *this.
168
+ - Note that *this and item will contain independent copies of the
169
+ contents of item. That is, this function performs a deep
170
+ copy and therefore does not result in *this containing
171
+ any kind of reference to item.
172
+ !*/
173
+
174
+ void swap (
175
+ any_trainer& item
176
+ );
177
+ /*!
178
+ ensures
179
+ - swaps *this and item
180
+ !*/
181
+
182
+ };
183
+
184
+ // ----------------------------------------------------------------------------------------
185
+
186
+ template <
187
+ typename sample_type,
188
+ typename scalar_type
189
+ >
190
+ inline void swap (
191
+ any_trainer<sample_type,scalar_type>& a,
192
+ any_trainer<sample_type,scalar_type>& b
193
+ ) { a.swap(b); }
194
+ /*!
195
+ provides a global swap function
196
+ !*/
197
+
198
+ // ----------------------------------------------------------------------------------------
199
+
200
+ template <
201
+ typename T,
202
+ typename sample_type,
203
+ typename scalar_type
204
+ >
205
+ T& any_cast(
206
+ any_trainer<sample_type,scalar_type>& a
207
+ ) { return a.cast_to<T>(); }
208
+ /*!
209
+ ensures
210
+ - returns a.cast_to<T>()
211
+ !*/
212
+
213
+ // ----------------------------------------------------------------------------------------
214
+
215
+ template <
216
+ typename T,
217
+ typename sample_type,
218
+ typename scalar_type
219
+ >
220
+ const T& any_cast(
221
+ const any_trainer<sample_type,scalar_type>& a
222
+ ) { return a.cast_to<T>(); }
223
+ /*!
224
+ ensures
225
+ - returns a.cast_to<T>()
226
+ !*/
227
+
228
+ // ----------------------------------------------------------------------------------------
229
+
230
+ }
231
+
232
+ #endif // DLIB_AnY_TRAINER_ABSTRACT_H_
233
+
234
+
dlibs/dlib/appveyor/dtest.yml ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ version: "{build}"
2
+
3
+ configuration: Release
4
+
5
+ build_script:
6
+ # build test
7
+ - mkdir %APPVEYOR_BUILD_FOLDER%\build_test
8
+ - cd %APPVEYOR_BUILD_FOLDER%\build_test
9
+ - cmake -G "Visual Studio 14 2015 Win64" -T host=x64 ../dlib/test
10
+ - cmake --build . --config %CONFIGURATION% --target dlib_all_source_cpp
11
+ - cmake --build . --config %CONFIGURATION% --target imglab
12
+ - cmake --build . --config %CONFIGURATION% --target htmlify
13
+ - cmake --build . --config %CONFIGURATION% --target gui
14
+ - cmake --build . --config %CONFIGURATION% --target dtest
15
+
16
+ test_script:
17
+ # run test
18
+ - cd %APPVEYOR_BUILD_FOLDER%\build_test\%CONFIGURATION%
19
+ - dtest --runall
dlibs/dlib/appveyor/dtest_vc2017.yml ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ version: "{build}"
2
+
3
+ configuration: Release
4
+
5
+ image: Visual Studio 2017
6
+
7
+ build_script:
8
+ # build test
9
+ - mkdir %APPVEYOR_BUILD_FOLDER%\build_test
10
+ - cd %APPVEYOR_BUILD_FOLDER%\build_test
11
+ - cmake -G "Visual Studio 15 2017 Win64" -T host=x64 ../dlib/test
12
+ - cmake --build . --config %CONFIGURATION% --target dlib_all_source_cpp
13
+ - cmake --build . --config %CONFIGURATION% --target imglab
14
+ - cmake --build . --config %CONFIGURATION% --target htmlify
15
+ - cmake --build . --config %CONFIGURATION% --target gui
16
+ - cmake --build . --config %CONFIGURATION% --target dtest
17
+
18
+ test_script:
19
+ # run test
20
+ - cd %APPVEYOR_BUILD_FOLDER%\build_test\%CONFIGURATION%
21
+ - dtest --runall
dlibs/dlib/appveyor/examples.yml ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ version: "{build}"
2
+
3
+ configuration: Release
4
+
5
+ image: Visual Studio 2017
6
+
7
+ build_script:
8
+ # build test
9
+ - mkdir %APPVEYOR_BUILD_FOLDER%\build_examples
10
+ - cd %APPVEYOR_BUILD_FOLDER%\build_examples
11
+ #- cmake -G "Visual Studio 14 2015 Win64" -T host=x64 ../examples
12
+ - cmake -G "Visual Studio 15 2017 Win64" -T host=x64 ../examples
13
+ - cmake --build . --config %CONFIGURATION%
14
+
15
+ test_script:
16
+ # run test
dlibs/dlib/appveyor/python.yml ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ environment:
3
+ matrix:
4
+ - PATH: C:\Python36;%PATH%
5
+ - PATH: C:\Python36-x64;%PATH%
6
+ - PATH: C:\Python37;%PATH%
7
+ - PATH: C:\Python37-x64;%PATH%
8
+
9
+
10
+ build_script:
11
+ - python setup.py build --clean
12
+
13
+ test_script:
14
+ - python setup.py test
dlibs/dlib/array.h ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (C) 2003 Davis E. King ([email protected])
2
+ // License: Boost Software License See LICENSE.txt for the full license.
3
+ #ifndef DLIB_ARRAy_
4
+ #define DLIB_ARRAy_
5
+
6
+ #include "array/array_kernel.h"
7
+ #include "array/array_tools.h"
8
+
9
+ #endif // DLIB_ARRAy_
10
+
dlibs/dlib/array/array_kernel.h ADDED
@@ -0,0 +1,809 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (C) 2003 Davis E. King ([email protected])
2
+ // License: Boost Software License See LICENSE.txt for the full license.
3
+ #ifndef DLIB_ARRAY_KERNEl_2_
4
+ #define DLIB_ARRAY_KERNEl_2_
5
+
6
+ #include "array_kernel_abstract.h"
7
+ #include "../interfaces/enumerable.h"
8
+ #include "../algs.h"
9
+ #include "../serialize.h"
10
+ #include "../sort.h"
11
+ #include "../is_kind.h"
12
+
13
+ namespace dlib
14
+ {
15
+
16
+ template <
17
+ typename T,
18
+ typename mem_manager = default_memory_manager
19
+ >
20
+ class array : public enumerable<T>
21
+ {
22
+
23
+ /*!
24
+ INITIAL VALUE
25
+ - array_size == 0
26
+ - max_array_size == 0
27
+ - array_elements == 0
28
+ - pos == 0
29
+ - last_pos == 0
30
+ - _at_start == true
31
+
32
+ CONVENTION
33
+ - array_size == size()
34
+ - max_array_size == max_size()
35
+ - if (max_array_size > 0)
36
+ - array_elements == pointer to max_array_size elements of type T
37
+ - else
38
+ - array_elements == 0
39
+
40
+ - if (array_size > 0)
41
+ - last_pos == array_elements + array_size - 1
42
+ - else
43
+ - last_pos == 0
44
+
45
+
46
+ - at_start() == _at_start
47
+ - current_element_valid() == pos != 0
48
+ - if (current_element_valid()) then
49
+ - *pos == element()
50
+ !*/
51
+
52
+ public:
53
+
54
+ // These typedefs are here for backwards compatibility with old versions of dlib.
55
+ typedef array kernel_1a;
56
+ typedef array kernel_1a_c;
57
+ typedef array kernel_2a;
58
+ typedef array kernel_2a_c;
59
+ typedef array sort_1a;
60
+ typedef array sort_1a_c;
61
+ typedef array sort_1b;
62
+ typedef array sort_1b_c;
63
+ typedef array sort_2a;
64
+ typedef array sort_2a_c;
65
+ typedef array sort_2b;
66
+ typedef array sort_2b_c;
67
+ typedef array expand_1a;
68
+ typedef array expand_1a_c;
69
+ typedef array expand_1b;
70
+ typedef array expand_1b_c;
71
+ typedef array expand_1c;
72
+ typedef array expand_1c_c;
73
+ typedef array expand_1d;
74
+ typedef array expand_1d_c;
75
+
76
+
77
+
78
+
79
+ typedef T type;
80
+ typedef T value_type;
81
+ typedef mem_manager mem_manager_type;
82
+
83
+ array (
84
+ ) :
85
+ array_size(0),
86
+ max_array_size(0),
87
+ array_elements(0),
88
+ pos(0),
89
+ last_pos(0),
90
+ _at_start(true)
91
+ {}
92
+
93
+ array(const array&) = delete;
94
+ array& operator=(array&) = delete;
95
+
96
+ array(
97
+ array&& item
98
+ ) : array()
99
+ {
100
+ swap(item);
101
+ }
102
+
103
+ array& operator=(
104
+ array&& item
105
+ )
106
+ {
107
+ swap(item);
108
+ return *this;
109
+ }
110
+
111
+ explicit array (
112
+ size_t new_size
113
+ ) :
114
+ array_size(0),
115
+ max_array_size(0),
116
+ array_elements(0),
117
+ pos(0),
118
+ last_pos(0),
119
+ _at_start(true)
120
+ {
121
+ resize(new_size);
122
+ }
123
+
124
+ ~array (
125
+ );
126
+
127
+ void clear (
128
+ );
129
+
130
+ inline const T& operator[] (
131
+ size_t pos
132
+ ) const;
133
+
134
+ inline T& operator[] (
135
+ size_t pos
136
+ );
137
+
138
+ void set_size (
139
+ size_t size
140
+ );
141
+
142
+ inline size_t max_size(
143
+ ) const;
144
+
145
+ void set_max_size(
146
+ size_t max
147
+ );
148
+
149
+ void swap (
150
+ array& item
151
+ );
152
+
153
+ // functions from the enumerable interface
154
+ inline size_t size (
155
+ ) const;
156
+
157
+ inline bool at_start (
158
+ ) const;
159
+
160
+ inline void reset (
161
+ ) const;
162
+
163
+ bool current_element_valid (
164
+ ) const;
165
+
166
+ inline const T& element (
167
+ ) const;
168
+
169
+ inline T& element (
170
+ );
171
+
172
+ bool move_next (
173
+ ) const;
174
+
175
+ void sort (
176
+ );
177
+
178
+ void resize (
179
+ size_t new_size
180
+ );
181
+
182
+ const T& back (
183
+ ) const;
184
+
185
+ T& back (
186
+ );
187
+
188
+ void pop_back (
189
+ );
190
+
191
+ void pop_back (
192
+ T& item
193
+ );
194
+
195
+ void push_back (
196
+ T& item
197
+ );
198
+
199
+ void push_back (
200
+ T&& item
201
+ );
202
+
203
+ typedef T* iterator;
204
+ typedef const T* const_iterator;
205
+ iterator begin() { return array_elements; }
206
+ const_iterator begin() const { return array_elements; }
207
+ iterator end() { return array_elements+array_size; }
208
+ const_iterator end() const { return array_elements+array_size; }
209
+
210
+ private:
211
+
212
+ typename mem_manager::template rebind<T>::other pool;
213
+
214
+ // data members
215
+ size_t array_size;
216
+ size_t max_array_size;
217
+ T* array_elements;
218
+
219
+ mutable T* pos;
220
+ T* last_pos;
221
+ mutable bool _at_start;
222
+
223
+ };
224
+
225
+ template <
226
+ typename T,
227
+ typename mem_manager
228
+ >
229
+ inline void swap (
230
+ array<T,mem_manager>& a,
231
+ array<T,mem_manager>& b
232
+ ) { a.swap(b); }
233
+
234
+ // ----------------------------------------------------------------------------------------
235
+
236
+ template <
237
+ typename T,
238
+ typename mem_manager
239
+ >
240
+ void serialize (
241
+ const array<T,mem_manager>& item,
242
+ std::ostream& out
243
+ )
244
+ {
245
+ try
246
+ {
247
+ serialize(item.max_size(),out);
248
+ serialize(item.size(),out);
249
+
250
+ for (size_t i = 0; i < item.size(); ++i)
251
+ serialize(item[i],out);
252
+ }
253
+ catch (serialization_error& e)
254
+ {
255
+ throw serialization_error(e.info + "\n while serializing object of type array");
256
+ }
257
+ }
258
+
259
+ template <
260
+ typename T,
261
+ typename mem_manager
262
+ >
263
+ void deserialize (
264
+ array<T,mem_manager>& item,
265
+ std::istream& in
266
+ )
267
+ {
268
+ try
269
+ {
270
+ size_t max_size, size;
271
+ deserialize(max_size,in);
272
+ deserialize(size,in);
273
+ item.set_max_size(max_size);
274
+ item.set_size(size);
275
+ for (size_t i = 0; i < size; ++i)
276
+ deserialize(item[i],in);
277
+ }
278
+ catch (serialization_error& e)
279
+ {
280
+ item.clear();
281
+ throw serialization_error(e.info + "\n while deserializing object of type array");
282
+ }
283
+ }
284
+
285
+ // ----------------------------------------------------------------------------------------
286
+ // ----------------------------------------------------------------------------------------
287
+ // member function definitions
288
+ // ----------------------------------------------------------------------------------------
289
+ // ----------------------------------------------------------------------------------------
290
+
291
+ template <
292
+ typename T,
293
+ typename mem_manager
294
+ >
295
+ array<T,mem_manager>::
296
+ ~array (
297
+ )
298
+ {
299
+ if (array_elements)
300
+ {
301
+ pool.deallocate_array(array_elements);
302
+ }
303
+ }
304
+
305
+ // ----------------------------------------------------------------------------------------
306
+
307
+ template <
308
+ typename T,
309
+ typename mem_manager
310
+ >
311
+ void array<T,mem_manager>::
312
+ clear (
313
+ )
314
+ {
315
+ reset();
316
+ last_pos = 0;
317
+ array_size = 0;
318
+ if (array_elements)
319
+ {
320
+ pool.deallocate_array(array_elements);
321
+ }
322
+ array_elements = 0;
323
+ max_array_size = 0;
324
+
325
+ }
326
+
327
+ // ----------------------------------------------------------------------------------------
328
+
329
+ template <
330
+ typename T,
331
+ typename mem_manager
332
+ >
333
+ const T& array<T,mem_manager>::
334
+ operator[] (
335
+ size_t pos
336
+ ) const
337
+ {
338
+ // make sure requires clause is not broken
339
+ DLIB_ASSERT( pos < this->size() ,
340
+ "\tconst T& array::operator[]"
341
+ << "\n\tpos must < size()"
342
+ << "\n\tpos: " << pos
343
+ << "\n\tsize(): " << this->size()
344
+ << "\n\tthis: " << this
345
+ );
346
+
347
+ return array_elements[pos];
348
+ }
349
+
350
+ // ----------------------------------------------------------------------------------------
351
+
352
+ template <
353
+ typename T,
354
+ typename mem_manager
355
+ >
356
+ T& array<T,mem_manager>::
357
+ operator[] (
358
+ size_t pos
359
+ )
360
+ {
361
+ // make sure requires clause is not broken
362
+ DLIB_ASSERT( pos < this->size() ,
363
+ "\tT& array::operator[]"
364
+ << "\n\tpos must be < size()"
365
+ << "\n\tpos: " << pos
366
+ << "\n\tsize(): " << this->size()
367
+ << "\n\tthis: " << this
368
+ );
369
+
370
+ return array_elements[pos];
371
+ }
372
+
373
+ // ----------------------------------------------------------------------------------------
374
+
375
+ template <
376
+ typename T,
377
+ typename mem_manager
378
+ >
379
+ void array<T,mem_manager>::
380
+ set_size (
381
+ size_t size
382
+ )
383
+ {
384
+ // make sure requires clause is not broken
385
+ DLIB_CASSERT(( size <= this->max_size() ),
386
+ "\tvoid array::set_size"
387
+ << "\n\tsize must be <= max_size()"
388
+ << "\n\tsize: " << size
389
+ << "\n\tmax size: " << this->max_size()
390
+ << "\n\tthis: " << this
391
+ );
392
+
393
+ reset();
394
+ array_size = size;
395
+ if (size > 0)
396
+ last_pos = array_elements + size - 1;
397
+ else
398
+ last_pos = 0;
399
+ }
400
+
401
+ // ----------------------------------------------------------------------------------------
402
+
403
+ template <
404
+ typename T,
405
+ typename mem_manager
406
+ >
407
+ size_t array<T,mem_manager>::
408
+ size (
409
+ ) const
410
+ {
411
+ return array_size;
412
+ }
413
+
414
+ // ----------------------------------------------------------------------------------------
415
+
416
+ template <
417
+ typename T,
418
+ typename mem_manager
419
+ >
420
+ void array<T,mem_manager>::
421
+ set_max_size(
422
+ size_t max
423
+ )
424
+ {
425
+ reset();
426
+ array_size = 0;
427
+ last_pos = 0;
428
+ if (max != 0)
429
+ {
430
+ // if new max size is different
431
+ if (max != max_array_size)
432
+ {
433
+ if (array_elements)
434
+ {
435
+ pool.deallocate_array(array_elements);
436
+ }
437
+ // try to get more memroy
438
+ try { array_elements = pool.allocate_array(max); }
439
+ catch (...) { array_elements = 0; max_array_size = 0; throw; }
440
+ max_array_size = max;
441
+ }
442
+
443
+ }
444
+ // if the array is being made to be zero
445
+ else
446
+ {
447
+ if (array_elements)
448
+ pool.deallocate_array(array_elements);
449
+ max_array_size = 0;
450
+ array_elements = 0;
451
+ }
452
+ }
453
+
454
+ // ----------------------------------------------------------------------------------------
455
+
456
+ template <
457
+ typename T,
458
+ typename mem_manager
459
+ >
460
+ size_t array<T,mem_manager>::
461
+ max_size (
462
+ ) const
463
+ {
464
+ return max_array_size;
465
+ }
466
+
467
+ // ----------------------------------------------------------------------------------------
468
+
469
+ template <
470
+ typename T,
471
+ typename mem_manager
472
+ >
473
+ void array<T,mem_manager>::
474
+ swap (
475
+ array<T,mem_manager>& item
476
+ )
477
+ {
478
+ auto array_size_temp = item.array_size;
479
+ auto max_array_size_temp = item.max_array_size;
480
+ T* array_elements_temp = item.array_elements;
481
+
482
+ item.array_size = array_size;
483
+ item.max_array_size = max_array_size;
484
+ item.array_elements = array_elements;
485
+
486
+ array_size = array_size_temp;
487
+ max_array_size = max_array_size_temp;
488
+ array_elements = array_elements_temp;
489
+
490
+ exchange(_at_start,item._at_start);
491
+ exchange(pos,item.pos);
492
+ exchange(last_pos,item.last_pos);
493
+ pool.swap(item.pool);
494
+ }
495
+
496
+ // ----------------------------------------------------------------------------------------
497
+ // ----------------------------------------------------------------------------------------
498
+ // enumerable function definitions
499
+ // ----------------------------------------------------------------------------------------
500
+ // ----------------------------------------------------------------------------------------
501
+
502
+ template <
503
+ typename T,
504
+ typename mem_manager
505
+ >
506
+ bool array<T,mem_manager>::
507
+ at_start (
508
+ ) const
509
+ {
510
+ return _at_start;
511
+ }
512
+
513
+ // ----------------------------------------------------------------------------------------
514
+
515
+ template <
516
+ typename T,
517
+ typename mem_manager
518
+ >
519
+ void array<T,mem_manager>::
520
+ reset (
521
+ ) const
522
+ {
523
+ _at_start = true;
524
+ pos = 0;
525
+ }
526
+
527
+ // ----------------------------------------------------------------------------------------
528
+
529
+ template <
530
+ typename T,
531
+ typename mem_manager
532
+ >
533
+ bool array<T,mem_manager>::
534
+ current_element_valid (
535
+ ) const
536
+ {
537
+ return pos != 0;
538
+ }
539
+
540
+ // ----------------------------------------------------------------------------------------
541
+
542
+ template <
543
+ typename T,
544
+ typename mem_manager
545
+ >
546
+ const T& array<T,mem_manager>::
547
+ element (
548
+ ) const
549
+ {
550
+ // make sure requires clause is not broken
551
+ DLIB_ASSERT(this->current_element_valid(),
552
+ "\tconst T& array::element()"
553
+ << "\n\tThe current element must be valid if you are to access it."
554
+ << "\n\tthis: " << this
555
+ );
556
+
557
+ return *pos;
558
+ }
559
+
560
+ // ----------------------------------------------------------------------------------------
561
+
562
+ template <
563
+ typename T,
564
+ typename mem_manager
565
+ >
566
+ T& array<T,mem_manager>::
567
+ element (
568
+ )
569
+ {
570
+ // make sure requires clause is not broken
571
+ DLIB_ASSERT(this->current_element_valid(),
572
+ "\tT& array::element()"
573
+ << "\n\tThe current element must be valid if you are to access it."
574
+ << "\n\tthis: " << this
575
+ );
576
+
577
+ return *pos;
578
+ }
579
+
580
+ // ----------------------------------------------------------------------------------------
581
+
582
+ template <
583
+ typename T,
584
+ typename mem_manager
585
+ >
586
+ bool array<T,mem_manager>::
587
+ move_next (
588
+ ) const
589
+ {
590
+ if (!_at_start)
591
+ {
592
+ if (pos < last_pos)
593
+ {
594
+ ++pos;
595
+ return true;
596
+ }
597
+ else
598
+ {
599
+ pos = 0;
600
+ return false;
601
+ }
602
+ }
603
+ else
604
+ {
605
+ _at_start = false;
606
+ if (array_size > 0)
607
+ {
608
+ pos = array_elements;
609
+ return true;
610
+ }
611
+ else
612
+ {
613
+ return false;
614
+ }
615
+ }
616
+ }
617
+
618
+ // ----------------------------------------------------------------------------------------
619
+ // ----------------------------------------------------------------------------------------
620
+ // Yet more functions
621
+ // ----------------------------------------------------------------------------------------
622
+ // ----------------------------------------------------------------------------------------
623
+
624
+ template <
625
+ typename T,
626
+ typename mem_manager
627
+ >
628
+ void array<T,mem_manager>::
629
+ sort (
630
+ )
631
+ {
632
+ if (this->size() > 1)
633
+ {
634
+ // call the quick sort function for arrays that is in algs.h
635
+ dlib::qsort_array(*this,0,this->size()-1);
636
+ }
637
+ this->reset();
638
+ }
639
+
640
+ // ----------------------------------------------------------------------------------------
641
+
642
+ template <
643
+ typename T,
644
+ typename mem_manager
645
+ >
646
+ void array<T,mem_manager>::
647
+ resize (
648
+ size_t new_size
649
+ )
650
+ {
651
+ if (this->max_size() < new_size)
652
+ {
653
+ array temp;
654
+ temp.set_max_size(new_size);
655
+ temp.set_size(new_size);
656
+ for (size_t i = 0; i < this->size(); ++i)
657
+ {
658
+ exchange((*this)[i],temp[i]);
659
+ }
660
+ temp.swap(*this);
661
+ }
662
+ else
663
+ {
664
+ this->set_size(new_size);
665
+ }
666
+ }
667
+
668
+ // ----------------------------------------------------------------------------------------
669
+
670
+ template <
671
+ typename T,
672
+ typename mem_manager
673
+ >
674
+ T& array<T,mem_manager>::
675
+ back (
676
+ )
677
+ {
678
+ // make sure requires clause is not broken
679
+ DLIB_ASSERT( this->size() > 0 ,
680
+ "\tT& array::back()"
681
+ << "\n\tsize() must be bigger than 0"
682
+ << "\n\tsize(): " << this->size()
683
+ << "\n\tthis: " << this
684
+ );
685
+
686
+ return (*this)[this->size()-1];
687
+ }
688
+
689
+ // ----------------------------------------------------------------------------------------
690
+
691
+ template <
692
+ typename T,
693
+ typename mem_manager
694
+ >
695
+ const T& array<T,mem_manager>::
696
+ back (
697
+ ) const
698
+ {
699
+ // make sure requires clause is not broken
700
+ DLIB_ASSERT( this->size() > 0 ,
701
+ "\tconst T& array::back()"
702
+ << "\n\tsize() must be bigger than 0"
703
+ << "\n\tsize(): " << this->size()
704
+ << "\n\tthis: " << this
705
+ );
706
+
707
+ return (*this)[this->size()-1];
708
+ }
709
+
710
+ // ----------------------------------------------------------------------------------------
711
+
712
+ template <
713
+ typename T,
714
+ typename mem_manager
715
+ >
716
+ void array<T,mem_manager>::
717
+ pop_back (
718
+ T& item
719
+ )
720
+ {
721
+ // make sure requires clause is not broken
722
+ DLIB_ASSERT( this->size() > 0 ,
723
+ "\tvoid array::pop_back()"
724
+ << "\n\tsize() must be bigger than 0"
725
+ << "\n\tsize(): " << this->size()
726
+ << "\n\tthis: " << this
727
+ );
728
+
729
+ exchange(item,(*this)[this->size()-1]);
730
+ this->set_size(this->size()-1);
731
+ }
732
+
733
+ // ----------------------------------------------------------------------------------------
734
+
735
+ template <
736
+ typename T,
737
+ typename mem_manager
738
+ >
739
+ void array<T,mem_manager>::
740
+ pop_back (
741
+ )
742
+ {
743
+ // make sure requires clause is not broken
744
+ DLIB_ASSERT( this->size() > 0 ,
745
+ "\tvoid array::pop_back()"
746
+ << "\n\tsize() must be bigger than 0"
747
+ << "\n\tsize(): " << this->size()
748
+ << "\n\tthis: " << this
749
+ );
750
+
751
+ this->set_size(this->size()-1);
752
+ }
753
+
754
+ // ----------------------------------------------------------------------------------------
755
+
756
+ template <
757
+ typename T,
758
+ typename mem_manager
759
+ >
760
+ void array<T,mem_manager>::
761
+ push_back (
762
+ T& item
763
+ )
764
+ {
765
+ if (this->max_size() == this->size())
766
+ {
767
+ // double the size of the array
768
+ array temp;
769
+ temp.set_max_size(this->size()*2 + 1);
770
+ temp.set_size(this->size()+1);
771
+ for (size_t i = 0; i < this->size(); ++i)
772
+ {
773
+ exchange((*this)[i],temp[i]);
774
+ }
775
+ exchange(item,temp[temp.size()-1]);
776
+ temp.swap(*this);
777
+ }
778
+ else
779
+ {
780
+ this->set_size(this->size()+1);
781
+ exchange(item,(*this)[this->size()-1]);
782
+ }
783
+ }
784
+
785
+ // ----------------------------------------------------------------------------------------
786
+
787
+ template <
788
+ typename T,
789
+ typename mem_manager
790
+ >
791
+ void array<T,mem_manager>::
792
+ push_back (
793
+ T&& item
794
+ ) { push_back(item); }
795
+
796
+ // ----------------------------------------------------------------------------------------
797
+
798
+ template <typename T, typename MM>
799
+ struct is_array <array<T,MM> >
800
+ {
801
+ const static bool value = true;
802
+ };
803
+
804
+ // ----------------------------------------------------------------------------------------
805
+
806
+ }
807
+
808
+ #endif // DLIB_ARRAY_KERNEl_2_
809
+
dlibs/dlib/array/array_kernel_abstract.h ADDED
@@ -0,0 +1,360 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (C) 2003 Davis E. King ([email protected])
2
+ // License: Boost Software License See LICENSE.txt for the full license.
3
+ #undef DLIB_ARRAY_KERNEl_ABSTRACT_
4
+ #ifdef DLIB_ARRAY_KERNEl_ABSTRACT_
5
+
6
+ #include "../interfaces/enumerable.h"
7
+ #include "../serialize.h"
8
+ #include "../algs.h"
9
+
10
+ namespace dlib
11
+ {
12
+
13
+ template <
14
+ typename T,
15
+ typename mem_manager = default_memory_manager
16
+ >
17
+ class array : public enumerable<T>
18
+ {
19
+
20
+ /*!
21
+ REQUIREMENTS ON T
22
+ T must have a default constructor.
23
+
24
+ REQUIREMENTS ON mem_manager
25
+ must be an implementation of memory_manager/memory_manager_kernel_abstract.h or
26
+ must be an implementation of memory_manager_global/memory_manager_global_kernel_abstract.h or
27
+ must be an implementation of memory_manager_stateless/memory_manager_stateless_kernel_abstract.h
28
+ mem_manager::type can be set to anything.
29
+
30
+ POINTERS AND REFERENCES TO INTERNAL DATA
31
+ front(), back(), swap(), max_size(), set_size(), and operator[]
32
+ functions do not invalidate pointers or references to internal data.
33
+ All other functions have no such guarantee.
34
+
35
+ INITIAL VALUE
36
+ size() == 0
37
+ max_size() == 0
38
+
39
+ ENUMERATION ORDER
40
+ The enumerator will iterate over the elements of the array in the
41
+ order (*this)[0], (*this)[1], (*this)[2], ...
42
+
43
+ WHAT THIS OBJECT REPRESENTS
44
+ This object represents an ordered 1-dimensional array of items,
45
+ each item is associated with an integer value. The items are
46
+ numbered from 0 though size() - 1 and the operator[] functions
47
+ run in constant time.
48
+
49
+ Also note that unless specified otherwise, no member functions
50
+ of this object throw exceptions.
51
+ !*/
52
+
53
+ public:
54
+
55
+ typedef T type;
56
+ typedef T value_type;
57
+ typedef mem_manager mem_manager_type;
58
+
59
+ array (
60
+ );
61
+ /*!
62
+ ensures
63
+ - #*this is properly initialized
64
+ throws
65
+ - std::bad_alloc or any exception thrown by T's constructor
66
+ !*/
67
+
68
+ explicit array (
69
+ size_t new_size
70
+ );
71
+ /*!
72
+ ensures
73
+ - #*this is properly initialized
74
+ - #size() == new_size
75
+ - #max_size() == new_size
76
+ - All elements of the array will have initial values for their type.
77
+ throws
78
+ - std::bad_alloc or any exception thrown by T's constructor
79
+ !*/
80
+
81
+ ~array (
82
+ );
83
+ /*!
84
+ ensures
85
+ - all memory associated with *this has been released
86
+ !*/
87
+
88
+ array(
89
+ array&& item
90
+ );
91
+ /*!
92
+ ensures
93
+ - move constructs *this from item. Therefore, the state of item is
94
+ moved into *this and #item has a valid but unspecified state.
95
+ !*/
96
+
97
+ array& operator=(
98
+ array&& item
99
+ );
100
+ /*!
101
+ ensures
102
+ - move assigns *this from item. Therefore, the state of item is
103
+ moved into *this and #item has a valid but unspecified state.
104
+ - returns a reference to #*this
105
+ !*/
106
+
107
+ void clear (
108
+ );
109
+ /*!
110
+ ensures
111
+ - #*this has its initial value
112
+ throws
113
+ - std::bad_alloc or any exception thrown by T's constructor
114
+ if this exception is thrown then the array object is unusable
115
+ until clear() is called and succeeds
116
+ !*/
117
+
118
+ const T& operator[] (
119
+ size_t pos
120
+ ) const;
121
+ /*!
122
+ requires
123
+ - pos < size()
124
+ ensures
125
+ - returns a const reference to the element at position pos
126
+ !*/
127
+
128
+ T& operator[] (
129
+ size_t pos
130
+ );
131
+ /*!
132
+ requires
133
+ - pos < size()
134
+ ensures
135
+ - returns a non-const reference to the element at position pos
136
+ !*/
137
+
138
+ void set_size (
139
+ size_t size
140
+ );
141
+ /*!
142
+ requires
143
+ - size <= max_size()
144
+ ensures
145
+ - #size() == size
146
+ - any element with index between 0 and size - 1 which was in the
147
+ array before the call to set_size() retains its value and index.
148
+ All other elements have undetermined (but valid for their type)
149
+ values. (e.g. this object might buffer old T objects and reuse
150
+ them without reinitializing them between calls to set_size())
151
+ - #at_start() == true
152
+ throws
153
+ - std::bad_alloc or any exception thrown by T's constructor
154
+ may throw this exception if there is not enough memory and
155
+ if it does throw then the call to set_size() has no effect
156
+ !*/
157
+
158
+ size_t max_size(
159
+ ) const;
160
+ /*!
161
+ ensures
162
+ - returns the maximum size of *this
163
+ !*/
164
+
165
+ void set_max_size(
166
+ size_t max
167
+ );
168
+ /*!
169
+ ensures
170
+ - #max_size() == max
171
+ - #size() == 0
172
+ - #at_start() == true
173
+ throws
174
+ - std::bad_alloc or any exception thrown by T's constructor
175
+ may throw this exception if there is not enough
176
+ memory and if it does throw then max_size() == 0
177
+ !*/
178
+
179
+ void swap (
180
+ array<T>& item
181
+ );
182
+ /*!
183
+ ensures
184
+ - swaps *this and item
185
+ !*/
186
+
187
+ void sort (
188
+ );
189
+ /*!
190
+ requires
191
+ - T must be a type with that is comparable via operator<
192
+ ensures
193
+ - for all elements in #*this the ith element is <= the i+1 element
194
+ - #at_start() == true
195
+ throws
196
+ - std::bad_alloc or any exception thrown by T's constructor
197
+ data may be lost if sort() throws
198
+ !*/
199
+
200
+ void resize (
201
+ size_t new_size
202
+ );
203
+ /*!
204
+ ensures
205
+ - #size() == new_size
206
+ - #max_size() == max(new_size,max_size())
207
+ - for all i < size() && i < new_size:
208
+ - #(*this)[i] == (*this)[i]
209
+ (i.e. All the original elements of *this which were at index
210
+ values less than new_size are unmodified.)
211
+ - for all valid i >= size():
212
+ - #(*this)[i] has an undefined value
213
+ (i.e. any new elements of the array have an undefined value)
214
+ throws
215
+ - std::bad_alloc or any exception thrown by T's constructor.
216
+ If an exception is thrown then it has no effect on *this.
217
+ !*/
218
+
219
+
220
+ const T& back (
221
+ ) const;
222
+ /*!
223
+ requires
224
+ - size() != 0
225
+ ensures
226
+ - returns a const reference to (*this)[size()-1]
227
+ !*/
228
+
229
+ T& back (
230
+ );
231
+ /*!
232
+ requires
233
+ - size() != 0
234
+ ensures
235
+ - returns a non-const reference to (*this)[size()-1]
236
+ !*/
237
+
238
+ void pop_back (
239
+ T& item
240
+ );
241
+ /*!
242
+ requires
243
+ - size() != 0
244
+ ensures
245
+ - #size() == size() - 1
246
+ - swaps (*this)[size()-1] into item
247
+ - All elements with an index less than size()-1 are
248
+ unmodified by this operation.
249
+ !*/
250
+
251
+ void pop_back (
252
+ );
253
+ /*!
254
+ requires
255
+ - size() != 0
256
+ ensures
257
+ - #size() == size() - 1
258
+ - All elements with an index less than size()-1 are
259
+ unmodified by this operation.
260
+ !*/
261
+
262
+ void push_back (
263
+ T& item
264
+ );
265
+ /*!
266
+ ensures
267
+ - #size() == size()+1
268
+ - swaps item into (*this)[#size()-1]
269
+ - #back() == item
270
+ - #item has some undefined value (whatever happens to
271
+ get swapped out of the array)
272
+ throws
273
+ - std::bad_alloc or any exception thrown by T's constructor.
274
+ If an exception is thrown then it has no effect on *this.
275
+ !*/
276
+
277
+ void push_back (T&& item) { push_back(item); }
278
+ /*!
279
+ enable push_back from rvalues
280
+ !*/
281
+
282
+ typedef T* iterator;
283
+ typedef const T* const_iterator;
284
+
285
+ iterator begin(
286
+ );
287
+ /*!
288
+ ensures
289
+ - returns an iterator that points to the first element in this array or
290
+ end() if the array is empty.
291
+ !*/
292
+
293
+ const_iterator begin(
294
+ ) const;
295
+ /*!
296
+ ensures
297
+ - returns a const iterator that points to the first element in this
298
+ array or end() if the array is empty.
299
+ !*/
300
+
301
+ iterator end(
302
+ );
303
+ /*!
304
+ ensures
305
+ - returns an iterator that points to one past the end of the array.
306
+ !*/
307
+
308
+ const_iterator end(
309
+ ) const;
310
+ /*!
311
+ ensures
312
+ - returns a const iterator that points to one past the end of the
313
+ array.
314
+ !*/
315
+
316
+ private:
317
+
318
+ // restricted functions
319
+ array(array<T>&); // copy constructor
320
+ array<T>& operator=(array<T>&); // assignment operator
321
+
322
+ };
323
+
324
+ template <
325
+ typename T
326
+ >
327
+ inline void swap (
328
+ array<T>& a,
329
+ array<T>& b
330
+ ) { a.swap(b); }
331
+ /*!
332
+ provides a global swap function
333
+ !*/
334
+
335
+ template <
336
+ typename T
337
+ >
338
+ void serialize (
339
+ const array<T>& item,
340
+ std::ostream& out
341
+ );
342
+ /*!
343
+ provides serialization support
344
+ !*/
345
+
346
+ template <
347
+ typename T
348
+ >
349
+ void deserialize (
350
+ array<T>& item,
351
+ std::istream& in
352
+ );
353
+ /*!
354
+ provides deserialization support
355
+ !*/
356
+
357
+ }
358
+
359
+ #endif // DLIB_ARRAY_KERNEl_ABSTRACT_
360
+
dlibs/dlib/array/array_tools.h ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (C) 2013 Davis E. King ([email protected])
2
+ // License: Boost Software License See LICENSE.txt for the full license.
3
+ #ifndef DLIB_ARRAY_tOOLS_H_
4
+ #define DLIB_ARRAY_tOOLS_H_
5
+
6
+ #include "../assert.h"
7
+ #include "array_tools_abstract.h"
8
+
9
+ namespace dlib
10
+ {
11
+ template <typename T>
12
+ void split_array (
13
+ T& a,
14
+ T& b,
15
+ double frac
16
+ )
17
+ {
18
+ // make sure requires clause is not broken
19
+ DLIB_ASSERT(0 <= frac && frac <= 1,
20
+ "\t void split_array()"
21
+ << "\n\t frac must be between 0 and 1."
22
+ << "\n\t frac: " << frac
23
+ );
24
+
25
+ const unsigned long asize = static_cast<unsigned long>(a.size()*frac);
26
+ const unsigned long bsize = a.size()-asize;
27
+
28
+ b.resize(bsize);
29
+ for (unsigned long i = 0; i < b.size(); ++i)
30
+ {
31
+ swap(b[i], a[i+asize]);
32
+ }
33
+ a.resize(asize);
34
+ }
35
+ }
36
+
37
+ #endif // DLIB_ARRAY_tOOLS_H_
38
+
dlibs/dlib/array/array_tools_abstract.h ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (C) 2013 Davis E. King ([email protected])
2
+ // License: Boost Software License See LICENSE.txt for the full license.
3
+ #undef DLIB_ARRAY_tOOLS_ABSTRACT_H_
4
+ #ifdef DLIB_ARRAY_tOOLS_ABSTRACT_H_
5
+
6
+ #include "array_kernel_abstract.h"
7
+
8
+ namespace dlib
9
+ {
10
+ template <typename T>
11
+ void split_array (
12
+ T& a,
13
+ T& b,
14
+ double frac
15
+ );
16
+ /*!
17
+ requires
18
+ - 0 <= frac <= 1
19
+ - T must be an array type such as dlib::array or std::vector
20
+ ensures
21
+ - This function takes the elements of a and splits them into two groups. The
22
+ first group remains in a and the second group is put into b. The ordering of
23
+ elements in a is preserved. In particular, concatenating #a with #b will
24
+ reproduce the original contents of a.
25
+ - The elements in a are moved around using global swap(). So they must be
26
+ swappable, but do not need to be copyable.
27
+ - #a.size() == floor(a.size()*frac)
28
+ - #b.size() == a.size()-#a.size()
29
+ !*/
30
+ }
31
+
32
+ #endif // DLIB_ARRAY_tOOLS_ABSTRACT_H_
33
+
dlibs/dlib/array2d.h ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (C) 2006 Davis E. King ([email protected])
2
+ // License: Boost Software License See LICENSE.txt for the full license.
3
+ #ifndef DLIB_ARRAY2d_
4
+ #define DLIB_ARRAY2d_
5
+
6
+
7
+ #include "array2d/array2d_kernel.h"
8
+ #include "array2d/serialize_pixel_overloads.h"
9
+ #include "array2d/array2d_generic_image.h"
10
+
11
+ #endif // DLIB_ARRAY2d_
12
+
dlibs/dlib/array2d/array2d_generic_image.h ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (C) 2014 Davis E. King ([email protected])
2
+ // License: Boost Software License See LICENSE.txt for the full license.
3
+ #ifndef DLIB_ARRAY2D_GENERIC_iMAGE_Hh_
4
+ #define DLIB_ARRAY2D_GENERIC_iMAGE_Hh_
5
+
6
+ #include "array2d_kernel.h"
7
+ #include "../image_processing/generic_image.h"
8
+
9
+ namespace dlib
10
+ {
11
+ template <typename T, typename mm>
12
+ struct image_traits<array2d<T,mm> >
13
+ {
14
+ typedef T pixel_type;
15
+ };
16
+ template <typename T, typename mm>
17
+ struct image_traits<const array2d<T,mm> >
18
+ {
19
+ typedef T pixel_type;
20
+ };
21
+
22
+ template <typename T, typename mm>
23
+ inline long num_rows( const array2d<T,mm>& img) { return img.nr(); }
24
+ template <typename T, typename mm>
25
+ inline long num_columns( const array2d<T,mm>& img) { return img.nc(); }
26
+
27
+ template <typename T, typename mm>
28
+ inline void set_image_size(
29
+ array2d<T,mm>& img,
30
+ long rows,
31
+ long cols
32
+ ) { img.set_size(rows,cols); }
33
+
34
+ template <typename T, typename mm>
35
+ inline void* image_data(
36
+ array2d<T,mm>& img
37
+ )
38
+ {
39
+ if (img.size() != 0)
40
+ return &img[0][0];
41
+ else
42
+ return 0;
43
+ }
44
+
45
+ template <typename T, typename mm>
46
+ inline const void* image_data(
47
+ const array2d<T,mm>& img
48
+ )
49
+ {
50
+ if (img.size() != 0)
51
+ return &img[0][0];
52
+ else
53
+ return 0;
54
+ }
55
+
56
+ template <typename T, typename mm>
57
+ inline long width_step(
58
+ const array2d<T,mm>& img
59
+ )
60
+ {
61
+ return img.width_step();
62
+ }
63
+
64
+ }
65
+
66
+ #endif // DLIB_ARRAY2D_GENERIC_iMAGE_Hh_
67
+
dlibs/dlib/array2d/array2d_kernel.h ADDED
@@ -0,0 +1,522 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (C) 2006 Davis E. King ([email protected])
2
+ // License: Boost Software License See LICENSE.txt for the full license.
3
+ #ifndef DLIB_ARRAY2D_KERNEl_1_
4
+ #define DLIB_ARRAY2D_KERNEl_1_
5
+
6
+ #include "array2d_kernel_abstract.h"
7
+ #include "../algs.h"
8
+ #include "../interfaces/enumerable.h"
9
+ #include "../serialize.h"
10
+ #include "../geometry/rectangle.h"
11
+
12
+ namespace dlib
13
+ {
14
+ template <
15
+ typename T,
16
+ typename mem_manager = default_memory_manager
17
+ >
18
+ class array2d : public enumerable<T>
19
+ {
20
+
21
+ /*!
22
+ INITIAL VALUE
23
+ - nc_ == 0
24
+ - nr_ == 0
25
+ - data == 0
26
+ - at_start_ == true
27
+ - cur == 0
28
+ - last == 0
29
+
30
+ CONVENTION
31
+ - nc_ == nc()
32
+ - nr_ == nc()
33
+ - if (data != 0) then
34
+ - last == a pointer to the last element in the data array
35
+ - data == pointer to an array of nc_*nr_ T objects
36
+ - else
37
+ - nc_ == 0
38
+ - nr_ == 0
39
+ - data == 0
40
+ - last == 0
41
+
42
+
43
+ - nr_ * nc_ == size()
44
+ - if (cur == 0) then
45
+ - current_element_valid() == false
46
+ - else
47
+ - current_element_valid() == true
48
+ - *cur == element()
49
+
50
+ - at_start_ == at_start()
51
+ !*/
52
+
53
+
54
+ class row_helper;
55
+ public:
56
+
57
+ // These typedefs are here for backwards compatibility with older versions of dlib.
58
+ typedef array2d kernel_1a;
59
+ typedef array2d kernel_1a_c;
60
+
61
+ typedef T type;
62
+ typedef mem_manager mem_manager_type;
63
+ typedef T* iterator;
64
+ typedef const T* const_iterator;
65
+
66
+
67
+ // -----------------------------------
68
+
69
+ class row
70
+ {
71
+ /*!
72
+ CONVENTION
73
+ - nc_ == nc()
74
+ - for all x < nc_:
75
+ - (*this)[x] == data[x]
76
+ !*/
77
+
78
+ friend class array2d<T,mem_manager>;
79
+ friend class row_helper;
80
+
81
+ public:
82
+ long nc (
83
+ ) const { return nc_; }
84
+
85
+ const T& operator[] (
86
+ long column
87
+ ) const
88
+ {
89
+ // make sure requires clause is not broken
90
+ DLIB_ASSERT(column < nc() && column >= 0,
91
+ "\tconst T& array2d::operator[](long column) const"
92
+ << "\n\tThe column index given must be less than the number of columns."
93
+ << "\n\tthis: " << this
94
+ << "\n\tcolumn: " << column
95
+ << "\n\tnc(): " << nc()
96
+ );
97
+
98
+ return data[column];
99
+ }
100
+
101
+ T& operator[] (
102
+ long column
103
+ )
104
+ {
105
+ // make sure requires clause is not broken
106
+ DLIB_ASSERT(column < nc() && column >= 0,
107
+ "\tT& array2d::operator[](long column)"
108
+ << "\n\tThe column index given must be less than the number of columns."
109
+ << "\n\tthis: " << this
110
+ << "\n\tcolumn: " << column
111
+ << "\n\tnc(): " << nc()
112
+ );
113
+
114
+ return data[column];
115
+ }
116
+
117
+ private:
118
+
119
+ row(T* data_, long cols) : data(data_), nc_(cols) {}
120
+
121
+ T* data;
122
+ long nc_;
123
+
124
+
125
+ // restricted functions
126
+ row(){}
127
+ row& operator=(row&);
128
+ };
129
+
130
+ // -----------------------------------
131
+
132
+ array2d (
133
+ ) :
134
+ data(0),
135
+ nc_(0),
136
+ nr_(0),
137
+ cur(0),
138
+ last(0),
139
+ at_start_(true)
140
+ {
141
+ }
142
+
143
+ array2d(
144
+ long rows,
145
+ long cols
146
+ ) :
147
+ data(0),
148
+ nc_(0),
149
+ nr_(0),
150
+ cur(0),
151
+ last(0),
152
+ at_start_(true)
153
+ {
154
+ // make sure requires clause is not broken
155
+ DLIB_ASSERT((cols >= 0 && rows >= 0),
156
+ "\t array2d::array2d(long rows, long cols)"
157
+ << "\n\t The array2d can't have negative rows or columns."
158
+ << "\n\t this: " << this
159
+ << "\n\t cols: " << cols
160
+ << "\n\t rows: " << rows
161
+ );
162
+
163
+ set_size(rows,cols);
164
+ }
165
+
166
+ array2d(const array2d&) = delete; // copy constructor
167
+ array2d& operator=(const array2d&) = delete; // assignment operator
168
+
169
+ #ifdef DLIB_HAS_RVALUE_REFERENCES
170
+ array2d(array2d&& item) : array2d()
171
+ {
172
+ swap(item);
173
+ }
174
+
175
+ array2d& operator= (
176
+ array2d&& rhs
177
+ )
178
+ {
179
+ swap(rhs);
180
+ return *this;
181
+ }
182
+ #endif
183
+
184
+ virtual ~array2d (
185
+ ) { clear(); }
186
+
187
+ long nc (
188
+ ) const { return nc_; }
189
+
190
+ long nr (
191
+ ) const { return nr_; }
192
+
193
+ row operator[] (
194
+ long row_
195
+ )
196
+ {
197
+ // make sure requires clause is not broken
198
+ DLIB_ASSERT(row_ < nr() && row_ >= 0,
199
+ "\trow array2d::operator[](long row_)"
200
+ << "\n\tThe row index given must be less than the number of rows."
201
+ << "\n\tthis: " << this
202
+ << "\n\trow_: " << row_
203
+ << "\n\tnr(): " << nr()
204
+ );
205
+
206
+ return row(data+row_*nc_, nc_);
207
+ }
208
+
209
+ const row operator[] (
210
+ long row_
211
+ ) const
212
+ {
213
+ // make sure requires clause is not broken
214
+ DLIB_ASSERT(row_ < nr() && row_ >= 0,
215
+ "\tconst row array2d::operator[](long row_) const"
216
+ << "\n\tThe row index given must be less than the number of rows."
217
+ << "\n\tthis: " << this
218
+ << "\n\trow_: " << row_
219
+ << "\n\tnr(): " << nr()
220
+ );
221
+
222
+ return row(data+row_*nc_, nc_);
223
+ }
224
+
225
+ void swap (
226
+ array2d& item
227
+ )
228
+ {
229
+ exchange(data,item.data);
230
+ exchange(nr_,item.nr_);
231
+ exchange(nc_,item.nc_);
232
+ exchange(at_start_,item.at_start_);
233
+ exchange(cur,item.cur);
234
+ exchange(last,item.last);
235
+ pool.swap(item.pool);
236
+ }
237
+
238
+ void clear (
239
+ )
240
+ {
241
+ if (data != 0)
242
+ {
243
+ pool.deallocate_array(data);
244
+ nc_ = 0;
245
+ nr_ = 0;
246
+ data = 0;
247
+ at_start_ = true;
248
+ cur = 0;
249
+ last = 0;
250
+ }
251
+ }
252
+
253
+ void set_size (
254
+ long rows,
255
+ long cols
256
+ );
257
+
258
+ bool at_start (
259
+ ) const { return at_start_; }
260
+
261
+ void reset (
262
+ ) const { at_start_ = true; cur = 0; }
263
+
264
+ bool current_element_valid (
265
+ ) const { return (cur != 0); }
266
+
267
+ const T& element (
268
+ ) const
269
+ {
270
+ // make sure requires clause is not broken
271
+ DLIB_ASSERT(current_element_valid() == true,
272
+ "\tconst T& array2d::element()()"
273
+ << "\n\tYou can only call element() when you are at a valid one."
274
+ << "\n\tthis: " << this
275
+ );
276
+
277
+ return *cur;
278
+ }
279
+
280
+ T& element (
281
+ )
282
+ {
283
+ // make sure requires clause is not broken
284
+ DLIB_ASSERT(current_element_valid() == true,
285
+ "\tT& array2d::element()()"
286
+ << "\n\tYou can only call element() when you are at a valid one."
287
+ << "\n\tthis: " << this
288
+ );
289
+
290
+ return *cur;
291
+ }
292
+
293
+ bool move_next (
294
+ ) const
295
+ {
296
+ if (cur != 0)
297
+ {
298
+ if (cur != last)
299
+ {
300
+ ++cur;
301
+ return true;
302
+ }
303
+ cur = 0;
304
+ return false;
305
+ }
306
+ else if (at_start_)
307
+ {
308
+ cur = data;
309
+ at_start_ = false;
310
+ return (data != 0);
311
+ }
312
+ else
313
+ {
314
+ return false;
315
+ }
316
+ }
317
+
318
+ size_t size (
319
+ ) const { return static_cast<size_t>(nc_) * static_cast<size_t>(nr_); }
320
+
321
+ long width_step (
322
+ ) const
323
+ {
324
+ return nc_*sizeof(T);
325
+ }
326
+
327
+ iterator begin()
328
+ {
329
+ return data;
330
+ }
331
+
332
+ iterator end()
333
+ {
334
+ return data+size();
335
+ }
336
+
337
+ const_iterator begin() const
338
+ {
339
+ return data;
340
+ }
341
+
342
+ const_iterator end() const
343
+ {
344
+ return data+size();
345
+ }
346
+
347
+
348
+ private:
349
+
350
+
351
+ T* data;
352
+ long nc_;
353
+ long nr_;
354
+
355
+ typename mem_manager::template rebind<T>::other pool;
356
+ mutable T* cur;
357
+ T* last;
358
+ mutable bool at_start_;
359
+
360
+ };
361
+
362
+ // ----------------------------------------------------------------------------------------
363
+
364
+ template <
365
+ typename T,
366
+ typename mem_manager
367
+ >
368
+ inline void swap (
369
+ array2d<T,mem_manager>& a,
370
+ array2d<T,mem_manager>& b
371
+ ) { a.swap(b); }
372
+
373
+
374
+ template <
375
+ typename T,
376
+ typename mem_manager
377
+ >
378
+ void serialize (
379
+ const array2d<T,mem_manager>& item,
380
+ std::ostream& out
381
+ )
382
+ {
383
+ try
384
+ {
385
+ // The reason the serialization is a little funny is because we are trying to
386
+ // maintain backwards compatibility with an older serialization format used by
387
+ // dlib while also encoding things in a way that lets the array2d and matrix
388
+ // objects have compatible serialization formats.
389
+ serialize(-item.nr(),out);
390
+ serialize(-item.nc(),out);
391
+
392
+ item.reset();
393
+ while (item.move_next())
394
+ serialize(item.element(),out);
395
+ item.reset();
396
+ }
397
+ catch (serialization_error& e)
398
+ {
399
+ throw serialization_error(e.info + "\n while serializing object of type array2d");
400
+ }
401
+ }
402
+
403
+ template <
404
+ typename T,
405
+ typename mem_manager
406
+ >
407
+ void deserialize (
408
+ array2d<T,mem_manager>& item,
409
+ std::istream& in
410
+ )
411
+ {
412
+ try
413
+ {
414
+ long nr, nc;
415
+ deserialize(nr,in);
416
+ deserialize(nc,in);
417
+
418
+ // this is the newer serialization format
419
+ if (nr < 0 || nc < 0)
420
+ {
421
+ nr *= -1;
422
+ nc *= -1;
423
+ }
424
+ else
425
+ {
426
+ std::swap(nr,nc);
427
+ }
428
+
429
+ item.set_size(nr,nc);
430
+
431
+ while (item.move_next())
432
+ deserialize(item.element(),in);
433
+ item.reset();
434
+ }
435
+ catch (serialization_error& e)
436
+ {
437
+ item.clear();
438
+ throw serialization_error(e.info + "\n while deserializing object of type array2d");
439
+ }
440
+ }
441
+
442
+ // ----------------------------------------------------------------------------------------
443
+ // ----------------------------------------------------------------------------------------
444
+ // member function definitions
445
+ // ----------------------------------------------------------------------------------------
446
+ // ----------------------------------------------------------------------------------------
447
+
448
+ template <
449
+ typename T,
450
+ typename mem_manager
451
+ >
452
+ void array2d<T,mem_manager>::
453
+ set_size (
454
+ long rows,
455
+ long cols
456
+ )
457
+ {
458
+ // make sure requires clause is not broken
459
+ DLIB_ASSERT((cols >= 0 && rows >= 0) ,
460
+ "\tvoid array2d::set_size(long rows, long cols)"
461
+ << "\n\tThe array2d can't have negative rows or columns."
462
+ << "\n\tthis: " << this
463
+ << "\n\tcols: " << cols
464
+ << "\n\trows: " << rows
465
+ );
466
+
467
+ // set the enumerator back at the start
468
+ at_start_ = true;
469
+ cur = 0;
470
+
471
+ // don't do anything if we are already the right size.
472
+ if (nc_ == cols && nr_ == rows)
473
+ {
474
+ return;
475
+ }
476
+
477
+ nc_ = cols;
478
+ nr_ = rows;
479
+
480
+ // free any existing memory
481
+ if (data != 0)
482
+ {
483
+ pool.deallocate_array(data);
484
+ data = 0;
485
+ }
486
+
487
+ // now setup this object to have the new size
488
+ try
489
+ {
490
+ if (nr_ > 0)
491
+ {
492
+ data = pool.allocate_array(nr_*nc_);
493
+ last = data + nr_*nc_ - 1;
494
+ }
495
+ }
496
+ catch (...)
497
+ {
498
+ if (data)
499
+ pool.deallocate_array(data);
500
+
501
+ data = 0;
502
+ nc_ = 0;
503
+ nr_ = 0;
504
+ last = 0;
505
+ throw;
506
+ }
507
+ }
508
+
509
+ // ----------------------------------------------------------------------------------------
510
+
511
+ template <typename T, typename MM>
512
+ struct is_array2d <array2d<T,MM> >
513
+ {
514
+ const static bool value = true;
515
+ };
516
+
517
+ // ----------------------------------------------------------------------------------------
518
+
519
+ }
520
+
521
+ #endif // DLIB_ARRAY2D_KERNEl_1_
522
+
dlibs/dlib/array2d/array2d_kernel_abstract.h ADDED
@@ -0,0 +1,339 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (C) 2006 Davis E. King ([email protected])
2
+ // License: Boost Software License See LICENSE.txt for the full license.
3
+ #undef DLIB_ARRAY2D_KERNEl_ABSTRACT_
4
+ #ifdef DLIB_ARRAY2D_KERNEl_ABSTRACT_
5
+
6
+ #include "../interfaces/enumerable.h"
7
+ #include "../serialize.h"
8
+ #include "../algs.h"
9
+ #include "../geometry/rectangle_abstract.h"
10
+
11
+ namespace dlib
12
+ {
13
+
14
+ template <
15
+ typename T,
16
+ typename mem_manager = default_memory_manager
17
+ >
18
+ class array2d : public enumerable<T>
19
+ {
20
+
21
+ /*!
22
+ REQUIREMENTS ON T
23
+ T must have a default constructor.
24
+
25
+ REQUIREMENTS ON mem_manager
26
+ must be an implementation of memory_manager/memory_manager_kernel_abstract.h or
27
+ must be an implementation of memory_manager_global/memory_manager_global_kernel_abstract.h or
28
+ must be an implementation of memory_manager_stateless/memory_manager_stateless_kernel_abstract.h
29
+ mem_manager::type can be set to anything.
30
+
31
+ POINTERS AND REFERENCES TO INTERNAL DATA
32
+ No member functions in this object will invalidate pointers
33
+ or references to internal data except for the set_size()
34
+ and clear() member functions.
35
+
36
+ INITIAL VALUE
37
+ nr() == 0
38
+ nc() == 0
39
+
40
+ ENUMERATION ORDER
41
+ The enumerator will iterate over the elements of the array starting
42
+ with row 0 and then proceeding to row 1 and so on. Each row will be
43
+ fully enumerated before proceeding on to the next row and the elements
44
+ in a row will be enumerated beginning with the 0th column, then the 1st
45
+ column and so on.
46
+
47
+ WHAT THIS OBJECT REPRESENTS
48
+ This object represents a 2-Dimensional array of objects of
49
+ type T.
50
+
51
+ Also note that unless specified otherwise, no member functions
52
+ of this object throw exceptions.
53
+
54
+
55
+ Finally, note that this object stores its data contiguously and in
56
+ row major order. Moreover, there is no padding at the end of each row.
57
+ This means that its width_step() value is always equal to sizeof(type)*nc().
58
+ !*/
59
+
60
+
61
+ public:
62
+
63
+ // ----------------------------------------
64
+
65
+ typedef T type;
66
+ typedef mem_manager mem_manager_type;
67
+ typedef T* iterator;
68
+ typedef const T* const_iterator;
69
+
70
+ // ----------------------------------------
71
+
72
+ class row
73
+ {
74
+ /*!
75
+ POINTERS AND REFERENCES TO INTERNAL DATA
76
+ No member functions in this object will invalidate pointers
77
+ or references to internal data.
78
+
79
+ WHAT THIS OBJECT REPRESENTS
80
+ This object represents a row of Ts in an array2d object.
81
+ !*/
82
+ public:
83
+ long nc (
84
+ ) const;
85
+ /*!
86
+ ensures
87
+ - returns the number of columns in this row
88
+ !*/
89
+
90
+ const T& operator[] (
91
+ long column
92
+ ) const;
93
+ /*!
94
+ requires
95
+ - 0 <= column < nc()
96
+ ensures
97
+ - returns a const reference to the T in the given column
98
+ !*/
99
+
100
+ T& operator[] (
101
+ long column
102
+ );
103
+ /*!
104
+ requires
105
+ - 0 <= column < nc()
106
+ ensures
107
+ - returns a non-const reference to the T in the given column
108
+ !*/
109
+
110
+ private:
111
+ // restricted functions
112
+ row();
113
+ row& operator=(row&);
114
+ };
115
+
116
+ // ----------------------------------------
117
+
118
+ array2d (
119
+ );
120
+ /*!
121
+ ensures
122
+ - #*this is properly initialized
123
+ throws
124
+ - std::bad_alloc
125
+ !*/
126
+
127
+ array2d(const array2d&) = delete; // copy constructor
128
+ array2d& operator=(const array2d&) = delete; // assignment operator
129
+
130
+ array2d(
131
+ array2d&& item
132
+ );
133
+ /*!
134
+ ensures
135
+ - Moves the state of item into *this.
136
+ - #item is in a valid but unspecified state.
137
+ !*/
138
+
139
+ array2d (
140
+ long rows,
141
+ long cols
142
+ );
143
+ /*!
144
+ requires
145
+ - rows >= 0 && cols >= 0
146
+ ensures
147
+ - #nc() == cols
148
+ - #nr() == rows
149
+ - #at_start() == true
150
+ - all elements in this array have initial values for their type
151
+ throws
152
+ - std::bad_alloc
153
+ !*/
154
+
155
+ virtual ~array2d (
156
+ );
157
+ /*!
158
+ ensures
159
+ - all resources associated with *this has been released
160
+ !*/
161
+
162
+ void clear (
163
+ );
164
+ /*!
165
+ ensures
166
+ - #*this has an initial value for its type
167
+ !*/
168
+
169
+ long nc (
170
+ ) const;
171
+ /*!
172
+ ensures
173
+ - returns the number of elements there are in a row. i.e. returns
174
+ the number of columns in *this
175
+ !*/
176
+
177
+ long nr (
178
+ ) const;
179
+ /*!
180
+ ensures
181
+ - returns the number of rows in *this
182
+ !*/
183
+
184
+ void set_size (
185
+ long rows,
186
+ long cols
187
+ );
188
+ /*!
189
+ requires
190
+ - rows >= 0 && cols >= 0
191
+ ensures
192
+ - #nc() == cols
193
+ - #nr() == rows
194
+ - #at_start() == true
195
+ - if (the call to set_size() doesn't change the dimensions of this array) then
196
+ - all elements in this array retain their values from before this function was called
197
+ - else
198
+ - all elements in this array have initial values for their type
199
+ throws
200
+ - std::bad_alloc
201
+ If this exception is thrown then #*this will have an initial
202
+ value for its type.
203
+ !*/
204
+
205
+ row operator[] (
206
+ long row_index
207
+ );
208
+ /*!
209
+ requires
210
+ - 0 <= row_index < nr()
211
+ ensures
212
+ - returns a non-const row of nc() elements that represents the
213
+ given row_index'th row in *this.
214
+ !*/
215
+
216
+ const row operator[] (
217
+ long row_index
218
+ ) const;
219
+ /*!
220
+ requires
221
+ - 0 <= row_index < nr()
222
+ ensures
223
+ - returns a const row of nc() elements that represents the
224
+ given row_index'th row in *this.
225
+ !*/
226
+
227
+ void swap (
228
+ array2d& item
229
+ );
230
+ /*!
231
+ ensures
232
+ - swaps *this and item
233
+ !*/
234
+
235
+ array2d& operator= (
236
+ array2d&& rhs
237
+ );
238
+ /*!
239
+ ensures
240
+ - Moves the state of item into *this.
241
+ - #item is in a valid but unspecified state.
242
+ - returns #*this
243
+ !*/
244
+
245
+ long width_step (
246
+ ) const;
247
+ /*!
248
+ ensures
249
+ - returns the size of one row of the image, in bytes.
250
+ More precisely, return a number N such that:
251
+ (char*)&item[0][0] + N == (char*)&item[1][0].
252
+ - for dlib::array2d objects, the returned value
253
+ is always equal to sizeof(type)*nc(). However,
254
+ other objects which implement dlib::array2d style
255
+ interfaces might have padding at the ends of their
256
+ rows and therefore might return larger numbers.
257
+ An example of such an object is the dlib::cv_image.
258
+ !*/
259
+
260
+ iterator begin(
261
+ );
262
+ /*!
263
+ ensures
264
+ - returns a random access iterator pointing to the first element in this
265
+ object.
266
+ - The iterator will iterate over the elements of the object in row major
267
+ order.
268
+ !*/
269
+
270
+ iterator end(
271
+ );
272
+ /*!
273
+ ensures
274
+ - returns a random access iterator pointing to one past the end of the last
275
+ element in this object.
276
+ !*/
277
+
278
+ const_iterator begin(
279
+ ) const;
280
+ /*!
281
+ ensures
282
+ - returns a random access iterator pointing to the first element in this
283
+ object.
284
+ - The iterator will iterate over the elements of the object in row major
285
+ order.
286
+ !*/
287
+
288
+ const_iterator end(
289
+ ) const;
290
+ /*!
291
+ ensures
292
+ - returns a random access iterator pointing to one past the end of the last
293
+ element in this object.
294
+ !*/
295
+
296
+ };
297
+
298
+ template <
299
+ typename T,
300
+ typename mem_manager
301
+ >
302
+ inline void swap (
303
+ array2d<T,mem_manager>& a,
304
+ array2d<T,mem_manager>& b
305
+ ) { a.swap(b); }
306
+ /*!
307
+ provides a global swap function
308
+ !*/
309
+
310
+ template <
311
+ typename T,
312
+ typename mem_manager
313
+ >
314
+ void serialize (
315
+ const array2d<T,mem_manager>& item,
316
+ std::ostream& out
317
+ );
318
+ /*!
319
+ Provides serialization support. Note that the serialization formats used by the
320
+ dlib::matrix and dlib::array2d objects are compatible. That means you can load the
321
+ serialized data from one into another and it will work properly.
322
+ !*/
323
+
324
+ template <
325
+ typename T,
326
+ typename mem_manager
327
+ >
328
+ void deserialize (
329
+ array2d<T,mem_manager>& item,
330
+ std::istream& in
331
+ );
332
+ /*!
333
+ provides deserialization support
334
+ !*/
335
+
336
+ }
337
+
338
+ #endif // DLIB_ARRAY2D_KERNEl_ABSTRACT_
339
+
dlibs/dlib/array2d/serialize_pixel_overloads.h ADDED
@@ -0,0 +1,371 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (C) 2006 Davis E. King ([email protected])
2
+ // License: Boost Software License See LICENSE.txt for the full license.
3
+ #ifndef DLIB_ARRAY2D_SERIALIZE_PIXEL_OvERLOADS_Hh_
4
+ #define DLIB_ARRAY2D_SERIALIZE_PIXEL_OvERLOADS_Hh_
5
+
6
+ #include "array2d_kernel.h"
7
+ #include "../pixel.h"
8
+
9
+ namespace dlib
10
+ {
11
+
12
+ // ----------------------------------------------------------------------------------------
13
+
14
+ /*
15
+ This file contains overloads of the serialize functions for array2d object
16
+ for the case where they contain simple 8bit POD pixel types. In these
17
+ cases we can perform a much faster serialization by writing data in chunks
18
+ instead of one pixel at a time (this avoids a lot of function call overhead
19
+ inside the iostreams).
20
+ */
21
+
22
+ // ----------------------------------------------------------------------------------------
23
+
24
+ template <
25
+ typename mem_manager
26
+ >
27
+ void serialize (
28
+ const array2d<rgb_pixel,mem_manager>& item,
29
+ std::ostream& out
30
+ )
31
+ {
32
+ try
33
+ {
34
+ // The reason the serialization is a little funny is because we are trying to
35
+ // maintain backwards compatibility with an older serialization format used by
36
+ // dlib while also encoding things in a way that lets the array2d and matrix
37
+ // objects have compatible serialization formats.
38
+ serialize(-item.nr(),out);
39
+ serialize(-item.nc(),out);
40
+
41
+ COMPILE_TIME_ASSERT(sizeof(rgb_pixel) == 3);
42
+
43
+ if (item.size() != 0)
44
+ out.write((char*)&item[0][0], sizeof(rgb_pixel)*item.size());
45
+ }
46
+ catch (serialization_error& e)
47
+ {
48
+ throw serialization_error(e.info + "\n while serializing object of type array2d");
49
+ }
50
+ }
51
+
52
+ template <
53
+ typename mem_manager
54
+ >
55
+ void deserialize (
56
+ array2d<rgb_pixel,mem_manager>& item,
57
+ std::istream& in
58
+ )
59
+ {
60
+ try
61
+ {
62
+ COMPILE_TIME_ASSERT(sizeof(rgb_pixel) == 3);
63
+
64
+ long nr, nc;
65
+ deserialize(nr,in);
66
+ deserialize(nc,in);
67
+
68
+ // this is the newer serialization format
69
+ if (nr < 0 || nc < 0)
70
+ {
71
+ nr *= -1;
72
+ nc *= -1;
73
+ }
74
+ else
75
+ {
76
+ std::swap(nr,nc);
77
+ }
78
+
79
+ item.set_size(nr,nc);
80
+
81
+ if (item.size() != 0)
82
+ in.read((char*)&item[0][0], sizeof(rgb_pixel)*item.size());
83
+ }
84
+ catch (serialization_error& e)
85
+ {
86
+ item.clear();
87
+ throw serialization_error(e.info + "\n while deserializing object of type array2d");
88
+ }
89
+ }
90
+
91
+ // ----------------------------------------------------------------------------------------
92
+
93
+ template <
94
+ typename mem_manager
95
+ >
96
+ void serialize (
97
+ const array2d<bgr_pixel,mem_manager>& item,
98
+ std::ostream& out
99
+ )
100
+ {
101
+ try
102
+ {
103
+ // The reason the serialization is a little funny is because we are trying to
104
+ // maintain backwards compatibility with an older serialization format used by
105
+ // dlib while also encoding things in a way that lets the array2d and matrix
106
+ // objects have compatible serialization formats.
107
+ serialize(-item.nr(),out);
108
+ serialize(-item.nc(),out);
109
+
110
+ COMPILE_TIME_ASSERT(sizeof(bgr_pixel) == 3);
111
+
112
+ if (item.size() != 0)
113
+ out.write((char*)&item[0][0], sizeof(bgr_pixel)*item.size());
114
+ }
115
+ catch (serialization_error& e)
116
+ {
117
+ throw serialization_error(e.info + "\n while serializing object of type array2d");
118
+ }
119
+ }
120
+
121
+ template <
122
+ typename mem_manager
123
+ >
124
+ void deserialize (
125
+ array2d<bgr_pixel,mem_manager>& item,
126
+ std::istream& in
127
+ )
128
+ {
129
+ try
130
+ {
131
+ COMPILE_TIME_ASSERT(sizeof(bgr_pixel) == 3);
132
+
133
+ long nr, nc;
134
+ deserialize(nr,in);
135
+ deserialize(nc,in);
136
+
137
+ // this is the newer serialization format
138
+ if (nr < 0 || nc < 0)
139
+ {
140
+ nr *= -1;
141
+ nc *= -1;
142
+ }
143
+ else
144
+ {
145
+ std::swap(nr,nc);
146
+ }
147
+
148
+
149
+ item.set_size(nr,nc);
150
+
151
+ if (item.size() != 0)
152
+ in.read((char*)&item[0][0], sizeof(bgr_pixel)*item.size());
153
+ }
154
+ catch (serialization_error& e)
155
+ {
156
+ item.clear();
157
+ throw serialization_error(e.info + "\n while deserializing object of type array2d");
158
+ }
159
+ }
160
+
161
+ // ----------------------------------------------------------------------------------------
162
+
163
+ template <
164
+ typename mem_manager
165
+ >
166
+ void serialize (
167
+ const array2d<hsi_pixel,mem_manager>& item,
168
+ std::ostream& out
169
+ )
170
+ {
171
+ try
172
+ {
173
+ // The reason the serialization is a little funny is because we are trying to
174
+ // maintain backwards compatibility with an older serialization format used by
175
+ // dlib while also encoding things in a way that lets the array2d and matrix
176
+ // objects have compatible serialization formats.
177
+ serialize(-item.nr(),out);
178
+ serialize(-item.nc(),out);
179
+
180
+ COMPILE_TIME_ASSERT(sizeof(hsi_pixel) == 3);
181
+
182
+ if (item.size() != 0)
183
+ out.write((char*)&item[0][0], sizeof(hsi_pixel)*item.size());
184
+ }
185
+ catch (serialization_error& e)
186
+ {
187
+ throw serialization_error(e.info + "\n while serializing object of type array2d");
188
+ }
189
+ }
190
+
191
+ template <
192
+ typename mem_manager
193
+ >
194
+ void deserialize (
195
+ array2d<hsi_pixel,mem_manager>& item,
196
+ std::istream& in
197
+ )
198
+ {
199
+ try
200
+ {
201
+ COMPILE_TIME_ASSERT(sizeof(hsi_pixel) == 3);
202
+
203
+ long nr, nc;
204
+ deserialize(nr,in);
205
+ deserialize(nc,in);
206
+
207
+ // this is the newer serialization format
208
+ if (nr < 0 || nc < 0)
209
+ {
210
+ nr *= -1;
211
+ nc *= -1;
212
+ }
213
+ else
214
+ {
215
+ std::swap(nr,nc);
216
+ }
217
+
218
+
219
+ item.set_size(nr,nc);
220
+
221
+ if (item.size() != 0)
222
+ in.read((char*)&item[0][0], sizeof(hsi_pixel)*item.size());
223
+ }
224
+ catch (serialization_error& e)
225
+ {
226
+ item.clear();
227
+ throw serialization_error(e.info + "\n while deserializing object of type array2d");
228
+ }
229
+ }
230
+
231
+ // ----------------------------------------------------------------------------------------
232
+
233
+ template <
234
+ typename mem_manager
235
+ >
236
+ void serialize (
237
+ const array2d<rgb_alpha_pixel,mem_manager>& item,
238
+ std::ostream& out
239
+ )
240
+ {
241
+ try
242
+ {
243
+ // The reason the serialization is a little funny is because we are trying to
244
+ // maintain backwards compatibility with an older serialization format used by
245
+ // dlib while also encoding things in a way that lets the array2d and matrix
246
+ // objects have compatible serialization formats.
247
+ serialize(-item.nr(),out);
248
+ serialize(-item.nc(),out);
249
+
250
+ COMPILE_TIME_ASSERT(sizeof(rgb_alpha_pixel) == 4);
251
+
252
+ if (item.size() != 0)
253
+ out.write((char*)&item[0][0], sizeof(rgb_alpha_pixel)*item.size());
254
+ }
255
+ catch (serialization_error& e)
256
+ {
257
+ throw serialization_error(e.info + "\n while serializing object of type array2d");
258
+ }
259
+ }
260
+
261
+ template <
262
+ typename mem_manager
263
+ >
264
+ void deserialize (
265
+ array2d<rgb_alpha_pixel,mem_manager>& item,
266
+ std::istream& in
267
+ )
268
+ {
269
+ try
270
+ {
271
+ COMPILE_TIME_ASSERT(sizeof(rgb_alpha_pixel) == 4);
272
+
273
+ long nr, nc;
274
+ deserialize(nr,in);
275
+ deserialize(nc,in);
276
+
277
+ // this is the newer serialization format
278
+ if (nr < 0 || nc < 0)
279
+ {
280
+ nr *= -1;
281
+ nc *= -1;
282
+ }
283
+ else
284
+ {
285
+ std::swap(nr,nc);
286
+ }
287
+
288
+
289
+ item.set_size(nr,nc);
290
+
291
+ if (item.size() != 0)
292
+ in.read((char*)&item[0][0], sizeof(rgb_alpha_pixel)*item.size());
293
+ }
294
+ catch (serialization_error& e)
295
+ {
296
+ item.clear();
297
+ throw serialization_error(e.info + "\n while deserializing object of type array2d");
298
+ }
299
+ }
300
+
301
+ // ----------------------------------------------------------------------------------------
302
+
303
+ template <
304
+ typename mem_manager
305
+ >
306
+ void serialize (
307
+ const array2d<unsigned char,mem_manager>& item,
308
+ std::ostream& out
309
+ )
310
+ {
311
+ try
312
+ {
313
+ // The reason the serialization is a little funny is because we are trying to
314
+ // maintain backwards compatibility with an older serialization format used by
315
+ // dlib while also encoding things in a way that lets the array2d and matrix
316
+ // objects have compatible serialization formats.
317
+ serialize(-item.nr(),out);
318
+ serialize(-item.nc(),out);
319
+
320
+ if (item.size() != 0)
321
+ out.write((char*)&item[0][0], sizeof(unsigned char)*item.size());
322
+ }
323
+ catch (serialization_error& e)
324
+ {
325
+ throw serialization_error(e.info + "\n while serializing object of type array2d");
326
+ }
327
+ }
328
+
329
+ template <
330
+ typename mem_manager
331
+ >
332
+ void deserialize (
333
+ array2d<unsigned char,mem_manager>& item,
334
+ std::istream& in
335
+ )
336
+ {
337
+ try
338
+ {
339
+ long nr, nc;
340
+ deserialize(nr,in);
341
+ deserialize(nc,in);
342
+ // this is the newer serialization format
343
+ if (nr < 0 || nc < 0)
344
+ {
345
+ nr *= -1;
346
+ nc *= -1;
347
+ }
348
+ else
349
+ {
350
+ std::swap(nr,nc);
351
+ }
352
+
353
+
354
+ item.set_size(nr,nc);
355
+
356
+ if (item.size() != 0)
357
+ in.read((char*)&item[0][0], sizeof(unsigned char)*item.size());
358
+ }
359
+ catch (serialization_error& e)
360
+ {
361
+ item.clear();
362
+ throw serialization_error(e.info + "\n while deserializing object of type array2d");
363
+ }
364
+ }
365
+
366
+ // ----------------------------------------------------------------------------------------
367
+
368
+ }
369
+
370
+ #endif // DLIB_ARRAY2D_SERIALIZE_PIXEL_OvERLOADS_Hh_
371
+
dlibs/dlib/assert.h ADDED
@@ -0,0 +1,217 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (C) 2003 Davis E. King ([email protected])
2
+ // License: Boost Software License See LICENSE.txt for the full license.
3
+ #ifndef DLIB_ASSERt_
4
+ #define DLIB_ASSERt_
5
+
6
+ #include "config.h"
7
+ #include <sstream>
8
+ #include <iosfwd>
9
+ #include "error.h"
10
+
11
+ // -----------------------------
12
+
13
+ // Use some stuff from boost here
14
+ // (C) Copyright John Maddock 2001 - 2003.
15
+ // (C) Copyright Darin Adler 2001.
16
+ // (C) Copyright Peter Dimov 2001.
17
+ // (C) Copyright Bill Kempf 2002.
18
+ // (C) Copyright Jens Maurer 2002.
19
+ // (C) Copyright David Abrahams 2002 - 2003.
20
+ // (C) Copyright Gennaro Prota 2003.
21
+ // (C) Copyright Eric Friedman 2003.
22
+ // License: Boost Software License See LICENSE.txt for the full license.
23
+ //
24
+ #ifndef DLIB_BOOST_JOIN
25
+ #define DLIB_BOOST_JOIN( X, Y ) DLIB_BOOST_DO_JOIN( X, Y )
26
+ #define DLIB_BOOST_DO_JOIN( X, Y ) DLIB_BOOST_DO_JOIN2(X,Y)
27
+ #define DLIB_BOOST_DO_JOIN2( X, Y ) X##Y
28
+ #endif
29
+
30
+ // figure out if the compiler has rvalue references.
31
+ #if defined(__clang__)
32
+ # if __has_feature(cxx_rvalue_references)
33
+ # define DLIB_HAS_RVALUE_REFERENCES
34
+ # endif
35
+ # if __has_feature(cxx_generalized_initializers)
36
+ # define DLIB_HAS_INITIALIZER_LISTS
37
+ # endif
38
+ #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 2)) && defined(__GXX_EXPERIMENTAL_CXX0X__)
39
+ # define DLIB_HAS_RVALUE_REFERENCES
40
+ # define DLIB_HAS_INITIALIZER_LISTS
41
+ #elif defined(_MSC_VER) && _MSC_VER >= 1800
42
+ # define DLIB_HAS_INITIALIZER_LISTS
43
+ # define DLIB_HAS_RVALUE_REFERENCES
44
+ #elif defined(_MSC_VER) && _MSC_VER >= 1600
45
+ # define DLIB_HAS_RVALUE_REFERENCES
46
+ #elif defined(__INTEL_COMPILER) && defined(BOOST_INTEL_STDCXX0X)
47
+ # define DLIB_HAS_RVALUE_REFERENCES
48
+ # define DLIB_HAS_INITIALIZER_LISTS
49
+ #endif
50
+
51
+ #if defined(__APPLE__) && defined(__GNUC_LIBSTD__) && ((__GNUC_LIBSTD__-0) * 100 + __GNUC_LIBSTD_MINOR__-0 <= 402)
52
+ // Apple has not updated libstdc++ in some time and anything under 4.02 does not have <initializer_list> for sure.
53
+ # undef DLIB_HAS_INITIALIZER_LISTS
54
+ #endif
55
+
56
+ // figure out if the compiler has static_assert.
57
+ #if defined(__clang__)
58
+ # if __has_feature(cxx_static_assert)
59
+ # define DLIB_HAS_STATIC_ASSERT
60
+ # endif
61
+ #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 2)) && defined(__GXX_EXPERIMENTAL_CXX0X__)
62
+ # define DLIB_HAS_STATIC_ASSERT
63
+ #elif defined(_MSC_VER) && _MSC_VER >= 1600
64
+ # define DLIB_HAS_STATIC_ASSERT
65
+ #elif defined(__INTEL_COMPILER) && defined(BOOST_INTEL_STDCXX0X)
66
+ # define DLIB_HAS_STATIC_ASSERT
67
+ #endif
68
+
69
+
70
+ // -----------------------------
71
+
72
+ namespace dlib
73
+ {
74
+ template <bool value> struct compile_time_assert;
75
+ template <> struct compile_time_assert<true> { enum {value=1}; };
76
+
77
+ template <typename T, typename U> struct assert_are_same_type;
78
+ template <typename T> struct assert_are_same_type<T,T> {enum{value=1};};
79
+ template <typename T, typename U> struct assert_are_not_same_type {enum{value=1}; };
80
+ template <typename T> struct assert_are_not_same_type<T,T> {};
81
+
82
+ template <typename T, typename U> struct assert_types_match {enum{value=0};};
83
+ template <typename T> struct assert_types_match<T,T> {enum{value=1};};
84
+ }
85
+
86
+
87
+ // gcc 4.8 will warn about unused typedefs. But we use typedefs in some of the compile
88
+ // time assert macros so we need to make it not complain about them "not being used".
89
+ #ifdef __GNUC__
90
+ #define DLIB_NO_WARN_UNUSED __attribute__ ((unused))
91
+ #else
92
+ #define DLIB_NO_WARN_UNUSED
93
+ #endif
94
+
95
+ // Use the newer static_assert if it's available since it produces much more readable error
96
+ // messages.
97
+ #ifdef DLIB_HAS_STATIC_ASSERT
98
+ #define COMPILE_TIME_ASSERT(expression) static_assert(expression, "Failed assertion")
99
+ #define ASSERT_ARE_SAME_TYPE(type1, type2) static_assert(::dlib::assert_types_match<type1,type2>::value, "These types should be the same but aren't.")
100
+ #define ASSERT_ARE_NOT_SAME_TYPE(type1, type2) static_assert(!::dlib::assert_types_match<type1,type2>::value, "These types should NOT be the same.")
101
+ #else
102
+ #define COMPILE_TIME_ASSERT(expression) \
103
+ DLIB_NO_WARN_UNUSED typedef char DLIB_BOOST_JOIN(DLIB_CTA, __LINE__)[::dlib::compile_time_assert<(bool)(expression)>::value]
104
+
105
+ #define ASSERT_ARE_SAME_TYPE(type1, type2) \
106
+ DLIB_NO_WARN_UNUSED typedef char DLIB_BOOST_JOIN(DLIB_AAST, __LINE__)[::dlib::assert_are_same_type<type1,type2>::value]
107
+
108
+ #define ASSERT_ARE_NOT_SAME_TYPE(type1, type2) \
109
+ DLIB_NO_WARN_UNUSED typedef char DLIB_BOOST_JOIN(DLIB_AANST, __LINE__)[::dlib::assert_are_not_same_type<type1,type2>::value]
110
+ #endif
111
+
112
+ // -----------------------------
113
+
114
+ #if defined DLIB_DISABLE_ASSERTS
115
+ // if DLIB_DISABLE_ASSERTS is on then never enable DLIB_ASSERT no matter what.
116
+ #undef ENABLE_ASSERTS
117
+ #endif
118
+
119
+ #if !defined(DLIB_DISABLE_ASSERTS) && ( defined DEBUG || defined _DEBUG)
120
+ // make sure ENABLE_ASSERTS is defined if we are indeed using them.
121
+ #ifndef ENABLE_ASSERTS
122
+ #define ENABLE_ASSERTS
123
+ #endif
124
+ #endif
125
+
126
+ // -----------------------------
127
+
128
+ #ifdef __GNUC__
129
+ // There is a bug in version 4.4.5 of GCC on Ubuntu which causes GCC to segfault
130
+ // when __PRETTY_FUNCTION__ is used within certain templated functions. So just
131
+ // don't use it with this version of GCC.
132
+ # if !(__GNUC__ == 4 && __GNUC_MINOR__ == 4 && __GNUC_PATCHLEVEL__ == 5)
133
+ # define DLIB_FUNCTION_NAME __PRETTY_FUNCTION__
134
+ # else
135
+ # define DLIB_FUNCTION_NAME "unknown function"
136
+ # endif
137
+ #elif defined(_MSC_VER)
138
+ #define DLIB_FUNCTION_NAME __FUNCSIG__
139
+ #else
140
+ #define DLIB_FUNCTION_NAME "unknown function"
141
+ #endif
142
+
143
+ #define DLIBM_CASSERT(_exp,_message) \
144
+ {if ( !(_exp) ) \
145
+ { \
146
+ dlib_assert_breakpoint(); \
147
+ std::ostringstream dlib_o_out; \
148
+ dlib_o_out << "\n\nError detected at line " << __LINE__ << ".\n"; \
149
+ dlib_o_out << "Error detected in file " << __FILE__ << ".\n"; \
150
+ dlib_o_out << "Error detected in function " << DLIB_FUNCTION_NAME << ".\n\n"; \
151
+ dlib_o_out << "Failing expression was " << #_exp << ".\n"; \
152
+ dlib_o_out << std::boolalpha << _message << "\n"; \
153
+ throw dlib::fatal_error(dlib::EBROKEN_ASSERT,dlib_o_out.str()); \
154
+ }}
155
+
156
+ // This macro is not needed if you have a real C++ compiler. It's here to work around bugs in Visual Studio's preprocessor.
157
+ #define DLIB_WORKAROUND_VISUAL_STUDIO_BUGS(x) x
158
+ // Make it so the 2nd argument of DLIB_CASSERT is optional. That is, you can call it like
159
+ // DLIB_CASSERT(exp) or DLIB_CASSERT(exp,message).
160
+ #define DLIBM_CASSERT_1_ARGS(exp) DLIBM_CASSERT(exp,"")
161
+ #define DLIBM_CASSERT_2_ARGS(exp,message) DLIBM_CASSERT(exp,message)
162
+ #define DLIBM_GET_3TH_ARG(arg1, arg2, arg3, ...) arg3
163
+ #define DLIBM_CASSERT_CHOOSER(...) DLIB_WORKAROUND_VISUAL_STUDIO_BUGS(DLIBM_GET_3TH_ARG(__VA_ARGS__, DLIBM_CASSERT_2_ARGS, DLIBM_CASSERT_1_ARGS, DLIB_CASSERT_NEVER_USED))
164
+ #define DLIB_CASSERT(...) DLIB_WORKAROUND_VISUAL_STUDIO_BUGS(DLIBM_CASSERT_CHOOSER(__VA_ARGS__)(__VA_ARGS__))
165
+
166
+
167
+ #ifdef ENABLE_ASSERTS
168
+ #define DLIB_ASSERT(...) DLIB_CASSERT(__VA_ARGS__)
169
+ #define DLIB_IF_ASSERT(exp) exp
170
+ #else
171
+ #define DLIB_ASSERT(...) {}
172
+ #define DLIB_IF_ASSERT(exp)
173
+ #endif
174
+
175
+ // ----------------------------------------------------------------------------------------
176
+
177
+ /*!A DLIB_ASSERT_HAS_STANDARD_LAYOUT
178
+
179
+ This macro is meant to cause a compiler error if a type doesn't have a simple
180
+ memory layout (like a C struct). In particular, types with simple layouts are
181
+ ones which can be copied via memcpy().
182
+
183
+
184
+ This was called a POD type in C++03 and in C++0x we are looking to check if
185
+ it is a "standard layout type". Once we can use C++0x we can change this macro
186
+ to something that uses the std::is_standard_layout type_traits class.
187
+ See: http://www2.research.att.com/~bs/C++0xFAQ.html#PODs
188
+ !*/
189
+ // Use the fact that in C++03 you can't put non-PODs into a union.
190
+ #define DLIB_ASSERT_HAS_STANDARD_LAYOUT(type) \
191
+ union DLIB_BOOST_JOIN(DAHSL_,__LINE__) { type TYPE_NOT_STANDARD_LAYOUT; }; \
192
+ DLIB_NO_WARN_UNUSED typedef char DLIB_BOOST_JOIN(DAHSL2_,__LINE__)[sizeof(DLIB_BOOST_JOIN(DAHSL_,__LINE__))];
193
+
194
+ // ----------------------------------------------------------------------------------------
195
+ // ----------------------------------------------------------------------------------------
196
+ // ----------------------------------------------------------------------------------------
197
+
198
+ // breakpoints
199
+ extern "C"
200
+ {
201
+ inline void dlib_assert_breakpoint(
202
+ ) {}
203
+ /*!
204
+ ensures
205
+ - this function does nothing
206
+ It exists just so you can put breakpoints on it in a debugging tool.
207
+ It is called only when an DLIB_ASSERT or DLIB_CASSERT fails and is about to
208
+ throw an exception.
209
+ !*/
210
+ }
211
+
212
+ // -----------------------------
213
+
214
+ #include "stack_trace.h"
215
+
216
+ #endif // DLIB_ASSERt_
217
+
dlibs/dlib/base64.h ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (C) 2006 Davis E. King ([email protected])
2
+ // License: Boost Software License See LICENSE.txt for the full license.
3
+ #ifndef DLIB_BASe64_
4
+ #define DLIB_BASe64_
5
+
6
+ #include "base64/base64_kernel_1.h"
7
+
8
+ #endif // DLIB_BASe64_
9
+
dlibs/dlib/base64/base64_kernel_1.cpp ADDED
@@ -0,0 +1,403 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (C) 2006 Davis E. King ([email protected])
2
+ // License: Boost Software License See LICENSE.txt for the full license.
3
+ #ifndef DLIB_BASE64_KERNEL_1_CPp_
4
+ #define DLIB_BASE64_KERNEL_1_CPp_
5
+
6
+ #include "base64_kernel_1.h"
7
+ #include <iostream>
8
+ #include <sstream>
9
+ #include <climits>
10
+
11
+ namespace dlib
12
+ {
13
+
14
+ // ----------------------------------------------------------------------------------------
15
+
16
+ base64::line_ending_type base64::
17
+ line_ending (
18
+ ) const
19
+ {
20
+ return eol_style;
21
+ }
22
+
23
+ // ----------------------------------------------------------------------------------------
24
+
25
+ void base64::
26
+ set_line_ending (
27
+ line_ending_type eol_style_
28
+ )
29
+ {
30
+ eol_style = eol_style_;
31
+ }
32
+
33
+ // ----------------------------------------------------------------------------------------
34
+
35
+ base64::
36
+ base64 (
37
+ ) :
38
+ encode_table(0),
39
+ decode_table(0),
40
+ bad_value(100),
41
+ eol_style(LF)
42
+ {
43
+ try
44
+ {
45
+ encode_table = new char[64];
46
+ decode_table = new unsigned char[UCHAR_MAX];
47
+ }
48
+ catch (...)
49
+ {
50
+ if (encode_table) delete [] encode_table;
51
+ if (decode_table) delete [] decode_table;
52
+ throw;
53
+ }
54
+
55
+ // now set up the tables with the right stuff
56
+ encode_table[0] = 'A';
57
+ encode_table[17] = 'R';
58
+ encode_table[34] = 'i';
59
+ encode_table[51] = 'z';
60
+
61
+ encode_table[1] = 'B';
62
+ encode_table[18] = 'S';
63
+ encode_table[35] = 'j';
64
+ encode_table[52] = '0';
65
+
66
+ encode_table[2] = 'C';
67
+ encode_table[19] = 'T';
68
+ encode_table[36] = 'k';
69
+ encode_table[53] = '1';
70
+
71
+ encode_table[3] = 'D';
72
+ encode_table[20] = 'U';
73
+ encode_table[37] = 'l';
74
+ encode_table[54] = '2';
75
+
76
+ encode_table[4] = 'E';
77
+ encode_table[21] = 'V';
78
+ encode_table[38] = 'm';
79
+ encode_table[55] = '3';
80
+
81
+ encode_table[5] = 'F';
82
+ encode_table[22] = 'W';
83
+ encode_table[39] = 'n';
84
+ encode_table[56] = '4';
85
+
86
+ encode_table[6] = 'G';
87
+ encode_table[23] = 'X';
88
+ encode_table[40] = 'o';
89
+ encode_table[57] = '5';
90
+
91
+ encode_table[7] = 'H';
92
+ encode_table[24] = 'Y';
93
+ encode_table[41] = 'p';
94
+ encode_table[58] = '6';
95
+
96
+ encode_table[8] = 'I';
97
+ encode_table[25] = 'Z';
98
+ encode_table[42] = 'q';
99
+ encode_table[59] = '7';
100
+
101
+ encode_table[9] = 'J';
102
+ encode_table[26] = 'a';
103
+ encode_table[43] = 'r';
104
+ encode_table[60] = '8';
105
+
106
+ encode_table[10] = 'K';
107
+ encode_table[27] = 'b';
108
+ encode_table[44] = 's';
109
+ encode_table[61] = '9';
110
+
111
+ encode_table[11] = 'L';
112
+ encode_table[28] = 'c';
113
+ encode_table[45] = 't';
114
+ encode_table[62] = '+';
115
+
116
+ encode_table[12] = 'M';
117
+ encode_table[29] = 'd';
118
+ encode_table[46] = 'u';
119
+ encode_table[63] = '/';
120
+
121
+ encode_table[13] = 'N';
122
+ encode_table[30] = 'e';
123
+ encode_table[47] = 'v';
124
+
125
+ encode_table[14] = 'O';
126
+ encode_table[31] = 'f';
127
+ encode_table[48] = 'w';
128
+
129
+ encode_table[15] = 'P';
130
+ encode_table[32] = 'g';
131
+ encode_table[49] = 'x';
132
+
133
+ encode_table[16] = 'Q';
134
+ encode_table[33] = 'h';
135
+ encode_table[50] = 'y';
136
+
137
+
138
+
139
+ // we can now fill out the decode_table by using the encode_table
140
+ for (int i = 0; i < UCHAR_MAX; ++i)
141
+ {
142
+ decode_table[i] = bad_value;
143
+ }
144
+ for (unsigned char i = 0; i < 64; ++i)
145
+ {
146
+ decode_table[(unsigned char)encode_table[i]] = i;
147
+ }
148
+ }
149
+
150
+ // ----------------------------------------------------------------------------------------
151
+
152
+ base64::
153
+ ~base64 (
154
+ )
155
+ {
156
+ delete [] encode_table;
157
+ delete [] decode_table;
158
+ }
159
+
160
+ // ----------------------------------------------------------------------------------------
161
+
162
+ void base64::
163
+ encode (
164
+ std::istream& in_,
165
+ std::ostream& out_
166
+ ) const
167
+ {
168
+ using namespace std;
169
+ streambuf& in = *in_.rdbuf();
170
+ streambuf& out = *out_.rdbuf();
171
+
172
+ unsigned char inbuf[3];
173
+ unsigned char outbuf[4];
174
+ streamsize status = in.sgetn(reinterpret_cast<char*>(&inbuf),3);
175
+
176
+ unsigned char c1, c2, c3, c4, c5, c6;
177
+
178
+ int counter = 19;
179
+
180
+ // while we haven't hit the end of the input stream
181
+ while (status != 0)
182
+ {
183
+ if (counter == 0)
184
+ {
185
+ counter = 19;
186
+ // write a newline
187
+ char ch;
188
+ switch (eol_style)
189
+ {
190
+ case CR:
191
+ ch = '\r';
192
+ if (out.sputn(&ch,1)!=1)
193
+ throw std::ios_base::failure("error occurred in the base64 object");
194
+ break;
195
+ case LF:
196
+ ch = '\n';
197
+ if (out.sputn(&ch,1)!=1)
198
+ throw std::ios_base::failure("error occurred in the base64 object");
199
+ break;
200
+ case CRLF:
201
+ ch = '\r';
202
+ if (out.sputn(&ch,1)!=1)
203
+ throw std::ios_base::failure("error occurred in the base64 object");
204
+ ch = '\n';
205
+ if (out.sputn(&ch,1)!=1)
206
+ throw std::ios_base::failure("error occurred in the base64 object");
207
+ break;
208
+ default:
209
+ DLIB_CASSERT(false,"this should never happen");
210
+ }
211
+ }
212
+ --counter;
213
+
214
+ if (status == 3)
215
+ {
216
+ // encode the bytes in inbuf to base64 and write them to the output stream
217
+ c1 = inbuf[0]&0xfc;
218
+ c2 = inbuf[0]&0x03;
219
+ c3 = inbuf[1]&0xf0;
220
+ c4 = inbuf[1]&0x0f;
221
+ c5 = inbuf[2]&0xc0;
222
+ c6 = inbuf[2]&0x3f;
223
+
224
+ outbuf[0] = c1>>2;
225
+ outbuf[1] = (c2<<4)|(c3>>4);
226
+ outbuf[2] = (c4<<2)|(c5>>6);
227
+ outbuf[3] = c6;
228
+
229
+
230
+ outbuf[0] = encode_table[outbuf[0]];
231
+ outbuf[1] = encode_table[outbuf[1]];
232
+ outbuf[2] = encode_table[outbuf[2]];
233
+ outbuf[3] = encode_table[outbuf[3]];
234
+
235
+ // write the encoded bytes to the output stream
236
+ if (out.sputn(reinterpret_cast<char*>(&outbuf),4)!=4)
237
+ {
238
+ throw std::ios_base::failure("error occurred in the base64 object");
239
+ }
240
+
241
+ // get 3 more input bytes
242
+ status = in.sgetn(reinterpret_cast<char*>(&inbuf),3);
243
+ continue;
244
+ }
245
+ else if (status == 2)
246
+ {
247
+ // we are at the end of the input stream and need to add some padding
248
+
249
+ // encode the bytes in inbuf to base64 and write them to the output stream
250
+ c1 = inbuf[0]&0xfc;
251
+ c2 = inbuf[0]&0x03;
252
+ c3 = inbuf[1]&0xf0;
253
+ c4 = inbuf[1]&0x0f;
254
+ c5 = 0;
255
+
256
+ outbuf[0] = c1>>2;
257
+ outbuf[1] = (c2<<4)|(c3>>4);
258
+ outbuf[2] = (c4<<2)|(c5>>6);
259
+ outbuf[3] = '=';
260
+
261
+ outbuf[0] = encode_table[outbuf[0]];
262
+ outbuf[1] = encode_table[outbuf[1]];
263
+ outbuf[2] = encode_table[outbuf[2]];
264
+
265
+ // write the encoded bytes to the output stream
266
+ if (out.sputn(reinterpret_cast<char*>(&outbuf),4)!=4)
267
+ {
268
+ throw std::ios_base::failure("error occurred in the base64 object");
269
+ }
270
+
271
+
272
+ break;
273
+ }
274
+ else // in this case status must be 1
275
+ {
276
+ // we are at the end of the input stream and need to add some padding
277
+
278
+ // encode the bytes in inbuf to base64 and write them to the output stream
279
+ c1 = inbuf[0]&0xfc;
280
+ c2 = inbuf[0]&0x03;
281
+ c3 = 0;
282
+
283
+ outbuf[0] = c1>>2;
284
+ outbuf[1] = (c2<<4)|(c3>>4);
285
+ outbuf[2] = '=';
286
+ outbuf[3] = '=';
287
+
288
+ outbuf[0] = encode_table[outbuf[0]];
289
+ outbuf[1] = encode_table[outbuf[1]];
290
+
291
+
292
+ // write the encoded bytes to the output stream
293
+ if (out.sputn(reinterpret_cast<char*>(&outbuf),4)!=4)
294
+ {
295
+ throw std::ios_base::failure("error occurred in the base64 object");
296
+ }
297
+
298
+ break;
299
+ }
300
+ } // while (status != 0)
301
+
302
+
303
+ // make sure the stream buffer flushes to its I/O channel
304
+ out.pubsync();
305
+ }
306
+
307
+ // ----------------------------------------------------------------------------------------
308
+
309
+ void base64::
310
+ decode (
311
+ std::istream& in_,
312
+ std::ostream& out_
313
+ ) const
314
+ {
315
+ using namespace std;
316
+ streambuf& in = *in_.rdbuf();
317
+ streambuf& out = *out_.rdbuf();
318
+
319
+ unsigned char inbuf[4];
320
+ unsigned char outbuf[3];
321
+ int inbuf_pos = 0;
322
+ streamsize status = in.sgetn(reinterpret_cast<char*>(inbuf),1);
323
+
324
+ // only count this character if it isn't some kind of filler
325
+ if (status == 1 && decode_table[inbuf[0]] != bad_value )
326
+ ++inbuf_pos;
327
+
328
+ unsigned char c1, c2, c3, c4, c5, c6;
329
+ streamsize outsize;
330
+
331
+ // while we haven't hit the end of the input stream
332
+ while (status != 0)
333
+ {
334
+ // if we have 4 valid characters
335
+ if (inbuf_pos == 4)
336
+ {
337
+ inbuf_pos = 0;
338
+
339
+ // this might be the end of the encoded data so we need to figure out if
340
+ // there was any padding applied.
341
+ outsize = 3;
342
+ if (inbuf[3] == '=')
343
+ {
344
+ if (inbuf[2] == '=')
345
+ outsize = 1;
346
+ else
347
+ outsize = 2;
348
+ }
349
+
350
+ // decode the incoming characters
351
+ inbuf[0] = decode_table[inbuf[0]];
352
+ inbuf[1] = decode_table[inbuf[1]];
353
+ inbuf[2] = decode_table[inbuf[2]];
354
+ inbuf[3] = decode_table[inbuf[3]];
355
+
356
+
357
+ // now pack these guys into bytes rather than 6 bit chunks
358
+ c1 = inbuf[0]<<2;
359
+ c2 = inbuf[1]>>4;
360
+ c3 = inbuf[1]<<4;
361
+ c4 = inbuf[2]>>2;
362
+ c5 = inbuf[2]<<6;
363
+ c6 = inbuf[3];
364
+
365
+ outbuf[0] = c1|c2;
366
+ outbuf[1] = c3|c4;
367
+ outbuf[2] = c5|c6;
368
+
369
+
370
+ // write the encoded bytes to the output stream
371
+ if (out.sputn(reinterpret_cast<char*>(&outbuf),outsize)!=outsize)
372
+ {
373
+ throw std::ios_base::failure("error occurred in the base64 object");
374
+ }
375
+ }
376
+
377
+ // get more input characters
378
+ status = in.sgetn(reinterpret_cast<char*>(inbuf + inbuf_pos),1);
379
+ // only count this character if it isn't some kind of filler
380
+ if ((decode_table[inbuf[inbuf_pos]] != bad_value || inbuf[inbuf_pos] == '=') &&
381
+ status != 0)
382
+ ++inbuf_pos;
383
+ } // while (status != 0)
384
+
385
+ if (inbuf_pos != 0)
386
+ {
387
+ ostringstream sout;
388
+ sout << inbuf_pos << " extra characters were found at the end of the encoded data."
389
+ << " This may indicate that the data stream has been truncated.";
390
+ // this happens if we hit EOF in the middle of decoding a 24bit block.
391
+ throw decode_error(sout.str());
392
+ }
393
+
394
+ // make sure the stream buffer flushes to its I/O channel
395
+ out.pubsync();
396
+ }
397
+
398
+ // ----------------------------------------------------------------------------------------
399
+
400
+ }
401
+
402
+ #endif // DLIB_BASE64_KERNEL_1_CPp_
403
+
dlibs/dlib/base64/base64_kernel_1.h ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (C) 2006 Davis E. King ([email protected])
2
+ // License: Boost Software License See LICENSE.txt for the full license.
3
+ #ifndef DLIB_BASE64_KERNEl_1_
4
+ #define DLIB_BASE64_KERNEl_1_
5
+
6
+ #include "../algs.h"
7
+ #include "base64_kernel_abstract.h"
8
+ #include <iosfwd>
9
+
10
+ namespace dlib
11
+ {
12
+
13
+ class base64
14
+ {
15
+ /*!
16
+ INITIAL VALUE
17
+ - bad_value == 100
18
+ - encode_table == a pointer to an array of 64 chars
19
+ - where x is a 6 bit value the following is true:
20
+ - encode_table[x] == the base64 encoding of x
21
+ - decode_table == a pointer to an array of UCHAR_MAX chars
22
+ - where x is any char value:
23
+ - if (x is a valid character in the base64 coding scheme) then
24
+ - decode_table[x] == the 6 bit value that x encodes
25
+ - else
26
+ - decode_table[x] == bad_value
27
+
28
+ CONVENTION
29
+ - The state of this object never changes so just refer to its
30
+ initial value.
31
+
32
+
33
+ !*/
34
+
35
+ public:
36
+ // this is here for backwards compatibility with older versions of dlib.
37
+ typedef base64 kernel_1a;
38
+
39
+ class decode_error : public dlib::error { public:
40
+ decode_error( const std::string& e) : error(e) {}};
41
+
42
+ base64 (
43
+ );
44
+
45
+ virtual ~base64 (
46
+ );
47
+
48
+ enum line_ending_type
49
+ {
50
+ CR, // i.e. "\r"
51
+ LF, // i.e. "\n"
52
+ CRLF // i.e. "\r\n"
53
+ };
54
+
55
+ line_ending_type line_ending (
56
+ ) const;
57
+
58
+ void set_line_ending (
59
+ line_ending_type eol_style_
60
+ );
61
+
62
+ void encode (
63
+ std::istream& in,
64
+ std::ostream& out
65
+ ) const;
66
+
67
+ void decode (
68
+ std::istream& in,
69
+ std::ostream& out
70
+ ) const;
71
+
72
+ private:
73
+
74
+ char* encode_table;
75
+ unsigned char* decode_table;
76
+ const unsigned char bad_value;
77
+ line_ending_type eol_style;
78
+
79
+ // restricted functions
80
+ base64(base64&); // copy constructor
81
+ base64& operator=(base64&); // assignment operator
82
+
83
+ };
84
+
85
+ }
86
+
87
+ #ifdef NO_MAKEFILE
88
+ #include "base64_kernel_1.cpp"
89
+ #endif
90
+
91
+ #endif // DLIB_BASE64_KERNEl_1_
92
+
dlibs/dlib/base64/base64_kernel_abstract.h ADDED
@@ -0,0 +1,121 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (C) 2006 Davis E. King ([email protected])
2
+ // License: Boost Software License See LICENSE.txt for the full license.
3
+ #undef DLIB_BASE64_KERNEl_ABSTRACT_
4
+ #ifdef DLIB_BASE64_KERNEl_ABSTRACT_
5
+
6
+ #include "../algs.h"
7
+ #include <iosfwd>
8
+
9
+ namespace dlib
10
+ {
11
+
12
+ class base64
13
+ {
14
+ /*!
15
+ INITIAL VALUE
16
+ - line_ending() == LF
17
+
18
+ WHAT THIS OBJECT REPRESENTS
19
+ This object consists of the two functions encode and decode.
20
+ These functions allow you to encode and decode data to and from
21
+ the Base64 Content-Transfer-Encoding defined in section 6.8 of
22
+ rfc2045.
23
+ !*/
24
+
25
+ public:
26
+
27
+ class decode_error : public dlib::error {};
28
+
29
+ base64 (
30
+ );
31
+ /*!
32
+ ensures
33
+ - #*this is properly initialized
34
+ throws
35
+ - std::bad_alloc
36
+ !*/
37
+
38
+ virtual ~base64 (
39
+ );
40
+ /*!
41
+ ensures
42
+ - all memory associated with *this has been released
43
+ !*/
44
+
45
+ enum line_ending_type
46
+ {
47
+ CR, // i.e. "\r"
48
+ LF, // i.e. "\n"
49
+ CRLF // i.e. "\r\n"
50
+ };
51
+
52
+ line_ending_type line_ending (
53
+ ) const;
54
+ /*!
55
+ ensures
56
+ - returns the type of end of line bytes the encoder
57
+ will use when encoding data to base64 blocks. Note that
58
+ the ostream object you use might apply some sort of transform
59
+ to line endings as well. For example, C++ ofstream objects
60
+ usually convert '\n' into whatever a normal newline is for
61
+ your platform unless you open a file in binary mode. But
62
+ aside from file streams the ostream objects usually don't
63
+ modify the data you pass to them.
64
+ !*/
65
+
66
+ void set_line_ending (
67
+ line_ending_type eol_style
68
+ );
69
+ /*!
70
+ ensures
71
+ - #line_ending() == eol_style
72
+ !*/
73
+
74
+ void encode (
75
+ std::istream& in,
76
+ std::ostream& out
77
+ ) const;
78
+ /*!
79
+ ensures
80
+ - reads all data from in (until EOF is reached) and encodes it
81
+ and writes it to out
82
+ throws
83
+ - std::ios_base::failure
84
+ if there was a problem writing to out then this exception will
85
+ be thrown.
86
+ - any other exception
87
+ this exception may be thrown if there is any other problem
88
+ !*/
89
+
90
+ void decode (
91
+ std::istream& in,
92
+ std::ostream& out
93
+ ) const;
94
+ /*!
95
+ ensures
96
+ - reads data from in (until EOF is reached), decodes it,
97
+ and writes it to out.
98
+ throws
99
+ - std::ios_base::failure
100
+ if there was a problem writing to out then this exception will
101
+ be thrown.
102
+ - decode_error
103
+ if an error was detected in the encoded data that prevented
104
+ it from being correctly decoded then this exception is
105
+ thrown.
106
+ - any other exception
107
+ this exception may be thrown if there is any other problem
108
+ !*/
109
+
110
+ private:
111
+
112
+ // restricted functions
113
+ base64(base64&); // copy constructor
114
+ base64& operator=(base64&); // assignment operator
115
+
116
+ };
117
+
118
+ }
119
+
120
+ #endif // DLIB_BASE64_KERNEl_ABSTRACT_
121
+
dlibs/dlib/bayes_utils.h ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (C) 2007 Davis E. King ([email protected])
2
+ // License: Boost Software License See LICENSE.txt for the full license.
3
+ #ifndef DLIB_BAYES_UTILs_H_
4
+ #define DLIB_BAYES_UTILs_H_
5
+
6
+ #include "bayes_utils/bayes_utils.h"
7
+
8
+ #endif // DLIB_BAYES_UTILs_H_
9
+
10
+
11
+
dlibs/dlib/bayes_utils/bayes_utils.h ADDED
@@ -0,0 +1,1678 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (C) 2007 Davis E. King ([email protected])
2
+ // License: Boost Software License See LICENSE.txt for the full license.
3
+ #ifndef DLIB_BAYES_UTILs_
4
+ #define DLIB_BAYES_UTILs_
5
+
6
+ #include "bayes_utils_abstract.h"
7
+
8
+ #include <algorithm>
9
+ #include <ctime>
10
+ #include <memory>
11
+ #include <vector>
12
+
13
+ #include "../string.h"
14
+ #include "../map.h"
15
+ #include "../matrix.h"
16
+ #include "../rand.h"
17
+ #include "../array.h"
18
+ #include "../set.h"
19
+ #include "../algs.h"
20
+ #include "../noncopyable.h"
21
+ #include "../graph.h"
22
+
23
+ namespace dlib
24
+ {
25
+
26
+ // ----------------------------------------------------------------------------------------
27
+
28
+ class assignment
29
+ {
30
+ public:
31
+
32
+ assignment()
33
+ {
34
+ }
35
+
36
+ assignment(
37
+ const assignment& a
38
+ )
39
+ {
40
+ a.reset();
41
+ while (a.move_next())
42
+ {
43
+ unsigned long idx = a.element().key();
44
+ unsigned long value = a.element().value();
45
+ vals.add(idx,value);
46
+ }
47
+ }
48
+
49
+ assignment& operator = (
50
+ const assignment& rhs
51
+ )
52
+ {
53
+ if (this == &rhs)
54
+ return *this;
55
+
56
+ assignment(rhs).swap(*this);
57
+ return *this;
58
+ }
59
+
60
+ void clear()
61
+ {
62
+ vals.clear();
63
+ }
64
+
65
+ bool operator < (
66
+ const assignment& item
67
+ ) const
68
+ {
69
+ if (size() < item.size())
70
+ return true;
71
+ else if (size() > item.size())
72
+ return false;
73
+
74
+ reset();
75
+ item.reset();
76
+ while (move_next())
77
+ {
78
+ item.move_next();
79
+ if (element().key() < item.element().key())
80
+ return true;
81
+ else if (element().key() > item.element().key())
82
+ return false;
83
+ else if (element().value() < item.element().value())
84
+ return true;
85
+ else if (element().value() > item.element().value())
86
+ return false;
87
+ }
88
+
89
+ return false;
90
+ }
91
+
92
+ bool has_index (
93
+ unsigned long idx
94
+ ) const
95
+ {
96
+ return vals.is_in_domain(idx);
97
+ }
98
+
99
+ void add (
100
+ unsigned long idx,
101
+ unsigned long value = 0
102
+ )
103
+ {
104
+ // make sure requires clause is not broken
105
+ DLIB_ASSERT( has_index(idx) == false ,
106
+ "\tvoid assignment::add(idx)"
107
+ << "\n\tYou can't add the same index to an assignment object more than once"
108
+ << "\n\tidx: " << idx
109
+ << "\n\tthis: " << this
110
+ );
111
+
112
+ vals.add(idx, value);
113
+ }
114
+
115
+ unsigned long& operator[] (
116
+ const long idx
117
+ )
118
+ {
119
+ // make sure requires clause is not broken
120
+ DLIB_ASSERT( has_index(idx) == true ,
121
+ "\tunsigned long assignment::operator[](idx)"
122
+ << "\n\tYou can't access an index value if it isn't already in the object"
123
+ << "\n\tidx: " << idx
124
+ << "\n\tthis: " << this
125
+ );
126
+
127
+ return vals[idx];
128
+ }
129
+
130
+ const unsigned long& operator[] (
131
+ const long idx
132
+ ) const
133
+ {
134
+ // make sure requires clause is not broken
135
+ DLIB_ASSERT( has_index(idx) == true ,
136
+ "\tunsigned long assignment::operator[](idx)"
137
+ << "\n\tYou can't access an index value if it isn't already in the object"
138
+ << "\n\tidx: " << idx
139
+ << "\n\tthis: " << this
140
+ );
141
+
142
+ return vals[idx];
143
+ }
144
+
145
+ void swap (
146
+ assignment& item
147
+ )
148
+ {
149
+ vals.swap(item.vals);
150
+ }
151
+
152
+ void remove (
153
+ unsigned long idx
154
+ )
155
+ {
156
+ // make sure requires clause is not broken
157
+ DLIB_ASSERT( has_index(idx) == true ,
158
+ "\tunsigned long assignment::remove(idx)"
159
+ << "\n\tYou can't remove an index value if it isn't already in the object"
160
+ << "\n\tidx: " << idx
161
+ << "\n\tthis: " << this
162
+ );
163
+
164
+ vals.destroy(idx);
165
+ }
166
+
167
+ unsigned long size() const { return vals.size(); }
168
+
169
+ void reset() const { vals.reset(); }
170
+
171
+ bool move_next() const { return vals.move_next(); }
172
+
173
+ map_pair<unsigned long, unsigned long>& element()
174
+ {
175
+ // make sure requires clause is not broken
176
+ DLIB_ASSERT(current_element_valid() == true,
177
+ "\tmap_pair<unsigned long,unsigned long>& assignment::element()"
178
+ << "\n\tyou can't access the current element if it doesn't exist"
179
+ << "\n\tthis: " << this
180
+ );
181
+ return vals.element();
182
+ }
183
+
184
+ const map_pair<unsigned long, unsigned long>& element() const
185
+ {
186
+ // make sure requires clause is not broken
187
+ DLIB_ASSERT(current_element_valid() == true,
188
+ "\tconst map_pair<unsigned long,unsigned long>& assignment::element() const"
189
+ << "\n\tyou can't access the current element if it doesn't exist"
190
+ << "\n\tthis: " << this
191
+ );
192
+
193
+ return vals.element();
194
+ }
195
+
196
+ bool at_start() const { return vals.at_start(); }
197
+
198
+ bool current_element_valid() const { return vals.current_element_valid(); }
199
+
200
+ friend inline void serialize (
201
+ const assignment& item,
202
+ std::ostream& out
203
+ )
204
+ {
205
+ serialize(item.vals, out);
206
+ }
207
+
208
+ friend inline void deserialize (
209
+ assignment& item,
210
+ std::istream& in
211
+ )
212
+ {
213
+ deserialize(item.vals, in);
214
+ }
215
+
216
+ private:
217
+ mutable dlib::map<unsigned long, unsigned long>::kernel_1b_c vals;
218
+ };
219
+
220
+ inline std::ostream& operator << (
221
+ std::ostream& out,
222
+ const assignment& a
223
+ )
224
+ {
225
+ a.reset();
226
+ out << "(";
227
+ if (a.move_next())
228
+ out << a.element().key() << ":" << a.element().value();
229
+
230
+ while (a.move_next())
231
+ {
232
+ out << ", " << a.element().key() << ":" << a.element().value();
233
+ }
234
+
235
+ out << ")";
236
+ return out;
237
+ }
238
+
239
+
240
+ inline void swap (
241
+ assignment& a,
242
+ assignment& b
243
+ )
244
+ {
245
+ a.swap(b);
246
+ }
247
+
248
+
249
+ // ------------------------------------------------------------------------
250
+
251
+ class joint_probability_table
252
+ {
253
+ /*!
254
+ INITIAL VALUE
255
+ - table.size() == 0
256
+
257
+ CONVENTION
258
+ - size() == table.size()
259
+ - probability(a) == table[a]
260
+ !*/
261
+ public:
262
+
263
+ joint_probability_table (
264
+ const joint_probability_table& t
265
+ )
266
+ {
267
+ t.reset();
268
+ while (t.move_next())
269
+ {
270
+ assignment a = t.element().key();
271
+ double p = t.element().value();
272
+ set_probability(a,p);
273
+ }
274
+ }
275
+
276
+ joint_probability_table() {}
277
+
278
+ joint_probability_table& operator= (
279
+ const joint_probability_table& rhs
280
+ )
281
+ {
282
+ if (this == &rhs)
283
+ return *this;
284
+ joint_probability_table(rhs).swap(*this);
285
+ return *this;
286
+ }
287
+
288
+ void set_probability (
289
+ const assignment& a,
290
+ double p
291
+ )
292
+ {
293
+ // make sure requires clause is not broken
294
+ DLIB_ASSERT(0.0 <= p && p <= 1.0,
295
+ "\tvoid& joint_probability_table::set_probability(a,p)"
296
+ << "\n\tyou have given an invalid probability value"
297
+ << "\n\tp: " << p
298
+ << "\n\ta: " << a
299
+ << "\n\tthis: " << this
300
+ );
301
+
302
+ if (table.is_in_domain(a))
303
+ {
304
+ table[a] = p;
305
+ }
306
+ else
307
+ {
308
+ assignment temp(a);
309
+ table.add(temp,p);
310
+ }
311
+ }
312
+
313
+ bool has_entry_for (
314
+ const assignment& a
315
+ ) const
316
+ {
317
+ return table.is_in_domain(a);
318
+ }
319
+
320
+ void add_probability (
321
+ const assignment& a,
322
+ double p
323
+ )
324
+ {
325
+ // make sure requires clause is not broken
326
+ DLIB_ASSERT(0.0 <= p && p <= 1.0,
327
+ "\tvoid& joint_probability_table::add_probability(a,p)"
328
+ << "\n\tyou have given an invalid probability value"
329
+ << "\n\tp: " << p
330
+ << "\n\ta: " << a
331
+ << "\n\tthis: " << this
332
+ );
333
+
334
+ if (table.is_in_domain(a))
335
+ {
336
+ table[a] += p;
337
+ if (table[a] > 1.0)
338
+ table[a] = 1.0;
339
+ }
340
+ else
341
+ {
342
+ assignment temp(a);
343
+ table.add(temp,p);
344
+ }
345
+ }
346
+
347
+ double probability (
348
+ const assignment& a
349
+ ) const
350
+ {
351
+ return table[a];
352
+ }
353
+
354
+ void clear()
355
+ {
356
+ table.clear();
357
+ }
358
+
359
+ size_t size () const { return table.size(); }
360
+ bool move_next() const { return table.move_next(); }
361
+ void reset() const { table.reset(); }
362
+ map_pair<assignment,double>& element()
363
+ {
364
+ // make sure requires clause is not broken
365
+ DLIB_ASSERT(current_element_valid() == true,
366
+ "\tmap_pair<assignment,double>& joint_probability_table::element()"
367
+ << "\n\tyou can't access the current element if it doesn't exist"
368
+ << "\n\tthis: " << this
369
+ );
370
+
371
+ return table.element();
372
+ }
373
+
374
+ const map_pair<assignment,double>& element() const
375
+ {
376
+ // make sure requires clause is not broken
377
+ DLIB_ASSERT(current_element_valid() == true,
378
+ "\tconst map_pair<assignment,double>& joint_probability_table::element() const"
379
+ << "\n\tyou can't access the current element if it doesn't exist"
380
+ << "\n\tthis: " << this
381
+ );
382
+
383
+ return table.element();
384
+ }
385
+
386
+ bool at_start() const { return table.at_start(); }
387
+
388
+ bool current_element_valid() const { return table.current_element_valid(); }
389
+
390
+
391
+ template <typename T>
392
+ void marginalize (
393
+ const T& vars,
394
+ joint_probability_table& out
395
+ ) const
396
+ {
397
+ out.clear();
398
+ double p;
399
+ reset();
400
+ while (move_next())
401
+ {
402
+ assignment a;
403
+ const assignment& asrc = element().key();
404
+ p = element().value();
405
+
406
+ asrc.reset();
407
+ while (asrc.move_next())
408
+ {
409
+ if (vars.is_member(asrc.element().key()))
410
+ a.add(asrc.element().key(), asrc.element().value());
411
+ }
412
+
413
+ out.add_probability(a,p);
414
+ }
415
+ }
416
+
417
+ void marginalize (
418
+ const unsigned long var,
419
+ joint_probability_table& out
420
+ ) const
421
+ {
422
+ out.clear();
423
+ double p;
424
+ reset();
425
+ while (move_next())
426
+ {
427
+ assignment a;
428
+ const assignment& asrc = element().key();
429
+ p = element().value();
430
+
431
+ asrc.reset();
432
+ while (asrc.move_next())
433
+ {
434
+ if (var == asrc.element().key())
435
+ a.add(asrc.element().key(), asrc.element().value());
436
+ }
437
+
438
+ out.add_probability(a,p);
439
+ }
440
+ }
441
+
442
+ void normalize (
443
+ )
444
+ {
445
+ double sum = 0;
446
+
447
+ reset();
448
+ while (move_next())
449
+ sum += element().value();
450
+
451
+ reset();
452
+ while (move_next())
453
+ element().value() /= sum;
454
+ }
455
+
456
+ void swap (
457
+ joint_probability_table& item
458
+ )
459
+ {
460
+ table.swap(item.table);
461
+ }
462
+
463
+ friend inline void serialize (
464
+ const joint_probability_table& item,
465
+ std::ostream& out
466
+ )
467
+ {
468
+ serialize(item.table, out);
469
+ }
470
+
471
+ friend inline void deserialize (
472
+ joint_probability_table& item,
473
+ std::istream& in
474
+ )
475
+ {
476
+ deserialize(item.table, in);
477
+ }
478
+
479
+ private:
480
+
481
+ dlib::map<assignment, double >::kernel_1b_c table;
482
+ };
483
+
484
+ inline void swap (
485
+ joint_probability_table& a,
486
+ joint_probability_table& b
487
+ ) { a.swap(b); }
488
+
489
+ // ----------------------------------------------------------------------------------------
490
+
491
+ class conditional_probability_table : noncopyable
492
+ {
493
+ /*!
494
+ INITIAL VALUE
495
+ - table.size() == 0
496
+
497
+ CONVENTION
498
+ - if (table.is_in_domain(ps) && value < num_vals && table[ps](value) >= 0) then
499
+ - has_entry_for(value,ps) == true
500
+ - probability(value,ps) == table[ps](value)
501
+ - else
502
+ - has_entry_for(value,ps) == false
503
+
504
+ - num_values() == num_vals
505
+ !*/
506
+ public:
507
+
508
+ conditional_probability_table()
509
+ {
510
+ clear();
511
+ }
512
+
513
+ void set_num_values (
514
+ unsigned long num
515
+ )
516
+ {
517
+ num_vals = num;
518
+ table.clear();
519
+ }
520
+
521
+ bool has_entry_for (
522
+ unsigned long value,
523
+ const assignment& ps
524
+ ) const
525
+ {
526
+ if (table.is_in_domain(ps) && value < num_vals && table[ps](value) >= 0)
527
+ return true;
528
+ else
529
+ return false;
530
+ }
531
+
532
+ unsigned long num_values (
533
+ ) const { return num_vals; }
534
+
535
+ void set_probability (
536
+ unsigned long value,
537
+ const assignment& ps,
538
+ double p
539
+ )
540
+ {
541
+ // make sure requires clause is not broken
542
+ DLIB_ASSERT( value < num_values() && 0.0 <= p && p <= 1.0 ,
543
+ "\tvoid conditional_probability_table::set_probability()"
544
+ << "\n\tinvalid arguments to set_probability"
545
+ << "\n\tvalue: " << value
546
+ << "\n\tnum_values(): " << num_values()
547
+ << "\n\tp: " << p
548
+ << "\n\tps: " << ps
549
+ << "\n\tthis: " << this
550
+ );
551
+
552
+ if (table.is_in_domain(ps))
553
+ {
554
+ table[ps](value) = p;
555
+ }
556
+ else
557
+ {
558
+ matrix<double,1> dist(num_vals);
559
+ set_all_elements(dist,-1);
560
+ dist(value) = p;
561
+ assignment temp(ps);
562
+ table.add(temp,dist);
563
+ }
564
+ }
565
+
566
+ double probability(
567
+ unsigned long value,
568
+ const assignment& ps
569
+ ) const
570
+ {
571
+ // make sure requires clause is not broken
572
+ DLIB_ASSERT( value < num_values() && has_entry_for(value,ps) ,
573
+ "\tvoid conditional_probability_table::probability()"
574
+ << "\n\tinvalid arguments to probability"
575
+ << "\n\tvalue: " << value
576
+ << "\n\tnum_values(): " << num_values()
577
+ << "\n\tps: " << ps
578
+ << "\n\tthis: " << this
579
+ );
580
+
581
+ return table[ps](value);
582
+ }
583
+
584
+ void clear()
585
+ {
586
+ table.clear();
587
+ num_vals = 0;
588
+ }
589
+
590
+ void empty_table ()
591
+ {
592
+ table.clear();
593
+ }
594
+
595
+ void swap (
596
+ conditional_probability_table& item
597
+ )
598
+ {
599
+ exchange(num_vals, item.num_vals);
600
+ table.swap(item.table);
601
+ }
602
+
603
+ friend inline void serialize (
604
+ const conditional_probability_table& item,
605
+ std::ostream& out
606
+ )
607
+ {
608
+ serialize(item.table, out);
609
+ serialize(item.num_vals, out);
610
+ }
611
+
612
+ friend inline void deserialize (
613
+ conditional_probability_table& item,
614
+ std::istream& in
615
+ )
616
+ {
617
+ deserialize(item.table, in);
618
+ deserialize(item.num_vals, in);
619
+ }
620
+
621
+ private:
622
+ dlib::map<assignment, matrix<double,1> >::kernel_1b_c table;
623
+ unsigned long num_vals;
624
+ };
625
+
626
+ inline void swap (
627
+ conditional_probability_table& a,
628
+ conditional_probability_table& b
629
+ ) { a.swap(b); }
630
+
631
+ // ------------------------------------------------------------------------
632
+
633
+ class bayes_node : noncopyable
634
+ {
635
+ public:
636
+ bayes_node ()
637
+ {
638
+ is_instantiated = false;
639
+ value_ = 0;
640
+ }
641
+
642
+ unsigned long value (
643
+ ) const { return value_;}
644
+
645
+ void set_value (
646
+ unsigned long new_value
647
+ )
648
+ {
649
+ // make sure requires clause is not broken
650
+ DLIB_ASSERT( new_value < table().num_values(),
651
+ "\tvoid bayes_node::set_value(new_value)"
652
+ << "\n\tnew_value must be less than the number of possible values for this node"
653
+ << "\n\tnew_value: " << new_value
654
+ << "\n\ttable().num_values(): " << table().num_values()
655
+ << "\n\tthis: " << this
656
+ );
657
+
658
+ value_ = new_value;
659
+ }
660
+
661
+ conditional_probability_table& table (
662
+ ) { return table_; }
663
+
664
+ const conditional_probability_table& table (
665
+ ) const { return table_; }
666
+
667
+ bool is_evidence (
668
+ ) const { return is_instantiated; }
669
+
670
+ void set_as_nonevidence (
671
+ ) { is_instantiated = false; }
672
+
673
+ void set_as_evidence (
674
+ ) { is_instantiated = true; }
675
+
676
+ void swap (
677
+ bayes_node& item
678
+ )
679
+ {
680
+ exchange(value_, item.value_);
681
+ exchange(is_instantiated, item.is_instantiated);
682
+ table_.swap(item.table_);
683
+ }
684
+
685
+ friend inline void serialize (
686
+ const bayes_node& item,
687
+ std::ostream& out
688
+ )
689
+ {
690
+ serialize(item.value_, out);
691
+ serialize(item.is_instantiated, out);
692
+ serialize(item.table_, out);
693
+ }
694
+
695
+ friend inline void deserialize (
696
+ bayes_node& item,
697
+ std::istream& in
698
+ )
699
+ {
700
+ deserialize(item.value_, in);
701
+ deserialize(item.is_instantiated, in);
702
+ deserialize(item.table_, in);
703
+ }
704
+
705
+ private:
706
+
707
+ unsigned long value_;
708
+ bool is_instantiated;
709
+ conditional_probability_table table_;
710
+ };
711
+
712
+ inline void swap (
713
+ bayes_node& a,
714
+ bayes_node& b
715
+ ) { a.swap(b); }
716
+
717
+ // ------------------------------------------------------------------------
718
+
719
+ namespace bayes_node_utils
720
+ {
721
+
722
+ template <typename T>
723
+ unsigned long node_num_values (
724
+ const T& bn,
725
+ unsigned long n
726
+ )
727
+ {
728
+ // make sure requires clause is not broken
729
+ DLIB_ASSERT( n < bn.number_of_nodes(),
730
+ "\tvoid bayes_node_utils::node_num_values(bn, n)"
731
+ << "\n\tInvalid arguments to this function"
732
+ << "\n\tn: " << n
733
+ << "\n\tbn.number_of_nodes(): " << bn.number_of_nodes()
734
+ );
735
+
736
+ return bn.node(n).data.table().num_values();
737
+ }
738
+
739
+ // ----------------------------------------------------------------------------------------
740
+
741
+ template <typename T>
742
+ void set_node_value (
743
+ T& bn,
744
+ unsigned long n,
745
+ unsigned long val
746
+ )
747
+ {
748
+ // make sure requires clause is not broken
749
+ DLIB_ASSERT( n < bn.number_of_nodes() && val < node_num_values(bn,n),
750
+ "\tvoid bayes_node_utils::set_node_value(bn, n, val)"
751
+ << "\n\tInvalid arguments to this function"
752
+ << "\n\tn: " << n
753
+ << "\n\tval: " << val
754
+ << "\n\tbn.number_of_nodes(): " << bn.number_of_nodes()
755
+ << "\n\tnode_num_values(bn,n): " << node_num_values(bn,n)
756
+ );
757
+
758
+ bn.node(n).data.set_value(val);
759
+ }
760
+
761
+ // ----------------------------------------------------------------------------------------
762
+ template <typename T>
763
+ unsigned long node_value (
764
+ const T& bn,
765
+ unsigned long n
766
+ )
767
+ {
768
+ // make sure requires clause is not broken
769
+ DLIB_ASSERT( n < bn.number_of_nodes(),
770
+ "\tunsigned long bayes_node_utils::node_value(bn, n)"
771
+ << "\n\tInvalid arguments to this function"
772
+ << "\n\tn: " << n
773
+ << "\n\tbn.number_of_nodes(): " << bn.number_of_nodes()
774
+ );
775
+
776
+ return bn.node(n).data.value();
777
+ }
778
+ // ----------------------------------------------------------------------------------------
779
+
780
+ template <typename T>
781
+ bool node_is_evidence (
782
+ const T& bn,
783
+ unsigned long n
784
+ )
785
+ {
786
+ // make sure requires clause is not broken
787
+ DLIB_ASSERT( n < bn.number_of_nodes(),
788
+ "\tbool bayes_node_utils::node_is_evidence(bn, n)"
789
+ << "\n\tInvalid arguments to this function"
790
+ << "\n\tn: " << n
791
+ << "\n\tbn.number_of_nodes(): " << bn.number_of_nodes()
792
+ );
793
+
794
+ return bn.node(n).data.is_evidence();
795
+ }
796
+
797
+ // ----------------------------------------------------------------------------------------
798
+
799
+ template <typename T>
800
+ void set_node_as_evidence (
801
+ T& bn,
802
+ unsigned long n
803
+ )
804
+ {
805
+ // make sure requires clause is not broken
806
+ DLIB_ASSERT( n < bn.number_of_nodes(),
807
+ "\tvoid bayes_node_utils::set_node_as_evidence(bn, n)"
808
+ << "\n\tInvalid arguments to this function"
809
+ << "\n\tn: " << n
810
+ << "\n\tbn.number_of_nodes(): " << bn.number_of_nodes()
811
+ );
812
+
813
+ bn.node(n).data.set_as_evidence();
814
+ }
815
+
816
+ // ----------------------------------------------------------------------------------------
817
+ template <typename T>
818
+ void set_node_as_nonevidence (
819
+ T& bn,
820
+ unsigned long n
821
+ )
822
+ {
823
+ // make sure requires clause is not broken
824
+ DLIB_ASSERT( n < bn.number_of_nodes(),
825
+ "\tvoid bayes_node_utils::set_node_as_nonevidence(bn, n)"
826
+ << "\n\tInvalid arguments to this function"
827
+ << "\n\tn: " << n
828
+ << "\n\tbn.number_of_nodes(): " << bn.number_of_nodes()
829
+ );
830
+
831
+ bn.node(n).data.set_as_nonevidence();
832
+ }
833
+
834
+ // ----------------------------------------------------------------------------------------
835
+
836
+ template <typename T>
837
+ void set_node_num_values (
838
+ T& bn,
839
+ unsigned long n,
840
+ unsigned long num
841
+ )
842
+ {
843
+ // make sure requires clause is not broken
844
+ DLIB_ASSERT( n < bn.number_of_nodes(),
845
+ "\tvoid bayes_node_utils::set_node_num_values(bn, n, num)"
846
+ << "\n\tInvalid arguments to this function"
847
+ << "\n\tn: " << n
848
+ << "\n\tbn.number_of_nodes(): " << bn.number_of_nodes()
849
+ );
850
+
851
+ bn.node(n).data.table().set_num_values(num);
852
+ }
853
+
854
+ // ----------------------------------------------------------------------------------------
855
+
856
+ template <typename T>
857
+ double node_probability (
858
+ const T& bn,
859
+ unsigned long n,
860
+ unsigned long value,
861
+ const assignment& parents
862
+ )
863
+ {
864
+ // make sure requires clause is not broken
865
+ DLIB_ASSERT( n < bn.number_of_nodes() && value < node_num_values(bn,n),
866
+ "\tdouble bayes_node_utils::node_probability(bn, n, value, parents)"
867
+ << "\n\tInvalid arguments to this function"
868
+ << "\n\tn: " << n
869
+ << "\n\tvalue: " << value
870
+ << "\n\tbn.number_of_nodes(): " << bn.number_of_nodes()
871
+ << "\n\tnode_num_values(bn,n): " << node_num_values(bn,n)
872
+ );
873
+
874
+ DLIB_ASSERT( parents.size() == bn.node(n).number_of_parents(),
875
+ "\tdouble bayes_node_utils::node_probability(bn, n, value, parents)"
876
+ << "\n\tInvalid arguments to this function"
877
+ << "\n\tn: " << n
878
+ << "\n\tparents.size(): " << parents.size()
879
+ << "\n\tb.node(n).number_of_parents(): " << bn.node(n).number_of_parents()
880
+ );
881
+
882
+ #ifdef ENABLE_ASSERTS
883
+ parents.reset();
884
+ while (parents.move_next())
885
+ {
886
+ const unsigned long x = parents.element().key();
887
+ DLIB_ASSERT( bn.has_edge(x, n),
888
+ "\tdouble bayes_node_utils::node_probability(bn, n, value, parents)"
889
+ << "\n\tInvalid arguments to this function"
890
+ << "\n\tn: " << n
891
+ << "\n\tx: " << x
892
+ );
893
+ DLIB_ASSERT( parents[x] < node_num_values(bn,x),
894
+ "\tdouble bayes_node_utils::node_probability(bn, n, value, parents)"
895
+ << "\n\tInvalid arguments to this function"
896
+ << "\n\tn: " << n
897
+ << "\n\tx: " << x
898
+ << "\n\tparents[x]: " << parents[x]
899
+ << "\n\tnode_num_values(bn,x): " << node_num_values(bn,x)
900
+ );
901
+ }
902
+ #endif
903
+
904
+ return bn.node(n).data.table().probability(value, parents);
905
+ }
906
+
907
+ // ----------------------------------------------------------------------------------------
908
+
909
+ template <typename T>
910
+ void set_node_probability (
911
+ T& bn,
912
+ unsigned long n,
913
+ unsigned long value,
914
+ const assignment& parents,
915
+ double p
916
+ )
917
+ {
918
+ // make sure requires clause is not broken
919
+ DLIB_ASSERT( n < bn.number_of_nodes() && value < node_num_values(bn,n),
920
+ "\tvoid bayes_node_utils::set_node_probability(bn, n, value, parents, p)"
921
+ << "\n\tInvalid arguments to this function"
922
+ << "\n\tn: " << n
923
+ << "\n\tp: " << p
924
+ << "\n\tvalue: " << value
925
+ << "\n\tbn.number_of_nodes(): " << bn.number_of_nodes()
926
+ << "\n\tnode_num_values(bn,n): " << node_num_values(bn,n)
927
+ );
928
+
929
+ DLIB_ASSERT( parents.size() == bn.node(n).number_of_parents(),
930
+ "\tvoid bayes_node_utils::set_node_probability(bn, n, value, parents, p)"
931
+ << "\n\tInvalid arguments to this function"
932
+ << "\n\tn: " << n
933
+ << "\n\tp: " << p
934
+ << "\n\tparents.size(): " << parents.size()
935
+ << "\n\tbn.node(n).number_of_parents(): " << bn.node(n).number_of_parents()
936
+ );
937
+
938
+ DLIB_ASSERT( 0.0 <= p && p <= 1.0,
939
+ "\tvoid bayes_node_utils::set_node_probability(bn, n, value, parents, p)"
940
+ << "\n\tInvalid arguments to this function"
941
+ << "\n\tn: " << n
942
+ << "\n\tp: " << p
943
+ );
944
+
945
+ #ifdef ENABLE_ASSERTS
946
+ parents.reset();
947
+ while (parents.move_next())
948
+ {
949
+ const unsigned long x = parents.element().key();
950
+ DLIB_ASSERT( bn.has_edge(x, n),
951
+ "\tvoid bayes_node_utils::set_node_probability(bn, n, value, parents, p)"
952
+ << "\n\tInvalid arguments to this function"
953
+ << "\n\tn: " << n
954
+ << "\n\tx: " << x
955
+ );
956
+ DLIB_ASSERT( parents[x] < node_num_values(bn,x),
957
+ "\tvoid bayes_node_utils::set_node_probability(bn, n, value, parents, p)"
958
+ << "\n\tInvalid arguments to this function"
959
+ << "\n\tn: " << n
960
+ << "\n\tx: " << x
961
+ << "\n\tparents[x]: " << parents[x]
962
+ << "\n\tnode_num_values(bn,x): " << node_num_values(bn,x)
963
+ );
964
+ }
965
+ #endif
966
+
967
+ bn.node(n).data.table().set_probability(value,parents,p);
968
+ }
969
+
970
+ // ----------------------------------------------------------------------------------------
971
+
972
+ template <typename T>
973
+ const assignment node_first_parent_assignment (
974
+ const T& bn,
975
+ unsigned long n
976
+ )
977
+ {
978
+ // make sure requires clause is not broken
979
+ DLIB_ASSERT( n < bn.number_of_nodes(),
980
+ "\tconst assignment bayes_node_utils::node_first_parent_assignment(bn, n)"
981
+ << "\n\tInvalid arguments to this function"
982
+ << "\n\tn: " << n
983
+ );
984
+
985
+ assignment a;
986
+ const unsigned long num_parents = bn.node(n).number_of_parents();
987
+ for (unsigned long i = 0; i < num_parents; ++i)
988
+ {
989
+ a.add(bn.node(n).parent(i).index(), 0);
990
+ }
991
+ return a;
992
+ }
993
+
994
+ // ----------------------------------------------------------------------------------------
995
+
996
+ template <typename T>
997
+ bool node_next_parent_assignment (
998
+ const T& bn,
999
+ unsigned long n,
1000
+ assignment& a
1001
+ )
1002
+ {
1003
+ // make sure requires clause is not broken
1004
+ DLIB_ASSERT( n < bn.number_of_nodes(),
1005
+ "\tbool bayes_node_utils::node_next_parent_assignment(bn, n, a)"
1006
+ << "\n\tInvalid arguments to this function"
1007
+ << "\n\tn: " << n
1008
+ );
1009
+
1010
+ DLIB_ASSERT( a.size() == bn.node(n).number_of_parents(),
1011
+ "\tbool bayes_node_utils::node_next_parent_assignment(bn, n, a)"
1012
+ << "\n\tInvalid arguments to this function"
1013
+ << "\n\tn: " << n
1014
+ << "\n\ta.size(): " << a.size()
1015
+ << "\n\tbn.node(n).number_of_parents(): " << bn.node(n).number_of_parents()
1016
+ );
1017
+
1018
+ #ifdef ENABLE_ASSERTS
1019
+ a.reset();
1020
+ while (a.move_next())
1021
+ {
1022
+ const unsigned long x = a.element().key();
1023
+ DLIB_ASSERT( bn.has_edge(x, n),
1024
+ "\tbool bayes_node_utils::node_next_parent_assignment(bn, n, a)"
1025
+ << "\n\tInvalid arguments to this function"
1026
+ << "\n\tn: " << n
1027
+ << "\n\tx: " << x
1028
+ );
1029
+ DLIB_ASSERT( a[x] < node_num_values(bn,x),
1030
+ "\tbool bayes_node_utils::node_next_parent_assignment(bn, n, a)"
1031
+ << "\n\tInvalid arguments to this function"
1032
+ << "\n\tn: " << n
1033
+ << "\n\tx: " << x
1034
+ << "\n\ta[x]: " << a[x]
1035
+ << "\n\tnode_num_values(bn,x): " << node_num_values(bn,x)
1036
+ );
1037
+ }
1038
+ #endif
1039
+
1040
+ // basically this loop just adds 1 to the assignment but performs
1041
+ // carries if necessary
1042
+ for (unsigned long p = 0; p < a.size(); ++p)
1043
+ {
1044
+ const unsigned long pindex = bn.node(n).parent(p).index();
1045
+ a[pindex] += 1;
1046
+
1047
+ // if we need to perform a carry
1048
+ if (a[pindex] >= node_num_values(bn,pindex))
1049
+ {
1050
+ a[pindex] = 0;
1051
+ }
1052
+ else
1053
+ {
1054
+ // no carry necessary so we are done
1055
+ return true;
1056
+ }
1057
+ }
1058
+
1059
+ // we got through the entire loop which means a carry propagated all the way out
1060
+ // so there must not be any more valid assignments left
1061
+ return false;
1062
+ }
1063
+
1064
+ // ----------------------------------------------------------------------------------------
1065
+
1066
+ template <typename T>
1067
+ bool node_cpt_filled_out (
1068
+ const T& bn,
1069
+ unsigned long n
1070
+ )
1071
+ {
1072
+ // make sure requires clause is not broken
1073
+ DLIB_ASSERT( n < bn.number_of_nodes(),
1074
+ "\tbool bayes_node_utils::node_cpt_filled_out(bn, n)"
1075
+ << "\n\tInvalid arguments to this function"
1076
+ << "\n\tn: " << n
1077
+ << "\n\tbn.number_of_nodes(): " << bn.number_of_nodes()
1078
+ );
1079
+
1080
+ const unsigned long num_values = node_num_values(bn,n);
1081
+
1082
+
1083
+ const conditional_probability_table& table = bn.node(n).data.table();
1084
+
1085
+ // now loop over all the possible parent assignments for this node
1086
+ assignment a(node_first_parent_assignment(bn,n));
1087
+ do
1088
+ {
1089
+ double sum = 0;
1090
+ // make sure that this assignment has an entry for all the values this node can take one
1091
+ for (unsigned long value = 0; value < num_values; ++value)
1092
+ {
1093
+ if (table.has_entry_for(value,a) == false)
1094
+ return false;
1095
+ else
1096
+ sum += table.probability(value,a);
1097
+ }
1098
+
1099
+ // check if the sum of probabilities equals 1 as it should
1100
+ if (std::abs(sum-1.0) > 1e-5)
1101
+ return false;
1102
+ } while (node_next_parent_assignment(bn,n,a));
1103
+
1104
+ return true;
1105
+ }
1106
+
1107
+ }
1108
+
1109
+ // ----------------------------------------------------------------------------------------
1110
+
1111
+ class bayesian_network_gibbs_sampler : noncopyable
1112
+ {
1113
+ public:
1114
+
1115
+ bayesian_network_gibbs_sampler ()
1116
+ {
1117
+ rnd.set_seed(cast_to_string(std::time(0)));
1118
+ }
1119
+
1120
+
1121
+ template <
1122
+ typename T
1123
+ >
1124
+ void sample_graph (
1125
+ T& bn
1126
+ )
1127
+ {
1128
+ using namespace bayes_node_utils;
1129
+ for (unsigned long n = 0; n < bn.number_of_nodes(); ++n)
1130
+ {
1131
+ if (node_is_evidence(bn, n))
1132
+ continue;
1133
+
1134
+ samples.set_size(node_num_values(bn,n));
1135
+ // obtain the probability distribution for this node
1136
+ for (long i = 0; i < samples.nc(); ++i)
1137
+ {
1138
+ set_node_value(bn, n, i);
1139
+ samples(i) = node_probability(bn, n);
1140
+
1141
+ for (unsigned long j = 0; j < bn.node(n).number_of_children(); ++j)
1142
+ samples(i) *= node_probability(bn, bn.node(n).child(j).index());
1143
+ }
1144
+
1145
+ //normalize samples
1146
+ samples /= sum(samples);
1147
+
1148
+
1149
+ // select a random point in the probability distribution
1150
+ double prob = rnd.get_random_double();
1151
+
1152
+ // now find the point in the distribution this probability corresponds to
1153
+ long j;
1154
+ for (j = 0; j < samples.nc()-1; ++j)
1155
+ {
1156
+ if (prob <= samples(j))
1157
+ break;
1158
+ else
1159
+ prob -= samples(j);
1160
+ }
1161
+
1162
+ set_node_value(bn, n, j);
1163
+ }
1164
+ }
1165
+
1166
+
1167
+ private:
1168
+
1169
+ template <
1170
+ typename T
1171
+ >
1172
+ double node_probability (
1173
+ const T& bn,
1174
+ unsigned long n
1175
+ )
1176
+ /*!
1177
+ requires
1178
+ - n < bn.number_of_nodes()
1179
+ ensures
1180
+ - computes the probability of node n having its current value given
1181
+ the current values of its parents in the network bn
1182
+ !*/
1183
+ {
1184
+ v.clear();
1185
+ for (unsigned long i = 0; i < bn.node(n).number_of_parents(); ++i)
1186
+ {
1187
+ v.add(bn.node(n).parent(i).index(), bn.node(n).parent(i).data.value());
1188
+ }
1189
+ return bn.node(n).data.table().probability(bn.node(n).data.value(), v);
1190
+ }
1191
+
1192
+ assignment v;
1193
+
1194
+ dlib::rand rnd;
1195
+ matrix<double,1> samples;
1196
+ };
1197
+
1198
+ // ----------------------------------------------------------------------------------------
1199
+
1200
+ namespace bayesian_network_join_tree_helpers
1201
+ {
1202
+ class bnjt
1203
+ {
1204
+ /*!
1205
+ this object is the base class used in this pimpl idiom
1206
+ !*/
1207
+ public:
1208
+ virtual ~bnjt() {}
1209
+
1210
+ virtual const matrix<double,1> probability(
1211
+ unsigned long idx
1212
+ ) const = 0;
1213
+ };
1214
+
1215
+ template <typename T, typename U>
1216
+ class bnjt_impl : public bnjt
1217
+ {
1218
+ /*!
1219
+ This object is the implementation in the pimpl idiom
1220
+ !*/
1221
+
1222
+ public:
1223
+
1224
+ bnjt_impl (
1225
+ const T& bn,
1226
+ const U& join_tree
1227
+ )
1228
+ {
1229
+ create_bayesian_network_join_tree(bn, join_tree, join_tree_values);
1230
+
1231
+ cliques.resize(bn.number_of_nodes());
1232
+
1233
+ // figure out which cliques contain each node
1234
+ for (unsigned long i = 0; i < cliques.size(); ++i)
1235
+ {
1236
+ // find the smallest clique that contains node with index i
1237
+ unsigned long smallest_clique = 0;
1238
+ unsigned long size = std::numeric_limits<unsigned long>::max();
1239
+
1240
+ for (unsigned long n = 0; n < join_tree.number_of_nodes(); ++n)
1241
+ {
1242
+ if (join_tree.node(n).data.is_member(i) && join_tree.node(n).data.size() < size)
1243
+ {
1244
+ size = join_tree.node(n).data.size();
1245
+ smallest_clique = n;
1246
+ }
1247
+ }
1248
+
1249
+ cliques[i] = smallest_clique;
1250
+ }
1251
+ }
1252
+
1253
+ virtual const matrix<double,1> probability(
1254
+ unsigned long idx
1255
+ ) const
1256
+ {
1257
+ join_tree_values.node(cliques[idx]).data.marginalize(idx, table);
1258
+ table.normalize();
1259
+ var.clear();
1260
+ var.add(idx);
1261
+ dist.set_size(table.size());
1262
+
1263
+ // read the probabilities out of the table and into the row matrix
1264
+ for (unsigned long i = 0; i < table.size(); ++i)
1265
+ {
1266
+ var[idx] = i;
1267
+ dist(i) = table.probability(var);
1268
+ }
1269
+
1270
+ return dist;
1271
+ }
1272
+
1273
+ private:
1274
+
1275
+ graph< joint_probability_table, joint_probability_table >::kernel_1a_c join_tree_values;
1276
+ array<unsigned long> cliques;
1277
+ mutable joint_probability_table table;
1278
+ mutable assignment var;
1279
+ mutable matrix<double,1> dist;
1280
+
1281
+
1282
+ // ----------------------------------------------------------------------------------------
1283
+
1284
+ template <typename set_type, typename node_type>
1285
+ bool set_contains_all_parents_of_node (
1286
+ const set_type& set,
1287
+ const node_type& node
1288
+ )
1289
+ {
1290
+ for (unsigned long i = 0; i < node.number_of_parents(); ++i)
1291
+ {
1292
+ if (set.is_member(node.parent(i).index()) == false)
1293
+ return false;
1294
+ }
1295
+ return true;
1296
+ }
1297
+
1298
+ // ----------------------------------------------------------------------------------------
1299
+
1300
+ template <
1301
+ typename V
1302
+ >
1303
+ void pass_join_tree_message (
1304
+ const U& join_tree,
1305
+ V& bn_join_tree ,
1306
+ unsigned long from,
1307
+ unsigned long to
1308
+ )
1309
+ {
1310
+ using namespace bayes_node_utils;
1311
+ const typename U::edge_type& e = edge(join_tree, from, to);
1312
+ typename V::edge_type& old_s = edge(bn_join_tree, from, to);
1313
+
1314
+ typedef typename V::edge_type joint_prob_table;
1315
+
1316
+ joint_prob_table new_s;
1317
+ bn_join_tree.node(from).data.marginalize(e, new_s);
1318
+
1319
+ joint_probability_table temp(new_s);
1320
+ // divide new_s by old_s and store the result in temp.
1321
+ // if old_s is empty then that is the same as if it was all 1s
1322
+ // so we don't have to do this if that is the case.
1323
+ if (old_s.size() > 0)
1324
+ {
1325
+ temp.reset();
1326
+ old_s.reset();
1327
+ while (temp.move_next())
1328
+ {
1329
+ old_s.move_next();
1330
+ if (old_s.element().value() != 0)
1331
+ temp.element().value() /= old_s.element().value();
1332
+ }
1333
+ }
1334
+
1335
+ // now multiply temp by d and store the results in d
1336
+ joint_probability_table& d = bn_join_tree.node(to).data;
1337
+ d.reset();
1338
+ while (d.move_next())
1339
+ {
1340
+ assignment a;
1341
+ const assignment& asrc = d.element().key();
1342
+ asrc.reset();
1343
+ while (asrc.move_next())
1344
+ {
1345
+ if (e.is_member(asrc.element().key()))
1346
+ a.add(asrc.element().key(), asrc.element().value());
1347
+ }
1348
+
1349
+ d.element().value() *= temp.probability(a);
1350
+
1351
+ }
1352
+
1353
+ // store new_s in old_s
1354
+ new_s.swap(old_s);
1355
+
1356
+ }
1357
+
1358
+ // ----------------------------------------------------------------------------------------
1359
+
1360
+ template <
1361
+ typename V
1362
+ >
1363
+ void create_bayesian_network_join_tree (
1364
+ const T& bn,
1365
+ const U& join_tree,
1366
+ V& bn_join_tree
1367
+ )
1368
+ /*!
1369
+ requires
1370
+ - bn is a proper bayesian network
1371
+ - join_tree is the join tree for that bayesian network
1372
+ ensures
1373
+ - bn_join_tree == the output of the join tree algorithm for bayesian network inference.
1374
+ So each node in this graph contains a joint_probability_table for the clique
1375
+ in the corresponding node in the join_tree graph.
1376
+ !*/
1377
+ {
1378
+ using namespace bayes_node_utils;
1379
+ bn_join_tree.clear();
1380
+ copy_graph_structure(join_tree, bn_join_tree);
1381
+
1382
+ // we need to keep track of which node is "in" each clique for the purposes of
1383
+ // initializing the tables in each clique. So this vector will be used to do that
1384
+ // and a value of join_tree.number_of_nodes() means that the node with
1385
+ // that index is unassigned.
1386
+ std::vector<unsigned long> node_assigned_to(bn.number_of_nodes(),join_tree.number_of_nodes());
1387
+
1388
+ // populate evidence with all the evidence node indices and their values
1389
+ dlib::map<unsigned long, unsigned long>::kernel_1b_c evidence;
1390
+ for (unsigned long i = 0; i < bn.number_of_nodes(); ++i)
1391
+ {
1392
+ if (node_is_evidence(bn, i))
1393
+ {
1394
+ unsigned long idx = i;
1395
+ unsigned long value = node_value(bn, i);
1396
+ evidence.add(idx,value);
1397
+ }
1398
+ }
1399
+
1400
+
1401
+ // initialize the bn join tree
1402
+ for (unsigned long i = 0; i < join_tree.number_of_nodes(); ++i)
1403
+ {
1404
+ bool contains_evidence = false;
1405
+ std::vector<unsigned long> indices;
1406
+ assignment value;
1407
+
1408
+ // loop over all the nodes in this clique in the join tree. In this loop
1409
+ // we are making an assignment with all the values of the nodes it represents set to 0
1410
+ join_tree.node(i).data.reset();
1411
+ while (join_tree.node(i).data.move_next())
1412
+ {
1413
+ const unsigned long idx = join_tree.node(i).data.element();
1414
+ indices.push_back(idx);
1415
+ value.add(idx);
1416
+
1417
+ if (evidence.is_in_domain(join_tree.node(i).data.element()))
1418
+ contains_evidence = true;
1419
+ }
1420
+
1421
+ // now loop over all possible combinations of values that the nodes this
1422
+ // clique in the join tree can take on. We do this by counting by one through all
1423
+ // legal values
1424
+ bool more_assignments = true;
1425
+ while (more_assignments)
1426
+ {
1427
+ bn_join_tree.node(i).data.set_probability(value,1);
1428
+
1429
+ // account for any evidence
1430
+ if (contains_evidence)
1431
+ {
1432
+ // loop over all the nodes in this cluster
1433
+ for (unsigned long j = 0; j < indices.size(); ++j)
1434
+ {
1435
+ // if the current node is an evidence node
1436
+ if (evidence.is_in_domain(indices[j]))
1437
+ {
1438
+ const unsigned long idx = indices[j];
1439
+ const unsigned long evidence_value = evidence[idx];
1440
+ if (value[idx] != evidence_value)
1441
+ bn_join_tree.node(i).data.set_probability(value , 0);
1442
+ }
1443
+ }
1444
+ }
1445
+
1446
+
1447
+ // now check if any of the nodes in this cluster also have their parents in this cluster
1448
+ join_tree.node(i).data.reset();
1449
+ while (join_tree.node(i).data.move_next())
1450
+ {
1451
+ const unsigned long idx = join_tree.node(i).data.element();
1452
+ // if this clique contains all the parents of this node and also hasn't
1453
+ // been assigned to another clique
1454
+ if (set_contains_all_parents_of_node(join_tree.node(i).data, bn.node(idx)) &&
1455
+ (i == node_assigned_to[idx] || node_assigned_to[idx] == join_tree.number_of_nodes()) )
1456
+ {
1457
+ // note that this node is now assigned to this clique
1458
+ node_assigned_to[idx] = i;
1459
+ // node idx has all its parents in the cluster
1460
+ assignment parent_values;
1461
+ for (unsigned long j = 0; j < bn.node(idx).number_of_parents(); ++j)
1462
+ {
1463
+ const unsigned long pidx = bn.node(idx).parent(j).index();
1464
+ parent_values.add(pidx, value[pidx]);
1465
+ }
1466
+
1467
+ double temp = bn_join_tree.node(i).data.probability(value);
1468
+ bn_join_tree.node(i).data.set_probability(value, temp * node_probability(bn, idx, value[idx], parent_values));
1469
+
1470
+ }
1471
+ }
1472
+
1473
+
1474
+ // now advance the value variable to its next possible state if there is one
1475
+ more_assignments = false;
1476
+ value.reset();
1477
+ while (value.move_next())
1478
+ {
1479
+ value.element().value() += 1;
1480
+ // if overflow
1481
+ if (value.element().value() == node_num_values(bn, value.element().key()))
1482
+ {
1483
+ value.element().value() = 0;
1484
+ }
1485
+ else
1486
+ {
1487
+ more_assignments = true;
1488
+ break;
1489
+ }
1490
+ }
1491
+
1492
+ } // end while (more_assignments)
1493
+ }
1494
+
1495
+
1496
+
1497
+
1498
+ // the tree is now initialized. Now all we need to do is perform the propagation and
1499
+ // we are done
1500
+ dlib::array<dlib::set<unsigned long>::compare_1b_c> remaining_msg_to_send;
1501
+ dlib::array<dlib::set<unsigned long>::compare_1b_c> remaining_msg_to_receive;
1502
+ remaining_msg_to_receive.resize(join_tree.number_of_nodes());
1503
+ remaining_msg_to_send.resize(join_tree.number_of_nodes());
1504
+ for (unsigned long i = 0; i < remaining_msg_to_receive.size(); ++i)
1505
+ {
1506
+ for (unsigned long j = 0; j < join_tree.node(i).number_of_neighbors(); ++j)
1507
+ {
1508
+ const unsigned long idx = join_tree.node(i).neighbor(j).index();
1509
+ unsigned long temp;
1510
+ temp = idx; remaining_msg_to_receive[i].add(temp);
1511
+ temp = idx; remaining_msg_to_send[i].add(temp);
1512
+ }
1513
+ }
1514
+
1515
+ // now remaining_msg_to_receive[i] contains all the nodes that node i hasn't yet received
1516
+ // a message from.
1517
+ // we will consider node 0 to be the root node.
1518
+
1519
+
1520
+ bool message_sent = true;
1521
+ std::vector<unsigned long>::iterator iter;
1522
+ while (message_sent)
1523
+ {
1524
+ message_sent = false;
1525
+ for (unsigned long i = 1; i < remaining_msg_to_send.size(); ++i)
1526
+ {
1527
+ // if node i hasn't sent any messages but has received all but one then send a message to the one
1528
+ // node who hasn't sent i a message
1529
+ if (remaining_msg_to_send[i].size() == join_tree.node(i).number_of_neighbors() && remaining_msg_to_receive[i].size() == 1)
1530
+ {
1531
+ unsigned long to;
1532
+ // get the last remaining thing from this set
1533
+ remaining_msg_to_receive[i].remove_any(to);
1534
+
1535
+ // send the message
1536
+ pass_join_tree_message(join_tree, bn_join_tree, i, to);
1537
+
1538
+ // record that we sent this message
1539
+ remaining_msg_to_send[i].destroy(to);
1540
+ remaining_msg_to_receive[to].destroy(i);
1541
+
1542
+ // put to back in since we still need to receive it
1543
+ remaining_msg_to_receive[i].add(to);
1544
+ message_sent = true;
1545
+ }
1546
+ else if (remaining_msg_to_receive[i].size() == 0 && remaining_msg_to_send[i].size() > 0)
1547
+ {
1548
+ unsigned long to;
1549
+ remaining_msg_to_send[i].remove_any(to);
1550
+ remaining_msg_to_receive[to].destroy(i);
1551
+ pass_join_tree_message(join_tree, bn_join_tree, i, to);
1552
+ message_sent = true;
1553
+ }
1554
+ }
1555
+
1556
+ if (remaining_msg_to_receive[0].size() == 0)
1557
+ {
1558
+ // send a message to all of the root nodes neighbors unless we have already sent out he messages
1559
+ while (remaining_msg_to_send[0].size() > 0)
1560
+ {
1561
+ unsigned long to;
1562
+ remaining_msg_to_send[0].remove_any(to);
1563
+ remaining_msg_to_receive[to].destroy(0);
1564
+ pass_join_tree_message(join_tree, bn_join_tree, 0, to);
1565
+ message_sent = true;
1566
+ }
1567
+ }
1568
+
1569
+
1570
+ }
1571
+
1572
+ }
1573
+
1574
+ };
1575
+ }
1576
+
1577
+ class bayesian_network_join_tree : noncopyable
1578
+ {
1579
+ /*!
1580
+ use the pimpl idiom to push the template arguments from the class level to the
1581
+ constructor level
1582
+ !*/
1583
+
1584
+ public:
1585
+
1586
+ template <
1587
+ typename T,
1588
+ typename U
1589
+ >
1590
+ bayesian_network_join_tree (
1591
+ const T& bn,
1592
+ const U& join_tree
1593
+ )
1594
+ {
1595
+ // make sure requires clause is not broken
1596
+ DLIB_ASSERT( bn.number_of_nodes() > 0 ,
1597
+ "\tbayesian_network_join_tree::bayesian_network_join_tree(bn,join_tree)"
1598
+ << "\n\tYou have given an invalid bayesian network"
1599
+ << "\n\tthis: " << this
1600
+ );
1601
+
1602
+ DLIB_ASSERT( is_join_tree(bn, join_tree) == true ,
1603
+ "\tbayesian_network_join_tree::bayesian_network_join_tree(bn,join_tree)"
1604
+ << "\n\tYou have given an invalid join tree for the supplied bayesian network"
1605
+ << "\n\tthis: " << this
1606
+ );
1607
+ DLIB_ASSERT( graph_contains_length_one_cycle(bn) == false,
1608
+ "\tbayesian_network_join_tree::bayesian_network_join_tree(bn,join_tree)"
1609
+ << "\n\tYou have given an invalid bayesian network"
1610
+ << "\n\tthis: " << this
1611
+ );
1612
+ DLIB_ASSERT( graph_is_connected(bn) == true,
1613
+ "\tbayesian_network_join_tree::bayesian_network_join_tree(bn,join_tree)"
1614
+ << "\n\tYou have given an invalid bayesian network"
1615
+ << "\n\tthis: " << this
1616
+ );
1617
+
1618
+ #ifdef ENABLE_ASSERTS
1619
+ for (unsigned long i = 0; i < bn.number_of_nodes(); ++i)
1620
+ {
1621
+ DLIB_ASSERT(bayes_node_utils::node_cpt_filled_out(bn,i) == true,
1622
+ "\tbayesian_network_join_tree::bayesian_network_join_tree(bn,join_tree)"
1623
+ << "\n\tYou have given an invalid bayesian network. "
1624
+ << "\n\tYou must finish filling out the conditional_probability_table of node " << i
1625
+ << "\n\tthis: " << this
1626
+ );
1627
+ }
1628
+ #endif
1629
+
1630
+ impl.reset(new bayesian_network_join_tree_helpers::bnjt_impl<T,U>(bn, join_tree));
1631
+ num_nodes = bn.number_of_nodes();
1632
+ }
1633
+
1634
+ const matrix<double,1> probability(
1635
+ unsigned long idx
1636
+ ) const
1637
+ {
1638
+ // make sure requires clause is not broken
1639
+ DLIB_ASSERT( idx < number_of_nodes() ,
1640
+ "\tconst matrix<double,1> bayesian_network_join_tree::probability(idx)"
1641
+ << "\n\tYou have specified an invalid node index"
1642
+ << "\n\tidx: " << idx
1643
+ << "\n\tnumber_of_nodes(): " << number_of_nodes()
1644
+ << "\n\tthis: " << this
1645
+ );
1646
+
1647
+ return impl->probability(idx);
1648
+ }
1649
+
1650
+ unsigned long number_of_nodes (
1651
+ ) const { return num_nodes; }
1652
+
1653
+ void swap (
1654
+ bayesian_network_join_tree& item
1655
+ )
1656
+ {
1657
+ exchange(num_nodes, item.num_nodes);
1658
+ impl.swap(item.impl);
1659
+ }
1660
+
1661
+ private:
1662
+
1663
+ std::unique_ptr<bayesian_network_join_tree_helpers::bnjt> impl;
1664
+ unsigned long num_nodes;
1665
+
1666
+ };
1667
+
1668
+ inline void swap (
1669
+ bayesian_network_join_tree& a,
1670
+ bayesian_network_join_tree& b
1671
+ ) { a.swap(b); }
1672
+
1673
+ }
1674
+
1675
+ // ----------------------------------------------------------------------------------------
1676
+
1677
+ #endif // DLIB_BAYES_UTILs_
1678
+
dlibs/dlib/bayes_utils/bayes_utils_abstract.h ADDED
@@ -0,0 +1,1042 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (C) 2007 Davis E. King ([email protected])
2
+ // License: Boost Software License See LICENSE.txt for the full license.
3
+ #undef DLIB_BAYES_UTILs_ABSTRACT_
4
+ #ifdef DLIB_BAYES_UTILs_ABSTRACT_
5
+
6
+ #include "../algs.h"
7
+ #include "../noncopyable.h"
8
+ #include "../interfaces/enumerable.h"
9
+ #include "../interfaces/map_pair.h"
10
+ #include "../serialize.h"
11
+ #include <iostream>
12
+
13
+ namespace dlib
14
+ {
15
+
16
+ // ----------------------------------------------------------------------------------------
17
+
18
+ class assignment : public enumerable<map_pair<unsigned long, unsigned long> >
19
+ {
20
+ /*!
21
+ INITIAL VALUE
22
+ - size() == 0
23
+
24
+ ENUMERATION ORDER
25
+ The enumerator will iterate over the entries in the assignment in
26
+ ascending order according to index values. (i.e. the elements are
27
+ enumerated in sorted order according to the value of their keys)
28
+
29
+ WHAT THIS OBJECT REPRESENTS
30
+ This object models an assignment of random variables to particular values.
31
+ It is used with the joint_probability_table and conditional_probability_table
32
+ objects to represent assignments of various random variables to actual values.
33
+
34
+ So for example, if you had a joint_probability_table that represented the
35
+ following table:
36
+ P(A = 0, B = 0) = 0.2
37
+ P(A = 0, B = 1) = 0.3
38
+ P(A = 1, B = 0) = 0.1
39
+ P(A = 1, B = 1) = 0.4
40
+
41
+ Also lets define an enum so we have concrete index numbers for A and B
42
+ enum { A = 0, B = 1};
43
+
44
+ Then you could query the value of P(A=1, B=0) as follows:
45
+ assignment a;
46
+ a.set(A, 1);
47
+ a.set(B, 0);
48
+ // and now it is the case that:
49
+ table.probability(a) == 0.1
50
+ a[A] == 1
51
+ a[B] == 0
52
+
53
+
54
+ Also note that when enumerating the elements of an assignment object
55
+ the key() refers to the index and the value() refers to the value at that
56
+ index. For example:
57
+
58
+ // assume a is an assignment object
59
+ a.reset();
60
+ while (a.move_next())
61
+ {
62
+ // in this loop it is always the case that:
63
+ // a[a.element().key()] == a.element().value()
64
+ }
65
+ !*/
66
+
67
+ public:
68
+
69
+ assignment(
70
+ );
71
+ /*!
72
+ ensures
73
+ - this object is properly initialized
74
+ !*/
75
+
76
+ assignment(
77
+ const assignment& a
78
+ );
79
+ /*!
80
+ ensures
81
+ - #*this is a copy of a
82
+ !*/
83
+
84
+ assignment& operator = (
85
+ const assignment& rhs
86
+ );
87
+ /*!
88
+ ensures
89
+ - #*this is a copy of rhs
90
+ - returns *this
91
+ !*/
92
+
93
+ void clear(
94
+ );
95
+ /*!
96
+ ensures
97
+ - this object has been returned to its initial value
98
+ !*/
99
+
100
+ bool operator < (
101
+ const assignment& item
102
+ ) const;
103
+ /*!
104
+ ensures
105
+ - The exact functioning of this operator is undefined. The only guarantee
106
+ is that it establishes a total ordering on all possible assignment objects.
107
+ In other words, this operator makes it so that you can use assignment
108
+ objects in the associative containers but otherwise isn't of any
109
+ particular use.
110
+ !*/
111
+
112
+ bool has_index (
113
+ unsigned long idx
114
+ ) const;
115
+ /*!
116
+ ensures
117
+ - if (this assignment object has an entry for index idx) then
118
+ - returns true
119
+ - else
120
+ - returns false
121
+ !*/
122
+
123
+ void add (
124
+ unsigned long idx,
125
+ unsigned long value = 0
126
+ );
127
+ /*!
128
+ requires
129
+ - has_index(idx) == false
130
+ ensures
131
+ - #has_index(idx) == true
132
+ - #(*this)[idx] == value
133
+ !*/
134
+
135
+ void remove (
136
+ unsigned long idx
137
+ );
138
+ /*!
139
+ requires
140
+ - has_index(idx) == true
141
+ ensures
142
+ - #has_index(idx) == false
143
+ !*/
144
+
145
+ unsigned long& operator[] (
146
+ const long idx
147
+ );
148
+ /*!
149
+ requires
150
+ - has_index(idx) == true
151
+ ensures
152
+ - returns a reference to the value associated with index idx
153
+ !*/
154
+
155
+ const unsigned long& operator[] (
156
+ const long idx
157
+ ) const;
158
+ /*!
159
+ requires
160
+ - has_index(idx) == true
161
+ ensures
162
+ - returns a const reference to the value associated with index idx
163
+ !*/
164
+
165
+ void swap (
166
+ assignment& item
167
+ );
168
+ /*!
169
+ ensures
170
+ - swaps *this and item
171
+ !*/
172
+
173
+ };
174
+
175
+ inline void swap (
176
+ assignment& a,
177
+ assignment& b
178
+ ) { a.swap(b); }
179
+ /*!
180
+ provides a global swap
181
+ !*/
182
+
183
+ std::ostream& operator << (
184
+ std::ostream& out,
185
+ const assignment& a
186
+ );
187
+ /*!
188
+ ensures
189
+ - writes a to the given output stream in the following format:
190
+ (index1:value1, index2:value2, ..., indexN:valueN)
191
+ !*/
192
+
193
+ void serialize (
194
+ const assignment& item,
195
+ std::ostream& out
196
+ );
197
+ /*!
198
+ provides serialization support
199
+ !*/
200
+
201
+ void deserialize (
202
+ assignment& item,
203
+ std::istream& in
204
+ );
205
+ /*!
206
+ provides deserialization support
207
+ !*/
208
+
209
+ // ------------------------------------------------------------------------
210
+
211
+ class joint_probability_table : public enumerable<map_pair<assignment, double> >
212
+ {
213
+ /*!
214
+ INITIAL VALUE
215
+ - size() == 0
216
+
217
+ ENUMERATION ORDER
218
+ The enumerator will iterate over the entries in the probability table
219
+ in no particular order but they will all be visited.
220
+
221
+ WHAT THIS OBJECT REPRESENTS
222
+ This object models a joint probability table. That is, it models
223
+ the function p(X). So this object models the probability of a particular
224
+ set of variables (referred to as X).
225
+ !*/
226
+
227
+ public:
228
+
229
+ joint_probability_table(
230
+ );
231
+ /*!
232
+ ensures
233
+ - this object is properly initialized
234
+ !*/
235
+
236
+ joint_probability_table (
237
+ const joint_probability_table& t
238
+ );
239
+ /*!
240
+ ensures
241
+ - this object is a copy of t
242
+ !*/
243
+
244
+ void clear(
245
+ );
246
+ /*!
247
+ ensures
248
+ - this object has its initial value
249
+ !*/
250
+
251
+ joint_probability_table& operator= (
252
+ const joint_probability_table& rhs
253
+ );
254
+ /*!
255
+ ensures
256
+ - this object is a copy of rhs
257
+ - returns a reference to *this
258
+ !*/
259
+
260
+ bool has_entry_for (
261
+ const assignment& a
262
+ ) const;
263
+ /*!
264
+ ensures
265
+ - if (this joint_probability_table has an entry for p(X = a)) then
266
+ - returns true
267
+ - else
268
+ - returns false
269
+ !*/
270
+
271
+ void set_probability (
272
+ const assignment& a,
273
+ double p
274
+ );
275
+ /*!
276
+ requires
277
+ - 0 <= p <= 1
278
+ ensures
279
+ - if (has_entry_for(a) == false) then
280
+ - #size() == size() + 1
281
+ - #probability(a) == p
282
+ - #has_entry_for(a) == true
283
+ !*/
284
+
285
+ void add_probability (
286
+ const assignment& a,
287
+ double p
288
+ );
289
+ /*!
290
+ requires
291
+ - 0 <= p <= 1
292
+ ensures
293
+ - if (has_entry_for(a) == false) then
294
+ - #size() == size() + 1
295
+ - #probability(a) == p
296
+ - else
297
+ - #probability(a) == min(probability(a) + p, 1.0)
298
+ (i.e. does a saturating add)
299
+ - #has_entry_for(a) == true
300
+ !*/
301
+
302
+ const double probability (
303
+ const assignment& a
304
+ ) const;
305
+ /*!
306
+ ensures
307
+ - returns the probability p(X == a)
308
+ !*/
309
+
310
+ template <
311
+ typename T
312
+ >
313
+ void marginalize (
314
+ const T& vars,
315
+ joint_probability_table& output_table
316
+ ) const;
317
+ /*!
318
+ requires
319
+ - T is an implementation of set/set_kernel_abstract.h
320
+ ensures
321
+ - marginalizes *this by summing over all variables not in vars. The
322
+ result is stored in output_table.
323
+ !*/
324
+
325
+ void marginalize (
326
+ const unsigned long var,
327
+ joint_probability_table& output_table
328
+ ) const;
329
+ /*!
330
+ ensures
331
+ - is identical to calling the above marginalize() function with a set
332
+ that contains only var. Or in other words, performs a marginalization
333
+ with just one variable var. So that output_table will contain a table giving
334
+ the marginal probability of var all by itself.
335
+ !*/
336
+
337
+ void normalize (
338
+ );
339
+ /*!
340
+ ensures
341
+ - let sum == the sum of all the probabilities in this table
342
+ - after normalize() has finished it will be the case that the sum of all
343
+ the entries in this table is 1.0. This is accomplished by dividing all
344
+ the entries by the sum described above.
345
+ !*/
346
+
347
+ void swap (
348
+ joint_probability_table& item
349
+ );
350
+ /*!
351
+ ensures
352
+ - swaps *this and item
353
+ !*/
354
+
355
+ };
356
+
357
+ inline void swap (
358
+ joint_probability_table& a,
359
+ joint_probability_table& b
360
+ ) { a.swap(b); }
361
+ /*!
362
+ provides a global swap
363
+ !*/
364
+
365
+ void serialize (
366
+ const joint_probability_table& item,
367
+ std::ostream& out
368
+ );
369
+ /*!
370
+ provides serialization support
371
+ !*/
372
+
373
+ void deserialize (
374
+ joint_probability_table& item,
375
+ std::istream& in
376
+ );
377
+ /*!
378
+ provides deserialization support
379
+ !*/
380
+
381
+ // ----------------------------------------------------------------------------------------
382
+
383
+ class conditional_probability_table : noncopyable
384
+ {
385
+ /*!
386
+ INITIAL VALUE
387
+ - num_values() == 0
388
+ - has_value_for(x, y) == false for all values of x and y
389
+
390
+ WHAT THIS OBJECT REPRESENTS
391
+ This object models a conditional probability table. That is, it models
392
+ the function p( X | parents). So this object models the conditional
393
+ probability of a particular variable (referred to as X) given another set
394
+ of variables (referred to as parents).
395
+ !*/
396
+
397
+ public:
398
+
399
+ conditional_probability_table(
400
+ );
401
+ /*!
402
+ ensures
403
+ - this object is properly initialized
404
+ !*/
405
+
406
+ void clear(
407
+ );
408
+ /*!
409
+ ensures
410
+ - this object has its initial value
411
+ !*/
412
+
413
+ void empty_table (
414
+ );
415
+ /*!
416
+ ensures
417
+ - for all possible v and p:
418
+ - #has_entry_for(v,p) == false
419
+ (i.e. this function clears out the table when you call it but doesn't
420
+ change the value of num_values())
421
+ !*/
422
+
423
+ void set_num_values (
424
+ unsigned long num
425
+ );
426
+ /*!
427
+ ensures
428
+ - #num_values() == num
429
+ - for all possible v and p:
430
+ - #has_entry_for(v,p) == false
431
+ (i.e. this function clears out the table when you call it)
432
+ !*/
433
+
434
+ unsigned long num_values (
435
+ ) const;
436
+ /*!
437
+ ensures
438
+ - This object models the probability table p(X | parents). This
439
+ function returns the number of values X can take on.
440
+ !*/
441
+
442
+ bool has_entry_for (
443
+ unsigned long value,
444
+ const assignment& ps
445
+ ) const;
446
+ /*!
447
+ ensures
448
+ - if (this conditional_probability_table has an entry for p(X = value, parents = ps)) then
449
+ - returns true
450
+ - else
451
+ - returns false
452
+ !*/
453
+
454
+ void set_probability (
455
+ unsigned long value,
456
+ const assignment& ps,
457
+ double p
458
+ );
459
+ /*!
460
+ requires
461
+ - value < num_values()
462
+ - 0 <= p <= 1
463
+ ensures
464
+ - #probability(ps, value) == p
465
+ - #has_entry_for(value, ps) == true
466
+ !*/
467
+
468
+ double probability(
469
+ unsigned long value,
470
+ const assignment& ps
471
+ ) const;
472
+ /*!
473
+ requires
474
+ - value < num_values()
475
+ - has_entry_for(value, ps) == true
476
+ ensures
477
+ - returns the probability p( X = value | parents = ps).
478
+ !*/
479
+
480
+ void swap (
481
+ conditional_probability_table& item
482
+ );
483
+ /*!
484
+ ensures
485
+ - swaps *this and item
486
+ !*/
487
+ };
488
+
489
+ inline void swap (
490
+ conditional_probability_table& a,
491
+ conditional_probability_table& b
492
+ ) { a.swap(b); }
493
+ /*!
494
+ provides a global swap
495
+ !*/
496
+
497
+ void serialize (
498
+ const conditional_probability_table& item,
499
+ std::ostream& out
500
+ );
501
+ /*!
502
+ provides serialization support
503
+ !*/
504
+
505
+ void deserialize (
506
+ conditional_probability_table& item,
507
+ std::istream& in
508
+ );
509
+ /*!
510
+ provides deserialization support
511
+ !*/
512
+
513
+ // ------------------------------------------------------------------------
514
+ // ------------------------------------------------------------------------
515
+ // ------------------------------------------------------------------------
516
+
517
+ class bayes_node : noncopyable
518
+ {
519
+ /*!
520
+ INITIAL VALUE
521
+ - is_evidence() == false
522
+ - value() == 0
523
+ - table().num_values() == 0
524
+
525
+ WHAT THIS OBJECT REPRESENTS
526
+ This object represents a node in a bayesian network. It is
527
+ intended to be used inside the dlib::directed_graph object to
528
+ represent bayesian networks.
529
+ !*/
530
+
531
+ public:
532
+ bayes_node (
533
+ );
534
+ /*!
535
+ ensures
536
+ - this object is properly initialized
537
+ !*/
538
+
539
+ unsigned long value (
540
+ ) const;
541
+ /*!
542
+ ensures
543
+ - returns the current value of this node
544
+ !*/
545
+
546
+ void set_value (
547
+ unsigned long new_value
548
+ );
549
+ /*!
550
+ requires
551
+ - new_value < table().num_values()
552
+ ensures
553
+ - #value() == new_value
554
+ !*/
555
+
556
+ conditional_probability_table& table (
557
+ );
558
+ /*!
559
+ ensures
560
+ - returns a reference to the conditional_probability_table associated with this node
561
+ !*/
562
+
563
+ const conditional_probability_table& table (
564
+ ) const;
565
+ /*!
566
+ ensures
567
+ - returns a const reference to the conditional_probability_table associated with this
568
+ node.
569
+ !*/
570
+
571
+ bool is_evidence (
572
+ ) const;
573
+ /*!
574
+ ensures
575
+ - if (this is an evidence node) then
576
+ - returns true
577
+ - else
578
+ - returns false
579
+ !*/
580
+
581
+ void set_as_nonevidence (
582
+ );
583
+ /*!
584
+ ensures
585
+ - #is_evidence() == false
586
+ !*/
587
+
588
+ void set_as_evidence (
589
+ );
590
+ /*!
591
+ ensures
592
+ - #is_evidence() == true
593
+ !*/
594
+
595
+ void swap (
596
+ bayes_node& item
597
+ );
598
+ /*!
599
+ ensures
600
+ - swaps *this and item
601
+ !*/
602
+
603
+ };
604
+
605
+ inline void swap (
606
+ bayes_node& a,
607
+ bayes_node& b
608
+ ) { a.swap(b); }
609
+ /*!
610
+ provides a global swap
611
+ !*/
612
+
613
+ void serialize (
614
+ const bayes_node& item,
615
+ std::ostream& out
616
+ );
617
+ /*!
618
+ provides serialization support
619
+ !*/
620
+
621
+ void deserialize (
622
+ bayes_node& item,
623
+ std::istream& in
624
+ );
625
+ /*!
626
+ provides deserialization support
627
+ !*/
628
+
629
+ // ----------------------------------------------------------------------------------------
630
+ // ----------------------------------------------------------------------------------------
631
+ // ----------------------------------------------------------------------------------------
632
+
633
+ /*
634
+ The following group of functions are convenience functions for manipulating
635
+ bayes_node objects while they are inside a directed_graph. These functions
636
+ also have additional requires clauses that, in debug mode, will protect you
637
+ from attempts to manipulate a bayesian network in an inappropriate way.
638
+ */
639
+
640
+ namespace bayes_node_utils
641
+ {
642
+
643
+ template <
644
+ typename T
645
+ >
646
+ void set_node_value (
647
+ T& bn,
648
+ unsigned long n,
649
+ unsigned long val
650
+ );
651
+ /*!
652
+ requires
653
+ - T is an implementation of directed_graph/directed_graph_kernel_abstract.h
654
+ - T::type == bayes_node
655
+ - n < bn.number_of_nodes()
656
+ - val < node_num_values(bn, n)
657
+ ensures
658
+ - #bn.node(n).data.value() = val
659
+ !*/
660
+
661
+ // ------------------------------------------------------------------------------------
662
+
663
+ template <
664
+ typename T
665
+ >
666
+ unsigned long node_value (
667
+ const T& bn,
668
+ unsigned long n
669
+ );
670
+ /*!
671
+ requires
672
+ - T is an implementation of directed_graph/directed_graph_kernel_abstract.h
673
+ - T::type == bayes_node
674
+ - n < bn.number_of_nodes()
675
+ ensures
676
+ - returns bn.node(n).data.value()
677
+ !*/
678
+
679
+ // ------------------------------------------------------------------------------------
680
+
681
+ template <
682
+ typename T
683
+ >
684
+ bool node_is_evidence (
685
+ const T& bn,
686
+ unsigned long n
687
+ );
688
+ /*!
689
+ requires
690
+ - T is an implementation of directed_graph/directed_graph_kernel_abstract.h
691
+ - T::type == bayes_node
692
+ - n < bn.number_of_nodes()
693
+ ensures
694
+ - returns bn.node(n).data.is_evidence()
695
+ !*/
696
+
697
+ // ------------------------------------------------------------------------------------
698
+
699
+ template <
700
+ typename T
701
+ >
702
+ void set_node_as_evidence (
703
+ T& bn,
704
+ unsigned long n
705
+ );
706
+ /*!
707
+ requires
708
+ - T is an implementation of directed_graph/directed_graph_kernel_abstract.h
709
+ - T::type == bayes_node
710
+ - n < bn.number_of_nodes()
711
+ ensures
712
+ - executes: bn.node(n).data.set_as_evidence()
713
+ !*/
714
+
715
+ // ------------------------------------------------------------------------------------
716
+
717
+ template <
718
+ typename T
719
+ >
720
+ void set_node_as_nonevidence (
721
+ T& bn,
722
+ unsigned long n
723
+ );
724
+ /*!
725
+ requires
726
+ - T is an implementation of directed_graph/directed_graph_kernel_abstract.h
727
+ - T::type == bayes_node
728
+ - n < bn.number_of_nodes()
729
+ ensures
730
+ - executes: bn.node(n).data.set_as_nonevidence()
731
+ !*/
732
+
733
+ // ------------------------------------------------------------------------------------
734
+
735
+ template <
736
+ typename T
737
+ >
738
+ void set_node_num_values (
739
+ T& bn,
740
+ unsigned long n,
741
+ unsigned long num
742
+ );
743
+ /*!
744
+ requires
745
+ - T is an implementation of directed_graph/directed_graph_kernel_abstract.h
746
+ - T::type == bayes_node
747
+ - n < bn.number_of_nodes()
748
+ ensures
749
+ - #bn.node(n).data.table().num_values() == num
750
+ (i.e. sets the number of different values this node can take)
751
+ !*/
752
+
753
+ // ------------------------------------------------------------------------------------
754
+
755
+ template <
756
+ typename T
757
+ >
758
+ unsigned long node_num_values (
759
+ const T& bn,
760
+ unsigned long n
761
+ );
762
+ /*!
763
+ requires
764
+ - T is an implementation of directed_graph/directed_graph_kernel_abstract.h
765
+ - T::type == bayes_node
766
+ - n < bn.number_of_nodes()
767
+ ensures
768
+ - returns bn.node(n).data.table().num_values()
769
+ (i.e. returns the number of different values this node can take)
770
+ !*/
771
+
772
+ // ------------------------------------------------------------------------------------
773
+
774
+ template <
775
+ typename T
776
+ >
777
+ const double node_probability (
778
+ const T& bn,
779
+ unsigned long n,
780
+ unsigned long value,
781
+ const assignment& parents
782
+ );
783
+ /*!
784
+ requires
785
+ - T is an implementation of directed_graph/directed_graph_kernel_abstract.h
786
+ - T::type == bayes_node
787
+ - n < bn.number_of_nodes()
788
+ - value < node_num_values(bn,n)
789
+ - parents.size() == bn.node(n).number_of_parents()
790
+ - if (parents.has_index(x)) then
791
+ - bn.has_edge(x, n)
792
+ - parents[x] < node_num_values(bn,x)
793
+ ensures
794
+ - returns bn.node(n).data.table().probability(value, parents)
795
+ (i.e. returns the probability of node n having the given value when
796
+ its parents have the given assignment)
797
+ !*/
798
+
799
+ // ------------------------------------------------------------------------------------
800
+
801
+ template <
802
+ typename T
803
+ >
804
+ const double set_node_probability (
805
+ const T& bn,
806
+ unsigned long n,
807
+ unsigned long value,
808
+ const assignment& parents,
809
+ double p
810
+ );
811
+ /*!
812
+ requires
813
+ - T is an implementation of directed_graph/directed_graph_kernel_abstract.h
814
+ - T::type == bayes_node
815
+ - n < bn.number_of_nodes()
816
+ - value < node_num_values(bn,n)
817
+ - 0 <= p <= 1
818
+ - parents.size() == bn.node(n).number_of_parents()
819
+ - if (parents.has_index(x)) then
820
+ - bn.has_edge(x, n)
821
+ - parents[x] < node_num_values(bn,x)
822
+ ensures
823
+ - #bn.node(n).data.table().probability(value, parents) == p
824
+ (i.e. sets the probability of node n having the given value when
825
+ its parents have the given assignment to the probability p)
826
+ !*/
827
+
828
+ // ------------------------------------------------------------------------------------
829
+
830
+ template <typename T>
831
+ const assignment node_first_parent_assignment (
832
+ const T& bn,
833
+ unsigned long n
834
+ );
835
+ /*!
836
+ requires
837
+ - T is an implementation of directed_graph/directed_graph_kernel_abstract.h
838
+ - T::type == bayes_node
839
+ - n < bn.number_of_nodes()
840
+ ensures
841
+ - returns an assignment A such that:
842
+ - A.size() == bn.node(n).number_of_parents()
843
+ - if (P is a parent of bn.node(n)) then
844
+ - A.has_index(P)
845
+ - A[P] == 0
846
+ - I.e. this function returns an assignment that contains all
847
+ the parents of the given node. Also, all the values of each
848
+ parent in the assignment is set to zero.
849
+ !*/
850
+
851
+ // ------------------------------------------------------------------------------------
852
+
853
+ template <typename T>
854
+ bool node_next_parent_assignment (
855
+ const T& bn,
856
+ unsigned long n,
857
+ assignment& A
858
+ );
859
+ /*!
860
+ requires
861
+ - T is an implementation of directed_graph/directed_graph_kernel_abstract.h
862
+ - T::type == bayes_node
863
+ - n < bn.number_of_nodes()
864
+ - A.size() == bn.node(n).number_of_parents()
865
+ - if (A.has_index(x)) then
866
+ - bn.has_edge(x, n)
867
+ - A[x] < node_num_values(bn,x)
868
+ ensures
869
+ - The behavior of this function is defined by the following code:
870
+ assignment a(node_first_parent_assignment(bn,n);
871
+ do {
872
+ // this loop loops over all possible parent assignments
873
+ // of the node bn.node(n). Each time through the loop variable a
874
+ // will be the next assignment.
875
+ } while (node_next_parent_assignment(bn,n,a))
876
+ !*/
877
+
878
+ // ------------------------------------------------------------------------------------
879
+
880
+ template <typename T>
881
+ bool node_cpt_filled_out (
882
+ const T& bn,
883
+ unsigned long n
884
+ );
885
+ /*!
886
+ requires
887
+ - T is an implementation of directed_graph/directed_graph_kernel_abstract.h
888
+ - T::type == bayes_node
889
+ - n < bn.number_of_nodes()
890
+ ensures
891
+ - if (the conditional_probability_table bn.node(n).data.table() is
892
+ fully filled out for this node) then
893
+ - returns true
894
+ - This means that each parent assignment for the given node
895
+ along with all possible values of this node shows up in the
896
+ table.
897
+ - It also means that all the probabilities conditioned on the
898
+ same parent assignment sum to 1.0
899
+ - else
900
+ - returns false
901
+ !*/
902
+
903
+ }
904
+
905
+ // ----------------------------------------------------------------------------------------
906
+ // ----------------------------------------------------------------------------------------
907
+ // ----------------------------------------------------------------------------------------
908
+
909
+ class bayesian_network_gibbs_sampler : noncopyable
910
+ {
911
+ /*!
912
+ INITIAL VALUE
913
+ This object has no state
914
+
915
+ WHAT THIS OBJECT REPRESENTS
916
+ This object performs Markov Chain Monte Carlo sampling of a bayesian
917
+ network using the Gibbs sampling technique.
918
+
919
+ Note that this object is limited to only bayesian networks that
920
+ don't contain deterministic nodes. That is, incorrect results may
921
+ be computed if this object is used when the bayesian network contains
922
+ any nodes that have a probability of 1 in their conditional probability
923
+ tables for any event. So don't use this object for networks with
924
+ deterministic nodes.
925
+ !*/
926
+ public:
927
+
928
+ bayesian_network_gibbs_sampler (
929
+ );
930
+ /*!
931
+ ensures
932
+ - this object is properly initialized
933
+ !*/
934
+
935
+ template <
936
+ typename T
937
+ >
938
+ void sample_graph (
939
+ T& bn
940
+ )
941
+ /*!
942
+ requires
943
+ - T is an implementation of directed_graph/directed_graph_kernel_abstract.h
944
+ - T::type == bayes_node
945
+ ensures
946
+ - modifies randomly (via the Gibbs sampling technique) samples all the nodes
947
+ in the network and updates their values with the newly sampled values
948
+ !*/
949
+ };
950
+
951
+ // ----------------------------------------------------------------------------------------
952
+
953
+ class bayesian_network_join_tree : noncopyable
954
+ {
955
+ /*!
956
+ WHAT THIS OBJECT REPRESENTS
957
+ This object represents an implementation of the join tree algorithm
958
+ for inference in bayesian networks. It doesn't have any mutable state.
959
+ To you use you just give it a directed_graph that contains a bayesian
960
+ network and a graph object that contains that networks corresponding
961
+ join tree. Then you may query this object to determine the probabilities
962
+ of any variables in the original bayesian network.
963
+ !*/
964
+
965
+ public:
966
+
967
+ template <
968
+ typename bn_type,
969
+ typename join_tree_type
970
+ >
971
+ bayesian_network_join_tree (
972
+ const bn_type& bn,
973
+ const join_tree_type& join_tree
974
+ );
975
+ /*!
976
+ requires
977
+ - bn_type is an implementation of directed_graph/directed_graph_kernel_abstract.h
978
+ - bn_type::type == bayes_node
979
+ - join_tree_type is an implementation of graph/graph_kernel_abstract.h
980
+ - join_tree_type::type is an implementation of set/set_compare_abstract.h and
981
+ this set type contains unsigned long objects.
982
+ - join_tree_type::edge_type is an implementation of set/set_compare_abstract.h and
983
+ this set type contains unsigned long objects.
984
+ - is_join_tree(bn, join_tree) == true
985
+ - bn == a valid bayesian network with all its conditional probability tables
986
+ filled out
987
+ - for all valid n:
988
+ - node_cpt_filled_out(bn,n) == true
989
+ - graph_contains_length_one_cycle(bn) == false
990
+ - graph_is_connected(bn) == true
991
+ - bn.number_of_nodes() > 0
992
+ ensures
993
+ - this object is properly initialized
994
+ !*/
995
+
996
+ unsigned long number_of_nodes (
997
+ ) const;
998
+ /*!
999
+ ensures
1000
+ - returns the number of nodes in the bayesian network that this
1001
+ object was instantiated from.
1002
+ !*/
1003
+
1004
+ const matrix<double,1> probability(
1005
+ unsigned long idx
1006
+ ) const;
1007
+ /*!
1008
+ requires
1009
+ - idx < number_of_nodes()
1010
+ ensures
1011
+ - returns the probability distribution for the node with index idx that was in the bayesian
1012
+ network that *this was instantiated from. Let D represent this distribution, then:
1013
+ - D.nc() == the number of values the node idx ranges over
1014
+ - D.nr() == 1
1015
+ - D(i) == the probability of node idx taking on the value i
1016
+ !*/
1017
+
1018
+ void swap (
1019
+ bayesian_network_join_tree& item
1020
+ );
1021
+ /*!
1022
+ ensures
1023
+ - swaps *this with item
1024
+ !*/
1025
+
1026
+ };
1027
+
1028
+ inline void swap (
1029
+ bayesian_network_join_tree& a,
1030
+ bayesian_network_join_tree& b
1031
+ ) { a.swap(b); }
1032
+ /*!
1033
+ provides a global swap
1034
+ !*/
1035
+
1036
+ // ----------------------------------------------------------------------------------------
1037
+
1038
+ }
1039
+
1040
+ #endif // DLIB_BAYES_UTILs_ABSTRACT_
1041
+
1042
+
dlibs/dlib/bigint.h ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (C) 2003 Davis E. King ([email protected])
2
+ // License: Boost Software License See LICENSE.txt for the full license.
3
+ #ifndef DLIB_BIGINt_
4
+ #define DLIB_BIGINt_
5
+
6
+ #include "bigint/bigint_kernel_1.h"
7
+ #include "bigint/bigint_kernel_2.h"
8
+ #include "bigint/bigint_kernel_c.h"
9
+
10
+
11
+
12
+
13
+ namespace dlib
14
+ {
15
+
16
+
17
+ class bigint
18
+ {
19
+ bigint() {}
20
+
21
+
22
+ public:
23
+
24
+ //----------- kernels ---------------
25
+
26
+ // kernel_1a
27
+ typedef bigint_kernel_1
28
+ kernel_1a;
29
+ typedef bigint_kernel_c<kernel_1a>
30
+ kernel_1a_c;
31
+
32
+ // kernel_2a
33
+ typedef bigint_kernel_2
34
+ kernel_2a;
35
+ typedef bigint_kernel_c<kernel_2a>
36
+ kernel_2a_c;
37
+
38
+
39
+ };
40
+ }
41
+
42
+ #endif // DLIB_BIGINt_
43
+
dlibs/dlib/bigint/bigint_kernel_1.cpp ADDED
@@ -0,0 +1,1720 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (C) 2003 Davis E. King ([email protected])
2
+ // License: Boost Software License See LICENSE.txt for the full license.
3
+ #ifndef DLIB_BIGINT_KERNEL_1_CPp_
4
+ #define DLIB_BIGINT_KERNEL_1_CPp_
5
+ #include "bigint_kernel_1.h"
6
+
7
+ #include <iostream>
8
+
9
+ namespace dlib
10
+ {
11
+
12
+ // ----------------------------------------------------------------------------------------
13
+ // ----------------------------------------------------------------------------------------
14
+ // member/friend function definitions
15
+ // ----------------------------------------------------------------------------------------
16
+ // ----------------------------------------------------------------------------------------
17
+
18
+ bigint_kernel_1::
19
+ bigint_kernel_1 (
20
+ ) :
21
+ slack(25),
22
+ data(new data_record(slack))
23
+ {}
24
+
25
+ // ----------------------------------------------------------------------------------------
26
+
27
+ bigint_kernel_1::
28
+ bigint_kernel_1 (
29
+ uint32 value
30
+ ) :
31
+ slack(25),
32
+ data(new data_record(slack))
33
+ {
34
+ *(data->number) = static_cast<uint16>(value&0xFFFF);
35
+ *(data->number+1) = static_cast<uint16>((value>>16)&0xFFFF);
36
+ if (*(data->number+1) != 0)
37
+ data->digits_used = 2;
38
+ }
39
+
40
+ // ----------------------------------------------------------------------------------------
41
+
42
+ bigint_kernel_1::
43
+ bigint_kernel_1 (
44
+ const bigint_kernel_1& item
45
+ ) :
46
+ slack(25),
47
+ data(item.data)
48
+ {
49
+ data->references += 1;
50
+ }
51
+
52
+ // ----------------------------------------------------------------------------------------
53
+
54
+ bigint_kernel_1::
55
+ ~bigint_kernel_1 (
56
+ )
57
+ {
58
+ if (data->references == 1)
59
+ {
60
+ delete data;
61
+ }
62
+ else
63
+ {
64
+ data->references -= 1;
65
+ }
66
+ }
67
+
68
+ // ----------------------------------------------------------------------------------------
69
+
70
+ const bigint_kernel_1 bigint_kernel_1::
71
+ operator+ (
72
+ const bigint_kernel_1& rhs
73
+ ) const
74
+ {
75
+ data_record* temp = new data_record (
76
+ std::max(rhs.data->digits_used,data->digits_used) + slack
77
+ );
78
+ long_add(data,rhs.data,temp);
79
+ return bigint_kernel_1(temp,0);
80
+ }
81
+
82
+ // ----------------------------------------------------------------------------------------
83
+
84
+ bigint_kernel_1& bigint_kernel_1::
85
+ operator+= (
86
+ const bigint_kernel_1& rhs
87
+ )
88
+ {
89
+ // if there are other references to our data
90
+ if (data->references != 1)
91
+ {
92
+ data_record* temp = new data_record(std::max(data->digits_used,rhs.data->digits_used)+slack);
93
+ data->references -= 1;
94
+ long_add(data,rhs.data,temp);
95
+ data = temp;
96
+ }
97
+ // if data is not big enough for the result
98
+ else if (data->size <= std::max(data->digits_used,rhs.data->digits_used))
99
+ {
100
+ data_record* temp = new data_record(std::max(data->digits_used,rhs.data->digits_used)+slack);
101
+ long_add(data,rhs.data,temp);
102
+ delete data;
103
+ data = temp;
104
+ }
105
+ // there is enough size and no references
106
+ else
107
+ {
108
+ long_add(data,rhs.data,data);
109
+ }
110
+ return *this;
111
+ }
112
+
113
+ // ----------------------------------------------------------------------------------------
114
+
115
+ const bigint_kernel_1 bigint_kernel_1::
116
+ operator- (
117
+ const bigint_kernel_1& rhs
118
+ ) const
119
+ {
120
+ data_record* temp = new data_record (
121
+ data->digits_used + slack
122
+ );
123
+ long_sub(data,rhs.data,temp);
124
+ return bigint_kernel_1(temp,0);
125
+ }
126
+
127
+ // ----------------------------------------------------------------------------------------
128
+
129
+ bigint_kernel_1& bigint_kernel_1::
130
+ operator-= (
131
+ const bigint_kernel_1& rhs
132
+ )
133
+ {
134
+ // if there are other references to this data
135
+ if (data->references != 1)
136
+ {
137
+ data_record* temp = new data_record(data->digits_used+slack);
138
+ data->references -= 1;
139
+ long_sub(data,rhs.data,temp);
140
+ data = temp;
141
+ }
142
+ else
143
+ {
144
+ long_sub(data,rhs.data,data);
145
+ }
146
+ return *this;
147
+ }
148
+
149
+ // ----------------------------------------------------------------------------------------
150
+
151
+ const bigint_kernel_1 bigint_kernel_1::
152
+ operator* (
153
+ const bigint_kernel_1& rhs
154
+ ) const
155
+ {
156
+ data_record* temp = new data_record (
157
+ data->digits_used + rhs.data->digits_used + slack
158
+ );
159
+ long_mul(data,rhs.data,temp);
160
+ return bigint_kernel_1(temp,0);
161
+ }
162
+
163
+ // ----------------------------------------------------------------------------------------
164
+
165
+ bigint_kernel_1& bigint_kernel_1::
166
+ operator*= (
167
+ const bigint_kernel_1& rhs
168
+ )
169
+ {
170
+ // create a data_record to store the result of the multiplication in
171
+ data_record* temp = new data_record(rhs.data->digits_used+data->digits_used+slack);
172
+ long_mul(data,rhs.data,temp);
173
+
174
+ // if there are other references to data
175
+ if (data->references != 1)
176
+ {
177
+ data->references -= 1;
178
+ }
179
+ else
180
+ {
181
+ delete data;
182
+ }
183
+ data = temp;
184
+ return *this;
185
+ }
186
+
187
+ // ----------------------------------------------------------------------------------------
188
+
189
+ const bigint_kernel_1 bigint_kernel_1::
190
+ operator/ (
191
+ const bigint_kernel_1& rhs
192
+ ) const
193
+ {
194
+ data_record* temp = new data_record(data->digits_used+slack);
195
+ data_record* remainder;
196
+ try {
197
+ remainder = new data_record(data->digits_used+slack);
198
+ } catch (...) { delete temp; throw; }
199
+
200
+ long_div(data,rhs.data,temp,remainder);
201
+ delete remainder;
202
+
203
+
204
+ return bigint_kernel_1(temp,0);
205
+ }
206
+
207
+ // ----------------------------------------------------------------------------------------
208
+
209
+ bigint_kernel_1& bigint_kernel_1::
210
+ operator/= (
211
+ const bigint_kernel_1& rhs
212
+ )
213
+ {
214
+
215
+ data_record* temp = new data_record(data->digits_used+slack);
216
+ data_record* remainder;
217
+ try {
218
+ remainder = new data_record(data->digits_used+slack);
219
+ } catch (...) { delete temp; throw; }
220
+
221
+ long_div(data,rhs.data,temp,remainder);
222
+
223
+ // check if there are other references to data
224
+ if (data->references != 1)
225
+ {
226
+ data->references -= 1;
227
+ }
228
+ // if there are no references to data then it must be deleted
229
+ else
230
+ {
231
+ delete data;
232
+ }
233
+ data = temp;
234
+ delete remainder;
235
+
236
+
237
+ return *this;
238
+ }
239
+
240
+ // ----------------------------------------------------------------------------------------
241
+
242
+ const bigint_kernel_1 bigint_kernel_1::
243
+ operator% (
244
+ const bigint_kernel_1& rhs
245
+ ) const
246
+ {
247
+ data_record* temp = new data_record(data->digits_used+slack);
248
+ data_record* remainder;
249
+ try {
250
+ remainder = new data_record(data->digits_used+slack);
251
+ } catch (...) { delete temp; throw; }
252
+
253
+ long_div(data,rhs.data,temp,remainder);
254
+ delete temp;
255
+ return bigint_kernel_1(remainder,0);
256
+ }
257
+
258
+ // ----------------------------------------------------------------------------------------
259
+
260
+ bigint_kernel_1& bigint_kernel_1::
261
+ operator%= (
262
+ const bigint_kernel_1& rhs
263
+ )
264
+ {
265
+ data_record* temp = new data_record(data->digits_used+slack);
266
+ data_record* remainder;
267
+ try {
268
+ remainder = new data_record(data->digits_used+slack);
269
+ } catch (...) { delete temp; throw; }
270
+
271
+ long_div(data,rhs.data,temp,remainder);
272
+
273
+ // check if there are other references to data
274
+ if (data->references != 1)
275
+ {
276
+ data->references -= 1;
277
+ }
278
+ // if there are no references to data then it must be deleted
279
+ else
280
+ {
281
+ delete data;
282
+ }
283
+ data = remainder;
284
+ delete temp;
285
+ return *this;
286
+ }
287
+
288
+ // ----------------------------------------------------------------------------------------
289
+
290
+ bool bigint_kernel_1::
291
+ operator < (
292
+ const bigint_kernel_1& rhs
293
+ ) const
294
+ {
295
+ return is_less_than(data,rhs.data);
296
+ }
297
+
298
+ // ----------------------------------------------------------------------------------------
299
+
300
+ bool bigint_kernel_1::
301
+ operator == (
302
+ const bigint_kernel_1& rhs
303
+ ) const
304
+ {
305
+ return is_equal_to(data,rhs.data);
306
+ }
307
+
308
+ // ----------------------------------------------------------------------------------------
309
+
310
+ bigint_kernel_1& bigint_kernel_1::
311
+ operator= (
312
+ const bigint_kernel_1& rhs
313
+ )
314
+ {
315
+ if (this == &rhs)
316
+ return *this;
317
+
318
+ // if we have the only reference to our data then delete it
319
+ if (data->references == 1)
320
+ {
321
+ delete data;
322
+ data = rhs.data;
323
+ data->references += 1;
324
+ }
325
+ else
326
+ {
327
+ data->references -= 1;
328
+ data = rhs.data;
329
+ data->references += 1;
330
+ }
331
+
332
+ return *this;
333
+ }
334
+
335
+ // ----------------------------------------------------------------------------------------
336
+
337
+ std::ostream& operator<< (
338
+ std::ostream& out_,
339
+ const bigint_kernel_1& rhs
340
+ )
341
+ {
342
+ std::ostream out(out_.rdbuf());
343
+
344
+ typedef bigint_kernel_1 bigint;
345
+
346
+ bigint::data_record* temp = new bigint::data_record(*rhs.data,0);
347
+
348
+
349
+
350
+ // get a char array big enough to hold the number in ascii format
351
+ char* str;
352
+ try {
353
+ str = new char[(rhs.data->digits_used)*5+10];
354
+ } catch (...) { delete temp; throw; }
355
+
356
+ char* str_start = str;
357
+ str += (rhs.data->digits_used)*5+9;
358
+ *str = 0; --str;
359
+
360
+
361
+ uint16 remainder;
362
+ rhs.short_div(temp,10000,temp,remainder);
363
+
364
+ // pull the digits out of remainder
365
+ char a = remainder % 10 + '0';
366
+ remainder /= 10;
367
+ char b = remainder % 10 + '0';
368
+ remainder /= 10;
369
+ char c = remainder % 10 + '0';
370
+ remainder /= 10;
371
+ char d = remainder % 10 + '0';
372
+ remainder /= 10;
373
+
374
+
375
+ *str = a; --str;
376
+ *str = b; --str;
377
+ *str = c; --str;
378
+ *str = d; --str;
379
+
380
+
381
+ // keep looping until temp represents zero
382
+ while (temp->digits_used != 1 || *(temp->number) != 0)
383
+ {
384
+ rhs.short_div(temp,10000,temp,remainder);
385
+
386
+ // pull the digits out of remainder
387
+ char a = remainder % 10 + '0';
388
+ remainder /= 10;
389
+ char b = remainder % 10 + '0';
390
+ remainder /= 10;
391
+ char c = remainder % 10 + '0';
392
+ remainder /= 10;
393
+ char d = remainder % 10 + '0';
394
+ remainder /= 10;
395
+
396
+ *str = a; --str;
397
+ *str = b; --str;
398
+ *str = c; --str;
399
+ *str = d; --str;
400
+ }
401
+
402
+ // throw away and extra leading zeros
403
+ ++str;
404
+ if (*str == '0')
405
+ ++str;
406
+ if (*str == '0')
407
+ ++str;
408
+ if (*str == '0')
409
+ ++str;
410
+
411
+
412
+
413
+
414
+ out << str;
415
+ delete [] str_start;
416
+ delete temp;
417
+ return out_;
418
+
419
+ }
420
+
421
+ // ----------------------------------------------------------------------------------------
422
+
423
+ std::istream& operator>> (
424
+ std::istream& in_,
425
+ bigint_kernel_1& rhs
426
+ )
427
+ {
428
+ std::istream in(in_.rdbuf());
429
+
430
+ // ignore any leading whitespaces
431
+ while (in.peek() == ' ' || in.peek() == '\t' || in.peek() == '\n')
432
+ {
433
+ in.get();
434
+ }
435
+
436
+ // if the first digit is not an integer then this is an error
437
+ if ( !(in.peek() >= '0' && in.peek() <= '9'))
438
+ {
439
+ in_.clear(std::ios::failbit);
440
+ return in_;
441
+ }
442
+
443
+ int num_read;
444
+ bigint_kernel_1 temp;
445
+ do
446
+ {
447
+
448
+ // try to get 4 chars from in
449
+ num_read = 1;
450
+ char a = 0;
451
+ char b = 0;
452
+ char c = 0;
453
+ char d = 0;
454
+
455
+ if (in.peek() >= '0' && in.peek() <= '9')
456
+ {
457
+ num_read *= 10;
458
+ a = in.get();
459
+ }
460
+ if (in.peek() >= '0' && in.peek() <= '9')
461
+ {
462
+ num_read *= 10;
463
+ b = in.get();
464
+ }
465
+ if (in.peek() >= '0' && in.peek() <= '9')
466
+ {
467
+ num_read *= 10;
468
+ c = in.get();
469
+ }
470
+ if (in.peek() >= '0' && in.peek() <= '9')
471
+ {
472
+ num_read *= 10;
473
+ d = in.get();
474
+ }
475
+
476
+ // merge the for digits into an uint16
477
+ uint16 num = 0;
478
+ if (a != 0)
479
+ {
480
+ num = a - '0';
481
+ }
482
+ if (b != 0)
483
+ {
484
+ num *= 10;
485
+ num += b - '0';
486
+ }
487
+ if (c != 0)
488
+ {
489
+ num *= 10;
490
+ num += c - '0';
491
+ }
492
+ if (d != 0)
493
+ {
494
+ num *= 10;
495
+ num += d - '0';
496
+ }
497
+
498
+
499
+ if (num_read != 1)
500
+ {
501
+ // shift the digits in temp left by the number of new digits we just read
502
+ temp *= num_read;
503
+ // add in new digits
504
+ temp += num;
505
+ }
506
+
507
+ } while (num_read == 10000);
508
+
509
+
510
+ rhs = temp;
511
+ return in_;
512
+ }
513
+
514
+ // ----------------------------------------------------------------------------------------
515
+
516
+ const bigint_kernel_1 operator+ (
517
+ uint16 lhs,
518
+ const bigint_kernel_1& rhs
519
+ )
520
+ {
521
+ typedef bigint_kernel_1 bigint;
522
+ bigint::data_record* temp = new bigint::data_record
523
+ (rhs.data->digits_used+rhs.slack);
524
+
525
+ rhs.short_add(rhs.data,lhs,temp);
526
+ return bigint_kernel_1(temp,0);
527
+ }
528
+
529
+ // ----------------------------------------------------------------------------------------
530
+
531
+ const bigint_kernel_1 operator+ (
532
+ const bigint_kernel_1& lhs,
533
+ uint16 rhs
534
+ )
535
+ {
536
+ typedef bigint_kernel_1 bigint;
537
+ bigint::data_record* temp = new bigint::data_record
538
+ (lhs.data->digits_used+lhs.slack);
539
+
540
+ lhs.short_add(lhs.data,rhs,temp);
541
+ return bigint_kernel_1(temp,0);
542
+ }
543
+
544
+ // ----------------------------------------------------------------------------------------
545
+
546
+ bigint_kernel_1& bigint_kernel_1::
547
+ operator+= (
548
+ uint16 rhs
549
+ )
550
+ {
551
+ // if there are other references to this data
552
+ if (data->references != 1)
553
+ {
554
+ data_record* temp = new data_record(data->digits_used+slack);
555
+ data->references -= 1;
556
+ short_add(data,rhs,temp);
557
+ data = temp;
558
+ }
559
+ // or if we need to enlarge data then do so
560
+ else if (data->digits_used == data->size)
561
+ {
562
+ data_record* temp = new data_record(data->digits_used+slack);
563
+ short_add(data,rhs,temp);
564
+ delete data;
565
+ data = temp;
566
+ }
567
+ // or if there is plenty of space and no references
568
+ else
569
+ {
570
+ short_add(data,rhs,data);
571
+ }
572
+ return *this;
573
+ }
574
+
575
+ // ----------------------------------------------------------------------------------------
576
+
577
+ const bigint_kernel_1 operator- (
578
+ uint16 lhs,
579
+ const bigint_kernel_1& rhs
580
+ )
581
+ {
582
+ typedef bigint_kernel_1 bigint;
583
+ bigint::data_record* temp = new bigint::data_record(rhs.slack);
584
+
585
+ *(temp->number) = lhs - *(rhs.data->number);
586
+
587
+ return bigint_kernel_1(temp,0);
588
+ }
589
+
590
+ // ----------------------------------------------------------------------------------------
591
+
592
+ const bigint_kernel_1 operator- (
593
+ const bigint_kernel_1& lhs,
594
+ uint16 rhs
595
+ )
596
+ {
597
+ typedef bigint_kernel_1 bigint;
598
+ bigint::data_record* temp = new bigint::data_record
599
+ (lhs.data->digits_used+lhs.slack);
600
+
601
+ lhs.short_sub(lhs.data,rhs,temp);
602
+ return bigint_kernel_1(temp,0);
603
+ }
604
+
605
+ // ----------------------------------------------------------------------------------------
606
+
607
+ bigint_kernel_1& bigint_kernel_1::
608
+ operator-= (
609
+ uint16 rhs
610
+ )
611
+ {
612
+ // if there are other references to this data
613
+ if (data->references != 1)
614
+ {
615
+ data_record* temp = new data_record(data->digits_used+slack);
616
+ data->references -= 1;
617
+ short_sub(data,rhs,temp);
618
+ data = temp;
619
+ }
620
+ else
621
+ {
622
+ short_sub(data,rhs,data);
623
+ }
624
+ return *this;
625
+ }
626
+
627
+ // ----------------------------------------------------------------------------------------
628
+
629
+ const bigint_kernel_1 operator* (
630
+ uint16 lhs,
631
+ const bigint_kernel_1& rhs
632
+ )
633
+ {
634
+ typedef bigint_kernel_1 bigint;
635
+ bigint::data_record* temp = new bigint::data_record
636
+ (rhs.data->digits_used+rhs.slack);
637
+
638
+ rhs.short_mul(rhs.data,lhs,temp);
639
+ return bigint_kernel_1(temp,0);
640
+ }
641
+
642
+ // ----------------------------------------------------------------------------------------
643
+
644
+ const bigint_kernel_1 operator* (
645
+ const bigint_kernel_1& lhs,
646
+ uint16 rhs
647
+ )
648
+ {
649
+ typedef bigint_kernel_1 bigint;
650
+ bigint::data_record* temp = new bigint::data_record
651
+ (lhs.data->digits_used+lhs.slack);
652
+
653
+ lhs.short_mul(lhs.data,rhs,temp);
654
+ return bigint_kernel_1(temp,0);
655
+ }
656
+
657
+ // ----------------------------------------------------------------------------------------
658
+
659
+ bigint_kernel_1& bigint_kernel_1::
660
+ operator*= (
661
+ uint16 rhs
662
+ )
663
+ {
664
+ // if there are other references to this data
665
+ if (data->references != 1)
666
+ {
667
+ data_record* temp = new data_record(data->digits_used+slack);
668
+ data->references -= 1;
669
+ short_mul(data,rhs,temp);
670
+ data = temp;
671
+ }
672
+ // or if we need to enlarge data
673
+ else if (data->digits_used == data->size)
674
+ {
675
+ data_record* temp = new data_record(data->digits_used+slack);
676
+ short_mul(data,rhs,temp);
677
+ delete data;
678
+ data = temp;
679
+ }
680
+ else
681
+ {
682
+ short_mul(data,rhs,data);
683
+ }
684
+ return *this;
685
+ }
686
+
687
+ // ----------------------------------------------------------------------------------------
688
+
689
+ const bigint_kernel_1 operator/ (
690
+ uint16 lhs,
691
+ const bigint_kernel_1& rhs
692
+ )
693
+ {
694
+ typedef bigint_kernel_1 bigint;
695
+ bigint::data_record* temp = new bigint::data_record(rhs.slack);
696
+
697
+ // if rhs might not be bigger than lhs
698
+ if (rhs.data->digits_used == 1)
699
+ {
700
+ *(temp->number) = lhs/ *(rhs.data->number);
701
+ }
702
+
703
+ return bigint_kernel_1(temp,0);
704
+ }
705
+
706
+ // ----------------------------------------------------------------------------------------
707
+
708
+ const bigint_kernel_1 operator/ (
709
+ const bigint_kernel_1& lhs,
710
+ uint16 rhs
711
+ )
712
+ {
713
+ typedef bigint_kernel_1 bigint;
714
+ bigint::data_record* temp = new bigint::data_record
715
+ (lhs.data->digits_used+lhs.slack);
716
+
717
+ uint16 remainder;
718
+ lhs.short_div(lhs.data,rhs,temp,remainder);
719
+ return bigint_kernel_1(temp,0);
720
+ }
721
+
722
+ // ----------------------------------------------------------------------------------------
723
+
724
+ bigint_kernel_1& bigint_kernel_1::
725
+ operator/= (
726
+ uint16 rhs
727
+ )
728
+ {
729
+ uint16 remainder;
730
+ // if there are other references to this data
731
+ if (data->references != 1)
732
+ {
733
+ data_record* temp = new data_record(data->digits_used+slack);
734
+ data->references -= 1;
735
+ short_div(data,rhs,temp,remainder);
736
+ data = temp;
737
+ }
738
+ else
739
+ {
740
+ short_div(data,rhs,data,remainder);
741
+ }
742
+ return *this;
743
+ }
744
+
745
+ // ----------------------------------------------------------------------------------------
746
+
747
+ const bigint_kernel_1 operator% (
748
+ uint16 lhs,
749
+ const bigint_kernel_1& rhs
750
+ )
751
+ {
752
+ typedef bigint_kernel_1 bigint;
753
+ // temp is zero by default
754
+ bigint::data_record* temp = new bigint::data_record(rhs.slack);
755
+
756
+ if (rhs.data->digits_used == 1)
757
+ {
758
+ // if rhs is just an uint16 inside then perform the modulus
759
+ *(temp->number) = lhs % *(rhs.data->number);
760
+ }
761
+ else
762
+ {
763
+ // if rhs is bigger than lhs then the answer is lhs
764
+ *(temp->number) = lhs;
765
+ }
766
+
767
+ return bigint_kernel_1(temp,0);
768
+ }
769
+
770
+ // ----------------------------------------------------------------------------------------
771
+
772
+ const bigint_kernel_1 operator% (
773
+ const bigint_kernel_1& lhs,
774
+ uint16 rhs
775
+ )
776
+ {
777
+ typedef bigint_kernel_1 bigint;
778
+ bigint::data_record* temp = new bigint::data_record(lhs.data->digits_used+lhs.slack);
779
+
780
+ uint16 remainder;
781
+
782
+ lhs.short_div(lhs.data,rhs,temp,remainder);
783
+ temp->digits_used = 1;
784
+ *(temp->number) = remainder;
785
+ return bigint_kernel_1(temp,0);
786
+ }
787
+
788
+ // ----------------------------------------------------------------------------------------
789
+
790
+ bigint_kernel_1& bigint_kernel_1::
791
+ operator%= (
792
+ uint16 rhs
793
+ )
794
+ {
795
+ uint16 remainder;
796
+ // if there are other references to this data
797
+ if (data->references != 1)
798
+ {
799
+ data_record* temp = new data_record(data->digits_used+slack);
800
+ data->references -= 1;
801
+ short_div(data,rhs,temp,remainder);
802
+ data = temp;
803
+ }
804
+ else
805
+ {
806
+ short_div(data,rhs,data,remainder);
807
+ }
808
+
809
+ data->digits_used = 1;
810
+ *(data->number) = remainder;
811
+ return *this;
812
+ }
813
+
814
+ // ----------------------------------------------------------------------------------------
815
+
816
+ bool operator < (
817
+ uint16 lhs,
818
+ const bigint_kernel_1& rhs
819
+ )
820
+ {
821
+ return (rhs.data->digits_used > 1 || lhs < *(rhs.data->number) );
822
+ }
823
+
824
+ // ----------------------------------------------------------------------------------------
825
+
826
+ bool operator < (
827
+ const bigint_kernel_1& lhs,
828
+ uint16 rhs
829
+ )
830
+ {
831
+ return (lhs.data->digits_used == 1 && *(lhs.data->number) < rhs);
832
+ }
833
+
834
+ // ----------------------------------------------------------------------------------------
835
+
836
+ bool operator == (
837
+ const bigint_kernel_1& lhs,
838
+ uint16 rhs
839
+ )
840
+ {
841
+ return (lhs.data->digits_used == 1 && *(lhs.data->number) == rhs);
842
+ }
843
+
844
+ // ----------------------------------------------------------------------------------------
845
+
846
+ bool operator == (
847
+ uint16 lhs,
848
+ const bigint_kernel_1& rhs
849
+ )
850
+ {
851
+ return (rhs.data->digits_used == 1 && *(rhs.data->number) == lhs);
852
+ }
853
+
854
+ // ----------------------------------------------------------------------------------------
855
+
856
+ bigint_kernel_1& bigint_kernel_1::
857
+ operator= (
858
+ uint16 rhs
859
+ )
860
+ {
861
+ // check if there are other references to our data
862
+ if (data->references != 1)
863
+ {
864
+ data->references -= 1;
865
+ try {
866
+ data = new data_record(slack);
867
+ } catch (...) { data->references += 1; throw; }
868
+ }
869
+ else
870
+ {
871
+ data->digits_used = 1;
872
+ }
873
+
874
+ *(data->number) = rhs;
875
+
876
+ return *this;
877
+ }
878
+
879
+ // ----------------------------------------------------------------------------------------
880
+
881
+ bigint_kernel_1& bigint_kernel_1::
882
+ operator++ (
883
+ )
884
+ {
885
+ // if there are other references to this data then make a copy of it
886
+ if (data->references != 1)
887
+ {
888
+ data_record* temp = new data_record(data->digits_used+slack);
889
+ data->references -= 1;
890
+ increment(data,temp);
891
+ data = temp;
892
+ }
893
+ // or if we need to enlarge data then do so
894
+ else if (data->digits_used == data->size)
895
+ {
896
+ data_record* temp = new data_record(data->digits_used+slack);
897
+ increment(data,temp);
898
+ delete data;
899
+ data = temp;
900
+ }
901
+ else
902
+ {
903
+ increment(data,data);
904
+ }
905
+
906
+ return *this;
907
+ }
908
+
909
+ // ----------------------------------------------------------------------------------------
910
+
911
+ const bigint_kernel_1 bigint_kernel_1::
912
+ operator++ (
913
+ int
914
+ )
915
+ {
916
+ data_record* temp; // this is the copy of temp we will return in the end
917
+
918
+ data_record* temp2 = new data_record(data->digits_used+slack);
919
+ increment(data,temp2);
920
+
921
+ temp = data;
922
+ data = temp2;
923
+
924
+ return bigint_kernel_1(temp,0);
925
+ }
926
+
927
+ // ----------------------------------------------------------------------------------------
928
+
929
+ bigint_kernel_1& bigint_kernel_1::
930
+ operator-- (
931
+ )
932
+ {
933
+ // if there are other references to this data
934
+ if (data->references != 1)
935
+ {
936
+ data_record* temp = new data_record(data->digits_used+slack);
937
+ data->references -= 1;
938
+ decrement(data,temp);
939
+ data = temp;
940
+ }
941
+ else
942
+ {
943
+ decrement(data,data);
944
+ }
945
+
946
+ return *this;
947
+ }
948
+
949
+ // ----------------------------------------------------------------------------------------
950
+
951
+ const bigint_kernel_1 bigint_kernel_1::
952
+ operator-- (
953
+ int
954
+ )
955
+ {
956
+ data_record* temp; // this is the copy of temp we will return in the end
957
+
958
+ data_record* temp2 = new data_record(data->digits_used+slack);
959
+ decrement(data,temp2);
960
+
961
+ temp = data;
962
+ data = temp2;
963
+
964
+ return bigint_kernel_1(temp,0);
965
+ }
966
+
967
+ // ----------------------------------------------------------------------------------------
968
+ // ----------------------------------------------------------------------------------------
969
+ // private member function definitions
970
+ // ----------------------------------------------------------------------------------------
971
+ // ----------------------------------------------------------------------------------------
972
+
973
+ void bigint_kernel_1::
974
+ short_add (
975
+ const data_record* data,
976
+ uint16 value,
977
+ data_record* result
978
+ ) const
979
+ {
980
+ // put value into the carry part of temp
981
+ uint32 temp = value;
982
+ temp <<= 16;
983
+
984
+
985
+ const uint16* number = data->number;
986
+ const uint16* end = number + data->digits_used; // one past the end of number
987
+ uint16* r = result->number;
988
+
989
+ while (number != end)
990
+ {
991
+ // add *number and the current carry
992
+ temp = *number + (temp>>16);
993
+ // put the low word of temp into *r
994
+ *r = static_cast<uint16>(temp & 0xFFFF);
995
+
996
+ ++number;
997
+ ++r;
998
+ }
999
+
1000
+ // if there is a final carry
1001
+ if ((temp>>16) != 0)
1002
+ {
1003
+ result->digits_used = data->digits_used + 1;
1004
+ // store the carry in the most significant digit of the result
1005
+ *r = static_cast<uint16>(temp>>16);
1006
+ }
1007
+ else
1008
+ {
1009
+ result->digits_used = data->digits_used;
1010
+ }
1011
+ }
1012
+
1013
+ // ----------------------------------------------------------------------------------------
1014
+
1015
+ void bigint_kernel_1::
1016
+ short_sub (
1017
+ const data_record* data,
1018
+ uint16 value,
1019
+ data_record* result
1020
+ ) const
1021
+ {
1022
+
1023
+
1024
+ const uint16* number = data->number;
1025
+ const uint16* end = number + data->digits_used - 1;
1026
+ uint16* r = result->number;
1027
+
1028
+ uint32 temp = *number - value;
1029
+
1030
+ // put the low word of temp into *data
1031
+ *r = static_cast<uint16>(temp & 0xFFFF);
1032
+
1033
+
1034
+ while (number != end)
1035
+ {
1036
+ ++number;
1037
+ ++r;
1038
+
1039
+ // subtract the carry from *number
1040
+ temp = *number - (temp>>31);
1041
+
1042
+ // put the low word of temp into *r
1043
+ *r = static_cast<uint16>(temp & 0xFFFF);
1044
+ }
1045
+
1046
+ // if we lost a digit in the subtraction
1047
+ if (*r == 0)
1048
+ {
1049
+ if (data->digits_used == 1)
1050
+ result->digits_used = 1;
1051
+ else
1052
+ result->digits_used = data->digits_used - 1;
1053
+ }
1054
+ else
1055
+ {
1056
+ result->digits_used = data->digits_used;
1057
+ }
1058
+
1059
+
1060
+ }
1061
+
1062
+ // ----------------------------------------------------------------------------------------
1063
+
1064
+ void bigint_kernel_1::
1065
+ short_mul (
1066
+ const data_record* data,
1067
+ uint16 value,
1068
+ data_record* result
1069
+ ) const
1070
+ {
1071
+
1072
+ uint32 temp = 0;
1073
+
1074
+
1075
+ const uint16* number = data->number;
1076
+ uint16* r = result->number;
1077
+ const uint16* end = r + data->digits_used;
1078
+
1079
+
1080
+
1081
+ while ( r != end)
1082
+ {
1083
+
1084
+ // multiply *data and value and add in the carry
1085
+ temp = *number*(uint32)value + (temp>>16);
1086
+
1087
+ // put the low word of temp into *data
1088
+ *r = static_cast<uint16>(temp & 0xFFFF);
1089
+
1090
+ ++number;
1091
+ ++r;
1092
+ }
1093
+
1094
+ // if there is a final carry
1095
+ if ((temp>>16) != 0)
1096
+ {
1097
+ result->digits_used = data->digits_used + 1;
1098
+ // put the final carry into the most significant digit of the result
1099
+ *r = static_cast<uint16>(temp>>16);
1100
+ }
1101
+ else
1102
+ {
1103
+ result->digits_used = data->digits_used;
1104
+ }
1105
+
1106
+
1107
+ }
1108
+
1109
+ // ----------------------------------------------------------------------------------------
1110
+
1111
+ void bigint_kernel_1::
1112
+ short_div (
1113
+ const data_record* data,
1114
+ uint16 value,
1115
+ data_record* result,
1116
+ uint16& rem
1117
+ ) const
1118
+ {
1119
+
1120
+ uint16 remainder = 0;
1121
+ uint32 temp;
1122
+
1123
+
1124
+
1125
+ const uint16* number = data->number + data->digits_used - 1;
1126
+ const uint16* end = number - data->digits_used;
1127
+ uint16* r = result->number + data->digits_used - 1;
1128
+
1129
+
1130
+ // if we are losing a digit in this division
1131
+ if (*number < value)
1132
+ {
1133
+ if (data->digits_used == 1)
1134
+ result->digits_used = 1;
1135
+ else
1136
+ result->digits_used = data->digits_used - 1;
1137
+ }
1138
+ else
1139
+ {
1140
+ result->digits_used = data->digits_used;
1141
+ }
1142
+
1143
+
1144
+ // perform the actual division
1145
+ while (number != end)
1146
+ {
1147
+
1148
+ temp = *number + (((uint32)remainder)<<16);
1149
+
1150
+ *r = static_cast<uint16>(temp/value);
1151
+ remainder = static_cast<uint16>(temp%value);
1152
+
1153
+ --number;
1154
+ --r;
1155
+ }
1156
+
1157
+ rem = remainder;
1158
+ }
1159
+
1160
+ // ----------------------------------------------------------------------------------------
1161
+
1162
+ void bigint_kernel_1::
1163
+ long_add (
1164
+ const data_record* lhs,
1165
+ const data_record* rhs,
1166
+ data_record* result
1167
+ ) const
1168
+ {
1169
+ // put value into the carry part of temp
1170
+ uint32 temp=0;
1171
+
1172
+ uint16* min_num; // the number with the least digits used
1173
+ uint16* max_num; // the number with the most digits used
1174
+ uint16* min_end; // one past the end of min_num
1175
+ uint16* max_end; // one past the end of max_num
1176
+ uint16* r = result->number;
1177
+
1178
+ uint32 max_digits_used;
1179
+ if (lhs->digits_used < rhs->digits_used)
1180
+ {
1181
+ max_digits_used = rhs->digits_used;
1182
+ min_num = lhs->number;
1183
+ max_num = rhs->number;
1184
+ min_end = min_num + lhs->digits_used;
1185
+ max_end = max_num + rhs->digits_used;
1186
+ }
1187
+ else
1188
+ {
1189
+ max_digits_used = lhs->digits_used;
1190
+ min_num = rhs->number;
1191
+ max_num = lhs->number;
1192
+ min_end = min_num + rhs->digits_used;
1193
+ max_end = max_num + lhs->digits_used;
1194
+ }
1195
+
1196
+
1197
+
1198
+
1199
+ while (min_num != min_end)
1200
+ {
1201
+ // add *min_num, *max_num and the current carry
1202
+ temp = *min_num + *max_num + (temp>>16);
1203
+ // put the low word of temp into *r
1204
+ *r = static_cast<uint16>(temp & 0xFFFF);
1205
+
1206
+ ++min_num;
1207
+ ++max_num;
1208
+ ++r;
1209
+ }
1210
+
1211
+
1212
+ while (max_num != max_end)
1213
+ {
1214
+ // add *max_num and the current carry
1215
+ temp = *max_num + (temp>>16);
1216
+ // put the low word of temp into *r
1217
+ *r = static_cast<uint16>(temp & 0xFFFF);
1218
+
1219
+ ++max_num;
1220
+ ++r;
1221
+ }
1222
+
1223
+ // check if there was a final carry
1224
+ if ((temp>>16) != 0)
1225
+ {
1226
+ result->digits_used = max_digits_used + 1;
1227
+ // put the carry into the most significant digit in the result
1228
+ *r = static_cast<uint16>(temp>>16);
1229
+ }
1230
+ else
1231
+ {
1232
+ result->digits_used = max_digits_used;
1233
+ }
1234
+
1235
+
1236
+ }
1237
+
1238
+ // ----------------------------------------------------------------------------------------
1239
+
1240
+ void bigint_kernel_1::
1241
+ long_sub (
1242
+ const data_record* lhs,
1243
+ const data_record* rhs,
1244
+ data_record* result
1245
+ ) const
1246
+ {
1247
+
1248
+
1249
+ const uint16* number1 = lhs->number;
1250
+ const uint16* number2 = rhs->number;
1251
+ const uint16* end = number2 + rhs->digits_used;
1252
+ uint16* r = result->number;
1253
+
1254
+
1255
+
1256
+ uint32 temp =0;
1257
+
1258
+
1259
+ while (number2 != end)
1260
+ {
1261
+
1262
+ // subtract *number2 from *number1 and then subtract any carry
1263
+ temp = *number1 - *number2 - (temp>>31);
1264
+
1265
+ // put the low word of temp into *r
1266
+ *r = static_cast<uint16>(temp & 0xFFFF);
1267
+
1268
+ ++number1;
1269
+ ++number2;
1270
+ ++r;
1271
+ }
1272
+
1273
+ end = lhs->number + lhs->digits_used;
1274
+ while (number1 != end)
1275
+ {
1276
+
1277
+ // subtract the carry from *number1
1278
+ temp = *number1 - (temp>>31);
1279
+
1280
+ // put the low word of temp into *r
1281
+ *r = static_cast<uint16>(temp & 0xFFFF);
1282
+
1283
+ ++number1;
1284
+ ++r;
1285
+ }
1286
+
1287
+ result->digits_used = lhs->digits_used;
1288
+ // adjust the number of digits used appropriately
1289
+ --r;
1290
+ while (*r == 0 && result->digits_used > 1)
1291
+ {
1292
+ --r;
1293
+ --result->digits_used;
1294
+ }
1295
+ }
1296
+
1297
+ // ----------------------------------------------------------------------------------------
1298
+
1299
+ void bigint_kernel_1::
1300
+ long_div (
1301
+ const data_record* lhs,
1302
+ const data_record* rhs,
1303
+ data_record* result,
1304
+ data_record* remainder
1305
+ ) const
1306
+ {
1307
+ // zero result
1308
+ result->digits_used = 1;
1309
+ *(result->number) = 0;
1310
+
1311
+ uint16* a;
1312
+ uint16* b;
1313
+ uint16* end;
1314
+
1315
+ // copy lhs into remainder
1316
+ remainder->digits_used = lhs->digits_used;
1317
+ a = remainder->number;
1318
+ end = a + remainder->digits_used;
1319
+ b = lhs->number;
1320
+ while (a != end)
1321
+ {
1322
+ *a = *b;
1323
+ ++a;
1324
+ ++b;
1325
+ }
1326
+
1327
+
1328
+ // if rhs is bigger than lhs then result == 0 and remainder == lhs
1329
+ // so then we can quit right now
1330
+ if (is_less_than(lhs,rhs))
1331
+ {
1332
+ return;
1333
+ }
1334
+
1335
+
1336
+ // make a temporary number
1337
+ data_record temp(lhs->digits_used + slack);
1338
+
1339
+
1340
+ // shift rhs left until it is one shift away from being larger than lhs and
1341
+ // put the number of left shifts necessary into shifts
1342
+ uint32 shifts;
1343
+ shifts = (lhs->digits_used - rhs->digits_used) * 16;
1344
+
1345
+ shift_left(rhs,&temp,shifts);
1346
+
1347
+
1348
+ // while (lhs > temp)
1349
+ while (is_less_than(&temp,lhs))
1350
+ {
1351
+ shift_left(&temp,&temp,1);
1352
+ ++shifts;
1353
+ }
1354
+ // make sure lhs isn't smaller than temp
1355
+ while (is_less_than(lhs,&temp))
1356
+ {
1357
+ shift_right(&temp,&temp);
1358
+ --shifts;
1359
+ }
1360
+
1361
+
1362
+
1363
+ // we want to execute the loop shifts +1 times
1364
+ ++shifts;
1365
+ while (shifts != 0)
1366
+ {
1367
+ shift_left(result,result,1);
1368
+ // if (temp <= remainder)
1369
+ if (!is_less_than(remainder,&temp))
1370
+ {
1371
+ long_sub(remainder,&temp,remainder);
1372
+
1373
+ // increment result
1374
+ uint16* r = result->number;
1375
+ uint16* end = r + result->digits_used;
1376
+ while (true)
1377
+ {
1378
+ ++(*r);
1379
+ // if there was no carry then we are done
1380
+ if (*r != 0)
1381
+ break;
1382
+
1383
+ ++r;
1384
+
1385
+ // if we hit the end of r and there is still a carry then
1386
+ // the next digit of r is 1 and there is one more digit used
1387
+ if (r == end)
1388
+ {
1389
+ *r = 1;
1390
+ ++(result->digits_used);
1391
+ break;
1392
+ }
1393
+ }
1394
+ }
1395
+ shift_right(&temp,&temp);
1396
+ --shifts;
1397
+ }
1398
+
1399
+
1400
+ }
1401
+
1402
+ // ----------------------------------------------------------------------------------------
1403
+
1404
+ void bigint_kernel_1::
1405
+ long_mul (
1406
+ const data_record* lhs,
1407
+ const data_record* rhs,
1408
+ data_record* result
1409
+ ) const
1410
+ {
1411
+ // make result be zero
1412
+ result->digits_used = 1;
1413
+ *(result->number) = 0;
1414
+
1415
+
1416
+ const data_record* aa;
1417
+ const data_record* bb;
1418
+
1419
+ if (lhs->digits_used < rhs->digits_used)
1420
+ {
1421
+ // make copies of lhs and rhs and give them an appropriate amount of
1422
+ // extra memory so there won't be any overflows
1423
+ aa = lhs;
1424
+ bb = rhs;
1425
+ }
1426
+ else
1427
+ {
1428
+ // make copies of lhs and rhs and give them an appropriate amount of
1429
+ // extra memory so there won't be any overflows
1430
+ aa = rhs;
1431
+ bb = lhs;
1432
+ }
1433
+ // this is where we actually copy lhs and rhs
1434
+ data_record b(*bb,aa->digits_used+slack); // the larger(approximately) of lhs and rhs
1435
+
1436
+
1437
+ uint32 shift_value = 0;
1438
+ uint16* anum = aa->number;
1439
+ uint16* end = anum + aa->digits_used;
1440
+ while (anum != end )
1441
+ {
1442
+ uint16 bit = 0x0001;
1443
+
1444
+ for (int i = 0; i < 16; ++i)
1445
+ {
1446
+ // if the specified bit of a is 1
1447
+ if ((*anum & bit) != 0)
1448
+ {
1449
+ shift_left(&b,&b,shift_value);
1450
+ shift_value = 0;
1451
+ long_add(&b,result,result);
1452
+ }
1453
+ ++shift_value;
1454
+ bit <<= 1;
1455
+ }
1456
+
1457
+ ++anum;
1458
+ }
1459
+ }
1460
+
1461
+ // ----------------------------------------------------------------------------------------
1462
+
1463
+ void bigint_kernel_1::
1464
+ shift_left (
1465
+ const data_record* data,
1466
+ data_record* result,
1467
+ uint32 shift_amount
1468
+ ) const
1469
+ {
1470
+ uint32 offset = shift_amount/16;
1471
+ shift_amount &= 0xf; // same as shift_amount %= 16;
1472
+
1473
+ uint16* r = result->number + data->digits_used + offset; // result
1474
+ uint16* end = data->number;
1475
+ uint16* s = end + data->digits_used; // source
1476
+ const uint32 temp = 16 - shift_amount;
1477
+
1478
+ *r = (*(--s) >> temp);
1479
+ // set the number of digits used in the result
1480
+ // if the upper bits from *s were zero then don't count this first word
1481
+ if (*r == 0)
1482
+ {
1483
+ result->digits_used = data->digits_used + offset;
1484
+ }
1485
+ else
1486
+ {
1487
+ result->digits_used = data->digits_used + offset + 1;
1488
+ }
1489
+ --r;
1490
+
1491
+ while (s != end)
1492
+ {
1493
+ *r = ((*s << shift_amount) | ( *(s-1) >> temp));
1494
+ --r;
1495
+ --s;
1496
+ }
1497
+ *r = *s << shift_amount;
1498
+
1499
+ // now zero the rest of the result
1500
+ end = result->number;
1501
+ while (r != end)
1502
+ *(--r) = 0;
1503
+
1504
+ }
1505
+
1506
+ // ----------------------------------------------------------------------------------------
1507
+
1508
+ void bigint_kernel_1::
1509
+ shift_right (
1510
+ const data_record* data,
1511
+ data_record* result
1512
+ ) const
1513
+ {
1514
+
1515
+ uint16* r = result->number; // result
1516
+ uint16* s = data->number; // source
1517
+ uint16* end = s + data->digits_used - 1;
1518
+
1519
+ while (s != end)
1520
+ {
1521
+ *r = (*s >> 1) | (*(s+1) << 15);
1522
+ ++r;
1523
+ ++s;
1524
+ }
1525
+ *r = *s >> 1;
1526
+
1527
+
1528
+ // calculate the new number for digits_used
1529
+ if (*r == 0)
1530
+ {
1531
+ if (data->digits_used != 1)
1532
+ result->digits_used = data->digits_used - 1;
1533
+ else
1534
+ result->digits_used = 1;
1535
+ }
1536
+ else
1537
+ {
1538
+ result->digits_used = data->digits_used;
1539
+ }
1540
+
1541
+
1542
+ }
1543
+
1544
+ // ----------------------------------------------------------------------------------------
1545
+
1546
+ bool bigint_kernel_1::
1547
+ is_less_than (
1548
+ const data_record* lhs,
1549
+ const data_record* rhs
1550
+ ) const
1551
+ {
1552
+ uint32 lhs_digits_used = lhs->digits_used;
1553
+ uint32 rhs_digits_used = rhs->digits_used;
1554
+
1555
+ // if lhs is definitely less than rhs
1556
+ if (lhs_digits_used < rhs_digits_used )
1557
+ return true;
1558
+ // if lhs is definitely greater than rhs
1559
+ else if (lhs_digits_used > rhs_digits_used)
1560
+ return false;
1561
+ else
1562
+ {
1563
+ uint16* end = lhs->number;
1564
+ uint16* l = end + lhs_digits_used;
1565
+ uint16* r = rhs->number + rhs_digits_used;
1566
+
1567
+ while (l != end)
1568
+ {
1569
+ --l;
1570
+ --r;
1571
+ if (*l < *r)
1572
+ return true;
1573
+ else if (*l > *r)
1574
+ return false;
1575
+ }
1576
+
1577
+ // at this point we know that they are equal
1578
+ return false;
1579
+ }
1580
+
1581
+ }
1582
+
1583
+ // ----------------------------------------------------------------------------------------
1584
+
1585
+ bool bigint_kernel_1::
1586
+ is_equal_to (
1587
+ const data_record* lhs,
1588
+ const data_record* rhs
1589
+ ) const
1590
+ {
1591
+ // if lhs and rhs are definitely not equal
1592
+ if (lhs->digits_used != rhs->digits_used )
1593
+ {
1594
+ return false;
1595
+ }
1596
+ else
1597
+ {
1598
+ uint16* l = lhs->number;
1599
+ uint16* r = rhs->number;
1600
+ uint16* end = l + lhs->digits_used;
1601
+
1602
+ while (l != end)
1603
+ {
1604
+ if (*l != *r)
1605
+ return false;
1606
+ ++l;
1607
+ ++r;
1608
+ }
1609
+
1610
+ // at this point we know that they are equal
1611
+ return true;
1612
+ }
1613
+
1614
+ }
1615
+
1616
+ // ----------------------------------------------------------------------------------------
1617
+
1618
+ void bigint_kernel_1::
1619
+ increment (
1620
+ const data_record* source,
1621
+ data_record* dest
1622
+ ) const
1623
+ {
1624
+ uint16* s = source->number;
1625
+ uint16* d = dest->number;
1626
+ uint16* end = s + source->digits_used;
1627
+ while (true)
1628
+ {
1629
+ *d = *s + 1;
1630
+
1631
+ // if there was no carry then break out of the loop
1632
+ if (*d != 0)
1633
+ {
1634
+ dest->digits_used = source->digits_used;
1635
+
1636
+ // copy the rest of the digits over to d
1637
+ ++d; ++s;
1638
+ while (s != end)
1639
+ {
1640
+ *d = *s;
1641
+ ++d;
1642
+ ++s;
1643
+ }
1644
+
1645
+ break;
1646
+ }
1647
+
1648
+
1649
+ ++s;
1650
+
1651
+ // if we have hit the end of s and there was a carry up to this point
1652
+ // then just make the next digit 1 and add one to the digits used
1653
+ if (s == end)
1654
+ {
1655
+ ++d;
1656
+ dest->digits_used = source->digits_used + 1;
1657
+ *d = 1;
1658
+ break;
1659
+ }
1660
+
1661
+ ++d;
1662
+ }
1663
+ }
1664
+
1665
+ // ----------------------------------------------------------------------------------------
1666
+
1667
+ void bigint_kernel_1::
1668
+ decrement (
1669
+ const data_record* source,
1670
+ data_record* dest
1671
+ ) const
1672
+ {
1673
+ uint16* s = source->number;
1674
+ uint16* d = dest->number;
1675
+ uint16* end = s + source->digits_used;
1676
+ while (true)
1677
+ {
1678
+ *d = *s - 1;
1679
+
1680
+ // if there was no carry then break out of the loop
1681
+ if (*d != 0xFFFF)
1682
+ {
1683
+ // if we lost a digit in the subtraction
1684
+ if (*d == 0 && s+1 == end)
1685
+ {
1686
+ if (source->digits_used == 1)
1687
+ dest->digits_used = 1;
1688
+ else
1689
+ dest->digits_used = source->digits_used - 1;
1690
+ }
1691
+ else
1692
+ {
1693
+ dest->digits_used = source->digits_used;
1694
+ }
1695
+ break;
1696
+ }
1697
+ else
1698
+ {
1699
+ ++d;
1700
+ ++s;
1701
+ }
1702
+
1703
+ }
1704
+
1705
+ // copy the rest of the digits over to d
1706
+ ++d;
1707
+ ++s;
1708
+ while (s != end)
1709
+ {
1710
+ *d = *s;
1711
+ ++d;
1712
+ ++s;
1713
+ }
1714
+ }
1715
+
1716
+ // ----------------------------------------------------------------------------------------
1717
+
1718
+ }
1719
+ #endif // DLIB_BIGINT_KERNEL_1_CPp_
1720
+
dlibs/dlib/bigint/bigint_kernel_1.h ADDED
@@ -0,0 +1,543 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (C) 2003 Davis E. King ([email protected])
2
+ // License: Boost Software License See LICENSE.txt for the full license.
3
+ #ifndef DLIB_BIGINT_KERNEl_1_
4
+ #define DLIB_BIGINT_KERNEl_1_
5
+
6
+ #include "bigint_kernel_abstract.h"
7
+ #include "../algs.h"
8
+ #include "../serialize.h"
9
+ #include "../uintn.h"
10
+ #include <iosfwd>
11
+
12
+ namespace dlib
13
+ {
14
+
15
+
16
+ class bigint_kernel_1
17
+ {
18
+ /*!
19
+ INITIAL VALUE
20
+ slack == 25
21
+ data->number[0] == 0
22
+ data->size == slack
23
+ data->references == 1
24
+ data->digits_used == 1
25
+
26
+
27
+ CONVENTION
28
+ slack == the number of extra digits placed into the number when it is
29
+ created. the slack value should never be less than 1
30
+
31
+ data->number == pointer to an array of data->size uint16s.
32
+ data represents a string of base 65535 numbers with data[0] being
33
+ the least significant bit and data[data->digits_used-1] being the most
34
+ significant
35
+
36
+
37
+ NOTE: In the comments I will consider a word to be a 16 bit value
38
+
39
+
40
+ data->digits_used == the number of significant digits in the number.
41
+ data->digits_used tells us the number of used elements in the
42
+ data->number array so everything beyond data->number[data->digits_used-1]
43
+ is undefined
44
+
45
+ data->references == the number of bigint_kernel_1 objects which refer
46
+ to this data_record
47
+
48
+
49
+
50
+ !*/
51
+
52
+
53
+ struct data_record
54
+ {
55
+
56
+
57
+ explicit data_record(
58
+ uint32 size_
59
+ ) :
60
+ size(size_),
61
+ number(new uint16[size_]),
62
+ references(1),
63
+ digits_used(1)
64
+ {*number = 0;}
65
+ /*!
66
+ ensures
67
+ - initializes *this to represent zero
68
+ !*/
69
+
70
+ data_record(
71
+ const data_record& item,
72
+ uint32 additional_size
73
+ ) :
74
+ size(item.digits_used + additional_size),
75
+ number(new uint16[size]),
76
+ references(1),
77
+ digits_used(item.digits_used)
78
+ {
79
+ uint16* source = item.number;
80
+ uint16* dest = number;
81
+ uint16* end = source + digits_used;
82
+ while (source != end)
83
+ {
84
+ *dest = *source;
85
+ ++dest;
86
+ ++source;
87
+ }
88
+ }
89
+ /*!
90
+ ensures
91
+ - *this is a copy of item except with
92
+ size == item.digits_used + additional_size
93
+ !*/
94
+
95
+ ~data_record(
96
+ )
97
+ {
98
+ delete [] number;
99
+ }
100
+
101
+
102
+ const uint32 size;
103
+ uint16* number;
104
+ uint32 references;
105
+ uint32 digits_used;
106
+
107
+ private:
108
+ // no copy constructor
109
+ data_record ( data_record&);
110
+ };
111
+
112
+
113
+
114
+ // note that the second parameter is just there
115
+ // to resolve the ambiguity between this constructor and
116
+ // bigint_kernel_1(uint32)
117
+ explicit bigint_kernel_1 (
118
+ data_record* data_, int
119
+ ): slack(25),data(data_) {}
120
+ /*!
121
+ ensures
122
+ - *this is initialized with data_ as its data member
123
+ !*/
124
+
125
+
126
+ public:
127
+
128
+ bigint_kernel_1 (
129
+ );
130
+
131
+ bigint_kernel_1 (
132
+ uint32 value
133
+ );
134
+
135
+ bigint_kernel_1 (
136
+ const bigint_kernel_1& item
137
+ );
138
+
139
+ virtual ~bigint_kernel_1 (
140
+ );
141
+
142
+ const bigint_kernel_1 operator+ (
143
+ const bigint_kernel_1& rhs
144
+ ) const;
145
+
146
+ bigint_kernel_1& operator+= (
147
+ const bigint_kernel_1& rhs
148
+ );
149
+
150
+ const bigint_kernel_1 operator- (
151
+ const bigint_kernel_1& rhs
152
+ ) const;
153
+
154
+ bigint_kernel_1& operator-= (
155
+ const bigint_kernel_1& rhs
156
+ );
157
+
158
+ const bigint_kernel_1 operator* (
159
+ const bigint_kernel_1& rhs
160
+ ) const;
161
+
162
+ bigint_kernel_1& operator*= (
163
+ const bigint_kernel_1& rhs
164
+ );
165
+
166
+ const bigint_kernel_1 operator/ (
167
+ const bigint_kernel_1& rhs
168
+ ) const;
169
+
170
+ bigint_kernel_1& operator/= (
171
+ const bigint_kernel_1& rhs
172
+ );
173
+
174
+ const bigint_kernel_1 operator% (
175
+ const bigint_kernel_1& rhs
176
+ ) const;
177
+
178
+ bigint_kernel_1& operator%= (
179
+ const bigint_kernel_1& rhs
180
+ );
181
+
182
+ bool operator < (
183
+ const bigint_kernel_1& rhs
184
+ ) const;
185
+
186
+ bool operator == (
187
+ const bigint_kernel_1& rhs
188
+ ) const;
189
+
190
+ bigint_kernel_1& operator= (
191
+ const bigint_kernel_1& rhs
192
+ );
193
+
194
+ friend std::ostream& operator<< (
195
+ std::ostream& out,
196
+ const bigint_kernel_1& rhs
197
+ );
198
+
199
+ friend std::istream& operator>> (
200
+ std::istream& in,
201
+ bigint_kernel_1& rhs
202
+ );
203
+
204
+ bigint_kernel_1& operator++ (
205
+ );
206
+
207
+ const bigint_kernel_1 operator++ (
208
+ int
209
+ );
210
+
211
+ bigint_kernel_1& operator-- (
212
+ );
213
+
214
+ const bigint_kernel_1 operator-- (
215
+ int
216
+ );
217
+
218
+ friend const bigint_kernel_1 operator+ (
219
+ uint16 lhs,
220
+ const bigint_kernel_1& rhs
221
+ );
222
+
223
+ friend const bigint_kernel_1 operator+ (
224
+ const bigint_kernel_1& lhs,
225
+ uint16 rhs
226
+ );
227
+
228
+ bigint_kernel_1& operator+= (
229
+ uint16 rhs
230
+ );
231
+
232
+ friend const bigint_kernel_1 operator- (
233
+ uint16 lhs,
234
+ const bigint_kernel_1& rhs
235
+ );
236
+
237
+ friend const bigint_kernel_1 operator- (
238
+ const bigint_kernel_1& lhs,
239
+ uint16 rhs
240
+ );
241
+
242
+ bigint_kernel_1& operator-= (
243
+ uint16 rhs
244
+ );
245
+
246
+ friend const bigint_kernel_1 operator* (
247
+ uint16 lhs,
248
+ const bigint_kernel_1& rhs
249
+ );
250
+
251
+ friend const bigint_kernel_1 operator* (
252
+ const bigint_kernel_1& lhs,
253
+ uint16 rhs
254
+ );
255
+
256
+ bigint_kernel_1& operator*= (
257
+ uint16 rhs
258
+ );
259
+
260
+ friend const bigint_kernel_1 operator/ (
261
+ uint16 lhs,
262
+ const bigint_kernel_1& rhs
263
+ );
264
+
265
+ friend const bigint_kernel_1 operator/ (
266
+ const bigint_kernel_1& lhs,
267
+ uint16 rhs
268
+ );
269
+
270
+ bigint_kernel_1& operator/= (
271
+ uint16 rhs
272
+ );
273
+
274
+ friend const bigint_kernel_1 operator% (
275
+ uint16 lhs,
276
+ const bigint_kernel_1& rhs
277
+ );
278
+
279
+ friend const bigint_kernel_1 operator% (
280
+ const bigint_kernel_1& lhs,
281
+ uint16 rhs
282
+ );
283
+
284
+ bigint_kernel_1& operator%= (
285
+ uint16 rhs
286
+ );
287
+
288
+ friend bool operator < (
289
+ uint16 lhs,
290
+ const bigint_kernel_1& rhs
291
+ );
292
+
293
+ friend bool operator < (
294
+ const bigint_kernel_1& lhs,
295
+ uint16 rhs
296
+ );
297
+
298
+ friend bool operator == (
299
+ const bigint_kernel_1& lhs,
300
+ uint16 rhs
301
+ );
302
+
303
+ friend bool operator == (
304
+ uint16 lhs,
305
+ const bigint_kernel_1& rhs
306
+ );
307
+
308
+ bigint_kernel_1& operator= (
309
+ uint16 rhs
310
+ );
311
+
312
+
313
+ void swap (
314
+ bigint_kernel_1& item
315
+ ) { data_record* temp = data; data = item.data; item.data = temp; }
316
+
317
+
318
+ private:
319
+
320
+ void long_add (
321
+ const data_record* lhs,
322
+ const data_record* rhs,
323
+ data_record* result
324
+ ) const;
325
+ /*!
326
+ requires
327
+ - result->size >= max(lhs->digits_used,rhs->digits_used) + 1
328
+ ensures
329
+ - result == lhs + rhs
330
+ !*/
331
+
332
+ void long_sub (
333
+ const data_record* lhs,
334
+ const data_record* rhs,
335
+ data_record* result
336
+ ) const;
337
+ /*!
338
+ requires
339
+ - lhs >= rhs
340
+ - result->size >= lhs->digits_used
341
+ ensures
342
+ - result == lhs - rhs
343
+ !*/
344
+
345
+ void long_div (
346
+ const data_record* lhs,
347
+ const data_record* rhs,
348
+ data_record* result,
349
+ data_record* remainder
350
+ ) const;
351
+ /*!
352
+ requires
353
+ - rhs != 0
354
+ - result->size >= lhs->digits_used
355
+ - remainder->size >= lhs->digits_used
356
+ - each parameter is unique (i.e. lhs != result, lhs != remainder, etc.)
357
+ ensures
358
+ - result == lhs / rhs
359
+ - remainder == lhs % rhs
360
+ !*/
361
+
362
+ void long_mul (
363
+ const data_record* lhs,
364
+ const data_record* rhs,
365
+ data_record* result
366
+ ) const;
367
+ /*!
368
+ requires
369
+ - result->size >= lhs->digits_used + rhs->digits_used
370
+ - result != lhs
371
+ - result != rhs
372
+ ensures
373
+ - result == lhs * rhs
374
+ !*/
375
+
376
+ void short_add (
377
+ const data_record* data,
378
+ uint16 value,
379
+ data_record* result
380
+ ) const;
381
+ /*!
382
+ requires
383
+ - result->size >= data->size + 1
384
+ ensures
385
+ - result == data + value
386
+ !*/
387
+
388
+ void short_sub (
389
+ const data_record* data,
390
+ uint16 value,
391
+ data_record* result
392
+ ) const;
393
+ /*!
394
+ requires
395
+ - data >= value
396
+ - result->size >= data->digits_used
397
+ ensures
398
+ - result == data - value
399
+ !*/
400
+
401
+ void short_mul (
402
+ const data_record* data,
403
+ uint16 value,
404
+ data_record* result
405
+ ) const;
406
+ /*!
407
+ requires
408
+ - result->size >= data->digits_used + 1
409
+ ensures
410
+ - result == data * value
411
+ !*/
412
+
413
+ void short_div (
414
+ const data_record* data,
415
+ uint16 value,
416
+ data_record* result,
417
+ uint16& remainder
418
+ ) const;
419
+ /*!
420
+ requires
421
+ - value != 0
422
+ - result->size >= data->digits_used
423
+ ensures
424
+ - result = data*value
425
+ - remainder = data%value
426
+ !*/
427
+
428
+ void shift_left (
429
+ const data_record* data,
430
+ data_record* result,
431
+ uint32 shift_amount
432
+ ) const;
433
+ /*!
434
+ requires
435
+ - result->size >= data->digits_used + shift_amount/8 + 1
436
+ ensures
437
+ - result == data << shift_amount
438
+ !*/
439
+
440
+ void shift_right (
441
+ const data_record* data,
442
+ data_record* result
443
+ ) const;
444
+ /*!
445
+ requires
446
+ - result->size >= data->digits_used
447
+ ensures
448
+ - result == data >> 1
449
+ !*/
450
+
451
+ bool is_less_than (
452
+ const data_record* lhs,
453
+ const data_record* rhs
454
+ ) const;
455
+ /*!
456
+ ensures
457
+ - returns true if lhs < rhs
458
+ - returns false otherwise
459
+ !*/
460
+
461
+ bool is_equal_to (
462
+ const data_record* lhs,
463
+ const data_record* rhs
464
+ ) const;
465
+ /*!
466
+ ensures
467
+ - returns true if lhs == rhs
468
+ - returns false otherwise
469
+ !*/
470
+
471
+ void increment (
472
+ const data_record* source,
473
+ data_record* dest
474
+ ) const;
475
+ /*!
476
+ requires
477
+ - dest->size >= source->digits_used + 1
478
+ ensures
479
+ - dest = source + 1
480
+ !*/
481
+
482
+ void decrement (
483
+ const data_record* source,
484
+ data_record* dest
485
+ ) const;
486
+ /*!
487
+ requires
488
+ source != 0
489
+ ensuers
490
+ dest = source - 1
491
+ !*/
492
+
493
+ // member data
494
+ const uint32 slack;
495
+ data_record* data;
496
+
497
+
498
+
499
+ };
500
+
501
+ inline void swap (
502
+ bigint_kernel_1& a,
503
+ bigint_kernel_1& b
504
+ ) { a.swap(b); }
505
+
506
+ inline void serialize (
507
+ const bigint_kernel_1& item,
508
+ std::ostream& out
509
+ )
510
+ {
511
+ std::ios::fmtflags oldflags = out.flags();
512
+ out << item << ' ';
513
+ out.flags(oldflags);
514
+ if (!out) throw serialization_error("Error serializing object of type bigint_kernel_c");
515
+ }
516
+
517
+ inline void deserialize (
518
+ bigint_kernel_1& item,
519
+ std::istream& in
520
+ )
521
+ {
522
+ std::ios::fmtflags oldflags = in.flags();
523
+ in >> item;
524
+ in.flags(oldflags);
525
+ if (in.get() != ' ')
526
+ {
527
+ item = 0;
528
+ throw serialization_error("Error deserializing object of type bigint_kernel_c");
529
+ }
530
+ }
531
+
532
+ inline bool operator> (const bigint_kernel_1& a, const bigint_kernel_1& b) { return b < a; }
533
+ inline bool operator!= (const bigint_kernel_1& a, const bigint_kernel_1& b) { return !(a == b); }
534
+ inline bool operator<= (const bigint_kernel_1& a, const bigint_kernel_1& b) { return !(b < a); }
535
+ inline bool operator>= (const bigint_kernel_1& a, const bigint_kernel_1& b) { return !(a < b); }
536
+ }
537
+
538
+ #ifdef NO_MAKEFILE
539
+ #include "bigint_kernel_1.cpp"
540
+ #endif
541
+
542
+ #endif // DLIB_BIGINT_KERNEl_1_
543
+
dlibs/dlib/bigint/bigint_kernel_2.cpp ADDED
@@ -0,0 +1,1945 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (C) 2003 Davis E. King ([email protected])
2
+ // License: Boost Software License See LICENSE.txt for the full license.
3
+ #ifndef DLIB_BIGINT_KERNEL_2_CPp_
4
+ #define DLIB_BIGINT_KERNEL_2_CPp_
5
+ #include "bigint_kernel_2.h"
6
+
7
+ #include <iostream>
8
+ #include <cmath>
9
+
10
+ namespace dlib
11
+ {
12
+
13
+ // ----------------------------------------------------------------------------------------
14
+ // ----------------------------------------------------------------------------------------
15
+ // member/friend function definitions
16
+ // ----------------------------------------------------------------------------------------
17
+ // ----------------------------------------------------------------------------------------
18
+
19
+ bigint_kernel_2::
20
+ bigint_kernel_2 (
21
+ ) :
22
+ slack(25),
23
+ data(new data_record(slack))
24
+ {}
25
+
26
+ // ----------------------------------------------------------------------------------------
27
+
28
+ bigint_kernel_2::
29
+ bigint_kernel_2 (
30
+ uint32 value
31
+ ) :
32
+ slack(25),
33
+ data(new data_record(slack))
34
+ {
35
+ *(data->number) = static_cast<uint16>(value&0xFFFF);
36
+ *(data->number+1) = static_cast<uint16>((value>>16)&0xFFFF);
37
+ if (*(data->number+1) != 0)
38
+ data->digits_used = 2;
39
+ }
40
+
41
+ // ----------------------------------------------------------------------------------------
42
+
43
+ bigint_kernel_2::
44
+ bigint_kernel_2 (
45
+ const bigint_kernel_2& item
46
+ ) :
47
+ slack(25),
48
+ data(item.data)
49
+ {
50
+ data->references += 1;
51
+ }
52
+
53
+ // ----------------------------------------------------------------------------------------
54
+
55
+ bigint_kernel_2::
56
+ ~bigint_kernel_2 (
57
+ )
58
+ {
59
+ if (data->references == 1)
60
+ {
61
+ delete data;
62
+ }
63
+ else
64
+ {
65
+ data->references -= 1;
66
+ }
67
+ }
68
+
69
+ // ----------------------------------------------------------------------------------------
70
+
71
+ const bigint_kernel_2 bigint_kernel_2::
72
+ operator+ (
73
+ const bigint_kernel_2& rhs
74
+ ) const
75
+ {
76
+ data_record* temp = new data_record (
77
+ std::max(rhs.data->digits_used,data->digits_used) + slack
78
+ );
79
+ long_add(data,rhs.data,temp);
80
+ return bigint_kernel_2(temp,0);
81
+ }
82
+
83
+ // ----------------------------------------------------------------------------------------
84
+
85
+ bigint_kernel_2& bigint_kernel_2::
86
+ operator+= (
87
+ const bigint_kernel_2& rhs
88
+ )
89
+ {
90
+ // if there are other references to our data
91
+ if (data->references != 1)
92
+ {
93
+ data_record* temp = new data_record(std::max(data->digits_used,rhs.data->digits_used)+slack);
94
+ data->references -= 1;
95
+ long_add(data,rhs.data,temp);
96
+ data = temp;
97
+ }
98
+ // if data is not big enough for the result
99
+ else if (data->size <= std::max(data->digits_used,rhs.data->digits_used))
100
+ {
101
+ data_record* temp = new data_record(std::max(data->digits_used,rhs.data->digits_used)+slack);
102
+ long_add(data,rhs.data,temp);
103
+ delete data;
104
+ data = temp;
105
+ }
106
+ // there is enough size and no references
107
+ else
108
+ {
109
+ long_add(data,rhs.data,data);
110
+ }
111
+ return *this;
112
+ }
113
+
114
+ // ----------------------------------------------------------------------------------------
115
+
116
+ const bigint_kernel_2 bigint_kernel_2::
117
+ operator- (
118
+ const bigint_kernel_2& rhs
119
+ ) const
120
+ {
121
+ data_record* temp = new data_record (
122
+ data->digits_used + slack
123
+ );
124
+ long_sub(data,rhs.data,temp);
125
+ return bigint_kernel_2(temp,0);
126
+ }
127
+
128
+ // ----------------------------------------------------------------------------------------
129
+
130
+ bigint_kernel_2& bigint_kernel_2::
131
+ operator-= (
132
+ const bigint_kernel_2& rhs
133
+ )
134
+ {
135
+ // if there are other references to this data
136
+ if (data->references != 1)
137
+ {
138
+ data_record* temp = new data_record(data->digits_used+slack);
139
+ data->references -= 1;
140
+ long_sub(data,rhs.data,temp);
141
+ data = temp;
142
+ }
143
+ else
144
+ {
145
+ long_sub(data,rhs.data,data);
146
+ }
147
+ return *this;
148
+ }
149
+
150
+ // ----------------------------------------------------------------------------------------
151
+
152
+ const bigint_kernel_2 bigint_kernel_2::
153
+ operator* (
154
+ const bigint_kernel_2& rhs
155
+ ) const
156
+ {
157
+ data_record* temp = new data_record (
158
+ data->digits_used + rhs.data->digits_used + slack
159
+ );
160
+ long_mul(data,rhs.data,temp);
161
+ return bigint_kernel_2(temp,0);
162
+ }
163
+
164
+ // ----------------------------------------------------------------------------------------
165
+
166
+ bigint_kernel_2& bigint_kernel_2::
167
+ operator*= (
168
+ const bigint_kernel_2& rhs
169
+ )
170
+ {
171
+ // create a data_record to store the result of the multiplication in
172
+ data_record* temp = new data_record(rhs.data->digits_used+data->digits_used+slack);
173
+ long_mul(data,rhs.data,temp);
174
+
175
+ // if there are other references to data
176
+ if (data->references != 1)
177
+ {
178
+ data->references -= 1;
179
+ }
180
+ else
181
+ {
182
+ delete data;
183
+ }
184
+ data = temp;
185
+ return *this;
186
+ }
187
+
188
+ // ----------------------------------------------------------------------------------------
189
+
190
+ const bigint_kernel_2 bigint_kernel_2::
191
+ operator/ (
192
+ const bigint_kernel_2& rhs
193
+ ) const
194
+ {
195
+ data_record* temp = new data_record(data->digits_used+slack);
196
+ data_record* remainder;
197
+ try {
198
+ remainder = new data_record(data->digits_used+slack);
199
+ } catch (...) { delete temp; throw; }
200
+
201
+ long_div(data,rhs.data,temp,remainder);
202
+ delete remainder;
203
+
204
+
205
+ return bigint_kernel_2(temp,0);
206
+ }
207
+
208
+ // ----------------------------------------------------------------------------------------
209
+
210
+ bigint_kernel_2& bigint_kernel_2::
211
+ operator/= (
212
+ const bigint_kernel_2& rhs
213
+ )
214
+ {
215
+
216
+ data_record* temp = new data_record(data->digits_used+slack);
217
+ data_record* remainder;
218
+ try {
219
+ remainder = new data_record(data->digits_used+slack);
220
+ } catch (...) { delete temp; throw; }
221
+
222
+ long_div(data,rhs.data,temp,remainder);
223
+
224
+ // check if there are other references to data
225
+ if (data->references != 1)
226
+ {
227
+ data->references -= 1;
228
+ }
229
+ // if there are no references to data then it must be deleted
230
+ else
231
+ {
232
+ delete data;
233
+ }
234
+ data = temp;
235
+ delete remainder;
236
+
237
+
238
+ return *this;
239
+ }
240
+
241
+ // ----------------------------------------------------------------------------------------
242
+
243
+ const bigint_kernel_2 bigint_kernel_2::
244
+ operator% (
245
+ const bigint_kernel_2& rhs
246
+ ) const
247
+ {
248
+ data_record* temp = new data_record(data->digits_used+slack);
249
+ data_record* remainder;
250
+ try {
251
+ remainder = new data_record(data->digits_used+slack);
252
+ } catch (...) { delete temp; throw; }
253
+
254
+ long_div(data,rhs.data,temp,remainder);
255
+ delete temp;
256
+ return bigint_kernel_2(remainder,0);
257
+ }
258
+
259
+ // ----------------------------------------------------------------------------------------
260
+
261
+ bigint_kernel_2& bigint_kernel_2::
262
+ operator%= (
263
+ const bigint_kernel_2& rhs
264
+ )
265
+ {
266
+ data_record* temp = new data_record(data->digits_used+slack);
267
+ data_record* remainder;
268
+ try {
269
+ remainder = new data_record(data->digits_used+slack);
270
+ } catch (...) { delete temp; throw; }
271
+
272
+ long_div(data,rhs.data,temp,remainder);
273
+
274
+ // check if there are other references to data
275
+ if (data->references != 1)
276
+ {
277
+ data->references -= 1;
278
+ }
279
+ // if there are no references to data then it must be deleted
280
+ else
281
+ {
282
+ delete data;
283
+ }
284
+ data = remainder;
285
+ delete temp;
286
+ return *this;
287
+ }
288
+
289
+ // ----------------------------------------------------------------------------------------
290
+
291
+ bool bigint_kernel_2::
292
+ operator < (
293
+ const bigint_kernel_2& rhs
294
+ ) const
295
+ {
296
+ return is_less_than(data,rhs.data);
297
+ }
298
+
299
+ // ----------------------------------------------------------------------------------------
300
+
301
+ bool bigint_kernel_2::
302
+ operator == (
303
+ const bigint_kernel_2& rhs
304
+ ) const
305
+ {
306
+ return is_equal_to(data,rhs.data);
307
+ }
308
+
309
+ // ----------------------------------------------------------------------------------------
310
+
311
+ bigint_kernel_2& bigint_kernel_2::
312
+ operator= (
313
+ const bigint_kernel_2& rhs
314
+ )
315
+ {
316
+ if (this == &rhs)
317
+ return *this;
318
+
319
+ // if we have the only reference to our data then delete it
320
+ if (data->references == 1)
321
+ {
322
+ delete data;
323
+ data = rhs.data;
324
+ data->references += 1;
325
+ }
326
+ else
327
+ {
328
+ data->references -= 1;
329
+ data = rhs.data;
330
+ data->references += 1;
331
+ }
332
+
333
+ return *this;
334
+ }
335
+
336
+ // ----------------------------------------------------------------------------------------
337
+
338
+ std::ostream& operator<< (
339
+ std::ostream& out_,
340
+ const bigint_kernel_2& rhs
341
+ )
342
+ {
343
+ std::ostream out(out_.rdbuf());
344
+
345
+ typedef bigint_kernel_2 bigint;
346
+
347
+ bigint::data_record* temp = new bigint::data_record(*rhs.data,0);
348
+
349
+
350
+
351
+ // get a char array big enough to hold the number in ascii format
352
+ char* str;
353
+ try {
354
+ str = new char[(rhs.data->digits_used)*5+10];
355
+ } catch (...) { delete temp; throw; }
356
+
357
+ char* str_start = str;
358
+ str += (rhs.data->digits_used)*5+9;
359
+ *str = 0; --str;
360
+
361
+
362
+ uint16 remainder;
363
+ rhs.short_div(temp,10000,temp,remainder);
364
+
365
+ // pull the digits out of remainder
366
+ char a = remainder % 10 + '0';
367
+ remainder /= 10;
368
+ char b = remainder % 10 + '0';
369
+ remainder /= 10;
370
+ char c = remainder % 10 + '0';
371
+ remainder /= 10;
372
+ char d = remainder % 10 + '0';
373
+ remainder /= 10;
374
+
375
+
376
+ *str = a; --str;
377
+ *str = b; --str;
378
+ *str = c; --str;
379
+ *str = d; --str;
380
+
381
+
382
+ // keep looping until temp represents zero
383
+ while (temp->digits_used != 1 || *(temp->number) != 0)
384
+ {
385
+ rhs.short_div(temp,10000,temp,remainder);
386
+
387
+ // pull the digits out of remainder
388
+ char a = remainder % 10 + '0';
389
+ remainder /= 10;
390
+ char b = remainder % 10 + '0';
391
+ remainder /= 10;
392
+ char c = remainder % 10 + '0';
393
+ remainder /= 10;
394
+ char d = remainder % 10 + '0';
395
+ remainder /= 10;
396
+
397
+ *str = a; --str;
398
+ *str = b; --str;
399
+ *str = c; --str;
400
+ *str = d; --str;
401
+ }
402
+
403
+ // throw away and extra leading zeros
404
+ ++str;
405
+ if (*str == '0')
406
+ ++str;
407
+ if (*str == '0')
408
+ ++str;
409
+ if (*str == '0')
410
+ ++str;
411
+
412
+
413
+
414
+
415
+ out << str;
416
+ delete [] str_start;
417
+ delete temp;
418
+ return out_;
419
+
420
+ }
421
+
422
+ // ----------------------------------------------------------------------------------------
423
+
424
+ std::istream& operator>> (
425
+ std::istream& in_,
426
+ bigint_kernel_2& rhs
427
+ )
428
+ {
429
+ std::istream in(in_.rdbuf());
430
+
431
+ // ignore any leading whitespaces
432
+ while (in.peek() == ' ' || in.peek() == '\t' || in.peek() == '\n')
433
+ {
434
+ in.get();
435
+ }
436
+
437
+ // if the first digit is not an integer then this is an error
438
+ if ( !(in.peek() >= '0' && in.peek() <= '9'))
439
+ {
440
+ in_.clear(std::ios::failbit);
441
+ return in_;
442
+ }
443
+
444
+ int num_read;
445
+ bigint_kernel_2 temp;
446
+ do
447
+ {
448
+
449
+ // try to get 4 chars from in
450
+ num_read = 1;
451
+ char a = 0;
452
+ char b = 0;
453
+ char c = 0;
454
+ char d = 0;
455
+
456
+ if (in.peek() >= '0' && in.peek() <= '9')
457
+ {
458
+ num_read *= 10;
459
+ a = in.get();
460
+ }
461
+ if (in.peek() >= '0' && in.peek() <= '9')
462
+ {
463
+ num_read *= 10;
464
+ b = in.get();
465
+ }
466
+ if (in.peek() >= '0' && in.peek() <= '9')
467
+ {
468
+ num_read *= 10;
469
+ c = in.get();
470
+ }
471
+ if (in.peek() >= '0' && in.peek() <= '9')
472
+ {
473
+ num_read *= 10;
474
+ d = in.get();
475
+ }
476
+
477
+ // merge the for digits into an uint16
478
+ uint16 num = 0;
479
+ if (a != 0)
480
+ {
481
+ num = a - '0';
482
+ }
483
+ if (b != 0)
484
+ {
485
+ num *= 10;
486
+ num += b - '0';
487
+ }
488
+ if (c != 0)
489
+ {
490
+ num *= 10;
491
+ num += c - '0';
492
+ }
493
+ if (d != 0)
494
+ {
495
+ num *= 10;
496
+ num += d - '0';
497
+ }
498
+
499
+
500
+ if (num_read != 1)
501
+ {
502
+ // shift the digits in temp left by the number of new digits we just read
503
+ temp *= num_read;
504
+ // add in new digits
505
+ temp += num;
506
+ }
507
+
508
+ } while (num_read == 10000);
509
+
510
+
511
+ rhs = temp;
512
+ return in_;
513
+ }
514
+
515
+ // ----------------------------------------------------------------------------------------
516
+
517
+ const bigint_kernel_2 operator+ (
518
+ uint16 lhs,
519
+ const bigint_kernel_2& rhs
520
+ )
521
+ {
522
+ typedef bigint_kernel_2 bigint;
523
+ bigint::data_record* temp = new bigint::data_record
524
+ (rhs.data->digits_used+rhs.slack);
525
+
526
+ rhs.short_add(rhs.data,lhs,temp);
527
+ return bigint_kernel_2(temp,0);
528
+ }
529
+
530
+ // ----------------------------------------------------------------------------------------
531
+
532
+ const bigint_kernel_2 operator+ (
533
+ const bigint_kernel_2& lhs,
534
+ uint16 rhs
535
+ )
536
+ {
537
+ typedef bigint_kernel_2 bigint;
538
+ bigint::data_record* temp = new bigint::data_record
539
+ (lhs.data->digits_used+lhs.slack);
540
+
541
+ lhs.short_add(lhs.data,rhs,temp);
542
+ return bigint_kernel_2(temp,0);
543
+ }
544
+
545
+ // ----------------------------------------------------------------------------------------
546
+
547
+ bigint_kernel_2& bigint_kernel_2::
548
+ operator+= (
549
+ uint16 rhs
550
+ )
551
+ {
552
+ // if there are other references to this data
553
+ if (data->references != 1)
554
+ {
555
+ data_record* temp = new data_record(data->digits_used+slack);
556
+ data->references -= 1;
557
+ short_add(data,rhs,temp);
558
+ data = temp;
559
+ }
560
+ // or if we need to enlarge data then do so
561
+ else if (data->digits_used == data->size)
562
+ {
563
+ data_record* temp = new data_record(data->digits_used+slack);
564
+ short_add(data,rhs,temp);
565
+ delete data;
566
+ data = temp;
567
+ }
568
+ // or if there is plenty of space and no references
569
+ else
570
+ {
571
+ short_add(data,rhs,data);
572
+ }
573
+ return *this;
574
+ }
575
+
576
+ // ----------------------------------------------------------------------------------------
577
+
578
+ const bigint_kernel_2 operator- (
579
+ uint16 lhs,
580
+ const bigint_kernel_2& rhs
581
+ )
582
+ {
583
+ typedef bigint_kernel_2 bigint;
584
+ bigint::data_record* temp = new bigint::data_record(rhs.slack);
585
+
586
+ *(temp->number) = lhs - *(rhs.data->number);
587
+
588
+ return bigint_kernel_2(temp,0);
589
+ }
590
+
591
+ // ----------------------------------------------------------------------------------------
592
+
593
+ const bigint_kernel_2 operator- (
594
+ const bigint_kernel_2& lhs,
595
+ uint16 rhs
596
+ )
597
+ {
598
+ typedef bigint_kernel_2 bigint;
599
+ bigint::data_record* temp = new bigint::data_record
600
+ (lhs.data->digits_used+lhs.slack);
601
+
602
+ lhs.short_sub(lhs.data,rhs,temp);
603
+ return bigint_kernel_2(temp,0);
604
+ }
605
+
606
+ // ----------------------------------------------------------------------------------------
607
+
608
+ bigint_kernel_2& bigint_kernel_2::
609
+ operator-= (
610
+ uint16 rhs
611
+ )
612
+ {
613
+ // if there are other references to this data
614
+ if (data->references != 1)
615
+ {
616
+ data_record* temp = new data_record(data->digits_used+slack);
617
+ data->references -= 1;
618
+ short_sub(data,rhs,temp);
619
+ data = temp;
620
+ }
621
+ else
622
+ {
623
+ short_sub(data,rhs,data);
624
+ }
625
+ return *this;
626
+ }
627
+
628
+ // ----------------------------------------------------------------------------------------
629
+
630
+ const bigint_kernel_2 operator* (
631
+ uint16 lhs,
632
+ const bigint_kernel_2& rhs
633
+ )
634
+ {
635
+ typedef bigint_kernel_2 bigint;
636
+ bigint::data_record* temp = new bigint::data_record
637
+ (rhs.data->digits_used+rhs.slack);
638
+
639
+ rhs.short_mul(rhs.data,lhs,temp);
640
+ return bigint_kernel_2(temp,0);
641
+ }
642
+
643
+ // ----------------------------------------------------------------------------------------
644
+
645
+ const bigint_kernel_2 operator* (
646
+ const bigint_kernel_2& lhs,
647
+ uint16 rhs
648
+ )
649
+ {
650
+ typedef bigint_kernel_2 bigint;
651
+ bigint::data_record* temp = new bigint::data_record
652
+ (lhs.data->digits_used+lhs.slack);
653
+
654
+ lhs.short_mul(lhs.data,rhs,temp);
655
+ return bigint_kernel_2(temp,0);
656
+ }
657
+
658
+ // ----------------------------------------------------------------------------------------
659
+
660
+ bigint_kernel_2& bigint_kernel_2::
661
+ operator*= (
662
+ uint16 rhs
663
+ )
664
+ {
665
+ // if there are other references to this data
666
+ if (data->references != 1)
667
+ {
668
+ data_record* temp = new data_record(data->digits_used+slack);
669
+ data->references -= 1;
670
+ short_mul(data,rhs,temp);
671
+ data = temp;
672
+ }
673
+ // or if we need to enlarge data
674
+ else if (data->digits_used == data->size)
675
+ {
676
+ data_record* temp = new data_record(data->digits_used+slack);
677
+ short_mul(data,rhs,temp);
678
+ delete data;
679
+ data = temp;
680
+ }
681
+ else
682
+ {
683
+ short_mul(data,rhs,data);
684
+ }
685
+ return *this;
686
+ }
687
+
688
+ // ----------------------------------------------------------------------------------------
689
+
690
+ const bigint_kernel_2 operator/ (
691
+ uint16 lhs,
692
+ const bigint_kernel_2& rhs
693
+ )
694
+ {
695
+ typedef bigint_kernel_2 bigint;
696
+ bigint::data_record* temp = new bigint::data_record(rhs.slack);
697
+
698
+ // if rhs might not be bigger than lhs
699
+ if (rhs.data->digits_used == 1)
700
+ {
701
+ *(temp->number) = lhs/ *(rhs.data->number);
702
+ }
703
+
704
+ return bigint_kernel_2(temp,0);
705
+ }
706
+
707
+ // ----------------------------------------------------------------------------------------
708
+
709
+ const bigint_kernel_2 operator/ (
710
+ const bigint_kernel_2& lhs,
711
+ uint16 rhs
712
+ )
713
+ {
714
+ typedef bigint_kernel_2 bigint;
715
+ bigint::data_record* temp = new bigint::data_record
716
+ (lhs.data->digits_used+lhs.slack);
717
+
718
+ uint16 remainder;
719
+ lhs.short_div(lhs.data,rhs,temp,remainder);
720
+ return bigint_kernel_2(temp,0);
721
+ }
722
+
723
+ // ----------------------------------------------------------------------------------------
724
+
725
+ bigint_kernel_2& bigint_kernel_2::
726
+ operator/= (
727
+ uint16 rhs
728
+ )
729
+ {
730
+ uint16 remainder;
731
+ // if there are other references to this data
732
+ if (data->references != 1)
733
+ {
734
+ data_record* temp = new data_record(data->digits_used+slack);
735
+ data->references -= 1;
736
+ short_div(data,rhs,temp,remainder);
737
+ data = temp;
738
+ }
739
+ else
740
+ {
741
+ short_div(data,rhs,data,remainder);
742
+ }
743
+ return *this;
744
+ }
745
+
746
+ // ----------------------------------------------------------------------------------------
747
+
748
+ const bigint_kernel_2 operator% (
749
+ uint16 lhs,
750
+ const bigint_kernel_2& rhs
751
+ )
752
+ {
753
+ typedef bigint_kernel_2 bigint;
754
+ // temp is zero by default
755
+ bigint::data_record* temp = new bigint::data_record(rhs.slack);
756
+
757
+ if (rhs.data->digits_used == 1)
758
+ {
759
+ // if rhs is just an uint16 inside then perform the modulus
760
+ *(temp->number) = lhs % *(rhs.data->number);
761
+ }
762
+ else
763
+ {
764
+ // if rhs is bigger than lhs then the answer is lhs
765
+ *(temp->number) = lhs;
766
+ }
767
+
768
+ return bigint_kernel_2(temp,0);
769
+ }
770
+
771
+ // ----------------------------------------------------------------------------------------
772
+
773
+ const bigint_kernel_2 operator% (
774
+ const bigint_kernel_2& lhs,
775
+ uint16 rhs
776
+ )
777
+ {
778
+ typedef bigint_kernel_2 bigint;
779
+ bigint::data_record* temp = new bigint::data_record(lhs.data->digits_used+lhs.slack);
780
+
781
+ uint16 remainder;
782
+
783
+ lhs.short_div(lhs.data,rhs,temp,remainder);
784
+ temp->digits_used = 1;
785
+ *(temp->number) = remainder;
786
+ return bigint_kernel_2(temp,0);
787
+ }
788
+
789
+ // ----------------------------------------------------------------------------------------
790
+
791
+ bigint_kernel_2& bigint_kernel_2::
792
+ operator%= (
793
+ uint16 rhs
794
+ )
795
+ {
796
+ uint16 remainder;
797
+ // if there are other references to this data
798
+ if (data->references != 1)
799
+ {
800
+ data_record* temp = new data_record(data->digits_used+slack);
801
+ data->references -= 1;
802
+ short_div(data,rhs,temp,remainder);
803
+ data = temp;
804
+ }
805
+ else
806
+ {
807
+ short_div(data,rhs,data,remainder);
808
+ }
809
+
810
+ data->digits_used = 1;
811
+ *(data->number) = remainder;
812
+ return *this;
813
+ }
814
+
815
+ // ----------------------------------------------------------------------------------------
816
+
817
+ bool operator < (
818
+ uint16 lhs,
819
+ const bigint_kernel_2& rhs
820
+ )
821
+ {
822
+ return (rhs.data->digits_used > 1 || lhs < *(rhs.data->number) );
823
+ }
824
+
825
+ // ----------------------------------------------------------------------------------------
826
+
827
+ bool operator < (
828
+ const bigint_kernel_2& lhs,
829
+ uint16 rhs
830
+ )
831
+ {
832
+ return (lhs.data->digits_used == 1 && *(lhs.data->number) < rhs);
833
+ }
834
+
835
+ // ----------------------------------------------------------------------------------------
836
+
837
+ bool operator == (
838
+ const bigint_kernel_2& lhs,
839
+ uint16 rhs
840
+ )
841
+ {
842
+ return (lhs.data->digits_used == 1 && *(lhs.data->number) == rhs);
843
+ }
844
+
845
+ // ----------------------------------------------------------------------------------------
846
+
847
+ bool operator == (
848
+ uint16 lhs,
849
+ const bigint_kernel_2& rhs
850
+ )
851
+ {
852
+ return (rhs.data->digits_used == 1 && *(rhs.data->number) == lhs);
853
+ }
854
+
855
+ // ----------------------------------------------------------------------------------------
856
+
857
+ bigint_kernel_2& bigint_kernel_2::
858
+ operator= (
859
+ uint16 rhs
860
+ )
861
+ {
862
+ // check if there are other references to our data
863
+ if (data->references != 1)
864
+ {
865
+ data->references -= 1;
866
+ try {
867
+ data = new data_record(slack);
868
+ } catch (...) { data->references += 1; throw; }
869
+ }
870
+ else
871
+ {
872
+ data->digits_used = 1;
873
+ }
874
+
875
+ *(data->number) = rhs;
876
+
877
+ return *this;
878
+ }
879
+
880
+ // ----------------------------------------------------------------------------------------
881
+
882
+ bigint_kernel_2& bigint_kernel_2::
883
+ operator++ (
884
+ )
885
+ {
886
+ // if there are other references to this data then make a copy of it
887
+ if (data->references != 1)
888
+ {
889
+ data_record* temp = new data_record(data->digits_used+slack);
890
+ data->references -= 1;
891
+ increment(data,temp);
892
+ data = temp;
893
+ }
894
+ // or if we need to enlarge data then do so
895
+ else if (data->digits_used == data->size)
896
+ {
897
+ data_record* temp = new data_record(data->digits_used+slack);
898
+ increment(data,temp);
899
+ delete data;
900
+ data = temp;
901
+ }
902
+ else
903
+ {
904
+ increment(data,data);
905
+ }
906
+
907
+ return *this;
908
+ }
909
+
910
+ // ----------------------------------------------------------------------------------------
911
+
912
+ const bigint_kernel_2 bigint_kernel_2::
913
+ operator++ (
914
+ int
915
+ )
916
+ {
917
+ data_record* temp; // this is the copy of temp we will return in the end
918
+
919
+ data_record* temp2 = new data_record(data->digits_used+slack);
920
+ increment(data,temp2);
921
+
922
+ temp = data;
923
+ data = temp2;
924
+
925
+ return bigint_kernel_2(temp,0);
926
+ }
927
+
928
+ // ----------------------------------------------------------------------------------------
929
+
930
+ bigint_kernel_2& bigint_kernel_2::
931
+ operator-- (
932
+ )
933
+ {
934
+ // if there are other references to this data
935
+ if (data->references != 1)
936
+ {
937
+ data_record* temp = new data_record(data->digits_used+slack);
938
+ data->references -= 1;
939
+ decrement(data,temp);
940
+ data = temp;
941
+ }
942
+ else
943
+ {
944
+ decrement(data,data);
945
+ }
946
+
947
+ return *this;
948
+ }
949
+
950
+ // ----------------------------------------------------------------------------------------
951
+
952
+ const bigint_kernel_2 bigint_kernel_2::
953
+ operator-- (
954
+ int
955
+ )
956
+ {
957
+ data_record* temp; // this is the copy of temp we will return in the end
958
+
959
+ data_record* temp2 = new data_record(data->digits_used+slack);
960
+ decrement(data,temp2);
961
+
962
+ temp = data;
963
+ data = temp2;
964
+
965
+ return bigint_kernel_2(temp,0);
966
+ }
967
+
968
+ // ----------------------------------------------------------------------------------------
969
+ // ----------------------------------------------------------------------------------------
970
+ // private member function definitions
971
+ // ----------------------------------------------------------------------------------------
972
+ // ----------------------------------------------------------------------------------------
973
+
974
+ void bigint_kernel_2::
975
+ short_add (
976
+ const data_record* data,
977
+ uint16 value,
978
+ data_record* result
979
+ ) const
980
+ {
981
+ // put value into the carry part of temp
982
+ uint32 temp = value;
983
+ temp <<= 16;
984
+
985
+
986
+ const uint16* number = data->number;
987
+ const uint16* end = number + data->digits_used; // one past the end of number
988
+ uint16* r = result->number;
989
+
990
+ while (number != end)
991
+ {
992
+ // add *number and the current carry
993
+ temp = *number + (temp>>16);
994
+ // put the low word of temp into *r
995
+ *r = static_cast<uint16>(temp & 0xFFFF);
996
+
997
+ ++number;
998
+ ++r;
999
+ }
1000
+
1001
+ // if there is a final carry
1002
+ if ((temp>>16) != 0)
1003
+ {
1004
+ result->digits_used = data->digits_used + 1;
1005
+ // store the carry in the most significant digit of the result
1006
+ *r = static_cast<uint16>(temp>>16);
1007
+ }
1008
+ else
1009
+ {
1010
+ result->digits_used = data->digits_used;
1011
+ }
1012
+ }
1013
+
1014
+ // ----------------------------------------------------------------------------------------
1015
+
1016
+ void bigint_kernel_2::
1017
+ short_sub (
1018
+ const data_record* data,
1019
+ uint16 value,
1020
+ data_record* result
1021
+ ) const
1022
+ {
1023
+
1024
+
1025
+ const uint16* number = data->number;
1026
+ const uint16* end = number + data->digits_used - 1;
1027
+ uint16* r = result->number;
1028
+
1029
+ uint32 temp = *number - value;
1030
+
1031
+ // put the low word of temp into *data
1032
+ *r = static_cast<uint16>(temp & 0xFFFF);
1033
+
1034
+
1035
+ while (number != end)
1036
+ {
1037
+ ++number;
1038
+ ++r;
1039
+
1040
+ // subtract the carry from *number
1041
+ temp = *number - (temp>>31);
1042
+
1043
+ // put the low word of temp into *r
1044
+ *r = static_cast<uint16>(temp & 0xFFFF);
1045
+ }
1046
+
1047
+ // if we lost a digit in the subtraction
1048
+ if (*r == 0)
1049
+ {
1050
+ if (data->digits_used == 1)
1051
+ result->digits_used = 1;
1052
+ else
1053
+ result->digits_used = data->digits_used - 1;
1054
+ }
1055
+ else
1056
+ {
1057
+ result->digits_used = data->digits_used;
1058
+ }
1059
+
1060
+
1061
+ }
1062
+
1063
+ // ----------------------------------------------------------------------------------------
1064
+
1065
+ void bigint_kernel_2::
1066
+ short_mul (
1067
+ const data_record* data,
1068
+ uint16 value,
1069
+ data_record* result
1070
+ ) const
1071
+ {
1072
+
1073
+ uint32 temp = 0;
1074
+
1075
+
1076
+ const uint16* number = data->number;
1077
+ uint16* r = result->number;
1078
+ const uint16* end = r + data->digits_used;
1079
+
1080
+
1081
+
1082
+ while ( r != end)
1083
+ {
1084
+
1085
+ // multiply *data and value and add in the carry
1086
+ temp = *number*(uint32)value + (temp>>16);
1087
+
1088
+ // put the low word of temp into *data
1089
+ *r = static_cast<uint16>(temp & 0xFFFF);
1090
+
1091
+ ++number;
1092
+ ++r;
1093
+ }
1094
+
1095
+ // if there is a final carry
1096
+ if ((temp>>16) != 0)
1097
+ {
1098
+ result->digits_used = data->digits_used + 1;
1099
+ // put the final carry into the most significant digit of the result
1100
+ *r = static_cast<uint16>(temp>>16);
1101
+ }
1102
+ else
1103
+ {
1104
+ result->digits_used = data->digits_used;
1105
+ }
1106
+
1107
+
1108
+ }
1109
+
1110
+ // ----------------------------------------------------------------------------------------
1111
+
1112
+ void bigint_kernel_2::
1113
+ short_div (
1114
+ const data_record* data,
1115
+ uint16 value,
1116
+ data_record* result,
1117
+ uint16& rem
1118
+ ) const
1119
+ {
1120
+
1121
+ uint16 remainder = 0;
1122
+ uint32 temp;
1123
+
1124
+
1125
+
1126
+ const uint16* number = data->number + data->digits_used - 1;
1127
+ const uint16* end = number - data->digits_used;
1128
+ uint16* r = result->number + data->digits_used - 1;
1129
+
1130
+
1131
+ // if we are losing a digit in this division
1132
+ if (*number < value)
1133
+ {
1134
+ if (data->digits_used == 1)
1135
+ result->digits_used = 1;
1136
+ else
1137
+ result->digits_used = data->digits_used - 1;
1138
+ }
1139
+ else
1140
+ {
1141
+ result->digits_used = data->digits_used;
1142
+ }
1143
+
1144
+
1145
+ // perform the actual division
1146
+ while (number != end)
1147
+ {
1148
+
1149
+ temp = *number + (((uint32)remainder)<<16);
1150
+
1151
+ *r = static_cast<uint16>(temp/value);
1152
+ remainder = static_cast<uint16>(temp%value);
1153
+
1154
+ --number;
1155
+ --r;
1156
+ }
1157
+
1158
+ rem = remainder;
1159
+ }
1160
+
1161
+ // ----------------------------------------------------------------------------------------
1162
+
1163
+ void bigint_kernel_2::
1164
+ long_add (
1165
+ const data_record* lhs,
1166
+ const data_record* rhs,
1167
+ data_record* result
1168
+ ) const
1169
+ {
1170
+ // put value into the carry part of temp
1171
+ uint32 temp=0;
1172
+
1173
+ uint16* min_num; // the number with the least digits used
1174
+ uint16* max_num; // the number with the most digits used
1175
+ uint16* min_end; // one past the end of min_num
1176
+ uint16* max_end; // one past the end of max_num
1177
+ uint16* r = result->number;
1178
+
1179
+ uint32 max_digits_used;
1180
+ if (lhs->digits_used < rhs->digits_used)
1181
+ {
1182
+ max_digits_used = rhs->digits_used;
1183
+ min_num = lhs->number;
1184
+ max_num = rhs->number;
1185
+ min_end = min_num + lhs->digits_used;
1186
+ max_end = max_num + rhs->digits_used;
1187
+ }
1188
+ else
1189
+ {
1190
+ max_digits_used = lhs->digits_used;
1191
+ min_num = rhs->number;
1192
+ max_num = lhs->number;
1193
+ min_end = min_num + rhs->digits_used;
1194
+ max_end = max_num + lhs->digits_used;
1195
+ }
1196
+
1197
+
1198
+
1199
+
1200
+ while (min_num != min_end)
1201
+ {
1202
+ // add *min_num, *max_num and the current carry
1203
+ temp = *min_num + *max_num + (temp>>16);
1204
+ // put the low word of temp into *r
1205
+ *r = static_cast<uint16>(temp & 0xFFFF);
1206
+
1207
+ ++min_num;
1208
+ ++max_num;
1209
+ ++r;
1210
+ }
1211
+
1212
+
1213
+ while (max_num != max_end)
1214
+ {
1215
+ // add *max_num and the current carry
1216
+ temp = *max_num + (temp>>16);
1217
+ // put the low word of temp into *r
1218
+ *r = static_cast<uint16>(temp & 0xFFFF);
1219
+
1220
+ ++max_num;
1221
+ ++r;
1222
+ }
1223
+
1224
+ // check if there was a final carry
1225
+ if ((temp>>16) != 0)
1226
+ {
1227
+ result->digits_used = max_digits_used + 1;
1228
+ // put the carry into the most significant digit in the result
1229
+ *r = static_cast<uint16>(temp>>16);
1230
+ }
1231
+ else
1232
+ {
1233
+ result->digits_used = max_digits_used;
1234
+ }
1235
+
1236
+
1237
+ }
1238
+
1239
+ // ----------------------------------------------------------------------------------------
1240
+
1241
+ void bigint_kernel_2::
1242
+ long_sub (
1243
+ const data_record* lhs,
1244
+ const data_record* rhs,
1245
+ data_record* result
1246
+ ) const
1247
+ {
1248
+
1249
+
1250
+ const uint16* number1 = lhs->number;
1251
+ const uint16* number2 = rhs->number;
1252
+ const uint16* end = number2 + rhs->digits_used;
1253
+ uint16* r = result->number;
1254
+
1255
+
1256
+
1257
+ uint32 temp =0;
1258
+
1259
+
1260
+ while (number2 != end)
1261
+ {
1262
+
1263
+ // subtract *number2 from *number1 and then subtract any carry
1264
+ temp = *number1 - *number2 - (temp>>31);
1265
+
1266
+ // put the low word of temp into *r
1267
+ *r = static_cast<uint16>(temp & 0xFFFF);
1268
+
1269
+ ++number1;
1270
+ ++number2;
1271
+ ++r;
1272
+ }
1273
+
1274
+ end = lhs->number + lhs->digits_used;
1275
+ while (number1 != end)
1276
+ {
1277
+
1278
+ // subtract the carry from *number1
1279
+ temp = *number1 - (temp>>31);
1280
+
1281
+ // put the low word of temp into *r
1282
+ *r = static_cast<uint16>(temp & 0xFFFF);
1283
+
1284
+ ++number1;
1285
+ ++r;
1286
+ }
1287
+
1288
+ result->digits_used = lhs->digits_used;
1289
+ // adjust the number of digits used appropriately
1290
+ --r;
1291
+ while (*r == 0 && result->digits_used > 1)
1292
+ {
1293
+ --r;
1294
+ --result->digits_used;
1295
+ }
1296
+ }
1297
+
1298
+ // ----------------------------------------------------------------------------------------
1299
+
1300
+ void bigint_kernel_2::
1301
+ long_div (
1302
+ const data_record* lhs,
1303
+ const data_record* rhs,
1304
+ data_record* result,
1305
+ data_record* remainder
1306
+ ) const
1307
+ {
1308
+ // zero result
1309
+ result->digits_used = 1;
1310
+ *(result->number) = 0;
1311
+
1312
+ uint16* a;
1313
+ uint16* b;
1314
+ uint16* end;
1315
+
1316
+ // copy lhs into remainder
1317
+ remainder->digits_used = lhs->digits_used;
1318
+ a = remainder->number;
1319
+ end = a + remainder->digits_used;
1320
+ b = lhs->number;
1321
+ while (a != end)
1322
+ {
1323
+ *a = *b;
1324
+ ++a;
1325
+ ++b;
1326
+ }
1327
+
1328
+
1329
+ // if rhs is bigger than lhs then result == 0 and remainder == lhs
1330
+ // so then we can quit right now
1331
+ if (is_less_than(lhs,rhs))
1332
+ {
1333
+ return;
1334
+ }
1335
+
1336
+
1337
+ // make a temporary number
1338
+ data_record temp(lhs->digits_used + slack);
1339
+
1340
+
1341
+ // shift rhs left until it is one shift away from being larger than lhs and
1342
+ // put the number of left shifts necessary into shifts
1343
+ uint32 shifts;
1344
+ shifts = (lhs->digits_used - rhs->digits_used) * 16;
1345
+
1346
+ shift_left(rhs,&temp,shifts);
1347
+
1348
+
1349
+ // while (lhs > temp)
1350
+ while (is_less_than(&temp,lhs))
1351
+ {
1352
+ shift_left(&temp,&temp,1);
1353
+ ++shifts;
1354
+ }
1355
+ // make sure lhs isn't smaller than temp
1356
+ while (is_less_than(lhs,&temp))
1357
+ {
1358
+ shift_right(&temp,&temp);
1359
+ --shifts;
1360
+ }
1361
+
1362
+
1363
+
1364
+ // we want to execute the loop shifts +1 times
1365
+ ++shifts;
1366
+ while (shifts != 0)
1367
+ {
1368
+ shift_left(result,result,1);
1369
+ // if (temp <= remainder)
1370
+ if (!is_less_than(remainder,&temp))
1371
+ {
1372
+ long_sub(remainder,&temp,remainder);
1373
+
1374
+ // increment result
1375
+ uint16* r = result->number;
1376
+ uint16* end = r + result->digits_used;
1377
+ while (true)
1378
+ {
1379
+ ++(*r);
1380
+ // if there was no carry then we are done
1381
+ if (*r != 0)
1382
+ break;
1383
+
1384
+ ++r;
1385
+
1386
+ // if we hit the end of r and there is still a carry then
1387
+ // the next digit of r is 1 and there is one more digit used
1388
+ if (r == end)
1389
+ {
1390
+ *r = 1;
1391
+ ++(result->digits_used);
1392
+ break;
1393
+ }
1394
+ }
1395
+ }
1396
+ shift_right(&temp,&temp);
1397
+ --shifts;
1398
+ }
1399
+
1400
+
1401
+ }
1402
+
1403
+ // ----------------------------------------------------------------------------------------
1404
+
1405
+ void bigint_kernel_2::
1406
+ long_mul (
1407
+ const data_record* lhs,
1408
+ const data_record* rhs,
1409
+ data_record* result
1410
+ ) const
1411
+ {
1412
+ // if one of the numbers is small then use this simple but O(n^2) algorithm
1413
+ if (std::min(lhs->digits_used, rhs->digits_used) < 10)
1414
+ {
1415
+ // make result be zero
1416
+ result->digits_used = 1;
1417
+ *(result->number) = 0;
1418
+
1419
+
1420
+ const data_record* aa;
1421
+ const data_record* bb;
1422
+
1423
+ if (lhs->digits_used < rhs->digits_used)
1424
+ {
1425
+ // make copies of lhs and rhs and give them an appropriate amount of
1426
+ // extra memory so there won't be any overflows
1427
+ aa = lhs;
1428
+ bb = rhs;
1429
+ }
1430
+ else
1431
+ {
1432
+ // make copies of lhs and rhs and give them an appropriate amount of
1433
+ // extra memory so there won't be any overflows
1434
+ aa = rhs;
1435
+ bb = lhs;
1436
+ }
1437
+
1438
+ // copy the larger(approximately) of lhs and rhs into b
1439
+ data_record b(*bb,aa->digits_used+slack);
1440
+
1441
+
1442
+ uint32 shift_value = 0;
1443
+ uint16* anum = aa->number;
1444
+ uint16* end = anum + aa->digits_used;
1445
+ while (anum != end )
1446
+ {
1447
+ uint16 bit = 0x0001;
1448
+
1449
+ for (int i = 0; i < 16; ++i)
1450
+ {
1451
+ // if the specified bit of a is 1
1452
+ if ((*anum & bit) != 0)
1453
+ {
1454
+ shift_left(&b,&b,shift_value);
1455
+ shift_value = 0;
1456
+ long_add(&b,result,result);
1457
+ }
1458
+ ++shift_value;
1459
+ bit <<= 1;
1460
+ }
1461
+
1462
+ ++anum;
1463
+ }
1464
+ }
1465
+ else // else if both lhs and rhs are large then use the more complex
1466
+ // O(n*logn) algorithm
1467
+ {
1468
+ uint32 size = 1;
1469
+ // make size a power of 2
1470
+ while (size < (lhs->digits_used + rhs->digits_used)*2)
1471
+ {
1472
+ size *= 2;
1473
+ }
1474
+
1475
+ // allocate some temporary space so we can do the FFT
1476
+ ct* a = new ct[size];
1477
+ ct* b; try {b = new ct[size]; } catch (...) { delete [] a; throw; }
1478
+
1479
+ // load lhs into the a array. We are breaking the input number into
1480
+ // 8bit chunks for the purpose of using this fft algorithm. The reason
1481
+ // for this is so that we have smaller numbers coming out of the final
1482
+ // ifft. This helps avoid overflow.
1483
+ for (uint32 i = 0; i < lhs->digits_used; ++i)
1484
+ {
1485
+ a[i*2] = ct((t)(lhs->number[i]&0xFF),0);
1486
+ a[i*2+1] = ct((t)(lhs->number[i]>>8),0);
1487
+ }
1488
+ for (uint32 i = lhs->digits_used*2; i < size; ++i)
1489
+ {
1490
+ a[i] = 0;
1491
+ }
1492
+
1493
+ // load rhs into the b array
1494
+ for (uint32 i = 0; i < rhs->digits_used; ++i)
1495
+ {
1496
+ b[i*2] = ct((t)(rhs->number[i]&0xFF),0);
1497
+ b[i*2+1] = ct((t)(rhs->number[i]>>8),0);
1498
+ }
1499
+ for (uint32 i = rhs->digits_used*2; i < size; ++i)
1500
+ {
1501
+ b[i] = 0;
1502
+ }
1503
+
1504
+ // perform the forward fft of a and b
1505
+ fft(a,size);
1506
+ fft(b,size);
1507
+
1508
+ const double l = 1.0/size;
1509
+
1510
+ // do the pointwise multiply of a and b and also apply the scale
1511
+ // factor in this loop too.
1512
+ for (unsigned long i = 0; i < size; ++i)
1513
+ {
1514
+ a[i] = l*a[i]*b[i];
1515
+ }
1516
+
1517
+ // Now compute the inverse fft of the pointwise multiplication of a and b.
1518
+ // This is basically the result. We just have to take care of any carries
1519
+ // that should happen.
1520
+ ifft(a,size);
1521
+
1522
+ // loop over the result and propagate any carries that need to take place.
1523
+ // We will also be moving the resulting numbers into result->number at
1524
+ // the same time.
1525
+ uint64 carry = 0;
1526
+ result->digits_used = 0;
1527
+ int zeros = 0;
1528
+ const uint32 len = lhs->digits_used + rhs->digits_used;
1529
+ for (unsigned long i = 0; i < len; ++i)
1530
+ {
1531
+ uint64 num1 = static_cast<uint64>(std::floor(a[i*2].real()+0.5));
1532
+ num1 += carry;
1533
+ carry = 0;
1534
+ if (num1 > 255)
1535
+ {
1536
+ carry = num1 >> 8;
1537
+ num1 = (num1&0xFF);
1538
+ }
1539
+
1540
+ uint64 num2 = static_cast<uint64>(std::floor(a[i*2+1].real()+0.5));
1541
+ num2 += carry;
1542
+ carry = 0;
1543
+ if (num2 > 255)
1544
+ {
1545
+ carry = num2 >> 8;
1546
+ num2 = (num2&0xFF);
1547
+ }
1548
+
1549
+ // put the new number into its final place
1550
+ num1 = (num2<<8) | num1;
1551
+ result->number[i] = static_cast<uint16>(num1);
1552
+
1553
+ // keep track of the number of leading zeros
1554
+ if (num1 == 0)
1555
+ ++zeros;
1556
+ else
1557
+ zeros = 0;
1558
+ ++(result->digits_used);
1559
+ }
1560
+
1561
+ // adjust digits_used so that it reflects the actual number
1562
+ // of non-zero digits in our representation.
1563
+ result->digits_used -= zeros;
1564
+
1565
+ // if the result was zero then adjust the result accordingly
1566
+ if (result->digits_used == 0)
1567
+ {
1568
+ // make result be zero
1569
+ result->digits_used = 1;
1570
+ *(result->number) = 0;
1571
+ }
1572
+
1573
+ // free all the temporary buffers
1574
+ delete [] a;
1575
+ delete [] b;
1576
+ }
1577
+ }
1578
+
1579
+ // ----------------------------------------------------------------------------------------
1580
+
1581
+ void bigint_kernel_2::
1582
+ shift_left (
1583
+ const data_record* data,
1584
+ data_record* result,
1585
+ uint32 shift_amount
1586
+ ) const
1587
+ {
1588
+ uint32 offset = shift_amount/16;
1589
+ shift_amount &= 0xf; // same as shift_amount %= 16;
1590
+
1591
+ uint16* r = result->number + data->digits_used + offset; // result
1592
+ uint16* end = data->number;
1593
+ uint16* s = end + data->digits_used; // source
1594
+ const uint32 temp = 16 - shift_amount;
1595
+
1596
+ *r = (*(--s) >> temp);
1597
+ // set the number of digits used in the result
1598
+ // if the upper bits from *s were zero then don't count this first word
1599
+ if (*r == 0)
1600
+ {
1601
+ result->digits_used = data->digits_used + offset;
1602
+ }
1603
+ else
1604
+ {
1605
+ result->digits_used = data->digits_used + offset + 1;
1606
+ }
1607
+ --r;
1608
+
1609
+ while (s != end)
1610
+ {
1611
+ *r = ((*s << shift_amount) | ( *(s-1) >> temp));
1612
+ --r;
1613
+ --s;
1614
+ }
1615
+ *r = *s << shift_amount;
1616
+
1617
+ // now zero the rest of the result
1618
+ end = result->number;
1619
+ while (r != end)
1620
+ *(--r) = 0;
1621
+
1622
+ }
1623
+
1624
+ // ----------------------------------------------------------------------------------------
1625
+
1626
+ void bigint_kernel_2::
1627
+ shift_right (
1628
+ const data_record* data,
1629
+ data_record* result
1630
+ ) const
1631
+ {
1632
+
1633
+ uint16* r = result->number; // result
1634
+ uint16* s = data->number; // source
1635
+ uint16* end = s + data->digits_used - 1;
1636
+
1637
+ while (s != end)
1638
+ {
1639
+ *r = (*s >> 1) | (*(s+1) << 15);
1640
+ ++r;
1641
+ ++s;
1642
+ }
1643
+ *r = *s >> 1;
1644
+
1645
+
1646
+ // calculate the new number for digits_used
1647
+ if (*r == 0)
1648
+ {
1649
+ if (data->digits_used != 1)
1650
+ result->digits_used = data->digits_used - 1;
1651
+ else
1652
+ result->digits_used = 1;
1653
+ }
1654
+ else
1655
+ {
1656
+ result->digits_used = data->digits_used;
1657
+ }
1658
+
1659
+
1660
+ }
1661
+
1662
+ // ----------------------------------------------------------------------------------------
1663
+
1664
+ bool bigint_kernel_2::
1665
+ is_less_than (
1666
+ const data_record* lhs,
1667
+ const data_record* rhs
1668
+ ) const
1669
+ {
1670
+ uint32 lhs_digits_used = lhs->digits_used;
1671
+ uint32 rhs_digits_used = rhs->digits_used;
1672
+
1673
+ // if lhs is definitely less than rhs
1674
+ if (lhs_digits_used < rhs_digits_used )
1675
+ return true;
1676
+ // if lhs is definitely greater than rhs
1677
+ else if (lhs_digits_used > rhs_digits_used)
1678
+ return false;
1679
+ else
1680
+ {
1681
+ uint16* end = lhs->number;
1682
+ uint16* l = end + lhs_digits_used;
1683
+ uint16* r = rhs->number + rhs_digits_used;
1684
+
1685
+ while (l != end)
1686
+ {
1687
+ --l;
1688
+ --r;
1689
+ if (*l < *r)
1690
+ return true;
1691
+ else if (*l > *r)
1692
+ return false;
1693
+ }
1694
+
1695
+ // at this point we know that they are equal
1696
+ return false;
1697
+ }
1698
+
1699
+ }
1700
+
1701
+ // ----------------------------------------------------------------------------------------
1702
+
1703
+ bool bigint_kernel_2::
1704
+ is_equal_to (
1705
+ const data_record* lhs,
1706
+ const data_record* rhs
1707
+ ) const
1708
+ {
1709
+ // if lhs and rhs are definitely not equal
1710
+ if (lhs->digits_used != rhs->digits_used )
1711
+ {
1712
+ return false;
1713
+ }
1714
+ else
1715
+ {
1716
+ uint16* l = lhs->number;
1717
+ uint16* r = rhs->number;
1718
+ uint16* end = l + lhs->digits_used;
1719
+
1720
+ while (l != end)
1721
+ {
1722
+ if (*l != *r)
1723
+ return false;
1724
+ ++l;
1725
+ ++r;
1726
+ }
1727
+
1728
+ // at this point we know that they are equal
1729
+ return true;
1730
+ }
1731
+
1732
+ }
1733
+
1734
+ // ----------------------------------------------------------------------------------------
1735
+
1736
+ void bigint_kernel_2::
1737
+ increment (
1738
+ const data_record* source,
1739
+ data_record* dest
1740
+ ) const
1741
+ {
1742
+ uint16* s = source->number;
1743
+ uint16* d = dest->number;
1744
+ uint16* end = s + source->digits_used;
1745
+ while (true)
1746
+ {
1747
+ *d = *s + 1;
1748
+
1749
+ // if there was no carry then break out of the loop
1750
+ if (*d != 0)
1751
+ {
1752
+ dest->digits_used = source->digits_used;
1753
+
1754
+ // copy the rest of the digits over to d
1755
+ ++d; ++s;
1756
+ while (s != end)
1757
+ {
1758
+ *d = *s;
1759
+ ++d;
1760
+ ++s;
1761
+ }
1762
+
1763
+ break;
1764
+ }
1765
+
1766
+
1767
+ ++s;
1768
+
1769
+ // if we have hit the end of s and there was a carry up to this point
1770
+ // then just make the next digit 1 and add one to the digits used
1771
+ if (s == end)
1772
+ {
1773
+ ++d;
1774
+ dest->digits_used = source->digits_used + 1;
1775
+ *d = 1;
1776
+ break;
1777
+ }
1778
+
1779
+ ++d;
1780
+ }
1781
+ }
1782
+
1783
+ // ----------------------------------------------------------------------------------------
1784
+
1785
+ void bigint_kernel_2::
1786
+ decrement (
1787
+ const data_record* source,
1788
+ data_record* dest
1789
+ ) const
1790
+ {
1791
+ uint16* s = source->number;
1792
+ uint16* d = dest->number;
1793
+ uint16* end = s + source->digits_used;
1794
+ while (true)
1795
+ {
1796
+ *d = *s - 1;
1797
+
1798
+ // if there was no carry then break out of the loop
1799
+ if (*d != 0xFFFF)
1800
+ {
1801
+ // if we lost a digit in the subtraction
1802
+ if (*d == 0 && s+1 == end)
1803
+ {
1804
+ if (source->digits_used == 1)
1805
+ dest->digits_used = 1;
1806
+ else
1807
+ dest->digits_used = source->digits_used - 1;
1808
+ }
1809
+ else
1810
+ {
1811
+ dest->digits_used = source->digits_used;
1812
+ }
1813
+ break;
1814
+ }
1815
+ else
1816
+ {
1817
+ ++d;
1818
+ ++s;
1819
+ }
1820
+
1821
+ }
1822
+
1823
+ // copy the rest of the digits over to d
1824
+ ++d;
1825
+ ++s;
1826
+ while (s != end)
1827
+ {
1828
+ *d = *s;
1829
+ ++d;
1830
+ ++s;
1831
+ }
1832
+ }
1833
+
1834
+ // ----------------------------------------------------------------------------------------
1835
+
1836
+ void bigint_kernel_2::
1837
+ fft (
1838
+ ct* data,
1839
+ unsigned long len
1840
+ ) const
1841
+ {
1842
+ const t pi2 = -2.0*3.1415926535897932384626433832795028841971693993751;
1843
+
1844
+ const unsigned long half = len/2;
1845
+
1846
+ std::vector<ct> twiddle_factors;
1847
+ twiddle_factors.resize(half);
1848
+
1849
+ // compute the complex root of unity w
1850
+ const t temp = pi2/len;
1851
+ ct w = ct(std::cos(temp),std::sin(temp));
1852
+
1853
+ ct w_pow = 1;
1854
+
1855
+ // compute the twiddle factors
1856
+ for (std::vector<ct>::size_type j = 0; j < twiddle_factors.size(); ++j)
1857
+ {
1858
+ twiddle_factors[j] = w_pow;
1859
+ w_pow *= w;
1860
+ }
1861
+
1862
+ ct a, b;
1863
+
1864
+ // now compute the decimation in frequency. This first
1865
+ // outer loop loops log2(len) number of times
1866
+ unsigned long skip = 1;
1867
+ for (unsigned long step = half; step != 0; step >>= 1)
1868
+ {
1869
+ // do blocks of butterflies in this loop
1870
+ for (unsigned long j = 0; j < len; j += step*2)
1871
+ {
1872
+ // do step butterflies
1873
+ for (unsigned long k = 0; k < step; ++k)
1874
+ {
1875
+ const unsigned long a_idx = j+k;
1876
+ const unsigned long b_idx = j+k+step;
1877
+ a = data[a_idx] + data[b_idx];
1878
+ b = (data[a_idx] - data[b_idx])*twiddle_factors[k*skip];
1879
+ data[a_idx] = a;
1880
+ data[b_idx] = b;
1881
+ }
1882
+ }
1883
+ skip *= 2;
1884
+ }
1885
+ }
1886
+
1887
+ // ----------------------------------------------------------------------------------------
1888
+
1889
+ void bigint_kernel_2::
1890
+ ifft(
1891
+ ct* data,
1892
+ unsigned long len
1893
+ ) const
1894
+ {
1895
+ const t pi2 = 2.0*3.1415926535897932384626433832795028841971693993751;
1896
+
1897
+ const unsigned long half = len/2;
1898
+
1899
+ std::vector<ct> twiddle_factors;
1900
+ twiddle_factors.resize(half);
1901
+
1902
+ // compute the complex root of unity w
1903
+ const t temp = pi2/len;
1904
+ ct w = ct(std::cos(temp),std::sin(temp));
1905
+
1906
+ ct w_pow = 1;
1907
+
1908
+ // compute the twiddle factors
1909
+ for (std::vector<ct>::size_type j = 0; j < twiddle_factors.size(); ++j)
1910
+ {
1911
+ twiddle_factors[j] = w_pow;
1912
+ w_pow *= w;
1913
+ }
1914
+
1915
+ ct a, b;
1916
+
1917
+ // now compute the inverse decimation in frequency. This first
1918
+ // outer loop loops log2(len) number of times
1919
+ unsigned long skip = half;
1920
+ for (unsigned long step = 1; step <= half; step <<= 1)
1921
+ {
1922
+ // do blocks of butterflies in this loop
1923
+ for (unsigned long j = 0; j < len; j += step*2)
1924
+ {
1925
+ // do step butterflies
1926
+ for (unsigned long k = 0; k < step; ++k)
1927
+ {
1928
+ const unsigned long a_idx = j+k;
1929
+ const unsigned long b_idx = j+k+step;
1930
+ data[b_idx] *= twiddle_factors[k*skip];
1931
+ a = data[a_idx] + data[b_idx];
1932
+ b = data[a_idx] - data[b_idx];
1933
+ data[a_idx] = a;
1934
+ data[b_idx] = b;
1935
+ }
1936
+ }
1937
+ skip /= 2;
1938
+ }
1939
+ }
1940
+
1941
+ // ----------------------------------------------------------------------------------------
1942
+
1943
+ }
1944
+ #endif // DLIB_BIGINT_KERNEL_2_CPp_
1945
+
dlibs/dlib/bigint/bigint_kernel_2.h ADDED
@@ -0,0 +1,569 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (C) 2003 Davis E. King ([email protected])
2
+ // License: Boost Software License See LICENSE.txt for the full license.
3
+ #ifndef DLIB_BIGINT_KERNEl_2_
4
+ #define DLIB_BIGINT_KERNEl_2_
5
+
6
+ #include "bigint_kernel_abstract.h"
7
+ #include "../algs.h"
8
+ #include "../serialize.h"
9
+ #include "../uintn.h"
10
+ #include <iosfwd>
11
+ #include <cmath>
12
+ #include <complex>
13
+ #include <vector>
14
+
15
+ namespace dlib
16
+ {
17
+
18
+ class bigint_kernel_2
19
+ {
20
+ /*!
21
+ INITIAL VALUE
22
+ slack == 25
23
+ data->number[0] == 0
24
+ data->size == slack
25
+ data->references == 1
26
+ data->digits_used == 1
27
+
28
+
29
+ CONVENTION
30
+ slack == the number of extra digits placed into the number when it is
31
+ created. the slack value should never be less than 1
32
+
33
+ data->number == pointer to an array of data->size uint16s.
34
+ data represents a string of base 65535 numbers with data[0] being
35
+ the least significant bit and data[data->digits_used-1] being the most
36
+ significant
37
+
38
+
39
+ NOTE: In the comments I will consider a word to be a 16 bit value
40
+
41
+
42
+ data->digits_used == the number of significant digits in the number.
43
+ data->digits_used tells us the number of used elements in the
44
+ data->number array so everything beyond data->number[data->digits_used-1]
45
+ is undefined
46
+
47
+ data->references == the number of bigint_kernel_2 objects which refer
48
+ to this data_record
49
+ !*/
50
+
51
+
52
+ struct data_record
53
+ {
54
+
55
+
56
+ explicit data_record(
57
+ uint32 size_
58
+ ) :
59
+ size(size_),
60
+ number(new uint16[size_]),
61
+ references(1),
62
+ digits_used(1)
63
+ {*number = 0;}
64
+ /*!
65
+ ensures
66
+ - initializes *this to represent zero
67
+ !*/
68
+
69
+ data_record(
70
+ const data_record& item,
71
+ uint32 additional_size
72
+ ) :
73
+ size(item.digits_used + additional_size),
74
+ number(new uint16[size]),
75
+ references(1),
76
+ digits_used(item.digits_used)
77
+ {
78
+ uint16* source = item.number;
79
+ uint16* dest = number;
80
+ uint16* end = source + digits_used;
81
+ while (source != end)
82
+ {
83
+ *dest = *source;
84
+ ++dest;
85
+ ++source;
86
+ }
87
+ }
88
+ /*!
89
+ ensures
90
+ - *this is a copy of item except with
91
+ size == item.digits_used + additional_size
92
+ !*/
93
+
94
+ ~data_record(
95
+ )
96
+ {
97
+ delete [] number;
98
+ }
99
+
100
+
101
+ const uint32 size;
102
+ uint16* number;
103
+ uint32 references;
104
+ uint32 digits_used;
105
+
106
+ private:
107
+ // no copy constructor
108
+ data_record ( data_record&);
109
+ };
110
+
111
+
112
+ // note that the second parameter is just there
113
+ // to resolve the ambiguity between this constructor and
114
+ // bigint_kernel_2(uint32)
115
+ explicit bigint_kernel_2 (
116
+ data_record* data_, int
117
+ ): slack(25),data(data_) {}
118
+ /*!
119
+ ensures
120
+ - *this is initialized with data_ as its data member
121
+ !*/
122
+
123
+ public:
124
+
125
+ bigint_kernel_2 (
126
+ );
127
+
128
+ bigint_kernel_2 (
129
+ uint32 value
130
+ );
131
+
132
+ bigint_kernel_2 (
133
+ const bigint_kernel_2& item
134
+ );
135
+
136
+ virtual ~bigint_kernel_2 (
137
+ );
138
+
139
+ const bigint_kernel_2 operator+ (
140
+ const bigint_kernel_2& rhs
141
+ ) const;
142
+
143
+ bigint_kernel_2& operator+= (
144
+ const bigint_kernel_2& rhs
145
+ );
146
+
147
+ const bigint_kernel_2 operator- (
148
+ const bigint_kernel_2& rhs
149
+ ) const;
150
+
151
+ bigint_kernel_2& operator-= (
152
+ const bigint_kernel_2& rhs
153
+ );
154
+
155
+ const bigint_kernel_2 operator* (
156
+ const bigint_kernel_2& rhs
157
+ ) const;
158
+
159
+ bigint_kernel_2& operator*= (
160
+ const bigint_kernel_2& rhs
161
+ );
162
+
163
+ const bigint_kernel_2 operator/ (
164
+ const bigint_kernel_2& rhs
165
+ ) const;
166
+
167
+ bigint_kernel_2& operator/= (
168
+ const bigint_kernel_2& rhs
169
+ );
170
+
171
+ const bigint_kernel_2 operator% (
172
+ const bigint_kernel_2& rhs
173
+ ) const;
174
+
175
+ bigint_kernel_2& operator%= (
176
+ const bigint_kernel_2& rhs
177
+ );
178
+
179
+ bool operator < (
180
+ const bigint_kernel_2& rhs
181
+ ) const;
182
+
183
+ bool operator == (
184
+ const bigint_kernel_2& rhs
185
+ ) const;
186
+
187
+ bigint_kernel_2& operator= (
188
+ const bigint_kernel_2& rhs
189
+ );
190
+
191
+ friend std::ostream& operator<< (
192
+ std::ostream& out,
193
+ const bigint_kernel_2& rhs
194
+ );
195
+
196
+ friend std::istream& operator>> (
197
+ std::istream& in,
198
+ bigint_kernel_2& rhs
199
+ );
200
+
201
+ bigint_kernel_2& operator++ (
202
+ );
203
+
204
+ const bigint_kernel_2 operator++ (
205
+ int
206
+ );
207
+
208
+ bigint_kernel_2& operator-- (
209
+ );
210
+
211
+ const bigint_kernel_2 operator-- (
212
+ int
213
+ );
214
+
215
+ friend const bigint_kernel_2 operator+ (
216
+ uint16 lhs,
217
+ const bigint_kernel_2& rhs
218
+ );
219
+
220
+ friend const bigint_kernel_2 operator+ (
221
+ const bigint_kernel_2& lhs,
222
+ uint16 rhs
223
+ );
224
+
225
+ bigint_kernel_2& operator+= (
226
+ uint16 rhs
227
+ );
228
+
229
+ friend const bigint_kernel_2 operator- (
230
+ uint16 lhs,
231
+ const bigint_kernel_2& rhs
232
+ );
233
+
234
+ friend const bigint_kernel_2 operator- (
235
+ const bigint_kernel_2& lhs,
236
+ uint16 rhs
237
+ );
238
+
239
+ bigint_kernel_2& operator-= (
240
+ uint16 rhs
241
+ );
242
+
243
+ friend const bigint_kernel_2 operator* (
244
+ uint16 lhs,
245
+ const bigint_kernel_2& rhs
246
+ );
247
+
248
+ friend const bigint_kernel_2 operator* (
249
+ const bigint_kernel_2& lhs,
250
+ uint16 rhs
251
+ );
252
+
253
+ bigint_kernel_2& operator*= (
254
+ uint16 rhs
255
+ );
256
+
257
+ friend const bigint_kernel_2 operator/ (
258
+ uint16 lhs,
259
+ const bigint_kernel_2& rhs
260
+ );
261
+
262
+ friend const bigint_kernel_2 operator/ (
263
+ const bigint_kernel_2& lhs,
264
+ uint16 rhs
265
+ );
266
+
267
+ bigint_kernel_2& operator/= (
268
+ uint16 rhs
269
+ );
270
+
271
+ friend const bigint_kernel_2 operator% (
272
+ uint16 lhs,
273
+ const bigint_kernel_2& rhs
274
+ );
275
+
276
+ friend const bigint_kernel_2 operator% (
277
+ const bigint_kernel_2& lhs,
278
+ uint16 rhs
279
+ );
280
+
281
+ bigint_kernel_2& operator%= (
282
+ uint16 rhs
283
+ );
284
+
285
+ friend bool operator < (
286
+ uint16 lhs,
287
+ const bigint_kernel_2& rhs
288
+ );
289
+
290
+ friend bool operator < (
291
+ const bigint_kernel_2& lhs,
292
+ uint16 rhs
293
+ );
294
+
295
+ friend bool operator == (
296
+ const bigint_kernel_2& lhs,
297
+ uint16 rhs
298
+ );
299
+
300
+ friend bool operator == (
301
+ uint16 lhs,
302
+ const bigint_kernel_2& rhs
303
+ );
304
+
305
+ bigint_kernel_2& operator= (
306
+ uint16 rhs
307
+ );
308
+
309
+
310
+ void swap (
311
+ bigint_kernel_2& item
312
+ ) { data_record* temp = data; data = item.data; item.data = temp; }
313
+
314
+
315
+ private:
316
+
317
+ typedef double t;
318
+ typedef std::complex<t> ct;
319
+
320
+ void fft(
321
+ ct* data,
322
+ unsigned long len
323
+ ) const;
324
+ /*!
325
+ requires
326
+ - len == x^n for some integer n (i.e. len is a power of 2)
327
+ - len > 0
328
+ ensures
329
+ - #data == the FT decimation in frequency of data
330
+ !*/
331
+
332
+ void ifft(
333
+ ct* data,
334
+ unsigned long len
335
+ ) const;
336
+ /*!
337
+ requires
338
+ - len == x^n for some integer n (i.e. len is a power of 2)
339
+ - len > 0
340
+ ensures
341
+ - #data == the inverse decimation in frequency of data.
342
+ (i.e. the inverse of what fft(data,len,-1) does to data)
343
+ !*/
344
+
345
+ void long_add (
346
+ const data_record* lhs,
347
+ const data_record* rhs,
348
+ data_record* result
349
+ ) const;
350
+ /*!
351
+ requires
352
+ - result->size >= max(lhs->digits_used,rhs->digits_used) + 1
353
+ ensures
354
+ - result == lhs + rhs
355
+ !*/
356
+
357
+ void long_sub (
358
+ const data_record* lhs,
359
+ const data_record* rhs,
360
+ data_record* result
361
+ ) const;
362
+ /*!
363
+ requires
364
+ - lhs >= rhs
365
+ - result->size >= lhs->digits_used
366
+ ensures
367
+ - result == lhs - rhs
368
+ !*/
369
+
370
+ void long_div (
371
+ const data_record* lhs,
372
+ const data_record* rhs,
373
+ data_record* result,
374
+ data_record* remainder
375
+ ) const;
376
+ /*!
377
+ requires
378
+ - rhs != 0
379
+ - result->size >= lhs->digits_used
380
+ - remainder->size >= lhs->digits_used
381
+ - each parameter is unique (i.e. lhs != result, lhs != remainder, etc.)
382
+ ensures
383
+ - result == lhs / rhs
384
+ - remainder == lhs % rhs
385
+ !*/
386
+
387
+ void long_mul (
388
+ const data_record* lhs,
389
+ const data_record* rhs,
390
+ data_record* result
391
+ ) const;
392
+ /*!
393
+ requires
394
+ - result->size >= lhs->digits_used + rhs->digits_used
395
+ - result != lhs
396
+ - result != rhs
397
+ ensures
398
+ - result == lhs * rhs
399
+ !*/
400
+
401
+ void short_add (
402
+ const data_record* data,
403
+ uint16 value,
404
+ data_record* result
405
+ ) const;
406
+ /*!
407
+ requires
408
+ - result->size >= data->size + 1
409
+ ensures
410
+ - result == data + value
411
+ !*/
412
+
413
+ void short_sub (
414
+ const data_record* data,
415
+ uint16 value,
416
+ data_record* result
417
+ ) const;
418
+ /*!
419
+ requires
420
+ - data >= value
421
+ - result->size >= data->digits_used
422
+ ensures
423
+ - result == data - value
424
+ !*/
425
+
426
+ void short_mul (
427
+ const data_record* data,
428
+ uint16 value,
429
+ data_record* result
430
+ ) const;
431
+ /*!
432
+ requires
433
+ - result->size >= data->digits_used + 1
434
+ ensures
435
+ - result == data * value
436
+ !*/
437
+
438
+ void short_div (
439
+ const data_record* data,
440
+ uint16 value,
441
+ data_record* result,
442
+ uint16& remainder
443
+ ) const;
444
+ /*!
445
+ requires
446
+ - value != 0
447
+ - result->size >= data->digits_used
448
+ ensures
449
+ - result = data*value
450
+ - remainder = data%value
451
+ !*/
452
+
453
+ void shift_left (
454
+ const data_record* data,
455
+ data_record* result,
456
+ uint32 shift_amount
457
+ ) const;
458
+ /*!
459
+ requires
460
+ - result->size >= data->digits_used + shift_amount/8 + 1
461
+ ensures
462
+ - result == data << shift_amount
463
+ !*/
464
+
465
+ void shift_right (
466
+ const data_record* data,
467
+ data_record* result
468
+ ) const;
469
+ /*!
470
+ requires
471
+ - result->size >= data->digits_used
472
+ ensures
473
+ - result == data >> 1
474
+ !*/
475
+
476
+ bool is_less_than (
477
+ const data_record* lhs,
478
+ const data_record* rhs
479
+ ) const;
480
+ /*!
481
+ ensures
482
+ - returns true if lhs < rhs
483
+ - returns false otherwise
484
+ !*/
485
+
486
+ bool is_equal_to (
487
+ const data_record* lhs,
488
+ const data_record* rhs
489
+ ) const;
490
+ /*!
491
+ ensures
492
+ - returns true if lhs == rhs
493
+ - returns false otherwise
494
+ !*/
495
+
496
+ void increment (
497
+ const data_record* source,
498
+ data_record* dest
499
+ ) const;
500
+ /*!
501
+ requires
502
+ - dest->size >= source->digits_used + 1
503
+ ensures
504
+ - dest = source + 1
505
+ !*/
506
+
507
+ void decrement (
508
+ const data_record* source,
509
+ data_record* dest
510
+ ) const;
511
+ /*!
512
+ requires
513
+ source != 0
514
+ ensuers
515
+ dest = source - 1
516
+ !*/
517
+
518
+ // member data
519
+ const uint32 slack;
520
+ data_record* data;
521
+
522
+
523
+
524
+ };
525
+
526
+ inline void swap (
527
+ bigint_kernel_2& a,
528
+ bigint_kernel_2& b
529
+ ) { a.swap(b); }
530
+
531
+ inline void serialize (
532
+ const bigint_kernel_2& item,
533
+ std::ostream& out
534
+ )
535
+ {
536
+ std::ios::fmtflags oldflags = out.flags();
537
+ out << item << ' ';
538
+ out.flags(oldflags);
539
+ if (!out) throw serialization_error("Error serializing object of type bigint_kernel_c");
540
+ }
541
+
542
+ inline void deserialize (
543
+ bigint_kernel_2& item,
544
+ std::istream& in
545
+ )
546
+ {
547
+ std::ios::fmtflags oldflags = in.flags();
548
+ in >> item;
549
+ in.flags(oldflags);
550
+ if (in.get() != ' ')
551
+ {
552
+ item = 0;
553
+ throw serialization_error("Error deserializing object of type bigint_kernel_c");
554
+ }
555
+ }
556
+
557
+ inline bool operator> (const bigint_kernel_2& a, const bigint_kernel_2& b) { return b < a; }
558
+ inline bool operator!= (const bigint_kernel_2& a, const bigint_kernel_2& b) { return !(a == b); }
559
+ inline bool operator<= (const bigint_kernel_2& a, const bigint_kernel_2& b) { return !(b < a); }
560
+ inline bool operator>= (const bigint_kernel_2& a, const bigint_kernel_2& b) { return !(a < b); }
561
+
562
+ }
563
+
564
+ #ifdef NO_MAKEFILE
565
+ #include "bigint_kernel_2.cpp"
566
+ #endif
567
+
568
+ #endif // DLIB_BIGINT_KERNEl_2_
569
+
dlibs/dlib/bigint/bigint_kernel_abstract.h ADDED
@@ -0,0 +1,670 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (C) 2003 Davis E. King ([email protected])
2
+ // License: Boost Software License See LICENSE.txt for the full license.
3
+ #undef DLIB_BIGINT_KERNEl_ABSTRACT_
4
+ #ifdef DLIB_BIGINT_KERNEl_ABSTRACT_
5
+
6
+ #include <iosfwd>
7
+ #include "../algs.h"
8
+ #include "../serialize.h"
9
+ #include "../uintn.h"
10
+
11
+ namespace dlib
12
+ {
13
+
14
+ class bigint
15
+ {
16
+ /*!
17
+ INITIAL VALUE
18
+ *this == 0
19
+
20
+ WHAT THIS OBJECT REPRESENTS
21
+ This object represents an arbitrary precision unsigned integer
22
+
23
+ the following operators are supported:
24
+ operator +
25
+ operator +=
26
+ operator -
27
+ operator -=
28
+ operator *
29
+ operator *=
30
+ operator /
31
+ operator /=
32
+ operator %
33
+ operator %=
34
+ operator ==
35
+ operator <
36
+ operator =
37
+ operator << (for writing to ostreams)
38
+ operator >> (for reading from istreams)
39
+ operator++ // pre increment
40
+ operator++(int) // post increment
41
+ operator-- // pre decrement
42
+ operator--(int) // post decrement
43
+
44
+
45
+ the other comparison operators(>, !=, <=, and >=) are
46
+ available and come from the templates in dlib::relational_operators
47
+
48
+ THREAD SAFETY
49
+ bigint may be reference counted so it is very unthread safe.
50
+ use with care in a multithreaded program
51
+
52
+ !*/
53
+
54
+ public:
55
+
56
+ bigint (
57
+ );
58
+ /*!
59
+ ensures
60
+ - #*this is properly initialized
61
+ throws
62
+ - std::bad_alloc
63
+ if this is thrown the bigint will be unusable but
64
+ will not leak memory
65
+ !*/
66
+
67
+ bigint (
68
+ uint32 value
69
+ );
70
+ /*!
71
+ requires
72
+ - value <= (2^32)-1
73
+ ensures
74
+ - #*this is properly initialized
75
+ - #*this == value
76
+ throws
77
+ - std::bad_alloc
78
+ if this is thrown the bigint will be unusable but
79
+ will not leak memory
80
+ !*/
81
+
82
+ bigint (
83
+ const bigint& item
84
+ );
85
+ /*!
86
+ ensures
87
+ - #*this is properly initialized
88
+ - #*this == value
89
+ throws
90
+ - std::bad_alloc
91
+ if this is thrown the bigint will be unusable but
92
+ will not leak memory
93
+ !*/
94
+
95
+ virtual ~bigint (
96
+ );
97
+ /*!
98
+ ensures
99
+ - all resources associated with #*this have been released
100
+ !*/
101
+
102
+ const bigint operator+ (
103
+ const bigint& rhs
104
+ ) const;
105
+ /*!
106
+ ensures
107
+ - returns the result of adding rhs to *this
108
+ throws
109
+ - std::bad_alloc
110
+ if this function throws then it has no effect
111
+ !*/
112
+
113
+ bigint& operator+= (
114
+ const bigint& rhs
115
+ );
116
+ /*!
117
+ ensures
118
+ - #*this == *this + rhs
119
+ - returns #*this
120
+ throws
121
+ - std::bad_alloc
122
+ if this function throws then it has no effect
123
+ !*/
124
+
125
+ const bigint operator- (
126
+ const bigint& rhs
127
+ ) const;
128
+ /*!
129
+ requires
130
+ - *this >= rhs
131
+ ensures
132
+ - returns the result of subtracting rhs from *this
133
+ throws
134
+ - std::bad_alloc
135
+ if this function throws then it has no effect
136
+ !*/
137
+
138
+ bigint& operator-= (
139
+ const bigint& rhs
140
+ );
141
+ /*!
142
+ requires
143
+ - *this >= rhs
144
+ ensures
145
+ - #*this == *this - rhs
146
+ - returns #*this
147
+ throws
148
+ - std::bad_alloc
149
+ if this function throws then it has no effect
150
+ !*/
151
+
152
+ const bigint operator* (
153
+ const bigint& rhs
154
+ ) const;
155
+ /*!
156
+ ensures
157
+ - returns the result of multiplying *this and rhs
158
+ throws
159
+ - std::bad_alloc
160
+ if this function throws then it has no effect
161
+ !*/
162
+
163
+ bigint& operator*= (
164
+ const bigint& rhs
165
+ );
166
+ /*!
167
+ ensures
168
+ - #*this == *this * rhs
169
+ - returns #*this
170
+ throws
171
+ - std::bad_alloc
172
+ if this function throws then it has no effect
173
+ !*/
174
+
175
+ const bigint operator/ (
176
+ const bigint& rhs
177
+ ) const;
178
+ /*!
179
+ requires
180
+ - rhs != 0
181
+ ensures
182
+ - returns the result of dividing *this by rhs
183
+ throws
184
+ - std::bad_alloc
185
+ if this function throws then it has no effect
186
+ !*/
187
+
188
+ bigint& operator/= (
189
+ const bigint& rhs
190
+ );
191
+ /*!
192
+ requires
193
+ - rhs != 0
194
+ ensures
195
+ - #*this == *this / rhs
196
+ - returns #*this
197
+ throws
198
+ - std::bad_alloc
199
+ if this function throws then it has no effect
200
+ !*/
201
+
202
+ const bigint operator% (
203
+ const bigint& rhs
204
+ ) const;
205
+ /*!
206
+ requires
207
+ - rhs != 0
208
+ ensures
209
+ - returns the result of *this mod rhs
210
+ throws
211
+ - std::bad_alloc
212
+ if this function throws then it has no effect
213
+ !*/
214
+
215
+ bigint& operator%= (
216
+ const bigint& rhs
217
+ );
218
+ /*!
219
+ requires
220
+ - rhs != 0
221
+ ensures
222
+ - #*this == *this % rhs
223
+ - returns #*this
224
+ throws
225
+ - std::bad_alloc
226
+ if this function throws then it has no effect
227
+ !*/
228
+
229
+ bool operator < (
230
+ const bigint& rhs
231
+ ) const;
232
+ /*!
233
+ ensures
234
+ - returns true if *this is less than rhs
235
+ - returns false otherwise
236
+ !*/
237
+
238
+ bool operator == (
239
+ const bigint& rhs
240
+ ) const;
241
+ /*!
242
+ ensures
243
+ - returns true if *this and rhs represent the same number
244
+ - returns false otherwise
245
+ !*/
246
+
247
+ bigint& operator= (
248
+ const bigint& rhs
249
+ );
250
+ /*!
251
+ ensures
252
+ - #*this == rhs
253
+ throws
254
+ - std::bad_alloc
255
+ if this function throws then it has no effect
256
+ !*/
257
+
258
+
259
+ friend std::ostream& operator<< (
260
+ std::ostream& out,
261
+ const bigint& rhs
262
+ );
263
+ /*!
264
+ ensures
265
+ - the number in *this has been written to #out as a base ten number
266
+ throws
267
+ - std::bad_alloc
268
+ if this function throws then it has no effect (nothing
269
+ is written to out)
270
+ !*/
271
+
272
+ friend std::istream& operator>> (
273
+ std::istream& in,
274
+ bigint& rhs
275
+ );
276
+ /*!
277
+ ensures
278
+ - reads a number from in and puts it into #*this
279
+ - if (there is no positive base ten number on the input stream ) then
280
+ - #in.fail() == true
281
+ throws
282
+ - std::bad_alloc
283
+ if this function throws the value in rhs is undefined and some
284
+ characters may have been read from in. rhs is still usable though,
285
+ its value is just unknown.
286
+ !*/
287
+
288
+
289
+ bigint& operator++ (
290
+ );
291
+ /*!
292
+ ensures
293
+ - #*this == *this + 1
294
+ - returns #*this
295
+ throws
296
+ - std::bad_alloc
297
+ if this function throws then it has no effect
298
+ !*/
299
+
300
+ const bigint operator++ (
301
+ int
302
+ );
303
+ /*!
304
+ ensures
305
+ - #*this == *this + 1
306
+ - returns *this
307
+ throws
308
+ - std::bad_alloc
309
+ if this function throws then it has no effect
310
+ !*/
311
+
312
+ bigint& operator-- (
313
+ );
314
+ /*!
315
+ requires
316
+ - *this != 0
317
+ ensures
318
+ - #*this == *this - 1
319
+ - returns #*this
320
+ throws
321
+ - std::bad_alloc
322
+ if this function throws then it has no effect
323
+ !*/
324
+
325
+ const bigint operator-- (
326
+ int
327
+ );
328
+ /*!
329
+ requires
330
+ - *this != 0
331
+ ensures
332
+ - #*this == *this - 1
333
+ - returns *this
334
+ throws
335
+ - std::bad_alloc
336
+ if this function throws then it has no effect
337
+ !*/
338
+
339
+ void swap (
340
+ bigint& item
341
+ );
342
+ /*!
343
+ ensures
344
+ - swaps *this and item
345
+ !*/
346
+
347
+
348
+ // ------------------------------------------------------------------
349
+ // ---- The following functions are identical to the above -----
350
+ // ---- but take uint16 as one of their arguments. They ---
351
+ // ---- exist only to allow for a more efficient implementation ---
352
+ // ------------------------------------------------------------------
353
+
354
+
355
+ friend const bigint operator+ (
356
+ uint16 lhs,
357
+ const bigint& rhs
358
+ );
359
+ /*!
360
+ requires
361
+ - lhs <= 65535
362
+ ensures
363
+ - returns the result of adding rhs to lhs
364
+ throws
365
+ - std::bad_alloc
366
+ if this function throws then it has no effect
367
+ !*/
368
+
369
+ friend const bigint operator+ (
370
+ const bigint& lhs,
371
+ uint16 rhs
372
+ );
373
+ /*!
374
+ requires
375
+ - rhs <= 65535
376
+ ensures
377
+ - returns the result of adding rhs to lhs
378
+ throws
379
+ - std::bad_alloc
380
+ if this function throws then it has no effect
381
+ !*/
382
+
383
+ bigint& operator+= (
384
+ uint16 rhs
385
+ );
386
+ /*!
387
+ requires
388
+ - rhs <= 65535
389
+ ensures
390
+ - #*this == *this + rhs
391
+ - returns #this
392
+ throws
393
+ - std::bad_alloc
394
+ if this function throws then it has no effect
395
+ !*/
396
+
397
+ friend const bigint operator- (
398
+ uint16 lhs,
399
+ const bigint& rhs
400
+ );
401
+ /*!
402
+ requires
403
+ - lhs >= rhs
404
+ - lhs <= 65535
405
+ ensures
406
+ - returns the result of subtracting rhs from lhs
407
+ throws
408
+ - std::bad_alloc
409
+ if this function throws then it has no effect
410
+ !*/
411
+
412
+ friend const bigint operator- (
413
+ const bigint& lhs,
414
+ uint16 rhs
415
+ );
416
+ /*!
417
+ requires
418
+ - lhs >= rhs
419
+ - rhs <= 65535
420
+ ensures
421
+ - returns the result of subtracting rhs from lhs
422
+ throws
423
+ - std::bad_alloc
424
+ if this function throws then it has no effect
425
+ !*/
426
+
427
+ bigint& operator-= (
428
+ uint16 rhs
429
+ );
430
+ /*!
431
+ requires
432
+ - *this >= rhs
433
+ - rhs <= 65535
434
+ ensures
435
+ - #*this == *this - rhs
436
+ - returns #*this
437
+ throws
438
+ - std::bad_alloc
439
+ if this function throws then it has no effect
440
+ !*/
441
+
442
+ friend const bigint operator* (
443
+ uint16 lhs,
444
+ const bigint& rhs
445
+ );
446
+ /*!
447
+ requires
448
+ - lhs <= 65535
449
+ ensures
450
+ - returns the result of multiplying lhs and rhs
451
+ throws
452
+ - std::bad_alloc
453
+ if this function throws then it has no effect
454
+ !*/
455
+
456
+ friend const bigint operator* (
457
+ const bigint& lhs,
458
+ uint16 rhs
459
+ );
460
+ /*!
461
+ requires
462
+ - rhs <= 65535
463
+ ensures
464
+ - returns the result of multiplying lhs and rhs
465
+ throws
466
+ - std::bad_alloc
467
+ if this function throws then it has no effect
468
+ !*/
469
+
470
+ bigint& operator*= (
471
+ uint16 rhs
472
+ );
473
+ /*!
474
+ requires
475
+ - rhs <= 65535
476
+ ensures
477
+ - #*this == *this * rhs
478
+ - returns #*this
479
+ throws
480
+ - std::bad_alloc
481
+ if this function throws then it has no effect
482
+ !*/
483
+
484
+ friend const bigint operator/ (
485
+ uint16 lhs,
486
+ const bigint& rhs
487
+ );
488
+ /*!
489
+ requires
490
+ - rhs != 0
491
+ - lhs <= 65535
492
+ ensures
493
+ - returns the result of dividing lhs by rhs
494
+ throws
495
+ - std::bad_alloc
496
+ if this function throws then it has no effect
497
+ !*/
498
+
499
+ friend const bigint operator/ (
500
+ const bigint& lhs,
501
+ uint16 rhs
502
+ );
503
+ /*!
504
+ requires
505
+ - rhs != 0
506
+ - rhs <= 65535
507
+ ensures
508
+ - returns the result of dividing lhs by rhs
509
+ throws
510
+ - std::bad_alloc
511
+ if this function throws then it has no effect
512
+ !*/
513
+
514
+ bigint& operator/= (
515
+ uint16 rhs
516
+ );
517
+ /*!
518
+ requires
519
+ - rhs != 0
520
+ - rhs <= 65535
521
+ ensures
522
+ - #*this == *this / rhs
523
+ - returns #*this
524
+ throws
525
+ - std::bad_alloc
526
+ if this function throws then it has no effect
527
+ !*/
528
+
529
+ friend const bigint operator% (
530
+ uint16 lhs,
531
+ const bigint& rhs
532
+ );
533
+ /*!
534
+ requires
535
+ - rhs != 0
536
+ - lhs <= 65535
537
+ ensures
538
+ - returns the result of lhs mod rhs
539
+ throws
540
+ - std::bad_alloc
541
+ if this function throws then it has no effect
542
+ !*/
543
+
544
+ friend const bigint operator% (
545
+ const bigint& lhs,
546
+ uint16 rhs
547
+ );
548
+ /*!
549
+ requires
550
+ - rhs != 0
551
+ - rhs <= 65535
552
+ ensures
553
+ - returns the result of lhs mod rhs
554
+ throws
555
+ - std::bad_alloc
556
+ if this function throws then it has no effect
557
+ !*/
558
+
559
+ bigint& operator%= (
560
+ uint16 rhs
561
+ );
562
+ /*!
563
+ requires
564
+ - rhs != 0
565
+ - rhs <= 65535
566
+ ensures
567
+ - #*this == *this % rhs
568
+ - returns #*this
569
+ throws
570
+ - std::bad_alloc
571
+ if this function throws then it has no effect
572
+ !*/
573
+
574
+
575
+ friend bool operator < (
576
+ uint16 lhs,
577
+ const bigint& rhs
578
+ );
579
+ /*!
580
+ requires
581
+ - lhs <= 65535
582
+ ensures
583
+ - returns true if lhs is less than rhs
584
+ - returns false otherwise
585
+ !*/
586
+
587
+ friend bool operator < (
588
+ const bigint& lhs,
589
+ uint16 rhs
590
+ );
591
+ /*!
592
+ requires
593
+ - rhs <= 65535
594
+ ensures
595
+ - returns true if lhs is less than rhs
596
+ - returns false otherwise
597
+ !*/
598
+
599
+ friend bool operator == (
600
+ const bigint& lhs,
601
+ uint16 rhs
602
+ );
603
+ /*!
604
+ requires
605
+ - rhs <= 65535
606
+ ensures
607
+ - returns true if lhs and rhs represent the same number
608
+ - returns false otherwise
609
+ !*/
610
+
611
+ friend bool operator == (
612
+ uint16 lhs,
613
+ const bigint& rhs
614
+ );
615
+ /*!
616
+ requires
617
+ - lhs <= 65535
618
+ ensures
619
+ - returns true if lhs and rhs represent the same number
620
+ - returns false otherwise
621
+ !*/
622
+
623
+ bigint& operator= (
624
+ uint16 rhs
625
+ );
626
+ /*!
627
+ requires
628
+ - rhs <= 65535
629
+ ensures
630
+ - #*this == rhs
631
+ - returns #*this
632
+ throws
633
+ - std::bad_alloc
634
+ if this function throws then it has no effect
635
+ !*/
636
+
637
+ };
638
+
639
+ inline void swap (
640
+ bigint& a,
641
+ bigint& b
642
+ ) { a.swap(b); }
643
+ /*!
644
+ provides a global swap function
645
+ !*/
646
+
647
+ void serialize (
648
+ const bigint& item,
649
+ std::istream& in
650
+ );
651
+ /*!
652
+ provides serialization support
653
+ !*/
654
+
655
+ void deserialize (
656
+ bigint& item,
657
+ std::istream& in
658
+ );
659
+ /*!
660
+ provides deserialization support
661
+ !*/
662
+
663
+ inline bool operator> (const bigint& a, const bigint& b) { return b < a; }
664
+ inline bool operator!= (const bigint& a, const bigint& b) { return !(a == b); }
665
+ inline bool operator<= (const bigint& a, const bigint& b) { return !(b < a); }
666
+ inline bool operator>= (const bigint& a, const bigint& b) { return !(a < b); }
667
+ }
668
+
669
+ #endif // DLIB_BIGINT_KERNEl_ABSTRACT_
670
+
dlibs/dlib/bigint/bigint_kernel_c.h ADDED
@@ -0,0 +1,1140 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (C) 2003 Davis E. King ([email protected])
2
+ // License: Boost Software License See LICENSE.txt for the full license.
3
+ #ifndef DLIB_BIGINT_KERNEl_C_
4
+ #define DLIB_BIGINT_KERNEl_C_
5
+
6
+ #include "bigint_kernel_abstract.h"
7
+ #include "../algs.h"
8
+ #include "../assert.h"
9
+ #include <iostream>
10
+
11
+ namespace dlib
12
+ {
13
+
14
+ // ----------------------------------------------------------------------------------------
15
+
16
+ template <
17
+ typename bigint_base
18
+ >
19
+ class bigint_kernel_c
20
+ {
21
+ bigint_base data;
22
+
23
+ explicit bigint_kernel_c (
24
+ const bigint_base& item
25
+ ) : data(item) {}
26
+
27
+ public:
28
+
29
+
30
+ bigint_kernel_c (
31
+ );
32
+
33
+ bigint_kernel_c (
34
+ uint32 value
35
+ );
36
+
37
+ bigint_kernel_c (
38
+ const bigint_kernel_c<bigint_base>& item
39
+ );
40
+
41
+ ~bigint_kernel_c (
42
+ );
43
+
44
+ const bigint_kernel_c<bigint_base> operator+ (
45
+ const bigint_kernel_c<bigint_base>& rhs
46
+ ) const;
47
+
48
+ bigint_kernel_c<bigint_base>& operator+= (
49
+ const bigint_kernel_c<bigint_base>& rhs
50
+ );
51
+
52
+ const bigint_kernel_c<bigint_base> operator- (
53
+ const bigint_kernel_c<bigint_base>& rhs
54
+ ) const;
55
+ bigint_kernel_c<bigint_base>& operator-= (
56
+ const bigint_kernel_c<bigint_base>& rhs
57
+ );
58
+
59
+ const bigint_kernel_c<bigint_base> operator* (
60
+ const bigint_kernel_c<bigint_base>& rhs
61
+ ) const;
62
+
63
+ bigint_kernel_c<bigint_base>& operator*= (
64
+ const bigint_kernel_c<bigint_base>& rhs
65
+ );
66
+
67
+ const bigint_kernel_c<bigint_base> operator/ (
68
+ const bigint_kernel_c<bigint_base>& rhs
69
+ ) const;
70
+
71
+ bigint_kernel_c<bigint_base>& operator/= (
72
+ const bigint_kernel_c<bigint_base>& rhs
73
+ );
74
+
75
+ const bigint_kernel_c<bigint_base> operator% (
76
+ const bigint_kernel_c<bigint_base>& rhs
77
+ ) const;
78
+
79
+ bigint_kernel_c<bigint_base>& operator%= (
80
+ const bigint_kernel_c<bigint_base>& rhs
81
+ );
82
+
83
+ bool operator < (
84
+ const bigint_kernel_c<bigint_base>& rhs
85
+ ) const;
86
+
87
+ bool operator == (
88
+ const bigint_kernel_c<bigint_base>& rhs
89
+ ) const;
90
+
91
+ bigint_kernel_c<bigint_base>& operator= (
92
+ const bigint_kernel_c<bigint_base>& rhs
93
+ );
94
+
95
+ template <typename T>
96
+ friend std::ostream& operator<< (
97
+ std::ostream& out,
98
+ const bigint_kernel_c<T>& rhs
99
+ );
100
+
101
+ template <typename T>
102
+ friend std::istream& operator>> (
103
+ std::istream& in,
104
+ bigint_kernel_c<T>& rhs
105
+ );
106
+
107
+ bigint_kernel_c<bigint_base>& operator++ (
108
+ );
109
+
110
+ const bigint_kernel_c<bigint_base> operator++ (
111
+ int
112
+ );
113
+
114
+ bigint_kernel_c<bigint_base>& operator-- (
115
+ );
116
+
117
+ const bigint_kernel_c<bigint_base> operator-- (
118
+ int
119
+ );
120
+
121
+ template <typename T>
122
+ friend const bigint_kernel_c<T> operator+ (
123
+ uint16 lhs,
124
+ const bigint_kernel_c<T>& rhs
125
+ );
126
+
127
+ template <typename T>
128
+ friend const bigint_kernel_c<T> operator+ (
129
+ const bigint_kernel_c<T>& lhs,
130
+ uint16 rhs
131
+ );
132
+
133
+ bigint_kernel_c<bigint_base>& operator+= (
134
+ uint16 rhs
135
+ );
136
+
137
+ template <typename T>
138
+ friend const bigint_kernel_c<T> operator- (
139
+ uint16 lhs,
140
+ const bigint_kernel_c<T>& rhs
141
+ );
142
+
143
+ template <typename T>
144
+ friend const bigint_kernel_c<T> operator- (
145
+ const bigint_kernel_c<T>& lhs,
146
+ uint16 rhs
147
+ );
148
+
149
+ bigint_kernel_c<bigint_base>& operator-= (
150
+ uint16 rhs
151
+ );
152
+
153
+ template <typename T>
154
+ friend const bigint_kernel_c<T> operator* (
155
+ uint16 lhs,
156
+ const bigint_kernel_c<T>& rhs
157
+ );
158
+
159
+ template <typename T>
160
+ friend const bigint_kernel_c<T> operator* (
161
+ const bigint_kernel_c<T>& lhs,
162
+ uint16 rhs
163
+ );
164
+
165
+ bigint_kernel_c<bigint_base>& operator*= (
166
+ uint16 rhs
167
+ );
168
+
169
+ template <typename T>
170
+ friend const bigint_kernel_c<T> operator/ (
171
+ uint16 lhs,
172
+ const bigint_kernel_c<T>& rhs
173
+ );
174
+
175
+ template <typename T>
176
+ friend const bigint_kernel_c<T> operator/ (
177
+ const bigint_kernel_c<T>& lhs,
178
+ uint16 rhs
179
+ );
180
+
181
+ bigint_kernel_c<bigint_base>& operator/= (
182
+ uint16 rhs
183
+ );
184
+
185
+ template <typename T>
186
+ friend const bigint_kernel_c<T> operator% (
187
+ uint16 lhs,
188
+ const bigint_kernel_c<T>& rhs
189
+ );
190
+
191
+ template <typename T>
192
+ friend const bigint_kernel_c<T> operator% (
193
+ const bigint_kernel_c<T>& lhs,
194
+ uint16 rhs
195
+ );
196
+
197
+ bigint_kernel_c<bigint_base>& operator%= (
198
+ uint16 rhs
199
+ );
200
+
201
+ template <typename T>
202
+ friend bool operator < (
203
+ uint16 lhs,
204
+ const bigint_kernel_c<T>& rhs
205
+ );
206
+
207
+ template <typename T>
208
+ friend bool operator < (
209
+ const bigint_kernel_c<T>& lhs,
210
+ uint16 rhs
211
+ );
212
+
213
+ template <typename T>
214
+ friend bool operator == (
215
+ const bigint_kernel_c<T>& lhs,
216
+ uint16 rhs
217
+ );
218
+
219
+ template <typename T>
220
+ friend bool operator == (
221
+ uint16 lhs,
222
+ const bigint_kernel_c<T>& rhs
223
+ );
224
+
225
+ bigint_kernel_c<bigint_base>& operator= (
226
+ uint16 rhs
227
+ );
228
+
229
+
230
+ void swap (
231
+ bigint_kernel_c<bigint_base>& item
232
+ ) { data.swap(item.data); }
233
+
234
+ };
235
+
236
+ template <
237
+ typename bigint_base
238
+ >
239
+ void swap (
240
+ bigint_kernel_c<bigint_base>& a,
241
+ bigint_kernel_c<bigint_base>& b
242
+ ) { a.swap(b); }
243
+
244
+
245
+ // ----------------------------------------------------------------------------------------
246
+
247
+ template <
248
+ typename bigint_base
249
+ >
250
+ inline void serialize (
251
+ const bigint_kernel_c<bigint_base>& item,
252
+ std::ostream& out
253
+ )
254
+ {
255
+ std::ios::fmtflags oldflags = out.flags();
256
+ out << item << ' ';
257
+ out.flags(oldflags);
258
+ if (!out) throw serialization_error("Error serializing object of type bigint_kernel_c");
259
+ }
260
+
261
+ template <
262
+ typename bigint_base
263
+ >
264
+ inline void deserialize (
265
+ bigint_kernel_c<bigint_base>& item,
266
+ std::istream& in
267
+ )
268
+ {
269
+ std::ios::fmtflags oldflags = in.flags();
270
+ in >> item;
271
+ in.flags(oldflags);
272
+ if (in.get() != ' ')
273
+ {
274
+ item = 0;
275
+ throw serialization_error("Error deserializing object of type bigint_kernel_c");
276
+ }
277
+ }
278
+
279
+ // ----------------------------------------------------------------------------------------
280
+ // ----------------------------------------------------------------------------------------
281
+ // member function definitions
282
+ // ----------------------------------------------------------------------------------------
283
+ // ----------------------------------------------------------------------------------------
284
+
285
+ template <
286
+ typename bigint_base
287
+ >
288
+ bigint_kernel_c<bigint_base>::
289
+ bigint_kernel_c (
290
+ )
291
+ {}
292
+
293
+ // ----------------------------------------------------------------------------------------
294
+
295
+ template <
296
+ typename bigint_base
297
+ >
298
+ bigint_kernel_c<bigint_base>::
299
+ bigint_kernel_c (
300
+ uint32 value
301
+ ) :
302
+ data(value)
303
+ {
304
+ // make sure requires clause is not broken
305
+ DLIB_CASSERT( value <= 0xFFFFFFFF ,
306
+ "\tbigint::bigint(uint16)"
307
+ << "\n\t value must be <= (2^32)-1"
308
+ << "\n\tthis: " << this
309
+ << "\n\tvalue: " << value
310
+ );
311
+ }
312
+
313
+ // ----------------------------------------------------------------------------------------
314
+
315
+ template <
316
+ typename bigint_base
317
+ >
318
+ bigint_kernel_c<bigint_base>::
319
+ bigint_kernel_c (
320
+ const bigint_kernel_c<bigint_base>& item
321
+ ) :
322
+ data(item.data)
323
+ {}
324
+
325
+ // ----------------------------------------------------------------------------------------
326
+
327
+ template <
328
+ typename bigint_base
329
+ >
330
+ bigint_kernel_c<bigint_base>::
331
+ ~bigint_kernel_c (
332
+ )
333
+ {}
334
+
335
+ // ----------------------------------------------------------------------------------------
336
+
337
+ template <
338
+ typename bigint_base
339
+ >
340
+ const bigint_kernel_c<bigint_base> bigint_kernel_c<bigint_base>::
341
+ operator+ (
342
+ const bigint_kernel_c<bigint_base>& rhs
343
+ ) const
344
+ {
345
+ return bigint_kernel_c<bigint_base>(data + rhs.data);
346
+ }
347
+
348
+ // ----------------------------------------------------------------------------------------
349
+
350
+ template <
351
+ typename bigint_base
352
+ >
353
+ bigint_kernel_c<bigint_base>& bigint_kernel_c<bigint_base>::
354
+ operator+= (
355
+ const bigint_kernel_c<bigint_base>& rhs
356
+ )
357
+ {
358
+ data += rhs.data;
359
+ return *this;
360
+ }
361
+
362
+ // ----------------------------------------------------------------------------------------
363
+
364
+ template <
365
+ typename bigint_base
366
+ >
367
+ const bigint_kernel_c<bigint_base> bigint_kernel_c<bigint_base>::
368
+ operator- (
369
+ const bigint_kernel_c<bigint_base>& rhs
370
+ ) const
371
+ {
372
+ // make sure requires clause is not broken
373
+ DLIB_CASSERT( !(*this < rhs),
374
+ "\tconst bigint bigint::operator-(const bigint&)"
375
+ << "\n\t *this should not be less than rhs"
376
+ << "\n\tthis: " << this
377
+ << "\n\t*this: " << *this
378
+ << "\n\trhs: " << rhs
379
+ );
380
+
381
+ // call the real function
382
+ return bigint_kernel_c<bigint_base>(data-rhs.data);
383
+ }
384
+
385
+ // ----------------------------------------------------------------------------------------
386
+
387
+ template <
388
+ typename bigint_base
389
+ >
390
+ bigint_kernel_c<bigint_base>& bigint_kernel_c<bigint_base>::
391
+ operator-= (
392
+ const bigint_kernel_c<bigint_base>& rhs
393
+ )
394
+ {
395
+ // make sure requires clause is not broken
396
+ DLIB_CASSERT( !(*this < rhs),
397
+ "\tbigint& bigint::operator-=(const bigint&)"
398
+ << "\n\t *this should not be less than rhs"
399
+ << "\n\tthis: " << this
400
+ << "\n\t*this: " << *this
401
+ << "\n\trhs: " << rhs
402
+ );
403
+
404
+ // call the real function
405
+ data -= rhs.data;
406
+ return *this;
407
+ }
408
+
409
+ // ----------------------------------------------------------------------------------------
410
+
411
+ template <
412
+ typename bigint_base
413
+ >
414
+ const bigint_kernel_c<bigint_base> bigint_kernel_c<bigint_base>::
415
+ operator* (
416
+ const bigint_kernel_c<bigint_base>& rhs
417
+ ) const
418
+ {
419
+ return bigint_kernel_c<bigint_base>(data * rhs.data );
420
+ }
421
+
422
+ // ----------------------------------------------------------------------------------------
423
+
424
+ template <
425
+ typename bigint_base
426
+ >
427
+ bigint_kernel_c<bigint_base>& bigint_kernel_c<bigint_base>::
428
+ operator*= (
429
+ const bigint_kernel_c<bigint_base>& rhs
430
+ )
431
+ {
432
+ data *= rhs.data;
433
+ return *this;
434
+ }
435
+
436
+ // ----------------------------------------------------------------------------------------
437
+
438
+ template <
439
+ typename bigint_base
440
+ >
441
+ const bigint_kernel_c<bigint_base> bigint_kernel_c<bigint_base>::
442
+ operator/ (
443
+ const bigint_kernel_c<bigint_base>& rhs
444
+ ) const
445
+ {
446
+ //make sure requires clause is not broken
447
+ DLIB_CASSERT( !(rhs == 0),
448
+ "\tconst bigint bigint::operator/(const bigint&)"
449
+ << "\n\t can't divide by zero"
450
+ << "\n\tthis: " << this
451
+ );
452
+
453
+ // call the real function
454
+ return bigint_kernel_c<bigint_base>(data/rhs.data);
455
+ }
456
+
457
+ // ----------------------------------------------------------------------------------------
458
+
459
+ template <
460
+ typename bigint_base
461
+ >
462
+ bigint_kernel_c<bigint_base>& bigint_kernel_c<bigint_base>::
463
+ operator/= (
464
+ const bigint_kernel_c<bigint_base>& rhs
465
+ )
466
+ {
467
+ // make sure requires clause is not broken
468
+ DLIB_CASSERT( !(rhs == 0),
469
+ "\tbigint& bigint::operator/=(const bigint&)"
470
+ << "\n\t can't divide by zero"
471
+ << "\n\tthis: " << this
472
+ );
473
+
474
+ // call the real function
475
+ data /= rhs.data;
476
+ return *this;
477
+ }
478
+
479
+ // ----------------------------------------------------------------------------------------
480
+
481
+ template <
482
+ typename bigint_base
483
+ >
484
+ const bigint_kernel_c<bigint_base> bigint_kernel_c<bigint_base>::
485
+ operator% (
486
+ const bigint_kernel_c<bigint_base>& rhs
487
+ ) const
488
+ {
489
+ // make sure requires clause is not broken
490
+ DLIB_CASSERT( !(rhs == 0),
491
+ "\tconst bigint bigint::operator%(const bigint&)"
492
+ << "\n\t can't divide by zero"
493
+ << "\n\tthis: " << this
494
+ );
495
+
496
+ // call the real function
497
+ return bigint_kernel_c<bigint_base>(data%rhs.data);
498
+ }
499
+
500
+ // ----------------------------------------------------------------------------------------
501
+
502
+ template <
503
+ typename bigint_base
504
+ >
505
+ bigint_kernel_c<bigint_base>& bigint_kernel_c<bigint_base>::
506
+ operator%= (
507
+ const bigint_kernel_c<bigint_base>& rhs
508
+ )
509
+ {
510
+ // make sure requires clause is not broken
511
+ DLIB_CASSERT( !(rhs == 0),
512
+ "\tbigint& bigint::operator%=(const bigint&)"
513
+ << "\n\t can't divide by zero"
514
+ << "\n\tthis: " << this
515
+ );
516
+
517
+ // call the real function
518
+ data %= rhs.data;
519
+ return *this;
520
+ }
521
+
522
+ // ----------------------------------------------------------------------------------------
523
+
524
+ template <
525
+ typename bigint_base
526
+ >
527
+ bool bigint_kernel_c<bigint_base>::
528
+ operator < (
529
+ const bigint_kernel_c<bigint_base>& rhs
530
+ ) const
531
+ {
532
+ return data < rhs.data;
533
+ }
534
+
535
+ // ----------------------------------------------------------------------------------------
536
+
537
+ template <
538
+ typename bigint_base
539
+ >
540
+ bool bigint_kernel_c<bigint_base>::
541
+ operator == (
542
+ const bigint_kernel_c<bigint_base>& rhs
543
+ ) const
544
+ {
545
+ return data == rhs.data;
546
+ }
547
+
548
+ // ----------------------------------------------------------------------------------------
549
+
550
+ template <
551
+ typename bigint_base
552
+ >
553
+ bigint_kernel_c<bigint_base>& bigint_kernel_c<bigint_base>::
554
+ operator= (
555
+ const bigint_kernel_c<bigint_base>& rhs
556
+ )
557
+ {
558
+ data = rhs.data;
559
+ return *this;
560
+ }
561
+
562
+ // ----------------------------------------------------------------------------------------
563
+
564
+ template <
565
+ typename bigint_base
566
+ >
567
+ std::ostream& operator<< (
568
+ std::ostream& out,
569
+ const bigint_kernel_c<bigint_base>& rhs
570
+ )
571
+ {
572
+ out << rhs.data;
573
+ return out;
574
+ }
575
+
576
+ // ----------------------------------------------------------------------------------------
577
+
578
+ template <
579
+ typename bigint_base
580
+ >
581
+ std::istream& operator>> (
582
+ std::istream& in,
583
+ bigint_kernel_c<bigint_base>& rhs
584
+ )
585
+ {
586
+ in >> rhs.data;
587
+ return in;
588
+ }
589
+
590
+ // ----------------------------------------------------------------------------------------
591
+
592
+ template <
593
+ typename bigint_base
594
+ >
595
+ bigint_kernel_c<bigint_base>& bigint_kernel_c<bigint_base>::
596
+ operator++ (
597
+ )
598
+ {
599
+ ++data;
600
+ return *this;
601
+ }
602
+
603
+ // ----------------------------------------------------------------------------------------
604
+
605
+ template <
606
+ typename bigint_base
607
+ >
608
+ const bigint_kernel_c<bigint_base> bigint_kernel_c<bigint_base>::
609
+ operator++ (
610
+ int
611
+ )
612
+ {
613
+ return bigint_kernel_c<bigint_base>(data++);
614
+ }
615
+
616
+ // ----------------------------------------------------------------------------------------
617
+
618
+ template <
619
+ typename bigint_base
620
+ >
621
+ bigint_kernel_c<bigint_base>& bigint_kernel_c<bigint_base>::
622
+ operator-- (
623
+ )
624
+ {
625
+ // make sure requires clause is not broken
626
+ DLIB_CASSERT( !(*this == 0),
627
+ "\tbigint& bigint::operator--()"
628
+ << "\n\t *this to subtract from *this it must not be zero to begin with"
629
+ << "\n\tthis: " << this
630
+ );
631
+
632
+ // call the real function
633
+ --data;
634
+ return *this;
635
+ }
636
+
637
+ // ----------------------------------------------------------------------------------------
638
+
639
+ template <
640
+ typename bigint_base
641
+ >
642
+ const bigint_kernel_c<bigint_base> bigint_kernel_c<bigint_base>::
643
+ operator-- (
644
+ int
645
+ )
646
+ {
647
+ // make sure requires clause is not broken
648
+ DLIB_CASSERT( !(*this == 0),
649
+ "\tconst bigint bigint::operator--(int)"
650
+ << "\n\t *this to subtract from *this it must not be zero to begin with"
651
+ << "\n\tthis: " << this
652
+ );
653
+
654
+ // call the real function
655
+ return bigint_kernel_c<bigint_base>(data--);
656
+ }
657
+
658
+ // ----------------------------------------------------------------------------------------
659
+
660
+ template <
661
+ typename bigint_base
662
+ >
663
+ const bigint_kernel_c<bigint_base> operator+ (
664
+ uint16 l,
665
+ const bigint_kernel_c<bigint_base>& rhs
666
+ )
667
+ {
668
+ uint32 lhs = l;
669
+ // make sure requires clause is not broken
670
+ DLIB_CASSERT( lhs <= 65535,
671
+ "\tconst bigint operator+(uint16, const bigint&)"
672
+ << "\n\t lhs must be <= 65535"
673
+ << "\n\trhs: " << rhs
674
+ << "\n\tlhs: " << lhs
675
+ );
676
+
677
+ return bigint_kernel_c<bigint_base>(static_cast<uint16>(lhs)+rhs.data);
678
+ }
679
+
680
+ // ----------------------------------------------------------------------------------------
681
+
682
+ template <
683
+ typename bigint_base
684
+ >
685
+ const bigint_kernel_c<bigint_base> operator+ (
686
+ const bigint_kernel_c<bigint_base>& lhs,
687
+ uint16 r
688
+ )
689
+ {
690
+ uint32 rhs = r;
691
+ // make sure requires clause is not broken
692
+ DLIB_CASSERT( rhs <= 65535,
693
+ "\tconst bigint operator+(const bigint&, uint16)"
694
+ << "\n\t rhs must be <= 65535"
695
+ << "\n\trhs: " << rhs
696
+ << "\n\tlhs: " << lhs
697
+ );
698
+
699
+ return bigint_kernel_c<bigint_base>(lhs.data+static_cast<uint16>(rhs));
700
+ }
701
+
702
+ // ----------------------------------------------------------------------------------------
703
+
704
+ template <
705
+ typename bigint_base
706
+ >
707
+ bigint_kernel_c<bigint_base>& bigint_kernel_c<bigint_base>::
708
+ operator+= (
709
+ uint16 r
710
+ )
711
+ {
712
+ uint32 rhs = r;
713
+ // make sure requires clause is not broken
714
+ DLIB_CASSERT( rhs <= 65535,
715
+ "\tbigint& bigint::operator+=(uint16)"
716
+ << "\n\t rhs must be <= 65535"
717
+ << "\n\tthis: " << this
718
+ << "\n\t*this: " << *this
719
+ << "\n\trhs: " << rhs
720
+ );
721
+
722
+ data += rhs;
723
+ return *this;
724
+ }
725
+
726
+ // ----------------------------------------------------------------------------------------
727
+
728
+ template <
729
+ typename bigint_base
730
+ >
731
+ const bigint_kernel_c<bigint_base> operator- (
732
+ uint16 l,
733
+ const bigint_kernel_c<bigint_base>& rhs
734
+ )
735
+ {
736
+ uint32 lhs = l;
737
+ // make sure requires clause is not broken
738
+ DLIB_CASSERT( !(static_cast<uint16>(lhs) < rhs) && lhs <= 65535,
739
+ "\tconst bigint operator-(uint16,const bigint&)"
740
+ << "\n\t lhs must be greater than or equal to rhs and lhs <= 65535"
741
+ << "\n\tlhs: " << lhs
742
+ << "\n\trhs: " << rhs
743
+ << "\n\t&lhs: " << &lhs
744
+ << "\n\t&rhs: " << &rhs
745
+ );
746
+
747
+ // call the real function
748
+ return bigint_kernel_c<bigint_base>(static_cast<uint16>(lhs)-rhs.data);
749
+ }
750
+
751
+ // ----------------------------------------------------------------------------------------
752
+
753
+ template <
754
+ typename bigint_base
755
+ >
756
+ const bigint_kernel_c<bigint_base> operator- (
757
+ const bigint_kernel_c<bigint_base>& lhs,
758
+ uint16 r
759
+ )
760
+ {
761
+ uint32 rhs = r;
762
+ // make sure requires clause is not broken
763
+ DLIB_CASSERT( !(lhs < static_cast<uint16>(rhs)) && rhs <= 65535,
764
+ "\tconst bigint operator-(const bigint&,uint16)"
765
+ << "\n\t lhs must be greater than or equal to rhs and rhs <= 65535"
766
+ << "\n\tlhs: " << lhs
767
+ << "\n\trhs: " << rhs
768
+ << "\n\t&lhs: " << &lhs
769
+ << "\n\t&rhs: " << &rhs
770
+ );
771
+
772
+ // call the real function
773
+ return bigint_kernel_c<bigint_base>(lhs.data-static_cast<uint16>(rhs));
774
+ }
775
+
776
+ // ----------------------------------------------------------------------------------------
777
+
778
+ template <
779
+ typename bigint_base
780
+ >
781
+ bigint_kernel_c<bigint_base>& bigint_kernel_c<bigint_base>::
782
+ operator-= (
783
+ uint16 r
784
+ )
785
+ {
786
+ uint32 rhs = r;
787
+ // make sure requires clause is not broken
788
+ DLIB_CASSERT( !(*this < static_cast<uint16>(rhs)) && rhs <= 65535,
789
+ "\tbigint& bigint::operator-=(uint16)"
790
+ << "\n\t *this must not be less than rhs and rhs <= 65535"
791
+ << "\n\tthis: " << this
792
+ << "\n\t*this: " << *this
793
+ << "\n\trhs: " << rhs
794
+ );
795
+
796
+ // call the real function
797
+ data -= static_cast<uint16>(rhs);
798
+ return *this;
799
+ }
800
+
801
+ // ----------------------------------------------------------------------------------------
802
+
803
+ template <
804
+ typename bigint_base
805
+ >
806
+ const bigint_kernel_c<bigint_base> operator* (
807
+ uint16 l,
808
+ const bigint_kernel_c<bigint_base>& rhs
809
+ )
810
+ {
811
+ uint32 lhs = l;
812
+ // make sure requires clause is not broken
813
+ DLIB_CASSERT( lhs <= 65535,
814
+ "\tconst bigint operator*(uint16, const bigint&)"
815
+ << "\n\t lhs must be <= 65535"
816
+ << "\n\trhs: " << rhs
817
+ << "\n\tlhs: " << lhs
818
+ );
819
+
820
+ return bigint_kernel_c<bigint_base>(lhs*rhs.data);
821
+ }
822
+
823
+ // ----------------------------------------------------------------------------------------
824
+
825
+ template <
826
+ typename bigint_base
827
+ >
828
+ const bigint_kernel_c<bigint_base> operator* (
829
+ const bigint_kernel_c<bigint_base>& lhs,
830
+ uint16 r
831
+ )
832
+ {
833
+ uint32 rhs = r;
834
+ // make sure requires clause is not broken
835
+ DLIB_CASSERT( rhs <= 65535,
836
+ "\tconst bigint operator*(const bigint&, uint16)"
837
+ << "\n\t rhs must be <= 65535"
838
+ << "\n\trhs: " << rhs
839
+ << "\n\tlhs: " << lhs
840
+ );
841
+
842
+ return bigint_kernel_c<bigint_base>(lhs.data*rhs);
843
+ }
844
+
845
+ // ----------------------------------------------------------------------------------------
846
+
847
+ template <
848
+ typename bigint_base
849
+ >
850
+ bigint_kernel_c<bigint_base>& bigint_kernel_c<bigint_base>::
851
+ operator*= (
852
+ uint16 r
853
+ )
854
+ {
855
+ uint32 rhs = r;
856
+ // make sure requires clause is not broken
857
+ DLIB_CASSERT( rhs <= 65535,
858
+ "\t bigint bigint::operator*=(uint16)"
859
+ << "\n\t rhs must be <= 65535"
860
+ << "\n\tthis: " << this
861
+ << "\n\t*this: " << *this
862
+ << "\n\trhs: " << rhs
863
+ );
864
+
865
+ data *= static_cast<uint16>(rhs);
866
+ return *this;
867
+ }
868
+
869
+ // ----------------------------------------------------------------------------------------
870
+
871
+ template <
872
+ typename bigint_base
873
+ >
874
+ const bigint_kernel_c<bigint_base> operator/ (
875
+ uint16 l,
876
+ const bigint_kernel_c<bigint_base>& rhs
877
+ )
878
+ {
879
+ uint32 lhs = l;
880
+ // make sure requires clause is not broken
881
+ DLIB_CASSERT( !(rhs == 0) && lhs <= 65535,
882
+ "\tconst bigint operator/(uint16,const bigint&)"
883
+ << "\n\t you can't divide by zero and lhs <= 65535"
884
+ << "\n\t&lhs: " << &lhs
885
+ << "\n\t&rhs: " << &rhs
886
+ << "\n\tlhs: " << lhs
887
+ );
888
+
889
+ // call the real function
890
+ return bigint_kernel_c<bigint_base>(lhs/rhs.data);
891
+ }
892
+
893
+ // ----------------------------------------------------------------------------------------
894
+
895
+ template <
896
+ typename bigint_base
897
+ >
898
+ const bigint_kernel_c<bigint_base> operator/ (
899
+ const bigint_kernel_c<bigint_base>& lhs,
900
+ uint16 r
901
+ )
902
+ {
903
+ uint32 rhs = r;
904
+ // make sure requires clause is not broken
905
+ DLIB_CASSERT( !(rhs == 0) && rhs <= 65535,
906
+ "\tconst bigint operator/(const bigint&,uint16)"
907
+ << "\n\t you can't divide by zero and rhs <= 65535"
908
+ << "\n\t&lhs: " << &lhs
909
+ << "\n\t&rhs: " << &rhs
910
+ << "\n\trhs: " << rhs
911
+ );
912
+
913
+ // call the real function
914
+ return bigint_kernel_c<bigint_base>(lhs.data/static_cast<uint16>(rhs));
915
+ }
916
+
917
+ // ----------------------------------------------------------------------------------------
918
+
919
+ template <
920
+ typename bigint_base
921
+ >
922
+ bigint_kernel_c<bigint_base>& bigint_kernel_c<bigint_base>::
923
+ operator/= (
924
+ uint16 rhs
925
+ )
926
+ {
927
+ // make sure requires clause is not broken
928
+ DLIB_CASSERT( !(rhs == 0) && static_cast<uint32>(rhs) <= 65535,
929
+ "\tbigint& bigint::operator/=(uint16)"
930
+ << "\n\t you can't divide by zero and rhs must be <= 65535"
931
+ << "\n\tthis: " << this
932
+ << "\n\trhs: " << rhs
933
+ );
934
+
935
+ // call the real function
936
+ data /= rhs;
937
+ return *this;
938
+ }
939
+
940
+ // ----------------------------------------------------------------------------------------
941
+
942
+ template <
943
+ typename bigint_base
944
+ >
945
+ const bigint_kernel_c<bigint_base> operator% (
946
+ uint16 lhs,
947
+ const bigint_kernel_c<bigint_base>& rhs
948
+ )
949
+ {
950
+ // make sure requires clause is not broken
951
+ DLIB_CASSERT( !(rhs == 0) && static_cast<uint32>(lhs) <= 65535,
952
+ "\tconst bigint operator%(uint16,const bigint&)"
953
+ << "\n\t you can't divide by zero and lhs must be <= 65535"
954
+ << "\n\t&lhs: " << &lhs
955
+ << "\n\t&rhs: " << &rhs
956
+ << "\n\tlhs: " << lhs
957
+ );
958
+
959
+ // call the real function
960
+ return bigint_kernel_c<bigint_base>(lhs%rhs.data);
961
+ }
962
+
963
+ // ----------------------------------------------------------------------------------------
964
+
965
+ template <
966
+ typename bigint_base
967
+ >
968
+ const bigint_kernel_c<bigint_base> operator% (
969
+ const bigint_kernel_c<bigint_base>& lhs,
970
+ uint16 r
971
+ )
972
+ {
973
+ uint32 rhs = r;
974
+ // make sure requires clause is not broken
975
+ DLIB_CASSERT( !(rhs == 0) && rhs <= 65535,
976
+ "\tconst bigint operator%(const bigint&,uint16)"
977
+ << "\n\t you can't divide by zero and rhs must be <= 65535"
978
+ << "\n\t&lhs: " << &lhs
979
+ << "\n\t&rhs: " << &rhs
980
+ << "\n\trhs: " << rhs
981
+ );
982
+
983
+ // call the real function
984
+ return bigint_kernel_c<bigint_base>(lhs.data%static_cast<uint16>(rhs));
985
+ }
986
+
987
+ // ----------------------------------------------------------------------------------------
988
+
989
+ template <
990
+ typename bigint_base
991
+ >
992
+ bigint_kernel_c<bigint_base>& bigint_kernel_c<bigint_base>::
993
+ operator%= (
994
+ uint16 r
995
+ )
996
+ {
997
+
998
+ uint32 rhs = r;
999
+ // make sure requires clause is not broken
1000
+ DLIB_CASSERT( !(rhs == 0) && rhs <= 65535,
1001
+ "\tbigint& bigint::operator%=(uint16)"
1002
+ << "\n\t you can't divide by zero and rhs must be <= 65535"
1003
+ << "\n\tthis: " << this
1004
+ << "\n\trhs: " << rhs
1005
+ );
1006
+
1007
+ // call the real function
1008
+ data %= rhs;
1009
+ return *this;
1010
+ }
1011
+
1012
+ // ----------------------------------------------------------------------------------------
1013
+
1014
+ template <
1015
+ typename bigint_base
1016
+ >
1017
+ bool operator < (
1018
+ uint16 l,
1019
+ const bigint_kernel_c<bigint_base>& rhs
1020
+ )
1021
+ {
1022
+ uint32 lhs = l;
1023
+ // make sure requires clause is not broken
1024
+ DLIB_CASSERT( lhs <= 65535,
1025
+ "\tbool operator<(uint16, const bigint&)"
1026
+ << "\n\t lhs must be <= 65535"
1027
+ << "\n\trhs: " << rhs
1028
+ << "\n\tlhs: " << lhs
1029
+ );
1030
+
1031
+ return static_cast<uint16>(lhs) < rhs.data;
1032
+ }
1033
+
1034
+ // ----------------------------------------------------------------------------------------
1035
+
1036
+ template <
1037
+ typename bigint_base
1038
+ >
1039
+ bool operator < (
1040
+ const bigint_kernel_c<bigint_base>& lhs,
1041
+ uint16 r
1042
+ )
1043
+ {
1044
+ uint32 rhs = r;
1045
+ // make sure requires clause is not broken
1046
+ DLIB_CASSERT( rhs <= 65535,
1047
+ "\tbool operator<(const bigint&, uint16)"
1048
+ << "\n\t rhs must be <= 65535"
1049
+ << "\n\trhs: " << rhs
1050
+ << "\n\tlhs: " << lhs
1051
+ );
1052
+
1053
+ return lhs.data < static_cast<uint16>(rhs);
1054
+ }
1055
+
1056
+ // ----------------------------------------------------------------------------------------
1057
+
1058
+ template <
1059
+ typename bigint_base
1060
+ >
1061
+ bool operator == (
1062
+ const bigint_kernel_c<bigint_base>& lhs,
1063
+ uint16 r
1064
+ )
1065
+ {
1066
+ uint32 rhs = r;
1067
+ // make sure requires clause is not broken
1068
+ DLIB_CASSERT( rhs <= 65535,
1069
+ "\tbool operator==(const bigint&, uint16)"
1070
+ << "\n\t rhs must be <= 65535"
1071
+ << "\n\trhs: " << rhs
1072
+ << "\n\tlhs: " << lhs
1073
+ );
1074
+
1075
+ return lhs.data == static_cast<uint16>(rhs);
1076
+ }
1077
+
1078
+ // ----------------------------------------------------------------------------------------
1079
+
1080
+ template <
1081
+ typename bigint_base
1082
+ >
1083
+ bool operator == (
1084
+ uint16 l,
1085
+ const bigint_kernel_c<bigint_base>& rhs
1086
+ )
1087
+ {
1088
+ uint32 lhs = l;
1089
+ // make sure requires clause is not broken
1090
+ DLIB_CASSERT( lhs <= 65535,
1091
+ "\tbool operator==(uint16, const bigint&)"
1092
+ << "\n\t lhs must be <= 65535"
1093
+ << "\n\trhs: " << rhs
1094
+ << "\n\tlhs: " << lhs
1095
+ );
1096
+
1097
+ return static_cast<uint16>(lhs) == rhs.data;
1098
+ }
1099
+
1100
+ // ----------------------------------------------------------------------------------------
1101
+
1102
+ template <
1103
+ typename bigint_base
1104
+ >
1105
+ bigint_kernel_c<bigint_base>& bigint_kernel_c<bigint_base>::
1106
+ operator= (
1107
+ uint16 r
1108
+ )
1109
+ {
1110
+ uint32 rhs = r;
1111
+ // make sure requires clause is not broken
1112
+ DLIB_CASSERT( rhs <= 65535,
1113
+ "\tbigint bigint::operator=(uint16)"
1114
+ << "\n\t rhs must be <= 65535"
1115
+ << "\n\t*this: " << *this
1116
+ << "\n\tthis: " << this
1117
+ << "\n\tlhs: " << rhs
1118
+ );
1119
+
1120
+ data = static_cast<uint16>(rhs);
1121
+ return *this;
1122
+ }
1123
+
1124
+ // ----------------------------------------------------------------------------------------
1125
+
1126
+ template < typename bigint_base >
1127
+ inline bool operator> (const bigint_kernel_c<bigint_base>& a, const bigint_kernel_c<bigint_base>& b) { return b < a; }
1128
+ template < typename bigint_base >
1129
+ inline bool operator!= (const bigint_kernel_c<bigint_base>& a, const bigint_kernel_c<bigint_base>& b) { return !(a == b); }
1130
+ template < typename bigint_base >
1131
+ inline bool operator<= (const bigint_kernel_c<bigint_base>& a, const bigint_kernel_c<bigint_base>& b) { return !(b < a); }
1132
+ template < typename bigint_base >
1133
+ inline bool operator>= (const bigint_kernel_c<bigint_base>& a, const bigint_kernel_c<bigint_base>& b) { return !(a < b); }
1134
+
1135
+ // ----------------------------------------------------------------------------------------
1136
+
1137
+ }
1138
+
1139
+ #endif // DLIB_BIGINT_KERNEl_C_
1140
+
dlibs/dlib/binary_search_tree.h ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (C) 2003 Davis E. King ([email protected])
2
+ // License: Boost Software License See LICENSE.txt for the full license.
3
+ #ifndef DLIB_BINARY_SEARCH_TREe_
4
+ #define DLIB_BINARY_SEARCH_TREe_
5
+
6
+
7
+ #include "binary_search_tree/binary_search_tree_kernel_1.h"
8
+ #include "binary_search_tree/binary_search_tree_kernel_2.h"
9
+ #include "binary_search_tree/binary_search_tree_kernel_c.h"
10
+
11
+
12
+ #include "algs.h"
13
+ #include <functional>
14
+
15
+
16
+ namespace dlib
17
+ {
18
+
19
+ template <
20
+ typename domain,
21
+ typename range,
22
+ typename mem_manager = default_memory_manager,
23
+ typename compare = std::less<domain>
24
+ >
25
+ class binary_search_tree
26
+ {
27
+ binary_search_tree() {}
28
+
29
+ public:
30
+
31
+ //----------- kernels ---------------
32
+
33
+ // kernel_1a
34
+ typedef binary_search_tree_kernel_1<domain,range,mem_manager,compare>
35
+ kernel_1a;
36
+ typedef binary_search_tree_kernel_c<kernel_1a>
37
+ kernel_1a_c;
38
+
39
+
40
+ // kernel_2a
41
+ typedef binary_search_tree_kernel_2<domain,range,mem_manager,compare>
42
+ kernel_2a;
43
+ typedef binary_search_tree_kernel_c<kernel_2a>
44
+ kernel_2a_c;
45
+
46
+ };
47
+ }
48
+
49
+ #endif // DLIB_BINARY_SEARCH_TREe_
50
+