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
|
|
|