/*
**  CXSC is a C++ library for eXtended Scientific Computing
**
**  Copyright (C) 1990-2000 Institut fuer Angewandte Mathematik,
**                          Universitaet Karlsruhe, Germany
**            (C) 2000-2001 Wiss. Rechnen/Softwaretechnologie
**                          Universitaet Wuppertal, Germany   
**
**  This library is free software; you can redistribute it and/or
**  modify it under the terms of the GNU Library General Public
**  License as published by the Free Software Foundation; either
**  version 2 of the License, or (at your option) any later version.
**
**  This library 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
**  Library General Public License for more details.
**
**  You should have received a copy of the GNU Library General Public
**  License along with this library; if not, write to the Free
**  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

/* CVS $Id: interval.hpp,v 1.3 2001/08/09 11:37:55 cxsc Exp $ */

#ifndef INTERVAL_H_INCLUDED
#define INTERVAL_H_INCLUDED

#include <iostream>
#include <string>
#include "real.hpp"
#include "except.hpp"

namespace cxsc {

class ivector;
class ivector_slice;
class imatrix;
class imatrix_slice;

class interval
{
   private:
      // ---- Datenelemente ---------------------------------------
      real inf;
      real sup;

   public:
      // ---- Konstruktoren ---------------------------------------
      interval() {}
      inline interval(const real&, const real&) throw(ERROR_INTERVAL_EMPTY_INTERVAL);
      inline interval& operator= (const real& a);
      
      // ---- Typecasts     ---------------------------------------
      
      explicit inline interval(const real &r) throw() :inf(r),sup(r) { }
      
      friend inline interval _interval(const real & r) throw()                            { return interval(r); }
      friend inline interval _interval(const real & a, const real & b) throw(ERROR_INTERVAL_EMPTY_INTERVAL) { return interval(a,b); }
      friend inline interval _unchecked_interval(const real&, const real&);

#if(IndCheck)
      explicit INLINE interval(const ivector &) throw(ERROR_IVECTOR_TYPE_CAST_OF_THICK_OBJ,ERROR_IVECTOR_USE_OF_UNINITIALIZED_OBJ);      
      explicit INLINE interval(const ivector_slice &) throw(ERROR_IVECTOR_TYPE_CAST_OF_THICK_OBJ,ERROR_IVECTOR_USE_OF_UNINITIALIZED_OBJ);      
      explicit INLINE interval(const imatrix &m) throw(ERROR_IMATRIX_TYPE_CAST_OF_THICK_OBJ,ERROR_IMATRIX_USE_OF_UNINITIALIZED_OBJ);
      explicit INLINE interval(const imatrix_slice &m) throw(ERROR_IMATRIX_TYPE_CAST_OF_THICK_OBJ,ERROR_IMATRIX_USE_OF_UNINITIALIZED_OBJ);
      friend INLINE interval _interval(const ivector &) throw(ERROR_IVECTOR_TYPE_CAST_OF_THICK_OBJ,ERROR_IVECTOR_USE_OF_UNINITIALIZED_OBJ);      
      friend INLINE interval _interval(const ivector_slice &) throw(ERROR_IVECTOR_TYPE_CAST_OF_THICK_OBJ,ERROR_IVECTOR_USE_OF_UNINITIALIZED_OBJ);      
      friend INLINE interval _interval(const imatrix &m) throw(ERROR_IMATRIX_TYPE_CAST_OF_THICK_OBJ,ERROR_IMATRIX_USE_OF_UNINITIALIZED_OBJ);
      friend INLINE interval _interval(const imatrix_slice &m) throw(ERROR_IMATRIX_TYPE_CAST_OF_THICK_OBJ,ERROR_IMATRIX_USE_OF_UNINITIALIZED_OBJ);
#else
      explicit INLINE interval(const ivector &) throw();
      explicit INLINE interval(const ivector_slice &) throw();
      explicit INLINE interval(const imatrix &m) throw();
      explicit INLINE interval(const imatrix_slice &m) throw();
      friend INLINE interval _interval(const ivector &) throw();
      friend INLINE interval _interval(const ivector_slice &) throw();
      friend INLINE interval _interval(const imatrix &m) throw();
      friend INLINE interval _interval(const imatrix_slice &m) throw();
#endif
      explicit        interval(const l_real &) throw();     // in l_real.cpp
                      interval(const l_real &,const l_real &) throw(ERROR_INTERVAL_EMPTY_INTERVAL);
      explicit        interval(const l_interval &) throw(); // in l_interv.cpp
      explicit        interval(const dotprecision &) throw(); 
                      interval(const dotprecision &,const dotprecision &) throw(ERROR_INTERVAL_EMPTY_INTERVAL);
      explicit        interval(const idotprecision &) throw();
      
