Old snapshot `BigInteger-2004.12.16'; see the ChangeLog file.
[bigint/bigint.git] / BigUnsigned.cpp
CommitLineData
e67d6049
MM
1/*
2* Matt McCutchen's Big Integer Library
3* http://mysite.verizon.net/mccutchen/bigint/
4*/
5
6#include "BigUnsigned.h"
7
8// MANAGEMENT
9
10// This routine is called to ensure the number array is at least a
11// certain size before the result of an operation is written over it.
12void BigUnsigned::allocate(BlkNum c) {
13 // If the requested capacity is more than the current capacity...
14 if (c > cap) {
15 // Delete the old number array
16 delete [] blk;
17 // Allocate the new array
18 cap = c;
19 blk = new Blk[cap];
20 }
21}
22
23// This routine is called to ensure the number array is at least a
24// certain size without losing its contents.
25void BigUnsigned::allocateAndCopy(BlkNum c) {
26 // If the requested capacity is more than the current capacity...
27 if (c > cap) {
28 Blk *oldBlk = blk;
29 // Allocate the new number array
30 cap = c;
31 blk = new Blk[cap];
32 // Copy number blocks
33 BlkNum i;
34 Blk *blkI;
35 const Blk *oldBlkI;
36 for (i = 0, blkI = blk, oldBlkI = oldBlk; i < len; i++, blkI++, oldBlkI++)
37 *blkI = *oldBlkI;
38 // Delete the old array
39 delete [] oldBlk;
40 }
41}
42
43// Copy constructor
44BigUnsigned::BigUnsigned(const BigUnsigned &x) : len(x.len) {
45 // Create number array
46 cap = len;
47 blk = new Blk[cap];
48 // Copy number blocks
49 BlkNum i;
50 Blk *blkI;
51 const Blk *xBlkI;
52 for (i = 0, blkI = blk, xBlkI = x.blk; i < len; i++, blkI++, xBlkI++)
53 *blkI = *xBlkI;
54}
55
56// Assignment operator
57void BigUnsigned::operator=(const BigUnsigned &x) {
58 // Calls like a = a have no effect
59 if (this == &x)
60 return;
61 // Copy length
62 len = x.len;
63 // Expand number array if necessary
64 allocate(len);
65 // Copy number blocks
66 BlkNum i;
67 Blk *blkI;
68 const Blk *xBlkI;
69 for (i = 0, blkI = blk, xBlkI = x.blk; i < len; i++, blkI++, xBlkI++)
70 *blkI = *xBlkI;
71}
72
73// Constructor from an array of blocks
74BigUnsigned::BigUnsigned(const Blk *b, BlkNum l) : cap(l), len(l) {
75 // Create number array
76 blk = new Blk[cap];
77 // Copy number blocks
78 BlkNum i;
79 Blk *blkI;
80 const Blk *bI;
81 for (i = 0, blkI = blk, bI = b; i < len; i++, blkI++, bI++)
82 *blkI = *bI;
83 zapLeadingZeros();
84}
85
86/*
87* The steps for construction of a BigUnsigned
88* from an integral value x are as follows:
89* 1. If x is zero, create an empty BigUnsigned and stop.
90* 2. If x is negative, throw an exception.
91* 3. Allocate a one-block number array.
92* 4. If x is of a signed type, convert x to the unsigned
93* type of the same length.
94* 5. Expand x to a Blk, and store it in the number array.
95*/
96
97BigUnsigned::BigUnsigned(unsigned long x) {
98 if (x == 0) {
99 cap = 0;
100 blk = new Blk[0];
101 len = 0;
102 } else {
103 cap = 1;
104 blk = new Blk[1];
105 len = 1;
106 *blk = Blk(x);
107 }
108}
109
110BigUnsigned::BigUnsigned(long x) {
111 if (x == 0) {
112 cap = 0;
113 blk = new Blk[0];
114 len = 0;
115 } else if (x > 0) {
116 cap = 1;
117 blk = new Blk[1];
118 len = 1;
119 *blk = Blk(x);
120 } else
121 throw "BigUnsigned::BigUnsigned(long): Cannot construct a BigUnsigned from a negative number";
122}
123
124BigUnsigned::BigUnsigned(unsigned int x) {
125 if (x == 0) {
126 cap = 0;
127 blk = new Blk[0];
128 len = 0;
129 } else {
130 cap = 1;
131 blk = new Blk[1];
132 len = 1;
133 *blk = Blk(x);
134 }
135}
136
137BigUnsigned::BigUnsigned(int x) {
138 if (x == 0) {
139 cap = 0;
140 blk = new Blk[0];
141 len = 0;
142 } else if (x > 0) {
143 cap = 1;
144 blk = new Blk[1];
145 len = 1;
146 *blk = Blk(x);
147 } else
148 throw "BigUnsigned::BigUnsigned(int): Cannot construct a BigUnsigned from a negative number";
149}
150
151BigUnsigned::BigUnsigned(unsigned short x) {
152 if (x == 0) {
153 cap = 0;
154 blk = new Blk[0];
155 len = 0;
156 } else {
157 cap = 1;
158 blk = new Blk[1];
159 len = 1;
160 *blk = Blk(x);
161 }
162}
163
164BigUnsigned::BigUnsigned(short x) {
165 if (x == 0) {
166 cap = 0;
167 blk = new Blk[0];
168 len = 0;
169 } else if (x > 0) {
170 cap = 1;
171 blk = new Blk[1];
172 len = 1;
173 *blk = Blk(x);
174 } else
175 throw "BigUnsigned::BigUnsigned(short): Cannot construct a BigUnsigned from a negative number";
176}
177
178// CONVERTERS
179/*
180* The steps for conversion of a BigUnsigned to an
181* integral type are as follows:
182* 1. If the BigUnsigned is zero, return zero.
183* 2. If it is more than one block long or its lowest
184* block has bits set out of the range of the target
185* type, throw an exception.
186* 3. Otherwise, convert the lowest block to the
187* target type and return it.
188*/
189
190namespace {
191 // These masks are used to test whether a Blk has bits
192 // set out of the range of a smaller integral type. Note
193 // that this range is not considered to include the sign bit.
194 const BigUnsigned::Blk lMask = ~0 >> 1;
195 const BigUnsigned::Blk uiMask = (unsigned int)(~0);
196 const BigUnsigned::Blk iMask = uiMask >> 1;
197 const BigUnsigned::Blk usMask = (unsigned short)(~0);
198 const BigUnsigned::Blk sMask = usMask >> 1;
199}
200
201BigUnsigned::operator unsigned long() const {
202 if (len == 0)
203 return 0;
204 else if (len == 1)
205 return (unsigned long) *blk;
206 else
207 throw "BigUnsigned::operator unsigned long: Value is too big for an unsigned long";
208}
209
210BigUnsigned::operator long() const {
211 if (len == 0)
212 return 0;
213 else if (len == 1 && (*blk & lMask) == *blk)
214 return (long) *blk;
215 else
216 throw "BigUnsigned::operator long: Value is too big for a long";
217}
218
219BigUnsigned::operator unsigned int() const {
220 if (len == 0)
221 return 0;
222 else if (len == 1 && (*blk & uiMask) == *blk)
223 return (unsigned int) *blk;
224 else
225 throw "BigUnsigned::operator unsigned int: Value is too big for an unsigned int";
226}
227
228BigUnsigned::operator int() const {
229 if (len == 0)
230 return 0;
231 else if (len == 1 && (*blk & iMask) == *blk)
232 return (int) *blk;
233 else
234 throw "BigUnsigned::operator int: Value is too big for an int";
235}
236
237BigUnsigned::operator unsigned short() const {
238 if (len == 0)
239 return 0;
240 else if (len == 1 && (*blk & usMask) == *blk)
241 return (unsigned short) *blk;
242 else
243 throw "BigUnsigned::operator unsigned short: Value is too big for an unsigned short";
244}
245
246BigUnsigned::operator short() const {
247 if (len == 0)
248 return 0;
249 else if (len == 1 && (*blk & sMask) == *blk)
250 return (short) *blk;
251 else
252 throw "BigUnsigned::operator short: Value is too big for a short";
253}
254
255// COMPARISON
256BigUnsigned::CmpRes BigUnsigned::compareTo(const BigUnsigned &x) const {
257 // A bigger length implies a bigger number.
258 if (len < x.len)
259 return less;
260 else if (len > x.len)
261 return greater;
262 else {
263 // Compare blocks one by one from left to right.
264 BlkNum i = len;
265 const Blk *blkI = blk + len;
266 const Blk *xBlkI = x.blk + len;
267 while (i > 0) {
268 i--;
269 blkI--;
270 xBlkI--;
271 if (*blkI == *xBlkI)
272 continue;
273 else if (*blkI > *xBlkI)
274 return greater;
275 else
276 return less;
277 }
278 // If no blocks differed, the numbers are equal.
279 return equal;
280 }
281}
282
283// PUT-HERE OPERATIONS
284
285// Addition
286void BigUnsigned::add(const BigUnsigned &a, const BigUnsigned &b) {
287 // Block unsafe calls
288 if (this == &a || this == &b)
289 throw "BigUnsigned::add: One of the arguments is the invoked object";
290 // If one argument is zero, copy the other.
291 if (a.len == 0) {
292 operator =(b);
293 return;
294 } else if (b.len == 0) {
295 operator =(a);
296 return;
297 }
298 // Carries in and out of an addition stage
299 bool carryIn, carryOut;
300 Blk temp;
301 BlkNum i;
302 // a2 points to the longer input, b2 points to the shorter
303 const BigUnsigned *a2, *b2;
304 if (a.len >= b.len) {
305 a2 = &a;
306 b2 = &b;
307 } else {
308 a2 = &b;
309 b2 = &a;
310 }
311 // These point directly to the position of interest in the
312 // corresponding block arrays, for faster access.
313 Blk *blkI;
314 const Blk *a2BlkI, *b2BlkI;
315 // Set prelimiary length and make room in this BigUnsigned
316 len = a2->len + 1;
317 allocate(len);
318 // For each block index that is present in both inputs...
319 for (i = 0, blkI = blk, a2BlkI = a2->blk, b2BlkI = b2->blk,
320 carryIn = false; i < b2->len; i++, blkI++, a2BlkI++, b2BlkI++) {
321 // Add input blocks
322 temp = *a2BlkI + *b2BlkI;
323 // If a rollover occurred, the result is less than either input.
324 // This test is used many times in the BigUnsigned code.
325 carryOut = (temp < *a2BlkI);
326 // If a carry was input, handle it
327 if (carryIn) {
328 temp++;
329 carryOut |= (temp == 0);
330 }
331 *blkI = temp; // Save the addition result
332 carryIn = carryOut; // Pass the carry along
333 }
334 // If there is a carry left over, increase blocks until
335 // one does not roll over.
336 for (; i < a2->len && carryIn; i++, blkI++, a2BlkI++) {
337 temp = *a2BlkI + 1;
338 carryIn = (temp == 0);
339 *blkI = temp;
340 }
341 // If the carry was resolved but the larger number
342 // still has blocks, copy them over.
343 for (; i < a2->len; i++, blkI++, a2BlkI++)
344 *blkI = *a2BlkI;
345 // Set the extra block if there's still a carry, decrease length otherwise
346 if (carryIn)
347 *blkI = 1;
348 else
349 len--;
350}
351
352// Subtraction
353void BigUnsigned::subtract(const BigUnsigned &a, const BigUnsigned &b) {
354 // Block unsafe calls
355 if (this == &a || this == &b)
356 throw "BigUnsigned::subtract: One of the arguments is the invoked object";
357 // If b is zero, copy a. If a is shorter than b, the result is negative.
358 if (b.len == 0) {
359 operator =(a);
360 return;
361 } else if (a.len < b.len)
362 throw "BigUnsigned::subtract: Negative result in unsigned calculation";
363 bool borrowIn, borrowOut;
364 Blk temp;
365 BlkNum i;
366 // These point directly to the position of interest in the
367 // corresponding block arrays, for faster access.
368 Blk *blkI;
369 const Blk *aBlkI, *bBlkI;
370 // Set preliminary length and make room
371 len = a.len;
372 allocate(len);
373 // For each block index that is present in both inputs...
374 for (i = 0, blkI = blk, aBlkI = a.blk, bBlkI = b.blk,
375 borrowIn = false; i < b.len; i++, blkI++, aBlkI++, bBlkI++) {
376 temp = *aBlkI - *bBlkI;
377 // If a reverse rollover occurred, the result is greater than the block from a.
378 borrowOut = (temp > *aBlkI);
379 // Handle an incoming borrow
380 if (borrowIn) {
381 borrowOut |= (temp == 0);
382 temp--;
383 }
384 *blkI = temp; // Save the subtraction result
385 borrowIn = borrowOut; // Pass the borrow along
386 }
387 // If there is a borrow left over, decrease blocks until
388 // one does not reverse rollover.
389 for (; i < a.len && borrowIn; i++, blkI++, aBlkI++) {
390 borrowIn = (*aBlkI == 0);
391 *blkI = *aBlkI - 1;
392 }
393 // If there's still a borrow, the result is negative.
394 // Throw an exception, but zero out this object first.
395 if (borrowIn) {
396 len = 0;
397 throw "BigUnsigned::subtract: Negative result in unsigned calculation";
398 } else // Copy over the rest of the blocks
399 for (; i < a.len; i++, blkI++, aBlkI++)
400 *blkI = *aBlkI;
401 // Zap leading zeros
402 zapLeadingZeros();
403}
404
405// Multiplication
406void BigUnsigned::multiply(const BigUnsigned &a, const BigUnsigned &b) {
407 // Block unsafe calls
408 if (this == &a || this == &b)
409 throw "BigUnsigned::multiply: One of the arguments is the invoked object";
410 // If either a or b is zero, set to zero.
411 if (a.len == 0 || b.len == 0) {
412 len = 0;
413 return;
414 }
415 // Overall method: this = 0, then for each 1-bit of a, add b
416 // to this shifted the appropriate amount.
417 // Variables for the calculation
418 BlkNum i, j;
419 unsigned int i2;
420 Blk aBlk, bHigh, temp;
421 bool carryIn, carryOut;
422 // These point directly to the positions of interest in the
423 // corresponding block arrays, for faster access.
424 Blk *blkI, *blkK;
425 const Blk *aBlkI, *bBlkJ;
426 // Set preliminary length and make room
427 len = a.len + b.len;
428 allocate(len);
429 // Zero out this object
430 for (i = 0, blkI = blk; i < len; i++, blkI++)
431 *blkI = 0;
432 // For each block of the first number...
433 for (i = 0, blkI = blk, aBlkI = a.blk; i < a.len; i++, blkI++, aBlkI++)
434 // For each 1-bit of that block...
435 for (i2 = 0, aBlk = *aBlkI; aBlk != 0; i2++, aBlk >>= 1) {
436 if ((aBlk & 1) == 0)
437 continue;
438 /* Add b to this, shifted left i blocks and i2 bits.
439 * j is the index in b, and k = i + j is the index in this.
440 * The low bits of b.blk[j] are shifted and added to blk[k].
441 * bHigh is used to carry the high bits to the next addition. */
442 carryIn = false;
443 bHigh = 0;
444 for (j = 0, bBlkJ = b.blk, blkK = blkI; j < b.len; j++, bBlkJ++, blkK++) {
445 temp = *blkK + ((*bBlkJ << i2) | bHigh);
446 carryOut = (temp < *blkK);
447 if (carryIn) {
448 temp++;
449 carryOut |= (temp == 0);
450 }
451 *blkK = temp;
452 carryIn = carryOut;
453 bHigh = (i2 == 0) ? 0 : *bBlkJ >> (8 * sizeof(Blk) - i2);
454 }
455 temp = *blkK + bHigh;
456 carryOut = (temp < *blkK);
457 if (carryIn) {
458 temp++;
459 carryOut |= (temp == 0);
460 }
461 *blkK = temp;
462 carryIn = carryOut;
463 for (; carryIn; blkK++) {
464 (*blkK)++;
465 carryIn = (*blkK == 0);
466 }
467 }
468 // Zap leading zero
469 if (blk[len - 1] == 0)
470 len--;
471}
472
473// Division
474void BigUnsigned::divide(const BigUnsigned &a, const BigUnsigned &b) {
475 // Note: This is integer division. Any fractional part
476 // of the result is truncated.
477 // Block unsafe calls
478 if (this == &a || this == &b)
479 throw "BigUnsigned::divide: One of the arguments is the invoked object";
480 // If b is zero, throw an exception. If a is zero, set to zero.
481 else if (b.len == 0)
482 throw "BigUnsigned::divide: Division by zero";
483 else if (a.len < b.len) {
484 len = 0;
485 return;
486 }
487 /* Overall method: Subtract b, shifted varying amounts to
488 * the left, from a, setting the bit in the quotient
489 * whenever the subtraction succeeds. */
490 // Variables for the calculation
491 BlkNum i, j, k;
492 unsigned int i2;
493 Blk bHigh, temp;
494 bool borrowIn, borrowOut;
495 // work1 is a copy of a that can be modified
496 // after each successful subtraction.
497 Blk *work1 = new Blk[a.len + 1];
498 Blk *work1I = work1;
499 const Blk *aBlkI = a.blk;
500 for (i = 0; i < a.len; i++, work1I++, aBlkI++)
501 *work1I = *aBlkI;
502 *work1I = 0;
503 // work2 holds part of the result of a subtraction
504 Blk *work2 = new Blk[a.len + 1];
505 // These point directly to the positions of interest in the
506 // corresponding block arrays, for faster access.
507 Blk *blkI, *work1K, *work2J;
508 const Blk *bBlkJ;
509 // Set preliminary length and make room
510 len = a.len - b.len + 1;
511 allocate(len);
512 // For each possible left-shift of b in blocks...
513 i = len;
514 blkI = blk + len;
515 work1I = work1 + len;
516 while (i > 0) {
517 i--;
518 blkI--;
519 work1I--;
520 // For each possible left-shift of b in bits...
521 *blkI = 0;
522 i2 = 8 * sizeof(Blk);
523 while (i2 > 0) {
524 i2--;
525 // Subtract b, shifted left i blocks and i2 bits, from work1
526 // and store the answer in work2. See note in BigUnsigned::multiply.
527 bHigh = 0;
528 for (j = 0, bBlkJ = b.blk, work2J = work2, k = i, work1K = work1I,
529 borrowIn = false; j < b.len; j++, bBlkJ++, work2J++, k++, work1K++) {
530 temp = *work1K - ((*bBlkJ << i2) | bHigh);
531 borrowOut = (temp > *work1K);
532 if (borrowIn) {
533 borrowOut |= (temp == 0);
534 temp--;
535 }
536 *work2J = temp;
537 borrowIn = borrowOut;
538 bHigh = (i2 == 0) ? 0 : *bBlkJ >> (8 * sizeof(Blk) - i2);
539 }
540 temp = *work1K - bHigh;
541 borrowOut = (temp > *work1K);
542 if (borrowIn) {
543 borrowOut |= (temp == 0);
544 temp--;
545 }
546 *work2J = temp;
547 borrowIn = borrowOut;
548 j++;
549 work2J++;
550 k++;
551 work1K++;
552 for (; k < a.len + 1 && borrowIn; j++, work2J++, k++, work1K++) {
553 borrowIn = (*work1K == 0);
554 *work2J = *work1K - 1;
555 }
556 /* If the subtraction was performed successfully, set bit i2
557 * in block i of the quotient, and copy the changed portion of
558 * work2 back to work1. Otherwise, reset that bit and move on. */
559 if (!borrowIn) {
560 *blkI |= (1 << i2);
561 while (j > 0) {
562 j--;
563 work2J--;
564 k--;
565 work1K--;
566 *work1K = *work2J;
567 }
568 }
569 }
570 }
571 // Zap leading zero
572 if (blk[len - 1] == 0)
573 len--;
574 // Deallocate temporary arrays.
575 // (Thanks to Brad Spencer for noticing my accidental omission of this!)
576 delete [] work1;
577 delete [] work2;
578}
579
580// Modulo
581void BigUnsigned::modulo(const BigUnsigned &a, const BigUnsigned &b) {
582 /* Note that the mathematical definition of mod is somewhat
583 * different from the way the normal C++ % operator behaves.
584 * This function does it the mathematical way. */
585 // Block unsafe calls
586 if (this == &a || this == &b)
587 throw "BigUnsigned::modulo: One of the arguments is the invoked object";
588 // If b is zero, copy a and return. By the mathematical definition,
589 // x mod 0 = x, though the normal C++ % would throw an exception.
590 else if (b.len == 0) {
591 len = 0;
592 return;
593 // If a is zero, set to zero and return.
594 } else if (a.len < b.len) {
595 operator =(a);
596 return;
597 }
598 /* Overall method: Copy a into this. Then subtract b,
599 * shifted varying amounts to the left, from this.
600 * When no more subtraction is possible, stop; this
601 * will contain the remainder.
602 * This is very similar to the division routine, except
603 * that whether or not a subtraction succeeds is ignored,
604 * and "this" serves the purpose of work1. */
605 // Variables for the calculation
606 BlkNum i, j, k;
607 unsigned int i2;
608 Blk bHigh, temp;
609 bool borrowIn, borrowOut;
610 allocate(a.len + 1);
611 operator =(a);
612 blk[len] = 0;
613 // work2 holds part of the result of a subtraction
614 Blk *work2 = new Blk[a.len + 1];
615 // These point directly to the positions of interest in the
616 // corresponding block arrays, for faster access.
617 Blk *blkI, *blkK, *work2J;
618 const Blk *bBlkJ;
619 // For each possible left-shift of b in blocks...
620 i = len;
621 blkI = blk + len;
622 while (i > 0) {
623 i--;
624 blkI--;
625 // For each possible left-shift of b in bits...
626 i2 = 8 * sizeof(Blk);
627 while (i2 > 0) {
628 i2--;
629 // Subtract b, shifted left i blocks and i2 bits, from work1
630 // and store the answer in work2. See note in BigUnsigned::multiply.
631 bHigh = 0;
632 for (j = 0, bBlkJ = b.blk, work2J = work2, k = i, blkK = blkI,
633 borrowIn = false; j < b.len; j++, bBlkJ++, work2J++, k++, blkK++) {
634 temp = *blkK - ((*bBlkJ << i2) | bHigh);
635 borrowOut = (temp > *blkK);
636 if (borrowIn) {
637 borrowOut |= (temp == 0);
638 temp--;
639 }
640 *work2J = temp;
641 borrowIn = borrowOut;
642 bHigh = (i2 == 0) ? 0 : *bBlkJ >> (8 * sizeof(Blk) - i2);
643 }
644 temp = *blkK - bHigh;
645 borrowOut = (temp > *blkK);
646 if (borrowIn) {
647 borrowOut |= (temp == 0);
648 temp--;
649 }
650 *work2J = temp;
651 borrowIn = borrowOut;
652 j++;
653 work2J++;
654 k++;
655 blkK++;
656 for (; k < a.len + 1 && borrowIn; j++, work2J++, k++, blkK++) {
657 borrowIn = (*blkK == 0);
658 *work2J = *blkK - 1;
659 }
660 // If the subtraction was performed successfully, set bit i2
661 // in block i of the quotient, and copy the changed portion of
662 // work2 back to this.
663 if (!borrowIn)
664 while (j > 0) {
665 j--;
666 work2J--;
667 k--;
668 blkK--;
669 *blkK = *work2J;
670 }
671 }
672 }
673 // Blocks higher than the last block of the modulus are zero.
674 len = b.len;
675 // Zap leading zeros
676 zapLeadingZeros();
677}
678
679// Bitwise and
680void BigUnsigned::bitAnd(const BigUnsigned &a, const BigUnsigned &b) {
681 // Block unsafe calls
682 if (this == &a || this == &b)
683 throw "BigUnsigned::bitAnd: One of the arguments is the invoked object";
684 len = (a.len >= b.len) ? b.len : a.len;
685 allocate(len);
686 BlkNum i;
687 Blk *blkI;
688 const Blk *aBlkI, *bBlkI;
689 for (i = 0, blkI = blk, aBlkI = a.blk, bBlkI = b.blk;
690 i < len; i++, blkI++, aBlkI++, bBlkI++)
691 *blkI = *aBlkI & *bBlkI;
692 zapLeadingZeros();
693}
694
695// Bitwise or
696void BigUnsigned::bitOr(const BigUnsigned &a, const BigUnsigned &b) {
697 // Block unsafe calls
698 if (this == &a || this == &b)
699 throw "BigUnsigned::bitOr: One of the arguments is the invoked object";
700 BlkNum i;
701 Blk *blkI;
702 const BigUnsigned *a2, *b2;
703 if (a.len >= b.len) {
704 a2 = &a;
705 b2 = &b;
706 } else {
707 a2 = &b;
708 b2 = &a;
709 }
710 allocate(a2->len);
711 const Blk *a2BlkI, *b2BlkI;
712 for (i = 0, blkI = blk, a2BlkI = a2->blk, b2BlkI = b2->blk;
713 i < b2->len; i++, blkI++, a2BlkI++, b2BlkI++)
714 *blkI = *a2BlkI | *b2BlkI;
715 for (; i < a2->len; i++, blkI++, a2BlkI++)
716 *blkI = *a2BlkI;
717 len = a2->len;
718}
719
720// Bitwise xor
721void BigUnsigned::bitXor(const BigUnsigned &a, const BigUnsigned &b) {
722 // Block unsafe calls
723 if (this == &a || this == &b)
724 throw "BigUnsigned::bitXor: One of the arguments is the invoked object";
725 BlkNum i;
726 Blk *blkI;
727 const BigUnsigned *a2, *b2;
728 if (a.len >= b.len) {
729 a2 = &a;
730 b2 = &b;
731 } else {
732 a2 = &b;
733 b2 = &a;
734 }
735 allocate(b2->len);
736 const Blk *a2BlkI, *b2BlkI;
737 for (i = 0, blkI = blk, a2BlkI = a2->blk, b2BlkI = b2->blk;
738 i < b2->len; i++, blkI++, a2BlkI++, b2BlkI++)
739 *blkI = *a2BlkI ^ *b2BlkI;
740 for (; i < a2->len; i++, blkI++, a2BlkI++)
741 *blkI = *a2BlkI;
742 len = a2->len;
743 zapLeadingZeros();
744}
745
746// INCREMENT/DECREMENT OPERATORS
747
748// Prefix increment
749void BigUnsigned::operator ++() {
750 BlkNum i;
751 Blk *blkI;
752 bool carry = true;
753 for (i = 0, blkI = blk; i < len && carry; i++) {
754 (*blkI)++;
755 carry = (*blkI == 0);
756 }
757 if (carry) {
758 allocateAndCopy(len + 1);
759 *blkI = 1;
760 }
761}
762
763// Postfix increment: same as prefix
764void BigUnsigned::operator ++(int) {
765 operator ++();
766}
767
768// Prefix decrement
769void BigUnsigned::operator --() {
770 if (len == 0)
771 throw "BigUnsigned::operator --(): Cannot decrement an unsigned zero";
772 BlkNum i;
773 Blk *blkI;
774 bool borrow = true;
775 for (i = 0, blkI = blk; borrow; i++) {
776 borrow = (*blkI == 0);
777 (*blkI)--;
778 }
779 if (blk[len - 1] == 0)
780 len--;
781}
782
783// Postfix decrement: same as prefix
784void BigUnsigned::operator --(int) {
785 operator --();
786}
787