00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 # include "incls/_precompiled.incl"
00025 # include "incls/_integerOps.cpp.incl"
00026
00027
00028 static const int maxD = 36;
00029 static const int logB = sizeof(Digit)*8;
00030 static const Digit hlfB = 0x80000000;
00031 static const Digit oneB = 0xFFFFFFFF;
00032
00033
00034
00035
00036
00037
00038 const int sign_length = 1;
00039 const int exponent_length = 11;
00040 const int mantissa_length = 52;
00041 const int double_length = 64;
00042 const int exponent_bias = 1023;
00043 const int max_exponent = 2046;
00044
00045
00046
00047
00048 static void missing_code_for(char* s) {
00049 fatal1("code missing for %s", s);
00050 }
00051
00052
00053
00054
00055 static inline int exponent(double x) {
00056
00057 const int n = double_length/logB;
00058 Digit d[n];
00059 *((double*)d) = x;
00060 return int((d[n-1] << sign_length) >> (logB - exponent_length)) - exponent_bias;
00061 }
00062
00063
00064 static int length_in_bits(Digit x) {
00065
00066
00067 int i = 0;
00068 while (x != 0) { x >>= 1; i++; }
00069 return i;
00070 }
00071
00072
00073 static void shift_left(Digit d[], int length, int shift_count) {
00074
00075 if (shift_count <= 0) return;
00076
00077 if (shift_count % logB == 0) {
00078
00079 int i = length - 1;
00080 int k = shift_count / logB;
00081 while (i > k) {
00082 d[i] = d[i-k];
00083 i--;
00084 }
00085 while (i > 0) {
00086 d[i] = 0;
00087 i--;
00088 }
00089 } else {
00090
00091 int i = length - 1;
00092 int k = shift_count / logB;
00093 int h = shift_count % logB;
00094 int l = logB - h;
00095 while (i > k) {
00096 d[i] = (d[i-k] << h) | (d[i-k-1] >> l);
00097 i--;
00098 }
00099 d[i] = d[i-k] << h;
00100 i--;
00101 while (i > 0) {
00102 d[i] = 0;
00103 i--;
00104 }
00105 }
00106 }
00107
00108
00109 static void shift_right(Digit d[], int length, int shift_count) {
00110
00111 if (shift_count <= 0) return;
00112
00113 if (shift_count % logB == 0) {
00114
00115 int i = 0;
00116 int k = shift_count / logB;
00117 while (i < length - k) {
00118 d[i] = d[i+k];
00119 i++;
00120 }
00121 while (i < length) {
00122 d[i] = 0;
00123 i++;
00124 }
00125 } else {
00126
00127 int i = 0;
00128 int k = shift_count / logB;
00129 int l = shift_count % logB;
00130 int h = logB - l;
00131 while (i < length - k - 1) {
00132 d[i] = (d[i+k+1] << h) | (d[i+k] >> l);
00133 i++;
00134 }
00135 d[i] = d[i+k] >> l;
00136 i++;
00137 while (i < length) {
00138 d[i] = 0;
00139 i++;
00140 }
00141 }
00142 }
00143
00144
00145
00146
00147 int Integer::length_in_bits() const {
00148 if (is_zero()) {
00149 return 0;
00150 } else {
00151 int i = length() - 1;
00152 return i*logB + ::length_in_bits(operator[](i));
00153 }
00154 }
00155
00156
00157 int Integer::as_int(bool& ok) const {
00158 ok = true;
00159 switch (_signed_length) {
00160 case -1:
00161 if (-int(_first_digit) < 0) return -int(_first_digit);
00162 break;
00163 case 0:
00164 return 0;
00165 case 1:
00166 if ( int(_first_digit) > 0) return int(_first_digit);
00167 break;
00168 }
00169 ok = false;
00170 return 0;
00171 }
00172
00173
00174 double Integer::as_double(bool& ok) const {
00175
00176 ok = true;
00177 if (is_zero()) return 0.0;
00178
00179
00180
00181
00182 const int n = (mantissa_length + 1)/logB + 2;
00183 Digit d[n];
00184 int l = length();
00185 int i = 1;
00186 while (i <= n) {
00187 d[n-i] = l-i >= 0 ? operator[](l-i) : 0;
00188 i++;
00189 }
00190
00191
00192 int left_shift_count = logB - ::length_in_bits(d[n-1]) + 1;
00193 shift_left(d, n, left_shift_count);
00194
00195
00196 const int right_shift_count = sign_length + exponent_length;
00197 shift_right(d, n, right_shift_count);
00198
00199
00200 int exponent = exponent_bias + length_in_bits() - 1;
00201 if (exponent > max_exponent) {
00202
00203 ok = false;
00204 return 0.0;
00205 }
00206 assert(logB - right_shift_count > 0, "check this code");
00207 d[n-1] = d[n-1] | (Digit(exponent) << (logB - right_shift_count));
00208
00209
00210 double result = *((double*)&d[n - (double_length/logB)]);
00211 if (is_negative()) result = -result;
00212 return result;
00213 }
00214
00215
00216 smiOop Integer::as_smi(bool& ok) const {
00217 ok = true;
00218 switch (_signed_length) {
00219 case -1:
00220 if (_first_digit <= -smi_min) return as_smiOop(-int(_first_digit));
00221 break;
00222 case 0:
00223 return as_smiOop(0);
00224 case 1:
00225 if (_first_digit <= smi_max) return as_smiOop( int(_first_digit));
00226 break;
00227 }
00228 ok = false;
00229 return as_smiOop(0);
00230 }
00231
00232
00233 void Integer::print() {
00234 char s[100000];
00235 IntegerOps::Integer_to_string(*this, 10, s);
00236 int i = 0;
00237 while (s[i] != '\x0') {
00238 std->print("%c", s[i]);
00239 i++;
00240 }
00241 }
00242
00243
00244
00245
00246 inline Digit IntegerOps::as_Digit(char c) {
00247 if ('0' <= c && c <= '9') return Digit(c - '0');
00248 if ('A' <= c && c <= 'Z') return Digit(c - 'A') + 10;
00249 if ('a' <= c && c <= 'z') return Digit(c - 'a') + 10;
00250 fatal("illegal digit");
00251 return 0;
00252 }
00253
00254
00255 inline char IntegerOps::as_char(int i) {
00256 assert(0 <= i && i < maxD, "illegal digit");
00257 return "0123456789abcdefghijklmnopqrstuvwxyz"[i];
00258 }
00259
00260
00261 inline Digit IntegerOps::xpy(Digit x, Digit y, Digit& carry) {
00262
00263 Digit c = carry;
00264 Digit r;
00265 assert(c <= 1, "wrong carry");
00266 __asm {
00267
00268 mov eax, x
00269 add eax, y
00270 adc eax, c
00271 mov r, eax
00272 mov eax, 0
00273 adc eax, 0
00274 mov c, eax
00275
00276 }
00277 carry = c;
00278 return r;
00279 }
00280
00281
00282 inline Digit IntegerOps::xmy(Digit x, Digit y, Digit& carry) {
00283
00284 Digit c = carry;
00285 Digit r;
00286 assert(c <= 1, "wrong carry");
00287 __asm {
00288
00289 mov eax, x
00290 sub eax, y
00291 sbb eax, c
00292 mov r, eax
00293 mov eax, 0
00294 adc eax, 0
00295 mov c, eax
00296
00297 }
00298 carry = c;
00299 return r;
00300 }
00301
00302
00303 inline Digit IntegerOps::axpy(Digit a, Digit x, Digit y, Digit& carry) {
00304
00305 Digit c = carry;
00306 Digit r;
00307 __asm {
00308
00309
00310 mov eax, a
00311 mul x
00312 add eax, y
00313 adc edx, 0
00314 add eax, c
00315 adc edx, 0
00316 mov r, eax
00317 mov c, edx
00318
00319
00320 }
00321 carry = c;
00322 return r;
00323 }
00324
00325
00326 inline Digit IntegerOps::xdy(Digit x, Digit y, Digit& carry) {
00327
00328 Digit c = carry;
00329 Digit r;
00330 __asm {
00331
00332
00333 mov eax, x
00334 mov edx, c
00335 div y
00336 mov r, eax
00337 mov c, edx
00338
00339
00340 }
00341 carry = c;
00342 return r;
00343 }
00344
00345
00346 Digit IntegerOps::power(Digit x, int n) {
00347 Digit f = x;
00348 Digit p = 1;
00349 int i = n;
00350 while (i > 0) {
00351
00352 if (i & 1 == 1) {
00353
00354 p *= f;
00355 }
00356 f *= f;
00357 i >>= 1;
00358 }
00359 return p;
00360 }
00361
00362
00363 Digit IntegerOps::max_power(Digit x) {
00364 Digit n = 1;
00365 Digit p = x;
00366 Digit c = 0;
00367 while (c == 0) {
00368
00369 p = axpy(x, p, 0, c);
00370 n++;
00371 }
00372 return p == 0 ? n : n-1;
00373 }
00374
00375
00376
00377
00378 void IntegerOps::unsigned_add(Integer& x, Integer& y, Integer& z) {
00379 int xl = x.length();
00380 int yl = y.length();
00381 int l = min(xl, yl);
00382 int i = 0;
00383 Digit c = 0;
00384 while (i < l) { z[i] = xpy(x[i], y[i], c); i++; }
00385 while (i < xl) { z[i] = xpy(x[i], 0, c); i++; }
00386 while (i < yl) { z[i] = xpy(0, y[i], c); i++; }
00387 if (c != 0) { z[i] = c; i++; }
00388 z.set_length(i);
00389 }
00390
00391
00392 void IntegerOps::unsigned_sub(Integer& x, Integer& y, Integer& z) {
00393 int xl = x.length();
00394 int yl = y.length();
00395 int i = 0;
00396 Digit c = 0;
00397 while (i < yl) { z[i] = xmy(x[i], y[i], c); i++; }
00398 while (i < xl) { z[i] = xmy(x[i], 0, c); i++; }
00399 if (c != 0) fatal("negative result");
00400 while (i > 0 && z[i-1] == 0) i--;
00401 z.set_length(i);
00402 }
00403
00404
00405 void IntegerOps::unsigned_mul(Integer& x, Integer& y, Integer& z) {
00406 int xl = x.length();
00407 int yl = y.length();
00408
00409 int i = xl + yl;
00410 while (i > 0) { i--; z[i] = 0; }
00411
00412 int k = 0;
00413 while (i < xl) {
00414 Digit d = x[i];
00415 if (d != 0) {
00416 int j = 0;
00417 k = i;
00418 Digit c = 0;
00419 while (j < yl) { z[k] = axpy(d, y[j], z[k], c); j++; k++; }
00420 if (c != 0) { z[k] = c; k++; }
00421 i++;
00422 }
00423 }
00424 z.set_length(k);
00425 }
00426
00427
00428 Digit IntegerOps::scale(Digit* array, Digit factor, int length) {
00429
00430
00431
00432 int i = 0;
00433 Digit c = 0;
00434 while (i < length) { array[i] = axpy(factor, array[i], 0, c); i++; }
00435 return c;
00436 }
00437
00438
00439 Digit* IntegerOps::qr_decomposition(Integer& x0, Integer& y0) {
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450 int xl = x0.length();
00451 int yl = y0.length();
00452 if (xl < yl) fatal("division not needed");
00453 if (yl == 0) fatal("division by zero");
00454
00455 Digit* x = NEW_RESOURCE_ARRAY(Digit, xl+1);
00456 int i = xl;
00457 while (i > 0) { i--; x[i] = x0[i]; }
00458
00459 if (yl == 1) {
00460
00461 int i = xl;
00462 Digit c = 0;
00463 Digit d = y0._first_digit;
00464 while (i > 0) { i--; x[i+1] = xdy(x[i], d, c); }
00465 x[0] = c;
00466 } else if (xl >= yl) {
00467 missing_code_for("division by large integers");
00468
00469 x[xl] = 0;
00470 Digit* y = y0.digits();
00471 Digit d = (hlfB - 1) / y[yl-1] + 1;
00472
00473 if (d != 1) {
00474
00475 x[xl] = scale(x, d, xl);
00476
00477 y = NEW_RESOURCE_ARRAY(Digit, yl);
00478 int i = yl;
00479 while (i > 0) { i--; y[i] = y0[i]; }
00480
00481 Digit c = scale(y, d, yl);
00482 if (c != 0) fatal("qr_decomposition broken");
00483 }
00484
00485 Digit y1 = y[yl-1];
00486 Digit y2 = y[yl-2];
00487 int i = xl;
00488 while (i >= yl) {
00489 Digit q = (x[i] == y1) ? oneB : xdy(x[i-1], y1, x[i]);
00490
00491 while (true) {}
00492
00493 int j = i-yl;
00494 int k = 0;
00495 Digit c = 0;
00496 while (k < yl) { j++; k++; }
00497 if (true) {
00498
00499 } else {
00500 x[i] = q;
00501 }
00502 i--;
00503 }
00504 if (d != 1) {
00505 int i = yl;
00506 Digit c = 0;
00507 while (i > 0) { i--; x[i] = xdy(x[i], d, c); }
00508 }
00509 } else {
00510
00511
00512
00513 }
00514 return x;
00515 }
00516
00517
00518 void IntegerOps::unsigned_quo(Integer& x, Integer& y, Integer& z) {
00519 int xl = x.length();
00520 int yl = y.length();
00521 if (xl < yl) {
00522
00523 z.set_length(0);
00524 } else {
00525
00526 ResourceMark rm;
00527 Digit* qr = qr_decomposition(x, y);
00528 int i = xl;
00529 while (i >= yl && qr[i] == 0) i--;
00530
00531 z.set_length(i-yl+1);
00532 while (i >= yl) { z[i-yl] = qr[i]; i--; }
00533 }
00534 }
00535
00536
00537 void IntegerOps::unsigned_rem(Integer& x, Integer& y, Integer& z) {
00538 int xl = x.length();
00539 int yl = y.length();
00540 if (xl < yl) {
00541
00542 copy(y, z);
00543 } else {
00544
00545 ResourceMark rm;
00546 Digit* qr = qr_decomposition(x, y);
00547 int i = yl-1;
00548 while (i >= 0 && qr[i] == 0) i--;
00549
00550 z.set_length(i+1);
00551 while (i >= 0) { z[i] = qr[i]; i--; }
00552 }
00553 }
00554
00555
00556 int IntegerOps::unsigned_cmp(Integer& x, Integer& y) {
00557 int xl = x.length();
00558 int yl = y.length();
00559 if (xl == yl && xl > 0) {
00560 int i = xl - 1;
00561 while (i > 0 && x[i] == y[i]) i--;
00562 return int(x[i] - y[i]);
00563 } else {
00564 return xl - yl;
00565 }
00566 }
00567
00568
00569 Digit IntegerOps::last_digit(Integer& x, Digit b) {
00570 int xl = x.length();
00571 int i = xl;
00572 Digit c = 0;
00573 while (i > 0) { i--; x[i] = xdy(x[i], b, c); }
00574 if (xl > 0 && x[xl-1] == 0) x.set_length(xl-1);
00575 return c;
00576 }
00577
00578
00579 void IntegerOps::first_digit(Integer& x, Digit b, Digit c) {
00580 int xl = x.length();
00581 int i = 0;
00582 while (i < xl) { x[i] = axpy(b, x[i], 0, c); i++; }
00583 if (c != 0) { x[i] = c; i++; }
00584 x.set_length(i);
00585 }
00586
00587
00588
00589
00590 int IntegerOps::add_result_size_in_bytes(Integer& x, Integer& y) {
00591 int l;
00592 if (x.is_negative() == y.is_negative()) {
00593 l = unsigned_add_result_length(x, y);
00594 } else if (unsigned_cmp(x, y) < 0) {
00595 l = unsigned_sub_result_length(y, x);
00596 } else {
00597 l = unsigned_sub_result_length(x, y);
00598 }
00599 return Integer::length_to_size_in_bytes(l);
00600 }
00601
00602
00603 int IntegerOps::sub_result_size_in_bytes(Integer& x, Integer& y) {
00604 int l;
00605 if (x.is_negative() != y.is_negative()) {
00606 l = unsigned_add_result_length(x, y);
00607 } else if (unsigned_cmp(x, y) < 0) {
00608 l = unsigned_sub_result_length(y, x);
00609 } else {
00610 l = unsigned_sub_result_length(x, y);
00611 }
00612 return Integer::length_to_size_in_bytes(l);
00613 }
00614
00615
00616 int IntegerOps::mul_result_size_in_bytes(Integer& x, Integer& y) {
00617 return Integer::length_to_size_in_bytes(unsigned_mul_result_length(x, y));
00618 }
00619
00620
00621 int IntegerOps::quo_result_size_in_bytes(Integer& x, Integer& y) {
00622 return Integer::length_to_size_in_bytes(unsigned_quo_result_length(x, y));
00623 }
00624
00625
00626 int IntegerOps::rem_result_size_in_bytes(Integer& x, Integer& y) {
00627 return Integer::length_to_size_in_bytes(unsigned_rem_result_length(x, y));
00628 }
00629
00630
00631 int IntegerOps::div_result_size_in_bytes(Integer& x, Integer& y) {
00632 int l;
00633 if (!x.is_negative() && y.is_positive()) {
00634 l = unsigned_quo_result_length(x, y);
00635 } else {
00636 missing_code_for("division with negative numbers");
00637 }
00638 return Integer::length_to_size_in_bytes(l);
00639 }
00640
00641
00642 int IntegerOps::mod_result_size_in_bytes(Integer& x, Integer& y) {
00643 int l;
00644 if (!x.is_negative() && y.is_positive()) {
00645 l = unsigned_rem_result_length(x, y);
00646 } else {
00647 missing_code_for("division with negative numbers");
00648 }
00649 return Integer::length_to_size_in_bytes(l);
00650 }
00651
00652
00653 int IntegerOps::and_result_size_in_bytes(Integer& x, Integer& y) {
00654 int l;
00655 if (x.is_positive() && y.is_positive()) {
00656 l = min(x.length(), y.length());
00657 } else {
00658 missing_code_for("bitwise and with negative numbers");
00659 }
00660 return Integer::length_to_size_in_bytes(l);
00661 }
00662
00663
00664 int IntegerOps::or_result_size_in_bytes (Integer& x, Integer& y) {
00665 int l;
00666 if (x.is_positive() && y.is_positive()) {
00667 l = max(x.length(), y.length());
00668 } else {
00669 missing_code_for("bitwise or with negative numbers");
00670 }
00671 return Integer::length_to_size_in_bytes(l);
00672 }
00673
00674
00675 int IntegerOps::xor_result_size_in_bytes(Integer& x, Integer& y) {
00676 int l;
00677 if (x.is_positive() && y.is_positive()) {
00678 l = max(x.length(), y.length());
00679 } else {
00680 missing_code_for("bitwise xor with negative numbers");
00681 }
00682 return Integer::length_to_size_in_bytes(l);
00683 }
00684
00685
00686 int IntegerOps::ash_result_size_in_bytes(Integer& x, int n) {
00687 missing_code_for("arithmetic shift");
00688 return 0;
00689 }
00690
00691
00692 int IntegerOps::copy_result_size_in_bytes(Integer& x) {
00693 return x.size_in_bytes();
00694 }
00695
00696
00697 int IntegerOps::int_to_Integer_result_size_in_bytes(int i) {
00698 return Integer::length_to_size_in_bytes(i != 0);
00699 }
00700
00701
00702 int IntegerOps::double_to_Integer_result_size_in_bytes(double x) {
00703 if (x < 0.0) x = -x;
00704 return Integer::length_to_size_in_bytes(x < 1.0 ? 0 : (exponent(x) + logB)/logB);
00705 }
00706
00707
00708 int IntegerOps::string_to_Integer_result_size_in_bytes(char* s, int base) {
00709
00710 if (base == 10) {
00711 int i = 0;
00712 while (s[i] != '\x0') i++;
00713 return Integer::length_to_size_in_bytes(i/9 + 1);
00714 }
00715 missing_code_for("string conversion with base not equal to 10");
00716 return -1;
00717 }
00718
00719
00720 int IntegerOps::Integer_to_string_result_size_in_bytes(Integer& x, int base) {
00721
00722 if (base == 10) {
00723 return (x.length() + 1) * 10;
00724 }
00725 missing_code_for("string conversion with base not equal to 10");
00726 return -1;
00727 }
00728
00729
00730 void IntegerOps::add(Integer& x, Integer& y, Integer& z) {
00731 if (x.is_negative() == y.is_negative()) {
00732 unsigned_add(x, y, z);
00733 } else if (unsigned_cmp(x, y) < 0) {
00734 unsigned_sub(y, x, z); neg(z);
00735 } else {
00736 unsigned_sub(x, y, z);
00737 }
00738 if (x.is_negative()) neg(z);
00739 }
00740
00741
00742 void IntegerOps::sub(Integer& x, Integer& y, Integer& z) {
00743 if (x.is_negative() != y.is_negative()) {
00744 unsigned_add(x, y, z);
00745 } else if (unsigned_cmp(x, y) < 0) {
00746 unsigned_sub(y, x, z); neg(z);
00747 } else {
00748 unsigned_sub(x, y, z);
00749 }
00750 if (x.is_negative()) neg(z);
00751 }
00752
00753
00754 void IntegerOps::mul(Integer& x, Integer& y, Integer& z) {
00755 if (x.is_zero() || y.is_zero()) {
00756 z.set_length(0);
00757 } else if (x.length() < y.length()) {
00758 unsigned_mul(x, y, z);
00759 } else {
00760 unsigned_mul(y, x, z);
00761 }
00762 if (x.is_negative() != y.is_negative()) neg(z);
00763 }
00764
00765
00766 void IntegerOps::quo(Integer& x, Integer& y, Integer& z) {
00767 unsigned_quo(x, y, z);
00768 if (x.is_negative() != y.is_negative()) neg(z);
00769 }
00770
00771
00772 void IntegerOps::rem(Integer& x, Integer& y, Integer& z) {
00773 unsigned_rem(x, y, z);
00774 if (x.is_negative()) neg(z);
00775 }
00776
00777
00778 void IntegerOps::div(Integer& x, Integer& y, Integer& z) {
00779 if (!x.is_negative() && y.is_positive()) {
00780 unsigned_quo(x, y, z);
00781 } else {
00782 missing_code_for("division with negative numbers");
00783 }
00784 }
00785
00786
00787 void IntegerOps::mod(Integer& x, Integer& y, Integer& z) {
00788 if (!x.is_negative() && y.is_positive()) {
00789 unsigned_rem(x, y, z);
00790 } else {
00791 missing_code_for("division with negative numbers");
00792 }
00793 }
00794
00795
00796 void IntegerOps::and(Integer& x, Integer& y, Integer& z) {
00797 if (x.is_positive() && y.is_positive()) {
00798 int l = min(x.length(), y.length());
00799 int i = 0;
00800 while (i < l) { z[i] = x[i] & y[i]; i++; }
00801 z.set_length(i);
00802 } else {
00803 missing_code_for("bitwise and with negative numbers");
00804 }
00805 }
00806
00807
00808 void IntegerOps::or(Integer& x, Integer& y, Integer& z) {
00809 if (x.is_positive() && y.is_positive()) {
00810 int xl = x.length();
00811 int yl = y.length();
00812 int l = min(xl, yl);
00813 int i = 0;
00814 while (i < l) { z[i] = x[i] | y[i]; i++; }
00815 while (i < xl) { z[i] = x[i] ; i++; }
00816 while (i < yl) { z[i] = y[i]; i++; }
00817 z.set_length(i);
00818 } else {
00819 missing_code_for("bitwise or with negative numbers");
00820 }
00821 }
00822
00823
00824 void IntegerOps::xor(Integer& x, Integer& y, Integer& z) {
00825 if (x.is_positive() && y.is_positive()) {
00826 int xl = x.length();
00827 int yl = y.length();
00828 int l = min(xl, yl);
00829 int i = 0;
00830 while (i < l) { z[i] = x[i] ^ y[i]; i++; }
00831 while (i < xl) { z[i] = x[i] ; i++; }
00832 while (i < yl) { z[i] = y[i]; i++; }
00833 z.set_length(i);
00834 } else {
00835 missing_code_for("bitwise xor with negative numbers");
00836 }
00837 }
00838
00839
00840 void IntegerOps::ash(Integer& x, int n, Integer& z) {
00841 missing_code_for("arithmetic shift");
00842 }
00843
00844
00845 int IntegerOps::cmp(Integer& x, Integer& y) {
00846 if (x.is_negative() == y.is_negative()) {
00847 return x.is_negative() ? unsigned_cmp(y, x) : unsigned_cmp(x, y);
00848 } else {
00849 return x.signum();
00850 }
00851 }
00852
00853
00854 void IntegerOps::abs(Integer& x) {
00855 if (x.is_negative()) neg(x);
00856 }
00857
00858
00859 void IntegerOps::neg(Integer& x) {
00860 x.set_length(-x._signed_length);
00861 }
00862
00863
00864 void IntegerOps::copy(Integer& x, Integer& z) {
00865 z._signed_length = x._signed_length;
00866 int i = x.length();
00867 while (i > 0) { i--; z[i] = x[i]; }
00868 }
00869
00870
00871 void IntegerOps::int_to_Integer(int i, Integer& z) {
00872 if (i < 0) {
00873 z.set_length(-1);
00874 z._first_digit = Digit(-i);
00875 } else if (i == 0) {
00876 z.set_length( 0);
00877
00878 } else {
00879 z.set_length( 1);
00880 z._first_digit = Digit( i);
00881 }
00882 }
00883
00884
00885 void IntegerOps::double_to_Integer(double x, Integer& z) {
00886
00887 bool negative = false;
00888 if (x < 0.0) { negative = true; x = -x; }
00889
00890
00891 if (x < 1.0) { z.set_length(0); return; }
00892
00893
00894
00895
00896 const int n = (mantissa_length + 1)/logB + 2;
00897 Digit d[n];
00898 int i = 0;
00899 while (i < n) { d[i] = 0; i++; }
00900 *((double*)&d[n - (double_length/logB)]) = x;
00901
00902
00903 int length_in_bits = exponent(x) + 1;
00904 int l = (length_in_bits + logB - 1)/logB;
00905
00906
00907 const int left_shift_count = sign_length + exponent_length - 1;
00908 shift_left(d, n, left_shift_count);
00909
00910
00911 const Digit mask = Digit(-1) << (logB - 1);
00912 d[n-1] |= mask;
00913
00914
00915 const right_shift_count = logB - length_in_bits%logB;
00916 shift_right(d, n, right_shift_count);
00917
00918
00919 i = 1;
00920 while (l-i >= 0 && n-i >= 0) { z[l-i] = d[n-i]; i++; }
00921 while (l-i >= 0 ) { z[l-i] = 0; i++; }
00922
00923
00924 z.set_length(l);
00925 if (negative) neg(z);
00926 }
00927
00928
00929 void IntegerOps::string_to_Integer(char* s, int base, Integer& z) {
00930 int_to_Integer(0, z);
00931 int i = s[0] == '-';
00932 while (s[i] != '\x0') {
00933 first_digit(z, base, as_Digit(s[i]));
00934 i++;
00935 }
00936 if (s[0] == '-') neg(z);
00937 }
00938
00939
00940 void IntegerOps::Integer_to_string(Integer& x, int base, char* s) {
00941 assert(2 <= base && base <= maxD, "illegal base");
00942 Integer t;
00943 assert(x.size_in_bytes() <= 10001*sizeof(Digit), "temporary array too small");
00944 copy(x, t);
00945
00946 int i = 0;
00947 do {
00948 s[i] = as_char(last_digit(t, base));
00949 i++;
00950 } while (t.is_not_zero());
00951 if (x.is_negative()) { s[i] = '-'; i++; }
00952 s[i] = '\x0';
00953
00954 int j = i-1;
00955 i = 0;
00956 while (i < j) {
00957 char c = s[i]; s[i] = s[j]; s[j] = c;
00958 i++; j--;
00959 }
00960 }
00961
00962
00963
00964
00965 static inline void check(bool p, char* s) {
00966 if (!p) fatal(s);
00967 }
00968
00969
00970 static void factorial(int n) {
00971 Integer x, y, z;
00972 IntegerOps::int_to_Integer(1, z);
00973 for (int i = 2; i <= n; i++) {
00974 IntegerOps::int_to_Integer(i, x);
00975 IntegerOps::copy(z, y);
00976 IntegerOps::mul(x, y, z);
00977 assert(z.size_in_bytes() <= sizeof(z), "result too big");
00978 };
00979 std->print("%d! = ", n);
00980 z.print();
00981 std->cr();
00982 }
00983
00984
00985 static void unfactorial(int n) {
00986 Integer x, y, z;
00987 IntegerOps::int_to_Integer(1, z);
00988 for (int i = 2; i <= n; i++) {
00989 IntegerOps::int_to_Integer(i, x);
00990 IntegerOps::copy(z, y);
00991 IntegerOps::mul(x, y, z);
00992 assert(z.size_in_bytes() <= sizeof(z), "result too big");
00993 };
00994
00995 for (int j = 2; j <= n; j++) {
00996 IntegerOps::int_to_Integer(j, y);
00997 IntegerOps::copy(z, x);
00998 IntegerOps::div(x, y, z);
00999 assert(z.size_in_bytes() <= sizeof(z), "result too big");
01000 };
01001
01002 std->print("%dun! = ", n);
01003 z.print();
01004 std->cr();
01005 }
01006
01007
01008 static void convert_to_double(int n) {
01009 Integer z;
01010 IntegerOps::int_to_Integer(n, z);
01011 bool ok;
01012 std->print_cr("%d = %f", n, z.as_double(ok));
01013 }
01014
01015
01016 static void convert_to_integer(double x) {
01017 Integer z;
01018 IntegerOps::double_to_Integer(x, z);
01019 std->print("%f = ", x);
01020 z.print();
01021 std->cr();
01022 }
01023
01024
01025 static void convert_from_string(char* s) {
01026 Integer z;
01027 IntegerOps::string_to_Integer(s, 10, z);
01028 std->print("%s = ", s);
01029 z.print();
01030 std->cr();
01031 }
01032
01033
01034 void IntegerOps::self_test() {
01035 bool ok;
01036 const int n = 10000;
01037 const int l = n*sizeof(int);
01038 Integer x, y, z;
01039 int i, j;
01040
01041 for (i = -10; i <= 10; i++) {
01042 check(int((i == 0 ? 1 : 2)*sizeof(int)) == int_to_Integer_result_size_in_bytes(i), "int_to_Integer_result_size failed");
01043 int_to_Integer(i, z);
01044 check(i == z.as_int(ok), "int_to_Integer/Integer_to_int failed");
01045 }
01046
01047
01048
01049 for (i = -12345; i <= 12345; i += 1234) {
01050 for (j = -12345; j <= 12345; j += 1234) {
01051 int_to_Integer(i, x);
01052 int_to_Integer(j, y);
01053 add(x, y, z);
01054 check(z.as_int(ok) == i + j, "add failed");
01055 }
01056 }
01057
01058
01059 for (i = -12345; i <= 12345; i += 1234) {
01060 for (j = -12345; j <= 12345; j += 1234) {
01061 int_to_Integer(i, x);
01062 int_to_Integer(j, y);
01063 sub(x, y, z);
01064 check(z.as_int(ok) == i - j, "sub failed");
01065 }
01066 }
01067
01068
01069 for (i = -12345; i <= 12345; i += 1234) {
01070 for (j = -12345; j <= 12345; j += 1234) {
01071 int_to_Integer(i, x);
01072 int_to_Integer(j, y);
01073 mul(x, y, z);
01074 check(z.as_int(ok) == i * j, "mul failed");
01075 }
01076 }
01077
01078
01079 i = 0;
01080 while (i <= 10) { factorial(i); i++; }
01081 i = 20;
01082 while (i <= 100) { factorial(i); i += 10; }
01083 factorial(1000);
01084
01085
01086 i = 0;
01087 while (i <= 10) { unfactorial(i); i++; }
01088 i = 20;
01089 while (i <= 100) { unfactorial(i); i += 10; }
01090 unfactorial(1000);
01091
01092
01093 i = -10;
01094 while (i <= 10) { convert_to_double(i); i++; }
01095 i = 20;
01096 while (i <= 100) { convert_to_double(i); i += 10; }
01097
01098
01099 i = -10;
01100 while (i <= 10) { convert_to_integer(i); i++; }
01101 i = 20;
01102 while (i <= 100) { convert_to_integer(i); i += 10; }
01103 convert_to_integer(0.49);
01104 convert_to_integer(123.0e10);
01105 convert_to_integer(1.2e12);
01106 convert_to_integer(314.159265358979323e-2);
01107 convert_to_integer(-1.5);
01108
01109
01110 convert_from_string("0");
01111 convert_from_string("1");
01112 convert_from_string("1234");
01113 convert_from_string("-1");
01114 convert_from_string("-1234");
01115 convert_from_string("1234567890123456789");
01116 convert_from_string("12345674401234567891234567890123456789");
01117 convert_from_string("12345678901255678912345676601234567891234567890123456789");
01118
01119
01120 std->print_cr("IntegerOps::self_test() done");
01121 exit(0);
01122 }
01123
01124
01125 void integerOps_init() {
01126
01127
01128 }