Skip to content

Commit e3ad6c0

Browse files
committed
Update Big-Int with copy, move, swap
Fixes: #1340
1 parent c8f69b5 commit e3ad6c0

File tree

2 files changed

+108
-120
lines changed

2 files changed

+108
-120
lines changed

src/big-int/bigint.cc

+10-26
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,12 @@ BigInt::BigInt (BigInt const &y)
464464
memcpy (digit, y.digit, length * sizeof (onedig_t));
465465
}
466466

467+
BigInt::BigInt (BigInt &&y)
468+
: BigInt()
469+
{
470+
swap(y);
471+
}
472+
467473
BigInt::BigInt (char const *s, onedig_t b)
468474
: size (adjust_size (small)),
469475
length (0),
@@ -473,40 +479,18 @@ BigInt::BigInt (char const *s, onedig_t b)
473479
scan (s, b);
474480
}
475481

476-
477-
BigInt &
478-
BigInt::operator= (llong_t l)
479-
{
480-
reallocate (small);
481-
assign (l);
482-
return *this;
483-
}
484-
485-
BigInt &
486-
BigInt::operator= (ullong_t ul)
487-
{
488-
reallocate (small);
489-
assign (ul);
490-
return *this;
491-
}
492-
493482
BigInt &
494483
BigInt::operator= (BigInt const &y)
495484
{
496-
if (&y != this)
497-
{
498-
reallocate (y.length);
499-
length = y.length;
500-
positive = y.positive;
501-
memcpy (digit, y.digit, length * sizeof (onedig_t));
502-
}
485+
BigInt copy(y);
486+
swap(copy);
503487
return *this;
504488
}
505489

506490
BigInt &
507-
BigInt::operator= (char const *s)
491+
BigInt::operator= (BigInt &&y)
508492
{
509-
scan (s);
493+
swap(y);
510494
return *this;
511495
}
512496

src/big-int/bigint.hh

+98-94
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
#ifndef BIGINT_HH
66
#define BIGINT_HH
77

8+
#include <utility>
9+
810
// This one is pretty simple but has a fair divide implementation.
911
// Though I'm not ambitious enough to do that FFT-like stuff.
1012
//
@@ -166,12 +168,11 @@ public:
166168
BigInt (llong_t) _fast;
167169
BigInt (ullong_t) _fast;
168170
BigInt (BigInt const &) _fast;
171+
BigInt (BigInt &&) _fast;
169172
BigInt (char const *, onedig_t = 10) _fast;
170173

171-
BigInt &operator= (llong_t) _fast;
172-
BigInt &operator= (ullong_t) _fast;
173174
BigInt &operator= (BigInt const &) _fast;
174-
BigInt &operator= (char const *) _fast;
175+
BigInt &operator= (BigInt &&) _fast;
175176

176177
// Input conversion from text.
177178

@@ -220,8 +221,9 @@ public:
220221

221222
// Eliminate need for explicit casts when comparing.
222223

223-
int compare (int n) const { return compare (llong_t (n)); }
224-
int compare (unsigned n) const { return compare (ullong_t (n)); }
224+
int compare (unsigned long n) const { return compare (static_cast<ullong_t>(n)); }
225+
int compare (int n) const { return compare (static_cast<llong_t> (n)); }
226+
int compare (unsigned n) const { return compare (static_cast<ullong_t>(n)); }
225227

226228
// Tests. These are faster than comparing with 0 or of course %2.
227229

@@ -236,109 +238,51 @@ public:
236238
BigInt &negate() { if(!is_zero()) positive = !positive; return *this; }
237239
BigInt operator-() const { return BigInt (*this).negate(); }
238240

