summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/safe_numerics/test
diff options
context:
space:
mode:
Diffstat (limited to 'src/boost/libs/safe_numerics/test')
-rw-r--r--src/boost/libs/safe_numerics/test/CMakeLists.txt147
-rw-r--r--src/boost/libs/safe_numerics/test/Jamfile.v2121
-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.cpp69
-rw-r--r--src/boost/libs/safe_numerics/test/test_add_automatic_constexpr.cpp56
-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.cpp67
-rw-r--r--src/boost/libs/safe_numerics/test/test_add_native_constexpr.cpp57
-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.cpp135
-rw-r--r--src/boost/libs/safe_numerics/test/test_checked_add.cpp126
-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.cpp91
-rw-r--r--src/boost/libs/safe_numerics/test/test_checked_and.cpp126
-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.cpp91
-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.cpp129
-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.cpp129
-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.cpp138
-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.cpp99
-rw-r--r--src/boost/libs/safe_numerics/test/test_checked_or.cpp125
-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.cpp98
-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.cpp121
-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.cpp126
-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.cpp100
-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.cpp68
-rw-r--r--src/boost/libs/safe_numerics/test/test_multiply_automatic_constexpr.cpp56
-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.cpp66
-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.cpp53
-rw-r--r--src/boost/libs/safe_numerics/test/test_z.cpp758
147 files changed, 12049 insertions, 0 deletions
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 00000000..c2ad6046
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/CMakeLists.txt
@@ -0,0 +1,147 @@
+# 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_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 00000000..80468ed1
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/Jamfile.v2
@@ -0,0 +1,121 @@
+# 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
+ ;
+
+# 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_constexpr.cpp ;
+compile-fail test_trap.cpp ;
+
+# safe integer constexpr tests
+
+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 00000000..07e25f51
--- /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 void 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]);
+}
+
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 00000000..e4ef159e
--- /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 00000000..768373bc
--- /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 00000000..c48c5bb0
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_add_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_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(){
+ // sanity check on test matrix - should be symetrical
+ check_symmetry(test_addition_automatic_result);
+
+ //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 00000000..13b89ac8
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_add_automatic_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/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;
+
+ // 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_add_automatic_results.hpp b/src/boost/libs/safe_numerics/test/test_add_automatic_results.hpp
new file mode 100644
index 00000000..73af1d3f
--- /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 00000000..3c67e2b0
--- /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 00000000..b7a1ef92
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_add_native.cpp
@@ -0,0 +1,67 @@
+// 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(){
+ // sanity check on test matrix - should be symetrical
+ check_symmetry(test_addition_native_result);
+
+ 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 00000000..e54ecc71
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_add_native_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/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;
+
+ // 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_add_native_results.hpp b/src/boost/libs/safe_numerics/test/test_add_native_results.hpp
new file mode 100644
index 00000000..16364cfe
--- /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 00000000..5a53b0ac
--- /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 00000000..d181655b
--- /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 00000000..825df9d7
--- /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 00000000..afa2b1d3
--- /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 00000000..bb0054f6
--- /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 00000000..cddf59c9
--- /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 00000000..678e2cb8
--- /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 00000000..b73a8e17
--- /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 00000000..57b8c33a
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_cast.cpp
@@ -0,0 +1,135 @@
+// 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 T1 from safe<T2>(v2) */
+ 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;
+
+template<typename T>
+using extract_value_type = typename T::value_type;
+using test_types = mp_unique<
+ mp_transform<
+ extract_value_type,
+ test_values
+ >
+>;
+
+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_checked_add.cpp b/src/boost/libs/safe_numerics/test/test_checked_add.cpp
new file mode 100644
index 00000000..b74c956d
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_checked_add.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 <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(){
+ // sanity check on test matrix - should be symetrical
+ check_symmetry(signed_addition_results);
+ check_symmetry(unsigned_addition_results);
+
+ 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 00000000..24411cb0
--- /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 00000000..9eaa880e
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_checked_add_constexpr.cpp
@@ -0,0 +1,91 @@
+// 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(){
+ using namespace boost::mp11;
+ check_symmetry(signed_addition_results);
+ check_symmetry(unsigned_addition_results);
+
+ 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 00000000..81646f28
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_checked_and.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 <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;
+ 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;
+ }
+ 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(){
+ using namespace boost::mp11;
+ // sanity check on test matrix - should be symetrical
+ check_symmetry(signed_and_results);
+ check_symmetry(unsigned_and_results);
+
+ 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 00000000..d7ed82f3
--- /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 00000000..1080def6
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_checked_and_constexpr.cpp
@@ -0,0 +1,91 @@
+// 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(){
+ using namespace boost::mp11;
+ check_symmetry(signed_and_results);
+ check_symmetry(unsigned_and_results);
+
+ 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 00000000..f1d111d1
--- /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 00000000..e8efe576
--- /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 00000000..ac60dcdd
--- /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 00000000..74af9c7f
--- /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 00000000..ca471f1d
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_checked_divide.cpp
@@ -0,0 +1,129 @@
+// 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;
+ 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;
+ }
+ 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 00000000..9e2affe1
--- /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 00000000..6056f06a
--- /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 00000000..8517095b
--- /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 00000000..072f2371
--- /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 00000000..ca9789dd
--- /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 00000000..61d949a7
--- /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 00000000..25da8eb6
--- /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 00000000..b0702ca2
--- /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 00000000..3c9b89f3
--- /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 00000000..57b257b1
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_checked_modulus.cpp
@@ -0,0 +1,129 @@
+// 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;
+ 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;
+ }
+ 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 00000000..f2a818b7
--- /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 00000000..0d480dce
--- /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 00000000..de2ee679
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_checked_multiply.cpp
@@ -0,0 +1,138 @@
+// 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 *[]){
+ // sanity check on test matrix - should be symetrical
+ check_symmetry(signed_multiplication_results);
+ check_symmetry(unsigned_multiplication_results);
+
+ 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 00000000..5589f925
--- /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 00000000..c154a369
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_checked_multiply_constexpr.cpp
@@ -0,0 +1,99 @@
+// 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(){
+ using namespace boost::mp11;
+ check_symmetry(signed_multiplication_results);
+ check_symmetry(unsigned_multiplication_results);
+
+ 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 00000000..4638bf63
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_checked_or.cpp
@@ -0,0 +1,125 @@
+// 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;
+ 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;
+ }
+ 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(){
+ using namespace boost::mp11;
+ // sanity check on test matrix - should be symetrical
+ check_symmetry(signed_or_results);
+ check_symmetry(unsigned_or_results);
+
+ 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 00000000..b6fb0de4
--- /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 00000000..35491a0c
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_checked_or_constexpr.cpp
@@ -0,0 +1,98 @@
+// 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;
+ // sanity check on test matrix - should be symetrical
+ check_symmetry(signed_or_results);
+ check_symmetry(unsigned_or_results);
+
+ 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 00000000..6d37aea9
--- /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 00000000..d5f1f9df
--- /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 00000000..6e40a83b
--- /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 00000000..b6fc9204
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_checked_subtract.cpp
@@ -0,0 +1,121 @@
+// 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;
+ 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;
+ }
+ std::cout
+ << "failed to detect error in ition "
+ << 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 00000000..5a00147c
--- /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 00000000..4d8ba6a8
--- /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 00000000..957db559
--- /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 00000000..6709fc0f
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_checked_xor.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 <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;
+ 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;
+ }
+ 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(){
+ using namespace boost::mp11;
+ // sanity check on test matrix - should be symetrical
+ check_symmetry(signed_xor_results);
+ check_symmetry(unsigned_xor_results);
+
+ 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 00000000..f30725b1
--- /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 00000000..68667ad1
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_checked_xor_constexpr.cpp
@@ -0,0 +1,100 @@
+// 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(){
+ using namespace boost::mp11;
+ check_symmetry(signed_xor_results);
+ check_symmetry(unsigned_xor_results);
+
+ 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 00000000..52d677ce
--- /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 00000000..2b55dab9
--- /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 00000000..30bf18f6
--- /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 00000000..68ad43ef
--- /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 00000000..c9869c15
--- /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 00000000..93c53cc3
--- /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 00000000..d3caf049
--- /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 00000000..5ad430a9
--- /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 00000000..bb286058
--- /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 00000000..4ec0ef8f
--- /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 00000000..0299223d
--- /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 00000000..1a800a60
--- /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 00000000..b24a3541
--- /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 00000000..70e9006d
--- /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 00000000..9c02c3d2
--- /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 00000000..5168d590
--- /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 00000000..61887662
--- /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 00000000..2252fd12
--- /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 00000000..866a0df2
--- /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 00000000..c0e192db
--- /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 00000000..115f4abd
--- /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 00000000..f9f87e4e
--- /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 00000000..6aa22e29
--- /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 00000000..9ca5b96e
--- /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 00000000..5923855e
--- /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 00000000..defdb9a1
--- /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 00000000..00c92d20
--- /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 00000000..011ee37c
--- /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 00000000..f1685bb0
--- /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 00000000..6460ad6a
--- /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 00000000..a04f5fb7
--- /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 00000000..3c5be46d
--- /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 00000000..f3ecf588
--- /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 00000000..8dccebfc
--- /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 00000000..dfdd1a04
--- /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 00000000..cec70ae8
--- /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 00000000..2fd5c378
--- /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 00000000..3bb90867
--- /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 00000000..2530c78d
--- /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 00000000..8bf06589
--- /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 00000000..6484be1b
--- /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 00000000..0f21db94
--- /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 00000000..0cae9315
--- /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 00000000..fe44ab1f
--- /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 00000000..4d47d9f7
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_multiply_automatic.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 <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(){
+ // sanity check on test matrix - should be symetrical
+ check_symmetry(test_multiplication_automatic_result);
+
+ //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_multiply_automatic_constexpr.cpp b/src/boost/libs/safe_numerics/test/test_multiply_automatic_constexpr.cpp
new file mode 100644
index 00000000..0b9ce06d
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_multiply_automatic_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/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(){
+ using namespace boost::mp11;
+
+ // sanity check on test matrix - should be symetrical
+ check_symmetry(test_multiplication_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 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 00000000..97279840
--- /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 00000000..2fe107df
--- /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 00000000..8e4cc585
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_multiply_native.cpp
@@ -0,0 +1,66 @@
+// 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(){
+ // sanity check on test matrix - should be symetrical
+ check_symmetry(test_multiplication_native_result);
+ //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_multiply_native_constexpr.cpp b/src/boost/libs/safe_numerics/test/test_multiply_native_constexpr.cpp
new file mode 100644
index 00000000..2773bc7a
--- /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(){
+ using namespace boost::mp11;
+
+ // sanity check on test matrix - should be symetrical
+ check_symmetry(test_multiplication_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 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 00000000..888a00c5
--- /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 00000000..d2204a63
--- /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 00000000..f3eb16c3
--- /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 00000000..f8139ee1
--- /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 00000000..20c7a48c
--- /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 00000000..20844ce4
--- /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 00000000..92ec26e7
--- /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 00000000..d83034a7
--- /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 00000000..364a7671
--- /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 00000000..930b38ed
--- /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 00000000..8e60bf57
--- /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 00000000..8b46df4a
--- /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 00000000..1087f364
--- /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 00000000..05a66434
--- /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 00000000..26dc8ab7
--- /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 00000000..c4e2bab2
--- /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 00000000..f7c8b311
--- /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 00000000..59496354
--- /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 00000000..c299aa04
--- /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 00000000..41190566
--- /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 00000000..832d49e2
--- /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 00000000..dadd15d0
--- /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 00000000..bef25dae
--- /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 00000000..afa59e40
--- /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 00000000..a82c171e
--- /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 00000000..2f622a81
--- /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 00000000..3d8eae63
--- /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 00000000..030b6278
--- /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 00000000..fa067f46
--- /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 00000000..de533611
--- /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 00000000..4788d475
--- /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 00000000..4777f358
--- /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 00000000..4a8038f3
--- /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 00000000..c6cfb65c
--- /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 00000000..10288f14
--- /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 00000000..7ad71d81
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_xor_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_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>
+#include "check_symmetry.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 00000000..795ed4f8
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_z.cpp
@@ -0,0 +1,758 @@
+
+#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 T, 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;
+}
+#endif
+
+int main(){}