M
Marc Schellens
Does anybody know an easy way to get the atan of a complex number in C++?
thanks,
marc
thanks,
marc
Marc Schellens said:Does anybody know an easy way to get the atan of a complex number in C++?
thanks,
marc
Marc Schellens said:Can you do it with pen and paper?
Marc said:Does anybody know an easy way to get the atan of a complex number in C++?
thanks,
marc
Gianni said:tan(cplx) = sin(cplx)/cos(cplx)
cplx= real + i*imag
sin(i*imag) = i * sinh(imag)
sinh(imag) = ( exp(imag) - exp(-imag) )/2
cos(i*imag) = cosh(imag)
cosh(imag) = ( exp(imag) + exp(-imag) )/2
then
sin(cplx) = sin(real)*cosh(imag) + sinh(imag)*cos(real)
cos(cplx) = cos(real)&cosh(imag) - sin(real)*sinh(imag)
so finally
tan( real + i * imag ) =
sin(real)*cosh(imag) + i * sinh(imag)*cos(real)
-----------------------------------------------
cos(real)&cosh(imag) - i * sin(real)*sinh(imag)
- this leads to this:
template <typename T>
std::complex<T> tan( const std::complex<T> & theta )
{
register T r = theta.real();
register T v = theta.imag();
T exp_v = exp(v);
T exp_mv = 1/exp_v; // same as exp(-v)
T cos_r = cos(r);
T cosh_v = ( exp_v + exp_mv ) / 2;
T sin_r = sin(r);
T sinh_v = ( exp_v - exp_mv ) / 2;
std::complex<T> numerator( sin_r*cosh_v, cos_r*sinh_v );
std::complex<T> denominator( cos_r*cosh_v, - sin_r*sinh_v );
return numerator / denominator;
}
- I didn't check it, I'll leave that exercise to you.
If performance is critical, I suspect that you can do better than this.
Marc said:Gianni Mariani wrote:
....
But that (performance, elegance) was my point.
As Dan already suggested so helpfully, I could do it myself,
but I thought that somebody might have a tested performant solution.
Actually I suspected, that there is a standard 'hack' how to do it very
easyly in C++ (as its not in the STL).
Anyway, so far I came up myself with this:
// atan() for complex
template< typename C>
inline C atanC(const C& c)
{
const C i(0.0,1.0);
const C one(1.0,0.0);
return log( (one + i * c) / (one - i * c)) / (C(2.0,0.0)*i);
}
Gianni said:OK - seems like I still need to learn to *read* - atan - not tan...hmmm.
I don't have my old texts on my shelf any more so I'll go with what
you've got (and it works ... atan( tan( c ) ) == c ). I suppose it's
easy enough to work out ...
template< typename T >
std::complex<T> atanC(const std::complex<T> & c)
{
register T real = c.real();
register T imag = c.imag();
std::complex<T> log_v =
log(
std::complex<T>( T(1) - imag, real )
/ std::complex<T>( T(1) + imag, - real )
);
return std::complex<T>(
log_v.imag() * T(1.0/2), - log_v.real() * T(1.0/2)
);
}
This one does one complex division and one "log(complex<T>)". Hence I
don't think you can make it much faster. A quick perf test shows that
it is about the modified one above is 30% faster (no inlining) than the
one in the original post.
A 1.2GHz AMD does 870K complex atan's per second.
That looks quite optimized.
Thanks,
marc
P.J. Plauger said:It's fast all right, just not terribly accurate.
Want to reply to this thread or ask your own question?
You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.