@@ -8,6 +8,7 @@ Author: Daniel Kroening, kroening@kroening.com
8
8
9
9
#include " mp_arith.h"
10
10
11
+ #include < algorithm>
11
12
#include < cctype>
12
13
#include < cstdlib>
13
14
#include < limits>
@@ -219,34 +220,68 @@ unsigned integer2unsigned(const mp_integer &n)
219
220
return (unsigned )ull;
220
221
}
221
222
222
- // / bitwise or bitwise operations only make sense on native objects, hence the
223
- // / largest object size should be the largest available c++ integer size
224
- // / (currently long long)
225
- mp_integer bitwise_or (const mp_integer &a, const mp_integer &b)
223
+ // / bitwise binary operation over two integers, given as a functor
224
+ // / \param a: the first integer
225
+ // / \param b: the second integer
226
+ // / \param f: the function over two bits
227
+ mp_integer bitwise (
228
+ const mp_integer &a,
229
+ const mp_integer &b,
230
+ std::function<bool (bool , bool )> f)
226
231
{
227
- PRECONDITION (a.is_ulong () && b.is_ulong ());
228
- ullong_t result=a.to_ulong ()|b.to_ulong ();
232
+ const auto digits = std::max (a.digits (2 ), b.digits (2 ));
233
+
234
+ mp_integer result = 0 ;
235
+ mp_integer tmp_a = a, tmp_b = b;
236
+
237
+ for (std::size_t i = 0 ; i < digits; i++)
238
+ {
239
+ const bool bit_a = tmp_a.is_odd ();
240
+ const bool bit_b = tmp_b.is_odd ();
241
+ const bool bit_result = f (bit_a, bit_b);
242
+ if (bit_result)
243
+ result += power (2 , i);
244
+ tmp_a /= 2 ;
245
+ tmp_b /= 2 ;
246
+ }
247
+
229
248
return result;
230
249
}
231
250
232
- // / bitwise and bitwise operations only make sense on native objects, hence the
233
- // / largest object size should be the largest available c++ integer size
234
- // / (currently long long)
251
+ // / bitwise 'or' of two nonnegative integers
252
+ mp_integer bitwise_or (const mp_integer &a, const mp_integer &b)
253
+ {
254
+ PRECONDITION (!a.is_negative () && !b.is_negative ());
255
+
256
+ // fast path for small numbers
257
+ if (a.is_ulong () && b.is_ulong ())
258
+ return a.to_ulong () | b.to_ulong ();
259
+
260
+ return bitwise (a, b, [](bool a, bool b) { return a || b; });
261
+ }
262
+
263
+ // / bitwise 'and' of two nonnegative integers
235
264
mp_integer bitwise_and (const mp_integer &a, const mp_integer &b)
236
265
{
237
- PRECONDITION (a.is_ulong () && b.is_ulong ());
238
- ullong_t result=a.to_ulong ()&b.to_ulong ();
239
- return result;
266
+ PRECONDITION (!a.is_negative () && !b.is_negative ());
267
+
268
+ // fast path for small numbers
269
+ if (a.is_ulong () && b.is_ulong ())
270
+ return a.to_ulong () & b.to_ulong ();
271
+
272
+ return bitwise (a, b, [](bool a, bool b) { return a && b; });
240
273
}
241
274
242
- // / bitwise xor bitwise operations only make sense on native objects, hence the
243
- // / largest object size should be the largest available c++ integer size
244
- // / (currently long long)
275
+ // / bitwise 'xor' of two nonnegative integers
245
276
mp_integer bitwise_xor (const mp_integer &a, const mp_integer &b)
246
277
{
247
- PRECONDITION (a.is_ulong () && b.is_ulong ());
248
- ullong_t result=a.to_ulong ()^b.to_ulong ();
249
- return result;
278
+ PRECONDITION (!a.is_negative () && !b.is_negative ());
279
+
280
+ // fast path for small numbers
281
+ if (a.is_ulong () && b.is_ulong ())
282
+ return a.to_ulong () ^ b.to_ulong ();
283
+
284
+ return bitwise (a, b, [](bool a, bool b) { return a ^ b; });
250
285
}
251
286
252
287
// / arithmetic left shift bitwise operations only make sense on native objects,
0 commit comments