Chris@16
|
1 /* boost random/detail/signed_unsigned_tools.hpp header file
|
Chris@16
|
2 *
|
Chris@16
|
3 * Copyright Jens Maurer 2006
|
Chris@16
|
4 * Distributed under the Boost Software License, Version 1.0. (See
|
Chris@16
|
5 * accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
6 * http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
7 *
|
Chris@16
|
8 * See http://www.boost.org for most recent version including documentation.
|
Chris@16
|
9 */
|
Chris@16
|
10
|
Chris@16
|
11 #ifndef BOOST_RANDOM_DETAIL_SIGNED_UNSIGNED_TOOLS
|
Chris@16
|
12 #define BOOST_RANDOM_DETAIL_SIGNED_UNSIGNED_TOOLS
|
Chris@16
|
13
|
Chris@16
|
14 #include <boost/limits.hpp>
|
Chris@16
|
15 #include <boost/config.hpp>
|
Chris@16
|
16 #include <boost/type_traits/make_unsigned.hpp>
|
Chris@16
|
17
|
Chris@16
|
18 namespace boost {
|
Chris@16
|
19 namespace random {
|
Chris@16
|
20 namespace detail {
|
Chris@16
|
21
|
Chris@16
|
22
|
Chris@16
|
23 /*
|
Chris@16
|
24 * Compute x - y, we know that x >= y, return an unsigned value.
|
Chris@16
|
25 */
|
Chris@16
|
26
|
Chris@16
|
27 template<class T, bool sgn = std::numeric_limits<T>::is_signed>
|
Chris@16
|
28 struct subtract { };
|
Chris@16
|
29
|
Chris@16
|
30 template<class T>
|
Chris@16
|
31 struct subtract<T, /* signed */ false>
|
Chris@16
|
32 {
|
Chris@16
|
33 typedef T result_type;
|
Chris@16
|
34 result_type operator()(T x, T y) { return x - y; }
|
Chris@16
|
35 };
|
Chris@16
|
36
|
Chris@16
|
37 template<class T>
|
Chris@16
|
38 struct subtract<T, /* signed */ true>
|
Chris@16
|
39 {
|
Chris@16
|
40 typedef typename make_unsigned<T>::type result_type;
|
Chris@16
|
41 result_type operator()(T x, T y)
|
Chris@16
|
42 {
|
Chris@16
|
43 if (y >= 0) // because x >= y, it follows that x >= 0, too
|
Chris@16
|
44 return result_type(x) - result_type(y);
|
Chris@16
|
45 if (x >= 0) // y < 0
|
Chris@16
|
46 // avoid the nasty two's complement case for y == min()
|
Chris@16
|
47 return result_type(x) + result_type(-(y+1)) + 1;
|
Chris@16
|
48 // both x and y are negative: no signed overflow
|
Chris@16
|
49 return result_type(x - y);
|
Chris@16
|
50 }
|
Chris@16
|
51 };
|
Chris@16
|
52
|
Chris@16
|
53 /*
|
Chris@16
|
54 * Compute x + y, x is unsigned, result fits in type of "y".
|
Chris@16
|
55 */
|
Chris@16
|
56
|
Chris@16
|
57 template<class T1, class T2, bool sgn = std::numeric_limits<T2>::is_signed>
|
Chris@16
|
58 struct add { };
|
Chris@16
|
59
|
Chris@16
|
60 template<class T1, class T2>
|
Chris@16
|
61 struct add<T1, T2, /* signed */ false>
|
Chris@16
|
62 {
|
Chris@16
|
63 typedef T2 result_type;
|
Chris@16
|
64 result_type operator()(T1 x, T2 y) { return T2(x) + y; }
|
Chris@16
|
65 };
|
Chris@16
|
66
|
Chris@16
|
67 template<class T1, class T2>
|
Chris@16
|
68 struct add<T1, T2, /* signed */ true>
|
Chris@16
|
69 {
|
Chris@16
|
70 typedef T2 result_type;
|
Chris@16
|
71 result_type operator()(T1 x, T2 y)
|
Chris@16
|
72 {
|
Chris@16
|
73 if (y >= 0)
|
Chris@16
|
74 return T2(x) + y;
|
Chris@16
|
75 // y < 0
|
Chris@16
|
76 if (x > T1(-(y+1))) // result >= 0 after subtraction
|
Chris@16
|
77 // avoid the nasty two's complement edge case for y == min()
|
Chris@16
|
78 return T2(x - T1(-(y+1)) - 1);
|
Chris@16
|
79 // abs(x) < abs(y), thus T2 able to represent x
|
Chris@16
|
80 return T2(x) + y;
|
Chris@16
|
81 }
|
Chris@16
|
82 };
|
Chris@16
|
83
|
Chris@16
|
84 } // namespace detail
|
Chris@16
|
85 } // namespace random
|
Chris@16
|
86 } // namespace boost
|
Chris@16
|
87
|
Chris@16
|
88 #endif // BOOST_RANDOM_DETAIL_SIGNED_UNSIGNED_TOOLS
|
Chris@16
|
89
|