445,804 Members | 1,666 Online
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
8 Replies

 P: n/a "Marc Schellens" 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" 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 std::complex tan( const std::complex & 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 numerator( sin_r*cosh_v, cos_r*sinh_v ); std::complex 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 std::complex tan( const std::complex & 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 numerator( sin_r*cosh_v, cos_r*sinh_v ); std::complex 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 atanC(const std::complex & c) { register T real = c.real(); register T imag = c.imag(); std::complex log_v = log( std::complex( T(1) - imag, real ) / std::complex( T(1) + imag, - real ) ); return std::complex( log_v.imag() * T(1.0/2), - log_v.real() * T(1.0/2) ); } This one does one complex division and one "log(complex)". 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 atanC(const std::complex & c) { register T real = c.real(); register T imag = c.imag(); std::complex log_v = log( std::complex( T(1) - imag, real ) / std::complex( T(1) + imag, - real ) ); return std::complex( log_v.imag() * T(1.0/2), - log_v.real() * T(1.0/2) ); } This one does one complex division and one "log(complex)". 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" wrote in message news:3F**************@hotmail.com... This one does one complex division and one "log(complex)". 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" wrote in message news:3F**************@hotmail.com...This one does one complex division and one "log(complex)". Hence Idon't think you can make it much faster. A quick perf test shows thatit is about the modified one above is 30% faster (no inlining) than theone 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.