blob: e1dfa5698b917d8394951121652ed4a8bf80f785 [file] [log] [blame]
// -*- C++ -*-
/***************************************************************************
*
* <complex> - definitions of the template complex and specializations
*
* $Id$
*
***************************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*
* Copyright 2000-2007 Rogue Wave Software, Inc.
*
**************************************************************************/
#ifndef _RWSTD_COMPLEX_INCLUDED
#define _RWSTD_COMPLEX_INCLUDED
#include <sstream>
#include <iosfwd>
#include <utility>
#include <rw/_defs.h>
#include _RWSTD_CMATH
#ifdef _RWSTD_MSVC
# pragma warning (push)
// disable conversion from 'double' to 'float', possible loss of data
// until a conforming <cmath> header with float and long double overloads
// for the C functions is provided
# pragma warning (disable: 4244)
#endif // _RWSTD_MSVC
_RWSTD_NAMESPACE (std) {
// 26.2.2
template <class _TypeT>
class complex;
// 26.2.3
_RWSTD_SPECIALIZED_CLASS
class complex<float>;
// 26.2.3
_RWSTD_SPECIALIZED_CLASS
class complex<double>;
#ifndef _RWSTD_NO_LONG_DOUBLE
// 26.2.3
_RWSTD_SPECIALIZED_CLASS
class complex<long double>;
#endif // _RWSTD_NO_LONG_DOUBLE
// 26.2.6 complex non-member operations (used from within member functions)
// 26.2.6, p7
template <class _TypeT>
inline complex<_TypeT>
operator* (const complex<_TypeT> &__lhs, const complex<_TypeT> &__rhs)
{
return complex<_TypeT>(_TypeT ( __lhs.real () * __rhs.real ()
- __lhs.imag () * __rhs.imag ()),
_TypeT ( __lhs.imag () * __rhs.real ()
+ __lhs.real () * __rhs.imag ()));
}
// 26.2.6, p8
template <class _TypeT>
inline complex<_TypeT>
operator/ (const complex<_TypeT> &__lhs, const complex<_TypeT> &__rhs)
{
_TypeT __den = __rhs.real() * __rhs.real() + __rhs.imag() * __rhs.imag();
return complex<_TypeT>(_TypeT ( __lhs.real () * __rhs.real ()
+ __lhs.imag () * __rhs.imag ()) / __den,
_TypeT ( __lhs.imag () * __rhs.real ()
- __lhs.real () * __rhs.imag ()) / __den);
}
// 26.2.3 - complex specializations
_RWSTD_SPECIALIZED_CLASS
class complex<float>
{
public:
typedef float value_type;
// implicit conversion
complex (value_type __re = value_type (), value_type __im = value_type ())
: _C_re (__re), _C_im (__im) { }
// defined after the definition of the incomplete complex<double>
explicit complex (const complex<double>&);
#ifndef _RWSTD_NO_LONG_DOUBLE
// defined after the definition of the incomplete complex<long double>
explicit complex (const complex<long double>&);
#endif // _RWSTD_NO_LONG_DOUBLE
value_type imag () const {
return _C_im;
}
value_type real () const {
return _C_re;
}
#if defined (_COMPILER_VERSION) && _COMPILER_VERSION <= 730
// working around a MIPSpro 7.3.1 bug (SGI serial #0800690BCFC2)
complex<value_type>& operator= (const complex<value_type>& __rhs) {
return (_C_re = __rhs._C_re), (_C_im = __rhs._C_im), *this;
}
#endif // _COMPILER_VERSION <= 730
template <class _TypeT>
complex& operator= (const complex<_TypeT>& __rhs) {
return (_C_re = __rhs.real ()), (_C_im = __rhs.imag ()), *this;
}
template <class _TypeX>
complex<value_type>& operator+= (const complex<_TypeX> &__rhs) {
return (_C_re += __rhs.real ()), (_C_im += __rhs.imag ()), *this;
}
template <class _TypeX>
complex<value_type>& operator-= (const complex<_TypeX> &__rhs) {
return (_C_re -= __rhs.real ()), (_C_im -= __rhs.imag ()), *this;
}
template <class _TypeX>
complex<value_type>& operator*= (const complex<_TypeX> &__rhs) {
return *this = *this * complex<value_type>(__rhs);
}
template <class _TypeX>
complex<value_type>& operator/= (const complex<_TypeX> &__rhs) {
return *this = *this / complex<value_type>(__rhs);
}
complex<value_type>& operator= (value_type __rhs) {
return (_C_re = __rhs), (_C_im = value_type ()), *this;
}
complex<value_type>& operator+= (value_type __rhs) {
return _C_re += __rhs, *this;
}
complex<value_type>& operator-= (value_type __rhs) {
return _C_re -= __rhs, *this;
}
complex<value_type>& operator*= (value_type __rhs) {
return (_C_re *= __rhs), (_C_im *= __rhs), *this;
}
complex<value_type>& operator/= (value_type __rhs) {
return (_C_re /= __rhs), (_C_im /= __rhs), *this;
}
private:
value_type _C_re, _C_im;
};
_RWSTD_SPECIALIZED_CLASS
class complex<double>
{
public:
typedef double value_type;
// implicit conversion
complex (value_type __re = value_type (), value_type __im = value_type ())
: _C_re (__re), _C_im (__im) { }
// implicit conversion
complex (const complex<float> &__rhs)
: _C_re (__rhs.real ()), _C_im (__rhs.imag ()) { }
#ifndef _RWSTD_NO_LONG_DOUBLE
// defined after the definition of the incomplete complex<long double>
explicit complex (const complex<long double>&);
#endif // _RWSTD_NO_LONG_DOUBLE
value_type imag () const {
return _C_im;
}
value_type real () const {
return _C_re;
}
#if defined (_COMPILER_VERSION) && _COMPILER_VERSION <= 730
// working around a MIPSpro 7.3.1 bug (SGI serial #0800690BCFC2)
complex<value_type>& operator= (const complex<value_type>& __rhs) {
return (_C_re = __rhs._C_re), (_C_im = __rhs._C_im), *this;
}
#endif // _COMPILER_VERSION <= 730
template <class _TypeT>
complex& operator= (const complex<_TypeT>& __rhs) {
return (_C_re = __rhs.real ()), (_C_im = __rhs.imag ()), *this;
}
template <class _TypeX>
complex<value_type>& operator+= (const complex<_TypeX> &__rhs) {
return (_C_re += __rhs.real ()), (_C_im += __rhs.imag ()), *this;
}
template <class _TypeX>
complex<value_type>& operator-= (const complex<_TypeX> &__rhs) {
return (_C_re -= __rhs.real ()), (_C_im -= __rhs.imag ()), *this;
}
template <class _TypeX>
complex<value_type>& operator*= (const complex<_TypeX> &__rhs) {
return *this = *this * complex<value_type>(__rhs);
}
template <class _TypeX>
complex<value_type>& operator/= (const complex<_TypeX> &__rhs) {
return *this = *this / complex<value_type>(__rhs);
}
complex<value_type>& operator= (value_type __rhs) {
return (_C_re = __rhs), (_C_im = value_type ()), *this;
}
complex<value_type>& operator+= (value_type __rhs) {
return _C_re += __rhs, *this;
}
complex<value_type>& operator-= (value_type __rhs) {
return _C_re -= __rhs, *this;
}
complex<value_type>& operator*= (value_type __rhs) {
return (_C_re *= __rhs), (_C_im *= __rhs), *this;
}
complex<value_type>& operator/= (value_type __rhs) {
return (_C_re /= __rhs), (_C_im /= __rhs), *this;
}
private:
value_type _C_re, _C_im;
};
#ifndef _RWSTD_NO_LONG_DOUBLE
_RWSTD_SPECIALIZED_CLASS
class complex<long double>
{
public:
typedef long double value_type;
// implicit conversion
complex (value_type __re = value_type (), value_type __im = value_type ())
: _C_re (__re), _C_im (__im) { }
// implicit conversion
complex (const complex<float> &__rhs)
: _C_re (__rhs.real ()), _C_im (__rhs.imag ()) { }
// implicit conversion
complex (const complex<double> &__rhs)
: _C_re (__rhs.real ()), _C_im (__rhs.imag ()) { }
value_type imag () const {
return _C_im;
}
value_type real () const {
return _C_re;
}
template <class _TypeX>
complex<value_type>& operator+= (const complex<_TypeX> &__rhs) {
return (_C_re += __rhs.real ()), (_C_im += __rhs.imag ()), *this;
}
template <class _TypeX>
complex<value_type>& operator-= (const complex<_TypeX> &__rhs) {
return (_C_re -= __rhs.real ()), (_C_im -= __rhs.imag ()), *this;
}
template <class _TypeX>
complex<value_type>& operator*= (const complex<_TypeX> &__rhs) {
return *this = *this * complex<value_type>(__rhs);
}
template <class _TypeX>
complex<value_type>& operator/= (const complex<_TypeX> &__rhs) {
return *this = *this / complex<value_type>(__rhs);
}
#if defined (_COMPILER_VERSION) && _COMPILER_VERSION <= 730
// working around a MIPSpro 7.3.1 bug (SGI serial #0800690BCFC2)
complex<value_type>& operator= (const complex<value_type>& __rhs) {
return (_C_re = __rhs._C_re), (_C_im = __rhs._C_im), *this;
}
#endif // _COMPILER_VERSION <= 730
template <class _TypeT>
complex& operator= (const complex<_TypeT>& __rhs) {
return (_C_re = __rhs.real ()), (_C_im = __rhs.imag ()), *this;
}
complex& operator+= (value_type __rhs) {
return _C_re += __rhs, *this;
}
complex& operator-= (value_type __rhs) {
return _C_re -= __rhs, *this;
}
complex& operator*= (value_type __rhs) {
return (_C_re *= __rhs), (_C_im *= __rhs), *this;
}
complex& operator/= (value_type __rhs) {
return (_C_re /= __rhs), (_C_im /= __rhs), *this;
}
private:
value_type _C_re, _C_im;
};
#endif // _RWSTD_NO_LONG_DOUBLE
inline complex<float>::complex (const complex<double> &__rhs)
: _C_re (_RWSTD_STATIC_CAST (value_type, __rhs.real ())),
_C_im (_RWSTD_STATIC_CAST (value_type, __rhs.imag ()))
{ }
#ifndef _RWSTD_NO_LONG_DOUBLE
inline complex<float>::complex (const complex<long double> &__rhs)
: _C_re (_RWSTD_STATIC_CAST (value_type, __rhs.real ())),
_C_im (_RWSTD_STATIC_CAST (value_type, __rhs.imag ()))
{ }
inline complex<double>::complex (const complex<long double> &__rhs)
: _C_re (_RWSTD_STATIC_CAST (value_type, __rhs.real ())),
_C_im (_RWSTD_STATIC_CAST (value_type, __rhs.imag ()))
{ }
#endif // _RWSTD_NO_LONG_DOUBLE
// 26.2.2
template <class _TypeT>
class complex
{
public:
typedef _TypeT value_type;
complex (const value_type &__re = value_type (),
const value_type &__im = value_type ())
: _C_re (__re), _C_im (__im) { }
value_type imag () const {
return _C_im;
}
value_type real () const {
return _C_re;
}
template <class _TypeU>
complex (const complex<_TypeU>& __rhs)
: _C_re (_RWSTD_STATIC_CAST (value_type, __rhs.real ())),
_C_im (_RWSTD_STATIC_CAST (value_type, __rhs.imag ())) { }
template <class _TypeU>
complex& operator= (const complex<_TypeU>& __rhs) {
// not recursive: calls the compiler-generated operator=()
return *this = complex (__rhs);
}
template <class _TypeX>
complex<value_type>& operator+= (const complex<_TypeX> &__rhs) {
return *this = *this + __rhs;
}
template <class _TypeX>
complex<value_type>& operator-= (const complex<_TypeX> &__rhs) {
return *this = *this - __rhs;
}
template <class _TypeX>
complex<value_type>& operator*= (const complex<_TypeX> &__rhs) {
return *this = *this * __rhs;
}
template <class _TypeX>
complex<value_type>& operator/= (const complex<_TypeX> &__rhs) {
return *this = *this / __rhs;
}
complex& operator= (value_type __rhs) {
return (_C_re = __rhs), (_C_im = value_type ()), *this;
}
complex& operator+= (value_type __rhs) {
return _C_re += __rhs, *this;
}
complex& operator-= (value_type __rhs) {
return _C_re -= __rhs, *this;
}
complex& operator*= (value_type __rhs) {
return (_C_re *= __rhs), (_C_im *= __rhs), *this;
}
complex& operator/= (value_type __rhs) {
return (_C_re /= __rhs), (_C_im /= __rhs), *this;
}
private:
value_type _C_re, _C_im;
};
// 26.2.6 complex non-member operations
// 26.2.6, p1
template <class _TypeT>
inline complex<_TypeT>
operator+ (const complex<_TypeT> &__rhs)
{
return __rhs;
}
// 26.2.6, p3
template <class _TypeT>
inline complex<_TypeT>
operator+ (const complex<_TypeT> &__lhs, const complex<_TypeT> &__rhs)
{
return complex<_TypeT>(_TypeT (__lhs.real () + __rhs.real ()),
_TypeT (__lhs.imag () + __rhs.imag ()));
}
template <class _TypeT>
inline complex<_TypeT>
operator+ (const complex<_TypeT> &__lhs, const _TypeT &__rhs)
{
return complex<_TypeT>(__lhs.real () + __rhs, __lhs.imag ());
}
template <class _TypeT>
inline complex<_TypeT>
operator+ (const _TypeT &__lhs, const complex<_TypeT> &__rhs)
{
return __rhs + __lhs;
}
// 26.2.6, p4
template <class _TypeT>
inline complex<_TypeT>
operator- (const complex<_TypeT> &__rhs)
{
return complex<_TypeT>(-__rhs.real (), -__rhs.imag ());
}
// 26.2.6, p6
template <class _TypeT>
inline complex<_TypeT>
operator- (const complex<_TypeT> &__lhs, const complex<_TypeT> &__rhs)
{
return complex<_TypeT>(_TypeT (__lhs.real () - __rhs.real ()),
_TypeT (__lhs.imag () - __rhs.imag ()));
}
template <class _TypeT>
inline complex<_TypeT>
operator- (const complex<_TypeT> &__lhs, const _TypeT &__rhs)
{
return complex<_TypeT>(__lhs.real () - __rhs, __lhs.imag ());
}
template <class _TypeT>
inline complex<_TypeT>
operator- (const _TypeT &__lhs, const complex<_TypeT> &__rhs)
{
return complex<_TypeT>(__lhs - __rhs.real (), - __rhs.imag ());
}
// 26.2.6, p7
template <class _TypeT>
inline complex<_TypeT>
operator* (const complex<_TypeT> &__lhs, const _TypeT &__rhs)
{
return complex<_TypeT>(__lhs.real () * __rhs, __lhs.imag () * __rhs);
}
template <class _TypeT>
inline complex<_TypeT>
operator* (const _TypeT &__lhs, const complex<_TypeT> &__rhs)
{
return __rhs * __lhs;
}
// 26.2.6, p8
template <class _TypeT>
inline complex<_TypeT>
operator/ (const complex<_TypeT> &__lhs, const _TypeT &__rhs)
{
return complex<_TypeT>(__lhs.real () / __rhs,
__lhs.imag () / __rhs);
}
template <class _TypeT>
inline complex<_TypeT>
operator/ (const _TypeT &__lhs, const complex<_TypeT> &__rhs)
{
_TypeT __den = __rhs.real() * __rhs.real() + __rhs.imag() * __rhs.imag();
return complex<_TypeT>(_TypeT (__lhs * __rhs.real ()) / __den,
-_TypeT (__lhs * __rhs.imag ()) / __den);
}
// 26.2.6, p9
template <class _TypeT>
inline bool
operator== (const complex<_TypeT> &__lhs, const complex<_TypeT> &__rhs)
{
return __lhs.real () == __rhs.real () && __lhs.imag () == __rhs.imag ();
}
template <class _TypeT>
inline bool operator== (const complex<_TypeT> &__lhs, const _TypeT &__rhs)
{
return __lhs.real () == __rhs && __lhs.imag () == _TypeT ();
}
template <class _TypeT>
inline bool operator== (const _TypeT &__lhs, const complex<_TypeT> &__rhs)
{
return __rhs == __lhs;
}
// 26.2.6, p11
template <class _TypeT>
inline bool
operator!= (const complex<_TypeT> &__lhs, const complex<_TypeT> &__rhs)
{
return !(__lhs == __rhs);
}
template <class _TypeT>
inline bool operator!= (const complex<_TypeT> &__lhs, const _TypeT &__rhs)
{
return !(__lhs == __rhs);
}
template <class _TypeT>
inline bool operator!= (const _TypeT &__lhs, const complex<_TypeT> &__rhs)
{
return !(__lhs == __rhs);
}
// 26.2.7 - complex value operations
// 26.2.7, p1
template<class _TypeT>
inline _TypeT real (const complex<_TypeT> &__a)
{
return __a.real ();
}
// 26.2.7, p2
template<class _TypeT>
inline _TypeT imag (const complex<_TypeT> &__a)
{
return __a.imag ();
}
// 26.2.7, p3
template <class _TypeT>
inline _TypeT abs (const complex<_TypeT> &__a)
{
return _RWSTD_C::sqrt (norm (__a));
}
// 26.2.7, p4
template <class _TypeT>
inline _TypeT arg (const complex<_TypeT>& __a)
{
// guarantee that arg (complex<T>()) == 0
return __a == complex<_TypeT>() ? _TypeT ()
: _RWSTD_C::atan2 (__a.imag (), __a.real ());
}
// 26.2.7, p5
template <class _TypeT>
inline _TypeT norm (const complex<_TypeT> &__a)
{
return __a.real () * __a.real () + __a.imag () * __a.imag ();
}
// 26.2.7, p6
template <class _TypeT>
inline complex<_TypeT> conj (const complex<_TypeT> &__a)
{
return complex<_TypeT>(__a.real (), -__a.imag ());
}
// 26.2.7, p7, lwg issue 79
template <class _TypeT>
inline complex<_TypeT> polar (const _TypeT &__rho,
const _TypeT &__theta = _TypeT ())
{
return complex<_TypeT>(__rho * _RWSTD_C::cos (__theta),
__rho * _RWSTD_C::sin (__theta));
}
// 26.2.8 - complex transcendentals
// complex cosine of complex number `a'
// cos (a) = cos u * cosh v - i * sin u * sinh v
template <class _TypeT>
inline complex<_TypeT> cos (const complex<_TypeT>& __a)
{
return complex<_TypeT>( _RWSTD_C::cos (__a.real ())
* _RWSTD_C::cosh (__a.imag ()),
-_RWSTD_C::sin (__a.real ())
* _RWSTD_C::sinh (__a.imag ()));
}
// complex hyperbolic cosine of complex number `a'
// cosh (a) = cosh u * cosv + i * sinh u * sin v
template <class _TypeT>
inline complex<_TypeT> cosh (const complex<_TypeT>& __a)
{
return complex<_TypeT>( _RWSTD_C::cosh (__a.real ())
* _RWSTD_C::cos (__a.imag ()),
_RWSTD_C::sinh (__a.real ())
* _RWSTD_C::sin (__a.imag ()));
}
// complex exponential of complex number `a'
// exp (a) = exp(u) * (cos v + i * sin v)
template <class _TypeT>
inline complex<_TypeT> exp (const complex<_TypeT>& __a)
{
_TypeT __e = _RWSTD_C::exp (__a.real ());
return complex<_TypeT>(__e * _RWSTD_C::cos (__a.imag ()),
__e * _RWSTD_C::sin (__a.imag ()));
}
// complex<T> natural log of complex<T> number `a'
// log (a) = log(r) + i * theta
template <class _TypeT>
inline complex<_TypeT> log (const complex<_TypeT>& __a)
{
return complex<_TypeT>(_RWSTD_C::log (abs (__a)), arg (__a));
}
template <class _TypeT>
complex<_TypeT> log10 (const complex<_TypeT>&);
//
// For all the power functions:
//
// 0**0 == 1
// 0**x == 0 for x != 0
//
// complex number `a' raised to an integer power `n'
// a**n = r**n * (cos(n theta) + i sin (n theta))
_EXPORT
template <class _TypeT>
complex<_TypeT>
pow (const complex<_TypeT>&, int);
// complex number `a' raised to a real power `s'
// a**s = exp(s * log(a))
_EXPORT
template <class _TypeT>
complex<_TypeT>
pow (const complex<_TypeT>&, const _TypeT&);
// real number `s' raised to a complex power `a'
// s**a = exp(a * log (s))
_EXPORT
template <class _TypeT>
complex<_TypeT>
pow (const _TypeT&, const complex<_TypeT>&);
// 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
_EXPORT
template <class _TypeT>
complex<_TypeT>
pow (const complex<_TypeT>&, const complex<_TypeT>&);
// complex<T> sine of complex<T> number `a'
// sin (a) = sin u * cosh v + i * cos u * sinh v
template <class _TypeT>
inline complex<_TypeT> sin (const complex<_TypeT>& __a)
{
return complex<_TypeT>( _RWSTD_C::sin (__a.real ())
* _RWSTD_C::cosh (__a.imag ()),
_RWSTD_C::cos (__a.real ())
* _RWSTD_C::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 _TypeT>
inline complex<_TypeT> sinh (const complex<_TypeT>& __a)
{
return complex<_TypeT>( _RWSTD_C::sinh (__a.real ())
* _RWSTD_C::cos (__a.imag ()),
_RWSTD_C::cosh (__a.real ())
* _RWSTD_C::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 _TypeT>
inline complex<_TypeT> sqrt (const complex<_TypeT>& __a)
{
_TypeT __r = _RWSTD_C::sqrt(abs(__a));
_TypeT __th = arg (__a) / _TypeT (2.0);
return complex<_TypeT>(__r * _RWSTD_C::cos (__th),
__r * _RWSTD_C::sin (__th));
}
template <class _TypeT>
inline complex<_TypeT> tan (const complex<_TypeT>& __a)
{
return complex<_TypeT>(sin (__a) / cos (__a));
}
template <class _TypeT>
inline complex<_TypeT> tanh (const complex<_TypeT>& __a)
{
return complex<_TypeT>(sinh (__a) / cosh (__a));
}
template <class _TypeT>
inline complex<_TypeT> log10 (const complex<_TypeT>& __a)
{
const _TypeT __log10e = _TypeT (0.4342944819032518276511289189166051L);
return __log10e * log (__a);
}
// 26.2.6, p12: MT-safe extractor (not atomic)
_EXPORT
template <class _TypeT, class _CharT, class _Traits>
basic_istream<_CharT, _Traits >&
operator>> (basic_istream<_CharT, _Traits>&, complex<_TypeT>&);
// 26.2.6, p15: MT-safe atomic inserter
_EXPORT
template <class _TypeT, class _CharT, class _Traits>
basic_ostream<_CharT, _Traits>&
operator<< (basic_ostream<_CharT, _Traits>&, const complex<_TypeT>&);
} // namespace std
#ifdef _RWSTD_MSVC
# pragma warning (pop)
#endif // _RWSTD_MSVC
#if _RWSTD_DEFINE_TEMPLATE (_COMPLEX)
# include <complex.cc>
#endif // _RWSTD_DEFINE_TEMPLATE (_BASIC_OSTREAM)
#endif // _RWSTD_COMPLEX_INCLUDED