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

Generated on Fri May 20 13:13:54 2005 for CVC Lite by  doxygen 1.3.9.1