You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase.
89 lines
2.2 KiB
89 lines
2.2 KiB
/* 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/type_traits/make_unsigned.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> |
|
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 make_unsigned<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> |
|
struct add { }; |
|
|
|
template<class T1, class T2> |
|
struct add<T1, T2, /* signed */ 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 |
|
|
|
|