Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:51:09

0001 /* boost random/detail/signed_unsigned_tools.hpp header file
0002  *
0003  * Copyright Jens Maurer 2006
0004  * Distributed under the Boost Software License, Version 1.0. (See
0005  * accompanying file LICENSE_1_0.txt or copy at
0006  * http://www.boost.org/LICENSE_1_0.txt)
0007  *
0008  * See http://www.boost.org for most recent version including documentation.
0009  */
0010 
0011 #ifndef BOOST_RANDOM_DETAIL_SIGNED_UNSIGNED_TOOLS
0012 #define BOOST_RANDOM_DETAIL_SIGNED_UNSIGNED_TOOLS
0013 
0014 #include <boost/limits.hpp>
0015 #include <boost/config.hpp>
0016 #include <boost/random/traits.hpp>
0017 
0018 namespace boost {
0019 namespace random {
0020 namespace detail {
0021 
0022 
0023 /*
0024  * Compute x - y, we know that x >= y, return an unsigned value.
0025  */
0026 
0027 template<class T, bool sgn = std::numeric_limits<T>::is_signed && std::numeric_limits<T>::is_bounded>
0028 struct subtract { };
0029 
0030 template<class T>
0031 struct subtract<T, /* signed */ false>
0032 {
0033   typedef T result_type;
0034   result_type operator()(T x, T y) { return x - y; }
0035 };
0036 
0037 template<class T>
0038 struct subtract<T, /* signed */ true>
0039 {
0040   typedef typename boost::random::traits::make_unsigned_or_unbounded<T>::type result_type;
0041   result_type operator()(T x, T y)
0042   {
0043     if (y >= 0)   // because x >= y, it follows that x >= 0, too
0044       return result_type(x) - result_type(y);
0045     if (x >= 0)   // y < 0
0046       // avoid the nasty two's complement case for y == min()
0047       return result_type(x) + result_type(-(y+1)) + 1;
0048     // both x and y are negative: no signed overflow
0049     return result_type(x - y);
0050   }
0051 };
0052 
0053 /*
0054  * Compute x + y, x is unsigned, result fits in type of "y".
0055  */
0056 
0057 template<class T1, class T2, bool sgn = (std::numeric_limits<T2>::is_signed && (std::numeric_limits<T1>::digits >= std::numeric_limits<T2>::digits))>
0058 struct add { };
0059 
0060 template<class T1, class T2>
0061 struct add<T1, T2, /* signed or else T2 has more digits than T1 so the cast always works - needed when T2 is a multiprecision type and T1 is a native integer */ false>
0062 {
0063   typedef T2 result_type;
0064   result_type operator()(T1 x, T2 y) { return T2(x) + y; }
0065 };
0066 
0067 template<class T1, class T2>
0068 struct add<T1, T2, /* signed */ true>
0069 {
0070   typedef T2 result_type;
0071   result_type operator()(T1 x, T2 y)
0072   {
0073     if (y >= 0)
0074       return T2(x) + y;
0075     // y < 0
0076     if (x > T1(-(y+1)))  // result >= 0 after subtraction
0077       // avoid the nasty two's complement edge case for y == min()
0078       return T2(x - T1(-(y+1)) - 1);
0079     // abs(x) < abs(y), thus T2 able to represent x
0080     return T2(x) + y;
0081   }
0082 };
0083 
0084 } // namespace detail
0085 } // namespace random
0086 } // namespace boost
0087 
0088 #endif // BOOST_RANDOM_DETAIL_SIGNED_UNSIGNED_TOOLS
0089