239-
BigInt &operator+= (llong_t) _fast;
240-
BigInt &operator-= (llong_t) _fast;
241-
BigInt &operator*= (llong_t) _fast;
242-
BigInt &operator/= (llong_t) _fast;
243-
BigInt &operator%= (llong_t) _fast;
244-
245-
BigInt &operator= (unsigned long x) { return (*this)=(ullong_t)x; }
246-
BigInt &operator+= (unsigned long x) { return (*this)+=(ullong_t)x; }
247-
BigInt &operator-= (unsigned long x) { return (*this)-=(ullong_t)x; }
248-
BigInt &operator*= (unsigned long x) { return (*this)*=(ullong_t)x; }
249-
BigInt &operator/= (unsigned long x) { return (*this)/=(ullong_t)x; }
250-
BigInt &operator%= (unsigned long x) { return (*this)%=(ullong_t)x; }
251-
252-
BigInt &operator+= (ullong_t) _fast;
253-
BigInt &operator-= (ullong_t) _fast;
254-
BigInt &operator*= (ullong_t) _fast;
255-
BigInt &operator/= (ullong_t) _fast;
256-
BigInt &operator%= (ullong_t) _fast;
257-
258-
BigInt &operator+= (BigInt const &) _fast;
259-
BigInt &operator-= (BigInt const &) _fast;
260-
BigInt &operator*= (BigInt const &) _fast;
261-
BigInt &operator/= (BigInt const &) _fasta;
262-
BigInt &operator%= (BigInt const &) _fasta;
241+
#define IN_PLACE_OPERATOR(TYPE) \
242+
BigInt &operator+= (TYPE) _fast; \
243+
BigInt &operator-= (TYPE) _fast; \
244+
BigInt &operator*= (TYPE) _fast; \
245+
BigInt &operator/= (TYPE) _fast; \
246+
BigInt &operator%= (TYPE) _fast;
247+
248+
IN_PLACE_OPERATOR(const BigInt &)
249+
IN_PLACE_OPERATOR(llong_t)
250+
IN_PLACE_OPERATOR(ullong_t)
251+
#undef IN_PLACE_OPERATOR
252+
253+
#define OVERLOAD_IN_PLACE_OPERATOR(FROM, TO) \
254+
BigInt &operator+=(FROM x) { return operator+=(static_cast<TO>(x)); } \
255+
BigInt &operator-=(FROM x) { return operator-=(static_cast<TO>(x)); } \
256+
BigInt &operator*=(FROM x) { return operator*=(static_cast<TO>(x)); } \
257+
BigInt &operator/=(FROM x) { return operator/=(static_cast<TO>(x)); } \
258+
BigInt &operator%=(FROM x) { return operator%=(static_cast<TO>(x)); }
259+
260+
OVERLOAD_IN_PLACE_OPERATOR(unsigned long, ullong_t)
261+
OVERLOAD_IN_PLACE_OPERATOR(int, llong_t)
262+
OVERLOAD_IN_PLACE_OPERATOR(unsigned, ullong_t)
263+
#undef OVERLOAD_IN_PLACE_OPERATOR
263264

264265
BigInt &operator++ () { return operator+=(1); } // preincrement
265266
BigInt &operator-- () { return operator-=(1); } // predecrement
266267

267268
static void div (BigInt const &, BigInt const &,
268269
BigInt &quot, BigInt &rem) _fasta;
269270

