@@ -8,6 +8,7 @@ Author: Daniel Kroening, kroening@kroening.com
88
99#include " mp_arith.h"
1010
11+ #include < algorithm>
1112#include < cctype>
1213#include < cstdlib>
1314#include < limits>
@@ -219,34 +220,68 @@ unsigned integer2unsigned(const mp_integer &n)
219220 return (unsigned )ull;
220221}
221222
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)
226231{
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+
229248 return result;
230249}
231250
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
235264mp_integer bitwise_and (const mp_integer &a, const mp_integer &b)
236265{
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; });
240273}
241274
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
245276mp_integer bitwise_xor (const mp_integer &a, const mp_integer &b)
246277{
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; });
250285}
251286
252287// / arithmetic left shift bitwise operations only make sense on native objects,
0 commit comments