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

#ifndef COMPLEX_HPP_INCLUDED
#define COMPLEX_HPP_INCLUDED

#include <iostream>
#include <string>

#include "compiler.h"
#include "except.hpp"
#include "real.hpp"

namespace cxsc {

class cvector;
class cmatrix;
class cvector_slice;
class cmatrix_slice;

class complex
{
   private:
      // ---- Datenelemente ---------------------------------------
      real  re;
      real  im;

   public:
      // ---- Constructors  ---------------------------------------
      complex(void)  throw ()           {}
      complex(const real & a,const real & b) throw () : re(a), im(b) { }
      
      inline complex & operator= (const real & r) throw();

      // ---- Type-Casts    ---------------------------------------

      explicit inline complex(const real &r) throw() : re(r),im(0.0)     { }


      friend inline complex _complex(const real &a) throw ()             { return complex(a,0.0); }
      friend inline complex _complex(const real &a,const real &b) throw(){ return complex(a,b); }


      // The following are defined in the specific vector, matrix-files
#if(IndCheck) 
		explicit INLINE complex(const cvector &)       throw (ERROR_CVECTOR_TYPE_CAST_OF_THICK_OBJ,ERROR_CVECTOR_USE_OF_UNINITIALIZED_OBJ);
      explicit INLINE complex(const cvector_slice &) throw (ERROR_CVECTOR_TYPE_CAST_OF_THICK_OBJ,ERROR_CVECTOR_USE_OF_UNINITIALIZED_OBJ);
      explicit INLINE complex(const cmatrix &)       throw (ERROR_CMATRIX_TYPE_CAST_OF_THICK_OBJ,ERROR_CMATRIX_USE_OF_UNINITIALIZED_OBJ);
      explicit INLINE complex(const cmatrix_slice &) throw (ERROR_CMATRIX_TYPE_CAST_OF_THICK_OBJ,ERROR_CMATRIX_USE_OF_UNINITIALIZED_OBJ);
		friend INLINE complex _complex(const cvector &)       throw (ERROR_CVECTOR_TYPE_CAST_OF_THICK_OBJ,ERROR_CVECTOR_USE_OF_UNINITIALIZED_OBJ);
      friend INLINE complex _complex(const cvector_slice &) throw (ERROR_CVECTOR_TYPE_CAST_OF_THICK_OBJ,ERROR_CVECTOR_USE_OF_UNINITIALIZED_OBJ);
      friend INLINE complex _complex(const cmatrix &)       throw (ERROR_CMATRIX_TYPE_CAST_OF_THICK_OBJ,ERROR_CMATRIX_USE_OF_UNINITIALIZED_OBJ);
      friend INLINE complex _complex(const cmatrix_slice &) throw (ERROR_CMATRIX_TYPE_CAST_OF_THICK_OBJ,ERROR_CMATRIX_USE_OF_UNINITIALIZED_OBJ);
#else
		explicit INLINE complex(const cvector &)       throw ();
      explicit INLINE complex(const cvector_slice &) throw ();
      explicit INLINE complex(const cmatrix &)       throw ();
      explicit INLINE complex(const cmatrix_slice &) throw ();
      friend INLINE complex _complex(const cvector &)       throw ();
      friend INLINE complex _complex(const cvector_slice &) throw ();
      friend INLINE complex _complex(const cmatrix &)       throw ();
      friend INLINE complex _complex(const cmatrix_slice &) throw ();
#endif
      explicit        complex(const cdotprecision &) throw();
      friend inline complex _complex(const cdotprecision &a) throw() { return complex(a); }
      
      complex & operator =(const cdotprecision &) throw();

      // ---- Input/Output  ---------------------------------------
      friend std::ostream & operator <<(std::ostream &,const complex &) throw();
      friend std::istream & operator >>(std::istream &,complex &)       throw();
      friend std::string &  operator <<(std::string &,const complex &)  throw();
      friend std::string &  operator >>(std::string &,complex &)        throw();
      friend void           operator >>(const char *,complex &)         throw();
      friend void           operator >>(const std::string &,complex &)  throw();

      // ---- Std.Operators ---------------------------------------
      friend inline complex operator -(const complex &) throw ();
      friend inline complex operator +(const complex &) throw ();

      friend inline complex operator +(const complex &,const complex &) throw();
      friend inline complex operator -(const complex &,const complex &) throw();
      friend        complex operator *(const complex &,const complex &) throw();
      friend        complex operator /(const complex &,const complex &) throw();

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

      friend inline complex operator +(const complex &,const real &) throw();
      friend inline complex operator +(const real &,const complex &) throw();
      friend inline complex operator -(const complex &,const real &) throw();
      friend inline complex operator -(const real &,const complex &) throw();
      friend inline complex operator *(const complex &,const real &) throw();
      friend inline complex operator *(const real &,const complex &) throw();
      friend inline complex operator /(const complex &,const real &) throw();
      friend inline complex operator /(const real &,const complex &) throw();

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

      // ---- Comp.Operat.  ---------------------------------------
//             inline       operator void *() const throw() { if(re) return (void *)1; if(im) return (void *)1; else return 0; }
      friend inline bool operator!  (const complex & a)                    throw();
      friend inline bool operator== (const complex & a, const complex & b) throw();
      friend inline bool operator!= (const complex & a, const complex & b) throw();
      friend inline bool operator== (const complex & a, const real & b)    throw();
      friend inline bool operator== (const real & a, const complex & b)    throw();
      friend inline bool operator!= (const complex & a, const real & b)    throw();
      friend inline bool operator!= (const real & a, const complex & b)    throw();
      
      friend        bool operator== (const complex & a, const dotprecision & b)    throw();
      friend        bool operator== (const dotprecision & a, const complex & b)    throw();
      friend        bool operator!= (const complex & a, const dotprecision & b)    throw();
      friend        bool operator!= (const dotprecision & a, const complex & b)    throw();

      // ---- Others   -------------------------------------------
      friend real & Re(complex & a) { return a.re; }
      friend real   Re(const complex & a) { return a.re; }
      friend real & Im(complex & a) { return a.im; }
      friend real   Im(const complex & a) { return a.im; }
      
      friend complex & SetRe(complex & a,const real & b) { a.re=b; return a; }
      friend complex & SetIm(complex & a,const real & b) { a.im=b; return a; } 

      friend        real abs(complex) throw();
      friend        real abs2(const complex &) throw();
      friend inline complex conj(const complex &) throw();
};


} // namespace cxsc 

#include "complex.inl"

#endif



