00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include <assert.h>
00039 #include <string>
00040 #include <string.h>
00041 #include <libsherpa/BigNum.hxx>
00042 #include <libsherpa/UExcept.hxx>
00043
00044
00045
00046
00047
00048 const uint64_t UINT32_T_MAX = 4294967295ull;
00049
00055 static void *
00056 rmemset(void *s, int c, size_t n)
00057 {
00058 unsigned char *cp = (unsigned char *) s;
00059 for (size_t i = n; i > 0; i--)
00060 cp[i-1] = c;
00061
00062 return s;
00063 }
00064
00065 static inline uint32_t max(uint32_t a, uint32_t b)
00066 {
00067 return (a > b) ? a : b;
00068 }
00069
00070 static inline uint32_t min(uint32_t a, uint32_t b)
00071 {
00072 return (a < b) ? a : b;
00073 }
00074
00075 namespace sherpa {
00076
00077
00078
00079 struct nvec {
00080 size_t len;
00081 uint32_t *vec;
00082
00083 inline nvec()
00084 {
00085 len = 0;
00086 vec = 0;
00087 }
00088
00089 inline nvec(const sherpa::BigNum& bn)
00090 {
00091 if (bn.nDigits == 1) {
00092 len = 1;
00093 vec = (uint32_t *) &bn.oneDigit;
00094 }
00095 else {
00096 len = bn.nDigits;
00097 vec = (uint32_t *) bn.digits;
00098 }
00099 }
00100
00101 inline nvec(size_t l, uint32_t *v)
00102 {
00103 len = l, vec = v;
00104 }
00105
00106 inline uint64_t getDigit(size_t i) const
00107 {
00108 return (i >= len) ? 0 : vec[i];
00109 }
00110 } ;
00111
00112 static uint32_t u_zero = 0;
00113 static const nvec nv_zero(1, &u_zero);
00114 static uint32_t u_one = 1;
00115 static const nvec nv_one(1, &u_one);
00116
00120 static int
00121 vu_cmp(const nvec n1, const nvec n2)
00122 {
00123
00124 size_t len = max(n1.len, n2.len);
00125
00126 for (size_t i = 0; i < len; i++) {
00127 size_t pos = len - i - 1;
00128
00129 if (n1.getDigit(pos) < n2.getDigit(pos))
00130 return -1;
00131 if (n1.getDigit(pos) > n2.getDigit(pos))
00132 return 1;
00133 }
00134
00135 return 0;
00136 }
00137
00141 static void
00142 vu_rshift_digits(const nvec n1, size_t nShift, nvec n2)
00143 {
00144 if (nShift > n1.len) {
00145 memset(n2.vec, 0, n2.len * sizeof(uint32_t));
00146 return;
00147 }
00148
00149 for (size_t i = 0; i < min(n1.len - nShift, n2.len); i++)
00150 n2.vec[i] = n1.vec[i + nShift];
00151 for (size_t i = n1.len - nShift; i <n2.len; i++)
00152 n2.vec[i] = 0;
00153
00154 return;
00155 }
00156
00160 static void
00161 vu_lshift_digits(const nvec n1, size_t nShift, nvec n2)
00162 {
00163 for (size_t i = 0; i < min(n1.len, n2.len - nShift); i++)
00164 n2.vec[i+nShift] = n1.vec[i];
00165
00166 for (size_t i = 0; i < nShift; i++)
00167 n2.vec[i] = 0;
00168
00169 return;
00170 }
00171
00175 static void
00176 vu_rshift_bits(const nvec n1, size_t nShift, nvec n2)
00177 {
00178 vu_rshift_digits(n1, nShift / 32, n2);
00179 nShift %= 32;
00180
00181 for (size_t i = 0; i < n2.len; i++) {
00182 uint32_t u = n2.getDigit(i) >> nShift;
00183 u |= (n2.getDigit(i+1) << (32 - nShift));
00184
00185 n2.vec[i] = u;
00186 }
00187
00188 return;
00189 }
00190
00194 static void
00195 vu_lshift_bits(const nvec n1, size_t nShift, nvec n2)
00196 {
00197 vu_lshift_digits(n1, nShift / 32, n2);
00198 nShift %= 32;
00199
00200 for (size_t i = 0; i < min(n1.len, n2.len - nShift); i++) {
00201 size_t pos = n2.len - i - 1;
00202
00203 uint32_t u = n2.getDigit(pos) << nShift;
00204 if (pos > 0)
00205 u |= n2.getDigit(pos-1) >> (32 - nShift);
00206 n2.vec[pos] = u;
00207 }
00208
00209 return;
00210 }
00211
00212 static inline unsigned
00213 vu_get_bit(const nvec n1, size_t bit)
00214 {
00215 return (n1.vec[bit/32] & (1u << (bit % 32))) ? 1 : 0;
00216 }
00217
00218 static inline void
00219 vu_set_bit(nvec n1, size_t bit)
00220 {
00221 n1.vec[bit/32] |= (1u << (bit % 32));
00222 }
00223
00224 static inline void
00225 vu_clear_bit(nvec n1, size_t bit)
00226 {
00227 n1.vec[bit/32] &= ~(1u << (bit % 32));
00228 }
00229
00230 static inline void
00231 vu_copy(const nvec n1, nvec n2)
00232 {
00233 vu_lshift_digits(n1, 0, n2);
00234 }
00235
00236 BigNum BigNum::lshift_digits(size_t n) const
00237 {
00238 if ((nDigits == 1) && (oneDigit == 0))
00239 return *this;
00240
00241 if (n == 0)
00242 return *this;
00243
00244 size_t nNewDigits = nDigits + n;
00245 uint32_t *newDigits = (uint32_t *) alloca(nNewDigits * sizeof(uint32_t));
00246 rmemset(newDigits, 0, nNewDigits * sizeof(uint32_t));
00247
00248 for (size_t i = 0; i < nNewDigits; i++)
00249 newDigits[i+n] = getDigit(i);
00250
00251 return BigNum(nNewDigits, newDigits, negative);
00252 }
00253
00254
00262 static void
00263 vu_sub(const nvec n1, const nvec n2, nvec n3)
00264 {
00265 uint64_t borrow = 0llu;
00266
00267 assert(n1.len <= n3.len);
00268
00269 for (size_t i = n1.len; i < n3.len; i++)
00270 n3.vec[i] = 0;
00271
00272 for (size_t i = 0; i < n1.len; i++) {
00273
00274
00275 uint64_t n1digit = n1.getDigit(i);
00276 uint64_t n2digit = n2.getDigit(i) + borrow;
00277
00278 borrow = 0;
00279 if (n1digit < n2digit) {
00280 n1digit += (UINT32_T_MAX + 1);
00281 borrow = 1;
00282 }
00283
00284 assert(i < n3.len);
00285 n3.vec[i] = n1digit - n2digit;
00286 }
00287
00288 assert(borrow == 0);
00289 }
00290
00297 static void
00298 vu_add(const nvec n1, const nvec n2, nvec n3)
00299 {
00300 uint64_t carry = 0;
00301
00302 for (size_t i = 0; i < n3.len; i++) {
00303 carry = n1.getDigit(i) + n2.getDigit(i) + carry;
00304 if (i < n3.len)
00305 n3.vec[i] = carry;
00306 carry >>= 32;
00307 }
00308
00309 assert(carry == 0);
00310 }
00311
00318 static void
00319 vu_mul(const nvec n1, const nvec n2, nvec n3)
00320 {
00321 uint64_t carry = 0llu;
00322
00323 nvec step;
00324 step.len = n1.len + n2.len;
00325 step.vec = (uint32_t *) alloca(step.len * sizeof(uint32_t));
00326 rmemset(step.vec, 0, step.len * sizeof(uint32_t));
00327
00328 nvec result;
00329 result.len = n1.len + n2.len;
00330 result.vec = (uint32_t *) alloca(result.len * sizeof(uint32_t));
00331 rmemset(result.vec, 0, result.len * sizeof(uint32_t));
00332
00333 for (size_t i = 0; i < n1.len; i++) {
00334 memset(step.vec, 0, step.len * sizeof(uint32_t));
00335 carry = 0llu;
00336
00337 for (size_t j = 0; j < step.len; j++) {
00338 carry = n1.getDigit(i) * n2.getDigit(j) + carry;
00339 step.vec[i+j] = carry;
00340 carry >>= 32;
00341 }
00342
00343 vu_add(result, step, result);
00344 }
00345
00346 assert(carry == 0);
00347 vu_copy(result, n3);
00348 }
00349
00351 static void
00352 vu_divqr(const nvec dividend, const nvec divisor,
00353 nvec quotient, nvec remainder)
00354 {
00355 int cmp = vu_cmp(dividend, divisor);
00356 if (cmp < 0) {
00357 vu_copy(nv_zero, quotient);
00358 vu_copy(dividend, remainder);
00359 return;
00360 }
00361 else if (cmp == 0) {
00362 vu_copy(nv_one, quotient);
00363 vu_copy(nv_zero, remainder);
00364 return;
00365 }
00366
00367
00368
00369 nvec q;
00370 q.len = dividend.len;
00371 q.vec = (uint32_t *) alloca(q.len * sizeof(uint32_t));
00372 rmemset(q.vec, 0, q.len * sizeof(uint32_t));
00373
00374
00375 nvec tmp;
00376 tmp.len = q.len + divisor.len;
00377 tmp.vec = (uint32_t *) alloca(tmp.len * sizeof(uint32_t));
00378
00379 size_t bits = q.len * 32;
00380
00381 for (size_t i = 0; i < bits; i++) {
00382 size_t bitndx = bits - i - 1;
00383
00384 vu_set_bit(q, bitndx);
00385
00386 vu_mul(divisor, q, tmp);
00387 if (vu_cmp(tmp, dividend) > 0)
00388 vu_clear_bit(q, bitndx);
00389 }
00390
00391 vu_copy(q, quotient);
00392 vu_mul(divisor, q, tmp);
00393 vu_sub(dividend, tmp, remainder);
00394 }
00395
00396 BigNum::~BigNum()
00397 {
00398 if (nDigits > 1)
00399 delete [] digits;
00400 }
00401
00402 BigNum::BigNum(const BigNum& other)
00403 {
00404 negative = other.negative;
00405 nDigits = other.nDigits;
00406 if (nDigits > 1) {
00407 digits = new uint32_t[nDigits];
00408 for (size_t i = 0; i < nDigits; i++)
00409 digits[i] = other.digits[i];
00410 }
00411 else
00412 oneDigit = other.oneDigit;
00413 }
00414
00415 BigNum& BigNum::operator=(const BigNum& other)
00416 {
00417 if (nDigits > 1)
00418 delete [] digits;
00419
00420 negative = other.negative;
00421 nDigits = other.nDigits;
00422 if (nDigits > 1) {
00423 digits = new uint32_t[nDigits];
00424 for (size_t i = 0; i < nDigits; i++)
00425 digits[i] = other.digits[i];
00426 }
00427 else
00428 oneDigit = other.oneDigit;
00429
00430 return *this;
00431 }
00432
00433 BigNum::BigNum(uint64_t u, bool neg)
00434 {
00435 negative = neg;
00436 if (u > UINT32_T_MAX) {
00437 nDigits = 2;
00438 digits = new uint32_t[nDigits];
00439 digits[0] = u;
00440 digits[1] = (u >> 32);
00441 }
00442 else {
00443 nDigits = 1;
00444 oneDigit = u;
00445 }
00446 }
00447
00448 BigNum::BigNum(uint64_t u)
00449 {
00450 negative = false;
00451 if (u > UINT32_T_MAX) {
00452 nDigits = 2;
00453 digits = new uint32_t[nDigits];
00454 digits[0] = u;
00455 digits[1] = (u >> 32);
00456 }
00457 else {
00458 nDigits = 1;
00459 oneDigit = u;
00460 }
00461 }
00462
00463 BigNum::BigNum(int64_t i)
00464 {
00465 if (i < 0) {
00466 negative = true;
00467 i = -i;
00468 }
00469 else
00470 negative = false;
00471
00472
00473 uint64_t u = i;
00474 if (u > UINT32_T_MAX) {
00475 nDigits = 2;
00476 digits = new uint32_t[nDigits];
00477 digits[0] = u;
00478 digits[1] = (u >> 32);
00479 }
00480 else {
00481 nDigits = 1;
00482 oneDigit = u;
00483 }
00484 }
00485
00486
00487
00488 inline
00489 BigNum::BigNum(size_t _nDigits, uint32_t* _digits, bool _negative)
00490 {
00491 negative = _negative;
00492 nDigits = _nDigits;
00493
00494 while (nDigits > 1 && (_digits[nDigits - 1] == 0))
00495 nDigits--;
00496
00497 if (nDigits == 1) {
00498 oneDigit = _digits[0];
00499
00500 if (oneDigit == 0)
00501 negative = false;
00502 }
00503 else {
00504 digits = new uint32_t[nDigits];
00505 for (size_t i = 0; i < nDigits; i++)
00506 digits[i] = _digits[i];
00507
00508 return;
00509 }
00510 }
00511
00512 BigNum::BigNum(const std::string& s, uint32_t radix)
00513 {
00514
00515
00516
00517
00518 bool is_negative = false;
00519
00520
00521 negative = false;
00522 nDigits = 1;
00523 oneDigit = 0;
00524
00525 size_t i = 0;
00526
00527 if (s[0] == '-') {
00528 is_negative = true;
00529 i++;
00530 }
00531 else if (s[0] == '+') {
00532 i++;
00533 }
00534
00535 if (radix == 0) {
00536 if (s[i] == '0' && ((s[i+1] == 'x') || (s[i+1] == 'X'))) {
00537 radix = 16;
00538 i += 2;
00539 }
00540 else if (s[i] == 0) {
00541 radix = 8;
00542 i += 1;
00543 }
00544 else
00545 radix = 10;
00546 }
00547
00548 for (; i < s.size(); i++) {
00549 char c = s[i];
00550 uint32_t thisDigit = 0;
00551
00552 if (c >= '0' && c <= '9')
00553 thisDigit = c - '0';
00554 else if (c >= 'a' && c <= 'f')
00555 thisDigit = 10 + (c - 'a');
00556 else if (c >= 'A' && c <= 'F')
00557 thisDigit = 10 + (c - 'A');
00558
00559 *this = *this * radix + thisDigit;
00560 }
00561
00562 if (is_negative)
00563 negative = is_negative;
00564 }
00565
00566 BigNum BigNum::operator+(const BigNum& other) const
00567 {
00568
00569 if (negative == other.negative) {
00570 const nvec nvother(other);
00571 const nvec nvthis(*this);
00572
00573 nvec n3;
00574 n3.len = max(nvother.len, nvthis.len) + 1;
00575 n3.vec = (uint32_t *) alloca(n3.len * sizeof(uint32_t));
00576
00577 vu_add(nvthis, nvother, n3);
00578
00579 return BigNum(n3.len, n3.vec, negative);
00580 }
00581
00582 if (negative)
00583 return (other - this->abs());
00584
00585
00586 return (*this - other.abs());
00587 }
00588
00589 BigNum BigNum::operator-(const BigNum& other) const
00590 {
00591 const nvec nvother(other);
00592 const nvec nvthis(*this);
00593
00594
00595 if (negative != other.negative) {
00596 size_t osize = max(nDigits, other.nDigits) + 1;
00597 uint32_t *oDigits = (uint32_t *) alloca(osize * sizeof(uint32_t));
00598
00599 nvec n3(osize, oDigits);
00600 vu_add(nvthis, nvother, n3);
00601
00602 return BigNum(n3.len, n3.vec, negative);
00603 }
00604
00605
00606 nvec n3;
00607 n3.len = max(nvother.len, nvthis.len);
00608 n3.vec = (uint32_t *) alloca(n3.len * sizeof(uint32_t));
00609
00610 if (vu_cmp(nvthis, nvother) > 0) {
00611 vu_sub(nvthis, nvother, n3);
00612 return BigNum(n3.len, n3.vec, negative);
00613 }
00614 else {
00615 vu_sub(nvother, nvthis, n3);
00616 return BigNum(n3.len, n3.vec, !negative);
00617 }
00618
00619 }
00620
00621 BigNum BigNum::operator*(const BigNum& other) const
00622 {
00623 bool result_neg = (negative != other.negative);
00624
00625 const nvec nvother(other);
00626 const nvec nvthis(*this);
00627
00628 nvec n3;
00629 n3.len = nvother.len + nvthis.len;
00630 n3.vec = (uint32_t *) alloca(n3.len * sizeof(uint32_t));
00631
00632
00633 vu_mul(nvother, nvthis, n3);
00634
00635 return BigNum(n3.len, n3.vec, result_neg);
00636 }
00637
00638 BigNum BigNum::operator/(const BigNum& other) const
00639 {
00640 if (other == 0)
00641 THROW(excpt::BadValue, "Divide by zero");
00642
00643 bool result_neg = (negative != other.negative);
00644
00645 const nvec nvthis(*this);
00646 const nvec nvother(other);
00647
00648
00649
00650 nvec r;
00651 r.len = nvthis.len;
00652 r.vec = (uint32_t *) alloca(r.len * sizeof(uint32_t));
00653
00654 nvec q;
00655 q.len = nvthis.len;
00656 q.vec = (uint32_t *) alloca(q.len * sizeof(uint32_t));
00657
00658 vu_divqr(nvthis, nvother, q, r);
00659
00660 return BigNum(q.len, q.vec, result_neg);
00661 }
00662
00663 BigNum BigNum::operator%(const BigNum& other) const
00664 {
00665 const nvec nvthis(*this);
00666 const nvec nvother(other);
00667
00668
00669
00670 nvec r;
00671 r.len = nvthis.len;
00672 r.vec = (uint32_t *) alloca(r.len * sizeof(uint32_t));
00673
00674 nvec q;
00675 q.len = nvthis.len;
00676 q.vec = (uint32_t *) alloca(q.len * sizeof(uint32_t));
00677
00678 vu_divqr(nvthis, nvother, q, r);
00679
00680
00681 return BigNum(r.len, r.vec, negative);
00682 }
00683
00684 int BigNum::cmp(const BigNum& other) const
00685 {
00686 if (negative == other.negative) {
00687 const nvec n1(*this);
00688 const nvec n2(other);
00689 int result= vu_cmp(n1, n2);
00690 return negative ? -result : result;
00691 }
00692 else if (negative)
00693 return -1;
00694 else
00695 return 1;
00696 }
00697
00698 BigNum BigNum::abs() const
00699 {
00700 if (negative) {
00701 BigNum v = *this;
00702 v.negative = false;
00703 return v;
00704 }
00705 else
00706 return *this;
00707 }
00708
00709 BigNum BigNum::neg() const
00710 {
00711 if (nDigits == 0 && oneDigit == 0)
00712 return *this;
00713
00714 BigNum v = *this;
00715 v.negative = !negative;
00716 return v;
00717 }
00718
00719 BigNum BigNum::operator<<(size_t n)
00720 {
00721 nvec nv;
00722 nv.len = nDigits + ((n+31)/32);
00723 nv.vec = (uint32_t *) alloca(nv.len * sizeof(uint32_t));
00724
00725 const nvec me(*this);
00726 vu_lshift_bits(me, n, nv);
00727
00728 return BigNum(nv.len, nv.vec, negative);
00729 }
00730
00731 BigNum BigNum::operator>>(size_t n)
00732 {
00733 nvec nv;
00734 nv.len = nDigits - (n/32);
00735 nv.vec = (uint32_t *) alloca(nv.len * sizeof(uint32_t));
00736
00737 const nvec me(*this);
00738 vu_rshift_bits(me, n, nv);
00739
00740 return BigNum(nv.len, nv.vec, negative);
00741 }
00742
00743 std::string BigNum::asString(uint32_t radix) const
00744 {
00745 static const char *hexdigits = "0123456789ABCDEF";
00746 std::string s;
00747
00748 if (negative)
00749 s.append(1, '-');
00750
00751 if (radix == 16) {
00752 for (size_t i = 0; i < nDigits; i++) {
00753 size_t pos = nDigits - i - 1;
00754 uint32_t u = getDigit(pos);
00755
00756 for (size_t hd = 0; hd < sizeof(u)*2; hd++) {
00757 uint32_t nibble = sizeof(u)*2 - hd - 1;
00758
00759 uint32_t digit = (u >> (nibble * 4)) & 0xFu;
00760
00761 if (digit == 0) {
00762 if (s.size())
00763 s.append(1, hexdigits[digit]);
00764 }
00765 else
00766 s.append(1, hexdigits[digit]);
00767 }
00768 }
00769
00770 return s;
00771 }
00772 else {
00773 BigNum me = *this;
00774
00775 #if 0
00776 BigNum lastPlace(radix);
00777 BigNum place(radix);
00778
00779 while (place < *this) {
00780 lastPlace = place;
00781 place = lastPlace * radix;
00782 }
00783
00784
00785 place = lastPlace;
00786
00787 while (place != BigNum(0)) {
00788 BigNum thisDigit = me / place;
00789
00790 if (thisDigit == 0) {
00791 if (s.size())
00792 s.append(1, hexdigits[thisDigit.oneDigit]);
00793 }
00794 else
00795 s.append(1, hexdigits[thisDigit.oneDigit]);
00796
00797 me = me - (thisDigit * place);
00798 place = place / radix;
00799 }
00800
00801 if (s.size() == 0)
00802 s.append(1, '0');
00803 #else
00804 std::string result;
00805
00806 while (me != 0) {
00807 BigNum thisDigit = me % radix;
00808
00809 result.append(1, hexdigits[thisDigit.getDigit(0)]);
00810
00811 me /= radix;
00812 }
00813
00814 if (result.size() == 0)
00815 result.append(1, '0');
00816
00817 for (size_t i = 0; i < result.size(); i++)
00818 s.append(1, result[result.size() - i - 1]);
00819
00820 #endif
00821 }
00822
00823 return s;
00824 }
00825
00826 void BigNum::toStream(std::ostream& strm, uint32_t radix) const
00827 {
00828 strm << asString(radix);
00829 }
00830
00831 void BigNum::fromStream(std::istream& strm, uint32_t radix)
00832 {
00833 *this = 0;
00834
00835 for(;;) {
00836 char c;
00837 strm >> c;
00838
00839 if ('0' <= c && c <= '9' && radix > (size_t)(c - '0')) {
00840 *this *= radix;
00841 *this += (c - '0');
00842 }
00843 else if (radix == 16 && 'a' <= c && c <= 'f') {
00844 *this *= radix;
00845 *this += (c - 'a' + 10);
00846 }
00847 else if (radix == 16 && 'A' <= c && c <= 'F') {
00848 *this *= radix;
00849 *this += (c - 'A' + 10);
00850 }
00851 else {
00852 strm.putback(c);
00853 return;
00854 }
00855 }
00856 }
00857 }