Search code examples
c++performancenumberscomplex-numbersatan2

Precision of cos(atan2(y,x)) versus using complex <double>, C++


I'm writing some coordinate transformations (more specifically the Joukoswky Transform, Wikipedia Joukowsky Transform), and I'm interested in performance, but of course precision. I'm trying to do the coordinate transformations in two ways:

1) Calculating the real and complex parts in separate, using double precision, as below:

double r2 = chi.x*chi.x + chi.y*chi.y;

//double sq = pow(r2,-0.5*n) + pow(r2,0.5*n); //slow!!!
double sq = sqrt(r2); //way faster!
double co = cos(atan2(chi.y,chi.x));
double si = sin(atan2(chi.y,chi.x));

Z.x = 0.5*(co*sq + co/sq);
Z.y = 0.5*si*sq;

where chi and Z are simple structures with double x and y as members.

2) Using complex :

Z = 0.5 * (chi + (1.0 / chi));

Where Z and chi are complex . There interesting part is that indeed the case 1) is faster (about 20%), but the precision is bad, giving error in the third decimal number after the comma after the inverse transform, while the complex gives back the exact number. So, the problem is on the cos(atan2), sin(atan2)? But if it is, how the complex handles that?

EDIT: Just figured out that this was not exactly the question that I had in mind. I have to do the general transformation, as

Z = 1/2*(chi^n + (1/chi)^n), and so far the code above was the way I've figured to do it. More precisely,

    double sq = pow(sqrt(r2),n); //way faster!
double co = cos(n*atan2(chi.y,chi.x));
double si = sin(n*atan2(chi.y,chi.x));

Z.x = 0.5*(co*sq + co/sq);
Z.y = 0.5*(si*sq - sq/si);

Also correcting the bug on Z.y.


Solution

  • I think that in 1) it should be

    Z.y = 0.5*(si*sq - si/sq);
    

    If you want really good performance you may want to go back to first principles and observe that

    1/(a+ib) = (a-ib)/(a*a+b*b)
    

    No sqrt(), atan2() or cos() or sin().