blob: 46a95ffd25337fb8478d17481b50e45aa5b5021d [file] [log] [blame]
// -*- C++ -*-
/***************************************************************************
*
* complex.cc - 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-2006 Rogue Wave Software.
*
**************************************************************************/
_RWSTD_NAMESPACE (std) {
// 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>& __a, int __n)
{
if (__a == complex<_TypeT>())
return complex<_TypeT>(0 == __n);
if (_TypeT () == __a.imag ()) {
if (__a.real () < _TypeT ())
return pow (__a, complex<_TypeT>(__n));
return complex<_TypeT>(_RWSTD_C::pow (__a.real (), __n));
}
_TypeT __r = _RWSTD_C::pow (_TypeT (abs (__a)), __n);
_TypeT __th = __n * arg (__a);
return complex<_TypeT>(__r * _RWSTD_C::cos (__th),
__r * _RWSTD_C::sin (__th));
}
// 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> &__a, const _TypeT &__s)
{
if (__a == complex<_TypeT>())
return complex<_TypeT>(_TypeT () == __s);
if (_TypeT () == __a.imag ()) {
if (__a.real () < _TypeT ())
return pow (__a, complex<_TypeT>(__s));
return complex<_TypeT>(_RWSTD_C::pow (__a.real (), __s));
}
return exp (__s * log (__a));
}
// real number `s' raised to a complex power `a'
// s**a = exp(a * log (s))
_EXPORT
template <class _TypeT>
complex<_TypeT>
pow (const _TypeT& __s, const complex<_TypeT>& __a)
{
if (_TypeT() == __s)
return complex<_TypeT>(complex<_TypeT>() == __a);
if (__s < _TypeT ())
return pow (complex<_TypeT>(__s), __a);
if (_TypeT () == __a.imag ())
return complex<_TypeT>(_RWSTD_C::pow (__s, __a.real ()));
return complex<_TypeT>(exp(__a * _TypeT (_RWSTD_C::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
_EXPORT
template <class _TypeT>
complex<_TypeT>
pow (const complex<_TypeT>& __x, const complex<_TypeT>& __y)
{
if (complex<_TypeT>() == __x)
return complex<_TypeT>(complex<_TypeT>() == __y);
_TypeT __r1 = abs (__x);
_TypeT __u2 = real (__y);
_TypeT __v2 = imag (__y);
_TypeT __th1 = arg (__x);
_TypeT __rho = _RWSTD_C::pow (__r1, __u2) * _RWSTD_C::exp (-__v2 * __th1);
_TypeT __phi = __v2 * _RWSTD_C::log (__r1) + __u2 * __th1;
return complex<_TypeT>(__rho * _RWSTD_C::cos (__phi),
__rho * _RWSTD_C::sin (__phi));
}
_EXPORT
template <class _TypeT, class _CharT, class _Traits>
basic_istream<_CharT, _Traits >&
operator>> (basic_istream<_CharT, _Traits>& __strm, complex<_TypeT> &__val)
{
// read a complex number in one of the following forms:
// "r", "(r)", "(r, i)"
// lwg issue 156: extraction is performed as a series of simpler
// extractions. Therefore, the skipping of whitespace is specified
// to be the same for each of the simpler extractions.
_TypeT __re = _TypeT (),
__im = _TypeT ();
_CharT __ch;
if (!(__strm >> __ch))
return __strm;
if ('(' == __ch) {
if (__strm >> __re && __strm >> __ch) {
if (',' == __ch && __strm >> __im)
__strm >> __ch;
// avoid setting failbit if either badbit
// or failbit is already set in the stream
if (')' != __ch && __strm)
__strm.setstate (__strm.failbit);
}
}
else if (__strm.putback (__ch)) {
__strm >> __re;
}
if (__strm)
__val = complex<_TypeT>(__re, __im);
return __strm;
}
_EXPORT
template <class _TypeT, class _CharT, class _Traits>
basic_ostream<_CharT, _Traits>&
operator<< (basic_ostream<_CharT, _Traits >& __strm,
const complex<_TypeT>& __val)
{
basic_ostringstream<_CharT, _Traits, allocator<_CharT> > __ss;
__ss.flags (__strm.flags ());
__ss.imbue (__strm.getloc ());
__ss.precision (__strm.precision ());
__ss << '(' << __val.real () << ',' << __val.imag () << ')';
return __strm << __ss.str ();
}
} // namespace std