core/vnl/vnl_bignum.h

Go to the documentation of this file.
00001 // This is core/vnl/vnl_bignum.h
00002 #ifndef vnl_bignum_h_
00003 #define vnl_bignum_h_
00004 //:
00005 // \file
00006 // \brief Infinite precision integers
00007 //
00008 // The vnl_bignum class implements near-infinite precision integers
00009 // and arithmetic by using a dynamic bit vector. A
00010 // vnl_bignum object will grow in size as necessary to hold its
00011 // integer value.  Implicit conversion to the system defined
00012 // types: short, int, long, float, double and long double
00013 // is supported by overloaded operator member functions.
00014 // Addition and subtraction operators are performed by
00015 // simple bitwise addition and subtraction on
00016 // unsigned short boundaries with checks for carry flag propagation.
00017 // The multiplication, division, and remainder operations
00018 // utilize the algorithms from Knuth's Volume 2 of "The
00019 // Art of Computer Programming". However, despite the use of
00020 // these algorithms and inline member functions, arithmetic
00021 // operations on vnl_bignum objects are considerably slower than
00022 // the built-in integer types that use hardware integer arithmetic
00023 // capabilities.
00024 //
00025 // The vnl_bignum class supports the parsing of character string
00026 // representations of all the literal number formats, PLUS the
00027 // strings "Infinity", "+Infinity" and "-Infinity".  The following
00028 // table shows an example of a character string
00029 // representation on the left and a brief description of the
00030 // interpreted meaning on the right:
00031 //
00032 // Character String  Interpreted Meaning
00033 // 1234              1234
00034 // 1234l             1234
00035 // 1234L             1234
00036 // 1234u             1234
00037 // 1234U             1234
00038 // 1234ul            1234
00039 // 1234UL            1234
00040 // 01234             1234 in octal (leading 0)
00041 // 0x1234            1234 in hexadecimal (leading 0x)
00042 // 0X1234            1234 in hexadecimal (leading 0X)
00043 // 123.4             123 (value truncated)
00044 // 1.234e2           123 (exponent expanded/truncated)
00045 // 1.234e-5          0 (truncated value less than 1)
00046 // Infinity          +Inf ("maxval", obeying all conventional arithmetic)
00047 //
00048 // \author
00049 // Copyright (C) 1991 Texas Instruments Incorporated.
00050 //
00051 // Permission is granted to any individual or institution to use, copy, modify,
00052 // and distribute this software, provided that this complete copyright and
00053 // permission notice is maintained, intact, in all copies and supporting
00054 // documentation.
00055 //
00056 // Texas Instruments Incorporated provides this software "as is" without
00057 // express or implied warranty.
00058 //
00059 // \verbatim
00060 // Modifications
00061 //  Peter Vanroose, 24 January 2002: ported to vnl from COOL
00062 //  Peter Vanroose, 7 September 2002: added "Infinity" (incl. all arithmetic)
00063 //  Ian Scott, 23 March 2004: made ++ and -- much more efficient.
00064 //  Peter Vanroose, March 2008: try to fix divide bug: partially succeeded
00065 // \endverbatim
00066 
00067 #include <vcl_iostream.h>
00068 #include <vcl_string.h>
00069 
00070 class vnl_bignum;
00071 
00072 // These are all auxiliary functions:
00073 
00074 int magnitude_cmp(const vnl_bignum&, const vnl_bignum&);
00075 void add(const vnl_bignum&, const vnl_bignum&, vnl_bignum&);
00076 void subtract(const vnl_bignum&, const vnl_bignum&, vnl_bignum&);
00077 void multiply_aux(const vnl_bignum&, unsigned short d, vnl_bignum&, unsigned short i);
00078 unsigned short normalize(const vnl_bignum&, const vnl_bignum&, vnl_bignum&, vnl_bignum&);
00079 void divide_aux(const vnl_bignum&, unsigned short, vnl_bignum&, unsigned short&);
00080 unsigned short estimate_q_hat(const vnl_bignum&, const vnl_bignum&, unsigned short);
00081 unsigned short multiply_subtract(vnl_bignum&, const vnl_bignum&, unsigned short, unsigned short);
00082 void divide(const vnl_bignum&, const vnl_bignum&, vnl_bignum&, vnl_bignum&);
00083 vnl_bignum left_shift(const vnl_bignum& b1, int l);
00084 vnl_bignum right_shift(const vnl_bignum& b1, int l);
00085 void decrement (vnl_bignum& bnum);
00086 void increment (vnl_bignum& bnum);
00087 
00088 //: formatted output
00089 // \relates vnl_bignum
00090 vcl_ostream& operator<<(vcl_ostream& s, vnl_bignum const& r);
00091 
00092 //: simple input
00093 // \relates vnl_bignum
00094 vcl_istream& operator>>(vcl_istream& s, vnl_bignum& r);
00095 
00096 //: Infinite precision integers
00097 //
00098 // The vnl_bignum class implements near-infinite precision integers
00099 // and arithmetic by using a dynamic bit vector. A
00100 // vnl_bignum object will grow in size as necessary to hold its
00101 // integer value.  Implicit conversion to the system defined
00102 // types: short, int, long, float, double and long double
00103 // is supported by overloaded operator member functions.
00104 // Addition and subtraction operators are performed by
00105 // simple bitwise addition and subtraction on
00106 // unsigned short boundaries with checks for carry flag propagation.
00107 // The multiplication, division, and remainder operations
00108 // utilize the algorithms from Knuth's Volume 2 of "The
00109 // Art of Computer Programming". However, despite the use of
00110 // these algorithms and inline member functions, arithmetic
00111 // operations on vnl_bignum objects are considerably slower than
00112 // the built-in integer types that use hardware integer arithmetic
00113 // capabilities.
00114 //
00115 // The vnl_bignum class supports the parsing of character string
00116 // representations of all the literal number formats, PLUS the
00117 // strings "Infinity", "+Infinity" and "-Infinity".  The following
00118 // table shows an example of a character string
00119 // representation on the left and a brief description of the
00120 // interpreted meaning on the right:
00121 //
00122 // Character String  Interpreted Meaning
00123 // 1234              1234
00124 // 1234l             1234
00125 // 1234L             1234
00126 // 1234u             1234
00127 // 1234U             1234
00128 // 1234ul            1234
00129 // 1234UL            1234
00130 // 01234             1234 in octal (leading 0)
00131 // 0x1234            1234 in hexadecimal (leading 0x)
00132 // 0X1234            1234 in hexadecimal (leading 0X)
00133 // 123.4             123 (value truncated)
00134 // 1.234e2           123 (exponent expanded/truncated)
00135 // 1.234e-5          0 (truncated value less than 1)
00136 // Infinity          +Inf ("maxval", obeying all conventional arithmetic)
00137 //
00138 class vnl_bignum
00139 {
00140   unsigned short count; // Number of data elements (never 0 except for "0")
00141   int sign;             // Sign of vnl_bignum (+1 or -1, nothing else!!)
00142   unsigned short* data; // Pointer to data value
00143  public:
00144   vnl_bignum();                        // Void constructor
00145   vnl_bignum(long);                    // Long constructor
00146   vnl_bignum(unsigned long);           // Unsigned Long constructor
00147   vnl_bignum(int);                     // Int constructor
00148   vnl_bignum(unsigned int);            // Unsigned Int constructor
00149   vnl_bignum(float);                   // Float constructor
00150   vnl_bignum(double);                  // Double constructor
00151   vnl_bignum(long double);             // Long Double constructor
00152   vnl_bignum(vnl_bignum const&);       // Copy constructor
00153   vnl_bignum(const char*);             // String constructor
00154   ~vnl_bignum();                       // Destructor
00155 
00156   operator short() const;              // Implicit type conversion
00157   operator int() const;                // Implicit type conversion
00158   operator long() const;               // Implicit type conversion
00159   operator float() const;              // Implicit type conversion
00160   operator double() const;             // Implicit type conversion
00161   operator long double() const;        // Implicit type conversion
00162   inline operator short() { return ((const vnl_bignum*)this)->operator short(); }
00163   inline operator int() { return ((const vnl_bignum*)this)->operator int(); }
00164   inline operator long() { return ((const vnl_bignum*)this)->operator long(); }
00165   inline operator float() { return ((const vnl_bignum*)this)->operator float(); }
00166   inline operator double() { return ((const vnl_bignum*)this)->operator double(); }
00167   inline operator long double() { return ((const vnl_bignum*)this)->operator long double(); }
00168 
00169   vnl_bignum operator-() const;        // Unary minus operator
00170   inline vnl_bignum operator+() const { return *this; } // Unary plus operator
00171 
00172   vnl_bignum& operator=(const vnl_bignum&); // Assignment operator
00173 
00174   vnl_bignum operator<<(int l) const;  // Bit shift
00175   vnl_bignum operator>>(int l) const;  // Bit shift
00176   vnl_bignum operator+(vnl_bignum const& r) const;
00177   inline vnl_bignum& operator+=(vnl_bignum const& r) { return *this = operator+(r); }
00178   inline vnl_bignum& operator-=(vnl_bignum const& r) { return *this = operator+(-r); }
00179   vnl_bignum& operator*=(vnl_bignum const& r);
00180   vnl_bignum& operator/=(vnl_bignum const& r);
00181   vnl_bignum& operator%=(vnl_bignum const& r);
00182   inline vnl_bignum& operator<<=(int l) { return *this = *this << l; }
00183   inline vnl_bignum& operator>>=(int l) { return *this = *this >> l; }
00184 
00185   //: prefix increment (++b)
00186   vnl_bignum& operator++();
00187   //: decrement
00188   vnl_bignum& operator--();
00189   //: postfix increment (b++)
00190   inline vnl_bignum operator++(int) { vnl_bignum b=(*this); operator++(); return b; }
00191   //: decrement
00192   inline vnl_bignum operator--(int) { vnl_bignum b=(*this); operator--(); return b; }
00193 
00194   bool operator==(vnl_bignum const&) const; // equality
00195   bool operator< (vnl_bignum const&) const; // less than
00196   inline bool operator!=(vnl_bignum const& r) const { return !operator==(r); }
00197   inline bool operator> (vnl_bignum const& r) const { return r<(*this); }
00198   inline bool operator<=(vnl_bignum const& r) const { return !operator>(r); }
00199   inline bool operator>=(vnl_bignum const& r) const { return !operator<(r); }
00200   inline bool operator==(long r) const { return operator==(vnl_bignum(r)); }
00201   inline bool operator!=(long r) const { return !operator==(vnl_bignum(r)); }
00202   inline bool operator< (long r) const { return operator<(vnl_bignum(r)); }
00203   inline bool operator> (long r) const { return vnl_bignum(r) < (*this); }
00204   inline bool operator<=(long r) const { return !operator>(vnl_bignum(r)); }
00205   inline bool operator>=(long r) const { return !operator<(vnl_bignum(r)); }
00206   inline bool operator==(int r) const { return operator==(long(r)); }
00207   inline bool operator!=(int r) const { return !operator==(long(r)); }
00208   inline bool operator< (int r) const { return operator<(long(r)); }
00209   inline bool operator> (int r) const { return vnl_bignum(long(r)) < (*this); }
00210   inline bool operator<=(int r) const { return !operator>(long(r)); }
00211   inline bool operator>=(int r) const { return !operator<(long(r)); }
00212   inline bool operator==(double r) const { return r == this->operator double(); }
00213   inline bool operator!=(double r) const { return r != this->operator double(); }
00214   inline bool operator< (double r) const { return r > this->operator double(); }
00215   inline bool operator> (double r) const { return r < this->operator double(); }
00216   inline bool operator<=(double r) const { return r >= this->operator double(); }
00217   inline bool operator>=(double r) const { return r <= this->operator double(); }
00218   inline bool operator==(long double r) const { return r == this->operator long double(); }
00219   inline bool operator!=(long double r) const { return r != this->operator long double(); }
00220   inline bool operator< (long double r) const { return r > this->operator long double(); }
00221   inline bool operator> (long double r) const { return r < this->operator long double(); }
00222   inline bool operator<=(long double r) const { return r >= this->operator long double(); }
00223   inline bool operator>=(long double r) const { return r <= this->operator long double(); }
00224 
00225   inline vnl_bignum abs() const { return operator<(0L) ? operator-() : *this; }
00226 
00227   // "+/-Inf" is represented as: count=1, data[0]=0, sign=+/-1 :
00228   inline bool is_infinity() const { return count==1 && data[0]==0; }
00229   inline bool is_plus_infinity() const { return is_infinity() && sign==1; }
00230   inline bool is_minus_infinity() const { return is_infinity() && sign==-1; }
00231 
00232   void dump(vcl_ostream& = vcl_cout) const;     // Dump contents of vnl_bignum
00233 
00234   friend int magnitude_cmp(const vnl_bignum&, const vnl_bignum&);
00235   friend void add(const vnl_bignum&, const vnl_bignum&, vnl_bignum&);
00236   friend void subtract(const vnl_bignum&, const vnl_bignum&, vnl_bignum&);
00237   friend void increment (vnl_bignum& bnum);
00238   friend void decrement (vnl_bignum& bnum);
00239   friend void multiply_aux(const vnl_bignum&, unsigned short, vnl_bignum&, unsigned short);
00240   friend unsigned short normalize(const vnl_bignum&, const vnl_bignum&, vnl_bignum&, vnl_bignum&);
00241   friend void divide_aux(const vnl_bignum&, unsigned short, vnl_bignum&, unsigned short&);
00242   friend unsigned short estimate_q_hat(const vnl_bignum&, const vnl_bignum&, unsigned short);
00243   friend unsigned short multiply_subtract(vnl_bignum&, const vnl_bignum&, unsigned short, unsigned short);
00244   friend void divide(const vnl_bignum&, const vnl_bignum&, vnl_bignum&, vnl_bignum&);
00245   friend vnl_bignum left_shift(const vnl_bignum& b1, int l);
00246   friend vnl_bignum right_shift(const vnl_bignum& b1, int l);
00247   friend vcl_ostream& operator<< (vcl_ostream&, const vnl_bignum&);
00248   friend vcl_istream& operator>> (vcl_istream&, vnl_bignum&);
00249   friend vcl_string& vnl_bignum_to_string (vcl_string& s, const vnl_bignum& b);
00250   friend vnl_bignum& vnl_bignum_from_string (vnl_bignum& b, const vcl_string& s);
00251 
00252  private:
00253   void xtoBigNum(const char *s);       // convert hex to vnl_bignum
00254   int  dtoBigNum(const char *s);       // convert decimal to vnl_bignum
00255   void otoBigNum(const char *s);       // convert octal to vnl_bignum
00256   void exptoBigNum(const char *s);     // convert exponential to vnl_bignum
00257 
00258   void resize(short);                  // Resize vnl_bignum data
00259   vnl_bignum& trim();                  // Trim vnl_bignum data
00260 };
00261 
00262 
00263 //: Convert the number to a decimal representation in a string.
00264 // \relates vnl_bignum
00265 vcl_string& vnl_bignum_to_string (vcl_string& s, const vnl_bignum& b);
00266 
00267 //: Convert the number from a decimal representation in a string.
00268 // \relates vnl_bignum
00269 vnl_bignum& vnl_bignum_from_string (vnl_bignum& b, const vcl_string& s);
00270 
00271 //: Returns the sum of two bignum numbers.
00272 // \relates vnl_bignum
00273 inline vnl_bignum operator+(vnl_bignum const& r1, long r2) { return r1+vnl_bignum(r2); }
00274 inline vnl_bignum operator+(vnl_bignum const& r1, int r2) { return r1+long(r2); }
00275 inline vnl_bignum operator+(vnl_bignum const& r1, double r2) { return r1+vnl_bignum(r2); }
00276 inline vnl_bignum operator+(vnl_bignum const& r1, long double r2) { return r1+vnl_bignum(r2); }
00277 inline vnl_bignum operator+(long r2, vnl_bignum const& r1) { return r1 + r2; }
00278 inline vnl_bignum operator+(int r2, vnl_bignum const& r1) { return r1 + r2; }
00279 inline vnl_bignum operator+(double r2, vnl_bignum const& r1) { return r1 + r2; }
00280 inline vnl_bignum operator+(long double r2, vnl_bignum const& r1) { return r1 + r2; }
00281 
00282 //: Returns the difference of two bignum numbers.
00283 // \relates vnl_bignum
00284 inline vnl_bignum operator-(vnl_bignum const& r1, vnl_bignum const& r2) { return r1 + (-r2); }
00285 inline vnl_bignum operator-(vnl_bignum const& r1, long r2) { return r1 + (-r2); }
00286 inline vnl_bignum operator-(vnl_bignum const& r1, int r2) { return r1 + (-r2); }
00287 inline vnl_bignum operator-(vnl_bignum const& r1, double r2) { return r1 + (-r2); }
00288 inline vnl_bignum operator-(vnl_bignum const& r1, long double r2) { return r1 + (-r2); }
00289 inline vnl_bignum operator-(long r2, vnl_bignum const& r1) { return -(r1 + (-r2)); }
00290 inline vnl_bignum operator-(int r2, vnl_bignum const& r1) { return -(r1 + (-r2)); }
00291 inline vnl_bignum operator-(double r2, vnl_bignum const& r1) { return -(r1 + (-r2)); }
00292 inline vnl_bignum operator-(long double r2, vnl_bignum const& r1) { return -(r1 + (-r2)); }
00293 
00294 //: Returns the product of two bignum numbers.
00295 // \relates vnl_bignum
00296 inline vnl_bignum operator*(vnl_bignum const& r1, vnl_bignum const& r2)
00297 {
00298   vnl_bignum result(r1); return result *= r2;
00299 }
00300 
00301 inline vnl_bignum operator*(vnl_bignum const& r1, long r2)
00302 {
00303   vnl_bignum result(r1); return result *= vnl_bignum(r2);
00304 }
00305 
00306 inline vnl_bignum operator*(vnl_bignum const& r1, int r2)
00307 {
00308   vnl_bignum result(r1); return result *= (long)r2;
00309 }
00310 
00311 inline vnl_bignum operator*(vnl_bignum const& r1, double r2)
00312 {
00313   vnl_bignum result(r1); return result *= (vnl_bignum)r2;
00314 }
00315 
00316 inline vnl_bignum operator*(vnl_bignum const& r1, long double r2)
00317 {
00318   vnl_bignum result(r1); return result *= (vnl_bignum)r2;
00319 }
00320 
00321 inline vnl_bignum operator*(long r2, vnl_bignum const& r1)
00322 {
00323   vnl_bignum result(r1); return result *= r2;
00324 }
00325 
00326 inline vnl_bignum operator*(int r2, vnl_bignum const& r1)
00327 {
00328   vnl_bignum result(r1); return result *= (long)r2;
00329 }
00330 
00331 inline vnl_bignum operator*(double r2, vnl_bignum const& r1)
00332 {
00333   vnl_bignum result(r1); return result *= (vnl_bignum)r2;
00334 }
00335 
00336 inline vnl_bignum operator*(long double r2, vnl_bignum const& r1)
00337 {
00338   vnl_bignum result(r1); return result *= (vnl_bignum)r2;
00339 }
00340 
00341 //: Returns the division of two bignum numbers.
00342 // \relates vnl_bignum
00343 inline vnl_bignum operator/(vnl_bignum const& r1, vnl_bignum const& r2)
00344 {
00345   vnl_bignum result(r1); return result /= r2;
00346 }
00347 
00348 inline vnl_bignum operator/(vnl_bignum const& r1, long r2)
00349 {
00350   vnl_bignum result(r1); return result /= r2;
00351 }
00352 
00353 inline vnl_bignum operator/(vnl_bignum const& r1, int r2)
00354 {
00355   vnl_bignum result(r1); return result /= (long)r2;
00356 }
00357 
00358 inline vnl_bignum operator/(vnl_bignum const& r1, double r2)
00359 {
00360   vnl_bignum result(r1); return result /= (vnl_bignum)r2;
00361 }
00362 
00363 inline vnl_bignum operator/(vnl_bignum const& r1, long double r2)
00364 {
00365   vnl_bignum result(r1); return result /= (vnl_bignum)r2;
00366 }
00367 
00368 inline vnl_bignum operator/(long r1, vnl_bignum const& r2)
00369 {
00370   vnl_bignum result(r1); return result /= r2;
00371 }
00372 
00373 inline vnl_bignum operator/(int r1, vnl_bignum const& r2)
00374 {
00375   vnl_bignum result((long)r1); return result /= r2;
00376 }
00377 
00378 inline vnl_bignum operator/(double r1, vnl_bignum const& r2)
00379 {
00380   vnl_bignum result(r1); return result /= r2;
00381 }
00382 
00383 inline vnl_bignum operator/(long double r1, vnl_bignum const& r2)
00384 {
00385   vnl_bignum result(r1); return result /= r2;
00386 }
00387 
00388 //: Returns the remainder of r1 divided by r2.
00389 // \relates vnl_bignum
00390 inline vnl_bignum operator%(vnl_bignum const& r1, vnl_bignum const& r2)
00391 {
00392   vnl_bignum result(r1); return result %= r2;
00393 }
00394 
00395 inline vnl_bignum operator%(vnl_bignum const& r1, long r2)
00396 {
00397   vnl_bignum result(r1); return result %= vnl_bignum(r2);
00398 }
00399 
00400 inline vnl_bignum operator%(vnl_bignum const& r1, int r2)
00401 {
00402   vnl_bignum result(r1); return result %= vnl_bignum((long)r2);
00403 }
00404 
00405 inline vnl_bignum operator%(long r1, vnl_bignum const& r2)
00406 {
00407   vnl_bignum result(r1); return result %= r2;
00408 }
00409 
00410 inline vnl_bignum operator%(int r1, vnl_bignum const& r2)
00411 {
00412   vnl_bignum result((long)r1); return result %= r2;
00413 }
00414 
00415 // Miscellaneous operators and functions
00416 
00417 inline bool operator==(long r1, vnl_bignum const& r2) { return r2==r1; }
00418 inline bool operator!=(long r1, vnl_bignum const& r2) { return r2!=r1; }
00419 inline bool operator< (long r1, vnl_bignum const& r2) { return r2> r1; }
00420 inline bool operator> (long r1, vnl_bignum const& r2) { return r2< r1; }
00421 inline bool operator<=(long r1, vnl_bignum const& r2) { return r2>=r1; }
00422 inline bool operator>=(long r1, vnl_bignum const& r2) { return r2<=r1; }
00423 
00424 inline vnl_bignum vnl_math_abs(vnl_bignum const& x) { return x.abs(); }
00425 inline vnl_bignum vnl_math_squared_magnitude(vnl_bignum const& x) { return x*x; }
00426 inline vnl_bignum vnl_math_sqr(vnl_bignum const& x) { return x*x; }
00427 inline bool vnl_math_isnan(vnl_bignum const& ) { return false; }
00428 inline bool vnl_math_isfinite(vnl_bignum const& x) { return ! x.is_infinity(); }
00429 
00430 #endif // vnl_bignum_h_

Generated on Sat Nov 22 05:06:20 2008 for core/vnl by  doxygen 1.5.1