rational.h

Go to the documentation of this file.
00001 /*****************************************************************************/
00002 /*!
00003  * \file rational.h
00004  * 
00005  * Author: Sergey Berezin
00006  * 
00007  * Created: Dec 12 22:00:18 GMT 2002
00008  *
00009  * <hr>
00010  *
00011  * License to use, copy, modify, sell and/or distribute this software
00012  * and its documentation for any purpose is hereby granted without
00013  * royalty, subject to the terms and conditions defined in the \ref
00014  * LICENSE file provided with this distribution.
00015  * 
00016  * <hr>
00017  * 
00018  */
00019 /*****************************************************************************/
00020 // Class: Rational
00021 // Author: Sergey Berezin, 12/12/2002 (adapted from Bignum)
00022 //
00023 // Description: This is an abstration of a rational with arbitrary
00024 // precision.  It provides a constructor from a pair of ints and
00025 // strings, overloaded operator{+,-,*,/}, assignment, etc.  The
00026 // current implementation uses GMP mpq_class.
00027 ///////////////////////////////////////////////////////////////////////////////
00028 
00029 #ifndef _cvc3__rational_h_
00030 #define _cvc3__rational_h_
00031 
00032 // Do not include <gmpxx.h> here; it contains some depricated C++
00033 // headers.  We only include it in the .cpp file.
00034 
00035 #include <vector>
00036 #include "debug.h"
00037 
00038 // To be defined only in bignum.cpp
00039 namespace CVC3 {
00040 
00041   class CVC_DLL Rational {
00042   private:
00043     class Impl;
00044     Impl *d_n;
00045     // Debugging
00046 #ifdef _DEBUG_RATIONAL_
00047     // Encapsulate static values in a function to guarantee
00048     // initialization when we need it
00049     int& getCreated() {
00050       static int num_created = 0;
00051       return(num_created);
00052     }
00053       
00054     int& getDeleted() {
00055       static int num_deleted = 0;
00056       return(num_deleted);
00057     }
00058       
00059     void printStats();
00060 #endif
00061     // Private constructor (for internal consumption only)
00062     Rational(const Impl& t);
00063 
00064   public:
00065     // Constructors
00066     Rational();
00067     // Copy constructor
00068     Rational(const Rational &n);
00069     Rational(int n, int d = 1);
00070     Rational(const char* n, int base = 10);
00071     Rational(const std::string& n, int base = 10);
00072     Rational(const char* n, const char* d, int base = 10);
00073     Rational(const std::string& n, const std::string& d, int base = 10);
00074     // Destructor
00075     ~Rational();
00076 
00077     // Assignment
00078     Rational& operator=(const Rational& n);
00079 
00080     std::string toString(int base = 10) const;
00081 
00082     // Compute hash value (for DAG expression representation)
00083     size_t hash() const;
00084 
00085     friend bool operator==(const Rational &n1, const Rational &n2);
00086     friend bool operator<(const Rational &n1, const Rational &n2);
00087     friend bool operator<=(const Rational &n1, const Rational &n2);
00088     friend bool operator>(const Rational &n1, const Rational &n2);
00089     friend bool operator>=(const Rational &n1, const Rational &n2);
00090     friend bool operator!=(const Rational &n1, const Rational &n2);
00091     friend Rational operator+(const Rational &n1, const Rational &n2);
00092     friend Rational operator-(const Rational &n1, const Rational &n2);
00093     friend Rational operator*(const Rational &n1, const Rational &n2);
00094     friend Rational operator/(const Rational &n1, const Rational &n2);
00095     // 'mod' operator, defined only for integer values of n1 and n2
00096     friend Rational operator%(const Rational &n1, const Rational &n2);
00097 
00098     // Unary minus
00099     Rational operator-() const;
00100     Rational &operator+=(const Rational &n2);
00101     Rational &operator-=(const Rational &n2);
00102     Rational &operator*=(const Rational &n2);
00103     Rational &operator/=(const Rational &n2);
00104     //! Prefix increment
00105     const Rational& operator++() { *this = (*this)+1; return *this; }
00106     //! Postfix increment
00107     Rational operator++(int) { Rational x(*this); *this = x+1; return x; }
00108     //! Prefix decrement
00109     const Rational& operator--() { *this = (*this)-1; return *this; }
00110     //! Postfix decrement
00111     Rational operator--(int) { Rational x(*this); *this = x-1; return x; }
00112 
00113     // Result is integer
00114     Rational getNumerator() const;
00115     Rational getDenominator() const;
00116 
00117     // Equivalent to (getDenominator() == 1), but possibly more efficient
00118     bool isInteger() const;
00119     // Convert to int; defined only on integer values
00120     int getInt() const;
00121     // Equivalent to (*this >= 0 && isInteger())
00122     bool isUnsigned() const { return (isInteger() && (*this) >= 0); }
00123     // Convert to unsigned int; defined only on non-negative integer values
00124     unsigned int getUnsigned() const;
00125 
00126     friend std::ostream &operator<<(std::ostream &os, const Rational &n);
00127 
00128     /* Computes gcd and lcm on *integer* values. Result is always a
00129        positive integer. */
00130 
00131     friend Rational gcd(const Rational &x, const Rational &y);
00132     friend Rational gcd(const std::vector<Rational> &v);
00133     friend Rational lcm(const Rational &x, const Rational &y);
00134     friend Rational lcm(const std::vector<Rational> &v);
00135 
00136     friend Rational abs(const Rational &x);
00137 
00138     //! Compute the floor of x (result is an integer)
00139     friend Rational floor(const Rational &x);
00140     //! Compute the ceiling of x (result is an integer)
00141     friend Rational ceil(const Rational &x);
00142     //! Compute non-negative remainder for *integer* x,y.
00143     friend Rational mod(const Rational &x, const Rational &y);
00144 
00145     // For debugging, to be able to print in gdb
00146     void print() const;
00147 
00148   }; // Rational class
00149 
00150   //! Raise 'base' into the power of 'pow' (pow must be an integer)
00151   inline Rational pow(Rational pow, const Rational& base) {
00152     DebugAssert(pow.isInteger(), "pow("+pow.toString()
00153     +", "+base.toString()+")");
00154     FatalAssert(base != 0 || pow >= 0, "Attempt to divide by zero");
00155     bool neg(pow < 0);
00156     if(neg) pow = -pow;
00157     Rational res(1);
00158     for(; pow > 0; --pow) res *= base;
00159     if(neg) res = 1/res;
00160     return res;
00161   }
00162 
00163   
00164   // Methods creating new Rational values, similar to the
00165   // constructors, but can be nested
00166   inline Rational newRational(int n, int d = 1) { return Rational(n, d); }
00167   inline Rational newRational(const char* n, int base = 10)
00168     { return Rational(n, base); }
00169   inline Rational newRational(const std::string& n, int base = 10)
00170     { return Rational(n, base); }
00171   inline Rational newRational(const char* n, const char* d, int base = 10)
00172     { return Rational(n, d, base); }
00173   inline Rational newRational(const std::string& n, const std::string& d,
00174             int base = 10)
00175     { return Rational(n, d, base); }
00176     
00177   // Debugging print
00178   void printRational(const Rational &x);
00179 
00180 } // end of namespace CVC3
00181 
00182 #endif

Generated on Tue Jul 3 14:33:38 2007 for CVC3 by  doxygen 1.5.1