      friend inline interval _interval(const l_real &a) throw(); // in l_interv.inl
      friend inline interval _interval(const l_real &a,const l_real &b) throw(ERROR_INTERVAL_EMPTY_INTERVAL) { return interval(a,b); }
      friend        interval _interval(const l_interval &a) throw(); // in l_interv.inl
      friend inline interval _interval(const dotprecision &a) throw() { return interval(a); } 
      friend inline interval _interval(const dotprecision &a,const dotprecision &b) throw(ERROR_INTERVAL_EMPTY_INTERVAL) { return interval(a,b); }
      friend inline interval _interval(const idotprecision &a) throw() { return interval(a); }
      
      // interval & operator= (const interval& a); Default passt
      interval & operator =(const l_real &) throw();
      interval & operator =(const l_interval &) throw();
      interval & operator =(const dotprecision &) throw();      
      interval & operator =(const idotprecision &) throw();

      // ---- Destruktor    ----
      // ~interval() {} unnoetig

      // ---- Typwandlungen ----
      
      // ---- Ausgabefunkt. ---------------------------------------
      friend std::istream& operator >> (std::istream& s, interval& a)       throw();
      friend std::ostream& operator << (std::ostream& s, const interval& a) throw();
      friend std::string & operator >> (std::string&  s, interval& a)       throw();
      friend std::string & operator << (std::string&  s, const interval& a) throw();
      friend void          operator >> (const std::string& s,interval &a)   throw();
      friend void          operator >> (const char *       s,interval &a)   throw();      

      // ---- Standardfunkt ---- (arithmetische Operatoren)
      friend     inline interval operator -(const interval &) throw();
      friend     inline interval operator +(const interval &) throw();

      friend     interval operator +(const interval &,const interval &) throw();
      friend     interval operator -(const interval &,const interval &) throw();
      friend     interval operator *(const interval &,const interval &) throw();
      friend     interval operator /(const interval &,const interval &) throw();
      friend     inline interval operator |(const interval &,const interval &) throw();
      friend     inline interval operator &(const interval &,const interval &) throw(ERROR_INTERVAL_EMPTY_INTERVAL);

      friend     interval operator +(const interval &,const real &) throw();
      friend     interval operator +(const real &,const interval &) throw();
      friend     interval operator -(const interval &,const real &) throw();
      friend     interval operator -(const real &,const interval &) throw();
      friend     interval operator *(const interval &,const real &) throw();
      friend     interval operator *(const real &,const interval &) throw();
      friend     interval operator /(const interval &,const real &) throw();
      friend     interval operator /(const real &,const interval &) throw();
      friend     inline interval operator |(const real &,const interval &) throw();
      friend     inline interval operator |(const interval &,const real &) throw();
      friend     inline interval operator |(const real &,const real &)     throw();
      friend     inline interval operator &(const real &,const interval &) throw(ERROR_INTERVAL_EMPTY_INTERVAL);
      friend     inline interval operator &(const interval &,const real &) throw(ERROR_INTERVAL_EMPTY_INTERVAL);


      friend     inline idotprecision operator +(const idotprecision &,const interval &) throw();
      friend     inline idotprecision operator +(const interval &,const idotprecision &) throw();
      friend     inline idotprecision operator -(const idotprecision &,const interval &) throw();
      friend     inline idotprecision operator -(const interval &,const idotprecision &) throw();
      friend     inline idotprecision operator |(const interval &,const idotprecision &) throw();
      friend     inline idotprecision operator |(const idotprecision &,const interval &) throw();
      friend     inline idotprecision operator &(const interval &,const idotprecision &) throw(ERROR_IDOTPRECISION_EMPTY_INTERVAL);
      friend     inline idotprecision operator &(const idotprecision &,const interval &) throw(ERROR_IDOTPRECISION_EMPTY_INTERVAL);
 
