90 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			90 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
|   | /* boost random/detail/signed_unsigned_tools.hpp header file | ||
|  |  * | ||
|  |  * Copyright Jens Maurer 2006 | ||
|  |  * 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) | ||
|  |  * | ||
|  |  * See http://www.boost.org for most recent version including documentation. | ||
|  |  */ | ||
|  | 
 | ||
|  | #ifndef BOOST_RANDOM_DETAIL_SIGNED_UNSIGNED_TOOLS | ||
|  | #define BOOST_RANDOM_DETAIL_SIGNED_UNSIGNED_TOOLS | ||
|  | 
 | ||
|  | #include <boost/limits.hpp> | ||
|  | #include <boost/config.hpp> | ||
|  | #include <boost/random/traits.hpp> | ||
|  | 
 | ||
|  | namespace boost { | ||
|  | namespace random { | ||
|  | namespace detail { | ||
|  | 
 | ||
|  | 
 | ||
|  | /* | ||
|  |  * Compute x - y, we know that x >= y, return an unsigned value. | ||
|  |  */ | ||
|  | 
 | ||
|  | template<class T, bool sgn = std::numeric_limits<T>::is_signed && std::numeric_limits<T>::is_bounded> | ||
|  | struct subtract { }; | ||
|  | 
 | ||
|  | template<class T> | ||
|  | struct subtract<T, /* signed */ false> | ||
|  | { | ||
|  |   typedef T result_type; | ||
|  |   result_type operator()(T x, T y) { return x - y; } | ||
|  | }; | ||
|  | 
 | ||
|  | template<class T> | ||
|  | struct subtract<T, /* signed */ true> | ||
|  | { | ||
|  |   typedef typename boost::random::traits::make_unsigned_or_unbounded<T>::type result_type; | ||
|  |   result_type operator()(T x, T y) | ||
|  |   { | ||
|  |     if (y >= 0)   // because x >= y, it follows that x >= 0, too | ||
|  |       return result_type(x) - result_type(y); | ||
|  |     if (x >= 0)   // y < 0 | ||
|  |       // avoid the nasty two's complement case for y == min() | ||
|  |       return result_type(x) + result_type(-(y+1)) + 1; | ||
|  |     // both x and y are negative: no signed overflow | ||
|  |     return result_type(x - y); | ||
|  |   } | ||
|  | }; | ||
|  | 
 | ||
|  | /* | ||
|  |  * Compute x + y, x is unsigned, result fits in type of "y". | ||
|  |  */ | ||
|  | 
 | ||
|  | template<class T1, class T2, bool sgn = (std::numeric_limits<T2>::is_signed && (std::numeric_limits<T1>::digits >= std::numeric_limits<T2>::digits))> | ||
|  | struct add { }; | ||
|  | 
 | ||
|  | template<class T1, class T2> | ||
|  | 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> | ||
|  | { | ||
|  |   typedef T2 result_type; | ||
|  |   result_type operator()(T1 x, T2 y) { return T2(x) + y; } | ||
|  | }; | ||
|  | 
 | ||
|  | template<class T1, class T2> | ||
|  | struct add<T1, T2, /* signed */ true> | ||
|  | { | ||
|  |   typedef T2 result_type; | ||
|  |   result_type operator()(T1 x, T2 y) | ||
|  |   { | ||
|  |     if (y >= 0) | ||
|  |       return T2(x) + y; | ||
|  |     // y < 0 | ||
|  |     if (x > T1(-(y+1)))  // result >= 0 after subtraction | ||
|  |       // avoid the nasty two's complement edge case for y == min() | ||
|  |       return T2(x - T1(-(y+1)) - 1); | ||
|  |     // abs(x) < abs(y), thus T2 able to represent x | ||
|  |     return T2(x) + y; | ||
|  |   } | ||
|  | }; | ||
|  | 
 | ||
|  | } // namespace detail | ||
|  | } // namespace random | ||
|  | } // namespace boost | ||
|  | 
 | ||
|  | #endif // BOOST_RANDOM_DETAIL_SIGNED_UNSIGNED_TOOLS | ||
|  | 
 |