integerOps.hpp

Go to the documentation of this file.
00001 /* Copyright 1994 - 1996 LongView Technologies L.L.C. $Revision: 1.3 $ */
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 
00025 // Integer is the representation for arbitrary long integers. A non-
00026 // zero Integer x is represented by n Digits to a base B such that:
00027 //
00028 // x = x[n-1]*B^(n-1) + x[n-2]*B^(n-2) + ... + x[1]*B + x[0]
00029 //
00030 // with 0 <= x[i] < B for 0 <= i < n and x[n-1] > 0. n is called the
00031 // length of x. x = 0 is represented by the length n = 0 and no digits.
00032 
00033 class IntegerOps;
00034 typedef unsigned int Digit;
00035 
00036 class Integer: ValueObj {
00037  private:
00038   int    _signed_length;
00039   Digit  _first_digit;
00040   Digit  _debug[9999];
00041 
00042   int    length() const                         { return _signed_length < 0 ? -_signed_length : _signed_length; }
00043   void   set_length(int l)                      { _signed_length = l; }
00044   Digit* digits() const                         { return (Digit*)&_first_digit; }
00045   Digit& operator[] (int i) const               { return digits()[i]; }
00046 
00047   static int length_to_size_in_bytes(int l)     { return sizeof(int) + l*sizeof(Digit); }
00048   
00049   int    length_in_bits() const;
00050 
00051  public:
00052   int    signum() const                         { return _signed_length; }      // returns < 0 for x < 0; 0 for x = 0; > 0 for x > 0
00053   bool   is_zero() const                        { return signum() == 0; }
00054   bool   is_not_zero() const                    { return signum() != 0; }
00055   bool   is_positive() const                    { return signum() >  0; }
00056   bool   is_negative() const                    { return signum() <  0; }
00057 
00058   bool   is_odd() const                         { return is_not_zero() && (_first_digit & 1) == 1; }
00059   bool   is_even() const                        { return !is_odd(); }
00060 
00061   bool   is_valid() const                       { return is_zero() || operator[](length() - 1) != 0; }
00062   int    size_in_bytes() const                  { return length_to_size_in_bytes(length()); }
00063 
00064   int    as_int   (bool& ok) const;
00065   double as_double(bool& ok) const;
00066   smiOop as_smi   (bool& ok) const;
00067 
00068   void print();
00069 
00070   friend class IntegerOps;
00071 };
00072 
00073 
00074 // IntegerOps provides arithmethic & logic operations on Integers. Integer arguments are
00075 // usually denoted by x & y, the result Integer is z. The space for the resulting integer
00076 // must have been allocated before performing the operation, the amount of space needed
00077 // can be computed via the corresponding functions.
00078 
00079 class IntegerOps: AllStatic {
00080  private:
00081   static inline Digit as_Digit(char c);
00082   static inline char  as_char(int i);
00083 
00084   static inline Digit xpy (         Digit x, Digit y, Digit& carry);
00085   static inline Digit xmy (         Digit x, Digit y, Digit& carry);
00086   static inline Digit axpy(Digit a, Digit x, Digit y, Digit& carry);
00087   static inline Digit xdy (         Digit x, Digit y, Digit& carry);
00088 
00089   static Digit  power(Digit x, int n);                                  // returns x^n
00090   static Digit  max_power(Digit x);                                     // returns the largest y with x^y <= B
00091   
00092   static int    unsigned_add_result_length(Integer& x, Integer& y)      { return max(x.length(), y.length()) + 1; }
00093   static int    unsigned_sub_result_length(Integer& x, Integer& y)      { return x.length(); }
00094   static int    unsigned_mul_result_length(Integer& x, Integer& y)      { return x.is_zero() || y.is_zero() ? 0 : x.length() + y.length(); }
00095   static int    unsigned_quo_result_length(Integer& x, Integer& y)      { return max(x.length() - y.length() + 1, 0); }
00096   static int    unsigned_rem_result_length(Integer& x, Integer& y)      { return y.length(); }
00097   
00098   static void   unsigned_add(Integer& x, Integer& y, Integer& z);
00099   static void   unsigned_sub(Integer& x, Integer& y, Integer& z);
00100   static void   unsigned_mul(Integer& x, Integer& y, Integer& z);
00101   static void   unsigned_quo(Integer& x, Integer& y, Integer& z);
00102   static void   unsigned_rem(Integer& x, Integer& y, Integer& z);
00103   static int    unsigned_cmp(Integer& x, Integer& y            );
00104 
00105   static Digit   scale(Digit* array, Digit factor, int length);
00106   static Digit*  qr_decomposition(Integer& x, Integer& y);
00107   static Digit   last_digit (Integer& x, Digit b);                      // divides x by b and returns x mod b
00108   static void    first_digit(Integer& x, Digit b, Digit c);             // multiplies x by b and adds c
00109 
00110  public:
00111   // the following functions return the maximum result size
00112   // in bytes for the operation specified in the function name
00113   static int  add_result_size_in_bytes(Integer& x, Integer& y);
00114   static int  sub_result_size_in_bytes(Integer& x, Integer& y);
00115   static int  mul_result_size_in_bytes(Integer& x, Integer& y);
00116   static int  quo_result_size_in_bytes(Integer& x, Integer& y);
00117   static int  rem_result_size_in_bytes(Integer& x, Integer& y);
00118   static int  div_result_size_in_bytes(Integer& x, Integer& y);
00119   static int  mod_result_size_in_bytes(Integer& x, Integer& y);
00120 
00121   static int  and_result_size_in_bytes(Integer& x, Integer& y);
00122   static int  or_result_size_in_bytes (Integer& x, Integer& y);
00123   static int  xor_result_size_in_bytes(Integer& x, Integer& y);
00124   static int  ash_result_size_in_bytes(Integer& x, int      n);
00125 
00126   static int  copy_result_size_in_bytes(Integer& x);
00127   static int  int_to_Integer_result_size_in_bytes(int i);
00128   static int  double_to_Integer_result_size_in_bytes(double x);
00129   static int  string_to_Integer_result_size_in_bytes(char* s, int base);
00130   static int  Integer_to_string_result_size_in_bytes(Integer& x, int base);
00131 
00132   // arithmetic/binary operations & tests
00133   static void add(Integer& x, Integer& y, Integer& z);  // z := x + y
00134   static void sub(Integer& x, Integer& y, Integer& z);  // z := x - y
00135   static void mul(Integer& x, Integer& y, Integer& z);  // z := x * y
00136   static void quo(Integer& x, Integer& y, Integer& z);  // z := x quo y
00137   static void rem(Integer& x, Integer& y, Integer& z);  // z := x rem y
00138   static void div(Integer& x, Integer& y, Integer& z);  // z := x div y
00139   static void mod(Integer& x, Integer& y, Integer& z);  // z := x mod y
00140 
00141   static void and(Integer& x, Integer& y, Integer& z);  // z := x and y, bitwise, assuming 2's complement representation
00142   static void or (Integer& x, Integer& y, Integer& z);  // z := x or  y, bitwise, assuming 2's complement representation
00143   static void xor(Integer& x, Integer& y, Integer& z);  // z := x xor y, bitwise, assuming 2's complement representation
00144   static void ash(Integer& x, int      n, Integer& z);  // z := x * 2^n
00145 
00146   static int  cmp(Integer& x, Integer& y            );  // returns < 0 for x < y; 0 for x = y; > 0 for x > y
00147 
00148   static void abs(Integer& x);                          // x := |x|
00149   static void neg(Integer& x);                          // x := -x
00150 
00151   // copy & conversion operations
00152   static void copy(Integer& x, Integer& z);
00153   static void int_to_Integer(int i, Integer& z);
00154   static void double_to_Integer(double x, Integer& z);
00155   static void string_to_Integer(char* s, int base, Integer& z);
00156   static void Integer_to_string(Integer& x, int base, char* s);
00157 
00158   // testing/debugging
00159   static void self_test();
00160 };

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