#ifndef __STD_COMPLEX
#define __STD_COMPLEX
//
//
//  Copyright Digital Equipment Corporation 1996. All rights reserved.
//
//  Restricted Rights: Use, duplication, or disclosure by the U.S.
//  Government is subject to restrictions as set forth in subparagraph
//  (c) (1) (ii) of DFARS 252.227-7013, or in FAR 52.227-19, or in FAR
//  52.227-14 Alt. III, as applicable.
//
//  This software is proprietary to and embodies the confidential
//  technology of Digital Equipment Corporation. Possession, use, or
//  copying of this software and media is authorized only pursuant to a
//  valid written license from Digital or an authorized sublicensor.
//
//

/***************************************************************************
 *
 * complex - Declaration for the Standard Library complex class
 *
 * $Id: complex,v 1.99 1996/09/27 07:49:07 smithey Exp $
 *
 ***************************************************************************
 *
 * (c) Copyright 1994-1996 Rogue Wave Software, Inc.
 * ALL RIGHTS RESERVED
 *
 * The software and information contained herein are proprietary to, and
 * comprise valuable trade secrets of, Rogue Wave Software, Inc., which
 * intends to preserve as trade secrets such software and information.
 * This software is furnished pursuant to a written license agreement and
 * may be used, copied, transmitted, and stored only in accordance with
 * the terms of such license and with the inclusion of the above copyright
 * notice.  This software and information or any other copies thereof may
 * not be provided or otherwise made available to any other person.
 *
 * Notwithstanding any other lease or license that may pertain to, or
 * accompany the delivery of, this computer software and information, the
 * rights of the Government regarding its use, reproduction and disclosure
 * are as set forth in Section 52.227-19 of the FARS Computer
 * Software-Restricted Rights clause.
 * 
 * Use, duplication, or disclosure by the Government is subject to
 * restrictions as set forth in subparagraph (c)(1)(ii) of the Rights in
 * Technical Data and Computer Software clause at DFARS 252.227-7013.
 * Contractor/Manufacturer is Rogue Wave Software, Inc.,
 * P.O. Box 2328, Corvallis, Oregon 97339.
 *
 * This computer software and information is distributed with "restricted
 * rights."  Use, duplication or disclosure is subject to restrictions as
 * set forth in NASA FAR SUP 18-52.227-79 (April 1985) "Commercial
 * Computer Software-Restricted Rights (April 1985)."  If the Clause at
 * 18-52.227-74 "Rights in Data General" is specified in the contract,
 * then the "Alternate III" clause applies.
 *
 **************************************************************************/

#include <stdcomp>
#include <stddefs>
#include <math.h>

#ifndef _RWSTD_HEADER_REQUIRES_HPP
#include <utility>
#else
#include <utility.hpp>
#endif

#ifndef __USE_STD_IOSTREAM
#include <iostream.h>
#else
#include <iostream>
#endif

#if defined(__DECCXX)
#   ifdef __PRAGMA_ENVIRONMENT
#      pragma __environment __save
#      pragma __environment __header_defaults
#   endif
#endif

#ifndef _RWSTD_NO_NAMESPACE 
namespace std {
#endif

#ifdef _RWSTD_NO_FO_RWARD_SPECIALIZATIONS
template <class T>
class _RWSTDExportTemplate complex
{
  public:
    typedef T value_type;

    complex (const T& re_arg=0, const T& imag_arg=0) { re_=re_arg; im_=imag_arg; } 
    ~complex() { ; }

    T imag () const { return im_; }
    T real () const { return re_; }

#ifndef _RWSTD_NO_MEMBER_TEMPLATES
    template <class X> complex (const complex<X>& rhs) {re_=rhs.real(); im_=rhs.imag();}

    template <class X> complex<T>& operator=  (const complex<X>& rhs) {re_=rhs.real(); im_=rhs.imag(); return *this;}
    template <class X> complex<T>& operator+= (const complex<X>& rhs) {re_+=rhs.real(); im_+=rhs.imag(); return *this;}
    template <class X> complex<T>& operator-= (const complex<X>& rhs) {re_-=rhs.real(); im_-=rhs.imag(); return *this;}
    template <class X> complex<T>& operator*= (const complex<X>& rhs) {T tmp=re_*rhs.real()-im_*rhs.imag(); im_=im_*rhs.real()+re_*rhs.imag(); re_=tmp; return *this;}
    template <class X> complex<T>& operator/= (const complex<X>&); 
#endif
    
    complex<T>& operator=  (T); 
    complex<T>& operator+= (T); 
    complex<T>& operator-= (T); 
    complex<T>& operator*= (T); 
    complex<T>& operator/= (T); 

  private:
    T re_, im_;
};


#else

//
// The complex template definition must be placed after specializations to 
// satisfy several compilers' rather bizarre preference.
//
template <class T>
class _RWSTDExportTemplate complex;
#endif

#ifndef _RWSTD_NO_FO_RWARD_SPECIALIZATIONS 
#if defined(__DECCXX) && !defined(__DECFIXCXXL508)
template <>
#endif
class _RWSTDExport complex<float>;
#if defined(__DECCXX) && !defined(__DECFIXCXXL508)
template <>
#endif
class _RWSTDExport complex<double>;
#ifndef _RWSTD_NO_LONGDOUBLE
#if defined(__DECCXX) && !defined(__DECFIXCXXL508)
template <>
#endif
class _RWSTDExport complex<long double>;
#endif
#endif


#if defined(__DECCXX) && !defined(__DECFIXCXXL508)
template <>
#endif
class _RWSTDExport complex<float>
{
  public:
    typedef float value_type;

    complex (const float& re_arg=0.0f, const float& imag_arg=0.0f) { re_=re_arg; im_=imag_arg; }
    complex (const complex<float>&);
	#ifndef _RWSTD_NO_FO_RWARD_SPECIALIZATIONS
    _EXPLICIT complex (const complex<double>&); 
	#ifndef _RWSTD_NO_LONGDOUBLE
    _EXPLICIT complex (const complex<long double>&);
    #endif
    #endif 
    ~complex() { ; }

    float imag () const { return im_; }
    float real () const { return re_; }

#ifndef _RWSTD_NO_MEMBER_TEMPLATES
    template <class X> complex<float>& operator=  (const complex<X>& rhs) {re_=rhs.real(); im_=rhs.imag(); return *this;}
    template <class X> complex<float>& operator+= (const complex<X>& rhs) {re_+=rhs.real(); im_+=rhs.imag(); return *this;}
    template <class X> complex<float>& operator-= (const complex<X>& rhs) {re_-=rhs.real(); im_-=rhs.imag(); return *this;}
    template <class X> complex<float>& operator*= (const complex<X>& rhs) {float tmp=re_*rhs.real()-im_*rhs.imag(); im_=im_*rhs.real()+re_*rhs.imag(); re_=tmp; return *this;}
    template <class X> complex<float>& operator/= (const complex<X>&); 
#else /* Have to specialize each one :-( */

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