      friend     inline interval & operator +=(interval &,const interval &) throw();
      friend     inline interval & operator -=(interval &,const interval &) throw();
      friend     inline interval & operator *=(interval &,const interval &) throw();
      friend     inline interval & operator /=(interval &,const interval &) throw();
      friend     inline interval & operator |=(interval &,const interval &) throw();
      friend     inline interval & operator &=(interval &,const interval &) throw(ERROR_INTERVAL_EMPTY_INTERVAL);

      friend     inline interval & operator +=(interval &,const real &) throw();      
      friend     inline interval & operator -=(interval &,const real &) throw();
      friend     inline interval & operator *=(interval &,const real &) throw();              friend     inline interval & operator /=(interval &,const real &) throw(); 
      friend     inline interval & operator |=(interval &,const real &) throw();
      friend     inline interval & operator &=(interval &,const real &) throw(ERROR_INTERVAL_EMPTY_INTERVAL);
 
      // ---- Vergleichsop. ----

      friend inline bool operator ==(const interval &,const interval &) throw();
      friend inline bool operator !=(const interval &,const interval &) throw();

      friend inline bool operator !(const interval &) throw();
//             inline      operator void*(void) const throw() { return (void*)(!(!*this)); } 

      friend inline bool operator ==(const real &,const interval &) throw();
      friend inline bool operator !=(const real &,const interval &) throw();

      friend inline bool operator ==(const interval &,const real &) throw();
      friend inline bool operator !=(const interval &,const real &) throw();

      friend        bool operator ==(const dotprecision &,const interval &) throw();
      friend        bool operator !=(const dotprecision &,const interval &) throw();

      friend        bool operator ==(const interval &,const dotprecision &) throw();
      friend        bool operator !=(const interval &,const dotprecision &) throw();

      friend inline bool operator ==(const int &,const interval &) throw();
      friend inline bool operator !=(const int &,const interval &) throw();

      friend inline bool operator ==(const interval &,const int &) throw();
      friend inline bool operator !=(const interval &,const int &) throw();

      // ---- Mengenvergle. ----

      friend inline bool operator  <(const interval &,const interval &) throw();
      friend inline bool operator  >(const interval &,const interval &) throw();
      friend inline bool operator <=(const interval &,const interval &) throw();
      friend inline bool operator >=(const interval &,const interval &) throw();

      friend inline bool operator  <(const real &,const interval &) throw();
      friend inline bool operator  >(const real &,const interval &) throw() { return false; }
      friend inline bool operator <=(const real &,const interval &) throw();
      friend inline bool operator >=(const real &,const interval &) throw();

      friend inline bool operator  <(const interval &,const real &) throw() { return false; }
      friend inline bool operator  >(const interval &,const real &) throw();
      friend inline bool operator <=(const interval &,const real &) throw();
      friend inline bool operator >=(const interval &,const real &) throw();

      friend        bool operator  <(const dotprecision &,const interval &) throw();
      friend        bool operator  >(const dotprecision &,const interval &) throw() { return false; }
      friend        bool operator <=(const dotprecision &,const interval &) throw();
      friend        bool operator >=(const dotprecision &,const interval &) throw();

      friend        bool operator  <(const interval &,const dotprecision &) throw() { return false; }
      friend        bool operator  >(const interval &,const dotprecision &) throw();
      friend        bool operator <=(const interval &,const dotprecision &) throw();
      friend        bool operator >=(const interval &,const dotprecision &) throw();

      // ---- Funktionen    ----
      
      friend inline       real & Inf (interval& a)       throw() { return a.inf; }
      friend inline const real & Inf (const interval &a) throw() { return a.inf; }
      friend inline       real & Sup (interval& a)       throw() { return a.sup; }
      friend inline const real & Sup (const interval &a) throw() { return a.sup; }
      
      friend inline interval& SetInf (interval& a, const real& b)  throw() {a.inf=b; return a;}
      friend inline interval& SetSup (interval& a, const real& b) throw()  {a.sup=b; return a;}
      friend inline interval& UncheckedSetInf (interval& a, const real& b) throw() { a.inf=b; return a;}
      friend inline interval& UncheckedSetSup (interval& a, const real& b) throw() { a.sup=b; return a;}

      friend inline bool IsEmpty (const interval& a) throw();

      friend inline interval abs  (const interval& a) throw();
      friend        real     mid  (const interval& a) throw();
      friend inline real     diam (const interval& a) throw();
};

} // namespace cxsc 

#include "interval.inl"

#endif

