/*
**  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: l_real.hpp,v 1.3 2001/08/09 11:37:57 cxsc Exp $ */

#ifndef L_REAL_INCLUDED
#define L_REAL_INCLUDED

#include <iostream>
#include <string>

#include "dot.hpp"
#include "real.hpp"
#include "except.hpp"

namespace cxsc {

class l_interval;
class interval;

//
// stagprec:#reals pro l_real
//
extern int stagprec;

//----------------------------------------------------------------------------
// Klasse "l_real"
//
//   long reals
//

class l_real
{
   private:
      // ---- Datenelemente ----
      int   prec;
      real  *data;

   public:
      // ---- Konstruktoren ----
      l_real(void) throw();
      l_real(const l_real &) throw();
      

      l_real & operator =(const l_real &) throw();
      l_real & operator =(const real &) throw();
      l_real & operator =(const dotprecision &) throw();

      // ---- Destruktor    ----
      ~l_real(void) throw();

      // ---- Typwandlungen ----
      explicit l_real(int)          throw();
      explicit l_real(const real &) throw();
      explicit l_real(const dotprecision &) throw();
      
      friend real::real(const l_real &) throw();
      friend dotprecision::dotprecision(const l_real &) throw();
      friend dotprecision & dotprecision::operator =(const l_real &) throw();

      friend real         _real(const l_real & a) throw()         { return real(a); }
      friend l_real       _l_real(const real & a) throw()         { return l_real(a); }
      friend dotprecision _dotprecision(const l_real & a) throw() { return dotprecision(a); }
      friend l_real       _l_real(const dotprecision & a) throw() { return l_real(a); }
      friend l_interval   _unchecked_l_interval(const l_real &, const l_real &) throw();

      // The following are defined in the specific vector, matrix-files
#if(IndCheck) 
		explicit INLINE l_real(const l_rvector &)       throw (ERROR_LRVECTOR_TYPE_CAST_OF_THICK_OBJ,ERROR_LRVECTOR_USE_OF_UNINITIALIZED_OBJ);
      explicit INLINE l_real(const l_rvector_slice &) throw (ERROR_LRVECTOR_TYPE_CAST_OF_THICK_OBJ,ERROR_LRVECTOR_USE_OF_UNINITIALIZED_OBJ);
      explicit INLINE l_real(const l_rmatrix &)       throw (ERROR_LRMATRIX_TYPE_CAST_OF_THICK_OBJ,ERROR_LRMATRIX_USE_OF_UNINITIALIZED_OBJ);
      explicit INLINE l_real(const l_rmatrix_slice &) throw (ERROR_LRMATRIX_TYPE_CAST_OF_THICK_OBJ,ERROR_LRMATRIX_USE_OF_UNINITIALIZED_OBJ);
      friend INLINE real _l_real(const l_rvector &)       throw (ERROR_LRVECTOR_TYPE_CAST_OF_THICK_OBJ,ERROR_LRVECTOR_USE_OF_UNINITIALIZED_OBJ);
      friend INLINE real _l_real(const l_rvector_slice &) throw (ERROR_LRVECTOR_TYPE_CAST_OF_THICK_OBJ,ERROR_LRVECTOR_USE_OF_UNINITIALIZED_OBJ);
      friend INLINE real _l_real(const l_rmatrix &)       throw (ERROR_LRMATRIX_TYPE_CAST_OF_THICK_OBJ,ERROR_LRMATRIX_USE_OF_UNINITIALIZED_OBJ);
      friend INLINE real _l_real(const l_rmatrix_slice &) throw (ERROR_LRMATRIX_TYPE_CAST_OF_THICK_OBJ,ERROR_LRMATRIX_USE_OF_UNINITIALIZED_OBJ);
#else
		explicit INLINE l_real(const l_rvector &)       throw ();
      explicit INLINE l_real(const l_rvector_slice &) throw ();
      explicit INLINE l_real(const l_rmatrix &)       throw ();
      explicit INLINE l_real(const l_rmatrix_slice &) throw ();
      friend INLINE real _l_real(const l_rvector &)       throw ();
      friend INLINE real _l_real(const l_rvector_slice &) throw ();
      friend INLINE real _l_real(const l_rmatrix &)       throw ();
      friend INLINE real _l_real(const l_rmatrix_slice &) throw ();
#endif


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

      // ---- Standardfunkt ---- (arithmetische Operatoren)
      real&             operator[](int) const throw();

      friend     l_real operator -(const l_real& lr1) throw();
      friend     l_real operator +(const l_real& lr1) throw();

      friend     l_real operator +(const l_real &,const l_real &) throw();
      friend     l_real operator -(const l_real &,const l_real &) throw();
      friend     l_real operator *(const l_real &,const l_real &) throw();
      friend     l_real operator /(const l_real &,const l_real &) throw();
      friend inline l_interval operator |(const l_real &,const l_real &) throw();

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

      friend  dotprecision operator +(const l_real &,const dotprecision &) throw();
      friend  dotprecision operator +(const dotprecision &,const l_real &) throw();
      friend  dotprecision operator -(const l_real &,const dotprecision &) throw();
      friend  dotprecision operator -(const dotprecision &,const l_real &) throw();
      friend inline idotprecision operator |(const dotprecision &,const l_real &) throw();
      friend inline idotprecision operator |(const l_real &,const dotprecision &) throw();