    #ifndef _RWSTD_NO_FO_RWARD_SPECIALIZATIONS
    complex<float>& operator=  (const complex<double>&); 
    complex<float>& operator+= (const complex<double>&); 
    complex<float>& operator-= (const complex<double>&); 
    complex<float>& operator*= (const complex<double>&); 
    complex<float>& operator/= (const complex<double>&); 

    #ifndef _RWSTD_NO_LONGDOUBLE
    complex<float>& operator=  (const complex<long double>&); 
    complex<float>& operator+= (const complex<long double>&); 
    complex<float>& operator-= (const complex<long double>&); 
    complex<float>& operator*= (const complex<long double>&); 
    complex<float>& operator/= (const complex<long double>&);
	#endif
    #endif  
#endif

    complex<float>& operator=  (float); 
    complex<float>& operator+= (float); 
    complex<float>& operator-= (float); 
    complex<float>& operator*= (float); 
    complex<float>& operator/= (float); 

  private:
    float re_, im_;
};


#if defined(__DECCXX) && !defined(__DECFIXCXXL508)
template <>
#endif
class  _RWSTDExport complex<double>
{
  public:
    typedef double value_type;

    complex (const double& re_arg=0.0, const double& imag_arg=0.0) { re_=re_arg; im_=imag_arg; } 
    complex (const complex<float>&); 
    complex (const complex<double>&);
    #ifndef _RWSTD_NO_FO_RWARD_SPECIALIZATIONS
    #ifndef _RWSTD_NO_LONGDOUBLE  
    _EXPLICIT complex (const complex<long double>&); 
	#endif
	#endif
    ~complex() { ; }

    double imag () const { return im_; }
    double real () const { return re_; }

#ifndef _RWSTD_NO_MEMBER_TEMPLATES
    template <class X> complex<double>& operator=  (const complex<X>& rhs) {re_=rhs.real(); im_=rhs.imag(); return *this;}
    template <class X> complex<double>& operator+= (const complex<X>& rhs) {re_+=rhs.real(); im_+=rhs.imag(); return *this;}
    template <class X> complex<double>& operator-= (const complex<X>& rhs) {re_-=rhs.real(); im_-=rhs.imag(); return *this;}
    template <class X> complex<double>& operator*= (const complex<X>& rhs) {double tmp=re_*rhs.real()-im_*rhs.imag(); im_=im_*rhs.real()+re_*rhs.imag(); re_=tmp; return *this;}
    template <class X> complex<double>& operator/= (const complex<X>&);

#else /* Have to specialize each one :-( */

    complex<double>& operator=  (const complex<float>&); 
    complex<double>& operator+= (const complex<float>&); 
    complex<double>& operator-= (const complex<float>&);
    complex<double>& operator*= (const complex<float>& rhs); 
    complex<double>& operator/= (const complex<float>&); 

    complex<double>& operator=  (const complex<double>& rhs); 
    complex<double>& operator+= (const complex<double>& rhs); 
    complex<double>& operator-= (const complex<double>& rhs); 
    complex<double>& operator*= (const complex<double>& rhs); 
    complex<double>& operator/= (const complex<double>&); 

    #ifndef _RWSTD_NO_FO_RWARD_SPECIALIZATIONS
    #ifndef _RWSTD_NO_LONGDOUBLE  
    complex<double>& operator=  (const complex<long double>&); 
    complex<double>& operator+= (const complex<long double>&); 
    complex<double>& operator-= (const complex<long double>&); 
    complex<double>& operator*= (const complex<long double>&); 
    complex<double>& operator/= (const complex<long double>&);
    #endif
    #endif 
#endif

    complex<double>& operator=  (double); 
    complex<double>& operator+= (double); 
    complex<double>& operator-= (double); 
    complex<double>& operator*= (double); 
    complex<double>& operator/= (double); 


  private:
    double re_, im_;
};

#ifndef _RWSTD_NO_LONGDOUBLE  
#if defined(__DECCXX) && !defined(__DECFIXCXXL508)
template <>
#endif
class _RWSTDExport complex<long double>
{
  public:
    typedef long double value_type;

    complex (const long double& re_arg=0.0L, const long double& imag_arg=0.0L) { re_=re_arg; im_=imag_arg; } 
    complex (const complex<float>&);
    complex (const complex<double>&);
    complex (const complex<long double>&);
    ~complex() { ; }

    long double imag () const { return im_; }
    long double real () const { return re_; }

#ifndef _RWSTD_NO_MEMBER_TEMPLATES
    template <class X> complex<long double>& operator=  (const complex<X>& rhs) {re_=rhs.real(); im_=rhs.imag(); return *this;}
    template <class X> complex<long double>& operator+= (const complex<X>& rhs) {re_+=rhs.real(); im_+=rhs.imag(); return *this;}
    template <class X> complex<long double>& operator-= (const complex<X>& rhs) {re_-=rhs.real(); im_-=rhs.imag(); return *this;}
    template <class X> complex<long double>& operator*= (const complex<X>& rhs) {long double tmp=re_*rhs.real()-im_*rhs.imag(); im_=im_*rhs.real()+re_*rhs.imag(); re_=tmp; return *this;}
    template <class X> complex<long double>& operator/= (const complex<X>&); 

#else /* Have to specialize each one :-( */

    complex<long double>& operator=  (const complex<float>&); 
    complex<long double>& operator+= (const complex<float>&); 
    complex<long double>& operator-= (const complex<float>&); 
    complex<long double>& operator*= (const complex<float>&); 
    complex<long double>& operator/= (const complex<float>&); 

    complex<long double>& operator=  (const complex<double>&); 
    complex<long double>& operator+= (const complex<double>&); 
    complex<long double>& operator-= (const complex<double>&); 
    complex<long double>& operator*= (const complex<double>&); 
    complex<long double>& operator/= (const complex<double>&); 

    complex<long double>& operator=  (const complex<long double>&); 
    complex<long double>& operator+= (const complex<long double>&); 
    complex<long double>& operator-= (const complex<long double>&); 
    complex<long double>& operator*= (const complex<long double>&); 
    complex<long double>& operator/= (const complex<long double>&); 
#endif

    complex<long double>& operator=  (long double); 
    complex<long double>& operator+= (long double); 
    complex<long double>& operator-= (long double); 
    complex<long double>& operator*= (long double); 
    complex<long double>& operator/= (long double); 


  private:
    long double re_, im_;
};
#endif

#ifndef _RWSTD_NO_FO_RWARD_SPECIALIZATIONS
template <class T>
class _RWSTDExportTemplate complex
{
  public:
    typedef T value_type;

