/* Declarations for the Interval class and its constituents.
   Copyright (C) 2001-2004 Roberto Bagnara <bagnara@cs.unipr.it>

This file is part of the Parma Polyhedra Library (PPL).

The PPL is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.

The PPL is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
USA.

For the most up-to-date information see the Parma Polyhedra Library
site: http://www.cs.unipr.it/ppl/ . */

#ifndef PPL_Interval_defs_hh
#define PPL_Interval_defs_hh 1

#include "Interval.types.hh"

#include "Integer.types.hh"
#include <gmpxx.h>
#include <iosfwd>

namespace Parma_Polyhedra_Library {

#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
//! Returns <CODE>true</CODE> if and only if \p x is equal to \p y.
/*! \relates ERational */
#endif // PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
bool operator==(const ERational& x, const ERational& y);

#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
//! Returns <CODE>true</CODE> if and only if \p x and \p y are different.
/*! \relates ERational */
#endif // PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
bool operator!=(const ERational& x, const ERational& y);

#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
//! \brief
//! Returns <CODE>true</CODE> if and only if
//! \p x is less than or equal to  \p y.
/*! \relates ERational */
#endif // PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
bool operator<=(const ERational& x, const ERational& y);

#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
//! \brief
//! Returns <CODE>true</CODE> if and only if
//! \p x is greater than or equal to  \p y.
/*! \relates ERational */
#endif // PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
bool operator>=(const ERational& x, const ERational& y);

#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
//! Returns <CODE>true</CODE> if and only if \p x is less than \p y.
/*! \relates ERational */
#endif // PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
bool operator<(const ERational& x, const ERational& y);

#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
//! Returns <CODE>true</CODE> if and only if \p x is greater than \p y.
/*! \relates ERational */
#endif // PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
bool operator>(const ERational& x, const ERational& y);

namespace IO_Operators {

#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
//! Output operator.
/*! \relates Parma_Polyhedra_Library::ERational */
#endif // PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
std::ostream& operator<<(std::ostream& s, const ERational& x);

} // namespace IO_Operators

} // namespace Parma_Polyhedra_Library

#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
//! An extended rational number.
/*!
  An object of class ERational represents an element of the extended
  set of rational numbers \f$\Qset \union \{ -\infty, +\infty \}\f$.
  Elements of class ERational are totally ordered by the usual
  extension of the natural ordering on rational numbers, so that
  \f$-\infty < q < +\infty\f$ for all \f$q \in \Qset\f$.

  A finite rational number \f$q \in \Qset\f$ is internally represented
  by a \p mpq_class object
  (see the GMP's manual available at http://swox.com/gmp/ ).
*/
#endif // PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
class Parma_Polyhedra_Library::ERational {
public:
  //! Builds the finite rational number \p num / \p den.
  /*!
    An undefined behavior is obtained if \p den is equal to zero.
  */
  ERational(const Integer& num, const Integer& den);

  //! \brief
  //! Builds \f$+\infty\f$ (resp., \f$-\infty\f$)
  //! if \p sign is equal to <CODE>'+'</CODE> (resp., <CODE>'-'</CODE>).
  /*!
    An undefined behavior is obtained for any other value of \p sign.
  */
  explicit ERational(char sign);

  //! Copy constructor.
  ERational(const ERational& y);

  //! Assignment operator.
  ERational& operator=(const ERational& y);

  //! \brief
  //! Returns a negative integer if \p *this is equal to \f$-\infty\f$,
  //! zero if \p *this is an extended rational having a finite value,
  //! a positive integer if \p *this is equal to \f$+\infty\f$.
  int direction_of_infinity() const;

  //! Returns the numerator of the canonical form for \p *this.
  /*!
    The result is undefined if \p *this represents an infinity.
  */
  const Integer& numerator() const;

  //! Returns the denominator of the canonical form for \p *this.
  /*!
    The result is undefined if \p *this represent an infinity.
  */
  const Integer& denominator() const;

  friend bool
  Parma_Polyhedra_Library::operator==(const ERational& x, const ERational& y);
  friend bool
  Parma_Polyhedra_Library::operator!=(const ERational& x, const ERational& y);
  friend bool
  Parma_Polyhedra_Library::operator<=(const ERational& x, const ERational& y);
  friend bool
  Parma_Polyhedra_Library::operator>=(const ERational& x, const ERational& y);
  friend bool
  Parma_Polyhedra_Library::operator<(const ERational& x, const ERational& y);
  friend bool
  Parma_Polyhedra_Library::operator>(const ERational& x, const ERational& y);
  friend std::ostream&
  Parma_Polyhedra_Library::IO_Operators::operator<<(std::ostream& s,
						    const ERational& x);

private:
  //! Positive if \f$+\infty\f$, negative if \f$-\infty\f$, zero otherwise.
  int e;