270-
// Avoid the need for explicit casts to [u]llong_t.
271-
272-
// disabled by DK
273-
//operator int() const { return int (operator llong_t()); }
274-
//operator unsigned() const { return unsigned (operator ullong_t()); }
275-
276-
BigInt &operator = (int n) { return operator = (llong_t (n)); }
277-
BigInt &operator+= (int n) { return operator+= (llong_t (n)); }
278-
BigInt &operator-= (int n) { return operator-= (llong_t (n)); }
279-
BigInt &operator*= (int n) { return operator*= (llong_t (n)); }
280-
BigInt &operator/= (int n) { return operator/= (llong_t (n)); }
281-
BigInt &operator%= (int n) { return operator%= (llong_t (n)); }
282-
283-
BigInt &operator = (unsigned n) { return operator = (ullong_t (n)); }
284-
BigInt &operator+= (unsigned n) { return operator+= (ullong_t (n)); }
285-
BigInt &operator-= (unsigned n) { return operator-= (ullong_t (n)); }
286-
BigInt &operator*= (unsigned n) { return operator*= (ullong_t (n)); }
287-
BigInt &operator/= (unsigned n) { return operator/= (ullong_t (n)); }
288-
BigInt &operator%= (unsigned n) { return operator%= (ullong_t (n)); }
289-
290-
// Binary arithmetic operators. These are entirely syntactic sugar.
291-
// Though there's joy in repetition -- let the preprocessor enjoy.
292-
293-
#define decl_binary(T) \
294-
BigInt operator+ (T b) const { return BigInt (*this) += b; } \
295-
BigInt operator- (T b) const { return BigInt (*this) -= b; } \
296-
BigInt operator* (T b) const { return BigInt (*this) *= b; } \
297-
BigInt operator/ (T b) const { return BigInt (*this) /= b; } \
298-
BigInt operator% (T b) const { return BigInt (*this) %= b; }
299-
decl_binary (int);
300-
decl_binary (unsigned);
301-
decl_binary (llong_t);
302-
decl_binary (ullong_t);
303-
decl_binary (BigInt const &);
304-
#undef decl_binary
305-
306-
BigInt operator+ (unsigned long b) const { return BigInt (*this) += (ullong_t)b; } \
307-
BigInt operator- (unsigned long b) const { return BigInt (*this) -= (ullong_t)b; } \
308-
BigInt operator* (unsigned long b) const { return BigInt (*this) *= (ullong_t)b; } \
309-
BigInt operator/ (unsigned long b) const { return BigInt (*this) /= (ullong_t)b; } \
310-
BigInt operator% (unsigned long b) const { return BigInt (*this) %= (ullong_t)b; }
311-
312-
// Binary comparision operators.
313-
314-
#define decl_binary(T) \
315-
bool operator< (T b) const { return compare (b) < 0; } \
316-
bool operator> (T b) const { return compare (b) > 0; } \
317-
bool operator<= (T b) const { return compare (b) <= 0; } \
318-
bool operator>= (T b) const { return compare (b) >= 0; } \
319-
bool operator== (T b) const { return compare (b) == 0; } \
320-
bool operator!= (T b) const { return compare (b) != 0; }
321-
decl_binary (int);
322-
decl_binary (unsigned);
323-
decl_binary (llong_t);
324-
decl_binary (ullong_t);
325-
decl_binary (BigInt const &);
326-
#undef decl_binary
327-
328-
bool operator< (unsigned long b) const { return compare ((ullong_t)b) < 0; } \
329-
bool operator> (unsigned long b) const { return compare ((ullong_t)b) > 0; } \
330-
bool operator<= (unsigned long b) const { return compare ((ullong_t)b) <= 0; } \
331-
bool operator>= (unsigned long b) const { return compare ((ullong_t)b) >= 0; } \
332-
bool operator== (unsigned long b) const { return compare ((ullong_t)b) == 0; } \
333-
bool operator!= (unsigned long b) const { return compare ((ullong_t)b) != 0; }
334-
335271
// Returns the largest x such that 2^x <= abs() or 0 if input is 0
336272
// Not part of original BigInt.
337273
unsigned floorPow2 () const _fast;
338274

339275
// Sets the number to the power of two given by the exponent
340276
// Not part of original BigInt.
341277
void setPower2 (unsigned exponent) _fast;
278+
279+
void swap (BigInt &other)
280+
{
281+
std::swap(other.size, size);
282+
std::swap(other.length, length);
283+
std::swap(other.digit, digit);
284+
std::swap(other.positive, positive);
285+
}
342286
};
343287

344288

@@ -350,5 +294,65 @@ BigInt sqrt (BigInt const &) _fast;
350294
BigInt gcd (const BigInt &, const BigInt &) _fast;
351295
BigInt modinv (const BigInt &, const BigInt &) _fast;
352296

