181 lines
5.3 KiB
C++
181 lines
5.3 KiB
C++
// -*- C++ -*-
|
|
/***************************************************************************
|
|
*
|
|
* complex.cc - definitions of the template complex and specializations
|
|
*
|
|
* $Id: complex.cc 590060 2007-10-30 13:12:23Z faridz $
|
|
*
|
|
***************************************************************************
|
|
*
|
|
* 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
|