@@ -219,34 +219,65 @@ unsigned integer2unsigned(const mp_integer &n)
219
219
return (unsigned )ull;
220
220
}
221
221
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)
226
227
{
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
+
229
244
return result;
230
245
}
231
246
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
235
260
mp_integer bitwise_and (const mp_integer &a, const mp_integer &b)
236
261
{
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; });
240
269
}
241
270
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
245
272
mp_integer bitwise_xor (const mp_integer &a, const mp_integer &b)
246
273
{
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; });
250
281
}
251
282
252
283
// / bitwise negation bitwise operations only make sense on native objects, hence
0 commit comments