    complex (const T& re_arg=0, const T& imag_arg=0) { re_=re_arg; im_=imag_arg; } 
    ~complex() { ; }

    T imag () const { return im_; }
    T real () const { return re_; }

#ifndef _RWSTD_NO_MEMBER_TEMPLATES
    template <class X> complex (const complex<X>& rhs) {re_=rhs.real(); im_=rhs.imag();}

    template <class X> complex<T>& operator=  (const complex<X>& rhs) {re_=rhs.real(); im_=rhs.imag(); return *this;}
    template <class X> complex<T>& operator+= (const complex<X>& rhs) {re_+=rhs.real(); im_+=rhs.imag(); return *this;}
    template <class X> complex<T>& operator-= (const complex<X>& rhs) {re_-=rhs.real(); im_-=rhs.imag(); return *this;}
    template <class X> complex<T>& operator*= (const complex<X>& rhs) {T tmp=re_*rhs.real()-im_*rhs.imag(); im_=im_*rhs.real()+re_*rhs.imag(); re_=tmp; return *this;}
    template <class X> complex<T>& operator/= (const complex<X>&); 
#endif
    
    complex<T>& operator=  (T); 
    complex<T>& operator+= (T); 
    complex<T>& operator-= (T); 
    complex<T>& operator*= (T); 
    complex<T>& operator/= (T); 

