From 2a5c0e373cccbdf295eaaea0ab9ed71048b0ce42 Mon Sep 17 00:00:00 2001 From: Robert Ramey Date: Thu, 25 Jun 2015 08:44:38 -0700 Subject: [PATCH] test0 not working example6 not working --- examples/example4.cpp | 2 +- examples/example6.cpp | 10 +- include/concept/promotion_policy.hpp | 2 +- include/interval.hpp | 6 + include/numeric.hpp | 312 +++++++++++++++++++++++++++ include/safe_base.hpp | 3 +- include/safe_base_operations.hpp | 9 +- include/safe_integer.hpp | 4 +- include/safe_range.hpp | 112 ++++++---- test/test0.cpp | 116 +--------- test/test_cast copy.cpp | 92 -------- test/test_cast.cpp | 31 +-- test/test_checked.cpp | 163 -------------- test/test_conversion.cpp | 17 +- test/test_z copy.cpp | 281 ------------------------ test/test_z.cpp | 2 +- 16 files changed, 436 insertions(+), 726 deletions(-) create mode 100644 include/numeric.hpp delete mode 100644 test/test_cast copy.cpp delete mode 100644 test/test_checked.cpp delete mode 100644 test/test_z copy.cpp diff --git a/examples/example4.cpp b/examples/example4.cpp index c98b0f5..0b9abe9 100644 --- a/examples/example4.cpp +++ b/examples/example4.cpp @@ -27,7 +27,7 @@ int main(int argc, const char * argv[]){ std::cout << x << " != " << -1; detected_msg(false); } - catchstd::exception){ + catch(std::exception){ assert(false); // never arrive here } // solution: replace unsigned int with safe diff --git a/examples/example6.cpp b/examples/example6.cpp index 29fad0e..cb65e7b 100644 --- a/examples/example6.cpp +++ b/examples/example6.cpp @@ -33,16 +33,8 @@ int main(int argc, const char * argv[]){ is >> x >> y; // get integer values from the user detected_msg(false); } - catch(std::range_error & e){ - std::cout << e.what() << std::endl; - detected_msg(true); - } - try{ - z = x + y; - detected_msg(false); - } catch(std::exception e){ - std::cout << z << std::endl; // display sum of the values + std::cout << e.what() << std::endl; detected_msg(true); } } diff --git a/include/concept/promotion_policy.hpp b/include/concept/promotion_policy.hpp index 7cc255c..91076aa 100644 --- a/include/concept/promotion_policy.hpp +++ b/include/concept/promotion_policy.hpp @@ -12,7 +12,7 @@ // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#include "boost/concept/usage.hpp" +//#include "boost/concept/usage.hpp" namespace boost { namespace numeric { diff --git a/include/interval.hpp b/include/interval.hpp index 94ef74d..0e873dd 100644 --- a/include/interval.hpp +++ b/include/interval.hpp @@ -28,11 +28,17 @@ template struct interval { checked_result l; checked_result u; + /* template SAFE_NUMERIC_CONSTEXPR interval(const T & lower, const U & upper) : l(lower), u(upper) {} + */ + SAFE_NUMERIC_CONSTEXPR interval(const R & lower, const R & upper) : + l(lower), + u(upper) + {} SAFE_NUMERIC_CONSTEXPR interval(const interval & rhs) : l(rhs.l), u(rhs.u) diff --git a/include/numeric.hpp b/include/numeric.hpp new file mode 100644 index 0000000..185ccbf --- /dev/null +++ b/include/numeric.hpp @@ -0,0 +1,312 @@ +#ifndef BOOST_NUMERIC_NUMERIC_HPP +#define BOOST_NUMERIC_NUMERIC_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "concept/numeric.hpp" +#include "boost/concept/assert.hpp" + +namespace boost { +namespace numeric { + +namespace detail { + template + struct log; + + template + struct log<0, BASE> : public + boost::mpl::integral_c< + boost::intmax_t , + 0 + > + {}; + template + struct log<-1, BASE> : public + boost::mpl::integral_c< + boost::intmax_t , + 0 + > + {}; + + template + struct log : public + boost::mpl::integral_c< + boost::intmax_t , + (1 + log::value ) + > + {}; + + template + struct ulog; + + template + struct ulog<0, BASE> : public + boost::mpl::integral_c< + boost::uintmax_t , + 0 + > + {}; + template + struct ulog : public + boost::mpl::integral_c< + boost::uintmax_t , + (1 + ulog::value) + > + {}; + +} //detail + +// can't use is_signed type traits as these are defined ONLY for C++ +// primitive types. They are are not (by design) implemented in terms +// of numeric_limits so they aren't helpful to us. We leave then in the +// boost/numeric namespace to distinguish them form the "official" type +// traits ! +template +struct is_signed : public + boost::mpl::integral_c< + bool, + std::numeric_limits::is_signed + > +{ + BOOST_CONCEPT_ASSERT((Numeric)); +}; +template +struct is_unsigned : public + boost::mpl::integral_c< + bool, + ! std::numeric_limits::is_signed + > +{ + BOOST_CONCEPT_ASSERT((Numeric)); +}; + +// return the number of bits in a type excluding any sign +template +struct digits : public + boost::mpl::integral_c::digits> +{ + BOOST_CONCEPT_ASSERT((Numeric)); +}; + +// return maximum bits in types T and U +template +struct max_digits : public + boost::mpl::max< + digits, + digits + >::type +{}; + +// return the number of bits in a type including the sign +template +struct bits : public + boost::mpl::plus< + typename boost::mpl::integral_c::digits>, + typename boost::mpl::integral_c::is_signed> + > +{}; + +// return maximum bits in types T and U +template +struct max_bits : public + boost::mpl::max< + bits, + bits + >::type +{}; + + +// return # of bit in the result of an addition of two types +template +struct addition_result_bits : public + boost::mpl::plus< + max_digits, + // if either is signed + typename boost::mpl::eval_if< + typename boost::mpl::or_< + is_signed, + is_signed + >, + // add one guard bit and one sign bit + boost::mpl::integral_c, + // add one guard bit to detect overflow + boost::mpl::integral_c + >::type + > +{}; + +// return smallest type that can hold the sum of types T and U +template +struct addition_result_type { + typedef typename boost::mpl::if_< + typename boost::mpl::or_< + is_signed, + is_signed + >, + typename boost::int_t< + boost::mpl::min< + bits, + addition_result_bits + >::type::value + >::least, + typename boost::uint_t< + boost::mpl::min< + bits, + addition_result_bits + >::type::value + >::least + >::type type; +}; + +// return # of bit in the result of an subtraction of two types +template +struct subtraction_result_bits : public + boost::mpl::plus< + max_digits, + // add one guard bit and one sign bit + boost::mpl::integral_c + > +{}; + +// return smallest type that can hold the difference of types T and U +template +struct subtraction_result_type { + typedef typename boost::int_t< + boost::mpl::min< + bits, + subtraction_result_bits + >::type::value + >::least type; +}; + +// return # of bits in the result of an product of two types +template +struct multiply_result_bits : public + boost::mpl::plus< + digits, + digits, + // if either is signed + typename boost::mpl::eval_if< + typename boost::mpl::or_< + is_signed, + is_signed + >, + // add one sign bit + boost::mpl::integral_c, + boost::mpl::integral_c + >::type + > +{}; + +// return smallest type that can hold the product of types T and U +template +struct multiply_result_type { + typedef typename boost::mpl::eval_if< + typename boost::mpl::or_< + is_signed, + is_signed + >, + typename boost::mpl::identity< + typename boost::int_t< + boost::mpl::min< + bits, + multiply_result_bits + >::type::value + >::least + >, + typename boost::mpl::identity< + typename boost::uint_t< + boost::mpl::min< + bits, + multiply_result_bits + >::type::value + >::least + > + >::type type; +}; + +// return # of bits in the result of an quotient of two types +template +struct division_result_bits : public + boost::mpl::plus< + digits, + // if either is signed + typename boost::mpl::eval_if< + typename boost::mpl::or_< + is_signed, + is_signed + >, + // add one sign bit + boost::mpl::integral_c, + boost::mpl::integral_c + >::type + > +{}; + +// return smallest type that can hold the quotient of types T and U +template +struct division_result_type { + typedef typename boost::mpl::if_< + typename boost::mpl::or_< + is_signed, + is_signed + >, + typename boost::int_t< + boost::mpl::min< + bits, + division_result_bits + >::type::value + >::least, + typename boost::uint_t< + boost::mpl::min< + bits, + division_result_bits + >::type::value + >::least + >::type type; +}; + +// return the type which results from usage of one the +// operators &, |, ^, <<, >> +template +struct logical_result_type { + typedef typename boost::mpl::if_< + typename boost::mpl::or_< + is_signed, + is_signed + >, + typename boost::int_t< + max_bits::value + >::least, + typename boost::uint_t< + max_bits::value + >::least + >::type type; +}; + +} // numeric +} // boost + +#endif // BOOST_NUMERIC_NUMERIC_HPP diff --git a/include/safe_base.hpp b/include/safe_base.hpp index 213b88f..99fffff 100644 --- a/include/safe_base.hpp +++ b/include/safe_base.hpp @@ -37,6 +37,7 @@ class safe_base { derived() const { return static_cast(*this); } +public: template SAFE_NUMERIC_CONSTEXPR bool validate(const T & t) const { return ! ( @@ -44,7 +45,7 @@ class safe_base { base_value(t), base_value(Derived::max()) ) - && + || boost::numeric::checked::less_than( base_value(t), base_value(Derived::min()) diff --git a/include/safe_base_operations.hpp b/include/safe_base_operations.hpp index 9dd0044..dbcfd06 100644 --- a/include/safe_base_operations.hpp +++ b/include/safe_base_operations.hpp @@ -598,16 +598,19 @@ operator<<( template typename std::enable_if< boost::numeric::is_safe::value, - std::ostream & + std::istream & >::type operator>>( std::istream & is, T & t ){ typedef typename boost::numeric::get_exception_policy::type exception_policy; - is >> t.get_stored_value(); - if(is.fail() || !t.validate()) + typename boost::numeric::base_type::type tx; + //int tx; + is >> tx; + if(is.fail() || !t.validate(tx)) exception_policy::range_error("error in file input"); + t.get_stored_value() = tx; return is; } diff --git a/include/safe_integer.hpp b/include/safe_integer.hpp index 9e6e250..ecdcbd9 100644 --- a/include/safe_integer.hpp +++ b/include/safe_integer.hpp @@ -128,10 +128,10 @@ class numeric_limits > public: // these expressions are not SAFE_NUMERIC_CONSTEXPR until C++14 so re-implement them here SAFE_NUMERIC_CONSTEXPR static SI min() noexcept { - return boost::numeric::safe(std::numeric_limits::min()); + return SI(std::numeric_limits::min()); } SAFE_NUMERIC_CONSTEXPR static SI max() noexcept { - return boost::numeric::safe(std::numeric_limits::max()); + return SI(std::numeric_limits::max()); } }; diff --git a/include/safe_range.hpp b/include/safe_range.hpp index ac62771..444ba87 100644 --- a/include/safe_range.hpp +++ b/include/safe_range.hpp @@ -12,11 +12,15 @@ // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) +#include // intmax_t, uintmax_t +#include // int_t, uint_t +#include + #include "safe_base.hpp" #include "safe_base_operations.hpp" #include "native.hpp" #include "exception_policies.hpp" -#include "native.hpp" +#include "numeric.hpp" ///////////////////////////////////////////////////////////////// // higher level types implemented in terms of safe_base @@ -26,8 +30,8 @@ namespace numeric { namespace detail { template< - boost::intmax_t MIN, - boost::intmax_t MAX + std::intmax_t MIN, + std::intmax_t MAX > struct signed_stored_type { // double check that MIN < MAX @@ -39,8 +43,8 @@ namespace detail { >::least type; }; template< - boost::uintmax_t MIN, - boost::uintmax_t MAX + std::uintmax_t MIN, + std::uintmax_t MAX > struct unsigned_stored_type { // calculate max(abs(MIN, MAX)) @@ -63,16 +67,16 @@ namespace boost { namespace numeric { template< - boost::intmax_t MIN, - boost::intmax_t MAX, + std::intmax_t MIN, + std::intmax_t MAX, class P, class E > -struct safe_signed_range; +class safe_signed_range; template< - boost::intmax_t MIN, - boost::intmax_t MAX, + std::intmax_t MIN, + std::intmax_t MAX, class P, class E > @@ -80,8 +84,8 @@ struct is_safe > : public std::true_type {}; template< - boost::intmax_t MIN, - boost::intmax_t MAX, + std::intmax_t MIN, + std::intmax_t MAX, class P, class E > @@ -90,8 +94,8 @@ struct get_promotion_policy > { }; template< - boost::intmax_t MIN, - boost::intmax_t MAX, + std::intmax_t MIN, + std::intmax_t MAX, class P, class E > @@ -100,19 +104,19 @@ struct get_exception_policy > { }; template< - boost::intmax_t MIN, - boost::intmax_t MAX, + std::intmax_t MIN, + std::intmax_t MAX, class P, class E > struct base_type > { - typedef T type; + typedef typename safe_signed_range::base_type type; }; template< - boost::intmax_t MIN, - boost::intmax_t MAX, - class P = native + std::intmax_t MIN, + std::intmax_t MAX, + class P = native, class E = throw_exception > class safe_signed_range : public @@ -131,20 +135,29 @@ class safe_signed_range : public BOOST_CONCEPT_ASSERT((ExceptionPolicy)); typedef typename detail::signed_stored_type::type stored_type; + SAFE_NUMERIC_CONSTEXPR static const stored_type min() { + return MIN; + } + SAFE_NUMERIC_CONSTEXPR static const stored_type max() { + return MAX; + } + +public: typedef typename boost::numeric::safe_base< stored_type, - safe_signed_range + safe_signed_range, + P, + E > base_type; friend base_type; -public: // note: Rule of Three. Don't specify custom move, copy etc. SAFE_NUMERIC_CONSTEXPR safe_signed_range() : base_type() {} template - SAFE_NUMERIC_CONSTEXPR safe_signed_range(const U & u) : - base_type(u) + SAFE_NUMERIC_CONSTEXPR safe_signed_range(const T & t) : + base_type(t) {} }; @@ -165,11 +178,16 @@ template< class P, class E > -class numeric_limits > - : public boost::numeric::base_type > +class numeric_limits< + boost::numeric::safe_signed_range + > + : public std::numeric_limits< + boost::numeric::base_type< + boost::numeric::safe_signed_range + > + > { - typedef boost::numeric::base_type SSR; - typedef typename boost::mpl::print::type t0; + typedef typename boost::numeric::base_type > SSR; public: SAFE_NUMERIC_CONSTEXPR static SSR min() noexcept { return SSR(MIN); } SAFE_NUMERIC_CONSTEXPR static SSR max() noexcept { return SSR(MAX); } @@ -189,7 +207,7 @@ template< class P, class E > -struct safe_unsigned_range; +class safe_unsigned_range; template< boost::uintmax_t MIN, @@ -227,13 +245,13 @@ template< class E > struct base_type > { - typedef T type; + typedef typename safe_unsigned_range::base_type type; }; template< boost::uintmax_t MIN, boost::uintmax_t MAX, - class P = native + class P = native, class E = throw_exception > class safe_unsigned_range : public @@ -244,29 +262,36 @@ class safe_unsigned_range : public E > { -private static_assert( MIN < MAX, "minimum must be less than maximum" ); - BOOST_CONCEPT_ASSERT((PromotionPolicy)); + BOOST_CONCEPT_ASSERT((PromotionPolicy

)); BOOST_CONCEPT_ASSERT((ExceptionPolicy)); + typedef typename detail::unsigned_stored_type::type stored_type; + +public: typedef typename boost::numeric::safe_base< - typename detail::unsigned_stored_type::type, + stored_type, safe_unsigned_range, P, E > base_type; friend base_type; -public: + SAFE_NUMERIC_CONSTEXPR static const stored_type min() { + return MIN; + } + SAFE_NUMERIC_CONSTEXPR static const stored_type max() { + return MAX; + } // note: Rule of Three. Don't specify custom move, copy etc. SAFE_NUMERIC_CONSTEXPR safe_unsigned_range() : base_type() {} template - SAFE_NUMERIC_CONSTEXPR safe_unsigned_range(const U & u) : - base_type(u) + SAFE_NUMERIC_CONSTEXPR safe_unsigned_range(const T & t) : + base_type(t) {} }; @@ -283,11 +308,16 @@ template< class P, class E > -class numeric_limits > - : public boost::numeric::base_type > +class numeric_limits< + boost::numeric::safe_unsigned_range + > + : public std::numeric_limits< + boost::numeric::base_type< + boost::numeric::safe_unsigned_range + > + > { - typedefboost::numeric::base_type SUR; - typedef typename boost::mpl::print::type t0; + typedef typename boost::numeric::base_type > SUR; public: SAFE_NUMERIC_CONSTEXPR static SUR min() noexcept { return SUR(MIN); } SAFE_NUMERIC_CONSTEXPR static SUR max() noexcept { return SUR(MAX); } diff --git a/test/test0.cpp b/test/test0.cpp index 751fd4c..468b48e 100644 --- a/test/test0.cpp +++ b/test/test0.cpp @@ -4,120 +4,11 @@ // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#if 1 - -#include "safe_integer.hpp" - -const intmax_t x = std::numeric_limits< - boost::numeric::safe< - signed char, - boost::numeric::policies< - boost::numeric::native, - boost::numeric::relaxed, boost::numeric::throw_exception - > - > ->::min(); - -#endif - -#if 0 -#include - -template< - class T, - class P -> -struct safe; - -std::numeric_limits ai0; - -namespace std { - -numeric_limits ai2; - -template -struct numeric_limits { - // no message here with numeric_limits because it's already - // specialized in - typedef typename boost::mpl::print::type t0; -}; - -template -struct std::numeric_limits > : public numeric_limits{ - typedef typename boost::mpl::print::type t0; - typedef typename boost::mpl::print

