By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
445,804 Members | 1,666 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 445,804 IT Pros & Developers. It's quick & easy.

arctan of complex number

P: n/a
Does anybody know an easy way to get the atan of a complex number in C++?
thanks,
marc

Jul 22 '05 #1
Share this Question
Share on Google+
8 Replies


P: n/a

"Marc Schellens" <m_*********@hotmail.com> wrote in message
news:3F**************@hotmail.com...
Does anybody know an easy way to get the atan of a complex number in C++?
thanks,
marc


Can you do it with pen and paper?

Jul 22 '05 #2

P: n/a
> "Marc Schellens" <m_*********@hotmail.com> wrote in message
news:3F**************@hotmail.com...
Does anybody know an easy way to get the atan of a complex number in C++?
thanks,
marc

Can you do it with pen and paper?


Thank you for this valuable reply!

Jul 22 '05 #3

P: n/a
Marc Schellens wrote:
Does anybody know an easy way to get the atan of a complex number in C++?
thanks,
marc


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.

Jul 22 '05 #4

P: n/a
Gianni Mariani wrote:
Marc Schellens wrote:
Does anybody know an easy way to get the atan of a complex number in C++?
thanks,
marc


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.


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);
}

But thanks anyway,
marc

Jul 22 '05 #5

P: n/a
Marc Schellens wrote:
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);
}


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.

Jul 22 '05 #6

P: n/a
Gianni Mariani wrote:
Marc Schellens wrote:
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);
}


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

Jul 22 '05 #7

P: n/a
"Marc Schellens" <m_*********@hotmail.com> wrote in message
news:3F**************@hotmail.com...
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


It's fast all right, just not terribly accurate.

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com
Jul 22 '05 #8

P: n/a
P.J. Plauger wrote:
"Marc Schellens" <m_*********@hotmail.com> wrote in message
news:3F**************@hotmail.com...

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

It's fast all right, just not terribly accurate.

What are you referring to ? atan2 ? rounding errors ? better
polynomial approximation ?

Jul 22 '05 #9

This discussion thread is closed

Replies have been disabled for this discussion.