// The template and inlines for the -*- C++ -*- complex number classes.

// Copyright (C) 1997-1999 Cygnus Solutions
//
// This file is part of the GNU ISO C++ Library.  This library 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, 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 General Public License for more details.

// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING.  If not, write to the Free
// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.

// As a special exception, you may use this file as part of a free software
// library without restriction.  Specifically, if other files instantiate
// templates or use macros or inline functions from this file, or you compile
// this file and link it with other files to produce an executable, this
// file does not by itself cause the resulting executable to be covered by
// the GNU General Public License.  This exception does not however
// invalidate any other reasons why the executable file might be covered by
// the GNU General Public License.

// Note: this is not a conforming implementation.

#ifndef _CPP_COMPLEX
#define _CPP_COMPLEX	1

#include <bits/c++config.h>
#include <bits/std_iosfwd.h>


namespace std {

  // 26.2.2  Template class complex
  template <class T>
  class complex
  {
  public:
    typedef T value_type;

  public:
    complex (const T &__re = T (), const T &__im = T ());
    complex (const complex &__z);
    template <class X> complex (const complex<X> &z);

    T real () const;
    T imag () const;

    complex<T> &operator= (const T &__z);
    complex<T> &operator+= (const T &__z);
    complex<T> &operator-= (const T &__z);
    complex<T> &operator*= (const T &__z);
    complex<T> &operator/= (const T &__z);

    complex &operator= (const complex &__z);

    template <class X> complex<T> &operator= (const complex<X> &__z);
    template <class X> complex<T> &operator+= (const complex<X> &__z);
    template <class X> complex<T> &operator-= (const complex<X> &__z);
    template <class X> complex<T> &operator*= (const complex<X> &__z);
    template <class X> complex<T> &operator/= (const complex<X> &__z);
  };


  // 26.2.3  complex specializations
  class complex<float>
  {
  public:
    typedef float value_type;

    // This is a non-standard convenient definition.
    typedef __complex__ float __complex_value_type;

  private:
    __complex_value_type __val;

  public:
    // These are non-standard members for a more efficient implementation.
    __complex_value_type __value () const { return __val; }
    complex (__complex_value_type __x) : __val (__x) { }


    complex (const float &__re = 0.0f, const float &__im = 0.0f)
    {
      __real__ __val = __re;
      __imag__ __val = __im;
    }
    complex (const complex &__z) : __val (__z.__value ()) { }
    template <class X> complex (const complex<X> &__z)
      : __val (__z.__value ()) { }

    float real () const { return __real__ __val; }
    float imag () const { return __imag__ __val; }

    complex<float> &operator= (const float &__z)
    {
      __real__ __val = __z;
      __imag__ __val = 0;
      return *this;
    }
    complex<float> &operator+= (const float &__z)
    {
      __real__ __val += __z;
      return *this;
    }
    complex<float> &operator-= (const float &__z)
    {
      __real__ __val -= __z;
      return *this;
    }
    complex<float> &operator*= (const float &__z)
    {
      __real__ __val *= __z;
      __imag__ __val *= __z;
      return *this;
    }
    complex<float> &operator/= (const float &__z)
    {
      __real__ __val /= __z;
      __imag__ __val /= __z;
      return *this;
    }

    complex &operator= (const complex &__z)
    {
      __val = __z.__value ();
      return *this;
    }

    template <class X>
    complex<float> &operator= (const complex<X> &__z)
    {
      __val = __complex_value_type (__z.__value ());
      return *this;
    }
    template <class X>
    complex<float> &operator+= (const complex<X> &__z)
    {
      __val += __complex_value_type (__z.__value ());
      return *this;
    }
    template <class X>
    complex<float> &operator-= (const complex<X> &__z)
    {
      __val -= __complex_value_type (__z.__value ());
      return *this;
    }
    template <class X>
    complex<float> &operator*= (const complex<X> &__z)
    {
      __val *= __complex_value_type (__z.__value ());
      return *this;
    }
    template <class X>
    complex<float> &operator/= (const complex<X> &__z)
    {
      __val /= __complex_value_type (__z.__value ());
      return *this;
    }
  };

  class complex<double>
  {
  public:
    typedef double value_type;

    // This is a non-standard convenient definition.
    typedef __complex__ double __complex_value_type;

  private:
    __complex_value_type __val;

  public:
    // These are non-standard members for a more efficient implementation.
    __complex_value_type __value () const { return __val; }
    complex (__complex_value_type __x) : __val (__x) { }


    complex (const double &__re = 0.0, const double &__im = 0.0)
      { __real__ __val = __re; __imag__ __val = __im; }
    complex (const complex &__z) : __val (__z.__value ()) { }
    template <class X> complex (const complex<X> &__z)
      : __val (__z.__value ()) { }