  //! The finite value: valid only if \p e is equal to zero.
  mpq_class v;
};


namespace Parma_Polyhedra_Library {

#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
//! Returns <CODE>true</CODE> if and only if \p x is less than \p y.
/*! \relates Boundary */
#endif // PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
bool operator<(const Boundary& x, const Boundary& y);

#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
//! Returns <CODE>true</CODE> if and only if \p x is greater than \p y.
/*! \relates Boundary */
#endif // PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
bool operator>(const Boundary& x, const Boundary& y);

} // namespace Parma_Polyhedra_Library


#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
//! An extended rational bound of an interval.
/*!
  An object of class Boundary represents either an upper or a lower
  bound of an interval over the set of extended rational numbers. 
*/
#endif // PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
class Parma_Polyhedra_Library::Boundary {
protected:
  //! Kinds of bounds.
  enum Flag {
    //! An open upper bound.
    NEG = -1,
    //! A closed (lower or upper) bound.
    ZERO = 0,
    //! An open lower bound.
    POS = 1
  };

  //! The extended rational value of the bound.
  ERational value;
  //! The kind of the bound.
  Flag flag;

  //! Builds a bound of kind \p f and having value \p v.   
  Boundary(const ERational& v, Flag f);

  friend bool
  Parma_Polyhedra_Library::operator<(const Boundary& x, const Boundary& y);
  friend bool
  Parma_Polyhedra_Library::operator>(const Boundary& x, const Boundary& y);

public:
  //! Returns <CODE>true</CODE> if and only if \p *this is a closed bound.
  bool is_closed() const;

  //! Returns a const reference to the value of the bound.
  const ERational& bound() const;
};


#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
//! The lower bound of an extended rational interval.
#endif // PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
class Parma_Polyhedra_Library::LBoundary : public Boundary {
public:
  //! Kinds of lower bounds.
  enum OpenClosed {
    //! An open lower bound.
    OPEN = Boundary::POS,
    //! A closed lower bound.
    CLOSED = Boundary::ZERO
  };

  //! Builds a lower bound of kind \p f and having value \p v.
  LBoundary(const ERational& v, OpenClosed f);

  //! Checks if all the invariants are satisfied.
  bool OK() const;
};

#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
//! The upper bound of an extended rational interval.
#endif // PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
class Parma_Polyhedra_Library::UBoundary : public Boundary {
public:
  //! Kinds of upper bounds.
  enum OpenClosed {
    //! An open upper bound.
    OPEN = Boundary::NEG,
    //! A closed upper bound.
    CLOSED = Boundary::ZERO
  };

  //! Builds an upper bound of kind \p f and having value \p v.   
  UBoundary(const ERational& v, OpenClosed f);

  //! Checks if all the invariants are satisfied.
  bool OK() const;
};

#ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
//! A interval over the set of rational numbers.
/*!
  An object of class Interval represents a closed/half-closed/open
  interval over the set of rational numbers \f$\Qset\f$.

  Note that, even though the implementation is capable to represent
  any interval on the set of <EM>extended</EM> rational numbers,
  the available public methods only allows for the construction
  and manipulation of intervals over \f$\Qset\f$.
  Namely, it is not possible to create a non-empty interval having
  a <EM>closed</EM> bound whose value is \f$-\infty\f$ or \f$+\infty\f$.
*/
#endif // PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS

class Parma_Polyhedra_Library::Interval {
public:
  //! Constructs the universe interval \f$(-\infty, +\infty) = \Qset\f$.
  Interval();

  //! Returns <CODE>true</CODE> if and only if \p *this is empty.
  bool is_empty() const;

  //! Returns a const reference to the interval's lower bound.
  const LBoundary& lower_bound() const;

  //! Returns a const reference to the interval's upper bound.
  const UBoundary& upper_bound() const;

  //! \brief
  //! Raises the interval's lower bound, if \p new_lower is higher
  //! than the current one.
  void raise_lower_bound(LBoundary new_lower);

  //! \brief
  //! Lowers the interval's upper bound, if \p new_upper is lower
  //! than the current one.
  void lower_upper_bound(UBoundary new_upper);

  //! Turns \p *this into the empty interval.
  void set_empty();

  //! Checks if all the invariants are satisfied.
  bool OK() const;

private:
  //! The interval's lower bound.
  LBoundary lower;

  //! The interval's upper bound.
  UBoundary upper;
};

#include "Interval.inlines.hh"

#endif // !defined(PPL_Interval_defs_hh)


syntax highlighted by Code2HTML, v. 0.9.1