summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/safe_numerics
diff options
context:
space:
mode:
Diffstat (limited to 'src/boost/libs/safe_numerics')
-rw-r--r--src/boost/libs/safe_numerics/CMakeLists.txt130
-rw-r--r--src/boost/libs/safe_numerics/Jamfile.v211
-rw-r--r--src/boost/libs/safe_numerics/LICENSE_1_0.txt23
-rw-r--r--src/boost/libs/safe_numerics/README.md12
-rw-r--r--src/boost/libs/safe_numerics/b2.log0
-rw-r--r--src/boost/libs/safe_numerics/example/CMakeLists.txt54
-rw-r--r--src/boost/libs/safe_numerics/example/Jamfile.v230
-rw-r--r--src/boost/libs/safe_numerics/example/Motor.c179
-rw-r--r--src/boost/libs/safe_numerics/example/example1.cpp42
-rw-r--r--src/boost/libs/safe_numerics/example/example10.cpp45
-rw-r--r--src/boost/libs/safe_numerics/example/example11.cpp42
-rw-r--r--src/boost/libs/safe_numerics/example/example13.cpp36
-rw-r--r--src/boost/libs/safe_numerics/example/example14.cpp37
-rw-r--r--src/boost/libs/safe_numerics/example/example15.cpp45
-rw-r--r--src/boost/libs/safe_numerics/example/example16.cpp16
-rw-r--r--src/boost/libs/safe_numerics/example/example17.cpp16
-rw-r--r--src/boost/libs/safe_numerics/example/example18.cpp19
-rw-r--r--src/boost/libs/safe_numerics/example/example19.cpp32
-rw-r--r--src/boost/libs/safe_numerics/example/example2.cpp40
-rw-r--r--src/boost/libs/safe_numerics/example/example20.cpp29
-rw-r--r--src/boost/libs/safe_numerics/example/example3.cpp47
-rw-r--r--src/boost/libs/safe_numerics/example/example4.cpp57
-rw-r--r--src/boost/libs/safe_numerics/example/example5.cpp39
-rw-r--r--src/boost/libs/safe_numerics/example/example6.cpp41
-rw-r--r--src/boost/libs/safe_numerics/example/example7.cpp84
-rw-r--r--src/boost/libs/safe_numerics/example/example8.cpp44
-rw-r--r--src/boost/libs/safe_numerics/example/example81.cpp18
-rw-r--r--src/boost/libs/safe_numerics/example/example82.cpp23
-rw-r--r--src/boost/libs/safe_numerics/example/example83.cpp37
-rw-r--r--src/boost/libs/safe_numerics/example/example84.cpp66
-rw-r--r--src/boost/libs/safe_numerics/example/example91.cpp90
-rw-r--r--src/boost/libs/safe_numerics/example/example92.cpp207
-rw-r--r--src/boost/libs/safe_numerics/example/example93.cpp306
-rw-r--r--src/boost/libs/safe_numerics/example/motor1.c152
-rw-r--r--src/boost/libs/safe_numerics/example/motor2.c169
-rw-r--r--src/boost/libs/safe_numerics/example/motor3.c197
-rw-r--r--src/boost/libs/safe_numerics/example/motor_test1.c44
-rw-r--r--src/boost/libs/safe_numerics/example/motor_test2.c48
-rw-r--r--src/boost/libs/safe_numerics/example/motor_test3.c58
-rw-r--r--src/boost/libs/safe_numerics/example/picsfr.h29
-rw-r--r--src/boost/libs/safe_numerics/example/safe_format.hpp52
-rw-r--r--src/boost/libs/safe_numerics/example/stepper-motor.pdfbin0 -> 1198964 bytes
-rw-r--r--src/boost/libs/safe_numerics/index.html15
-rw-r--r--src/boost/libs/safe_numerics/meta/libraries.json15
-rw-r--r--src/boost/libs/safe_numerics/test/CMakeLists.txt148
-rw-r--r--src/boost/libs/safe_numerics/test/Jamfile.v2122
-rw-r--r--src/boost/libs/safe_numerics/test/check_symmetry.hpp10
-rw-r--r--src/boost/libs/safe_numerics/test/test0.cpp146
-rw-r--r--src/boost/libs/safe_numerics/test/test_add.hpp147
-rw-r--r--src/boost/libs/safe_numerics/test/test_add_automatic.cpp71
-rw-r--r--src/boost/libs/safe_numerics/test/test_add_automatic_constexpr.cpp58
-rw-r--r--src/boost/libs/safe_numerics/test/test_add_automatic_results.hpp59
-rw-r--r--src/boost/libs/safe_numerics/test/test_add_constexpr.hpp30
-rw-r--r--src/boost/libs/safe_numerics/test/test_add_native.cpp69
-rw-r--r--src/boost/libs/safe_numerics/test/test_add_native_constexpr.cpp59
-rw-r--r--src/boost/libs/safe_numerics/test/test_add_native_results.hpp60
-rw-r--r--src/boost/libs/safe_numerics/test/test_and.hpp146
-rw-r--r--src/boost/libs/safe_numerics/test/test_and_automatic.cpp62
-rw-r--r--src/boost/libs/safe_numerics/test/test_and_automatic_constexpr.cpp58
-rw-r--r--src/boost/libs/safe_numerics/test/test_and_native.cpp62
-rw-r--r--src/boost/libs/safe_numerics/test/test_and_native_constexpr.cpp59
-rw-r--r--src/boost/libs/safe_numerics/test/test_assignment.cpp123
-rw-r--r--src/boost/libs/safe_numerics/test/test_assignment.hpp102
-rw-r--r--src/boost/libs/safe_numerics/test/test_auto.cpp89
-rw-r--r--src/boost/libs/safe_numerics/test/test_cast.cpp126
-rw-r--r--src/boost/libs/safe_numerics/test/test_cast_constexpr.cpp90
-rw-r--r--src/boost/libs/safe_numerics/test/test_checked_add.cpp131
-rw-r--r--src/boost/libs/safe_numerics/test/test_checked_add.hpp44
-rw-r--r--src/boost/libs/safe_numerics/test/test_checked_add_constexpr.cpp97
-rw-r--r--src/boost/libs/safe_numerics/test/test_checked_and.cpp134
-rw-r--r--src/boost/libs/safe_numerics/test/test_checked_and.hpp44
-rw-r--r--src/boost/libs/safe_numerics/test/test_checked_and_constexpr.cpp98
-rw-r--r--src/boost/libs/safe_numerics/test/test_checked_cast.cpp95
-rw-r--r--src/boost/libs/safe_numerics/test/test_checked_cast.hpp31
-rw-r--r--src/boost/libs/safe_numerics/test/test_checked_cast_constexpr.cpp65
-rw-r--r--src/boost/libs/safe_numerics/test/test_checked_comparison.hpp44
-rw-r--r--src/boost/libs/safe_numerics/test/test_checked_divide.cpp132
-rw-r--r--src/boost/libs/safe_numerics/test/test_checked_divide.hpp44
-rw-r--r--src/boost/libs/safe_numerics/test/test_checked_divide_constexpr.cpp92
-rw-r--r--src/boost/libs/safe_numerics/test/test_checked_equal_to.cpp118
-rw-r--r--src/boost/libs/safe_numerics/test/test_checked_equal_to_constexpr.cpp93
-rw-r--r--src/boost/libs/safe_numerics/test/test_checked_left_shift.cpp136
-rw-r--r--src/boost/libs/safe_numerics/test/test_checked_left_shift.hpp48
-rw-r--r--src/boost/libs/safe_numerics/test/test_checked_left_shift_constexpr.cpp96
-rw-r--r--src/boost/libs/safe_numerics/test/test_checked_less_than.cpp118
-rw-r--r--src/boost/libs/safe_numerics/test/test_checked_less_than_constexpr.cpp93
-rw-r--r--src/boost/libs/safe_numerics/test/test_checked_modulus.cpp132
-rw-r--r--src/boost/libs/safe_numerics/test/test_checked_modulus.hpp44
-rw-r--r--src/boost/libs/safe_numerics/test/test_checked_modulus_constexpr.cpp90
-rw-r--r--src/boost/libs/safe_numerics/test/test_checked_multiply.cpp143
-rw-r--r--src/boost/libs/safe_numerics/test/test_checked_multiply.hpp44
-rw-r--r--src/boost/libs/safe_numerics/test/test_checked_multiply_constexpr.cpp105
-rw-r--r--src/boost/libs/safe_numerics/test/test_checked_or.cpp133
-rw-r--r--src/boost/libs/safe_numerics/test/test_checked_or.hpp44
-rw-r--r--src/boost/libs/safe_numerics/test/test_checked_or_constexpr.cpp103
-rw-r--r--src/boost/libs/safe_numerics/test/test_checked_right_shift.cpp139
-rw-r--r--src/boost/libs/safe_numerics/test/test_checked_right_shift.hpp47
-rw-r--r--src/boost/libs/safe_numerics/test/test_checked_right_shift_constexpr.cpp115
-rw-r--r--src/boost/libs/safe_numerics/test/test_checked_subtract.cpp124
-rw-r--r--src/boost/libs/safe_numerics/test/test_checked_subtract.hpp44
-rw-r--r--src/boost/libs/safe_numerics/test/test_checked_subtract_constexpr.cpp94
-rw-r--r--src/boost/libs/safe_numerics/test/test_checked_values.hpp57
-rw-r--r--src/boost/libs/safe_numerics/test/test_checked_xor.cpp134
-rw-r--r--src/boost/libs/safe_numerics/test/test_checked_xor.hpp44
-rw-r--r--src/boost/libs/safe_numerics/test/test_checked_xor_constexpr.cpp107
-rw-r--r--src/boost/libs/safe_numerics/test/test_compare_automatic.hpp56
-rw-r--r--src/boost/libs/safe_numerics/test/test_compare_native.hpp48
-rw-r--r--src/boost/libs/safe_numerics/test/test_constexpr.cpp64
-rw-r--r--src/boost/libs/safe_numerics/test/test_construction.cpp172
-rw-r--r--src/boost/libs/safe_numerics/test/test_cpp.cpp36
-rw-r--r--src/boost/libs/safe_numerics/test/test_divide.hpp137
-rw-r--r--src/boost/libs/safe_numerics/test/test_divide_automatic.cpp62
-rw-r--r--src/boost/libs/safe_numerics/test/test_divide_automatic_constexpr.cpp52
-rw-r--r--src/boost/libs/safe_numerics/test/test_divide_automatic_results.hpp59
-rw-r--r--src/boost/libs/safe_numerics/test/test_divide_constexpr.hpp30
-rw-r--r--src/boost/libs/safe_numerics/test/test_divide_native.cpp63
-rw-r--r--src/boost/libs/safe_numerics/test/test_divide_native_constexpr.cpp53
-rw-r--r--src/boost/libs/safe_numerics/test/test_divide_native_results.hpp63
-rw-r--r--src/boost/libs/safe_numerics/test/test_equal.hpp162
-rw-r--r--src/boost/libs/safe_numerics/test/test_equal_automatic.cpp61
-rw-r--r--src/boost/libs/safe_numerics/test/test_equal_automatic_constexpr.cpp52
-rw-r--r--src/boost/libs/safe_numerics/test/test_equal_constexpr.hpp40
-rw-r--r--src/boost/libs/safe_numerics/test/test_equal_native.cpp60
-rw-r--r--src/boost/libs/safe_numerics/test/test_equal_native_constexpr.cpp52
-rw-r--r--src/boost/libs/safe_numerics/test/test_float.cpp36
-rw-r--r--src/boost/libs/safe_numerics/test/test_interval.cpp184
-rw-r--r--src/boost/libs/safe_numerics/test/test_left_shift.hpp148
-rw-r--r--src/boost/libs/safe_numerics/test/test_left_shift_automatic.cpp62
-rw-r--r--src/boost/libs/safe_numerics/test/test_left_shift_automatic_constexpr.cpp52
-rw-r--r--src/boost/libs/safe_numerics/test/test_left_shift_automatic_results.hpp65
-rw-r--r--src/boost/libs/safe_numerics/test/test_left_shift_constexpr.hpp30
-rw-r--r--src/boost/libs/safe_numerics/test/test_left_shift_native.cpp62
-rw-r--r--src/boost/libs/safe_numerics/test/test_left_shift_native_constexpr.cpp53
-rw-r--r--src/boost/libs/safe_numerics/test/test_left_shift_native_results.hpp60
-rw-r--r--src/boost/libs/safe_numerics/test/test_less_than.hpp163
-rw-r--r--src/boost/libs/safe_numerics/test/test_less_than_automatic.cpp61
-rw-r--r--src/boost/libs/safe_numerics/test/test_less_than_automatic_constexpr.cpp52
-rw-r--r--src/boost/libs/safe_numerics/test/test_less_than_constexpr.hpp40
-rw-r--r--src/boost/libs/safe_numerics/test/test_less_than_native.cpp60
-rw-r--r--src/boost/libs/safe_numerics/test/test_less_than_native_constexpr.cpp52
-rw-r--r--src/boost/libs/safe_numerics/test/test_modulus.hpp153
-rw-r--r--src/boost/libs/safe_numerics/test/test_modulus_automatic.cpp62
-rw-r--r--src/boost/libs/safe_numerics/test/test_modulus_automatic_constexpr.cpp52
-rw-r--r--src/boost/libs/safe_numerics/test/test_modulus_automatic_results.hpp60
-rw-r--r--src/boost/libs/safe_numerics/test/test_modulus_constexpr.hpp30
-rw-r--r--src/boost/libs/safe_numerics/test/test_modulus_native.cpp61
-rw-r--r--src/boost/libs/safe_numerics/test/test_modulus_native_constexpr.cpp52
-rw-r--r--src/boost/libs/safe_numerics/test/test_modulus_native_results.hpp60
-rw-r--r--src/boost/libs/safe_numerics/test/test_multiply.hpp151
-rw-r--r--src/boost/libs/safe_numerics/test/test_multiply_automatic.cpp69
-rw-r--r--src/boost/libs/safe_numerics/test/test_multiply_automatic_constexpr.cpp57
-rw-r--r--src/boost/libs/safe_numerics/test/test_multiply_automatic_results.hpp59
-rw-r--r--src/boost/libs/safe_numerics/test/test_multiply_constexpr.hpp30
-rw-r--r--src/boost/libs/safe_numerics/test/test_multiply_native.cpp68
-rw-r--r--src/boost/libs/safe_numerics/test/test_multiply_native_constexpr.cpp56
-rw-r--r--src/boost/libs/safe_numerics/test/test_multiply_native_results.hpp48
-rw-r--r--src/boost/libs/safe_numerics/test/test_notepad.hpp12
-rw-r--r--src/boost/libs/safe_numerics/test/test_or.hpp147
-rw-r--r--src/boost/libs/safe_numerics/test/test_or_automatic.cpp62
-rw-r--r--src/boost/libs/safe_numerics/test/test_or_automatic_constexpr.cpp53
-rw-r--r--src/boost/libs/safe_numerics/test/test_or_constexpr.hpp30
-rw-r--r--src/boost/libs/safe_numerics/test/test_or_native.cpp62
-rw-r--r--src/boost/libs/safe_numerics/test/test_or_native_constexpr.cpp53
-rw-r--r--src/boost/libs/safe_numerics/test/test_performance.cpp112
-rw-r--r--src/boost/libs/safe_numerics/test/test_range.cpp96
-rw-r--r--src/boost/libs/safe_numerics/test/test_rational.cpp109
-rw-r--r--src/boost/libs/safe_numerics/test/test_right_shift.hpp149
-rw-r--r--src/boost/libs/safe_numerics/test/test_right_shift_automatic.cpp63
-rw-r--r--src/boost/libs/safe_numerics/test/test_right_shift_automatic_constexpr.cpp52
-rw-r--r--src/boost/libs/safe_numerics/test/test_right_shift_automatic_results.hpp60
-rw-r--r--src/boost/libs/safe_numerics/test/test_right_shift_constexpr.hpp30
-rw-r--r--src/boost/libs/safe_numerics/test/test_right_shift_native.cpp62
-rw-r--r--src/boost/libs/safe_numerics/test/test_right_shift_native_constexpr.cpp52
-rw-r--r--src/boost/libs/safe_numerics/test/test_right_shift_native_results.hpp59
-rw-r--r--src/boost/libs/safe_numerics/test/test_safe_compare.cpp165
-rw-r--r--src/boost/libs/safe_numerics/test/test_subtract.hpp146
-rw-r--r--src/boost/libs/safe_numerics/test/test_subtract_automatic.cpp64
-rw-r--r--src/boost/libs/safe_numerics/test/test_subtract_automatic_constexpr.cpp52
-rw-r--r--src/boost/libs/safe_numerics/test/test_subtract_automatic_results.hpp65
-rw-r--r--src/boost/libs/safe_numerics/test/test_subtract_constexpr.hpp30
-rw-r--r--src/boost/libs/safe_numerics/test/test_subtract_native.cpp65
-rw-r--r--src/boost/libs/safe_numerics/test/test_subtract_native_constexpr.cpp53
-rw-r--r--src/boost/libs/safe_numerics/test/test_subtract_native_results.hpp48
-rw-r--r--src/boost/libs/safe_numerics/test/test_trap.cpp44
-rw-r--r--src/boost/libs/safe_numerics/test/test_values.hpp71
-rw-r--r--src/boost/libs/safe_numerics/test/test_xor.hpp176
-rw-r--r--src/boost/libs/safe_numerics/test/test_xor_automatic.cpp60
-rw-r--r--src/boost/libs/safe_numerics/test/test_xor_automatic_constexpr.cpp52
-rw-r--r--src/boost/libs/safe_numerics/test/test_xor_constexpr.hpp30
-rw-r--r--src/boost/libs/safe_numerics/test/test_xor_native.cpp61
-rw-r--r--src/boost/libs/safe_numerics/test/test_xor_native_constexpr.cpp51
-rw-r--r--src/boost/libs/safe_numerics/test/test_z.cpp793
192 files changed, 14927 insertions, 0 deletions
diff --git a/src/boost/libs/safe_numerics/CMakeLists.txt b/src/boost/libs/safe_numerics/CMakeLists.txt
new file mode 100644
index 000000000..ba45fbe55
--- /dev/null
+++ b/src/boost/libs/safe_numerics/CMakeLists.txt
@@ -0,0 +1,130 @@
+# CMake build control file for safe numerics Library Examples
+
+cmake_minimum_required(VERSION 3.8.6)
+
+project("SafeIntegers")
+enable_language(CXX)
+
+########################################################
+# Create interface library
+#
+add_library(boost_safe_numerics INTERFACE)
+add_library(Boost::safe_numerics ALIAS boost_safe_numerics)
+
+target_include_directories(boost_safe_numerics INTERFACE "${Boost_INCLUDE_DIRS}")
+target_compile_features(boost_safe_numerics INTERFACE cxx_std_14)
+
+########################################################
+# Compiler settings - special settings for known compilers
+#
+
+set(CMAKE_CXX_STANDARD 14)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+set(CMAKE_CXX_EXTENSIONS OFF)
+
+message(STATUS "compiler is ${CMAKE_CXX_COMPILER_ID}" )
+
+if( CMAKE_CXX_COMPILER_ID STREQUAL "GNU" )
+ add_definitions( -ftemplate-depth=255 )
+ add_compile_options(-Wnon-virtual-dtor -ansi -Wcast-align -Wchar-subscripts -Wall -Wextra -W -Wshadow -Wsign-compare )
+elseif( CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" )
+ add_definitions( /wd4996 /wd4068 )
+ # warning level 4 and all warnings as errors
+ add_compile_options(/W4 /WX)
+elseif( CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" )
+ add_definitions( -ftemplate-depth=255 )
+ add_compile_options(-Wnon-virtual-dtor -ansi -Wcast-align -Wchar-subscripts -Wall -Wextra -W -Wshadow -Wsign-compare )
+elseif( CMAKE_CXX_COMPILER_ID STREQUAL "Clang" )
+ add_definitions( -ftemplate-depth=255 )
+ add_compile_options(-Wnon-virtual-dtor -ansi -Wcast-align -Wchar-subscripts -Wall -Wextra -W -Wshadow -Wsign-compare )
+endif()
+
+#
+# Project settings
+#
+
+find_package(Boost )
+
+if(Boost_FOUND)
+ if( CMAKE_HOST_APPLE )
+ set(Boost_ADDRESS_MODEL 64 CACHE STRING "32/64 bits")
+ endif()
+ message(STATUS "Boost directories found at ${Boost_INCLUDE_DIRS}")
+ message(STATUS "Boost version found is ${Boost_VERSION}")
+ include_directories("${Boost_INCLUDE_DIRS}") # note: sets header search path?
+elseif()
+ message("Boost NOT Found!")
+endif()
+
+message(STATUS "include directories are:" )
+get_property(dirs DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY INCLUDE_DIRECTORIES)
+foreach(dir ${dirs})
+ message(STATUS " ${dir}")
+endforeach()
+
+#use folders in organization of the IDE
+set(USE_FOLDERS TRUE)
+
+###########################
+# testing and submitting test results to the test dashboard
+
+if(0)
+
+## Create a file named CTestConfig.cmake adjacent to the current file.
+## This new file should contain the following:
+
+set(CTEST_PROJECT_NAME "Safe Numerics")
+set(CTEST_NIGHTLY_START_TIME "01:00:00 UTC")
+
+set(CTEST_DROP_METHOD "http")
+set(CTEST_DROP_SITE "my.cdash.org")
+# set(CTEST_DROP_LOCATION "/cdash/submit.php?project=MyProject")
+set(CTEST_DROP_LOCATION "/index.php?project=Safe+Numerics")
+set(CTEST_DROP_SITE_CDASH TRUE)
+
+endif()
+
+function(test_run_pass base_name )
+ message(STATUS ${base_name})
+ add_executable(${base_name} ${base_name}.cpp)
+ add_test(NAME ${base_name} COMMAND ${base_name})
+endfunction(test_run_pass)
+
+function(test_compile_pass base_name )
+ message(STATUS ${base_name} - compile only)
+ add_library(${base_name} OBJECT ${base_name})
+endfunction(test_compile_pass)
+
+function(test_compile_fail base_name )
+ message(STATUS ${base_name})
+ # Add failing-to-compile targets
+ add_executable(${base_name} ${base_name}.cpp)
+
+ # Avoid building these targets normally
+ set_target_properties(${base_name} PROPERTIES
+ EXCLUDE_FROM_ALL TRUE
+ EXCLUDE_FROM_DEFAULT_BUILD TRUE
+ )
+
+ # Add the tests. These invoke "cmake --build ..." which is a
+ # cross-platform way of building the given target.
+ add_test(NAME ${base_name}
+ COMMAND ${CMAKE_COMMAND} --build . --target ${base_name} --config $<CONFIGURATION>
+ WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
+ )
+
+ # Expect these tests to fail
+ # (i.e. cmake --build should return a non-zero value)
+ set_tests_properties(${base_name} PROPERTIES WILL_FAIL TRUE)
+endfunction( test_compile_fail base_name )
+
+########################################################
+# End Compiler settings
+#
+
+enable_testing()
+
+add_subdirectory("include/boost/safe_numerics")
+add_subdirectory("example")
+add_subdirectory("test")
+
diff --git a/src/boost/libs/safe_numerics/Jamfile.v2 b/src/boost/libs/safe_numerics/Jamfile.v2
new file mode 100644
index 000000000..31fb5b0bd
--- /dev/null
+++ b/src/boost/libs/safe_numerics/Jamfile.v2
@@ -0,0 +1,11 @@
+# Boost.SafeNumerics Library example Jamfile
+#
+# Copyright (c) 2017 Robert Ramey
+#
+# Distributed under the Boost Software License, Version 1.0.
+# See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt
+
+build-project example ;
+build-project test ;
+#build-project performance ;
diff --git a/src/boost/libs/safe_numerics/LICENSE_1_0.txt b/src/boost/libs/safe_numerics/LICENSE_1_0.txt
new file mode 100644
index 000000000..36b7cd93c
--- /dev/null
+++ b/src/boost/libs/safe_numerics/LICENSE_1_0.txt
@@ -0,0 +1,23 @@
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/src/boost/libs/safe_numerics/README.md b/src/boost/libs/safe_numerics/README.md
new file mode 100644
index 000000000..badb9897c
--- /dev/null
+++ b/src/boost/libs/safe_numerics/README.md
@@ -0,0 +1,12 @@
+safe_numerics
+=============
+
+Arithmetic operations in C++ are NOT guaranteed to yield a correct mathematical result. This feature is inherited from the early days of C. The behavior of int, unsigned int and others were designed to map closely to the underlying hardware. Computer hardware implements these types as a fixed number of bits. When the result of arithmetic operations exceeds this number of bits, the result is undefined and usually not what the programmer intended. It is incumbent upon the C++ programmer to guarantee that this behavior does not result in incorrect behavior of the program. This library implements special versions of these data types which behave exactly like the original ones EXCEPT that the results of these operations are checked to be sure that an exception will be thrown anytime an attempt is made to store the result of an undefined operation.
+
+Note: This is the subject of a various presentations at CPPCon.
+
+The first one is a short version which gives the main motivation for the library with a rowsing sales pitch. Fun and suitable for upper management. https://www.youtube.com/watch?v=cw_8QkFXZjI&t=1s
+
+The second is more extensive in that it addresses a real world case study which touches on most of the important aspects of the libary. https://www.youtube.com/watch?v=93Cjg42bGEw .
+
+Finally, for those who still enjoy the written word there is the documentation in which significant effort has been invested. http://htmlpreview.github.io/?https://github.com/robertramey/safe_numerics/master/doc/html/index.html
diff --git a/src/boost/libs/safe_numerics/b2.log b/src/boost/libs/safe_numerics/b2.log
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/boost/libs/safe_numerics/b2.log
diff --git a/src/boost/libs/safe_numerics/example/CMakeLists.txt b/src/boost/libs/safe_numerics/example/CMakeLists.txt
new file mode 100644
index 000000000..dfd581648
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/CMakeLists.txt
@@ -0,0 +1,54 @@
+# CMake build control file for safe numerics Library Examples
+
+###########################
+# examples
+
+message( STATUS "Runtimes are stored in ${CMAKE_CURRENT_BINARY_DIR}" )
+
+set(run_examples_list
+ example1
+ example2
+ example3
+ example4
+ example5
+ example6
+ example7
+ example8
+ example10
+ example11
+ example13
+ example14
+ example15
+ example18
+ example19
+ example20
+ example82
+ example83
+ example84
+ example92
+ example93
+)
+
+foreach(test_name ${run_examples_list})
+ test_run_pass(${test_name})
+ set_target_properties(${test_name} PROPERTIES FOLDER "run test examples")
+endforeach(test_name)
+
+test_compile_fail(example81)
+set_target_properties(example81 PROPERTIES FOLDER "safe numeric compile fail tests")
+
+# end examples targets
+####################
+
+###########################
+# add misc files to IDE
+
+file(GLOB misc_files
+ RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
+ "${CMAKE_CURRENT_SOURCE_DIR}/*.h" "${CMAKE_CURRENT_SOURCE_DIR}/*.c"
+)
+add_custom_target(miscellaneous SOURCES ${misc_files})
+set_target_properties(miscellaneous PROPERTIES FOLDER "examples")
+
+# end headers in IDE
+####################
diff --git a/src/boost/libs/safe_numerics/example/Jamfile.v2 b/src/boost/libs/safe_numerics/example/Jamfile.v2
new file mode 100644
index 000000000..46aecb29c
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/Jamfile.v2
@@ -0,0 +1,30 @@
+# Boost.SafeNumerics Library test Jamfile
+#
+# Copyright (c) 2017 Robert Ramey
+#
+# Distributed under the Boost Software License, Version 1.0.
+# See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt
+
+import testing ;
+
+run example1.cpp ;
+run example11.cpp ;
+run example2.cpp ;
+run example3.cpp ;
+run example4.cpp ;
+run example5.cpp ;
+run example6.cpp ;
+run example7.cpp ;
+run example8.cpp ;
+compile-fail example81.cpp ;
+run example82.cpp ;
+run example83.cpp ;
+run example84.cpp ;
+run example10.cpp ;
+run example11.cpp ;
+run example13.cpp ;
+run example15.cpp ;
+run example92.cpp ;
+run example93.cpp ;
+
diff --git a/src/boost/libs/safe_numerics/example/Motor.c b/src/boost/libs/safe_numerics/example/Motor.c
new file mode 100644
index 000000000..cc9e91c5e
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/Motor.c
@@ -0,0 +1,179 @@
+// Demo program for stepper motor control with linear ramps
+// Hardware: PIC18F252, L6219
+#include "18F252.h"
+
+// PIC18F252 SFRs
+#byte TRISC = 0xf94
+#byte T3CON = 0xfb1
+#byte CCP2CON = 0xfba
+#byte CCPR2L = 0xfbb
+#byte CCPR2H = 0xfbc
+#byte CCP1CON = 0xfbd
+#byte CCPR1L = 0xfbe
+#byte CCPR1H = 0xfbf
+#byte T1CON = 0xfcd
+#byte TMR1L = 0xfce
+#byte TMR1H = 0xfcf
+#bit TMR1ON = T1CON.0
+
+// 1st step=50ms; max speed=120rpm (based on 1MHz timer, 1.8deg steps)
+#define C0 50000
+#define C_MIN 2500
+
+// ramp state-machine states
+#define ramp_idle 0
+#define ramp_up 1
+#define ramp_max 2
+#define ramp_down 3
+#define ramp_last 4
+
+// Types: int8,int16,int32=8,16,32bit integers, unsigned by default
+int8 ramp_sts=ramp_idle;
+signed int16 motor_pos = 0; // absolute step number
+signed int16 pos_inc=0; // motor_pos increment
+int16 phase=0; // ccpPhase[phase_ix]
+int8 phase_ix=0; // index to ccpPhase[]
+int8 phase_inc; // phase_ix increment
+int8 run_flg; // true while motor is running
+int16 ccpr; // copy of CCPR1&2
+int16 c; // integer delay count
+int16 step_no; // progress of move
+int16 step_down; // start of down-ramp
+int16 move; // total steps to move
+int16 midpt; // midpoint of move
+int32 c32; // 24.8 fixed point delay count
+signed int16 denom; // 4.n+1 in ramp algo
+
+// Config data to make CCP1&2 generate quadrature sequence on PHASE pins
+// Action on CCP match: 8=set+irq; 9=clear+irq
+int16 const ccpPhase[] = {0x909, 0x908, 0x808, 0x809}; // 00,01,11,10
+
+void current_on(){/* code as needed */} // motor drive current
+void current_off(){/* code as needed */} // reduce to holding value
+
+// compiler-specific ISR declaration
+#INT_CCP1
+void isr_motor_step()
+{ // CCP1 match -> step pulse + IRQ
+ ccpr += c; // next comparator value: add step delay count
+ switch (ramp_sts)
+ {
+ case ramp_up: // accel
+ if (step_no==midpt)
+ { // midpoint: decel
+ ramp_sts = ramp_down;
+ denom = ((step_no - move)<<2)+1;
+ if (!(move & 1))
+ { // even move: repeat last delay before decel
+ denom +=4;
+ break;
+ }
+ }
+ // no break: share code for ramp algo
+ case ramp_down: // decel
+ if (step_no == move-1)
+ { // next irq is cleanup (no step)
+ ramp_sts = ramp_last;
+ break;
+ }
+ denom+=4;
+ c32 -= (c32<<1)/denom; // ramp algorithm
+ // beware confict with foreground code if long div not reentrant
+ c = (c32+128)>>8; // round 24.8format->int16
+ if (c <= C_MIN)
+ { // go to constant speed
+ ramp_sts = ramp_max;
+ step_down = move - step_no;
+ c = C_MIN;
+ break;
+ }
+ break;
+ case ramp_max: // constant speed
+ if (step_no == step_down)
+ { // start decel
+ ramp_sts = ramp_down;
+ denom = ((step_no - move)<<2)+5;
+ }
+ break;
+ default: // last step: cleanup
+ ramp_sts = ramp_idle;
+ current_off(); // reduce motor current to holding value
+ disable_interrupts(INT_CCP1);
+ run_flg = FALSE; // move complete
+ break;
+ } // switch (ramp_sts)
+ if (ramp_sts!=ramp_idle)
+ {
+ motor_pos += pos_inc;
+ ++step_no;
+ CCPR2H = CCPR1H = (ccpr >> 8); // timer value at next CCP match
+ CCPR2L = CCPR1L = (ccpr & 0xff);
+ if (ramp_sts!=ramp_last) // else repeat last action: no step
+ phase_ix = (phase_ix + phase_inc) & 3;
+ phase = ccpPhase[phase_ix];
+ CCP1CON = phase & 0xff; // set CCP action on next match
+ CCP2CON = phase >> 8;
+ } // if (ramp_sts != ramp_idle)
+} // isr_motor_step()
+
+void motor_run(short pos_new)
+{ // set up to drive motor to pos_new (absolute step#)
+ if (pos_new < motor_pos) // get direction & #steps
+ {
+ move = motor_pos-pos_new;
+ pos_inc = -1;
+ phase_inc = 0xff;
+ }
+ else if (pos_new != motor_pos)
+ {
+ move = pos_new-motor_pos;
+ pos_inc = 1;
+ phase_inc = 1;
+ }
+ else return; // already there
+ midpt = (move-1)>>1;
+ c = C0;
+ c32 = c<<8; // keep c in 24.8 fixed-point format for ramp calcs
+ step_no = 0; // step counter
+ denom = 1; // 4.n+1, n=0
+ ramp_sts = ramp_up; // start ramp state-machine
+ run_flg = TRUE;
+ TMR1ON = 0; // stop timer1;
+ ccpr = make16(TMR1H,TMR1L); // 16bit value of Timer1
+ ccpr += 1000; // 1st step + irq 1ms after timer1 restart
+ CCPR2H = CCPR1H = (ccpr >> 8);
+ CCPR2L = CCPR1L = (ccpr & 0xff);
+ phase_ix = (phase_ix + phase_inc) & 3;
+ phase = ccpPhase[phase_ix];
+ CCP1CON = phase & 0xff; // sets action on match
+ CCP2CON = phase >> 8;
+ current_on(); // current in motor windings
+ enable_interrupts(INT_CCP1);
+ TMR1ON=1; // restart timer1;
+} // motor_run()
+
+
+void initialize()
+{
+ disable_interrupts(GLOBAL);
+ disable_interrupts(INT_CCP1);
+ disable_interrupts(INT_CCP2);
+ output_c(0);
+ set_tris_c(0);
+ T3CON = 0;
+ T1CON = 0x35;
+ enable_interrupts(GLOBAL);
+} // initialize()
+
+void main()
+{
+ initialize();
+ while (1)
+ { // repeat 5 revs forward & back
+ motor_run(1000);
+ while (run_flg);
+ motor_run(0);
+ while (run_flg);
+ }
+} // main()
+// end of file motor.c
diff --git a/src/boost/libs/safe_numerics/example/example1.cpp b/src/boost/libs/safe_numerics/example/example1.cpp
new file mode 100644
index 000000000..2d2f67fdf
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/example1.cpp
@@ -0,0 +1,42 @@
+// Copyright (c) 2018 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+
+int main(int, const char *[]){
+ std::cout << "example 1:";
+ std::cout << "undetected erroneous expression evaluation" << std::endl;
+ std::cout << "Not using safe numerics" << std::endl;
+ try{
+ std::int8_t x = 127;
+ std::int8_t y = 2;
+ std::int8_t z;
+ // this produces an invalid result !
+ z = x + y;
+ std::cout << "error NOT detected!" << std::endl;
+ std::cout << (int)z << " != " << (int)x << " + " << (int)y << std::endl;
+ }
+ catch(const std::exception &){
+ std::cout << "error detected!" << std::endl;
+ }
+ // solution: replace int with safe<int>
+ std::cout << "Using safe numerics" << std::endl;
+ try{
+ using namespace boost::safe_numerics;
+ safe<std::int8_t> x = INT_MAX;
+ safe<std::int8_t> y = 2;
+ safe<std::int8_t> z;
+ // rather than producing an invalid result an exception is thrown
+ z = x + y;
+ }
+ catch(const std::exception & e){
+ // which we can catch here
+ std::cout << "error detected:" << e.what() << std::endl;
+ }
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/example/example10.cpp b/src/boost/libs/safe_numerics/example/example10.cpp
new file mode 100644
index 000000000..f67969748
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/example10.cpp
@@ -0,0 +1,45 @@
+#include <iostream>
+#include <cstdint>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+
+using namespace std;
+using namespace boost::safe_numerics;
+
+void f(const unsigned int & x, const int8_t & y){
+ cout << x * y << endl;
+}
+void safe_f(
+ const safe<unsigned int> & x,
+ const safe<int8_t> & y
+){
+ cout << x * y << endl;
+}
+
+int main(){
+ cout << "example 4: ";
+ cout << "mixing types produces surprising results" << endl;
+ try {
+ std::cout << "Not using safe numerics" << std::endl;
+ // problem: mixing types produces surprising results.
+ f(100, 100); // works as expected
+ f(100, -100); // wrong result - unnoticed
+ cout << "error NOT detected!" << endl;;
+ }
+ catch(const std::exception & e){
+ // never arrive here
+ cout << "error detected:" << e.what() << endl;;
+ }
+ try {
+ // solution: use safe types
+ std::cout << "Using safe numerics" << std::endl;
+ safe_f(100, 100); // works as expected
+ safe_f(100, -100); // throw error
+ cout << "error NOT detected!" << endl;;
+ }
+ catch(const std::exception & e){
+ cout << "error detected:" << e.what() << endl;;
+ }
+ return 0;
+}
+
diff --git a/src/boost/libs/safe_numerics/example/example11.cpp b/src/boost/libs/safe_numerics/example/example11.cpp
new file mode 100644
index 000000000..51c17f05f
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/example11.cpp
@@ -0,0 +1,42 @@
+// Copyright (c) 2018 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+
+int main(int, const char * []){
+ std::cout << "example 1:";
+ std::cout << "undetected erroneous expression evaluation" << std::endl;
+ std::cout << "Not using safe numerics" << std::endl;
+ // problem: arithmetic operations can yield incorrect results.
+ try{
+ std::int8_t x = 127;
+ std::int8_t y = 2;
+ std::int8_t z;
+ // this produces an invalid result !
+ z = x + y;
+ std::cout << z << " != " << x + y << std::endl;
+ std::cout << "error NOT detected!" << std::endl;
+ }
+ catch(const std::exception &){
+ std::cout << "error detected!" << std::endl;
+ }
+ // solution: replace std::int8_t with safe<std::int8_t>
+ std::cout << "Using safe numerics" << std::endl;
+ try{
+ using namespace boost::safe_numerics;
+ safe<std::int8_t> x = 127;
+ safe<std::int8_t> y = 2;
+ // rather than producing and invalid result an exception is thrown
+ safe<std::int8_t> z = x + y;
+ }
+ catch(const std::exception & e){
+ // which can catch here
+ std::cout << e.what() << std::endl;
+ }
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/example/example13.cpp b/src/boost/libs/safe_numerics/example/example13.cpp
new file mode 100644
index 000000000..f78c6dc5d
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/example13.cpp
@@ -0,0 +1,36 @@
+#include <stdexcept>
+#include <iostream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+
+int main(int, const char *[]){
+ // problem: cannot recover from arithmetic errors
+ std::cout << "example 7: ";
+ std::cout << "cannot recover from arithmetic errors" << std::endl;
+ std::cout << "Not using safe numerics" << std::endl;
+
+ try{
+ int x = 1;
+ int y = 0;
+ // can't do this as it will crash the program with no
+ // opportunity for recovery - comment out for example
+ // std::cout << x / y;
+ std::cout << "error cannot be handled at runtime!" << std::endl;
+ }
+ catch(const std::exception &){
+ std::cout << "error handled at runtime!" << std::endl;
+ }
+ // solution: replace int with safe<int>
+ std::cout << "Using safe numerics" << std::endl;
+ try{
+ using namespace boost::safe_numerics;
+ const safe<int> x = 1;
+ const safe<int> y = 0;
+ std::cout << x / y;
+ std::cout << "error NOT detected!" << std::endl;
+ }
+ catch(const std::exception & e){
+ std::cout << "error handled at runtime!" << e.what() << std::endl;
+ }
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/example/example14.cpp b/src/boost/libs/safe_numerics/example/example14.cpp
new file mode 100644
index 000000000..44a206d21
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/example14.cpp
@@ -0,0 +1,37 @@
+#include <stdexcept>
+#include <iostream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+
+int main(int, const char *[]){
+ // problem: cannot recover from arithmetic errors
+ std::cout << "example 8: ";
+ std::cout << "cannot detect compile time arithmetic errors" << std::endl;
+ std::cout << "Not using safe numerics" << std::endl;
+
+ try{
+ const int x = 1;
+ const int y = 0;
+ // will emit warning at compile time
+ // will leave an invalid result at runtime.
+ std::cout << x / y; // will display "0"!
+ std::cout << "error NOT detected!" << std::endl;
+ }
+ catch(const std::exception &){
+ std::cout << "error detected!" << std::endl;
+ }
+ // solution: replace int with safe<int>
+ std::cout << "Using safe numerics" << std::endl;
+ try{
+ using namespace boost::safe_numerics;
+ const safe<int> x = 1;
+ const safe<int> y = 0;
+ // constexpr const safe<int> z = x / y; // note constexpr here!
+ std::cout << x / y; // error would be detected at runtime
+ std::cout << " error NOT detected!" << std::endl;
+ }
+ catch(const std::exception & e){
+ std::cout << "error detected:" << e.what() << std::endl;
+ }
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/example/example15.cpp b/src/boost/libs/safe_numerics/example/example15.cpp
new file mode 100644
index 000000000..829dff299
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/example15.cpp
@@ -0,0 +1,45 @@
+#include <iostream>
+#include <limits>
+
+#include <boost/rational.hpp>
+#include <boost/safe_numerics/safe_integer.hpp>
+
+int main(int, const char *[]){
+ // simple demo of rational library
+ const boost::rational<int> r {1, 2};
+ std::cout << "r = " << r << std::endl;
+ const boost::rational<int> q {-2, 4};
+ std::cout << "q = " << q << std::endl;
+ // display the product
+ std::cout << "r * q = " << r * q << std::endl;
+
+ // problem: rational doesn't handle integer overflow well
+ const boost::rational<int> c {1, INT_MAX};
+ std::cout << "c = " << c << std::endl;
+ const boost::rational<int> d {1, 2};
+ std::cout << "d = " << d << std::endl;
+ // display the product - wrong answer
+ std::cout << "c * d = " << c * d << std::endl;
+
+ // solution: use safe integer in rational definition
+ using safe_rational = boost::rational<
+ boost::safe_numerics::safe<int>
+ >;
+
+ // use rationals created with safe_t
+ const safe_rational sc {1, INT_MAX};
+ std::cout << "c = " << sc << std::endl;
+ const safe_rational sd {1, 2};
+ std::cout << "d = " << sd << std::endl;
+ std::cout << "c * d = ";
+ try {
+ // multiply them. This will overflow
+ std::cout << sc * sd << std::endl;
+ }
+ catch (std::exception const& e) {
+ // catch exception due to multiplication overflow
+ std::cout << e.what() << std::endl;
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/example/example16.cpp b/src/boost/libs/safe_numerics/example/example16.cpp
new file mode 100644
index 000000000..d67824526
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/example16.cpp
@@ -0,0 +1,16 @@
+#include <boost/safe_numerics/safe_integer.hpp>
+using namespace boost::safe_numerics;
+
+int f(int i){
+ return i;
+}
+
+using safe_t = safe<long>;
+
+int main(){
+ const long x = 97;
+ f(x); // OK - implicit conversion to int
+ const safe_t y = 97;
+ f(y); // Also OK - checked implicit conversion to int
+ return 0;
+} \ No newline at end of file
diff --git a/src/boost/libs/safe_numerics/example/example17.cpp b/src/boost/libs/safe_numerics/example/example17.cpp
new file mode 100644
index 000000000..372be9cca
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/example17.cpp
@@ -0,0 +1,16 @@
+#include <boost/safe_numerics/safe_integer.hpp>
+using namespace boost::safe_numerics;
+
+int f(int i){
+ return i;
+}
+
+using safe_t = safe<long, native, loose_trap_policy>;
+
+int main(){
+ const long x = 97;
+ f(x); // OK - implicit conversion to int
+ const safe_t y = 97;
+ f(y); // Would be OK, but will invoke compile time error
+ return 0;
+} \ No newline at end of file
diff --git a/src/boost/libs/safe_numerics/example/example18.cpp b/src/boost/libs/safe_numerics/example/example18.cpp
new file mode 100644
index 000000000..bb59602ee
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/example18.cpp
@@ -0,0 +1,19 @@
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/safe_integer_literal.hpp>
+
+using namespace boost::safe_numerics;
+
+int f(int i){
+ return i;
+}
+
+template<intmax_t N>
+using safe_literal = safe_signed_literal<N, native, loose_trap_policy>;
+
+int main(){
+ const long x = 97;
+ f(x); // OK - implicit conversion to int
+ const safe_literal<97> y;
+ f(y); // OK - y is a type with min/max = 97;
+ return 0;
+} \ No newline at end of file
diff --git a/src/boost/libs/safe_numerics/example/example19.cpp b/src/boost/libs/safe_numerics/example/example19.cpp
new file mode 100644
index 000000000..e9cd46488
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/example19.cpp
@@ -0,0 +1,32 @@
+#include <type_traits>
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/safe_integer_range.hpp>
+
+#include <boost/safe_numerics/utility.hpp>
+
+using namespace boost::safe_numerics;
+
+void f(){
+ safe_unsigned_range<7, 24> i;
+ // since the range is included in [0,255], the underlying type of i
+ // will be an unsigned char.
+ i = 0; // throws out_of_range exception
+ i = 9; // ok
+ i *= 9; // throws out_of_range exception
+ i = -1; // throws out_of_range exception
+ std::uint8_t j = 4;
+ auto k = i + j;
+
+ // if either or both types are safe types, the result is a safe type
+ // determined by promotion policy. In this instance
+ // the range of i is [7, 24] and the range of j is [0,255].
+ // so the type of k will be a safe type with a range of [7,279]
+ static_assert(
+ is_safe<decltype(k)>::value
+ && std::numeric_limits<decltype(k)>::min() == 7
+ && std::numeric_limits<decltype(k)>::max() == 279,
+ "k is a safe range of [7,279]"
+ );
+}
+
+int main(){}
diff --git a/src/boost/libs/safe_numerics/example/example2.cpp b/src/boost/libs/safe_numerics/example/example2.cpp
new file mode 100644
index 000000000..3866fe854
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/example2.cpp
@@ -0,0 +1,40 @@
+// Copyright (c) 2018 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+
+int main(int, const char *[]){
+ std::cout << "example 2:";
+ std::cout << "undetected overflow in data type" << std::endl;
+ // problem: undetected overflow
+ std::cout << "Not using safe numerics" << std::endl;
+ try{
+ int x = INT_MAX;
+ // the following silently produces an incorrect result
+ ++x;
+ std::cout << x << " != " << INT_MAX << " + 1" << std::endl;
+ std::cout << "error NOT detected!" << std::endl;
+ }
+ catch(const std::exception &){
+ std::cout << "error detected!" << std::endl;
+ }
+ // solution: replace int with safe<int>
+ std::cout << "Using safe numerics" << std::endl;
+ try{
+ using namespace boost::safe_numerics;
+ safe<int> x = INT_MAX;
+ // throws exception when result is past maximum possible
+ ++x;
+ assert(false); // never arrive here
+ }
+ catch(const std::exception & e){
+ std::cout << e.what() << std::endl;
+ std::cout << "error detected!" << std::endl;
+ }
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/example/example20.cpp b/src/boost/libs/safe_numerics/example/example20.cpp
new file mode 100644
index 000000000..160995d0f
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/example20.cpp
@@ -0,0 +1,29 @@
+// Copyright (c) 2018 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+#include <boost/safe_numerics/checked_result.hpp>
+#include <boost/safe_numerics/checked_result_operations.hpp>
+
+int main(){
+ using ext_uint = boost::safe_numerics::checked_result<unsigned int>;
+ const ext_uint x{4};
+ const ext_uint y{3};
+
+ // operation is a success!
+ std::cout << "success! x - y = " << x - y;
+
+ // subtraction would result in -1, and invalid result for an unsigned value
+ std::cout << "problem: y - x = " << y - x;
+
+ const ext_uint z = y - x;
+ std::cout << "z = " << z;
+ // sum of two negative overflows is a negative overflow.
+ std::cout << "z + z" << z + z;
+
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/example/example3.cpp b/src/boost/libs/safe_numerics/example/example3.cpp
new file mode 100644
index 000000000..15b810ebb
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/example3.cpp
@@ -0,0 +1,47 @@
+// Copyright (c) 2018 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+
+int main(int, const char *[]){
+ std::cout << "example 3:";
+ std::cout << "undetected underflow in data type" << std::endl;
+ std::cout << "Not using safe numerics" << std::endl;
+ // problem: decrement can yield incorrect result
+ try{
+ unsigned int x = 0;
+ // the following silently produces an incorrect result
+ --x;
+ std::cout << x << " != " << -1 << std::endl;
+
+ // when comparing int and unsigned int, C++ converts
+ // the int to unsigned int so the following assertion
+ // fails to detect the above error!
+ assert(x == -1);
+
+ std::cout << "error NOT detected!" << std::endl;
+ }
+ catch(const std::exception &){
+ // never arrive here
+ std::cout << "error detected!" << std::endl;
+ }
+ // solution: replace unsigned int with safe<unsigned int>
+ std::cout << "Using safe numerics" << std::endl;
+ try{
+ using namespace boost::safe_numerics;
+ safe<unsigned int> x = 0;
+ // decrement unsigned to less than zero throws exception
+ --x;
+ assert(false); // never arrive here
+ }
+ catch(const std::exception & e){
+ std::cout << e.what() << std::endl;
+ std::cout << "error detected!" << std::endl;
+ }
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/example/example4.cpp b/src/boost/libs/safe_numerics/example/example4.cpp
new file mode 100644
index 000000000..d3b8eae77
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/example4.cpp
@@ -0,0 +1,57 @@
+// Copyright (c) 2018Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+
+int main(){
+ std::cout << "example 4: ";
+ std::cout << "implicit conversions change data values" << std::endl;
+ std::cout << "Not using safe numerics" << std::endl;
+
+ // problem: implicit conversions change data values
+ try{
+ signed int a{-1};
+ unsigned int b{1};
+ std::cout << "a is " << a << " b is " << b << '\n';
+ if(a < b){
+ std::cout << "a is less than b\n";
+ }
+ else{
+ std::cout << "b is less than a\n";
+ }
+ std::cout << "error NOT detected!" << std::endl;
+ }
+ catch(const std::exception &){
+ // never arrive here - just produce the wrong answer!
+ std::cout << "error detected!" << std::endl;
+ return 1;
+ }
+
+ // solution: replace int with safe<int> and unsigned int with safe<unsigned int>
+ std::cout << "Using safe numerics" << std::endl;
+ try{
+ using namespace boost::safe_numerics;
+ safe<signed int> a{-1};
+ safe<unsigned int> b{1};
+ std::cout << "a is " << a << " b is " << b << '\n';
+ if(a < b){
+ std::cout << "a is less than b\n";
+ }
+ else{
+ std::cout << "b is less than a\n";
+ }
+ std::cout << "error NOT detected!" << std::endl;
+ return 1;
+ }
+ catch(const std::exception & e){
+ // never arrive here - just produce the correct answer!
+ std::cout << e.what() << std::endl;
+ std::cout << "error detected!" << std::endl;
+ }
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/example/example5.cpp b/src/boost/libs/safe_numerics/example/example5.cpp
new file mode 100644
index 000000000..efb3d2ea2
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/example5.cpp
@@ -0,0 +1,39 @@
+#include <stdexcept>
+#include <iostream>
+#include <array>
+
+#include <boost/safe_numerics/safe_integer_range.hpp>
+
+void detected_msg(bool detected){
+ std::cout << (detected ? "error detected!" : "error NOT detected! ") << std::endl;
+}
+
+int main(int, const char *[]){
+ // problem: array index values can exceed array bounds
+ std::cout << "example 5: ";
+ std::cout << "array index values can exceed array bounds" << std::endl;
+ std::cout << "Not using safe numerics" << std::endl;
+ std::array<int, 37> i_array;
+
+ // unsigned int i_index = 43;
+ // the following corrupts memory.
+ // This may or may not be detected at run time.
+ // i_array[i_index] = 84; // comment this out so it can be tested!
+ std::cout << "error NOT detected!" << std::endl;
+
+ // solution: replace unsigned array index with safe_unsigned_range
+ std::cout << "Using safe numerics" << std::endl;
+ try{
+ using namespace boost::safe_numerics;
+ using i_index_t = safe_unsigned_range<0, i_array.size() - 1>;
+ i_index_t i_index;
+ i_index = 36; // this works fine
+ i_array[i_index] = 84;
+ i_index = 43; // throw exception here!
+ std::cout << "error NOT detected!" << std::endl; // so we never arrive here
+ }
+ catch(const std::exception & e){
+ std::cout << "error detected:" << e.what() << std::endl;
+ }
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/example/example6.cpp b/src/boost/libs/safe_numerics/example/example6.cpp
new file mode 100644
index 000000000..fbd44a8e3
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/example6.cpp
@@ -0,0 +1,41 @@
+#include <stdexcept>
+#include <sstream>
+#include <iostream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+
+int main(int, const char *[]){
+ // problem: checking of externally produced value can be overlooked
+ std::cout << "example 6: ";
+ std::cout << "checking of externally produced value can be overlooked" << std::endl;
+ std::cout << "Not using safe numerics" << std::endl;
+
+ std::istringstream is("12317289372189 1231287389217389217893");
+
+ try{
+ int x, y;
+ is >> x >> y; // get integer values from the user
+ std::cout << x << ' ' << y << std::endl;
+ std::cout << "error NOT detected!" << std::endl;
+ }
+ catch(const std::exception &){
+ std::cout << "error detected!" << std::endl;
+ }
+
+ // solution: assign externally retrieved values to safe equivalents
+ std::cout << "Using safe numerics" << std::endl;
+ {
+ using namespace boost::safe_numerics;
+ safe<int> x, y;
+ is.seekg(0);
+ try{
+ is >> x >> y; // get integer values from the user
+ std::cout << x << ' ' << y << std::endl;
+ std::cout << "error NOT detected!" << std::endl;
+ }
+ catch(const std::exception & e){
+ std::cout << "error detected:" << e.what() << std::endl;
+ }
+ }
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/example/example7.cpp b/src/boost/libs/safe_numerics/example/example7.cpp
new file mode 100644
index 000000000..076abfd82
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/example7.cpp
@@ -0,0 +1,84 @@
+#include <cassert>
+#include <stdexcept>
+#include <sstream>
+#include <iostream>
+
+#include <boost/safe_numerics/safe_integer_range.hpp>
+
+// NOT using safe numerics - enforce program contract explicitly
+// return total number of minutes
+unsigned int contract_convert(
+ const unsigned int & hours,
+ const unsigned int & minutes
+) {
+ // check that parameters are within required limits
+ // invokes a runtime cost EVERYTIME the function is called
+ // and the overhead of supporting an interrupt.
+ // note high runtime cost!
+ if(minutes > 59)
+ throw std::domain_error("minutes exceeded 59");
+ if(hours > 23)
+ throw std::domain_error("hours exceeded 23");
+ return hours * 60 + minutes;
+}
+
+// Use safe numerics to enforce program contract automatically
+// define convenient typenames for hours and minutes hh:mm
+using hours_t = boost::safe_numerics::safe_unsigned_range<0, 23>;
+using minutes_t = boost::safe_numerics::safe_unsigned_range<0, 59>;
+using minutes_total_t = boost::safe_numerics::safe_unsigned_range<0, 59>;
+
+// return total number of minutes
+// type returned is safe_unsigned_range<0, 24*60 - 1>
+auto convert(const hours_t & hours, const minutes_t & minutes) {
+ // no need to test pre-conditions
+ // input parameters are guaranteed to hold legitimate values
+ // no need to test post-conditions
+ // return value guaranteed to hold result
+ return hours * 60 + minutes;
+}
+
+unsigned int test1(unsigned int hours, unsigned int minutes){
+ // problem: checking of externally produced value can be expensive
+ // invalid parameters - detected - but at a heavy cost
+ return contract_convert(hours, minutes);
+}
+
+auto test2(unsigned int hours, unsigned int minutes){
+ // solution: use safe numerics
+ // safe types can be implicitly constructed base types
+ // construction guarentees corectness
+ // return value is known to fit in unsigned int
+ return convert(hours, minutes);
+}
+
+auto test3(unsigned int hours, unsigned int minutes){
+ // actually we don't even need the convert function any more
+ return hours_t(hours) * 60 + minutes_t(minutes);
+}
+
+int main(int, const char *[]){
+ std::cout << "example 7: ";
+ std::cout << "enforce contracts with zero runtime cost" << std::endl;
+
+ unsigned int total_minutes;
+
+ try {
+ total_minutes = test3(17, 83);
+ std::cout << "total minutes = " << total_minutes << std::endl;
+ }
+ catch(const std::exception & e){
+ std::cout << "parameter error detected" << std::endl;
+ }
+
+ try {
+ total_minutes = test3(17, 10);
+ std::cout << "total minutes = " << total_minutes << std::endl;
+ }
+ catch(const std::exception & e){
+ // should never arrive here
+ std::cout << "parameter error erroneously detected" << std::endl;
+ return 1;
+ }
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/example/example8.cpp b/src/boost/libs/safe_numerics/example/example8.cpp
new file mode 100644
index 000000000..a8229f197
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/example8.cpp
@@ -0,0 +1,44 @@
+// Copyright (c) 2018 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+
+int main(int, const char *[]){
+ std::cout << "example 8:";
+ std::cout << "undetected erroneous expression evaluation" << std::endl;
+ std::cout << "Not using safe numerics" << std::endl;
+ try{
+ unsigned int x = 127;
+ unsigned int y = 2;
+ unsigned int z;
+ // this produces an invalid result !
+ z = y - x;
+ std::cout << "error NOT detected!" << std::endl;
+ std::cout << z << " != " << y << " - " << x << std::endl;
+ }
+ catch(const std::exception &){
+ std::cout << "error detected!" << std::endl;
+ }
+ // solution: replace int with safe<int>
+ std::cout << "Using safe numerics" << std::endl;
+ try{
+ using namespace boost::safe_numerics;
+ safe<unsigned int> x = 127;
+ safe<unsigned int> y = 2;
+ safe<unsigned int> z;
+ // rather than producing an invalid result an exception is thrown
+ z = y - x;
+ std::cout << "error NOT detected!" << std::endl;
+ std::cout << z << " != " << y << " - " << x << std::endl;
+ }
+ catch(const std::exception & e){
+ // which we can catch here
+ std::cout << "error detected:" << e.what() << std::endl;
+ }
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/example/example81.cpp b/src/boost/libs/safe_numerics/example/example81.cpp
new file mode 100644
index 000000000..0d7f7c0e8
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/example81.cpp
@@ -0,0 +1,18 @@
+#include <iostream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/exception_policies.hpp> // include exception policies
+
+using safe_t = boost::safe_numerics::safe<
+ int,
+ boost::safe_numerics::native,
+ boost::safe_numerics::loose_trap_policy // note use of "loose_trap_exception" policy!
+>;
+
+int main(){
+ std::cout << "example 81:\n";
+ safe_t x(INT_MAX);
+ safe_t y(2);
+ safe_t z = x + y; // will fail to compile !
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/example/example82.cpp b/src/boost/libs/safe_numerics/example/example82.cpp
new file mode 100644
index 000000000..0e49e9e74
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/example82.cpp
@@ -0,0 +1,23 @@
+#include <iostream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/exception_policies.hpp>
+#include <boost/safe_numerics/automatic.hpp>
+#include "safe_format.hpp" // prints out range and value of any type
+
+using safe_t = boost::safe_numerics::safe<
+ int,
+ boost::safe_numerics::automatic, // note use of "automatic" policy!!!
+ boost::safe_numerics::loose_trap_policy
+>;
+
+int main(int, const char *[]){
+ std::cout << "example 82:\n";
+ safe_t x(INT_MAX);
+ safe_t y = 2;
+ std::cout << "x = " << safe_format(x) << std::endl;
+ std::cout << "y = " << safe_format(y) << std::endl;
+ std::cout << "x + y = " << safe_format(x + y) << std::endl;
+ return 0;
+}
+
diff --git a/src/boost/libs/safe_numerics/example/example83.cpp b/src/boost/libs/safe_numerics/example/example83.cpp
new file mode 100644
index 000000000..3d345b62f
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/example83.cpp
@@ -0,0 +1,37 @@
+#include <iostream>
+
+#include <boost/safe_numerics/safe_integer_range.hpp>
+#include <boost/safe_numerics/safe_integer_literal.hpp>
+#include <boost/safe_numerics/exception.hpp>
+#include <boost/safe_numerics/native.hpp>
+#include "safe_format.hpp" // prints out range and value of any type
+
+using namespace boost::safe_numerics;
+
+// create a type for holding small integers in a specific range
+using safe_t = safe_signed_range<
+ -24,
+ 82,
+ native, // C++ type promotion rules work OK for this example
+ loose_trap_policy // catch problems at compile time
+>;
+
+// create a type to hold one specific value
+template<int I>
+using const_safe_t = safe_signed_literal<I, native, loose_trap_policy>;
+
+// We "know" that C++ type promotion rules will work such that
+// addition will never overflow. If we change the program to break this,
+// the usage of the loose_trap_policy promotion policy will prevent compilation.
+int main(int, const char *[]){
+ std::cout << "example 83:\n";
+
+ constexpr const const_safe_t<10> x;
+ std::cout << "x = " << safe_format(x) << std::endl;
+ constexpr const const_safe_t<67> y;
+ std::cout << "y = " << safe_format(y) << std::endl;
+ const safe_t z = x + y;
+ std::cout << "x + y = " << safe_format(x + y) << std::endl;
+ std::cout << "z = " << safe_format(z) << std::endl;
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/example/example84.cpp b/src/boost/libs/safe_numerics/example/example84.cpp
new file mode 100644
index 000000000..f7809d9a7
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/example84.cpp
@@ -0,0 +1,66 @@
+#include <stdexcept>
+#include <iostream>
+#include <sstream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/safe_integer_range.hpp>
+#include <boost/safe_numerics/native.hpp>
+#include <boost/safe_numerics/exception.hpp>
+
+#include "safe_format.hpp" // prints out range and value of any type
+
+using namespace boost::safe_numerics;
+
+using safe_t = safe_signed_range<
+ -24,
+ 82,
+ native,
+ loose_trap_policy
+>;
+
+// define variables used for input
+using input_safe_t = safe_signed_range<
+ -24,
+ 82,
+ native, // we don't need automatic in this case
+ loose_exception_policy // assignment of out of range value should throw
+>;
+
+// function arguments can never be outside of limits
+auto f(const safe_t & x, const safe_t & y){
+ auto z = x + y; // we know that this cannot fail
+ std::cout << "z = " << safe_format(z) << std::endl;
+ std::cout << "(x + y) = " << safe_format(x + y) << std::endl;
+ std::cout << "(x - y) = " << safe_format(x - y) << std::endl;
+ return z;
+}
+
+bool test(const char * test_string){
+ std::istringstream sin(test_string);
+ input_safe_t x, y;
+ try{
+ std::cout << "type in values in format x y:" << test_string << std::endl;
+ sin >> x >> y; // read varibles, maybe throw exception
+ }
+ catch(const std::exception & e){
+ // none of the above should trap. Mark failure if they do
+ std::cout << e.what() << '\n' << "input failure" << std::endl;
+ return false;
+ }
+ std::cout << "x" << safe_format(x) << std::endl;
+ std::cout << "y" << safe_format(y) << std::endl;
+ std::cout << safe_format(f(x, y)) << std::endl;
+ std::cout << "input success" << std::endl;
+ return true;
+}
+
+int main(){
+ std::cout << "example 84:\n";
+ bool result =
+ ! test("123 125")
+ && test("0 0")
+ && test("-24 82")
+ ;
+ std::cout << (result ? "Success!" : "Failure") << std::endl;
+ return result ? EXIT_SUCCESS : EXIT_FAILURE;
+}
diff --git a/src/boost/libs/safe_numerics/example/example91.cpp b/src/boost/libs/safe_numerics/example/example91.cpp
new file mode 100644
index 000000000..f3bc48725
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/example91.cpp
@@ -0,0 +1,90 @@
+//////////////////////////////////////////////////////////////////
+// example91.cpp
+//
+// Copyright (c) 2015 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+#include <limits>
+
+#include <boost/safe_numerics/cpp.hpp>
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics//safe_integer_range.hpp>
+
+// use same type promotion as used by the pic compiler
+// see the following comment in motor.c
+// Types: int8,int16,int32=8,16,32bit integers
+
+using pic16_promotion = boost::safe_numerics::cpp<
+ 8, // char
+ 8, // short
+ 8, // int
+ 16, // long
+ 32 // long long
+>;
+
+// define safe types used desktop version of the program. In conjunction
+// with the promotion policy above, this will permit us to guarantee that
+// the resulting program will be free of arithmetic errors introduced by
+// C expression syntax and type promotion with no runtime penalty
+template <typename T> // T is char, int, etc data type
+using safe_t = boost::safe_numerics::safe<
+ T,
+ pic16_promotion,
+ boost::safe_numerics::default_exception_policy // use for compiling and running tests
+>;
+using safe_bool_t = boost::safe_numerics::safe_unsigned_range<
+ 0,
+ 1,
+ pic16_promotion,
+ boost::safe_numerics::default_exception_policy // use for compiling and running tests
+>;
+
+#define DESKTOP
+#include "motor1.c"
+
+#include <chrono>
+#include <thread>
+
+void sleep(int16){
+ std::this_thread::sleep_for(std::chrono::microseconds(ccpr));
+}
+
+int main(){
+ std::cout << "start test\n";
+ try{
+ initialize();
+ motor_run(100);
+ do{
+ isr_motor_step();
+ }while (run_flg);
+
+ // move motor to position 1000
+ motor_run(1000);
+ do{
+ sleep(ccpr);
+ isr_motor_step();
+ }while (run_flg);
+
+ // move back to position 0
+ motor_run(0);
+ do{
+ sleep(ccpr);
+ isr_motor_step();
+ }while (run_flg);
+ }
+ catch(std::exception & e){
+ std::cout << e.what() << '\n';
+ // we expect to trap an exception
+ return 0;
+ }
+ catch(...){
+ std::cout << "test interrupted\n";
+ return 1;
+ }
+ std::cout << "end test\n";
+ return 1;
+}
diff --git a/src/boost/libs/safe_numerics/example/example92.cpp b/src/boost/libs/safe_numerics/example/example92.cpp
new file mode 100644
index 000000000..cec7928f1
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/example92.cpp
@@ -0,0 +1,207 @@
+//////////////////////////////////////////////////////////////////
+// example92.cpp
+//
+// Copyright (c) 2015 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+// ***************************
+// 1. include headers to support safe integers
+#include <boost/safe_numerics/cpp.hpp>
+#include <boost/safe_numerics/exception.hpp>
+#include <boost/safe_numerics/safe_integer.hpp>
+
+// ***************************
+// 2. specify a promotion policy to support proper emulation of
+// PIC types on the desktop
+using pic16_promotion = boost::safe_numerics::cpp<
+ 8, // char 8 bits
+ 16, // short 16 bits
+ 16, // int 16 bits
+ 16, // long 16 bits
+ 32 // long long 32 bits
+>;
+
+// 1st step=50ms; max speed=120rpm (based on 1MHz timer, 1.8deg steps)
+#define C0 (50000 << 8)
+#define C_MIN (2500 << 8)
+
+static_assert(C0 < 0xffffff, "Largest step too long");
+static_assert(C_MIN > 0, "Smallest step must be greater than zero");
+static_assert(C_MIN < C0, "Smallest step must be smaller than largest step");
+
+// ***************************
+// 3. define PIC integer type names to be safe integer types of he same size.
+
+template <typename T> // T is char, int, etc data type
+using safe_t = boost::safe_numerics::safe<
+ T,
+ pic16_promotion
+>;
+
+// alias original program's integer types to corresponding PIC safe types
+// In conjunction with the promotion policy above, this will permit us to
+// guarantee that the resulting program will be free of arithmetic errors
+// introduced by C expression syntax and type promotion with no runtime penalty
+
+typedef safe_t<int8_t> int8;
+typedef safe_t<int16_t> int16;
+typedef safe_t<int32_t> int32;
+typedef safe_t<uint8_t> uint8;
+typedef safe_t<uint16_t> uint16;
+typedef safe_t<uint32_t> uint32;
+
+// ***************************
+// 4. emulate PIC features on the desktop
+
+// filter out special keyword used only by XC8 compiler
+#define __interrupt
+// filter out XC8 enable/disable global interrupts
+#define ei()
+#define di()
+
+// emulate PIC special registers
+uint8 RCON;
+uint8 INTCON;
+uint8 CCP1IE;
+uint8 CCP2IE;
+uint8 PORTC;
+uint8 TRISC;
+uint8 T3CON;
+uint8 T1CON;
+
+uint8 CCPR2H;
+uint8 CCPR2L;
+uint8 CCPR1H;
+uint8 CCPR1L;
+uint8 CCP1CON;
+uint8 CCP2CON;
+uint8 TMR1H;
+uint8 TMR1L;
+
+// create type used to map PIC bit names to
+// correct bit in PIC register
+template<typename T, std::int8_t N>
+struct bit {
+ T & m_word;
+ constexpr explicit bit(T & rhs) :
+ m_word(rhs)
+ {}
+ constexpr bit & operator=(int b){
+ if(b != 0)
+ m_word |= (1 << N);
+ else
+ m_word &= ~(1 << N);
+ return *this;
+ }
+ constexpr operator int () const {
+ return m_word >> N & 1;
+ }
+};
+
+// define bits for T1CON register
+struct {
+ bit<uint8, 7> RD16{T1CON};
+ bit<uint8, 5> T1CKPS1{T1CON};
+ bit<uint8, 4> T1CKPS0{T1CON};
+ bit<uint8, 3> T1OSCEN{T1CON};
+ bit<uint8, 2> T1SYNC{T1CON};
+ bit<uint8, 1> TMR1CS{T1CON};
+ bit<uint8, 0> TMR1ON{T1CON};
+} T1CONbits;
+
+// define bits for T1CON register
+struct {
+ bit<uint8, 7> GEI{INTCON};
+ bit<uint8, 5> PEIE{INTCON};
+ bit<uint8, 4> TMR0IE{INTCON};
+ bit<uint8, 3> RBIE{INTCON};
+ bit<uint8, 2> TMR0IF{INTCON};
+ bit<uint8, 1> INT0IF{INTCON};
+ bit<uint8, 0> RBIF{INTCON};
+} INTCONbits;
+
+// ***************************
+// 5. include the environment independent code we want to test
+#include "motor2.c"
+
+#include <chrono>
+#include <thread>
+
+// round 24.8 format to microseconds
+int32 to_microseconds(uint32 t){
+ return (t + 128) / 256;
+}
+
+using result_t = uint8_t;
+const result_t success = 1;
+const result_t fail = 0;
+
+// move motor to the indicated target position in steps
+result_t test(int32 m){
+ try {
+ std::cout << "move motor to " << m << '\n';
+ motor_run(m);
+ std::cout
+ << "step #" << ' '
+ << "delay(us)(24.8)" << ' '
+ << "delay(us)" << ' '
+ << "CCPR" << ' '
+ << "motor position" << '\n';
+ do{
+ std::this_thread::sleep_for(std::chrono::microseconds(to_microseconds(c)));
+ uint32 last_c = c;
+ uint32 last_ccpr = ccpr;
+ isr_motor_step();
+ std::cout
+ << step_no << ' '
+ << last_c << ' '
+ << to_microseconds(last_c) << ' '
+ << std::hex << last_ccpr << std::dec << ' '
+ << motor_pos << '\n';
+ }while(run_flg);
+ }
+ catch(const std::exception & e){
+ std::cout << e.what() << '\n';
+ return fail;
+ }
+ return success;
+}
+
+int main(){
+ std::cout << "start test\n";
+ result_t result = success;
+ try{
+ initialize();
+ // move motor to position 1000
+ result &= test(1000);
+ // move motor to position 200
+ result &= test(200);
+ // move motor to position 200 again! Should result in no movement.
+ result &= test(200);
+ // move back to position 0
+ result &= test(0);
+ // ***************************
+ // 6. error detected here! data types can't handle enough
+ // steps to move the carriage from end to end! Suppress this
+ // test for now.
+ // move motor to position 50000.
+// result &= test(50000);
+ // move motor back to position 0.
+ result &= test(0);
+ }
+ catch(const std::exception & e){
+ std::cout << e.what() << '\n';
+ return 1;
+ }
+ catch(...){
+ std::cout << "test interrupted\n";
+ return EXIT_FAILURE;
+ }
+ std::cout << "end test\n";
+ return result == success ? EXIT_SUCCESS : EXIT_FAILURE;
+}
diff --git a/src/boost/libs/safe_numerics/example/example93.cpp b/src/boost/libs/safe_numerics/example/example93.cpp
new file mode 100644
index 000000000..4044b2540
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/example93.cpp
@@ -0,0 +1,306 @@
+//////////////////////////////////////////////////////////////////
+// example93.cpp
+//
+// Copyright (c) 2015 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+// include headers to support safe integers
+#include <boost/safe_numerics/cpp.hpp>
+#include <boost/safe_numerics/exception.hpp>
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/safe_integer_range.hpp>
+#include <boost/safe_numerics/safe_integer_literal.hpp>
+
+// use same type promotion as used by the pic compiler
+// target compiler XC8 supports:
+using pic16_promotion = boost::safe_numerics::cpp<
+ 8, // char 8 bits
+ 16, // short 16 bits
+ 16, // int 16 bits
+ 16, // long 16 bits
+ 32 // long long 32 bits
+>;
+
+// ***************************
+// 1. Specify exception policies so we will generate a
+// compile time error whenever an operation MIGHT fail.
+
+// ***************************
+// generate runtime errors if operation could fail
+using exception_policy = boost::safe_numerics::default_exception_policy;
+
+// generate compile time errors if operation could fail
+using trap_policy = boost::safe_numerics::loose_trap_policy;
+
+// ***************************
+// 2. Create a macro named literal an integral value
+// that can be evaluated at compile time.
+#define literal(n) make_safe_literal(n, pic16_promotion, void)
+
+// For min speed of 2 mm / sec (24.8 format)
+// sec / step = sec / 2 mm * 2 mm / rotation * rotation / 200 steps
+#define C0 literal(5000 << 8)
+
+// For max speed of 400 mm / sec
+// sec / step = sec / 400 mm * 2 mm / rotation * rotation / 200 steps
+#define C_MIN literal(25 << 8)
+
+static_assert(
+ C0 < make_safe_literal(0xffffff, pic16_promotion,trap_policy),
+ "Largest step too long"
+);
+static_assert(
+ C_MIN > make_safe_literal(0, pic16_promotion,trap_policy),
+ "Smallest step must be greater than zero"
+);
+
+// ***************************
+// 3. Create special ranged types for the motor program
+// These wiil guarantee that values are in the expected
+// ranges and permit compile time determination of when
+// exceptional conditions might occur.
+
+using pic_register_t = boost::safe_numerics::safe<
+ uint8_t,
+ pic16_promotion,
+ trap_policy // use for compiling and running tests
+>;
+
+// note: the maximum value of step_t would be:
+// 50000 = 500 mm / 2 mm/rotation * 200 steps/rotation.
+// But in one expression the value of number of steps * 4 is
+// used. To prevent introduction of error, permit this
+// type to hold the larger value.
+using step_t = boost::safe_numerics::safe_unsigned_range<
+ 0,
+ 200000,
+ pic16_promotion,
+ exception_policy
+>;
+
+// position
+using position_t = boost::safe_numerics::safe_unsigned_range<
+ 0,
+ 50000, // 500 mm / 2 mm/rotation * 200 steps/rotation
+ pic16_promotion,
+ exception_policy
+>;
+
+// next end of step timer value in format 24.8
+// where the .8 is the number of bits in the fractional part.
+using ccpr_t = boost::safe_numerics::safe<
+ uint32_t,
+ pic16_promotion,
+ exception_policy
+>;
+
+// pulse length in format 24.8
+// note: this value is constrainted to be a positive value. But
+// we still need to make it a signed type. We get an arithmetic
+// error when moving to a negative step number.
+using c_t = boost::safe_numerics::safe_unsigned_range<
+ C_MIN,
+ C0,
+ pic16_promotion,
+ exception_policy
+>;
+
+// 32 bit unsigned integer used for temporary purposes
+using temp_t = boost::safe_numerics::safe_unsigned_range<
+ 0, 0xffffffff,
+ pic16_promotion,
+ exception_policy
+>;
+
+// index into phase table
+// note: The legal values are 0-3. So why must this be a signed
+// type? Turns out that expressions like phase_ix + d
+// will convert both operands to unsigned. This in turn will
+// create an exception. So leave it signed even though the
+// value is greater than zero.
+using phase_ix_t = boost::safe_numerics::safe_signed_range<
+ 0,
+ 3,
+ pic16_promotion,
+ trap_policy
+>;
+
+// settings for control value output
+using phase_t = boost::safe_numerics::safe<
+ uint16_t,
+ pic16_promotion,
+ trap_policy
+>;
+
+// direction of rotation
+using direction_t = boost::safe_numerics::safe_signed_range<
+ -1,
+ +1,
+ pic16_promotion,
+ trap_policy
+>;
+
+// some number of microseconds
+using microseconds = boost::safe_numerics::safe<
+ uint32_t,
+ pic16_promotion,
+ trap_policy
+>;
+
+// ***************************
+// emulate PIC features on the desktop
+
+// filter out special keyword used only by XC8 compiler
+#define __interrupt
+// filter out XC8 enable/disable global interrupts
+#define ei()
+#define di()
+
+// emulate PIC special registers
+pic_register_t RCON;
+pic_register_t INTCON;
+pic_register_t CCP1IE;
+pic_register_t CCP2IE;
+pic_register_t PORTC;
+pic_register_t TRISC;
+pic_register_t T3CON;
+pic_register_t T1CON;
+
+pic_register_t CCPR2H;
+pic_register_t CCPR2L;
+pic_register_t CCPR1H;
+pic_register_t CCPR1L;
+pic_register_t CCP1CON;
+pic_register_t CCP2CON;
+pic_register_t TMR1H;
+pic_register_t TMR1L;
+
+// ***************************
+// special checked type for bits - values restricted to 0 or 1
+using safe_bit_t = boost::safe_numerics::safe_unsigned_range<
+ 0,
+ 1,
+ pic16_promotion,
+ trap_policy
+>;
+
+// create type used to map PIC bit names to
+// correct bit in PIC register
+template<typename T, std::int8_t N>
+struct bit {
+ T & m_word;
+ constexpr explicit bit(T & rhs) :
+ m_word(rhs)
+ {}
+ // special functions for assignment of literal
+ constexpr bit & operator=(decltype(literal(1))){
+ m_word |= literal(1 << N);
+ return *this;
+ }
+ constexpr bit & operator=(decltype(literal(0))){
+ m_word &= ~literal(1 << N);
+ return *this;
+ }
+ // operator to convert to 0 or 1
+ constexpr operator safe_bit_t () const {
+ return m_word >> literal(N) & literal(1);
+ }
+};
+
+// define bits for T1CON register
+struct {
+ bit<pic_register_t, 7> RD16{T1CON};
+ bit<pic_register_t, 5> T1CKPS1{T1CON};
+ bit<pic_register_t, 4> T1CKPS0{T1CON};
+ bit<pic_register_t, 3> T1OSCEN{T1CON};
+ bit<pic_register_t, 2> T1SYNC{T1CON};
+ bit<pic_register_t, 1> TMR1CS{T1CON};
+ bit<pic_register_t, 0> TMR1ON{T1CON};
+} T1CONbits;
+
+// define bits for T1CON register
+struct {
+ bit<pic_register_t, 7> GEI{INTCON};
+ bit<pic_register_t, 5> PEIE{INTCON};
+ bit<pic_register_t, 4> TMR0IE{INTCON};
+ bit<pic_register_t, 3> RBIE{INTCON};
+ bit<pic_register_t, 2> TMR0IF{INTCON};
+ bit<pic_register_t, 1> INT0IF{INTCON};
+ bit<pic_register_t, 0> RBIF{INTCON};
+} INTCONbits;
+
+#include "motor3.c"
+
+#include <chrono>
+#include <thread>
+
+// round 24.8 format to microseconds
+microseconds to_microseconds(ccpr_t t){
+ return (t + literal(128)) / literal(256);
+}
+
+using result_t = uint8_t;
+const result_t success = 1;
+const result_t fail = 0;
+
+// move motor to the indicated target position in steps
+result_t test(position_t new_position){
+ try {
+ std::cout << "move motor to " << new_position << '\n';
+ motor_run(new_position);
+ std::cout
+ << "step #" << ' '
+ << "delay(us)(24.8)" << ' '
+ << "delay(us)" << ' '
+ << "CCPR" << ' '
+ << "motor position" << '\n';
+ while(busy()){
+ std::this_thread::sleep_for(std::chrono::microseconds(to_microseconds(c)));
+ c_t last_c = c;
+ ccpr_t last_ccpr = ccpr;
+ isr_motor_step();
+ std::cout << i << ' '
+ << last_c << ' '
+ << to_microseconds(last_c) << ' '
+ << std::hex << last_ccpr << std::dec << ' '
+ << motor_position << '\n';
+ };
+ }
+ catch(const std::exception & e){
+ std::cout << e.what() << '\n';
+ return fail;
+ }
+ return success;
+}
+
+int main(){
+ std::cout << "start test\n";
+ result_t result = success;
+ try {
+ initialize();
+ // move motor to position 1000
+ result &= test(literal(9000));
+ // move to the left before zero position
+ // fails to compile !
+ // result &= ! test(-10);
+ // move motor to position 200
+ result &= test(literal(200));
+ // move motor to position 200 again! Should result in no movement.
+ result &= test(literal(200));
+ // move motor to position 50000.
+ result &= test(literal(50000));
+ // move motor back to position 0.
+ result &= test(literal(0));
+ }
+ catch(...){
+ std::cout << "test interrupted\n";
+ return EXIT_FAILURE;
+ }
+ std::cout << "end test\n";
+ return result == success ? EXIT_SUCCESS : EXIT_FAILURE;
+}
diff --git a/src/boost/libs/safe_numerics/example/motor1.c b/src/boost/libs/safe_numerics/example/motor1.c
new file mode 100644
index 000000000..d8fb51b91
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/motor1.c
@@ -0,0 +1,152 @@
+/*
+ * david austin
+ * http://www.embedded.com/design/mcus-processors-and-socs/4006438/Generate-stepper-motor-speed-profiles-in-real-time
+ * DECEMBER 30, 2004
+ *
+ * Demo program for stepper motor control with linear ramps
+ * Hardware: PIC18F252, L6219
+ *
+ * Copyright (c) 2015 Robert Ramey
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See
+ * accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+// ramp state-machine states
+enum ramp_state {
+ ramp_idle = 0,
+ ramp_up = 1,
+ ramp_max = 2,
+ ramp_down = 3,
+ ramp_last = 4,
+};
+
+enum ramp_state ramp_sts=ramp_idle;
+int16 motor_pos = 0; // absolute step number
+int16 pos_inc=0; // motor_pos increment
+uint16 phase=0; // ccpPhase[phase_ix]
+uint8 phase_ix=0; // index to ccpPhase[]
+uint8 phase_inc; // phase_ix increment
+uint8 run_flg; // true while motor is running
+uint16 ccpr; // copy of CCPR1&2
+uint16 c; // integer delay count
+uint16 step_no; // progress of move
+uint16 step_down; // start of down-ramp
+uint16 move; // total steps to move
+uint16 midpt; // midpoint of move
+uint32 c32; // 24.8 fixed point delay count
+int16 denom; // 4.n+1 in ramp algo
+
+// Config data to make CCP1&2 generate quadrature sequence on PHASE pins
+// Action on CCP match: 8=set+irq; 9=clear+irq
+uint16 const ccpPhase[] = {0x909, 0x908, 0x808, 0x809}; // 00,01,11,10
+
+void current_on(){/* code as needed */} // motor drive current
+void current_off(){/* code as needed */} // reduce to holding value
+
+uint16 make16(uint8 l, uint8 r) {
+ return (uint16) l << 8 + r;
+}
+
+// compiler-specific ISR declaration
+
+void __interrupt isr_motor_step(void) { // CCP1 match -> step pulse + IRQ
+ ccpr += c; // next comparator value
+ switch (ramp_sts) {
+ case ramp_up: // accel
+ if (step_no == midpt) { // midpoint: decel
+ ramp_sts = ramp_down;
+ denom = ((step_no - move) << 2) + 1;
+ if (!(move & 1)) { // even move: repeat last delay before decel
+ denom += 4;
+ break;
+ }
+ }
+ // no break: share code for ramp algo
+ case ramp_down: // decel
+ if (step_no == move - 1) { // next irq is cleanup (no step)
+ ramp_sts = ramp_last;
+ break;
+ }
+ denom += 4;
+ c32 -= (c32 << 1) / denom; // ramp algorithm
+ // beware confict with foreground code if long div not reentrant
+ c = (c32 + 128) >> 8; // round 24.8format->int16
+ if (c <= C_MIN) { // go to constant speed
+ ramp_sts = ramp_max;
+ step_down = move - step_no;
+ c = C_MIN;
+ break;
+ }
+ break;
+ case ramp_max: // constant speed
+ if (step_no == step_down) { // start decel
+ ramp_sts = ramp_down;
+ denom = ((step_no - move) << 2) + 5;
+ }
+ break;
+ default: // last step: cleanup
+ ramp_sts = ramp_idle;
+ current_off(); // reduce motor current to holding value
+ CCP1IE = 0; // disable_interrupts(INT_CCP1);
+ run_flg = false; // move complete
+ break;
+ } // switch (ramp_sts)
+ if (ramp_sts != ramp_idle) {
+ motor_pos += pos_inc;
+ ++step_no;
+ CCPR2H = CCPR1H = (ccpr >> 8); // timer value at next CCP match
+ CCPR2L = CCPR1L = (ccpr & 0xff);
+ if (ramp_sts != ramp_last) // else repeat last action: no step
+ phase_ix = (phase_ix + phase_inc) & 3;
+ phase = ccpPhase[phase_ix];
+ CCP1CON = phase & 0xff; // set CCP action on next match
+ CCP2CON = phase >> 8;
+ } // if (ramp_sts != ramp_idle)
+} // isr_motor_step()
+
+void motor_run(int16 pos_new) { // set up to drive motor to pos_new (absolute step#)
+ if (pos_new < motor_pos) { // get direction & #steps
+ move = motor_pos - pos_new;
+ pos_inc = -1;
+ phase_inc = 0xff;
+ }
+ else if (pos_new != motor_pos) {
+ move = pos_new - motor_pos;
+ pos_inc = 1;
+ phase_inc = 1;
+ } else return; // already there
+ midpt = (move - 1) >> 1;
+ c = C0;
+ c32 = c << 8; // keep c in 24.8 fixed-point format for ramp calcs
+ step_no = 0; // step counter
+ denom = 1; // 4.n+1, n=0
+ ramp_sts = ramp_up; // start ramp state-machine
+ run_flg = true;
+ T1CONbits.TMR1ON = 0; // stop timer1;
+ ccpr = make16(TMR1H, TMR1L); // 16bit value of Timer1
+ ccpr += 1000; // 1st step + irq 1ms after timer1 restart
+ CCPR2H = CCPR1H = (ccpr >> 8);
+ CCPR2L = CCPR1L = (ccpr & 0xff);
+ phase_ix = (phase_ix + phase_inc) & 3;
+ phase = ccpPhase[phase_ix];
+ CCP1CON = phase & 0xff; // sets action on match
+ CCP2CON = phase >> 8;
+ current_on(); // current in motor windings
+ CCP1IE = 1; // enable_interrupts(INT_CCP1);
+ T1CONbits.TMR1ON = 1; // restart timer1;
+} // motor_run()
+
+void initialize() {
+ di(); // disable_interrupts(GLOBAL);
+ CCP1IE = 0; // disable_interrupts(INT_CCP1);
+ CCP2IE = 0; // disable_interrupts(INT_CCP2);
+ PORTC = 0; // output_c(0);
+ TRISC = 0; // set_tris_c(0);
+ T3CON = 0;
+ T1CON = 0x35;
+ INTCONbits.PEIE = 1;
+ INTCONbits.RBIF = 0;
+ ei(); // enable_interrupts(GLOBAL);
+} // initialize()
diff --git a/src/boost/libs/safe_numerics/example/motor2.c b/src/boost/libs/safe_numerics/example/motor2.c
new file mode 100644
index 000000000..78e08fef6
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/motor2.c
@@ -0,0 +1,169 @@
+/*
+ * david austin
+ * http://www.embedded.com/design/mcus-processors-and-socs/4006438/Generate-stepper-motor-speed-profiles-in-real-time
+ * DECEMBER 30, 2004
+ *
+ * Demo program for stepper motor control with linear ramps
+ * Hardware: PIC18F252, L6219
+ *
+ * Copyright (c) 2015 Robert Ramey
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See
+ * accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+// ramp state-machine states
+enum ramp_state {
+ ramp_idle = 0,
+ ramp_up = 1,
+ ramp_max = 2,
+ ramp_down = 3,
+ ramp_last = 4,
+};
+
+enum ramp_state ramp_sts=ramp_idle;
+int16 motor_pos = 0; // absolute step number
+int16 pos_inc=0; // motor_pos increment
+uint16 phase=0; // ccpPhase[phase_ix]
+uint8 phase_ix=0; // index to ccpPhase[]
+uint8 phase_inc; // phase_ix increment
+uint8 run_flg; // true while motor is running
+// ***************************
+// 1. keep track of total delay count
+uint32 ccpr; // 24.8 fixed point delay count
+uint32 c; // 24.8 fixed point delay count increment
+uint16 step_no; // progress of move
+uint16 step_down; // start of down-ramp
+uint16 move; // total steps to move
+uint16 midpt; // midpoint of move
+int16 denom; // 4.n+1 in ramp algo
+
+// Config data to make CCP1&2 generate quadrature sequence on PHASE pins
+// Action on CCP match: 8=set+irq; 9=clear+irq
+uint16 const ccpPhase[] = {0x909, 0x908, 0x808, 0x809}; // 00,01,11,10
+
+void current_on(){/* code as needed */} // motor drive current
+void current_off(){/* code as needed */} // reduce to holding value
+
+uint16 make16(uint8 l, uint8 r) {
+ return (uint16) l << 8 + r;
+}
+
+// compiler-specific ISR declaration
+
+void __interrupt isr_motor_step(void) { // CCP1 match -> step pulse + IRQ
+ ccpr += c; // next comparator value
+ switch (ramp_sts) {
+ case ramp_up: // accel
+ if (step_no == midpt) { // midpoint: decel
+ ramp_sts = ramp_down;
+ // ***************************
+ // 2. convert shift to multiplication
+ // 3. avoid negative result from subtraction of unsigned values
+ // denom = ((step_no - move) << 2) + 1;
+ if(step_no > move)
+ denom = ((step_no - move) * 4) + 1;
+ else
+ denom = ((move - step_no) * 4) - 1;
+ if (!(move & 1)) { // even move: repeat last delay before decel
+ denom += 4;
+ break;
+ }
+ }
+ // no break: share code for ramp algo
+ case ramp_down: // decel
+ if (step_no == move - 1) { // next irq is cleanup (no step)
+ ramp_sts = ramp_last;
+ break;
+ }
+ denom += 4;
+ // calculate increment/decrement in delay count
+ // ***************************
+ // 3. avoid negative result from subtraction of unsigned values
+ // c -= (c << 1) / denom; // ramp algorithm
+ if(denom > 0)
+ c -= (c << 1) / denom;
+ else
+ c += (c << 1) / -denom;
+
+ if (c <= C_MIN) { // go to constant speed
+ ramp_sts = ramp_max;
+ step_down = move - step_no;
+ c = C_MIN;
+ break;
+ }
+ break;
+ case ramp_max: // constant speed
+ if (step_no == step_down) { // start decel
+ ramp_sts = ramp_down;
+ // ***************************
+ // 2. convert shift to multiplication
+ // 3. avoid negative result from subtraction of unsigned values
+ // denom = ((step_no - move) << 2) + 1;
+ denom = 5 - ((move - step_no) * 4);
+ }
+ break;
+ default: // last step: cleanup
+ ramp_sts = ramp_idle;
+ current_off(); // reduce motor current to holding value
+ CCP1IE = 0; // disable_interrupts(INT_CCP1);
+ run_flg = false; // move complete
+ break;
+ } // switch (ramp_sts)
+ if (ramp_sts != ramp_idle) {
+ motor_pos += pos_inc;
+ ++step_no;
+ CCPR2H = CCPR1H = (ccpr >> 8); // timer value at next CCP match
+ CCPR2L = CCPR1L = (ccpr & 0xff);
+ if (ramp_sts != ramp_last) // else repeat last action: no step
+ phase_ix = (phase_ix + phase_inc) & 3;
+ phase = ccpPhase[phase_ix];
+ CCP1CON = phase & 0xff; // set CCP action on next match
+ CCP2CON = phase >> 8;
+ } // if (ramp_sts != ramp_idle)
+} // isr_motor_step()
+
+void motor_run(int16 pos_new) { // set up to drive motor to pos_new (absolute step#)
+ if (pos_new < motor_pos) { // get direction & #steps
+ move = motor_pos - pos_new;
+ pos_inc = -1;
+ phase_inc = 0xff;
+ }
+ else if (pos_new != motor_pos) {
+ move = pos_new - motor_pos;
+ pos_inc = 1;
+ phase_inc = 1;
+ } else return; // already there
+ midpt = (move - 1) >> 1;
+ c = C0;
+ step_no = 0; // step counter
+ denom = 1; // 4.n+1, n=0
+ ramp_sts = ramp_up; // start ramp state-machine
+ run_flg = true;
+ T1CONbits.TMR1ON = 0; // stop timer1;
+ ccpr = make16(TMR1H, TMR1L); // 16bit value of Timer1
+ ccpr += 1000; // 1st step + irq 1ms after timer1 restart
+ CCPR2H = CCPR1H = (ccpr >> 8);
+ CCPR2L = CCPR1L = (ccpr & 0xff);
+ phase_ix = (phase_ix + phase_inc) & 3;
+ phase = ccpPhase[phase_ix];
+ CCP1CON = phase & 0xff; // sets action on match
+ CCP2CON = phase >> 8;
+ current_on(); // current in motor windings
+ CCP1IE = 1; // enable_interrupts(INT_CCP1);
+ T1CONbits.TMR1ON = 1; // restart timer1;
+} // motor_run()
+
+void initialize() {
+ di(); // disable_interrupts(GLOBAL);
+ CCP1IE = 0; // disable_interrupts(INT_CCP1);
+ CCP2IE = 0; // disable_interrupts(INT_CCP2);
+ PORTC = 0; // output_c(0);
+ TRISC = 0; // set_tris_c(0);
+ T3CON = 0;
+ T1CON = 0x35;
+ INTCONbits.PEIE = 1;
+ INTCONbits.RBIF = 0;
+ ei(); // enable_interrupts(GLOBAL);
+} // initialize()
diff --git a/src/boost/libs/safe_numerics/example/motor3.c b/src/boost/libs/safe_numerics/example/motor3.c
new file mode 100644
index 000000000..1e805738b
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/motor3.c
@@ -0,0 +1,197 @@
+/*
+ * david austin
+ * http://www.embedded.com/design/mcus-processors-and-socs/4006438/Generate-stepper-motor-speed-profiles-in-real-time
+ * DECEMBER 30, 2004
+ *
+ * Demo program for stepper motor control with linear ramps
+ * Hardware: PIC18F252, L6219
+ *
+ * Copyright (c) 2015 Robert Ramey
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See
+ * accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#include <assert.h>
+
+// ramp state-machine states
+enum ramp_state {
+ ramp_idle = 0,
+ ramp_up = 1,
+ ramp_const = 2,
+ ramp_down = 3,
+};
+
+// ***************************
+// 1. Define state variables using custom strong types
+
+// initial setup
+enum ramp_state ramp_sts;
+position_t motor_position;
+position_t m; // target position
+position_t m2; // midpoint or point where acceleration changes
+direction_t d; // direction of traval -1 or +1
+
+// curent state along travel
+step_t i; // step number
+c_t c; // 24.8 fixed point delay count increment
+ccpr_t ccpr; // 24.8 fixed point delay count
+phase_ix_t phase_ix; // motor phase index
+
+// ***************************
+// 2. Surround all literal values with the "literal" keyword
+
+// Config data to make CCP1&2 generate quadrature sequence on PHASE pins
+// Action on CCP match: 8=set+irq; 9=clear+irq
+phase_t const ccpPhase[] = {
+ literal(0x909),
+ literal(0x908),
+ literal(0x808),
+ literal(0x809)
+}; // 00,01,11,10
+
+void current_on(){/* code as needed */} // motor drive current
+void current_off(){/* code as needed */} // reduce to holding value
+
+// ***************************
+// 3. Refactor code to make it easier to understand
+// and relate to the documentation
+
+bool busy(){
+ return ramp_idle != ramp_sts;
+}
+
+// set outputs to energize motor coils
+void update(ccpr_t ccpr, phase_ix_t phase_ix){
+ // energize correct windings
+ const phase_t phase = ccpPhase[phase_ix];
+ CCP1CON = phase & literal(0xff); // set CCP action on next match
+ CCP2CON = phase >> literal(8);
+ // timer value at next CCP match
+ CCPR1H = literal(0xff) & (ccpr >> literal(8));
+ CCPR1L = literal(0xff) & ccpr;
+}
+
+// compiler-specific ISR declaration
+// ***************************
+// 4. Rewrite interrupt handler in a way which mirrors the orginal
+// description of the algorithm and minimizes usage of state variable,
+// accumulated values, etc.
+void __interrupt isr_motor_step(void) { // CCP1 match -> step pulse + IRQ
+ // *** possible exception
+ // motor_position += d;
+ // use the following to avoid mixing exception policies which is an error
+ if(d < 0)
+ --motor_position;
+ else
+ ++motor_position;
+ // *** possible exception
+ ++i;
+ // calculate next difference in time
+ for(;;){
+ switch (ramp_sts) {
+ case ramp_up: // acceleration
+ if (i == m2) {
+ ramp_sts = ramp_down;
+ continue;
+ }
+ // equation 13
+ // *** possible negative overflow on update of c
+ c -= literal(2) * c / (literal(4) * i + literal(1));
+ if(c < C_MIN){
+ c = C_MIN;
+ ramp_sts = ramp_const;
+ // *** possible exception
+ m2 = m - i; // new inflection point
+ continue;
+ }
+ break;
+ case ramp_const: // constant speed
+ if(i > m2) {
+ ramp_sts = ramp_down;
+ continue;
+ }
+ break;
+ case ramp_down: // deceleration
+ if (i == m) {
+ ramp_sts = ramp_idle;
+ current_off(); // reduce motor current to holding value
+ CCP1IE = literal(0); // disable_interrupts(INT_CCP1);
+ return;
+ }
+ // equation 14
+ // *** possible positive overflow on update of c
+ // note: re-arrange expression to avoid negative result
+ // from difference of two unsigned values
+ {
+ // testing discovered that this can overflow. It's not easy to
+ // avoid so we'll use a temporary unsigned variable 32 bits wide
+ const temp_t x = c + literal(2) * c / (literal(4) * (m - i) - literal(1));
+ c = x > C0 ? C0 : x;
+ }
+ break;
+ default:
+ // should never arrive here!
+ assert(false);
+ } // switch (ramp_sts)
+ break;
+ }
+ assert(c <= C0 && c >= C_MIN);
+ // *** possible exception
+ ccpr = literal(0xffffff) & (ccpr + c);
+ phase_ix = (phase_ix + d) & literal(3);
+ update(ccpr, phase_ix);
+} // isr_motor_step()
+
+// set up to drive motor to pos_new (absolute step#)
+void motor_run(position_t new_position) {
+ if(new_position > motor_position){
+ d = literal(1);
+ // *** possible exception
+ m = new_position - motor_position;
+ }
+ else
+ if(motor_position > new_position){
+ d = literal(-1);
+ // *** possible exception
+ m = motor_position - new_position;
+ }
+ else{
+ d = literal(0);
+ m = literal(0);
+ ramp_sts = ramp_idle; // start ramp state-machine
+ return;
+ }
+
+ i = literal(0);
+ m2 = m / literal(2);
+
+ ramp_sts = ramp_up; // start ramp state-machine
+
+ T1CONbits.TMR1ON = literal(0); // stop timer1;
+
+ current_on(); // current in motor windings
+
+ c = C0;
+ ccpr = (TMR1H << literal(8) | TMR1L) + C0 + literal(1000);
+ phase_ix = d & literal(3);
+ update(ccpr, phase_ix);
+
+ CCP1IE = literal(1); // enable_interrupts(INT_CCP1);
+ T1CONbits.TMR1ON = literal(1); // restart timer1;
+} // motor_run()
+
+void initialize() {
+ di(); // disable_interrupts(GLOBAL);
+ motor_position = literal(0);
+ CCP1IE = literal(0); // disable_interrupts(INT_CCP1);
+ CCP2IE = literal(0); // disable_interrupts(INT_CCP2);
+ PORTC = literal(0); // output_c(0);
+ TRISC = literal(0); // set_tris_c(0);
+ T3CON = literal(0);
+ T1CON = literal(0x35);
+ INTCONbits.PEIE = literal(1);
+ INTCONbits.RBIF = literal(0);
+ ei(); // enable_interrupts(GLOBAL);
+} // initialize()
diff --git a/src/boost/libs/safe_numerics/example/motor_test1.c b/src/boost/libs/safe_numerics/example/motor_test1.c
new file mode 100644
index 000000000..afe54cb79
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/motor_test1.c
@@ -0,0 +1,44 @@
+/*
+ * david austin
+ * http://www.embedded.com/design/mcus-processors-and-socs/4006438/Generate-stepper-motor-speed-profiles-in-real-time
+ * DECEMBER 30, 2004
+ *
+ * Demo program for stepper motor control with linear ramps
+ * Hardware: PIC18F252, L6219
+ *
+ * Compile with on Microchip XC8 compiler with the command line:
+ * XC8 --chip=18F252 motor_test1.c
+ *
+ * Copyright (c) 2015 Robert Ramey
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See
+ * accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#include <xc.h>
+#include <stdint.h>
+#include <stdbool.h> /* For true/false definition */
+
+typedef int8_t int8;
+typedef int16_t int16;
+typedef int32_t int32;
+typedef uint8_t uint8;
+typedef uint16_t uint16;
+typedef uint32_t uint32;
+
+// 1st step=50ms; max speed=120rpm (based on 1MHz timer, 1.8deg steps)
+#define C0 (50000 << 8)
+#define C_MIN (2500 << 8)
+
+#include "motor1.c"
+
+void main() {
+ initialize();
+ while (1) { // repeat 5 revs forward & back
+ motor_run(1000);
+ while (run_flg);
+ motor_run(0);
+ while (run_flg);
+ }
+} // main()
diff --git a/src/boost/libs/safe_numerics/example/motor_test2.c b/src/boost/libs/safe_numerics/example/motor_test2.c
new file mode 100644
index 000000000..23f705760
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/motor_test2.c
@@ -0,0 +1,48 @@
+/*
+ * david austin
+ * http://www.embedded.com/design/mcus-processors-and-socs/4006438/Generate-stepper-motor-speed-profiles-in-real-time
+ * DECEMBER 30, 2004
+ *
+ * Demo program for stepper motor control with linear ramps
+ * Hardware: PIC18F252, L6219
+ *
+ * Compile with on Microchip XC8 compiler with the command line:
+ * XC8 --chip=18F252 motor_test2.c
+ *
+ * Copyright (c) 2015 Robert Ramey
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See
+ * accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#include <xc.h>
+#include <stdint.h>
+#include <stdbool.h> /* For true/false definition */
+
+// ***************************
+// alias integer types standard C integer types
+typedef int8_t int8;
+typedef int16_t int16;
+typedef int32_t int32;
+typedef uint8_t uint8;
+typedef uint16_t uint16;
+typedef uint32_t uint32;
+
+// 1st step=50ms; max speed=120rpm (based on 1MHz timer, 1.8deg steps)
+#define C0 (50000*8l)
+#define C_MIN (2500*8)
+
+#include "motor2.c"
+
+void main() {
+ initialize();
+ while (1) { // repeat 5 revs forward & back
+ motor_run(1000);
+ while (run_flg);
+ motor_run(0);
+ while (run_flg);
+ motor_run(50000);
+ while (run_flg);
+ }
+} // main()
diff --git a/src/boost/libs/safe_numerics/example/motor_test3.c b/src/boost/libs/safe_numerics/example/motor_test3.c
new file mode 100644
index 000000000..0ef5a0227
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/motor_test3.c
@@ -0,0 +1,58 @@
+/*
+ * david austin
+ * http://www.embedded.com/design/mcus-processors-and-socs/4006438/Generate-stepper-motor-speed-profiles-in-real-time
+ * DECEMBER 30, 2004
+ *
+ * Demo program for stepper motor control with linear ramps
+ * Hardware: PIC18F252, L6219
+ *
+ * Compile with on Microchip XC8 compiler with the command line:
+ * XC8 --chip=18F252 motor_test3.c
+ *
+ * Copyright (c) 2015 Robert Ramey
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See
+ * accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#include <xc.h>
+
+// 8 MHz internal clock
+#define _XTAL_FREQ 8000000
+
+#include <stdint.h>
+#include <stdbool.h> /* For true/false definition */
+
+// ***************************
+// nullify macro for literals
+#define literal(n) n
+
+// ***************************
+// map strong types to appropriate underlying types.
+typedef uint16_t position_t;
+typedef int16_t step_t;
+typedef uint32_t ccpr_t;
+typedef int32_t c_t;
+typedef uint16_t phase_t;
+typedef uint8_t phase_ix_t;
+typedef int8_t direction_t;
+
+// 1st step=10ms; max speed=300rpm (based on 1MHz timer, 1.8deg steps)
+#define C_MIN literal((1000 << 8))
+#define C0 literal((10000 << 8))
+
+#include "motor3.c"
+
+void main() {
+ initialize();
+ // move motor to position 200
+ motor_run(200);
+ while(busy()) __delay_ms(100);
+ // move motor to position 1000
+ motor_run(1000);
+ while(busy()) __delay_ms(100);
+ // move back to position 0
+ motor_run(200);
+ while(busy()) __delay_ms(100);
+} // main()
diff --git a/src/boost/libs/safe_numerics/example/picsfr.h b/src/boost/libs/safe_numerics/example/picsfr.h
new file mode 100644
index 000000000..a100731cc
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/picsfr.h
@@ -0,0 +1,29 @@
+//////////////////////////////////////////////////////////////////
+// picsfr.h
+// Copyright (c) 2015 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// Put these in a separate file so they can conditionally included.
+// This is necessary since their mere inclusion will cause syntax
+// errors on some compilers.
+
+#ifndef PICSFR_H
+#define PICSFR_H
+
+#byte TRISC = 0xf94
+#byte T3CON = 0xfb1
+#byte CCP2CON = 0xfba
+#byte CCPR2L = 0xfbb
+#byte CCPR2H = 0xfbc
+#byte CCP1CON = 0xfbd
+#byte CCPR1L = 0xfbe
+#byte CCPR1H = 0xfbf
+#byte T1CON = 0xfcd
+#byte TMR1L = 0xfce
+#byte TMR1H = 0xfcf
+#bit TMR1ON = T1CON.0
+
+#endif // PICSFR_H
diff --git a/src/boost/libs/safe_numerics/example/safe_format.hpp b/src/boost/libs/safe_numerics/example/safe_format.hpp
new file mode 100644
index 000000000..317c22018
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/safe_format.hpp
@@ -0,0 +1,52 @@
+#ifndef BOOST_SAFE_FORMAT_HPP
+#define BOOST_SAFE_FORMAT_HPP
+
+// Copyright (c) 2015 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <ostream>
+#include <typeinfo>
+
+#include <boost/core/demangle.hpp>
+#include <boost/safe_numerics/safe_common.hpp>
+
+namespace {
+
+// create an output manipulator which prints variable type and limits
+// as well as value
+template<typename T>
+struct safe_format_impl {
+ const T & m_t;
+ safe_format_impl(const T & t) :
+ m_t(t)
+ {}
+ template <class charT, class Traits>
+ friend std::basic_ostream<charT,Traits> &
+ operator<<(
+ std::basic_ostream<charT,Traits> & os,
+ const safe_format_impl<T> & f
+ ){
+ return os
+ << "<"
+ << boost::core::demangle(typeid(
+ typename boost::safe_numerics::base_type<T>::type
+ ).name()
+ )
+ << ">["
+ << std::numeric_limits<T>::min() << ","
+ << std::numeric_limits<T>::max() << "] = "
+ << f.m_t;
+ }
+};
+
+} // anonymous namespace
+
+template<typename T>
+auto safe_format(const T & t){
+ return safe_format_impl<T>(t);
+}
+
+#endif // BOOST_SAFE_FORMAT_HPP
diff --git a/src/boost/libs/safe_numerics/example/stepper-motor.pdf b/src/boost/libs/safe_numerics/example/stepper-motor.pdf
new file mode 100644
index 000000000..7088a779d
--- /dev/null
+++ b/src/boost/libs/safe_numerics/example/stepper-motor.pdf
Binary files differ
diff --git a/src/boost/libs/safe_numerics/index.html b/src/boost/libs/safe_numerics/index.html
new file mode 100644
index 000000000..a78bced52
--- /dev/null
+++ b/src/boost/libs/safe_numerics/index.html
@@ -0,0 +1,15 @@
+<html>
+<!--
+(C) Copyright 2017 Robert Ramey - http://www.rrsd.com .
+Use, modification and distribution is subject to the Boost Software
+License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+-->
+<head>
+<meta http-equiv="refresh" content="0; URL=doc/html/index.html">
+</head>
+<body>
+Automatic redirection failed, please go to
+<a href="doc/html/index.html">doc/html/index.html</a>.
+</body>
+</html>
diff --git a/src/boost/libs/safe_numerics/meta/libraries.json b/src/boost/libs/safe_numerics/meta/libraries.json
new file mode 100644
index 000000000..456f494fe
--- /dev/null
+++ b/src/boost/libs/safe_numerics/meta/libraries.json
@@ -0,0 +1,15 @@
+{
+ "key": "safe_numerics",
+ "name": "Safe Numerics",
+ "authors": [
+ "Robert Ramey"
+ ],
+ "description": "Guaranteed Correct Integer Arithmetic",
+ "category": [
+ "Math",
+ "Correctness"
+ ],
+ "maintainers": [
+ "Robert Ramey <ramey -at- rrsd.com>"
+ ]
+}
diff --git a/src/boost/libs/safe_numerics/test/CMakeLists.txt b/src/boost/libs/safe_numerics/test/CMakeLists.txt
new file mode 100644
index 000000000..e1aac4682
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/CMakeLists.txt
@@ -0,0 +1,148 @@
+# CMake build control file for safe numerics Library tests
+
+###########################
+# test targets
+
+message( STATUS "Runtimes are stored in ${CMAKE_CURRENT_BINARY_DIR}" )
+
+# compile and run tests
+set( run_test_list
+ test_add_automatic
+ test_add_native
+ test_and_automatic
+ test_and_native
+ test_assignment
+ test_auto
+ test_cast
+ test_checked_add
+ test_checked_and
+ test_checked_cast
+ test_checked_divide
+ test_checked_equal_to
+ test_checked_left_shift
+ test_checked_less_than
+ test_checked_modulus
+ test_checked_multiply
+ test_checked_or
+ test_checked_right_shift
+ test_checked_subtract
+ test_checked_xor
+ test_construction
+ test_cpp
+ test_divide_automatic
+ test_divide_native
+ test_equal_automatic
+ test_equal_native
+ test_float
+ test_interval
+ test_left_shift_automatic
+ test_left_shift_native
+ test_less_than_automatic
+ test_less_than_native
+ test_modulus_automatic
+ test_modulus_native
+ test_multiply_automatic
+ test_multiply_native
+ test_or_automatic
+ test_or_native
+ # test_performance
+ test_range
+ test_rational
+ test_right_shift_automatic
+ test_right_shift_native
+ test_safe_compare
+ test_subtract_automatic
+ test_subtract_native
+ test_xor_automatic
+ test_xor_native
+ test_z
+)
+
+foreach(test_name ${run_test_list})
+ test_run_pass(${test_name})
+ set_target_properties(${test_name} PROPERTIES FOLDER "safe numeric runtime tests")
+endforeach(test_name)
+
+# compile fail tests
+set(compile_fail_test_list
+ test_trap
+ test_constexpr
+)
+
+foreach(test_name ${compile_fail_test_list})
+ test_compile_fail(${test_name})
+ set_target_properties(${test_name} PROPERTIES FOLDER "safe numeric compile fail tests")
+endforeach(test_name)
+
+## safe integer constexpr tests
+set(safe_constexpr_test_list
+ test_add_automatic_constexpr
+ test_add_native_constexpr
+ test_cast_constexpr
+ test_divide_automatic_constexpr
+ test_divide_native_constexpr
+ test_equal_automatic_constexpr
+ test_equal_native_constexpr
+ test_left_shift_automatic_constexpr
+ test_left_shift_native_constexpr
+ test_less_than_automatic_constexpr
+ test_less_than_native_constexpr
+ test_modulus_automatic_constexpr
+ test_modulus_native_constexpr
+ test_multiply_automatic_constexpr
+ test_multiply_native_constexpr
+ test_or_automatic_constexpr
+ test_or_native_constexpr
+ test_right_shift_automatic_constexpr
+ test_right_shift_native_constexpr
+ test_xor_automatic_constexpr
+ test_xor_native_constexpr
+ test_subtract_native_constexpr
+ test_subtract_automatic_constexpr
+)
+
+foreach(test_name ${safe_constexpr_test_list})
+ test_compile_pass(${test_name})
+ set_target_properties(${test_name} PROPERTIES FOLDER "safe constexpr tests - compile only")
+endforeach(test_name)
+
+# checked results constexpr
+
+set(checked_result_test_list
+ test_checked_add_constexpr
+ test_checked_and_constexpr
+ test_checked_cast_constexpr
+ test_checked_divide_constexpr
+ test_checked_equal_to_constexpr
+ test_checked_left_shift_constexpr
+ test_checked_less_than_constexpr
+ test_checked_modulus_constexpr
+ test_checked_multiply_constexpr
+ test_checked_or_constexpr
+ test_checked_right_shift_constexpr
+ test_checked_subtract_constexpr
+ test_checked_xor_constexpr
+)
+
+foreach(test_name ${checked_result_test_list})
+ test_compile_pass(${test_name})
+ set_target_properties(${test_name} PROPERTIES FOLDER "checked result tests - compile only")
+endforeach(test_name)
+
+# end test targets
+####################
+
+###########################
+# add headers to IDE
+
+if(0)
+file(GLOB include_files
+ RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
+ "${CMAKE_CURRENT_SOURCE_DIR}/*.hpp"
+)
+add_custom_target(include SOURCES ${include_files})
+set_target_properties(include PROPERTIES FOLDER "tests")
+endif(0)
+
+# end headers in IDE
+####################
diff --git a/src/boost/libs/safe_numerics/test/Jamfile.v2 b/src/boost/libs/safe_numerics/test/Jamfile.v2
new file mode 100644
index 000000000..666ceef6c
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/Jamfile.v2
@@ -0,0 +1,122 @@
+# Boost.SafeNumerics Library test Jamfile
+#
+# Copyright (c) 2017 Robert Ramey
+#
+# Distributed under the Boost Software License, Version 1.0.
+# See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt
+
+import testing ;
+import ../../config/checks/config : requires ;
+project
+ : requirements
+ [ requires cxx14_constexpr ]
+ # toolset optimizations
+ <c++-template-depth>1024
+ <warnings>extra
+ ;
+
+# compile and run tests
+
+run test_add_automatic.cpp ;
+run test_add_native.cpp ;
+run test_and_automatic.cpp ;
+run test_and_native.cpp ;
+run test_assignment.cpp ;
+run test_auto.cpp ;
+run test_cast.cpp ;
+
+run test_checked_add.cpp ;
+run test_checked_and.cpp ;
+run test_checked_cast.cpp ;
+run test_checked_divide.cpp ;
+run test_checked_equal_to.cpp ;
+run test_checked_left_shift.cpp ;
+run test_checked_less_than.cpp ;
+run test_checked_modulus.cpp ;
+run test_checked_multiply.cpp ;
+run test_checked_or.cpp ;
+run test_checked_right_shift.cpp ;
+run test_checked_subtract.cpp ;
+run test_checked_xor.cpp ;
+
+run test_construction.cpp ;
+run test_cpp.cpp ;
+run test_divide_automatic.cpp ;
+run test_divide_native.cpp ;
+run test_equal_automatic.cpp ;
+run test_equal_native.cpp ;
+run test_float.cpp ;
+run test_interval.cpp ;
+run test_left_shift_automatic.cpp ;
+run test_left_shift_native.cpp ;
+run test_less_than_automatic.cpp ;
+run test_less_than_native.cpp ;
+run test_modulus_automatic.cpp ;
+run test_modulus_native.cpp ;
+run test_multiply_automatic.cpp ;
+run test_multiply_native.cpp ;
+run test_or_automatic.cpp ;
+run test_or_native.cpp ;
+run test_performance.cpp # sources
+ : # args
+ : # input
+ : <variant>debug:<build>no # requirements
+ ;
+run test_range.cpp ;
+run test_rational.cpp ;
+run test_right_shift_automatic.cpp ;
+run test_right_shift_native.cpp ;
+run test_safe_compare.cpp ;
+run test_subtract_automatic.cpp ;
+run test_subtract_native.cpp ;
+run test_xor_automatic.cpp ;
+run test_xor_native.cpp ;
+run test_z.cpp ;
+
+# compile fail tests
+
+compile-fail test_trap.cpp ;
+
+# safe integer constexpr tests
+
+compile test_cast_constexpr.cpp ;
+compile test_add_automatic_constexpr.cpp ;
+compile test_add_native_constexpr.cpp ;
+compile test_divide_automatic_constexpr.cpp ;
+compile test_divide_native_constexpr.cpp ;
+compile test_equal_automatic_constexpr.cpp ;
+compile test_equal_native_constexpr.cpp ;
+compile test_left_shift_automatic_constexpr.cpp ;
+compile test_left_shift_native_constexpr.cpp ;
+compile test_less_than_automatic_constexpr.cpp ;
+compile test_less_than_native_constexpr.cpp ;
+compile test_modulus_automatic_constexpr.cpp ;
+compile test_modulus_native_constexpr.cpp ;
+compile test_multiply_automatic_constexpr.cpp ;
+compile test_multiply_native_constexpr.cpp ;
+compile test_or_automatic_constexpr.cpp ;
+compile test_or_native_constexpr.cpp ;
+compile test_right_shift_automatic_constexpr.cpp ;
+compile test_right_shift_native_constexpr.cpp ;
+compile test_xor_automatic_constexpr.cpp ;
+compile test_xor_native_constexpr.cpp ;
+compile test_subtract_native_constexpr.cpp ;
+compile test_subtract_automatic_constexpr.cpp ;
+
+# checked results constexpr
+
+compile test_checked_add_constexpr.cpp ;
+compile test_checked_and_constexpr.cpp ;
+compile test_checked_cast_constexpr.cpp ;
+compile test_checked_divide_constexpr.cpp ;
+compile test_checked_equal_to_constexpr.cpp ;
+compile test_checked_left_shift_constexpr.cpp ;
+compile test_checked_less_than_constexpr.cpp ;
+compile test_checked_modulus_constexpr.cpp ;
+compile test_checked_multiply_constexpr.cpp ;
+compile test_checked_or_constexpr.cpp ;
+compile test_checked_right_shift_constexpr.cpp ;
+compile test_checked_subtract_constexpr.cpp ;
+compile test_checked_xor_constexpr.cpp ;
+
diff --git a/src/boost/libs/safe_numerics/test/check_symmetry.hpp b/src/boost/libs/safe_numerics/test/check_symmetry.hpp
new file mode 100644
index 000000000..09d1643ca
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/check_symmetry.hpp
@@ -0,0 +1,10 @@
+// given an array of values of a particular type
+template<typename T, unsigned int N>
+constexpr bool check_symmetry(const T (&value)[N]) {
+ using namespace boost::safe_numerics;
+ // for each pair of values p1, p2 (100)
+ for(unsigned int i = 0; i < N; i++)
+ for(unsigned int j = 0; j < N; j++)
+ assert(value[i][j] == value[j][i]);
+ return true;
+}
diff --git a/src/boost/libs/safe_numerics/test/test0.cpp b/src/boost/libs/safe_numerics/test/test0.cpp
new file mode 100644
index 000000000..e4ef159ea
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test0.cpp
@@ -0,0 +1,146 @@
+// Copyright (c) 2012 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+#include <boost/safe_numerics/safe_integer_range.hpp>
+#include <boost/safe_numerics/safe_integer.hpp>
+
+bool test1(){
+ std::cout << "test1" << std::endl;
+ boost::safe_numerics::safe_signed_range<-64, 63> x, y, z;
+ x = 1;
+ y = 2;
+ z = 3;
+ z = x + y;
+ z = x - y;
+
+ try{
+ short int yi, zi;
+ yi = y;
+ zi = x + yi;
+ }
+ catch(const std::exception & e){
+ // none of the above should trap. Mark failure if they do
+ std::cout << e.what() << std::endl;
+ return false;
+ }
+ return true;
+}
+
+bool test2(){
+ std::cout << "test2" << std::endl;
+ boost::safe_numerics::safe_unsigned_range<0, 64> x, y, z;
+ x = 1;
+ y = 2;
+ z = 3;
+
+ bool success = false;
+ try{
+ z = x - y; // should trap here
+ }
+ catch(const std::exception & e){
+ success = true;
+ }
+ if(success == false)
+ return false;
+
+ try{
+ int yi = y;
+ z = x + yi; // should trap here
+ }
+ catch(const std::exception & e){
+ // none of the above should trap. Mark failure if they do
+ std::cout << e.what() << std::endl;
+ return false;
+ }
+ return true;
+}
+
+bool test3(){
+ using namespace boost::safe_numerics;
+ std::cout << "test3" << std::endl;
+ safe<int> x, y, z;
+ x = 1;
+ y = 2;
+ z = 3;
+ try{
+ z = x + y;
+ z = x - y;
+ int yi, zi;
+ zi = x + yi;
+ z = x + yi;
+ }
+ catch(const std::exception & e){
+ // none of the above should trap. Mark failure if they do
+ std::cout << e.what() << std::endl;
+ return false;
+ }
+ return true;
+}
+
+bool test4(){
+ std::cout << "test4" << std::endl;
+ boost::safe_numerics::safe<unsigned int> x, y, z;
+ x = 1;
+ y = 2;
+ z = 3;
+ z = x + y;
+ bool success = false;
+ try{
+ z = x - y; // should trap here
+ }
+ catch(const std::exception & e){
+ success = true;
+ }
+ if(success == false)
+ return false;
+ unsigned int yi, zi;
+ zi = x;
+ zi = x + yi;
+ z = x + yi;
+ zi = x + y;
+ return true;
+}
+
+#include <cstdint>
+
+bool test5(){
+ std::cout << "test5" << std::endl;
+ boost::safe_numerics::safe<boost::uint64_t> x, y, z;
+ x = 1;
+ y = 2;
+ z = 3;
+ z = x + y;
+ bool success = false;
+ try{
+ z = x - y; // should trap here
+ }
+ catch(const std::exception & e){
+ success = true;
+ }
+ if(success == false)
+ return false;
+ boost::uint64_t yi, zi;
+ zi = x;
+ zi = x + yi;
+ z = x + yi;
+ zi = x + y;
+ return true;
+}
+
+int main(int, char *[]){
+ bool rval = (
+ test1() &&
+ test2() &&
+ test3() &&
+ test4() &&
+ test5()
+ );
+ std::cout << (rval ? "success!" : "failure") << std::endl;
+ return rval ? EXIT_SUCCESS : EXIT_FAILURE;
+}
+
diff --git a/src/boost/libs/safe_numerics/test/test_add.hpp b/src/boost/libs/safe_numerics/test/test_add.hpp
new file mode 100644
index 000000000..768373bca
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_add.hpp
@@ -0,0 +1,147 @@
+#ifndef BOOST_TEST_ADD_HPP
+#define BOOST_TEST_ADD_HPP
+
+// Copyright (c) 2015 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/range_value.hpp>
+
+template<class T1, class T2>
+bool test_add(
+ T1 v1,
+ T2 v2,
+ const char *av1,
+ const char *av2,
+ char expected_result
+){
+ std::cout << "testing"<< std::endl;
+ {
+ safe_t<T1> t1 = v1;
+ std::cout << "safe<" << av1 << "> + " << av2 << " -> ";
+ static_assert(
+ boost::safe_numerics::is_safe<safe_t<T1> >::value,
+ "safe_t not safe!"
+ );
+ try{
+ // use auto to avoid checking assignment.
+ auto result = t1 + v2;
+ static_assert(
+ boost::safe_numerics::is_safe<decltype(result)>::value,
+ "Expression failed to return safe type"
+ );
+ std::cout << make_result_display(result);
+ if(expected_result == 'x'){
+ std::cout
+ << " ! = "<< av1 << " + " << av2
+ << " failed to detect error in addition "
+ << std::endl;
+ t1 + v2;
+ return false;
+ }
+ std::cout << std::endl;
+ }
+ catch(const std::exception &){
+ if(expected_result == '.'){
+ std::cout
+ << " == "<< av1 << " + " << av2
+ << " erroneously detected error in addition "
+ << std::endl;
+ try{
+ t1 + v2;
+ }
+ catch(const std::exception &){}
+ return false;
+ }
+ std::cout << std::endl;
+ }
+ }
+ {
+ safe_t<T2> t2 = v2;
+ using result_type = decltype(v1 + t2);
+ std::cout << av1 << " + " << "safe<" << av2 << "> -> ";
+ static_assert(
+ boost::safe_numerics::is_safe<safe_t<T2> >::value,
+ "safe_t not safe!"
+ );
+ static_assert(
+ boost::safe_numerics::is_safe<result_type>::value,
+ "Expression failed to return safe type"
+ );
+ try{
+ // use auto to avoid checking assignment.
+ auto result = v1 + t2;
+ std::cout << make_result_display(result);
+ if(expected_result == 'x'){
+ std::cout
+ << " ! = "<< av1 << " + " << av2
+ << " failed to detect error in addition "
+ << std::endl;
+ v1 + t2;
+ return false;
+ }
+ std::cout << std::endl;
+ }
+ catch(const std::exception &){
+ if(expected_result == '.'){
+ std::cout
+ << " == "<< av1 << " + " << av2
+ << " erroneously detected error in addition "
+ << std::endl;
+ try{
+ v1 + t2;
+ }
+ catch(const std::exception &){}
+ return false;
+ }
+ std::cout << std::endl;
+ }
+ }
+ {
+ safe_t<T1> t1 = v1;
+ safe_t<T2> t2 = v2;
+ using result_type = decltype(t1 + t2);
+ std::cout << "safe<" << av1 << "> + " << "safe<" << av2 << "> -> ";
+ static_assert(
+ boost::safe_numerics::is_safe<result_type>::value,
+ "Expression failed to return safe type"
+ );
+
+ try{
+ // use auto to avoid checking assignment.
+ auto result = t1 + t2;
+ std::cout << make_result_display(result);
+ if(expected_result == 'x'){
+ std::cout
+ << " ! = "<< av1 << " + " << av2
+ << " failed to detect error in addition "
+ << std::endl;
+ t1 + t2;
+ return false;
+ }
+ std::cout << std::endl;
+ }
+ catch(const std::exception &){
+ if(expected_result == '.'){
+ std::cout
+ << " == "<< av1 << " + " << av2
+ << " erroneously detected error in addition "
+ << std::endl;
+ try{
+ t1 + t2;
+ }
+ catch(const std::exception &){}
+ return false;
+ }
+ std::cout << std::endl;
+ }
+ }
+ return true; // correct result
+}
+
+#endif // BOOST_TEST_DIVIDE
diff --git a/src/boost/libs/safe_numerics/test/test_add_automatic.cpp b/src/boost/libs/safe_numerics/test/test_add_automatic.cpp
new file mode 100644
index 000000000..939f54d55
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_add_automatic.cpp
@@ -0,0 +1,71 @@
+// Copyright (c) 2012 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/automatic.hpp>
+#include "test_add_automatic_results.hpp"
+
+template <class T>
+using safe_t = boost::safe_numerics::safe<
+ T,
+ boost::safe_numerics::automatic
+>;
+
+#include "test_add.hpp"
+
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/algorithm.hpp>
+#include <boost/core/demangle.hpp>
+
+using namespace boost::mp11;
+
+template<typename L>
+struct test {
+ static_assert(mp_is_list<L>(), "must be a list of integral constants");
+ bool m_error;
+ test(bool b = true) : m_error(b) {}
+ operator bool(){
+ return m_error;
+ }
+ template<typename T>
+ void operator()(const T &){
+ static_assert(mp_is_list<T>(), "must be a list of two integral constants");
+ constexpr size_t i1 = mp_first<T>(); // index of first argument
+ constexpr size_t i2 = mp_second<T>();// index of second argument
+ std::cout << i1 << ',' << i2 << ',';
+ using T1 = typename mp_at_c<L, i1>::value_type;
+ using T2 = typename mp_at_c<L, i2>::value_type;
+ m_error &= test_add(
+ mp_at_c<L, i1>()(), // value of first argument
+ mp_at_c<L, i2>()(), // value of second argument
+ boost::core::demangle(typeid(T1).name()).c_str(),
+ boost::core::demangle(typeid(T2).name()).c_str(),
+ test_addition_automatic_result[i1][i2]
+ );
+ }
+};
+
+#include "check_symmetry.hpp"
+
+int main(){
+ static_assert(
+ check_symmetry(test_addition_automatic_result),
+ "sanity check on test matrix - should be symmetrical"
+ );
+
+ //TEST_EACH_VALUE_PAIR
+ test<test_values> rval(true);
+
+ using value_indices = mp_iota_c<mp_size<test_values>::value>;
+ mp_for_each<
+ mp_product<mp_list, value_indices, value_indices>
+ >(rval);
+
+ std::cout << (rval ? "success!" : "failure") << std::endl;
+ return ! rval ;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_add_automatic_constexpr.cpp b/src/boost/libs/safe_numerics/test/test_add_automatic_constexpr.cpp
new file mode 100644
index 000000000..13326bad6
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_add_automatic_constexpr.cpp
@@ -0,0 +1,58 @@
+// Copyright (c) 2019 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/automatic.hpp>
+#include "test_add_automatic_results.hpp"
+
+template <class T>
+using safe_t = boost::safe_numerics::safe<
+ T,
+ boost::safe_numerics::automatic
+>;
+
+#include "test_add_constexpr.hpp"
+
+using namespace boost::mp11;
+
+template<typename First, typename Second>
+struct test_pair {
+ static const std::size_t i = First();
+ static const std::size_t j = Second();
+ constexpr static const bool value = test_add_constexpr(
+ mp_at_c<test_values, i>()(),
+ mp_at_c<test_values, j>()(),
+ test_addition_automatic_result[i][j]
+ );
+};
+
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/algorithm.hpp>
+#include "check_symmetry.hpp"
+
+int main(){
+ using namespace boost::mp11;
+
+ static_assert(
+ check_symmetry(test_addition_automatic_result),
+ "sanity check on test matrix - should be symmetrical"
+ );
+
+ using value_indices = mp_iota_c<mp_size<test_values>::value>;
+
+ static_assert(
+ mp_all_of<
+ mp_product<
+ test_pair,
+ value_indices,
+ value_indices
+ >,
+ mp_to_bool
+ >(),
+ "all values for all integer types correctly added"
+ );
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_add_automatic_results.hpp b/src/boost/libs/safe_numerics/test/test_add_automatic_results.hpp
new file mode 100644
index 000000000..73af1d3fa
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_add_automatic_results.hpp
@@ -0,0 +1,59 @@
+#ifndef BOOST_SAFE_NUMERICS_TEST_ADD_AUTOMATIC_RESULTS_HPP
+#define BOOST_SAFE_NUMERICS_TEST_ADD_AUTOMATIC_RESULTS_HPP
+
+// Copyright (c) 2019 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include "test_values.hpp"
+
+constexpr const char *test_addition_automatic_result[
+ boost::mp11::mp_size<test_values>::value
+] = {
+// 0 0 0 0
+// 012345670123456701234567012345670
+// 012345678901234567890123456789012
+/* 0*/ ".............x...............xxx.",
+/* 1*/ ".............x...............xxx.",
+/* 2*/ "..............x...............xx.",
+/* 3*/ "..............x...............xx.",
+/* 4*/ ".............x...............xxx.",
+/* 5*/ ".............x...............xxx.",
+/* 6*/ "..............x...............xx.",
+/* 7*/ "..............x...............xx.",
+
+/* 8*/ ".............x...............xxx.",
+/* 9*/ ".............x...............xxx.",
+/*10*/ "..............x...............xx.",
+/*11*/ "..............x...............xx.",
+/*12*/ ".............x...............xxx.",
+/*13*/ "xx..xx..xx..xx..xxxxxxxxxxxxxxxx.",
+/*14*/ "..xx..xx..xx..xx..............xx.",
+/*15*/ "..............x...............xx.",
+
+// 0 0 0 0
+// 012345670123456701234567012345670
+// 012345678901234567890123456789012
+/*16*/ ".............x.................x.",
+/*17*/ ".............x.................x.",
+/*18*/ ".............x.................x.",
+/*19*/ ".............x.................x.",
+/*20*/ ".............x.................x.",
+/*21*/ ".............x.................x.",
+/*22*/ ".............x.................x.",
+/*23*/ ".............x.................x.",
+
+/*24*/ ".............x.................x.",
+/*25*/ ".............x.................x.",
+/*26*/ ".............x.................x.",
+/*27*/ ".............x.................x.",
+/*28*/ ".............x.................x.",
+/*29*/ "xx..xx..xx..xx.................x.",
+/*30*/ "xxxxxxxxxxxxxxxx..............xxx",
+/*31*/ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+/*32*/ "..............................xx."
+};
+
+#endif
diff --git a/src/boost/libs/safe_numerics/test/test_add_constexpr.hpp b/src/boost/libs/safe_numerics/test/test_add_constexpr.hpp
new file mode 100644
index 000000000..3c67e2b02
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_add_constexpr.hpp
@@ -0,0 +1,30 @@
+#ifndef BOOST_TEST_ADD_CONSTEXPR_HPP
+#define BOOST_TEST_ADD_CONSTEXPR_HPP
+
+// Copyright (c) 2015 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/safe_numerics/safe_integer.hpp>
+
+template<class T1, class T2>
+constexpr bool test_add_constexpr(
+ T1 v1,
+ T2 v2,
+ char expected_result
+){
+ using namespace boost::safe_numerics;
+ // if we don't expect the operation to pass, we can't
+ // check the constexpr version of the calculation so
+ // just return success.
+ if(expected_result == 'x')
+ return true;
+ safe_t<T1>(v1) + v2;
+ v1 + safe_t<T2>(v2);
+ safe_t<T1>(v1) + safe_t<T2>(v2);
+ return true; // correct result
+}
+
+#endif // BOOST_TEST_ADD_CONSTEXPR_HPP
diff --git a/src/boost/libs/safe_numerics/test/test_add_native.cpp b/src/boost/libs/safe_numerics/test/test_add_native.cpp
new file mode 100644
index 000000000..31ce206e1
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_add_native.cpp
@@ -0,0 +1,69 @@
+// Copyright (c) 2012 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/native.hpp>
+#include "test_add_native_results.hpp"
+
+template <class T>
+using safe_t = boost::safe_numerics::safe<
+ T,
+ boost::safe_numerics::native
+>;
+#include "test_add.hpp"
+
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/algorithm.hpp>
+#include <boost/core/demangle.hpp>
+
+using namespace boost::mp11;
+
+template<typename L>
+struct test {
+ static_assert(mp_is_list<L>(), "must be a list of integral constants");
+ bool m_error;
+ test(bool b = true) : m_error(b) {}
+ operator bool(){
+ return m_error;
+ }
+ template<typename T>
+ void operator()(const T &){
+ static_assert(mp_is_list<T>(), "must be a list of two integral constants");
+ constexpr size_t i1 = mp_first<T>(); // index of first argument
+ constexpr size_t i2 = mp_second<T>();// index of second argument
+ std::cout << i1 << ',' << i2 << ',';
+ using T1 = typename mp_at_c<L, i1>::value_type;
+ using T2 = typename mp_at_c<L, i2>::value_type;
+ m_error &= test_add(
+ mp_at_c<L, i1>()(), // value of first argument
+ mp_at_c<L, i2>()(), // value of second argument
+ boost::core::demangle(typeid(T1).name()).c_str(),
+ boost::core::demangle(typeid(T2).name()).c_str(),
+ test_addition_native_result[i1][i2]
+ );
+ }
+};
+
+#include "check_symmetry.hpp"
+
+int main(){
+ static_assert(
+ check_symmetry(test_addition_native_result),
+ "sanity check on test matrix - should be symmetrical"
+ );
+
+ test<test_values> rval(true);
+
+ using value_indices = mp_iota_c<mp_size<test_values>::value>;
+ mp_for_each<
+ mp_product<mp_list, value_indices, value_indices>
+ >(rval);
+
+ std::cout << (rval ? "success!" : "failure") << std::endl;
+ return ! rval ;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_add_native_constexpr.cpp b/src/boost/libs/safe_numerics/test/test_add_native_constexpr.cpp
new file mode 100644
index 000000000..32a149893
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_add_native_constexpr.cpp
@@ -0,0 +1,59 @@
+// Copyright (c) 2019 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/native.hpp>
+
+#include "test_add_native_results.hpp"
+
+template <class T>
+using safe_t = boost::safe_numerics::safe<
+ T,
+ boost::safe_numerics::native
+>;
+
+#include "test_add_constexpr.hpp"
+
+using namespace boost::mp11;
+
+template<typename First, typename Second>
+struct test_pair {
+ static const std::size_t i = First();
+ static const std::size_t j = Second();
+ constexpr static const bool value = test_add_constexpr(
+ mp_at_c<test_values, i>()(),
+ mp_at_c<test_values, j>()(),
+ test_addition_native_result[i][j]
+ );
+};
+
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/algorithm.hpp>
+#include "check_symmetry.hpp"
+
+int main(){
+ using namespace boost::mp11;
+
+ static_assert(
+ check_symmetry(test_addition_native_result),
+ "sanity check on test matrix - should be symmetrical"
+ );
+
+ using value_indices = mp_iota_c<mp_size<test_values>::value>;
+
+ static_assert(
+ mp_all_of<
+ mp_product<
+ test_pair,
+ value_indices,
+ value_indices
+ >,
+ mp_to_bool
+ >(),
+ "all values for all integer types correctly added"
+ );
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_add_native_results.hpp b/src/boost/libs/safe_numerics/test/test_add_native_results.hpp
new file mode 100644
index 000000000..16364cfe2
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_add_native_results.hpp
@@ -0,0 +1,60 @@
+#ifndef BOOST_SAFE_NUMERICS_TEST_ADD_NATIVE_RESULTS_HPP
+#define BOOST_SAFE_NUMERICS_TEST_ADD_NATIVE_RESULTS_HPP
+
+// Copyright (c) 2019 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include "test_values.hpp"
+
+constexpr const char *test_addition_native_result[
+ boost::mp11::mp_size<test_values>::value
+] = {
+// 0 0 0 0
+// 012345670123456701234567012345670
+// 012345678901234567890123456789012
+/* 0*/ ".........x...x.............x...x.",
+/* 1*/ ".........x...x.............x...x.",
+/* 2*/ "..........x...x.........xxxxxxxx.",
+/* 3*/ "..........x...x.........xxxxxxxx.",
+/* 4*/ ".........x...x.............x...x.",
+/* 5*/ ".........x...x.............x...x.",
+/* 6*/ "..........x...x.........xxxxxxxx.",
+/* 7*/ "..........x...x.........xxxxxxxx.",
+
+/* 8*/ ".........x...x.............x...x.",
+/* 9*/ "xx..xx..xx...x..xxxxxxxx...x...x.",
+/*10*/ "..xx..xx..xx..x.........xxxxxxxx.",
+/*11*/ "..........x...x.........xxxxxxxx.",
+/*12*/ ".............x.................x.",
+/*13*/ "xx..xx..xx..xx..xxxxxxxxxxxx...x.",
+/*14*/ "..xx..xx..xx..xx............xxxx.",
+/*15*/ "..............x.............xxxx.",
+
+// 0 0 0 0
+// 012345670123456701234567012345670
+// 012345678901234567890123456789012
+/*16*/ ".........x...x.............x...x.",
+/*17*/ ".........x...x.............x...x.",
+/*18*/ ".........x...x.............x...x.",
+/*19*/ ".........x...x.............x...x.",
+/*20*/ ".........x...x.............x...x.",
+/*21*/ ".........x...x.............x...x.",
+/*22*/ ".........x...x.............x...x.",
+/*23*/ ".........x...x.............x...x.",
+
+/*24*/ "..xx..xx..xx.x.............x...x.",
+/*25*/ "..xx..xx..xx.x.............x...x.",
+/*26*/ "..xx..xx..xx.x............xx...x.",
+/*27*/ "xxxxxxxxxxxx.x..xxxxxxxxxxxx...x.",
+/*28*/ "..xx..xx..xx..xx...............x.",
+/*29*/ "..xx..xx..xx..xx...............x.",
+/*30*/ "..xx..xx..xx..xx..............xx.",
+/*31*/ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.",
+/*32*/ "................................."
+};
+
+#endif // BOOST_SAFE_NUMERICS_TEST_ADD_NATIVE_RESULTS_HPP
+
diff --git a/src/boost/libs/safe_numerics/test/test_and.hpp b/src/boost/libs/safe_numerics/test/test_and.hpp
new file mode 100644
index 000000000..5a53b0ac2
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_and.hpp
@@ -0,0 +1,146 @@
+#ifndef BOOST_TEST_AND_HPP
+#define BOOST_TEST_AND_HPP
+
+// Copyright (c) 2015 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/range_value.hpp>
+
+template<class T1, class T2>
+bool test_and(
+ T1 v1,
+ T2 v2,
+ const char *av1,
+ const char *av2,
+ char expected_result
+){
+ std::cout << "testing"<< std::endl;
+ {
+ safe_t<T1> t1 = v1;
+ using result_type = decltype(t1 & v2);
+ std::cout << "safe<" << av1 << "> & " << av2 << " -> ";
+ static_assert(
+ boost::safe_numerics::is_safe<safe_t<T1> >::value,
+ "safe_t not safe!"
+ );
+ static_assert(
+ boost::safe_numerics::is_safe<result_type>::value,
+ "Expression failed to return safe type"
+ );
+ try{
+ // use auto to avoid checking assignment.
+ auto result = t1 & v2;
+ std::cout << make_result_display(result);
+ if(expected_result == 'x'){
+ std::cout
+ << " ! = "<< av1 << " & " << av2
+ << " failed to detect error in and operation "
+ << std::endl;
+ t1 & v2;
+ return false;
+ }
+ std::cout << std::endl;
+ }
+ catch(const std::exception &){
+ if(expected_result == '.'){
+ std::cout
+ << " == "<< av1 << " & " << av2
+ << " erroneously detected error in and operation "
+ << std::endl;
+ try{
+ t1 & v2;
+ }
+ catch(const std::exception &){}
+ return false;
+ }
+ }
+ }
+ {
+ safe_t<T2> t2 = v2;
+ using result_type = decltype(v1 & t2);
+ std::cout << av1 << " & " << "safe<" << av2 << "> -> ";
+ static_assert(
+ boost::safe_numerics::is_safe<safe_t<T2> >::value,
+ "safe_t not safe!"
+ );
+ static_assert(
+ boost::safe_numerics::is_safe<result_type>::value,
+ "Expression failed to return safe type"
+ );
+
+ try{
+ // use auto to avoid checking assignment.
+ auto result = v1 & t2;
+ std::cout << make_result_display(result);
+ if(expected_result == 'x'){
+ std::cout
+ << " ! = "<< av1 << " & " << av2
+ << " failed to detect error in and operation "
+ << std::endl;
+ v1 & t2;
+ return false;
+ }
+ std::cout << std::endl;
+ }
+ catch(const std::exception &){
+ if(expected_result == '.'){
+ std::cout
+ << " == "<< av1 << " & " << av2
+ << " erroneously detected error in and operation "
+ << std::endl;
+ try{
+ v1 & t2;
+ }
+ catch(const std::exception &){}
+ return false;
+ }
+ }
+ }
+ {
+ safe_t<T1> t1 = v1;
+ safe_t<T2> t2 = v2;
+ using result_type = decltype(t1 & t2);
+ std::cout << "safe<" << av1 << "> & " << "safe<" << av2 << "> -> ";
+ static_assert(
+ boost::safe_numerics::is_safe<result_type>::value,
+ "Expression failed to return safe type"
+ );
+
+ try{
+ // use auto to avoid checking assignment.
+ auto result = t1 & t2;
+ std::cout << make_result_display(result);
+ if(expected_result == 'x'){
+ std::cout
+ << " != "<< av1 << " & " << av2
+ << " failed to detect error in and operation"
+ << std::endl;
+ t1 & t2;
+ return false;
+ }
+ std::cout << std::endl;
+ }
+ catch(const std::exception &){
+ if(expected_result == '.'){
+ std::cout
+ << " == "<< av1 << " & " << av2
+ << " erroneously detected error in and operation"
+ << std::endl;
+ try{
+ t1 & t2;
+ }
+ catch(const std::exception &){}
+ return false;
+ }
+ }
+ }
+ return true; // correct result
+}
+
+#endif // BOOST_TEST_AND_HPP
diff --git a/src/boost/libs/safe_numerics/test/test_and_automatic.cpp b/src/boost/libs/safe_numerics/test/test_and_automatic.cpp
new file mode 100644
index 000000000..d181655b3
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_and_automatic.cpp
@@ -0,0 +1,62 @@
+// Copyright (c) 2012 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/automatic.hpp>
+
+template <class T>
+using safe_t = boost::safe_numerics::safe<
+ T,
+ boost::safe_numerics::automatic
+>;
+#include "test_and.hpp"
+
+#include "test_values.hpp"
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/algorithm.hpp>
+#include <boost/core/demangle.hpp>
+
+using namespace boost::mp11;
+
+template<typename L>
+struct test {
+ static_assert(mp_is_list<L>(), "must be a list of integral constants");
+ bool m_error;
+ test(bool b = true) : m_error(b) {}
+ operator bool(){
+ return m_error;
+ }
+ template<typename T>
+ void operator()(const T &){
+ static_assert(mp_is_list<T>(), "must be a list of two integral constants");
+ constexpr size_t i1 = mp_first<T>(); // index of first argument
+ constexpr size_t i2 = mp_second<T>();// index of second argument
+ std::cout << i1 << ',' << i2 << ',';
+ using T1 = typename mp_at_c<L, i1>::value_type;
+ using T2 = typename mp_at_c<L, i2>::value_type;
+ m_error &= test_and(
+ mp_at_c<L, i1>()(), // value of first argument
+ mp_at_c<L, i2>()(), // value of second argument
+ boost::core::demangle(typeid(T1).name()).c_str(),
+ boost::core::demangle(typeid(T2).name()).c_str(),
+ '.'
+ );
+ }
+};
+
+int main(){
+ test<test_values> rval(true);
+
+ using value_indices = mp_iota_c<mp_size<test_values>::value>;
+ mp_for_each<
+ mp_product<mp_list, value_indices, value_indices>
+ >(rval);
+
+ std::cout << (rval ? "success!" : "failure") << std::endl;
+ return ! rval ;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_and_automatic_constexpr.cpp b/src/boost/libs/safe_numerics/test/test_and_automatic_constexpr.cpp
new file mode 100644
index 000000000..825df9d72
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_and_automatic_constexpr.cpp
@@ -0,0 +1,58 @@
+// Copyright (c) 2019 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/automatic.hpp>
+#include "test_add_automatic_results.hpp"
+
+template <class T>
+using safe_t = boost::safe_numerics::safe<
+ T,
+ boost::safe_numerics::automatic
+>;
+
+#include "test_add_constexpr.hpp"
+
+using namespace boost::mp11;
+
+template<typename First, typename Second>
+struct test_pair {
+ static const std::size_t i = First();
+ static const std::size_t j = Second();
+ constexpr static const bool value = test_add_constexpr(
+ typename boost::mp11::mp_at_c<test_values, i>()(),
+ typename boost::mp11::mp_at_c<test_values, j>()(),
+ test_addition_automatic_result[i][j]
+ );
+};
+
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/algorithm.hpp>
+#include "check_symmetry.hpp"
+
+int main(){
+ using namespace boost::mp11;
+
+ // sanity check on test matrix - should be symetrical
+ check_symmetry(test_addition_automatic_result);
+
+ using value_indices = mp_iota_c<mp_size<test_values>::value>;
+
+ static_assert(
+ mp_all_of<
+ mp_product<
+ test_pair,
+ value_indices,
+ value_indices
+ >,
+ mp_to_bool
+ >(),
+ "all values for all integer types correctly added"
+ );
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_and_native.cpp b/src/boost/libs/safe_numerics/test/test_and_native.cpp
new file mode 100644
index 000000000..afa2b1d36
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_and_native.cpp
@@ -0,0 +1,62 @@
+// Copyright (c) 2012 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/native.hpp>
+
+template <class T>
+using safe_t = boost::safe_numerics::safe<
+ T,
+ boost::safe_numerics::native
+>;
+#include "test_and.hpp"
+
+#include "test_values.hpp"
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/algorithm.hpp>
+#include <boost/core/demangle.hpp>
+
+using namespace boost::mp11;
+
+template<typename L>
+struct test {
+ static_assert(mp_is_list<L>(), "must be a list of integral constants");
+ bool m_error;
+ test(bool b = true) : m_error(b) {}
+ operator bool(){
+ return m_error;
+ }
+ template<typename T>
+ void operator()(const T &){
+ static_assert(mp_is_list<T>(), "must be a list of two integral constants");
+ constexpr size_t i1 = mp_first<T>(); // index of first argument
+ constexpr size_t i2 = mp_second<T>();// index of second argument
+ std::cout << i1 << ',' << i2 << ',';
+ using T1 = typename mp_at_c<L, i1>::value_type;
+ using T2 = typename mp_at_c<L, i2>::value_type;
+ m_error &= test_and(
+ mp_at_c<L, i1>()(), // value of first argument
+ mp_at_c<L, i2>()(), // value of second argument
+ boost::core::demangle(typeid(T1).name()).c_str(),
+ boost::core::demangle(typeid(T2).name()).c_str(),
+ '.'
+ );
+ }
+};
+
+int main(){
+ test<test_values> rval(true);
+
+ using value_indices = mp_iota_c<mp_size<test_values>::value>;
+ mp_for_each<
+ mp_product<mp_list, value_indices, value_indices>
+ >(rval);
+
+ std::cout << (rval ? "success!" : "failure") << std::endl;
+ return ! rval ;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_and_native_constexpr.cpp b/src/boost/libs/safe_numerics/test/test_and_native_constexpr.cpp
new file mode 100644
index 000000000..bb0054f68
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_and_native_constexpr.cpp
@@ -0,0 +1,59 @@
+// Copyright (c) 2019 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/native.hpp>
+
+#include "test_add_native_results.hpp"
+
+template <class T>
+using safe_t = boost::safe_numerics::safe<
+ T,
+ boost::safe_numerics::native
+>;
+
+#include "test_add_constexpr.hpp"
+
+using namespace boost::mp11;
+
+template<typename First, typename Second>
+struct test_pair {
+ static const std::size_t i = First();
+ static const std::size_t j = Second();
+ constexpr static const bool value = test_add_constexpr(
+ typename boost::mp11::mp_at_c<test_values, i>()(),
+ typename boost::mp11::mp_at_c<test_values, j>()(),
+ test_addition_native_result[i][j]
+ );
+};
+
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/algorithm.hpp>
+#include "check_symmetry.hpp"
+
+int main(){
+ using namespace boost::mp11;
+
+ // sanity check on test matrix - should be symetrical
+ check_symmetry(test_addition_native_result);
+
+ using value_indices = mp_iota_c<mp_size<test_values>::value>;
+
+ static_assert(
+ mp_all_of<
+ mp_product<
+ test_pair,
+ value_indices,
+ value_indices
+ >,
+ mp_to_bool
+ >(),
+ "all values for all integer types correctly added"
+ );
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_assignment.cpp b/src/boost/libs/safe_numerics/test/test_assignment.cpp
new file mode 100644
index 000000000..cddf59c98
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_assignment.cpp
@@ -0,0 +1,123 @@
+// Copyright (c) 2017 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// test construction assignments
+
+#include <iostream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+
+template <class T>
+using safe_t = boost::safe_numerics::safe<
+ T,
+ boost::safe_numerics::native
+>;
+
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/algorithm.hpp>
+#include "test_values.hpp"
+
+// note: same test matrix as used in test_checked. Here we test all combinations
+// safe and unsafe integers. in test_checked we test all combinations of
+// integer primitives
+
+const char *test_assignment_result[boost::mp11::mp_size<test_values>::value] = {
+// 0 0 0 0
+// 012345670123456701234567012345670
+// 012345678901234567890123456789012
+/* 0*/ ".....xx..xx..xx...xx.xxx.xxx.xxx.",
+/* 1*/ ".....xx..xx..xx...xx.xxx.xxx.xxx.",
+/* 2*/ ".....xx..xx..xx...xx.xxx.xxx.xxx.",
+/* 3*/ ".....xx..xx..xx...xx.xxx.xxx.xxx.",
+/* 4*/ ".........xx..xx.......xx.xxx.xxx.",
+/* 5*/ ".........xx..xx.......xx.xxx.xxx.",
+/* 6*/ ".........xx..xx.......xx.xxx.xxx.",
+/* 7*/ ".........xx..xx.......xx.xxx.xxx.",
+
+/* 8*/ ".............xx...........xx.xxx.",
+/* 9*/ ".............xx...........xx.xxx.",
+/*10*/ ".............xx...........xx.xxx.",
+/*11*/ ".............xx...........xx.xxx.",
+/*12*/ "..............................xx.",
+/*13*/ "..............................xx.",
+/*14*/ "..............................xx.",
+/*15*/ "..............................xx.",
+
+// 0 0 0 0
+// 012345670123456701234567012345670
+// 012345678901234567890123456789012
+/*16*/ "..xx.xxx.xxx.xxx.....xxx.xxx.xxx.",
+/*17*/ "..xx.xxx.xxx.xxx.....xxx.xxx.xxx.",
+/*18*/ "..xx.xxx.xxx.xxx.....xxx.xxx.xxx.",
+/*19*/ "..xx.xxx.xxx.xxx.....xxx.xxx.xxx.",
+/*20*/ "..xx..xx.xxx.xxx.........xxx.xxx.",
+/*21*/ "..xx..xx.xxx.xxx.........xxx.xxx.",
+/*22*/ "..xx..xx.xxx.xxx.........xxx.xxx.",
+/*23*/ "..xx..xx.xxx.xxx.........xxx.xxx.",
+
+/*24*/ "..xx..xx..xx.xxx.............xxx.",
+/*25*/ "..xx..xx..xx.xxx.............xxx.",
+/*26*/ "..xx..xx..xx.xxx.............xxx.",
+/*27*/ "..xx..xx..xx.xxx.............xxx.",
+/*28*/ "..xx..xx..xx..xx.................",
+/*29*/ "..xx..xx..xx..xx.................",
+/*30*/ "..xx..xx..xx..xx.................",
+/*31*/ "..xx..xx..xx..xx.................",
+// 012345678901234567890123456789012
+/*32*/ ".....xx..xx..xx...xx.xxx.xxx.xxx."
+};
+
+#include <boost/mp11/algorithm.hpp>
+#include <boost/core/demangle.hpp>
+
+template <class T>
+using safe_t = boost::safe_numerics::safe<
+ T,
+ boost::safe_numerics::native
+>;
+#include "test_assignment.hpp"
+
+using namespace boost::mp11;
+
+template<typename L>
+struct test {
+ static_assert(mp_is_list<L>(), "must be a list of integral constants");
+ bool m_error;
+ test(bool b = true) : m_error(b) {}
+ operator bool(){
+ return m_error;
+ }
+ template<typename T>
+ void operator()(const T &){
+ static_assert(mp_is_list<T>(), "must be a list of two integral constants");
+ constexpr size_t i1 = mp_first<T>(); // index of first argument
+ constexpr size_t i2 = mp_second<T>();// index of second argument
+ std::cout << i1 << ',' << i2 << ',';
+ using T1 = typename boost::mp11::mp_at_c<L, i1>::value_type;
+ using T2 = typename boost::mp11::mp_at_c<L, i2>::value_type;
+ m_error &= test_assignment<T1, T2>(
+ boost::mp11::mp_at_c<L, i1>(), // value of first argument
+ boost::mp11::mp_at_c<L, i2>(), // value of second argument
+ boost::core::demangle(typeid(T1).name()).c_str(),
+ boost::core::demangle(typeid(T2).name()).c_str(),
+ test_assignment_result[i1][i2]
+ );
+ }
+};
+
+int main(int, char *[]){
+
+ // TEST_EACH_VALUE_PAIR
+ test<test_values> rval(true);
+
+ using value_indices = mp_iota_c<mp_size<test_values>::value>;
+ mp_for_each<
+ mp_product<mp_list, value_indices, value_indices>
+ >(rval);
+
+ std::cout << (rval ? "success!" : "failure") << std::endl;
+ return ! rval ;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_assignment.hpp b/src/boost/libs/safe_numerics/test/test_assignment.hpp
new file mode 100644
index 000000000..678e2cb8e
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_assignment.hpp
@@ -0,0 +1,102 @@
+#ifndef BOOST_TEST_ASSIGNMENT_HPP
+#define BOOST_TEST_ASSIGNMENT_HPP
+
+// Copyright (c) 2015 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+#include <boost/core/demangle.hpp>
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/range_value.hpp>
+
+template<class T1, class T2>
+bool test_assignment(
+ T1 t1,
+ T2 t2,
+ const char *at1,
+ const char *at2,
+ char expected_result
+){
+ std::cout << "testing " << std::endl;
+ {
+ std::cout << "safe<" << at1 << "> = " << at2 << std::endl;
+ // std::cout << boost::core::demangle(typeid(t1).name()) << " = " << at2 << std::endl;
+ safe_t<T2> s2(t2);
+
+ static_assert(
+ boost::safe_numerics::is_safe<safe_t<T1> >::value,
+ "safe_t not safe!"
+ );
+ try{
+ t1 = s2;
+ if(expected_result == 'x'){
+ std::cout
+ << "failed to detect error in assignment "
+ << boost::core::demangle(typeid(t1).name())
+ << " = "
+ << at2
+ << std::endl;
+ t1 = s2;
+ return false;
+ }
+ }
+ catch(const std::exception &){
+ if(expected_result == '.'){
+ std::cout
+ << "erroneously detected error in assignment "
+ << boost::core::demangle(typeid(t1).name())
+ << " = "
+ << at2
+ << std::endl;
+ try{
+ t1 = s2;
+ }
+ catch(const std::exception &){}
+ return false;
+ }
+ }
+ }
+ {
+ safe_t<T1> s1(t1);
+ safe_t<T2> s2(t2);
+ std::cout
+ << "safe<" << boost::core::demangle(typeid(t1).name()) << ">"
+ << " = "
+ << "safe<" << at2 << '>' << std::endl;
+ try{
+ s1 = s2;
+ if(expected_result == 'x'){
+ std::cout
+ << "failed to detect error in assignment "
+ << "safe<" << boost::core::demangle(typeid(t1).name()) << ">"
+ << " = "
+ << at2
+ << std::endl;
+ s1 = s2;
+ return false;
+ }
+ }
+ catch(const std::exception &){
+ if(expected_result == '.'){
+ std::cout
+ << "erroneously detected error in assignment "
+ << "safe<" << boost::core::demangle(typeid(t1).name()) << ">"
+ << " = "
+ << at2
+ << std::endl;
+ try{
+ s1 = t2;
+ }
+ catch(const std::exception &){}
+ return false;
+ }
+ }
+ }
+ return true; // correct result
+}
+
+#endif // BOOST_TEST_ASSIGNMENT_HPP
diff --git a/src/boost/libs/safe_numerics/test/test_auto.cpp b/src/boost/libs/safe_numerics/test/test_auto.cpp
new file mode 100644
index 000000000..b73a8e170
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_auto.cpp
@@ -0,0 +1,89 @@
+#include <iostream>
+#include <cassert>
+#include <boost/core/demangle.hpp>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/safe_integer_range.hpp>
+#include <boost/safe_numerics/automatic.hpp>
+#include <boost/safe_numerics/utility.hpp>
+
+int test_log(){
+ using namespace boost::safe_numerics::utility;
+ assert(ilog2(127u) == 6);
+ assert(ilog2(128u) == 7);
+ assert(ilog2(129u) == 7);
+ assert(ilog2(255u) == 7);
+ assert(ilog2(256u) == 8);
+
+ assert(ilog2(127) == 6);
+ assert(ilog2(128) == 7);
+ assert(ilog2(129) == 7);
+ assert(ilog2(255) == 7);
+ assert(ilog2(256) == 8);
+ return 0;
+}
+
+template<class T>
+void print_argument_type(const T & t){
+ const std::type_info & ti = typeid(T);
+ std::cout
+ << boost::core::demangle(ti.name()) << ' ' << t << std::endl;
+}
+
+template<typename T, typename U>
+int test_auto(const T & t, const U & u){
+ using namespace boost::safe_numerics;
+
+ try{
+ safe<T, automatic>(t) + u;
+ }
+ catch(const std::exception &){
+ safe<T, automatic>(t) + u;
+ }
+
+ try{
+ t + safe<U, automatic>(u);
+ }
+ catch(const std::exception &){
+ t + safe<U, automatic>(u);
+ }
+ return 0;
+}
+
+int test_auto_result(){
+ using namespace boost::safe_numerics;
+ automatic::addition_result<
+ safe<std::int8_t, automatic>,
+ safe<std::uint16_t, automatic>
+ >::type r1;
+ print_argument_type(r1);
+
+ automatic::addition_result<
+ safe_signed_range<-3, 8, automatic>,
+ safe_signed_range<-4, 9, automatic>
+ >::type r2;
+ print_argument_type(r2);
+ return 0;
+}
+
+int test_compare_result(){
+ using namespace boost::safe_numerics;
+
+ automatic::comparison_result<
+ safe<std::int16_t, automatic>,
+ safe<std::int16_t, automatic>
+ >::type r1;
+ print_argument_type(r1);
+
+ return 0;
+}
+
+int main(){
+ using namespace boost::safe_numerics;
+
+ test_log();
+ test_auto<std::int8_t, std::int8_t>(1, -128);
+ test_auto_result();
+ test_compare_result();
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_cast.cpp b/src/boost/libs/safe_numerics/test/test_cast.cpp
new file mode 100644
index 000000000..a7b48b8d2
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_cast.cpp
@@ -0,0 +1,126 @@
+// Copyright (c) 2012 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+#include <cstdlib> // EXIT_SUCCESS
+
+#include <boost/safe_numerics/safe_compare.hpp>
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/range_value.hpp>
+
+using namespace boost::safe_numerics;
+
+// works for both GCC and clang
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-value"
+
+// test conversion to T2 from different literal types
+template<class T2, class T1>
+bool test_cast(T1 v1, const char *t2_name, const char *t1_name){
+ std::cout
+ << "testing static_cast<safe<" << t2_name << ">>(" << t1_name << ")"
+ << std::endl;
+ {
+ /* test conversion constructor to safe<T2> from v1 */
+ try{
+ // use auto to avoid checking assignment.
+ auto result = static_cast<safe<T2>>(v1);
+ std::cout << make_result_display(result) << " <- " << v1
+ << std::endl;
+ if(! safe_compare::equal(base_value(result), v1)){
+ std::cout
+ << ' ' << t2_name << "<-" << t1_name
+ << " failed to detect error in construction"
+ << std::endl;
+ static_cast<safe<T2> >(v1);
+ return false;
+ }
+ }
+ catch(const std::exception &){
+ if( safe_compare::equal(static_cast<T2>(v1), v1)){
+ std::cout
+ << ' ' << t1_name << "<-" << t2_name
+ << " erroneously emitted error "
+ << std::endl;
+ try{
+ static_cast<safe<T2> >(v1);
+ }
+ catch(const std::exception &){}
+ return false;
+ }
+ }
+ }
+ {
+ /* test conversion to T2 from safe<T1>(v1) */
+ safe<T1> s1(v1);
+ try{
+ auto result = static_cast<T2>(s1);
+ std::cout << make_result_display(result) << " <- " << v1
+ << std::endl;
+ if(! safe_compare::equal(result, v1)){
+ std::cout
+ << ' ' << t2_name << "<-" << t1_name
+ << " failed to detect error in construction"
+ << std::endl;
+ static_cast<T2>(s1);
+ return false;
+ }
+ }
+ catch(const std::exception &){
+ if(safe_compare::equal(static_cast<T2>(v1), v1)){
+ std::cout
+ << ' ' << t1_name << "<-" << t2_name
+ << " erroneously emitted error"
+ << std::endl;
+ try{
+ static_cast<T2>(s1);
+ }
+ catch(const std::exception &){}
+ return false;
+ }
+ }
+ }
+ return true; // passed test
+}
+#pragma GCC diagnostic pop
+
+#include <boost/mp11/algorithm.hpp>
+#include <boost/core/demangle.hpp>
+#include "test_values.hpp"
+
+using namespace boost::mp11;
+
+struct test {
+ bool m_error;
+ test(bool b = true) : m_error(b) {}
+ operator bool(){
+ return m_error;
+ }
+ template<typename T>
+ void operator()(const T &){
+ static_assert(mp_is_list<T>(), "must be a list of two types");
+ using T1 = mp_first<T>; // first element is a type
+ // second element is an integral constant
+ using T2 = typename mp_second<T>::value_type; // get it's type
+ constexpr T2 v2 = mp_second<T>(); // get it's value
+ m_error &= test_cast<T1>(
+ v2,
+ boost::core::demangle(typeid(T1).name()).c_str(),
+ boost::core::demangle(typeid(T2).name()).c_str()
+ );
+ }
+};
+
+int main(){
+ test rval(true);
+
+ mp_for_each<
+ mp_product<mp_list, test_types, test_values>
+ >(rval);
+
+ std::cout << (rval ? "success!" : "failure") << std::endl;
+ return ! rval ;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_cast_constexpr.cpp b/src/boost/libs/safe_numerics/test/test_cast_constexpr.cpp
new file mode 100644
index 000000000..1cd9dde0b
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_cast_constexpr.cpp
@@ -0,0 +1,90 @@
+// Copyright (c) 2019 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// compile only test to test constexpr casting
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/native.hpp>
+#include <boost/safe_numerics/exception_policies.hpp>
+
+template <class T>
+using safe_t = boost::safe_numerics::safe<
+ T,
+ boost::safe_numerics::native,
+ boost::safe_numerics::trap_exception
+>;
+
+constexpr const char * test_casting_results[] = {
+// 0 0 0 0
+// 012345670123456701234567012345670
+// 012345678901234567890123456789012
+/* 0*/ ".....xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/* 1*/ ".........xxx.xxx...x.xxx.xxx.xxx.",
+/* 2*/ ".............xxx...x...x.xxx.xxx.",
+/* 3*/ "...................x...x...x.xxx.",
+/* 4*/ "..xx.xxx.xxx.xxx..xx.xxx.xxx.xxx.",
+/* 5*/ "..xx..xx.xxx.xxx......xx.xxx.xxx.",
+/* 6*/ "..xx..xx..xx.xxx..........xx.xxx.",
+/* 7*/ "..xx..xx..xx..xx..............xx.",
+};
+
+#include <boost/safe_numerics/safe_integer_literal.hpp>
+using namespace boost::safe_numerics;
+
+#include <boost/mp11/algorithm.hpp>
+
+using namespace boost::mp11;
+
+template<class T>
+struct p {
+ constexpr static bool value = '.' == test_casting_results[mp_first<T>::value][mp_second<T>::value];
+};
+
+template<class T2, class T1>
+constexpr bool test_cast_constexpr(const T1 & v1){
+ // if we don't expect the operation to pass, we can't
+ // check the constexpr version of the calculation so
+ // just return success.
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wunused-value"
+ static_cast<safe_t<T2>>(v1);
+ static_cast<T2>(v1);
+ #pragma GCC diagnostic pop
+ return true;
+}
+
+#include "test_values.hpp"
+
+template<typename L2>
+struct test {
+ static_assert(mp_is_list<L2>(), "must be a list of two indices");
+ const static std::size_t i = mp_first<L2>();
+ const static std::size_t j = mp_second<L2>();
+ using T = mp_at_c<test_types, i>; // first element is a type
+ using T1 = typename mp_at_c<test_values, j>::value_type;
+ const static T1 v = mp_at_c<test_values, j>::value;
+ const static bool value =
+ test_cast_constexpr<T>(make_safe_literal(v, native, trap_exception));
+};
+
+int main(){
+ using namespace boost::safe_numerics;
+
+ using type_indices = mp_iota_c<mp_size<test_types>::value>;
+ using value_indices = mp_iota_c<mp_size<test_values>::value>;
+
+ // generate all combinations of types <- value
+ using l = mp_product<mp_list,type_indices,value_indices>;
+ //boost::safe_numerics::utility::print_types<l> lp;
+
+ // filter out the invalid ones
+ using l1 = mp_copy_if<l, p>;
+ //boost::safe_numerics::utility::print_types<l1> l1p;
+
+ // verify that all valid ones compile without error
+ static_assert(mp_all_of<l1, test>(), "testing all valid casts");
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_checked_add.cpp b/src/boost/libs/safe_numerics/test/test_checked_add.cpp
new file mode 100644
index 000000000..655dbe761
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_checked_add.cpp
@@ -0,0 +1,131 @@
+// Copyright (c) 2012 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+#include <boost/core/demangle.hpp>
+#include <boost/safe_numerics/checked_result_operations.hpp>
+#include <boost/safe_numerics/checked_integer.hpp>
+
+// note: T should be of type checked_result<R> for some integer type R
+template<class T>
+bool test_checked_add(
+ T v1,
+ T v2,
+ char expected_result
+){
+ using namespace boost::safe_numerics;
+ const T result = v1 + v2;
+ std::cout
+ << "testing " << boost::core::demangle(typeid(T).name()) << ' '
+ << v1 << " + " << v2 << " -> " << result
+ << std::endl;
+
+ switch(expected_result){
+ case '.':
+ if(result.exception()){
+ std::cout
+ << "erroneously detected error in addition "
+ << std::endl;
+ v1 + v2;
+ return false;
+ }
+ return true;
+ case '-':
+ if(safe_numerics_error::negative_overflow_error == result.m_e)
+ return true;
+ break;
+ case '+':
+ if(safe_numerics_error::positive_overflow_error == result.m_e)
+ return true;
+ break;
+ case '!':
+ if(safe_numerics_error::range_error == result.m_e)
+ return true;
+ break;
+ }
+ std::cout
+ << "failed to detect error in addition "
+ << std::hex << result << "(" << std::dec << result << ")"
+ << " != "<< v1 << " + " << v2
+ << std::endl;
+ v1 + v2;
+ return false;
+}
+
+#include "test_checked_add.hpp"
+
+template<typename T, typename First, typename Second>
+struct test_signed_pair {
+ bool operator()() const {
+ std::size_t i = First();
+ std::size_t j = Second();
+ std::cout << std::dec << i << ',' << j << ','
+ << "testing " << boost::core::demangle(typeid(T).name()) << ' ';
+ return test_checked_add(
+ signed_values<T>[i],
+ signed_values<T>[j],
+ signed_addition_results[i][j]
+ );
+ };
+};
+
+template<typename T, typename First, typename Second>
+struct test_unsigned_pair {
+ bool operator()() const {
+ std::size_t i = First();
+ std::size_t j = Second();
+ std::cout << std::dec << i << ',' << j << ','
+ << "testing " << boost::core::demangle(typeid(T).name()) << ' ';
+ return test_checked_add(
+ unsigned_values<T>[i],
+ unsigned_values<T>[j],
+ unsigned_addition_results[i][j]
+ );
+ };
+};
+
+#include "check_symmetry.hpp"
+
+#include <boost/mp11/algorithm.hpp>
+
+int main(){
+ static_assert(
+ check_symmetry(signed_addition_results),
+ "sanity check on test matrix - should be symmetrical"
+ );
+ static_assert(
+ check_symmetry(unsigned_addition_results),
+ "sanity check on test matrix - should be symmetrical"
+ );
+
+ using namespace boost::mp11;
+ bool rval = true;
+
+ mp_for_each<
+ mp_product<
+ test_signed_pair,
+ signed_test_types,
+ signed_value_indices,
+ signed_value_indices
+ >
+ >([&](auto I){
+ rval &= I();
+ });
+
+ mp_for_each<
+ mp_product<
+ test_unsigned_pair,
+ unsigned_test_types,
+ unsigned_value_indices, unsigned_value_indices
+ >
+ >([&](auto I){
+ rval &= I();
+ });
+
+ std::cout << (rval ? "success!" : "failure") << std::endl;
+ return rval ? 0 : 1;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_checked_add.hpp b/src/boost/libs/safe_numerics/test/test_checked_add.hpp
new file mode 100644
index 000000000..24411cb04
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_checked_add.hpp
@@ -0,0 +1,44 @@
+#ifndef BOOST_SAFE_NUMERICS_TEST_CHECKED_ADD_HPP
+#define BOOST_SAFE_NUMERICS_TEST_CHECKED_ADD_HPP
+
+// Copyright (c) 2018 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include "test_checked_values.hpp"
+
+// test result matrices
+
+// key
+// . success
+// - negative_overflow_error
+// + positive_overflow_error
+// ! range_error
+
+constexpr const char * signed_addition_results[] = {
+// 012345678
+/* 0*/ "!!!!!!!!!",
+/* 1*/ "!!!!!!!!!",
+/* 2*/ "!!++++++!",
+/* 3*/ "!!+++...-",
+/* 4*/ "!!++....-",
+/* 5*/ "!!+.....-",
+/* 6*/ "!!+....--",
+/* 7*/ "!!+...---",
+/* 8*/ "!!!------",
+};
+
+constexpr const char * unsigned_addition_results[] = {
+// 0123456
+/* 0*/ "!!!!!!!",
+/* 1*/ "!!!!!!!",
+/* 2*/ "!!++++!",
+/* 3*/ "!!+++.-",
+/* 4*/ "!!++..-",
+/* 5*/ "!!+...-",
+/* 6*/ "!!!----",
+};
+
+#endif // BOOST_SAFE_NUMERICS_TEST_CHECKED_ADD_HPP
diff --git a/src/boost/libs/safe_numerics/test/test_checked_add_constexpr.cpp b/src/boost/libs/safe_numerics/test/test_checked_add_constexpr.cpp
new file mode 100644
index 000000000..9bc1adc98
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_checked_add_constexpr.cpp
@@ -0,0 +1,97 @@
+// Copyright (c) 2012 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/safe_numerics/checked_result.hpp>
+#include <boost/safe_numerics/checked_result_operations.hpp>
+#include <boost/safe_numerics/checked_integer.hpp>
+
+// note: T should be of tyme checked_result<R> for some integer type R
+template<class T>
+constexpr bool test_checked_add(
+ const T & v1,
+ const T & v2,
+ char expected_result
+){
+ using namespace boost::safe_numerics;
+ const T result = v1 + v2;
+ switch(expected_result){
+ case '.':
+ return ! result.exception();
+ case '-':
+ return safe_numerics_error::negative_overflow_error == result.m_e;
+ case '+':
+ return safe_numerics_error::positive_overflow_error == result.m_e;
+ case '!':
+ return safe_numerics_error::range_error == result.m_e;
+ }
+ return false;
+}
+
+#include "test_checked_add.hpp"
+
+template<typename T, typename First, typename Second>
+struct test_signed_pair {
+ static const std::size_t i = First();
+ static const std::size_t j = Second();
+ // note: is constexpr really required here? compilers disagree!
+ constexpr static const bool value = test_checked_add(
+ signed_values<T>[i],
+ signed_values<T>[j],
+ signed_addition_results[i][j]
+ );
+};
+
+template<typename T, typename First, typename Second>
+struct test_unsigned_pair {
+ static const std::size_t i = First();
+ static const std::size_t j = Second();
+ // note: is constexpr really required here? compilers disagree!
+ constexpr static const bool value = test_checked_add(
+ unsigned_values<T>[i],
+ unsigned_values<T>[j],
+ unsigned_addition_results[i][j]
+ );
+};
+
+#include "check_symmetry.hpp"
+#include <boost/mp11/algorithm.hpp>
+
+int main(){
+ static_assert(
+ check_symmetry(signed_addition_results),
+ "sanity check on test matrix - should be symmetrical"
+ );
+ static_assert(
+ check_symmetry(unsigned_addition_results),
+ "sanity check on test matrix - should be symmetrical"
+ );
+
+ using namespace boost::mp11;
+ static_assert(
+ mp_all_of<
+ mp_product<
+ test_signed_pair,
+ signed_test_types,
+ signed_value_indices, signed_value_indices
+ >,
+ mp_to_bool
+ >(),
+ "all values for all signed types correctly added"
+ );
+
+ static_assert(
+ mp_all_of<
+ mp_product<
+ test_unsigned_pair,
+ unsigned_test_types,
+ unsigned_value_indices, unsigned_value_indices
+ >,
+ mp_to_bool
+ >(),
+ "all values for all unsigned types correctly added"
+ );
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_checked_and.cpp b/src/boost/libs/safe_numerics/test/test_checked_and.cpp
new file mode 100644
index 000000000..87d6bde9c
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_checked_and.cpp
@@ -0,0 +1,134 @@
+// Copyright (c) 2012 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+#include <boost/core/demangle.hpp>
+#include <boost/safe_numerics/checked_result_operations.hpp>
+#include <boost/safe_numerics/checked_integer.hpp>
+
+// note: T should be of tyme checked_result<R> for some integer type R
+template<class T>
+bool test_checked_and(
+ T v1,
+ T v2,
+ char expected_result
+){
+ using namespace boost::safe_numerics;
+ const T result = v1 & v2;
+ std::cout
+ << v1 << " & " << v2 << " -> " << result
+ << std::endl;
+
+ switch(expected_result){
+ case '.':
+ if(result.exception()){
+ std::cout
+ << "erroneously detected error in and operation "
+ << std::endl;
+ v1 & v2;
+ return false;
+ }
+ return true;
+ case '-':
+ if(safe_numerics_error::negative_overflow_error == result.m_e)
+ return true;
+ break;
+ case '+':
+ if(safe_numerics_error::positive_overflow_error == result.m_e)
+ return true;
+ break;
+ case '!':
+ if(safe_numerics_error::range_error == result.m_e)
+ return true;
+ break;
+ }
+ std::cout
+ << "failed to detect error in and operation "
+ << std::hex << result << "(" << std::dec << result << ")"
+ << " != "<< v1 << " & " << v2
+ << std::endl;
+ v1 & v2;
+ return false;
+}
+
+#include "test_checked_and.hpp"
+
+template<typename T, typename First, typename Second>
+struct test_signed_pair {
+ bool operator()() const {
+ std::size_t i = First();
+ std::size_t j = Second();
+ std::cout << std::dec << i << ',' << j << ','
+ << "testing " << boost::core::demangle(typeid(T).name()) << ' ';
+ return test_checked_and(
+ signed_values<T>[i],
+ signed_values<T>[j],
+ signed_and_results[i][j]
+ );
+ };
+};
+
+template<typename T, typename First, typename Second>
+struct test_unsigned_pair {
+ bool operator()() const {
+ std::size_t i = First();
+ std::size_t j = Second();
+ std::cout << std::dec << i << ',' << j << ','
+ << "testing " << boost::core::demangle(typeid(T).name()) << ' ';
+ return test_checked_and(
+ unsigned_values<T>[i],
+ unsigned_values<T>[j],
+ unsigned_and_results[i][j]
+ );
+ };
+};
+
+#include "check_symmetry.hpp"
+
+#include <boost/mp11/algorithm.hpp>
+
+int main(){
+ static_assert(
+ check_symmetry(signed_and_results),
+ "sanity check on test matrix - should be symmetrical"
+ );
+ static_assert(
+ check_symmetry(unsigned_and_results),
+ "sanity check on test matrix - should be symmetrical"
+ );
+
+ using namespace boost::mp11;
+ bool rval = true;
+
+ std::cout << "*** testing signed values\n";
+
+ mp_for_each<
+ mp_product<
+ test_signed_pair,
+ signed_test_types,
+ signed_value_indices,
+ signed_value_indices
+ >
+ >([&](auto I){
+ rval &= I();
+ });
+
+ std::cout << "*** testing unsigned values\n";
+
+ mp_for_each<
+ mp_product<
+ test_unsigned_pair,
+ unsigned_test_types,
+ unsigned_value_indices, unsigned_value_indices
+ >
+ >([&](auto I){
+ rval &= I();
+ });
+
+ std::cout << (rval ? "success!" : "failure") << std::endl;
+ return rval ? 0 : 1;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_checked_and.hpp b/src/boost/libs/safe_numerics/test/test_checked_and.hpp
new file mode 100644
index 000000000..d7ed82f32
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_checked_and.hpp
@@ -0,0 +1,44 @@
+#ifndef BOOST_SAFE_NUMERICS_TEST_CHECKED_AND_HPP
+#define BOOST_SAFE_NUMERICS_TEST_CHECKED_AND_HPP
+
+// Copyright (c) 2018 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include "test_checked_values.hpp"
+
+// test result matrices
+
+// key
+// . success
+// - negative_overflow_error
+// + positive_overflow_error
+// ? range_error
+
+constexpr const char * signed_and_results[] = {
+// 012345678
+/* 0*/ "!!!!!!!!!",
+/* 1*/ "!!!!!!!!!",
+/* 2*/ "!!!!!!!!!",
+/* 3*/ "!!!.....!",
+/* 4*/ "!!!.....!",
+/* 5*/ "!!!.....!",
+/* 6*/ "!!!.....!",
+/* 7*/ "!!!.....!",
+/* 8*/ "!!!!!!!!!",
+};
+
+constexpr const char * unsigned_and_results[] = {
+// 0123456
+/* 0*/ "!!!!!!!",
+/* 1*/ "!!!!!!!",
+/* 2*/ "!!!!!!!",
+/* 3*/ "!!!...!",
+/* 4*/ "!!!...!",
+/* 5*/ "!!!...!",
+/* 6*/ "!!!!!!!",
+};
+
+#endif // BOOST_SAFE_NUMERICS_TEST_CHECKED_AND_HPP
diff --git a/src/boost/libs/safe_numerics/test/test_checked_and_constexpr.cpp b/src/boost/libs/safe_numerics/test/test_checked_and_constexpr.cpp
new file mode 100644
index 000000000..45f8e42da
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_checked_and_constexpr.cpp
@@ -0,0 +1,98 @@
+// Copyright (c) 2018 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/safe_numerics/checked_result.hpp>
+#include <boost/safe_numerics/checked_result_operations.hpp>
+#include <boost/safe_numerics/checked_integer.hpp>
+
+// note: T should be of tyme checked_result<R> for some integer type R
+template<class T>
+constexpr bool test_checked_and(
+ const T & v1,
+ const T & v2,
+ char expected_result
+){
+ using namespace boost::safe_numerics;
+ const T result = v1 & v2;
+ switch(expected_result){
+ case '.':
+ return ! result.exception();
+ case '-':
+ return safe_numerics_error::negative_overflow_error == result.m_e;
+ case '+':
+ return safe_numerics_error::positive_overflow_error == result.m_e;
+ case '!':
+ return safe_numerics_error::range_error == result.m_e;
+ }
+ return false;
+}
+
+#include "test_checked_and.hpp"
+
+template<typename T, typename First, typename Second>
+struct test_signed_pair {
+ static const std::size_t i = First();
+ static const std::size_t j = Second();
+ // note: is constexpr really required here? compilers disagree!
+ constexpr static const bool value = test_checked_and(
+ signed_values<T>[i],
+ signed_values<T>[j],
+ signed_and_results[i][j]
+ );
+};
+
+template<typename T, typename First, typename Second>
+struct test_unsigned_pair {
+ static const std::size_t i = First();
+ static const std::size_t j = Second();
+ // note: is constexpr really required here? compilers disagree!
+ constexpr static const bool value = test_checked_and(
+ unsigned_values<T>[i],
+ unsigned_values<T>[j],
+ unsigned_and_results[i][j]
+ );
+};
+
+#include "check_symmetry.hpp"
+#include <boost/mp11/algorithm.hpp>
+
+int main(){
+ static_assert(
+ check_symmetry(signed_and_results),
+ "sanity check on test matrix - should be symmetrical"
+ );
+ static_assert(
+ check_symmetry(unsigned_and_results),
+ "sanity check on test matrix - should be symmetrical"
+ );
+
+ using namespace boost::mp11;
+
+ static_assert(
+ mp_all_of<
+ mp_product<
+ test_signed_pair,
+ signed_test_types,
+ signed_value_indices, signed_value_indices
+ >,
+ mp_to_bool
+ >(),
+ "all values for all signed types correctly anded"
+ );
+
+ static_assert(
+ mp_all_of<
+ mp_product<
+ test_unsigned_pair,
+ unsigned_test_types,
+ unsigned_value_indices, unsigned_value_indices
+ >,
+ mp_to_bool
+ >(),
+ "all values for all unsigned types correctly anded"
+ );
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_checked_cast.cpp b/src/boost/libs/safe_numerics/test/test_checked_cast.cpp
new file mode 100644
index 000000000..f1d111d19
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_checked_cast.cpp
@@ -0,0 +1,95 @@
+// Copyright (c) 2012 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+#include "test_checked_cast.hpp"
+#include <boost/safe_numerics/checked_integer.hpp>
+
+// test conversion to TResult from different literal types
+template<class TResult, class TArg>
+bool test_cast(
+ const TArg & v,
+ const char *tresult_name,
+ const char *targ_name,
+ char expected_result
+){
+ std::cout
+ << "testing static_cast<" << tresult_name << ">(" << targ_name << ")"
+ << std::endl;
+
+ boost::safe_numerics::checked_result<TResult> r2 =
+ boost::safe_numerics::checked::cast<TResult>(v);
+
+ if(expected_result == 'x' && ! r2.exception()){
+ std::cout
+ << "failed to detect error in construction "
+ << tresult_name << "<-" << targ_name
+ << std::endl;
+ boost::safe_numerics::checked::cast<TResult>(v);
+ return false;
+ }
+ if(expected_result == '.' && r2.exception()){
+ std::cout
+ << "erroneously emitted error "
+ << tresult_name << "<-" << targ_name
+ << std::endl;
+ boost::safe_numerics::checked::cast<TResult>(v);
+ return false;
+ }
+ return true; // passed test
+}
+
+#include <boost/mp11/algorithm.hpp>
+#include <boost/core/demangle.hpp>
+
+using namespace boost::mp11;
+
+// given a list of integral constants I, return a list of values
+template<typename I>
+struct get_values {
+ static_assert(mp_is_list<I>(), "must be a list of two types");
+ static_assert(2 == mp_size<I>::value, "must be a list of two types");
+ static constexpr const size_t first = mp_first<I>(); // index of first argument
+ static constexpr const size_t second = mp_second<I>();// index of second argument
+};
+
+struct test_pair {
+ bool m_error;
+ test_pair(bool b = true) : m_error(b) {}
+ operator bool(){
+ return m_error;
+ }
+ template<typename I>
+ void operator()(const I &){
+ using pair = get_values<I>;
+ using TResult = mp_at<test_types, mp_first<I>>;
+ using TArg = typename mp_at<test_values, mp_second<I>>::value_type;
+ static constexpr TArg v = mp_at<test_values, mp_second<I>>()();
+ m_error &= test_cast<TResult>(
+ v,
+ boost::core::demangle(typeid(TResult).name()).c_str(),
+ boost::core::demangle(typeid(TArg).name()).c_str(),
+ test_result_cast[pair::first][pair::second]
+ );
+ }
+};
+
+int main(){
+ // list of indices for values (integral constants)
+ using value_indices = mp_iota_c<mp_size<test_values>::value>;
+ // list of indices for types (integral constants)
+ using type_indices = mp_iota_c<mp_size<test_types>::value>;
+
+ // test runtime behavior
+ test_pair rval(true);
+ mp_for_each<
+ mp_product<mp_list, type_indices, value_indices>
+ >(rval);
+
+ std::cout << (rval ? "success!" : "failure") << std::endl;
+ return ! rval ;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_checked_cast.hpp b/src/boost/libs/safe_numerics/test/test_checked_cast.hpp
new file mode 100644
index 000000000..e8efe5761
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_checked_cast.hpp
@@ -0,0 +1,31 @@
+#ifndef BOOST_SAFE_NUMERICS_TEST_CHECKED_CAST_HPP
+#define BOOST_SAFE_NUMERICS_TEST_CHECKED_CAST_HPP
+
+// Copyright (c) 2018 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/mp11/integral.hpp>
+#include "test_values.hpp"
+
+// note: the types indexed on the left side of the table are gathered
+// by filtering the test_values list. So the types are in the same
+// sequence
+
+constexpr const char *test_result_cast[boost::mp11::mp_size<test_values>::value] = {
+// 0 0 0 0
+// 01234567012345670123456701234567
+// 01234567890123456789012345678901
+/* 0*/ ".....xx..xx..xx...xx.xxx.xxx.xxx",
+/* 1*/ ".........xx..xx.......xx.xxx.xxx",
+/* 2*/ ".............xx...........xx.xxx",
+/* 3*/ "..............................xx",
+/* 4*/ "..xx.xxx.xxx.xxx.....xxx.xxx.xxx",
+/* 5*/ "..xx..xx.xxx.xxx.........xxx.xxx",
+/* 6*/ "..xx..xx..xx.xxx.............xxx",
+/* 7*/ "..xx..xx..xx..xx................"
+};
+
+#endif // BOOST_SAFE_NUMERICS_TEST_CHECKED_CAST_HPP
diff --git a/src/boost/libs/safe_numerics/test/test_checked_cast_constexpr.cpp b/src/boost/libs/safe_numerics/test/test_checked_cast_constexpr.cpp
new file mode 100644
index 000000000..ac60dcdd3
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_checked_cast_constexpr.cpp
@@ -0,0 +1,65 @@
+// Copyright (c) 2012 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+#include <boost/safe_numerics/checked_integer.hpp>
+
+// test conversion to T2 from different literal types
+template<class T2, class T1>
+constexpr bool test_cast_constexpr(
+ const T1 & v1,
+ char result
+){
+ const boost::safe_numerics::checked_result<T2> r2 =
+ boost::safe_numerics::checked::cast<T2>(v1);
+ return ('x' == result) ?
+ r2.exception() :
+ ! r2.exception();
+}
+
+#include "test_checked_cast.hpp"
+
+#include <boost/mp11/algorithm.hpp> // mp_iota
+#include <boost/mp11/list.hpp> // mp_first, mp_second, mp_size, mp_is_list
+
+using namespace boost::mp11;
+
+// given a list of integral constants I, return a list of values
+template<typename I>
+struct get_values {
+ static_assert(mp_is_list<I>(), "must be a list of two types");
+ static_assert(2 == mp_size<I>::value, "must be a list of two types");
+ static constexpr const size_t first = mp_first<I>(); // index of first argument
+ static constexpr const size_t second = mp_second<I>();// index of second argument
+};
+
+template<typename I>
+struct test_pair_constexpr {
+ using pair = get_values<I>;
+ using TResult = mp_at<test_types, mp_first<I>>;
+ using TArg = typename mp_at<test_values, mp_second<I>>::value_type;
+ static constexpr TArg v = mp_at<test_values, mp_second<I>>()();
+ static constexpr bool value = test_cast_constexpr<TResult>(
+ v,
+ test_result_cast[pair::first][pair::second]
+ );
+};
+
+int main(){
+ // list of indices for values (integral constants)
+ using value_indices = mp_iota_c<mp_size<test_values>::value>;
+ // list of indices for types (integral constants)
+ using type_indices = mp_iota_c<mp_size<test_types>::value>;
+ // all combinations of type index, value index
+ using index_pairs = mp_product<mp_list, type_indices, value_indices>;
+ // test all type/value pairs to verify that cast can be done.
+ static_assert(
+ mp_all_of<index_pairs, test_pair_constexpr>::value,
+ "all type/value pairs correctly cast"
+ );
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_checked_comparison.hpp b/src/boost/libs/safe_numerics/test/test_checked_comparison.hpp
new file mode 100644
index 000000000..74af9c7f4
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_checked_comparison.hpp
@@ -0,0 +1,44 @@
+#ifndef BOOST_SAFE_NUMERICS_TEST_CHECKED_COMPARISON_HPP
+#define BOOST_SAFE_NUMERICS_TEST_CHECKED_COMPARISON_HPP
+
+// Copyright (c) 2018 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include "test_checked_values.hpp"
+
+// test result matrices
+
+// key
+// < less than
+// > greater than
+// = equal to
+// ! indeterminant
+
+constexpr const char * signed_comparison_results[] = {
+// 012345678
+/* 0*/ "!!!!!!!!!",
+/* 1*/ "!!!!!!!!!",
+/* 2*/ "!!!>>>>>>",
+/* 3*/ "!!<=>>>>>",
+/* 4*/ "!!<<=>>>>",
+/* 5*/ "!!<<<=>>>",
+/* 6*/ "!!<<<<=>>",
+/* 7*/ "!!<<<<<=>",
+/* 8*/ "!!<<<<<<!",
+};
+
+constexpr const char * unsigned_comparison_results[] = {
+// 0123456
+/* 0*/ "!!!!!!!",
+/* 1*/ "!!!!!!!",
+/* 2*/ "!!!>>>>",
+/* 3*/ "!!<=>>>",
+/* 4*/ "!!<<=>>",
+/* 5*/ "!!<<<=>",
+/* 6*/ "!!<<<<!",
+};
+
+#endif // BOOST_SAFE_NUMERICS_TEST_CHECKED_COMPARISON_HPP
diff --git a/src/boost/libs/safe_numerics/test/test_checked_divide.cpp b/src/boost/libs/safe_numerics/test/test_checked_divide.cpp
new file mode 100644
index 000000000..f91efb75f
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_checked_divide.cpp
@@ -0,0 +1,132 @@
+// Copyright (c) 2012 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+#include <boost/core/demangle.hpp>
+#include <boost/safe_numerics/checked_result_operations.hpp>
+#include <boost/safe_numerics/checked_integer.hpp>
+
+// note: T should be of type checked_result<R> for some integer type R
+template<class T>
+bool test_checked_divide(
+ T v1,
+ T v2,
+ char expected_result
+){
+ using namespace boost::safe_numerics;
+ const T result = v1 / v2;
+ std::cout
+ << v1 << " / " << v2 << " -> " << result
+ << std::endl;
+
+ switch(expected_result){
+ case '.':
+ case '0':
+ if(result.exception()){
+ std::cout
+ << "*** erroneously detected error in division"
+ << std::endl;
+ v1 / v2;
+ return false;
+ }
+ if(expected_result == '0'
+ && result != T(0)
+ ){
+ std::cout
+ << "*** failed to get expected zero result "
+ << std::endl;
+ v1 / v2;
+ return false;
+ }
+ return true;
+ case '-':
+ if(safe_numerics_error::negative_overflow_error == result.m_e)
+ return true;
+ break;
+ case '+':
+ if(safe_numerics_error::positive_overflow_error == result.m_e)
+ return true;
+ break;
+ case '!':
+ if(safe_numerics_error::range_error == result.m_e)
+ return true;
+ break;
+ }
+ std::cout
+ << "*** failed to detect error in division "
+ << std::hex << result << "(" << std::dec << result << ")"
+ << " != "<< v1 << " / " << v2
+ << std::endl;
+ v1 / v2;
+ return false;
+}
+
+#include "test_checked_divide.hpp"
+
+template<typename T, typename First, typename Second>
+struct test_signed_pair {
+ bool operator()() const {
+ std::size_t i = First();
+ std::size_t j = Second();
+ std::cout << std::dec << i << ',' << j << ','
+ << "testing " << boost::core::demangle(typeid(T).name()) << ' ';
+ return test_checked_divide(
+ signed_values<T>[i],
+ signed_values<T>[j],
+ signed_division_results[i][j]
+ );
+ };
+};
+
+template<typename T, typename First, typename Second>
+struct test_unsigned_pair {
+ bool operator()() const {
+ std::size_t i = First();
+ std::size_t j = Second();
+ std::cout << std::dec << i << ',' << j << ','
+ << "testing " << boost::core::demangle(typeid(T).name()) << ' ';
+ return test_checked_divide(
+ unsigned_values<T>[i],
+ unsigned_values<T>[j],
+ unsigned_division_results[i][j]
+ );
+ };
+};
+
+#include <boost/mp11/algorithm.hpp>
+
+int main(){
+ using namespace boost::mp11;
+
+ bool rval = true;
+
+ std::cout << "*** testing signed values\n";
+ mp_for_each<
+ mp_product<
+ test_signed_pair,
+ signed_test_types,
+ signed_value_indices,
+ signed_value_indices
+ >
+ >([&](auto I){
+ rval &= I();
+ });
+
+ std::cout << "*** testing unsigned values\n";
+ mp_for_each<
+ mp_product<
+ test_unsigned_pair,
+ unsigned_test_types,
+ unsigned_value_indices, unsigned_value_indices
+ >
+ >([&](auto I){
+ rval &= I();
+ });
+
+ std::cout << (rval ? "success!" : "failure") << std::endl;
+ return rval ? 0 : 1;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_checked_divide.hpp b/src/boost/libs/safe_numerics/test/test_checked_divide.hpp
new file mode 100644
index 000000000..9e2affe18
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_checked_divide.hpp
@@ -0,0 +1,44 @@
+#ifndef BOOST_SAFE_NUMERICS_TEST_CHECKED_DIVIDE_HPP
+#define BOOST_SAFE_NUMERICS_TEST_CHECKED_DIVIDE_HPP
+
+// Copyright (c) 2018 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include "test_checked_values.hpp"
+
+// test result matrices
+
+// key
+// . success
+// - negative_overflow_error
+// + positive_overflow_error
+// ! range_error
+
+constexpr const char * signed_division_results[] = {
+// 012345678
+/* 0*/ "!!!!!!!!!",
+/* 1*/ "!!!!!!!!!",
+/* 2*/ "!!!+++---",
+/* 3*/ "!!0..+..0",
+/* 4*/ "!!0..+.00",
+/* 5*/ "!!000!000",
+/* 6*/ "!!0..-.00",
+/* 7*/ "!!0..-+.0",
+/* 8*/ "!!----++!",
+};
+
+constexpr const char * unsigned_division_results[] = {
+// 0123456
+/* 0*/ "!!!!!!!",
+/* 1*/ "!!!!!!!",
+/* 2*/ "!!!+++-",
+/* 3*/ "!!0..+.",
+/* 4*/ "!!0..+.",
+/* 5*/ "!!000!0",
+/* 6*/ "!!----!",
+};
+
+#endif // BOOST_SAFE_NUMERICS_TEST_CHECKED_DIVIDE_HPP
diff --git a/src/boost/libs/safe_numerics/test/test_checked_divide_constexpr.cpp b/src/boost/libs/safe_numerics/test/test_checked_divide_constexpr.cpp
new file mode 100644
index 000000000..6056f06a1
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_checked_divide_constexpr.cpp
@@ -0,0 +1,92 @@
+// Copyright (c) 2012 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <cstdint> // std::int8, ...
+
+#include <boost/safe_numerics/checked_result.hpp>
+#include <boost/safe_numerics/checked_result_operations.hpp>
+#include <boost/safe_numerics/checked_integer.hpp>
+
+// note: T should be of tyme checked_result<R> for some integer type R
+template<class T>
+constexpr bool test_checked_divide(
+ const T & v1,
+ const T & v2,
+ char expected_result
+){
+ using namespace boost::safe_numerics;
+ const T result = v1 / v2;
+ switch(expected_result){
+ case '0':
+ case '.':
+ return ! result.exception();
+ case '-':
+ return safe_numerics_error::negative_overflow_error == result.m_e;
+ case '+':
+ return safe_numerics_error::positive_overflow_error == result.m_e;
+ case '!':
+ return safe_numerics_error::range_error == result.m_e;
+ }
+ return false;
+}
+
+#include "test_checked_divide.hpp"
+
+template<typename T, typename First, typename Second>
+struct test_signed_pair {
+ static const std::size_t i = First();
+ static const std::size_t j = Second();
+ // note: is constexpr really required here? compilers disagree!
+ constexpr static const bool value = test_checked_divide(
+ signed_values<T>[i],
+ signed_values<T>[j],
+ signed_division_results[i][j]
+ );
+};
+
+template<typename T, typename First, typename Second>
+struct test_unsigned_pair {
+ static const std::size_t i = First();
+ static const std::size_t j = Second();
+ // note: is constexpr really required here? compilers disagree!
+ constexpr static const bool value = test_checked_divide(
+ unsigned_values<T>[i],
+ unsigned_values<T>[j],
+ unsigned_division_results[i][j]
+ );
+};
+
+#include <boost/mp11/algorithm.hpp>
+#include <boost/mp11/function.hpp>
+
+int main(){
+ using namespace boost::mp11;
+
+ static_assert(
+ mp_all_of<
+ mp_product<
+ test_signed_pair,
+ signed_test_types,
+ signed_value_indices, signed_value_indices
+ >,
+ mp_to_bool
+ >(),
+ "all values for all signed types correctly divided"
+ );
+
+ static_assert(
+ mp_all_of<
+ mp_product<
+ test_unsigned_pair,
+ unsigned_test_types,
+ unsigned_value_indices, unsigned_value_indices
+ >,
+ mp_to_bool
+ >(),
+ "all values for all unsigned types correctly divided"
+ );
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_checked_equal_to.cpp b/src/boost/libs/safe_numerics/test/test_checked_equal_to.cpp
new file mode 100644
index 000000000..8517095b2
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_checked_equal_to.cpp
@@ -0,0 +1,118 @@
+// Copyright (c) 2012 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+#include <boost/logic/tribool_io.hpp>
+
+#include <boost/core/demangle.hpp>
+#include <boost/safe_numerics/checked_result_operations.hpp>
+#include <boost/safe_numerics/checked_integer.hpp>
+
+// works for both GCC and clang
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-value"
+
+// note: T should be of type checked_result<R> for some integer type R
+template<class T>
+bool test_checked_equal_to(
+ T v1,
+ T v2,
+ char expected_result
+){
+ using namespace boost::safe_numerics;
+ const boost::logic::tribool result = (v1 == v2);
+ std::cout
+ << std::boolalpha << v1 << " == " << v2 << " -> " << result
+ << std::endl;
+
+ switch(expected_result){
+ case '<':
+ case '>':
+ if(! result)
+ return true;
+ break;
+ case '=':
+ if(result)
+ return true;
+ break;
+ case '!':
+ if(indeterminate(result))
+ return true;
+ break;
+ }
+ std::cout
+ << "failed to detect error in addition "
+ << std::hex << result << "(" << std::dec << result << ")"
+ << " != "<< v1 << " == " << v2
+ << std::endl;
+ v1 == v2;
+ return false;
+}
+
+#pragma GCC diagnostic pop
+
+#include "test_checked_comparison.hpp"
+
+template<typename T, typename First, typename Second>
+struct test_signed_pair {
+ bool operator()() const {
+ std::size_t i = First();
+ std::size_t j = Second();
+ std::cout << std::dec << i << ',' << j << ','
+ << "testing " << boost::core::demangle(typeid(T).name()) << ' ';
+ return test_checked_equal_to(
+ signed_values<T>[i],
+ signed_values<T>[j],
+ signed_comparison_results[i][j]
+ );
+ };
+};
+
+template<typename T, typename First, typename Second>
+struct test_unsigned_pair {
+ bool operator()() const {
+ std::size_t i = First();
+ std::size_t j = Second();
+ std::cout << std::dec << i << ',' << j << ','
+ << "testing " << boost::core::demangle(typeid(T).name()) << ' ';
+ return test_checked_equal_to(
+ unsigned_values<T>[i],
+ unsigned_values<T>[j],
+ unsigned_comparison_results[i][j]
+ );
+ };
+};
+
+#include <boost/mp11/algorithm.hpp>
+
+int main(){
+ using namespace boost::mp11;
+ bool rval = true;
+
+ mp_for_each<
+ mp_product<
+ test_signed_pair,
+ signed_test_types,
+ signed_value_indices,
+ signed_value_indices
+ >
+ >([&](auto I){
+ rval &= I();
+ });
+
+ mp_for_each<
+ mp_product<
+ test_unsigned_pair,
+ unsigned_test_types,
+ unsigned_value_indices, unsigned_value_indices
+ >
+ >([&](auto I){
+ rval &= I();
+ });
+
+ std::cout << (rval ? "success!" : "failure") << std::endl;
+ return rval ? 0 : 1;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_checked_equal_to_constexpr.cpp b/src/boost/libs/safe_numerics/test/test_checked_equal_to_constexpr.cpp
new file mode 100644
index 000000000..072f23714
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_checked_equal_to_constexpr.cpp
@@ -0,0 +1,93 @@
+// Copyright (c) 2018 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/safe_numerics/checked_result.hpp>
+#include <boost/safe_numerics/checked_result_operations.hpp>
+#include <boost/safe_numerics/checked_integer.hpp>
+
+// note: T should be of tyme checked_result<R> for some integer type R
+template<class T>
+constexpr bool test_checked_equal_to(
+ T v1,
+ T v2,
+ char expected_result
+){
+ using namespace boost::safe_numerics;
+ const boost::logic::tribool result = (v1 == v2);
+ switch(expected_result){
+ case '<':
+ case '>':
+ if(! result)
+ return true;
+ break;
+ case '=':
+ if(result)
+ return true;
+ break;
+ case '!':
+ if(indeterminate(result))
+ return true;
+ break;
+ }
+ return false;
+}
+
+#include "test_checked_comparison.hpp"
+
+template<typename T, typename First, typename Second>
+struct test_signed_pair {
+ static const std::size_t i = First();
+ static const std::size_t j = Second();
+ // note: is constexpr really required here? compilers disagree!
+ constexpr static const bool value = test_checked_equal_to(
+ signed_values<T>[i],
+ signed_values<T>[j],
+ signed_comparison_results[i][j]
+ );
+};
+
+template<typename T, typename First, typename Second>
+struct test_unsigned_pair {
+ static const std::size_t i = First();
+ static const std::size_t j = Second();
+ // note: is constexpr really required here? compilers disagree!
+ constexpr static const bool value = test_checked_equal_to(
+ unsigned_values<T>[i],
+ unsigned_values<T>[j],
+ unsigned_comparison_results[i][j]
+ );
+};
+
+#include <boost/mp11/algorithm.hpp>
+
+int main(){
+ using namespace boost::mp11;
+
+ static_assert(
+ mp_all_of<
+ mp_product<
+ test_signed_pair,
+ signed_test_types,
+ signed_value_indices, signed_value_indices
+ >,
+ mp_to_bool
+ >(),
+ "all values for all signed types correctly compared"
+ );
+
+ static_assert(
+ mp_all_of<
+ mp_product<
+ test_unsigned_pair,
+ unsigned_test_types,
+ unsigned_value_indices, unsigned_value_indices
+ >,
+ mp_to_bool
+ >(),
+ "all values for all unsigned types correctly compared"
+ );
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_checked_left_shift.cpp b/src/boost/libs/safe_numerics/test/test_checked_left_shift.cpp
new file mode 100644
index 000000000..ca9789dd7
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_checked_left_shift.cpp
@@ -0,0 +1,136 @@
+// Copyright (c) 2012 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+#include <boost/core/demangle.hpp>
+#include <boost/safe_numerics/checked_result_operations.hpp>
+#include <boost/safe_numerics/checked_integer.hpp>
+
+template<class T>
+bool test_checked_left_shift(
+ T v1,
+ T v2,
+ char expected_result
+){
+ using namespace boost::safe_numerics;
+
+ const T result = v1 << v2;
+ std::cout
+ << v1 << " << " << v2 << " -> " << result
+ << std::endl;
+
+ switch(expected_result){
+ case '.':
+ if(result.exception()){
+ std::cout
+ << "erroneously detected error in left shift "
+ << std::endl;
+ v1 << v2;
+ return false;
+ }
+ return true;
+ case '-':
+ if(safe_numerics_error::negative_overflow_error == result.m_e)
+ return true;
+ break;
+ case '+':
+ if(safe_numerics_error::positive_overflow_error == result.m_e)
+ return true;
+ break;
+ case '!':
+ if(result.exception())
+ return true;
+ break;
+ case 'n': // n negative_shift
+ if(safe_numerics_error::negative_shift == result.m_e)
+ return true;
+ break;
+ case 's': // s negative_value_shift
+ if(safe_numerics_error::negative_value_shift == result.m_e)
+ return true;
+ break;
+ case 'l': // l shift_too_large
+ if(safe_numerics_error::shift_too_large == result.m_e)
+ return true;
+ break;
+ default:
+ assert(false);
+ }
+ std::cout
+ << "failed to detect error in left shift "
+ << std::hex << result << "(" << std::dec << result << ")"
+ << " != "<< v1 << " << " << v2
+ << std::endl;
+ v1 << v2;
+ return false;
+}
+
+#include "test_checked_left_shift.hpp"
+
+template<typename T, typename First, typename Second>
+struct test_signed_pair {
+ bool operator()() const {
+ std::size_t i = First();
+ std::size_t j = Second();
+ std::cout << std::dec << i << ',' << j << ','
+ << "testing " << boost::core::demangle(typeid(T).name()) << ' ';
+ return test_checked_left_shift(
+ signed_values<T>[i],
+ signed_values<T>[j],
+ signed_left_shift_results[i][j]
+ );
+ };
+};
+
+template<typename T, typename First, typename Second>
+struct test_unsigned_pair {
+ bool operator()() const {
+ std::size_t i = First();
+ std::size_t j = Second();
+ std::cout << std::dec << i << ',' << j << ','
+ << "testing " << boost::core::demangle(typeid(T).name()) << ' ';
+ return test_checked_left_shift(
+ unsigned_values<T>[i],
+ unsigned_values<T>[j],
+ unsigned_left_shift_results[i][j]
+ );
+ };
+};
+
+#include <boost/mp11/algorithm.hpp>
+
+int main(){
+ using namespace boost::mp11;
+
+ bool rval = true;
+
+ std::cout << "*** testing signed values\n";
+ mp_for_each<
+ mp_product<
+ test_signed_pair,
+ signed_test_types,
+ signed_value_indices,
+ signed_value_indices
+ >
+ >([&](auto I){
+ rval &= I();
+ });
+
+ std::cout << "*** testing unsigned values\n";
+ mp_for_each<
+ mp_product<
+ test_unsigned_pair,
+ unsigned_test_types,
+ unsigned_value_indices, unsigned_value_indices
+ >
+ >([&](auto I){
+ rval &= I();
+ });
+
+ std::cout << (rval ? "success!" : "failure") << std::endl;
+ return rval ? 0 : 1;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_checked_left_shift.hpp b/src/boost/libs/safe_numerics/test/test_checked_left_shift.hpp
new file mode 100644
index 000000000..61d949a73
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_checked_left_shift.hpp
@@ -0,0 +1,48 @@
+#ifndef BOOST_SAFE_NUMERICS_TEST_CHECKED_LEFT_SHIFT_HPP
+#define BOOST_SAFE_NUMERICS_TEST_CHECKED_LEFT_SHIFT_HPP
+
+// Copyright (c) 2018 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include "test_checked_values.hpp"
+
+// test result matrices
+
+// key
+// . success
+// - negative_overflow_error
+// + positive_overflow_error
+// ! range_error
+// n negative_shift, // negative value in shift operator
+// s negative_value_shift, // shift a negative value
+// l shift_too_large, // l/r shift exceeds variable size
+
+constexpr char const * const signed_left_shift_results[] = {
+// 012345678
+/* 0*/ "!!!!!!!!!",
+/* 1*/ "!!!!!!!!!",
+/* 2*/ "!!++++++!",
+/* 3*/ "!!+++....",
+/* 4*/ "!!++.....",
+/* 5*/ ".........",
+/* 6*/ "!!--.....",
+/* 7*/ "!!---....",
+/* 8*/ "!!------!",
+};
+
+constexpr char const * const unsigned_left_shift_results[] = {
+// 0123456
+/* 0*/ "!!!!!!!",
+/* 1*/ "!!!!!!!",
+/* 2*/ "!!++++!",
+/* 3*/ "!!+++..",
+/* 4*/ "!!++...",
+/* 5*/ ".......",
+/* 6*/ "!!----!",
+};
+
+#endif // BOOST_SAFE_NUMERICS_TEST_CHECKED_LEFT_SHIFT_HPP
+
diff --git a/src/boost/libs/safe_numerics/test/test_checked_left_shift_constexpr.cpp b/src/boost/libs/safe_numerics/test/test_checked_left_shift_constexpr.cpp
new file mode 100644
index 000000000..25da8eb6e
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_checked_left_shift_constexpr.cpp
@@ -0,0 +1,96 @@
+// Copyright (c) 2018 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/safe_numerics/checked_result.hpp>
+#include <boost/safe_numerics/checked_result_operations.hpp>
+#include <boost/safe_numerics/checked_integer.hpp>
+
+template<class T>
+constexpr bool test_checked_left_shift(
+ const T & v1,
+ const T & v2,
+ char expected_result
+){
+ using namespace boost::safe_numerics;
+ const T result = v1 << v2;
+ switch(expected_result){
+ case '.':
+ return ! result.exception();
+ case '-':
+ return safe_numerics_error::negative_overflow_error == result.m_e;
+ case '+':
+ return safe_numerics_error::positive_overflow_error == result.m_e;
+ case '!':
+ return safe_numerics_error::range_error == result.m_e;
+ case 'n': // n negative_shift
+ return safe_numerics_error::negative_shift == result.m_e;
+ case 's': // s negative_value_shift
+ return safe_numerics_error::negative_value_shift == result.m_e;
+ case 'l': // l shift_too_large
+ return safe_numerics_error::shift_too_large == result.m_e;
+ default:
+ assert(false);
+ }
+ return false;
+}
+
+#include "test_checked_left_shift.hpp"
+
+template<typename T, typename First, typename Second>
+struct test_signed_pair {
+ static const std::size_t i = First();
+ static const std::size_t j = Second();
+ // note: is constexpr really required here? compilers disagree!
+ constexpr static const bool value = test_checked_left_shift(
+ signed_values<T>[i],
+ signed_values<T>[j],
+ signed_left_shift_results[i][j]
+ );
+};
+
+template<typename T, typename First, typename Second>
+struct test_unsigned_pair {
+ static const std::size_t i = First();
+ static const std::size_t j = Second();
+ // note: is constexpr really required here? compilers disagree!
+ constexpr static const bool value = test_checked_left_shift(
+ unsigned_values<T>[i],
+ unsigned_values<T>[j],
+ unsigned_left_shift_results[i][j]
+ );
+};
+
+#include <boost/mp11/algorithm.hpp>
+
+int main(){
+ using namespace boost::mp11;
+
+ static_assert(
+ mp_all_of<
+ mp_product<
+ test_signed_pair,
+ signed_test_types,
+ signed_value_indices, signed_value_indices
+ >,
+ mp_to_bool
+ >(),
+ "all values for all signed types correctly shifted"
+ );
+
+ static_assert(
+ mp_all_of<
+ mp_product<
+ test_unsigned_pair,
+ unsigned_test_types,
+ unsigned_value_indices, unsigned_value_indices
+ >,
+ mp_to_bool
+ >(),
+ "all values for all unsigned types correctly shifted"
+ );
+
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_checked_less_than.cpp b/src/boost/libs/safe_numerics/test/test_checked_less_than.cpp
new file mode 100644
index 000000000..b0702ca21
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_checked_less_than.cpp
@@ -0,0 +1,118 @@
+// Copyright (c) 2012 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+#include <boost/logic/tribool_io.hpp>
+
+#include <boost/core/demangle.hpp>
+#include <boost/safe_numerics/checked_result_operations.hpp>
+#include <boost/safe_numerics/checked_integer.hpp>
+
+// works for both GCC and clang
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-value"
+
+// note: T should be of type checked_result<R> for some integer type R
+template<class T>
+bool test_checked_less_than(
+ T v1,
+ T v2,
+ char expected_result
+){
+ using namespace boost::safe_numerics;
+ const boost::logic::tribool result = v1 < v2;
+ std::cout
+ << std::boolalpha << v1 << " < " << v2 << " -> " << result
+ << std::endl;
+
+ switch(expected_result){
+ case '<':
+ if(result)
+ return true;
+ break;
+ case '>':
+ case '=':
+ if(!result)
+ return true;
+ break;
+ case '!':
+ if(indeterminate(result))
+ return true;
+ break;
+ }
+ std::cout
+ << "failed to detect error in addition "
+ << std::hex << result << "(" << std::dec << result << ")"
+ << " != "<< v1 << " < " << v2
+ << std::endl;
+ v1 < v2;
+ return false;
+}
+
+#pragma GCC diagnostic pop
+
+#include "test_checked_comparison.hpp"
+
+template<typename T, typename First, typename Second>
+struct test_signed_pair {
+ bool operator()() const {
+ std::size_t i = First();
+ std::size_t j = Second();
+ std::cout << std::dec << i << ',' << j << ','
+ << "testing " << boost::core::demangle(typeid(T).name()) << ' ';
+ return test_checked_less_than(
+ signed_values<T>[i],
+ signed_values<T>[j],
+ signed_comparison_results[i][j]
+ );
+ };
+};
+
+template<typename T, typename First, typename Second>
+struct test_unsigned_pair {
+ bool operator()() const {
+ std::size_t i = First();
+ std::size_t j = Second();
+ std::cout << std::dec << i << ',' << j << ','
+ << "testing " << boost::core::demangle(typeid(T).name()) << ' ';
+ return test_checked_less_than(
+ unsigned_values<T>[i],
+ unsigned_values<T>[j],
+ unsigned_comparison_results[i][j]
+ );
+ };
+};
+
+#include <boost/mp11/algorithm.hpp>
+
+int main(){
+ using namespace boost::mp11;
+ bool rval = true;
+
+ mp_for_each<
+ mp_product<
+ test_signed_pair,
+ signed_test_types,
+ signed_value_indices,
+ signed_value_indices
+ >
+ >([&](auto I){
+ rval &= I();
+ });
+
+ mp_for_each<
+ mp_product<
+ test_unsigned_pair,
+ unsigned_test_types,
+ unsigned_value_indices, unsigned_value_indices
+ >
+ >([&](auto I){
+ rval &= I();
+ });
+
+ std::cout << (rval ? "success!" : "failure") << std::endl;
+ return rval ? 0 : 1;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_checked_less_than_constexpr.cpp b/src/boost/libs/safe_numerics/test/test_checked_less_than_constexpr.cpp
new file mode 100644
index 000000000..3c9b89f3c
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_checked_less_than_constexpr.cpp
@@ -0,0 +1,93 @@
+// Copyright (c) 2018 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/safe_numerics/checked_result.hpp>
+#include <boost/safe_numerics/checked_result_operations.hpp>
+#include <boost/safe_numerics/checked_integer.hpp>
+
+// note: T should be of tyme checked_result<R> for some integer type R
+template<class T>
+constexpr bool test_checked_less_than(
+ T v1,
+ T v2,
+ char expected_result
+){
+ using namespace boost::safe_numerics;
+ const boost::logic::tribool result = v1 < v2;
+ switch(expected_result){
+ case '<':
+ if(result)
+ return true;
+ break;
+ case '>':
+ case '=':
+ if(!result)
+ return true;
+ break;
+ case '!':
+ if(indeterminate(result))
+ return true;
+ break;
+ }
+ return false;
+}
+
+#include "test_checked_comparison.hpp"
+
+template<typename T, typename First, typename Second>
+struct test_signed_pair {
+ static const std::size_t i = First();
+ static const std::size_t j = Second();
+ // note: is constexpr really required here? compilers disagree!
+ constexpr static const bool value = test_checked_less_than(
+ signed_values<T>[i],
+ signed_values<T>[j],
+ signed_comparison_results[i][j]
+ );
+};
+
+template<typename T, typename First, typename Second>
+struct test_unsigned_pair {
+ static const std::size_t i = First();
+ static const std::size_t j = Second();
+ // note: is constexpr really required here? compilers disagree!
+ constexpr static const bool value = test_checked_less_than(
+ unsigned_values<T>[i],
+ unsigned_values<T>[j],
+ unsigned_comparison_results[i][j]
+ );
+};
+
+#include <boost/mp11/algorithm.hpp>
+
+int main(){
+ using namespace boost::mp11;
+
+ static_assert(
+ mp_all_of<
+ mp_product<
+ test_signed_pair,
+ signed_test_types,
+ signed_value_indices, signed_value_indices
+ >,
+ mp_to_bool
+ >(),
+ "all values for all signed types correctly compared"
+ );
+
+ static_assert(
+ mp_all_of<
+ mp_product<
+ test_unsigned_pair,
+ unsigned_test_types,
+ unsigned_value_indices, unsigned_value_indices
+ >,
+ mp_to_bool
+ >(),
+ "all values for all unsigned types correctly compared"
+ );
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_checked_modulus.cpp b/src/boost/libs/safe_numerics/test/test_checked_modulus.cpp
new file mode 100644
index 000000000..9679ed62d
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_checked_modulus.cpp
@@ -0,0 +1,132 @@
+// Copyright (c) 2012 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+#include <boost/core/demangle.hpp>
+#include <boost/safe_numerics/checked_result_operations.hpp>
+#include <boost/safe_numerics/checked_integer.hpp>
+
+template<class T>
+bool test_checked_modulus(
+ T v1,
+ T v2,
+ char expected_result
+){
+ using namespace boost::safe_numerics;
+
+ const T result = v1 % v2;
+ std::cout
+ << v1 << " % " << v2 << " -> " << result
+ << std::endl;
+
+ switch(expected_result){
+ case '.':
+ case '0':
+ if(result.exception()){
+ std::cout
+ << "erroneously detected error in division"
+ << std::endl;
+ v1 % v2;
+ return false;
+ }
+ if(expected_result == '0'
+ && result != T(0)
+ ){
+ std::cout
+ << "failed to get expected zero result "
+ << std::endl;
+ v1 % v2;
+ return false;
+ }
+ return true;
+ case '-':
+ if(safe_numerics_error::negative_overflow_error == result.m_e)
+ return true;
+ break;
+ case '+':
+ if(safe_numerics_error::positive_overflow_error == result.m_e)
+ return true;
+ break;
+ case '!':
+ if(safe_numerics_error::range_error == result.m_e)
+ return true;
+ break;
+ }
+ std::cout
+ << "failed to detect error in modulus "
+ << std::hex << result << "(" << std::dec << result << ")"
+ << " != "<< v1 << " % " << v2
+ << std::endl;
+ v1 % v2;
+ return false;
+}
+
+#include "test_checked_modulus.hpp"
+
+template<typename T, typename First, typename Second>
+struct test_signed_pair {
+ bool operator()() const {
+ std::size_t i = First();
+ std::size_t j = Second();
+ std::cout << std::dec << i << ',' << j << ','
+ << "testing " << boost::core::demangle(typeid(T).name()) << ' ';
+ return test_checked_modulus(
+ signed_values<T>[i],
+ signed_values<T>[j],
+ signed_modulus_results[i][j]
+ );
+ };
+};
+
+template<typename T, typename First, typename Second>
+struct test_unsigned_pair {
+ bool operator()() const {
+ std::size_t i = First();
+ std::size_t j = Second();
+ std::cout << std::dec << i << ',' << j << ','
+ << "testing " << boost::core::demangle(typeid(T).name()) << ' ';
+ return test_checked_modulus(
+ unsigned_values<T>[i],
+ unsigned_values<T>[j],
+ unsigned_modulus_results[i][j]
+ );
+ };
+};
+
+#include <boost/mp11/algorithm.hpp>
+
+int main(){
+ using namespace boost::mp11;
+
+ bool rval = true;
+
+ std::cout << "*** testing signed values\n";
+ mp_for_each<
+ mp_product<
+ test_signed_pair,
+ signed_test_types,
+ signed_value_indices,
+ signed_value_indices
+ >
+ >([&](auto I){
+ rval &= I();
+ });
+
+ std::cout << "*** testing unsigned values\n";
+ mp_for_each<
+ mp_product<
+ test_unsigned_pair,
+ unsigned_test_types,
+ unsigned_value_indices, unsigned_value_indices
+ >
+ >([&](auto I){
+ rval &= I();
+ });
+
+ std::cout << (rval ? "success!" : "failure") << std::endl;
+ return rval ? 0 : 1;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_checked_modulus.hpp b/src/boost/libs/safe_numerics/test/test_checked_modulus.hpp
new file mode 100644
index 000000000..f2a818b7d
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_checked_modulus.hpp
@@ -0,0 +1,44 @@
+#ifndef BOOST_SAFE_NUMERICS_TEST_CHECKED_MODULUS_HPP
+#define BOOST_SAFE_NUMERICS_TEST_CHECKED_MODULUS_HPP
+
+// Copyright (c) 2018 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include "test_checked_values.hpp"
+
+// test result matrices
+
+// key
+// . success
+// - negative_overflow_error
+// + positive_overflow_error
+// ! range_error
+
+constexpr const char * signed_modulus_results[] = {
+// 012345678
+/* 0*/ "!!!!!!!!!",
+/* 1*/ "!!!!!!!!!",
+/* 2*/ "!!!.0!.-!",
+/* 3*/ "!!...!...",
+/* 4*/ "!!...!...",
+/* 5*/ "!!000!000",
+/* 6*/ "!!...!...",
+/* 7*/ "!!...!...",
+/* 8*/ "!!!..!.+!",
+};
+
+constexpr const char * unsigned_modulus_results[] = {
+// 0123456
+/* 0*/ "!!!!!!!",
+/* 1*/ "!!!!!!!",
+/* 2*/ "!!!.0!!",
+/* 3*/ "!!...!.",
+/* 4*/ "!!...!.",
+/* 5*/ "!!000!0",
+/* 6*/ "!!!-.!!",
+};
+
+#endif // BOOST_SAFE_NUMERICS_TEST_CHECKED_MODULUS_HPP
diff --git a/src/boost/libs/safe_numerics/test/test_checked_modulus_constexpr.cpp b/src/boost/libs/safe_numerics/test/test_checked_modulus_constexpr.cpp
new file mode 100644
index 000000000..0d480dcec
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_checked_modulus_constexpr.cpp
@@ -0,0 +1,90 @@
+// Copyright (c) 2018 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/safe_numerics/checked_result.hpp>
+#include <boost/safe_numerics/checked_result_operations.hpp>
+#include <boost/safe_numerics/checked_integer.hpp>
+
+template<class T>
+constexpr bool test_checked_modulus(
+ const T & v1,
+ const T & v2,
+ char expected_result
+){
+ using namespace boost::safe_numerics;
+ const T result = v1 % v2;
+ switch(expected_result){
+ case '0':
+ case '.':
+ return ! result.exception();
+ case '-':
+ return safe_numerics_error::negative_overflow_error == result.m_e;
+ case '+':
+ return safe_numerics_error::positive_overflow_error == result.m_e;
+ case '!':
+ return safe_numerics_error::range_error == result.m_e;
+ }
+ return false;
+}
+
+#include "test_checked_modulus.hpp"
+
+#include <boost/mp11/algorithm.hpp>
+
+template<typename T, typename First, typename Second>
+struct test_signed_pair {
+ static const std::size_t i = First();
+ static const std::size_t j = Second();
+ // note: is constexpr really required here? compilers disagree!
+ constexpr static const bool value = test_checked_modulus(
+ signed_values<T>[i],
+ signed_values<T>[j],
+ signed_modulus_results[i][j]
+ );
+};
+
+template<typename T, typename First, typename Second>
+struct test_unsigned_pair {
+ static const std::size_t i = First();
+ static const std::size_t j = Second();
+ // note: is constexpr really required here? compilers disagree!
+ constexpr static const bool value = test_checked_modulus(
+ unsigned_values<T>[i],
+ unsigned_values<T>[j],
+ unsigned_modulus_results[i][j]
+ );
+};
+
+#include <boost/mp11/algorithm.hpp>
+#include <boost/mp11/function.hpp>
+
+int main(){
+ using namespace boost::mp11;
+ static_assert(
+ mp_all_of<
+ mp_product<
+ test_signed_pair,
+ signed_test_types,
+ signed_value_indices, signed_value_indices
+ >,
+ mp_to_bool
+ >(),
+ "modulus for all signed values correct"
+ );
+
+ static_assert(
+ mp_all_of<
+ mp_product<
+ test_unsigned_pair,
+ unsigned_test_types,
+ unsigned_value_indices, unsigned_value_indices
+ >,
+ mp_to_bool
+ >(),
+ "modulus for all unsigned values correct"
+ );
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_checked_multiply.cpp b/src/boost/libs/safe_numerics/test/test_checked_multiply.cpp
new file mode 100644
index 000000000..1a964cbcb
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_checked_multiply.cpp
@@ -0,0 +1,143 @@
+// Copyright (c) 2012 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+#include <boost/core/demangle.hpp>
+#include <boost/safe_numerics/checked_result_operations.hpp>
+#include <boost/safe_numerics/checked_integer.hpp>
+
+// note: T should be of type checked_result<R> for some integer type R
+template<class T>
+bool test_checked_multiply(
+ T v1,
+ T v2,
+ char expected_result
+){
+ using namespace boost::safe_numerics;
+ const T result = v1 * v2;
+ std::cout
+ << "testing "
+ << v1 << " * " << v2 << " -> " << result
+ << std::endl;
+
+ switch(expected_result){
+ case '0':
+ case '.':
+ if(result.exception()){
+ std::cout
+ << "erroneously detected error in multiplication "
+ << std::endl;
+ v1 * v2;
+ return false;
+ }
+ if(expected_result == '0'
+ && result != T(0)
+ ){
+ std::cout
+ << "failed to get expected zero result "
+ << std::endl;
+ v1 * v2;
+ return false;
+ }
+ return true;
+ case '-':
+ if(safe_numerics_error::negative_overflow_error == result.m_e)
+ return true;
+ break;
+ case '+':
+ if(safe_numerics_error::positive_overflow_error == result.m_e)
+ return true;
+ break;
+ case '!':
+ if(safe_numerics_error::range_error == result.m_e)
+ return true;
+ break;
+ }
+ std::cout
+ << "failed to detect error in multiplication "
+ << std::hex << result << "(" << std::dec << result << ")"
+ << " != "<< v1 << " * " << v2
+ << std::endl;
+ v1 * v2;
+ return false;
+}
+
+#include "test_checked_multiply.hpp"
+
+template<typename T, typename First, typename Second>
+struct test_signed_pair {
+ bool operator()() const {
+ std::size_t i = First();
+ std::size_t j = Second();
+ std::cout << std::dec << i << ',' << j << ','
+ << "testing " << boost::core::demangle(typeid(T).name()) << ' ';
+ return test_checked_multiply(
+ signed_values<T>[i],
+ signed_values<T>[j],
+ signed_multiplication_results[i][j]
+ );
+ };
+};
+
+template<typename T, typename First, typename Second>
+struct test_unsigned_pair {
+ bool operator()() const {
+ std::size_t i = First();
+ std::size_t j = Second();
+ std::cout << std::dec << i << ',' << j << ','
+ << "testing " << boost::core::demangle(typeid(T).name()) << ' ';
+ return test_checked_multiply(
+ unsigned_values<T>[i],
+ unsigned_values<T>[j],
+ unsigned_multiplication_results[i][j]
+ );
+ };
+};
+
+#include "check_symmetry.hpp"
+
+#include <boost/mp11/algorithm.hpp>
+
+int main(int , char *[]){
+ static_assert(
+ check_symmetry(signed_multiplication_results),
+ "sanity check on test matrix - should be symmetrical"
+ );
+ static_assert(
+ check_symmetry(unsigned_multiplication_results),
+ "sanity check on test matrix - should be symmetrical"
+ );
+
+ using namespace boost::mp11;
+ bool rval = true;
+
+ mp_for_each<
+ mp_product<
+ test_signed_pair,
+ signed_test_types,
+ signed_value_indices,
+ signed_value_indices
+ >
+ >([&](auto I){
+ rval &= I();
+ });
+
+ std::cout << "*** testing unsigned values\n";
+
+ mp_for_each<
+ mp_product<
+ test_unsigned_pair,
+ unsigned_test_types,
+ unsigned_value_indices, unsigned_value_indices
+ >
+ >([&](auto I){
+ rval &= I();
+ });
+
+ std::cout << (rval ? "success!" : "failure") << std::endl;
+ return rval ? 0 : 1;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_checked_multiply.hpp b/src/boost/libs/safe_numerics/test/test_checked_multiply.hpp
new file mode 100644
index 000000000..5589f9254
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_checked_multiply.hpp
@@ -0,0 +1,44 @@
+#ifndef BOOST_SAFE_NUMERICS_TEST_CHECKED_MULTIPLY_HPP
+#define BOOST_SAFE_NUMERICS_TEST_CHECKED_MULTIPLY_HPP
+
+// Copyright (c) 2018 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include "test_checked_values.hpp"
+
+// test result matrices
+
+// key
+// . success
+// - negative_overflow_error
+// + positive_overflow_error
+// ! range_error
+
+constexpr const char * signed_multiplication_results[] = {
+// 012345678
+/* 0*/ "!!!!!!!!!",
+/* 1*/ "!!!!!!!!!",
+/* 2*/ "!!+++.---",
+/* 3*/ "!!++...--",
+/* 4*/ "!!+.....-",
+/* 5*/ "!!...0000",
+/* 6*/ "!!-..0.++",
+/* 7*/ "!!--.0+++",
+/* 8*/ "!!---0+++",
+};
+
+constexpr const char * unsigned_multiplication_results[] = {
+// 0123456
+/* 0*/ "!!!!!!!",
+/* 1*/ "!!!!!!!",
+/* 2*/ "!!+++.-",
+/* 3*/ "!!++..-",
+/* 4*/ "!!+...-",
+/* 5*/ "!!...00",
+/* 6*/ "!!---0+",
+};
+
+#endif // BOOST_SAFE_NUMERICS_TEST_CHECKED_MULTIPLY_HPP
diff --git a/src/boost/libs/safe_numerics/test/test_checked_multiply_constexpr.cpp b/src/boost/libs/safe_numerics/test/test_checked_multiply_constexpr.cpp
new file mode 100644
index 000000000..09028d7f9
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_checked_multiply_constexpr.cpp
@@ -0,0 +1,105 @@
+// Copyright (c) 2018 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/safe_numerics/checked_result.hpp>
+#include <boost/safe_numerics/checked_result_operations.hpp>
+#include <boost/safe_numerics/checked_integer.hpp>
+
+template<class T>
+constexpr bool test_checked_multiply(
+ T v1,
+ T v2,
+ char expected_result
+){
+ using namespace boost::safe_numerics;
+ const T result = v1 * v2;
+ switch(expected_result){
+ case '0':
+ case '.':
+ if(result.exception()){
+ return false;
+ }
+ if(expected_result == '0'
+ && result != T(0)
+ ){
+ return false;
+ }
+ return true;
+ case '-':
+ return safe_numerics_error::negative_overflow_error == result.m_e;
+ case '+':
+ return safe_numerics_error::positive_overflow_error == result.m_e;
+ case '!':
+ return safe_numerics_error::range_error == result.m_e;
+ }
+ return false;
+}
+
+#include "test_checked_multiply.hpp"
+
+template<typename T, typename First, typename Second>
+struct test_signed_pair {
+ static const std::size_t i = First();
+ static const std::size_t j = Second();
+ // note: is constexpr really required here? compilers disagree!
+ constexpr static const bool value = test_checked_multiply(
+ signed_values<T>[i],
+ signed_values<T>[j],
+ signed_multiplication_results[i][j]
+ );
+};
+
+template<typename T, typename First, typename Second>
+struct test_unsigned_pair {
+ static const std::size_t i = First();
+ static const std::size_t j = Second();
+ // note: is constexpr really required here? compilers disagree!
+ constexpr static const bool value = test_checked_multiply(
+ unsigned_values<T>[i],
+ unsigned_values<T>[j],
+ unsigned_multiplication_results[i][j]
+ );
+};
+
+#include "check_symmetry.hpp"
+#include <boost/mp11/algorithm.hpp>
+
+int main(){
+ static_assert(
+ check_symmetry(signed_multiplication_results),
+ "sanity check on test matrix - should be symmetrical"
+ );
+ static_assert(
+ check_symmetry(unsigned_multiplication_results),
+ "sanity check on test matrix - should be symmetrical"
+ );
+ using namespace boost::mp11;
+
+ static_assert(
+ mp_all_of<
+ mp_product<
+ test_signed_pair,
+ signed_test_types,
+ signed_value_indices, signed_value_indices
+ >,
+ mp_to_bool
+ >(),
+ "all values for all signed types correctly multiplied"
+ );
+
+ static_assert(
+ mp_all_of<
+ mp_product<
+ test_unsigned_pair,
+ unsigned_test_types,
+ unsigned_value_indices, unsigned_value_indices
+ >,
+ mp_to_bool
+ >(),
+ "all values for all unsigned types correctly multiplied"
+ );
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_checked_or.cpp b/src/boost/libs/safe_numerics/test/test_checked_or.cpp
new file mode 100644
index 000000000..df6706005
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_checked_or.cpp
@@ -0,0 +1,133 @@
+// Copyright (c) 2018 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+#include <boost/core/demangle.hpp>
+#include <boost/safe_numerics/checked_result_operations.hpp>
+#include <boost/safe_numerics/checked_integer.hpp>
+
+// note: T should be of tyme checked_result<R> for some integer type R
+template<class T>
+bool test_checked_or(
+ T v1,
+ T v2,
+ char expected_result
+){
+ using namespace boost::safe_numerics;
+ const T result = v1 | v2;
+ std::cout
+ << v1 << " | " << v2 << " -> " << result
+ << std::endl;
+
+ switch(expected_result){
+ case '.':
+ if(result.exception()){
+ std::cout
+ << "erroneously detected error in bitwise or "
+ << std::endl;
+ v1 | v2;
+ return false;
+ }
+ return true;
+ case '-':
+ if(safe_numerics_error::negative_overflow_error == result.m_e)
+ return true;
+ break;
+ case '+':
+ if(safe_numerics_error::positive_overflow_error == result.m_e)
+ return true;
+ break;
+ case '!':
+ if(safe_numerics_error::range_error == result.m_e)
+ return true;
+ break;
+ }
+ std::cout
+ << "failed to detect error in bitwise or "
+ << std::hex << result << "(" << std::dec << result << ")"
+ << " != "<< v1 << " | " << v2
+ << std::endl;
+ v1 | v2;
+ return false;
+}
+
+#include "test_checked_or.hpp"
+
+template<typename T, typename First, typename Second>
+struct test_signed_pair {
+ bool operator()() const {
+ std::size_t i = First();
+ std::size_t j = Second();
+ std::cout << std::dec << i << ',' << j << ','
+ << "testing " << boost::core::demangle(typeid(T).name()) << ' ';
+ return test_checked_or(
+ signed_values<T>[i],
+ signed_values<T>[j],
+ signed_or_results[i][j]
+ );
+ };
+};
+
+template<typename T, typename First, typename Second>
+struct test_unsigned_pair {
+ bool operator()() const {
+ std::size_t i = First();
+ std::size_t j = Second();
+ std::cout << std::dec << i << ',' << j << ','
+ << "testing " << boost::core::demangle(typeid(T).name()) << ' ';
+ return test_checked_or(
+ unsigned_values<T>[i],
+ unsigned_values<T>[j],
+ unsigned_or_results[i][j]
+ );
+ };
+};
+
+#include "check_symmetry.hpp"
+
+#include <boost/mp11/algorithm.hpp>
+
+int main(){
+ static_assert(
+ check_symmetry(signed_or_results),
+ "sanity check on test matrix - should be symmetrical"
+ );
+ static_assert(
+ check_symmetry(unsigned_or_results),
+ "sanity check on test matrix - should be symmetrical"
+ );
+
+ using namespace boost::mp11;
+ bool rval = true;
+
+ std::cout << "*** testing signed values\n";
+ mp_for_each<
+ mp_product<
+ test_signed_pair,
+ signed_test_types,
+ signed_value_indices,
+ signed_value_indices
+ >
+ >([&](auto I){
+ rval &= I();
+ });
+
+ std::cout << "*** testing unsigned values\n";
+
+ mp_for_each<
+ mp_product<
+ test_unsigned_pair,
+ unsigned_test_types,
+ unsigned_value_indices, unsigned_value_indices
+ >
+ >([&](auto I){
+ rval &= I();
+ });
+
+ std::cout << (rval ? "success!" : "failure") << std::endl;
+ return rval ? 0 : 1;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_checked_or.hpp b/src/boost/libs/safe_numerics/test/test_checked_or.hpp
new file mode 100644
index 000000000..bf415586b
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_checked_or.hpp
@@ -0,0 +1,44 @@
+#ifndef BOOST_SAFE_NUMERICS_TEST_CHECKED_OR_HPP
+#define BOOST_SAFE_NUMERICS_TEST_CHECKED_OR_HPP
+
+// Copyright (c) 2018 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include "test_checked_values.hpp"
+
+// test result matrices
+
+// key
+// . success
+// - negative_overflow_error
+// + positive_overflow_error
+// ? range_error
+
+constexpr const char * const signed_or_results[] = {
+// 012345678
+/* 0*/ "!!!!!!!!!",
+/* 1*/ "!!!!!!!!!",
+/* 2*/ "!!!!!!!!!",
+/* 3*/ "!!!.....!",
+/* 4*/ "!!!.....!",
+/* 5*/ "!!!.....!",
+/* 6*/ "!!!.....!",
+/* 7*/ "!!!.....!",
+/* 8*/ "!!!!!!!!!",
+};
+
+constexpr const char * const unsigned_or_results[] = {
+// 0123456
+/* 0*/ "!!!!!!!",
+/* 1*/ "!!!!!!!",
+/* 2*/ "!!!!!!!",
+/* 3*/ "!!!...!",
+/* 4*/ "!!!...!",
+/* 5*/ "!!!...!",
+/* 6*/ "!!!!!!!",
+};
+
+#endif // BOOST_SAFE_NUMERICS_TEST_CHECKED_OR_HPP
diff --git a/src/boost/libs/safe_numerics/test/test_checked_or_constexpr.cpp b/src/boost/libs/safe_numerics/test/test_checked_or_constexpr.cpp
new file mode 100644
index 000000000..f0c5324ee
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_checked_or_constexpr.cpp
@@ -0,0 +1,103 @@
+// Copyright (c) 2012 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/safe_numerics/checked_result.hpp>
+#include <boost/safe_numerics/checked_result_operations.hpp>
+#include <boost/safe_numerics/checked_integer.hpp>
+
+// note: T should be of tyme checked_result<R> for some integer type R
+template<class T>
+constexpr bool test_checked_or(
+ T v1,
+ T v2,
+ char expected_result
+){
+ using namespace boost::safe_numerics;
+ const T result = v1 | v2;
+ switch(expected_result){
+ case '.':
+ if(result.exception()){
+ return false;
+ }
+ return true;
+ case '-':
+ if(safe_numerics_error::negative_overflow_error == result.m_e)
+ return true;
+ case '+':
+ if(safe_numerics_error::positive_overflow_error == result.m_e)
+ return true;
+ case '!':
+ if(safe_numerics_error::range_error == result.m_e)
+ return true;
+ }
+ return false;
+}
+
+#include "test_checked_or.hpp"
+
+template<typename T, typename First, typename Second>
+struct test_signed_pair {
+ static const std::size_t i = First();
+ static const std::size_t j = Second();
+ // note: is constexpr really required here? compilers disagree!
+ constexpr static const bool value = test_checked_or(
+ signed_values<T>[i],
+ signed_values<T>[j],
+ signed_or_results[i][j]
+ );
+};
+
+template<typename T, typename First, typename Second>
+struct test_unsigned_pair {
+ static const std::size_t i = First();
+ static const std::size_t j = Second();
+ // note: is constexpr really required here? compilers disagree!
+ constexpr static const bool value = test_checked_or(
+ unsigned_values<T>[i],
+ unsigned_values<T>[j],
+ unsigned_or_results[i][j]
+ );
+};
+
+#include "check_symmetry.hpp"
+#include <boost/mp11/algorithm.hpp>
+
+int main(){
+ using namespace boost::mp11;
+ static_assert(
+ check_symmetry(signed_or_results),
+ "sanity check on test matrix - should be symmetrical"
+ );
+ static_assert(
+ check_symmetry(unsigned_or_results),
+ "sanity check on test matrix - should be symmetrical"
+ );
+
+ static_assert(
+ mp_all_of<
+ mp_product<
+ test_signed_pair,
+ signed_test_types,
+ signed_value_indices, signed_value_indices
+ >,
+ mp_to_bool
+ >(),
+ "all values for all signed types correctly or'ed"
+ );
+
+ static_assert(
+ mp_all_of<
+ mp_product<
+ test_unsigned_pair,
+ unsigned_test_types,
+ unsigned_value_indices, unsigned_value_indices
+ >,
+ mp_to_bool
+ >(),
+ "all values for all unsigned types correctly or'ed"
+ );
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_checked_right_shift.cpp b/src/boost/libs/safe_numerics/test/test_checked_right_shift.cpp
new file mode 100644
index 000000000..6d37aea98
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_checked_right_shift.cpp
@@ -0,0 +1,139 @@
+// Copyright (c) 2012 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+#include <boost/core/demangle.hpp>
+
+#include <boost/safe_numerics/checked_result.hpp>
+#include <boost/safe_numerics/checked_result_operations.hpp>
+#include <boost/safe_numerics/checked_integer.hpp>
+
+// note: T should be of tyme checked_result<R> for some integer type R
+template<class T>
+bool test_checked_right_shift(
+ T v1,
+ T v2,
+ char expected_result
+){
+ using namespace boost::safe_numerics;
+ const T result = v1 >> v2;
+ std::cout
+ << v1 << " >> " << v2 << " -> " << result
+ << std::endl;
+
+ switch(expected_result){
+ case '.':
+ if(result.exception()){
+ std::cout
+ << "erroneously detected error in right shift "
+ << std::endl;
+ v1 >> v2;
+ return false;
+ }
+ return true;
+ case '-':
+ if(safe_numerics_error::negative_overflow_error == result.m_e)
+ return true;
+ break;
+ case '+':
+ if(safe_numerics_error::positive_overflow_error == result.m_e)
+ return true;
+ break;
+ case '!':
+ if(safe_numerics_error::range_error == result.m_e)
+ return true;
+ break;
+ case 'n': // n negative_shift
+ if(safe_numerics_error::negative_shift == result.m_e)
+ return true;
+ break;
+ case 's': // s negative_value_shift
+ if(safe_numerics_error::negative_value_shift == result.m_e)
+ return true;
+ break;
+ case 'l': // l shift_too_large
+ if(safe_numerics_error::shift_too_large == result.m_e)
+ return true;
+ break;
+ default:
+ assert(false);
+ }
+ std::cout
+ << "failed to detect error in right shift "
+ << std::hex << result << "(" << std::dec << result << ")"
+ << " != "<< v1 << " >> " << v2
+ << std::endl;
+ v1 >> v2;
+ return false;
+}
+
+#include "test_checked_right_shift.hpp"
+
+template<typename T, typename First, typename Second>
+struct test_signed_pair {
+ bool operator()() const {
+ std::size_t i = First();
+ std::size_t j = Second();
+ std::cout << std::dec << i << ',' << j << ','
+ << "testing " << boost::core::demangle(typeid(T).name()) << ' ';
+ return test_checked_right_shift(
+ signed_values<T>[i],
+ signed_values<T>[j],
+ signed_right_shift_results[i][j]
+ );
+ };
+};
+
+template<typename T, typename First, typename Second>
+struct test_unsigned_pair {
+ bool operator()() const {
+ std::size_t i = First();
+ std::size_t j = Second();
+ std::cout << std::dec << i << ',' << j << ','
+ << "testing " << boost::core::demangle(typeid(T).name()) << ' ';
+ return test_checked_right_shift(
+ unsigned_values<T>[i],
+ unsigned_values<T>[j],
+ unsigned_right_shift_results[i][j]
+ );
+ };
+};
+
+#include <boost/mp11/algorithm.hpp>
+
+int main(){
+ using namespace boost::mp11;
+
+ bool rval = true;
+
+ std::cout << "*** testing signed values\n";
+
+ mp_for_each<
+ mp_product<
+ test_signed_pair,
+ signed_test_types,
+ signed_value_indices,
+ signed_value_indices
+ >
+ >([&](auto I){
+ rval &= I();
+ });
+
+ std::cout << "*** testing unsigned values\n";
+
+ mp_for_each<
+ mp_product<
+ test_unsigned_pair,
+ unsigned_test_types,
+ unsigned_value_indices, unsigned_value_indices
+ >
+ >([&](auto I){
+ rval &= I();
+ });
+
+ std::cout << (rval ? "success!" : "failure") << std::endl;
+ return rval ? 0 : 1;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_checked_right_shift.hpp b/src/boost/libs/safe_numerics/test/test_checked_right_shift.hpp
new file mode 100644
index 000000000..d5f1f9df9
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_checked_right_shift.hpp
@@ -0,0 +1,47 @@
+#ifndef BOOST_SAFE_NUMERICS_TEST_CHECKED_RIGHT_SHIFT_HPP
+#define BOOST_SAFE_NUMERICS_TEST_CHECKED_RIGHT_SHIFT_HPP
+
+// Copyright (c) 2018 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include "test_checked_values.hpp"
+
+// test result matrices
+
+// key
+// . success
+// - negative_overflow_error
+// + positive_overflow_error
+// ? range_error
+// n negative_shift, // negative value in shift operator
+// s negative_value_shift, // shift a negative value
+// l shift_too_large, // l/r shift exceeds variable size
+
+constexpr char const * const signed_right_shift_results[] = {
+// 012345678
+/* 0*/ "!!!!!!!!!",
+/* 1*/ "!!!!!!!!!",
+/* 2*/ "!!!++++++",
+/* 3*/ "!!....+++",
+/* 4*/ "!!.....++",
+/* 5*/ ".........",
+/* 6*/ "!!.....--",
+/* 7*/ "!!....---",
+/* 8*/ "!!!------",
+};
+
+constexpr char const * const unsigned_right_shift_results[] = {
+// 0123456
+/* 0*/ "!!!!!!!",
+/* 1*/ "!!!!!!!",
+/* 2*/ "!!!++++",
+/* 3*/ "!!....+",
+/* 4*/ "!!....+",
+/* 5*/ ".......",
+/* 6*/ "!!!----",
+};
+
+#endif // BOOST_SAFE_NUMERICS_TEST_CHECKED_RIGHT_SHIFT_HPP
diff --git a/src/boost/libs/safe_numerics/test/test_checked_right_shift_constexpr.cpp b/src/boost/libs/safe_numerics/test/test_checked_right_shift_constexpr.cpp
new file mode 100644
index 000000000..6e40a83b5
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_checked_right_shift_constexpr.cpp
@@ -0,0 +1,115 @@
+// Copyright (c) 2018 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+#include <boost/core/demangle.hpp>
+
+#include <boost/safe_numerics/checked_result.hpp>
+#include <boost/safe_numerics/checked_result_operations.hpp>
+#include <boost/safe_numerics/checked_integer.hpp>
+
+// note: T should be of tyme checked_result<R> for some integer type R
+template<class T>
+constexpr bool test_checked_right_shift(
+ const T & v1,
+ const T & v2,
+ char expected_result
+){
+ using namespace boost::safe_numerics;
+ const T result = v1 >> v2;
+
+ switch(expected_result){
+ case '.':
+ if(result.exception()){
+ return false;
+ }
+ return true;
+ case '-':
+ if(safe_numerics_error::negative_overflow_error == result.m_e)
+ return true;
+ break;
+ case '+':
+ if(safe_numerics_error::positive_overflow_error == result.m_e)
+ return true;
+ break;
+ case '!':
+ if(safe_numerics_error::range_error == result.m_e)
+ return true;
+ break;
+ case 'n': // n negative_shift
+ if(safe_numerics_error::negative_shift == result.m_e)
+ return true;
+ break;
+ case 's': // s negative_value_shift
+ if(safe_numerics_error::negative_value_shift == result.m_e)
+ return true;
+ break;
+ case 'l': // l shift_too_large
+ if(safe_numerics_error::shift_too_large == result.m_e)
+ return true;
+ break;
+ default:
+ assert(false);
+ }
+ return false;
+}
+
+#include "test_checked_right_shift.hpp"
+
+template<typename T, typename First, typename Second>
+struct test_signed_pair {
+ static const std::size_t i = First();
+ static const std::size_t j = Second();
+ // note: is constexpr really required here? compilers disagree!
+ constexpr static const bool value = test_checked_right_shift(
+ signed_values<T>[i],
+ signed_values<T>[j],
+ signed_right_shift_results[i][j]
+ );
+};
+
+template<typename T, typename First, typename Second>
+struct test_unsigned_pair {
+ static const std::size_t i = First();
+ static const std::size_t j = Second();
+ // note: is constexpr really required here? compilers disagree!
+ constexpr static const bool value = test_checked_right_shift(
+ unsigned_values<T>[i],
+ unsigned_values<T>[j],
+ unsigned_right_shift_results[i][j]
+ );
+};
+
+#include <boost/mp11/algorithm.hpp>
+
+int main(){
+ using namespace boost::mp11;
+
+ static_assert(
+ mp_all_of<
+ mp_product<
+ test_signed_pair,
+ signed_test_types,
+ signed_value_indices, signed_value_indices
+ >,
+ mp_to_bool
+ >(),
+ "all values for all signed types correctly right_shifted"
+ );
+
+ static_assert(
+ mp_all_of<
+ mp_product<
+ test_unsigned_pair,
+ unsigned_test_types,
+ unsigned_value_indices, unsigned_value_indices
+ >,
+ mp_to_bool
+ >(),
+ "all values for all unsigned types correctly right_shifted"
+ );
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_checked_subtract.cpp b/src/boost/libs/safe_numerics/test/test_checked_subtract.cpp
new file mode 100644
index 000000000..42794f91f
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_checked_subtract.cpp
@@ -0,0 +1,124 @@
+// Copyright (c) 2012 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+#include <boost/core/demangle.hpp>
+#include <boost/safe_numerics/checked_result_operations.hpp>
+#include <boost/safe_numerics/checked_integer.hpp>
+
+// note: T should be of tyme checked_result<R> for some integer type R
+template<class T>
+bool test_checked_subtract(
+ T v1,
+ T v2,
+ char expected_result
+){
+ using namespace boost::safe_numerics;
+ const T result = v1 - v2;
+ std::cout
+ << v1 << " - " << v2 << " -> " << result
+ << std::endl;
+
+ switch(expected_result){
+ case '.':
+ if(result.exception()){
+ std::cout
+ << "erroneously detected error in subtraction "
+ << std::endl;
+ v1 - v2;
+ return false;
+ }
+ return true;
+ case '-':
+ if(safe_numerics_error::negative_overflow_error == result.m_e)
+ return true;
+ break;
+ case '+':
+ if(safe_numerics_error::positive_overflow_error == result.m_e)
+ return true;
+ break;
+ case '!':
+ if(safe_numerics_error::range_error == result.m_e)
+ return true;
+ break;
+ }
+ std::cout
+ << "failed to detect error in subtraction "
+ << std::hex << result << "(" << std::dec << result << ")"
+ << " != "<< v1 << " - " << v2
+ << std::endl;
+ v1 - v2;
+ return false;
+}
+
+#include "test_checked_subtract.hpp"
+
+template<typename T, typename First, typename Second>
+struct test_signed_pair {
+ bool operator()() const {
+ std::size_t i = First();
+ std::size_t j = Second();
+ std::cout << std::dec << i << ',' << j << ','
+ << "testing " << boost::core::demangle(typeid(T).name()) << ' ';
+ return test_checked_subtract(
+ signed_values<T>[i],
+ signed_values<T>[j],
+ signed_subtraction_results[i][j]
+ );
+ };
+};
+
+template<typename T, typename First, typename Second>
+struct test_unsigned_pair {
+ bool operator()() const {
+ std::size_t i = First();
+ std::size_t j = Second();
+ std::cout << std::dec << i << ',' << j << ','
+ << "testing " << boost::core::demangle(typeid(T).name()) << ' ';
+ return test_checked_subtract(
+ unsigned_values<T>[i],
+ unsigned_values<T>[j],
+ unsigned_subtraction_results[i][j]
+ );
+ };
+};
+
+#include <boost/mp11/algorithm.hpp>
+
+int main(){
+ using namespace boost::mp11;
+
+ bool rval = true;
+
+ std::cout << "*** testing signed values\n";
+
+ mp_for_each<
+ mp_product<
+ test_signed_pair,
+ signed_test_types,
+ signed_value_indices,
+ signed_value_indices
+ >
+ >([&](auto I){
+ rval &= I();
+ });
+
+ std::cout << "*** testing unsigned values\n";
+
+ mp_for_each<
+ mp_product<
+ test_unsigned_pair,
+ unsigned_test_types,
+ unsigned_value_indices, unsigned_value_indices
+ >
+ >([&](auto I){
+ rval &= I();
+ });
+
+ std::cout << (rval ? "success!" : "failure") << std::endl;
+ return rval ? 0 : 1;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_checked_subtract.hpp b/src/boost/libs/safe_numerics/test/test_checked_subtract.hpp
new file mode 100644
index 000000000..23136f60f
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_checked_subtract.hpp
@@ -0,0 +1,44 @@
+#ifndef BOOST_SAFE_NUMERICS_TEST_CHECKED_AND_HPP
+#define BOOST_SAFE_NUMERICS_TEST_CHECKED_AND_HPP
+
+// Copyright (c) 2018 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include "test_checked_values.hpp"
+
+// test result matrices
+
+// key
+// . success
+// - negative_overflow_error
+// + positive_overflow_error
+// ? range_error
+
+constexpr const char * signed_subtraction_results[] = {
+// 012345678
+/* 0*/ "!!!!!!!!!",
+/* 1*/ "!!!!!!!!!",
+/* 2*/ "!!!++++++",
+/* 3*/ "!!-...+++",
+/* 4*/ "!!-....++",
+/* 5*/ "!!-....++",
+/* 6*/ "!!-.....+",
+/* 7*/ "!!---...+",
+/* 8*/ "!!------!",
+};
+
+constexpr const char * unsigned_subtraction_results[] = {
+// 0123456
+/* 0*/ "!!!!!!!",
+/* 1*/ "!!!!!!!",
+/* 2*/ "!!!++++",
+/* 3*/ "!!-...+",
+/* 4*/ "!!--..+",
+/* 5*/ "!!---.+",
+/* 6*/ "!!----!",
+};
+
+#endif // BOOST_SAFE_NUMERICS_TEST_CHECKED_AND_HPP
diff --git a/src/boost/libs/safe_numerics/test/test_checked_subtract_constexpr.cpp b/src/boost/libs/safe_numerics/test/test_checked_subtract_constexpr.cpp
new file mode 100644
index 000000000..4d8ba6a86
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_checked_subtract_constexpr.cpp
@@ -0,0 +1,94 @@
+// Copyright (c) 2012 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/safe_numerics/checked_result.hpp>
+#include <boost/safe_numerics/checked_result_operations.hpp>
+#include <boost/safe_numerics/checked_integer.hpp>
+
+// note: T should be of tyme checked_result<R> for some integer type R
+template<class T>
+constexpr bool test_checked_subtract(
+ const T & v1,
+ const T & v2,
+ char expected_result
+){
+ using namespace boost::safe_numerics;
+ const T result = v1 - v2;
+ switch(expected_result){
+ case '.':
+ if(result.exception()){
+ return false;
+ }
+ return true;
+ case '-':
+ if(safe_numerics_error::negative_overflow_error == result.m_e)
+ return true;
+ case '+':
+ if(safe_numerics_error::positive_overflow_error == result.m_e)
+ return true;
+ case '!':
+ if(safe_numerics_error::range_error == result.m_e)
+ return true;
+ }
+ return false;
+}
+
+#include "test_checked_subtract.hpp"
+
+template<typename T, typename First, typename Second>
+struct test_signed_pair {
+ static const std::size_t i = First();
+ static const std::size_t j = Second();
+ // note: is constexpr really required here? compilers disagree!
+ constexpr static const bool value = test_checked_subtract(
+ signed_values<T>[i],
+ signed_values<T>[j],
+ signed_subtraction_results[i][j]
+ );
+};
+
+template<typename T, typename First, typename Second>
+struct test_unsigned_pair {
+ static const std::size_t i = First();
+ static const std::size_t j = Second();
+ // note: is constexpr really required here? compilers disagree!
+ constexpr static const bool value = test_checked_subtract(
+ unsigned_values<T>[i],
+ unsigned_values<T>[j],
+ unsigned_subtraction_results[i][j]
+ );
+};
+
+#include <boost/mp11/algorithm.hpp>
+
+int main(){
+ using namespace boost::mp11;
+
+ static_assert(
+ mp_all_of<
+ mp_product<
+ test_signed_pair,
+ signed_test_types,
+ signed_value_indices, signed_value_indices
+ >,
+ mp_to_bool
+ >(),
+ "all values for all signed types correctly subtracted"
+ );
+
+ static_assert(
+ mp_all_of<
+ mp_product<
+ test_unsigned_pair,
+ unsigned_test_types,
+ unsigned_value_indices, unsigned_value_indices
+ >,
+ mp_to_bool
+ >(),
+ "all values for all unsigned types correctly subtracted"
+ );
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_checked_values.hpp b/src/boost/libs/safe_numerics/test/test_checked_values.hpp
new file mode 100644
index 000000000..957db559a
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_checked_values.hpp
@@ -0,0 +1,57 @@
+#ifndef BOOST_SAFE_NUMERICS_TEST_CHECKED_VALUES_HPP
+#define BOOST_SAFE_NUMERICS_TEST_CHECKED_VALUES_HPP
+
+// Copyright (c) 2018 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/safe_numerics/checked_result.hpp>
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/algorithm.hpp>
+
+// values
+// note: In theory explicity specifying the number of elements in the
+// array should not be necessary. However, this seems to crash the CLang
+// compilers with standards setting of C++17. So don't remove the array
+// bounds below
+template<typename T>
+constexpr const boost::safe_numerics::checked_result<T> signed_values[9] = {
+ boost::safe_numerics::safe_numerics_error::range_error,
+ boost::safe_numerics::safe_numerics_error::domain_error,
+ boost::safe_numerics::safe_numerics_error::positive_overflow_error,
+ std::numeric_limits<T>::max(),
+ 1,
+ 0,
+ -1,
+ std::numeric_limits<T>::lowest(),
+ boost::safe_numerics::safe_numerics_error::negative_overflow_error,
+};
+
+using signed_test_types = boost::mp11::mp_list<
+ std::int8_t, std::int16_t, std::int32_t, std::int64_t
+>;
+using signed_value_indices = boost::mp11::mp_iota_c<
+ sizeof(signed_values<int>) / sizeof(signed_values<int>[0])
+>;
+
+template<typename T>
+constexpr const boost::safe_numerics::checked_result<T> unsigned_values[7] = {
+ boost::safe_numerics::safe_numerics_error::range_error,
+ boost::safe_numerics::safe_numerics_error::domain_error,
+ boost::safe_numerics::safe_numerics_error::positive_overflow_error,
+ std::numeric_limits<T>::max(),
+ 1,
+ 0,
+ boost::safe_numerics::safe_numerics_error::negative_overflow_error,
+};
+
+using unsigned_test_types = boost::mp11::mp_list<
+ std::uint8_t, std::uint16_t, std::uint32_t, std::uint64_t
+>;
+using unsigned_value_indices = boost::mp11::mp_iota_c<
+ sizeof(unsigned_values<int>) / sizeof(unsigned_values<int>[0])
+>;
+
+#endif // BOOST_SAFE_NUMERICS_TEST_CHECKED_VALUES_HPP
diff --git a/src/boost/libs/safe_numerics/test/test_checked_xor.cpp b/src/boost/libs/safe_numerics/test/test_checked_xor.cpp
new file mode 100644
index 000000000..7fffd5f8d
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_checked_xor.cpp
@@ -0,0 +1,134 @@
+// Copyright (c) 2012 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+#include <boost/core/demangle.hpp>
+#include <boost/safe_numerics/checked_result_operations.hpp>
+#include <boost/safe_numerics/checked_integer.hpp>
+
+// note: T should be of tyme checked_result<R> for some integer type R
+template<class T>
+bool test_checked_xor(
+ T v1,
+ T v2,
+ char expected_result
+){
+ using namespace boost::safe_numerics;
+ const T result = v1 ^ v2;
+ std::cout
+ << v1 << " ^ " << v2 << " -> " << result
+ << std::endl;
+
+ switch(expected_result){
+ case '.':
+ if(result.exception()){
+ std::cout
+ << "erroneously detected error in exclusive or "
+ << std::endl;
+ v1 ^ v2;
+ return false;
+ }
+ return true;
+ case '-':
+ if(safe_numerics_error::negative_overflow_error == result.m_e)
+ return true;
+ break;
+ case '+':
+ if(safe_numerics_error::positive_overflow_error == result.m_e)
+ return true;
+ break;
+ case '!':
+ if(safe_numerics_error::range_error == result.m_e)
+ return true;
+ break;
+ }
+ std::cout
+ << "failed to detect error in exclusive or "
+ << std::hex << result << "(" << std::dec << result << ")"
+ << " != "<< v1 << " ^ " << v2
+ << std::endl;
+ v1 ^ v2;
+ return false;
+}
+
+#include "test_checked_xor.hpp"
+
+template<typename T, typename First, typename Second>
+struct test_signed_pair {
+ bool operator()() const {
+ std::size_t i = First();
+ std::size_t j = Second();
+ std::cout << std::dec << i << ',' << j << ','
+ << "testing " << boost::core::demangle(typeid(T).name()) << ' ';
+ return test_checked_xor(
+ signed_values<T>[i],
+ signed_values<T>[j],
+ signed_xor_results[i][j]
+ );
+ };
+};
+
+template<typename T, typename First, typename Second>
+struct test_unsigned_pair {
+ bool operator()() const {
+ std::size_t i = First();
+ std::size_t j = Second();
+ std::cout << std::dec << i << ',' << j << ','
+ << "testing " << boost::core::demangle(typeid(T).name()) << ' ';
+ return test_checked_xor(
+ unsigned_values<T>[i],
+ unsigned_values<T>[j],
+ unsigned_xor_results[i][j]
+ );
+ };
+};
+
+#include "check_symmetry.hpp"
+
+#include <boost/mp11/algorithm.hpp>
+
+int main(){
+ static_assert(
+ check_symmetry(signed_xor_results),
+ "sanity check on test matrix - should be symmetrical"
+ );
+ static_assert(
+ check_symmetry(unsigned_xor_results),
+ "sanity check on test matrix - should be symmetrical"
+ );
+
+ using namespace boost::mp11;
+ bool rval = true;
+
+ std::cout << "*** testing signed values\n";
+
+ mp_for_each<
+ mp_product<
+ test_signed_pair,
+ signed_test_types,
+ signed_value_indices,
+ signed_value_indices
+ >
+ >([&](auto I){
+ rval &= I();
+ });
+
+ std::cout << "*** testing unsigned values\n";
+
+ mp_for_each<
+ mp_product<
+ test_unsigned_pair,
+ unsigned_test_types,
+ unsigned_value_indices, unsigned_value_indices
+ >
+ >([&](auto I){
+ rval &= I();
+ });
+
+ std::cout << (rval ? "success!" : "failure") << std::endl;
+ return rval ? 0 : 1;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_checked_xor.hpp b/src/boost/libs/safe_numerics/test/test_checked_xor.hpp
new file mode 100644
index 000000000..004ba94c4
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_checked_xor.hpp
@@ -0,0 +1,44 @@
+#ifndef BOOST_SAFE_NUMERICS_TEST_CHECKED_XOR_HPP
+#define BOOST_SAFE_NUMERICS_TEST_CHECKED_XOR_HPP
+
+// Copyright (c) 2018 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include "test_checked_values.hpp"
+
+// test result matrices
+
+// key
+// . success
+// - negative_overflow_error
+// + positive_overflow_error
+// ? range_error
+
+constexpr const char * const signed_xor_results[] = {
+// 012345678
+/* 0*/ "!!!!!!!!!",
+/* 1*/ "!!!!!!!!!",
+/* 2*/ "!!!!!!!!!",
+/* 3*/ "!!!.....!",
+/* 4*/ "!!!.....!",
+/* 5*/ "!!!.....!",
+/* 6*/ "!!!.....!",
+/* 7*/ "!!!.....!",
+/* 8*/ "!!!!!!!!!",
+};
+
+constexpr const char * const unsigned_xor_results[] = {
+// 0123456
+/* 0*/ "!!!!!!!",
+/* 1*/ "!!!!!!!",
+/* 2*/ "!!!!!!!",
+/* 3*/ "!!!...!",
+/* 4*/ "!!!...!",
+/* 5*/ "!!!...!",
+/* 6*/ "!!!!!!!",
+};
+
+#endif // BOOST_SAFE_NUMERICS_TEST_CHECKED_XOR_HPP
diff --git a/src/boost/libs/safe_numerics/test/test_checked_xor_constexpr.cpp b/src/boost/libs/safe_numerics/test/test_checked_xor_constexpr.cpp
new file mode 100644
index 000000000..466208d75
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_checked_xor_constexpr.cpp
@@ -0,0 +1,107 @@
+// Copyright (c) 2018 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+#include <boost/core/demangle.hpp>
+#include <boost/safe_numerics/checked_result_operations.hpp>
+#include <boost/safe_numerics/checked_integer.hpp>
+
+// note: T should be of tyme checked_result<R> for some integer type R
+template<class T>
+constexpr bool test_checked_xor(
+ const T & v1,
+ const T & v2,
+ char expected_result
+){
+ using namespace boost::safe_numerics;
+ const T result = v1 ^ v2;
+
+ switch(expected_result){
+ case '.':
+ if(result.exception()){
+ return false;
+ }
+ return true;
+ case '-':
+ if(safe_numerics_error::negative_overflow_error == result.m_e)
+ return true;
+ case '+':
+ if(safe_numerics_error::positive_overflow_error == result.m_e)
+ return true;
+ case '!':
+ if(safe_numerics_error::range_error == result.m_e)
+ return true;
+ }
+ return false;
+}
+
+#include "test_checked_xor.hpp"
+
+template<typename T, typename First, typename Second>
+struct test_signed_pair {
+ static const std::size_t i = First();
+ static const std::size_t j = Second();
+ static const bool value = test_checked_xor(
+ signed_values<T>[i],
+ signed_values<T>[j],
+ signed_xor_results[i][j]
+ );
+};
+
+template<typename T, typename First, typename Second>
+struct test_unsigned_pair {
+ static const std::size_t i = First();
+ static const std::size_t j = Second();
+ // note: is constexpr really required here? compilers disagree!
+ constexpr static const bool value = test_checked_xor(
+ unsigned_values<T>[i],
+ unsigned_values<T>[j],
+ unsigned_xor_results[i][j]
+ );
+};
+
+#include "check_symmetry.hpp"
+#include <boost/mp11/algorithm.hpp>
+
+int main(){
+ static_assert(
+ check_symmetry(signed_xor_results),
+ "sanity check on test matrix - should be symmetrical"
+ );
+ static_assert(
+ check_symmetry(unsigned_xor_results),
+ "sanity check on test matrix - should be symmetrical"
+ );
+
+ using namespace boost::mp11;
+
+ static_assert(
+ mp_all_of<
+ mp_product<
+ test_signed_pair,
+ signed_test_types,
+ signed_value_indices, signed_value_indices
+ >,
+ mp_to_bool
+ >(),
+ "all values for all signed types correctly xor'ed"
+ );
+
+ static_assert(
+ mp_all_of<
+ mp_product<
+ test_unsigned_pair,
+ unsigned_test_types,
+ unsigned_value_indices, unsigned_value_indices
+ >,
+ mp_to_bool
+ >(),
+ "all values for all unsigned types correctly xor'ed"
+ );
+
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_compare_automatic.hpp b/src/boost/libs/safe_numerics/test/test_compare_automatic.hpp
new file mode 100644
index 000000000..52d677cea
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_compare_automatic.hpp
@@ -0,0 +1,56 @@
+// Copyright (c) 2018 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#pragma once
+
+#include "test_values.hpp"
+
+constexpr const char *test_compare_automatic_result[
+ boost::mp11::mp_size<test_values>::value
+] = {
+// 0 0 0 0
+// 012345670123456701234567012345670
+// 012345678901234567890123456789012
+/* 0*/ "=<>>=<>>=<>>=<>>=<<<=<<<=<<<=<xx>",
+/* 1*/ ">=>>><>>><>>><>>>=<<><<<><<<><xx>",
+/* 2*/ "<<=<<<><<<><<<><<<<<<<<<<<<<<<xx<",
+/* 3*/ "<<>=<<>=<<>=<<>=<<<<<<<<<<<<<<xx<",
+/* 4*/ "=<>>=<>>=<>>=<>>=<<<=<<<=<<<=<xx>",
+/* 5*/ ">>>>>=>>><>>><>>>>>>>=<<><<<><xx>",
+/* 6*/ "<<<<<<=<<<><<<><<<<<<<<<<<<<<<xx<",
+/* 7*/ "<<>=<<>=<<>=<<>=<<<<<<<<<<<<<<xx<",
+
+/* 8*/ "=<>>=<>>=<>>=<>>=<<<=<<<=<<<=<xx>",
+/* 9*/ ">>>>>>>>>=>>><>>>>>>>>>>>=<<><xx>",
+/*10*/ "<<<<<<<<<<=<<<><<<<<<<<<<<<<<<xx<",
+/*11*/ "<<>=<<>=<<>=<<>=<<<<<<<<<<<<<<xx<",
+/*12*/ "=<>>=<>>=<>>=<>>=<<<=<<<=<<<=<xx>",
+/*13*/ ">>>>>>>>>>>>>=>>>>>>>>>>>>>>>=xx>",
+/*14*/ "<<<<<<<<<<<<<<=<<<<<<<<<<<<<<<xx<",
+/*15*/ "<<>=<<>=<<>=<<>=<<<<<<<<<<<<<<xx<",
+
+// 0 0 0 0
+// 012345670123456701234567012345670
+// 012345678901234567890123456789012
+/*16*/ "=<>>=<>>=<>>=<>>=<<<=<<<=<<<=<<<>",
+/*17*/ ">=>>><>>><>>><>>>=<<><<<><<<><<<>",
+/*18*/ ">>>>><>>><>>><>>>>=<><<<><<<><<<>",
+/*19*/ ">>>>><>>><>>><>>>>>=><<<><<<><<<>",
+/*20*/ "=<>>=<>>=<>>=<>>=<<<=<<<=<<<=<<<>",
+/*21*/ ">>>>>=>>><>>><>>>>>>>=<<><<<><<<>",
+/*22*/ ">>>>>>>>><>>><>>>>>>>>=<><<<><<<>",
+/*23*/ ">>>>>>>>><>>><>>>>>>>>>=><<<><<<>",
+
+/*24*/ "=<>>=<>>=<>>=<>>=<<<=<<<=<<<=<<<>",
+/*25*/ ">>>>>>>>>=>>><>>>>>>>>>>>=<<><<<>",
+/*26*/ ">>>>>>>>>>>>><>>>>>>>>>>>>=<><<<>",
+/*27*/ ">>>>>>>>>>>>><>>>>>>>>>>>>>=><<<>",
+/*28*/ "=<>>=<>>=<>>=<>>=<<<=<<<=<<<=<<<>",
+/*29*/ ">>>>>>>>>>>>>=>>>>>>>>>>>>>>>=<<>",
+/*30*/ "xxxxxxxxxxxxxxxx>>>>>>>>>>>>>>=<x",
+/*31*/ "xxxxxxxxxxxxxxxx>>>>>>>>>>>>>>>=x",
+/*32*/ "<<>><<>><<>><<>><<<<<<<<<<<<<<xx="
+};
diff --git a/src/boost/libs/safe_numerics/test/test_compare_native.hpp b/src/boost/libs/safe_numerics/test/test_compare_native.hpp
new file mode 100644
index 000000000..2b55dab99
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_compare_native.hpp
@@ -0,0 +1,48 @@
+#include "test_values.hpp"
+
+constexpr const char *test_compare_native_result[
+ boost::mp11::mp_size<test_values>::value
+] = {
+// 0 0 0 0
+// 012345670123456701234567012345670
+// 012345678901234567890123456789012
+/* 0*/ "=<>>=<>>=<>>=<>>=<<<=<<<=<<<=<<<>",
+/* 1*/ ">=>>><>>><>>><>>>=<<><<<><<<><<<>",
+/* 2*/ "<<=<<<><<<><<<><<<<<<<<<xxxxxxxx<",
+/* 3*/ "<<>=<<>=<<>=<<>=<<<<<<<<xxxxxxxx<",
+/* 4*/ "=<>>=<>>=<>>=<>>=<<<=<<<=<<<=<<<>",
+/* 5*/ ">>>>>=>>><>>><>>>>>>>=<<><<<><<<>",
+/* 6*/ "<<<<<<=<<<><<<><<<<<<<<<xxxxxxxx<",
+/* 7*/ "<<>=<<>=<<>=<<>=<<<<<<<<xxxxxxxx<",
+
+/* 8*/ "=<>>=<>>=<>>=<>>=<<<=<<<=<<<=<<<>",
+/* 9*/ ">>>>>>>>>=>>><>>>>>>>>>>>=<<><<<>",
+/*10*/ "<<<<<<<<<<=<<<><<<<<<<<<xxxxxxxx<",
+/*11*/ "<<>=<<>=<<>=<<>=<<<<<<<<xxxxxxxx<",
+/*12*/ "=<>>=<>>=<>>=<>>=<<<=<<<=<<<=<<<>",
+/*13*/ ">>>>>>>>>>>>>=>>>>>>>>>>>>>>>=<<>",
+/*14*/ "<<<<<<<<<<<<<<=<<<<<<<<<<<<<xxxx<",
+/*15*/ "<<>=<<>=<<>=<<>=<<<<<<<<<<<<xxxx<",
+
+// 0 0 0 0
+// 012345670123456701234567012345670
+// 012345678901234567890123456789012
+/*16*/ "=<>>=<>>=<>>=<>>=<<<=<<<=<<<=<<<>",
+/*17*/ ">=>>><>>><>>><>>>=<<><<<><<<><<<>",
+/*18*/ ">>>>><>>><>>><>>>>=<><<<><<<><<<>",
+/*19*/ ">>>>><>>><>>><>>>>>=><<<><<<><<<>",
+/*20*/ "=<>>=<>>=<>>=<>>=<<<=<<<=<<<=<<<>",
+/*21*/ ">>>>>=>>><>>><>>>>>>>=<<><<<><<<>",
+/*22*/ ">>>>>>>>><>>><>>>>>>>>=<><<<><<<>",
+/*23*/ ">>>>>>>>><>>><>>>>>>>>>=><<<><<<>",
+
+/*24*/ "=<xx=<xx=<xx=<>>=<<<=<<<=<<<=<<<>",
+/*25*/ ">>xx>>xx>=xx><>>>>>>>>>>>=<<><<<>",
+/*26*/ ">>xx>>xx>>xx><>>>>>>>>>>>>=<><<<>",
+/*27*/ ">>xx>>xx>>xx><>>>>>>>>>>>>>=><<<>",
+/*28*/ "=<xx=<xx=<xx=<xx=<<<=<<<=<<<=<<<>",
+/*29*/ ">>xx>>xx>>xx>=xx>>>>>>>>>>>>>=<<>",
+/*30*/ ">>xx>>xx>>xx>>xx>>>>>>>>>>>>>>=<>",
+/*31*/ ">>xx>>xx>>xx>>xx>>>>>>>>>>>>>>>=>",
+/*32*/ "<<>><<>><<>><<>><<<<<<<<<<<<<<<<="
+};
diff --git a/src/boost/libs/safe_numerics/test/test_constexpr.cpp b/src/boost/libs/safe_numerics/test/test_constexpr.cpp
new file mode 100644
index 000000000..30bf18f68
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_constexpr.cpp
@@ -0,0 +1,64 @@
+// Copyright (c) 2014 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// Test constexpr operations on literals
+
+#include <iostream>
+
+#include <boost/safe_numerics/safe_integer_literal.hpp>
+#include <boost/safe_numerics/native.hpp>
+#include <boost/safe_numerics/exception.hpp>
+
+using namespace boost::safe_numerics;
+
+template<std::uintmax_t N>
+using compile_time_value = safe_unsigned_literal<N, native, loose_trap_policy>;
+
+int main(){
+ constexpr const compile_time_value<1000> x;
+ constexpr const compile_time_value<1> y;
+
+ // should compile and execute without problem
+ std::cout << x << '\n';
+
+ // all the following statements should compile
+ constexpr auto x_plus_y = x + y;
+ static_assert(1001 == x_plus_y, "1001 == x + y");
+
+ constexpr auto x_minus_y = x - y;
+ static_assert(999 == x_minus_y, "999 == x - y");
+
+ constexpr auto x_times_y = x * y;
+ static_assert(1000 == x_times_y, "1000 == x * y");
+
+ constexpr auto x_and_y = x & y;
+ static_assert(0 == x_and_y, "0 == x & y");
+
+ constexpr auto x_or_y = x | y;
+ static_assert(1001 == x_or_y, "1001 == x | y");
+
+ constexpr auto x_xor_y = x ^ y;
+ static_assert(1001 == x_xor_y, "1001 == x ^ y");
+
+ constexpr auto x_divided_by_y = x / y;
+ static_assert(1000 == x_divided_by_y, "1000 == x / y");
+
+ constexpr auto x_mod_y = x % y;
+ static_assert(0 == x_mod_y, "0 == x % y");
+
+ // this should fail compilation since a positive unsigned number
+ // can't be converted to a negative value of the same type
+ constexpr auto minus_x = -x;
+
+ // should compile OK since the negative inverse of a zero is still zero
+ constexpr const compile_time_value<0> x0;
+ constexpr auto minus_x0 = -x0; // should compile OK
+ static_assert(0 == minus_x0, "0 == -x where x == 0");
+
+ constexpr auto not_x = ~x;
+
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_construction.cpp b/src/boost/libs/safe_numerics/test/test_construction.cpp
new file mode 100644
index 000000000..68ad43ef6
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_construction.cpp
@@ -0,0 +1,172 @@
+// Copyright (c) 2012 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// test constructors
+
+#include <iostream>
+
+#include <boost/safe_numerics/safe_compare.hpp>
+#include <boost/safe_numerics/safe_integer.hpp>
+
+template<class T2, class T1>
+bool test_construction(T1 t1, const char *t2_name, const char *t1_name){
+ using namespace boost::safe_numerics;
+ std::cout
+ << "testing constructions to " << t2_name << " from " << t1_name
+ << std::endl;
+ {
+ /* (1) test construction of safe<T1> from T1 type */
+ try{
+ safe<T1> s1(t1);
+ // should always arrive here!
+ }
+ catch(const std::exception &){
+ // should never, ever arrive here
+ std::cout
+ << "erroneously detected error in construction "
+ << "safe<" << t1_name << "> (" << t1_name << ")"
+ << std::endl;
+ try{
+ safe<T1> s1(t1); // try again for debugging
+ }
+ catch(const std::exception &){}
+ return false;
+ }
+ }
+ {
+ /* (2) test construction of safe<T2> from T1 type */
+ T2 t2;
+ try{
+ t2 = safe<T2>(t1);
+ if(! safe_compare::equal(t2 , t1)){
+ std::cout
+ << "failed to detect error in construction "
+ << "safe<" << t2_name << "> (" << t1_name << ")"
+ << std::endl;
+ safe<T2> s2x(t1);
+ return false;
+ }
+ }
+ catch(const std::exception &){
+ if(safe_compare::equal(t2, t1)){
+ std::cout
+ << "erroneously detected error in construction "
+ << "safe<" << t2_name << "> (" << t1_name << ")"
+ << std::endl;
+ try{
+ safe<T2> sx2(t1); // try again for debugging
+ }
+ catch(const std::exception &){}
+ return false;
+ }
+ }
+ }
+ {
+ /* (3) test construction of safe<T1> from safe<T1> type */
+ safe<T1> s1x(t1);
+ try{
+ safe<T1> s1(s1x);
+ if(! (s1 == s1x)){
+ std::cout
+ << "copy constructor altered value "
+ << "safe<" << t1_name << "> (safe<" << t1_name << ">(" << t1 << "))"
+ << std::endl;
+ //safe<T1> s1(s1x);
+ return false;
+ }
+ }
+ catch(const std::exception &){
+ // should never arrive here
+ std::cout
+ << "erroneously detected error in construction "
+ << "safe<" << t1_name << "> (safe<" << t1_name << ">(" << t1 << "))"
+ << std::endl;
+ try{
+ safe<T1> s1(t1);
+ }
+ catch(const std::exception &){}
+ return false;
+ }
+ }
+ {
+ /* (4) test construction of safe<T2> from safe<T1> type */
+ T2 t2;
+ try{
+ safe<T1> s1(t1);
+ safe<T2> s2(s1);
+ t2 = static_cast<T2>(s2);
+ if(! (safe_compare::equal(t1, t2))){
+ std::cout
+ << "failed to detect error in construction "
+ << "safe<" << t1_name << "> (safe<" << t2_name << ">(" << t1 << "))"
+ << std::endl;
+ safe<T2> s1x(t1);
+ return false;
+ }
+ }
+ catch(const std::exception &){
+ if(safe_compare::equal(t1, t2)){
+ std::cout
+ << "erroneously detected error in construction "
+ << "safe<" << t2_name << "> (safe<" << t1_name << ">(" << t1 << "))"
+ << std::endl;
+ try{
+ safe<T2> s1(t1);
+ }
+ catch(const std::exception &){}
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+#include <boost/mp11/algorithm.hpp>
+#include <boost/core/demangle.hpp>
+#include "test_values.hpp"
+
+using namespace boost::mp11;
+
+struct test {
+ bool m_error;
+ test(bool b = true) : m_error(b) {}
+ operator bool(){
+ return m_error;
+ }
+ template<typename T>
+ void operator()(const T &){
+ static_assert(mp_is_list<T>(), "must be a list of two types");
+ using T1 = mp_first<T>; // first element is a type
+ // second element is an integral constant
+ using T2 = typename mp_second<T>::value_type; // get it's type
+ constexpr T2 v2 = mp_second<T>(); // get it's value
+ m_error &= test_construction<T1>(
+ v2,
+ boost::core::demangle(typeid(T1).name()).c_str(),
+ boost::core::demangle(typeid(T2).name()).c_str()
+ );
+ }
+};
+
+template<typename T>
+using extract_value_type = typename T::value_type;
+using test_types = mp_unique<
+ mp_transform<
+ extract_value_type,
+ test_values
+ >
+>;
+
+int main(){
+ test rval(true);
+
+ mp_for_each<
+ mp_product<mp_list, test_types, test_values>
+ >(rval);
+
+ std::cout << (rval ? "success!" : "failure") << std::endl;
+ return ! rval ;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_cpp.cpp b/src/boost/libs/safe_numerics/test/test_cpp.cpp
new file mode 100644
index 000000000..c9869c15d
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_cpp.cpp
@@ -0,0 +1,36 @@
+// Copyright (c) 2018 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/integer.hpp>
+#include <boost/safe_numerics/utility.hpp>
+
+// include headers to support safe integers
+#include <boost/safe_numerics/cpp.hpp>
+
+using promotion_policy = boost::safe_numerics::cpp<
+ 8, // char 8 bits
+ 16, // short 16 bits
+ 16, // int 16 bits
+ 16, // long 32 bits
+ 32 // long long 32 bits
+>;
+
+template<typename R, typename T, typename U>
+struct test {
+ using ResultType = promotion_policy::result_type<T,U>;
+ //boost::safe_numerics::utility::print_type<ResultType> pt;
+ static_assert(
+ std::is_same<R, ResultType>::value,
+ "is_same<R, ResultType>"
+ );
+};
+
+test<std::uint16_t, std::uint8_t, std::uint8_t> t1;
+
+int main(){
+ return 0;
+}
+
diff --git a/src/boost/libs/safe_numerics/test/test_divide.hpp b/src/boost/libs/safe_numerics/test/test_divide.hpp
new file mode 100644
index 000000000..93c53cc36
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_divide.hpp
@@ -0,0 +1,137 @@
+#ifndef BOOST_TEST_DIVIDE_HPP
+#define BOOST_TEST_DIVIDE_HPP
+
+// Copyright (c) 2015 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+#include <boost/core/demangle.hpp>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/range_value.hpp>
+
+template<class T1, class T2>
+bool test_divide(
+ T1 v1,
+ T2 v2,
+ const char *av1,
+ const char *av2,
+ char expected_result
+){
+ {
+ safe_t<T1> t1 = v1;
+ using result_type = decltype(t1 / v2);
+ std::cout
+ << "safe<" << av1 << "> / " << av2 << " -> "
+ << boost::core::demangle(typeid(result_type).name()) << '\n';
+ static_assert(
+ boost::safe_numerics::is_safe<safe_t<T1> >::value,
+ "safe_t not safe!"
+ );
+ static_assert(
+ boost::safe_numerics::is_safe<result_type>::value,
+ "Expression failed to return safe type"
+ );
+
+ try{
+ // use auto to avoid checking assignment.
+ auto result = t1 / v2;
+ std::cout << make_result_display(result);
+ if(expected_result == 'x'){
+ std::cout << " *** failed to detect error in division" << std::endl;
+ t1 / v2;
+ return false;
+ }
+ std::cout << std::endl;
+ }
+ catch(const std::exception &){
+ if(expected_result == '.'){
+ std::cout << " *** erroneously detected error in division" << std::endl;
+ try{
+ t1 / v2;
+ }
+ catch(const std::exception &){}
+ return false;
+ }
+ }
+ }
+ {
+ safe_t<T2> t2 = v2;
+ using result_type = decltype(v1 / t2);
+ std::cout
+ << "safe<" << av1 << "> / " << av2 << " -> "
+ << boost::core::demangle(typeid(result_type).name()) << '\n';
+
+ static_assert(
+ boost::safe_numerics::is_safe<safe_t<T2> >::value,
+ "safe_t not safe!"
+ );
+ static_assert(
+ boost::safe_numerics::is_safe<result_type>::value,
+ "Expression failed to return safe type"
+ );
+ try{
+ // use auto to avoid checking assignment.
+ auto result = v1 / t2;
+ std::cout << make_result_display(result);
+ if(expected_result == 'x'){
+ std::cout << " *** failed to detect error in division " << std::endl;
+ v1 / t2;
+ return false;
+ }
+ std::cout << std::endl;
+ }
+ catch(const std::exception &){
+ if(expected_result == '.'){
+ std::cout << "*** erroneously detected error in division " << std::endl;
+ try{
+ v1 / t2;
+ }
+ catch(const std::exception &){}
+ // assert(result == unsafe_result);
+ return false;
+ }
+ }
+ }
+ {
+ safe_t<T1> t1 = v1;
+ safe_t<T2> t2 = v2;
+ using result_type = decltype(t1 / t2);
+ std::cout
+ << "testing safe<" << av1 << "> / safe<" << av2 << "> -> "
+ << boost::core::demangle(typeid(result_type).name()) << '\n';
+
+ static_assert(
+ boost::safe_numerics::is_safe<result_type>::value,
+ "Expression failed to return safe type"
+ );
+
+ try{
+ // use auto to avoid checking assignment.
+ auto result = t1 / t2;
+ std::cout << make_result_display(result);
+ if(expected_result == 'x'){
+ std::cout << " *** failed to detect error in division" << std::endl;
+ t1 / t2;
+ return false;
+ }
+ std::cout << std::endl;
+ }
+ catch(const std::exception &){
+ if(expected_result == '.'){
+ std::cout << " *** erroneously detected error in division \\" << std::endl;
+ try{
+ t1 / t2;
+ }
+ catch(const std::exception &){}
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+#endif // BOOST_TEST_DIVIDE
diff --git a/src/boost/libs/safe_numerics/test/test_divide_automatic.cpp b/src/boost/libs/safe_numerics/test/test_divide_automatic.cpp
new file mode 100644
index 000000000..d3caf0496
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_divide_automatic.cpp
@@ -0,0 +1,62 @@
+// Copyright (c) 2012 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/automatic.hpp>
+#include "test_divide_automatic_results.hpp"
+
+template <class T>
+using safe_t = boost::safe_numerics::safe<
+ T,
+ boost::safe_numerics::automatic
+>;
+#include "test_divide.hpp"
+
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/algorithm.hpp>
+#include <boost/core/demangle.hpp>
+
+using namespace boost::mp11;
+
+template<typename L>
+struct test {
+ static_assert(mp_is_list<L>(), "must be a list of integral constants");
+ bool m_error;
+ test(bool b = true) : m_error(b) {}
+ operator bool(){
+ return m_error;
+ }
+ template<typename T>
+ void operator()(const T &){
+ static_assert(mp_is_list<T>(), "must be a list of two integral constants");
+ constexpr size_t i1 = mp_first<T>(); // index of first argument
+ constexpr size_t i2 = mp_second<T>();// index of second argument
+ std::cout << i1 << ',' << i2 << ',';
+ using T1 = typename mp_at_c<L, i1>::value_type;
+ using T2 = typename mp_at_c<L, i2>::value_type;
+ m_error &= test_divide(
+ boost::mp11::mp_at_c<L, i1>()(), // value of first argument
+ boost::mp11::mp_at_c<L, i2>()(), // value of second argument
+ boost::core::demangle(typeid(T1).name()).c_str(),
+ boost::core::demangle(typeid(T2).name()).c_str(),
+ test_division_automatic_result[i1][i2]
+ );
+ }
+};
+
+int main(){
+ test<test_values> rval(true);
+
+ using value_indices = mp_iota_c<mp_size<test_values>::value>;
+ mp_for_each<
+ mp_product<mp_list, value_indices, value_indices>
+ >(rval);
+
+ std::cout << (rval ? "success!" : "failure") << std::endl;
+ return ! rval ;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_divide_automatic_constexpr.cpp b/src/boost/libs/safe_numerics/test/test_divide_automatic_constexpr.cpp
new file mode 100644
index 000000000..5ad430a9a
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_divide_automatic_constexpr.cpp
@@ -0,0 +1,52 @@
+// Copyright (c) 2019 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/automatic.hpp>
+#include "test_divide_automatic_results.hpp"
+
+template <class T>
+using safe_t = boost::safe_numerics::safe<
+ T,
+ boost::safe_numerics::automatic
+>;
+
+#include "test_divide_constexpr.hpp"
+
+using namespace boost::mp11;
+
+template<typename First, typename Second>
+struct test_pair {
+ static const std::size_t i = First();
+ static const std::size_t j = Second();
+ constexpr static const bool value = test_divide_constexpr(
+ mp_at_c<test_values, i>()(),
+ mp_at_c<test_values, j>()(),
+ test_division_automatic_result[i][j]
+ );
+};
+
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/algorithm.hpp>
+
+int main(){
+ using namespace boost::mp11;
+
+ using value_indices = mp_iota_c<mp_size<test_values>::value>;
+
+ static_assert(
+ mp_all_of<
+ mp_product<
+ test_pair,
+ value_indices,
+ value_indices
+ >,
+ mp_to_bool
+ >(),
+ "all values for all integer types correctly divided"
+ );
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_divide_automatic_results.hpp b/src/boost/libs/safe_numerics/test/test_divide_automatic_results.hpp
new file mode 100644
index 000000000..bb2860581
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_divide_automatic_results.hpp
@@ -0,0 +1,59 @@
+#ifndef BOOST_SAFE_NUMERICS_TEST_DIVIDE_AUTOMATIC_RESULTS_HPP
+#define BOOST_SAFE_NUMERICS_TEST_DIVIDE_AUTOMATIC_RESULTS_HPP
+
+// Copyright (c) 2019 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include "test_values.hpp"
+
+constexpr const char *test_division_automatic_result[
+ boost::mp11::mp_size<test_values>::value
+] = {
+// 0 0 0 0
+// 012345670123456701234567012345670
+// 012345678901234567890123456789012
+/* 0*/ "..............................xxx",
+/* 1*/ "..............................xxx",
+/* 2*/ "..............................xxx",
+/* 3*/ "..............................xxx",
+/* 4*/ "..............................xxx",
+/* 5*/ "..............................xxx",
+/* 6*/ "..............................xxx",
+/* 7*/ "..............................xxx",
+
+/* 8*/ "..............................xxx",
+/* 9*/ "..............................xxx",
+/*10*/ "..............................xxx",
+/*11*/ "..............................xxx",
+/*12*/ "..............................xxx",
+/*13*/ "..............................xxx",
+/*14*/ "...x...x...x...x..............xxx",
+/*15*/ "..............................xxx",
+
+// 0 0 0 0
+// 012345670123456701234567012345670
+// 012345678901234567890123456789012
+/*16*/ "................................x",
+/*17*/ "................................x",
+/*18*/ "................................x",
+/*19*/ "................................x",
+/*20*/ "................................x",
+/*21*/ "................................x",
+/*22*/ "................................x",
+/*23*/ "................................x",
+
+/*24*/ "................................x",
+/*25*/ "................................x",
+/*26*/ "................................x",
+/*27*/ "................................x",
+/*28*/ "................................x",
+/*29*/ "................................x",
+/*30*/ "xxxxxxxxxxxxxxxx................x",
+/*31*/ "xxxxxxxxxxxxxxxx................x",
+/*32*/ "..............................xxx"
+};
+
+#endif // BOOST_SAFE_NUMERICS_TEST_DIVIDE_AUTOMATIC_RESULTS_HPP
diff --git a/src/boost/libs/safe_numerics/test/test_divide_constexpr.hpp b/src/boost/libs/safe_numerics/test/test_divide_constexpr.hpp
new file mode 100644
index 000000000..4ec0ef8f0
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_divide_constexpr.hpp
@@ -0,0 +1,30 @@
+#ifndef BOOST_TEST_DIVIDE_CONSTEXPR_HPP
+#define BOOST_TEST_DIVIDE_CONSTEXPR_HPP
+
+// Copyright (c) 2015 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/safe_numerics/safe_integer.hpp>
+
+template<class T1, class T2>
+constexpr bool test_divide_constexpr(
+ T1 v1,
+ T2 v2,
+ char expected_result
+){
+ using namespace boost::safe_numerics;
+ // if we don't expect the operation to pass, we can't
+ // check the constexpr version of the calculation so
+ // just return success.
+ if(expected_result == 'x')
+ return true;
+ safe_t<T1>(v1) / v2;
+ v1 / safe_t<T2>(v2);
+ safe_t<T1>(v1) / safe_t<T2>(v2);
+ return true; // correct result
+}
+
+#endif // BOOST_TEST_DIVIDE_CONSTEXPR_HPP
diff --git a/src/boost/libs/safe_numerics/test/test_divide_native.cpp b/src/boost/libs/safe_numerics/test/test_divide_native.cpp
new file mode 100644
index 000000000..0299223d9
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_divide_native.cpp
@@ -0,0 +1,63 @@
+// Copyright (c) 2012 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/native.hpp>
+#include "test_divide_native_results.hpp"
+
+template <class T>
+using safe_t = boost::safe_numerics::safe<
+ T,
+ boost::safe_numerics::native
+>;
+#include "test_divide.hpp"
+
+using namespace boost::mp11;
+
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/algorithm.hpp>
+#include <boost/mp11/algorithm.hpp>
+#include <boost/core/demangle.hpp>
+
+template<typename L>
+struct test {
+ static_assert(mp_is_list<L>(), "must be a list of integral constants");
+ bool m_error;
+ test(bool b = true) : m_error(b) {}
+ operator bool(){
+ return m_error;
+ }
+ template<typename T>
+ void operator()(const T &){
+ static_assert(mp_is_list<T>(), "must be a list of two integral constants");
+ constexpr size_t i1 = mp_first<T>(); // index of first argument
+ constexpr size_t i2 = mp_second<T>();// index of second argument
+ std::cout << i1 << ',' << i2 << ',';
+ using T1 = typename mp_at_c<L, i1>::value_type;
+ using T2 = typename mp_at_c<L, i2>::value_type;
+ m_error &= test_divide(
+ mp_at_c<L, i1>()(), // value of first argument
+ mp_at_c<L, i2>()(), // value of second argument
+ boost::core::demangle(typeid(T1).name()).c_str(),
+ boost::core::demangle(typeid(T2).name()).c_str(),
+ test_division_native_result[i1][i2]
+ );
+ }
+};
+
+int main(){
+ test<test_values> rval(true);
+
+ using value_indices = mp_iota_c<mp_size<test_values>::value>;
+ mp_for_each<
+ mp_product<mp_list, value_indices, value_indices>
+ >(rval);
+
+ std::cout << (rval ? "success!" : "failure") << std::endl;
+ return ! rval ;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_divide_native_constexpr.cpp b/src/boost/libs/safe_numerics/test/test_divide_native_constexpr.cpp
new file mode 100644
index 000000000..1a800a60b
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_divide_native_constexpr.cpp
@@ -0,0 +1,53 @@
+// Copyright (c) 2019 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/native.hpp>
+
+#include "test_divide_native_results.hpp"
+
+template <class T>
+using safe_t = boost::safe_numerics::safe<
+ T,
+ boost::safe_numerics::native
+>;
+
+#include "test_divide_constexpr.hpp"
+
+using namespace boost::mp11;
+
+template<typename First, typename Second>
+struct test_pair {
+ static const std::size_t i = First();
+ static const std::size_t j = Second();
+ constexpr static const bool value = test_divide_constexpr(
+ mp_at_c<test_values, i>()(),
+ mp_at_c<test_values, j>()(),
+ test_division_native_result[i][j]
+ );
+};
+
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/algorithm.hpp>
+
+int main(){
+ using namespace boost::mp11;
+
+ using value_indices = mp_iota_c<mp_size<test_values>::value>;
+
+ static_assert(
+ mp_all_of<
+ mp_product<
+ test_pair,
+ value_indices,
+ value_indices
+ >,
+ mp_to_bool
+ >(),
+ "all values for all integer types correctly divided"
+ );
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_divide_native_results.hpp b/src/boost/libs/safe_numerics/test/test_divide_native_results.hpp
new file mode 100644
index 000000000..b24a35418
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_divide_native_results.hpp
@@ -0,0 +1,63 @@
+#ifndef BOOST_SAFE_NUMERICS_TEST_DIVIDE_NATIVE_RESULTS_HPP
+#define BOOST_SAFE_NUMERICS_TEST_DIVIDE_NATIVE_RESULTS_HPP
+
+// Copyright (c) 2019 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include "test_values.hpp"
+
+// note: These tables presume that the the size of an int is 32 bits.
+// This should be changed for a different architecture or better yet
+// be dynamically adjusted depending on the indicated architecture
+
+constexpr const char *test_division_native_result[
+ boost::mp11::mp_size<test_values>::value
+] = {
+// 0 0 0 0
+// 012345670123456701234567012345670
+// 012345678901234567890123456789012
+/* 0*/ "................................x",
+/* 1*/ "................................x",
+/* 2*/ "........................xxxxxxxxx",
+/* 3*/ "........................xxxxxxxxx",
+/* 4*/ "................................x",
+/* 5*/ "................................x",
+/* 6*/ "........................xxxxxxxxx",
+/* 7*/ "........................xxxxxxxxx",
+
+/* 8*/ "................................x",
+/* 9*/ "................................x",
+/*10*/ "...x...x...x............xxxxxxxxx",
+/*11*/ "........................xxxxxxxxx",
+/*12*/ "................................x",
+/*13*/ "................................x",
+/*14*/ "...x...x...x...x............xxxxx",
+/*15*/ "............................xxxxx",
+
+// 0 0 0 0
+// 012345670123456701234567012345670
+// 012345678901234567890123456789012
+/*16*/ "................................x",
+/*17*/ "................................x",
+/*18*/ "................................x",
+/*19*/ "................................x",
+/*20*/ "................................x",
+/*21*/ "................................x",
+/*22*/ "................................x",
+/*23*/ "................................x",
+
+/*24*/ "..xx..xx..xx....................x",
+/*25*/ "..xx..xx..xx....................x",
+/*26*/ "..xx..xx..xx....................x",
+/*27*/ "..xx..xx..xx....................x",
+/*28*/ "..xx..xx..xx..xx................x",
+/*29*/ "..xx..xx..xx..xx................x",
+/*30*/ "..xx..xx..xx..xx................x",
+/*31*/ "..xx..xx..xx..xx................x",
+/*32*/ "................................x"
+};
+
+#endif // BOOST_SAFE_NUMERICS_TEST_DIVIDE_NATIVE_RESULTS_HPP
diff --git a/src/boost/libs/safe_numerics/test/test_equal.hpp b/src/boost/libs/safe_numerics/test/test_equal.hpp
new file mode 100644
index 000000000..70e9006d3
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_equal.hpp
@@ -0,0 +1,162 @@
+ #ifndef BOOST_TEST_LESS_THAN_HPP
+#define BOOST_TEST_LESS_THAN_HPP
+
+// Copyright (c) 2015 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/range_value.hpp>
+
+// works for both GCC and clang
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-value"
+
+template<class T1, class T2>
+bool test_equal(
+ T1 v1,
+ T2 v2,
+ const char *av1,
+ const char *av2,
+ char expected_result
+){
+ using namespace boost::safe_numerics;
+ std::cout << "testing"<< std::boolalpha << std::endl;
+ {
+ safe_t<T1> t1 = v1;
+ std::cout << "safe<" << av1 << "> == " << av2 << " -> ";
+ static_assert(
+ boost::safe_numerics::is_safe<safe_t<T1> >::value,
+ "safe_t not safe!"
+ );
+ try{
+ // use auto to avoid checking assignment.
+ auto result = (t1 == v2);
+ std::cout << make_result_display(result);
+ if(expected_result == 'x'){
+ std::cout
+ << " ! = "<< av1 << " == " << av2
+ << " failed to detect error in equals"
+ << std::endl;
+ t1 == v2;
+ return false;
+ }
+ if(result != (expected_result == '=')){
+ std::cout
+ << " ! = "<< av1 << " == " << av2
+ << " produced the wrong answer"
+ << std::endl;
+ t1 == v2;
+ return false;
+ }
+ std::cout << std::endl;
+ }
+ catch(const std::exception &){
+ if(expected_result != 'x'){
+ std::cout
+ << " == "<< av1 << " == " << av2
+ << " erroneously detected error in equals"
+ << std::endl;
+ try{
+ t1 == v2;
+ }
+ catch(const std::exception &){}
+ return false;
+ }
+ std::cout << std::endl;
+ }
+ }
+ {
+ safe_t<T2> t2 = v2;
+ std::cout << av1 << " == " << "safe<" << av2 << "> -> ";
+ static_assert(
+ boost::safe_numerics::is_safe<safe_t<T2> >::value,
+ "safe_t not safe!"
+ );
+ try{
+ // use auto to avoid checking assignment.
+ auto result = (v1 == t2);
+ std::cout << make_result_display(result);
+ if(expected_result == 'x'){
+ std::cout
+ << " ! = "<< av1 << " == " << av2
+ << " failed to detect error in equals "
+ << std::endl;
+ v1 == t2;
+ return false;
+ }
+ if(result != (expected_result == '=')){
+ std::cout
+ << " ! = "<< av1 << " == " << av2
+ << " produced the wrong answer "
+ << std::endl;
+ v1 == t2;
+ return false;
+ }
+ std::cout << std::endl;
+ }
+ catch(const std::exception &){
+ if(expected_result != 'x'){
+ std::cout
+ << " == "<< av1 << " == " << av2
+ << " erroneously detected error in equals"
+ << std::endl;
+ try{
+ v1 == t2;
+ }
+ catch(const std::exception &){}
+ return false;
+ }
+ std::cout << std::endl;
+ }
+ }
+ {
+ safe_t<T1> t1 = v1;
+ safe_t<T2> t2 = v2;
+ std::cout << "safe<" << av1 << "> < " << "safe<" << av2 << "> -> ";
+
+ try{
+ auto result = (t1 == t2);
+ std::cout << make_result_display(result);
+ if(expected_result == 'x'){
+ std::cout
+ << " ! = "<< av1 << " == " << av2
+ << " failed to detect error in equals"
+ << std::endl;
+ t1 == t2;
+ return false;
+ }
+ if(result != (expected_result == '=')){
+ std::cout
+ << " ! = "<< av1 << " == " << av2
+ << " produced the wrong answer"
+ << std::endl;
+ t1 == t2;
+ return false;
+ }
+ std::cout << std::endl;
+ }
+ catch(const std::exception &){
+ if(expected_result == '.'){
+ std::cout
+ << " == "<< av1 << " == " << av2
+ << " erroneously detected error in equals"
+ << std::endl;
+ try{
+ t1 == t2;
+ }
+ catch(const std::exception &){}
+ return false;
+ }
+ std::cout << std::endl;
+ }
+ }
+ return true; // correct result
+}
+#pragma GCC diagnostic pop
+
+#endif // BOOST_TEST_SUBTRACT
diff --git a/src/boost/libs/safe_numerics/test/test_equal_automatic.cpp b/src/boost/libs/safe_numerics/test/test_equal_automatic.cpp
new file mode 100644
index 000000000..9c02c3d2b
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_equal_automatic.cpp
@@ -0,0 +1,61 @@
+// Copyright (c) 2012 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/automatic.hpp>
+
+template <class T>
+using safe_t = boost::safe_numerics::safe<
+ T,
+ boost::safe_numerics::automatic
+>;
+#include "test_equal.hpp"
+
+#include <boost/mp11/algorithm.hpp>
+#include <boost/core/demangle.hpp>
+#include "test_compare_automatic.hpp"
+
+using namespace boost::mp11;
+
+template<typename L>
+struct test {
+ static_assert(mp_is_list<L>(), "must be a list of integral constants");
+ bool m_error;
+ test(bool b = true) : m_error(b) {}
+ operator bool(){
+ return m_error;
+ }
+ template<typename T>
+ void operator()(const T &){
+ static_assert(mp_is_list<T>(), "must be a list of two integral constants");
+ constexpr size_t i1 = mp_first<T>(); // index of first argument
+ constexpr size_t i2 = mp_second<T>();// index of second argument
+ std::cout << i1 << ',' << i2 << ',';
+ using T1 = typename mp_at_c<L, i1>::value_type;
+ using T2 = typename mp_at_c<L, i2>::value_type;
+ m_error &= test_equal(
+ mp_at_c<L, i1>()(), // value of first argument
+ mp_at_c<L, i2>()(), // value of second argument
+ boost::core::demangle(typeid(T1).name()).c_str(),
+ boost::core::demangle(typeid(T2).name()).c_str(),
+ test_compare_automatic_result[i1][i2]
+ );
+ }
+};
+
+int main(){
+ test<test_values> rval(true);
+
+ using value_indices = mp_iota_c<mp_size<test_values>::value>;
+ mp_for_each<
+ mp_product<mp_list, value_indices, value_indices>
+ >(rval);
+
+ std::cout << (rval ? "success!" : "failure") << std::endl;
+ return ! rval ;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_equal_automatic_constexpr.cpp b/src/boost/libs/safe_numerics/test/test_equal_automatic_constexpr.cpp
new file mode 100644
index 000000000..5168d5903
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_equal_automatic_constexpr.cpp
@@ -0,0 +1,52 @@
+// Copyright (c) 2019 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/automatic.hpp>
+#include "test_compare_automatic.hpp"
+
+template <class T>
+using safe_t = boost::safe_numerics::safe<
+ T,
+ boost::safe_numerics::automatic
+>;
+
+#include "test_equal_constexpr.hpp"
+
+using namespace boost::mp11;
+
+template<typename First, typename Second>
+struct test_pair {
+ static const std::size_t i = First();
+ static const std::size_t j = Second();
+ constexpr static const bool value = test_equal_constexpr(
+ mp_at_c<test_values, i>()(),
+ mp_at_c<test_values, j>()(),
+ test_compare_automatic_result[i][j]
+ );
+};
+
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/algorithm.hpp>
+
+int main(){
+ using namespace boost::mp11;
+
+ using value_indices = mp_iota_c<mp_size<test_values>::value>;
+
+ static_assert(
+ mp_all_of<
+ mp_product<
+ test_pair,
+ value_indices,
+ value_indices
+ >,
+ mp_to_bool
+ >(),
+ "all values for all integer types correctly compared for equality"
+ );
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_equal_constexpr.hpp b/src/boost/libs/safe_numerics/test/test_equal_constexpr.hpp
new file mode 100644
index 000000000..618876624
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_equal_constexpr.hpp
@@ -0,0 +1,40 @@
+#ifndef BOOST_TEST_EQUAL_CONSTEXPR_HPP
+#define BOOST_TEST_EQUAL_CONSTEXPR_HPP
+
+// Copyright (c) 2015 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/config.hpp> // BOOST_CLANG
+#include <boost/safe_numerics/safe_integer.hpp>
+
+#if BOOST_CLANG == 1
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-comparison"
+#endif
+
+template<class T1, class T2>
+constexpr bool test_equal_constexpr(
+ T1 v1,
+ T2 v2,
+ char expected_result
+){
+ using namespace boost::safe_numerics;
+ // if we don't expect the operation to pass, we can't
+ // check the constexpr version of the calculation so
+ // just return success.
+ if(expected_result == 'x')
+ return true;
+ safe_t<T1>(v1) == v2;
+ v1 == safe_t<T2>(v2);
+ safe_t<T1>(v1) == safe_t<T2>(v2);
+ return true; // correct result
+}
+
+#if BOOST_CLANG == 1
+#pragma GCC diagnostic pop
+#endif
+
+#endif // BOOST_TEST_EQUAL_CONSTEXPR_HPP
diff --git a/src/boost/libs/safe_numerics/test/test_equal_native.cpp b/src/boost/libs/safe_numerics/test/test_equal_native.cpp
new file mode 100644
index 000000000..2252fd124
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_equal_native.cpp
@@ -0,0 +1,60 @@
+// Copyright (c) 2012 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+
+template <class T>
+using safe_t = boost::safe_numerics::safe<
+ T,
+ boost::safe_numerics::native
+>;
+#include "test_equal.hpp"
+
+#include <boost/mp11/algorithm.hpp>
+#include <boost/core/demangle.hpp>
+#include "test_compare_native.hpp"
+
+using namespace boost::mp11;
+
+template<typename L>
+struct test {
+ static_assert(mp_is_list<L>(), "must be a list of integral constants");
+ bool m_error;
+ test(bool b = true) : m_error(b) {}
+ operator bool(){
+ return m_error;
+ }
+ template<typename T>
+ void operator()(const T &){
+ static_assert(mp_is_list<T>(), "must be a list of two integral constants");
+ constexpr size_t i1 = mp_first<T>(); // index of first argument
+ constexpr size_t i2 = mp_second<T>();// index of second argument
+ std::cout << i1 << ',' << i2 << ',';
+ using T1 = typename mp_at_c<L, i1>::value_type;
+ using T2 = typename mp_at_c<L, i2>::value_type;
+ m_error &= test_equal(
+ mp_at_c<L, i1>()(), // value of first argument
+ mp_at_c<L, i2>()(), // value of second argument
+ boost::core::demangle(typeid(T1).name()).c_str(),
+ boost::core::demangle(typeid(T2).name()).c_str(),
+ test_compare_native_result[i1][i2]
+ );
+ }
+};
+
+int main(){
+ test<test_values> rval(true);
+
+ using value_indices = mp_iota_c<mp_size<test_values>::value>;
+ mp_for_each<
+ mp_product<mp_list, value_indices, value_indices>
+ >(rval);
+
+ std::cout << (rval ? "success!" : "failure") << std::endl;
+ return ! rval ;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_equal_native_constexpr.cpp b/src/boost/libs/safe_numerics/test/test_equal_native_constexpr.cpp
new file mode 100644
index 000000000..866a0df24
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_equal_native_constexpr.cpp
@@ -0,0 +1,52 @@
+// Copyright (c) 2019 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/native.hpp>
+#include "test_compare_native.hpp"
+
+template <class T>
+using safe_t = boost::safe_numerics::safe<
+ T,
+ boost::safe_numerics::native
+>;
+
+#include "test_equal_constexpr.hpp"
+
+using namespace boost::mp11;
+
+template<typename First, typename Second>
+struct test_pair {
+ static const std::size_t i = First();
+ static const std::size_t j = Second();
+ constexpr static const bool value = test_equal_constexpr(
+ mp_at_c<test_values, i>()(),
+ mp_at_c<test_values, j>()(),
+ test_compare_native_result[i][j]
+ );
+};
+
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/algorithm.hpp>
+
+int main(){
+ using namespace boost::mp11;
+
+ using value_indices = mp_iota_c<mp_size<test_values>::value>;
+
+ static_assert(
+ mp_all_of<
+ mp_product<
+ test_pair,
+ value_indices,
+ value_indices
+ >,
+ mp_to_bool
+ >(),
+ "all values for all integer types correctly compared for equality"
+ );
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_float.cpp b/src/boost/libs/safe_numerics/test/test_float.cpp
new file mode 100644
index 000000000..c0e192db5
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_float.cpp
@@ -0,0 +1,36 @@
+// Copyright (c) 2012 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// testing floating point
+
+// this is a compile only test - but since many build systems
+// can't handle a compile-only test - make sure it passes trivially.
+#include <cassert>
+#include <boost/safe_numerics/safe_integer.hpp>
+
+template<typename T, typename U>
+void test(){
+ T t;
+ U u;
+ float x = t;
+ t = x;
+ t + u;
+ t - u;
+ t * u;
+ t / u;
+/**/
+ // the operators below are restricted to integral types
+}
+int main(){
+ using namespace boost::safe_numerics;
+ /*
+ test<safe<std::int8_t>, float>();
+ test<safe<std::int16_t>,float>();
+ test<safe<std::int32_t>, float>();
+ test<safe<std::int64_t>, float>();
+ */
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_interval.cpp b/src/boost/libs/safe_numerics/test/test_interval.cpp
new file mode 100644
index 000000000..115f4abd0
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_interval.cpp
@@ -0,0 +1,184 @@
+// Copyright (c) 2012 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+#include <limits>
+#include <functional>
+#include <array>
+
+#include <boost/core/demangle.hpp>
+#include <boost/safe_numerics/checked_result.hpp>
+#include <boost/safe_numerics/checked_result_operations.hpp>
+#include <boost/safe_numerics/interval.hpp>
+
+template<typename T>
+using fptr = T (*)(const T &, const T &);
+template<typename T>
+using fptr_interval = fptr<boost::safe_numerics::interval<T>>;
+
+template<typename T>
+struct op {
+ const fptr<T> m_f;
+ const fptr_interval<T> m_finterval;
+ const char * m_symbol;
+ const bool skip_zeros;
+};
+
+template<
+ typename T,
+ unsigned int N
+>
+bool test_type_operator(
+ const T (&value)[N],
+ const op<T> & opi
+){
+ using namespace boost::safe_numerics;
+
+ // for each pair of values p1, p2 (100)
+ for(const T & l1 : value)
+ for(const T & u1 : value){
+ if(l1 > u1) continue; // skip reverse range
+ const interval<T> p1(l1, u1);
+ for(const T & l2 : value)
+ for(const T & u2 : value){
+ if(l2 > u2) continue; // skip reverse range
+ const interval<T> p2(l2, u2);
+
+ // maybe skip intervals which include zero
+ if(opi.skip_zeros){
+ if(l2 == safe_numerics_error::range_error
+ || l2 == safe_numerics_error::domain_error
+ || u2 == safe_numerics_error::range_error
+ || u2 == safe_numerics_error::domain_error
+ || p2.includes(T(0))
+ )
+ continue;
+ }
+
+ // create a new interval from the operation
+ const interval<T> result_interval = opi.m_finterval(p1, p2);
+ std::cout
+ << p1 << opi.m_symbol << p2 << " -> " << result_interval << std::endl;
+
+ // if resulting interval is null
+ if(result_interval.u < result_interval.l)
+ continue;
+
+ // for each pair test values
+ for(const T r1 : value)
+ for(const T r2 : value){
+ // calculate result of operation
+ const T result = opi.m_f(r1, r2);
+ if(result != safe_numerics_error::range_error
+ && result != safe_numerics_error::domain_error ){
+ // note usage of tribool logic here !!!
+ // includes returns indeterminate the conditional
+ // returns false in both cases and this is what we want.
+ // This is very subtle, don't skim over this.
+ // if both r1 and r2 are within they're respective bounds
+ if(p1.includes(r1) && p2.includes(r2)
+ && ! result_interval.includes(result)){
+ #if 0
+ const boost::logic::tribool b1 = p1.includes(r1);
+ const boost::logic::tribool b2 = p2.includes(r2);
+ const boost::logic::tribool b3 = result_interval.includes(result);
+ const interval<T> result_intervalx = opi.m_finterval(p1, p2);
+ const T resultx = opi.m_f(r1, r2);
+ #endif
+ return false;
+ }
+ }
+ }
+ }
+ }
+ return true;
+}
+
+// values
+// note: need to explicitly specify number of elements to avoid msvc failure
+template<typename T>
+const boost::safe_numerics::checked_result<T> value[8] = {
+ boost::safe_numerics::safe_numerics_error::negative_overflow_error,
+ std::numeric_limits<T>::lowest(),
+ T(-1),
+ T(0),
+ T(1),
+ std::numeric_limits<T>::max(),
+ boost::safe_numerics::safe_numerics_error::positive_overflow_error,
+ boost::safe_numerics::safe_numerics_error::domain_error
+};
+
+// note: need to explicitly specify number of elements to avoid msvc failure
+template<typename T>
+const boost::safe_numerics::checked_result<T> unsigned_value[6] = {
+ boost::safe_numerics::safe_numerics_error::negative_overflow_error,
+ T(0),
+ T(1),
+ std::numeric_limits<T>::max(),
+ boost::safe_numerics::safe_numerics_error::positive_overflow_error,
+ boost::safe_numerics::safe_numerics_error::domain_error
+};
+
+// invoke for each type
+struct test_type {
+ unsigned int m_error_count;
+ test_type() :
+ m_error_count(0)
+ {}
+ template<typename T>
+ bool operator()(const T &){
+ using namespace boost::safe_numerics;
+ std::cout
+ << "** testing "
+ << boost::core::demangle(typeid(T).name())
+ << std::endl;
+
+ using R = checked_result<T>;
+ // pointers to operands for types T
+ static const std::array<op<R>, 5> op_table{{
+ {operator+, operator+, "+", false},
+ {operator-, operator-, "-", false},
+ {operator*, operator*, "*", false},
+ {operator<<, operator<<, "<<", false},
+ {operator>>, operator>>, ">>", false},
+ }};
+
+ //for(unsigned int i = 0; i < sizeof(op_table)/sizeof(op) / sizeof(fptr<R>); ++i){
+ for(const op<R> & o : op_table){
+ if(std::is_signed<T>::value){
+ if(! test_type_operator(value<T>, o)){
+ ++m_error_count;
+ return false;
+ }
+ }
+ else{
+ if(! test_type_operator(unsigned_value<T>, o)){
+ ++m_error_count;
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+};
+
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/algorithm.hpp>
+
+int main(int, char *[]){
+ using namespace boost::mp11;
+ // list of signed types
+ using signed_types = mp_list<std::int8_t, std::int16_t, std::int32_t, std::int64_t>;
+ // list of unsigned types
+ using unsigned_types = mp_list<std::uint8_t, std::uint16_t, std::uint32_t, std::uint64_t>;
+
+ test_type t;
+ mp_for_each<unsigned_types>(t);
+ mp_for_each<signed_types>(t);
+
+ std::cout << (t.m_error_count == 0 ? "success!" : "failure") << std::endl;
+ return t.m_error_count ;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_left_shift.hpp b/src/boost/libs/safe_numerics/test/test_left_shift.hpp
new file mode 100644
index 000000000..f9f87e4eb
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_left_shift.hpp
@@ -0,0 +1,148 @@
+#ifndef BOOST_TEST_LEFT_SHIFT_HPP
+#define BOOST_TEST_LEFT_SHIFT_HPP
+
+// Copyright (c) 2015 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/range_value.hpp>
+
+template<class T1, class T2>
+bool test_left_shift(
+ T1 v1,
+ T2 v2,
+ const char *av1,
+ const char *av2,
+ char expected_result
+){
+ std::cout
+ << "testing "
+ << av1 << " << " << av2
+ << std::endl;
+ {
+ safe_t<T1> t1 = v1;
+ using result_type = decltype(t1 << v2);
+ std::cout << "safe<" << av1 << "> << " << av2 << " -> ";
+ static_assert(
+ boost::safe_numerics::is_safe<result_type>::value,
+ "Expression failed to return safe type"
+ );
+ try{
+ // use auto to avoid checking assignment.
+ auto result = t1 << v2;
+ std::cout << make_result_display(result);
+ if(expected_result == 'x'){
+ std::cout
+ << " ! = "<< av1 << " << " << av2
+ << " failed to detect arithmetic error in left shift"
+ << std::endl;
+ t1 << v2;
+ return false;
+ }
+ std::cout << std::endl;
+ }
+ catch(const std::exception & e){
+ if(expected_result == '.'){
+ std::cout
+ << "erroneously detected arithmetic error in left shift"
+ << " == "<< av1 << " << " << av2
+ << ' ' << e.what()
+ << std::endl;
+ try{
+ t1 << v2;
+ }
+ catch(const std::exception &){}
+ return false;
+ }
+ std::cout << std::endl;
+ }
+ }
+ {
+ safe_t<T2> t2 = v2;
+ using result_type = decltype(v1 << t2);
+ std::cout << av1 << " << " << "safe<" << av2 << "> -> ";
+ static_assert(
+ boost::safe_numerics::is_safe<result_type>::value,
+ "Expression failed to return safe type"
+ );
+
+ try{
+ // use auto to avoid checking assignment.
+ auto result = v1 << t2;
+ std::cout << make_result_display(result);
+ if(expected_result == 'x'){
+ std::cout
+ << " ! = "<< av1 << " << " << av2
+ << " failed to detect error in left shift"
+ << std::hex << result << "(" << std::dec << result << ")"
+ << std::endl;
+ v1 << t2;
+ return false;
+ }
+ std::cout << std::endl;
+ }
+ catch(const std::exception & e){
+ if(expected_result == '.'){
+ std::cout
+ << " == "<< av1 << " << " << av2
+ << "erroneously detected error in left shift "
+ << ' ' << e.what()
+ << std::endl;
+ try{
+ v1 << t2;
+ }
+ catch(const std::exception &){}
+ return false;
+ }
+ std::cout << std::endl;
+ }
+ }
+ {
+ safe_t<T1> t1 = v1;
+ safe_t<T2> t2 = v2;
+ using result_type = decltype(t1 << t2);
+ std::cout << "safe<" << av1 << "> << " << "safe<" << av2 << "> -> ";
+ static_assert(
+ boost::safe_numerics::is_safe<result_type>::value,
+ "Expression failed to return safe type"
+ );
+
+ try{
+ // use auto to avoid checking assignment.
+ auto result = t1 << t2;
+ std::cout << make_result_display(result);
+ if(expected_result == 'x'){
+ std::cout
+ << " ! = "<< av1 << " << " << av2
+ << " failed to detect error in left shift"
+ << std::endl;
+ t1 << t2;
+ return false;
+ }
+ std::cout << std::endl;
+ }
+ catch(const std::exception & e){
+ if(expected_result == '.'){
+ std::cout
+ << " == "<< av1 << " << " << av2
+ << " erroneously detected error in left shift"
+ << ' ' << e.what()
+ << std::endl;
+ try{
+ t1 << t2;
+ }
+ catch(const std::exception &){}
+ return false;
+ }
+ std::cout << std::endl;
+ }
+ }
+ return true; // correct result
+}
+
+#endif // BOOST_TEST_DIVIDE
diff --git a/src/boost/libs/safe_numerics/test/test_left_shift_automatic.cpp b/src/boost/libs/safe_numerics/test/test_left_shift_automatic.cpp
new file mode 100644
index 000000000..6aa22e291
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_left_shift_automatic.cpp
@@ -0,0 +1,62 @@
+// Copyright (c) 2012 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/automatic.hpp>
+#include "test_left_shift_automatic_results.hpp"
+
+template <class T>
+using safe_t = boost::safe_numerics::safe<
+ T,
+ boost::safe_numerics::automatic
+>;
+#include "test_left_shift.hpp"
+
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/algorithm.hpp>
+#include <boost/core/demangle.hpp>
+
+using namespace boost::mp11;
+
+template<typename L>
+struct test {
+ static_assert(mp_is_list<L>(), "must be a list of integral constants");
+ bool m_error;
+ test(bool b = true) : m_error(b) {}
+ operator bool(){
+ return m_error;
+ }
+ template<typename T>
+ void operator()(const T &){
+ static_assert(mp_is_list<T>(), "must be a list of two integral constants");
+ constexpr size_t i1 = mp_first<T>(); // index of first argument
+ constexpr size_t i2 = mp_second<T>();// index of second argument
+ std::cout << i1 << ',' << i2 << ',';
+ using T1 = typename mp_at_c<L, i1>::value_type;
+ using T2 = typename mp_at_c<L, i2>::value_type;
+ m_error &= test_left_shift(
+ mp_at_c<L, i1>()(), // value of first argument
+ mp_at_c<L, i2>()(), // value of second argument
+ boost::core::demangle(typeid(T1).name()).c_str(),
+ boost::core::demangle(typeid(T2).name()).c_str(),
+ test_left_shift_automatic_result[i1][i2]
+ );
+ }
+};
+
+int main(){
+ test<test_values> rval(true);
+
+ using value_indices = mp_iota_c<mp_size<test_values>::value>;
+ mp_for_each<
+ mp_product<mp_list, value_indices, value_indices>
+ >(rval);
+
+ std::cout << (rval ? "success!" : "failure") << std::endl;
+ return ! rval ;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_left_shift_automatic_constexpr.cpp b/src/boost/libs/safe_numerics/test/test_left_shift_automatic_constexpr.cpp
new file mode 100644
index 000000000..9ca5b96ea
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_left_shift_automatic_constexpr.cpp
@@ -0,0 +1,52 @@
+// Copyright (c) 2019 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/automatic.hpp>
+#include "test_left_shift_automatic_results.hpp"
+
+template <class T>
+using safe_t = boost::safe_numerics::safe<
+ T,
+ boost::safe_numerics::automatic
+>;
+
+#include "test_left_shift_constexpr.hpp"
+
+using namespace boost::mp11;
+
+template<typename First, typename Second>
+struct test_pair {
+ static const std::size_t i = First();
+ static const std::size_t j = Second();
+ constexpr static const bool value = test_left_shift_constexpr(
+ mp_at_c<test_values, i>()(),
+ mp_at_c<test_values, j>()(),
+ test_left_shift_automatic_result[i][j]
+ );
+};
+
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/algorithm.hpp>
+
+int main(){
+ using namespace boost::mp11;
+
+ using value_indices = mp_iota_c<mp_size<test_values>::value>;
+
+ static_assert(
+ mp_all_of<
+ mp_product<
+ test_pair,
+ value_indices,
+ value_indices
+ >,
+ mp_to_bool
+ >(),
+ "all values for all integer types correctly shifted to the left"
+ );
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_left_shift_automatic_results.hpp b/src/boost/libs/safe_numerics/test/test_left_shift_automatic_results.hpp
new file mode 100644
index 000000000..5923855e0
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_left_shift_automatic_results.hpp
@@ -0,0 +1,65 @@
+#ifndef BOOST_SAFE_NUMERICS_TEST_LEFT_SHIFT_AUTOMATIC_RESULTS_HPP
+#define BOOST_SAFE_NUMERICS_TEST_LEFT_SHIFT_AUTOMATIC_RESULTS_HPP
+
+// Copyright (c) 2019 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include "test_values.hpp"
+
+// note: same test matrix as used in test_checked. Here we test all combinations
+// safe and unsafe integers. in test_checked we test all combinations of
+// integer primitives
+
+constexpr const char *test_left_shift_automatic_result[
+ boost::mp11::mp_size<test_values>::value
+] = {
+// 0 0 0 0
+// 012345670123456701234567012345670
+// 012345678901234567890123456789012
+/* 0*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/* 1*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/* 2*/ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.",
+/* 3*/ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.",
+/* 4*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/* 5*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/* 6*/ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.",
+/* 7*/ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.",
+
+/* 8*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/* 9*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*10*/ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.",
+/*11*/ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.",
+/*12*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*13*/ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.",
+/*14*/ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.",
+/*15*/ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.",
+
+// 0 0 0 0
+// 012345670123456701234567012345670
+// 012345678901234567890123456789012
+/*16*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*17*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*18*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*19*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*20*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*21*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*22*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*23*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+
+/*24*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*25*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*26*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*27*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*28*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*29*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*30*/ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.",
+/*31*/ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.",
+/*32*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx."
+};
+
+#endif // BOOST_SAFE_NUMERICS_TEST_LEFT_SHIFT_AUTOMATIC_RESULTS_HPP
+
+
diff --git a/src/boost/libs/safe_numerics/test/test_left_shift_constexpr.hpp b/src/boost/libs/safe_numerics/test/test_left_shift_constexpr.hpp
new file mode 100644
index 000000000..defdb9a18
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_left_shift_constexpr.hpp
@@ -0,0 +1,30 @@
+#ifndef BOOST_TEST_LEFT_SHIFT_CONSTEXPR_HPP
+#define BOOST_TEST_LEFT_SHIFT_CONSTEXPR_HPP
+
+// Copyright (c) 2019 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/safe_numerics/safe_integer.hpp>
+
+template<class T1, class T2>
+constexpr bool test_left_shift_constexpr(
+ T1 v1,
+ T2 v2,
+ char expected_result
+){
+ using namespace boost::safe_numerics;
+ // if we don't expect the operation to pass, we can't
+ // check the constexpr version of the calculation so
+ // just return success.
+ if(expected_result == 'x')
+ return true;
+ safe_t<T1>(v1) << v2;
+ v1 << safe_t<T2>(v2);
+ safe_t<T1>(v1) << safe_t<T2>(v2);
+ return true; // correct result
+}
+
+#endif // BOOST_TEST_LEFT_SHIFT_CONSTEXPR_HPP
diff --git a/src/boost/libs/safe_numerics/test/test_left_shift_native.cpp b/src/boost/libs/safe_numerics/test/test_left_shift_native.cpp
new file mode 100644
index 000000000..00c92d204
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_left_shift_native.cpp
@@ -0,0 +1,62 @@
+// Copyright (c) 2012 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/native.hpp>
+#include "test_left_shift_native_results.hpp"
+
+template <class T>
+using safe_t = boost::safe_numerics::safe<
+ T,
+ boost::safe_numerics::native
+>;
+#include "test_left_shift.hpp"
+
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/algorithm.hpp>
+#include <boost/core/demangle.hpp>
+
+using namespace boost::mp11;
+
+template<typename L>
+struct test {
+ static_assert(mp_is_list<L>(), "must be a list of integral constants");
+ bool m_error;
+ test(bool b = true) : m_error(b) {}
+ operator bool(){
+ return m_error;
+ }
+ template<typename T>
+ void operator()(const T &){
+ static_assert(mp_is_list<T>(), "must be a list of two integral constants");
+ constexpr size_t i1 = mp_first<T>(); // index of first argument
+ constexpr size_t i2 = mp_second<T>();// index of second argument
+ std::cout << i1 << ',' << i2 << ',';
+ using T1 = typename mp_at_c<L, i1>::value_type;
+ using T2 = typename mp_at_c<L, i2>::value_type;
+ m_error &= test_left_shift<T1, T2>(
+ mp_at_c<L, i1>()(), // value of first argument
+ mp_at_c<L, i2>()(), // value of second argument
+ boost::core::demangle(typeid(T1).name()).c_str(),
+ boost::core::demangle(typeid(T2).name()).c_str(),
+ test_left_shift_native_result[i1][i2]
+ );
+ }
+};
+
+int main(){
+ test<test_values> rval(true);
+
+ using value_indices = mp_iota_c<mp_size<test_values>::value>;
+ mp_for_each<
+ mp_product<mp_list, value_indices, value_indices>
+ >(rval);
+
+ std::cout << (rval ? "success!" : "failure") << std::endl;
+ return ! rval ;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_left_shift_native_constexpr.cpp b/src/boost/libs/safe_numerics/test/test_left_shift_native_constexpr.cpp
new file mode 100644
index 000000000..011ee37c8
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_left_shift_native_constexpr.cpp
@@ -0,0 +1,53 @@
+// Copyright (c) 2019 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/native.hpp>
+
+#include "test_left_shift_native_results.hpp"
+
+template <class T>
+using safe_t = boost::safe_numerics::safe<
+ T,
+ boost::safe_numerics::native
+>;
+
+#include "test_left_shift_constexpr.hpp"
+
+using namespace boost::mp11;
+
+template<typename First, typename Second>
+struct test_pair {
+ static const std::size_t i = First();
+ static const std::size_t j = Second();
+ constexpr static const bool value = test_left_shift_constexpr(
+ mp_at_c<test_values, i>()(),
+ mp_at_c<test_values, j>()(),
+ test_left_shift_native_result[i][j]
+ );
+};
+
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/algorithm.hpp>
+
+int main(){
+ using namespace boost::mp11;
+
+ using value_indices = mp_iota_c<mp_size<test_values>::value>;
+
+ static_assert(
+ mp_all_of<
+ mp_product<
+ test_pair,
+ value_indices,
+ value_indices
+ >,
+ mp_to_bool
+ >(),
+ "all values for all integer types correctly shifted to the left"
+ );
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_left_shift_native_results.hpp b/src/boost/libs/safe_numerics/test/test_left_shift_native_results.hpp
new file mode 100644
index 000000000..f1685bb07
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_left_shift_native_results.hpp
@@ -0,0 +1,60 @@
+#ifndef BOOST_SAFE_NUMERICS_TEST_LEFT_SHIFT_NATIVE_RESULTS_HPP
+#define BOOST_SAFE_NUMERICS_TEST_LEFT_SHIFT_NATIVE_RESULTS_HPP
+
+// Copyright (c) 2019 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include "test_values.hpp"
+
+constexpr const char *test_left_shift_native_result[
+ boost::mp11::mp_size<test_values>::value
+] = {
+// 0 0 0 0
+// 012345670123456701234567012345670
+// 012345678901234567890123456789012
+/* 0*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/* 1*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/* 2*/ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.",
+/* 3*/ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.",
+/* 4*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/* 5*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/* 6*/ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.",
+/* 7*/ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.",
+
+/* 8*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/* 9*/ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.",
+/*10*/ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.",
+/*11*/ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.",
+/*12*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*13*/ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.",
+/*14*/ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.",
+/*15*/ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.",
+
+// 0 0 0 0
+// 012345670123456701234567012345670
+// 012345678901234567890123456789012
+/*16*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*17*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*18*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*19*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*20*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*21*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*22*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*23*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+
+/*24*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*25*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*26*/ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.",
+/*27*/ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.",
+/*28*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*29*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*30*/ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.",
+/*31*/ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.",
+/*32*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx."
+};
+
+#endif // BOOST_SAFE_NUMERICS_TEST_LEFT_SHIFT_NATIVE_RESULTS_HPP
+
diff --git a/src/boost/libs/safe_numerics/test/test_less_than.hpp b/src/boost/libs/safe_numerics/test/test_less_than.hpp
new file mode 100644
index 000000000..6460ad6ac
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_less_than.hpp
@@ -0,0 +1,163 @@
+// Copyright (c) 2015 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_TEST_LESS_THAN_HPP
+#define BOOST_TEST_LESS_THAN_HPP
+
+#include <iostream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/range_value.hpp>
+
+// works for both GCC and clang
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-value"
+
+template<class T1, class T2>
+bool test_less_than(
+ T1 v1,
+ T2 v2,
+ const char *av1,
+ const char *av2,
+ char expected_result
+){
+ using namespace boost::safe_numerics;
+ std::cout << "testing"<< std::boolalpha << std::endl;
+ {
+ safe_t<T1> t1 = v1;
+ std::cout << "safe<" << av1 << "> < " << av2 << " -> ";
+ static_assert(
+ boost::safe_numerics::is_safe<safe_t<T1> >::value,
+ "safe_t not safe!"
+ );
+ try{
+ // use auto to avoid checking assignment.
+ auto result = t1 < v2;
+ std::cout << make_result_display(result);
+ if(expected_result == 'x'){
+ std::cout
+ << " ! = "<< av1 << " < " << av2
+ << " failed to detect error in less than"
+ << std::endl;
+ t1 < v2;
+ return false;
+ }
+ if(result != (expected_result == '<')){
+ std::cout
+ << " ! = "<< av1 << " < " << av2
+ << " produced the wrong answer"
+ << std::endl;
+ t1 < v2;
+ return false;
+ }
+ std::cout << std::endl;
+ }
+ catch(const std::exception &){
+ if(expected_result != 'x'){
+ std::cout
+ << " == "<< av1 << " < " << av2
+ << " erroneously detected error in less than"
+ << std::endl;
+ try{
+ t1 < v2;
+ }
+ catch(const std::exception &){}
+ return false;
+ }
+ std::cout << std::endl;
+ }
+ }
+ {
+ safe_t<T2> t2 = v2;
+ std::cout << av1 << " < " << "safe<" << av2 << "> -> ";
+ static_assert(
+ boost::safe_numerics::is_safe<safe_t<T2> >::value,
+ "safe_t not safe!"
+ );
+ try{
+ // use auto to avoid checking assignment.
+ auto result = v1 < t2;
+ std::cout << make_result_display(result);
+ if(expected_result == 'x'){
+ std::cout
+ << " ! = "<< av1 << " < " << av2
+ << " failed to detect error in less than"
+ << std::endl;
+ v1 < t2;
+ return false;
+ }
+ if(result != (expected_result == '<')){
+ std::cout
+ << " ! = "<< av1 << " < " << av2
+ << " produced the wrong answer"
+ << std::endl;
+ v1 < t2;
+ return false;
+ }
+ std::cout << std::endl;
+ }
+ catch(const std::exception &){
+ if(expected_result != 'x'){
+ std::cout
+ << " == "<< av1 << " < " << av2
+ << " erroneously detected error in less than"
+ << std::endl;
+ try{
+ v1 < t2;
+ }
+ catch(const std::exception &){}
+ return false;
+ }
+ std::cout << std::endl;
+ }
+ }
+ {
+ safe_t<T1> t1 = v1;
+ safe_t<T2> t2 = v2;
+ std::cout << "safe<" << av1 << "> < " << "safe<" << av2 << "> -> ";
+
+ try{
+ // use auto to avoid checking assignment.
+ auto result = t1 < t2;
+ std::cout << make_result_display(result);
+ if(expected_result == 'x'){
+ std::cout
+ << " ! = "<< av1 << " < " << av2
+ << " failed to detect error in less than"
+ << std::endl;
+ t1 < t2;
+ return false;
+ }
+ if(result != (expected_result == '<')){
+ std::cout
+ << " ! = "<< av1 << " < " << av2
+ << " produced the wrong answer"
+ << std::endl;
+ t1 < t2;
+ return false;
+ }
+ std::cout << std::endl;
+ }
+ catch(const std::exception &){
+ if(expected_result == '.'){
+ std::cout
+ << " == "<< av1 << " < " << av2
+ << " erroneously detected error in less than"
+ << std::endl;
+ try{
+ t1 < t2;
+ }
+ catch(const std::exception &){}
+ return false;
+ }
+ std::cout << std::endl;
+ }
+ }
+ return true; // correct result
+}
+#pragma GCC diagnostic pop
+
+#endif // BOOST_TEST_SUBTRACT
diff --git a/src/boost/libs/safe_numerics/test/test_less_than_automatic.cpp b/src/boost/libs/safe_numerics/test/test_less_than_automatic.cpp
new file mode 100644
index 000000000..a04f5fb7a
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_less_than_automatic.cpp
@@ -0,0 +1,61 @@
+// Copyright (c) 2012 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/automatic.hpp>
+
+template <class T>
+using safe_t = boost::safe_numerics::safe<
+ T,
+ boost::safe_numerics::automatic
+>;
+#include "test_less_than.hpp"
+
+#include <boost/mp11/algorithm.hpp>
+#include <boost/core/demangle.hpp>
+#include "test_compare_automatic.hpp"
+
+using namespace boost::mp11;
+
+template<typename L>
+struct test {
+ static_assert(mp_is_list<L>(), "must be a list of integral constants");
+ bool m_error;
+ test(bool b = true) : m_error(b) {}
+ operator bool(){
+ return m_error;
+ }
+ template<typename T>
+ void operator()(const T &){
+ static_assert(mp_is_list<T>(), "must be a list of two integral constants");
+ constexpr size_t i1 = mp_first<T>(); // index of first argument
+ constexpr size_t i2 = mp_second<T>();// index of second argument
+ std::cout << i1 << ',' << i2 << ',';
+ using T1 = typename mp_at_c<L, i1>::value_type;
+ using T2 = typename mp_at_c<L, i2>::value_type;
+ m_error &= test_less_than(
+ mp_at_c<L, i1>()(), // value of first argument
+ mp_at_c<L, i2>()(), // value of second argument
+ boost::core::demangle(typeid(T1).name()).c_str(),
+ boost::core::demangle(typeid(T2).name()).c_str(),
+ test_compare_automatic_result[i1][i2]
+ );
+ }
+};
+
+int main(){
+ test<test_values> rval(true);
+
+ using value_indices = mp_iota_c<mp_size<test_values>::value>;
+ mp_for_each<
+ mp_product<mp_list, value_indices, value_indices>
+ >(rval);
+
+ std::cout << (rval ? "success!" : "failure") << std::endl;
+ return ! rval ;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_less_than_automatic_constexpr.cpp b/src/boost/libs/safe_numerics/test/test_less_than_automatic_constexpr.cpp
new file mode 100644
index 000000000..3c5be46d8
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_less_than_automatic_constexpr.cpp
@@ -0,0 +1,52 @@
+// Copyright (c) 2019 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/automatic.hpp>
+#include "test_compare_automatic.hpp"
+
+template <class T>
+using safe_t = boost::safe_numerics::safe<
+ T,
+ boost::safe_numerics::automatic
+>;
+
+#include "test_less_than_constexpr.hpp"
+
+using namespace boost::mp11;
+
+template<typename First, typename Second>
+struct test_pair {
+ static const std::size_t i = First();
+ static const std::size_t j = Second();
+ constexpr static const bool value = test_less_than_constexpr(
+ mp_at_c<test_values, i>()(),
+ mp_at_c<test_values, j>()(),
+ test_compare_automatic_result[i][j]
+ );
+};
+
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/algorithm.hpp>
+
+int main(){
+ using namespace boost::mp11;
+
+ using value_indices = mp_iota_c<mp_size<test_values>::value>;
+
+ static_assert(
+ mp_all_of<
+ mp_product<
+ test_pair,
+ value_indices,
+ value_indices
+ >,
+ mp_to_bool
+ >(),
+ "all values for all integer types correctly compared"
+ );
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_less_than_constexpr.hpp b/src/boost/libs/safe_numerics/test/test_less_than_constexpr.hpp
new file mode 100644
index 000000000..f3ecf5886
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_less_than_constexpr.hpp
@@ -0,0 +1,40 @@
+#ifndef BOOST_TEST_LESS_THAN_CONSTEXPR_HPP
+#define BOOST_TEST_LESS_THAN_CONSTEXPR_HPP
+
+// Copyright (c) 2019 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/config.hpp> // BOOST_CLANG
+#include <boost/safe_numerics/safe_integer.hpp>
+
+#if BOOST_CLANG==1
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-comparison"
+#endif
+
+template<class T1, class T2>
+constexpr bool test_less_than_constexpr(
+ T1 v1,
+ T2 v2,
+ char expected_result
+){
+ using namespace boost::safe_numerics;
+ // if we don't expect the operation to pass, we can't
+ // check the constexpr version of the calculation so
+ // just return success.
+ if(expected_result == 'x')
+ return true;
+ safe_t<T1>(v1) < v2;
+ v1 < safe_t<T2>(v2);
+ safe_t<T1>(v1) < safe_t<T2>(v2);
+ return true; // correct result
+}
+
+#if BOOST_CLANG==1
+#pragma GCC diagnostic pop
+#endif
+
+#endif // BOOST_TEST_LESS_THAN_CONSTEXPR_HPP
diff --git a/src/boost/libs/safe_numerics/test/test_less_than_native.cpp b/src/boost/libs/safe_numerics/test/test_less_than_native.cpp
new file mode 100644
index 000000000..8dccebfc0
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_less_than_native.cpp
@@ -0,0 +1,60 @@
+// Copyright (c) 2012 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+
+template <class T>
+using safe_t = boost::safe_numerics::safe<
+ T,
+ boost::safe_numerics::native
+>;
+#include "test_less_than.hpp"
+
+#include <boost/mp11/algorithm.hpp>
+#include <boost/core/demangle.hpp>
+#include "test_compare_native.hpp"
+
+using namespace boost::mp11;
+
+template<typename L>
+struct test {
+ static_assert(mp_is_list<L>(), "must be a list of integral constants");
+ bool m_error;
+ test(bool b = true) : m_error(b) {}
+ operator bool(){
+ return m_error;
+ }
+ template<typename T>
+ void operator()(const T &){
+ static_assert(mp_is_list<T>(), "must be a list of two integral constants");
+ constexpr size_t i1 = mp_first<T>(); // index of first argument
+ constexpr size_t i2 = mp_second<T>();// index of second argument
+ std::cout << i1 << ',' << i2 << ',';
+ using T1 = typename mp_at_c<L, i1>::value_type;
+ using T2 = typename mp_at_c<L, i2>::value_type;
+ m_error &= test_less_than<T1, T2>(
+ mp_at_c<L, i1>(), // value of first argument
+ mp_at_c<L, i2>(), // value of second argument
+ boost::core::demangle(typeid(T1).name()).c_str(),
+ boost::core::demangle(typeid(T2).name()).c_str(),
+ test_compare_native_result[i1][i2]
+ );
+ }
+};
+
+int main(){
+ test<test_values> rval(true);
+
+ using value_indices = mp_iota_c<mp_size<test_values>::value>;
+ mp_for_each<
+ mp_product<mp_list, value_indices, value_indices>
+ >(rval);
+
+ std::cout << (rval ? "success!" : "failure") << std::endl;
+ return ! rval ;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_less_than_native_constexpr.cpp b/src/boost/libs/safe_numerics/test/test_less_than_native_constexpr.cpp
new file mode 100644
index 000000000..dfdd1a040
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_less_than_native_constexpr.cpp
@@ -0,0 +1,52 @@
+// Copyright (c) 2019 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/native.hpp>
+#include "test_compare_native.hpp"
+
+template <class T>
+using safe_t = boost::safe_numerics::safe<
+ T,
+ boost::safe_numerics::native
+>;
+
+#include "test_less_than_constexpr.hpp"
+
+using namespace boost::mp11;
+
+template<typename First, typename Second>
+struct test_pair {
+ static const std::size_t i = First();
+ static const std::size_t j = Second();
+ constexpr static const bool value = test_less_than_constexpr(
+ mp_at_c<test_values, i>()(),
+ mp_at_c<test_values, j>()(),
+ test_compare_native_result[i][j]
+ );
+};
+
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/algorithm.hpp>
+
+int main(){
+ using namespace boost::mp11;
+
+ using value_indices = mp_iota_c<mp_size<test_values>::value>;
+
+ static_assert(
+ mp_all_of<
+ mp_product<
+ test_pair,
+ value_indices,
+ value_indices
+ >,
+ mp_to_bool
+ >(),
+ "all values for all integer types correctly compared"
+ );
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_modulus.hpp b/src/boost/libs/safe_numerics/test/test_modulus.hpp
new file mode 100644
index 000000000..cec70ae8e
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_modulus.hpp
@@ -0,0 +1,153 @@
+#ifndef BOOST_TEST_MODULUS_HPP
+#define BOOST_TEST_MODULUS_HPP
+
+// Copyright (c) 2015 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/range_value.hpp>
+
+template<class T1, class T2>
+bool test_modulus(
+ T1 v1,
+ T2 v2,
+ const char *av1,
+ const char *av2,
+ char expected_result
+){
+ std::cout << "testing"<< std::endl;
+ {
+ safe_t<T1> t1 = v1;
+ using result_type = decltype(t1 % v2);
+ std::cout << "safe<" << av1 << "> % " << av2 << " -> ";
+ static_assert(
+ boost::safe_numerics::is_safe<safe_t<T1> >::value,
+ "safe_t not safe!"
+ );
+ static_assert(
+ boost::safe_numerics::is_safe<result_type>::value,
+ "Expression failed to return safe type"
+ );
+
+ try{
+ // use auto to avoid checking assignment.
+ auto result = t1 % v2;
+ std::cout << make_result_display(result);
+ if(expected_result == 'x'){
+ std::cout
+ << " ! = "<< av1 << " % " << av2
+ << " failed to detect error in modulus"
+ << std::endl;
+ t1 % v2;
+ return false;
+ }
+ std::cout << std::endl;
+ }
+ catch(const std::exception &){
+ if(expected_result == '.'){
+ std::cout
+ << " == "<< av1 << " % " << av2
+ << " erroneously detected error in modulus"
+ << std::endl;
+ try{
+ t1 % v2;
+ }
+ catch(const std::exception &){}
+ return false;
+ }
+ }
+ }
+ {
+ safe_t<T2> t2 = v2;
+ using result_type = decltype(v1 % t2);
+ std::cout << av1 << " % " << "safe<" << av2 << "> -> ";
+ static_assert(
+ boost::safe_numerics::is_safe<safe_t<T2> >::value,
+ "safe_t not safe!"
+ );
+ static_assert(
+ boost::safe_numerics::is_safe<result_type>::value,
+ "Expression failed to return safe type"
+ );
+
+ try{
+ // use auto to avoid checking assignment.
+ auto result = v1 % t2;
+ std::cout << make_result_display(result);
+ if(expected_result =='x'){
+ std::cout
+ << " ! = "<< av1 << " % " << av2
+ << " failed to detect error in modulus"
+ << std::endl;
+ try{
+ v1 % t2;
+ }
+ catch(const std::exception &){}
+ return false;
+ }
+ std::cout << std::endl;
+ }
+ catch(const std::exception &){
+ if(expected_result != 'x'){
+ std::cout
+ << " == "<< av1 << " % " << av2
+ << " erroneously detected error in modulus"
+ << std::endl;
+ try{
+ v1 % t2;
+ }
+ catch(const std::exception &){}
+ return false;
+ }
+ }
+ }
+ {
+ safe_t<T1> t1 = v1;
+ safe_t<T2> t2 = v2;
+ using result_type = decltype(t1 + t2);
+ std::cout << "safe<" << av1 << "> % " << "safe<" << av2 << "> -> ";
+ static_assert(
+ boost::safe_numerics::is_safe<result_type>::value,
+ "Expression failed to return safe type"
+ );
+
+ try{
+ // use auto to avoid checking assignment.
+ auto result = t1 % t2;
+ std::cout << make_result_display(result);
+ if(expected_result != '.'){
+ std::cout
+ << " ! = "<< av1 << " % " << av2
+ << " failed to detect error in modulus"
+ << std::endl;
+ try{
+ t1 % t2;
+ }
+ catch(const std::exception &){}
+ return false;
+ }
+ std::cout << std::endl;
+ }
+ catch(const std::exception &){
+ if(expected_result != 'x'){
+ std::cout
+ << " == "<< av1 << " % " << av2
+ << " erroneously detected error in modulus"
+ << std::endl;
+ try{
+ t1 % t2;
+ }
+ catch(const std::exception &){}
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+#endif // BOOST_TEST_MODULUS
diff --git a/src/boost/libs/safe_numerics/test/test_modulus_automatic.cpp b/src/boost/libs/safe_numerics/test/test_modulus_automatic.cpp
new file mode 100644
index 000000000..2fd5c3781
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_modulus_automatic.cpp
@@ -0,0 +1,62 @@
+// Copyright (c) 2012 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/automatic.hpp>
+#include "test_modulus_automatic_results.hpp"
+
+template <class T>
+using safe_t = boost::safe_numerics::safe<
+ T,
+ boost::safe_numerics::automatic
+>;
+#include "test_modulus.hpp"
+
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/algorithm.hpp>
+#include <boost/core/demangle.hpp>
+
+using namespace boost::mp11;
+
+template<typename L>
+struct test {
+ static_assert(mp_is_list<L>(), "must be a list of integral constants");
+ bool m_error;
+ test(bool b = true) : m_error(b) {}
+ operator bool(){
+ return m_error;
+ }
+ template<typename T>
+ void operator()(const T &){
+ static_assert(mp_is_list<T>(), "must be a list of two integral constants");
+ constexpr size_t i1 = mp_first<T>(); // index of first argument
+ constexpr size_t i2 = mp_second<T>();// index of second argument
+ std::cout << i1 << ',' << i2 << ',';
+ using T1 = typename mp_at_c<L, i1>::value_type;
+ using T2 = typename mp_at_c<L, i2>::value_type;
+ m_error &= test_modulus<T1, T2>(
+ mp_at_c<L, i1>()(), // value of first argument
+ mp_at_c<L, i2>()(), // value of second argument
+ boost::core::demangle(typeid(T1).name()).c_str(),
+ boost::core::demangle(typeid(T2).name()).c_str(),
+ test_modulus_automatic_result[i1][i2]
+ );
+ }
+};
+
+int main(){
+ test<test_values> rval(true);
+
+ using value_indices = mp_iota_c<mp_size<test_values>::value>;
+ mp_for_each<
+ mp_product<mp_list, value_indices, value_indices>
+ >(rval);
+
+ std::cout << (rval ? "success!" : "failure") << std::endl;
+ return ! rval ;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_modulus_automatic_constexpr.cpp b/src/boost/libs/safe_numerics/test/test_modulus_automatic_constexpr.cpp
new file mode 100644
index 000000000..3bb908679
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_modulus_automatic_constexpr.cpp
@@ -0,0 +1,52 @@
+// Copyright (c) 2019 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/automatic.hpp>
+#include "test_modulus_automatic_results.hpp"
+
+template <class T>
+using safe_t = boost::safe_numerics::safe<
+ T,
+ boost::safe_numerics::automatic
+>;
+
+#include "test_modulus_constexpr.hpp"
+
+using namespace boost::mp11;
+
+template<typename First, typename Second>
+struct test_pair {
+ static const std::size_t i = First();
+ static const std::size_t j = Second();
+ constexpr static const bool value = test_modulus_constexpr(
+ mp_at_c<test_values, i>()(),
+ mp_at_c<test_values, j>()(),
+ test_modulus_automatic_result[i][j]
+ );
+};
+
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/algorithm.hpp>
+
+int main(){
+ using namespace boost::mp11;
+
+ using value_indices = mp_iota_c<mp_size<test_values>::value>;
+
+ static_assert(
+ mp_all_of<
+ mp_product<
+ test_pair,
+ value_indices,
+ value_indices
+ >,
+ mp_to_bool
+ >(),
+ "all values for all integer types correctly invoked modulus"
+ );
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_modulus_automatic_results.hpp b/src/boost/libs/safe_numerics/test/test_modulus_automatic_results.hpp
new file mode 100644
index 000000000..2530c78d0
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_modulus_automatic_results.hpp
@@ -0,0 +1,60 @@
+#ifndef BOOST_SAFE_NUMERICS_TEST_MODULUS_AUTOMATIC_RESULTS_HPP
+#define BOOST_SAFE_NUMERICS_TEST_MODULUS_AUTOMATIC_RESULTS_HPP
+
+// Copyright (c) 2019 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include "test_values.hpp"
+
+constexpr const char *test_modulus_automatic_result[
+ boost::mp11::mp_size<test_values>::value
+] = {
+// 0 0 0 0
+// 012345670123456701234567012345672
+// 012345678901234567890123456789010
+/* 0*/ "..............................xxx",
+/* 1*/ "..............................xxx",
+/* 2*/ "..............................xxx",
+/* 3*/ "..............................xxx",
+/* 4*/ "..............................xxx",
+/* 5*/ "..............................xxx",
+/* 6*/ "..............................xxx",
+/* 7*/ "..............................xxx",
+
+/* 8*/ "..............................xxx",
+/* 9*/ "..............................xxx",
+/*10*/ "..............................xxx",
+/*11*/ "..............................xxx",
+/*12*/ "..............................xxx",
+/*13*/ "..............................xxx",
+/*14*/ "..............................xxx",
+/*15*/ "..............................xxx",
+
+// 0 0 0 0
+// 012345670123456701234567012345670
+// 012345678901234567890123456789012
+/*16*/ "................................x",
+/*17*/ "................................x",
+/*18*/ "................................x",
+/*19*/ "................................x",
+/*20*/ "................................x",
+/*21*/ "................................x",
+/*22*/ "................................x",
+/*23*/ "................................x",
+
+/*24*/ "................................x",
+/*25*/ "................................x",
+/*26*/ "................................x",
+/*27*/ "................................x",
+/*28*/ "................................x",
+/*29*/ "................................x",
+/*30*/ "xxxxxxxxxxxxxxxx................x",
+/*31*/ "xxxxxxxxxxxxxxxx................x",
+/*32*/ "..............................xxx"
+};
+
+#endif // BOOST_SAFE_NUMERICS_TEST_MODULUS_AUTOMATIC_RESULTS_HPP
+
diff --git a/src/boost/libs/safe_numerics/test/test_modulus_constexpr.hpp b/src/boost/libs/safe_numerics/test/test_modulus_constexpr.hpp
new file mode 100644
index 000000000..8bf06589c
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_modulus_constexpr.hpp
@@ -0,0 +1,30 @@
+#ifndef BOOST_TEST_ADD_CONSTEXPR_HPP
+#define BOOST_TEST_ADD_CONSTEXPR_HPP
+
+// Copyright (c) 2015 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/safe_numerics/safe_integer.hpp>
+
+template<class T1, class T2>
+constexpr bool test_modulus_constexpr(
+ T1 v1,
+ T2 v2,
+ char expected_result
+){
+ using namespace boost::safe_numerics;
+ // if we don't expect the operation to pass, we can't
+ // check the constexpr version of the calculation so
+ // just return success.
+ if(expected_result == 'x')
+ return true;
+ safe_t<T1>(v1) % v2;
+ v1 % safe_t<T2>(v2);
+ safe_t<T1>(v1) % safe_t<T2>(v2);
+ return true; // correct result
+}
+
+#endif // BOOST_TEST_ADD_CONSTEXPR_HPP
diff --git a/src/boost/libs/safe_numerics/test/test_modulus_native.cpp b/src/boost/libs/safe_numerics/test/test_modulus_native.cpp
new file mode 100644
index 000000000..6484be1b9
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_modulus_native.cpp
@@ -0,0 +1,61 @@
+// Copyright (c) 2012 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include "test_modulus_native_results.hpp"
+
+template <class T>
+using safe_t = boost::safe_numerics::safe<
+ T,
+ boost::safe_numerics::native
+>;
+#include "test_modulus.hpp"
+
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/algorithm.hpp>
+#include <boost/core/demangle.hpp>
+
+using namespace boost::mp11;
+
+template<typename L>
+struct test {
+ static_assert(mp_is_list<L>(), "must be a list of integral constants");
+ bool m_error;
+ test(bool b = true) : m_error(b) {}
+ operator bool(){
+ return m_error;
+ }
+ template<typename T>
+ void operator()(const T &){
+ static_assert(mp_is_list<T>(), "must be a list of two integral constants");
+ constexpr size_t i1 = mp_first<T>(); // index of first argument
+ constexpr size_t i2 = mp_second<T>();// index of second argument
+ std::cout << i1 << ',' << i2 << ',';
+ using T1 = typename mp_at_c<L, i1>::value_type;
+ using T2 = typename mp_at_c<L, i2>::value_type;
+ m_error &= test_modulus<T1, T2>(
+ mp_at_c<L, i1>()(), // value of first argument
+ mp_at_c<L, i2>()(), // value of second argument
+ boost::core::demangle(typeid(T1).name()).c_str(),
+ boost::core::demangle(typeid(T2).name()).c_str(),
+ test_modulus_native_result[i1][i2]
+ );
+ }
+};
+
+int main(){
+ test<test_values> rval(true);
+
+ using value_indices = mp_iota_c<mp_size<test_values>::value>;
+ mp_for_each<
+ mp_product<mp_list, value_indices, value_indices>
+ >(rval);
+
+ std::cout << (rval ? "success!" : "failure") << std::endl;
+ return ! rval ;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_modulus_native_constexpr.cpp b/src/boost/libs/safe_numerics/test/test_modulus_native_constexpr.cpp
new file mode 100644
index 000000000..0f21db944
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_modulus_native_constexpr.cpp
@@ -0,0 +1,52 @@
+// Copyright (c) 2019 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/native.hpp>
+#include "test_modulus_native_results.hpp"
+
+template <class T>
+using safe_t = boost::safe_numerics::safe<
+ T,
+ boost::safe_numerics::native
+>;
+
+#include "test_modulus_constexpr.hpp"
+
+using namespace boost::mp11;
+
+template<typename First, typename Second>
+struct test_pair {
+ static const std::size_t i = First();
+ static const std::size_t j = Second();
+ constexpr static const bool value = test_modulus_constexpr(
+ mp_at_c<test_values, i>()(),
+ mp_at_c<test_values, j>()(),
+ test_modulus_native_result[i][j]
+ );
+};
+
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/algorithm.hpp>
+
+int main(){
+ using namespace boost::mp11;
+
+ using value_indices = mp_iota_c<mp_size<test_values>::value>;
+
+ static_assert(
+ mp_all_of<
+ mp_product<
+ test_pair,
+ value_indices,
+ value_indices
+ >,
+ mp_to_bool
+ >(),
+ "all values for all integer types correctly invoked modulus"
+ );
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_modulus_native_results.hpp b/src/boost/libs/safe_numerics/test/test_modulus_native_results.hpp
new file mode 100644
index 000000000..0cae93150
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_modulus_native_results.hpp
@@ -0,0 +1,60 @@
+#ifndef BOOST_SAFE_NUMERICS_TEST_MODULUS_NATIVE_RESULTS_HPP
+#define BOOST_SAFE_NUMERICS_TEST_MODULUS_NATIVE_RESULTS_HPP
+
+// Copyright (c) 2019 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include "test_values.hpp"
+
+constexpr const char *test_modulus_native_result[
+ boost::mp11::mp_size<test_values>::value
+] = {
+// 0 0 0 0
+// 012345670123456701234567012345672
+// 012345678901234567890123456789010
+/* 0*/ "................................x",
+/* 1*/ "................................x",
+/* 2*/ "........................xxxxxxxxx",
+/* 3*/ "........................xxxxxxxxx",
+/* 4*/ "................................x",
+/* 5*/ "................................x",
+/* 6*/ "........................xxxxxxxxx",
+/* 7*/ "........................xxxxxxxxx",
+
+/* 8*/ "................................x",
+/* 9*/ "................................x",
+/*10*/ "........................xxxxxxxxx",
+/*11*/ "........................xxxxxxxxx",
+/*12*/ "................................x",
+/*13*/ "................................x",
+/*14*/ "............................xxxxx",
+/*15*/ "............................xxxxx",
+
+// 0 0 0 0
+// 012345670123456701234567012345672
+// 012345678901234567890123456789010
+/*16*/ "................................x",
+/*17*/ "................................x",
+/*18*/ "................................x",
+/*19*/ "................................x",
+/*20*/ "................................x",
+/*21*/ "................................x",
+/*22*/ "................................x",
+/*23*/ "................................x",
+
+/*24*/ "..xx..xx..xx....................x",
+/*25*/ "..xx..xx..xx....................x",
+/*26*/ "..xx..xx..xx....................x",
+/*27*/ "..xx..xx..xx....................x",
+/*28*/ "..xx..xx..xx..xx................x",
+/*29*/ "..xx..xx..xx..xx................x",
+/*30*/ "..xx..xx..xx..xx................x",
+/*31*/ "..xx..xx..xx..xx................x",
+/*32*/ "................................x"
+};
+
+#endif // BOOST_SAFE_NUMERICS_TEST_MODULUS_NATIVE_RESULTS_HPP
+
diff --git a/src/boost/libs/safe_numerics/test/test_multiply.hpp b/src/boost/libs/safe_numerics/test/test_multiply.hpp
new file mode 100644
index 000000000..fe44ab1f1
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_multiply.hpp
@@ -0,0 +1,151 @@
+#ifndef BOOST_TEST_MULTIPLY_HPP
+#define BOOST_TEST_MULTIPLY_HPP
+
+// Copyright (c) 2015 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+#include <boost/core/demangle.hpp>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/range_value.hpp>
+
+template<class T1, class T2>
+bool test_multiply(
+ T1 v1,
+ T2 v2,
+ const char *av1,
+ const char *av2,
+ char expected_result
+){
+ std::cout << "testing"<< std::endl;
+ {
+ safe_t<T1> t1 = v1;
+
+ using result_type = decltype(t1 * v2);
+ std::cout << "safe<" << av1 << "> * " << av2 << " -> ";
+ static_assert(
+ boost::safe_numerics::is_safe<safe_t<T1> >::value,
+ "safe_t not safe!"
+ );
+ static_assert(
+ boost::safe_numerics::is_safe<result_type>::value,
+ "Expression failed to return safe type"
+ );
+
+ try{
+ // use auto to avoid checking assignment.
+ auto result = t1 * v2;
+ std::cout << make_result_display(result);
+ if(expected_result == 'x'){
+ const std::type_info & ti = typeid(result);
+ std::cout
+ << " *** failed to detect error in multiplication"
+ << boost::core::demangle(ti.name())
+ << std::endl;
+ t1 * v2;
+ return false;
+ }
+ std::cout << std::endl;
+ }
+ catch(const std::exception &){
+ if(expected_result == '.'){
+ std::cout
+ << " *** erroneously detected error in multiplication"
+ << std::endl;
+ try{
+ t1 * v2;
+ }
+ catch(const std::exception &){}
+ return false;
+ }
+ }
+ }
+ {
+ safe_t<T2> t2 = v2;
+ using result_type = decltype(v1 * t2);
+ std::cout << av1 << " * " << "safe<" << av2 << "> -> ";
+ static_assert(
+ boost::safe_numerics::is_safe<safe_t<T2> >::value,
+ "safe_t not safe!"
+ );
+ static_assert(
+ boost::safe_numerics::is_safe<result_type>::value,
+ "Expression failed to return safe type"
+ );
+
+ try{
+ // use auto to avoid checking assignment.
+ auto result = v1 * t2;
+ std::cout << make_result_display(result);
+ if(expected_result == 'x'){
+ const std::type_info & ti = typeid(result);
+ std::cout
+ << " *** failed to detect error in multiplication"
+ << boost::core::demangle(ti.name())
+ << std::endl;
+ v1 * t2;
+ return false;
+ }
+ std::cout << std::endl;
+ }
+ catch(const std::exception &){
+ if(expected_result == '.'){
+ std::cout
+ << " *** erroneously detected error in multiplication"
+ << std::endl;
+ try{
+ v1 * t2;
+ }
+ catch(const std::exception &){}
+ return false;
+ }
+ }
+ }
+ {
+ safe_t<T1> t1 = v1;
+ safe_t<T2> t2 = v2;
+
+ using result_type = decltype(t1 * t2);
+ std::cout << "safe<" << av1 << "> * " << "safe<" << av2 << "> -> ";
+ static_assert(
+ boost::safe_numerics::is_safe<result_type>::value,
+ "Expression failed to return safe type"
+ );
+
+ try{
+ // use auto to avoid checking assignment.
+ auto result = t1 * t2;
+ std::cout << make_result_display(result);
+ if(expected_result == 'x'){
+ const std::type_info & ti = typeid(result);
+ std::cout
+ << " *** failed to detect error in multiplication"
+ << boost::core::demangle(ti.name())
+ << std::endl;
+ t1 * t2;
+ return false;
+ }
+ std::cout << std::endl;
+ }
+ catch(const std::exception &){
+ if(expected_result == '.'){
+ std::cout
+ << " *** erroneously detected error in multiplication"
+ << std::endl;
+ try{
+ t1 * t2;
+ }
+ catch(const std::exception &){}
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+
+#endif // BOOST_TEST_MULTIPLY
diff --git a/src/boost/libs/safe_numerics/test/test_multiply_automatic.cpp b/src/boost/libs/safe_numerics/test/test_multiply_automatic.cpp
new file mode 100644
index 000000000..3382a397a
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_multiply_automatic.cpp
@@ -0,0 +1,69 @@
+// Copyright (c) 2012 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/automatic.hpp>
+#include "test_multiply_automatic_results.hpp"
+
+template <class T>
+using safe_t = boost::safe_numerics::safe<
+ T,
+ boost::safe_numerics::automatic
+>;
+#include "test_multiply.hpp"
+
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/algorithm.hpp>
+#include <boost/core/demangle.hpp>
+
+using namespace boost::mp11;
+
+template<typename L>
+struct test {
+ static_assert(mp_is_list<L>(), "must be a list of integral constants");
+ bool m_error;
+ test(bool b = true) : m_error(b) {}
+ operator bool(){
+ return m_error;
+ }
+ template<typename T>
+ void operator()(const T &){
+ static_assert(mp_is_list<T>(), "must be a list of two integral constants");
+ constexpr size_t i1 = mp_first<T>(); // index of first argument
+ constexpr size_t i2 = mp_second<T>();// index of second argument
+ std::cout << i1 << ',' << i2 << ',';
+ using T1 = typename mp_at_c<L, i1>::value_type;
+ using T2 = typename mp_at_c<L, i2>::value_type;
+ m_error &= test_multiply(
+ mp_at_c<L, i1>()(), // value of first argument
+ mp_at_c<L, i2>()(), // value of second argument
+ boost::core::demangle(typeid(T1).name()).c_str(),
+ boost::core::demangle(typeid(T2).name()).c_str(),
+ test_multiplication_automatic_result[i1][i2]
+ );
+ }
+};
+
+#include "check_symmetry.hpp"
+
+int main(){
+ static_assert(
+ check_symmetry(test_multiplication_automatic_result),
+ "sanity check on test matrix - should be symmetrical"
+ );
+
+ test<test_values> rval(true);
+
+ using value_indices = mp_iota_c<mp_size<test_values>::value>;
+ mp_for_each<
+ mp_product<mp_list, value_indices, value_indices>
+ >(rval);
+
+ std::cout << (rval ? "success!" : "failure") << std::endl;
+ return ! rval ;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_multiply_automatic_constexpr.cpp b/src/boost/libs/safe_numerics/test/test_multiply_automatic_constexpr.cpp
new file mode 100644
index 000000000..357b8ada7
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_multiply_automatic_constexpr.cpp
@@ -0,0 +1,57 @@
+// Copyright (c) 2019 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/automatic.hpp>
+#include "test_multiply_automatic_results.hpp"
+
+template <class T>
+using safe_t = boost::safe_numerics::safe<
+ T,
+ boost::safe_numerics::automatic
+>;
+
+#include "test_multiply_constexpr.hpp"
+
+using namespace boost::mp11;
+
+template<typename First, typename Second>
+struct test_pair {
+ static const std::size_t i = First();
+ static const std::size_t j = Second();
+ constexpr static const bool value = test_multiply_constexpr(
+ mp_at_c<test_values, i>()(),
+ mp_at_c<test_values, j>()(),
+ test_multiplication_automatic_result[i][j]
+ );
+};
+
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/algorithm.hpp>
+#include "check_symmetry.hpp"
+
+int main(){
+ static_assert(
+ check_symmetry(test_multiplication_automatic_result),
+ "sanity check on test matrix - should be symmetrical"
+ );
+
+ using namespace boost::mp11;
+ using value_indices = mp_iota_c<mp_size<test_values>::value>;
+
+ static_assert(
+ mp_all_of<
+ mp_product<
+ test_pair,
+ value_indices,
+ value_indices
+ >,
+ mp_to_bool
+ >(),
+ "all values for all integer types correctly multiplied"
+ );
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_multiply_automatic_results.hpp b/src/boost/libs/safe_numerics/test/test_multiply_automatic_results.hpp
new file mode 100644
index 000000000..972798405
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_multiply_automatic_results.hpp
@@ -0,0 +1,59 @@
+#ifndef BOOST_SAFE_NUMERICS_TEST_MULTIPLY_AUTOMATIC_RESULTS_HPP
+#define BOOST_SAFE_NUMERICS_TEST_MULTIPLY_AUTOMATIC_RESULTS_HPP
+
+// Copyright (c) 2019 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include "test_values.hpp"
+
+constexpr const char *test_multiplication_automatic_result[
+ boost::mp11::mp_size<test_values>::value
+] = {
+// 0 0 0 0
+// 012345670123456701234567012345670
+// 012345678901234567890123456789012
+/* 0*/ "..............................xx.",
+/* 1*/ ".............xx..............xxx.",
+/* 2*/ ".............xx..............xxx.",
+/* 3*/ "..............x...............xx.",
+/* 4*/ "..............................xx.",
+/* 5*/ ".............xx..............xxx.",
+/* 6*/ ".............xx..............xxx.",
+/* 7*/ "..............x...............xx.",
+
+/* 8*/ "..............................xx.",
+/* 9*/ ".............xx..............xxx.",
+/*10*/ ".............xx..............xxx.",
+/*11*/ "..............x...............xx.",
+/*12*/ "..............................xx.",
+/*13*/ ".xx..xx..xx..xx..xxx.xxx.xxx.xxx.",
+/*14*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*15*/ "..............x...............xx.",
+
+// 0 0 0 0
+// 012345670123456701234567012345670
+// 012345678901234567890123456789012
+/*16*/ ".................................",
+/*17*/ ".............xx..............xxx.",
+/*18*/ ".............xx..............xxx.",
+/*19*/ ".............xx..............xxx.",
+/*20*/ ".................................",
+/*21*/ ".............xx..............xxx.",
+/*22*/ ".............xx..............xxx.",
+/*23*/ ".............xx..............xxx.",
+
+/*24*/ ".................................",
+/*25*/ ".............xx..............xxx.",
+/*26*/ ".............xx..............xxx.",
+/*27*/ ".............xx..............xxx.",
+/*28*/ ".................................",
+/*29*/ ".xx..xx..xx..xx..xxx.xxx.xxx.xxx.",
+/*30*/ "xxxxxxxxxxxxxxxx.xxx.xxx.xxx.xxxx",
+/*31*/ "xxxxxxxxxxxxxxxx.xxx.xxx.xxx.xxxx",
+/*32*/ "..............................xx."
+};
+
+#endif // BOOST_SAFE_NUMERICS_TEST_MULTIPLY_AUTOMATIC_RESULTS_HPP
diff --git a/src/boost/libs/safe_numerics/test/test_multiply_constexpr.hpp b/src/boost/libs/safe_numerics/test/test_multiply_constexpr.hpp
new file mode 100644
index 000000000..2fe107df9
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_multiply_constexpr.hpp
@@ -0,0 +1,30 @@
+#ifndef BOOST_TEST_MULTIPLY_CONSTEXPR_HPP
+#define BOOST_TEST_MULTIPLY_CONSTEXPR_HPP
+
+// Copyright (c) 2019 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/safe_numerics/safe_integer.hpp>
+
+template<class T1, class T2>
+constexpr bool test_multiply_constexpr(
+ T1 v1,
+ T2 v2,
+ char expected_result
+){
+ using namespace boost::safe_numerics;
+ // if we don't expect the operation to pass, we can't
+ // check the constexpr version of the calculation so
+ // just return success.
+ if(expected_result == 'x')
+ return true;
+ safe_t<T1>(v1) * v2;
+ v1 * safe_t<T2>(v2);
+ safe_t<T1>(v1) * safe_t<T2>(v2);
+ return true; // correct result
+}
+
+#endif // BOOST_TEST_MULTIPLY_CONSTEXPR_HPP
diff --git a/src/boost/libs/safe_numerics/test/test_multiply_native.cpp b/src/boost/libs/safe_numerics/test/test_multiply_native.cpp
new file mode 100644
index 000000000..4c4a48ed8
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_multiply_native.cpp
@@ -0,0 +1,68 @@
+// Copyright (c) 2012 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include "test_multiply_native_results.hpp"
+
+template <class T>
+using safe_t = boost::safe_numerics::safe<
+ T,
+ boost::safe_numerics::native
+>;
+#include "test_multiply.hpp"
+
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/algorithm.hpp>
+#include <boost/core/demangle.hpp>
+
+using namespace boost::mp11;
+
+template<typename L>
+struct test {
+ static_assert(mp_is_list<L>(), "must be a list of integral constants");
+ bool m_error;
+ test(bool b = true) : m_error(b) {}
+ operator bool(){
+ return m_error;
+ }
+ template<typename T>
+ void operator()(const T &){
+ static_assert(mp_is_list<T>(), "must be a list of two integral constants");
+ constexpr size_t i1 = mp_first<T>(); // index of first argument
+ constexpr size_t i2 = mp_second<T>();// index of second argument
+ std::cout << i1 << ',' << i2 << ',';
+ using T1 = typename mp_at_c<L, i1>::value_type;
+ using T2 = typename mp_at_c<L, i2>::value_type;
+ m_error &= test_multiply<T1, T2>(
+ mp_at_c<L, i1>()(), // value of first argument
+ mp_at_c<L, i2>()(), // value of second argument
+ boost::core::demangle(typeid(T1).name()).c_str(),
+ boost::core::demangle(typeid(T2).name()).c_str(),
+ test_multiplication_native_result[i1][i2]
+ );
+ }
+};
+
+#include "check_symmetry.hpp"
+
+int main(){
+ static_assert(
+ check_symmetry(test_multiplication_native_result),
+ "sanity check on test matrix - should be symmetrical"
+ );
+
+ test<test_values> rval(true);
+
+ using value_indices = mp_iota_c<mp_size<test_values>::value>;
+ mp_for_each<
+ mp_product<mp_list, value_indices, value_indices>
+ >(rval);
+
+ std::cout << (rval ? "success!" : "failure") << std::endl;
+ return ! rval ;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_multiply_native_constexpr.cpp b/src/boost/libs/safe_numerics/test/test_multiply_native_constexpr.cpp
new file mode 100644
index 000000000..b1617242a
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_multiply_native_constexpr.cpp
@@ -0,0 +1,56 @@
+// Copyright (c) 2019 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/native.hpp>
+#include "test_multiply_native_results.hpp"
+
+template <class T>
+using safe_t = boost::safe_numerics::safe<
+ T,
+ boost::safe_numerics::native
+>;
+
+#include "test_multiply_constexpr.hpp"
+
+using namespace boost::mp11;
+
+template<typename First, typename Second>
+struct test_pair {
+ static const std::size_t i = First();
+ static const std::size_t j = Second();
+ constexpr static const bool value = test_multiply_constexpr(
+ mp_at_c<test_values, i>()(),
+ mp_at_c<test_values, j>()(),
+ test_multiplication_native_result[i][j]
+ );
+};
+
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/algorithm.hpp>
+#include "check_symmetry.hpp"
+
+int main(){
+ static_assert(
+ check_symmetry(test_multiplication_native_result),
+ "sanity check on test matrix - should be symmetrical"
+ );
+ using namespace boost::mp11;
+ using value_indices = mp_iota_c<mp_size<test_values>::value>;
+
+ static_assert(
+ mp_all_of<
+ mp_product<
+ test_pair,
+ value_indices,
+ value_indices
+ >,
+ mp_to_bool
+ >(),
+ "all values for all integer types correctly multiplied"
+ );
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_multiply_native_results.hpp b/src/boost/libs/safe_numerics/test/test_multiply_native_results.hpp
new file mode 100644
index 000000000..888a00c5a
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_multiply_native_results.hpp
@@ -0,0 +1,48 @@
+#include "test_values.hpp"
+
+constexpr const char *test_multiplication_native_result[
+ boost::mp11::mp_size<test_values>::value
+] = {
+// 0 0 0 0
+// 012345670123456701234567012345670
+// 012345678901234567890123456789012
+/* 0*/ ".................................",
+/* 1*/ ".........xx..xx..........xxx.xxx.",
+/* 2*/ ".........xx..xx.........xxxxxxxx.",
+/* 3*/ "..........x...x.........xxxxxxxx.",
+/* 4*/ ".................................",
+/* 5*/ ".........xx..xx..........xxx.xxx.",
+/* 6*/ ".........xx..xx.........xxxxxxxx.",
+/* 7*/ "..........x...x.........xxxxxxxx.",
+
+/* 8*/ ".................................",
+/* 9*/ ".xx..xx..xx..xx..xxx.xxx.xxx.xxx.",
+/*10*/ ".xxx.xxx.xxx.xx..xxx.xxxxxxxxxxx.",
+/*11*/ "..........x...x.........xxxxxxxx.",
+/*12*/ ".................................",
+/*13*/ ".xx..xx..xx..xx..xxx.xxx.xxx.xxx.",
+/*14*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxxxxxx.",
+/*15*/ "..............x.............xxxx.",
+
+// 0 0 0 0
+// 012345670123456701234567012345670
+// 012345678901234567890123456789012
+/*16*/ ".................................",
+/*17*/ ".........xx..xx..........xxx.xxx.",
+/*18*/ ".........xx..xx..........xxx.xxx.",
+/*19*/ ".........xx..xx..........xxx.xxx.",
+/*20*/ ".................................",
+/*21*/ ".........xx..xx..........xxx.xxx.",
+/*22*/ ".........xx..xx..........xxx.xxx.",
+/*23*/ ".........xx..xx........x.xxx.xxx.",
+
+/*24*/ "..xx..xx..xx.....................",
+/*25*/ ".xxx.xxx.xxx.xx..xxx.xxx.xxx.xxx.",
+/*26*/ ".xxx.xxx.xxx.xx..xxx.xxx.xxx.xxx.",
+/*27*/ ".xxx.xxx.xxx.xx..xxx.xxx.xxx.xxx.",
+/*28*/ "..xx..xx..xx..xx.................",
+/*29*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*30*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*31*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*31*/ "................................."
+};
diff --git a/src/boost/libs/safe_numerics/test/test_notepad.hpp b/src/boost/libs/safe_numerics/test/test_notepad.hpp
new file mode 100644
index 000000000..d2204a636
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_notepad.hpp
@@ -0,0 +1,12 @@
+// this is a hack to workaround the limititation of template
+// expansion depth in the MSVC compiler.
+template<class L, class F>
+BOOST_MP11_CONSTEXPR mp_if_c<mp_size<L>::value <= 1024, F> mp_for_each_1( F && f ){
+ return detail::mp_for_each_impl( mp_rename<L, mp_list>(), std::forward<F>(f) );
+}
+template<class L, class F>
+BOOST_MP11_CONSTEXPR mp_if_c<mp_size<L>::value >= 1025, F> mp_for_each_1( F && f ){
+ mp_for_each<mp_take_c<L, 1024>>( std::forward<F>(f) );
+ return mp_for_each_1<mp_drop_c<L, 1024>>( std::forward<F>(f) );
+}
+
diff --git a/src/boost/libs/safe_numerics/test/test_or.hpp b/src/boost/libs/safe_numerics/test/test_or.hpp
new file mode 100644
index 000000000..f3eb16c3d
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_or.hpp
@@ -0,0 +1,147 @@
+#ifndef BOOST_TEST_OR_HPP
+#define BOOST_TEST_OR_HPP
+
+// Copyright (c) 2015 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/range_value.hpp>
+
+template<class T1, class T2>
+bool test_or(
+ T1 v1,
+ T2 v2,
+ const char *av1,
+ const char *av2,
+ char expected_result
+){
+ std::cout << "testing"<< std::endl;
+ {
+ safe_t<T1> t1 = v1;
+ using result_type = decltype(t1 | v2);
+ std::cout << "safe<" << av1 << "> | " << av2 << " -> ";
+ static_assert(
+ boost::safe_numerics::is_safe<safe_t<T1> >::value,
+ "safe_t not safe!"
+ );
+ static_assert(
+ boost::safe_numerics::is_safe<result_type>::value,
+ "Expression failed to return safe type"
+ );
+
+ try{
+ // use auto to avoid checking assignment.
+ auto result = t1 | v2;
+ std::cout << make_result_display(result);
+ if(expected_result == 'x'){
+ std::cout
+ << " ! = "<< av1 << " | " << av2
+ << " failed to detect error in bitwise or"
+ << std::endl;
+ t1 | v2;
+ return false;
+ }
+ std::cout << std::endl;
+ }
+ catch(const std::exception &){
+ if(expected_result == '.'){
+ std::cout
+ << " != "<< av1 << " | " << av2
+ << " erroneously detected error in bitwise or"
+ << std::endl;
+ try{
+ t1 | v2;
+ }
+ catch(const std::exception &){}
+ return false;
+ }
+ }
+ }
+ {
+ safe_t<T2> t2 = v2;
+ using result_type = decltype(v1 | t2);
+ std::cout << av1 << " | " << "safe<" << av2 << "> -> ";
+ static_assert(
+ boost::safe_numerics::is_safe<safe_t<T2> >::value,
+ "safe_t not safe!"
+ );
+ static_assert(
+ boost::safe_numerics::is_safe<result_type>::value,
+ "Expression failed to return safe type"
+ );
+
+ try{
+ // use auto to avoid checking assignment.
+ auto result = v1 | t2;
+ std::cout << make_result_display(result);
+ if(expected_result == 'x'){
+ std::cout
+ << " ! = "<< av1 << " | " << av2
+ << " failed to detect error in bitwise or"
+ << std::endl;
+ v1 | t2;
+ return false;
+ }
+ std::cout << std::endl;
+ }
+ catch(const std::exception &){
+ if(expected_result == '.'){
+ std::cout
+ << " == "<< av1 << " | " << av2
+ << " erroneously detected error in bitwise or"
+ << std::endl;
+ try{
+ v1 | t2;
+ }
+ catch(const std::exception &){}
+ return false;
+ }
+ }
+ }
+ {
+ safe_t<T1> t1 = v1;
+ safe_t<T2> t2 = v2;
+ using result_type = decltype(t1 | t2);
+ std::cout << "safe<" << av1 << "> | " << "safe<" << av2 << "> -> ";
+ static_assert(
+ boost::safe_numerics::is_safe<result_type>::value,
+ "Expression failed to return safe type"
+ );
+
+ try{
+ // use auto to avoid checking assignment.
+ auto result = t1 | t2;
+ std::cout << make_result_display(result);
+ if(expected_result == 'x'){
+ std::cout
+ << " ! = "<< av1 << " | " << av2
+ << " failed to detect error in bitwise or"
+ << std::endl;
+ t1 | t2;
+ return false;
+ }
+ std::cout << std::endl;
+ }
+ catch(const std::exception &){
+ if(expected_result == '.'){
+ std::cout
+ << " == "<< av1 << " | " << av2
+ << " erroneously detected error in bitwise or"
+ << std::endl;
+ try{
+ t1 | t2;
+ }
+ catch(const std::exception &){}
+ return false;
+ }
+ }
+ }
+ return true; // correct result
+}
+
+#endif // BOOST_TEST_DIVIDE
diff --git a/src/boost/libs/safe_numerics/test/test_or_automatic.cpp b/src/boost/libs/safe_numerics/test/test_or_automatic.cpp
new file mode 100644
index 000000000..f8139ee12
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_or_automatic.cpp
@@ -0,0 +1,62 @@
+// Copyright (c) 2012 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/automatic.hpp>
+
+template <class T>
+using safe_t = boost::safe_numerics::safe<
+ T,
+ boost::safe_numerics::automatic
+>;
+#include "test_or.hpp"
+
+#include "test_values.hpp"
+#include <boost/mp11/algorithm.hpp>
+#include <boost/core/demangle.hpp>
+
+using namespace boost::mp11;
+
+template<typename L>
+struct test {
+ static_assert(mp_is_list<L>(), "must be a list of integral constants");
+ bool m_error;
+ test(bool b = true) : m_error(b) {}
+ operator bool(){
+ return m_error;
+ }
+ template<typename T>
+ void operator()(const T &){
+ static_assert(mp_is_list<T>(), "must be a list of two integral constants");
+ constexpr size_t i1 = mp_first<T>(); // index of first argument
+ constexpr size_t i2 = mp_second<T>();// index of second argument
+ std::cout << i1 << ',' << i2 << ',';
+ using T1 = typename mp_at_c<L, i1>::value_type;
+ using T2 = typename mp_at_c<L, i2>::value_type;
+ m_error &= test_or(
+ mp_at_c<L, i1>()(), // value of first argument
+ mp_at_c<L, i2>()(), // value of second argument
+ boost::core::demangle(typeid(T1).name()).c_str(),
+ boost::core::demangle(typeid(T2).name()).c_str(),
+ '.'
+ );
+ }
+};
+
+int main(){
+ //TEST_EACH_VALUE_PAIR
+ test<test_values> rval(true);
+
+ using value_indices = mp_iota_c<mp_size<test_values>::value>;
+ mp_for_each<
+ mp_product<mp_list, value_indices, value_indices>
+ >(rval);
+
+ std::cout << (rval ? "success!" : "failure") << std::endl;
+ return ! rval ;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_or_automatic_constexpr.cpp b/src/boost/libs/safe_numerics/test/test_or_automatic_constexpr.cpp
new file mode 100644
index 000000000..20c7a48c5
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_or_automatic_constexpr.cpp
@@ -0,0 +1,53 @@
+// Copyright (c) 2019 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/automatic.hpp>
+
+template <class T>
+using safe_t = boost::safe_numerics::safe<
+ T,
+ boost::safe_numerics::automatic
+>;
+
+#include "test_or_constexpr.hpp"
+
+#include "test_values.hpp"
+
+using namespace boost::mp11;
+
+template<typename First, typename Second>
+struct test_pair {
+ static const std::size_t i = First();
+ static const std::size_t j = Second();
+ constexpr static const bool value = test_or_constexpr(
+ mp_at_c<test_values, i>()(),
+ mp_at_c<test_values, j>()(),
+ '.'
+ );
+};
+
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/algorithm.hpp>
+
+int main(){
+ using namespace boost::mp11;
+
+ using value_indices = mp_iota_c<mp_size<test_values>::value>;
+
+ static_assert(
+ mp_all_of<
+ mp_product<
+ test_pair,
+ value_indices,
+ value_indices
+ >,
+ mp_to_bool
+ >(),
+ "all values for all integer types correctly or'ed"
+ );
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_or_constexpr.hpp b/src/boost/libs/safe_numerics/test/test_or_constexpr.hpp
new file mode 100644
index 000000000..20844ce49
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_or_constexpr.hpp
@@ -0,0 +1,30 @@
+#ifndef BOOST_TEST_ADD_CONSTEXPR_HPP
+#define BOOST_TEST_ADD_CONSTEXPR_HPP
+
+// Copyright (c) 2015 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/safe_numerics/safe_integer.hpp>
+
+template<class T1, class T2>
+constexpr bool test_or_constexpr(
+ T1 v1,
+ T2 v2,
+ char expected_result
+){
+ using namespace boost::safe_numerics;
+ // if we don't expect the operation to pass, we can't
+ // check the constexpr version of the calculation so
+ // just return success.
+ if(expected_result == 'x')
+ return true;
+ safe_t<T1>(v1) | v2;
+ v1 | safe_t<T2>(v2);
+ safe_t<T1>(v1) | safe_t<T2>(v2);
+ return true; // correct result
+}
+
+#endif // BOOST_TEST_ADD_CONSTEXPR_HPP
diff --git a/src/boost/libs/safe_numerics/test/test_or_native.cpp b/src/boost/libs/safe_numerics/test/test_or_native.cpp
new file mode 100644
index 000000000..92ec26e73
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_or_native.cpp
@@ -0,0 +1,62 @@
+// Copyright (c) 2012 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+
+template <class T>
+using safe_t = boost::safe_numerics::safe<
+ T,
+ boost::safe_numerics::native
+>;
+#include "test_or.hpp"
+#include "test_values.hpp"
+
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/algorithm.hpp>
+#include <boost/core/demangle.hpp>
+
+using namespace boost::mp11;
+
+template<typename L>
+struct test {
+ static_assert(mp_is_list<L>(), "must be a list of integral constants");
+ bool m_error;
+ test(bool b = true) : m_error(b) {}
+ operator bool(){
+ return m_error;
+ }
+ template<typename T>
+ void operator()(const T &){
+ static_assert(mp_is_list<T>(), "must be a list of two integral constants");
+ constexpr size_t i1 = mp_first<T>(); // index of first argument
+ constexpr size_t i2 = mp_second<T>();// index of second argument
+ std::cout << i1 << ',' << i2 << ',';
+ using T1 = typename mp_at_c<L, i1>::value_type;
+ using T2 = typename mp_at_c<L, i2>::value_type;
+ m_error &= test_or<T1, T2>(
+ mp_at_c<L, i1>(), // value of first argument
+ mp_at_c<L, i2>(), // value of second argument
+ boost::core::demangle(typeid(T1).name()).c_str(),
+ boost::core::demangle(typeid(T2).name()).c_str(),
+ '.'
+ );
+ }
+};
+
+int main(){
+ //TEST_EACH_VALUE_PAIR
+ test<test_values> rval(true);
+
+ using value_indices = mp_iota_c<mp_size<test_values>::value>;
+ mp_for_each<
+ mp_product<mp_list, value_indices, value_indices>
+ >(rval);
+
+ std::cout << (rval ? "success!" : "failure") << std::endl;
+ return ! rval ;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_or_native_constexpr.cpp b/src/boost/libs/safe_numerics/test/test_or_native_constexpr.cpp
new file mode 100644
index 000000000..d83034a7e
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_or_native_constexpr.cpp
@@ -0,0 +1,53 @@
+// Copyright (c) 2019 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/native.hpp>
+
+template <class T>
+using safe_t = boost::safe_numerics::safe<
+ T,
+ boost::safe_numerics::native
+>;
+
+#include "test_or_constexpr.hpp"
+
+#include "test_values.hpp"
+
+using namespace boost::mp11;
+
+template<typename First, typename Second>
+struct test_pair {
+ static const std::size_t i = First();
+ static const std::size_t j = Second();
+ constexpr static const bool value = test_or_constexpr(
+ mp_at_c<test_values, i>()(),
+ mp_at_c<test_values, j>()(),
+ '.'
+ );
+};
+
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/algorithm.hpp>
+
+int main(){
+ using namespace boost::mp11;
+
+ using value_indices = mp_iota_c<mp_size<test_values>::value>;
+
+ static_assert(
+ mp_all_of<
+ mp_product<
+ test_pair,
+ value_indices,
+ value_indices
+ >,
+ mp_to_bool
+ >(),
+ "all values for all integer types correctly or'ed"
+ );
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_performance.cpp b/src/boost/libs/safe_numerics/test/test_performance.cpp
new file mode 100644
index 000000000..364a76715
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_performance.cpp
@@ -0,0 +1,112 @@
+// test performance.cpp : Defines the entry point for the console application.
+//
+
+#include <cstdio>
+#include <cstdint>
+#include <iostream>
+#include <chrono>
+#include <boost/multiprecision/cpp_int.hpp>
+#include <boost/multiprecision/integer.hpp>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+
+typedef boost::safe_numerics::safe<unsigned> safe_type;
+
+namespace boost {
+namespace multiprecision {
+
+ template <class Integer, class I2>
+ typename enable_if_c<boost::safe_numerics::is_safe<Integer>::value, Integer&>::type
+ multiply(Integer& result, const I2& a, const I2& b){
+ return result = static_cast<Integer>(a) * static_cast<Integer>(b);
+ }
+
+ template <class Integer>
+ typename enable_if_c<boost::safe_numerics::is_safe<Integer>::value, bool>::type
+ bit_test(const Integer& val, unsigned index){
+ Integer mask = 1;
+ if (index >= sizeof(Integer) * CHAR_BIT)
+ return 0;
+ if (index)
+ mask <<= index;
+ return val & mask ? true : false;
+ }
+
+ template <class I1, class I2>
+ typename enable_if_c<boost::safe_numerics::is_safe<I1>::value, I2>::type
+ integer_modulus(const I1& x, I2 val){
+ return x % val;
+ }
+
+ namespace detail {
+ template <class T> struct double_integer;
+
+ template <>
+ struct double_integer<safe_type>{
+ using type = boost::safe_numerics::safe<std::uint64_t>;
+ };
+ }
+
+ template <class I1, class I2, class I3>
+ typename enable_if_c<boost::safe_numerics::is_safe<I1>::value, I1>::type
+ powm(const I1& a, I2 b, I3 c){
+ typedef typename detail::double_integer<I1>::type double_type;
+
+ I1 x(1), y(a);
+ double_type result;
+
+ while (b > 0){
+ if (b & 1){
+ multiply(result, x, y);
+ x = integer_modulus(result, c);
+ }
+ multiply(result, y, y);
+ y = integer_modulus(result, c);
+ b >>= 1;
+ }
+ return x % c;
+ }
+
+ template <class T, class PP, class EP>
+ inline unsigned
+ lsb(const boost::safe_numerics::safe<T, PP, EP>& x){
+ return lsb(static_cast<T>(x));
+ }
+
+} }
+
+#include <boost/multiprecision/miller_rabin.hpp>
+
+template <class Clock>
+class stopwatch
+{
+ const typename Clock::time_point m_start;
+public:
+ stopwatch() :
+ m_start(Clock::now())
+ {}
+ typename Clock::duration elapsed() const {
+ return Clock::now() - m_start;
+ }
+};
+
+template<typename T>
+void test(const char * msg){
+ const stopwatch<std::chrono::high_resolution_clock> c;
+
+ unsigned count = 0;
+ for (T i = 3; i < 30000000; ++i)
+ if (boost::multiprecision::miller_rabin_test(i, 25)) ++count;
+
+ std::chrono::duration<double> time = c.elapsed();
+ std::cout<< msg << ":\ntime = " << time.count();
+ std::cout << "\ncount = " << count << std::endl;
+}
+
+int main()
+{
+ test<unsigned>("Testing type unsigned");
+ test<boost::safe_numerics::safe<unsigned>>("Testing type safe<unsigned>");
+ return 0;
+}
+
diff --git a/src/boost/libs/safe_numerics/test/test_range.cpp b/src/boost/libs/safe_numerics/test/test_range.cpp
new file mode 100644
index 000000000..930b38ed6
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_range.cpp
@@ -0,0 +1,96 @@
+#include <iostream>
+#include <cassert>
+#include <limits>
+
+#include <boost/safe_numerics/utility.hpp>
+#include <boost/safe_numerics/safe_integer_range.hpp>
+
+template<typename T>
+void display_log(T Max){
+ std::cout
+ << "ilog2(" << Max << ") = "
+ << boost::safe_numerics::utility::ilog2(Max) << std::endl;
+}
+
+bool test_significant_bits(){
+ using namespace boost::safe_numerics;
+ assert(utility::significant_bits(127u) == 7); // 7 bits
+ assert(utility::significant_bits(127u) == 7); // 7 bits
+ assert(utility::significant_bits(128u) == 8); // 8 bits
+ assert(utility::significant_bits(129u) == 8); // 8 bits
+ assert(utility::significant_bits(255u) == 8); // 8 bits
+ assert(utility::significant_bits(256u) == 9); // 9 bits
+ return true;
+}
+
+bool test1(){
+ using namespace boost::safe_numerics;
+ using t2 = safe_unsigned_range<0u, 1000u>;
+ static_assert(
+ std::numeric_limits<t2>::is_signed == false,
+ "this range should be unsigned"
+ );
+ return true;
+}
+
+#include <boost/safe_numerics/automatic.hpp>
+
+template <
+ std::intmax_t Min,
+ std::intmax_t Max
+>
+using safe_t = boost::safe_numerics::safe_signed_range<
+ Min,
+ Max,
+ boost::safe_numerics::automatic,
+ boost::safe_numerics::default_exception_policy
+>;
+
+bool test2(){
+ std::cout << "test1" << std::endl;
+ try{
+ const safe_t<-64, 63> x(1);
+ safe_t<-64, 63> y;
+ y = 2;
+ std::cout << "x = " << x << std::endl;
+ std::cout << "y = " << y << std::endl;
+ auto z = x + y;
+ std::cout << "x + y = ["
+ << std::numeric_limits<decltype(z)>::min() << ","
+ << std::numeric_limits<decltype(z)>::max() << "] = "
+ << z << std::endl;
+
+ auto z2 = x - y;
+ std::cout << "x - y = ["
+ << std::numeric_limits<decltype(z2)>::min() << ","
+ << std::numeric_limits<decltype(z2)>::max() << "] = "
+ << z2 << std::endl;
+
+ short int yi, zi;
+ yi = y;
+ zi = x + yi;
+ }
+ catch(const std::exception & e){
+ // none of the above should trap. Mark failure if they do
+ std::cout << e.what() << std::endl;
+ return false;
+ }
+ return true;
+}
+
+int main(){
+ //using namespace boost::safe_numerics;
+ //safe_signed_literal2<100> one_hundred;
+ //one_hundred = 200;
+
+ bool rval =
+ test_significant_bits() &&
+ test1() &&
+ test2() /* &&
+ test3() &&
+ test4()
+ */
+ ;
+ std::cout << (rval ? "success!" : "failure") << std::endl;
+ return rval ? EXIT_SUCCESS : EXIT_FAILURE;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_rational.cpp b/src/boost/libs/safe_numerics/test/test_rational.cpp
new file mode 100644
index 000000000..8e60bf579
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_rational.cpp
@@ -0,0 +1,109 @@
+//////////////////////////////////////////////////////////////////
+// example94.cpp
+//
+// Copyright (c) 2015 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// illustrate usage of safe<int> as drop-in replacement for int in
+// a more complex library. Use an example from the boost.rational
+// library with modifications to use safe<int> rather than int
+
+// rational number example program ----------------------------------------//
+
+// (C) Copyright Paul Moore 1999. Permission to copy, use, modify, sell
+// and distribute this software is granted provided this copyright notice
+// appears in all copies. This software is provided "as is" without express or
+// implied warranty, and with no claim as to its suitability for any purpose.
+
+// boostinspect:nolicense (don't complain about the lack of a Boost license)
+// (Paul Moore hasn't been in contact for years, so there's no way to change the
+// license.)
+
+// Revision History
+// 14 Dec 99 Initial version
+
+#include <iostream>
+#include <cassert>
+#include <cstdlib>
+#include <boost/config.hpp>
+#include <limits>
+#include <exception>
+#include <boost/rational.hpp>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+
+using std::cout;
+using std::endl;
+using boost::rational;
+using namespace boost::safe_numerics;
+
+using int_type = safe<int>;
+
+int main ()
+{
+ rational<int_type> half(1,2);
+ rational<int_type> one(1);
+ rational<int_type> two(2);
+
+ // Some basic checks
+ assert(half.numerator() == 1);
+ assert(half.denominator() == 2);
+// assert(boost::rational_cast<double>(half) == 0.5);
+
+ static_assert(
+ ! boost::safe_numerics::is_safe<rational<int_type>>::value,
+ "rational<int_type> is safe"
+ );
+
+ // Arithmetic
+ assert(half + half == one);
+ assert(one - half == half);
+ assert(two * half == one);
+ assert(one / half == two);
+
+ // With conversions to integer
+ assert(half+half == 1);
+ assert(2 * half == one);
+ assert(2 * half == 1);
+ assert(one / half == 2);
+ assert(1 / half == 2);
+
+ // Sign handling
+ rational<int_type> minus_half(-1,2);
+ assert(-half == minus_half);
+ assert(abs(minus_half) == half);
+
+ // Do we avoid overflow?
+ int maxint = (std::numeric_limits<int>::max)();
+ rational<int_type> big(maxint, 2);
+ assert(2 * big == maxint);
+
+ // Print some of the above results
+ cout << half << "+" << half << "=" << one << endl;
+ cout << one << "-" << half << "=" << half << endl;
+ cout << two << "*" << half << "=" << one << endl;
+ cout << one << "/" << half << "=" << two << endl;
+ cout << "abs(" << minus_half << ")=" << half << endl;
+ cout << "2 * " << big << "=" << maxint
+ << " (rational: " << rational<int>(maxint) << ")" << endl;
+
+ // Some extras
+// rational<int_type> pi(22,7);
+// cout << "pi = " << boost::rational_cast<double>(pi) << " (nearly)" << endl;
+
+ // Exception handling
+ try {
+ rational<int_type> r; // Forgot to initialise - set to 0
+ r = 1/r; // Boom!
+ }
+ catch (const boost::bad_rational &e) {
+ cout << "Bad rational, as expected: " << e.what() << endl;
+ }
+ catch (...) {
+ cout << "Wrong exception raised!" << endl;
+ }
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_right_shift.hpp b/src/boost/libs/safe_numerics/test/test_right_shift.hpp
new file mode 100644
index 000000000..8b46df4a0
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_right_shift.hpp
@@ -0,0 +1,149 @@
+#ifndef BOOST_TEST_RIGHT_SHIFT_HPP
+#define BOOST_TEST_RIGHT_SHIFT_HPP
+
+// Copyright (c) 2015 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/range_value.hpp>
+
+template<class T1, class T2>
+bool test_right_shift(
+ T1 v1,
+ T2 v2,
+ const char *av1,
+ const char *av2,
+ char expected_result
+){
+ std::cout
+ << "testing "
+ << av1 << " >> " << av2
+ << std::endl;
+ {
+ safe_t<T1> t1 = v1;
+ using result_type = decltype(t1 >> v2);
+ std::cout << "safe<" << av1 << "> << " << av2 << " -> ";
+ static_assert(
+ boost::safe_numerics::is_safe<result_type>::value,
+ "Expression failed to return safe type"
+ );
+
+ try{
+ // use auto to avoid checking assignment.
+ auto result = t1 >> v2;
+ std::cout << make_result_display(result);
+ if(expected_result == 'x'){
+ std::cout
+ << " ! = "<< av1 << " >> " << av2
+ << " failed to detect error in right shift"
+ << std::endl;
+ t1 >> v2;
+ return false;
+ }
+ std::cout << std::endl;
+ }
+ catch(const std::exception & e){
+ if(expected_result == '.'){
+ std::cout
+ << " == "<< av1 << " >> " << av2
+ << " erroneously detected error in right shift"
+ << ' ' << e.what()
+ << std::endl;
+ try{
+ t1 >> v2;
+ }
+ catch(const std::exception &){}
+ return false;
+ }
+ std::cout << std::endl;
+ }
+ }
+ {
+ safe_t<T2> t2 = v2;
+ using result_type = decltype(v1 >> t2);
+ std::cout << av1 << " >> " << "safe<" << av2 << "> -> ";
+ static_assert(
+ boost::safe_numerics::is_safe<result_type>::value,
+ "Expression failed to return safe type"
+ );
+
+ try{
+ // use auto to avoid checking assignment.
+ auto result = v1 >> t2;
+ std::cout << make_result_display(result);
+ if(expected_result == 'x'){
+ std::cout
+ << " ! = "<< av1 << " >> " << av2
+ << " failed to detect error in right shift"
+ << std::hex << result << "(" << std::dec << result << ")"
+ << std::endl;
+ v1 >> t2;
+ return false;
+ }
+ std::cout << std::endl;
+ }
+ catch(const std::exception & e){
+ if(expected_result == '.'){
+ std::cout
+ << " == "<< av1 << " >> " << av2
+ << " erroneously detected error in right shift"
+ << ' ' << e.what()
+ << std::endl;
+ try{
+ v1 >> t2;
+ }
+ catch(const std::exception &){}
+ return false;
+ }
+ std::cout << std::endl;
+ }
+ }
+ {
+ safe_t<T1> t1 = v1;
+ safe_t<T2> t2 = v2;
+ using result_type = decltype(t1 >> t2);
+ std::cout << "safe<" << av1 << "> >> " << "safe<" << av2 << "> -> ";
+ static_assert(
+ boost::safe_numerics::is_safe<result_type>::value,
+ "Expression failed to return safe type"
+ );
+
+ try{
+ // use auto to avoid checking assignment.
+ auto result = t1 >> t2;
+ std::cout << make_result_display(result);
+ if(expected_result == 'x'){
+ std::cout
+ << " ! = "<< av1 << " << " << av2
+ << " failed to detect error in right shift"
+ << std::endl;
+ t1 >> t2;
+ return false;
+ }
+ std::cout << std::endl;
+ }
+ catch(const std::exception & e){
+ if(expected_result == '.'){
+ std::cout
+ << " == "<< av1 << " << " << av2
+ << " erroneously detected error in right shift"
+ << ' ' << e.what()
+ << std::endl;
+ try{
+ t1 >> t2;
+ }
+ catch(const std::exception &){}
+ return false;
+ }
+ std::cout << std::endl;
+ }
+ }
+ return true; // correct result
+}
+
+#endif // BOOST_TEST_RIGHT_SHIFT_HPP
diff --git a/src/boost/libs/safe_numerics/test/test_right_shift_automatic.cpp b/src/boost/libs/safe_numerics/test/test_right_shift_automatic.cpp
new file mode 100644
index 000000000..1087f3640
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_right_shift_automatic.cpp
@@ -0,0 +1,63 @@
+// Copyright (c) 2012 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/automatic.hpp>
+#include "test_right_shift_automatic_results.hpp"
+
+template <class T>
+using safe_t = boost::safe_numerics::safe<
+ T,
+ boost::safe_numerics::automatic
+>;
+#include "test_right_shift.hpp"
+
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/algorithm.hpp>
+#include <boost/core/demangle.hpp>
+
+using namespace boost::mp11;
+
+template<typename L>
+struct test {
+ static_assert(mp_is_list<L>(), "must be a list of integral constants");
+ bool m_error;
+ test(bool b = true) : m_error(b) {}
+ operator bool(){
+ return m_error;
+ }
+ template<typename T>
+ void operator()(const T &){
+ static_assert(mp_is_list<T>(), "must be a list of two integral constants");
+ constexpr size_t i1 = mp_first<T>(); // index of first argument
+ constexpr size_t i2 = mp_second<T>();// index of second argument
+ std::cout << i1 << ',' << i2 << ',';
+ using T1 = typename mp_at_c<L, i1>::value_type;
+ using T2 = typename mp_at_c<L, i2>::value_type;
+ m_error &= test_right_shift<T1, T2>(
+ mp_at_c<L, i1>()(), // value of first argument
+ mp_at_c<L, i2>()(), // value of second argument
+ boost::core::demangle(typeid(T1).name()).c_str(),
+ boost::core::demangle(typeid(T2).name()).c_str(),
+ test_right_shift_automatic_result[i1][i2]
+ );
+ }
+};
+
+int main(){
+ //TEST_EACH_VALUE_PAIR
+ test<test_values> rval(true);
+
+ using value_indices = mp_iota_c<mp_size<test_values>::value>;
+ mp_for_each<
+ mp_product<mp_list, value_indices, value_indices>
+ >(rval);
+
+ std::cout << (rval ? "success!" : "failure") << std::endl;
+ return ! rval ;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_right_shift_automatic_constexpr.cpp b/src/boost/libs/safe_numerics/test/test_right_shift_automatic_constexpr.cpp
new file mode 100644
index 000000000..05a664344
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_right_shift_automatic_constexpr.cpp
@@ -0,0 +1,52 @@
+// Copyright (c) 2019 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/automatic.hpp>
+#include "test_right_shift_automatic_results.hpp"
+
+template <class T>
+using safe_t = boost::safe_numerics::safe<
+ T,
+ boost::safe_numerics::automatic
+>;
+
+#include "test_right_shift_constexpr.hpp"
+
+using namespace boost::mp11;
+
+template<typename First, typename Second>
+struct test_pair {
+ static const std::size_t i = First();
+ static const std::size_t j = Second();
+ constexpr static const bool value = test_right_shift_constexpr(
+ mp_at_c<test_values, i>()(),
+ mp_at_c<test_values, j>()(),
+ test_right_shift_automatic_result[i][j]
+ );
+};
+
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/algorithm.hpp>
+
+int main(){
+ using namespace boost::mp11;
+
+ using value_indices = mp_iota_c<mp_size<test_values>::value>;
+
+ static_assert(
+ mp_all_of<
+ mp_product<
+ test_pair,
+ value_indices,
+ value_indices
+ >,
+ mp_to_bool
+ >(),
+ "all values for all integer types correctly right shifted"
+ );
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_right_shift_automatic_results.hpp b/src/boost/libs/safe_numerics/test/test_right_shift_automatic_results.hpp
new file mode 100644
index 000000000..26dc8ab71
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_right_shift_automatic_results.hpp
@@ -0,0 +1,60 @@
+#ifndef BOOST_SAFE_NUMERICS_TEST_RIGHT_SHIFT_AUTOMATIC_RESULTS_HPP
+#define BOOST_SAFE_NUMERICS_TEST_RIGHT_SHIFT_AUTOMATIC_RESULTS_HPP
+
+// Copyright (c) 2019 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include "test_values.hpp"
+
+constexpr const char *test_right_shift_automatic_result[
+ boost::mp11::mp_size<test_values>::value
+] = {
+// 0 0 0 0
+// 012345670123456701234567012345670
+// 012345678901234567890123456789012
+/* 0*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/* 1*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/* 2*/ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+/* 3*/ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+/* 4*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/* 5*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/* 6*/ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+/* 7*/ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+
+/* 8*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/* 9*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*10*/ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+/*11*/ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+/*12*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*13*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*14*/ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+/*15*/ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+
+// 0 0 0 0
+// 012345670123456701234567012345670
+// 012345678901234567890123456789012
+/*16*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*17*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*18*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*19*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*20*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*21*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*22*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*23*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+
+/*24*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*25*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*26*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*27*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*28*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*29*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*30*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*31*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*32*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx."
+};
+
+#endif // BOOST_SAFE_NUMERICS_TEST_RIGHT_SHIFT_AUTOMATIC_RESULTS_HPP
+
diff --git a/src/boost/libs/safe_numerics/test/test_right_shift_constexpr.hpp b/src/boost/libs/safe_numerics/test/test_right_shift_constexpr.hpp
new file mode 100644
index 000000000..c4e2bab27
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_right_shift_constexpr.hpp
@@ -0,0 +1,30 @@
+#ifndef BOOST_TEST_RIGHT_SHIFT_CONSTEXPR_HPP
+#define BOOST_TEST_RIGHT_SHIFT_CONSTEXPR_HPP
+
+// Copyright (c) 2015 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/safe_numerics/safe_integer.hpp>
+
+template<class T1, class T2>
+constexpr bool test_right_shift_constexpr(
+ T1 v1,
+ T2 v2,
+ char expected_result
+){
+ using namespace boost::safe_numerics;
+ // if we don't expect the operation to pass, we can't
+ // check the constexpr version of the calculation so
+ // just return success.
+ if(expected_result == 'x')
+ return true;
+ safe_t<T1>(v1) >> v2;
+ v1 >> safe_t<T2>(v2);
+ safe_t<T1>(v1) >> safe_t<T2>(v2);
+ return true; // correct result
+}
+
+#endif // BOOST_TEST_RIGHT_SHIFT_CONSTEXPR_HPP
diff --git a/src/boost/libs/safe_numerics/test/test_right_shift_native.cpp b/src/boost/libs/safe_numerics/test/test_right_shift_native.cpp
new file mode 100644
index 000000000..f7c8b3119
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_right_shift_native.cpp
@@ -0,0 +1,62 @@
+// Copyright (c) 2012 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include "test_right_shift_native_results.hpp"
+
+template <class T>
+using safe_t = boost::safe_numerics::safe<
+ T,
+ boost::safe_numerics::native
+>;
+#include "test_right_shift.hpp"
+
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/algorithm.hpp>
+#include <boost/core/demangle.hpp>
+
+using namespace boost::mp11;
+
+template<typename L>
+struct test {
+ static_assert(mp_is_list<L>(), "must be a list of integral constants");
+ bool m_error;
+ test(bool b = true) : m_error(b) {}
+ operator bool(){
+ return m_error;
+ }
+ template<typename T>
+ void operator()(const T &){
+ static_assert(mp_is_list<T>(), "must be a list of two integral constants");
+ constexpr size_t i1 = mp_first<T>(); // index of first argument
+ constexpr size_t i2 = mp_second<T>();// index of second argument
+ std::cout << i1 << ',' << i2 << ',';
+ using T1 = typename mp_at_c<L, i1>::value_type;
+ using T2 = typename mp_at_c<L, i2>::value_type;
+ m_error &= test_right_shift<T1, T2>(
+ mp_at_c<L, i1>(), // value of first argument
+ mp_at_c<L, i2>(), // value of second argument
+ boost::core::demangle(typeid(T1).name()).c_str(),
+ boost::core::demangle(typeid(T2).name()).c_str(),
+ test_right_shift_native_result[i1][i2]
+ );
+ }
+};
+
+int main(){
+ //TEST_EACH_VALUE_PAIR
+ test<test_values> rval(true);
+
+ using value_indices = mp_iota_c<mp_size<test_values>::value>;
+ mp_for_each<
+ mp_product<mp_list, value_indices, value_indices>
+ >(rval);
+
+ std::cout << (rval ? "success!" : "failure") << std::endl;
+ return ! rval ;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_right_shift_native_constexpr.cpp b/src/boost/libs/safe_numerics/test/test_right_shift_native_constexpr.cpp
new file mode 100644
index 000000000..59496354a
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_right_shift_native_constexpr.cpp
@@ -0,0 +1,52 @@
+// Copyright (c) 2019 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/native.hpp>
+#include "test_right_shift_native_results.hpp"
+
+template <class T>
+using safe_t = boost::safe_numerics::safe<
+ T,
+ boost::safe_numerics::native
+>;
+
+#include "test_right_shift_constexpr.hpp"
+
+using namespace boost::mp11;
+
+template<typename First, typename Second>
+struct test_pair {
+ static const std::size_t i = First();
+ static const std::size_t j = Second();
+ constexpr static const bool value = test_right_shift_constexpr(
+ mp_at_c<test_values, i>()(),
+ mp_at_c<test_values, j>()(),
+ test_right_shift_native_result[i][j]
+ );
+};
+
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/algorithm.hpp>
+
+int main(){
+ using namespace boost::mp11;
+
+ using value_indices = mp_iota_c<mp_size<test_values>::value>;
+
+ static_assert(
+ mp_all_of<
+ mp_product<
+ test_pair,
+ value_indices,
+ value_indices
+ >,
+ mp_to_bool
+ >(),
+ "all values for all integer types correctly right shifted"
+ );
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_right_shift_native_results.hpp b/src/boost/libs/safe_numerics/test/test_right_shift_native_results.hpp
new file mode 100644
index 000000000..c299aa049
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_right_shift_native_results.hpp
@@ -0,0 +1,59 @@
+#ifndef BOOST_SAFE_NUMERICS_TEST_RIGHT_SHIFT_NATIVE_RESULTS_HPP
+#define BOOST_SAFE_NUMERICS_TEST_RIGHT_SHIFT_NATIVE_RESULTS_HPP
+
+// Copyright (c) 2019 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include "test_values.hpp"
+
+constexpr const char *test_right_shift_native_result[
+ boost::mp11::mp_size<test_values>::value
+] = {
+// 0 0 0 0
+// 012345670123456701234567012345670
+// 012345678901234567890123456789012
+/* 0*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/* 1*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/* 2*/ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+/* 3*/ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+/* 4*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/* 5*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/* 6*/ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+/* 7*/ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+
+/* 8*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/* 9*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*10*/ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+/*11*/ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+/*12*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*13*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*14*/ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+/*15*/ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+
+// 0 0 0 0
+// 012345670123456701234567012345670
+// 012345678901234567890123456789012
+/*16*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*17*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*18*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*19*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*20*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*21*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*22*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*23*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+
+/*24*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*25*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*26*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*27*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*28*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*29*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*30*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*31*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*32*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx."
+};
+
+#endif // BOOST_SAFE_NUMERICS_TEST_RIGHT_SHIFT_NATIVE_RESULTS_HPP
diff --git a/src/boost/libs/safe_numerics/test/test_safe_compare.cpp b/src/boost/libs/safe_numerics/test/test_safe_compare.cpp
new file mode 100644
index 000000000..41190566a
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_safe_compare.cpp
@@ -0,0 +1,165 @@
+// Copyright (c) 2014 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+#include <boost/core/demangle.hpp>
+#include <boost/safe_numerics/safe_compare.hpp>
+
+template<class T1, class T2>
+void print_argument_types(
+ T1 v1,
+ T2 v2
+){
+ const std::type_info & ti1 = typeid(v1);
+ const std::type_info & ti2 = typeid(v2);
+
+ std::cout
+ << boost::core::demangle(ti1.name()) << ','
+ << boost::core::demangle(ti2.name());
+}
+
+#include <boost/mp11/algorithm.hpp>
+
+using namespace boost::safe_numerics;
+
+template<class T1, class T2>
+bool test_safe_compare_impl(
+ T1 v1,
+ T2 v2,
+ char expected_result
+){
+ switch(expected_result){
+ case '=': {
+ if(! safe_compare::equal(v1, v2))
+ return false;
+ if(safe_compare::less_than(v1, v2))
+ return false;
+ if(safe_compare::greater_than(v1, v2))
+ return false;
+ break;
+ }
+ case '<': {
+ if(! safe_compare::less_than(v1, v2))
+ return false;
+ if(safe_compare::greater_than(v1, v2))
+ return false;
+ if(safe_compare::equal(v1, v2))
+ return false;
+ break;
+ }
+ case '>':{
+ if(! safe_compare::greater_than(v1, v2))
+ return false;
+ if(safe_compare::less_than(v1, v2))
+ return false;
+ if(safe_compare::equal(v1, v2))
+ return false;
+ break;
+ }
+ }
+ return true;
+}
+
+template<class T1, class T2>
+bool test_safe_compare(
+ T1 v1,
+ T2 v2,
+ char expected_result
+){
+ print_argument_types(v1, v2);
+ const bool result = test_safe_compare_impl(v1, v2, expected_result);
+ if(! result)
+ std::cout << " failed";
+ std::cout << '\n';
+ return result;
+}
+
+#include "test_values.hpp"
+
+const char *test_compare_result[boost::mp11::mp_size<test_values>::value] = {
+// 0 0 0 0
+// 012345670123456701234567012345670
+// 012345678901234567890123456789012
+/* 0*/ "=<>>=<>>=<>>=<>>=<<<=<<<=<<<=<<<>",
+/* 1*/ ">=>>><>>><>>><>>>=<<><<<><<<><<<>",
+/* 2*/ "<<=<<<><<<><<<><<<<<<<<<<<<<<<<<<",
+/* 3*/ "<<>=<<>=<<>=<<>=<<<<<<<<<<<<<<<<<",
+/* 4*/ "=<>>=<>>=<>>=<>>=<<<=<<<=<<<=<<<>",
+/* 5*/ ">>>>>=>>><>>><>>>>>>>=<<><<<><<<>",
+/* 6*/ "<<<<<<=<<<><<<><<<<<<<<<<<<<<<<<<",
+/* 7*/ "<<>=<<>=<<>=<<>=<<<<<<<<<<<<<<<<<",
+
+/* 8*/ "=<>>=<>>=<>>=<>>=<<<=<<<=<<<=<<<>",
+/* 9*/ ">>>>>>>>>=>>><>>>>>>>>>>>=<<><<<>",
+/*10*/ "<<<<<<<<<<=<<<><<<<<<<<<<<<<<<<<<",
+/*11*/ "<<>=<<>=<<>=<<>=<<<<<<<<<<<<<<<<<",
+/*12*/ "=<>>=<>>=<>>=<>>=<<<=<<<=<<<=<<<>",
+/*13*/ ">>>>>>>>>>>>>=>>>>>>>>>>>>>>>=<<>",
+/*14*/ "<<<<<<<<<<<<<<=<<<<<<<<<<<<<<<<<<",
+/*15*/ "<<>=<<>=<<>=<<>=<<<<<<<<<<<<<<<<",
+
+// 0 0 0 0
+// 012345670123456701234567012345670
+// 012345678901234567890123456789012
+/*16*/ "=<>>=<>>=<>>=<>>=<<<=<<<=<<<=<<<>",
+/*17*/ ">=>>><>>><>>><>>>=<<><<<><<<><<<>",
+/*18*/ ">>>>><>>><>>><>>>>=<><<<><<<><<<>",
+/*19*/ ">>>>><>>><>>><>>>>>=><<<><<<><<<>",
+/*20*/ "=<>>=<>>=<>>=<>>=<<<=<<<=<<<=<<<>",
+/*21*/ ">>>>>=>>><>>><>>>>>>>=<<><<<><<<>",
+/*22*/ ">>>>>>>>><>>><>>>>>>>>=<><<<><<<>",
+/*23*/ ">>>>>>>>><>>><>>>>>>>>>=><<<><<<>",
+
+/*24*/ "=<>>=<>>=<>>=<>>=<<<=<<<=<<<=<<<>",
+/*25*/ ">>>>>>>>>=>>><>>>>>>>>>>>=<<><<<>",
+/*26*/ ">>>>>>>>>>>>><>>>>>>>>>>>>=<><<<>",
+/*27*/ ">>>>>>>>>>>>><>>>>>>>>>>>>>=><<<>",
+/*28*/ "=<>>=<>>=<>>=<>>=<<<=<<<=<<<=<<<>",
+/*29*/ ">>>>>>>>>>>>>=>>>>>>>>>>>>>>>=<<>",
+/*30*/ ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>=<>",
+/*31*/ ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>=>",
+/*32*/ "<<>><<>><<>><<>><<<<<<<<<<<<<<<<="
+};
+
+using namespace boost::mp11;
+
+template<typename L>
+struct test {
+ static_assert(mp_is_list<L>(), "must be a list of integral constants");
+ bool m_error;
+ test(bool b = true) : m_error(b) {}
+ operator bool(){
+ return m_error;
+ }
+ template<typename T>
+ void operator()(const T &){
+ static_assert(mp_is_list<T>(), "must be a list of two integral constants");
+ constexpr size_t i1 = mp_first<T>(); // index of first argument
+ constexpr size_t i2 = mp_second<T>();// index of second argument
+ std::cout << i1 << ',' << i2 << ',';
+ using T1 = typename boost::mp11::mp_at_c<L, i1>::value_type;
+ using T2 = typename boost::mp11::mp_at_c<L, i2>::value_type;
+ m_error &= test_safe_compare<T1, T2>(
+ boost::mp11::mp_at_c<L, i1>(), // value of first argument
+ boost::mp11::mp_at_c<L, i2>(), // value of second argument
+ test_compare_result[i1][i2]
+ );
+ }
+};
+
+int main(){
+ //TEST_EACH_VALUE_PAIR
+ test<test_values> rval(true);
+
+ using value_indices = mp_iota_c<mp_size<test_values>::value>;
+ mp_for_each<
+ mp_product<mp_list, value_indices, value_indices>
+ >(rval);
+
+ std::cout << (rval ? "success!" : "failure") << std::endl;
+ return ! rval ;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_subtract.hpp b/src/boost/libs/safe_numerics/test/test_subtract.hpp
new file mode 100644
index 000000000..832d49e23
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_subtract.hpp
@@ -0,0 +1,146 @@
+#ifndef BOOST_TEST_SUBTRACT_HPP
+#define BOOST_TEST_SUBTRACT_HPP
+
+// Copyright (c) 2015 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/range_value.hpp>
+
+template<class T1, class T2>
+bool test_subtract(
+ T1 v1,
+ T2 v2,
+ const char *av1,
+ const char *av2,
+ char expected_result
+){
+ std::cout << "testing"<< std::endl;
+ {
+ safe_t<T1> t1 = v1;
+ using result_type = decltype(t1 - v2);
+ std::cout << "safe<" << av1 << "> - " << av2 << " -> ";
+ static_assert(
+ boost::safe_numerics::is_safe<safe_t<T1> >::value,
+ "safe_t not safe!"
+ );
+ static_assert(
+ boost::safe_numerics::is_safe<result_type>::value,
+ "Expression failed to return safe type"
+ );
+
+ try{
+ // use auto to avoid checking assignment.
+ auto result = t1 - v2;
+ std::cout << make_result_display(result);
+ if(expected_result == 'x'){
+ std::cout
+ << " ! = "<< av1 << " - " << av2
+ << " failed to detect error in subtraction "
+ << std::endl;
+ t1 - v2;
+ return false;
+ }
+ std::cout << std::endl;
+ }
+ catch(const std::exception &){
+ if(expected_result == '.'){
+ std::cout
+ << " == "<< av1 << " - " << av2
+ << " erroneously detected error in subtraction "
+ << std::endl;
+ try{
+ t1 - v2;
+ }
+ catch(const std::exception &){}
+ return false;
+ }
+ }
+ }
+ {
+ safe_t<T2> t2 = v2;
+ using result_type = decltype(v1 - t2);
+ std::cout << av1 << " - " << "safe<" << av2 << "> -> ";
+ static_assert(
+ boost::safe_numerics::is_safe<safe_t<T2> >::value,
+ "safe_t not safe!"
+ );
+ static_assert(
+ boost::safe_numerics::is_safe<result_type>::value,
+ "Expression failed to return safe type"
+ );
+
+ try{
+ // use auto to avoid checking assignment.
+ auto result = v1 - t2;
+ std::cout << make_result_display(result);
+ if(expected_result == 'x'){
+ std::cout
+ << " ! = "<< av1 << " - " << av2
+ << " failed to detect error in subtraction "
+ << std::endl;
+ v1 - t2;
+ return false;
+ }
+ std::cout << std::endl;
+ }
+ catch(const std::exception &){
+ if(expected_result == '.'){
+ std::cout
+ << " == "<< av1 << " - " << av2
+ << " erroneously detected error in subtraction "
+ << std::endl;
+ try{
+ v1 - t2;
+ }
+ catch(const std::exception &){}
+ return false;
+ }
+ }
+ }
+ {
+ safe_t<T1> t1 = v1;
+ safe_t<T2> t2 = v2;
+ using result_type = decltype(t1 - t2);
+ std::cout << "safe<" << av1 << "> - " << "safe<" << av2 << "> -> ";
+ static_assert(
+ boost::safe_numerics::is_safe<result_type>::value,
+ "Expression failed to return safe type"
+ );
+ try{
+ // use auto to avoid checking assignment.
+ auto result = t1 - t2;
+ std::cout << make_result_display(result);
+ if(expected_result == 'x'){
+ std::cout
+ << " ! = "<< av1 << " - " << av2
+ << " failed to detect error in subtraction "
+ << std::endl;
+ t1 - t2;
+ return false;
+ }
+ std::cout << std::endl;
+ }
+ catch(const std::exception &){
+ if(expected_result == '.'){
+ std::cout
+ << " == "<< av1 << " - " << av2
+ << "erroneously detected error in subtraction "
+ << std::endl;
+ try{
+ t1 - t2;
+ }
+ catch(const std::exception &){}
+ return false;
+ }
+ }
+ }
+ return true; // correct result
+}
+
+#endif // BOOST_TEST_SUBTRACT
diff --git a/src/boost/libs/safe_numerics/test/test_subtract_automatic.cpp b/src/boost/libs/safe_numerics/test/test_subtract_automatic.cpp
new file mode 100644
index 000000000..dadd15d05
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_subtract_automatic.cpp
@@ -0,0 +1,64 @@
+// Copyright (c) 2012 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/automatic.hpp>
+#include "test_subtract_automatic_results.hpp"
+
+template <class T>
+using safe_t = boost::safe_numerics::safe<
+ T,
+ boost::safe_numerics::automatic
+>;
+
+#include "test_subtract.hpp"
+
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/algorithm.hpp>
+#include <boost/core/demangle.hpp>
+
+using namespace boost::mp11;
+
+template<typename L>
+struct test {
+ static_assert(mp_is_list<L>(), "must be a list of integral constants");
+ bool m_error;
+ test(bool b = true) : m_error(b) {}
+ operator bool(){
+ return m_error;
+ }
+ template<typename T>
+ void operator()(const T &){
+ static_assert(mp_is_list<T>(), "must be a list of two integral constants");
+ constexpr size_t i1 = mp_first<T>(); // index of first argument
+ constexpr size_t i2 = mp_second<T>();// index of second argument
+ std::cout << i1 << ',' << i2 << ',';
+ using T1 = typename mp_at_c<L, i1>::value_type;
+ using T2 = typename mp_at_c<L, i2>::value_type;
+ m_error &= test_subtract<T1, T2>(
+ mp_at_c<L, i1>(), // value of first argument
+ mp_at_c<L, i2>(), // value of second argument
+ boost::core::demangle(typeid(T1).name()).c_str(),
+ boost::core::demangle(typeid(T2).name()).c_str(),
+ test_subtraction_automatic_result[i1][i2]
+ );
+ }
+};
+
+int main(){
+ //TEST_EACH_VALUE_PAIR
+ test<test_values> rval(true);
+
+ using value_indices = mp_iota_c<mp_size<test_values>::value>;
+ mp_for_each<
+ mp_product<mp_list, value_indices, value_indices>
+ >(rval);
+
+ std::cout << (rval ? "success!" : "failure") << std::endl;
+ return ! rval ;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_subtract_automatic_constexpr.cpp b/src/boost/libs/safe_numerics/test/test_subtract_automatic_constexpr.cpp
new file mode 100644
index 000000000..bef25dae6
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_subtract_automatic_constexpr.cpp
@@ -0,0 +1,52 @@
+// Copyright (c) 2019 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/automatic.hpp>
+#include "test_subtract_automatic_results.hpp"
+
+template <class T>
+using safe_t = boost::safe_numerics::safe<
+ T,
+ boost::safe_numerics::automatic
+>;
+
+#include "test_subtract_constexpr.hpp"
+
+using namespace boost::mp11;
+
+template<typename First, typename Second>
+struct test_pair {
+ static const std::size_t i = First();
+ static const std::size_t j = Second();
+ constexpr static const bool value = test_subtract_constexpr(
+ mp_at_c<test_values, i>()(),
+ mp_at_c<test_values, j>()(),
+ test_subtraction_automatic_result[i][j]
+ );
+};
+
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/algorithm.hpp>
+
+int main(){
+ using namespace boost::mp11;
+
+ using value_indices = mp_iota_c<mp_size<test_values>::value>;
+
+ static_assert(
+ mp_all_of<
+ mp_product<
+ test_pair,
+ value_indices,
+ value_indices
+ >,
+ mp_to_bool
+ >(),
+ "all values for all integer types correctly subtracted"
+ );
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_subtract_automatic_results.hpp b/src/boost/libs/safe_numerics/test/test_subtract_automatic_results.hpp
new file mode 100644
index 000000000..afa59e407
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_subtract_automatic_results.hpp
@@ -0,0 +1,65 @@
+#ifndef BOOST_SAFE_NUMERICS_TEST_ADD_AUTOMATIC_RESULTS_HPP
+#define BOOST_SAFE_NUMERICS_TEST_ADD_AUTOMATIC_RESULTS_HPP
+
+// Copyright (c) 2019 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include "test_values.hpp"
+
+// note: same test matrix as used in test_checked. Here we test all combinations
+// safe and unsafe integers. in test_checked we test all combinations of
+// integer primitives
+
+constexpr const char *test_subtraction_automatic_result[
+ boost::mp11::mp_size<test_values>::value
+] = {
+// 0 0 0 0
+// 012345670123456701234567012345670
+// 012345678901234567890123456789012
+/* 0*/ "..............x...............xx.",
+/* 1*/ "..............x...............xx.",
+/* 2*/ ".............x...............xxx.",
+/* 3*/ "..............................xx.",
+/* 4*/ "..............x...............xx.",
+/* 5*/ "..............x...............xx.",
+/* 6*/ ".............x...............xxx.",
+/* 7*/ "..............................xx.",
+
+/* 8*/ "..............x...............xx.",
+/* 9*/ "..............x...............xx.",
+/*10*/ ".............x...............xxx.",
+/*11*/ "..............................xx.",
+/*12*/ "..............x...............xx.",
+/*13*/ "..xx..xx..xx..xx..............xx.",
+/*14*/ "xx..xx..xx..xx..xxxxxxxxxxxxxxxx.",
+/*15*/ "..............................xx.",
+
+// 0 0 0 0
+// 012345670123456701234567012345670
+// 012345678901234567890123456789012
+/*16*/ "..............x...............xx.",
+/*17*/ "..............x...............xx.",
+/*18*/ "..............x...............xx.",
+/*19*/ "..............x...............xx.",
+/*20*/ "..............x...............xx.",
+/*21*/ "..............x...............xx.",
+/*22*/ "..............x...............xx.",
+/*23*/ "..............x...............xx.",
+
+/*24*/ "..............x...............xx.",
+/*25*/ "..............x...............xx.",
+/*26*/ "..............x...............xx.",
+/*27*/ "..............x...............xx.",
+/*28*/ "..............x...............xx.",
+/*29*/ "..xx..xx..xx..xx..............xx.",
+/*30*/ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+/*31*/ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+/*32*/ "..............x...............xx."
+};
+
+
+#endif
+
diff --git a/src/boost/libs/safe_numerics/test/test_subtract_constexpr.hpp b/src/boost/libs/safe_numerics/test/test_subtract_constexpr.hpp
new file mode 100644
index 000000000..a82c171e2
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_subtract_constexpr.hpp
@@ -0,0 +1,30 @@
+#ifndef BOOST_TEST_SUBTRACT_CONSTEXPR_HPP
+#define BOOST_TEST_SUBTRACT_CONSTEXPR_HPP
+
+// Copyright (c) 2019 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/safe_numerics/safe_integer.hpp>
+
+template<class T1, class T2>
+constexpr bool test_subtract_constexpr(
+ T1 v1,
+ T2 v2,
+ char expected_result
+){
+ using namespace boost::safe_numerics;
+ // if we don't expect the operation to pass, we can't
+ // check the constexpr version of the calculation so
+ // just return success.
+ if(expected_result == 'x')
+ return true;
+ safe_t<T1>(v1) - v2;
+ v1 - safe_t<T2>(v2);
+ safe_t<T1>(v1) - safe_t<T2>(v2);
+ return true; // correct result
+}
+
+#endif // BOOST_TEST_SUBTRACT_CONSTEXPR_HPP
diff --git a/src/boost/libs/safe_numerics/test/test_subtract_native.cpp b/src/boost/libs/safe_numerics/test/test_subtract_native.cpp
new file mode 100644
index 000000000..2f622a812
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_subtract_native.cpp
@@ -0,0 +1,65 @@
+// Copyright (c) 2012 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/automatic.hpp>
+#include "test_subtract_native_results.hpp"
+
+template <class T>
+using safe_t = boost::safe_numerics::safe<
+ T,
+ boost::safe_numerics::native
+>;
+#include "test_subtract.hpp"
+
+using namespace boost::mp11;
+
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/algorithm.hpp>
+#include <boost/core/demangle.hpp>
+
+using namespace boost::mp11;
+
+template<typename L>
+struct test {
+ static_assert(mp_is_list<L>(), "must be a list of integral constants");
+ bool m_error;
+ test(bool b = true) : m_error(b) {}
+ operator bool(){
+ return m_error;
+ }
+ template<typename T>
+ void operator()(const T &){
+ static_assert(mp_is_list<T>(), "must be a list of two integral constants");
+ constexpr size_t i1 = mp_first<T>(); // index of first argument
+ constexpr size_t i2 = mp_second<T>();// index of second argument
+ std::cout << i1 << ',' << i2 << ',';
+ using T1 = typename mp_at_c<L, i1>::value_type;
+ using T2 = typename mp_at_c<L, i2>::value_type;
+ m_error &= test_subtract(
+ boost::mp11::mp_at_c<L, i1>()(), // value of first argument
+ boost::mp11::mp_at_c<L, i2>()(), // value of second argument
+ boost::core::demangle(typeid(T1).name()).c_str(),
+ boost::core::demangle(typeid(T2).name()).c_str(),
+ test_subtraction_native_result[i1][i2]
+ );
+ }
+};
+
+int main(){
+ //TEST_EACH_VALUE_PAIR
+ test<test_values> rval(true);
+
+ using value_indices = mp_iota_c<mp_size<test_values>::value>;
+ mp_for_each<
+ mp_product<mp_list, value_indices, value_indices>
+ >(rval);
+
+ std::cout << (rval ? "success!" : "failure") << std::endl;
+ return ! rval ;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_subtract_native_constexpr.cpp b/src/boost/libs/safe_numerics/test/test_subtract_native_constexpr.cpp
new file mode 100644
index 000000000..3d8eae630
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_subtract_native_constexpr.cpp
@@ -0,0 +1,53 @@
+// Copyright (c) 2019Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/native.hpp>
+
+#include "test_subtract_native_results.hpp"
+
+template <class T>
+using safe_t = boost::safe_numerics::safe<
+ T,
+ boost::safe_numerics::native
+>;
+
+#include "test_subtract_constexpr.hpp"
+
+using namespace boost::mp11;
+
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/algorithm.hpp>
+
+template<typename First, typename Second>
+struct test_pair {
+ static const std::size_t i = First();
+ static const std::size_t j = Second();
+ constexpr static const bool value = test_subtract_constexpr(
+ mp_at_c<test_values, i>()(),
+ mp_at_c<test_values, j>()(),
+ test_subtraction_native_result[i][j]
+ );
+};
+
+int main(){
+ using namespace boost::mp11;
+
+ using value_indices = mp_iota_c<mp_size<test_values>::value>;
+
+ static_assert(
+ mp_all_of<
+ mp_product<
+ test_pair,
+ value_indices,
+ value_indices
+ >,
+ mp_to_bool
+ >(),
+ "all values for all integer types correctly subtracted"
+ );
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_subtract_native_results.hpp b/src/boost/libs/safe_numerics/test/test_subtract_native_results.hpp
new file mode 100644
index 000000000..030b6278c
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_subtract_native_results.hpp
@@ -0,0 +1,48 @@
+#include "test_values.hpp"
+
+constexpr const char *test_subtraction_native_result[
+ boost::mp11::mp_size<test_values>::value
+] = {
+// 0 0 0 0
+// 012345670123456701234567012345670
+// 012345678901234567890123456789012
+/* 0*/ "..........x...x..........xxx.xxx.",
+/* 1*/ "..........x...x..........xxx.xxx.",
+/* 2*/ ".........x...x..........xxxxxxxx.",
+/* 3*/ "........................xxxxxxxx.",
+/* 4*/ "..........x...x..........xxx.xxx.",
+/* 5*/ "..........x...x..........xxx.xxx.",
+/* 6*/ ".........x...x..........xxxxxxxx.",
+/* 7*/ "........................xxxxxxxx.",
+
+/* 8*/ "..........x...x..........xxx.xxx.",
+/* 9*/ "..xx..xx..xx..x...........xx.xxx.",
+/*10*/ "xx..xx..xx...x..xxxxxxxxxxxxxxxx.",
+/*11*/ "........................xxxxxxxx.",
+/*12*/ "..............x..............xxx.",
+/*13*/ "..xx..xx..xx..xx..............xx.",
+/*14*/ "xx..xx..xx..xx..xxxxxxxxxxxxxxxx.",
+/*15*/ "............................xxxx.",
+
+// 0 0 0 0
+// 012345670123456701234567012345670
+// 012345678901234567890123456789012
+/*16*/ "..........x...x..........xxx.xxx.",
+/*17*/ "..........x...x..........xxx.xxx.",
+/*18*/ "..........x...x..........xxx.xxx.",
+/*19*/ "..........x...x..........xxx.xxx.",
+/*20*/ "..........x...x..........xxx.xxx.",
+/*21*/ "..........x...x..........xxx.xxx.",
+/*22*/ "..........x...x..........xxx.xxx.",
+/*23*/ "..........x...x..........xxx.xxx.",
+
+/*24*/ ".xxx.xxx.xxx..x..xxx.xxx.xxx.xxx.",
+/*25*/ "..xx..xx..xx..x...........xx.xxx.",
+/*26*/ "..xx..xx..xx..x............x.xxx.",
+/*27*/ "..xx..xx..xx..x..............xxx.",
+/*28*/ ".xxx.xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
+/*29*/ "..xx..xx..xx..xx..............xx.",
+/*30*/ "..xx..xx..xx..xx...............x.",
+/*31*/ "..xx..xx..xx..xx.................",
+/*32*/ "..........x...x.........xxxxxxxx."
+};
diff --git a/src/boost/libs/safe_numerics/test/test_trap.cpp b/src/boost/libs/safe_numerics/test/test_trap.cpp
new file mode 100644
index 000000000..fa067f465
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_trap.cpp
@@ -0,0 +1,44 @@
+// Copyright (c) 2012 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// testing trap
+
+// this is a compile only test - but since many build systems
+// can't handle a compile-only test - make sure it passes trivially.
+
+#include <boost/safe_numerics/exception_policies.hpp>
+#include <boost/safe_numerics/safe_integer.hpp>
+
+using namespace boost::safe_numerics;
+template <typename T> // T is char, int, etc data type
+using safe_t = safe<
+ T,
+ native,
+ loose_trap_policy // use for compiling and running tests
+>;
+
+template<typename T, typename U>
+void test(){
+ safe_t<T> t;
+ safe_t<U> u;
+ t + u;
+ t - u;
+ t * u;
+ t / u; // could fail regardless of data type
+ t % u; // could fail regardless of data type
+ t << u;
+ t >> u;
+ t | u;
+ t & u;
+ t ^ u;
+}
+int main(int, char *[]){
+ test<std::int8_t, std::int8_t>(); // should compile
+ test<std::int16_t, std::int16_t>(); // should compile
+ test<std::int32_t, std::int32_t>(); // should fail to compile
+ test<std::int64_t, std::int64_t>(); // should fail to compile
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_values.hpp b/src/boost/libs/safe_numerics/test/test_values.hpp
new file mode 100644
index 000000000..de5336110
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_values.hpp
@@ -0,0 +1,71 @@
+#ifndef BOOST_SAFE_NUMERICS_TEST_VALUES_HPP
+#define BOOST_SAFE_NUMERICS_TEST_VALUES_HPP
+
+// test_values.hpp
+//
+// Copyright (c) 2012 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <cstdint>
+#include <type_traits> // integral_constant
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/algorithm.hpp>
+
+#define TEST_VALUE(type, value) std::integral_constant<type,(type)value>
+
+using test_values = boost::mp11::mp_list<
+ TEST_VALUE(std::int8_t,0x01),
+ TEST_VALUE(std::int8_t,0x7f),
+ TEST_VALUE(std::int8_t,0x80),
+ TEST_VALUE(std::int8_t,0xff),
+ TEST_VALUE(std::int16_t,0x0001),
+ TEST_VALUE(std::int16_t,0x7fff),
+ TEST_VALUE(std::int16_t,0x8000),
+ TEST_VALUE(std::int16_t,0xffff),
+ TEST_VALUE(std::int32_t,0x00000001),
+ TEST_VALUE(std::int32_t,0x7fffffff),
+ TEST_VALUE(std::int32_t,0x80000000),
+ TEST_VALUE(std::int32_t,0xffffffff),
+ TEST_VALUE(std::int64_t,0x0000000000000001),
+ TEST_VALUE(std::int64_t,0x7fffffffffffffff),
+ TEST_VALUE(std::int64_t,0x8000000000000000),
+ TEST_VALUE(std::int64_t,0xffffffffffffffff),
+ TEST_VALUE(std::uint8_t,0x01),
+ TEST_VALUE(std::uint8_t,0x7f),
+ TEST_VALUE(std::uint8_t,0x80),
+ TEST_VALUE(std::uint8_t,0xff),
+ TEST_VALUE(std::uint16_t,0x0001),
+ TEST_VALUE(std::uint16_t,0x7fff),
+ TEST_VALUE(std::uint16_t,0x8000),
+ TEST_VALUE(std::uint16_t,0xffff),
+ TEST_VALUE(std::uint32_t,0x00000001),
+ TEST_VALUE(std::uint32_t,0x7fffffff),
+ TEST_VALUE(std::uint32_t,0x80000000),
+ TEST_VALUE(std::uint32_t,0xffffffff),
+ TEST_VALUE(std::uint64_t,0x0000000000000001),
+ TEST_VALUE(std::uint64_t,0x7fffffffffffffff),
+ TEST_VALUE(std::uint64_t,0x8000000000000000),
+ TEST_VALUE(std::uint64_t,0xffffffffffffffff),
+ TEST_VALUE(std::int8_t,0x0) // uh oh - breaks test_types
+>;
+
+/*
+template<typename T>
+using extract_value_type = typename T::value_type;
+using test_types = boost::mp11:: mp_unique<
+ boost::mp11::mp_transform<
+ extract_value_type,
+ test_values
+ >
+>;
+*/
+
+using test_types = boost::mp11::mp_list<
+ std::int8_t, std::int16_t, std::int32_t, std::int64_t,
+ std::uint8_t, std::uint16_t, std::uint32_t, std::uint64_t
+>;
+
+#endif
diff --git a/src/boost/libs/safe_numerics/test/test_xor.hpp b/src/boost/libs/safe_numerics/test/test_xor.hpp
new file mode 100644
index 000000000..4788d475d
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_xor.hpp
@@ -0,0 +1,176 @@
+#ifndef BOOST_TEST_XOR_HPP
+#define BOOST_TEST_XOR_HPP
+
+// Copyright (c) 2015 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+#include <iosfwd>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/range_value.hpp>
+
+template<class T1, class T2>
+bool test_xor(
+ T1 v1,
+ T2 v2,
+ const char *av1,
+ const char *av2,
+ char expected_result
+){
+ std::cout << "testing"<< std::endl;
+ {
+ safe_t<T1> t1 = v1;
+ using result_type = decltype(t1 ^ v2);
+ std::cout << "safe<" << av1 << "> ^ " << av2 << " -> ";
+ static_assert(
+ boost::safe_numerics::is_safe<safe_t<T1> >::value,
+ "safe_t not safe!"
+ );
+ static_assert(
+ boost::safe_numerics::is_safe<result_type>::value,
+ "Expression failed to return safe type"
+ );
+
+ try{
+ // use auto to avoid checking assignment.
+ auto result = t1 ^ v2;
+ std::cout << make_result_display(result);
+ if(expected_result == 'x'){
+ std::cout
+ << " ! = "<< av1 << " ^ " << av2
+ << " failed to detect error in xor operation"
+ << std::endl;
+ t1 ^ v2;
+ return false;
+ }
+ else
+ if(result != (v1 ^ v2)){
+ std::cout
+ << " ! = "<< av1 << " ^ " << av2
+ << " incorrect result in xor operation"
+ << std::endl;
+ t1 ^ v2;
+ boost::safe_numerics::safe_compare::equal(base_value(result), (v1 ^ v2));
+ return false;
+ }
+ std::cout << std::endl;
+ }
+ catch(const std::exception &){
+ if(expected_result == '.'){
+ std::cout
+ << " == "<< av1 << " ^ " << av2
+ << " erroneously detected error in xor operation"
+ << std::endl;
+ try{
+ t1 ^ v2;
+ }
+ catch(const std::exception &){}
+ return false;
+ }
+ }
+ }
+ {
+ safe_t<T2> t2 = v2;
+ using result_type = decltype(v1 ^ t2);
+ std::cout << av1 << " ^ " << "safe<" << av2 << "> -> ";
+ static_assert(
+ boost::safe_numerics::is_safe<safe_t<T2> >::value,
+ "safe_t not safe!"
+ );
+ static_assert(
+ boost::safe_numerics::is_safe<result_type>::value,
+ "Expression failed to return safe type"
+ );
+
+ try{
+ // use auto to avoid checking assignment.
+ auto result = v1 ^ t2;
+ std::cout << make_result_display(result);
+ if(expected_result == 'x'){
+ std::cout
+ << " ! = "<< av1 << " ^ " << av2
+ << " failed to detect error in and operation"
+ << std::endl;
+ v1 ^ t2;
+ return false;
+ }
+ else
+ if(result != (v1 ^ v2)){
+ std::cout
+ << " ! = "<< av1 << " ^ " << av2
+ << " incorrect result in xor operation"
+ << std::endl;
+ v1 ^ t2;
+ return false;
+ }
+ std::cout << std::endl;
+ }
+ catch(const std::exception &){
+ if(expected_result == '.'){
+ std::cout
+ << " == "<< av1 << " ^ " << av2
+ << " erroneously detected error in and operation"
+ << std::endl;
+ try{
+ v1 ^ t2;
+ }
+ catch(const std::exception &){}
+ return false;
+ }
+ }
+ }
+ {
+ safe_t<T1> t1 = v1;
+ safe_t<T2> t2 = v2;
+ using result_type = decltype(t1 ^ t2);
+ std::cout << "safe<" << av1 << "> ^ " << "safe<" << av2 << "> -> ";
+ static_assert(
+ boost::safe_numerics::is_safe<result_type>::value,
+ "Expression failed to return safe type"
+ );
+
+ try{
+ // use auto to avoid checking assignment.
+ auto result = t1 ^ t2;
+ std::cout << make_result_display(result);
+ if(expected_result == 'x'){
+ std::cout
+ << " ! = "<< av1 << " ^ " << av2
+ << " failed to detect error in and operation"
+ << std::endl;
+ t1 ^ t2;
+ return false;
+ }
+ else
+ if(result != (v1 ^ v2)){
+ std::cout
+ << " ! = "<< av1 << " ^ " << av2
+ << " incorrect result in xor operation"
+ << std::endl;
+ t1 ^ t2;
+ return false;
+ }
+ std::cout << std::endl;
+ }
+ catch(const std::exception &){
+ if(expected_result == '.'){
+ std::cout
+ << " == "<< av1 << " ^ " << av2
+ << " erroneously detected error in and operation"
+ << std::endl;
+ try{
+ t1 ^ t2;
+ }
+ catch(const std::exception &){}
+ return false;
+ }
+ }
+ }
+ return true; // correct result
+}
+
+#endif // BOOST_TEST_XOR_HPP
diff --git a/src/boost/libs/safe_numerics/test/test_xor_automatic.cpp b/src/boost/libs/safe_numerics/test/test_xor_automatic.cpp
new file mode 100644
index 000000000..4777f358a
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_xor_automatic.cpp
@@ -0,0 +1,60 @@
+// Copyright (c) 2012 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/automatic.hpp>
+
+template <class T>
+using safe_t = boost::safe_numerics::safe<
+ T,
+ boost::safe_numerics::automatic
+>;
+#include "test_xor.hpp"
+#include "test_values.hpp"
+
+#include <boost/mp11/algorithm.hpp>
+#include <boost/core/demangle.hpp>
+
+using namespace boost::mp11;
+
+template<typename L>
+struct test {
+ static_assert(mp_is_list<L>(), "must be a list of integral constants");
+ bool m_error;
+ test(bool b = true) : m_error(b) {}
+ operator bool(){
+ return m_error;
+ }
+ template<typename T>
+ void operator()(const T &){
+ static_assert(mp_is_list<T>(), "must be a list of two integral constants");
+ constexpr size_t i1 = mp_first<T>(); // index of first argument
+ constexpr size_t i2 = mp_second<T>();// index of second argument
+ std::cout << i1 << ',' << i2 << ',';
+ using T1 = typename mp_at_c<L, i1>::value_type;
+ using T2 = typename mp_at_c<L, i2>::value_type;
+ m_error &= test_xor<T1, T2>(
+ mp_at_c<L, i1>()(), // value of first argument
+ mp_at_c<L, i2>()(), // value of second argument
+ boost::core::demangle(typeid(T1).name()).c_str(),
+ boost::core::demangle(typeid(T2).name()).c_str(),
+ '.'
+ );
+ }
+};
+
+int main(){
+ //TEST_EACH_VALUE_PAIR
+ test<test_values> rval(true);
+
+ using value_indices = mp_iota_c<mp_size<test_values>::value>;
+ mp_for_each<
+ mp_product<mp_list, value_indices, value_indices>
+ >(rval);
+
+ std::cout << (rval ? "success!" : "failure") << std::endl;
+ return ! rval ;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_xor_automatic_constexpr.cpp b/src/boost/libs/safe_numerics/test/test_xor_automatic_constexpr.cpp
new file mode 100644
index 000000000..4a8038f3a
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_xor_automatic_constexpr.cpp
@@ -0,0 +1,52 @@
+// Copyright (c) 2019 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/automatic.hpp>
+
+template <class T>
+using safe_t = boost::safe_numerics::safe<
+ T,
+ boost::safe_numerics::automatic
+>;
+
+#include "test_xor_constexpr.hpp"
+#include "test_values.hpp"
+
+using namespace boost::mp11;
+
+template<typename First, typename Second>
+struct test_pair {
+ static const std::size_t i = First();
+ static const std::size_t j = Second();
+ constexpr static const bool value = test_xor_constexpr(
+ mp_at_c<test_values, i>()(),
+ mp_at_c<test_values, j>()(),
+ '.'
+ );
+};
+
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/algorithm.hpp>
+
+int main(){
+ using namespace boost::mp11;
+
+ using value_indices = mp_iota_c<mp_size<test_values>::value>;
+
+ static_assert(
+ mp_all_of<
+ mp_product<
+ test_pair,
+ value_indices,
+ value_indices
+ >,
+ mp_to_bool
+ >(),
+ "all values for all integer types correctly xor'ed"
+ );
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_xor_constexpr.hpp b/src/boost/libs/safe_numerics/test/test_xor_constexpr.hpp
new file mode 100644
index 000000000..c6cfb65cb
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_xor_constexpr.hpp
@@ -0,0 +1,30 @@
+#ifndef BOOST_TEST_XOR_CONSTEXPR_HPP
+#define BOOST_TEST_XOR_CONSTEXPR_HPP
+
+// Copyright (c) 2019 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/safe_numerics/safe_integer.hpp>
+
+template<class T1, class T2>
+constexpr bool test_xor_constexpr(
+ T1 v1,
+ T2 v2,
+ char expected_result
+){
+ using namespace boost::safe_numerics;
+ // if we don't expect the operation to pass, we can't
+ // check the constexpr version of the calculation so
+ // just return success.
+ if(expected_result == 'x')
+ return true;
+ safe_t<T1>(v1) ^ v2;
+ v1 ^ safe_t<T2>(v2);
+ safe_t<T1>(v1) ^ safe_t<T2>(v2);
+ return true; // correct result
+}
+
+#endif // BOOST_TEST_XOR_CONSTEXPR_HPP
diff --git a/src/boost/libs/safe_numerics/test/test_xor_native.cpp b/src/boost/libs/safe_numerics/test/test_xor_native.cpp
new file mode 100644
index 000000000..10288f14a
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_xor_native.cpp
@@ -0,0 +1,61 @@
+// Copyright (c) 2012 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+
+#include <boost/safe_numerics/safe_integer.hpp>
+
+template <class T>
+using safe_t = boost::safe_numerics::safe<
+ T,
+ boost::safe_numerics::native
+>;
+#include "test_xor.hpp"
+#include "test_values.hpp"
+
+#include <boost/mp11/algorithm.hpp>
+#include <boost/core/demangle.hpp>
+
+using namespace boost::mp11;
+
+template<typename L>
+struct test {
+ static_assert(mp_is_list<L>(), "must be a list of integral constants");
+ bool m_error;
+ test(bool b = true) : m_error(b) {}
+ operator bool(){
+ return m_error;
+ }
+ template<typename T>
+ void operator()(const T &){
+ static_assert(mp_is_list<T>(), "must be a list of two integral constants");
+ constexpr size_t i1 = mp_first<T>(); // index of first argument
+ constexpr size_t i2 = mp_second<T>();// index of second argument
+ std::cout << i1 << ',' << i2 << ',';
+ using T1 = typename mp_at_c<L, i1>::value_type;
+ using T2 = typename mp_at_c<L, i2>::value_type;
+ m_error &= test_xor<T1, T2>(
+ mp_at_c<L, i1>(), // value of first argument
+ mp_at_c<L, i2>(), // value of second argument
+ boost::core::demangle(typeid(T1).name()).c_str(),
+ boost::core::demangle(typeid(T2).name()).c_str(),
+ '.'
+ );
+ }
+};
+
+int main(){
+ //TEST_EACH_VALUE_PAIR
+ test<test_values> rval(true);
+
+ using value_indices = mp_iota_c<mp_size<test_values>::value>;
+ mp_for_each<
+ mp_product<mp_list, value_indices, value_indices>
+ >(rval);
+
+ std::cout << (rval ? "success!" : "failure") << std::endl;
+ return ! rval ;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_xor_native_constexpr.cpp b/src/boost/libs/safe_numerics/test/test_xor_native_constexpr.cpp
new file mode 100644
index 000000000..b917f7697
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_xor_native_constexpr.cpp
@@ -0,0 +1,51 @@
+// Copyright (c) 2019 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/native.hpp>
+
+template <class T>
+using safe_t = boost::safe_numerics::safe<
+ T,
+ boost::safe_numerics::native
+>;
+
+#include "test_xor_constexpr.hpp"
+#include "test_values.hpp"
+
+using namespace boost::mp11;
+
+template<typename First, typename Second>
+struct test_pair {
+ static const std::size_t i = First();
+ static const std::size_t j = Second();
+ constexpr static const bool value = test_xor_constexpr(
+ mp_at_c<test_values, i>()(),
+ mp_at_c<test_values, j>()(),
+ '.'
+ );
+};
+
+#include <boost/mp11/list.hpp>
+#include <boost/mp11/algorithm.hpp>
+
+int main(){
+ using namespace boost::mp11;
+ using value_indices = mp_iota_c<mp_size<test_values>::value>;
+
+ static_assert(
+ mp_all_of<
+ mp_product<
+ test_pair,
+ value_indices,
+ value_indices
+ >,
+ mp_to_bool
+ >(),
+ "all values for all integer types correctly xor'ed"
+ );
+ return 0;
+}
diff --git a/src/boost/libs/safe_numerics/test/test_z.cpp b/src/boost/libs/safe_numerics/test/test_z.cpp
new file mode 100644
index 000000000..d7035c293
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_z.cpp
@@ -0,0 +1,793 @@
+
+#if 0
+auto val()
+{
+ return -0xFFFFFFFF;
+}
+
+#include <stdexcept>
+#include <iostream>
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/safe_integer_literal.hpp>
+
+void val0(){
+ const boost::safe_numerics::safe<unsigned int> x{0};
+ std::cout << x << std::endl;
+ std::cout << -x << std::endl;
+ auto y = -x;
+ std::cout << y << std::endl;
+}
+
+constexpr boost::safe_numerics::safe<unsigned int> val1()
+{
+ constexpr boost::safe_numerics::safe<unsigned int> x = 0xFFFFFFFF;
+ return -x;
+}
+constexpr boost::safe_numerics::safe<unsigned int> val2()
+{
+ boost::safe_numerics::safe<unsigned int> x = - boost::safe_numerics::safe_unsigned_literal<0xFFFFFFFF>();
+ return x;
+}
+
+constexpr boost::safe_numerics::safe<unsigned int> val3()
+{
+ return - boost::safe_numerics::safe_unsigned_literal<0xFFFFFFFF>();
+}
+
+int main(){
+ val0();
+ std::cout << val1() << std::endl;
+ std::cout << val2() << std::endl;
+ std::cout << val3() << std::endl;
+ return 0;
+}
+
+// test utility
+#include <boost/safe_numerics/utility.hpp>
+
+int main(){
+ using namespace boost::safe_numerics;
+ using x = unsigned_stored_type<0, 42>;
+ print_type<x> p1;
+
+ return 0;
+}
+
+// test automatic type promotion
+#include <boost/safe_numerics/automatic.hpp>
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <type_traits>
+#include <cstdint>
+#include <iostream>
+
+int main(){
+ using namespace boost::safe_numerics;
+ using ar = automatic::addition_result<std::uint8_t, std::uint8_t>;
+ static_assert(
+ std::is_same<ar::type, std::uint16_t>::value,
+ "sum of two 8 bit unsigned integers should fit in on 16 bit unsigned integer"
+ );
+ return 0;
+}
+
+
+// test automatic type promotion
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/safe_integer_range.hpp>
+#include <boost/safe_numerics/safe_integer_literal.hpp>
+#include <boost/safe_numerics/automatic.hpp>
+#include <type_traits>
+#include <cstdint>
+#include <iostream>
+
+int main(){
+ using namespace boost::safe_numerics;
+ unsigned char t1 = 1;
+ constexpr const safe_unsigned_literal<42, automatic, default_exception_policy> v2;
+ using result_type = decltype(t1 + v2);
+
+ static_assert(
+ std::is_same<
+ result_type,
+ safe_unsigned_range<42, 297, automatic, default_exception_policy>
+ >::value,
+ "result type should have a range 42-297"
+ );
+ return 0;
+}
+void f1(){
+ using namespace boost::safe_numerics;
+ constexpr safe<int> j = 0;
+ constexpr safe<int> k = 3;
+ constexpr safe<int> l = j + k; // compile error
+}
+
+void f2(){
+ using namespace boost::safe_numerics;
+ constexpr safe<int> j = boost::safe_numerics::safe_signed_literal<0>();
+ constexpr safe<int> k = boost::safe_numerics::safe_signed_literal<3>();
+ constexpr safe<int> l = j + k; // compile error
+}
+
+void f3(){
+ using namespace boost::safe_numerics;
+ constexpr auto j = safe_signed_literal<0, native, loose_trap_policy>();
+ constexpr auto k = safe_signed_literal<3>();
+ constexpr const safe<int> l = j + k;
+}
+
+void f4(){
+ using namespace boost::safe_numerics;
+ safe_signed_literal<0, native, loose_trap_policy> j;
+ safe_signed_literal<3> k;
+ constexpr auto l = safe_signed_literal<3>();
+ constexpr const safe<int> l2 = j + k;
+}
+
+#include <boost/safe_numerics/interval.hpp>
+
+int main(){
+ return 0;
+}
+
+#include <boost/safe_numerics/utility.hpp>
+#include <boost/safe_numerics/cpp.hpp>
+#include <boost/safe_numerics/safe_common.hpp>
+
+using pic16_promotion = boost::safe_numerics::cpp<
+ 8, // char
+ 8, // short
+ 8, // int
+ 16, // long
+ 32 // long long
+>;
+
+#include <type_traits>
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/range_value.hpp>
+#include <iostream>
+
+int main(){
+ using namespace boost::safe_numerics;
+ static_assert(
+ std::is_literal_type<safe<int>>::value,
+ "safe type is a literal type"
+ );
+ static_assert(
+ std::is_literal_type<interval<int>>::value,
+ "interval type is a literal type"
+ );
+ static_assert(
+ std::is_literal_type<interval<
+ safe<int>
+ >>::value,
+ "interval of safe types is a literal type"
+ );
+ static_assert(
+ std::is_literal_type<range_value<
+ safe<int>
+ >>::value,
+ "range_value of safe types is a literal type"
+ );
+ safe<int> x = 42;
+ std::cout << make_range_value(x);
+ return 0;
+}
+
+auto val()
+{
+ return -0xFFFFFFFF;
+}
+
+#include <stdexcept>
+#include <iostream>
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/safe_integer_literal.hpp>
+
+void val0(){
+ const boost::safe_numerics::safe<unsigned int> x{0};
+ std::cout << x << std::endl;
+ std::cout << -x << std::endl;
+ auto y = -x;
+ std::cout << y << std::endl;
+}
+
+constexpr boost::safe_numerics::safe<unsigned int> val1(){
+ constexpr boost::safe_numerics::safe<unsigned int> x = 0xFFFFFFFF;
+ return -x;
+}
+constexpr boost::safe_numerics::safe<unsigned int> val2(){
+ const boost::safe_numerics::safe<unsigned int> x
+ = -boost::safe_numerics::safe_unsigned_literal<0xFFFFFFFF>();
+ return x;
+}
+constexpr boost::safe_numerics::safe<unsigned int> val3(){
+ return - boost::safe_numerics::safe_unsigned_literal<0xFFFFFFFF>();
+}
+
+int main(){
+ val0();
+ std::cout << val1() << std::endl;
+ std::cout << val2() << std::endl;
+ std::cout << val3() << std::endl;
+ return 0;
+}
+
+#include <boost/logic/tribool.hpp>
+#include <boost/safe_integer/checked_integer.hpp>
+#include <boost/safe_integer/checked_result.hpp>
+#include <boost/safe_integer/checked_result_operations.hpp>
+#include <boost/safe_integer/interval.hpp>
+
+namespace boost {
+namespace safe_numerics {
+
+template<class EP, typename R>
+constexpr void
+dispatch(const checked_result<R> & cr){
+}
+
+template<class T>
+constexpr T base_value(const T & t){
+ return t;
+}
+
+template<typename R, R Min, R Max, typename E>
+struct validate_detail {
+
+ constexpr static const interval<checked_result<R>> t_interval{
+ checked::cast<R>(base_value(std::numeric_limits<T>::min())),
+ checked::cast<R>(base_value(std::numeric_limits<T>::max()))
+ };
+ constexpr static const interval<checked_result<R>> r_interval{Min, Max};
+
+/*
+ static_assert(
+ ! static_cast<bool>(r_interval.excludes(t_interval)),
+ "ranges don't overlap: can't cast"
+ );
+*/
+
+ struct exception_possible {
+ constexpr static R return_value(
+ const T & t
+ ){
+ static_assert(
+ ! static_cast<bool>(r_interval.includes(t_interval)),
+ "exeption not possible"
+ );
+ // INT08-C
+ const checked_result<R> r = checked::cast<R>(t);
+ dispatch<E>(r);
+ return base_value(r);
+ }
+ };
+ struct exception_not_possible {
+ constexpr static R return_value(
+ const T & t
+ ){
+ static_assert(
+ static_cast<bool>(r_interval.includes(t_interval)),
+ "exeption not possible"
+ );
+ return static_cast<R>(t);
+ }
+ };
+
+ static R return_value(const T & t){
+ return std::conditional<
+ static_cast<bool>(r_interval.includes(t_interval)),
+ exception_not_possible,
+ exception_possible
+ >::type::return_value(t);
+ }
+};
+
+template<typename R, R Min, R Max, typename T>
+bool test1(const T & t){
+ const interval<checked_result<R>> t_interval{
+ checked::cast<R>(base_value(std::numeric_limits<T>::min())),
+ checked::cast<R>(base_value(std::numeric_limits<T>::max()))
+ };
+ const interval<checked_result<R>> r_interval{Min, Max};
+
+/*
+ static_assert(
+ ! static_cast<bool>(r_interval.excludes(t_interval)),
+ "ranges don't overlap: can't cast"
+ );
+*/
+ const boost::logic::tribool tb1 = r_interval.includes(t_interval);
+ const bool x1 = tb1;
+
+ const boost::logic::tribool tb2 = r_interval.excludes(t_interval);
+ const bool x2 = tb2;
+ return x2;
+}
+
+
+} // safe_numerics
+} // boost
+
+int main(){
+ unsigned int x1 = boost::safe_numerics::test1<
+ unsigned int, 0, 100, signed char
+ >(-1);
+ bool x2 = boost::safe_numerics::validate_detail<
+ unsigned int, 0, 100, signed char, void
+ >::return_value(-1);
+ return 0;
+}
+
+using uint8_t = unsigned char;
+
+enum class safe_numerics_error : uint8_t {
+ success = 0,
+ failure, // result is above representational maximum
+ error_count
+};
+
+template<typename R>
+struct checked_result {
+ const safe_numerics_error m_e;
+ const union {
+ const R m_r;
+ char const * const m_msg;
+ };
+ constexpr /*explicit*/ checked_result(const R & r) :
+ m_e(safe_numerics_error::success),
+ m_r(r)
+ {}
+ constexpr /*explicit*/ checked_result(const safe_numerics_error & e) :
+ m_e(e),
+ m_msg("")
+ {}
+};
+
+// integers addition
+template<class T>
+constexpr inline checked_result<T> operator+(
+ const checked_result<T> & t,
+ const checked_result<T> & u
+){
+#if 1 // compile fails
+ constexpr const safe_numerics_error x[2][2]{
+ // t == success
+ {
+ // u == ...
+ safe_numerics_error::success,
+ safe_numerics_error::failure
+ },
+ // t == positive_overflow_error,
+ {
+ // u == ...
+ safe_numerics_error::success,
+ safe_numerics_error::failure
+ }
+ };
+
+ // "Constexpr variable 'e' must be initialized by a constant expression"
+ constexpr const safe_numerics_error e = x
+ [static_cast<uint8_t>(t.m_e)]
+ [static_cast<uint8_t>(u.m_e)]
+ ;
+
+ return
+ safe_numerics_error::success == e
+ ? t.m_r + u.m_r
+ : checked_result<T>(e)
+ ;
+#else // works as expected
+ constexpr const safe_numerics_error x[2][2]{
+ // t == success
+ {
+ // u == ...
+ safe_numerics_error::success,
+ safe_numerics_error::failure
+ },
+ // t == failure,
+ {
+ // u == ...
+ safe_numerics_error::failure,
+ safe_numerics_error::failure
+ }
+ };
+
+ return
+ safe_numerics_error::success == x
+ [static_cast<uint8_t>(t.m_e)]
+ [static_cast<uint8_t>(u.m_e)]
+ ? t.m_r + u.m_r
+ : checked_result<T>(x
+ [static_cast<uint8_t>(t.m_e)]
+ [static_cast<uint8_t>(u.m_e)]
+ )
+ ;
+#endif
+}
+
+int main(){
+ constexpr const checked_result<unsigned> i = 0;
+ constexpr const checked_result<unsigned> j = 0;
+
+ constexpr const checked_result<unsigned> k = i + j;
+
+ // return k.m_r;
+
+ constexpr const checked_result<unsigned> i2 = safe_numerics_error::failure;
+ constexpr const checked_result<unsigned> j2 = 0;
+
+ constexpr const checked_result<unsigned> k2 = i2 + j2;
+ return k2.m_r;
+}
+#endif
+
+#if 0
+using uint8_t = unsigned char;
+
+
+#if 1
+enum class safe_numerics_error : uint8_t {
+ success = 0,
+ failure, // result is above representational maximum
+ error_count
+};
+#else
+// avoiding enum class fails to solve problem
+struct safe_numerics_error {
+ const uint8_t m_t;
+ constexpr const static uint8_t success = 0;
+ constexpr const static uint8_t failure = 1;
+ constexpr safe_numerics_error(uint8_t t) :
+ m_t(t)
+ {}
+ constexpr operator uint8_t () const {
+ return m_t;
+ }
+};
+#endif
+
+template<typename R>
+struct checked_result {
+ const safe_numerics_error m_e;
+ const union {
+ const R m_r;
+ char const * const m_msg;
+ };
+ constexpr /*explicit*/ checked_result(const R & r) :
+ m_e(safe_numerics_error::success),
+ m_r(r)
+ {}
+ constexpr /*explicit*/ checked_result(const safe_numerics_error & e) :
+ m_e(e),
+ m_msg("")
+ {}
+};
+
+// integers addition
+template<class T>
+constexpr inline checked_result<T> operator+(
+ const checked_result<T> & t,
+ const checked_result<T> & u
+){
+ // "Constexpr variable 'e' must be initialized by a constant expression"
+ constexpr const safe_numerics_error x[2][2]{
+ // t == success
+ {
+ // u == ...
+ safe_numerics_error::success,
+ safe_numerics_error::failure
+ },
+ // t == positive_overflow_error,
+ {
+ // u == ...
+ safe_numerics_error::failure,
+ safe_numerics_error::failure
+ }
+ };
+
+#if 1 // compile fails
+ const safe_numerics_error e = x
+ [static_cast<uint8_t>(t.m_e)]
+ [static_cast<uint8_t>(u.m_e)]
+ ;
+
+ return
+ (safe_numerics_error::success == e)
+ ? t.m_r + u.m_r
+ : checked_result<T>(e)
+ ;
+#else // works as expected
+ return
+ safe_numerics_error::success == x
+ [static_cast<uint8_t>(t.m_e)]
+ [static_cast<uint8_t>(u.m_e)]
+ ? t.m_r + u.m_r
+ : checked_result<T>(x
+ [static_cast<uint8_t>(t.m_e)]
+ [static_cast<uint8_t>(u.m_e)]
+ )
+ ;
+#endif
+}
+
+int main(){
+ constexpr const checked_result<unsigned> i = 0;
+ constexpr const checked_result<unsigned> j = 0;
+
+ //constexpr const checked_result<unsigned> k = i + j;
+ // return k.m_r;
+
+ constexpr const checked_result<unsigned> i2 = safe_numerics_error::failure;
+ constexpr const checked_result<unsigned> j2 = 0;
+
+ constexpr const checked_result<unsigned> k2 = i2 + j2;
+ return 0;
+}
+
+#endif
+
+#if 0
+//#include "safe_common.hpp>
+//#include "checked_result.hpp>
+//#include "checked_default.hpp>
+#include <cassert>
+#include <boost/logic/tribool.hpp>
+
+#include <iostream>
+
+// note: Don't reorder these. Code in the file checked_result_operations.hpp
+// depends upon this order !!!
+enum class safe_numerics_error : std::uint8_t {
+ success = 0,
+ positive_overflow_error, // result is above representational maximum
+ negative_overflow_error, // result is below representational minimum
+ domain_error, // one operand is out of valid range
+ range_error, // result cannot be produced for this operation
+ precision_overflow_error, // result lost precision
+ underflow_error, // result is too small to be represented
+ negative_value_shift, // negative value in shift operator
+ negative_shift, // shift a negative value
+ shift_too_large, // l/r shift exceeds variable size
+ uninitialized_value // l/r shift exceeds variable size
+};
+
+// checked result is an "extended version" of the type R. That is it's domain is
+// the domain of R U possible other values which might result from arithmetic
+// operations. An example of such a value would be safe_error::positive_overflow_error.
+template<typename R>
+struct checked_result {
+ const safe_numerics_error m_e;
+ const union {
+ R m_r;
+ char const * m_msg;
+ };
+
+ constexpr /*explicit*/ checked_result(const R & r) :
+ m_e(safe_numerics_error::success),
+ m_r(r)
+ {}
+ constexpr /*explicit*/ checked_result(
+ safe_numerics_error e,
+ const char * msg = ""
+ ) :
+ m_e(e),
+ m_msg(msg)
+ {
+ assert(m_e != safe_numerics_error::success);
+ }
+ constexpr bool exception() const {
+ return m_e != safe_numerics_error::success;
+ }
+
+ // don't permit construction without initial value;
+ checked_result() = delete;
+
+ // disallow assignment
+ checked_result & operator=(const checked_result &) = delete;
+};
+
+// all arithmetic operations of type T are supported on checked_result<T>.
+// but the results might surprising. For example
+
+
+constexpr signed int test_constexpr(
+ const checked_result<signed int> & t,
+ const checked_result<signed int> & u
+){
+ const boost::logic::tribool tb2 = t < u;
+ const signed int x = (tb2) ? 2 : 3;
+ return x;
+}
+
+using namespace boost::safe_numerics;
+
+int main()
+{
+ constexpr const checked_result<signed int> po = safe_numerics_error::positive_overflow_error;
+ constexpr const checked_result<signed int> no = safe_numerics_error::negative_overflow_error;
+ constexpr const boost::logic::tribool tb = no < po;
+ const boost::logic::tribool tb1 = no > po;
+ constexpr const checked_result<signed int> re = safe_numerics_error::range_error;
+ const boost::logic::tribool tb2 = no < re;
+ const checked_result<signed int> x = no < re ? no : re;
+
+ static_assert(test_constexpr(no, re) == 3, "test_constexpr(no, re)");
+
+
+ static_assert(tb, "no < po");
+
+ signed int result;
+ if(tb)
+ result = 0;
+ else
+ result = 1;
+ std::cout << result;
+ return result;
+}
+
+#endif
+
+#if 0
+
+#include <boost/logic/tribool.hpp>
+#include <cassert>
+int main(){
+ constexpr const boost::tribool tb_t{true};
+ static_assert(tb_t, "tb_t");
+ assert(static_cast<bool>(tb_t));
+ constexpr boost::tribool tb_f{false};
+ static_assert(! tb_f, "tb_f");
+ assert(! static_cast<bool>(tb_f));
+ return 0;
+}
+#endif
+
+#if 0
+#include <boost/integer.hpp>
+#include <boost/safe_numerics/utility.hpp>
+
+// include headers to support safe integers
+#include <boost/safe_numerics/cpp.hpp>
+//#include <boost/safe_numerics/exception.hpp>
+
+using promotion_policy = boost::safe_numerics::cpp<
+ 8, // char 8 bits
+ 16, // short 16 bits
+ 16, // int 16 bits
+ 16, // long 32 bits
+ 32 // long long 32 bits
+>;
+
+template<typename R, typename T, typename U>
+struct test {
+ using ResultType = promotion_policy::result_type<T,U>;
+ //boost::safe_numerics::utility::print_type<ResultType> pt;
+ static_assert(
+ std::is_same<R, ResultType>::value,
+ "is_same<R, ResultType>"
+ );
+};
+
+test<std::uint16_t, std::uint8_t, std::uint8_t> t1;
+
+int main(){
+ return 0;
+}
+
+#endif
+
+#if 0
+#include <string>
+#include <unordered_map>
+#include <boost/safe_numerics/safe_integer.hpp>
+
+#include <functional> // hash
+
+template<typename T>
+struct safe_hash {
+ size_t operator()(boost::safe_numerics::safe<T> const& t) const {
+ return std::hash<T>()(t);
+ }
+};
+
+int main(){
+ auto foo = std::unordered_map<
+ boost::safe_numerics::safe<int>,
+ std::string,
+ safe_hash<int>
+ >{};
+ foo[boost::safe_numerics::safe<int>(42)] = "hello, world!";
+ foo[42] = "hello, world!";
+}
+
+#endif
+
+#if 0
+
+#include <string>
+#include <unordered_map>
+#include <boost/safe_numerics/safe_integer.hpp>
+
+#include <functional> // hash
+
+template<typename T>
+struct safe_hash {
+ size_t operator()(boost::safe_numerics::safe<T> const& t) const {
+ return std::hash<T>()(t);
+ }
+};
+
+int main(){
+ auto foo = std::unordered_map<int, std::string>{};
+ foo[boost::safe_numerics::safe<int>(42)] = "hello, world!";
+}
+
+#endif
+
+#if 0
+
+#include <iostream>
+#include <boost/safe_numerics/safe_integer.hpp>
+//#include <boost/safe_numerics/automatic.hpp>
+
+using namespace boost::safe_numerics;
+
+int main(){
+ using safe_int = safe<
+ int,
+ automatic,
+ loose_trap_policy
+ >;
+ safe_int i;
+ std::cin >> i; // might throw exception
+ auto j = i * i;
+ // won't ever trap
+ // result type can hold the maximum value of i * i
+ static_assert(is_safe<decltype(j)>::value, "result is a safe type");
+ static_assert(
+ std::numeric_limits<decltype(i * i)>::max() >=
+ std::numeric_limits<safe_int>::max() * std::numeric_limits<safe_int>::max(),
+ "result can never overflow"
+ ); // always true
+
+ return 0;
+}
+
+
+#include <cstdint>
+#include <boost/safe_numerics/safe_integer_range.hpp>
+#include <boost/safe_numerics/safe_integer_literal.hpp>
+
+template <uintmax_t Min, uintmax_t Max>
+using urange = boost::safe_numerics::safe_unsigned_range<
+ Min,
+ Max,
+ boost::safe_numerics::native,
+ boost::safe_numerics::strict_trap_policy
+>;
+
+template <uintmax_t N>
+using ulit = boost::safe_numerics::safe_unsigned_literal<
+ N,
+ boost::safe_numerics::native,
+ boost::safe_numerics::strict_trap_policy
+>;
+
+int main(){
+ urange<0,4095> x = ulit<0>(); // 12 bits
+ urange<0, 69615> y = x * ulit<17>(); // no error - resulting value
+ // cannot exceed 69615
+ auto z = y / ulit<17>() ; //Boom, compile-time error
+ return z;
+}
+
+#endif
+
+#include <boost/safe_numerics/safe_integer_range.hpp>
+
+int main(){
+ using namespace boost::safe_numerics;
+ safe_unsigned_range<0, 36> a = 30;
+ return 0;
+}