    double real () const { return __real__ __val; }
    double imag () const { return __imag__ __val; }

    complex<double> &operator= (const double &__z)
    {
      __real__ __val = __z;
      __imag__ __val = 0;
      return *this;
    }
    complex<double> &operator+= (const double &__z)
    {
      __real__ __val += __z;
      return *this;
    }
    complex<double> &operator-= (const double &__z)
    {
      __real__ __val -= __z;
      return *this;
    }
    complex<double> &operator*= (const double &__z)
    {
      __val *= __z;
      return *this;
    }
    complex<double> &operator/= (const double &__z)
    {
      __val /= __z;
      return *this;
    }

    complex &operator= (const complex &__z)
    {
      __val = __z.__value ();
      return *this;
    }

    template <class X> complex<double> &operator= (const complex<X> &__z)
    {
      __val = __complex_value_type (__z.__value ());
      return *this;
    }
    template <class X> complex<double> &operator+= (const complex<X> &__z)
    {
      __val += __complex_value_type (__z.__value ());
      return *this;
    }
    template <class X> complex<double> &operator-= (const complex<X> &__z)
    {
      __val -= __complex_value_type (__z.__value ());
      return *this;
    }
    template <class X> complex<double> &operator*= (const complex<X> &__z)
    {
      __val *= __complex_value_type (__z.__value ());
      return *this;
    }
    template <class X> complex<double> &operator/= (const complex<X> &__z)
    {
      __val /= __complex_value_type (__z.__value ());
      return *this;
    }
  };

  class complex<long double>
  {
  public:
    typedef long double value_type;

    // This is a non-standard convenient definition.
    typedef __complex__ long double __complex_value_type;

  private:
    __complex_value_type __val;

  public:
    // These are non-standard members for a more efficient implementation.
    __complex_value_type __value () const { return __val; }
    complex (__complex_value_type __x) : __val (__x) { }


    complex (const long double &__re = 0.0L, const long double &__im = 0.0L)
      { __real__ __val = __re; __imag__ __val = __im; }
    complex (const complex &__z) : __val (__z.__value ()) { }
    template <class X> complex (const complex<X> &__z)
      : __val (__z.__value ()) { }

    long double real () const { return __real__ __val; }
    long double imag () const { return __imag__ __val; }

    complex<long double> &operator= (const long double &__z)
    {
      __real__ __val = __z;
      __imag__ __val = 0;
      return *this;
    }
    complex<long double> &operator+= (const long double &__z)
    {
      __real__ __val += __z;
      return *this;
    }
    complex<long double> &operator-= (const long double &__z)
    {
      __real__ __val -= __z;
      return *this;
    }
    complex<long double> &operator*= (const long double &__z)
    {
      __val *= __z;
      return *this;
    }
    complex<long double> &operator/= (const long double &__z)
    {
      __val /= __z;
      return *this;
    }

    complex &operator= (const complex &__z)
    {
      __val = __z.__value ();
      return *this;
    }

    template <class X>
    complex<long double> &operator= (const complex<X> &__z)
    {
      __val = __complex_value_type (__z.__value ());
      return *this;
    }
    template <class X>
    complex<long double> &operator+= (const complex<X> &__z)
    {
      __val += __complex_value_type (__z.__value ());
      return *this;
    }
    template <class X>
    complex<long double> &operator-= (const complex<X> &__z)
    {
      __val -= __complex_value_type (__z.__value ());
      return *this;
    }
    template <class X>
    complex<long double> &operator*= (const complex<X> &__z)
    {
      __val *= __complex_value_type (__z.__value ());
      return *this;
    }
    template <class X>
    complex<long double> &operator/= (const complex<X> &__z)
    {
      __val /= __complex_value_type (__z.__value ());
      return *this;
    }
  };


  // Operators:
  template <class T>
  complex<T>
  operator+ (const complex<T> &__x, const complex<T> &__y)
  {
    return complex<T> (__x) += __y;
  }

  template <class T>
  complex<T>
  operator+ (const complex<T> &__x, const T &__y)
  {
    return complex<T> (__x) += __y;
  }

  template <class T>
  complex<T>
  operator+ (const T &__x, const complex<T> &__y)
  {
    return complex<T> (__y) += __x;
  }

  template <class T>
  complex<T>
  operator- (const complex<T> &__x, const complex<T> &__y)
  {
    return complex<T> (__x) -= __y;
  }

  template <class T>
  complex<T>
  operator- (const complex<T> &__x, const T &__y)
  {
    return complex<T> (__x) -= __y;
  }

