Upload 2271 files
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- .gitattributes +25 -0
- difpoint/lib/.DS_Store +0 -0
- difpoint/lib/dlib/.DS_Store +0 -0
- difpoint/lib/dlib/.github/ISSUE_TEMPLATE/bug.yml +80 -0
- difpoint/lib/dlib/.github/ISSUE_TEMPLATE/config.yml +5 -0
- difpoint/lib/dlib/.github/ISSUE_TEMPLATE/feature.yml +24 -0
- difpoint/lib/dlib/.github/workflows/build_cpp.yml +274 -0
- difpoint/lib/dlib/.github/workflows/build_matlab.yml +52 -0
- difpoint/lib/dlib/.github/workflows/build_python.yml +80 -0
- difpoint/lib/dlib/.gitignore +20 -0
- difpoint/lib/dlib/CMakeLists.txt +37 -0
- difpoint/lib/dlib/LICENSE.txt +23 -0
- difpoint/lib/dlib/MANIFEST.in +19 -0
- difpoint/lib/dlib/README.md +77 -0
- difpoint/lib/dlib/dlib/CMakeLists.txt +1061 -0
- difpoint/lib/dlib/dlib/LICENSE.txt +23 -0
- difpoint/lib/dlib/dlib/algs.h +919 -0
- difpoint/lib/dlib/dlib/all/source.cpp +100 -0
- difpoint/lib/dlib/dlib/any.h +13 -0
- difpoint/lib/dlib/dlib/any/any.h +72 -0
- difpoint/lib/dlib/dlib/any/any_abstract.h +209 -0
- difpoint/lib/dlib/dlib/any/any_decision_function.h +23 -0
- difpoint/lib/dlib/dlib/any/any_decision_function_abstract.h +24 -0
- difpoint/lib/dlib/dlib/any/any_function.h +126 -0
- difpoint/lib/dlib/dlib/any/any_function_abstract.h +274 -0
- difpoint/lib/dlib/dlib/any/any_trainer.h +119 -0
- difpoint/lib/dlib/dlib/any/any_trainer_abstract.h +243 -0
- difpoint/lib/dlib/dlib/any/storage.h +977 -0
- difpoint/lib/dlib/dlib/array.h +10 -0
- difpoint/lib/dlib/dlib/array/array_kernel.h +809 -0
- difpoint/lib/dlib/dlib/array/array_kernel_abstract.h +360 -0
- difpoint/lib/dlib/dlib/array/array_tools.h +38 -0
- difpoint/lib/dlib/dlib/array/array_tools_abstract.h +33 -0
- difpoint/lib/dlib/dlib/array2d.h +12 -0
- difpoint/lib/dlib/dlib/array2d/array2d_generic_image.h +67 -0
- difpoint/lib/dlib/dlib/array2d/array2d_kernel.h +524 -0
- difpoint/lib/dlib/dlib/array2d/array2d_kernel_abstract.h +339 -0
- difpoint/lib/dlib/dlib/array2d/serialize_pixel_overloads.h +371 -0
- difpoint/lib/dlib/dlib/assert.h +217 -0
- difpoint/lib/dlib/dlib/base64.h +9 -0
- difpoint/lib/dlib/dlib/base64/base64_kernel_1.cpp +403 -0
- difpoint/lib/dlib/dlib/base64/base64_kernel_1.h +92 -0
- difpoint/lib/dlib/dlib/base64/base64_kernel_abstract.h +121 -0
- difpoint/lib/dlib/dlib/bayes_utils.h +11 -0
- difpoint/lib/dlib/dlib/bayes_utils/bayes_utils.h +1677 -0
- difpoint/lib/dlib/dlib/bayes_utils/bayes_utils_abstract.h +1042 -0
- difpoint/lib/dlib/dlib/bigint.h +43 -0
- difpoint/lib/dlib/dlib/bigint/bigint_kernel_1.cpp +1720 -0
- difpoint/lib/dlib/dlib/bigint/bigint_kernel_1.h +543 -0
- difpoint/lib/dlib/dlib/bigint/bigint_kernel_2.cpp +1945 -0
.gitattributes
CHANGED
|
@@ -48,3 +48,28 @@ difpoint/checkpoints/liveportrait_onnx/stitching_lip.trt filter=lfs diff=lfs mer
|
|
| 48 |
difpoint/checkpoints/liveportrait_onnx/landmark.trt filter=lfs diff=lfs merge=lfs -text
|
| 49 |
difpoint/checkpoints/liveportrait_onnx/libgrid_sample_3d_plugin.so filter=lfs diff=lfs merge=lfs -text
|
| 50 |
difpoint/dataset_process/ckpts/shape_predictor_68_face_landmarks.dat filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 48 |
difpoint/checkpoints/liveportrait_onnx/landmark.trt filter=lfs diff=lfs merge=lfs -text
|
| 49 |
difpoint/checkpoints/liveportrait_onnx/libgrid_sample_3d_plugin.so filter=lfs diff=lfs merge=lfs -text
|
| 50 |
difpoint/dataset_process/ckpts/shape_predictor_68_face_landmarks.dat filter=lfs diff=lfs merge=lfs -text
|
| 51 |
+
difpoint/lib/dlib/dlib/test/ffmpeg_data/116-288045-0000.flac filter=lfs diff=lfs merge=lfs -text
|
| 52 |
+
difpoint/lib/dlib/dlib/test/ffmpeg_data/dog.jpg filter=lfs diff=lfs merge=lfs -text
|
| 53 |
+
difpoint/lib/dlib/dlib/test/ffmpeg_data/eagle.jpg filter=lfs diff=lfs merge=lfs -text
|
| 54 |
+
difpoint/lib/dlib/dlib/test/ffmpeg_data/elon-musk-smoke.gif filter=lfs diff=lfs merge=lfs -text
|
| 55 |
+
difpoint/lib/dlib/dlib/test/ffmpeg_data/giraffe.jpg filter=lfs diff=lfs merge=lfs -text
|
| 56 |
+
difpoint/lib/dlib/dlib/test/ffmpeg_data/horses.jpg filter=lfs diff=lfs merge=lfs -text
|
| 57 |
+
difpoint/lib/dlib/dlib/test/ffmpeg_data/MOT17-13-SDP-raw.h265 filter=lfs diff=lfs merge=lfs -text
|
| 58 |
+
difpoint/lib/dlib/dlib/test/ffmpeg_data/MOT20-05-raw_even_shorter.mp4 filter=lfs diff=lfs merge=lfs -text
|
| 59 |
+
difpoint/lib/dlib/dlib/test/ffmpeg_data/MOT20-08-raw_shorter.h264 filter=lfs diff=lfs merge=lfs -text
|
| 60 |
+
difpoint/lib/dlib/dlib/test/ffmpeg_data/scream.jpg filter=lfs diff=lfs merge=lfs -text
|
| 61 |
+
difpoint/lib/dlib/docs/docs/chm/htmlhelp/hha.dll filter=lfs diff=lfs merge=lfs -text
|
| 62 |
+
difpoint/lib/dlib/docs/docs/chm/htmlhelp/itcc.dll filter=lfs diff=lfs merge=lfs -text
|
| 63 |
+
difpoint/lib/dlib/docs/docs/chm/htmlhelp/itircl.dll filter=lfs diff=lfs merge=lfs -text
|
| 64 |
+
difpoint/lib/dlib/docs/docs/chm/htmlhelp/itss.dll filter=lfs diff=lfs merge=lfs -text
|
| 65 |
+
difpoint/lib/dlib/docs/docs/face_landmarking_example.png filter=lfs diff=lfs merge=lfs -text
|
| 66 |
+
difpoint/lib/dlib/docs/docs/find_max_global_example.mp4 filter=lfs diff=lfs merge=lfs -text
|
| 67 |
+
difpoint/lib/dlib/docs/docs/find_max_global_example.webm filter=lfs diff=lfs merge=lfs -text
|
| 68 |
+
difpoint/lib/dlib/docs/docs/quadratic_image_models_IGARSS2013.pdf filter=lfs diff=lfs merge=lfs -text
|
| 69 |
+
difpoint/lib/dlib/docs/docs/watershed.mp4 filter=lfs diff=lfs merge=lfs -text
|
| 70 |
+
difpoint/lib/dlib/docs/docs/watershed.webm filter=lfs diff=lfs merge=lfs -text
|
| 71 |
+
difpoint/lib/dlib/examples/faces/2008_007676.jpg filter=lfs diff=lfs merge=lfs -text
|
| 72 |
+
difpoint/lib/dlib/examples/faces/bald_guys.jpg filter=lfs diff=lfs merge=lfs -text
|
| 73 |
+
difpoint/lib/dlib/examples/faces/dogs.jpg filter=lfs diff=lfs merge=lfs -text
|
| 74 |
+
difpoint/lib/dlib/examples/mmod_cars_test_image.jpg filter=lfs diff=lfs merge=lfs -text
|
| 75 |
+
difpoint/lib/dlib/examples/mmod_cars_test_image2.jpg filter=lfs diff=lfs merge=lfs -text
|
difpoint/lib/.DS_Store
ADDED
|
Binary file (6.15 kB). View file
|
|
|
difpoint/lib/dlib/.DS_Store
ADDED
|
Binary file (8.2 kB). View file
|
|
|
difpoint/lib/dlib/.github/ISSUE_TEMPLATE/bug.yml
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
name: Bug Report
|
| 2 |
+
description: Create a bug report.
|
| 3 |
+
title: "[Bug]: "
|
| 4 |
+
assignees: []
|
| 5 |
+
body:
|
| 6 |
+
- type: markdown
|
| 7 |
+
attributes:
|
| 8 |
+
value: |
|
| 9 |
+
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.
|
| 10 |
+
- type: dropdown
|
| 11 |
+
id: platform
|
| 12 |
+
attributes:
|
| 13 |
+
label: What Operating System(s) are you seeing this problem on?
|
| 14 |
+
description: Select all that apply
|
| 15 |
+
multiple: true
|
| 16 |
+
options:
|
| 17 |
+
- Linux (x86-64)
|
| 18 |
+
- Linux (aarch64)
|
| 19 |
+
- macOS (Intel)
|
| 20 |
+
- macOS (Apple Silicon)
|
| 21 |
+
- Windows
|
| 22 |
+
- Other (plase, specify in the Steps to Reproduce)
|
| 23 |
+
validations:
|
| 24 |
+
required: true
|
| 25 |
+
- type: input
|
| 26 |
+
id: version
|
| 27 |
+
attributes:
|
| 28 |
+
label: dlib version
|
| 29 |
+
description: "The commit hash, tag name, or package version"
|
| 30 |
+
placeholder: "19.24"
|
| 31 |
+
validations:
|
| 32 |
+
required: true
|
| 33 |
+
- type: input
|
| 34 |
+
id: python
|
| 35 |
+
attributes:
|
| 36 |
+
label: Python version
|
| 37 |
+
description: "The version of Python you are using"
|
| 38 |
+
placeholder: "3.8"
|
| 39 |
+
validations:
|
| 40 |
+
required: false
|
| 41 |
+
- type: input
|
| 42 |
+
id: compiler
|
| 43 |
+
attributes:
|
| 44 |
+
label: Compiler
|
| 45 |
+
description: "The compiler and version you used to build dlib from source"
|
| 46 |
+
placeholder: "e.g.: GCC 9, MSVC 19, clang 10"
|
| 47 |
+
validations:
|
| 48 |
+
required: true
|
| 49 |
+
- type: textarea
|
| 50 |
+
id: expected
|
| 51 |
+
attributes:
|
| 52 |
+
label: Expected Behavior
|
| 53 |
+
description: |
|
| 54 |
+
A clear and concise description of what you expected to happen
|
| 55 |
+
- type: textarea
|
| 56 |
+
id: current
|
| 57 |
+
attributes:
|
| 58 |
+
label: Current Behavior
|
| 59 |
+
description: A clear and concise description of what the bug is
|
| 60 |
+
placeholder: |
|
| 61 |
+
Tell us what happened. Expain in detail the current behavior.
|
| 62 |
+
validations:
|
| 63 |
+
required: true
|
| 64 |
+
- type: textarea
|
| 65 |
+
id: reproduce
|
| 66 |
+
validations:
|
| 67 |
+
required: true
|
| 68 |
+
attributes:
|
| 69 |
+
label: Steps to Reproduce
|
| 70 |
+
description: Steps to reproduce the behavior
|
| 71 |
+
placeholder: |
|
| 72 |
+
Please include as much information as possible that can help to reproduce and
|
| 73 |
+
understand the issue. Including a minimal example that reproduces the bug is very useful.
|
| 74 |
+
|
| 75 |
+
- type: textarea
|
| 76 |
+
id: other
|
| 77 |
+
attributes:
|
| 78 |
+
label: Anything else?
|
| 79 |
+
description: |
|
| 80 |
+
Add any other context about the problem here.
|
difpoint/lib/dlib/.github/ISSUE_TEMPLATE/config.yml
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
blank_issues_enabled: false
|
| 2 |
+
contact_links:
|
| 3 |
+
- name: 💬 Discussions
|
| 4 |
+
url: https://github.com/davisking/dlib/discussions
|
| 5 |
+
about: Please start usage discussions here
|
difpoint/lib/dlib/.github/ISSUE_TEMPLATE/feature.yml
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
name: Feature Request
|
| 2 |
+
description: Suggest an idea for dlib
|
| 3 |
+
labels: type:enhancement
|
| 4 |
+
assignees: []
|
| 5 |
+
body:
|
| 6 |
+
- type: markdown
|
| 7 |
+
attributes:
|
| 8 |
+
value: |
|
| 9 |
+
It is OK to suggest interesting improvements to dlib, even if you are not volunteering to implement them.
|
| 10 |
+
**However, the issue tracker is not a code writing service, do not ask for someone to write code for you**.
|
| 11 |
+
E.g. Do not ask for feature improvements to the example programs.
|
| 12 |
+
**If there is some feature improvement you want in an example program then it's up to you to write it**.
|
| 13 |
+
- type: textarea
|
| 14 |
+
id: description
|
| 15 |
+
attributes:
|
| 16 |
+
label: Main idea
|
| 17 |
+
description: Describe what you want to add or improve
|
| 18 |
+
validations:
|
| 19 |
+
required: true
|
| 20 |
+
- type: textarea
|
| 21 |
+
id: other
|
| 22 |
+
attributes:
|
| 23 |
+
label: Anything else?
|
| 24 |
+
description: Add any other context about the suggestion here.
|
difpoint/lib/dlib/.github/workflows/build_cpp.yml
ADDED
|
@@ -0,0 +1,274 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
name: C++
|
| 2 |
+
|
| 3 |
+
on:
|
| 4 |
+
push:
|
| 5 |
+
branches:
|
| 6 |
+
- master
|
| 7 |
+
paths:
|
| 8 |
+
- ".github/workflows/build_cpp.yml"
|
| 9 |
+
- "**.cpp"
|
| 10 |
+
- "**.h"
|
| 11 |
+
- "**.c"
|
| 12 |
+
- "**.cu"
|
| 13 |
+
- "**.cmake"
|
| 14 |
+
- "**CMakeLists.txt"
|
| 15 |
+
pull_request:
|
| 16 |
+
branches:
|
| 17 |
+
- master
|
| 18 |
+
paths:
|
| 19 |
+
- ".github/workflows/build_cpp.yml"
|
| 20 |
+
- "**.cpp"
|
| 21 |
+
- "**.h"
|
| 22 |
+
- "**.c"
|
| 23 |
+
- "**.cu"
|
| 24 |
+
- "**.cmake"
|
| 25 |
+
- "**CMakeLists.txt"
|
| 26 |
+
|
| 27 |
+
defaults:
|
| 28 |
+
run:
|
| 29 |
+
shell: bash
|
| 30 |
+
working-directory: dlib/test
|
| 31 |
+
|
| 32 |
+
jobs:
|
| 33 |
+
ubuntu-latest-gcc-default-cmake-3-8-ffmpeg5:
|
| 34 |
+
runs-on: 'ubuntu-latest'
|
| 35 |
+
steps:
|
| 36 |
+
- uses: actions/checkout@v2
|
| 37 |
+
|
| 38 |
+
- name: Install dependencies
|
| 39 |
+
run: |
|
| 40 |
+
sudo apt update
|
| 41 |
+
sudo apt install libwebp-dev make yasm
|
| 42 |
+
|
| 43 |
+
- name: Cache cmake 3.8.0
|
| 44 |
+
uses: actions/cache@v3
|
| 45 |
+
id: cache-cmake-download
|
| 46 |
+
with:
|
| 47 |
+
# cache this folder:
|
| 48 |
+
path: ~/cmake-3.8.0-Linux-x86_64
|
| 49 |
+
key: cmake-3.8.0_try3
|
| 50 |
+
|
| 51 |
+
- run: |
|
| 52 |
+
# Get the minimum version of cmake dlib supports
|
| 53 |
+
wget https://cmake.org/files/v3.8/cmake-3.8.0-Linux-x86_64.tar.gz
|
| 54 |
+
tar -xf cmake-3.8.0-Linux-x86_64.tar.gz -C ~
|
| 55 |
+
if: steps.cache-cmake-download.outputs.cache-hit != 'true'
|
| 56 |
+
|
| 57 |
+
- name: Cache FFmpeg 5
|
| 58 |
+
uses: actions/cache@v3
|
| 59 |
+
id: cache-ffmpeg5
|
| 60 |
+
with:
|
| 61 |
+
path: /home/runner/ffmpeg-n5.1.3_installation
|
| 62 |
+
key: ffmpeg-n5.1.3_try4
|
| 63 |
+
|
| 64 |
+
- name: Build FFmpeg 5
|
| 65 |
+
if: steps.cache-ffmpeg5.outputs.cache-hit != 'true'
|
| 66 |
+
run: |
|
| 67 |
+
wget https://github.com/FFmpeg/FFmpeg/archive/refs/tags/n5.1.3.tar.gz
|
| 68 |
+
tar -xf n5.1.3.tar.gz
|
| 69 |
+
cd FFmpeg-n5.1.3
|
| 70 |
+
./configure --prefix=/home/runner/ffmpeg-n5.1.3_installation --disable-doc --disable-programs
|
| 71 |
+
make -j4
|
| 72 |
+
make install
|
| 73 |
+
cd ..
|
| 74 |
+
|
| 75 |
+
- name: Configure
|
| 76 |
+
run: |
|
| 77 |
+
mkdir build
|
| 78 |
+
cd build
|
| 79 |
+
~/cmake-3.8.0-Linux-x86_64/bin/cmake -DCMAKE_PREFIX_PATH=/home/runner/ffmpeg-n5.1.3_installation ..
|
| 80 |
+
|
| 81 |
+
- name: Build just tests
|
| 82 |
+
run: |
|
| 83 |
+
cd build
|
| 84 |
+
make -j4 dtest
|
| 85 |
+
|
| 86 |
+
- name: Test
|
| 87 |
+
run: build/dtest --runall -q
|
| 88 |
+
|
| 89 |
+
- name: Build examples, etc
|
| 90 |
+
run: |
|
| 91 |
+
cd build
|
| 92 |
+
make -j2
|
| 93 |
+
|
| 94 |
+
ubuntu-latest-gcc-11-blas:
|
| 95 |
+
runs-on: 'ubuntu-latest'
|
| 96 |
+
steps:
|
| 97 |
+
- uses: actions/checkout@v2
|
| 98 |
+
- name: Install dependencies
|
| 99 |
+
run: |
|
| 100 |
+
sudo apt update
|
| 101 |
+
sudo apt install libwebp-dev libavformat-dev libavcodec-dev libavdevice-dev libavfilter-dev libswresample-dev libswscale-dev libavutil-dev
|
| 102 |
+
sudo apt install libopenblas-dev liblapack-dev
|
| 103 |
+
- name: Install gcc 11
|
| 104 |
+
run: |
|
| 105 |
+
sudo apt install gcc-11 g++-11
|
| 106 |
+
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-11 110 --slave /usr/bin/g++ g++ /usr/bin/g++-11 --slave /usr/bin/gcov gcov /usr/bin/gcov-11
|
| 107 |
+
- name: Configure
|
| 108 |
+
run: cmake ${{ github.workspace }}/dlib/test -B build
|
| 109 |
+
- name: Build just tests
|
| 110 |
+
run: cmake --build build --config Release --target dtest --parallel 4
|
| 111 |
+
- name: Test
|
| 112 |
+
run: build/dtest --runall -q
|
| 113 |
+
- name: Build examples, etc
|
| 114 |
+
run: cmake --build build --config Release --parallel 2
|
| 115 |
+
|
| 116 |
+
# Test the BLAS bindings
|
| 117 |
+
- name: Configure BLAS binding tests
|
| 118 |
+
run: cmake ${{ github.workspace }}/dlib/test/blas_bindings -B build_blas_bindings
|
| 119 |
+
- name: Build blas binding tests
|
| 120 |
+
run: cmake --build build_blas_bindings --config Debug --parallel 4
|
| 121 |
+
- name: Test BLAS bindings
|
| 122 |
+
run: build_blas_bindings/dtest --runall -q
|
| 123 |
+
|
| 124 |
+
ubuntu-20_04-gcc-7:
|
| 125 |
+
runs-on: 'ubuntu-20.04'
|
| 126 |
+
steps:
|
| 127 |
+
- uses: actions/checkout@v2
|
| 128 |
+
|
| 129 |
+
- name: Install dependencies
|
| 130 |
+
run: |
|
| 131 |
+
sudo apt update
|
| 132 |
+
sudo apt install libwebp-dev make yasm
|
| 133 |
+
|
| 134 |
+
- name: Install gcc 7
|
| 135 |
+
run: |
|
| 136 |
+
sudo apt install gcc-7 g++-7
|
| 137 |
+
|
| 138 |
+
- name: Cache FFmpeg 3.2.18
|
| 139 |
+
uses: actions/cache@v3
|
| 140 |
+
id: cache-ffmpeg3
|
| 141 |
+
with:
|
| 142 |
+
path: /home/runner/ffmpeg-n3.2.18_installation
|
| 143 |
+
key: ffmpeg-n3.2.18_try1
|
| 144 |
+
|
| 145 |
+
- name: Build FFmpeg 3.2.18
|
| 146 |
+
if: steps.cache-ffmpeg3.outputs.cache-hit != 'true'
|
| 147 |
+
run: |
|
| 148 |
+
wget https://github.com/FFmpeg/FFmpeg/archive/refs/tags/n3.2.18.tar.gz
|
| 149 |
+
tar -xf n3.2.18.tar.gz
|
| 150 |
+
cd FFmpeg-n3.2.18
|
| 151 |
+
./configure --prefix=/home/runner/ffmpeg-n3.2.18_installation --disable-doc --disable-programs
|
| 152 |
+
make -j4
|
| 153 |
+
make install
|
| 154 |
+
cd ..
|
| 155 |
+
|
| 156 |
+
- name: Configure
|
| 157 |
+
run: |
|
| 158 |
+
export CC=/usr/bin/gcc-7
|
| 159 |
+
export CXX=/usr/bin/g++-7
|
| 160 |
+
cmake ${{ github.workspace }}/dlib/test -B build -DCMAKE_PREFIX_PATH=/home/runner/ffmpeg-n3.2.18_installation
|
| 161 |
+
|
| 162 |
+
- name: Build just tests
|
| 163 |
+
run: cmake --build build --config Release --target dtest --parallel 4
|
| 164 |
+
|
| 165 |
+
- name: Test
|
| 166 |
+
run: build/dtest --runall -q
|
| 167 |
+
|
| 168 |
+
- name: Build examples, etc
|
| 169 |
+
run: cmake --build build --config Release --parallel 2
|
| 170 |
+
|
| 171 |
+
# Test cmake scrips can build standalone dlib as a shared library
|
| 172 |
+
- name: Configure dlib as shared library
|
| 173 |
+
run: cmake ${{ github.workspace }}/dlib -B build_dlib_shared -DBUILD_SHARED_LIBS=1 -DCMAKE_PREFIX_PATH=/home/runner/ffmpeg-n3.2.18_installation
|
| 174 |
+
|
| 175 |
+
- name: Build dlib as shared library
|
| 176 |
+
run: cmake --build build_dlib_shared --parallel 4
|
| 177 |
+
|
| 178 |
+
ubuntu-latest-clang-default-avx:
|
| 179 |
+
runs-on: 'ubuntu-latest'
|
| 180 |
+
steps:
|
| 181 |
+
- uses: actions/checkout@v2
|
| 182 |
+
- name: Install dependencies
|
| 183 |
+
run: |
|
| 184 |
+
sudo apt update
|
| 185 |
+
sudo apt install libwebp-dev libavformat-dev libavcodec-dev libavdevice-dev libavfilter-dev libswresample-dev libswscale-dev libavutil-dev
|
| 186 |
+
- name: Configure
|
| 187 |
+
run: |
|
| 188 |
+
export CC=/usr/bin/clang
|
| 189 |
+
export CXX=/usr/bin/clang++
|
| 190 |
+
cmake ${{ github.workspace }}/dlib/test -B build -DUSE_AVX_INSTRUCTIONS=1
|
| 191 |
+
- name: Build just tests
|
| 192 |
+
run: cmake --build build --config Release --target dtest --parallel 4
|
| 193 |
+
- name: Test
|
| 194 |
+
run: build/dtest --runall -q
|
| 195 |
+
- name: Build examples, etc
|
| 196 |
+
run: cmake --build build --config Release --parallel 2
|
| 197 |
+
|
| 198 |
+
ubuntu-latest-ffmpeg7:
|
| 199 |
+
runs-on: 'ubuntu-latest'
|
| 200 |
+
steps:
|
| 201 |
+
- uses: actions/checkout@v2
|
| 202 |
+
|
| 203 |
+
- name: Install dependencies
|
| 204 |
+
run: |
|
| 205 |
+
sudo apt update
|
| 206 |
+
sudo apt install make yasm
|
| 207 |
+
|
| 208 |
+
- name: Cache FFmpeg 7
|
| 209 |
+
uses: actions/cache@v3
|
| 210 |
+
id: cache-ffmpeg7
|
| 211 |
+
with:
|
| 212 |
+
path: /home/runner/ffmpeg-n7.0.1_installation
|
| 213 |
+
key: ffmpeg-n7.0.1_try2
|
| 214 |
+
|
| 215 |
+
- name: Build FFmpeg 7
|
| 216 |
+
if: steps.cache-ffmpeg7.outputs.cache-hit != 'true'
|
| 217 |
+
run: |
|
| 218 |
+
wget https://github.com/FFmpeg/FFmpeg/archive/refs/tags/n7.0.1.tar.gz
|
| 219 |
+
tar -xf n7.0.1.tar.gz
|
| 220 |
+
cd FFmpeg-n7.0.1
|
| 221 |
+
./configure --prefix=/home/runner/ffmpeg-n7.0.1_installation --disable-doc --disable-programs
|
| 222 |
+
make -j4
|
| 223 |
+
make install
|
| 224 |
+
cd ..
|
| 225 |
+
|
| 226 |
+
- name: Configure
|
| 227 |
+
run: cmake . -B build -DCMAKE_PREFIX_PATH=/home/runner/ffmpeg-n7.0.1_installation
|
| 228 |
+
- name: Build ffmpeg example
|
| 229 |
+
run: cmake --build build --config Release --target ffmpeg_video_muxing_ex --parallel 4
|
| 230 |
+
|
| 231 |
+
windows-latest:
|
| 232 |
+
runs-on: 'windows-latest'
|
| 233 |
+
steps:
|
| 234 |
+
- uses: actions/checkout@v2
|
| 235 |
+
- name: Configure
|
| 236 |
+
run: |
|
| 237 |
+
# don't use CMake 3.25.0 https://gitlab.kitware.com/cmake/cmake/-/issues/23975
|
| 238 |
+
pip3 install cmake==3.24.0
|
| 239 |
+
cmake . -B build
|
| 240 |
+
- name: Build just tests
|
| 241 |
+
run: cmake --build build --config Release --target dtest --parallel 4
|
| 242 |
+
- name: Test
|
| 243 |
+
run: build/Release/dtest.exe --runall -q
|
| 244 |
+
- name: Build ancillary tools
|
| 245 |
+
run: cmake --build build --config Release --target imglab htmlify dtoc --parallel 4
|
| 246 |
+
|
| 247 |
+
windows-2019:
|
| 248 |
+
runs-on: 'windows-2019'
|
| 249 |
+
steps:
|
| 250 |
+
- uses: actions/checkout@v2
|
| 251 |
+
- name: Configure
|
| 252 |
+
run: |
|
| 253 |
+
# don't use CMake 3.25.0 https://gitlab.kitware.com/cmake/cmake/-/issues/23975
|
| 254 |
+
pip3 install cmake==3.24.0
|
| 255 |
+
cmake . -B build
|
| 256 |
+
- name: Build just tests
|
| 257 |
+
run: cmake --build build --config Debug --target dtest --parallel 4
|
| 258 |
+
- name: Build ancillary tools
|
| 259 |
+
run: cmake --build build --config Release --target imglab htmlify dtoc --parallel 4
|
| 260 |
+
|
| 261 |
+
# Disable this because macos targets aren't working on github actions right now.
|
| 262 |
+
#macos-latest:
|
| 263 |
+
# runs-on: 'macos-latest'
|
| 264 |
+
# steps:
|
| 265 |
+
# - uses: actions/checkout@v2
|
| 266 |
+
# - name: Configure
|
| 267 |
+
# # MacOS machines often come with low quality BLAS libraries installed, so don't use those.
|
| 268 |
+
# run: cmake ${{ github.workspace }}/dlib/test -B build -DDLIB_USE_BLAS=0 -DDLIB_USE_LAPACK=0
|
| 269 |
+
# - name: Build just tests
|
| 270 |
+
# run: cmake --build build --config Release --target dtest --parallel 4
|
| 271 |
+
# - name: Test
|
| 272 |
+
# run: build/dtest --runall --no_test_timer -q
|
| 273 |
+
# - name: Build examples, etc
|
| 274 |
+
# run: cmake --build build --config Release --parallel 2
|
difpoint/lib/dlib/.github/workflows/build_matlab.yml
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
name: Matlab
|
| 2 |
+
|
| 3 |
+
on:
|
| 4 |
+
push:
|
| 5 |
+
branches:
|
| 6 |
+
- master
|
| 7 |
+
paths:
|
| 8 |
+
- ".github/workflows/build_matlab.yml"
|
| 9 |
+
- "**.cpp"
|
| 10 |
+
- "**.h"
|
| 11 |
+
- "**.c"
|
| 12 |
+
- "**.cu"
|
| 13 |
+
- "**.cmake"
|
| 14 |
+
- "**CMakeLists.txt"
|
| 15 |
+
pull_request:
|
| 16 |
+
branches:
|
| 17 |
+
- master
|
| 18 |
+
paths:
|
| 19 |
+
- ".github/workflows/build_matlab.yml"
|
| 20 |
+
- "**.cpp"
|
| 21 |
+
- "**.h"
|
| 22 |
+
- "**.c"
|
| 23 |
+
- "**.cu"
|
| 24 |
+
- "**.cmake"
|
| 25 |
+
- "**CMakeLists.txt"
|
| 26 |
+
|
| 27 |
+
defaults:
|
| 28 |
+
run:
|
| 29 |
+
shell: bash
|
| 30 |
+
working-directory: dlib/matlab
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
jobs:
|
| 34 |
+
mex-wrapper:
|
| 35 |
+
runs-on: 'ubuntu-latest'
|
| 36 |
+
steps:
|
| 37 |
+
- uses: actions/checkout@v2
|
| 38 |
+
- name: Setup MATLAB
|
| 39 |
+
uses: matlab-actions/setup-matlab@v1
|
| 40 |
+
- name: Compile mex wrappers
|
| 41 |
+
run: |
|
| 42 |
+
pwd
|
| 43 |
+
mkdir build
|
| 44 |
+
cd build
|
| 45 |
+
cmake ..
|
| 46 |
+
cmake --build . --config Release --target install --parallel 4
|
| 47 |
+
- name: Run example script
|
| 48 |
+
uses: matlab-actions/run-command@v1
|
| 49 |
+
with:
|
| 50 |
+
command: cd dlib/matlab; example
|
| 51 |
+
|
| 52 |
+
|
difpoint/lib/dlib/.github/workflows/build_python.yml
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
name: Python
|
| 2 |
+
|
| 3 |
+
on:
|
| 4 |
+
push:
|
| 5 |
+
branches:
|
| 6 |
+
- master
|
| 7 |
+
paths:
|
| 8 |
+
- ".github/workflows/build_python.yml"
|
| 9 |
+
- "**.cpp"
|
| 10 |
+
- "**.h"
|
| 11 |
+
- "**.c"
|
| 12 |
+
- "**.cu"
|
| 13 |
+
- "**.cmake"
|
| 14 |
+
- "**CMakeLists.txt"
|
| 15 |
+
- "**py"
|
| 16 |
+
pull_request:
|
| 17 |
+
branches:
|
| 18 |
+
- master
|
| 19 |
+
paths:
|
| 20 |
+
- ".github/workflows/build_python.yml"
|
| 21 |
+
- "**.cpp"
|
| 22 |
+
- "**.h"
|
| 23 |
+
- "**.c"
|
| 24 |
+
- "**.cu"
|
| 25 |
+
- "**.cmake"
|
| 26 |
+
- "**CMakeLists.txt"
|
| 27 |
+
- "**py"
|
| 28 |
+
|
| 29 |
+
defaults:
|
| 30 |
+
run:
|
| 31 |
+
shell: bash
|
| 32 |
+
|
| 33 |
+
jobs:
|
| 34 |
+
Windows:
|
| 35 |
+
runs-on: 'windows-latest'
|
| 36 |
+
steps:
|
| 37 |
+
- uses: actions/checkout@v3
|
| 38 |
+
- uses: actions/setup-python@v4
|
| 39 |
+
- name: Install python deps
|
| 40 |
+
run: |
|
| 41 |
+
pip install pytest numpy
|
| 42 |
+
# don't use CMake 3.25.0 https://gitlab.kitware.com/cmake/cmake/-/issues/23975
|
| 43 |
+
pip3 install cmake==3.24.0
|
| 44 |
+
- name: Build
|
| 45 |
+
run: |
|
| 46 |
+
pip3 install cmake==3.24.0
|
| 47 |
+
python setup.py build
|
| 48 |
+
python setup.py install --user
|
| 49 |
+
- name: Test
|
| 50 |
+
run: python -m pytest --ignore docs --ignore dlib
|
| 51 |
+
|
| 52 |
+
Ubuntu:
|
| 53 |
+
runs-on: 'ubuntu-latest'
|
| 54 |
+
steps:
|
| 55 |
+
- uses: actions/checkout@v3
|
| 56 |
+
- uses: actions/setup-python@v4
|
| 57 |
+
- name: Install python deps
|
| 58 |
+
run: pip install pytest numpy
|
| 59 |
+
- name: Build
|
| 60 |
+
run: |
|
| 61 |
+
python setup.py build
|
| 62 |
+
python setup.py install --user
|
| 63 |
+
- name: Test
|
| 64 |
+
run: python -m pytest --ignore docs --ignore dlib
|
| 65 |
+
|
| 66 |
+
# Disabled for now since something is going sideways with python packages on github actions
|
| 67 |
+
# MacOS:
|
| 68 |
+
# runs-on: 'macos-latest'
|
| 69 |
+
# steps:
|
| 70 |
+
# - uses: actions/checkout@v3
|
| 71 |
+
# - uses: actions/setup-python@v4
|
| 72 |
+
# - name: Install python deps
|
| 73 |
+
# run: pip3 install pytest numpy
|
| 74 |
+
# - name: Build
|
| 75 |
+
# run: |
|
| 76 |
+
# python3 setup.py build
|
| 77 |
+
# python3 setup.py install --user
|
| 78 |
+
# - name: Test
|
| 79 |
+
# run: python3 -m pytest --ignore docs --ignore dlib
|
| 80 |
+
|
difpoint/lib/dlib/.gitignore
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
**/.idea
|
| 2 |
+
*~
|
| 3 |
+
*.swp
|
| 4 |
+
*.o
|
| 5 |
+
*.so
|
| 6 |
+
*.pyc
|
| 7 |
+
build
|
| 8 |
+
build2
|
| 9 |
+
dist
|
| 10 |
+
*.egg-info/
|
| 11 |
+
docs/release/
|
| 12 |
+
docs/docs/web/
|
| 13 |
+
docs/docs/chm/
|
| 14 |
+
docs/docs/cache/
|
| 15 |
+
docs/docs/git-logs.xml
|
| 16 |
+
docs/docs/python/classes.txt
|
| 17 |
+
docs/docs/python/functions.txt
|
| 18 |
+
docs/docs/python/constants.txt
|
| 19 |
+
**/.vscode
|
| 20 |
+
**/venv
|
difpoint/lib/dlib/CMakeLists.txt
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
cmake_minimum_required(VERSION 3.8.0)
|
| 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)
|
difpoint/lib/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.
|
difpoint/lib/dlib/MANIFEST.in
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#
|
| 2 |
+
# MANIFEST.in
|
| 3 |
+
#
|
| 4 |
+
# Manifest template for creating the dlib source distribution.
|
| 5 |
+
|
| 6 |
+
include MANIFEST.in
|
| 7 |
+
include setup.py
|
| 8 |
+
include README.md
|
| 9 |
+
|
| 10 |
+
# sources
|
| 11 |
+
recursive-include dlib **
|
| 12 |
+
recursive-include python_examples *.txt *.py
|
| 13 |
+
recursive-include tools/python **
|
| 14 |
+
|
| 15 |
+
prune tools/python/build*
|
| 16 |
+
prune dlib/cmake_utils/*/build*
|
| 17 |
+
prune dlib/test
|
| 18 |
+
|
| 19 |
+
global-exclude *.pyc
|
difpoint/lib/dlib/README.md
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# dlib C++ library [](https://github.com/davisking/dlib/actions/workflows/build_cpp.yml) [](https://github.com/davisking/dlib/actions/workflows/build_python.yml)
|
| 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 install the build requirement.
|
| 41 |
+
```bash
|
| 42 |
+
python -m venv venv
|
| 43 |
+
pip install build
|
| 44 |
+
```
|
| 45 |
+
|
| 46 |
+
Then you must compile dlib and install it in your environment. Type:
|
| 47 |
+
```bash
|
| 48 |
+
python -m build --wheel
|
| 49 |
+
pip install dist/dlib-<version>.whl
|
| 50 |
+
```
|
| 51 |
+
|
| 52 |
+
Or download dlib using PyPi:
|
| 53 |
+
```bash
|
| 54 |
+
pip install dlib
|
| 55 |
+
```
|
| 56 |
+
|
| 57 |
+
## Running the unit test suite
|
| 58 |
+
|
| 59 |
+
Type the following to compile and run the dlib unit test suite:
|
| 60 |
+
|
| 61 |
+
```bash
|
| 62 |
+
cd dlib/test
|
| 63 |
+
mkdir build
|
| 64 |
+
cd build
|
| 65 |
+
cmake ..
|
| 66 |
+
cmake --build . --config Release
|
| 67 |
+
./dtest --runall
|
| 68 |
+
```
|
| 69 |
+
|
| 70 |
+
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.
|
| 71 |
+
|
| 72 |
+
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.
|
| 73 |
+
|
| 74 |
+
## dlib sponsors
|
| 75 |
+
|
| 76 |
+
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.
|
| 77 |
+
|
difpoint/lib/dlib/dlib/CMakeLists.txt
ADDED
|
@@ -0,0 +1,1061 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 3.8.0)
|
| 8 |
+
|
| 9 |
+
set(CMAKE_DISABLE_SOURCE_CHANGES ON)
|
| 10 |
+
set(CMAKE_DISABLE_IN_SOURCE_BUILD ON)
|
| 11 |
+
|
| 12 |
+
if(POLICY CMP0077)
|
| 13 |
+
cmake_policy(SET CMP0077 NEW)
|
| 14 |
+
endif()
|
| 15 |
+
|
| 16 |
+
project(dlib)
|
| 17 |
+
|
| 18 |
+
set(CPACK_PACKAGE_NAME "dlib")
|
| 19 |
+
set(CPACK_PACKAGE_VERSION_MAJOR "19")
|
| 20 |
+
set(CPACK_PACKAGE_VERSION_MINOR "24")
|
| 21 |
+
set(CPACK_PACKAGE_VERSION_PATCH "99")
|
| 22 |
+
set(VERSION ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH})
|
| 23 |
+
# Only print these messages once, even if dlib is added multiple times via add_subdirectory()
|
| 24 |
+
if (NOT TARGET dlib)
|
| 25 |
+
message(STATUS "Using CMake version: ${CMAKE_VERSION}")
|
| 26 |
+
message(STATUS "Compiling dlib version: ${VERSION}")
|
| 27 |
+
endif()
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
include(cmake_utils/set_compiler_specific_options.cmake)
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
# Adhere to GNU filesystem layout conventions
|
| 34 |
+
include(GNUInstallDirs)
|
| 35 |
+
|
| 36 |
+
if (POLICY CMP0075)
|
| 37 |
+
cmake_policy(SET CMP0075 NEW)
|
| 38 |
+
endif()
|
| 39 |
+
|
| 40 |
+
# default to a Release build (except if CMAKE_BUILD_TYPE is set)
|
| 41 |
+
include(cmake_utils/release_build_by_default)
|
| 42 |
+
|
| 43 |
+
# Set DLIB_VERSION in the including CMake file so they can use it to do whatever they want.
|
| 44 |
+
get_directory_property(has_parent PARENT_DIRECTORY)
|
| 45 |
+
if(has_parent)
|
| 46 |
+
set(DLIB_VERSION ${VERSION} PARENT_SCOPE)
|
| 47 |
+
if (NOT DEFINED DLIB_IN_PROJECT_BUILD)
|
| 48 |
+
set(DLIB_IN_PROJECT_BUILD true)
|
| 49 |
+
endif()
|
| 50 |
+
endif()
|
| 51 |
+
|
| 52 |
+
|
| 53 |
+
if (COMMAND pybind11_add_module AND MSVC)
|
| 54 |
+
# True when building a python extension module using Visual Studio. We care
|
| 55 |
+
# about this because a huge number of windows users have broken systems, and
|
| 56 |
+
# in particular, they have broken or incompatibly installed copies of things
|
| 57 |
+
# like libjpeg or libpng. So if we detect we are in this mode we will never
|
| 58 |
+
# ever link to those libraries. Instead, we link to the copy included with
|
| 59 |
+
# dlib.
|
| 60 |
+
set (BUILDING_PYTHON_IN_MSVC true)
|
| 61 |
+
else()
|
| 62 |
+
set (BUILDING_PYTHON_IN_MSVC false)
|
| 63 |
+
endif()
|
| 64 |
+
|
| 65 |
+
if (DLIB_IN_PROJECT_BUILD)
|
| 66 |
+
|
| 67 |
+
# Check if we are being built as part of a pybind11 module.
|
| 68 |
+
if (COMMAND pybind11_add_module)
|
| 69 |
+
set(CMAKE_POSITION_INDEPENDENT_CODE True)
|
| 70 |
+
if (CMAKE_COMPILER_IS_GNUCXX)
|
| 71 |
+
# Just setting CMAKE_POSITION_INDEPENDENT_CODE should be enough to set
|
| 72 |
+
# -fPIC for GCC but sometimes it still doesn't get set, so make sure it
|
| 73 |
+
# does.
|
| 74 |
+
add_definitions("-fPIC")
|
| 75 |
+
endif()
|
| 76 |
+
# Make DLIB_ASSERT statements not abort the python interpreter, but just return an error.
|
| 77 |
+
list(APPEND active_preprocessor_switches "-DDLIB_NO_ABORT_ON_2ND_FATAL_ERROR")
|
| 78 |
+
endif()
|
| 79 |
+
|
| 80 |
+
# DLIB_IN_PROJECT_BUILD==true means you are using dlib by invoking
|
| 81 |
+
# add_subdirectory(dlib) in the parent project. In this case, we always want
|
| 82 |
+
# to build dlib as a static library so the parent project doesn't need to
|
| 83 |
+
# deal with some random dlib shared library file. It is much better to
|
| 84 |
+
# statically compile dlib into the parent project. So the following bit of
|
| 85 |
+
# CMake ensures that happens. However, we have to take care to compile dlib
|
| 86 |
+
# with position independent code if appropriate (i.e. if the parent project
|
| 87 |
+
# is a shared library).
|
| 88 |
+
if (BUILD_SHARED_LIBS)
|
| 89 |
+
if (CMAKE_COMPILER_IS_GNUCXX)
|
| 90 |
+
# Just setting CMAKE_POSITION_INDEPENDENT_CODE should be enough to set
|
| 91 |
+
# -fPIC for GCC but sometimes it still doesn't get set, so make sure it
|
| 92 |
+
# does.
|
| 93 |
+
add_definitions("-fPIC")
|
| 94 |
+
endif()
|
| 95 |
+
set(CMAKE_POSITION_INDEPENDENT_CODE true)
|
| 96 |
+
endif()
|
| 97 |
+
|
| 98 |
+
# Tell cmake to build dlib as a static library
|
| 99 |
+
set(BUILD_SHARED_LIBS false)
|
| 100 |
+
|
| 101 |
+
elseif(BUILD_SHARED_LIBS)
|
| 102 |
+
if (MSVC)
|
| 103 |
+
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.")
|
| 104 |
+
endif()
|
| 105 |
+
endif()
|
| 106 |
+
|
| 107 |
+
|
| 108 |
+
if (CMAKE_VERSION VERSION_LESS "3.9.0")
|
| 109 |
+
# Set only because there are old target_link_libraries() statements in the
|
| 110 |
+
# FindCUDA.cmake file that comes with CMake that error out if the new behavior
|
| 111 |
+
# is used. In newer versions of CMake we can instead set CUDA_LINK_LIBRARIES_KEYWORD which fixes this issue.
|
| 112 |
+
cmake_policy(SET CMP0023 OLD)
|
| 113 |
+
else()
|
| 114 |
+
set(CUDA_LINK_LIBRARIES_KEYWORD PUBLIC)
|
| 115 |
+
endif()
|
| 116 |
+
|
| 117 |
+
|
| 118 |
+
macro (enable_preprocessor_switch option_name)
|
| 119 |
+
list(APPEND active_preprocessor_switches "-D${option_name}")
|
| 120 |
+
endmacro()
|
| 121 |
+
|
| 122 |
+
macro (disable_preprocessor_switch option_name)
|
| 123 |
+
if (active_preprocessor_switches)
|
| 124 |
+
list(REMOVE_ITEM active_preprocessor_switches "-D${option_name}")
|
| 125 |
+
endif()
|
| 126 |
+
endmacro()
|
| 127 |
+
|
| 128 |
+
macro (toggle_preprocessor_switch option_name)
|
| 129 |
+
if (${option_name})
|
| 130 |
+
enable_preprocessor_switch(${option_name})
|
| 131 |
+
else()
|
| 132 |
+
disable_preprocessor_switch(${option_name})
|
| 133 |
+
endif()
|
| 134 |
+
endmacro()
|
| 135 |
+
|
| 136 |
+
|
| 137 |
+
|
| 138 |
+
# Suppress superfluous randlib warnings about libdlib.a having no symbols on MacOSX.
|
| 139 |
+
if (CMAKE_C_COMPILER_ID STREQUAL "AppleClang")
|
| 140 |
+
set(CMAKE_C_ARCHIVE_CREATE "<CMAKE_AR> Scr <TARGET> <LINK_FLAGS> <OBJECTS>")
|
| 141 |
+
set(CMAKE_C_ARCHIVE_FINISH "<CMAKE_RANLIB> -no_warning_for_no_symbols -c <TARGET>")
|
| 142 |
+
endif()
|
| 143 |
+
if (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
|
| 144 |
+
set(CMAKE_CXX_ARCHIVE_CREATE "<CMAKE_AR> Scr <TARGET> <LINK_FLAGS> <OBJECTS>")
|
| 145 |
+
set(CMAKE_CXX_ARCHIVE_FINISH "<CMAKE_RANLIB> -no_warning_for_no_symbols -c <TARGET>")
|
| 146 |
+
endif()
|
| 147 |
+
|
| 148 |
+
# Don't try to call add_library(dlib) and setup dlib's stuff if it has already
|
| 149 |
+
# been done by some other part of the current cmake project. We do this
|
| 150 |
+
# because it avoids getting warnings/errors about cmake policy CMP0002. This
|
| 151 |
+
# happens when a project tries to call add_subdirectory() on dlib more than
|
| 152 |
+
# once. This most often happens when the top level of a project depends on two
|
| 153 |
+
# or more other things which both depend on dlib.
|
| 154 |
+
if (NOT TARGET dlib)
|
| 155 |
+
|
| 156 |
+
set (DLIB_ISO_CPP_ONLY_STR
|
| 157 |
+
"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)" )
|
| 158 |
+
set (DLIB_NO_GUI_SUPPORT_STR
|
| 159 |
+
"Enable this if you don't want to compile any of the dlib GUI code" )
|
| 160 |
+
set (DLIB_ENABLE_STACK_TRACE_STR
|
| 161 |
+
"Enable this if you want to turn on the DLIB_STACK_TRACE macros" )
|
| 162 |
+
set (DLIB_USE_BLAS_STR
|
| 163 |
+
"Disable this if you don't want to use a BLAS library" )
|
| 164 |
+
set (DLIB_USE_LAPACK_STR
|
| 165 |
+
"Disable this if you don't want to use a LAPACK library" )
|
| 166 |
+
set (DLIB_USE_CUDA_STR
|
| 167 |
+
"Disable this if you don't want to use NVIDIA CUDA" )
|
| 168 |
+
set (DLIB_USE_CUDA_COMPUTE_CAPABILITIES_STR
|
| 169 |
+
"Set this to a comma-separated list of CUDA compute capabilities" )
|
| 170 |
+
set (DLIB_USE_MKL_SEQUENTIAL_STR
|
| 171 |
+
"Enable this if you have MKL installed and want to use the sequential version instead of the multi-core version." )
|
| 172 |
+
set (DLIB_USE_MKL_WITH_TBB_STR
|
| 173 |
+
"Enable this if you have MKL installed and want to use the tbb version instead of the openmp version." )
|
| 174 |
+
set (DLIB_PNG_SUPPORT_STR
|
| 175 |
+
"Disable this if you don't want to link against libpng" )
|
| 176 |
+
set (DLIB_GIF_SUPPORT_STR
|
| 177 |
+
"Disable this if you don't want to link against libgif" )
|
| 178 |
+
set (DLIB_JPEG_SUPPORT_STR
|
| 179 |
+
"Disable this if you don't want to link against libjpeg" )
|
| 180 |
+
set (DLIB_WEBP_SUPPORT_STR
|
| 181 |
+
"Disable this if you don't want to link against libwebp" )
|
| 182 |
+
set (DLIB_JXL_SUPPORT_STR
|
| 183 |
+
"Disable this if you don't want to link against libjxl" )
|
| 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 |
+
set (DLIB_USE_FFMPEG_STR
|
| 192 |
+
"Disable this if you don't want to use the FFMPEG library" )
|
| 193 |
+
|
| 194 |
+
option(DLIB_ENABLE_ASSERTS ${DLIB_ENABLE_ASSERTS_STR} OFF)
|
| 195 |
+
option(DLIB_ISO_CPP_ONLY ${DLIB_ISO_CPP_ONLY_STR} OFF)
|
| 196 |
+
toggle_preprocessor_switch(DLIB_ISO_CPP_ONLY)
|
| 197 |
+
option(DLIB_NO_GUI_SUPPORT ${DLIB_NO_GUI_SUPPORT_STR} OFF)
|
| 198 |
+
toggle_preprocessor_switch(DLIB_NO_GUI_SUPPORT)
|
| 199 |
+
option(DLIB_ENABLE_STACK_TRACE ${DLIB_ENABLE_STACK_TRACE_STR} OFF)
|
| 200 |
+
toggle_preprocessor_switch(DLIB_ENABLE_STACK_TRACE)
|
| 201 |
+
option(DLIB_USE_MKL_SEQUENTIAL ${DLIB_USE_MKL_SEQUENTIAL_STR} OFF)
|
| 202 |
+
option(DLIB_USE_MKL_WITH_TBB ${DLIB_USE_MKL_WITH_TBB_STR} OFF)
|
| 203 |
+
|
| 204 |
+
if(DLIB_ENABLE_ASSERTS)
|
| 205 |
+
# Set these variables so they are set in the config.h.in file when dlib
|
| 206 |
+
# is installed.
|
| 207 |
+
set (DLIB_DISABLE_ASSERTS false)
|
| 208 |
+
set (ENABLE_ASSERTS true)
|
| 209 |
+
enable_preprocessor_switch(ENABLE_ASSERTS)
|
| 210 |
+
disable_preprocessor_switch(DLIB_DISABLE_ASSERTS)
|
| 211 |
+
else()
|
| 212 |
+
# Set these variables so they are set in the config.h.in file when dlib
|
| 213 |
+
# is installed.
|
| 214 |
+
set (DLIB_DISABLE_ASSERTS true)
|
| 215 |
+
set (ENABLE_ASSERTS false)
|
| 216 |
+
disable_preprocessor_switch(ENABLE_ASSERTS)
|
| 217 |
+
# Never force the asserts off when doing an in project build. The only
|
| 218 |
+
# time this matters is when using visual studio. The visual studio IDE
|
| 219 |
+
# has a drop down that lets the user select either release or debug
|
| 220 |
+
# builds. The DLIB_ASSERT macro is setup to enable/disable automatically
|
| 221 |
+
# based on this drop down (via preprocessor magic). However, if
|
| 222 |
+
# DLIB_DISABLE_ASSERTS is defined it permanently disables asserts no
|
| 223 |
+
# matter what, which would defeat the visual studio drop down. So here
|
| 224 |
+
# we make a point to not do that kind of severe disabling when in a
|
| 225 |
+
# project build. It should also be pointed out that DLIB_DISABLE_ASSERTS
|
| 226 |
+
# is only needed when building and installing dlib as a separately
|
| 227 |
+
# installed library. It doesn't matter when doing an in project build.
|
| 228 |
+
if (NOT DLIB_IN_PROJECT_BUILD)
|
| 229 |
+
enable_preprocessor_switch(DLIB_DISABLE_ASSERTS)
|
| 230 |
+
endif()
|
| 231 |
+
endif()
|
| 232 |
+
|
| 233 |
+
if (DLIB_ISO_CPP_ONLY)
|
| 234 |
+
option(DLIB_JPEG_SUPPORT ${DLIB_JPEG_SUPPORT_STR} OFF)
|
| 235 |
+
option(DLIB_LINK_WITH_SQLITE3 ${DLIB_LINK_WITH_SQLITE3_STR} OFF)
|
| 236 |
+
option(DLIB_USE_BLAS ${DLIB_USE_BLAS_STR} OFF)
|
| 237 |
+
option(DLIB_USE_LAPACK ${DLIB_USE_LAPACK_STR} OFF)
|
| 238 |
+
option(DLIB_USE_CUDA ${DLIB_USE_CUDA_STR} OFF)
|
| 239 |
+
option(DLIB_PNG_SUPPORT ${DLIB_PNG_SUPPORT_STR} OFF)
|
| 240 |
+
option(DLIB_GIF_SUPPORT ${DLIB_GIF_SUPPORT_STR} OFF)
|
| 241 |
+
option(DLIB_WEBP_SUPPORT ${DLIB_WEBP_SUPPORT_STR} OFF)
|
| 242 |
+
option(DLIB_JXL_SUPPORT ${DLIB_JXL_SUPPORT_STR} OFF)
|
| 243 |
+
#option(DLIB_USE_FFTW ${DLIB_USE_FFTW_STR} OFF)
|
| 244 |
+
option(DLIB_USE_MKL_FFT ${DLIB_USE_MKL_FFT_STR} OFF)
|
| 245 |
+
option(DLIB_USE_FFMPEG ${DLIB_USE_FFMPEG_STR} OFF)
|
| 246 |
+
else()
|
| 247 |
+
option(DLIB_JPEG_SUPPORT ${DLIB_JPEG_SUPPORT_STR} ON)
|
| 248 |
+
option(DLIB_LINK_WITH_SQLITE3 ${DLIB_LINK_WITH_SQLITE3_STR} ON)
|
| 249 |
+
option(DLIB_USE_BLAS ${DLIB_USE_BLAS_STR} ON)
|
| 250 |
+
option(DLIB_USE_LAPACK ${DLIB_USE_LAPACK_STR} ON)
|
| 251 |
+
option(DLIB_USE_CUDA ${DLIB_USE_CUDA_STR} ON)
|
| 252 |
+
set(DLIB_USE_CUDA_COMPUTE_CAPABILITIES 50 CACHE STRING ${DLIB_USE_CUDA_COMPUTE_CAPABILITIES_STR})
|
| 253 |
+
option(DLIB_PNG_SUPPORT ${DLIB_PNG_SUPPORT_STR} ON)
|
| 254 |
+
option(DLIB_GIF_SUPPORT ${DLIB_GIF_SUPPORT_STR} ON)
|
| 255 |
+
option(DLIB_WEBP_SUPPORT ${DLIB_WEBP_SUPPORT_STR} ON)
|
| 256 |
+
option(DLIB_JXL_SUPPORT ${DLIB_JXL_SUPPORT_STR} ON)
|
| 257 |
+
#option(DLIB_USE_FFTW ${DLIB_USE_FFTW_STR} ON)
|
| 258 |
+
option(DLIB_USE_MKL_FFT ${DLIB_USE_MKL_FFT_STR} ON)
|
| 259 |
+
option(DLIB_USE_FFMPEG ${DLIB_USE_FFMPEG_STR} ON)
|
| 260 |
+
endif()
|
| 261 |
+
toggle_preprocessor_switch(DLIB_JPEG_SUPPORT)
|
| 262 |
+
toggle_preprocessor_switch(DLIB_USE_BLAS)
|
| 263 |
+
toggle_preprocessor_switch(DLIB_USE_LAPACK)
|
| 264 |
+
toggle_preprocessor_switch(DLIB_USE_CUDA)
|
| 265 |
+
toggle_preprocessor_switch(DLIB_PNG_SUPPORT)
|
| 266 |
+
toggle_preprocessor_switch(DLIB_GIF_SUPPORT)
|
| 267 |
+
toggle_preprocessor_switch(DLIB_WEBP_SUPPORT)
|
| 268 |
+
toggle_preprocessor_switch(DLIB_JXL_SUPPORT)
|
| 269 |
+
#toggle_preprocessor_switch(DLIB_USE_FFTW)
|
| 270 |
+
toggle_preprocessor_switch(DLIB_USE_MKL_FFT)
|
| 271 |
+
toggle_preprocessor_switch(DLIB_USE_FFMPEG)
|
| 272 |
+
|
| 273 |
+
|
| 274 |
+
set(source_files
|
| 275 |
+
base64/base64_kernel_1.cpp
|
| 276 |
+
bigint/bigint_kernel_1.cpp
|
| 277 |
+
bigint/bigint_kernel_2.cpp
|
| 278 |
+
bit_stream/bit_stream_kernel_1.cpp
|
| 279 |
+
entropy_decoder/entropy_decoder_kernel_1.cpp
|
| 280 |
+
entropy_decoder/entropy_decoder_kernel_2.cpp
|
| 281 |
+
entropy_encoder/entropy_encoder_kernel_1.cpp
|
| 282 |
+
entropy_encoder/entropy_encoder_kernel_2.cpp
|
| 283 |
+
md5/md5_kernel_1.cpp
|
| 284 |
+
tokenizer/tokenizer_kernel_1.cpp
|
| 285 |
+
unicode/unicode.cpp
|
| 286 |
+
test_for_odr_violations.cpp
|
| 287 |
+
fft/fft.cpp
|
| 288 |
+
)
|
| 289 |
+
|
| 290 |
+
set(dlib_needed_public_libraries)
|
| 291 |
+
set(dlib_needed_public_includes)
|
| 292 |
+
set(dlib_needed_public_cflags)
|
| 293 |
+
set(dlib_needed_public_ldflags)
|
| 294 |
+
set(dlib_needed_private_libraries)
|
| 295 |
+
set(dlib_needed_private_includes)
|
| 296 |
+
|
| 297 |
+
if (DLIB_ISO_CPP_ONLY)
|
| 298 |
+
add_library(dlib ${source_files} )
|
| 299 |
+
else()
|
| 300 |
+
|
| 301 |
+
set(source_files ${source_files}
|
| 302 |
+
sockets/sockets_kernel_1.cpp
|
| 303 |
+
bsp/bsp.cpp
|
| 304 |
+
dir_nav/dir_nav_kernel_1.cpp
|
| 305 |
+
dir_nav/dir_nav_kernel_2.cpp
|
| 306 |
+
dir_nav/dir_nav_extensions.cpp
|
| 307 |
+
gui_widgets/fonts.cpp
|
| 308 |
+
linker/linker_kernel_1.cpp
|
| 309 |
+
logger/extra_logger_headers.cpp
|
| 310 |
+
logger/logger_kernel_1.cpp
|
| 311 |
+
logger/logger_config_file.cpp
|
| 312 |
+
misc_api/misc_api_kernel_1.cpp
|
| 313 |
+
misc_api/misc_api_kernel_2.cpp
|
| 314 |
+
sockets/sockets_extensions.cpp
|
| 315 |
+
sockets/sockets_kernel_2.cpp
|
| 316 |
+
sockstreambuf/sockstreambuf.cpp
|
| 317 |
+
sockstreambuf/sockstreambuf_unbuffered.cpp
|
| 318 |
+
server/server_kernel.cpp
|
| 319 |
+
server/server_iostream.cpp
|
| 320 |
+
server/server_http.cpp
|
| 321 |
+
threads/multithreaded_object_extension.cpp
|
| 322 |
+
threads/threaded_object_extension.cpp
|
| 323 |
+
threads/threads_kernel_1.cpp
|
| 324 |
+
threads/threads_kernel_2.cpp
|
| 325 |
+
threads/threads_kernel_shared.cpp
|
| 326 |
+
threads/thread_pool_extension.cpp
|
| 327 |
+
threads/async.cpp
|
| 328 |
+
timer/timer.cpp
|
| 329 |
+
stack_trace.cpp
|
| 330 |
+
cuda/cpu_dlib.cpp
|
| 331 |
+
cuda/tensor_tools.cpp
|
| 332 |
+
data_io/image_dataset_metadata.cpp
|
| 333 |
+
data_io/mnist.cpp
|
| 334 |
+
data_io/cifar.cpp
|
| 335 |
+
global_optimization/global_function_search.cpp
|
| 336 |
+
filtering/kalman_filter.cpp
|
| 337 |
+
svm/auto.cpp
|
| 338 |
+
)
|
| 339 |
+
|
| 340 |
+
if(UNIX)
|
| 341 |
+
set(CMAKE_THREAD_PREFER_PTHREAD ON)
|
| 342 |
+
find_package(Threads REQUIRED)
|
| 343 |
+
list (APPEND dlib_needed_private_libraries ${CMAKE_THREAD_LIBS_INIT})
|
| 344 |
+
endif()
|
| 345 |
+
|
| 346 |
+
# we want to link to the right stuff depending on our platform.
|
| 347 |
+
if (WIN32 AND NOT CYGWIN) ###############################################################################
|
| 348 |
+
if (DLIB_NO_GUI_SUPPORT)
|
| 349 |
+
list (APPEND dlib_needed_private_libraries ws2_32 winmm)
|
| 350 |
+
else()
|
| 351 |
+
list (APPEND dlib_needed_private_libraries ws2_32 winmm comctl32 gdi32 imm32)
|
| 352 |
+
endif()
|
| 353 |
+
elseif(APPLE) ############################################################################
|
| 354 |
+
set(CMAKE_MACOSX_RPATH 1)
|
| 355 |
+
if (NOT DLIB_NO_GUI_SUPPORT)
|
| 356 |
+
find_package(X11 QUIET)
|
| 357 |
+
if (X11_FOUND)
|
| 358 |
+
# If both X11 and anaconda are installed, it's possible for the
|
| 359 |
+
# anaconda path to appear before /opt/X11, so we remove anaconda.
|
| 360 |
+
foreach (ITR ${X11_INCLUDE_DIR})
|
| 361 |
+
if ("${ITR}" MATCHES "(.*)(Ana|ana|mini)conda(.*)")
|
| 362 |
+
list (REMOVE_ITEM X11_INCLUDE_DIR ${ITR})
|
| 363 |
+
endif ()
|
| 364 |
+
endforeach(ITR)
|
| 365 |
+
list (APPEND dlib_needed_public_includes ${X11_INCLUDE_DIR})
|
| 366 |
+
list (APPEND dlib_needed_public_libraries ${X11_LIBRARIES})
|
| 367 |
+
else()
|
| 368 |
+
find_library(xlib X11)
|
| 369 |
+
# Make sure X11 is in the include path. Note that we look for
|
| 370 |
+
# Xlocale.h rather than Xlib.h because it avoids finding a partial
|
| 371 |
+
# copy of the X11 headers on systems with anaconda installed.
|
| 372 |
+
find_path(xlib_path Xlocale.h
|
| 373 |
+
PATHS
|
| 374 |
+
/Developer/SDKs/MacOSX10.4u.sdk/usr/X11R6/include
|
| 375 |
+
/opt/local/include
|
| 376 |
+
PATH_SUFFIXES X11
|
| 377 |
+
)
|
| 378 |
+
if (xlib AND xlib_path)
|
| 379 |
+
get_filename_component(x11_path ${xlib_path} PATH CACHE)
|
| 380 |
+
list (APPEND dlib_needed_public_includes ${x11_path})
|
| 381 |
+
list (APPEND dlib_needed_public_libraries ${xlib})
|
| 382 |
+
set(X11_FOUND 1)
|
| 383 |
+
endif()
|
| 384 |
+
endif()
|
| 385 |
+
if (NOT X11_FOUND)
|
| 386 |
+
message(" *****************************************************************************")
|
| 387 |
+
message(" *** DLIB GUI SUPPORT DISABLED BECAUSE X11 DEVELOPMENT LIBRARIES NOT FOUND ***")
|
| 388 |
+
message(" *** Make sure XQuartz is installed if you want GUI support. ***")
|
| 389 |
+
message(" *** You can download XQuartz from: https://www.xquartz.org/ ***")
|
| 390 |
+
message(" *****************************************************************************")
|
| 391 |
+
set(DLIB_NO_GUI_SUPPORT ON CACHE STRING ${DLIB_NO_GUI_SUPPORT_STR} FORCE )
|
| 392 |
+
enable_preprocessor_switch(DLIB_NO_GUI_SUPPORT)
|
| 393 |
+
endif()
|
| 394 |
+
endif()
|
| 395 |
+
|
| 396 |
+
mark_as_advanced(xlib xlib_path x11_path)
|
| 397 |
+
else () ##################################################################################
|
| 398 |
+
# link to the socket library if it exists. this is something you need on solaris
|
| 399 |
+
find_library(socketlib socket)
|
| 400 |
+
if (socketlib)
|
| 401 |
+
list (APPEND dlib_needed_private_libraries ${socketlib})
|
| 402 |
+
endif ()
|
| 403 |
+
|
| 404 |
+
if (NOT DLIB_NO_GUI_SUPPORT)
|
| 405 |
+
include(FindX11)
|
| 406 |
+
if (X11_FOUND)
|
| 407 |
+
list (APPEND dlib_needed_private_includes ${X11_INCLUDE_DIR})
|
| 408 |
+
list (APPEND dlib_needed_private_libraries ${X11_LIBRARIES})
|
| 409 |
+
else()
|
| 410 |
+
message(" *****************************************************************************")
|
| 411 |
+
message(" *** DLIB GUI SUPPORT DISABLED BECAUSE X11 DEVELOPMENT LIBRARIES NOT FOUND ***")
|
| 412 |
+
message(" *** Make sure libx11-dev is installed if you want GUI support. ***")
|
| 413 |
+
message(" *** On Ubuntu run: sudo apt-get install libx11-dev ***")
|
| 414 |
+
message(" *****************************************************************************")
|
| 415 |
+
set(DLIB_NO_GUI_SUPPORT ON CACHE STRING ${DLIB_NO_GUI_SUPPORT_STR} FORCE )
|
| 416 |
+
enable_preprocessor_switch(DLIB_NO_GUI_SUPPORT)
|
| 417 |
+
endif()
|
| 418 |
+
endif()
|
| 419 |
+
|
| 420 |
+
mark_as_advanced(nsllib socketlib)
|
| 421 |
+
endif () ##################################################################################
|
| 422 |
+
|
| 423 |
+
if (NOT DLIB_NO_GUI_SUPPORT)
|
| 424 |
+
set(source_files ${source_files}
|
| 425 |
+
gui_widgets/widgets.cpp
|
| 426 |
+
gui_widgets/drawable.cpp
|
| 427 |
+
gui_widgets/canvas_drawing.cpp
|
| 428 |
+
gui_widgets/style.cpp
|
| 429 |
+
gui_widgets/base_widgets.cpp
|
| 430 |
+
gui_core/gui_core_kernel_1.cpp
|
| 431 |
+
gui_core/gui_core_kernel_2.cpp
|
| 432 |
+
)
|
| 433 |
+
endif()
|
| 434 |
+
|
| 435 |
+
INCLUDE (CheckFunctionExists)
|
| 436 |
+
|
| 437 |
+
if (DLIB_GIF_SUPPORT)
|
| 438 |
+
find_package(GIF QUIET)
|
| 439 |
+
if (GIF_FOUND)
|
| 440 |
+
list (APPEND dlib_needed_public_includes ${GIF_INCLUDE_DIR})
|
| 441 |
+
list (APPEND dlib_needed_public_libraries ${GIF_LIBRARY})
|
| 442 |
+
else()
|
| 443 |
+
set(DLIB_GIF_SUPPORT OFF CACHE STRING ${DLIB_GIF_SUPPORT_STR} FORCE )
|
| 444 |
+
toggle_preprocessor_switch(DLIB_GIF_SUPPORT)
|
| 445 |
+
endif()
|
| 446 |
+
endif()
|
| 447 |
+
|
| 448 |
+
if (DLIB_PNG_SUPPORT)
|
| 449 |
+
include(cmake_utils/find_libpng.cmake)
|
| 450 |
+
if (PNG_FOUND)
|
| 451 |
+
list (APPEND dlib_needed_private_includes ${PNG_INCLUDE_DIR})
|
| 452 |
+
list (APPEND dlib_needed_private_libraries ${PNG_LIBRARIES})
|
| 453 |
+
else()
|
| 454 |
+
# If we can't find libpng then statically compile it in.
|
| 455 |
+
include_directories(external/libpng external/zlib)
|
| 456 |
+
set(source_files ${source_files}
|
| 457 |
+
external/libpng/arm/arm_init.c
|
| 458 |
+
external/libpng/arm/filter_neon_intrinsics.c
|
| 459 |
+
external/libpng/arm/palette_neon_intrinsics.c
|
| 460 |
+
external/libpng/png.c
|
| 461 |
+
external/libpng/pngerror.c
|
| 462 |
+
external/libpng/pngget.c
|
| 463 |
+
external/libpng/pngmem.c
|
| 464 |
+
external/libpng/pngpread.c
|
| 465 |
+
external/libpng/pngread.c
|
| 466 |
+
external/libpng/pngrio.c
|
| 467 |
+
external/libpng/pngrtran.c
|
| 468 |
+
external/libpng/pngrutil.c
|
| 469 |
+
external/libpng/pngset.c
|
| 470 |
+
external/libpng/pngtrans.c
|
| 471 |
+
external/libpng/pngwio.c
|
| 472 |
+
external/libpng/pngwrite.c
|
| 473 |
+
external/libpng/pngwtran.c
|
| 474 |
+
external/libpng/pngwutil.c
|
| 475 |
+
external/zlib/adler32.c
|
| 476 |
+
external/zlib/compress.c
|
| 477 |
+
external/zlib/crc32.c
|
| 478 |
+
external/zlib/deflate.c
|
| 479 |
+
external/zlib/gzclose.c
|
| 480 |
+
external/zlib/gzlib.c
|
| 481 |
+
external/zlib/gzread.c
|
| 482 |
+
external/zlib/gzwrite.c
|
| 483 |
+
external/zlib/infback.c
|
| 484 |
+
external/zlib/inffast.c
|
| 485 |
+
external/zlib/inflate.c
|
| 486 |
+
external/zlib/inftrees.c
|
| 487 |
+
external/zlib/trees.c
|
| 488 |
+
external/zlib/uncompr.c
|
| 489 |
+
external/zlib/zutil.c
|
| 490 |
+
)
|
| 491 |
+
|
| 492 |
+
include(cmake_utils/check_if_neon_available.cmake)
|
| 493 |
+
if (ARM_NEON_IS_AVAILABLE)
|
| 494 |
+
message (STATUS "NEON instructions will be used for libpng.")
|
| 495 |
+
enable_language(ASM)
|
| 496 |
+
set(source_files ${source_files}
|
| 497 |
+
external/libpng/arm/arm_init.c
|
| 498 |
+
external/libpng/arm/filter_neon_intrinsics.c
|
| 499 |
+
external/libpng/arm/filter_neon.S
|
| 500 |
+
)
|
| 501 |
+
set_source_files_properties(external/libpng/arm/filter_neon.S PROPERTIES COMPILE_FLAGS "${CMAKE_ASM_FLAGS} ${CMAKE_CXX_FLAGS} -x assembler-with-cpp")
|
| 502 |
+
endif()
|
| 503 |
+
endif()
|
| 504 |
+
set(source_files ${source_files}
|
| 505 |
+
image_loader/png_loader.cpp
|
| 506 |
+
image_saver/save_png.cpp
|
| 507 |
+
)
|
| 508 |
+
endif()
|
| 509 |
+
|
| 510 |
+
if (DLIB_JPEG_SUPPORT)
|
| 511 |
+
include(cmake_utils/find_libjpeg.cmake)
|
| 512 |
+
if (JPEG_FOUND)
|
| 513 |
+
list (APPEND dlib_needed_private_includes ${JPEG_INCLUDE_DIR})
|
| 514 |
+
list (APPEND dlib_needed_private_libraries ${JPEG_LIBRARY})
|
| 515 |
+
else()
|
| 516 |
+
# If we can't find libjpeg then statically compile it in.
|
| 517 |
+
add_definitions(-DDLIB_JPEG_STATIC)
|
| 518 |
+
set(source_files ${source_files}
|
| 519 |
+
external/libjpeg/jaricom.c
|
| 520 |
+
external/libjpeg/jcapimin.c
|
| 521 |
+
external/libjpeg/jcapistd.c
|
| 522 |
+
external/libjpeg/jcarith.c
|
| 523 |
+
external/libjpeg/jccoefct.c
|
| 524 |
+
external/libjpeg/jccolor.c
|
| 525 |
+
external/libjpeg/jcdctmgr.c
|
| 526 |
+
external/libjpeg/jchuff.c
|
| 527 |
+
external/libjpeg/jcinit.c
|
| 528 |
+
external/libjpeg/jcmainct.c
|
| 529 |
+
external/libjpeg/jcmarker.c
|
| 530 |
+
external/libjpeg/jcmaster.c
|
| 531 |
+
external/libjpeg/jcomapi.c
|
| 532 |
+
external/libjpeg/jcparam.c
|
| 533 |
+
external/libjpeg/jcprepct.c
|
| 534 |
+
external/libjpeg/jcsample.c
|
| 535 |
+
external/libjpeg/jdapimin.c
|
| 536 |
+
external/libjpeg/jdapistd.c
|
| 537 |
+
external/libjpeg/jdarith.c
|
| 538 |
+
external/libjpeg/jdatadst.c
|
| 539 |
+
external/libjpeg/jdatasrc.c
|
| 540 |
+
external/libjpeg/jdcoefct.c
|
| 541 |
+
external/libjpeg/jdcolor.c
|
| 542 |
+
external/libjpeg/jddctmgr.c
|
| 543 |
+
external/libjpeg/jdhuff.c
|
| 544 |
+
external/libjpeg/jdinput.c
|
| 545 |
+
external/libjpeg/jdmainct.c
|
| 546 |
+
external/libjpeg/jdmarker.c
|
| 547 |
+
external/libjpeg/jdmaster.c
|
| 548 |
+
external/libjpeg/jdmerge.c
|
| 549 |
+
external/libjpeg/jdpostct.c
|
| 550 |
+
external/libjpeg/jdsample.c
|
| 551 |
+
external/libjpeg/jerror.c
|
| 552 |
+
external/libjpeg/jfdctflt.c
|
| 553 |
+
external/libjpeg/jfdctfst.c
|
| 554 |
+
external/libjpeg/jfdctint.c
|
| 555 |
+
external/libjpeg/jidctflt.c
|
| 556 |
+
external/libjpeg/jidctfst.c
|
| 557 |
+
external/libjpeg/jidctint.c
|
| 558 |
+
external/libjpeg/jmemmgr.c
|
| 559 |
+
external/libjpeg/jmemnobs.c
|
| 560 |
+
external/libjpeg/jquant1.c
|
| 561 |
+
external/libjpeg/jquant2.c
|
| 562 |
+
external/libjpeg/jutils.c
|
| 563 |
+
)
|
| 564 |
+
endif()
|
| 565 |
+
set(source_files ${source_files}
|
| 566 |
+
image_loader/jpeg_loader.cpp
|
| 567 |
+
image_saver/save_jpeg.cpp
|
| 568 |
+
)
|
| 569 |
+
endif()
|
| 570 |
+
if (DLIB_WEBP_SUPPORT)
|
| 571 |
+
include(cmake_utils/find_libwebp.cmake)
|
| 572 |
+
if (WEBP_FOUND)
|
| 573 |
+
list (APPEND dlib_needed_private_includes ${WEBP_INCLUDE_DIR})
|
| 574 |
+
list (APPEND dlib_needed_private_libraries ${WEBP_LIBRARY})
|
| 575 |
+
set(source_files ${source_files}
|
| 576 |
+
image_loader/webp_loader.cpp
|
| 577 |
+
image_saver/save_webp.cpp
|
| 578 |
+
)
|
| 579 |
+
else()
|
| 580 |
+
set(DLIB_WEBP_SUPPORT OFF CACHE BOOL ${DLIB_WEBP_SUPPORT_STR} FORCE )
|
| 581 |
+
toggle_preprocessor_switch(DLIB_WEBP_SUPPORT)
|
| 582 |
+
endif()
|
| 583 |
+
endif()
|
| 584 |
+
if (DLIB_JXL_SUPPORT)
|
| 585 |
+
include(cmake_utils/find_libjxl.cmake)
|
| 586 |
+
if (JXL_FOUND)
|
| 587 |
+
list (APPEND dlib_needed_private_includes ${JXL_INCLUDE_DIRS})
|
| 588 |
+
list (APPEND dlib_needed_private_libraries ${JXL_LIBRARIES})
|
| 589 |
+
list (APPEND dlib_needed_public_cflags ${JXL_CFLAGS})
|
| 590 |
+
list (APPEND dlib_needed_public_ldflags ${JXL_LDFLAGS})
|
| 591 |
+
set(source_files ${source_files}
|
| 592 |
+
image_loader/jxl_loader.cpp
|
| 593 |
+
image_saver/save_jxl.cpp
|
| 594 |
+
)
|
| 595 |
+
enable_preprocessor_switch(DLIB_JXL_SUPPORT)
|
| 596 |
+
else()
|
| 597 |
+
set(DLIB_JXL_SUPPORT OFF CACHE BOOL ${DLIB_JXL_SUPPORT_STR} FORCE)
|
| 598 |
+
disable_preprocessor_switch(DLIB_JXL_SUPPORT)
|
| 599 |
+
endif()
|
| 600 |
+
endif()
|
| 601 |
+
|
| 602 |
+
|
| 603 |
+
if (DLIB_USE_BLAS OR DLIB_USE_LAPACK OR DLIB_USE_MKL_FFT)
|
| 604 |
+
if (DLIB_USE_MKL_WITH_TBB AND DLIB_USE_MKL_SEQUENTIAL)
|
| 605 |
+
set(DLIB_USE_MKL_SEQUENTIAL OFF CACHE STRING ${DLIB_USE_MKL_SEQUENTIAL_STR} FORCE )
|
| 606 |
+
toggle_preprocessor_switch(DLIB_USE_MKL_SEQUENTIAL)
|
| 607 |
+
message(STATUS "Disabling DLIB_USE_MKL_SEQUENTIAL. It cannot be used simultaneously with DLIB_USE_MKL_WITH_TBB.")
|
| 608 |
+
endif()
|
| 609 |
+
|
| 610 |
+
|
| 611 |
+
# Try to find BLAS, LAPACK and MKL
|
| 612 |
+
include(cmake_utils/find_blas.cmake)
|
| 613 |
+
|
| 614 |
+
if (DLIB_USE_BLAS)
|
| 615 |
+
if (blas_found)
|
| 616 |
+
list (APPEND dlib_needed_public_libraries ${blas_libraries})
|
| 617 |
+
else()
|
| 618 |
+
set(DLIB_USE_BLAS OFF CACHE STRING ${DLIB_USE_BLAS_STR} FORCE )
|
| 619 |
+
toggle_preprocessor_switch(DLIB_USE_BLAS)
|
| 620 |
+
endif()
|
| 621 |
+
endif()
|
| 622 |
+
|
| 623 |
+
if (DLIB_USE_LAPACK)
|
| 624 |
+
if (lapack_found)
|
| 625 |
+
list (APPEND dlib_needed_public_libraries ${lapack_libraries})
|
| 626 |
+
if (lapack_with_underscore)
|
| 627 |
+
set(LAPACK_FORCE_UNDERSCORE 1)
|
| 628 |
+
enable_preprocessor_switch(LAPACK_FORCE_UNDERSCORE)
|
| 629 |
+
elseif (lapack_without_underscore)
|
| 630 |
+
set(LAPACK_FORCE_NOUNDERSCORE 1)
|
| 631 |
+
enable_preprocessor_switch(LAPACK_FORCE_NOUNDERSCORE)
|
| 632 |
+
endif ()
|
| 633 |
+
else()
|
| 634 |
+
set(DLIB_USE_LAPACK OFF CACHE STRING ${DLIB_USE_LAPACK_STR} FORCE )
|
| 635 |
+
toggle_preprocessor_switch(DLIB_USE_LAPACK)
|
| 636 |
+
endif()
|
| 637 |
+
endif()
|
| 638 |
+
|
| 639 |
+
if (DLIB_USE_MKL_FFT)
|
| 640 |
+
if (found_intel_mkl AND found_intel_mkl_headers)
|
| 641 |
+
list (APPEND dlib_needed_public_includes ${mkl_include_dir})
|
| 642 |
+
list (APPEND dlib_needed_public_libraries ${mkl_libraries})
|
| 643 |
+
else()
|
| 644 |
+
set(DLIB_USE_MKL_FFT OFF CACHE STRING ${DLIB_USE_MKL_FFT_STR} FORCE )
|
| 645 |
+
toggle_preprocessor_switch(DLIB_USE_MKL_FFT)
|
| 646 |
+
endif()
|
| 647 |
+
endif()
|
| 648 |
+
endif()
|
| 649 |
+
|
| 650 |
+
|
| 651 |
+
if (DLIB_USE_CUDA)
|
| 652 |
+
find_package(CUDA 7.5)
|
| 653 |
+
|
| 654 |
+
if (CUDA_VERSION VERSION_GREATER 9.1 AND CMAKE_VERSION VERSION_LESS 3.12.2)
|
| 655 |
+
# This bit of weirdness is to work around a bug in cmake
|
| 656 |
+
list(REMOVE_ITEM CUDA_CUBLAS_LIBRARIES "CUDA_cublas_device_LIBRARY-NOTFOUND")
|
| 657 |
+
endif()
|
| 658 |
+
|
| 659 |
+
|
| 660 |
+
if (CUDA_FOUND AND MSVC AND NOT CUDA_CUBLAS_LIBRARIES AND "${CMAKE_SIZEOF_VOID_P}" EQUAL "4")
|
| 661 |
+
message(WARNING "You have CUDA installed, but we can't use it unless you put visual studio in 64bit mode.")
|
| 662 |
+
set(CUDA_FOUND 0)
|
| 663 |
+
endif()
|
| 664 |
+
|
| 665 |
+
if (NOT CUDA_CUBLAS_LIBRARIES)
|
| 666 |
+
message(STATUS "Found CUDA, but CMake was unable to find the cuBLAS libraries that should be part of every basic CUDA "
|
| 667 |
+
"install. Your CUDA install is somehow broken or incomplete. Since cuBLAS is required for dlib to use CUDA we won't use CUDA.")
|
| 668 |
+
set(CUDA_FOUND 0)
|
| 669 |
+
endif()
|
| 670 |
+
|
| 671 |
+
if (CUDA_FOUND)
|
| 672 |
+
|
| 673 |
+
# There is some bug in cmake that causes it to mess up the
|
| 674 |
+
# -std=c++11 option if you let it propagate it to nvcc in some
|
| 675 |
+
# cases. So instead we disable this and manually include
|
| 676 |
+
# things from CMAKE_CXX_FLAGS in the CUDA_NVCC_FLAGS list below.
|
| 677 |
+
if (APPLE)
|
| 678 |
+
set(CUDA_PROPAGATE_HOST_FLAGS OFF)
|
| 679 |
+
# Grab all the -D flags from CMAKE_CXX_FLAGS so we can pass them
|
| 680 |
+
# to nvcc.
|
| 681 |
+
string(REGEX MATCHALL "-D[^ ]*" FLAGS_FOR_NVCC "${CMAKE_CXX_FLAGS}")
|
| 682 |
+
|
| 683 |
+
# Check if we are being built as part of a pybind11 module.
|
| 684 |
+
if (COMMAND pybind11_add_module)
|
| 685 |
+
# Don't export unnecessary symbols.
|
| 686 |
+
list(APPEND FLAGS_FOR_NVCC "-Xcompiler=-fvisibility=hidden")
|
| 687 |
+
endif()
|
| 688 |
+
endif()
|
| 689 |
+
|
| 690 |
+
set(CUDA_HOST_COMPILATION_CPP ON)
|
| 691 |
+
string(REPLACE "," ";" DLIB_CUDA_COMPUTE_CAPABILITIES ${DLIB_USE_CUDA_COMPUTE_CAPABILITIES})
|
| 692 |
+
foreach(CAP ${DLIB_CUDA_COMPUTE_CAPABILITIES})
|
| 693 |
+
list(APPEND CUDA_NVCC_FLAGS "-gencode arch=compute_${CAP},code=[sm_${CAP},compute_${CAP}]")
|
| 694 |
+
endforeach()
|
| 695 |
+
# Note that we add __STRICT_ANSI__ to avoid freaking out nvcc with gcc specific
|
| 696 |
+
# magic in the standard C++ header files (since nvcc uses gcc headers on linux).
|
| 697 |
+
list(APPEND CUDA_NVCC_FLAGS "-D__STRICT_ANSI__;-D_MWAITXINTRIN_H_INCLUDED;-D_FORCE_INLINES;${FLAGS_FOR_NVCC}")
|
| 698 |
+
list(APPEND CUDA_NVCC_FLAGS ${active_preprocessor_switches})
|
| 699 |
+
if (NOT DLIB_IN_PROJECT_BUILD)
|
| 700 |
+
LIST(APPEND CUDA_NVCC_FLAGS -DDLIB__CMAKE_GENERATED_A_CONFIG_H_FILE)
|
| 701 |
+
endif()
|
| 702 |
+
if (NOT MSVC)
|
| 703 |
+
list(APPEND CUDA_NVCC_FLAGS "-std=c++14")
|
| 704 |
+
endif()
|
| 705 |
+
if (CMAKE_POSITION_INDEPENDENT_CODE)
|
| 706 |
+
# sometimes this setting isn't propagated to NVCC, which then causes the
|
| 707 |
+
# compile to fail. So make sure it's propagated.
|
| 708 |
+
if (NOT MSVC) # Visual studio doesn't have -fPIC so don't do it in that case.
|
| 709 |
+
list(APPEND CUDA_NVCC_FLAGS "-Xcompiler -fPIC")
|
| 710 |
+
endif()
|
| 711 |
+
endif()
|
| 712 |
+
|
| 713 |
+
include(cmake_utils/test_for_cudnn/find_cudnn.txt)
|
| 714 |
+
|
| 715 |
+
if (cudnn AND cudnn_include AND NOT DEFINED cuda_test_compile_worked AND NOT DEFINED cudnn_test_compile_worked)
|
| 716 |
+
# make sure cuda is really working by doing a test compile
|
| 717 |
+
message(STATUS "Building a CUDA test project to see if your compiler is compatible with CUDA...")
|
| 718 |
+
|
| 719 |
+
set(CUDA_TEST_CMAKE_FLAGS
|
| 720 |
+
"-DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH}"
|
| 721 |
+
"-DCMAKE_INCLUDE_PATH=${CMAKE_INCLUDE_PATH}"
|
| 722 |
+
"-DCMAKE_LIBRARY_PATH=${CMAKE_LIBRARY_PATH}")
|
| 723 |
+
|
| 724 |
+
if (NOT MSVC) # see https://github.com/davisking/dlib/issues/363
|
| 725 |
+
list(APPEND CUDA_TEST_CMAKE_FLAGS "-DCUDA_HOST_COMPILER=${CUDA_HOST_COMPILER}")
|
| 726 |
+
endif()
|
| 727 |
+
|
| 728 |
+
try_compile(cuda_test_compile_worked
|
| 729 |
+
${PROJECT_BINARY_DIR}/cuda_test_build
|
| 730 |
+
${PROJECT_SOURCE_DIR}/cmake_utils/test_for_cuda cuda_test
|
| 731 |
+
CMAKE_FLAGS ${CUDA_TEST_CMAKE_FLAGS}
|
| 732 |
+
OUTPUT_VARIABLE try_compile_output_message
|
| 733 |
+
)
|
| 734 |
+
if (NOT cuda_test_compile_worked)
|
| 735 |
+
string(REPLACE "\n" "\n *** " try_compile_output_message "${try_compile_output_message}")
|
| 736 |
+
message(STATUS "*****************************************************************************************************************")
|
| 737 |
+
message(STATUS "*** CUDA was found but your compiler failed to compile a simple CUDA program so dlib isn't going to use CUDA. ")
|
| 738 |
+
message(STATUS "*** The output of the failed CUDA test compile is shown below: ")
|
| 739 |
+
message(STATUS "*** ")
|
| 740 |
+
message(STATUS "*** ${try_compile_output_message}")
|
| 741 |
+
message(STATUS "*****************************************************************************************************************")
|
| 742 |
+
else()
|
| 743 |
+
message(STATUS "Building a cuDNN test project to check if you have the right version of cuDNN installed...")
|
| 744 |
+
try_compile(cudnn_test_compile_worked
|
| 745 |
+
${PROJECT_BINARY_DIR}/cudnn_test_build
|
| 746 |
+
${PROJECT_SOURCE_DIR}/cmake_utils/test_for_cudnn cudnn_test
|
| 747 |
+
CMAKE_FLAGS ${CUDA_TEST_CMAKE_FLAGS}
|
| 748 |
+
OUTPUT_VARIABLE try_compile_output_message
|
| 749 |
+
)
|
| 750 |
+
if (NOT cudnn_test_compile_worked)
|
| 751 |
+
string(REPLACE "\n" "\n *** " try_compile_output_message "${try_compile_output_message}")
|
| 752 |
+
message(STATUS "*****************************************************************************************************")
|
| 753 |
+
message(STATUS "*** Found cuDNN, but we failed to compile the dlib/cmake_utils/test_for_cudnn project. ")
|
| 754 |
+
message(STATUS "*** You either have an unsupported version of cuDNN or something is wrong with your cudDNN install.")
|
| 755 |
+
message(STATUS "*** Since a functional cuDNN is not found DLIB WILL NOT USE CUDA. ")
|
| 756 |
+
message(STATUS "*** The output of the failed test_for_cudnn build is: ")
|
| 757 |
+
message(STATUS "*** ")
|
| 758 |
+
message(STATUS "*** ${try_compile_output_message}")
|
| 759 |
+
message(STATUS "*****************************************************************************************************")
|
| 760 |
+
endif()
|
| 761 |
+
endif()
|
| 762 |
+
endif()
|
| 763 |
+
|
| 764 |
+
# Find where cuSOLVER is since the FindCUDA cmake package doesn't
|
| 765 |
+
# bother to look for it in older versions of cmake.
|
| 766 |
+
if (NOT CUDA_cusolver_LIBRARY)
|
| 767 |
+
get_filename_component(cuda_blas_path "${CUDA_CUBLAS_LIBRARIES}" DIRECTORY)
|
| 768 |
+
find_library(CUDA_cusolver_LIBRARY cusolver HINTS ${cuda_blas_path})
|
| 769 |
+
# CUDA 10.1 doesn't install symbolic links to libcusolver.so in
|
| 770 |
+
# the usual place. This is probably a bug in the cuda
|
| 771 |
+
# installer. In any case, If we haven't found cusolver yet go
|
| 772 |
+
# look in the cuda install folder for it. New versions of cmake
|
| 773 |
+
# do this correctly, but older versions need help.
|
| 774 |
+
if (NOT CUDA_cusolver_LIBRARY)
|
| 775 |
+
find_library(CUDA_cusolver_LIBRARY cusolver HINTS
|
| 776 |
+
/usr/local/cuda/lib64/
|
| 777 |
+
)
|
| 778 |
+
endif()
|
| 779 |
+
mark_as_advanced(CUDA_cusolver_LIBRARY)
|
| 780 |
+
endif()
|
| 781 |
+
# Also find OpenMP since cuSOLVER needs it. Importantly, we only
|
| 782 |
+
# look for one to link to if our use of BLAS, specifically the
|
| 783 |
+
# Intel MKL, hasn't already decided what to use. This is because
|
| 784 |
+
# it makes the MKL bug out if you link to another openmp lib other
|
| 785 |
+
# than Intel's when you use the MKL. I'm also not really sure when
|
| 786 |
+
# explicit linking to openmp became unnecessary, but for
|
| 787 |
+
# sufficiently older versions of cuda it was needed. Then in
|
| 788 |
+
# versions of cmake newer than 3.11 linking to openmp started to
|
| 789 |
+
# mess up the switches passed to nvcc, so you can't just leave
|
| 790 |
+
# these "try to link to openmp" statements here going forward. Fun
|
| 791 |
+
# times.
|
| 792 |
+
if (CUDA_VERSION VERSION_LESS "9.1" AND NOT openmp_libraries AND NOT MSVC AND NOT XCODE AND NOT APPLE)
|
| 793 |
+
find_package(OpenMP)
|
| 794 |
+
if (OPENMP_FOUND)
|
| 795 |
+
set(openmp_libraries ${OpenMP_CXX_FLAGS})
|
| 796 |
+
else()
|
| 797 |
+
message(STATUS "*** Didn't find OpenMP, which is required to use CUDA. ***")
|
| 798 |
+
set(CUDA_FOUND 0)
|
| 799 |
+
endif()
|
| 800 |
+
endif()
|
| 801 |
+
endif()
|
| 802 |
+
|
| 803 |
+
if (CUDA_FOUND AND cudnn AND cuda_test_compile_worked AND cudnn_test_compile_worked AND cudnn_include)
|
| 804 |
+
set(source_files ${source_files}
|
| 805 |
+
cuda/cuda_dlib.cu
|
| 806 |
+
cuda/cudnn_dlibapi.cpp
|
| 807 |
+
cuda/cublas_dlibapi.cpp
|
| 808 |
+
cuda/cusolver_dlibapi.cu
|
| 809 |
+
cuda/curand_dlibapi.cpp
|
| 810 |
+
cuda/cuda_data_ptr.cpp
|
| 811 |
+
cuda/gpu_data.cpp
|
| 812 |
+
)
|
| 813 |
+
list (APPEND dlib_needed_private_libraries ${CUDA_CUBLAS_LIBRARIES})
|
| 814 |
+
list (APPEND dlib_needed_private_libraries ${cudnn})
|
| 815 |
+
list (APPEND dlib_needed_private_libraries ${CUDA_curand_LIBRARY})
|
| 816 |
+
list (APPEND dlib_needed_private_libraries ${CUDA_cusolver_LIBRARY})
|
| 817 |
+
list (APPEND dlib_needed_private_libraries ${CUDA_CUDART_LIBRARY})
|
| 818 |
+
if(openmp_libraries)
|
| 819 |
+
list (APPEND dlib_needed_private_libraries ${openmp_libraries})
|
| 820 |
+
endif()
|
| 821 |
+
|
| 822 |
+
include_directories(${cudnn_include})
|
| 823 |
+
message(STATUS "Enabling CUDA support for dlib. DLIB WILL USE CUDA, compute capabilities: ${DLIB_CUDA_COMPUTE_CAPABILITIES}")
|
| 824 |
+
else()
|
| 825 |
+
set(DLIB_USE_CUDA OFF CACHE STRING ${DLIB_USE_BLAS_STR} FORCE )
|
| 826 |
+
toggle_preprocessor_switch(DLIB_USE_CUDA)
|
| 827 |
+
if (NOT CUDA_FOUND)
|
| 828 |
+
message(STATUS "DID NOT FIND CUDA")
|
| 829 |
+
endif()
|
| 830 |
+
message(STATUS "Disabling CUDA support for dlib. DLIB WILL NOT USE CUDA")
|
| 831 |
+
endif()
|
| 832 |
+
endif()
|
| 833 |
+
|
| 834 |
+
|
| 835 |
+
if (DLIB_LINK_WITH_SQLITE3)
|
| 836 |
+
find_library(sqlite sqlite3)
|
| 837 |
+
# make sure sqlite3.h is in the include path
|
| 838 |
+
find_path(sqlite_path sqlite3.h)
|
| 839 |
+
if (sqlite AND sqlite_path)
|
| 840 |
+
list (APPEND dlib_needed_public_includes ${sqlite_path})
|
| 841 |
+
list (APPEND dlib_needed_public_libraries ${sqlite} )
|
| 842 |
+
else()
|
| 843 |
+
set(DLIB_LINK_WITH_SQLITE3 OFF CACHE STRING ${DLIB_LINK_WITH_SQLITE3_STR} FORCE )
|
| 844 |
+
endif()
|
| 845 |
+
mark_as_advanced(sqlite sqlite_path)
|
| 846 |
+
endif()
|
| 847 |
+
|
| 848 |
+
|
| 849 |
+
|
| 850 |
+
if (DLIB_USE_FFTW)
|
| 851 |
+
find_library(fftw fftw3)
|
| 852 |
+
# make sure fftw3.h is in the include path
|
| 853 |
+
find_path(fftw_path fftw3.h)
|
| 854 |
+
if (fftw AND fftw_path)
|
| 855 |
+
list (APPEND dlib_needed_private_includes ${fftw_path})
|
| 856 |
+
list (APPEND dlib_needed_private_libraries ${fftw})
|
| 857 |
+
else()
|
| 858 |
+
set(DLIB_USE_FFTW OFF CACHE STRING ${DLIB_USE_FFTW_STR} FORCE )
|
| 859 |
+
toggle_preprocessor_switch(DLIB_USE_FFTW)
|
| 860 |
+
endif()
|
| 861 |
+
mark_as_advanced(fftw fftw_path)
|
| 862 |
+
endif()
|
| 863 |
+
|
| 864 |
+
if (DLIB_USE_FFMPEG)
|
| 865 |
+
include(cmake_utils/find_ffmpeg.cmake)
|
| 866 |
+
if (FFMPEG_FOUND)
|
| 867 |
+
list (APPEND dlib_needed_public_includes ${FFMPEG_INCLUDE_DIRS})
|
| 868 |
+
list (APPEND dlib_needed_public_libraries ${FFMPEG_LINK_LIBRARIES})
|
| 869 |
+
list (APPEND dlib_needed_public_cflags ${FFMPEG_CFLAGS})
|
| 870 |
+
list (APPEND dlib_needed_public_ldflags ${FFMPEG_LDFLAGS})
|
| 871 |
+
enable_preprocessor_switch(DLIB_USE_FFMPEG)
|
| 872 |
+
else()
|
| 873 |
+
set(DLIB_USE_FFMPEG OFF CACHE BOOL ${DLIB_USE_FFMPEG_STR} FORCE )
|
| 874 |
+
disable_preprocessor_switch(DLIB_USE_FFMPEG)
|
| 875 |
+
endif()
|
| 876 |
+
endif()
|
| 877 |
+
|
| 878 |
+
# Tell CMake to build dlib via add_library()/cuda_add_library()
|
| 879 |
+
if (DLIB_USE_CUDA)
|
| 880 |
+
# The old cuda_add_library() command doesn't support CMake's newer dependency
|
| 881 |
+
# stuff, so we have to set the include path manually still, which we do here.
|
| 882 |
+
include_directories(${dlib_needed_public_includes})
|
| 883 |
+
cuda_add_library(dlib ${source_files} )
|
| 884 |
+
else()
|
| 885 |
+
add_library(dlib ${source_files} )
|
| 886 |
+
endif()
|
| 887 |
+
|
| 888 |
+
endif () ##### end of if NOT DLIB_ISO_CPP_ONLY ##########################################################
|
| 889 |
+
|
| 890 |
+
|
| 891 |
+
target_include_directories(dlib
|
| 892 |
+
INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..>
|
| 893 |
+
INTERFACE $<INSTALL_INTERFACE:include>
|
| 894 |
+
PUBLIC ${dlib_needed_public_includes}
|
| 895 |
+
PRIVATE ${dlib_needed_private_includes}
|
| 896 |
+
)
|
| 897 |
+
target_link_libraries(dlib PUBLIC ${dlib_needed_public_libraries} ${dlib_needed_public_ldflags})
|
| 898 |
+
target_link_libraries(dlib PRIVATE ${dlib_needed_private_libraries})
|
| 899 |
+
target_compile_options(dlib PUBLIC ${dlib_needed_public_cflags})
|
| 900 |
+
if (DLIB_IN_PROJECT_BUILD)
|
| 901 |
+
target_compile_options(dlib PUBLIC ${active_preprocessor_switches})
|
| 902 |
+
else()
|
| 903 |
+
# These are private in this case because they will be controlled by the
|
| 904 |
+
# contents of dlib/config.h once it's installed. But for in project
|
| 905 |
+
# builds, there is no real config.h so they are public in the above case.
|
| 906 |
+
target_compile_options(dlib PRIVATE ${active_preprocessor_switches})
|
| 907 |
+
# Do this so that dlib/config.h won't set DLIB_NOT_CONFIGURED. This will then allow
|
| 908 |
+
# the code in dlib/threads_kernel_shared.cpp to emit a linker error for users who
|
| 909 |
+
# don't use the configured config.h file generated by cmake.
|
| 910 |
+
target_compile_options(dlib PRIVATE -DDLIB__CMAKE_GENERATED_A_CONFIG_H_FILE)
|
| 911 |
+
|
| 912 |
+
# Do this so that dlib/config.h can record the version of dlib it's configured with
|
| 913 |
+
# and ultimately issue a linker error to people who try to use a binary dlib that is
|
| 914 |
+
# the wrong version.
|
| 915 |
+
set(DLIB_CHECK_FOR_VERSION_MISMATCH
|
| 916 |
+
DLIB_VERSION_MISMATCH_CHECK__EXPECTED_VERSION_${CPACK_PACKAGE_VERSION_MAJOR}_${CPACK_PACKAGE_VERSION_MINOR}_${CPACK_PACKAGE_VERSION_PATCH})
|
| 917 |
+
target_compile_options(dlib PRIVATE "-DDLIB_CHECK_FOR_VERSION_MISMATCH=${DLIB_CHECK_FOR_VERSION_MISMATCH}")
|
| 918 |
+
endif()
|
| 919 |
+
|
| 920 |
+
|
| 921 |
+
# Allow the unit tests to ask us to compile the all/source.cpp file just to make sure it compiles.
|
| 922 |
+
if (DLIB_TEST_COMPILE_ALL_SOURCE_CPP)
|
| 923 |
+
add_library(dlib_all_source_cpp STATIC all/source.cpp)
|
| 924 |
+
target_link_libraries(dlib_all_source_cpp dlib)
|
| 925 |
+
target_compile_options(dlib_all_source_cpp PUBLIC ${active_preprocessor_switches})
|
| 926 |
+
target_compile_features(dlib_all_source_cpp PUBLIC cxx_std_14)
|
| 927 |
+
endif()
|
| 928 |
+
|
| 929 |
+
target_compile_features(dlib PUBLIC cxx_std_14)
|
| 930 |
+
if((MSVC AND CMAKE_VERSION VERSION_LESS 3.11))
|
| 931 |
+
target_compile_options(dlib PUBLIC ${active_compile_opts})
|
| 932 |
+
target_compile_options(dlib PRIVATE ${active_compile_opts_private})
|
| 933 |
+
else()
|
| 934 |
+
target_compile_options(dlib PUBLIC $<$<COMPILE_LANGUAGE:CXX>:${active_compile_opts}>)
|
| 935 |
+
target_compile_options(dlib PRIVATE $<$<COMPILE_LANGUAGE:CXX>:${active_compile_opts_private}>)
|
| 936 |
+
endif()
|
| 937 |
+
|
| 938 |
+
# Install the library
|
| 939 |
+
if (NOT DLIB_IN_PROJECT_BUILD)
|
| 940 |
+
string (REPLACE ";" " " pkg_config_dlib_needed_libraries "${dlib_needed_public_libraries}")
|
| 941 |
+
# Make the -I include options for pkg-config
|
| 942 |
+
foreach (ITR ${dlib_needed_public_includes})
|
| 943 |
+
set (pkg_config_dlib_needed_includes "${pkg_config_dlib_needed_includes} -I${ITR}")
|
| 944 |
+
endforeach()
|
| 945 |
+
set_target_properties(dlib PROPERTIES
|
| 946 |
+
VERSION ${VERSION})
|
| 947 |
+
install(TARGETS dlib
|
| 948 |
+
EXPORT dlib
|
| 949 |
+
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} # Windows considers .dll to be runtime artifacts
|
| 950 |
+
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
| 951 |
+
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
| 952 |
+
|
| 953 |
+
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dlib
|
| 954 |
+
FILES_MATCHING
|
| 955 |
+
PATTERN "*.h"
|
| 956 |
+
PATTERN "*.cmake"
|
| 957 |
+
PATTERN "*_tutorial.txt"
|
| 958 |
+
PATTERN "cassert"
|
| 959 |
+
PATTERN "cstring"
|
| 960 |
+
PATTERN "fstream"
|
| 961 |
+
PATTERN "iomanip"
|
| 962 |
+
PATTERN "iosfwd"
|
| 963 |
+
PATTERN "iostream"
|
| 964 |
+
PATTERN "istream"
|
| 965 |
+
PATTERN "locale"
|
| 966 |
+
PATTERN "ostream"
|
| 967 |
+
PATTERN "sstream"
|
| 968 |
+
REGEX "${CMAKE_CURRENT_BINARY_DIR}" EXCLUDE)
|
| 969 |
+
|
| 970 |
+
|
| 971 |
+
configure_file(${PROJECT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
| 972 |
+
# overwrite config.h with the configured one
|
| 973 |
+
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/config.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dlib)
|
| 974 |
+
|
| 975 |
+
configure_file(${PROJECT_SOURCE_DIR}/revision.h.in ${CMAKE_CURRENT_BINARY_DIR}/revision.h)
|
| 976 |
+
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/revision.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dlib)
|
| 977 |
+
|
| 978 |
+
## Config.cmake generation and installation
|
| 979 |
+
|
| 980 |
+
set(ConfigPackageLocation "${CMAKE_INSTALL_LIBDIR}/cmake/dlib")
|
| 981 |
+
install(EXPORT dlib
|
| 982 |
+
NAMESPACE dlib::
|
| 983 |
+
DESTINATION ${ConfigPackageLocation})
|
| 984 |
+
|
| 985 |
+
configure_file(cmake_utils/dlibConfig.cmake.in "${CMAKE_CURRENT_BINARY_DIR}/config/dlibConfig.cmake" @ONLY)
|
| 986 |
+
|
| 987 |
+
include(CMakePackageConfigHelpers)
|
| 988 |
+
write_basic_package_version_file(
|
| 989 |
+
"${CMAKE_CURRENT_BINARY_DIR}/config/dlibConfigVersion.cmake"
|
| 990 |
+
VERSION ${VERSION}
|
| 991 |
+
COMPATIBILITY AnyNewerVersion
|
| 992 |
+
)
|
| 993 |
+
|
| 994 |
+
install(FILES
|
| 995 |
+
"${CMAKE_CURRENT_BINARY_DIR}/config/dlibConfig.cmake"
|
| 996 |
+
"${CMAKE_CURRENT_BINARY_DIR}/config/dlibConfigVersion.cmake"
|
| 997 |
+
DESTINATION ${ConfigPackageLocation})
|
| 998 |
+
|
| 999 |
+
## dlib-1.pc generation and installation
|
| 1000 |
+
|
| 1001 |
+
configure_file("cmake_utils/dlib.pc.in" "dlib-1.pc" @ONLY)
|
| 1002 |
+
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/dlib-1.pc"
|
| 1003 |
+
DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
|
| 1004 |
+
|
| 1005 |
+
# Add a cpack "package" target. This will create an archive containing
|
| 1006 |
+
# the built library file, the header files, and cmake and pkgconfig
|
| 1007 |
+
# configuration files.
|
| 1008 |
+
include(CPack)
|
| 1009 |
+
|
| 1010 |
+
endif()
|
| 1011 |
+
|
| 1012 |
+
endif()
|
| 1013 |
+
|
| 1014 |
+
if (MSVC)
|
| 1015 |
+
# Give the output library files names that are unique functions of the
|
| 1016 |
+
# visual studio mode that compiled them. We do this so that people who
|
| 1017 |
+
# compile dlib and then copy the .lib files around (which they shouldn't be
|
| 1018 |
+
# doing in the first place!) will hopefully be slightly less confused by
|
| 1019 |
+
# what happens since, at the very least, the filenames will indicate what
|
| 1020 |
+
# visual studio runtime they go with.
|
| 1021 |
+
math(EXPR numbits ${CMAKE_SIZEOF_VOID_P}*8)
|
| 1022 |
+
set_target_properties(dlib PROPERTIES DEBUG_POSTFIX "${VERSION}_debug_${numbits}bit_msvc${MSVC_VERSION}")
|
| 1023 |
+
set_target_properties(dlib PROPERTIES RELEASE_POSTFIX "${VERSION}_release_${numbits}bit_msvc${MSVC_VERSION}")
|
| 1024 |
+
set_target_properties(dlib PROPERTIES MINSIZEREL_POSTFIX "${VERSION}_minsizerel_${numbits}bit_msvc${MSVC_VERSION}")
|
| 1025 |
+
set_target_properties(dlib PROPERTIES RELWITHDEBINFO_POSTFIX "${VERSION}_relwithdebinfo_${numbits}bit_msvc${MSVC_VERSION}")
|
| 1026 |
+
endif()
|
| 1027 |
+
|
| 1028 |
+
# Check if we are being built as part of a pybind11 module.
|
| 1029 |
+
if (COMMAND pybind11_add_module)
|
| 1030 |
+
# Don't export unnecessary symbols.
|
| 1031 |
+
set_target_properties(dlib PROPERTIES CXX_VISIBILITY_PRESET "hidden")
|
| 1032 |
+
set_target_properties(dlib PROPERTIES CUDA_VISIBILITY_PRESET "hidden")
|
| 1033 |
+
endif()
|
| 1034 |
+
|
| 1035 |
+
if (WIN32 AND mkl_iomp_dll)
|
| 1036 |
+
# If we are using the Intel MKL on windows then try and copy the iomp dll
|
| 1037 |
+
# file to the output folder. We do this since a very large number of
|
| 1038 |
+
# windows users don't understand that they need to add the Intel MKL's
|
| 1039 |
+
# folders to their PATH to use the Intel MKL. They then complain on the
|
| 1040 |
+
# dlib forums. Copying the Intel MKL dlls to the output directory removes
|
| 1041 |
+
# the need to add the Intel MKL to the PATH.
|
| 1042 |
+
if (CMAKE_LIBRARY_OUTPUT_DIRECTORY)
|
| 1043 |
+
add_custom_command(TARGET dlib POST_BUILD
|
| 1044 |
+
# In some newer versions of windows/visual studio the output Config folder doesn't
|
| 1045 |
+
# exist at first, so you can't copy to it unless you make it yourself. So make
|
| 1046 |
+
# sure the target folder exists first.
|
| 1047 |
+
COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/"
|
| 1048 |
+
COMMAND ${CMAKE_COMMAND} -E copy "${mkl_iomp_dll}" "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/"
|
| 1049 |
+
)
|
| 1050 |
+
else()
|
| 1051 |
+
add_custom_command(TARGET dlib POST_BUILD
|
| 1052 |
+
# In some newer versions of windows/visual studio the output Config folder doesn't
|
| 1053 |
+
# exist at first, so you can't copy to it unless you make it yourself. So make
|
| 1054 |
+
# sure the target folder exists first.
|
| 1055 |
+
COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_BINARY_DIR}/$<CONFIG>/"
|
| 1056 |
+
COMMAND ${CMAKE_COMMAND} -E copy "${mkl_iomp_dll}" "${CMAKE_BINARY_DIR}/$<CONFIG>/"
|
| 1057 |
+
)
|
| 1058 |
+
endif()
|
| 1059 |
+
endif()
|
| 1060 |
+
|
| 1061 |
+
add_library(dlib::dlib ALIAS dlib)
|
difpoint/lib/dlib/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.
|
difpoint/lib/dlib/dlib/algs.h
ADDED
|
@@ -0,0 +1,919 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
|
| 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++14 option a reminder
|
| 14 |
+
#if (defined(__GNUC__) && ((__GNUC__ >= 5 && __GNUC_MINOR__ >= 0) || (__GNUC__ > 5))) || \
|
| 15 |
+
(defined(__clang__) && ((__clang_major__ >= 3 && __clang_minor__ >= 4) || (__clang_major__ >= 3)))
|
| 16 |
+
#if __cplusplus < 201402L
|
| 17 |
+
#error "Dlib requires C++14 support. Give your compiler the -std=c++14 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 |
+
#ifdef __NVCC_DIAG_PRAGMA_SUPPORT__
|
| 26 |
+
#pragma nv_diag_suppress code_is_unreachable
|
| 27 |
+
#else
|
| 28 |
+
#pragma diag_suppress code_is_unreachable
|
| 29 |
+
#endif
|
| 30 |
+
#endif
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
#ifdef _MSC_VER
|
| 34 |
+
|
| 35 |
+
#if _MSC_VER < 1900
|
| 36 |
+
#error "dlib versions newer than v19.1 use C++11 and therefore require Visual Studio 2015 or newer."
|
| 37 |
+
#endif
|
| 38 |
+
|
| 39 |
+
// Disable the following warnings for Visual Studio
|
| 40 |
+
|
| 41 |
+
// this is to disable the "'this' : used in base member initializer list"
|
| 42 |
+
// warning you get from some of the GUI objects since all the objects
|
| 43 |
+
// require that their parent class be passed into their constructor.
|
| 44 |
+
// In this case though it is totally safe so it is ok to disable this warning.
|
| 45 |
+
#pragma warning(disable : 4355)
|
| 46 |
+
|
| 47 |
+
// This is a warning you get sometimes when Visual Studio performs a Koenig Lookup.
|
| 48 |
+
// This is a bug in visual studio. It is a totally legitimate thing to
|
| 49 |
+
// expect from a compiler.
|
| 50 |
+
#pragma warning(disable : 4675)
|
| 51 |
+
|
| 52 |
+
// This is a warning you get from visual studio 2005 about things in the standard C++
|
| 53 |
+
// library being "deprecated." I checked the C++ standard and it doesn't say jack
|
| 54 |
+
// about any of them (I checked the searchable PDF). So this warning is total Bunk.
|
| 55 |
+
#pragma warning(disable : 4996)
|
| 56 |
+
|
| 57 |
+
// This is a warning you get from visual studio 2003:
|
| 58 |
+
// warning C4345: behavior change: an object of POD type constructed with an initializer
|
| 59 |
+
// of the form () will be default-initialized.
|
| 60 |
+
// I love it when this compiler gives warnings about bugs in previous versions of itself.
|
| 61 |
+
#pragma warning(disable : 4345)
|
| 62 |
+
|
| 63 |
+
|
| 64 |
+
// Disable warnings about conversion from size_t to unsigned long and long.
|
| 65 |
+
#pragma warning(disable : 4267)
|
| 66 |
+
|
| 67 |
+
// Disable warnings about conversion from double to float
|
| 68 |
+
#pragma warning(disable : 4244)
|
| 69 |
+
#pragma warning(disable : 4305)
|
| 70 |
+
|
| 71 |
+
// Disable "warning C4180: qualifier applied to function type has no meaning; ignored".
|
| 72 |
+
// This warning happens often in generic code that works with functions and isn't useful.
|
| 73 |
+
#pragma warning(disable : 4180)
|
| 74 |
+
|
| 75 |
+
// Disable "warning C4290: C++ exception specification ignored except to indicate a function is not __declspec(nothrow)"
|
| 76 |
+
#pragma warning(disable : 4290)
|
| 77 |
+
|
| 78 |
+
|
| 79 |
+
// DNN module uses template-based network declaration that leads to very long
|
| 80 |
+
// type names. Visual Studio will produce Warning C4503 in such cases. https://msdn.microsoft.com/en-us/library/074af4b6.aspx says
|
| 81 |
+
// that correct binaries are still produced even when this warning happens, but linker errors from visual studio, if they occur could be confusing.
|
| 82 |
+
#pragma warning( disable: 4503 )
|
| 83 |
+
|
| 84 |
+
|
| 85 |
+
#endif
|
| 86 |
+
|
| 87 |
+
#ifdef __BORLANDC__
|
| 88 |
+
// Disable the following warnings for the Borland Compilers
|
| 89 |
+
//
|
| 90 |
+
// These warnings just say that the compiler is refusing to inline functions with
|
| 91 |
+
// loops or try blocks in them.
|
| 92 |
+
//
|
| 93 |
+
#pragma option -w-8027
|
| 94 |
+
#pragma option -w-8026
|
| 95 |
+
#endif
|
| 96 |
+
|
| 97 |
+
#include <string> // for the exceptions
|
| 98 |
+
|
| 99 |
+
#ifdef __CYGWIN__
|
| 100 |
+
namespace std
|
| 101 |
+
{
|
| 102 |
+
typedef std::basic_string<wchar_t> wstring;
|
| 103 |
+
}
|
| 104 |
+
#endif
|
| 105 |
+
|
| 106 |
+
#include "platform.h"
|
| 107 |
+
#include "windows_magic.h"
|
| 108 |
+
|
| 109 |
+
|
| 110 |
+
#include <algorithm> // for std::swap
|
| 111 |
+
#include <new> // for std::bad_alloc
|
| 112 |
+
#include <cstdlib>
|
| 113 |
+
#include <stddef.h>
|
| 114 |
+
#include <limits>
|
| 115 |
+
#include <cmath> // for std::isfinite for is_finite()
|
| 116 |
+
#include "assert.h"
|
| 117 |
+
#include "error.h"
|
| 118 |
+
#include "noncopyable.h"
|
| 119 |
+
#include "enable_if.h"
|
| 120 |
+
#include "uintn.h"
|
| 121 |
+
#include "numeric_constants.h"
|
| 122 |
+
#include "memory_manager_stateless/memory_manager_stateless_kernel_1.h" // for the default memory manager
|
| 123 |
+
#include "type_traits.h"
|
| 124 |
+
|
| 125 |
+
// ----------------------------------------------------------------------------------------
|
| 126 |
+
/*!A _dT !*/
|
| 127 |
+
|
| 128 |
+
template <typename charT>
|
| 129 |
+
inline charT _dTcast (const char a, const wchar_t b);
|
| 130 |
+
template <>
|
| 131 |
+
inline char _dTcast<char> (const char a, const wchar_t ) { return a; }
|
| 132 |
+
template <>
|
| 133 |
+
inline wchar_t _dTcast<wchar_t> (const char , const wchar_t b) { return b; }
|
| 134 |
+
|
| 135 |
+
template <typename charT>
|
| 136 |
+
inline const charT* _dTcast ( const char* a, const wchar_t* b);
|
| 137 |
+
template <>
|
| 138 |
+
inline const char* _dTcast<char> ( const char* a, const wchar_t* ) { return a; }
|
| 139 |
+
template <>
|
| 140 |
+
inline const wchar_t* _dTcast<wchar_t> ( const char* , const wchar_t* b) { return b; }
|
| 141 |
+
|
| 142 |
+
|
| 143 |
+
#define _dT(charT,str) _dTcast<charT>(str,L##str)
|
| 144 |
+
/*!
|
| 145 |
+
requires
|
| 146 |
+
- charT == char or wchar_t
|
| 147 |
+
- str == a string or character literal
|
| 148 |
+
ensures
|
| 149 |
+
- returns the literal in the form of a charT type literal.
|
| 150 |
+
!*/
|
| 151 |
+
|
| 152 |
+
// ----------------------------------------------------------------------------------------
|
| 153 |
+
|
| 154 |
+
|
| 155 |
+
|
| 156 |
+
namespace dlib
|
| 157 |
+
{
|
| 158 |
+
|
| 159 |
+
// ----------------------------------------------------------------------------------------
|
| 160 |
+
|
| 161 |
+
/*!A default_memory_manager
|
| 162 |
+
|
| 163 |
+
This memory manager just calls new and delete directly.
|
| 164 |
+
|
| 165 |
+
!*/
|
| 166 |
+
typedef memory_manager_stateless_kernel_1<char> default_memory_manager;
|
| 167 |
+
|
| 168 |
+
// ----------------------------------------------------------------------------------------
|
| 169 |
+
|
| 170 |
+
/*!A swap !*/
|
| 171 |
+
// make swap available in the dlib namespace
|
| 172 |
+
using std::swap;
|
| 173 |
+
|
| 174 |
+
// ----------------------------------------------------------------------------------------
|
| 175 |
+
|
| 176 |
+
/*!
|
| 177 |
+
Here is where I define my return codes. It is
|
| 178 |
+
important that they all be < 0.
|
| 179 |
+
!*/
|
| 180 |
+
|
| 181 |
+
enum general_return_codes
|
| 182 |
+
{
|
| 183 |
+
TIMEOUT = -1,
|
| 184 |
+
WOULDBLOCK = -2,
|
| 185 |
+
OTHER_ERROR = -3,
|
| 186 |
+
SHUTDOWN = -4,
|
| 187 |
+
PORTINUSE = -5
|
| 188 |
+
};
|
| 189 |
+
|
| 190 |
+
// ----------------------------------------------------------------------------------------
|
| 191 |
+
|
| 192 |
+
inline unsigned long square_root (
|
| 193 |
+
unsigned long value
|
| 194 |
+
)
|
| 195 |
+
/*!
|
| 196 |
+
requires
|
| 197 |
+
- value <= 2^32 - 1
|
| 198 |
+
ensures
|
| 199 |
+
- returns the square root of value. if the square root is not an
|
| 200 |
+
integer then it will be rounded up to the nearest integer.
|
| 201 |
+
!*/
|
| 202 |
+
{
|
| 203 |
+
unsigned long x;
|
| 204 |
+
|
| 205 |
+
// set the initial guess for what the root is depending on
|
| 206 |
+
// how big value is
|
| 207 |
+
if (value < 3)
|
| 208 |
+
return value;
|
| 209 |
+
else if (value < 4096) // 12
|
| 210 |
+
x = 45;
|
| 211 |
+
else if (value < 65536) // 16
|
| 212 |
+
x = 179;
|
| 213 |
+
else if (value < 1048576) // 20
|
| 214 |
+
x = 717;
|
| 215 |
+
else if (value < 16777216) // 24
|
| 216 |
+
x = 2867;
|
| 217 |
+
else if (value < 268435456) // 28
|
| 218 |
+
x = 11469;
|
| 219 |
+
else // 32
|
| 220 |
+
x = 45875;
|
| 221 |
+
|
| 222 |
+
|
| 223 |
+
|
| 224 |
+
// find the root
|
| 225 |
+
x = (x + value/x)>>1;
|
| 226 |
+
x = (x + value/x)>>1;
|
| 227 |
+
x = (x + value/x)>>1;
|
| 228 |
+
x = (x + value/x)>>1;
|
| 229 |
+
|
| 230 |
+
|
| 231 |
+
|
| 232 |
+
if (x*x < value)
|
| 233 |
+
return x+1;
|
| 234 |
+
else
|
| 235 |
+
return x;
|
| 236 |
+
}
|
| 237 |
+
|
| 238 |
+
// ----------------------------------------------------------------------------------------
|
| 239 |
+
|
| 240 |
+
template <
|
| 241 |
+
typename T
|
| 242 |
+
>
|
| 243 |
+
void median (
|
| 244 |
+
T& one,
|
| 245 |
+
T& two,
|
| 246 |
+
T& three
|
| 247 |
+
);
|
| 248 |
+
/*!
|
| 249 |
+
requires
|
| 250 |
+
- T implements operator<
|
| 251 |
+
- T is swappable by a global swap()
|
| 252 |
+
ensures
|
| 253 |
+
- #one is the median
|
| 254 |
+
- #one, #two, and #three is some permutation of one, two, and three.
|
| 255 |
+
!*/
|
| 256 |
+
|
| 257 |
+
|
| 258 |
+
template <
|
| 259 |
+
typename T
|
| 260 |
+
>
|
| 261 |
+
void median (
|
| 262 |
+
T& one,
|
| 263 |
+
T& two,
|
| 264 |
+
T& three
|
| 265 |
+
)
|
| 266 |
+
{
|
| 267 |
+
using std::swap;
|
| 268 |
+
using dlib::swap;
|
| 269 |
+
|
| 270 |
+
if ( one < two )
|
| 271 |
+
{
|
| 272 |
+
// one < two
|
| 273 |
+
if ( two < three )
|
| 274 |
+
{
|
| 275 |
+
// one < two < three : two
|
| 276 |
+
swap(one,two);
|
| 277 |
+
|
| 278 |
+
}
|
| 279 |
+
else
|
| 280 |
+
{
|
| 281 |
+
// one < two >= three
|
| 282 |
+
if ( one < three)
|
| 283 |
+
{
|
| 284 |
+
// three
|
| 285 |
+
swap(three,one);
|
| 286 |
+
}
|
| 287 |
+
}
|
| 288 |
+
|
| 289 |
+
}
|
| 290 |
+
else
|
| 291 |
+
{
|
| 292 |
+
// one >= two
|
| 293 |
+
if ( three < one )
|
| 294 |
+
{
|
| 295 |
+
// three <= one >= two
|
| 296 |
+
if ( three < two )
|
| 297 |
+
{
|
| 298 |
+
// two
|
| 299 |
+
swap(two,one);
|
| 300 |
+
}
|
| 301 |
+
else
|
| 302 |
+
{
|
| 303 |
+
// three
|
| 304 |
+
swap(three,one);
|
| 305 |
+
}
|
| 306 |
+
}
|
| 307 |
+
}
|
| 308 |
+
}
|
| 309 |
+
|
| 310 |
+
// ----------------------------------------------------------------------------------------
|
| 311 |
+
|
| 312 |
+
namespace relational_operators
|
| 313 |
+
{
|
| 314 |
+
template <
|
| 315 |
+
typename A,
|
| 316 |
+
typename B
|
| 317 |
+
>
|
| 318 |
+
constexpr bool operator> (
|
| 319 |
+
const A& a,
|
| 320 |
+
const B& b
|
| 321 |
+
) { return b < a; }
|
| 322 |
+
|
| 323 |
+
// ---------------------------------
|
| 324 |
+
|
| 325 |
+
template <
|
| 326 |
+
typename A,
|
| 327 |
+
typename B
|
| 328 |
+
>
|
| 329 |
+
constexpr bool operator!= (
|
| 330 |
+
const A& a,
|
| 331 |
+
const B& b
|
| 332 |
+
) { return !(a == b); }
|
| 333 |
+
|
| 334 |
+
// ---------------------------------
|
| 335 |
+
|
| 336 |
+
template <
|
| 337 |
+
typename A,
|
| 338 |
+
typename B
|
| 339 |
+
>
|
| 340 |
+
constexpr bool operator<= (
|
| 341 |
+
const A& a,
|
| 342 |
+
const B& b
|
| 343 |
+
) { return !(b < a); }
|
| 344 |
+
|
| 345 |
+
// ---------------------------------
|
| 346 |
+
|
| 347 |
+
template <
|
| 348 |
+
typename A,
|
| 349 |
+
typename B
|
| 350 |
+
>
|
| 351 |
+
constexpr bool operator>= (
|
| 352 |
+
const A& a,
|
| 353 |
+
const B& b
|
| 354 |
+
) { return !(a < b); }
|
| 355 |
+
|
| 356 |
+
}
|
| 357 |
+
|
| 358 |
+
// ----------------------------------------------------------------------------------------
|
| 359 |
+
|
| 360 |
+
template <
|
| 361 |
+
typename T
|
| 362 |
+
>
|
| 363 |
+
void exchange (
|
| 364 |
+
T& a,
|
| 365 |
+
T& b
|
| 366 |
+
)
|
| 367 |
+
/*!
|
| 368 |
+
This function does the exact same thing that global swap does and it does it by
|
| 369 |
+
just calling swap. But a lot of compilers have problems doing a Koenig Lookup
|
| 370 |
+
and the fact that this has a different name (global swap has the same name as
|
| 371 |
+
the member functions called swap) makes them compile right.
|
| 372 |
+
|
| 373 |
+
So this is a workaround but not too ugly of one. But hopefully I can get
|
| 374 |
+
rid of this in a few years. So this function is already deprecated.
|
| 375 |
+
|
| 376 |
+
This also means you should NOT use this function in your own code unless
|
| 377 |
+
you have to support an old buggy compiler that benefits from this hack.
|
| 378 |
+
!*/
|
| 379 |
+
{
|
| 380 |
+
using std::swap;
|
| 381 |
+
using dlib::swap;
|
| 382 |
+
swap(a,b);
|
| 383 |
+
}
|
| 384 |
+
|
| 385 |
+
// ----------------------------------------------------------------------------------------
|
| 386 |
+
|
| 387 |
+
struct general_ {};
|
| 388 |
+
struct special_ : general_ {};
|
| 389 |
+
template<typename> struct int_ { typedef int type; };
|
| 390 |
+
|
| 391 |
+
// ----------------------------------------------------------------------------------------
|
| 392 |
+
|
| 393 |
+
|
| 394 |
+
/*!A is_same_object
|
| 395 |
+
|
| 396 |
+
This is a templated function which checks if both of its arguments are actually
|
| 397 |
+
references to the same object. It returns true if they are and false otherwise.
|
| 398 |
+
|
| 399 |
+
!*/
|
| 400 |
+
|
| 401 |
+
// handle the case where T and U are unrelated types.
|
| 402 |
+
template < typename T, typename U >
|
| 403 |
+
std::enable_if_t<!std::is_convertible<T*, U*>::value && !std::is_convertible<U*,T*>::value, bool>
|
| 404 |
+
is_same_object (
|
| 405 |
+
const T& a,
|
| 406 |
+
const U& b
|
| 407 |
+
)
|
| 408 |
+
{
|
| 409 |
+
return ((void*)&a == (void*)&b);
|
| 410 |
+
}
|
| 411 |
+
|
| 412 |
+
// handle the case where T and U are related types because their pointers can be
|
| 413 |
+
// implicitly converted into one or the other. E.g. a derived class and its base class.
|
| 414 |
+
// Or where both T and U are just the same type. This way we make sure that if there is a
|
| 415 |
+
// valid way to convert between these two pointer types then we will take that route rather
|
| 416 |
+
// than the void* approach used otherwise.
|
| 417 |
+
template < typename T, typename U >
|
| 418 |
+
std::enable_if_t<std::is_convertible<T*, U*>::value || std::is_convertible<U*,T*>::value, bool>
|
| 419 |
+
is_same_object (
|
| 420 |
+
const T& a,
|
| 421 |
+
const U& b
|
| 422 |
+
)
|
| 423 |
+
{
|
| 424 |
+
return (&a == &b);
|
| 425 |
+
}
|
| 426 |
+
|
| 427 |
+
// ----------------------------------------------------------------------------------------
|
| 428 |
+
|
| 429 |
+
template <
|
| 430 |
+
typename T
|
| 431 |
+
>
|
| 432 |
+
class copy_functor
|
| 433 |
+
{
|
| 434 |
+
public:
|
| 435 |
+
void operator() (
|
| 436 |
+
const T& source,
|
| 437 |
+
T& destination
|
| 438 |
+
) const
|
| 439 |
+
{
|
| 440 |
+
destination = source;
|
| 441 |
+
}
|
| 442 |
+
};
|
| 443 |
+
|
| 444 |
+
// ----------------------------------------------------------------------------------------
|
| 445 |
+
|
| 446 |
+
/*!A static_switch
|
| 447 |
+
|
| 448 |
+
To use this template you give it some number of boolean expressions and it
|
| 449 |
+
tells you which one of them is true. If more than one of them is true then
|
| 450 |
+
it causes a compile time error.
|
| 451 |
+
|
| 452 |
+
for example:
|
| 453 |
+
static_switch<1 + 1 == 2, 4 - 1 == 4>::value == 1 // because the first expression is true
|
| 454 |
+
static_switch<1 + 1 == 3, 4 == 4>::value == 2 // because the second expression is true
|
| 455 |
+
static_switch<1 + 1 == 3, 4 == 5>::value == 0 // 0 here because none of them are true
|
| 456 |
+
static_switch<1 + 1 == 2, 4 == 4>::value == compiler error // because more than one expression is true
|
| 457 |
+
!*/
|
| 458 |
+
|
| 459 |
+
template < bool v1 = 0, bool v2 = 0, bool v3 = 0, bool v4 = 0, bool v5 = 0,
|
| 460 |
+
bool v6 = 0, bool v7 = 0, bool v8 = 0, bool v9 = 0, bool v10 = 0,
|
| 461 |
+
bool v11 = 0, bool v12 = 0, bool v13 = 0, bool v14 = 0, bool v15 = 0 >
|
| 462 |
+
struct static_switch;
|
| 463 |
+
|
| 464 |
+
template <> struct static_switch<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0> { const static int value = 0; };
|
| 465 |
+
template <> struct static_switch<1,0,0,0,0,0,0,0,0,0,0,0,0,0,0> { const static int value = 1; };
|
| 466 |
+
template <> struct static_switch<0,1,0,0,0,0,0,0,0,0,0,0,0,0,0> { const static int value = 2; };
|
| 467 |
+
template <> struct static_switch<0,0,1,0,0,0,0,0,0,0,0,0,0,0,0> { const static int value = 3; };
|
| 468 |
+
template <> struct static_switch<0,0,0,1,0,0,0,0,0,0,0,0,0,0,0> { const static int value = 4; };
|
| 469 |
+
template <> struct static_switch<0,0,0,0,1,0,0,0,0,0,0,0,0,0,0> { const static int value = 5; };
|
| 470 |
+
template <> struct static_switch<0,0,0,0,0,1,0,0,0,0,0,0,0,0,0> { const static int value = 6; };
|
| 471 |
+
template <> struct static_switch<0,0,0,0,0,0,1,0,0,0,0,0,0,0,0> { const static int value = 7; };
|
| 472 |
+
template <> struct static_switch<0,0,0,0,0,0,0,1,0,0,0,0,0,0,0> { const static int value = 8; };
|
| 473 |
+
template <> struct static_switch<0,0,0,0,0,0,0,0,1,0,0,0,0,0,0> { const static int value = 9; };
|
| 474 |
+
template <> struct static_switch<0,0,0,0,0,0,0,0,0,1,0,0,0,0,0> { const static int value = 10; };
|
| 475 |
+
template <> struct static_switch<0,0,0,0,0,0,0,0,0,0,1,0,0,0,0> { const static int value = 11; };
|
| 476 |
+
template <> struct static_switch<0,0,0,0,0,0,0,0,0,0,0,1,0,0,0> { const static int value = 12; };
|
| 477 |
+
template <> struct static_switch<0,0,0,0,0,0,0,0,0,0,0,0,1,0,0> { const static int value = 13; };
|
| 478 |
+
template <> struct static_switch<0,0,0,0,0,0,0,0,0,0,0,0,0,1,0> { const static int value = 14; };
|
| 479 |
+
template <> struct static_switch<0,0,0,0,0,0,0,0,0,0,0,0,0,0,1> { const static int value = 15; };
|
| 480 |
+
|
| 481 |
+
// ----------------------------------------------------------------------------------------
|
| 482 |
+
|
| 483 |
+
template <typename T>
|
| 484 |
+
std::enable_if_t<std::is_floating_point<T>::value, bool> is_finite(T value)
|
| 485 |
+
/*!
|
| 486 |
+
requires
|
| 487 |
+
- value must be some kind of scalar type such as int or double
|
| 488 |
+
ensures
|
| 489 |
+
- returns true if value is a finite value (e.g. not infinity or NaN) and false
|
| 490 |
+
otherwise.
|
| 491 |
+
!*/
|
| 492 |
+
{
|
| 493 |
+
return std::isfinite(value);
|
| 494 |
+
}
|
| 495 |
+
|
| 496 |
+
template <typename T>
|
| 497 |
+
std::enable_if_t<std::is_integral<T>::value, bool> is_finite(T value)
|
| 498 |
+
{
|
| 499 |
+
return std::isfinite((double)value);
|
| 500 |
+
}
|
| 501 |
+
|
| 502 |
+
// ----------------------------------------------------------------------------------------
|
| 503 |
+
|
| 504 |
+
/*!A promote
|
| 505 |
+
|
| 506 |
+
This is a template that takes one of the built in scalar types and gives you another
|
| 507 |
+
scalar type that should be big enough to hold sums of values from the original scalar
|
| 508 |
+
type. The new scalar type will also always be signed.
|
| 509 |
+
|
| 510 |
+
For example, promote<uint16>::type == int32
|
| 511 |
+
!*/
|
| 512 |
+
|
| 513 |
+
template <typename T, size_t s = sizeof(T)> struct promote;
|
| 514 |
+
template <typename T> struct promote<T,1> { typedef int32 type; };
|
| 515 |
+
template <typename T> struct promote<T,2> { typedef int32 type; };
|
| 516 |
+
template <typename T> struct promote<T,4> { typedef int64 type; };
|
| 517 |
+
template <typename T> struct promote<T,8> { typedef int64 type; };
|
| 518 |
+
|
| 519 |
+
template <> struct promote<float,sizeof(float)> { typedef double type; };
|
| 520 |
+
template <> struct promote<double,sizeof(double)> { typedef double type; };
|
| 521 |
+
template <> struct promote<long double,sizeof(long double)> { typedef long double type; };
|
| 522 |
+
|
| 523 |
+
// ----------------------------------------------------------------------------------------
|
| 524 |
+
|
| 525 |
+
/*!A assign_zero_if_built_in_scalar_type
|
| 526 |
+
|
| 527 |
+
This function assigns its argument the value of 0 if it is a built in scalar
|
| 528 |
+
type according to the is_built_in_scalar_type<> template. If it isn't a
|
| 529 |
+
built in scalar type then it does nothing.
|
| 530 |
+
!*/
|
| 531 |
+
|
| 532 |
+
template <typename T> inline typename disable_if<is_built_in_scalar_type<T>,void>::type assign_zero_if_built_in_scalar_type (T&){}
|
| 533 |
+
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;}
|
| 534 |
+
|
| 535 |
+
// ----------------------------------------------------------------------------------------
|
| 536 |
+
|
| 537 |
+
template <typename T>
|
| 538 |
+
T put_in_range (
|
| 539 |
+
const T& a,
|
| 540 |
+
const T& b,
|
| 541 |
+
const T& val
|
| 542 |
+
)
|
| 543 |
+
/*!
|
| 544 |
+
requires
|
| 545 |
+
- T is a type that looks like double, float, int, or so forth
|
| 546 |
+
ensures
|
| 547 |
+
- if (val is within the range [a,b]) then
|
| 548 |
+
- returns val
|
| 549 |
+
- else
|
| 550 |
+
- returns the end of the range [a,b] that is closest to val
|
| 551 |
+
!*/
|
| 552 |
+
{
|
| 553 |
+
if (a < b)
|
| 554 |
+
{
|
| 555 |
+
if (val < a)
|
| 556 |
+
return a;
|
| 557 |
+
else if (val > b)
|
| 558 |
+
return b;
|
| 559 |
+
}
|
| 560 |
+
else
|
| 561 |
+
{
|
| 562 |
+
if (val < b)
|
| 563 |
+
return b;
|
| 564 |
+
else if (val > a)
|
| 565 |
+
return a;
|
| 566 |
+
}
|
| 567 |
+
|
| 568 |
+
return val;
|
| 569 |
+
}
|
| 570 |
+
|
| 571 |
+
// overload for double
|
| 572 |
+
inline double put_in_range(const double& a, const double& b, const double& val)
|
| 573 |
+
{ return put_in_range<double>(a,b,val); }
|
| 574 |
+
|
| 575 |
+
// ----------------------------------------------------------------------------------------
|
| 576 |
+
|
| 577 |
+
/*!A tabs
|
| 578 |
+
|
| 579 |
+
This is a template to compute the absolute value a number at compile time.
|
| 580 |
+
|
| 581 |
+
For example,
|
| 582 |
+
abs<-4>::value == 4
|
| 583 |
+
abs<4>::value == 4
|
| 584 |
+
!*/
|
| 585 |
+
|
| 586 |
+
template <long x, typename enabled=void>
|
| 587 |
+
struct tabs { const static long value = x; };
|
| 588 |
+
template <long x>
|
| 589 |
+
struct tabs<x,typename enable_if_c<(x < 0)>::type> { const static long value = -x; };
|
| 590 |
+
|
| 591 |
+
// ----------------------------------------------------------------------------------------
|
| 592 |
+
|
| 593 |
+
/*!A tmax
|
| 594 |
+
|
| 595 |
+
This is a template to compute the max of two values at compile time
|
| 596 |
+
|
| 597 |
+
For example,
|
| 598 |
+
abs<4,7>::value == 7
|
| 599 |
+
!*/
|
| 600 |
+
|
| 601 |
+
template <long x, long y, typename enabled=void>
|
| 602 |
+
struct tmax { const static long value = x; };
|
| 603 |
+
template <long x, long y>
|
| 604 |
+
struct tmax<x,y,typename enable_if_c<(y > x)>::type> { const static long value = y; };
|
| 605 |
+
|
| 606 |
+
// ----------------------------------------------------------------------------------------
|
| 607 |
+
|
| 608 |
+
/*!A tmin
|
| 609 |
+
|
| 610 |
+
This is a template to compute the min of two values at compile time
|
| 611 |
+
|
| 612 |
+
For example,
|
| 613 |
+
abs<4,7>::value == 4
|
| 614 |
+
!*/
|
| 615 |
+
|
| 616 |
+
template <long x, long y, typename enabled=void>
|
| 617 |
+
struct tmin { const static long value = x; };
|
| 618 |
+
template <long x, long y>
|
| 619 |
+
struct tmin<x,y,typename enable_if_c<(y < x)>::type> { const static long value = y; };
|
| 620 |
+
|
| 621 |
+
// ----------------------------------------------------------------------------------------
|
| 622 |
+
|
| 623 |
+
#define DLIB_MAKE_HAS_MEMBER_FUNCTION_TEST(testname, returnT, funct_name, args) \
|
| 624 |
+
struct _two_bytes_##testname { char a[2]; }; \
|
| 625 |
+
template < typename T, returnT (T::*funct)args > \
|
| 626 |
+
struct _helper_##testname { typedef char type; }; \
|
| 627 |
+
template <typename T> \
|
| 628 |
+
static char _has_##testname##_helper( typename _helper_##testname<T,&T::funct_name >::type ) { return 0;} \
|
| 629 |
+
template <typename T> \
|
| 630 |
+
static _two_bytes_##testname _has_##testname##_helper(int) { return _two_bytes_##testname();} \
|
| 631 |
+
template <typename T> struct _##testname##workaroundbug { \
|
| 632 |
+
const static unsigned long U = sizeof(_has_##testname##_helper<T>('a')); }; \
|
| 633 |
+
template <typename T, unsigned long U = _##testname##workaroundbug<T>::U > \
|
| 634 |
+
struct testname { static const bool value = false; }; \
|
| 635 |
+
template <typename T> \
|
| 636 |
+
struct testname<T,1> { static const bool value = true; };
|
| 637 |
+
/*!A DLIB_MAKE_HAS_MEMBER_FUNCTION_TEST
|
| 638 |
+
|
| 639 |
+
The DLIB_MAKE_HAS_MEMBER_FUNCTION_TEST() macro is used to define traits templates
|
| 640 |
+
that tell you if a class has a certain member function. For example, to make a
|
| 641 |
+
test to see if a class has a public method with the signature void print(int) you
|
| 642 |
+
would say:
|
| 643 |
+
DLIB_MAKE_HAS_MEMBER_FUNCTION_TEST(has_print, void, print, (int))
|
| 644 |
+
|
| 645 |
+
Then you can check if a class, T, has this method by looking at the boolean value:
|
| 646 |
+
has_print<T>::value
|
| 647 |
+
which will be true if the member function is in the T class.
|
| 648 |
+
|
| 649 |
+
Note that you can test for member functions taking no arguments by simply passing
|
| 650 |
+
in empty () like so:
|
| 651 |
+
DLIB_MAKE_HAS_MEMBER_FUNCTION_TEST(has_print, void, print, ())
|
| 652 |
+
This would test for a member of the form:
|
| 653 |
+
void print().
|
| 654 |
+
|
| 655 |
+
To test for const member functions you would use a statement such as this:
|
| 656 |
+
DLIB_MAKE_HAS_MEMBER_FUNCTION_TEST(has_print, void, print, ()const)
|
| 657 |
+
This would test for a member of the form:
|
| 658 |
+
void print() const.
|
| 659 |
+
|
| 660 |
+
To test for const templated member functions you would use a statement such as this:
|
| 661 |
+
DLIB_MAKE_HAS_MEMBER_FUNCTION_TEST(has_print, void, template print<int>, ())
|
| 662 |
+
This would test for a member of the form:
|
| 663 |
+
template <typename T> void print().
|
| 664 |
+
!*/
|
| 665 |
+
|
| 666 |
+
// ----------------------------------------------------------------------------------------
|
| 667 |
+
|
| 668 |
+
template <typename T> class funct_wrap0
|
| 669 |
+
{
|
| 670 |
+
public:
|
| 671 |
+
funct_wrap0(T (&f_)()):f(f_){}
|
| 672 |
+
T operator()() const { return f(); }
|
| 673 |
+
private:
|
| 674 |
+
T (&f)();
|
| 675 |
+
};
|
| 676 |
+
template <typename T, typename A0> class funct_wrap1
|
| 677 |
+
{
|
| 678 |
+
public:
|
| 679 |
+
funct_wrap1(T (&f_)(A0)):f(f_){}
|
| 680 |
+
T operator()(A0 a0) const { return f(a0); }
|
| 681 |
+
private:
|
| 682 |
+
T (&f)(A0);
|
| 683 |
+
};
|
| 684 |
+
template <typename T, typename A0, typename A1> class funct_wrap2
|
| 685 |
+
{
|
| 686 |
+
public:
|
| 687 |
+
funct_wrap2(T (&f_)(A0,A1)):f(f_){}
|
| 688 |
+
T operator()(A0 a0, A1 a1) const { return f(a0,a1); }
|
| 689 |
+
private:
|
| 690 |
+
T (&f)(A0,A1);
|
| 691 |
+
};
|
| 692 |
+
template <typename T, typename A0, typename A1, typename A2> class funct_wrap3
|
| 693 |
+
{
|
| 694 |
+
public:
|
| 695 |
+
funct_wrap3(T (&f_)(A0,A1,A2)):f(f_){}
|
| 696 |
+
T operator()(A0 a0, A1 a1, A2 a2) const { return f(a0,a1,a2); }
|
| 697 |
+
private:
|
| 698 |
+
T (&f)(A0,A1,A2);
|
| 699 |
+
};
|
| 700 |
+
template <typename T, typename A0, typename A1, typename A2, typename A3> class funct_wrap4
|
| 701 |
+
{
|
| 702 |
+
public:
|
| 703 |
+
funct_wrap4(T (&f_)(A0,A1,A2,A3)):f(f_){}
|
| 704 |
+
T operator()(A0 a0, A1 a1, A2 a2, A3 a3) const { return f(a0,a1,a2,a3); }
|
| 705 |
+
private:
|
| 706 |
+
T (&f)(A0,A1,A2,A3);
|
| 707 |
+
};
|
| 708 |
+
template <typename T, typename A0, typename A1, typename A2, typename A3, typename A4> class funct_wrap5
|
| 709 |
+
{
|
| 710 |
+
public:
|
| 711 |
+
funct_wrap5(T (&f_)(A0,A1,A2,A3,A4)):f(f_){}
|
| 712 |
+
T operator()(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) const { return f(a0,a1,a2,a3,a4); }
|
| 713 |
+
private:
|
| 714 |
+
T (&f)(A0,A1,A2,A3,A4);
|
| 715 |
+
};
|
| 716 |
+
|
| 717 |
+
/*!A wrap_function
|
| 718 |
+
|
| 719 |
+
This is a template that allows you to turn a global function into a
|
| 720 |
+
function object. The reason for this template's existence is so you can
|
| 721 |
+
do stuff like this:
|
| 722 |
+
|
| 723 |
+
template <typename T>
|
| 724 |
+
void call_funct(const T& funct)
|
| 725 |
+
{ cout << funct(); }
|
| 726 |
+
|
| 727 |
+
std::string test() { return "asdfasf"; }
|
| 728 |
+
|
| 729 |
+
int main()
|
| 730 |
+
{
|
| 731 |
+
call_funct(wrap_function(test));
|
| 732 |
+
}
|
| 733 |
+
|
| 734 |
+
The above code doesn't work right on some compilers if you don't
|
| 735 |
+
use wrap_function.
|
| 736 |
+
!*/
|
| 737 |
+
|
| 738 |
+
template <typename T>
|
| 739 |
+
funct_wrap0<T> wrap_function(T (&f)()) { return funct_wrap0<T>(f); }
|
| 740 |
+
template <typename T, typename A0>
|
| 741 |
+
funct_wrap1<T,A0> wrap_function(T (&f)(A0)) { return funct_wrap1<T,A0>(f); }
|
| 742 |
+
template <typename T, typename A0, typename A1>
|
| 743 |
+
funct_wrap2<T,A0,A1> wrap_function(T (&f)(A0, A1)) { return funct_wrap2<T,A0,A1>(f); }
|
| 744 |
+
template <typename T, typename A0, typename A1, typename A2>
|
| 745 |
+
funct_wrap3<T,A0,A1,A2> wrap_function(T (&f)(A0, A1, A2)) { return funct_wrap3<T,A0,A1,A2>(f); }
|
| 746 |
+
template <typename T, typename A0, typename A1, typename A2, typename A3>
|
| 747 |
+
funct_wrap4<T,A0,A1,A2,A3> wrap_function(T (&f)(A0, A1, A2, A3)) { return funct_wrap4<T,A0,A1,A2,A3>(f); }
|
| 748 |
+
template <typename T, typename A0, typename A1, typename A2, typename A3, typename A4>
|
| 749 |
+
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); }
|
| 750 |
+
|
| 751 |
+
// ----------------------------------------------------------------------------------------
|
| 752 |
+
|
| 753 |
+
template <unsigned long bSIZE>
|
| 754 |
+
class stack_based_memory_block : noncopyable
|
| 755 |
+
{
|
| 756 |
+
/*!
|
| 757 |
+
WHAT THIS OBJECT REPRESENTS
|
| 758 |
+
This object is a simple container for a block of memory
|
| 759 |
+
of bSIZE bytes. This memory block is located on the stack
|
| 760 |
+
and properly aligned to hold any kind of object.
|
| 761 |
+
!*/
|
| 762 |
+
public:
|
| 763 |
+
static const unsigned long size = bSIZE;
|
| 764 |
+
|
| 765 |
+
stack_based_memory_block(): data(mem.data) {}
|
| 766 |
+
|
| 767 |
+
void* get () { return data; }
|
| 768 |
+
/*!
|
| 769 |
+
ensures
|
| 770 |
+
- returns a pointer to the block of memory contained in this object
|
| 771 |
+
!*/
|
| 772 |
+
|
| 773 |
+
const void* get () const { return data; }
|
| 774 |
+
/*!
|
| 775 |
+
ensures
|
| 776 |
+
- returns a pointer to the block of memory contained in this object
|
| 777 |
+
!*/
|
| 778 |
+
|
| 779 |
+
private:
|
| 780 |
+
|
| 781 |
+
// You obviously can't have a block of memory that has zero bytes in it.
|
| 782 |
+
COMPILE_TIME_ASSERT(bSIZE > 0);
|
| 783 |
+
|
| 784 |
+
union mem_block
|
| 785 |
+
{
|
| 786 |
+
// All of this garbage is to make sure this union is properly aligned
|
| 787 |
+
// (a union is always aligned such that everything in it would be properly
|
| 788 |
+
// aligned. So the assumption here is that one of these objects has
|
| 789 |
+
// a large enough alignment requirement to satisfy any object this
|
| 790 |
+
// block of memory might be cast into).
|
| 791 |
+
void* void_ptr;
|
| 792 |
+
int integer;
|
| 793 |
+
struct {
|
| 794 |
+
void (stack_based_memory_block::*callback)();
|
| 795 |
+
stack_based_memory_block* o;
|
| 796 |
+
} stuff;
|
| 797 |
+
long double more_stuff;
|
| 798 |
+
|
| 799 |
+
uint64 var1;
|
| 800 |
+
uint32 var2;
|
| 801 |
+
double var3;
|
| 802 |
+
|
| 803 |
+
char data[size];
|
| 804 |
+
} mem;
|
| 805 |
+
|
| 806 |
+
// The reason for having this variable is that doing it this way avoids
|
| 807 |
+
// warnings from gcc about violations of strict-aliasing rules.
|
| 808 |
+
void* const data;
|
| 809 |
+
};
|
| 810 |
+
|
| 811 |
+
// ----------------------------------------------------------------------------------------
|
| 812 |
+
|
| 813 |
+
template <
|
| 814 |
+
typename T,
|
| 815 |
+
typename F
|
| 816 |
+
>
|
| 817 |
+
auto max_scoring_element(
|
| 818 |
+
const T& container,
|
| 819 |
+
F score_func
|
| 820 |
+
) -> decltype(std::make_pair(*container.begin(), 0.0))
|
| 821 |
+
/*!
|
| 822 |
+
requires
|
| 823 |
+
- container has .begin() and .end(), allowing it to be enumerated.
|
| 824 |
+
- score_func() is a function that takes an element of the container and returns a double.
|
| 825 |
+
ensures
|
| 826 |
+
- This function finds the element of container that has the largest score,
|
| 827 |
+
according to score_func(), and returns a std::pair containing that maximal
|
| 828 |
+
element along with the score.
|
| 829 |
+
- If the container is empty then make_pair(a default initialized object, -infinity) is returned.
|
| 830 |
+
!*/
|
| 831 |
+
{
|
| 832 |
+
double best_score = -std::numeric_limits<double>::infinity();
|
| 833 |
+
auto best_i = container.begin();
|
| 834 |
+
for (auto i = container.begin(); i != container.end(); ++i)
|
| 835 |
+
{
|
| 836 |
+
auto score = score_func(*i);
|
| 837 |
+
if (score > best_score)
|
| 838 |
+
{
|
| 839 |
+
best_score = score;
|
| 840 |
+
best_i = i;
|
| 841 |
+
}
|
| 842 |
+
}
|
| 843 |
+
|
| 844 |
+
using item_type = typename std::remove_reference<decltype(*best_i)>::type;
|
| 845 |
+
|
| 846 |
+
if (best_i == container.end())
|
| 847 |
+
return std::make_pair(item_type(), best_score);
|
| 848 |
+
else
|
| 849 |
+
return std::make_pair(*best_i, best_score);
|
| 850 |
+
}
|
| 851 |
+
|
| 852 |
+
// ----------------------------------------------------------------------------------------
|
| 853 |
+
|
| 854 |
+
template <
|
| 855 |
+
typename T,
|
| 856 |
+
typename F
|
| 857 |
+
>
|
| 858 |
+
auto min_scoring_element(
|
| 859 |
+
const T& container,
|
| 860 |
+
F score_func
|
| 861 |
+
) -> decltype(std::make_pair(*container.begin(), 0.0))
|
| 862 |
+
/*!
|
| 863 |
+
requires
|
| 864 |
+
- container has .begin() and .end(), allowing it to be enumerated.
|
| 865 |
+
- score_func() is a function that takes an element of the container and returns a double.
|
| 866 |
+
ensures
|
| 867 |
+
- This function finds the element of container that has the smallest score,
|
| 868 |
+
according to score_func(), and returns a std::pair containing that minimal
|
| 869 |
+
element along with the score.
|
| 870 |
+
- If the container is empty then make_pair(a default initialized object, infinity) is returned.
|
| 871 |
+
!*/
|
| 872 |
+
{
|
| 873 |
+
double best_score = std::numeric_limits<double>::infinity();
|
| 874 |
+
auto best_i = container.begin();
|
| 875 |
+
for (auto i = container.begin(); i != container.end(); ++i)
|
| 876 |
+
{
|
| 877 |
+
auto score = score_func(*i);
|
| 878 |
+
if (score < best_score)
|
| 879 |
+
{
|
| 880 |
+
best_score = score;
|
| 881 |
+
best_i = i;
|
| 882 |
+
}
|
| 883 |
+
}
|
| 884 |
+
|
| 885 |
+
using item_type = typename std::remove_reference<decltype(*best_i)>::type;
|
| 886 |
+
|
| 887 |
+
if (best_i == container.end())
|
| 888 |
+
return std::make_pair(item_type(), best_score);
|
| 889 |
+
else
|
| 890 |
+
return std::make_pair(*best_i, best_score);
|
| 891 |
+
}
|
| 892 |
+
|
| 893 |
+
// ----------------------------------------------------------------------------------------
|
| 894 |
+
|
| 895 |
+
namespace detail
|
| 896 |
+
{
|
| 897 |
+
template <class Tuple, class F, std::size_t... I>
|
| 898 |
+
constexpr void for_each_impl(Tuple&& t, F&& f, std::index_sequence<I...>)
|
| 899 |
+
{
|
| 900 |
+
#ifdef __cpp_fold_expressions
|
| 901 |
+
(std::forward<F>(f)(std::get<I>(std::forward<Tuple>(t))),...);
|
| 902 |
+
#else
|
| 903 |
+
(void)std::initializer_list<int>{(std::forward<F>(f)(std::get<I>(std::forward<Tuple>(t))),0)...};
|
| 904 |
+
#endif
|
| 905 |
+
}
|
| 906 |
+
}
|
| 907 |
+
|
| 908 |
+
template <class Tuple, class F>
|
| 909 |
+
constexpr void for_each_in_tuple(Tuple&& t, F&& f)
|
| 910 |
+
{
|
| 911 |
+
detail::for_each_impl(std::forward<Tuple>(t), std::forward<F>(f),
|
| 912 |
+
std::make_index_sequence<std::tuple_size<std::remove_reference_t<Tuple>>::value>{});
|
| 913 |
+
}
|
| 914 |
+
|
| 915 |
+
// ----------------------------------------------------------------------------------------
|
| 916 |
+
}
|
| 917 |
+
|
| 918 |
+
#endif // DLIB_ALGs_
|
| 919 |
+
|
difpoint/lib/dlib/dlib/all/source.cpp
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Copyright (C) 2006 Davis E. King (davis@dlib.net)
|
| 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 |
+
|
difpoint/lib/dlib/dlib/any.h
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Copyright (C) 2010 Davis E. King (davis@dlib.net)
|
| 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 |
+
|
difpoint/lib/dlib/dlib/any/any.h
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Copyright (C) 2010 Davis E. King (davis@dlib.net)
|
| 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 <memory>
|
| 8 |
+
#include "storage.h"
|
| 9 |
+
|
| 10 |
+
namespace dlib
|
| 11 |
+
{
|
| 12 |
+
// ----------------------------------------------------------------------------------------
|
| 13 |
+
|
| 14 |
+
class any
|
| 15 |
+
{
|
| 16 |
+
public:
|
| 17 |
+
any() = default;
|
| 18 |
+
any(const any& other) = default;
|
| 19 |
+
any& operator=(const any& other) = default;
|
| 20 |
+
any(any&& other) = default;
|
| 21 |
+
any& operator=(any&& other) = default;
|
| 22 |
+
|
| 23 |
+
template<
|
| 24 |
+
typename T,
|
| 25 |
+
std::enable_if_t<!std::is_same<std::decay_t<T>, any>::value, bool> = true
|
| 26 |
+
>
|
| 27 |
+
any(T&& item)
|
| 28 |
+
: storage{std::forward<T>(item)}
|
| 29 |
+
{
|
| 30 |
+
}
|
| 31 |
+
|
| 32 |
+
template<
|
| 33 |
+
typename T,
|
| 34 |
+
typename T_ = std::decay_t<T>,
|
| 35 |
+
std::enable_if_t<!std::is_same<T_, any>::value, bool> = true
|
| 36 |
+
>
|
| 37 |
+
any& operator=(T&& item)
|
| 38 |
+
{
|
| 39 |
+
if (contains<T_>())
|
| 40 |
+
storage.unsafe_get<T_>() = std::forward<T>(item);
|
| 41 |
+
else
|
| 42 |
+
*this = std::move(any{std::forward<T>(item)});
|
| 43 |
+
return *this;
|
| 44 |
+
}
|
| 45 |
+
|
| 46 |
+
bool is_empty() const { return storage.is_empty(); }
|
| 47 |
+
void clear() { storage.clear(); }
|
| 48 |
+
void swap (any& item) { std::swap(*this, item); }
|
| 49 |
+
|
| 50 |
+
template<typename T> bool contains() const { return storage.contains<T>();}
|
| 51 |
+
template <typename T> T& cast_to() { return storage.cast_to<T>(); }
|
| 52 |
+
template <typename T> const T& cast_to() const { return storage.cast_to<T>(); }
|
| 53 |
+
template <typename T> T& get() { return storage.get<T>(); }
|
| 54 |
+
|
| 55 |
+
private:
|
| 56 |
+
te::storage_heap storage;
|
| 57 |
+
};
|
| 58 |
+
|
| 59 |
+
// ----------------------------------------------------------------------------------------
|
| 60 |
+
|
| 61 |
+
template <typename T> T& any_cast(any& a) { return a.cast_to<T>(); }
|
| 62 |
+
template <typename T> const T& any_cast(const any& a) { return a.cast_to<T>(); }
|
| 63 |
+
|
| 64 |
+
// ----------------------------------------------------------------------------------------
|
| 65 |
+
|
| 66 |
+
}
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
#endif // DLIB_AnY_H_
|
| 70 |
+
|
| 71 |
+
|
| 72 |
+
|
difpoint/lib/dlib/dlib/any/any_abstract.h
ADDED
|
@@ -0,0 +1,209 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Copyright (C) 2010 Davis E. King (davis@dlib.net)
|
| 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 |
+
any_function (
|
| 67 |
+
any_function&& item
|
| 68 |
+
);
|
| 69 |
+
/*!
|
| 70 |
+
ensures
|
| 71 |
+
- #item.is_empty() == true
|
| 72 |
+
- moves item into *this.
|
| 73 |
+
!*/
|
| 74 |
+
|
| 75 |
+
template < typename T >
|
| 76 |
+
any (
|
| 77 |
+
const T& item
|
| 78 |
+
);
|
| 79 |
+
/*!
|
| 80 |
+
ensures
|
| 81 |
+
- #contains<T>() == true
|
| 82 |
+
- #cast_to<T>() == item
|
| 83 |
+
(i.e. a copy of item will be stored in *this)
|
| 84 |
+
!*/
|
| 85 |
+
|
| 86 |
+
void clear (
|
| 87 |
+
);
|
| 88 |
+
/*!
|
| 89 |
+
ensures
|
| 90 |
+
- #*this will have its default value. I.e. #is_empty() == true
|
| 91 |
+
!*/
|
| 92 |
+
|
| 93 |
+
template <typename T>
|
| 94 |
+
bool contains (
|
| 95 |
+
) const;
|
| 96 |
+
/*!
|
| 97 |
+
ensures
|
| 98 |
+
- if (this object currently contains an object of type T) then
|
| 99 |
+
- returns true
|
| 100 |
+
- else
|
| 101 |
+
- returns false
|
| 102 |
+
!*/
|
| 103 |
+
|
| 104 |
+
bool is_empty(
|
| 105 |
+
) const;
|
| 106 |
+
/*!
|
| 107 |
+
ensures
|
| 108 |
+
- if (this object contains any kind of object) then
|
| 109 |
+
- returns false
|
| 110 |
+
- else
|
| 111 |
+
- returns true
|
| 112 |
+
!*/
|
| 113 |
+
|
| 114 |
+
template <typename T>
|
| 115 |
+
T& cast_to(
|
| 116 |
+
);
|
| 117 |
+
/*!
|
| 118 |
+
ensures
|
| 119 |
+
- if (contains<T>() == true) then
|
| 120 |
+
- returns a non-const reference to the object contained within *this
|
| 121 |
+
- else
|
| 122 |
+
- throws bad_any_cast
|
| 123 |
+
!*/
|
| 124 |
+
|
| 125 |
+
template <typename T>
|
| 126 |
+
const T& cast_to(
|
| 127 |
+
) const;
|
| 128 |
+
/*!
|
| 129 |
+
ensures
|
| 130 |
+
- if (contains<T>() == true) then
|
| 131 |
+
- returns a const reference to the object contained within *this
|
| 132 |
+
- else
|
| 133 |
+
- throws bad_any_cast
|
| 134 |
+
!*/
|
| 135 |
+
|
| 136 |
+
template <typename T>
|
| 137 |
+
T& get(
|
| 138 |
+
);
|
| 139 |
+
/*!
|
| 140 |
+
ensures
|
| 141 |
+
- #is_empty() == false
|
| 142 |
+
- #contains<T>() == true
|
| 143 |
+
- if (contains<T>() == true)
|
| 144 |
+
- returns a non-const reference to the object contained in *this.
|
| 145 |
+
- else
|
| 146 |
+
- Constructs an object of type T inside *this
|
| 147 |
+
- Any previous object stored in this any object is destructed and its
|
| 148 |
+
state is lost.
|
| 149 |
+
- returns a non-const reference to the newly created T object.
|
| 150 |
+
!*/
|
| 151 |
+
|
| 152 |
+
any& operator= (
|
| 153 |
+
const any& item
|
| 154 |
+
);
|
| 155 |
+
/*!
|
| 156 |
+
ensures
|
| 157 |
+
- copies the state of item into *this.
|
| 158 |
+
- Note that *this and item will contain independent copies of the
|
| 159 |
+
contents of item. That is, this function performs a deep
|
| 160 |
+
copy and therefore does not result in *this containing
|
| 161 |
+
any kind of reference to item.
|
| 162 |
+
!*/
|
| 163 |
+
|
| 164 |
+
void swap (
|
| 165 |
+
any& item
|
| 166 |
+
);
|
| 167 |
+
/*!
|
| 168 |
+
ensures
|
| 169 |
+
- swaps *this and item
|
| 170 |
+
- does not invalidate pointers or references to the object contained
|
| 171 |
+
inside *this or item. Moreover, a pointer or reference to the object in
|
| 172 |
+
*this will now refer to the contents of #item and vice versa.
|
| 173 |
+
!*/
|
| 174 |
+
|
| 175 |
+
};
|
| 176 |
+
|
| 177 |
+
// ----------------------------------------------------------------------------------------
|
| 178 |
+
|
| 179 |
+
template <
|
| 180 |
+
typename T
|
| 181 |
+
>
|
| 182 |
+
T& any_cast(
|
| 183 |
+
any& a
|
| 184 |
+
) { return a.cast_to<T>(); }
|
| 185 |
+
/*!
|
| 186 |
+
ensures
|
| 187 |
+
- returns a.cast_to<T>()
|
| 188 |
+
!*/
|
| 189 |
+
|
| 190 |
+
// ----------------------------------------------------------------------------------------
|
| 191 |
+
|
| 192 |
+
template <
|
| 193 |
+
typename T
|
| 194 |
+
>
|
| 195 |
+
const T& any_cast(
|
| 196 |
+
const any& a
|
| 197 |
+
) { return a.cast_to<T>(); }
|
| 198 |
+
/*!
|
| 199 |
+
ensures
|
| 200 |
+
- returns a.cast_to<T>()
|
| 201 |
+
!*/
|
| 202 |
+
|
| 203 |
+
// ----------------------------------------------------------------------------------------
|
| 204 |
+
|
| 205 |
+
}
|
| 206 |
+
|
| 207 |
+
#endif // DLIB_AnY_ABSTRACT_H_
|
| 208 |
+
|
| 209 |
+
|
difpoint/lib/dlib/dlib/any/any_decision_function.h
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Copyright (C) 2010 Davis E. King (davis@dlib.net)
|
| 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_decision_function_abstract.h"
|
| 7 |
+
#include "any_function.h"
|
| 8 |
+
#include "../algs.h"
|
| 9 |
+
|
| 10 |
+
namespace dlib
|
| 11 |
+
{
|
| 12 |
+
|
| 13 |
+
// ----------------------------------------------------------------------------------------
|
| 14 |
+
|
| 15 |
+
template <class sample_type, class result_type = double>
|
| 16 |
+
using any_decision_function = any_function<result_type(const sample_type&)>;
|
| 17 |
+
|
| 18 |
+
// ----------------------------------------------------------------------------------------
|
| 19 |
+
|
| 20 |
+
}
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
#endif // DLIB_AnY_DECISION_FUNCTION_Hh_
|
difpoint/lib/dlib/dlib/any/any_decision_function_abstract.h
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Copyright (C) 2010 Davis E. King (davis@dlib.net)
|
| 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_function_abstract.h"
|
| 7 |
+
#include "../algs.h"
|
| 8 |
+
|
| 9 |
+
namespace dlib
|
| 10 |
+
{
|
| 11 |
+
|
| 12 |
+
// ----------------------------------------------------------------------------------------
|
| 13 |
+
|
| 14 |
+
template <class sample_type, class result_type = double>
|
| 15 |
+
using any_decision_function = any_function<result_type(const sample_type&)>;
|
| 16 |
+
|
| 17 |
+
// ----------------------------------------------------------------------------------------
|
| 18 |
+
|
| 19 |
+
}
|
| 20 |
+
|
| 21 |
+
#endif // DLIB_AnY_DECISION_FUNCTION_ABSTRACT_H_
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
|
difpoint/lib/dlib/dlib/any/any_function.h
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Copyright (C) 2011 Davis E. King (davis@dlib.net)
|
| 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 "../assert.h"
|
| 7 |
+
#include "../functional.h"
|
| 8 |
+
#include "any.h"
|
| 9 |
+
#include "any_function_abstract.h"
|
| 10 |
+
|
| 11 |
+
namespace dlib
|
| 12 |
+
{
|
| 13 |
+
|
| 14 |
+
// ----------------------------------------------------------------------------------------
|
| 15 |
+
|
| 16 |
+
template <
|
| 17 |
+
class Storage,
|
| 18 |
+
class F
|
| 19 |
+
>
|
| 20 |
+
class any_function_basic;
|
| 21 |
+
|
| 22 |
+
template <
|
| 23 |
+
class Storage,
|
| 24 |
+
class R,
|
| 25 |
+
class... Args
|
| 26 |
+
>
|
| 27 |
+
class any_function_basic<Storage, R(Args...)>
|
| 28 |
+
{
|
| 29 |
+
private:
|
| 30 |
+
template<class F>
|
| 31 |
+
using is_valid = std::enable_if_t<!std::is_same<std::decay_t<F>, any_function_basic>::value &&
|
| 32 |
+
dlib::is_invocable_r<R, F, Args...>::value,
|
| 33 |
+
bool>;
|
| 34 |
+
|
| 35 |
+
template<typename Func>
|
| 36 |
+
static auto make_invoker()
|
| 37 |
+
{
|
| 38 |
+
return [](void* self, Args... args) -> R {
|
| 39 |
+
return dlib::invoke(*reinterpret_cast<std::add_pointer_t<Func>>(self),
|
| 40 |
+
std::forward<Args>(args)...);
|
| 41 |
+
};
|
| 42 |
+
}
|
| 43 |
+
|
| 44 |
+
Storage str;
|
| 45 |
+
R (*func)(void*, Args...) = nullptr;
|
| 46 |
+
|
| 47 |
+
public:
|
| 48 |
+
|
| 49 |
+
using result_type = R;
|
| 50 |
+
|
| 51 |
+
constexpr any_function_basic(std::nullptr_t) noexcept {}
|
| 52 |
+
constexpr any_function_basic() = default;
|
| 53 |
+
constexpr any_function_basic(const any_function_basic& other) = default;
|
| 54 |
+
constexpr any_function_basic& operator=(const any_function_basic& other) = default;
|
| 55 |
+
|
| 56 |
+
constexpr any_function_basic(any_function_basic&& other)
|
| 57 |
+
: str{std::move(other.str)},
|
| 58 |
+
func{std::exchange(other.func, nullptr)}
|
| 59 |
+
{
|
| 60 |
+
}
|
| 61 |
+
|
| 62 |
+
constexpr any_function_basic& operator=(any_function_basic&& other)
|
| 63 |
+
{
|
| 64 |
+
if (this != &other)
|
| 65 |
+
{
|
| 66 |
+
str = std::move(other.str);
|
| 67 |
+
func = std::exchange(other.func, nullptr);
|
| 68 |
+
}
|
| 69 |
+
|
| 70 |
+
return *this;
|
| 71 |
+
}
|
| 72 |
+
|
| 73 |
+
template<class F, is_valid<F> = true>
|
| 74 |
+
any_function_basic(
|
| 75 |
+
F&& f
|
| 76 |
+
) : str{std::forward<F>(f)},
|
| 77 |
+
func{make_invoker<F&&>()}
|
| 78 |
+
{
|
| 79 |
+
}
|
| 80 |
+
|
| 81 |
+
template<class F, is_valid<F> = true>
|
| 82 |
+
any_function_basic(
|
| 83 |
+
F* f
|
| 84 |
+
) : str{f},
|
| 85 |
+
func{make_invoker<F*>()}
|
| 86 |
+
{
|
| 87 |
+
}
|
| 88 |
+
|
| 89 |
+
R operator()(Args... args) const {
|
| 90 |
+
return func(const_cast<void*>(str.get_ptr()), std::forward<Args>(args)...);
|
| 91 |
+
}
|
| 92 |
+
|
| 93 |
+
void clear() { str.clear(); }
|
| 94 |
+
void swap (any_function_basic& item) { std::swap(*this, item); }
|
| 95 |
+
bool is_empty() const noexcept { return str.is_empty() || func == nullptr; }
|
| 96 |
+
bool is_set() const noexcept { return !is_empty(); }
|
| 97 |
+
explicit operator bool() const noexcept { return is_set(); }
|
| 98 |
+
|
| 99 |
+
template <typename T> bool contains() const { return str.template contains<T>();}
|
| 100 |
+
template <typename T> T& cast_to() { return str.template cast_to<T>(); }
|
| 101 |
+
template <typename T> const T& cast_to() const { return str.template cast_to<T>(); }
|
| 102 |
+
template <typename T> T& get() { return str.template get<T>(); }
|
| 103 |
+
};
|
| 104 |
+
|
| 105 |
+
// ----------------------------------------------------------------------------------------
|
| 106 |
+
|
| 107 |
+
template <class T, class Storage, class F>
|
| 108 |
+
T& any_cast(any_function_basic<Storage, F>& a) { return a.template cast_to<T>(); }
|
| 109 |
+
|
| 110 |
+
template <class T, class Storage, class F>
|
| 111 |
+
const T& any_cast(const any_function_basic<Storage, F>& a) { return a.template cast_to<T>(); }
|
| 112 |
+
|
| 113 |
+
// ----------------------------------------------------------------------------------------
|
| 114 |
+
|
| 115 |
+
template <class F>
|
| 116 |
+
using any_function = any_function_basic<te::storage_sbo<16>, F>;
|
| 117 |
+
|
| 118 |
+
template <class F>
|
| 119 |
+
using any_function_view = any_function_basic<te::storage_view, F>;
|
| 120 |
+
|
| 121 |
+
// ----------------------------------------------------------------------------------------
|
| 122 |
+
|
| 123 |
+
}
|
| 124 |
+
|
| 125 |
+
#endif // DLIB_AnY_FUNCTION_Hh_
|
| 126 |
+
|
difpoint/lib/dlib/dlib/any/any_function_abstract.h
ADDED
|
@@ -0,0 +1,274 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Copyright (C) 2011 Davis E. King (davis@dlib.net)
|
| 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 |
+
class Storage,
|
| 16 |
+
typename function_type
|
| 17 |
+
>
|
| 18 |
+
class any_function_basic
|
| 19 |
+
{
|
| 20 |
+
/*!
|
| 21 |
+
REQUIREMENTS ON Storage
|
| 22 |
+
This must be one of the storage types from dlib/any/storage.hh
|
| 23 |
+
E.g. storage_heap, storage_stack, etc.
|
| 24 |
+
|
| 25 |
+
It determines the method by which any_function_basic holds onto the function it uses.
|
| 26 |
+
|
| 27 |
+
REQUIREMENTS ON function_type
|
| 28 |
+
This type should be a function signature. Some examples are:
|
| 29 |
+
void (int,int) // a function returning nothing and taking two ints
|
| 30 |
+
void () // a function returning nothing and taking no arguments
|
| 31 |
+
char (double&) // a function returning a char and taking a reference to a double
|
| 32 |
+
|
| 33 |
+
The number of arguments in the function must be no greater than 10.
|
| 34 |
+
|
| 35 |
+
INITIAL VALUE
|
| 36 |
+
- is_empty() == true
|
| 37 |
+
- for all T: contains<T>() == false
|
| 38 |
+
|
| 39 |
+
WHAT THIS OBJECT REPRESENTS
|
| 40 |
+
This object is a version of dlib::any that is restricted to containing
|
| 41 |
+
elements which are some kind of function object with an operator() which
|
| 42 |
+
matches the function signature defined by function_type.
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
Here is an example:
|
| 46 |
+
#include <iostream>
|
| 47 |
+
#include <string>
|
| 48 |
+
#include "dlib/any.h"
|
| 49 |
+
using namespace std;
|
| 50 |
+
void print_message(string str) { cout << str << endl; }
|
| 51 |
+
|
| 52 |
+
int main()
|
| 53 |
+
{
|
| 54 |
+
dlib::any_function<void(string)> f;
|
| 55 |
+
f = print_message;
|
| 56 |
+
f("hello world"); // calls print_message("hello world")
|
| 57 |
+
}
|
| 58 |
+
|
| 59 |
+
Note that any_function_basic objects can be used to store general function
|
| 60 |
+
objects (i.e. defined by a class with an overloaded operator()) in
|
| 61 |
+
addition to regular global functions.
|
| 62 |
+
!*/
|
| 63 |
+
|
| 64 |
+
public:
|
| 65 |
+
|
| 66 |
+
// This is the type of object returned by function_type functions.
|
| 67 |
+
typedef result_type_for_function_type result_type;
|
| 68 |
+
|
| 69 |
+
any_function_basic(
|
| 70 |
+
);
|
| 71 |
+
/*!
|
| 72 |
+
ensures
|
| 73 |
+
- this object is properly initialized
|
| 74 |
+
!*/
|
| 75 |
+
|
| 76 |
+
any_function_basic (
|
| 77 |
+
const any_function_basic& 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 |
+
any_function_basic (
|
| 89 |
+
any_function_basic&& item
|
| 90 |
+
);
|
| 91 |
+
/*!
|
| 92 |
+
ensures
|
| 93 |
+
- moves item into *this.
|
| 94 |
+
- The exact move semantics are determined by which Storage type is used. E.g.
|
| 95 |
+
storage_heap will result in #item.is_empty()==true but storage_view would result
|
| 96 |
+
in #item.is_empty() == false
|
| 97 |
+
!*/
|
| 98 |
+
|
| 99 |
+
template < typename Funct >
|
| 100 |
+
any_function_basic (
|
| 101 |
+
Funct&& funct
|
| 102 |
+
);
|
| 103 |
+
/*!
|
| 104 |
+
ensures
|
| 105 |
+
- #contains<T>() == true
|
| 106 |
+
- #cast_to<T>() == item
|
| 107 |
+
(i.e. calling operator() will invoke funct())
|
| 108 |
+
!*/
|
| 109 |
+
|
| 110 |
+
void clear (
|
| 111 |
+
);
|
| 112 |
+
/*!
|
| 113 |
+
ensures
|
| 114 |
+
- #*this will have its default value. I.e. #is_empty() == true
|
| 115 |
+
!*/
|
| 116 |
+
|
| 117 |
+
template <typename T>
|
| 118 |
+
bool contains (
|
| 119 |
+
) const;
|
| 120 |
+
/*!
|
| 121 |
+
ensures
|
| 122 |
+
- if (this object currently contains an object of type T) then
|
| 123 |
+
- returns true
|
| 124 |
+
- else
|
| 125 |
+
- returns false
|
| 126 |
+
!*/
|
| 127 |
+
|
| 128 |
+
bool is_empty(
|
| 129 |
+
) const;
|
| 130 |
+
/*!
|
| 131 |
+
ensures
|
| 132 |
+
- if (this object contains any kind of object) then
|
| 133 |
+
- returns false
|
| 134 |
+
- else
|
| 135 |
+
- returns true
|
| 136 |
+
!*/
|
| 137 |
+
|
| 138 |
+
bool is_set (
|
| 139 |
+
) const;
|
| 140 |
+
/*!
|
| 141 |
+
ensures
|
| 142 |
+
- returns !is_empty()
|
| 143 |
+
!*/
|
| 144 |
+
|
| 145 |
+
explicit operator bool(
|
| 146 |
+
) const;
|
| 147 |
+
/*!
|
| 148 |
+
ensures
|
| 149 |
+
- returns is_set()
|
| 150 |
+
!*/
|
| 151 |
+
|
| 152 |
+
result_type operator(Args... args) (
|
| 153 |
+
) const;
|
| 154 |
+
/*!
|
| 155 |
+
requires
|
| 156 |
+
- is_empty() == false
|
| 157 |
+
- the signature defined by function_type takes no arguments
|
| 158 |
+
ensures
|
| 159 |
+
- Let F denote the function object contained within *this. Then
|
| 160 |
+
this function performs:
|
| 161 |
+
return F(std::forward<Args>(args)...)
|
| 162 |
+
!*/
|
| 163 |
+
|
| 164 |
+
template <typename T>
|
| 165 |
+
T& cast_to(
|
| 166 |
+
);
|
| 167 |
+
/*!
|
| 168 |
+
ensures
|
| 169 |
+
- if (contains<T>() == true) then
|
| 170 |
+
- returns a non-const reference to the object contained within *this
|
| 171 |
+
- else
|
| 172 |
+
- throws bad_any_cast
|
| 173 |
+
!*/
|
| 174 |
+
|
| 175 |
+
template <typename T>
|
| 176 |
+
const T& cast_to(
|
| 177 |
+
) const;
|
| 178 |
+
/*!
|
| 179 |
+
ensures
|
| 180 |
+
- if (contains<T>() == true) then
|
| 181 |
+
- returns a const reference to the object contained within *this
|
| 182 |
+
- else
|
| 183 |
+
- throws bad_any_cast
|
| 184 |
+
!*/
|
| 185 |
+
|
| 186 |
+
template <typename T>
|
| 187 |
+
T& get(
|
| 188 |
+
);
|
| 189 |
+
/*!
|
| 190 |
+
ensures
|
| 191 |
+
- #is_empty() == false
|
| 192 |
+
- #contains<T>() == true
|
| 193 |
+
- if (contains<T>() == true)
|
| 194 |
+
- returns a non-const reference to the object contained in *this.
|
| 195 |
+
- else
|
| 196 |
+
- Constructs an object of type T inside *this
|
| 197 |
+
- Any previous object stored in this any_function_basic object is destructed and its
|
| 198 |
+
state is lost.
|
| 199 |
+
- returns a non-const reference to the newly created T object.
|
| 200 |
+
!*/
|
| 201 |
+
|
| 202 |
+
any_function_basic& operator= (
|
| 203 |
+
const any_function_basic& item
|
| 204 |
+
);
|
| 205 |
+
/*!
|
| 206 |
+
ensures
|
| 207 |
+
- copies the state of item into *this.
|
| 208 |
+
- Note that the type of copy is determined by the Storage template argument. E.g.
|
| 209 |
+
storage_sbo will result in a deep copy, while storage_view would result in *this
|
| 210 |
+
and item referring to the same underlying function.
|
| 211 |
+
!*/
|
| 212 |
+
|
| 213 |
+
void swap (
|
| 214 |
+
any_function_basic& item
|
| 215 |
+
);
|
| 216 |
+
/*!
|
| 217 |
+
ensures
|
| 218 |
+
- swaps *this and item
|
| 219 |
+
!*/
|
| 220 |
+
|
| 221 |
+
};
|
| 222 |
+
|
| 223 |
+
// ----------------------------------------------------------------------------------------
|
| 224 |
+
|
| 225 |
+
template <
|
| 226 |
+
typename T,
|
| 227 |
+
typename function_type
|
| 228 |
+
>
|
| 229 |
+
T& any_cast(
|
| 230 |
+
any_function_basic<function_type>& a
|
| 231 |
+
) { return a.cast_to<T>(); }
|
| 232 |
+
/*!
|
| 233 |
+
ensures
|
| 234 |
+
- returns a.cast_to<T>()
|
| 235 |
+
!*/
|
| 236 |
+
|
| 237 |
+
// ----------------------------------------------------------------------------------------
|
| 238 |
+
|
| 239 |
+
template <
|
| 240 |
+
typename T,
|
| 241 |
+
typename function_type
|
| 242 |
+
>
|
| 243 |
+
const T& any_cast(
|
| 244 |
+
const any_function_basic<function_type>& a
|
| 245 |
+
) { return a.cast_to<T>(); }
|
| 246 |
+
/*!
|
| 247 |
+
ensures
|
| 248 |
+
- returns a.cast_to<T>()
|
| 249 |
+
!*/
|
| 250 |
+
|
| 251 |
+
// ----------------------------------------------------------------------------------------
|
| 252 |
+
|
| 253 |
+
/*!A any_function
|
| 254 |
+
|
| 255 |
+
A version of any_function_basic (defined above) that owns the function it contains. Uses
|
| 256 |
+
the small buffer optimization to make working with small lambdas faster.
|
| 257 |
+
!*/
|
| 258 |
+
template <class F>
|
| 259 |
+
using any_function = any_function_basic<te::storage_sbo<16>, F>;
|
| 260 |
+
|
| 261 |
+
/*!A any_function_view
|
| 262 |
+
|
| 263 |
+
A version of any_function_basic (defined above) that *DOES NOT* own the function it
|
| 264 |
+
contains. It merely holds a pointer to the function given to its constructor.
|
| 265 |
+
!*/
|
| 266 |
+
template <class F>
|
| 267 |
+
using any_function_view = any_function_basic<te::storage_view, F>;
|
| 268 |
+
|
| 269 |
+
// ----------------------------------------------------------------------------------------
|
| 270 |
+
|
| 271 |
+
}
|
| 272 |
+
|
| 273 |
+
#endif // DLIB_AnY_FUNCTION_ABSTRACT_H_
|
| 274 |
+
|
difpoint/lib/dlib/dlib/any/any_trainer.h
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Copyright (C) 2010 Davis E. King (davis@dlib.net)
|
| 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 |
+
#include "any_decision_function.h"
|
| 8 |
+
#include "any_trainer_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 |
+
public:
|
| 23 |
+
using sample_type = sample_type_;
|
| 24 |
+
using scalar_type = scalar_type_;
|
| 25 |
+
using mem_manager_type = default_memory_manager;
|
| 26 |
+
using trained_function_type = any_decision_function<sample_type, scalar_type>;
|
| 27 |
+
|
| 28 |
+
any_trainer() = default;
|
| 29 |
+
any_trainer(const any_trainer& other) = default;
|
| 30 |
+
any_trainer& operator=(const any_trainer& other) = default;
|
| 31 |
+
any_trainer(any_trainer&& other) = default;
|
| 32 |
+
any_trainer& operator=(any_trainer&& other) = default;
|
| 33 |
+
|
| 34 |
+
template <
|
| 35 |
+
class T,
|
| 36 |
+
class T_ = std::decay_t<T>,
|
| 37 |
+
std::enable_if_t<!std::is_same<T_,any_trainer>::value, bool> = true
|
| 38 |
+
>
|
| 39 |
+
any_trainer (
|
| 40 |
+
T&& item
|
| 41 |
+
) : storage{std::forward<T>(item)},
|
| 42 |
+
train_func{[](
|
| 43 |
+
const void* ptr,
|
| 44 |
+
const std::vector<sample_type>& samples,
|
| 45 |
+
const std::vector<scalar_type>& labels
|
| 46 |
+
) -> trained_function_type {
|
| 47 |
+
const T_& f = *reinterpret_cast<const T_*>(ptr);
|
| 48 |
+
return f.train(samples, labels);
|
| 49 |
+
}}
|
| 50 |
+
{
|
| 51 |
+
}
|
| 52 |
+
|
| 53 |
+
template <
|
| 54 |
+
class T,
|
| 55 |
+
class T_ = std::decay_t<T>,
|
| 56 |
+
std::enable_if_t<!std::is_same<T_,any_trainer>::value, bool> = true
|
| 57 |
+
>
|
| 58 |
+
any_trainer& operator= (
|
| 59 |
+
T&& item
|
| 60 |
+
)
|
| 61 |
+
{
|
| 62 |
+
if (contains<T_>())
|
| 63 |
+
storage.unsafe_get<T_>() = std::forward<T>(item);
|
| 64 |
+
else
|
| 65 |
+
*this = std::move(any_trainer{std::forward<T>(item)});
|
| 66 |
+
return *this;
|
| 67 |
+
}
|
| 68 |
+
|
| 69 |
+
trained_function_type train (
|
| 70 |
+
const std::vector<sample_type>& samples,
|
| 71 |
+
const std::vector<scalar_type>& labels
|
| 72 |
+
) const
|
| 73 |
+
{
|
| 74 |
+
// make sure requires clause is not broken
|
| 75 |
+
DLIB_ASSERT(is_empty() == false,
|
| 76 |
+
"\t trained_function_type any_trainer::train()"
|
| 77 |
+
<< "\n\t You can't call train() on an empty any_trainer"
|
| 78 |
+
<< "\n\t this: " << this
|
| 79 |
+
);
|
| 80 |
+
|
| 81 |
+
return train_func(storage.get_ptr(), samples, labels);
|
| 82 |
+
}
|
| 83 |
+
|
| 84 |
+
bool is_empty() const { return storage.is_empty(); }
|
| 85 |
+
void clear() { storage.clear(); }
|
| 86 |
+
void swap (any_trainer& item) { std::swap(*this, item); }
|
| 87 |
+
|
| 88 |
+
template <typename T> bool contains() const { return storage.contains<T>();}
|
| 89 |
+
template <typename T> T& cast_to() { return storage.cast_to<T>(); }
|
| 90 |
+
template <typename T> const T& cast_to() const { return storage.cast_to<T>(); }
|
| 91 |
+
template <typename T> T& get() { return storage.get<T>(); }
|
| 92 |
+
|
| 93 |
+
private:
|
| 94 |
+
te::storage_heap storage;
|
| 95 |
+
trained_function_type (*train_func) (
|
| 96 |
+
const void* self,
|
| 97 |
+
const std::vector<sample_type>& samples,
|
| 98 |
+
const std::vector<scalar_type>& labels
|
| 99 |
+
) = nullptr;
|
| 100 |
+
};
|
| 101 |
+
|
| 102 |
+
// ----------------------------------------------------------------------------------------
|
| 103 |
+
|
| 104 |
+
template <typename T, typename U, typename V>
|
| 105 |
+
T& any_cast(any_trainer<U,V>& a) { return a.template cast_to<T>(); }
|
| 106 |
+
|
| 107 |
+
template <typename T, typename U, typename V>
|
| 108 |
+
const T& any_cast(const any_trainer<U,V>& a) { return a.template cast_to<T>(); }
|
| 109 |
+
|
| 110 |
+
// ----------------------------------------------------------------------------------------
|
| 111 |
+
|
| 112 |
+
}
|
| 113 |
+
|
| 114 |
+
|
| 115 |
+
#endif // DLIB_AnY_TRAINER_H_
|
| 116 |
+
|
| 117 |
+
|
| 118 |
+
|
| 119 |
+
|
difpoint/lib/dlib/dlib/any/any_trainer_abstract.h
ADDED
|
@@ -0,0 +1,243 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Copyright (C) 2010 Davis E. King (davis@dlib.net)
|
| 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 |
+
any_trainer (
|
| 73 |
+
any_trainer&& item
|
| 74 |
+
);
|
| 75 |
+
/*!
|
| 76 |
+
ensures
|
| 77 |
+
- #item.is_empty() == true
|
| 78 |
+
- moves item into *this.
|
| 79 |
+
!*/
|
| 80 |
+
|
| 81 |
+
template < typename T >
|
| 82 |
+
any_trainer (
|
| 83 |
+
const T& item
|
| 84 |
+
);
|
| 85 |
+
/*!
|
| 86 |
+
ensures
|
| 87 |
+
- #contains<T>() == true
|
| 88 |
+
- #cast_to<T>() == item
|
| 89 |
+
(i.e. a copy of item will be stored in *this)
|
| 90 |
+
!*/
|
| 91 |
+
|
| 92 |
+
void clear (
|
| 93 |
+
);
|
| 94 |
+
/*!
|
| 95 |
+
ensures
|
| 96 |
+
- #*this will have its default value. I.e. #is_empty() == true
|
| 97 |
+
!*/
|
| 98 |
+
|
| 99 |
+
template <typename T>
|
| 100 |
+
bool contains (
|
| 101 |
+
) const;
|
| 102 |
+
/*!
|
| 103 |
+
ensures
|
| 104 |
+
- if (this object currently contains an object of type T) then
|
| 105 |
+
- returns true
|
| 106 |
+
- else
|
| 107 |
+
- returns false
|
| 108 |
+
!*/
|
| 109 |
+
|
| 110 |
+
bool is_empty(
|
| 111 |
+
) const;
|
| 112 |
+
/*!
|
| 113 |
+
ensures
|
| 114 |
+
- if (this object contains any kind of object) then
|
| 115 |
+
- returns false
|
| 116 |
+
- else
|
| 117 |
+
- returns true
|
| 118 |
+
!*/
|
| 119 |
+
|
| 120 |
+
trained_function_type train (
|
| 121 |
+
const std::vector<sample_type>& samples,
|
| 122 |
+
const std::vector<scalar_type>& labels
|
| 123 |
+
) const
|
| 124 |
+
/*!
|
| 125 |
+
requires
|
| 126 |
+
- is_empty() == false
|
| 127 |
+
ensures
|
| 128 |
+
- Let TRAINER denote the object contained within *this. Then
|
| 129 |
+
this function performs:
|
| 130 |
+
return TRAINER.train(samples, labels)
|
| 131 |
+
!*/
|
| 132 |
+
|
| 133 |
+
template <typename T>
|
| 134 |
+
T& cast_to(
|
| 135 |
+
);
|
| 136 |
+
/*!
|
| 137 |
+
ensures
|
| 138 |
+
- if (contains<T>() == true) then
|
| 139 |
+
- returns a non-const reference to the object contained within *this
|
| 140 |
+
- else
|
| 141 |
+
- throws bad_any_cast
|
| 142 |
+
!*/
|
| 143 |
+
|
| 144 |
+
template <typename T>
|
| 145 |
+
const T& cast_to(
|
| 146 |
+
) const;
|
| 147 |
+
/*!
|
| 148 |
+
ensures
|
| 149 |
+
- if (contains<T>() == true) then
|
| 150 |
+
- returns a const reference to the object contained within *this
|
| 151 |
+
- else
|
| 152 |
+
- throws bad_any_cast
|
| 153 |
+
!*/
|
| 154 |
+
|
| 155 |
+
template <typename T>
|
| 156 |
+
T& get(
|
| 157 |
+
);
|
| 158 |
+
/*!
|
| 159 |
+
ensures
|
| 160 |
+
- #is_empty() == false
|
| 161 |
+
- #contains<T>() == true
|
| 162 |
+
- if (contains<T>() == true)
|
| 163 |
+
- returns a non-const reference to the object contained in *this.
|
| 164 |
+
- else
|
| 165 |
+
- Constructs an object of type T inside *this
|
| 166 |
+
- Any previous object stored in this any_trainer object is destructed and its
|
| 167 |
+
state is lost.
|
| 168 |
+
- returns a non-const reference to the newly created T object.
|
| 169 |
+
!*/
|
| 170 |
+
|
| 171 |
+
any_trainer& operator= (
|
| 172 |
+
const any_trainer& item
|
| 173 |
+
);
|
| 174 |
+
/*!
|
| 175 |
+
ensures
|
| 176 |
+
- copies the state of item into *this.
|
| 177 |
+
- Note that *this and item will contain independent copies of the
|
| 178 |
+
contents of item. That is, this function performs a deep
|
| 179 |
+
copy and therefore does not result in *this containing
|
| 180 |
+
any kind of reference to item.
|
| 181 |
+
!*/
|
| 182 |
+
|
| 183 |
+
void swap (
|
| 184 |
+
any_trainer& item
|
| 185 |
+
);
|
| 186 |
+
/*!
|
| 187 |
+
ensures
|
| 188 |
+
- swaps *this and item
|
| 189 |
+
!*/
|
| 190 |
+
|
| 191 |
+
};
|
| 192 |
+
|
| 193 |
+
// ----------------------------------------------------------------------------------------
|
| 194 |
+
|
| 195 |
+
template <
|
| 196 |
+
typename sample_type,
|
| 197 |
+
typename scalar_type
|
| 198 |
+
>
|
| 199 |
+
inline void swap (
|
| 200 |
+
any_trainer<sample_type,scalar_type>& a,
|
| 201 |
+
any_trainer<sample_type,scalar_type>& b
|
| 202 |
+
) { a.swap(b); }
|
| 203 |
+
/*!
|
| 204 |
+
provides a global swap function
|
| 205 |
+
!*/
|
| 206 |
+
|
| 207 |
+
// ----------------------------------------------------------------------------------------
|
| 208 |
+
|
| 209 |
+
template <
|
| 210 |
+
typename T,
|
| 211 |
+
typename sample_type,
|
| 212 |
+
typename scalar_type
|
| 213 |
+
>
|
| 214 |
+
T& any_cast(
|
| 215 |
+
any_trainer<sample_type,scalar_type>& a
|
| 216 |
+
) { return a.cast_to<T>(); }
|
| 217 |
+
/*!
|
| 218 |
+
ensures
|
| 219 |
+
- returns a.cast_to<T>()
|
| 220 |
+
!*/
|
| 221 |
+
|
| 222 |
+
// ----------------------------------------------------------------------------------------
|
| 223 |
+
|
| 224 |
+
template <
|
| 225 |
+
typename T,
|
| 226 |
+
typename sample_type,
|
| 227 |
+
typename scalar_type
|
| 228 |
+
>
|
| 229 |
+
const T& any_cast(
|
| 230 |
+
const any_trainer<sample_type,scalar_type>& a
|
| 231 |
+
) { return a.cast_to<T>(); }
|
| 232 |
+
/*!
|
| 233 |
+
ensures
|
| 234 |
+
- returns a.cast_to<T>()
|
| 235 |
+
!*/
|
| 236 |
+
|
| 237 |
+
// ----------------------------------------------------------------------------------------
|
| 238 |
+
|
| 239 |
+
}
|
| 240 |
+
|
| 241 |
+
#endif // DLIB_AnY_TRAINER_ABSTRACT_H_
|
| 242 |
+
|
| 243 |
+
|
difpoint/lib/dlib/dlib/any/storage.h
ADDED
|
@@ -0,0 +1,977 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Copyright (C) 2022 Davis E. King (davis@dlib.net)
|
| 2 |
+
// License: Boost Software License See LICENSE.txt for the full license.
|
| 3 |
+
#ifndef DLIB_TYPE_ERASURE_H_
|
| 4 |
+
#define DLIB_TYPE_ERASURE_H_
|
| 5 |
+
|
| 6 |
+
#include <type_traits>
|
| 7 |
+
#include <utility>
|
| 8 |
+
#include <typeindex>
|
| 9 |
+
#include <new>
|
| 10 |
+
#include <memory>
|
| 11 |
+
#include "../assert.h"
|
| 12 |
+
|
| 13 |
+
namespace dlib
|
| 14 |
+
{
|
| 15 |
+
|
| 16 |
+
// -----------------------------------------------------------------------------------------------------
|
| 17 |
+
|
| 18 |
+
class bad_any_cast : public std::bad_cast
|
| 19 |
+
{
|
| 20 |
+
/*!
|
| 21 |
+
WHAT THIS OBJECT REPRESENTS
|
| 22 |
+
This object is the exception class used by the storage objects.
|
| 23 |
+
It is used to indicate when someone attempts to cast a storage
|
| 24 |
+
object into a type which isn't contained in the object.
|
| 25 |
+
!*/
|
| 26 |
+
|
| 27 |
+
public:
|
| 28 |
+
virtual const char * what() const throw()
|
| 29 |
+
{
|
| 30 |
+
return "bad_any_cast";
|
| 31 |
+
}
|
| 32 |
+
};
|
| 33 |
+
|
| 34 |
+
// -----------------------------------------------------------------------------------------------------
|
| 35 |
+
|
| 36 |
+
namespace te
|
| 37 |
+
{
|
| 38 |
+
|
| 39 |
+
/*!
|
| 40 |
+
This is used as a SFINAE tool to prevent a function taking a universal reference from
|
| 41 |
+
binding to some undesired type. For example:
|
| 42 |
+
template <
|
| 43 |
+
typename T,
|
| 44 |
+
T_is_not_this_type<SomeExcludedType, T> = true
|
| 45 |
+
>
|
| 46 |
+
void foo(T&&);
|
| 47 |
+
prevents foo() from binding to an object of type SomeExcludedType.
|
| 48 |
+
!*/
|
| 49 |
+
template<class Storage, class T>
|
| 50 |
+
using T_is_not_this_type = std::enable_if_t<!std::is_same<std::decay_t<T>, Storage>::value, bool>;
|
| 51 |
+
|
| 52 |
+
// -----------------------------------------------------------------------------------------------------
|
| 53 |
+
|
| 54 |
+
template<class Storage>
|
| 55 |
+
class storage_base
|
| 56 |
+
{
|
| 57 |
+
/*!
|
| 58 |
+
WHAT THIS OBJECT REPRESENTS
|
| 59 |
+
This class defines functionality common to all type erasure storage objects
|
| 60 |
+
(defined below in this file). These objects are essentially type-safe versions of
|
| 61 |
+
a void*. In particular, they are containers which can contain only one object
|
| 62 |
+
but the object may be of any type.
|
| 63 |
+
|
| 64 |
+
Each storage object implements a different way of storing the underlying object.
|
| 65 |
+
E.g. on the heap or stack or some other more specialized method.
|
| 66 |
+
!*/
|
| 67 |
+
|
| 68 |
+
public:
|
| 69 |
+
|
| 70 |
+
bool is_empty() const
|
| 71 |
+
/*!
|
| 72 |
+
ensures
|
| 73 |
+
- if (this object contains any kind of object) then
|
| 74 |
+
- returns false
|
| 75 |
+
- else
|
| 76 |
+
- returns true
|
| 77 |
+
!*/
|
| 78 |
+
{
|
| 79 |
+
const Storage& me = *static_cast<const Storage*>(this);
|
| 80 |
+
return me.get_ptr() == nullptr;
|
| 81 |
+
}
|
| 82 |
+
|
| 83 |
+
template<typename T>
|
| 84 |
+
bool contains() const
|
| 85 |
+
/*!
|
| 86 |
+
ensures
|
| 87 |
+
- if (this object currently contains an object of type T) then
|
| 88 |
+
- returns true
|
| 89 |
+
- else
|
| 90 |
+
- returns false
|
| 91 |
+
!*/
|
| 92 |
+
{
|
| 93 |
+
const Storage& me = *static_cast<const Storage*>(this);
|
| 94 |
+
return !is_empty() && me.type_id() == std::type_index{typeid(T)};
|
| 95 |
+
}
|
| 96 |
+
|
| 97 |
+
template<typename T>
|
| 98 |
+
T& unsafe_get()
|
| 99 |
+
/*!
|
| 100 |
+
requires
|
| 101 |
+
- contains<T>() == true
|
| 102 |
+
ensures
|
| 103 |
+
- returns a reference to the object contained within *this.
|
| 104 |
+
!*/
|
| 105 |
+
{
|
| 106 |
+
DLIB_ASSERT(contains<T>());
|
| 107 |
+
Storage& me = *static_cast<Storage*>(this);
|
| 108 |
+
return *reinterpret_cast<T*>(me.get_ptr());
|
| 109 |
+
}
|
| 110 |
+
|
| 111 |
+
template<typename T>
|
| 112 |
+
const T& unsafe_get() const
|
| 113 |
+
/*!
|
| 114 |
+
requires
|
| 115 |
+
- contains<T>() == true
|
| 116 |
+
ensures
|
| 117 |
+
- returns a const reference to the object contained within *this.
|
| 118 |
+
!*/
|
| 119 |
+
{
|
| 120 |
+
DLIB_ASSERT(contains<T>());
|
| 121 |
+
const Storage& me = *static_cast<const Storage*>(this);
|
| 122 |
+
return *reinterpret_cast<const T*>(me.get_ptr());
|
| 123 |
+
}
|
| 124 |
+
|
| 125 |
+
template <typename T>
|
| 126 |
+
T& get(
|
| 127 |
+
)
|
| 128 |
+
/*!
|
| 129 |
+
ensures
|
| 130 |
+
- #is_empty() == false
|
| 131 |
+
- #contains<T>() == true
|
| 132 |
+
- if (contains<T>() == true)
|
| 133 |
+
- returns a non-const reference to the object contained in *this.
|
| 134 |
+
- else
|
| 135 |
+
- Constructs an object of type T inside *this
|
| 136 |
+
- Any previous object stored in this any object is destructed and its
|
| 137 |
+
state is lost.
|
| 138 |
+
- returns a non-const reference to the newly created T object.
|
| 139 |
+
!*/
|
| 140 |
+
{
|
| 141 |
+
Storage& me = *static_cast<Storage*>(this);
|
| 142 |
+
|
| 143 |
+
if (!contains<T>())
|
| 144 |
+
me = T{};
|
| 145 |
+
return unsafe_get<T>();
|
| 146 |
+
}
|
| 147 |
+
|
| 148 |
+
template <typename T>
|
| 149 |
+
T& cast_to(
|
| 150 |
+
)
|
| 151 |
+
/*!
|
| 152 |
+
ensures
|
| 153 |
+
- if (contains<T>() == true) then
|
| 154 |
+
- returns a non-const reference to the object contained within *this
|
| 155 |
+
- else
|
| 156 |
+
- throws bad_any_cast
|
| 157 |
+
!*/
|
| 158 |
+
{
|
| 159 |
+
if (!contains<T>())
|
| 160 |
+
throw bad_any_cast{};
|
| 161 |
+
return unsafe_get<T>();
|
| 162 |
+
}
|
| 163 |
+
|
| 164 |
+
template <typename T>
|
| 165 |
+
const T& cast_to(
|
| 166 |
+
) const
|
| 167 |
+
/*!
|
| 168 |
+
ensures
|
| 169 |
+
- if (contains<T>() == true) then
|
| 170 |
+
- returns a const reference to the object contained within *this
|
| 171 |
+
- else
|
| 172 |
+
- throws bad_any_cast
|
| 173 |
+
!*/
|
| 174 |
+
{
|
| 175 |
+
if (!contains<T>())
|
| 176 |
+
throw bad_any_cast{};
|
| 177 |
+
return unsafe_get<T>();
|
| 178 |
+
}
|
| 179 |
+
};
|
| 180 |
+
|
| 181 |
+
// -----------------------------------------------------------------------------------------------------
|
| 182 |
+
|
| 183 |
+
class storage_heap : public storage_base<storage_heap>
|
| 184 |
+
{
|
| 185 |
+
public:
|
| 186 |
+
/*!
|
| 187 |
+
WHAT THIS OBJECT REPRESENTS
|
| 188 |
+
This object is a storage type that uses type erasure to erase any type.
|
| 189 |
+
|
| 190 |
+
This particular storage type uses heap allocation only.
|
| 191 |
+
!*/
|
| 192 |
+
|
| 193 |
+
storage_heap() = default;
|
| 194 |
+
/*!
|
| 195 |
+
ensures
|
| 196 |
+
- #is_empty() == true
|
| 197 |
+
- for all T: #contains<T>() == false
|
| 198 |
+
!*/
|
| 199 |
+
|
| 200 |
+
template <
|
| 201 |
+
class T,
|
| 202 |
+
class T_ = std::decay_t<T>,
|
| 203 |
+
T_is_not_this_type<storage_heap, T> = true
|
| 204 |
+
>
|
| 205 |
+
storage_heap(T &&t) noexcept(std::is_nothrow_constructible<T_,T&&>::value)
|
| 206 |
+
/*!
|
| 207 |
+
ensures
|
| 208 |
+
- copies or moves the incoming object (depending on the forwarding reference)
|
| 209 |
+
- #is_empty() == false
|
| 210 |
+
- #contains<std::decay_t<T>>() == true
|
| 211 |
+
- #unsafe_get<T>() will yield the provided t.
|
| 212 |
+
!*/
|
| 213 |
+
: ptr{new T_{std::forward<T>(t)}},
|
| 214 |
+
del{[](void *self) {
|
| 215 |
+
delete reinterpret_cast<T_*>(self);
|
| 216 |
+
}},
|
| 217 |
+
copy{[](const void *self) -> void * {
|
| 218 |
+
return new T_{*reinterpret_cast<const T_*>(self)};
|
| 219 |
+
}},
|
| 220 |
+
type_id_{[] {
|
| 221 |
+
return std::type_index{typeid(T_)};
|
| 222 |
+
}}
|
| 223 |
+
{
|
| 224 |
+
}
|
| 225 |
+
|
| 226 |
+
storage_heap(const storage_heap& other)
|
| 227 |
+
/*!
|
| 228 |
+
ensures
|
| 229 |
+
- #is_empty() == other.is_empty()
|
| 230 |
+
- if other.is_empty() == false then
|
| 231 |
+
- underlying object of other is copied using erased type's copy constructor.
|
| 232 |
+
!*/
|
| 233 |
+
: ptr{other.ptr ? other.copy(other.ptr) : nullptr},
|
| 234 |
+
del{other.del},
|
| 235 |
+
copy{other.copy},
|
| 236 |
+
type_id_{other.type_id_}
|
| 237 |
+
{
|
| 238 |
+
}
|
| 239 |
+
|
| 240 |
+
storage_heap& operator=(const storage_heap& other)
|
| 241 |
+
/*!
|
| 242 |
+
ensures
|
| 243 |
+
- if is_empty() == false then
|
| 244 |
+
- destructs the object contained in this class.
|
| 245 |
+
- #is_empty() == other.is_empty()
|
| 246 |
+
- if other.is_empty() == false then
|
| 247 |
+
- underlying object of other is copied using erased type's copy constructor.
|
| 248 |
+
!*/
|
| 249 |
+
{
|
| 250 |
+
if (this != &other)
|
| 251 |
+
*this = std::move(storage_heap{other});
|
| 252 |
+
return *this;
|
| 253 |
+
}
|
| 254 |
+
|
| 255 |
+
storage_heap(storage_heap&& other) noexcept
|
| 256 |
+
/*!
|
| 257 |
+
ensures
|
| 258 |
+
- The state of other is moved into *this.
|
| 259 |
+
- #other.is_empty() == true
|
| 260 |
+
!*/
|
| 261 |
+
: ptr{std::exchange(other.ptr, nullptr)},
|
| 262 |
+
del{std::exchange(other.del, nullptr)},
|
| 263 |
+
copy{std::exchange(other.copy, nullptr)},
|
| 264 |
+
type_id_{std::exchange(other.type_id_, nullptr)}
|
| 265 |
+
{
|
| 266 |
+
}
|
| 267 |
+
|
| 268 |
+
storage_heap& operator=(storage_heap&& other) noexcept
|
| 269 |
+
/*!
|
| 270 |
+
ensures
|
| 271 |
+
- The state of other is moved into *this.
|
| 272 |
+
- #other.is_empty() == true
|
| 273 |
+
- returns *this
|
| 274 |
+
!*/
|
| 275 |
+
{
|
| 276 |
+
if (this != &other)
|
| 277 |
+
{
|
| 278 |
+
clear();
|
| 279 |
+
ptr = std::exchange(other.ptr, nullptr);
|
| 280 |
+
del = std::exchange(other.del, nullptr);
|
| 281 |
+
copy = std::exchange(other.copy, nullptr);
|
| 282 |
+
type_id_ = std::exchange(other.type_id_, nullptr);
|
| 283 |
+
}
|
| 284 |
+
return *this;
|
| 285 |
+
}
|
| 286 |
+
|
| 287 |
+
~storage_heap()
|
| 288 |
+
/*!
|
| 289 |
+
ensures
|
| 290 |
+
- destructs the object contained in *this if one exists.
|
| 291 |
+
!*/
|
| 292 |
+
{
|
| 293 |
+
if (ptr)
|
| 294 |
+
del(ptr);
|
| 295 |
+
}
|
| 296 |
+
|
| 297 |
+
void clear()
|
| 298 |
+
/*!
|
| 299 |
+
ensures
|
| 300 |
+
- #is_empty() == true
|
| 301 |
+
!*/
|
| 302 |
+
{
|
| 303 |
+
storage_heap{std::move(*this)};
|
| 304 |
+
}
|
| 305 |
+
|
| 306 |
+
void* get_ptr()
|
| 307 |
+
/*!
|
| 308 |
+
ensures
|
| 309 |
+
- returns a pointer to the underlying object or nullptr if is_empty()
|
| 310 |
+
!*/
|
| 311 |
+
{
|
| 312 |
+
return ptr;
|
| 313 |
+
}
|
| 314 |
+
|
| 315 |
+
const void* get_ptr() const
|
| 316 |
+
/*!
|
| 317 |
+
ensures
|
| 318 |
+
- returns a const pointer to the underlying object or nullptr if is_empty()
|
| 319 |
+
!*/
|
| 320 |
+
{
|
| 321 |
+
return ptr;
|
| 322 |
+
}
|
| 323 |
+
|
| 324 |
+
std::type_index type_id() const
|
| 325 |
+
/*!
|
| 326 |
+
requires
|
| 327 |
+
- is_empty() == false
|
| 328 |
+
ensures
|
| 329 |
+
- returns the std::type_index of the type contained within this object.
|
| 330 |
+
I.e. if this object contains the type T then this returns std::type_index{typeid(T)}.
|
| 331 |
+
!*/
|
| 332 |
+
{
|
| 333 |
+
DLIB_ASSERT(!this->is_empty());
|
| 334 |
+
return type_id_();
|
| 335 |
+
}
|
| 336 |
+
|
| 337 |
+
private:
|
| 338 |
+
void* ptr = nullptr;
|
| 339 |
+
void (*del)(void*) = nullptr;
|
| 340 |
+
void* (*copy)(const void*) = nullptr;
|
| 341 |
+
std::type_index (*type_id_)() = nullptr;
|
| 342 |
+
};
|
| 343 |
+
|
| 344 |
+
// -----------------------------------------------------------------------------------------------------
|
| 345 |
+
|
| 346 |
+
template <std::size_t Size, std::size_t Alignment = 8>
|
| 347 |
+
class storage_stack : public storage_base<storage_stack<Size, Alignment>>
|
| 348 |
+
{
|
| 349 |
+
/*!
|
| 350 |
+
WHAT THIS OBJECT REPRESENTS
|
| 351 |
+
This object is a storage type that uses type erasure to erase any type.
|
| 352 |
+
|
| 353 |
+
This particular storage type uses stack allocation using a template size and alignment.
|
| 354 |
+
Therefore, only objects whose size and alignment fits the template parameters can be
|
| 355 |
+
erased and absorbed into this object. Attempting to store a type not
|
| 356 |
+
representable on the stack with those settings will result in a build error.
|
| 357 |
+
|
| 358 |
+
This object will be capable of storing any type with an alignment requirement
|
| 359 |
+
that is a divisor of Alignment.
|
| 360 |
+
!*/
|
| 361 |
+
|
| 362 |
+
public:
|
| 363 |
+
storage_stack() = default;
|
| 364 |
+
/*!
|
| 365 |
+
ensures
|
| 366 |
+
- #is_empty() == true
|
| 367 |
+
- for all T: #contains<T>() == false
|
| 368 |
+
!*/
|
| 369 |
+
|
| 370 |
+
template <
|
| 371 |
+
class T,
|
| 372 |
+
class T_ = std::decay_t<T>,
|
| 373 |
+
T_is_not_this_type<storage_stack, T> = true
|
| 374 |
+
>
|
| 375 |
+
storage_stack(T &&t) noexcept(std::is_nothrow_constructible<T_,T&&>::value)
|
| 376 |
+
/*!
|
| 377 |
+
ensures
|
| 378 |
+
- copies or moves the incoming object (depending on the forwarding reference)
|
| 379 |
+
- #is_empty() == false
|
| 380 |
+
- #contains<std::decay_t<T>>() == true
|
| 381 |
+
!*/
|
| 382 |
+
: del{[](storage_stack& self) {
|
| 383 |
+
reinterpret_cast<T_*>(&self.data)->~T_();
|
| 384 |
+
self.del = nullptr;
|
| 385 |
+
self.copy = nullptr;
|
| 386 |
+
self.move = nullptr;
|
| 387 |
+
self.type_id_ = nullptr;
|
| 388 |
+
}},
|
| 389 |
+
copy{[](const storage_stack& src, storage_stack& dst) {
|
| 390 |
+
new (&dst.data) T_{*reinterpret_cast<const T_*>(&src.data)};
|
| 391 |
+
dst.del = src.del;
|
| 392 |
+
dst.copy = src.copy;
|
| 393 |
+
dst.move = src.move;
|
| 394 |
+
dst.type_id_ = src.type_id_;
|
| 395 |
+
}},
|
| 396 |
+
move{[](storage_stack& src, storage_stack& dst) {
|
| 397 |
+
new (&dst.data) T_{std::move(*reinterpret_cast<T_*>(&src.data))};
|
| 398 |
+
dst.del = src.del;
|
| 399 |
+
dst.copy = src.copy;
|
| 400 |
+
dst.move = src.move;
|
| 401 |
+
dst.type_id_ = src.type_id_;
|
| 402 |
+
}},
|
| 403 |
+
type_id_{[] {
|
| 404 |
+
return std::type_index{typeid(T_)};
|
| 405 |
+
}}
|
| 406 |
+
{
|
| 407 |
+
static_assert(sizeof(T_) <= Size, "insufficient size");
|
| 408 |
+
static_assert(Alignment % alignof(T_) == 0, "bad alignment");
|
| 409 |
+
new (&data) T_{std::forward<T>(t)};
|
| 410 |
+
}
|
| 411 |
+
|
| 412 |
+
storage_stack(const storage_stack& other)
|
| 413 |
+
/*!
|
| 414 |
+
ensures
|
| 415 |
+
- #is_empty() == other.is_empty()
|
| 416 |
+
- if other.is_empty() == false then
|
| 417 |
+
- underlying object of other is copied using erased type's copy constructor.
|
| 418 |
+
!*/
|
| 419 |
+
{
|
| 420 |
+
if (other.copy)
|
| 421 |
+
other.copy(other, *this);
|
| 422 |
+
}
|
| 423 |
+
|
| 424 |
+
storage_stack& operator=(const storage_stack& other)
|
| 425 |
+
/*!
|
| 426 |
+
ensures
|
| 427 |
+
- #is_empty() == other.is_empty()
|
| 428 |
+
- if is_empty() == false then
|
| 429 |
+
- destructs the object contained in this class.
|
| 430 |
+
- if other.is_empty() == false then
|
| 431 |
+
- underlying object of other is copied using erased type's copy constructor
|
| 432 |
+
!*/
|
| 433 |
+
{
|
| 434 |
+
if (this != &other)
|
| 435 |
+
{
|
| 436 |
+
clear();
|
| 437 |
+
if (other.copy)
|
| 438 |
+
other.copy(other, *this);
|
| 439 |
+
}
|
| 440 |
+
return *this;
|
| 441 |
+
}
|
| 442 |
+
|
| 443 |
+
storage_stack(storage_stack&& other)
|
| 444 |
+
/*!
|
| 445 |
+
ensures
|
| 446 |
+
- #is_empty() == other.is_empty()
|
| 447 |
+
- if other.is_empty() == false then
|
| 448 |
+
- underlying object of other is moved using erased type's moved constructor
|
| 449 |
+
!*/
|
| 450 |
+
{
|
| 451 |
+
if (other.move)
|
| 452 |
+
other.move(other, *this);
|
| 453 |
+
}
|
| 454 |
+
|
| 455 |
+
storage_stack& operator=(storage_stack&& other)
|
| 456 |
+
/*!
|
| 457 |
+
ensures
|
| 458 |
+
- if is_empty() == false then
|
| 459 |
+
- destructs the object contained in this class.
|
| 460 |
+
- #is_empty() == other.is_empty()
|
| 461 |
+
- if other.is_empty() == false then
|
| 462 |
+
- underlying object of other is moved using erased type's moved constructor.
|
| 463 |
+
This does not make other empty. It will still contain a moved from object
|
| 464 |
+
of the underlying type in whatever that object's moved from state is.
|
| 465 |
+
- #other.is_empty() == false
|
| 466 |
+
!*/
|
| 467 |
+
{
|
| 468 |
+
if (this != &other)
|
| 469 |
+
{
|
| 470 |
+
clear();
|
| 471 |
+
if (other.move)
|
| 472 |
+
other.move(other, *this);
|
| 473 |
+
}
|
| 474 |
+
return *this;
|
| 475 |
+
}
|
| 476 |
+
|
| 477 |
+
~storage_stack()
|
| 478 |
+
/*!
|
| 479 |
+
ensures
|
| 480 |
+
- destructs the object contained in *this if one exists.
|
| 481 |
+
!*/
|
| 482 |
+
{
|
| 483 |
+
clear();
|
| 484 |
+
}
|
| 485 |
+
|
| 486 |
+
void clear()
|
| 487 |
+
/*!
|
| 488 |
+
ensures
|
| 489 |
+
- #is_empty() == true
|
| 490 |
+
!*/
|
| 491 |
+
{
|
| 492 |
+
if (del)
|
| 493 |
+
del(*this);
|
| 494 |
+
}
|
| 495 |
+
|
| 496 |
+
void* get_ptr()
|
| 497 |
+
/*!
|
| 498 |
+
ensures
|
| 499 |
+
- returns a pointer to the underlying object or nullptr if is_empty()
|
| 500 |
+
!*/
|
| 501 |
+
{
|
| 502 |
+
return del ? (void*)&data : nullptr;
|
| 503 |
+
}
|
| 504 |
+
|
| 505 |
+
const void* get_ptr() const
|
| 506 |
+
/*!
|
| 507 |
+
ensures
|
| 508 |
+
- returns a const pointer to the underlying object or nullptr if is_empty()
|
| 509 |
+
!*/
|
| 510 |
+
{
|
| 511 |
+
return del ? (const void*)&data : nullptr;
|
| 512 |
+
}
|
| 513 |
+
|
| 514 |
+
std::type_index type_id() const
|
| 515 |
+
/*!
|
| 516 |
+
requires
|
| 517 |
+
- is_empty() == false
|
| 518 |
+
ensures
|
| 519 |
+
- returns the std::type_index of the type contained within this object.
|
| 520 |
+
I.e. if this object contains the type T then this returns std::type_index{typeid(T)}.
|
| 521 |
+
!*/
|
| 522 |
+
{
|
| 523 |
+
DLIB_ASSERT(!this->is_empty());
|
| 524 |
+
return type_id_();
|
| 525 |
+
}
|
| 526 |
+
|
| 527 |
+
private:
|
| 528 |
+
std::aligned_storage_t<Size, Alignment> data;
|
| 529 |
+
void (*del)(storage_stack&) = nullptr;
|
| 530 |
+
void (*copy)(const storage_stack&, storage_stack&) = nullptr;
|
| 531 |
+
void (*move)(storage_stack&, storage_stack&) = nullptr;
|
| 532 |
+
std::type_index (*type_id_)() = nullptr;
|
| 533 |
+
};
|
| 534 |
+
|
| 535 |
+
// -----------------------------------------------------------------------------------------------------
|
| 536 |
+
|
| 537 |
+
template <std::size_t Size, std::size_t Alignment = 8>
|
| 538 |
+
class storage_sbo : public storage_base<storage_sbo<Size, Alignment>>
|
| 539 |
+
{
|
| 540 |
+
/*!
|
| 541 |
+
WHAT THIS OBJECT REPRESENTS
|
| 542 |
+
This object is a storage type that uses type erasure to erase any type.
|
| 543 |
+
|
| 544 |
+
This particular storage type uses small buffer optimization (SBO), i.e. optional
|
| 545 |
+
stack allocation if the erased type has sizeof <= Size and alignment
|
| 546 |
+
requirements no greater than the given Alignment template value. If not it
|
| 547 |
+
allocates the object on the heap.
|
| 548 |
+
!*/
|
| 549 |
+
|
| 550 |
+
public:
|
| 551 |
+
// type_fits<T>::value tells us if our SBO can hold T.
|
| 552 |
+
template<typename T>
|
| 553 |
+
struct type_fits : std::integral_constant<bool, sizeof(T) <= Size && Alignment % alignof(T) == 0>{};
|
| 554 |
+
|
| 555 |
+
storage_sbo() = default;
|
| 556 |
+
/*!
|
| 557 |
+
ensures
|
| 558 |
+
- #is_empty() == true
|
| 559 |
+
- for all T: #contains<T>() == false
|
| 560 |
+
!*/
|
| 561 |
+
|
| 562 |
+
template <
|
| 563 |
+
class T,
|
| 564 |
+
class T_ = std::decay_t<T>,
|
| 565 |
+
T_is_not_this_type<storage_sbo, T> = true,
|
| 566 |
+
std::enable_if_t<type_fits<T_>::value, bool> = true
|
| 567 |
+
>
|
| 568 |
+
storage_sbo(T &&t) noexcept(std::is_nothrow_constructible<T_,T&&>::value)
|
| 569 |
+
/*!
|
| 570 |
+
ensures
|
| 571 |
+
- copies or moves the incoming object (depending on the forwarding reference)
|
| 572 |
+
- #is_empty() == false
|
| 573 |
+
- #contains<std::decay_t<T>>() == true
|
| 574 |
+
- stack allocation is used
|
| 575 |
+
!*/
|
| 576 |
+
: ptr{new (&data) T_{std::forward<T>(t)}},
|
| 577 |
+
del{[](storage_sbo& self) {
|
| 578 |
+
reinterpret_cast<T_*>(&self.data)->~T_();
|
| 579 |
+
self.ptr = nullptr;
|
| 580 |
+
self.del = nullptr;
|
| 581 |
+
self.copy = nullptr;
|
| 582 |
+
self.move = nullptr;
|
| 583 |
+
self.type_id_ = nullptr;
|
| 584 |
+
}},
|
| 585 |
+
copy{[](const storage_sbo& src, storage_sbo& dst) {
|
| 586 |
+
dst.ptr = new (&dst.data) T_{*reinterpret_cast<const T_*>(src.ptr)};
|
| 587 |
+
dst.del = src.del;
|
| 588 |
+
dst.copy = src.copy;
|
| 589 |
+
dst.move = src.move;
|
| 590 |
+
dst.type_id_ = src.type_id_;
|
| 591 |
+
}},
|
| 592 |
+
move{[](storage_sbo& src, storage_sbo& dst) {
|
| 593 |
+
dst.ptr = new (&dst.data) T_{std::move(*reinterpret_cast<T_*>(src.ptr))};
|
| 594 |
+
dst.del = src.del;
|
| 595 |
+
dst.copy = src.copy;
|
| 596 |
+
dst.move = src.move;
|
| 597 |
+
dst.type_id_ = src.type_id_;
|
| 598 |
+
}},
|
| 599 |
+
type_id_{[] {
|
| 600 |
+
return std::type_index{typeid(T_)};
|
| 601 |
+
}}
|
| 602 |
+
{
|
| 603 |
+
}
|
| 604 |
+
|
| 605 |
+
template <
|
| 606 |
+
class T,
|
| 607 |
+
class T_ = std::decay_t<T>,
|
| 608 |
+
T_is_not_this_type<storage_sbo, T> = true,
|
| 609 |
+
std::enable_if_t<!type_fits<T_>::value, bool> = true
|
| 610 |
+
>
|
| 611 |
+
storage_sbo(T &&t) noexcept(std::is_nothrow_constructible<T_,T&&>::value)
|
| 612 |
+
/*!
|
| 613 |
+
ensures
|
| 614 |
+
- copies or moves the incoming object (depending on the forwarding reference)
|
| 615 |
+
- #is_empty() == false
|
| 616 |
+
- #contains<std::decay_t<T>>() == true
|
| 617 |
+
- heap allocation is used
|
| 618 |
+
!*/
|
| 619 |
+
: ptr{new T_{std::forward<T>(t)}},
|
| 620 |
+
del{[](storage_sbo& self) {
|
| 621 |
+
delete reinterpret_cast<T_*>(self.ptr);
|
| 622 |
+
self.ptr = nullptr;
|
| 623 |
+
self.del = nullptr;
|
| 624 |
+
self.copy = nullptr;
|
| 625 |
+
self.move = nullptr;
|
| 626 |
+
self.type_id_ = nullptr;
|
| 627 |
+
}},
|
| 628 |
+
copy{[](const storage_sbo& src, storage_sbo& dst) {
|
| 629 |
+
dst.ptr = new T_{*reinterpret_cast<const T_*>(src.ptr)};
|
| 630 |
+
dst.del = src.del;
|
| 631 |
+
dst.copy = src.copy;
|
| 632 |
+
dst.move = src.move;
|
| 633 |
+
dst.type_id_ = src.type_id_;
|
| 634 |
+
}},
|
| 635 |
+
move{[](storage_sbo& src, storage_sbo& dst) {
|
| 636 |
+
dst.ptr = std::exchange(src.ptr, nullptr);
|
| 637 |
+
dst.del = std::exchange(src.del, nullptr);
|
| 638 |
+
dst.copy = std::exchange(src.copy, nullptr);
|
| 639 |
+
dst.move = std::exchange(src.move, nullptr);
|
| 640 |
+
dst.type_id_ = std::exchange(src.type_id_, nullptr);
|
| 641 |
+
}},
|
| 642 |
+
type_id_{[] {
|
| 643 |
+
return std::type_index{typeid(T_)};
|
| 644 |
+
}}
|
| 645 |
+
{
|
| 646 |
+
}
|
| 647 |
+
|
| 648 |
+
storage_sbo(const storage_sbo& other)
|
| 649 |
+
/*!
|
| 650 |
+
ensures
|
| 651 |
+
- #is_empty() == other.is_empty()
|
| 652 |
+
- if other.is_empty() == false then
|
| 653 |
+
- underlying object of other is copied using erased type's copy constructor
|
| 654 |
+
!*/
|
| 655 |
+
{
|
| 656 |
+
if (other.copy)
|
| 657 |
+
other.copy(other, *this);
|
| 658 |
+
}
|
| 659 |
+
|
| 660 |
+
storage_sbo& operator=(const storage_sbo& other)
|
| 661 |
+
/*!
|
| 662 |
+
ensures
|
| 663 |
+
- if is_empty() == false then
|
| 664 |
+
- destructs the object contained in this class.
|
| 665 |
+
- #is_empty() == other.is_empty()
|
| 666 |
+
- if other.is_empty() == false then
|
| 667 |
+
- underlying object of other is copied using erased type's copy constructor
|
| 668 |
+
!*/
|
| 669 |
+
{
|
| 670 |
+
if (this != &other)
|
| 671 |
+
{
|
| 672 |
+
clear();
|
| 673 |
+
if (other.copy)
|
| 674 |
+
other.copy(other, *this);
|
| 675 |
+
}
|
| 676 |
+
return *this;
|
| 677 |
+
}
|
| 678 |
+
|
| 679 |
+
storage_sbo(storage_sbo&& other)
|
| 680 |
+
/*!
|
| 681 |
+
ensures
|
| 682 |
+
- #is_empty() == other.is_empty()
|
| 683 |
+
- if other.is_empty() == false then
|
| 684 |
+
- if underlying object of other is allocated on stack then
|
| 685 |
+
- underlying object of other is moved using erased type's moved constructor.
|
| 686 |
+
This does not make other empty. It will still contain a moved from
|
| 687 |
+
object of the underlying type in whatever that object's moved from
|
| 688 |
+
state is.
|
| 689 |
+
- #other.is_empty() == false
|
| 690 |
+
- else
|
| 691 |
+
- storage heap pointer is moved.
|
| 692 |
+
- #other.is_empty() == true
|
| 693 |
+
!*/
|
| 694 |
+
{
|
| 695 |
+
if (other.move)
|
| 696 |
+
other.move(other, *this);
|
| 697 |
+
}
|
| 698 |
+
|
| 699 |
+
storage_sbo& operator=(storage_sbo&& other)
|
| 700 |
+
/*!
|
| 701 |
+
ensures
|
| 702 |
+
- underlying object is destructed if is_empty() == false
|
| 703 |
+
- #is_empty() == other.is_empty()
|
| 704 |
+
- if other.is_empty() == false then
|
| 705 |
+
- if underlying object of other is allocated on stack then
|
| 706 |
+
- underlying object of other is moved using erased type's moved constructor.
|
| 707 |
+
This does not make other empty. It will still contain a moved from
|
| 708 |
+
object of the underlying type in whatever that object's moved from
|
| 709 |
+
state is.
|
| 710 |
+
- #other.is_empty() == false
|
| 711 |
+
- else
|
| 712 |
+
- storage heap pointer is moved.
|
| 713 |
+
- #other.is_empty() == true
|
| 714 |
+
!*/
|
| 715 |
+
{
|
| 716 |
+
if (this != &other)
|
| 717 |
+
{
|
| 718 |
+
clear();
|
| 719 |
+
if (other.move)
|
| 720 |
+
other.move(other, *this);
|
| 721 |
+
}
|
| 722 |
+
return *this;
|
| 723 |
+
}
|
| 724 |
+
|
| 725 |
+
~storage_sbo()
|
| 726 |
+
/*!
|
| 727 |
+
ensures
|
| 728 |
+
- destructs the object contained in *this if one exists.
|
| 729 |
+
!*/
|
| 730 |
+
{
|
| 731 |
+
clear();
|
| 732 |
+
}
|
| 733 |
+
|
| 734 |
+
void clear()
|
| 735 |
+
/*!
|
| 736 |
+
ensures
|
| 737 |
+
- #is_empty() == true
|
| 738 |
+
!*/
|
| 739 |
+
{
|
| 740 |
+
if (ptr)
|
| 741 |
+
del(*this);
|
| 742 |
+
}
|
| 743 |
+
|
| 744 |
+
void* get_ptr()
|
| 745 |
+
/*!
|
| 746 |
+
ensures
|
| 747 |
+
- returns a pointer to the underlying object or nullptr if is_empty()
|
| 748 |
+
!*/
|
| 749 |
+
{
|
| 750 |
+
return ptr;
|
| 751 |
+
}
|
| 752 |
+
|
| 753 |
+
const void* get_ptr() const
|
| 754 |
+
/*!
|
| 755 |
+
ensures
|
| 756 |
+
- returns a const pointer to the underlying object or nullptr if is_empty()
|
| 757 |
+
!*/
|
| 758 |
+
{
|
| 759 |
+
return ptr;
|
| 760 |
+
}
|
| 761 |
+
|
| 762 |
+
std::type_index type_id() const
|
| 763 |
+
/*!
|
| 764 |
+
requires
|
| 765 |
+
- is_empty() == false
|
| 766 |
+
ensures
|
| 767 |
+
- returns the std::type_index of the type contained within this object.
|
| 768 |
+
I.e. if this object contains the type T then this returns std::type_index{typeid(T)}.
|
| 769 |
+
!*/
|
| 770 |
+
{
|
| 771 |
+
DLIB_ASSERT(!this->is_empty());
|
| 772 |
+
return type_id_();
|
| 773 |
+
}
|
| 774 |
+
|
| 775 |
+
private:
|
| 776 |
+
std::aligned_storage_t<Size, Alignment> data;
|
| 777 |
+
void* ptr = nullptr;
|
| 778 |
+
void (*del)(storage_sbo&) = nullptr;
|
| 779 |
+
void (*copy)(const storage_sbo&, storage_sbo&) = nullptr;
|
| 780 |
+
void (*move)(storage_sbo&, storage_sbo&) = nullptr;
|
| 781 |
+
std::type_index (*type_id_)() = nullptr;
|
| 782 |
+
};
|
| 783 |
+
|
| 784 |
+
// -----------------------------------------------------------------------------------------------------
|
| 785 |
+
|
| 786 |
+
class storage_shared : public storage_base<storage_shared>
|
| 787 |
+
{
|
| 788 |
+
/*!
|
| 789 |
+
WHAT THIS OBJECT REPRESENTS
|
| 790 |
+
This object is a storage type that uses type erasure to erase any type.
|
| 791 |
+
|
| 792 |
+
This particular storage type uses std::shared_ptr<void> to store and erase
|
| 793 |
+
incoming objects. Therefore, it uses heap allocation and reference counting.
|
| 794 |
+
Moreover, it has the same copying and move semantics as std::shared_ptr. I.e.
|
| 795 |
+
it results in the underlying object being held by reference rather than by
|
| 796 |
+
value.
|
| 797 |
+
!*/
|
| 798 |
+
|
| 799 |
+
public:
|
| 800 |
+
storage_shared() = default;
|
| 801 |
+
/*!
|
| 802 |
+
ensures
|
| 803 |
+
- #is_empty() == true
|
| 804 |
+
- for all T: #contains<T>() == false
|
| 805 |
+
!*/
|
| 806 |
+
|
| 807 |
+
template <
|
| 808 |
+
class T,
|
| 809 |
+
class T_ = std::decay_t<T>,
|
| 810 |
+
T_is_not_this_type<storage_shared, T> = true
|
| 811 |
+
>
|
| 812 |
+
storage_shared(T &&t) noexcept(std::is_nothrow_constructible<T_,T&&>::value)
|
| 813 |
+
/*!
|
| 814 |
+
ensures
|
| 815 |
+
- copies or moves the incoming object (depending on the forwarding reference)
|
| 816 |
+
- #is_empty() == true
|
| 817 |
+
- #contains<std::decay_t<T>>() == true
|
| 818 |
+
!*/
|
| 819 |
+
: ptr{std::make_shared<T_>(std::forward<T>(t))},
|
| 820 |
+
type_id_{[] {
|
| 821 |
+
return std::type_index{typeid(T_)};
|
| 822 |
+
}}
|
| 823 |
+
{
|
| 824 |
+
}
|
| 825 |
+
|
| 826 |
+
// This object has the same copy/move semantics as a std::shared_ptr<void>
|
| 827 |
+
storage_shared(const storage_shared& other) = default;
|
| 828 |
+
storage_shared& operator=(const storage_shared& other) = default;
|
| 829 |
+
storage_shared(storage_shared&& other) noexcept = default;
|
| 830 |
+
storage_shared& operator=(storage_shared&& other) noexcept = default;
|
| 831 |
+
|
| 832 |
+
void clear()
|
| 833 |
+
/*!
|
| 834 |
+
ensures
|
| 835 |
+
- #is_empty() == true
|
| 836 |
+
!*/
|
| 837 |
+
{
|
| 838 |
+
ptr = nullptr;
|
| 839 |
+
type_id_ = nullptr;
|
| 840 |
+
}
|
| 841 |
+
|
| 842 |
+
void* get_ptr()
|
| 843 |
+
/*!
|
| 844 |
+
ensures
|
| 845 |
+
- returns a pointer to the underlying object or nullptr if is_empty()
|
| 846 |
+
!*/
|
| 847 |
+
{
|
| 848 |
+
return ptr.get();
|
| 849 |
+
}
|
| 850 |
+
|
| 851 |
+
const void* get_ptr() const
|
| 852 |
+
/*!
|
| 853 |
+
ensures
|
| 854 |
+
- returns a const pointer to the underlying object or nullptr if is_empty()
|
| 855 |
+
!*/
|
| 856 |
+
{
|
| 857 |
+
return ptr.get();
|
| 858 |
+
}
|
| 859 |
+
|
| 860 |
+
std::type_index type_id() const
|
| 861 |
+
/*!
|
| 862 |
+
requires
|
| 863 |
+
- is_empty() == false
|
| 864 |
+
ensures
|
| 865 |
+
- returns the std::type_index of the type contained within this object.
|
| 866 |
+
I.e. if this object contains the type T then this returns std::type_index{typeid(T)}.
|
| 867 |
+
!*/
|
| 868 |
+
{
|
| 869 |
+
DLIB_ASSERT(!this->is_empty());
|
| 870 |
+
return type_id_();
|
| 871 |
+
}
|
| 872 |
+
|
| 873 |
+
private:
|
| 874 |
+
std::shared_ptr<void> ptr = nullptr;
|
| 875 |
+
std::type_index (*type_id_)() = nullptr;
|
| 876 |
+
};
|
| 877 |
+
|
| 878 |
+
// -----------------------------------------------------------------------------------------------------
|
| 879 |
+
|
| 880 |
+
class storage_view : public storage_base<storage_view>
|
| 881 |
+
{
|
| 882 |
+
/*!
|
| 883 |
+
WHAT THIS OBJECT REPRESENTS
|
| 884 |
+
This object is a storage type that uses type erasure to erase any type.
|
| 885 |
+
|
| 886 |
+
This particular storage type is a view type, similar to std::string_view or
|
| 887 |
+
std::span. So underlying objects are only ever referenced, not copied, moved or
|
| 888 |
+
destructed. That is, instances of this object take no ownership of the objects
|
| 889 |
+
they contain. So they are only valid as long as the contained object exists.
|
| 890 |
+
So storage_view merely holds a pointer to the underlying object.
|
| 891 |
+
!*/
|
| 892 |
+
|
| 893 |
+
public:
|
| 894 |
+
storage_view() = default;
|
| 895 |
+
/*!
|
| 896 |
+
ensures
|
| 897 |
+
- #is_empty() == true
|
| 898 |
+
- for all T: #contains<T>() == false
|
| 899 |
+
!*/
|
| 900 |
+
|
| 901 |
+
template <
|
| 902 |
+
class T,
|
| 903 |
+
class T_ = std::decay_t<T>,
|
| 904 |
+
T_is_not_this_type<storage_view, T> = true
|
| 905 |
+
>
|
| 906 |
+
storage_view(T &&t) noexcept
|
| 907 |
+
/*!
|
| 908 |
+
ensures
|
| 909 |
+
- #get_ptr() == &t
|
| 910 |
+
- #is_empty() == false
|
| 911 |
+
- #contains<std::decay_t<T>>() == true
|
| 912 |
+
!*/
|
| 913 |
+
: ptr{&t},
|
| 914 |
+
type_id_{[] {
|
| 915 |
+
return std::type_index{typeid(T_)};
|
| 916 |
+
}}
|
| 917 |
+
{
|
| 918 |
+
}
|
| 919 |
+
|
| 920 |
+
// This object has the same copy/move semantics as a void*.
|
| 921 |
+
storage_view(const storage_view& other) = default;
|
| 922 |
+
storage_view& operator=(const storage_view& other) = default;
|
| 923 |
+
storage_view(storage_view&& other) noexcept = default;
|
| 924 |
+
storage_view& operator=(storage_view&& other) noexcept = default;
|
| 925 |
+
|
| 926 |
+
void clear()
|
| 927 |
+
/*!
|
| 928 |
+
ensures
|
| 929 |
+
- #is_empty() == true
|
| 930 |
+
!*/
|
| 931 |
+
{
|
| 932 |
+
ptr = nullptr;
|
| 933 |
+
type_id_ = nullptr;
|
| 934 |
+
}
|
| 935 |
+
|
| 936 |
+
void* get_ptr()
|
| 937 |
+
/*!
|
| 938 |
+
ensures
|
| 939 |
+
- returns a pointer to the underlying object or nullptr if is_empty()
|
| 940 |
+
!*/
|
| 941 |
+
{
|
| 942 |
+
return ptr;
|
| 943 |
+
}
|
| 944 |
+
|
| 945 |
+
const void* get_ptr() const
|
| 946 |
+
/*!
|
| 947 |
+
ensures
|
| 948 |
+
- returns a const pointer to the underlying object or nullptr if is_empty()
|
| 949 |
+
!*/
|
| 950 |
+
{
|
| 951 |
+
return ptr;
|
| 952 |
+
}
|
| 953 |
+
|
| 954 |
+
std::type_index type_id() const
|
| 955 |
+
/*!
|
| 956 |
+
requires
|
| 957 |
+
- is_empty() == false
|
| 958 |
+
ensures
|
| 959 |
+
- returns the std::type_index of the type contained within this object.
|
| 960 |
+
I.e. if this object contains the type T then this returns std::type_index{typeid(T)}.
|
| 961 |
+
!*/
|
| 962 |
+
{
|
| 963 |
+
DLIB_ASSERT(!this->is_empty());
|
| 964 |
+
return type_id_();
|
| 965 |
+
}
|
| 966 |
+
|
| 967 |
+
private:
|
| 968 |
+
void* ptr = nullptr;
|
| 969 |
+
std::type_index (*type_id_)() = nullptr;
|
| 970 |
+
};
|
| 971 |
+
|
| 972 |
+
// -----------------------------------------------------------------------------------------------------
|
| 973 |
+
|
| 974 |
+
}
|
| 975 |
+
}
|
| 976 |
+
|
| 977 |
+
#endif //DLIB_TYPE_ERASURE_H_
|
difpoint/lib/dlib/dlib/array.h
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
|
| 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 |
+
|
difpoint/lib/dlib/dlib/array/array_kernel.h
ADDED
|
@@ -0,0 +1,809 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
|
| 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 |
+
|
difpoint/lib/dlib/dlib/array/array_kernel_abstract.h
ADDED
|
@@ -0,0 +1,360 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
|
| 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 |
+
|
difpoint/lib/dlib/dlib/array/array_tools.h
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Copyright (C) 2013 Davis E. King (davis@dlib.net)
|
| 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 |
+
|
difpoint/lib/dlib/dlib/array/array_tools_abstract.h
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Copyright (C) 2013 Davis E. King (davis@dlib.net)
|
| 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 |
+
|
difpoint/lib/dlib/dlib/array2d.h
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Copyright (C) 2006 Davis E. King (davis@dlib.net)
|
| 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 |
+
|
difpoint/lib/dlib/dlib/array2d/array2d_generic_image.h
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Copyright (C) 2014 Davis E. King (davis@dlib.net)
|
| 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 |
+
|
difpoint/lib/dlib/dlib/array2d/array2d_kernel.h
ADDED
|
@@ -0,0 +1,524 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Copyright (C) 2006 Davis E. King (davis@dlib.net)
|
| 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 |
+
row(row&& r) = default;
|
| 121 |
+
row& operator=(row&& r) = default;
|
| 122 |
+
|
| 123 |
+
T* data = nullptr;
|
| 124 |
+
long nc_ = 0;
|
| 125 |
+
|
| 126 |
+
|
| 127 |
+
// restricted functions
|
| 128 |
+
row(const row&) = delete;
|
| 129 |
+
row& operator=(const row&) = delete;
|
| 130 |
+
};
|
| 131 |
+
|
| 132 |
+
// -----------------------------------
|
| 133 |
+
|
| 134 |
+
array2d (
|
| 135 |
+
) :
|
| 136 |
+
data(0),
|
| 137 |
+
nc_(0),
|
| 138 |
+
nr_(0),
|
| 139 |
+
cur(0),
|
| 140 |
+
last(0),
|
| 141 |
+
at_start_(true)
|
| 142 |
+
{
|
| 143 |
+
}
|
| 144 |
+
|
| 145 |
+
array2d(
|
| 146 |
+
long rows,
|
| 147 |
+
long cols
|
| 148 |
+
) :
|
| 149 |
+
data(0),
|
| 150 |
+
nc_(0),
|
| 151 |
+
nr_(0),
|
| 152 |
+
cur(0),
|
| 153 |
+
last(0),
|
| 154 |
+
at_start_(true)
|
| 155 |
+
{
|
| 156 |
+
// make sure requires clause is not broken
|
| 157 |
+
DLIB_ASSERT((cols >= 0 && rows >= 0),
|
| 158 |
+
"\t array2d::array2d(long rows, long cols)"
|
| 159 |
+
<< "\n\t The array2d can't have negative rows or columns."
|
| 160 |
+
<< "\n\t this: " << this
|
| 161 |
+
<< "\n\t cols: " << cols
|
| 162 |
+
<< "\n\t rows: " << rows
|
| 163 |
+
);
|
| 164 |
+
|
| 165 |
+
set_size(rows,cols);
|
| 166 |
+
}
|
| 167 |
+
|
| 168 |
+
array2d(const array2d&) = delete; // copy constructor
|
| 169 |
+
array2d& operator=(const array2d&) = delete; // assignment operator
|
| 170 |
+
|
| 171 |
+
#ifdef DLIB_HAS_RVALUE_REFERENCES
|
| 172 |
+
array2d(array2d&& item) : array2d()
|
| 173 |
+
{
|
| 174 |
+
swap(item);
|
| 175 |
+
}
|
| 176 |
+
|
| 177 |
+
array2d& operator= (
|
| 178 |
+
array2d&& rhs
|
| 179 |
+
)
|
| 180 |
+
{
|
| 181 |
+
swap(rhs);
|
| 182 |
+
return *this;
|
| 183 |
+
}
|
| 184 |
+
#endif
|
| 185 |
+
|
| 186 |
+
virtual ~array2d (
|
| 187 |
+
) { clear(); }
|
| 188 |
+
|
| 189 |
+
long nc (
|
| 190 |
+
) const { return nc_; }
|
| 191 |
+
|
| 192 |
+
long nr (
|
| 193 |
+
) const { return nr_; }
|
| 194 |
+
|
| 195 |
+
row operator[] (
|
| 196 |
+
long row_
|
| 197 |
+
)
|
| 198 |
+
{
|
| 199 |
+
// make sure requires clause is not broken
|
| 200 |
+
DLIB_ASSERT(row_ < nr() && row_ >= 0,
|
| 201 |
+
"\trow array2d::operator[](long row_)"
|
| 202 |
+
<< "\n\tThe row index given must be less than the number of rows."
|
| 203 |
+
<< "\n\tthis: " << this
|
| 204 |
+
<< "\n\trow_: " << row_
|
| 205 |
+
<< "\n\tnr(): " << nr()
|
| 206 |
+
);
|
| 207 |
+
|
| 208 |
+
return row(data+row_*nc_, nc_);
|
| 209 |
+
}
|
| 210 |
+
|
| 211 |
+
const row operator[] (
|
| 212 |
+
long row_
|
| 213 |
+
) const
|
| 214 |
+
{
|
| 215 |
+
// make sure requires clause is not broken
|
| 216 |
+
DLIB_ASSERT(row_ < nr() && row_ >= 0,
|
| 217 |
+
"\tconst row array2d::operator[](long row_) const"
|
| 218 |
+
<< "\n\tThe row index given must be less than the number of rows."
|
| 219 |
+
<< "\n\tthis: " << this
|
| 220 |
+
<< "\n\trow_: " << row_
|
| 221 |
+
<< "\n\tnr(): " << nr()
|
| 222 |
+
);
|
| 223 |
+
|
| 224 |
+
return row(data+row_*nc_, nc_);
|
| 225 |
+
}
|
| 226 |
+
|
| 227 |
+
void swap (
|
| 228 |
+
array2d& item
|
| 229 |
+
)
|
| 230 |
+
{
|
| 231 |
+
exchange(data,item.data);
|
| 232 |
+
exchange(nr_,item.nr_);
|
| 233 |
+
exchange(nc_,item.nc_);
|
| 234 |
+
exchange(at_start_,item.at_start_);
|
| 235 |
+
exchange(cur,item.cur);
|
| 236 |
+
exchange(last,item.last);
|
| 237 |
+
pool.swap(item.pool);
|
| 238 |
+
}
|
| 239 |
+
|
| 240 |
+
void clear (
|
| 241 |
+
)
|
| 242 |
+
{
|
| 243 |
+
if (data != 0)
|
| 244 |
+
{
|
| 245 |
+
pool.deallocate_array(data);
|
| 246 |
+
nc_ = 0;
|
| 247 |
+
nr_ = 0;
|
| 248 |
+
data = 0;
|
| 249 |
+
at_start_ = true;
|
| 250 |
+
cur = 0;
|
| 251 |
+
last = 0;
|
| 252 |
+
}
|
| 253 |
+
}
|
| 254 |
+
|
| 255 |
+
void set_size (
|
| 256 |
+
long rows,
|
| 257 |
+
long cols
|
| 258 |
+
);
|
| 259 |
+
|
| 260 |
+
bool at_start (
|
| 261 |
+
) const { return at_start_; }
|
| 262 |
+
|
| 263 |
+
void reset (
|
| 264 |
+
) const { at_start_ = true; cur = 0; }
|
| 265 |
+
|
| 266 |
+
bool current_element_valid (
|
| 267 |
+
) const { return (cur != 0); }
|
| 268 |
+
|
| 269 |
+
const T& element (
|
| 270 |
+
) const
|
| 271 |
+
{
|
| 272 |
+
// make sure requires clause is not broken
|
| 273 |
+
DLIB_ASSERT(current_element_valid() == true,
|
| 274 |
+
"\tconst T& array2d::element()()"
|
| 275 |
+
<< "\n\tYou can only call element() when you are at a valid one."
|
| 276 |
+
<< "\n\tthis: " << this
|
| 277 |
+
);
|
| 278 |
+
|
| 279 |
+
return *cur;
|
| 280 |
+
}
|
| 281 |
+
|
| 282 |
+
T& element (
|
| 283 |
+
)
|
| 284 |
+
{
|
| 285 |
+
// make sure requires clause is not broken
|
| 286 |
+
DLIB_ASSERT(current_element_valid() == true,
|
| 287 |
+
"\tT& array2d::element()()"
|
| 288 |
+
<< "\n\tYou can only call element() when you are at a valid one."
|
| 289 |
+
<< "\n\tthis: " << this
|
| 290 |
+
);
|
| 291 |
+
|
| 292 |
+
return *cur;
|
| 293 |
+
}
|
| 294 |
+
|
| 295 |
+
bool move_next (
|
| 296 |
+
) const
|
| 297 |
+
{
|
| 298 |
+
if (cur != 0)
|
| 299 |
+
{
|
| 300 |
+
if (cur != last)
|
| 301 |
+
{
|
| 302 |
+
++cur;
|
| 303 |
+
return true;
|
| 304 |
+
}
|
| 305 |
+
cur = 0;
|
| 306 |
+
return false;
|
| 307 |
+
}
|
| 308 |
+
else if (at_start_)
|
| 309 |
+
{
|
| 310 |
+
cur = data;
|
| 311 |
+
at_start_ = false;
|
| 312 |
+
return (data != 0);
|
| 313 |
+
}
|
| 314 |
+
else
|
| 315 |
+
{
|
| 316 |
+
return false;
|
| 317 |
+
}
|
| 318 |
+
}
|
| 319 |
+
|
| 320 |
+
size_t size (
|
| 321 |
+
) const { return static_cast<size_t>(nc_) * static_cast<size_t>(nr_); }
|
| 322 |
+
|
| 323 |
+
long width_step (
|
| 324 |
+
) const
|
| 325 |
+
{
|
| 326 |
+
return nc_*sizeof(T);
|
| 327 |
+
}
|
| 328 |
+
|
| 329 |
+
iterator begin()
|
| 330 |
+
{
|
| 331 |
+
return data;
|
| 332 |
+
}
|
| 333 |
+
|
| 334 |
+
iterator end()
|
| 335 |
+
{
|
| 336 |
+
return data+size();
|
| 337 |
+
}
|
| 338 |
+
|
| 339 |
+
const_iterator begin() const
|
| 340 |
+
{
|
| 341 |
+
return data;
|
| 342 |
+
}
|
| 343 |
+
|
| 344 |
+
const_iterator end() const
|
| 345 |
+
{
|
| 346 |
+
return data+size();
|
| 347 |
+
}
|
| 348 |
+
|
| 349 |
+
|
| 350 |
+
private:
|
| 351 |
+
|
| 352 |
+
|
| 353 |
+
T* data;
|
| 354 |
+
long nc_;
|
| 355 |
+
long nr_;
|
| 356 |
+
|
| 357 |
+
typename mem_manager::template rebind<T>::other pool;
|
| 358 |
+
mutable T* cur;
|
| 359 |
+
T* last;
|
| 360 |
+
mutable bool at_start_;
|
| 361 |
+
|
| 362 |
+
};
|
| 363 |
+
|
| 364 |
+
// ----------------------------------------------------------------------------------------
|
| 365 |
+
|
| 366 |
+
template <
|
| 367 |
+
typename T,
|
| 368 |
+
typename mem_manager
|
| 369 |
+
>
|
| 370 |
+
inline void swap (
|
| 371 |
+
array2d<T,mem_manager>& a,
|
| 372 |
+
array2d<T,mem_manager>& b
|
| 373 |
+
) { a.swap(b); }
|
| 374 |
+
|
| 375 |
+
|
| 376 |
+
template <
|
| 377 |
+
typename T,
|
| 378 |
+
typename mem_manager
|
| 379 |
+
>
|
| 380 |
+
void serialize (
|
| 381 |
+
const array2d<T,mem_manager>& item,
|
| 382 |
+
std::ostream& out
|
| 383 |
+
)
|
| 384 |
+
{
|
| 385 |
+
try
|
| 386 |
+
{
|
| 387 |
+
// The reason the serialization is a little funny is because we are trying to
|
| 388 |
+
// maintain backwards compatibility with an older serialization format used by
|
| 389 |
+
// dlib while also encoding things in a way that lets the array2d and matrix
|
| 390 |
+
// objects have compatible serialization formats.
|
| 391 |
+
serialize(-item.nr(),out);
|
| 392 |
+
serialize(-item.nc(),out);
|
| 393 |
+
|
| 394 |
+
item.reset();
|
| 395 |
+
while (item.move_next())
|
| 396 |
+
serialize(item.element(),out);
|
| 397 |
+
item.reset();
|
| 398 |
+
}
|
| 399 |
+
catch (serialization_error& e)
|
| 400 |
+
{
|
| 401 |
+
throw serialization_error(e.info + "\n while serializing object of type array2d");
|
| 402 |
+
}
|
| 403 |
+
}
|
| 404 |
+
|
| 405 |
+
template <
|
| 406 |
+
typename T,
|
| 407 |
+
typename mem_manager
|
| 408 |
+
>
|
| 409 |
+
void deserialize (
|
| 410 |
+
array2d<T,mem_manager>& item,
|
| 411 |
+
std::istream& in
|
| 412 |
+
)
|
| 413 |
+
{
|
| 414 |
+
try
|
| 415 |
+
{
|
| 416 |
+
long nr, nc;
|
| 417 |
+
deserialize(nr,in);
|
| 418 |
+
deserialize(nc,in);
|
| 419 |
+
|
| 420 |
+
// this is the newer serialization format
|
| 421 |
+
if (nr < 0 || nc < 0)
|
| 422 |
+
{
|
| 423 |
+
nr *= -1;
|
| 424 |
+
nc *= -1;
|
| 425 |
+
}
|
| 426 |
+
else
|
| 427 |
+
{
|
| 428 |
+
std::swap(nr,nc);
|
| 429 |
+
}
|
| 430 |
+
|
| 431 |
+
item.set_size(nr,nc);
|
| 432 |
+
|
| 433 |
+
while (item.move_next())
|
| 434 |
+
deserialize(item.element(),in);
|
| 435 |
+
item.reset();
|
| 436 |
+
}
|
| 437 |
+
catch (serialization_error& e)
|
| 438 |
+
{
|
| 439 |
+
item.clear();
|
| 440 |
+
throw serialization_error(e.info + "\n while deserializing object of type array2d");
|
| 441 |
+
}
|
| 442 |
+
}
|
| 443 |
+
|
| 444 |
+
// ----------------------------------------------------------------------------------------
|
| 445 |
+
// ----------------------------------------------------------------------------------------
|
| 446 |
+
// member function definitions
|
| 447 |
+
// ----------------------------------------------------------------------------------------
|
| 448 |
+
// ----------------------------------------------------------------------------------------
|
| 449 |
+
|
| 450 |
+
template <
|
| 451 |
+
typename T,
|
| 452 |
+
typename mem_manager
|
| 453 |
+
>
|
| 454 |
+
void array2d<T,mem_manager>::
|
| 455 |
+
set_size (
|
| 456 |
+
long rows,
|
| 457 |
+
long cols
|
| 458 |
+
)
|
| 459 |
+
{
|
| 460 |
+
// make sure requires clause is not broken
|
| 461 |
+
DLIB_ASSERT((cols >= 0 && rows >= 0) ,
|
| 462 |
+
"\tvoid array2d::set_size(long rows, long cols)"
|
| 463 |
+
<< "\n\tThe array2d can't have negative rows or columns."
|
| 464 |
+
<< "\n\tthis: " << this
|
| 465 |
+
<< "\n\tcols: " << cols
|
| 466 |
+
<< "\n\trows: " << rows
|
| 467 |
+
);
|
| 468 |
+
|
| 469 |
+
// set the enumerator back at the start
|
| 470 |
+
at_start_ = true;
|
| 471 |
+
cur = 0;
|
| 472 |
+
|
| 473 |
+
// don't do anything if we are already the right size.
|
| 474 |
+
if (nc_ == cols && nr_ == rows)
|
| 475 |
+
{
|
| 476 |
+
return;
|
| 477 |
+
}
|
| 478 |
+
|
| 479 |
+
nc_ = cols;
|
| 480 |
+
nr_ = rows;
|
| 481 |
+
|
| 482 |
+
// free any existing memory
|
| 483 |
+
if (data != 0)
|
| 484 |
+
{
|
| 485 |
+
pool.deallocate_array(data);
|
| 486 |
+
data = 0;
|
| 487 |
+
}
|
| 488 |
+
|
| 489 |
+
// now setup this object to have the new size
|
| 490 |
+
try
|
| 491 |
+
{
|
| 492 |
+
if (nr_ > 0)
|
| 493 |
+
{
|
| 494 |
+
data = pool.allocate_array(nr_*nc_);
|
| 495 |
+
last = data + nr_*nc_ - 1;
|
| 496 |
+
}
|
| 497 |
+
}
|
| 498 |
+
catch (...)
|
| 499 |
+
{
|
| 500 |
+
if (data)
|
| 501 |
+
pool.deallocate_array(data);
|
| 502 |
+
|
| 503 |
+
data = 0;
|
| 504 |
+
nc_ = 0;
|
| 505 |
+
nr_ = 0;
|
| 506 |
+
last = 0;
|
| 507 |
+
throw;
|
| 508 |
+
}
|
| 509 |
+
}
|
| 510 |
+
|
| 511 |
+
// ----------------------------------------------------------------------------------------
|
| 512 |
+
|
| 513 |
+
template <typename T, typename MM>
|
| 514 |
+
struct is_array2d <array2d<T,MM> >
|
| 515 |
+
{
|
| 516 |
+
const static bool value = true;
|
| 517 |
+
};
|
| 518 |
+
|
| 519 |
+
// ----------------------------------------------------------------------------------------
|
| 520 |
+
|
| 521 |
+
}
|
| 522 |
+
|
| 523 |
+
#endif // DLIB_ARRAY2D_KERNEl_1_
|
| 524 |
+
|
difpoint/lib/dlib/dlib/array2d/array2d_kernel_abstract.h
ADDED
|
@@ -0,0 +1,339 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Copyright (C) 2006 Davis E. King (davis@dlib.net)
|
| 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 |
+
|
difpoint/lib/dlib/dlib/array2d/serialize_pixel_overloads.h
ADDED
|
@@ -0,0 +1,371 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Copyright (C) 2006 Davis E. King (davis@dlib.net)
|
| 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 |
+
|
difpoint/lib/dlib/dlib/assert.h
ADDED
|
@@ -0,0 +1,217 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
|
| 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 |
+
|
difpoint/lib/dlib/dlib/base64.h
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Copyright (C) 2006 Davis E. King (davis@dlib.net)
|
| 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 |
+
|
difpoint/lib/dlib/dlib/base64/base64_kernel_1.cpp
ADDED
|
@@ -0,0 +1,403 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Copyright (C) 2006 Davis E. King (davis@dlib.net)
|
| 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 |
+
|
difpoint/lib/dlib/dlib/base64/base64_kernel_1.h
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Copyright (C) 2006 Davis E. King (davis@dlib.net)
|
| 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 |
+
|
difpoint/lib/dlib/dlib/base64/base64_kernel_abstract.h
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Copyright (C) 2006 Davis E. King (davis@dlib.net)
|
| 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 |
+
|
difpoint/lib/dlib/dlib/bayes_utils.h
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Copyright (C) 2007 Davis E. King (davis@dlib.net)
|
| 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 |
+
|
difpoint/lib/dlib/dlib/bayes_utils/bayes_utils.h
ADDED
|
@@ -0,0 +1,1677 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Copyright (C) 2007 Davis E. King (davis@dlib.net)
|
| 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 |
+
while (message_sent)
|
| 1522 |
+
{
|
| 1523 |
+
message_sent = false;
|
| 1524 |
+
for (unsigned long i = 1; i < remaining_msg_to_send.size(); ++i)
|
| 1525 |
+
{
|
| 1526 |
+
// if node i hasn't sent any messages but has received all but one then send a message to the one
|
| 1527 |
+
// node who hasn't sent i a message
|
| 1528 |
+
if (remaining_msg_to_send[i].size() == join_tree.node(i).number_of_neighbors() && remaining_msg_to_receive[i].size() == 1)
|
| 1529 |
+
{
|
| 1530 |
+
unsigned long to;
|
| 1531 |
+
// get the last remaining thing from this set
|
| 1532 |
+
remaining_msg_to_receive[i].remove_any(to);
|
| 1533 |
+
|
| 1534 |
+
// send the message
|
| 1535 |
+
pass_join_tree_message(join_tree, bn_join_tree, i, to);
|
| 1536 |
+
|
| 1537 |
+
// record that we sent this message
|
| 1538 |
+
remaining_msg_to_send[i].destroy(to);
|
| 1539 |
+
remaining_msg_to_receive[to].destroy(i);
|
| 1540 |
+
|
| 1541 |
+
// put to back in since we still need to receive it
|
| 1542 |
+
remaining_msg_to_receive[i].add(to);
|
| 1543 |
+
message_sent = true;
|
| 1544 |
+
}
|
| 1545 |
+
else if (remaining_msg_to_receive[i].size() == 0 && remaining_msg_to_send[i].size() > 0)
|
| 1546 |
+
{
|
| 1547 |
+
unsigned long to;
|
| 1548 |
+
remaining_msg_to_send[i].remove_any(to);
|
| 1549 |
+
remaining_msg_to_receive[to].destroy(i);
|
| 1550 |
+
pass_join_tree_message(join_tree, bn_join_tree, i, to);
|
| 1551 |
+
message_sent = true;
|
| 1552 |
+
}
|
| 1553 |
+
}
|
| 1554 |
+
|
| 1555 |
+
if (remaining_msg_to_receive[0].size() == 0)
|
| 1556 |
+
{
|
| 1557 |
+
// send a message to all of the root nodes neighbors unless we have already sent out he messages
|
| 1558 |
+
while (remaining_msg_to_send[0].size() > 0)
|
| 1559 |
+
{
|
| 1560 |
+
unsigned long to;
|
| 1561 |
+
remaining_msg_to_send[0].remove_any(to);
|
| 1562 |
+
remaining_msg_to_receive[to].destroy(0);
|
| 1563 |
+
pass_join_tree_message(join_tree, bn_join_tree, 0, to);
|
| 1564 |
+
message_sent = true;
|
| 1565 |
+
}
|
| 1566 |
+
}
|
| 1567 |
+
|
| 1568 |
+
|
| 1569 |
+
}
|
| 1570 |
+
|
| 1571 |
+
}
|
| 1572 |
+
|
| 1573 |
+
};
|
| 1574 |
+
}
|
| 1575 |
+
|
| 1576 |
+
class bayesian_network_join_tree : noncopyable
|
| 1577 |
+
{
|
| 1578 |
+
/*!
|
| 1579 |
+
use the pimpl idiom to push the template arguments from the class level to the
|
| 1580 |
+
constructor level
|
| 1581 |
+
!*/
|
| 1582 |
+
|
| 1583 |
+
public:
|
| 1584 |
+
|
| 1585 |
+
template <
|
| 1586 |
+
typename T,
|
| 1587 |
+
typename U
|
| 1588 |
+
>
|
| 1589 |
+
bayesian_network_join_tree (
|
| 1590 |
+
const T& bn,
|
| 1591 |
+
const U& join_tree
|
| 1592 |
+
)
|
| 1593 |
+
{
|
| 1594 |
+
// make sure requires clause is not broken
|
| 1595 |
+
DLIB_ASSERT( bn.number_of_nodes() > 0 ,
|
| 1596 |
+
"\tbayesian_network_join_tree::bayesian_network_join_tree(bn,join_tree)"
|
| 1597 |
+
<< "\n\tYou have given an invalid bayesian network"
|
| 1598 |
+
<< "\n\tthis: " << this
|
| 1599 |
+
);
|
| 1600 |
+
|
| 1601 |
+
DLIB_ASSERT( is_join_tree(bn, join_tree) == true ,
|
| 1602 |
+
"\tbayesian_network_join_tree::bayesian_network_join_tree(bn,join_tree)"
|
| 1603 |
+
<< "\n\tYou have given an invalid join tree for the supplied bayesian network"
|
| 1604 |
+
<< "\n\tthis: " << this
|
| 1605 |
+
);
|
| 1606 |
+
DLIB_ASSERT( graph_contains_length_one_cycle(bn) == false,
|
| 1607 |
+
"\tbayesian_network_join_tree::bayesian_network_join_tree(bn,join_tree)"
|
| 1608 |
+
<< "\n\tYou have given an invalid bayesian network"
|
| 1609 |
+
<< "\n\tthis: " << this
|
| 1610 |
+
);
|
| 1611 |
+
DLIB_ASSERT( graph_is_connected(bn) == true,
|
| 1612 |
+
"\tbayesian_network_join_tree::bayesian_network_join_tree(bn,join_tree)"
|
| 1613 |
+
<< "\n\tYou have given an invalid bayesian network"
|
| 1614 |
+
<< "\n\tthis: " << this
|
| 1615 |
+
);
|
| 1616 |
+
|
| 1617 |
+
#ifdef ENABLE_ASSERTS
|
| 1618 |
+
for (unsigned long i = 0; i < bn.number_of_nodes(); ++i)
|
| 1619 |
+
{
|
| 1620 |
+
DLIB_ASSERT(bayes_node_utils::node_cpt_filled_out(bn,i) == true,
|
| 1621 |
+
"\tbayesian_network_join_tree::bayesian_network_join_tree(bn,join_tree)"
|
| 1622 |
+
<< "\n\tYou have given an invalid bayesian network. "
|
| 1623 |
+
<< "\n\tYou must finish filling out the conditional_probability_table of node " << i
|
| 1624 |
+
<< "\n\tthis: " << this
|
| 1625 |
+
);
|
| 1626 |
+
}
|
| 1627 |
+
#endif
|
| 1628 |
+
|
| 1629 |
+
impl.reset(new bayesian_network_join_tree_helpers::bnjt_impl<T,U>(bn, join_tree));
|
| 1630 |
+
num_nodes = bn.number_of_nodes();
|
| 1631 |
+
}
|
| 1632 |
+
|
| 1633 |
+
const matrix<double,1> probability(
|
| 1634 |
+
unsigned long idx
|
| 1635 |
+
) const
|
| 1636 |
+
{
|
| 1637 |
+
// make sure requires clause is not broken
|
| 1638 |
+
DLIB_ASSERT( idx < number_of_nodes() ,
|
| 1639 |
+
"\tconst matrix<double,1> bayesian_network_join_tree::probability(idx)"
|
| 1640 |
+
<< "\n\tYou have specified an invalid node index"
|
| 1641 |
+
<< "\n\tidx: " << idx
|
| 1642 |
+
<< "\n\tnumber_of_nodes(): " << number_of_nodes()
|
| 1643 |
+
<< "\n\tthis: " << this
|
| 1644 |
+
);
|
| 1645 |
+
|
| 1646 |
+
return impl->probability(idx);
|
| 1647 |
+
}
|
| 1648 |
+
|
| 1649 |
+
unsigned long number_of_nodes (
|
| 1650 |
+
) const { return num_nodes; }
|
| 1651 |
+
|
| 1652 |
+
void swap (
|
| 1653 |
+
bayesian_network_join_tree& item
|
| 1654 |
+
)
|
| 1655 |
+
{
|
| 1656 |
+
exchange(num_nodes, item.num_nodes);
|
| 1657 |
+
impl.swap(item.impl);
|
| 1658 |
+
}
|
| 1659 |
+
|
| 1660 |
+
private:
|
| 1661 |
+
|
| 1662 |
+
std::unique_ptr<bayesian_network_join_tree_helpers::bnjt> impl;
|
| 1663 |
+
unsigned long num_nodes;
|
| 1664 |
+
|
| 1665 |
+
};
|
| 1666 |
+
|
| 1667 |
+
inline void swap (
|
| 1668 |
+
bayesian_network_join_tree& a,
|
| 1669 |
+
bayesian_network_join_tree& b
|
| 1670 |
+
) { a.swap(b); }
|
| 1671 |
+
|
| 1672 |
+
}
|
| 1673 |
+
|
| 1674 |
+
// ----------------------------------------------------------------------------------------
|
| 1675 |
+
|
| 1676 |
+
#endif // DLIB_BAYES_UTILs_
|
| 1677 |
+
|
difpoint/lib/dlib/dlib/bayes_utils/bayes_utils_abstract.h
ADDED
|
@@ -0,0 +1,1042 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Copyright (C) 2007 Davis E. King (davis@dlib.net)
|
| 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 |
+
|
difpoint/lib/dlib/dlib/bigint.h
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
|
| 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 |
+
|
difpoint/lib/dlib/dlib/bigint/bigint_kernel_1.cpp
ADDED
|
@@ -0,0 +1,1720 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
|
| 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 |
+
|
difpoint/lib/dlib/dlib/bigint/bigint_kernel_1.h
ADDED
|
@@ -0,0 +1,543 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
|
| 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 |
+
|
difpoint/lib/dlib/dlib/bigint/bigint_kernel_2.cpp
ADDED
|
@@ -0,0 +1,1945 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
|
| 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::round(a[i*2].real()));
|
| 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::round(a[i*2+1].real()));
|
| 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 |
+
|