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

#ifndef CXSC_CDOT_HPP_INCLUDED
#define CXSC_CDOT_HPP_INCLUDED

#include <iostream>
#include <string>
#include "dot.hpp"
#include "complex.hpp"

namespace cxsc {

class cdotprecision
{
   private:
      // ---- Datenelemente ---------------------------------------
      dotprecision re,im;

   public:
      // ---- Constructors  ---------------------------------------
      cdotprecision() {}
      inline cdotprecision(const dotprecision&, const dotprecision&);
      inline cdotprecision(const real &, const real &);
      inline cdotprecision(const cdotprecision&);
      
//      explicit inline cdotprecision(int n)                   : re(n),im(0) { }
//      explicit inline cdotprecision(int a,int b)             : re(a),im(b) { }
//      explicit inline cdotprecision(long n)                   : re(n),im(0) { }
//      explicit inline cdotprecision(long a,long b)            : re(a),im(b) { }
//      explicit inline cdotprecision(const float &d)         : re(d),im(0) { }
//      explicit inline cdotprecision(const float &a, const float &b) : re(a),im(b) { }
//      explicit inline cdotprecision(const double &d)         : re(d),im(0) { }
//      explicit inline cdotprecision(const double &a, const double &b) : re(a),im(b) { }
      explicit inline cdotprecision(const real         &r)   : re(r), im(0) { }
      explicit inline cdotprecision(const complex      &c)   : re(Re(c)),im(Im(c)) { }
      explicit inline cdotprecision(const dotprecision &r)   : re(r), im(0) { }      
      
//      inline cdotprecision& operator= (const double & a)       { re=a;im=0; return *this; }
      inline cdotprecision& operator= (const real & a)         { re=a;im=0; return *this; }
      inline cdotprecision& operator= (const complex & a)      { re=Re(a),im=Im(a); return *this; }
//      inline cdotprecision& operator= (const int & a)          { re=a;im=0; return *this; }
      inline cdotprecision& operator= (const dotprecision & a) { re=a;im=0; return *this; }
      inline cdotprecision& operator= (const cdotprecision & a){ re=a.re,im=a.im; return *this; }

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

      // ---- Typwandlungen ----
      friend inline cdotprecision _cdotprecision(const dotprecision&);
      friend inline cdotprecision _cdotprecision(const real&);
      friend inline cdotprecision _cdotprecision(const complex&);
      friend inline cdotprecision _cdotprecision(const dotprecision&, const dotprecision&);
      friend inline cdotprecision _codtprecision(const real&,const real&);

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

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

      friend     inline cdotprecision operator +(const cdotprecision &,const cdotprecision &) throw();
      friend     inline cdotprecision operator -(const cdotprecision &,const cdotprecision &) throw();

      friend     inline cdotprecision operator +(const cdotprecision &,const complex &) throw();
      friend     inline cdotprecision operator +(const complex &,const cdotprecision &) throw();
      friend     inline cdotprecision operator -(const cdotprecision &,const complex &) throw();
      friend     inline cdotprecision operator -(const complex &,const cdotprecision &) throw();
      
      friend     inline cdotprecision operator +(const cdotprecision &,const dotprecision &) throw();
      friend     inline cdotprecision operator +(const dotprecision &,const cdotprecision &) throw();
      friend     inline cdotprecision operator -(const cdotprecision &,const dotprecision &) throw();
      friend     inline cdotprecision operator -(const dotprecision &,const cdotprecision &) throw();
      
      friend     inline cdotprecision operator +(const cdotprecision &,const real &) throw();
      friend     inline cdotprecision operator +(const real &,const cdotprecision &) throw();
      friend     inline cdotprecision operator -(const cdotprecision &,const real &) throw();
      friend     inline cdotprecision operator -(const real &,const cdotprecision &) throw();

      friend     inline cdotprecision & operator +=(cdotprecision &,const cdotprecision &) throw();
      friend     inline cdotprecision & operator -=(cdotprecision &,const cdotprecision &) throw();
      friend     inline cdotprecision & operator +=(cdotprecision &,const complex &) throw();
      friend     inline cdotprecision & operator -=(cdotprecision &,const complex &) throw();
      friend     inline cdotprecision & operator +=(cdotprecision &,const real &) throw();
      friend     inline cdotprecision & operator -=(cdotprecision &,const real &) throw();
      
      friend     inline cdotprecision & operator +=(cdotprecision &,const dotprecision &) throw();      
      friend     inline cdotprecision & operator -=(cdotprecision &,const dotprecision &) throw();

      // ---- Vergleichsop. ----

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

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

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

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

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

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

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


      friend inline bool operator !(const cdotprecision&) throw();
//                         operator void *(void) throw() { return (void *)(!!*this); }
      
      // ---- Funktionen    ----
      
      friend dotprecision & Re(cdotprecision& a)  throw() { return a.re; }
      friend dotprecision & Im(cdotprecision& a)  throw() { return a.im; }
      friend const dotprecision & Re(const cdotprecision& a)  throw() { return a.re; }
      friend const dotprecision & Im(const cdotprecision& a)  throw() { return a.im; }
      friend inline cdotprecision& SetRe (cdotprecision& a, const dotprecision& b)  throw();
      friend inline cdotprecision& SetIm (cdotprecision& a, const dotprecision& b) throw();
      
      friend inline cdotprecision conj(const cdotprecision &a) throw();

      friend void rnd(const cdotprecision &,complex &,rndtype = RND_NEXT) throw();
      friend void rnd(const cdotprecision &,complex &,complex &) throw();
      friend complex rnd(const cdotprecision &,rndtype = RND_NEXT) throw();
      
      friend        void accumulate  (cdotprecision&, const complex&, const complex&) throw();
      friend inline void accumulate  (cdotprecision&, const complex&, const real&) throw();
      friend inline void accumulate  (cdotprecision&, const real&, const complex&) throw();
      friend inline void accumulate  (cdotprecision&, const real&, const real&) throw();
};

//----------------------------------------------------------------------
// global verfuegbare CDotprecision Akku's   

#define MAXCDOTAKKU     (MAXDOTAKKU / 2)
extern cdotprecision cdotakku[MAXCDOTAKKU];
  
//----------------------------------------------------------------------

} // namespace cxsc 

#include "cdot.inl"

#endif 
