@@ -12,8 +12,10 @@ Author: Daniel Kroening, kroening@kroening.com
12
12
13
13
#include < string>
14
14
#include < iosfwd>
15
+ #include < limits>
15
16
16
17
#include " big-int/bigint.hh"
18
+ #include " optional.h"
17
19
18
20
// NOLINTNEXTLINE(readability/identifiers)
19
21
typedef BigInt mp_integer;
@@ -48,9 +50,83 @@ const std::string integer2string(const mp_integer &, unsigned base=10);
48
50
const mp_integer string2integer (const std::string &, unsigned base=10 );
49
51
const std::string integer2binary (const mp_integer &, std::size_t width);
50
52
const mp_integer binary2integer (const std::string &, bool is_signed);
53
+
54
+ // / \deprecated use numeric_cast<unsigned long long> instead
51
55
mp_integer::ullong_t integer2ulong (const mp_integer &);
56
+
57
+ // / \deprecated use numeric_cast<std::size_t> instead
52
58
std::size_t integer2size_t (const mp_integer &);
59
+
60
+ // / \deprecated use numeric_cast<unsigned> instead
53
61
unsigned integer2unsigned (const mp_integer &);
62
+
54
63
const mp_integer mp_zero=string2integer(" 0" );
55
64
65
+ // / Numerical cast provides a unified way of converting from one numerical type
66
+ // / to another.
67
+ // / Generic case doesn't exist, this has to be specialized for different types.
68
+ template <typename T, typename = void >
69
+ struct numeric_castt final
70
+ {
71
+ };
72
+
73
+ // / Convert mp_integer to any signed type
74
+ // / \tparam T: type to convert to
75
+ // / \param mpi: mp_integer to convert
76
+ // / \return optional integer of type T if conversion is possible,
77
+ // / empty optional otherwise.
78
+ template <typename T>
79
+ struct numeric_castt <T,
80
+ typename std::enable_if<std::is_integral<T>::value &&
81
+ std::is_signed<T>::value>::type>
82
+ {
83
+ static optionalt<T> numeric_cast (const mp_integer &mpi)
84
+ {
85
+ static_assert (
86
+ std::numeric_limits<T>::max () <=
87
+ std::numeric_limits<decltype (mpi.to_long ())>::max () &&
88
+ std::numeric_limits<T>::min () >=
89
+ std::numeric_limits<decltype (mpi.to_long ())>::min (),
90
+ " Numeric cast only works for types smaller than long long" );
91
+ if (
92
+ mpi <= std::numeric_limits<T>::max () &&
93
+ mpi >= std::numeric_limits<T>::min ())
94
+ // to_long converts to long long which is the largest signed numeric type
95
+ return {static_cast <T>(mpi.to_long ())};
96
+ else
97
+ return {};
98
+ }
99
+ };
100
+
101
+ // / Convert mp_integer to any unsigned type
102
+ // / \tparam T: type to convert to
103
+ // / \param mpi: mp_integer to convert
104
+ // / \return optional integer of type T if conversion is possible,
105
+ // / empty optional otherwise.
106
+ template <typename T>
107
+ struct numeric_castt <T,
108
+ typename std::enable_if<std::is_integral<T>::value &&
109
+ !std::is_signed<T>::value>::type>
110
+ {
111
+ static optionalt<T> numeric_cast (const mp_integer &mpi)
112
+ {
113
+ static_assert (
114
+ std::numeric_limits<T>::max () <=
115
+ std::numeric_limits<decltype (mpi.to_ulong ())>::max () &&
116
+ std::numeric_limits<T>::min () >=
117
+ std::numeric_limits<decltype (mpi.to_ulong ())>::min (),
118
+ " Numeric cast only works for types smaller than unsigned long long" );
119
+ if (mpi <= std::numeric_limits<T>::max () && mpi >= 0 )
120
+ return {static_cast <T>(mpi.to_ulong ())};
121
+ else
122
+ return {};
123
+ }
124
+ };
125
+
126
+ template <typename T>
127
+ optionalt<T> numeric_cast (const mp_integer &mpi)
128
+ {
129
+ return numeric_castt<T>::numeric_cast (mpi);
130
+ }
131
+
56
132
#endif // CPROVER_UTIL_MP_ARITH_H
0 commit comments