      friend     l_real & operator +=(l_real &,const l_real &) throw();
      friend     l_real & operator -=(l_real &,const l_real &) throw();
      friend     l_real & operator *=(l_real &,const l_real &) throw();
      friend     l_real & operator /=(l_real &,const l_real &) throw();

      friend     l_real & operator +=(l_real &,const real &) throw();      
      friend     l_real & operator -=(l_real &,const real &) throw();
      friend     l_real & operator *=(l_real &,const real &) throw();      
      friend     l_real & operator /=(l_real &,const real &) throw();

      // ---- Zusaetzlich.. ----
      friend     real   & operator +=(real &,const l_real &) throw();
      friend     real   & operator -=(real &,const l_real &) throw();
      friend     real   & operator *=(real &,const l_real &) throw();
      friend     real   & operator /=(real &,const l_real &) throw();
      
      friend     inline dotprecision & operator +=(dotprecision &d,const l_real &lr) throw() { lr._akku_add(d); return d; }
      friend     inline dotprecision & operator -=(dotprecision &d,const l_real &lr) throw() { lr._akku_sub(d); return d; }

      // ---- Vergleichsop. ----
      friend bool operator ==(const l_real &,const l_real &) throw();
      friend bool operator !=(const l_real &,const l_real &) throw();
      friend bool operator  <(const l_real &,const l_real &) throw();
      friend bool operator  >(const l_real &,const l_real &) throw();
      friend bool operator <=(const l_real &,const l_real &) throw();
      friend bool operator >=(const l_real &,const l_real &) throw();

      friend bool operator ==(const real &,const l_real &) throw();
      friend bool operator !=(const real &,const l_real &) throw();
      friend bool operator  <(const real &,const l_real &) throw();
      friend bool operator  >(const real &,const l_real &) throw();
      friend bool operator <=(const real &,const l_real &) throw();
      friend bool operator >=(const real &,const l_real &) throw();

      friend bool operator ==(const l_real &,const real &) throw();
      friend bool operator !=(const l_real &,const real &) throw();
      friend bool operator  <(const l_real &,const real &) throw();
      friend bool operator  >(const l_real &,const real &) throw();
      friend bool operator <=(const l_real &,const real &) throw();
      friend bool operator >=(const l_real &,const real &) throw();

      friend bool operator ==(const dotprecision &,const l_real &) throw();
      friend bool operator !=(const dotprecision &,const l_real &) throw();
      friend bool operator  <(const dotprecision &,const l_real &) throw();
      friend bool operator  >(const dotprecision &,const l_real &) throw();
      friend bool operator <=(const dotprecision &,const l_real &) throw();
      friend bool operator >=(const dotprecision &,const l_real &) throw();

      friend bool operator ==(const l_real &,const dotprecision &) throw();
      friend bool operator !=(const l_real &,const dotprecision &) throw();
      friend bool operator  <(const l_real &,const dotprecision &) throw();
      friend bool operator  >(const l_real &,const dotprecision &) throw();
      friend bool operator <=(const l_real &,const dotprecision &) throw();
      friend bool operator >=(const l_real &,const dotprecision &) throw();

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

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

      friend bool operator ==(const idotprecision &,const l_real &) throw();
      friend bool operator !=(const idotprecision &,const l_real &) throw();
      friend bool operator  <(const idotprecision &,const l_real &) throw();
      friend bool operator  >(const idotprecision &,const l_real &) throw();
      friend bool operator <=(const idotprecision &,const l_real &) throw();
      friend bool operator >=(const idotprecision &,const l_real &) throw();

      friend bool operator ==(const l_real &,const idotprecision &) throw();
      friend bool operator !=(const l_real &,const idotprecision &) throw();
      friend bool operator  <(const l_real &,const idotprecision &) throw();
      friend bool operator  >(const l_real &,const idotprecision &) throw();
      friend bool operator <=(const l_real &,const idotprecision &) throw();
      friend bool operator >=(const l_real &,const idotprecision &) throw();


      friend bool operator!(const l_real& lr) throw();
//      operator void *() const throw() { if(*this!=0.) return (void *)1; else return 0; }      
      // ---- Funktionen    ----
      friend void accumulate(dotprecision&, const real&, const l_real&) throw();
      friend void accumulate(dotprecision&, const l_real&, const real&) throw();
      friend void accumulate(dotprecision&, const l_real&, const l_real&) throw();
      
      friend void accumulate(idotprecision&,const real&, const l_real&) throw();
      friend void accumulate(idotprecision&,const l_real&,const real&) throw();
      friend void accumulate(idotprecision&,const l_real&, const l_real&) throw();

      friend l_real   abs  (const l_real&) throw();
      friend int      sign (const l_real&) throw();
      friend int      StagPrec(const l_real&) throw();
      friend l_real   adjust(const l_real&) throw();

      // ---- Friends      -----
      
      friend inline l_real Inf(const l_interval &) throw();
      friend inline l_real Sup(const l_interval &) throw();
      friend        l_real mid(const l_interval &) throw();
   private:
      void _clear(int) throw(); // fuellt l_real ab Stelle p bis zum Ende mit Null.
      void _akku_out() throw(); // ein im dotakku[0] liegendes Zwischenergebnis wird in der entsprechenden Praezision in die aufrufende l_real Zahl gerundet.
      void _akku_add(dotprecision&) const throw(); // addiert aufrufenden l_real auf akku d.
      void _akku_sub(dotprecision&) const throw(); // subtrahiert aufrufenden l_real von akku d.
      inline real& elem(int i) const throw() {  return data[i-1];  }
};

} // namespace cxsc 

#endif

