integerOps.cpp

Go to the documentation of this file.
00001 /* Copyright 1994 - 1996 LongView Technologies L.L.C. $Revision: 1.5 $ */
00002 /* Copyright (c) 2006, Sun Microsystems, Inc.
00003 All rights reserved.
00004 
00005 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the 
00006 following conditions are met:
00007 
00008     * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
00009     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following 
00010           disclaimer in the documentation and/or other materials provided with the distribution.
00011     * Neither the name of Sun Microsystems nor the names of its contributors may be used to endorse or promote products derived 
00012           from this software without specific prior written permission.
00013 
00014 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 
00015 NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
00016 THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
00017 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
00018 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
00019 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
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 // double layout
00035 //
00036 // double fields: [s|exponent|mantissa]
00037 // field lengths: |1|<--11-->|<--52-->|
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 // Treating of unimplemented code
00047 
00048 static void missing_code_for(char* s) {
00049   fatal1("code missing for %s", s);
00050 }
00051 
00052 
00053 // Helper functions
00054 
00055 static inline int exponent(double x) {
00056 // Extracts the un-biased (binary) exponent of x.
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 // Computes the index of the most significant bit + 1
00066 // (length is 0 for x = 0).
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 // Implements d[length] << shift_count (logical bit-wise left shift).
00075   if (shift_count <= 0) return;
00076   // shift_count > 0
00077   if (shift_count % logB == 0) {
00078     // no bit-shifting needed
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     // bit-shifting needed
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 // Implements d[length] >> shift_count (logical bit-wise right shift).
00111   if (shift_count <= 0) return;
00112   // shift_count > 0
00113   if (shift_count % logB == 0) {
00114     // no bit shifting needed
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     // bit-shifting needed
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 // Implementation of Integer
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   // filter out trivial result 0.0
00176   ok = true;
00177   if (is_zero()) return 0.0;
00178   
00179   // get an n-Digit integer d[n] built from the n most significant digits of self
00180   // n needs to be big enough so that we have enough bits for the mantissa (note
00181   // that the mantissa consists of one (implicit) extra bit which is always 1).
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   // shift d[n] to the left so that the most significant bit of d is shifted out
00192   int left_shift_count = logB - ::length_in_bits(d[n-1]) + 1;
00193   shift_left(d, n, left_shift_count);
00194 
00195   // shift d[n] to the right so it builds the mantissa of a double
00196   const int right_shift_count = sign_length + exponent_length;
00197   shift_right(d, n, right_shift_count);
00198 
00199   // add exponent to d
00200   int exponent = exponent_bias + length_in_bits() - 1;
00201   if (exponent > max_exponent) {
00202     // integer too large => doesn't fit into double representation
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   // cast d into double & set sign
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]; // for the time being - FIX THIS
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 // Basic 32/64bit unsigned operations
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   // returns (x + y + c) mod B; sets carry = (x + y + c) div B
00263   Digit c = carry;      // make sure that carry is used below and not &carry
00264   Digit r;
00265   assert(c <= 1, "wrong carry");
00266   __asm {
00267     //push eax          // save eax
00268     mov eax, x          // eax = x
00269     add eax, y          // eax = (x + y    ) mod B,     0 <= carry = (x + y    ) div B <= 1
00270     adc eax, c          // eax = (x + y + c) mod B,     0 <= carry = (x + y + c) div B <= 1
00271     mov r, eax          // eax is result
00272     mov eax, 0          // cannot use xor because that clears carry bit!
00273     adc eax, 0          // eax = carry
00274     mov c, eax          // save carry
00275     //pop eax           // restore eax
00276   }
00277   carry = c;
00278   return r;
00279 }
00280 
00281 
00282 inline Digit IntegerOps::xmy(Digit x, Digit y, Digit& carry) {
00283   // returns (x - y - c) mod B; sets carry = -((x - y - c) div B)
00284   Digit c = carry;      // make sure that carry is used below and not &carry
00285   Digit r;
00286   assert(c <= 1, "wrong carry");
00287   __asm {
00288     //push eax          // save eax
00289     mov eax, x          // eax = x
00290     sub eax, y          // eax = (x - y    ) mod B,     0 <= carry = (x - y    ) div B <= 1
00291     sbb eax, c          // eax = (x - y - c) mod B,     0 <= carry = (x - y - c) div B <= 1
00292     mov r, eax          // eax is result
00293     mov eax, 0          // cannot use xor because that clears carry bit!
00294     adc eax, 0          // eax = carry
00295     mov c, eax          // save carry
00296     //pop eax           // restore eax
00297   }
00298   carry = c;
00299   return r;
00300 }
00301 
00302 
00303 inline Digit IntegerOps::axpy(Digit a, Digit x, Digit y, Digit& carry) {
00304   // returns (a*x + y + c) mod B; sets carry = (a*x + y + c) div B
00305   Digit c = carry;      // make sure that carry is used below and not &carry
00306   Digit r;
00307   __asm {
00308     //push eax          // save eax
00309     //push edx          // save edx
00310     mov eax, a          // eax = a
00311     mul x               // edx:eax = a*x
00312     add eax, y          //
00313     adc edx, 0          // edx:eax = a*x + y
00314     add eax, c          //
00315     adc edx, 0          // edx:eax = a*x + y + c
00316     mov r, eax          // eax is result
00317     mov c, edx          // save carry
00318     //pop edx           // restore edx
00319     //pop eax           // restore eax
00320   }
00321   carry = c;
00322   return r;
00323 }
00324 
00325 
00326 inline Digit IntegerOps::xdy(Digit x, Digit y, Digit& carry) {
00327   // returns (carry*B + x) div y; sets carry = (carry*B + x) mod y
00328   Digit c = carry;      // make sure that carry is used below and not &carry
00329   Digit r;
00330   __asm {
00331     //push eax          // save eax
00332     //push edx          // save edx
00333     mov eax, x          // eax = x
00334     mov edx, c          // edx:eax =  carry*B + x
00335     div y               // edx:eax = (carry*B + x) mod y : (carry*B + x) div y
00336     mov r, eax          // eax is result
00337     mov c, edx          // save carry
00338     //pop edx           // restore edx
00339     //pop eax           // restore eax
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     // p * f^i = x^n
00352     if (i & 1 == 1) {
00353       // i is odd
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     // x^n = c*B + p
00369     p = axpy(x, p, 0, c);
00370     n++;
00371   }
00372   return p == 0 ? n : n-1;
00373 }
00374 
00375 
00376 // Unsigned operations
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   // initialize z
00409   int i  = xl + yl;
00410   while (i > 0) { i--; z[i] = 0; }
00411   // i == 0
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 // scale multiplies an integer representation stored
00430 // in array by factor and returns the last carry.
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 // qr_decomposition divides x by y (unsigned) and returns its decomposition
00441 // into quotient (q) and remainder (r) packed into the array qr with length
00442 // x.length() + 1. The layout of the result qr is as follows:
00443 //
00444 // qr      [<--- quotient (q) ---->|<-- remainder (r) -->]
00445 // index   |xl  xl-1  ...  yl+1  yl|yl-1  yl-2  ...  1  0|
00446 //
00447 // length of quotient : ql = xl - yl + 1 (xl >= yl => ql >= 1)
00448 // length of remainder: rl = yl          (yl >   0 => rl >= 1)
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   // initialize qr
00455   Digit* x = NEW_RESOURCE_ARRAY(Digit, xl+1);
00456   int i = xl;
00457   while (i > 0) { i--; x[i] = x0[i]; }
00458   // decompose
00459   if (yl == 1) {
00460     // single-digit y => use simple division
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     // full division
00469     x[xl] = 0;
00470     Digit* y = y0.digits();
00471     Digit d = (hlfB - 1) / y[yl-1] + 1;
00472 
00473     if (d != 1) {
00474       // scale x (already copied)
00475       x[xl] = scale(x, d, xl);
00476       // make a copy of y
00477       y = NEW_RESOURCE_ARRAY(Digit, yl);
00478       int i = yl;
00479       while (i > 0) { i--; y[i] = y0[i]; }
00480       // scale y
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     // xl < yl
00511     //
00512     // add some more comments here
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     // unsigned x < unsigned y => z = 0
00523     z.set_length(0);
00524   } else {
00525     // xl >= yl
00526     ResourceMark rm;
00527     Digit* qr = qr_decomposition(x, y);
00528     int i  = xl;
00529     while (i >= yl && qr[i] == 0) i--;
00530     // i < yl || qr[i] != 0
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     // unsigned x < unsigned y => z = y
00542     copy(y, z);
00543   } else {
00544     // xl >= yl
00545     ResourceMark rm;
00546     Digit* qr = qr_decomposition(x, y);
00547     int i = yl-1;
00548     while (i >= 0 && qr[i] == 0) i--;
00549     // i < 0 || qr[i] != 0
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 // Implementation of IntegerOps
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   // for now: implement for base 10 only, use simple heuristics
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   // for now: implement for base 10 only, use simple heuristics
00722   if (base == 10) {
00723     return (x.length() + 1) * 10; // add one for sign & zero
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     // no digits in this case
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   // filter out sign
00887   bool negative = false;
00888   if (x < 0.0) { negative = true; x = -x; }
00889   
00890   // filter out trivial cases
00891   if (x < 1.0) { z.set_length(0); return; }
00892 
00893   // get an n-Digit integer d[n] built from x. n needs to be big enough
00894   // so that we don't loose bits after shifting (note that the mantissa
00895   // consists of one (implicit) extra bit which is always 1).
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   // compute length l of integer
00903   int length_in_bits = exponent(x) + 1;
00904   int l = (length_in_bits + logB - 1)/logB;
00905 
00906   // shift sign & exponent out but keep space for implicit 1 bit
00907   const int left_shift_count = sign_length + exponent_length - 1;
00908   shift_left(d, n, left_shift_count);
00909 
00910   // add implicit 1 bit
00911   const Digit mask = Digit(-1) << (logB - 1);
00912   d[n-1] |= mask;
00913 
00914   // shift right to the right
00915   const right_shift_count = logB - length_in_bits%logB;
00916   shift_right(d, n, right_shift_count);
00917   
00918   // copy most significant digits into z & fill with zeros
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   // set length & adjust sign
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   // convert t into s (destructive)
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   // reverse string
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 // testing
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   // test integer conversion
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   // test string conversion
01047 
01048   // test addition
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   // test subtraction
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   // test multiplication
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   // factorial
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   // unfactorial
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   // double
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   // double to Integer
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   // string conversion
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   // end
01120   std->print_cr("IntegerOps::self_test() done");
01121   exit(0);
01122 }
01123 
01124 
01125 void integerOps_init() {
01126   // uncomment line below if testing is desired
01127   // IntegerOps::self_test();
01128 }

Generated on Mon Oct 9 13:37:11 2006 for Strongtalk VM by  doxygen 1.4.7