diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 18:24:20 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 18:24:20 +0000 |
commit | 483eb2f56657e8e7f419ab1a4fab8dce9ade8609 (patch) | |
tree | e5d88d25d870d5dedacb6bbdbe2a966086a0a5cf /src/boost/libs/safe_numerics/test | |
parent | Initial commit. (diff) | |
download | ceph-upstream.tar.xz ceph-upstream.zip |
Adding upstream version 14.2.21.upstream/14.2.21upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/boost/libs/safe_numerics/test')
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(){} |