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 //  Peter Vanroose, June 2009: finally fixed this long standing divide bug
00066 // \endverbatim
00067 
00068 #include <vcl_iostream.h>
00069 #include <vcl_string.h>
00070 
00071 class vnl_bignum;
00072 
00073 // These are all auxiliary functions:
00074 
00075 int magnitude_cmp(const vnl_bignum&, const vnl_bignum&);
00076 void add(const vnl_bignum&, const vnl_bignum&, vnl_bignum&);
00077 void subtract(const vnl_bignum&, const vnl_bignum&, vnl_bignum&);
00078 void multiply_aux(const vnl_bignum&, unsigned short d, vnl_bignum&, unsigned short i);
00079 unsigned short normalize(const vnl_bignum&, const vnl_bignum&, vnl_bignum&, vnl_bignum&);
00080 void divide_aux(const vnl_bignum&, unsigned short, vnl_bignum&, unsigned short&);
00081 unsigned short estimate_q_hat(const vnl_bignum&, const vnl_bignum&, unsigned short);
00082 unsigned short multiply_subtract(vnl_bignum&, const vnl_bignum&, unsigned short, unsigned short);
00083 void divide(const vnl_bignum&, const vnl_bignum&, vnl_bignum&, vnl_bignum&);
00084 vnl_bignum left_shift(const vnl_bignum& b1, int l);
00085 vnl_bignum right_shift(const vnl_bignum& b1, int l);
00086 void decrement (vnl_bignum& bnum);
00087 void increment (vnl_bignum& bnum);
00088 
00089 //: formatted output
00090 // \relatesalso vnl_bignum
00091 vcl_ostream& operator<<(vcl_ostream& s, vnl_bignum const& r);
00092 
00093 //: simple input
00094 // \relatesalso vnl_bignum
00095 vcl_istream& operator>>(vcl_istream& s, vnl_bignum& r);
00096 
00097 //: Infinite precision integers
00098 //
00099 // The vnl_bignum class implements near-infinite precision integers
00100 // and arithmetic by using a dynamic bit vector. A
00101 // vnl_bignum object will grow in size as necessary to hold its
00102 // integer value.  Implicit conversion to the system defined
00103 // types: short, int, long, float, double and long double
00104 // is supported by overloaded operator member functions.
00105 // Addition and subtraction operators are performed by
00106 // simple bitwise addition and subtraction on
00107 // unsigned short boundaries with checks for carry flag propagation.
00108 // The multiplication, division, and remainder operations
00109 // utilize the algorithms from Knuth's Volume 2 of "The
00110 // Art of Computer Programming". However, despite the use of
00111 // these algorithms and inline member functions, arithmetic
00112 // operations on vnl_bignum objects are considerably slower than
00113 // the built-in integer types that use hardware integer arithmetic
00114 // capabilities.
00115 //
00116 // The vnl_bignum class supports the parsing of character string
00117 // representations of all the literal number formats, PLUS the
00118 // strings "Infinity", "+Infinity" and "-Infinity".  The following
00119 // table shows an example of a character string
00120 // representation on the left and a brief description of the
00121 // interpreted meaning on the right:
00122 //
00123 // Character String  Interpreted Meaning
00124 // 1234              1234
00125 // 1234l             1234
00126 // 1234L             1234
00127 // 1234u             1234
00128 // 1234U             1234
00129 // 1234ul            1234
00130 // 1234UL            1234
00131 // 01234             1234 in octal (leading 0)
00132 // 0x1234            1234 in hexadecimal (leading 0x)
00133 // 0X1234            1234 in hexadecimal (leading 0X)
00134 // 123.4             123 (value truncated)
00135 // 1.234e2           123 (exponent expanded/truncated)
00136 // 1.234e-5          0 (truncated value less than 1)
00137 // Infinity          +Inf ("maxval", obeying all conventional arithmetic)
00138 //
00139 class vnl_bignum
00140 {
00141   unsigned short count; // Number of data elements (never 0 except for "0")
00142   int sign;             // Sign of vnl_bignum (+1 or -1, nothing else!!)
00143   unsigned short* data; // Pointer to data value
00144  public:
00145   vnl_bignum();                        // Void constructor
00146   vnl_bignum(long);                    // Long constructor
00147   vnl_bignum(unsigned long);           // Unsigned Long constructor
00148   vnl_bignum(int);                     // Int constructor
00149   vnl_bignum(unsigned int);            // Unsigned Int constructor
00150   vnl_bignum(float);                   // Float constructor
00151   vnl_bignum(double);                  // Double constructor
00152   vnl_bignum(long double);             // Long Double constructor
00153   vnl_bignum(vnl_bignum const&);       // Copy constructor
00154   vnl_bignum(const char*);             // String constructor
00155   ~vnl_bignum();                       // Destructor
00156 
00157   operator short() const;              // Implicit type conversion
00158   operator int() const;                // Implicit type conversion
00159   operator long() const;               // Implicit type conversion
00160   operator float() const;              // Implicit type conversion
00161   operator double() const;             // Implicit type conversion
00162   operator long double() const;        // Implicit type conversion
00163   inline operator short() { return ((const vnl_bignum*)this)->operator short(); }
00164   inline operator int() { return ((const vnl_bignum*)this)->operator int(); }
00165   inline operator long() { return ((const vnl_bignum*)this)->operator long(); }
00166   inline operator float() { return ((const vnl_bignum*)this)->operator float(); }
00167   inline operator double() { return ((const vnl_bignum*)this)->operator double(); }
00168   inline operator long double() { return ((const vnl_bignum*)this)->operator long double(); }
00169 
00170   vnl_bignum operator-() const;        // Unary minus operator
00171   inline vnl_bignum operator+() const { return *this; } // Unary plus operator
00172 
00173   vnl_bignum& operator=(const vnl_bignum&); // Assignment operator
00174 
00175   vnl_bignum operator<<(int l) const;  // Bit shift
00176   vnl_bignum operator>>(int l) const;  // Bit shift
00177   vnl_bignum operator+(vnl_bignum const& r) const;
00178   inline vnl_bignum& operator+=(vnl_bignum const& r) { return *this = operator+(r); }
00179   inline vnl_bignum& operator-=(vnl_bignum const& r) { return *this = operator+(-r); }
00180   vnl_bignum& operator*=(vnl_bignum const& r);
00181   vnl_bignum& operator/=(vnl_bignum const& r);
00182   vnl_bignum& operator%=(vnl_bignum const& r);
00183   inline vnl_bignum& operator<<=(int l) { return *this = *this << l; }
00184   inline vnl_bignum& operator>>=(int l) { return *this = *this >> l; }
00185 
00186   //: prefix increment (++b)
00187   vnl_bignum& operator++();
00188   //: decrement
00189   vnl_bignum& operator--();
00190   //: postfix increment (b++)
00191   inline vnl_bignum operator++(int) { vnl_bignum b=(*this); operator++(); return b; }
00192   //: decrement
00193   inline vnl_bignum operator--(int) { vnl_bignum b=(*this); operator--(); return b; }
00194 
00195   bool operator==(vnl_bignum const&) const; // equality
00196   bool operator< (vnl_bignum const&) const; // less than
00197   inline bool operator!=(vnl_bignum const& r) const { return !operator==(r); }
00198   inline bool operator> (vnl_bignum const& r) const { return r<(*this); }
00199   inline bool operator<=(vnl_bignum const& r) const { return !operator>(r); }
00200   inline bool operator>=(vnl_bignum const& r) const { return !operator<(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 operator<(vnl_bignum(r)); }
00204   inline bool operator> (long r) const { return vnl_bignum(r) < (*this); }
00205   inline bool operator<=(long r) const { return !operator>(vnl_bignum(r)); }
00206   inline bool operator>=(long r) const { return !operator<(vnl_bignum(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 operator<(long(r)); }
00210   inline bool operator> (int r) const { return vnl_bignum(long(r)) < (*this); }
00211   inline bool operator<=(int r) const { return !operator>(long(r)); }
00212   inline bool operator>=(int r) const { return !operator<(long(r)); }
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>=(double r) const { return r <= this->operator 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   inline bool operator>=(long double r) const { return r <= this->operator long double(); }
00225 
00226   inline vnl_bignum abs() const { return operator<(0L) ? operator-() : *this; }
00227 
00228   // "+/-Inf" is represented as: count=1, data[0]=0, sign=+/-1 :
00229   inline bool is_infinity() const { return count==1 && data[0]==0; }
00230   inline bool is_plus_infinity() const { return is_infinity() && sign==1; }
00231   inline bool is_minus_infinity() const { return is_infinity() && sign==-1; }
00232 
00233   void dump(vcl_ostream& = vcl_cout) const;     // Dump contents of vnl_bignum
00234 
00235   friend int magnitude_cmp(const vnl_bignum&, const vnl_bignum&);
00236   friend void add(const vnl_bignum&, const vnl_bignum&, vnl_bignum&);
00237   friend void subtract(const vnl_bignum&, const vnl_bignum&, vnl_bignum&);
00238   friend void increment (vnl_bignum& bnum);
00239   friend void decrement (vnl_bignum& bnum);
00240   friend void multiply_aux(const vnl_bignum&, unsigned short, vnl_bignum&, unsigned short);
00241   friend unsigned short normalize(const vnl_bignum&, const vnl_bignum&, vnl_bignum&, vnl_bignum&);
00242   friend void divide_aux(const vnl_bignum&, unsigned short, vnl_bignum&, unsigned short&);
00243   friend unsigned short estimate_q_hat(const vnl_bignum&, const vnl_bignum&, unsigned short);
00244   friend unsigned short multiply_subtract(vnl_bignum&, const vnl_bignum&, unsigned short, unsigned short);
00245   friend void divide(const vnl_bignum&, const vnl_bignum&, vnl_bignum&, vnl_bignum&);
00246   friend vnl_bignum left_shift(const vnl_bignum& b1, int l);
00247   friend vnl_bignum right_shift(const vnl_bignum& b1, int l);
00248   friend vcl_ostream& operator<< (vcl_ostream&, const vnl_bignum&);
00249   friend vcl_istream& operator>> (vcl_istream&, vnl_bignum&);
00250   friend vcl_string& vnl_bignum_to_string (vcl_string& s, const vnl_bignum& b);
00251   friend vnl_bignum& vnl_bignum_from_string (vnl_bignum& b, const vcl_string& s);
00252 
00253  private:
00254   void xtoBigNum(const char *s);       // convert hex to vnl_bignum
00255   int  dtoBigNum(const char *s);       // convert decimal to vnl_bignum
00256   void otoBigNum(const char *s);       // convert octal to vnl_bignum
00257   void exptoBigNum(const char *s);     // convert exponential to vnl_bignum
00258 
00259   void resize(short);                  // Resize vnl_bignum data
00260   vnl_bignum& trim();                  // Trim vnl_bignum data
00261 };
00262 
00263 
00264 //: Convert the number to a decimal representation in a string.
00265 // \relatesalso vnl_bignum
00266 vcl_string& vnl_bignum_to_string (vcl_string& s, const vnl_bignum& b);
00267 
00268 //: Convert the number from a decimal representation in a string.
00269 // \relatesalso vnl_bignum
00270 vnl_bignum& vnl_bignum_from_string (vnl_bignum& b, const vcl_string& s);
00271 
00272 //: Returns the sum of two bignum numbers.
00273 // \relatesalso vnl_bignum
00274 inline vnl_bignum operator+(vnl_bignum const& r1, long r2) { return r1+vnl_bignum(r2); }
00275 inline vnl_bignum operator+(vnl_bignum const& r1, int r2) { return r1+long(r2); }
00276 inline vnl_bignum operator+(vnl_bignum const& r1, double r2) { return r1+vnl_bignum(r2); }
00277 inline vnl_bignum operator+(vnl_bignum const& r1, long double r2) { return r1+vnl_bignum(r2); }
00278 inline vnl_bignum operator+(long r2, vnl_bignum const& r1) { return r1 + r2; }
00279 inline vnl_bignum operator+(int r2, vnl_bignum const& r1) { return r1 + r2; }
00280 inline vnl_bignum operator+(double r2, vnl_bignum const& r1) { return r1 + r2; }
00281 inline vnl_bignum operator+(long double r2, vnl_bignum const& r1) { return r1 + r2; }
00282 
00283 //: Returns the difference of two bignum numbers.
00284 // \relatesalso vnl_bignum
00285 inline vnl_bignum operator-(vnl_bignum const& r1, vnl_bignum const& r2) { return r1 + (-r2); }
00286 inline vnl_bignum operator-(vnl_bignum const& r1, long r2) { return r1 + (-r2); }
00287 inline vnl_bignum operator-(vnl_bignum const& r1, int r2) { return r1 + (-r2); }
00288 inline vnl_bignum operator-(vnl_bignum const& r1, double r2) { return r1 + (-r2); }
00289 inline vnl_bignum operator-(vnl_bignum const& r1, long double r2) { return r1 + (-r2); }
00290 inline vnl_bignum operator-(long r2, vnl_bignum const& r1) { return -(r1 + (-r2)); }
00291 inline vnl_bignum operator-(int r2, vnl_bignum const& r1) { return -(r1 + (-r2)); }
00292 inline vnl_bignum operator-(double r2, vnl_bignum const& r1) { return -(r1 + (-r2)); }
00293 inline vnl_bignum operator-(long double r2, vnl_bignum const& r1) { return -(r1 + (-r2)); }
00294 
00295 //: Returns the product of two bignum numbers.
00296 // \relatesalso vnl_bignum
00297 inline vnl_bignum operator*(vnl_bignum const& r1, vnl_bignum const& r2)
00298 {
00299   vnl_bignum result(r1); return result *= r2;
00300 }
00301 
00302 inline vnl_bignum operator*(vnl_bignum const& r1, long r2)
00303 {
00304   vnl_bignum result(r1); return result *= vnl_bignum(r2);
00305 }
00306 
00307 inline vnl_bignum operator*(vnl_bignum const& r1, int r2)
00308 {
00309   vnl_bignum result(r1); return result *= (long)r2;
00310 }
00311 
00312 inline vnl_bignum operator*(vnl_bignum const& r1, double r2)
00313 {
00314   vnl_bignum result(r1); return result *= (vnl_bignum)r2;
00315 }
00316 
00317 inline vnl_bignum operator*(vnl_bignum const& r1, long double r2)
00318 {
00319   vnl_bignum result(r1); return result *= (vnl_bignum)r2;
00320 }
00321 
00322 inline vnl_bignum operator*(long r2, vnl_bignum const& r1)
00323 {
00324   vnl_bignum result(r1); return result *= r2;
00325 }
00326 
00327 inline vnl_bignum operator*(int r2, vnl_bignum const& r1)
00328 {
00329   vnl_bignum result(r1); return result *= (long)r2;
00330 }
00331 
00332 inline vnl_bignum operator*(double r2, vnl_bignum const& r1)
00333 {
00334   vnl_bignum result(r1); return result *= (vnl_bignum)r2;
00335 }
00336 
00337 inline vnl_bignum operator*(long double r2, vnl_bignum const& r1)
00338 {
00339   vnl_bignum result(r1); return result *= (vnl_bignum)r2;
00340 }
00341 
00342 //: Returns the division of two bignum numbers.
00343 // \relatesalso vnl_bignum
00344 inline vnl_bignum operator/(vnl_bignum const& r1, vnl_bignum const& r2)
00345 {
00346   vnl_bignum result(r1); return result /= r2;
00347 }
00348 
00349 inline vnl_bignum operator/(vnl_bignum const& r1, long r2)
00350 {
00351   vnl_bignum result(r1); return result /= r2;
00352 }
00353 
00354 inline vnl_bignum operator/(vnl_bignum const& r1, int r2)
00355 {
00356   vnl_bignum result(r1); return result /= (long)r2;
00357 }
00358 
00359 inline vnl_bignum operator/(vnl_bignum const& r1, double r2)
00360 {
00361   vnl_bignum result(r1); return result /= (vnl_bignum)r2;
00362 }
00363 
00364 inline vnl_bignum operator/(vnl_bignum const& r1, long double r2)
00365 {
00366   vnl_bignum result(r1); return result /= (vnl_bignum)r2;
00367 }
00368 
00369 inline vnl_bignum operator/(long r1, vnl_bignum const& r2)
00370 {
00371   vnl_bignum result(r1); return result /= r2;
00372 }
00373 
00374 inline vnl_bignum operator/(int r1, vnl_bignum const& r2)
00375 {
00376   vnl_bignum result((long)r1); return result /= r2;
00377 }
00378 
00379 inline vnl_bignum operator/(double r1, vnl_bignum const& r2)
00380 {
00381   vnl_bignum result(r1); return result /= r2;
00382 }
00383 
00384 inline vnl_bignum operator/(long double r1, vnl_bignum const& r2)
00385 {
00386   vnl_bignum result(r1); return result /= r2;
00387 }
00388 
00389 //: Returns the remainder of r1 divided by r2.
00390 // \relatesalso vnl_bignum
00391 inline vnl_bignum operator%(vnl_bignum const& r1, vnl_bignum const& r2)
00392 {
00393   vnl_bignum result(r1); return result %= r2;
00394 }
00395 
00396 inline vnl_bignum operator%(vnl_bignum const& r1, long r2)
00397 {
00398   vnl_bignum result(r1); return result %= vnl_bignum(r2);
00399 }
00400 
00401 inline vnl_bignum operator%(vnl_bignum const& r1, int r2)
00402 {
00403   vnl_bignum result(r1); return result %= vnl_bignum((long)r2);
00404 }
00405 
00406 inline vnl_bignum operator%(long r1, vnl_bignum const& r2)
00407 {
00408   vnl_bignum result(r1); return result %= r2;
00409 }
00410 
00411 inline vnl_bignum operator%(int r1, vnl_bignum const& r2)
00412 {
00413   vnl_bignum result((long)r1); return result %= r2;
00414 }
00415 
00416 // Miscellaneous operators and functions
00417 
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 inline bool operator>=(long r1, vnl_bignum const& r2) { return r2<=r1; }
00424 
00425 inline vnl_bignum vnl_math_abs(vnl_bignum const& x) { return x.abs(); }
00426 inline vnl_bignum vnl_math_squared_magnitude(vnl_bignum const& x) { return x*x; }
00427 inline vnl_bignum vnl_math_sqr(vnl_bignum const& x) { return x*x; }
00428 inline bool vnl_math_isnan(vnl_bignum const& ) { return false; }
00429 inline bool vnl_math_isfinite(vnl_bignum const& x) { return ! x.is_infinity(); }
00430 
00431 #endif // vnl_bignum_h_