Skip to content

Commit 6931fb7

Browse files
author
Daniel Kroening
committed
bitwise_or, _and, _xor can now do arbitrary widths
1 parent ec8b34d commit 6931fb7

File tree

1 file changed

+49
-18
lines changed

1 file changed

+49
-18
lines changed

src/util/mp_arith.cpp

Lines changed: 49 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -219,34 +219,65 @@ unsigned integer2unsigned(const mp_integer &n)
219219
return (unsigned)ull;
220220
}
221221

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)
222+
/// bitwise operation of two integers
223+
mp_integer bitwise(
224+
const mp_integer &a,
225+
const mp_integer &b,
226+
std::function<bool(bool, bool)> f)
226227
{
227-
PRECONDITION(a.is_ulong() && b.is_ulong());
228-
ullong_t result=a.to_ulong()|b.to_ulong();
228+
const auto digits = std::max(a.digits(2), b.digits(2));
229+
230+
mp_integer result = 0;
231+
mp_integer tmp_a = a, tmp_b = b;
232+
233+
for(std::size_t i = 0; i < digits; i++)
234+
{
235+
const bool bit_a = tmp_a.is_odd();
236+
const bool bit_b = tmp_b.is_odd();
237+
const bool bit_result = f(bit_a, bit_b);
238+
if(bit_result)
239+
result += power(2, i);
240+
tmp_a /= 2;
241+
tmp_b /= 2;
242+
}
243+
229244
return result;
230245
}
231246

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)
247+
/// bitwise 'or' of two nonnegative integers
248+
mp_integer bitwise_or(const mp_integer &a, const mp_integer &b)
249+
{
250+
PRECONDITION(!a.is_negative() && !b.is_negative());
251+
252+
// fast path for small numbers
253+
if(a.is_ulong() && b.is_ulong())
254+
return a.to_ulong() | b.to_ulong();
255+
256+
return bitwise(a, b, [](bool a, bool b) { return a || b; });
257+
}
258+
259+
/// bitwise 'and' of two nonnegative integers
235260
mp_integer bitwise_and(const mp_integer &a, const mp_integer &b)
236261
{
237-
PRECONDITION(a.is_ulong() && b.is_ulong());
238-
ullong_t result=a.to_ulong()&b.to_ulong();
239-
return result;
262+
PRECONDITION(!a.is_negative() && !b.is_negative());
263+
264+
// fast path for small numbers
265+
if(a.is_ulong() && b.is_ulong())
266+
return a.to_ulong() & b.to_ulong();
267+
268+
return bitwise(a, b, [](bool a, bool b) { return a && b; });
240269
}
241270

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)
271+
/// bitwise 'xor' of two nonnegative integers
245272
mp_integer bitwise_xor(const mp_integer &a, const mp_integer &b)
246273
{
247-
PRECONDITION(a.is_ulong() && b.is_ulong());
248-
ullong_t result=a.to_ulong()^b.to_ulong();
249-
return result;
274+
PRECONDITION(!a.is_negative() && !b.is_negative());
275+
276+
// fast path for small numbers
277+
if(a.is_ulong() && b.is_ulong())
278+
return a.to_ulong() ^ b.to_ulong();
279+
280+
return bitwise(a, b, [](bool a, bool b) { return a ^ b; });
250281
}
251282

252283
/// bitwise negation bitwise operations only make sense on native objects, hence

0 commit comments

Comments
 (0)