#ifndef BOOST_NUMERIC_CPP_HPP #define BOOST_NUMERIC_CPP_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) // policy which creates results types equal to that of C++ promotions. // Using the policy will permit the program to build and run in release // mode which is identical to that in debug mode except for the fact // that errors aren't trapped. #include // integral constant, remove_cv, conditional #include #include // integer type selection #include "safe_common.hpp" #include "checked_result.hpp" namespace boost { namespace safe_numerics { // in C++ the following rules govern integer arithmetic // This policy is use to emulate another compiler/machine architecture // For example, a Z80 has 8 bit char, 16 bit short, 16 bit int, 32 bit long. So one // would use cpp<8, 16, 16, 32, 32> to test programs destined to run on a Z80 // Follow section 5 of the standard. template< int CharBits, int ShortBits, int IntBits, int LongBits, int LongLongBits > struct cpp { public: using local_char_type = typename boost::int_t::exact; using local_short_type = typename boost::int_t::exact; using local_int_type = typename boost::int_t::exact; using local_long_type = typename boost::int_t::exact; using local_long_long_type = typename boost::int_t::exact; template using rank = typename std::conditional< std::is_same::type>::value, std::integral_constant, typename std::conditional< std::is_same::type>::value, std::integral_constant, typename std::conditional< std::is_same::type>::value, std::integral_constant, typename std::conditional< std::is_same::type>::value, std::integral_constant, typename std::conditional< std::is_same::type>::value, std::integral_constant, std::integral_constant // catch all - never promote integral >::type >::type >::type >::type >::type; // section 4.5 integral promotions // convert smaller of two types to the size of the larger template using higher_ranked_type = typename std::conditional< (rank::value < rank::value), U, T >::type; template using copy_sign = typename std::conditional< std::is_signed::value, typename std::make_signed::type, typename std::make_unsigned::type >::type; template using integral_promotion = copy_sign< higher_ranked_type, T >; // note presumption that T & U don't have he same sign // if that's not true, these won't work template using select_signed = typename std::conditional< std::numeric_limits::is_signed, T, U >::type; template using select_unsigned = typename std::conditional< std::numeric_limits::is_signed, U, T >::type; // section 5 clause 11 - usual arithmetic conversions template using usual_arithmetic_conversions = // clause 0 - if both operands have the same type typename std::conditional< std::is_same::value, // no further conversion is needed T, // clause 1 - otherwise if both operands have the same sign typename std::conditional< std::numeric_limits::is_signed == std::numeric_limits::is_signed, // convert to the higher ranked type higher_ranked_type, // clause 2 - otherwise if the rank of he unsigned type exceeds // the rank of the of the signed type typename std::conditional< rank>::value >= rank< select_signed>::value, // use unsigned type select_unsigned, // clause 3 - otherwise if the type of the signed integer type can // represent all the values of the unsigned type typename std::conditional< std::numeric_limits< select_signed>::digits >= std::numeric_limits< select_unsigned>::digits, // use signed type select_signed, // clause 4 - otherwise use unsigned version of the signed type std::make_signed< select_signed> >::type >::type >::type >; template using result_type = typename usual_arithmetic_conversions< integral_promotion::type>, integral_promotion::type> >::type; public: template struct addition_result { using type = result_type; }; template struct subtraction_result { using type = result_type; }; template struct multiplication_result { using type = result_type; }; template struct division_result { using type = result_type; }; template struct modulus_result { using type = result_type; }; // note: comparison_result (<, >, ...) is special. // The return value is always a bool. The type returned here is // the intermediate type applied to make the values comparable. template struct comparison_result { using type = result_type; }; template struct left_shift_result { using type = result_type; }; template struct right_shift_result { using type = result_type; }; template struct bitwise_and_result { using type = result_type; }; template struct bitwise_or_result { using type = result_type; }; template struct bitwise_xor_result { using type = result_type; }; }; } // safe_numerics } // boost #endif // BOOST_NUMERIC_cpp_HPP