Chris@16: /* boost random/detail/signed_unsigned_tools.hpp header file Chris@16: * Chris@16: * Copyright Jens Maurer 2006 Chris@16: * Distributed under the Boost Software License, Version 1.0. (See Chris@16: * accompanying file LICENSE_1_0.txt or copy at Chris@16: * http://www.boost.org/LICENSE_1_0.txt) Chris@16: * Chris@16: * See http://www.boost.org for most recent version including documentation. Chris@16: */ Chris@16: Chris@16: #ifndef BOOST_RANDOM_DETAIL_SIGNED_UNSIGNED_TOOLS Chris@16: #define BOOST_RANDOM_DETAIL_SIGNED_UNSIGNED_TOOLS Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: namespace boost { Chris@16: namespace random { Chris@16: namespace detail { Chris@16: Chris@16: Chris@16: /* Chris@16: * Compute x - y, we know that x >= y, return an unsigned value. Chris@16: */ Chris@16: Chris@16: template::is_signed> Chris@16: struct subtract { }; Chris@16: Chris@16: template Chris@16: struct subtract Chris@16: { Chris@16: typedef T result_type; Chris@16: result_type operator()(T x, T y) { return x - y; } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct subtract Chris@16: { Chris@16: typedef typename make_unsigned::type result_type; Chris@16: result_type operator()(T x, T y) Chris@16: { Chris@16: if (y >= 0) // because x >= y, it follows that x >= 0, too Chris@16: return result_type(x) - result_type(y); Chris@16: if (x >= 0) // y < 0 Chris@16: // avoid the nasty two's complement case for y == min() Chris@16: return result_type(x) + result_type(-(y+1)) + 1; Chris@16: // both x and y are negative: no signed overflow Chris@16: return result_type(x - y); Chris@16: } Chris@16: }; Chris@16: Chris@16: /* Chris@16: * Compute x + y, x is unsigned, result fits in type of "y". Chris@16: */ Chris@16: Chris@16: template::is_signed> Chris@16: struct add { }; Chris@16: Chris@16: template Chris@16: struct add Chris@16: { Chris@16: typedef T2 result_type; Chris@16: result_type operator()(T1 x, T2 y) { return T2(x) + y; } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct add Chris@16: { Chris@16: typedef T2 result_type; Chris@16: result_type operator()(T1 x, T2 y) Chris@16: { Chris@16: if (y >= 0) Chris@16: return T2(x) + y; Chris@16: // y < 0 Chris@16: if (x > T1(-(y+1))) // result >= 0 after subtraction Chris@16: // avoid the nasty two's complement edge case for y == min() Chris@16: return T2(x - T1(-(y+1)) - 1); Chris@16: // abs(x) < abs(y), thus T2 able to represent x Chris@16: return T2(x) + y; Chris@16: } Chris@16: }; Chris@16: Chris@16: } // namespace detail Chris@16: } // namespace random Chris@16: } // namespace boost Chris@16: Chris@16: #endif // BOOST_RANDOM_DETAIL_SIGNED_UNSIGNED_TOOLS Chris@16: