BitShares-Core  4.0.0
BitShares blockchain implementation and command-line interface software
safe_compare.hpp
Go to the documentation of this file.
1 #ifndef BOOST_NUMERIC_SAFE_COMPARE_HPP
2 #define BOOST_NUMERIC_SAFE_COMPARE_HPP
3 
4 // MS compatible compilers support #pragma once
5 #if defined(_MSC_VER) && (_MSC_VER >= 1020)
6 # pragma once
7 #endif
8 
9 // Copyright (c) 2012 Robert Ramey
10 //
11 // Distributed under the Boost Software License, Version 1.0. (See
12 // accompanying file BOOST_LICENSE_1_0.txt or copy at
13 // http://www.boost.org/LICENSE_1_0.txt)
14 
15 #include <type_traits>
16 #include <limits>
17 
18 namespace boost {
19 namespace safe_numerics {
20 namespace safe_compare {
21 
23 // safe comparison on primitive integral types
24 namespace safe_compare_detail {
25  template<typename T>
26  using make_unsigned = typename std::conditional<
27  std::is_signed<T>::value,
28  std::make_unsigned<T>,
29  T
30  >::type;
31 
32  // both arguments unsigned or signed
33  template<bool TS, bool US>
34  struct less_than {
35  template<class T, class U>
36  constexpr static bool invoke(const T & t, const U & u){
37  return t < u;
38  }
39  };
40 
41  // T unsigned, U signed
42  template<>
43  struct less_than<false, true> {
44  template<class T, class U>
45  constexpr static bool invoke(const T & t, const U & u){
46  return
47  (u < 0) ?
48  false
49  :
50  less_than<false, false>::invoke(
51  t,
52  static_cast<const typename make_unsigned<U>::type &>(u)
53  )
54  ;
55  }
56  };
57  // T signed, U unsigned
58  template<>
59  struct less_than<true, false> {
60  template<class T, class U>
61  constexpr static bool invoke(const T & t, const U & u){
62  return
63  (t < 0) ?
64  true
65  :
66  less_than<false, false>::invoke(
67  static_cast<const typename make_unsigned<T>::type &>(t),
68  u
69  )
70  ;
71  }
72  };
73 } // safe_compare_detail
74 
75 template<class T, class U>
76 typename std::enable_if<
77  std::is_integral<T>::value && std::is_integral<U>::value,
78  bool
79 >::type
80 constexpr less_than(const T & lhs, const U & rhs) {
81  return safe_compare_detail::less_than<
82  std::is_signed<T>::value,
83  std::is_signed<U>::value
84  >::template invoke(lhs, rhs);
85 }
86 
87 template<class T, class U>
88 typename std::enable_if<
89  std::is_floating_point<T>::value && std::is_floating_point<U>::value,
90  bool
91 >::type
92 constexpr less_than(const T & lhs, const U & rhs) {
93  return lhs < rhs;
94 }
95 
96 template<class T, class U>
97 constexpr bool greater_than(const T & lhs, const U & rhs) {
98  return less_than(rhs, lhs);
99 }
100 
101 template<class T, class U>
102 constexpr bool less_than_equal(const T & lhs, const U & rhs) {
103  return ! greater_than(lhs, rhs);
104 }
105 
106 template<class T, class U>
107 constexpr bool greater_than_equal(const T & lhs, const U & rhs) {
108  return ! less_than(lhs, rhs);
109 }
110 
111 namespace safe_compare_detail {
112  // both arguments unsigned or signed
113  template<bool TS, bool US>
114  struct equal {
115  template<class T, class U>
116  constexpr static bool invoke(const T & t, const U & u){
117  return t == u;
118  }
119  };
120 
121  // T unsigned, U signed
122  template<>
123  struct equal<false, true> {
124  template<class T, class U>
125  constexpr static bool invoke(const T & t, const U & u){
126  return
127  (u < 0) ?
128  false
129  :
130  equal<false, false>::invoke(
131  t,
132  static_cast<const typename make_unsigned<U>::type &>(u)
133  )
134  ;
135  }
136  };
137  // T signed, U unsigned
138  template<>
139  struct equal<true, false> {
140  template<class T, class U>
141  constexpr static bool invoke(const T & t, const U & u){
142  return
143  (t < 0) ?
144  false
145  :
146  equal<false, false>::invoke(
147  static_cast<const typename make_unsigned<T>::type &>(t),
148  u
149  )
150  ;
151  }
152  };
153 } // safe_compare_detail
154 
155 template<class T, class U>
156 typename std::enable_if<
157  std::is_integral<T>::value && std::is_integral<U>::value,
158  bool
159 >::type
160 constexpr equal(const T & lhs, const U & rhs) {
161  return safe_compare_detail::equal<
162  std::numeric_limits<T>::is_signed,
163  std::numeric_limits<U>::is_signed
164  >::template invoke(lhs, rhs);
165 }
166 
167 template<class T, class U>
168 typename std::enable_if<
169  std::is_floating_point<T>::value && std::is_floating_point<U>::value,
170  bool
171 >::type
172 constexpr equal(const T & lhs, const U & rhs) {
173  return lhs == rhs;
174 }
175 
176 template<class T, class U>
177 constexpr bool not_equal(const T & lhs, const U & rhs) {
178  return ! equal(lhs, rhs);
179 }
180 
181 } // safe_compare
182 } // safe_numerics
183 } // boost
184 
185 #endif // BOOST_NUMERIC_SAFE_COMPARE_HPP