::type t1; -}; - -numeric_limits ai3; - -} // std -#endif - -#if 0 - -#include -#include - -namespace std { -template class numeric_limits; -} // std - -template -class std::numeric_limits { - typedef typename boost::mpl::print::type t0; -}; - -std::numeric_limits ai; - -#endif - -#if 0 - -#include -#include - -namespace std { - -template -class numeric_limits { - typedef typename boost::mpl::print::type t0; -}; - -} // std - -std::numeric_limits ai; - - -#endif - -#if 0 -#include -#include // EXIT_SUCCESS #include - #include -#endif - -#if 0 -typedef boost::numeric::safe_signed_range<-64, 63> X; -//typedef boost::mpl::print::type>::type t8 ; -//typedef boost::mpl::print::type>::type t9 ; -//typedef boost::mpl::print::type >::type t7 ; -//typedef boost::mpl::print::type>::type t10; - -typedef boost::mpl::print::type> t13; -#endif - -#if 0 -typedef boost::numeric::safe_signed_range<-64, 63> X; -typedef boost::mpl::print::type>::type t12; -typedef boost::mpl::print::type -> t11; - -#endif - -#if 0 +#include "../include/safe_range.hpp" +#include "../include/numeric.hpp" bool test1(){ std::cout << "test1" << std::endl; @@ -259,7 +150,7 @@ bool test5(){ int main(int argc, char *argv[]){ return ( - test1() && +// test1() && test2() && test3() && test4() && @@ -267,5 +158,4 @@ int main(int argc, char *argv[]){ ) ? EXIT_SUCCESS : EXIT_FAILURE; } -#endif diff --git a/test/test_cast copy.cpp b/test/test_cast copy.cpp deleted file mode 100644 index e834f7f..0000000 --- a/test/test_cast copy.cpp +++ /dev/null @@ -1,92 +0,0 @@ -// 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 -#include -#include // EXIT_SUCCESS - -#include "safe_integer.hpp" - -// test conversion to T2 from different literal types -template -bool test_cast(T1 v1, const char *t2_name, const char *t1_name){ - std::cout - << "testing static_cast(" << t1_name << ")" - << std::endl; - /* test conversion constructor to safe */ - boost::numeric::safe s2; - try{ - s2 = static_cast >(v1); - if(! (s2 == v1)){ - std::cout - << "failed to detect error in construction " - << t2_name << "<-" << t1_name - << std::endl; - try{ - static_cast >(v1); - } - catch(std::exception){} - return false; - } - } - catch(std::exception){ - if( s2 == v1 ){ - std::cout - << "erroneously emitted error " - << t1_name << "<-" << t2_name - << std::endl; - try{ - static_cast >(v1); - } - catch(std::exception){} - return false; - } - } - return true; // passed test -} - - -#include -#include -#include -#include - -#include "test_types.hpp" -#include "test_values.hpp" -#include "test.hpp" - -#define TEST_CAST(T1, v) \ - rval = rval && test_cast( \ - v, \ - BOOST_PP_STRINGIZE(T1), \ - BOOST_PP_STRINGIZE(v) \ - ); -/**/ - -#define EACH_VALUE(z, value_index, type_index) \ - TEST_CAST( \ - BOOST_PP_ARRAY_ELEM(type_index, TYPES), \ - BOOST_PP_ARRAY_ELEM(value_index, VALUES) \ - ) \ -/**/ - -#define EACH_TYPE1(z, type_index, nothing) \ - BOOST_PP_REPEAT( \ - BOOST_PP_ARRAY_SIZE(VALUES), \ - EACH_VALUE, \ - type_index \ - ) \ -/**/ - -int main(int argc, char *argv[]){ - bool rval = true; - BOOST_PP_REPEAT( - BOOST_PP_ARRAY_SIZE(TYPES), - EACH_TYPE1, - nothing - ) - return rval ? EXIT_SUCCESS : EXIT_FAILURE; -} diff --git a/test/test_cast.cpp b/test/test_cast.cpp index a6ebdfb..e834f7f 100644 --- a/test/test_cast.cpp +++ b/test/test_cast.cpp @@ -8,40 +8,47 @@ #include #include // EXIT_SUCCESS -#include "../include/checked.hpp" +#include "safe_integer.hpp" // test conversion to T2 from different literal types template -bool test_cast(const T1 & v1, const char *t2_name, const char *t1_name){ +bool test_cast(T1 v1, const char *t2_name, const char *t1_name){ std::cout << "testing static_cast(" << t1_name << ")" << std::endl; - - constexpr const T1 cev1 = 0; - constexpr const boost::numeric::checked_result r2 = boost::numeric::checked::cast(cev1); - - if(r2 == boost::numeric::checked_result::exception_type::no_exception){ - if(! (r2 == v1)){ + /* test conversion constructor to safe */ + boost::numeric::safe s2; + try{ + s2 = static_cast >(v1); + if(! (s2 == v1)){ std::cout << "failed to detect error in construction " << t2_name << "<-" << t1_name << std::endl; - boost::numeric::checked::cast(v1); + try{ + static_cast >(v1); + } + catch(std::exception){} return false; } } - else{ - if( r2 == v1 ){ + catch(std::exception){ + if( s2 == v1 ){ std::cout << "erroneously emitted error " << t1_name << "<-" << t2_name << std::endl; - boost::numeric::checked::cast(v1); + try{ + static_cast >(v1); + } + catch(std::exception){} + return false; } } return true; // passed test } + #include #include #include diff --git a/test/test_checked.cpp b/test/test_checked.cpp deleted file mode 100644 index afc1f3d..0000000 --- a/test/test_checked.cpp +++ /dev/null @@ -1,163 +0,0 @@ -// 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 -#include // EXIT_SUCCESS -#include -#include - -#include "../include/checked_result.hpp" -#include "../include/checked.hpp" - -template -bool test_add( - T1 v1, - T2 v2, - const char *av1, - const char *av2, - char expected_result -){ - std::cout - << "testing " - << av1 << " + " << av2 - << std::endl; - - typedef decltype(T1() + T2()) result_type; - - boost::numeric::checked_result result - = boost::numeric::checked::add( - std::numeric_limits::min(), - std::numeric_limits::max(), - v1, - v2 - ); - - if(result == boost::numeric::checked_result::exception_type::no_exception - && expected_result == 'x'){ - std::cout - << "failed to detect error in addition " - << std::hex << result << "(" << std::dec << result << ")" - << " != "<< av1 << " + " << av2 - << std::endl; - boost::numeric::checked_result result - = boost::numeric::checked::add( - std::numeric_limits::min(), - std::numeric_limits::max(), - v1, - v2 - ); - return false; - } - else - if(result != boost::numeric::checked_result::exception_type::no_exception - && expected_result == '.'){ - std::cout - << "erroneously detected error " - << std::hex << result << av1 << " + " << av2 - << std::endl; - boost::numeric::checked_result result - = boost::numeric::checked::add( - std::numeric_limits::min(), - std::numeric_limits::max(), - v1, - v2 - ); - - return false; - } - - return true; // correct result -} - -#include "test.hpp" -#include "test_values.hpp" - -// note: same test matrix as used in test_add. Here we test all combinations -// safe and unsafe integers. in test_checked we test all combinations of -// integer primitives - -const char *test_addition_result[VALUE_ARRAY_SIZE] = { -// 0 0 0 0 -// 01234567012345670123456701234567 -// 01234567890123456789012345678901 -/* 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 -// 01234567012345670123456701234567 -// 01234567890123456789012345678901 -/*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" -}; - -#define TEST_IMPL(v1, v2, result) \ - rval &= test_add( \ - v1, \ - v2, \ - BOOST_PP_STRINGIZE(v1), \ - BOOST_PP_STRINGIZE(v2), \ - result \ - ); -/**/ - -#define TESTX(value_index1, value_index2) \ - (std::cout << value_index1 << ',' << value_index2 << ','); \ - TEST_IMPL( \ - BOOST_PP_ARRAY_ELEM(value_index1, VALUES), \ - BOOST_PP_ARRAY_ELEM(value_index2, VALUES), \ - test_addition_result[value_index1][value_index2] \ - ) -/**/ - -#define COUNT sizeof(test_addition_result) - -int main(int argc, char *argv[]){ - // sanity check on test matrix - should be symetrical - for(int i = 0; i < VALUE_ARRAY_SIZE; ++i) - for(int j = i + 1; j < VALUE_ARRAY_SIZE; ++j) - assert(test_addition_result[i][j] == test_addition_result[j][i]); - - bool rval = true; - - TEST_EACH_VALUE_PAIR - return ! rval ; - - return ( - test_add(1, 2, "1", "2", '.') - ) ? EXIT_SUCCESS : EXIT_FAILURE; -} - - diff --git a/test/test_conversion.cpp b/test/test_conversion.cpp index ec1a56b..64a544e 100644 --- a/test/test_conversion.cpp +++ b/test/test_conversion.cpp @@ -14,7 +14,11 @@ // test conversion to T2 from different literal types template bool test_conversion(T1 v1, const char *t2_name, const char *t1_name){ - /* test conversion constructor to T1 */ + std::cout + << "testing safe<" << t2_name << "> = " << t1_name << ")" + << std::endl; +{ + /* test conversion constructor to T2 */ boost::numeric::safe t2; try{ t2 = v1; @@ -23,10 +27,7 @@ bool test_conversion(T1 v1, const char *t2_name, const char *t1_name){ << "failed to detect error in construction " << t2_name << "<-" << t1_name << std::endl; - try{ - t2 = v1; - } - catch(std::exception){} + t2 = v1; return false; } } @@ -37,12 +38,15 @@ bool test_conversion(T1 v1, const char *t2_name, const char *t1_name){ << t2_name << "<-" << t2_name << std::endl; try{ - t2 = v1; + t2 = v1; // try again for debugging } catch(std::exception){} return false; } } +} +{ + boost::numeric::safe t2; boost::numeric::safe t1 = v1; try{ t2 = t1; @@ -73,6 +77,7 @@ bool test_conversion(T1 v1, const char *t2_name, const char *t1_name){ } return true; // passed test } +} #include "test.hpp" #include "test_types.hpp" diff --git a/test/test_z copy.cpp b/test/test_z copy.cpp deleted file mode 100644 index 5f81051..0000000 --- a/test/test_z copy.cpp +++ /dev/null @@ -1,281 +0,0 @@ -// 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) - -#if 1 - -/* Boost test/test_float.cpp - * test arithmetic operations on a range of intervals - * - * Copyright 2003 Guillaume Melquiond - * - * Distributed under the Boost Software License, Version 1.0. - * (See accompanying file LICENSE_1_0.txt or - * copy at http://www.boost.org/LICENSE_1_0.txt) - */ - -#include -#include -#include -//#include "bugs.hpp" - -/* All the following tests should be BOOST_CHECK; however, if a test fails, - the probability is high that hundreds of other tests will fail, so it is - replaced by BOOST_REQUIRE to avoid flooding the logs. */ - -template -void test_unary() { - typedef typename F::I I; - for(I a(-10., -9.91); a.lower() <= 10.; a += 0.3) { - if (!F::validate(a)) continue; - I rI = F::f_I(a); - T rT1 = F::f_T(a.lower()), rT2 = F::f_T(a.upper()), - rT3 = F::f_T(median(a)); - BOOST_REQUIRE(in(rT1, rI)); - BOOST_REQUIRE(in(rT2, rI)); - BOOST_REQUIRE(in(rT3, rI)); - } -} - -template -void test_binary() { - typedef typename F::I I; - for(I a(-10., -9.91); a.lower() <= 10.; a += 0.3) { - for(I b(-10., -9.91); b.lower() <= 10.; b += 0.3) { - if (!F::validate(a, b)) continue; - T al = a.lower(), au = a.upper(), bl = b.lower(), bu = b.upper(); - I rII = F::f_II(a, b); - I rIT1 = F::f_IT(a, bl), rIT2 = F::f_IT(a, bu); - I rTI1 = F::f_TI(al, b), rTI2 = F::f_TI(au, b); - I rTT1 = F::f_TT(al, bl), rTT2 = F::f_TT(al, bu); - I rTT3 = F::f_TT(au, bl), rTT4 = F::f_TT(au, bu); - BOOST_REQUIRE(subset(rTT1, rIT1)); - BOOST_REQUIRE(subset(rTT3, rIT1)); - BOOST_REQUIRE(subset(rTT2, rIT2)); - BOOST_REQUIRE(subset(rTT4, rIT2)); - BOOST_REQUIRE(subset(rTT1, rTI1)); - BOOST_REQUIRE(subset(rTT2, rTI1)); - BOOST_REQUIRE(subset(rTT3, rTI2)); - BOOST_REQUIRE(subset(rTT4, rTI2)); - BOOST_REQUIRE(subset(rIT1, rII)); - BOOST_REQUIRE(subset(rIT2, rII)); - BOOST_REQUIRE(subset(rTI1, rII)); - BOOST_REQUIRE(subset(rTI2, rII)); - } - } -} - -#define new_unary_bunch(name, op, val) \ - template \ - struct name { \ - typedef boost::numeric::interval I; \ - static I f_I(const I& a) { return op(a); } \ - static T f_T(const T& a) { return op(a); } \ - static bool validate(const I& a) { return val; } \ - } - -//#ifndef BOOST_NO_STDC_NAMESPACE -using std::abs; -using std::sqrt; -//#endif - -new_unary_bunch(bunch_pos, +, true); -new_unary_bunch(bunch_neg, -, true); -new_unary_bunch(bunch_sqrt, sqrt, a.lower() >= 0.); -//new_unary_bunch(bunch_abs, abs, true); - -template -void test_all_unaries() { - BOOST_TEST_CHECKPOINT("pos"); test_unary >(); - BOOST_TEST_CHECKPOINT("neg"); test_unary >(); - BOOST_TEST_CHECKPOINT("sqrt"); test_unary >(); - //BOOST_TEST_CHECKPOINT("abs"); test_unary >(); -} - -#define new_binary_bunch(name, op, val) \ - template \ - struct bunch_##name { \ - typedef boost::numeric::interval I; \ - static I f_II(const I& a, const I& b) { return a op b; } \ - static I f_IT(const I& a, const T& b) { return a op b; } \ - static I f_TI(const T& a, const I& b) { return a op b; } \ - static I f_TT(const T& a, const T& b) \ - { return boost::numeric::interval_lib::name(a,b); } \ - static bool validate(const I& a, const I& b) { return val; } \ - } - -new_binary_bunch(add, +, true); -new_binary_bunch(sub, -, true); -new_binary_bunch(mul, *, true); -new_binary_bunch(div, /, !zero_in(b)); - -template -void test_all_binaries() { - BOOST_TEST_CHECKPOINT("add"); test_binary >(); - BOOST_TEST_CHECKPOINT("sub"); test_binary >(); - BOOST_TEST_CHECKPOINT("mul"); test_binary >(); - BOOST_TEST_CHECKPOINT("div"); test_binary >(); -} - -namespace boost { -namespace unit_test { -bool boost::unit_test::test_suite * -init_unit_test_suite( int argc, char* argv[] ){ - return 0; -} -} -} - -int test_main(int, char *[]) { - BOOST_TEST_CHECKPOINT("int tests"); - test_all_unaries (); - test_all_binaries (); - BOOST_TEST_CHECKPOINT("unsigned int tests"); - test_all_unaries(); - test_all_binaries(); - return 0; -} - -#elif 0 -#include "../include/safe_integer.hpp" -#include -#include - -struct A {}; - -static_assert( - ! std::is_base_of::value, - "const int should not be a safe type" -); - -int main(int argc, char * argv[]){ - boost::numeric::safe x = 255; - int y = 1; - - static_assert( - boost::numeric::is_safe::value, - "x is not a safe type" - ); - static_assert( - ! boost::numeric::is_safe::value, - "y is a safe type" - ); - static_assert( - boost::mpl::or_< - boost::numeric::is_safe, - boost::numeric::is_safe - >::value, - "or fails to work" - ); - //x + y; - std::cout << x + y << std::endl; - return 0; -} - -#elif 0 -#include -#include -#include "../include/safe_integer.hpp" - -int main(int argc, char * argv[]){ - SAFE_NUMERIC_CONSTEXPR boost::numeric::safe si = 4; - typedef boost::mpl::print< - decltype(si + si) - >::type t2; // should be same as type above - - - std::cout << si + si; - - /* - boost::numeric::safe t; - boost::numeric::safe u; - - SAFE_NUMERIC_CONSTEXPR boost::numeric::safe x = std::numeric_limits::max(); - SAFE_NUMERIC_CONSTEXPR const int y = boost::numeric::base_value(std::numeric_limits::max()); - - SAFE_NUMERIC_CONSTEXPR boost::numeric::checked_result maxx = boost::numeric::checked::add( - boost::numeric::base_value(std::numeric_limits::max()), - boost::numeric::base_value(std::numeric_limits::max()) - ); - */ - return 0; -} - -#elif 0 -struct A { - int m_x; - A() = delete; - SAFE_NUMERIC_CONSTEXPR A(const int & x) : - m_x(x) - {} - SAFE_NUMERIC_CONSTEXPR A(const A & a) : - m_x(a.m_x) - {} - /* - SAFE_NUMERIC_CONSTEXPR A(const A & a) : - m_x(a.m_x) - {} - SAFE_NUMERIC_CONSTEXPR A(const int & x) : - m_x(x) - {} - */ -}; - -SAFE_NUMERIC_CONSTEXPR int f(int x){ - return x; -} - -SAFE_NUMERIC_CONSTEXPR int g(const int & x){ - return x; -} - -SAFE_NUMERIC_CONSTEXPR int h(const int && x){ - return x; -} - -SAFE_NUMERIC_CONSTEXPR const A a = {A(1)}; -SAFE_NUMERIC_CONSTEXPR int b = f(0); -SAFE_NUMERIC_CONSTEXPR int c = g(0); - -int main(int argc, char * argv[]){ - const int a = f(argc); - const int b = g(argc); - const int c = g(argc + argc); - const A d = A(argc + 4); - const A e = A(argc); - const A g = A(f(argc)); -} - -#elif 0 -#include -#include - - -BOOST_MPL_ASSERT_RELATION( - (boost::integer_traits::const_max), - >, - (boost::integer_traits::const_max) -); // compile error under clang - -enum { x = ( - (boost::integer_traits::const_max) - > - (boost::integer_traits::const_max) - ) -}; // compiles OK - can't figure out why - -SAFE_NUMERIC_CONSTEXPR bool result = ( - (boost::integer_traits::const_max) - > - (boost::integer_traits::const_max) - ); // compiles fine - -static_assert(result, "compilation error"); - -int main(int argc, char * argv[]){ - return ! (boost::integer_traits::const_max > boost::integer_traits::const_max); -} - -#endif diff --git a/test/test_z.cpp b/test/test_z.cpp index ca511b5..9775676 100644 --- a/test/test_z.cpp +++ b/test/test_z.cpp @@ -8,6 +8,6 @@ constexpr int factorial (int n) int main(){ int n; std::cin >> n; - constexpr int x = factorial( n ); + factorial( n ); return 0; }