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 }