  private:
    T re_, im_;
};
#endif

//
// Temporarily turn off the warnings under the Borland compiler that
// say 'Functions containing ... cannot be inlined'
//
#if defined(__BORLANDC__)
#pragma warn -inl
#endif

template <class T>
inline complex<T>&
complex<T>::operator= (T rhs) 
{
    re_ = rhs; im_ = 0.0; return *this;
}

template <class T>
inline complex<T>&
complex<T>::operator+= (T rhs) 
{
    re_ += rhs; return *this;
}

template <class T>
inline complex<T>&
complex<T>::operator-= (T rhs) 
{
    re_ -= rhs;  return *this;
}

template <class T>
inline complex<T>&
complex<T>::operator*= (T rhs) 
{	
    T tmp = re_*rhs; 
    im_       = im_*rhs; 
    re_       = tmp;
    return *this;
}

template <class T>
inline complex<T>& 
complex<T>::operator/= (T rhs)  
{
    T denom = rhs*rhs;
    T re    = (re_*rhs)/denom;
    T im    = (rhs*im_)/denom;
    re_               = re;
    im_               = im;
    return *this;
}


//
// complex<float> specializations.
//
inline
complex<float>::complex (const complex<float>& cf)
{
    re_ = cf.real(); im_ = cf.imag();
}

#ifndef _RWSTD_NO_FO_RWARD_SPECIALIZATIONS 
inline
complex<float>::complex (const complex<double>& cd)
{
    re_ = _RWSTD_STATIC_CAST(float,cd.real()); 
    im_ = _RWSTD_STATIC_CAST(float,cd.imag());
}

#ifndef _RWSTD_NO_LONGDOUBLE
inline
complex<float>::complex (const complex<long double>& cld)
{
    re_ = _RWSTD_STATIC_CAST(float,cld.real()); 
    im_ = _RWSTD_STATIC_CAST(float,cld.imag());
}
#endif
#endif

#if defined(__DECCXX) && !defined(__DECFIXCXXL440) && defined(_RWSTD_NO_MEMBER_TEMPLATES)
inline complex<float>&
complex<float>::operator= (const complex<float>& rhs) 
{
    re_ = rhs.real(); im_ = rhs.imag(); return *this;
}
#endif

inline complex<float>&
complex<float>::operator= (float rhs) 
{
    re_ = rhs; im_ = 0.0; return *this;
}

#if defined(__DECCXX) && !defined(__DECFIXCXXL440) && defined(_RWSTD_NO_MEMBER_TEMPLATES)
inline complex<float>&
complex<float>::operator+= (const complex<float>& rhs) 
{
    re_ += rhs.real(); im_ += rhs.imag(); return *this;
}
#endif

inline complex<float>&
complex<float>::operator+= (float rhs) 
{
    re_ += rhs; return *this;
}

#if defined(__DECCXX) && !defined(__DECFIXCXXL440) && defined(_RWSTD_NO_MEMBER_TEMPLATES)
inline complex<float>&
complex<float>::operator-= (const complex<float>& rhs) 
{
    re_ -= rhs.real(); im_ -= rhs.imag(); return *this;
}
#endif

inline complex<float>&
complex<float>::operator-= (float rhs) 
{
    re_ -= rhs;  return *this;
}

#if defined(__DECCXX) && !defined(__DECFIXCXXL440) && defined(_RWSTD_NO_MEMBER_TEMPLATES)
inline complex<float>&
complex<float>::operator*= (const complex<float>& rhs) 
{	
    float tmp = re_*rhs.real()-im_*rhs.imag(); 
    im_       = im_*rhs.real()+re_*rhs.imag(); 
    re_       = tmp;
    return *this;
}
#endif

inline complex<float>&
complex<float>::operator*= (float rhs) 
{	
    float tmp = re_*rhs; 
    im_       = im_*rhs; 
    re_       = tmp;
    return *this;
}

#ifndef _RWSTD_NO_FO_RWARD_SPECIALIZATIONS 
#if defined(__DECCXX) && !defined(__DECFIXCXXL440) && defined(_RWSTD_NO_MEMBER_TEMPLATES)
inline complex<float>&
complex<float>::operator= (const complex<double>& rhs) 
{
    re_ = _RWSTD_STATIC_CAST(float,rhs.real()); 
    im_ = _RWSTD_STATIC_CAST(float,rhs.imag()); 
    return *this;
}

inline complex<float>&
complex<float>::operator+= (const complex<double>& rhs) 
{
    re_ += _RWSTD_STATIC_CAST(float,rhs.real()); 
    im_ += _RWSTD_STATIC_CAST(float,rhs.imag()); 
    return *this;
}

inline complex<float>&
complex<float>::operator-= (const complex<double>& rhs) 
{	
    re_ -= _RWSTD_STATIC_CAST(float,rhs.real()); 
    im_ -= _RWSTD_STATIC_CAST(float,rhs.imag()); 
    return *this;
}

inline complex<float>&
complex<float>::operator*= (const complex<double>& rhs) 
{	
    float tmp = re_*_RWSTD_STATIC_CAST(float,rhs.real())-
                im_*_RWSTD_STATIC_CAST(float,rhs.imag()); 
    im_       = im_*_RWSTD_STATIC_CAST(float,rhs.real())+
                re_*_RWSTD_STATIC_CAST(float,rhs.imag()); 
    re_       = tmp;
    return *this;
}
#endif

#ifndef _RWSTD_NO_LONGDOUBLE
#if defined(__DECCXX) && !defined(__DECFIXCXXL440) && defined(_RWSTD_NO_MEMBER_TEMPLATES)
inline complex<float>&
complex<float>::operator= (const complex<long double>& rhs) 
{	
    re_ = _RWSTD_STATIC_CAST(float,rhs.real()); 
    im_ = _RWSTD_STATIC_CAST(float,rhs.imag()); 
    return *this;
}

inline complex<float>&
complex<float>::operator+= (const complex<long double>& rhs) 
{	
    re_ += _RWSTD_STATIC_CAST(float,rhs.real()); 
    im_ += _RWSTD_STATIC_CAST(float,rhs.imag()); 
    return *this;
}

inline complex<float>&
complex<float>::operator-= (const complex<long double>& rhs) 
{
    re_ -= _RWSTD_STATIC_CAST(float,rhs.real()); 
    im_ -= _RWSTD_STATIC_CAST(float,rhs.imag()); 
    return *this;
}

inline complex<float>&
complex<float>::operator*= (const complex<long double>& rhs) 
{	
    float tmp = re_*_RWSTD_STATIC_CAST(float,rhs.real())-
                im_*_RWSTD_STATIC_CAST(float,rhs.imag()); 
    im_       = im_*_RWSTD_STATIC_CAST(float,rhs.real())+
                re_*_RWSTD_STATIC_CAST(float,rhs.imag()); 
    re_       = tmp; 
    return *this;
}
#endif
#endif
#endif
//
// complex<double> specializations.
//

inline
complex<double>::complex (const complex<float>& cf)
    : re_(cf.real()), im_(cf.imag()) {}

inline 
complex<double>::complex (const complex<double>& cd)
    : re_(cd.real()), im_(cd.imag()) {}

#ifndef _RWSTD_NO_FO_RWARD_SPECIALIZATIONS 
#ifndef _RWSTD_NO_LONGDOUBLE
inline 
complex<double>::complex (const complex<long double>& cld)
    : re_(_RWSTD_STATIC_CAST(double,cld.real())), 
      im_(_RWSTD_STATIC_CAST(double,cld.imag())) {}
#endif
#endif

#if defined(__DECCXX) && !defined(__DECFIXCXXL440) && defined(_RWSTD_NO_MEMBER_TEMPLATES)
inline complex<double>&
complex<double>::operator= (const complex<float>& rhs) 
{
    re_ = rhs.real(); im_ = rhs.imag(); return *this;
}
#endif

inline complex<double>&
complex<double>::operator= (double rhs) 
{
    re_ = rhs; im_ = 0.0; return *this;
}

#if defined(__DECCXX) && !defined(__DECFIXCXXL440) && defined(_RWSTD_NO_MEMBER_TEMPLATES)
inline complex<double>&
complex<double>::operator+= (const complex<float>& rhs) 
{
    re_ += rhs.real(); im_ += rhs.imag(); return *this;
}
#endif

inline complex<double>&
complex<double>::operator+= (double rhs) 
{
    re_ += rhs; return *this;
}

#if defined(__DECCXX) && !defined(__DECFIXCXXL440) && defined(_RWSTD_NO_MEMBER_TEMPLATES)
inline complex<double>&
complex<double>::operator-= (const complex<float>& rhs) 
{
    re_ -= rhs.real(); im_ -= rhs.imag(); return *this;
}
#endif

inline complex<double>&
complex<double>::operator-= (double rhs) 
{
    re_ -= rhs;  return *this;
}

#if defined(__DECCXX) && !defined(__DECFIXCXXL440) && defined(_RWSTD_NO_MEMBER_TEMPLATES)
inline complex<double>&
complex<double>::operator*= (const complex<float>& rhs) 
{	
    double tmp = re_*rhs.real()-im_*rhs.imag(); 
    im_        = im_*rhs.real()+re_*rhs.imag(); 
    re_        = tmp;
    return *this;
}
#endif

#if defined(__DECCXX) && !defined(__DECFIXCXXL440) && defined(_RWSTD_NO_MEMBER_TEMPLATES)
inline complex<double>&
complex<double>::operator= (const complex<double>& rhs) 
{
    re_ = rhs.real(); im_ = rhs.imag(); return *this;
}

inline complex<double>&
complex<double>::operator+= (const complex<double>& rhs) 
{
    re_ += rhs.real(); im_ += rhs.imag(); return *this;
}

inline complex<double>&
complex<double>::operator-= (const complex<double>& rhs) 
{	
    re_ -= rhs.real(); im_ -= rhs.imag(); return *this;
}

inline complex<double>& 
complex<double>::operator*= (const complex<double>& rhs) 
{	
    double tmp = re_*rhs.real()-im_*rhs.imag(); 
    im_        = im_*rhs.real()+re_*rhs.imag(); 
    re_        = tmp;
    return *this;
}
#endif

inline complex<double>&
complex<double>::operator*= (double rhs) 
{	
    double tmp = re_*rhs; 
    im_       = im_*rhs; 
    re_       = tmp;
    return *this;
}


#ifndef _RWSTD_NO_FO_RWARD_SPECIALIZATIONS 
#ifndef _RWSTD_NO_LONGDOUBLE
#if defined(__DECCXX) && !defined(__DECFIXCXXL440) && defined(_RWSTD_NO_MEMBER_TEMPLATES)
inline complex<double>&
complex<double>::operator= (const complex<long double>& rhs) 
{	
    re_ = _RWSTD_STATIC_CAST(double,rhs.real()); 
    im_ = _RWSTD_STATIC_CAST(double,rhs.imag()); 
    return *this;
}

inline complex<double>&
complex<double>::operator+= (const complex<long double>& rhs) 
{	
    re_ += _RWSTD_STATIC_CAST(double,rhs.real()); 
    im_ += _RWSTD_STATIC_CAST(double,rhs.imag()); 
    return *this;
}

inline complex<double>& 
complex<double>::operator-= (const complex<long double>& rhs) 
{
    re_ -= _RWSTD_STATIC_CAST(double,rhs.real()); 
    im_ -= _RWSTD_STATIC_CAST(double,rhs.imag()); 
    return *this;
}

inline complex<double>& 
complex<double>::operator*= (const complex<long double>& rhs) 
{	
    double tmp = re_*_RWSTD_STATIC_CAST(double,rhs.real())-
                 im_*_RWSTD_STATIC_CAST(double,rhs.imag()); 
    im_        = im_*_RWSTD_STATIC_CAST(double,rhs.real())+
                 re_*_RWSTD_STATIC_CAST(double,rhs.imag()); 
    re_        = tmp; 
    return *this;
}
#endif
#endif
#endif

//
// complex<long double> specializations.
//

#ifndef _RWSTD_NO_LONGDOUBLE
inline 
complex<long double>::complex (const complex<float>& cf)
    : re_(cf.real()), im_(cf.imag()) {}

inline 
complex<long double>::complex (const complex<double>& cd)
    : re_(cd.real()), im_(cd.imag()) {}

inline 
complex<long double>::complex (const complex<long double>& cld)
    : re_(cld.real()), im_(cld.imag()) {}


#if defined(__DECCXX) && !defined(__DECFIXCXXL440) && defined(_RWSTD_NO_MEMBER_TEMPLATES)
inline complex<long double>& 
complex<long double>::operator= (const complex<float>& rhs) 
{
    re_ = rhs.real(); im_ = rhs.imag(); return *this;
}

inline complex<long double>& 
complex<long double>::operator+= (const complex<float>& rhs) 
{
    re_ += rhs.real(); im_ += rhs.imag(); return *this;
}
#endif

inline complex<long double>&
complex<long double>::operator+= (long double rhs) 
{
    re_ += rhs; return *this;
}

#if defined(__DECCXX) && !defined(__DECFIXCXXL440) && defined(_RWSTD_NO_MEMBER_TEMPLATES)
inline complex<long double>&
complex<long double>::operator-= (const complex<float>& rhs) 
{
    re_ -= rhs.real(); im_ -= rhs.imag(); return *this;
}

inline complex<long double>& 
complex<long double>::operator*= (const complex<float>& rhs) 
{	
    long double tmp = re_*rhs.real()-im_*rhs.imag(); 
    im_             = im_*rhs.real()+re_*rhs.imag(); 
    re_             = tmp;
    return *this;
}
       
inline complex<long double>& 
complex<long double>::operator= (const complex<double>& rhs) 
{
    re_ = rhs.real(); im_ = rhs.imag(); return *this;
}
#endif

inline complex<long double>&
complex<long double>::operator= (long double rhs) 
{
    re_ = rhs; im_ = 0.0; return *this;
}

#if defined(__DECCXX) && !defined(__DECFIXCXXL440) && defined(_RWSTD_NO_MEMBER_TEMPLATES)
inline complex<long double>& 
complex<long double>::operator+= (const complex<double>& rhs) 
{
    re_ += rhs.real(); im_ += rhs.imag(); return *this;
}

inline complex<long double>&
complex<long double>::operator-= (const complex<double>& rhs) 
{	
    re_ -= rhs.real(); im_ -= rhs.imag(); return *this;
}
#endif

inline complex<long double>&
complex<long double>::operator-= (long double rhs) 
{
    re_ -= rhs;  return *this;
}

#if defined(__DECCXX) && !defined(__DECFIXCXXL440) && defined(_RWSTD_NO_MEMBER_TEMPLATES)
inline complex<long double>& 
complex<long double>::operator*= (const complex<double>& rhs) 
{	
    long double tmp = re_*rhs.real()-im_*rhs.imag(); 
    im_             = im_*rhs.real()+re_*rhs.imag(); 
    re_             = tmp;
    return *this;
}
#endif

inline complex<long double>&
complex<long double>::operator*= (long double rhs) 
{	
    long double tmp = re_*rhs; 
    im_       = im_*rhs; 
    re_       = tmp;
    return *this;
}

#if defined(__DECCXX) && !defined(__DECFIXCXXL440) && defined(_RWSTD_NO_MEMBER_TEMPLATES)
inline complex<long double>&
complex<long double>::operator= (const complex<long double>& rhs) 
{	
    re_ = rhs.real(); im_ = rhs.imag(); return *this;
}

inline complex<long double>&
complex<long double>::operator+= (const complex<long double>& rhs) 
{	
    re_ += rhs.real(); im_ += rhs.imag(); return *this;
}

inline complex<long double>& 
complex<long double>::operator-= (const complex<long double>& rhs) 
{
    re_ -= rhs.real(); im_ -= rhs.imag(); return *this;
}

inline complex<long double>& 
complex<long double>::operator*= (const complex<long double>& rhs) 
{	
    long double tmp = re_*rhs.real()-im_*rhs.imag(); 
    im_             = im_*rhs.real()+re_*rhs.imag(); 
    re_             = tmp; 
    return *this;
}
#endif
#endif

#ifndef _RWSTD_NO_MEMBER_TEMPLATES
template <class T>
template <class X>
complex<T>&
complex<T>::operator/= (const complex<X>& rhs)
{
    T denom = rhs.real()*rhs.real() + rhs.imag()*rhs.imag();
    T re    = (re_*rhs.real()+im_*rhs.imag())/denom;
    T im    = (rhs.real()*im_-re_*rhs.imag())/denom;
    re_     = re;
    im_     = im;
    return *this;
}

template <class X>
complex<float>& 
complex<float>::operator/= (const complex<X>& rhs)  
{
    float denom = rhs.real()*rhs.real() + rhs.imag()*rhs.imag();
    float re    = (re_*rhs.real()+im_*rhs.imag())/denom;
    float im    = (rhs.real()*im_-re_*rhs.imag())/denom;
    re_         = re;
    im_         = im;
    return *this;
}

template <class X>
complex<double>& 
complex<double>::operator/= (const complex<X>& rhs)  
{
    double denom = rhs.real()*rhs.real() + rhs.imag()*rhs.imag();
    double re    = (re_*rhs.real()+im_*rhs.imag())/denom;
    double im    = (rhs.real()*im_-re_*rhs.imag())/denom;
    re_         = re;
    im_         = im;
    return *this;
}

#ifndef _RWSTD_NO_LONGDOUBLE
template <class X>
complex<long double>& 
complex<long double>::operator/= (const complex<X>& rhs)  
{
    long double denom = rhs.real()*rhs.real() + rhs.imag()*rhs.imag();
    long double re    = (re_*rhs.real()+im_*rhs.imag())/denom;
    long double im    = (rhs.real()*im_-re_*rhs.imag())/denom;
    re_         = re;
    im_         = im;
    return *this;
}
#endif
#else /* No member function templates, have to specialize :-( */

inline complex<float>& 
complex<float>::operator/= (const complex<float>& rhs)  
{
    float denom = rhs.real()*rhs.real() + rhs.imag()*rhs.imag();
    float re    = (re_*rhs.real()+im_*rhs.imag())/denom;
    float im    = (rhs.real()*im_-re_*rhs.imag())/denom;
    re_          = re;
    im_          = im;
    return *this;
}

#ifndef _RWSTD_NO_FO_RWARD_SPECIALIZATIONS
inline complex<float>& 
complex<float>::operator/= (const complex<double>& rhs)  
{
    float denom = _RWSTD_STATIC_CAST(float,rhs.real())*
                  _RWSTD_STATIC_CAST(float,rhs.real()) + 
                  _RWSTD_STATIC_CAST(float,rhs.imag())*
                  _RWSTD_STATIC_CAST(float,rhs.imag());
    float re    = (re_*_RWSTD_STATIC_CAST(float,rhs.real())+
                  im_*_RWSTD_STATIC_CAST(float,rhs.imag()))/denom;
    float im    = (_RWSTD_STATIC_CAST(float,rhs.real())*im_-re_*
                   _RWSTD_STATIC_CAST(float,rhs.imag()))/denom;
    re_          = re;
    im_          = im;
    return *this;
}

#ifndef _RWSTD_NO_LONGDOUBLE
inline complex<float>& 
complex<float>::operator/= (const complex<long double>& rhs)  
{
    float denom = _RWSTD_STATIC_CAST(float,rhs.real())*
                  _RWSTD_STATIC_CAST(float,rhs.real()) + 
                  _RWSTD_STATIC_CAST(float,rhs.imag())*
                  _RWSTD_STATIC_CAST(float,rhs.imag());
    float re    = (re_*_RWSTD_STATIC_CAST(float,rhs.real())+
                  im_*_RWSTD_STATIC_CAST(float,rhs.imag()))/denom;
    float im    = (_RWSTD_STATIC_CAST(float,rhs.real())*im_-
                   re_*_RWSTD_STATIC_CAST(float,rhs.imag()))/denom;
    re_          = re;
    im_          = im;
    return *this;
}
#endif 
#endif

inline complex<double>& 
complex<double>::operator/= (const complex<float>& rhs)  
{
    double denom = rhs.real()*rhs.real() + rhs.imag()*rhs.imag();
    double re    = (re_*rhs.real()+im_*rhs.imag())/denom;
    double im    = (rhs.real()*im_-re_*rhs.imag())/denom;
    re_               = re;
    im_               = im;
    return *this;
}

inline complex<double>&
complex<double>::operator/= (const complex<double>& rhs)
{
    double denom = rhs.real()*rhs.real() + rhs.imag()*rhs.imag();
    double re    = (re_*rhs.real()+im_*rhs.imag())/denom;
    double im    = (rhs.real()*im_-re_*rhs.imag())/denom;
    re_               = re;
    im_               = im;
    return *this;
}

#ifndef _RWSTD_NO_FO_RWARD_SPECIALIZATIONS
#ifndef _RWSTD_NO_LONGDOUBLE
inline complex<double>& 
complex<double>::operator/= (const complex<long double>& rhs)  
{
    double denom = _RWSTD_STATIC_CAST(double,rhs.real())*
                  _RWSTD_STATIC_CAST(double,rhs.real()) + 
                  _RWSTD_STATIC_CAST(double,rhs.imag())*
                  _RWSTD_STATIC_CAST(double,rhs.imag());
    double re    = (re_*_RWSTD_STATIC_CAST(double,rhs.real())+
                  im_*_RWSTD_STATIC_CAST(double,rhs.imag()))/denom;
    double im    = (_RWSTD_STATIC_CAST(double,rhs.real())*im_-
                   re_*_RWSTD_STATIC_CAST(double,rhs.imag()))/denom;
    re_          = re;
    im_          = im;
    return *this;
}
#endif
#endif

#ifndef _RWSTD_NO_LONGDOUBLE
inline complex<long double>& 
complex<long double>::operator/= (const complex<float>& rhs)  
{
    long double denom = rhs.real()*rhs.real() + rhs.imag()*rhs.imag();
    long double re    = (re_*rhs.real()+im_*rhs.imag())/denom;
    long double im    = (rhs.real()*im_-re_*rhs.imag())/denom;
    re_               = re;
    im_               = im;
    return *this;
}

inline complex<long double>& 
complex<long double>::operator/= (const complex<double>& rhs)  
{
    long double denom = rhs.real()*rhs.real() + rhs.imag()*rhs.imag();
    long double re    = (re_*rhs.real()+im_*rhs.imag())/denom;
    long double im    = (rhs.real()*im_-re_*rhs.imag())/denom;
    re_               = re;
    im_               = im;
    return *this;
}

inline complex<long double>& 
complex<long double>::operator/= (const complex<long double>& rhs)  
{
    long double denom = rhs.real()*rhs.real() + rhs.imag()*rhs.imag();
    long double re    = (re_*rhs.real()+im_*rhs.imag())/denom;
    long double im    = (rhs.real()*im_-re_*rhs.imag())/denom;
    re_               = re;
    im_               = im;
    return *this;
}
#endif
#endif

inline complex<float>& 
complex<float>::operator/= (float rhs)  
{
    float denom = rhs*rhs;
    float re    = (re_*rhs)/denom;
    float im    = (rhs*im_)/denom;
    re_               = re;
    im_               = im;
    return *this;
}

inline complex<double>& 
complex<double>::operator/= (double rhs)  
{
    double denom = rhs*rhs;
    double re    = (re_*rhs)/denom;
    double im    = (rhs*im_)/denom;
    re_               = re;
    im_               = im;
    return *this;
}

inline complex<long double>& 
complex<long double>::operator/= (long double rhs)  
{
    long double denom = rhs*rhs;
    long double re    = (re_*rhs)/denom;
    long double im    = (rhs*im_)/denom;
    re_               = re;
    im_               = im;
    return *this;
}




//
// complex non-member operations
//

template <class T>
inline complex<T> operator+ (const complex<T>& lhs, const complex<T>& rhs)
{
    complex<T> tmp = lhs; return tmp += rhs;
}

template <class T>
inline complex<T> operator+ (const complex<T>& lhs, const T& rhs)
{
    return complex<T>(rhs+lhs.real(), lhs.imag());
}

template <class T>
inline complex<T> operator+ (const T& lhs, const complex<T>& rhs)
{
    return complex<T>(lhs+rhs.real(), rhs.imag());
}

template <class T>
inline complex<T> operator- (const complex<T>& lhs, const complex<T>& rhs)
{
    complex<T> tmp = lhs; return tmp -= rhs;
}

template <class T>
inline complex<T> operator- (const complex<T>& lhs, const T& rhs)
{
    return complex<T>(lhs.real()-rhs, lhs.imag());
}

template <class T>
inline complex<T> operator- (const T& lhs, const complex<T>& rhs)
{
    return complex<T>(lhs-rhs.real(), -rhs.imag());
}

template <class T>
inline complex<T> operator* (const complex<T>& lhs, const complex<T>& rhs)
{
    complex<T> tmp = lhs; return tmp *= rhs;
}

template <class T>
inline complex<T> operator* (const complex<T>& lhs, const T& rhs)
{
    return complex<T>(rhs*lhs.real(), rhs*lhs.imag());
}

template <class T>
inline complex<T> operator* (const T& lhs, const complex<T>& rhs)
{
    return complex<T>(lhs*rhs.real(), lhs*rhs.imag());
}

template <class T>
inline complex<T> operator/ (const complex<T>& lhs, const complex<T>& rhs)
{
    complex<T> tmp = lhs; return tmp /= rhs;
}

template <class T>
inline complex<T> operator/ (const complex<T>& lhs, const T& rhs)
{
    return complex<T>(lhs.real()/rhs, lhs.imag()/rhs);
}

template <class T>
inline complex<T> operator/ (const T& lhs, const complex<T>& rhs)
{
    register T denom = rhs.real()*rhs.real() + rhs.imag()*rhs.imag();
    return complex<T>(lhs*rhs.real()/denom,(-lhs*rhs.imag())/denom);
}

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

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

template <class T>
inline bool operator== (const complex<T>& lhs, const complex<T>& rhs)
{
    return lhs.real() == rhs.real() && lhs.imag() == rhs.imag();
} 

template <class T>
inline bool operator== (const T& lhs, const complex<T>& rhs)
{
    return lhs == rhs.real() && rhs.imag() == 0;
} 

template <class T>
inline bool operator== (const complex<T>& lhs, const T& rhs)
{
    return lhs.real() == rhs && lhs.imag() == 0;
} 

#ifndef _RWSTD_NO_NAMESPACE
template <class T>
inline bool operator!= (const complex<T>& lhs, const complex<T>& rhs)
{
    return lhs.real() != rhs.real() || lhs.imag() != rhs.imag();
} 
#endif

template <class T>
inline bool operator!= (const T& lhs, const complex<T>& rhs)
{
    return lhs != rhs.real() || rhs.imag() != 0;
} 

template <class T>
inline bool operator!= (const complex<T>& lhs, const T& rhs)
{
    return lhs.real() != rhs || lhs.imag() != 0;
} 

//
// complex value operations
//

// Cope with namespace problems
#if defined(_RWSTD_NO_NEW_HEADER) && !defined(_RWSTD_NO_NAMESPACE) 
#define _RWSTD_C_SCOPE_SIN ::sin
#define _RWSTD_C_SCOPE_SINH ::sinh
#define _RWSTD_C_SCOPE_COS ::cos
#define _RWSTD_C_SCOPE_COSH ::cosh
#define _RWSTD_C_SCOPE_ATAN2 ::atan2
#define _RWSTD_C_SCOPE_ATAN ::atan
#define _RWSTD_C_SCOPE_EXP ::exp
#define _RWSTD_C_SCOPE_POW ::pow
#define _RWSTD_C_SCOPE_SQRT ::sqrt
#define _RWSTD_C_SCOPE_LOG ::log
#define _RWSTD_C_SCOPE_LOG10 ::log10
#else
#define _RWSTD_C_SCOPE_SIN sin
#define _RWSTD_C_SCOPE_SINH sinh
#define _RWSTD_C_SCOPE_COS cos
#define _RWSTD_C_SCOPE_COSH cosh
#define _RWSTD_C_SCOPE_ATAN2 atan2
#define _RWSTD_C_SCOPE_ATAN atan
#define _RWSTD_C_SCOPE_EXP exp
#define _RWSTD_C_SCOPE_POW pow
#define _RWSTD_C_SCOPE_SQRT sqrt
#define _RWSTD_C_SCOPE_LOG log
#define _RWSTD_C_SCOPE_LOG10 log10
#endif

template<class T>
inline T real (const complex<T>& a) { return a.real(); }

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

template <class T>
inline T norm (const complex<T>& a)
{
    return a.real()*a.real() + a.imag()*a.imag();
}

template <class T>
inline T abs (const complex<T>& a) { return (_RWSTD_C_SCOPE_SQRT(norm(a))); }

//
// We guarantee that arg(complex<T>(0,0)) == 0.
//

template <class T>
inline T arg (const complex<T>& a)
{
    return a == complex<T>(0,0) ? T(0) : _RWSTD_C_SCOPE_ATAN2(a.imag(), a.real());
}

template <class T>
complex<T> conj (const complex<T>& a)
{
    return complex<T>(a.real(), -a.imag());
}

#if _MSC_VER < 901
//
// A very bizarre Microsoft problem.
//
inline complex<float> conj (const complex<float>& a)
{
    return complex<float>(a.real(), -a.imag());
}
inline complex<double> conj (const complex<double>& a)
{
    return complex<double>(a.real(), -a.imag());
}

#ifndef _RWSTD_NO_LONGDOUBLE
inline complex<long double> conj (const complex<long double>& a)
{
    return complex<long double>(a.real(), -a.imag());
}
#endif
#endif

template <class T>
#ifndef _RWSTD_NO_INIT_CONST_TEMPLATE_REF_ARG
inline complex<T> polar (T r, const T& theta = 0)
#else
inline complex<T> polar (T r, const T& theta)
#endif
{
    return complex<T>(r*_RWSTD_C_SCOPE_COS(theta), r*_RWSTD_C_SCOPE_SIN(theta));
}

//
// transcendentals
//

//
// complex<T> cosine of complex<T> number a
//	cos (a) = cos u * cosh v - i * sin u * sinh v
//

template <class T>
inline complex<T> cos (const complex<T>& a)
{
    return complex<T>(_RWSTD_C_SCOPE_COS(a.real())*_RWSTD_C_SCOPE_COSH(a.imag()),
                      -_RWSTD_C_SCOPE_SIN(a.real())*_RWSTD_C_SCOPE_SINH(a.imag()));
}

//
// complex<T> hyperbolic cosine of complex<T> number a
//	cosh (a) = cosh u * cosv + i * sinh u * sin v
//

template <class T>
inline complex<T> cosh (const complex<T>& a)
{
    return complex<T>(_RWSTD_C_SCOPE_COSH(a.real())*_RWSTD_C_SCOPE_COS(a.imag()),
                      _RWSTD_C_SCOPE_SINH(a.real())*_RWSTD_C_SCOPE_SIN(a.imag()));
}

//
// complex<T> exponential of  complex<T> number a
//	exp (a) = exp(u) * (cos v + i * sin v)
//

template <class T>
inline complex<T> exp (const complex<T>& a)
{
    register T e = _RWSTD_C_SCOPE_EXP(a.real());
    return complex<T>(e*_RWSTD_C_SCOPE_COS(a.imag()), e*_RWSTD_C_SCOPE_SIN(a.imag()));
}

//
// complex<T> natural log of complex<T> number a
//	log(a) = log(r) + i * theta
//

template <class T>
inline complex<T> log (const complex<T>& a)
{
    return complex<T>(_RWSTD_C_SCOPE_LOG(abs(a)), arg(a));
}

template <class T>
complex<T> log10 (const complex<T>& a)
{
#if defined(__DECCXX) && !defined(__DECFIXCXXL397)
    const T log10e = _RWSTD_C_SCOPE_LOG10(_RWSTD_C_SCOPE_EXP(T(1)));
#else
    static const T log10e = _RWSTD_C_SCOPE_LOG10(_RWSTD_C_SCOPE_EXP(T(1)));
#endif
    return log10e * log(a);
}

//
// For all the power functions:
//
//   0**0 == 1
//   0**x == 0 for x != 0
//

//
// complex<T> number a raised to an integer power n
//
// a**n = r**n * (cos(n theta) + i sin (n theta))
//

template <class T>
complex<T> pow (const complex<T>& a, int n)
{
    if (a == complex<T>(0,0))
    {
        if (n == 0) 
          return complex<T>(1,0);
        else
          return complex<T>(0,0);
    }

    if (a.imag() == 0)
    {
       if (a.real() < 0)
          return pow(a, complex<T>(n,0));
       else
          return complex<T>(_RWSTD_C_SCOPE_POW(a.real(),T(n)), 0);
    }

    register T r  = _RWSTD_C_SCOPE_POW(T(abs(a)), T(n));
    register T th = T(n) * arg(a);

    return complex<T>(r*_RWSTD_C_SCOPE_COS(th), r*_RWSTD_C_SCOPE_SIN(th));
}


//
// complex<T> number a raised to a real power s
//
// a**s = exp(s * log(a))
//

template <class T>
complex<T> pow (const complex<T>& a, T s)
{
    if (a == complex<T>(0,0))
    {
        if (s == T(0))
           return complex<T>(1,0);
        else
           return complex<T>(0,0);
    }
    if (a.imag() == 0)
    {
       if (a.real() < 0)
          return pow(a, complex<T>(s,0));
       else
          return complex<T>(_RWSTD_C_SCOPE_POW(a.real(),s), 0);
    }
    return exp(s*log(a));
}   


//
// real number s raised to a complex<T> power a
//
//  s**a = exp(a * log (s))
//

template <class T>
complex<T> pow (T s, const complex<T>& a)
{
    if (s == T(0))
    {
        if (a == complex<T>(0,0)) 
           return complex<T>(1,0);
        else
           return complex<T>(0,0);
    }
    if (s < 0)
        return pow(complex<T>(s,0), a);

    if (a.imag() == 0)
        return complex<T>(_RWSTD_C_SCOPE_POW(s, a.real()), 0);
    return complex<T>(exp(a * (T) _RWSTD_C_SCOPE_LOG(s)));
}


//
// complex<T> number a1 raised to a complex<T> power a2
//
// a1**a2 = rho * (cos(phi) + i sin(phi))
//  	rho = r1 **u2   *  exp (-v2* theta1)
//	phi = v2 * log(r1) + u2 * theta1
//

template <class T>
complex<T> pow (const complex<T>& a1, const complex<T>& a2)
{
    if (a1 == complex<T>(0,0))
    {
        if (a2 == complex<T>(0,0))
           return complex<T>(1,0);
        else
           return complex<T>(0,0);
    }

    T r1   = abs(a1);
    T u2   = real(a2);
    T v2   = imag(a2);
    T th1  = arg(a1);
    T rho  = _RWSTD_C_SCOPE_POW(r1, u2) * _RWSTD_C_SCOPE_EXP(-v2 * th1);
    T phi  = v2 * _RWSTD_C_SCOPE_LOG(r1) + u2 * th1;

    return complex<T>(rho*_RWSTD_C_SCOPE_COS(phi), rho*_RWSTD_C_SCOPE_SIN(phi));
}	 


//
// complex<T> sine of complex<T> number a
//	sin (a) = sin u * cosh v + i * cos u * sinh v
//
template <class T>
inline complex<T> sin (const complex<T>& a)
{
    return complex<T>(_RWSTD_C_SCOPE_SIN(a.real())*_RWSTD_C_SCOPE_COSH(a.imag()),
                      _RWSTD_C_SCOPE_COS(a.real())*_RWSTD_C_SCOPE_SINH(a.imag()));
}

//
// complex<T> hyperbolic sine of complex<T> number a
//	sinh (a) = sinh u cos v + i cosh u sin v
//
template <class T>
inline complex<T> sinh (const complex<T>& a)
{
    return complex<T>(_RWSTD_C_SCOPE_SINH(a.real())*_RWSTD_C_SCOPE_COS(a.imag()),
                      _RWSTD_C_SCOPE_COSH(a.real())*_RWSTD_C_SCOPE_SIN(a.imag()));
}

//
// complex<T> square root of complex<T> number a
//  	sqrt(a) = sqrt(r) * ( cos (theta/2) + i sin (theta/2) )
//
template <class T>
inline complex<T> sqrt (const complex<T>& a)
{
    register T r  = _RWSTD_C_SCOPE_SQRT(abs(a));
    register T th = arg(a)/2.;
    return complex<T>(r*_RWSTD_C_SCOPE_COS(th), r*_RWSTD_C_SCOPE_SIN(th));
}

template <class T>
inline complex<T> tan (const complex<T>& a) { return sin(a)/cos(a); }

template <class T>
inline complex<T> tanh (const complex<T>& a) { return sinh(a)/cosh(a);
}


#ifdef __USE_STD_IOSTREAM

template <class T,class charT, class traits>
basic_istream<charT, traits >& _RWSTDExportTemplate 
operator>> (basic_istream<charT, traits >& is,complex<T>& x);
template <class T,class charT,class traits>

basic_ostream<charT,traits >& _RWSTDExportTemplate 
operator<< (basic_ostream<charT, traits >& os,const complex<T>& x);

#else

template <class T>
istream& _RWSTDExportTemplate operator>> (istream& is, complex<T>& x);
template <class T>
ostream& _RWSTDExportTemplate operator<< (ostream& os, const complex<T>& x);

#endif

#ifndef _RWSTD_NO_NAMESPACE
}
#endif

#if defined(_RWSTD_NO_DESTROY_BUILTIN) || defined(_RWSTD_NO_DESTROY_NONBUILTIN)

#ifndef _RWSTD_NO_NAMESPACE
namespace __rogue_wave_std {
#endif
//
// Specializations of STL destroy for complex.
//
inline void __destroy (complex<float>**)         {}
inline void __destroy (complex<float>***)        {}
inline void __destroy (complex<float>****)       {}
inline void __destroy (complex<double>**)        {}
inline void __destroy (complex<double>***)       {}
inline void __destroy (complex<double>****)      {}
#ifndef _RWSTD_NO_LONGDOUBLE
inline void __destroy (complex<long double>**)   {}
inline void __destroy (complex<long double>***)  {}
inline void __destroy (complex<long double>****) {}
#endif

#ifndef _RWSTD_NO_NAMESPACE
}
#endif
#endif

#ifdef _RWSTD_COMPILE_INSTANTIATE
#include <complex.cc>
#endif
        
#if defined(__DECCXX)
#   ifdef __PRAGMA_ENVIRONMENT
#      pragma __environment __restore
#   endif
#endif

#endif /* __STD_COMPLEX */