  template <class T>
  complex<T>
  operator- (const T &__x, const complex<T> &__y)
  {
    return complex<T> (__x) -= __y;
  }

  template <class T>
  complex<T>
  operator* (const complex<T> &__x, const complex<T> &__y)
  {
    return complex<T> (__x) *= __y;
  }

  template <class T>
  complex<T>
  operator* (const complex<T> &__x, const T &__y)
  {
    return complex<T> (__x) *= __y;
  }

  template <class T>
  complex<T>
  operator* (const T &__x, const complex<T> &__y)
  {
    return complex<T> (__y) *= __x;
  }

  template <class T>
  complex<T>
  operator/ (const complex<T> &__x, const complex<T> &__y)
  {
    return complex<T> (__x) /= __y;
  }

  template <class T>
  complex<T>
  operator/ (const complex<T> &__x, const T &__y)
  {
    return complex<T> (__x) /= __y;
  }

  template <class T>
  complex<T>
  operator/ (const T &__x, const complex<T> &__y)
  {
    return complex<T> (__x) /= __y;
  }

  template <class T>
  complex<T>
  operator+ (const complex<T> &__x)
  {
    return __x;
  }

  template <class T>
  complex<T>
  operator- (const complex<T> &__x)
  {
    return complex<T> (-real (__x), -imag (__x));
  }

  template <class T>
  bool
  operator== (const complex<T> &__x, const complex<T> &__y)
  {
    return real (__x) == real (__y) && imag (__x) == imag (__y);
  }

  template <class T>
  bool
  operator== (const complex<T> &__x, const T &__y)
  {
    return real (__x) == __y && imag (__x) == 0;
  }

  template <class T>
  bool
  operator== (const T &__x, const complex<T> &__y)
  {
    return __x == real (__y) && 0 == imag (__y);
  }

  template <class T>
  bool
  operator!= (const complex<T> &__x, const complex<T> &__y)
  {
    return real (__x) != real (__y) || imag (__x) != imag (__y);
  }

  template <class T>
  bool
  operator!= (const complex<T> &__x, const T &__y)
  {
    return real (__x) != __y || imag (__x) != 0;
  }

  template <class T>
  bool
  operator!= (const T &__x, const complex<T> &__y)
  {
    return __x != real (__y) || 0 != imag (__y);
  }

  template <class T, class charT, class traits>
  basic_istream <charT, traits> &
  operator>> (basic_istream<charT, traits> &__is, complex<T> &__x);

  template <class T, class charT, class traits>
  basic_ostream<charT, traits> &
  operator<< (basic_ostream<charT, traits> &__os, const complex<T> &__x);


  // Values:
  template <class T>
  T
  real (const complex<T> &__x)
  {
    return __x.real ();
  }

  template <class T>
  T
  imag (const complex<T> &__x)
  {
    return __x.imag ();
  }

  template <class T>
  T
  abs (const complex<T> &__x);

  template <class T>
  T
  arg (const complex<T> &__x);

  template <class T>
  T
  norm (const complex<T> &__x)
  {
    // Please note that we don't loose accuracy here.
    return real (__x) * real (__x) + imag (__x) * imag (__x);
  }

  template <class T>
  complex<T>
  conj (const complex<T> &__x);

  template <class T>
  complex<T>
  polar (const T &__rho, const T &__theta);


  // Transcendentals:
  template <class T> complex<T> cos (const complex<T> &__x);
  template <class T> complex<T> cosh (const complex<T> &__x);
  template <class T> complex<T> exp (const complex<T> &__x);
  template <class T> complex<T> log (const complex<T> &__x);
  template <class T> complex<T> log10 (const complex<T> &__x);
  template <class T> complex<T> pow (const complex<T> &__x, int __n);
  template <class T> complex<T> pow (const complex<T> &__x, const T &__y);
  template <class T> complex<T> pow (const complex<T> &__x,
				     const complex<T> &__y);
  template <class T> complex<T> pow (const T &__x, const complex<T> &__y);
  template <class T> complex<T> sin (const complex<T> &__x);
  template <class T> complex<T> sinh (const complex<T> &__x);
  template <class T> complex<T> sqrt (const complex<T> &__x);
  template <class T> complex<T> tan (const complex<T> &__x);
  template <class T> complex<T> tanh (const complex<T> &__x);


  // We use here a few more specializations.
  inline complex<float>
  conj (const complex<float> &__x)
  {
    return complex<float> (~__x.__value ());
  }

  inline complex<double>
  conj (const complex<double> &__x)
  {
    return complex<double> (~__x.__value ());
  }

  inline complex<long double>
  conj (const complex<long double> &__x)
  {
    return complex<long double> (~__x.__value ());
  }

} // namespace std

#endif	/* _CPP_COMPLEX */