297+
// Binary arithmetic operators
298+
299+
inline BigInt operator+ (const BigInt &lhs, const BigInt &rhs) { return BigInt(lhs) += rhs; }
300+
inline BigInt operator- (const BigInt &lhs, const BigInt &rhs) { return BigInt(lhs) -= rhs; }
301+
inline BigInt operator* (const BigInt &lhs, const BigInt &rhs) { return BigInt(lhs) *= rhs; }
302+
inline BigInt operator/ (const BigInt &lhs, const BigInt &rhs) { return BigInt(lhs) /= rhs; }
303+
inline BigInt operator% (const BigInt &lhs, const BigInt &rhs) { return BigInt(lhs) %= rhs; }
304+
305+
// Because the operators `+` and `*` are associative, we can do fast math, no
306+
// matter which side the BigInt is on. For the rest of the operators, which
307+
// are non-associative, we can only get speedups if the primitive type is on
308+
// the RHS.
309+
#define BINARY_ARITHMETIC_OPERATORS(OTHER) \
310+
inline BigInt operator+ (const BigInt &lhs, OTHER rhs) { return BigInt(lhs) += rhs; } \
311+
inline BigInt operator+ (OTHER lhs, const BigInt &rhs) { return BigInt(rhs) += lhs; } \
312+
inline BigInt operator* (const BigInt &lhs, OTHER rhs) { return BigInt(lhs) *= rhs; } \
313+
inline BigInt operator* (OTHER lhs, const BigInt &rhs) { return BigInt(rhs) *= lhs; } \
314+
inline BigInt operator- (const BigInt &lhs, OTHER rhs) { return BigInt(lhs) -= rhs; } \
315+
inline BigInt operator/ (const BigInt &lhs, OTHER rhs) { return BigInt(lhs) /= rhs; } \
316+
inline BigInt operator% (const BigInt &lhs, OTHER rhs) { return BigInt(lhs) %= rhs; }
317+
318+
BINARY_ARITHMETIC_OPERATORS(BigInt::llong_t)
319+
BINARY_ARITHMETIC_OPERATORS(BigInt::ullong_t)
320+
BINARY_ARITHMETIC_OPERATORS(unsigned long)
321+
BINARY_ARITHMETIC_OPERATORS(int)
322+
BINARY_ARITHMETIC_OPERATORS(unsigned)
323+
#undef BINARY_ARITHMETIC_OPERATORS
324+
325+
// Binary comparison operators
326+
327+
inline bool operator< (const BigInt &lhs, const BigInt &rhs) { return lhs.compare(rhs) < 0; }
328+
inline bool operator> (const BigInt &lhs, const BigInt &rhs) { return lhs.compare(rhs) > 0; }
329+
inline bool operator<= (const BigInt &lhs, const BigInt &rhs) { return lhs.compare(rhs) <= 0; }
330+
inline bool operator>= (const BigInt &lhs, const BigInt &rhs) { return lhs.compare(rhs) >= 0; }
331+
inline bool operator== (const BigInt &lhs, const BigInt &rhs) { return lhs.compare(rhs) == 0; }
332+
inline bool operator!= (const BigInt &lhs, const BigInt &rhs) { return lhs.compare(rhs) != 0; }
333+
334+
335+
// These operators are all associative, so we can define them all for
336+
// primitives on the LHS and RHS.
337+
#define COMPARISON_OPERATORS(OTHER) \
338+
inline bool operator< (const BigInt &lhs, OTHER rhs) { return lhs.compare(rhs) < 0; } \
339+
inline bool operator> (const BigInt &lhs, OTHER rhs) { return lhs.compare(rhs) > 0; } \
340+
inline bool operator<= (const BigInt &lhs, OTHER rhs) { return lhs.compare(rhs) <= 0; } \
341+
inline bool operator>= (const BigInt &lhs, OTHER rhs) { return lhs.compare(rhs) >= 0; } \
342+
inline bool operator== (const BigInt &lhs, OTHER rhs) { return lhs.compare(rhs) == 0; } \
343+
inline bool operator!= (const BigInt &lhs, OTHER rhs) { return lhs.compare(rhs) != 0; } \
344+
inline bool operator< (OTHER lhs, const BigInt &rhs) { return -rhs.compare(lhs) < 0; } \
345+
inline bool operator> (OTHER lhs, const BigInt &rhs) { return -rhs.compare(lhs) > 0; } \
346+
inline bool operator<= (OTHER lhs, const BigInt &rhs) { return -rhs.compare(lhs) <= 0; } \
347+
inline bool operator>= (OTHER lhs, const BigInt &rhs) { return -rhs.compare(lhs) >= 0; } \
348+
inline bool operator== (OTHER lhs, const BigInt &rhs) { return -rhs.compare(lhs) == 0; } \
349+
inline bool operator!= (OTHER lhs, const BigInt &rhs) { return -rhs.compare(lhs) != 0; }
350+
351+
COMPARISON_OPERATORS(BigInt::llong_t)
352+
COMPARISON_OPERATORS(BigInt::ullong_t)
353+
COMPARISON_OPERATORS(unsigned long)
354+
COMPARISON_OPERATORS(int)
355+
COMPARISON_OPERATORS(unsigned)
356+
#undef COMPARISON_OPERATORS
353357

354358
#endif//ndef BIGINT_HH

0 commit comments

Comments
 (0)