core/vnl/vnl_decnum.h
Go to the documentation of this file.
00001 // This is core/vnl/vnl_decnum.h
00002 #ifndef vnl_decnum_h_
00003 #define vnl_decnum_h_
00004 //:
00005 // \file
00006 // \brief Infinite precision numbers with decimal arithmetic
00007 //
00008 // The vnl_decnum class implements infinite precision integers and
00009 // floating point numbers, with all necessary arithmetic, by using a
00010 // dynamically allocated string of decimals for the mantissa.
00011 // Implicit conversion to the system defined types short, int, and long
00012 // is supported by overloaded operator member functions and explicit
00013 // conversions from these types is available through constructors;
00014 // additionally, an implicit "double" constructor is available (mainly
00015 // for use with vnl_decnum_traits), without any guarantees.
00016 //
00017 // Addition and subtraction operators are performed by simple decimal
00018 // arithmetic with checks for carry flag propagation.
00019 // The multiplication, division, and remainder operations utilize the
00020 // naive, commonly known decimal algorithms. Beware that these could be
00021 // considerably slower than both the operations on built-in integer
00022 // types and those implemented in the class vnl_bignum.
00023 // On the other hand, the I/O could be faster since no decimal <==> binary
00024 // conversion needs to be performed.
00025 // Rounding errors due to imprecise internal representation can never be
00026 // made with vnl_decnum, so consider using this class if decimal I/O and
00027 // precise arithmetic are crucial.
00028 //
00029 // Since the internal representation is decimal, there is no overhead
00030 // for converting between a vnl_decnum and a decimal character string
00031 // representation. Hence, there is a constructor from std::string, there
00032 // are both << and >> operators, and a cast method to std::string, all
00033 // of them essentially no-ops.
00034 //
00035 // Decimal point notation is only supported on input; internally,
00036 // only the scientific notation (mantissa and exponent) is used, with
00037 // integer mantissa (and, on output, without "e exponent" for integers).
00038 // Beware that, even for non-integers, the division and modulo operators
00039 // are logically speaking integer operations on the mantissa.
00040 // E.g., the result of 42e-3 / 30e-4 is 1e1, while 42e-3 / 3e-3 has as
00041 // outcome 14, even though numerically 30e-4 == 3e-3.
00042 // But then also 42e-3 % 30e-4 returns 12e-3 while 42e-3 % 3e-3 returns 0.
00043 // Both results are compatible with
00044 //   (a/b) * b + (a%b) = a
00045 // which is generally true for other integral types as well.
00046 //
00047 // The difference between using e.g. 1000 and 10e2 is essentially similar to
00048 // the use of the "P" format in Cobol: in the former case, a precision of
00049 // four digits is kept, while in the latter only two digits are present (with
00050 // two zeros implicitly there). Arithmetic is done with the available precision
00051 // only, which explains the outcomes of operator/ and operator%. A similar
00052 // logic holds for the difference between e.g. 1000e-2 and 10.
00053 //
00054 // When none of the used vnl_decnum constructor values have an "e" (or when
00055 // all constructors that you use in your program are on integers), no "e" is
00056 // ever introduced (except when explicitly using the method compactify()).
00057 // In that case, vnl_decnum really behaves as an integral type,
00058 // very similar to vnl_bignum, and as an extension of int and long.
00059 //
00060 // In addition to (arbitrary precision) numbers, vnl_decnum also represents
00061 // +Infinity, -Infinity, and Nan. Their internal representations are:
00062 // (sign,data,exp) = ('+','Inf',0L), ('-','Inf',0L'), and (' ','NaN',0L).
00063 // Arithmetic with these entities is as expected: e.g. 1/0=+Inf, 1/Inf=0,
00064 // -Inf < n < +Inf, 1+Inf=+Inf, 0/0=NaN, NaN op n = NaN.
00065 //
00066 // \sa vnl_bignum
00067 //
00068 // \author Peter Vanroose, ABIS Leuven
00069 // \date   August 2011
00070 //
00071 // \verbatim
00072 //  Modifications
00073 //   15 Aug. 2011 - Peter Vanroose - added member exp_ (and non-integer arith)
00074 //   16 Aug. 2011 - Peter Vanroose - added Inf & NaN and constructor from double
00075 // \endverbatim
00076 
00077 #include <vcl_iostream.h>
00078 #include <vcl_string.h>
00079 
00080 class vnl_decnum
00081 {
00082   char sign_;      // Sign of vnl_decnum ('+' or '-'; for zero and NaN, the sign is ' ')
00083   vcl_string data_;// The decimal mantissa data (absolute value)
00084                    // data_ consists of decimals (0-9) only, guaranteed without
00085                    // leading zero. This holds even for zero: represented by "".
00086                    // The only exceptions are "Inf" and "NaN".
00087   long exp_;       // The exponent; nonnegative for integers. Zero for Inf and NaN.
00088 
00089   // private constructor: arguments should satisfy the above constraints
00090   vnl_decnum(char s, vcl_string const& d, long e) : sign_(s), data_(d), exp_(e) {}
00091  public:
00092   vcl_string data() const { return data_; }
00093   char       sign() const { return sign_; }
00094   long       exp () const { return exp_; }
00095   //: Default constructor - creates the number zero.
00096   vnl_decnum() : sign_(' '), data_(""), exp_(0L) {}
00097   // Copy constructor
00098   vnl_decnum(vnl_decnum const& r)
00099   : sign_(r.sign_), data_(r.data_), exp_(r.exp_) {}
00100   //: Constructor from string
00101   //  This is the principal constructor for vnl_decnum; it essentially parses
00102   //  the input into (in that order) the sign, the mantissa, and the exponent,
00103   //  which turn out (surprise!) to be the three data members of this class.
00104   //  Parsing stops at the first unexpected character, so in the worst case
00105   //  no characters can be used and the decnum is zero.
00106   vnl_decnum(vcl_string const&);
00107   vnl_decnum(char const* r) { operator=(vcl_string(r)); }
00108   //: Creates a vnl_decnum from an unsigned long integer.
00109   explicit vnl_decnum(unsigned long);
00110   //: Creates a vnl_decnum from a long integer.
00111   // Uses the "unsigned long" constructor and additionally sets the sign
00112   explicit vnl_decnum(long r)
00113   : sign_(r<0 ? '-' : r>0 ? '+' : ' ')
00114   { vnl_decnum d((unsigned long)(r<0?-r:r)); data_=d.data(); exp_=d.exp(); }
00115   //: Creates a vnl_decnum from an unsigned integer.
00116   // Uses the "unsigned long" constructor.
00117   explicit vnl_decnum(unsigned int r)
00118   : sign_(r>0 ? '+' : ' ')
00119   { vnl_decnum d((unsigned long)r); data_=d.data(); exp_=d.exp(); }
00120   //: Creates a vnl_decnum from an integer.
00121   // Uses the "unsigned long" constructor and additionally sets the sign
00122   explicit vnl_decnum(int r)
00123   : sign_(r<0 ? '-' : r>0 ? '+' : ' ')
00124   { vnl_decnum d((unsigned long)(r<0?-r:r)); data_=d.data(); exp_=d.exp(); }
00125   //: Creates a vnl_decnum from a double.
00126   // No guarantees on the precise result!
00127   // Integers will be correctly converted, though.
00128   vnl_decnum(double);
00129 
00130   ~vnl_decnum() {}    // Destructor
00131 
00132   //: Implicit type conversion to a decimal string
00133   operator vcl_string() const;
00134 
00135   operator long() const;  // type conversion
00136   operator unsigned long() const;  // type conversion, drop the sign
00137   operator int() const;  // type conversion
00138   operator unsigned int() const;  // type conversion, drop the sign
00139 
00140   //: Unary plus operator
00141   inline vnl_decnum operator+() const { return *this; }
00142   //: Unary minus operator
00143   inline vnl_decnum operator-() const { if (sign_==' ') return *this; else return vnl_decnum(sign_=='-'?'+':'-', data_, exp_); }
00144 
00145   //: Left "bit" shift operator (actually: digit shift, or exponent translation)
00146   inline vnl_decnum operator<<(long int r) const { return sign_==' ' ? *this : vnl_decnum(sign_, data_, exp_+r); }
00147   inline vnl_decnum operator<<(int r) const { return operator<<((long int)r); }
00148   //: Right "bit" shift operator (actually: digit shift, or exponent translation)
00149   inline vnl_decnum operator>>(long int r) const { return sign_==' ' ? *this : vnl_decnum(sign_, data_, exp_-r); }
00150   inline vnl_decnum operator>>(int r) const { return operator>>((long int)r); }
00151   //: Left "bit" shift operator (actually: digit shift, or exponent translation)
00152   inline vnl_decnum& operator<<=(long int r) { if (sign_!=' ') exp_ += r; return *this; }
00153   inline vnl_decnum& operator<<=(int r) { if (sign_!=' ') exp_ += r; return *this; }
00154   //: Right "bit" shift operator (actually: digit shift, or exponent translation)
00155   inline vnl_decnum& operator>>=(long int r) { if (sign_!=' ') exp_ -= r; return *this; }
00156   inline vnl_decnum& operator>>=(int r) { if (sign_!=' ') exp_ -= r; return *this; }
00157 
00158   //: Remove all trailing zeros from the mantissa, and increase the exponent accordingly.
00159   // Return the (thus modified) *this.
00160   // This effectively compactifies the data representation of *this, and meanwhile increases the exponent.
00161   // No other methods have this effect; to the contrary: e.g. operator+(1) often decreases the exponent to 0.
00162   vnl_decnum& compactify();
00163 
00164   //: Expand integers to their non-compactified representation, i.e., without "e" notation.
00165   // Other operators (like + or -) might implicitly have this effect, as the implementation here indeed suggests.
00166   inline vnl_decnum& expand() { return *this = operator+(1L)-1L; }
00167 
00168   //: Assignment operator; no compactification or expansion occurs
00169   inline vnl_decnum& operator=(const vnl_decnum& r) { sign_=r.sign(); data_=r.data(); exp_=r.exp(); return *this; }
00170   //: Sum
00171   vnl_decnum operator+(vnl_decnum const& r) const;
00172   //: Difference
00173   inline vnl_decnum operator-(vnl_decnum const& r) const { return operator+(-r); }
00174   //: Product
00175   vnl_decnum operator*(vnl_decnum const& r) const;
00176   //: division operator
00177   // \returns integral part of quotient (long division) of *this with \p r
00178   // When \p r is zero, the result is Inf,
00179   // unless also *this is zero, in which case the result is NaN.
00180   vnl_decnum operator/(vnl_decnum const& r) const;
00181   //: modulo operator
00182   // \returns remainder of long division of *this with \p r
00183   // When \p r is zero, the result equals *this.
00184   vnl_decnum operator%(vnl_decnum const& r) const;
00185 
00186   inline vnl_decnum& operator+=(vnl_decnum const& r) { return *this = operator+(r); }
00187   inline vnl_decnum& operator-=(vnl_decnum const& r) { return *this = operator+(-r); }
00188   inline vnl_decnum& operator*=(vnl_decnum const& r) { return *this = operator*(r); }
00189   inline vnl_decnum& operator/=(vnl_decnum const& r) { return *this = operator/(r); }
00190   inline vnl_decnum& operator%=(vnl_decnum const& r) { return *this = operator%(r); }
00191 
00192   // === overloads for the above operators with other datatypes as rhs:
00193 
00194   inline vnl_decnum& operator=(vcl_string const& r) { return operator=(vnl_decnum(r)); }
00195   inline vnl_decnum& operator=(char const* r) { return operator=(vnl_decnum(vcl_string(r))); }
00196   inline vnl_decnum& operator=(unsigned long r) { return operator=(vnl_decnum(r)); }
00197   inline vnl_decnum& operator=(long r) { return operator=(vnl_decnum(r)); }
00198   inline vnl_decnum& operator=(unsigned  int r) { return operator=(vnl_decnum(r)); }
00199   inline vnl_decnum& operator=(int r) { return operator=(vnl_decnum(r)); }
00200   inline vnl_decnum& operator=(double r) { return operator=(vnl_decnum(r)); }
00201 
00202   inline vnl_decnum operator+(vcl_string const& r) const { return operator+(vnl_decnum(r)); }
00203   inline vnl_decnum operator+(char const* r) const { return operator+(vnl_decnum(vcl_string(r))); }
00204   inline vnl_decnum operator+(unsigned long r) const { return operator+(vnl_decnum(r)); }
00205   inline vnl_decnum operator+(long r) const { return operator+(vnl_decnum(r)); }
00206   inline vnl_decnum operator+(unsigned int r) const { return operator+(vnl_decnum(r)); }
00207   inline vnl_decnum operator+(int r) const { return operator+(vnl_decnum(r)); }
00208   inline vnl_decnum operator+(double r) const { return operator+(vnl_decnum(r)); }
00209 
00210   inline vnl_decnum operator-(vcl_string const& r) const { return operator-(vnl_decnum(r)); }
00211   inline vnl_decnum operator-(char const* r) const { return operator-(vnl_decnum(vcl_string(r))); }
00212   inline vnl_decnum operator-(unsigned long r) const { return operator-(vnl_decnum(r)); }
00213   inline vnl_decnum operator-(long r) const { return operator+(vnl_decnum(-r)); }
00214   inline vnl_decnum operator-(unsigned int r) const { return operator-(vnl_decnum(r)); }
00215   inline vnl_decnum operator-(int r) const { return operator+(vnl_decnum(-r)); }
00216   inline vnl_decnum operator-(double r) const { return operator+(vnl_decnum(-r)); }
00217 
00218   inline vnl_decnum operator*(vcl_string const& r) const { return operator*(vnl_decnum(r)); }
00219   inline vnl_decnum operator*(char const* r) const { return operator*(vnl_decnum(vcl_string(r))); }
00220   inline vnl_decnum operator*(unsigned long r) const { return operator*(vnl_decnum(r)); }
00221   inline vnl_decnum operator*(long r) const { return operator*(vnl_decnum(r)); }
00222   inline vnl_decnum operator*(unsigned int r) const { return operator*(vnl_decnum(r)); }
00223   inline vnl_decnum operator*(int r) const { return operator*(vnl_decnum(r)); }
00224   inline vnl_decnum operator*(double r) const { return operator*(vnl_decnum(r)); }
00225 
00226   inline vnl_decnum operator/(vcl_string const& r) const { return operator/(vnl_decnum(r)); }
00227   inline vnl_decnum operator/(char const* r) const { return operator/(vnl_decnum(vcl_string(r))); }
00228   inline vnl_decnum operator/(unsigned long r) const { return operator/(vnl_decnum(r)); }
00229   inline vnl_decnum operator/(long r) const { return operator/(vnl_decnum(r)); }
00230   inline vnl_decnum operator/(unsigned int r) const { return operator/(vnl_decnum(r)); }
00231   inline vnl_decnum operator/(int r) const { return operator/(vnl_decnum(r)); }
00232   inline vnl_decnum operator/(double r) const { return operator/(vnl_decnum(r)); }
00233 
00234   inline vnl_decnum operator%(vcl_string const& r) const { return operator%(vnl_decnum(r)); }
00235   inline vnl_decnum operator%(char const* r) const { return operator%(vnl_decnum(vcl_string(r))); }
00236   inline vnl_decnum operator%(unsigned long r) const { return operator%(vnl_decnum(r)); }
00237   inline vnl_decnum operator%(long r) const { return operator%(vnl_decnum(r)); }
00238   inline vnl_decnum operator%(unsigned int r) const { return operator%(vnl_decnum(r)); }
00239   inline vnl_decnum operator%(int r) const { return operator%(vnl_decnum(r)); }
00240   inline vnl_decnum operator%(double r) const { return operator%(vnl_decnum(r)); }
00241 
00242   inline vnl_decnum& operator+=(vcl_string const& r) { return *this = operator+(vnl_decnum(r)); }
00243   inline vnl_decnum& operator-=(vcl_string const& r) { return *this = operator-(vnl_decnum(r)); }
00244   inline vnl_decnum& operator*=(vcl_string const& r) { return *this = operator*(vnl_decnum(r)); }
00245   inline vnl_decnum& operator/=(vcl_string const& r) { return *this = operator/(vnl_decnum(r)); }
00246   inline vnl_decnum& operator%=(vcl_string const& r) { return *this = operator%(vnl_decnum(r)); }
00247 
00248   inline vnl_decnum& operator+=(char const* r) { return *this = operator+(vcl_string(r)); }
00249   inline vnl_decnum& operator-=(char const* r) { return *this = operator-(vcl_string(r)); }
00250   inline vnl_decnum& operator*=(char const* r) { return *this = operator*(vcl_string(r)); }
00251   inline vnl_decnum& operator/=(char const* r) { return *this = operator/(vcl_string(r)); }
00252   inline vnl_decnum& operator%=(char const* r) { return *this = operator%(vcl_string(r)); }
00253 
00254   inline vnl_decnum& operator+=(unsigned long r) { return *this = operator+(vnl_decnum(r)); }
00255   inline vnl_decnum& operator-=(unsigned long r) { return *this = operator-(vnl_decnum(r)); }
00256   inline vnl_decnum& operator*=(unsigned long r) { return *this = operator*(vnl_decnum(r)); }
00257   inline vnl_decnum& operator/=(unsigned long r) { return *this = operator/(vnl_decnum(r)); }
00258   inline vnl_decnum& operator%=(unsigned long r) { return *this = operator%(vnl_decnum(r)); }
00259 
00260   inline vnl_decnum& operator+=(long r) { return *this = operator+(vnl_decnum(r)); }
00261   inline vnl_decnum& operator-=(long r) { return *this = operator+(vnl_decnum(-r)); }
00262   inline vnl_decnum& operator*=(long r) { return *this = operator*(vnl_decnum(r)); }
00263   inline vnl_decnum& operator/=(long r) { return *this = operator/(vnl_decnum(r)); }
00264   inline vnl_decnum& operator%=(long r) { return *this = operator%(vnl_decnum(r)); }
00265 
00266   inline vnl_decnum& operator+=(unsigned int r) { return *this = operator+(vnl_decnum(r)); }
00267   inline vnl_decnum& operator-=(unsigned int r) { return *this = operator-(vnl_decnum(r)); }
00268   inline vnl_decnum& operator*=(unsigned int r) { return *this = operator*(vnl_decnum(r)); }
00269   inline vnl_decnum& operator/=(unsigned int r) { return *this = operator/(vnl_decnum(r)); }
00270   inline vnl_decnum& operator%=(unsigned int r) { return *this = operator%(vnl_decnum(r)); }
00271 
00272   inline vnl_decnum& operator+=(int r) { return *this = operator+(vnl_decnum(r)); }
00273   inline vnl_decnum& operator-=(int r) { return *this = operator+(vnl_decnum(-r)); }
00274   inline vnl_decnum& operator*=(int r) { return *this = operator*(vnl_decnum(r)); }
00275   inline vnl_decnum& operator/=(int r) { return *this = operator/(vnl_decnum(r)); }
00276   inline vnl_decnum& operator%=(int r) { return *this = operator%(vnl_decnum(r)); }
00277 
00278   inline vnl_decnum& operator+=(double r) { return *this = operator+(vnl_decnum(r)); }
00279   inline vnl_decnum& operator-=(double r) { return *this = operator+(vnl_decnum(-r)); }
00280   inline vnl_decnum& operator*=(double r) { return *this = operator*(vnl_decnum(r)); }
00281   inline vnl_decnum& operator/=(double r) { return *this = operator/(vnl_decnum(r)); }
00282   inline vnl_decnum& operator%=(double r) { return *this = operator%(vnl_decnum(r)); }
00283 
00284   //: prefix increment (++b)
00285   inline vnl_decnum& operator++() { return *this = operator+(1L); }
00286   //: decrement
00287   inline vnl_decnum& operator--() { return *this = operator-(1L); }
00288   //: postfix increment (b++)
00289   inline vnl_decnum operator++(int) { vnl_decnum b=(*this); operator++(); return b; }
00290   //: decrement
00291   inline vnl_decnum operator--(int) { vnl_decnum b=(*this); operator--(); return b; }
00292 
00293   bool operator==(vnl_decnum const&) const; // equality
00294   bool operator< (vnl_decnum const&) const; // less than
00295   inline bool operator!=(vnl_decnum const& r) const { return !operator==(r); }
00296   inline bool operator> (vnl_decnum const& r) const { return r<(*this); }
00297   inline bool operator<=(vnl_decnum const& r) const { return !operator>(r); }
00298   inline bool operator>=(vnl_decnum const& r) const { return !operator<(r); }
00299 
00300   inline bool operator==(vcl_string const& r) const { return operator==(vnl_decnum(r)); }
00301   inline bool operator< (vcl_string const& r) const { return operator< (vnl_decnum(r)); }
00302   inline bool operator!=(vcl_string const& r) const { return operator!=(vnl_decnum(r)); }
00303   inline bool operator> (vcl_string const& r) const { return operator> (vnl_decnum(r)); }
00304   inline bool operator<=(vcl_string const& r) const { return operator<=(vnl_decnum(r)); }
00305   inline bool operator>=(vcl_string const& r) const { return operator>=(vnl_decnum(r)); }
00306 
00307   inline bool operator==(char const* r) const { return operator==(vcl_string(r)); }
00308   inline bool operator< (char const* r) const { return operator< (vcl_string(r)); }
00309   inline bool operator!=(char const* r) const { return operator!=(vcl_string(r)); }
00310   inline bool operator> (char const* r) const { return operator> (vcl_string(r)); }
00311   inline bool operator<=(char const* r) const { return operator<=(vcl_string(r)); }
00312   inline bool operator>=(char const* r) const { return operator>=(vcl_string(r)); }
00313 
00314   inline bool operator==(unsigned long r) const { return operator==(vnl_decnum(r)); }
00315   inline bool operator< (unsigned long r) const { return operator< (vnl_decnum(r)); }
00316   inline bool operator!=(unsigned long r) const { return operator!=(vnl_decnum(r)); }
00317   inline bool operator> (unsigned long r) const { return operator> (vnl_decnum(r)); }
00318   inline bool operator<=(unsigned long r) const { return operator<=(vnl_decnum(r)); }
00319   inline bool operator>=(unsigned long r) const { return operator>=(vnl_decnum(r)); }
00320 
00321   inline bool operator==(long r) const { return operator==(vnl_decnum(r)); }
00322   inline bool operator< (long r) const { return operator< (vnl_decnum(r)); }
00323   inline bool operator!=(long r) const { return operator!=(vnl_decnum(r)); }
00324   inline bool operator> (long r) const { return operator> (vnl_decnum(r)); }
00325   inline bool operator<=(long r) const { return operator<=(vnl_decnum(r)); }
00326   inline bool operator>=(long r) const { return operator>=(vnl_decnum(r)); }
00327 
00328   inline bool operator==(unsigned int r) const { return operator==(vnl_decnum(r)); }
00329   inline bool operator< (unsigned int r) const { return operator< (vnl_decnum(r)); }
00330   inline bool operator!=(unsigned int r) const { return operator!=(vnl_decnum(r)); }
00331   inline bool operator> (unsigned int r) const { return operator> (vnl_decnum(r)); }
00332   inline bool operator<=(unsigned int r) const { return operator<=(vnl_decnum(r)); }
00333   inline bool operator>=(unsigned int r) const { return operator>=(vnl_decnum(r)); }
00334 
00335   inline bool operator==(int r) const { return operator==(vnl_decnum(r)); }
00336   inline bool operator< (int r) const { return operator< (vnl_decnum(r)); }
00337   inline bool operator!=(int r) const { return operator!=(vnl_decnum(r)); }
00338   inline bool operator> (int r) const { return operator> (vnl_decnum(r)); }
00339   inline bool operator<=(int r) const { return operator<=(vnl_decnum(r)); }
00340   inline bool operator>=(int r) const { return operator>=(vnl_decnum(r)); }
00341 
00342   inline bool operator==(double r) const { return operator==(vnl_decnum(r)); }
00343   inline bool operator< (double r) const { return operator< (vnl_decnum(r)); }
00344   inline bool operator!=(double r) const { return operator!=(vnl_decnum(r)); }
00345   inline bool operator> (double r) const { return operator> (vnl_decnum(r)); }
00346   inline bool operator<=(double r) const { return operator<=(vnl_decnum(r)); }
00347   inline bool operator>=(double r) const { return operator>=(vnl_decnum(r)); }
00348 
00349   inline vnl_decnum abs() const { return sign_=='-' ? operator-() : *this; }
00350   inline vnl_decnum trunc() const { return exp_>=0L ? *this : vnl_decnum(sign_,data_.substr(0L,data_.length()+exp_),0L); }
00351   inline vnl_decnum roundup() const { return operator==(trunc()) ? *this : sign_=='-' ? trunc()-1 : trunc()+1; }
00352   inline vnl_decnum floor() const { return sign_=='-' ? roundup() : trunc(); }
00353   inline vnl_decnum ceil() const { return sign_=='-' ? trunc() : roundup(); }
00354   inline vnl_decnum pow(unsigned long p) const { return p==0L ? vnl_decnum(1L) : p==1L ? *this : pow(p/2)*pow((p+1)/2); }
00355 
00356  private: // === Helper functions ===
00357   //: Returns the sum of the two first arguments (interpreted as mantissas with the same exponent).
00358   // Both arguments should consist of digits only.
00359   // The third argument will be used as the exponent of the result.
00360   static vnl_decnum plus(vcl_string const&, vcl_string const&, long);
00361   //: Returns the difference of the two first arguments (interpreted as mantissas with the same exponent).
00362   // Both arguments should consist of digits only
00363   // and the first one should be numerically larger than the second one.
00364   // The third argument will be used as the exponent of the result.
00365   static vnl_decnum minus(vcl_string const&, vcl_string const&, long);
00366   //: This is "operator<" for strings.
00367   // The arguments should consist of digits only (interpreted as mantissas with the same exponent).
00368   // The shorter of the two arguments is implicitly zero-padded.
00369   static bool comp(vcl_string const&, vcl_string const&);
00370   // Append n zeros to the source string, and return the new padded string
00371   inline static vcl_string add_zeros(vcl_string const& source, unsigned long n)
00372   { vcl_string d = source; while (n--!=0) d.push_back('0'); return d; }
00373   //: Returns the product of the two arguments.
00374   // The first argument should consist of digits only;
00375   // the second argument should be a single digit.
00376   static vcl_string mult(vcl_string const&, char);
00377   //: Returns the largest one-significant-digit divisor of the two arguments.
00378   // The largest multiple of the second argument not larger than the first one
00379   // is returned in the second argument.
00380   // (I.e.: the product of the original second argument with the returned divisor.)
00381   // The arguments should consist of digits only
00382   // and the first one should be numerically larger than the second one.
00383   static vcl_string div(vcl_string const&, vcl_string&);
00384 };
00385 
00386 //: decimal output
00387 // \relatesalso vnl_decnum
00388 inline vcl_ostream& operator<<(vcl_ostream& s, vnl_decnum const& r)
00389 { return s << vcl_string(r); }
00390 
00391 //: decimal input
00392 // \relatesalso vnl_decnum
00393 vcl_istream& operator>>(vcl_istream& s, vnl_decnum& r);
00394 
00395 inline vnl_decnum ceil(vnl_decnum const& x) { return x.ceil(); }
00396 inline vnl_decnum floor(vnl_decnum const& x) { return x.floor(); }
00397 inline vnl_decnum pow(vnl_decnum const& x, unsigned long p) { return x.pow(p); }
00398 
00399 inline vnl_decnum vnl_math_abs(vnl_decnum const& x) { return x.abs(); }
00400 inline vnl_decnum vnl_math_sqr(vnl_decnum const& x) { return x*x; }
00401 inline vnl_decnum vnl_math_cube(vnl_decnum const& x) { return x*x*x; }
00402 inline vnl_decnum vnl_math_squared_magnitude(vnl_decnum const& x) { return x*x; }
00403 inline bool vnl_math_isnan(vnl_decnum const& x) { return x.data() == "NaN"; }
00404 inline bool vnl_math_isfinite(vnl_decnum const& x) { return x.data() != "Inf" && x.data() != "NaN"; }
00405 inline vnl_decnum vnl_math_max(vnl_decnum const& x, vnl_decnum const& y) { return (x < y) ? y : x; }
00406 inline vnl_decnum vnl_math_min(vnl_decnum const& x, vnl_decnum const& y) { return (x < y) ? x : y; }
00407 inline int vnl_math_sgn(vnl_decnum x) { return x.sign()==' '?0:x.sign()=='+'?1:-1; }
00408 inline int vnl_math_sgn0(vnl_decnum x) { return x.sign()=='-'?-1:1; }
00409 
00410 #endif // vnl_decnum_h_