ccode atan2 generates nan

6 views (last 30 days)
Vincenzo Calabro
Vincenzo Calabro on 30 Aug 2017
Answered: Vincenzo Calabrò on 29 Jan 2019
Hi!
I have the following question related to the ccode function of the symbolic toolbox.
Let us consider the following piece of code:
syms a b real
ccode(atan2(a,b))
the result is:
' t0 = log((a*sqrt(-1.0)+b)/fabs(a*sqrt(-1.0)+b))*-sqrt(-1.0);'
Questions for the MathWorks:
1. Why ccode replace the atan2 function (which is available in c) with such log implementation?
2. There is a way to prevent such replacement (some additional optional parameter?)
The following Matlab script has been written to generate I/O pairs for the atan2 function to compare the output of the Matlab atan2 vs the C vs the ccode output:
p = -2:1:2;
[X,Y] = meshgrid(p,p);
Z = zeros(size(X));
for i=1:size(X,1)
for j=1:size(X,2)
Z(i,j) = atan2(Y(i,j),X(i,j));
end
end
And with those data I ran the following C code (Visual Studio)
#include "stdafx.h"
#include "math.h"
#include "complex.h"
double Atan2(double a, double b) {
return log((a*sqrt(-1.0) + b) / fabs(a*sqrt(-1.0) + b))*-sqrt(-1.0);
}
int main()
{
const unsigned int nTest = 25;
const double adX[nTest] = { -2.000000, -2.000000, -2.000000, -2.000000, -2.000000, -1.000000, -1.000000, -1.000000, -1.000000, -1.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 2.000000, 2.000000, 2.000000, 2.000000, 2.000000, };
const double adY[nTest] = { -2.000000, -1.000000, 0.000000, 1.000000, 2.000000, -2.000000, -1.000000, 0.000000, 1.000000, 2.000000, -2.000000, -1.000000, 0.000000, 1.000000, 2.000000, -2.000000, -1.000000, 0.000000, 1.000000, 2.000000, -2.000000, -1.000000, 0.000000, 1.000000, 2.000000, };
const double adZ[nTest] = { -2.356194, -2.677945, 3.141593, 2.677945, 2.356194, -2.034444, -2.356194, 3.141593, 2.356194, 2.034444, -1.570796, -1.570796, 0.000000, 1.570796, 1.570796, -1.107149, -0.785398, 0.000000, 0.785398, 1.107149, -0.785398, -0.463648, 0.000000, 0.463648, 0.785398, };
unsigned int nIdx = 0;
for (nIdx = 0; nIdx < nTest; nIdx++) {
printf("atan2(%+05.5f,%+05.5f)= Matlab(%+05.5f) C(%+05.5f) CCODE(%+05.5f)\n",
adY[nIdx], adX[nIdx],
adZ[nIdx],
atan2(adY[nIdx], adX[nIdx]),
Atan2(adY[nIdx], adX[nIdx]));
}
scanf("%d", &nIdx);
return 0;
}
The results are presented here:
atan2(-2.00000,-2.00000)= Matlab(-2.35619) C(-2.35619) CCODE(-nan(ind))
atan2(-1.00000,-2.00000)= Matlab(-2.67794) C(-2.67795) CCODE(-nan(ind))
atan2(+0.00000,-2.00000)= Matlab(+3.14159) C(+3.14159) CCODE(-nan(ind))
atan2(+1.00000,-2.00000)= Matlab(+2.67794) C(+2.67795) CCODE(-nan(ind))
atan2(+2.00000,-2.00000)= Matlab(+2.35619) C(+2.35619) CCODE(-nan(ind))
atan2(-2.00000,-1.00000)= Matlab(-2.03444) C(-2.03444) CCODE(-nan(ind))
atan2(-1.00000,-1.00000)= Matlab(-2.35619) C(-2.35619) CCODE(-nan(ind))
atan2(+0.00000,-1.00000)= Matlab(+3.14159) C(+3.14159) CCODE(-nan(ind))
atan2(+1.00000,-1.00000)= Matlab(+2.35619) C(+2.35619) CCODE(-nan(ind))
atan2(+2.00000,-1.00000)= Matlab(+2.03444) C(+2.03444) CCODE(-nan(ind))
atan2(-2.00000,+0.00000)= Matlab(-1.57080) C(-1.57080) CCODE(-nan(ind))
atan2(-1.00000,+0.00000)= Matlab(-1.57080) C(-1.57080) CCODE(-nan(ind))
atan2(+0.00000,+0.00000)= Matlab(+0.00000) C(+0.00000) CCODE(-nan(ind))
atan2(+1.00000,+0.00000)= Matlab(+1.57080) C(+1.57080) CCODE(-nan(ind))
atan2(+2.00000,+0.00000)= Matlab(+1.57080) C(+1.57080) CCODE(-nan(ind))
atan2(-2.00000,+1.00000)= Matlab(-1.10715) C(-1.10715) CCODE(-nan(ind))
atan2(-1.00000,+1.00000)= Matlab(-0.78540) C(-0.78540) CCODE(-nan(ind))
atan2(+0.00000,+1.00000)= Matlab(+0.00000) C(+0.00000) CCODE(-nan(ind))
atan2(+1.00000,+1.00000)= Matlab(+0.78540) C(+0.78540) CCODE(-nan(ind))
atan2(+2.00000,+1.00000)= Matlab(+1.10715) C(+1.10715) CCODE(-nan(ind))
atan2(-2.00000,+2.00000)= Matlab(-0.78540) C(-0.78540) CCODE(-nan(ind))
atan2(-1.00000,+2.00000)= Matlab(-0.46365) C(-0.46365) CCODE(-nan(ind))
atan2(+0.00000,+2.00000)= Matlab(+0.00000) C(+0.00000) CCODE(-nan(ind))
atan2(+1.00000,+2.00000)= Matlab(+0.46365) C(+0.46365) CCODE(-nan(ind))
atan2(+2.00000,+2.00000)= Matlab(+0.78540) C(+0.78540) CCODE(-nan(ind))
How can I fix this? Hoping to receive a valid answer asap.
Vincenzo

Answers (7)

Jan
Jan on 30 Aug 2017
Edited: Jan on 30 Aug 2017
There is no imaginary value for doubles in C. Then sqrt(-1.0) cannot be resolved with anything but NaN.
You are asking for atan2 in the title, but the symbolic expression contains atan. Is this a typo?
Questions for the MathWorks:
This is the public forum. If you want to ask MathWorks, use the "Contact Us" button on this page.

Vincenzo Calabro
Vincenzo Calabro on 30 Aug 2017
Edited: Vincenzo Calabro on 30 Aug 2017
Thanks to Jan Simon to highlight a typo.
The problem is still there and no valuable answer have been provided so far.
I hope someone will come forward with a solution to this bug.
  2 Comments
Karan Gill
Karan Gill on 30 Aug 2017
As Jan mentioned, to contact MathWorks, please use the "Contact Us" button at the top right of the page.
Jan
Jan on 30 Aug 2017
@Vincenzo: At least I can confirm that
log((a * 1i + b) / abs(a * 1i + b)) * -1i
calculates atan2, but only if complex numbers are used. Now you know, why the created C code fails. I consider this information and the hint to contact MathWorks directly as useful. Please post here, what they reply. Thanks.

Sign in to comment.


Vincenzo Calabro
Vincenzo Calabro on 21 Mar 2018
Matlab confirmed that is actually a bug and no estimate of time to fix has been provided during last contact I had.
Btw, I made an add-on for the symbolic toolbox (sym2code) in which I solved several bugs and I provided support for C/Mex/C#/Java/Python/LabVIEW targets as well ;)

Christophe Glinel
Christophe Glinel on 28 Jan 2019
I've the same issue with Matlab R2015b, is there is a fix now with the latest version ?

Vincenzo Calabrò
Vincenzo Calabrò on 28 Jan 2019
Edited: Vincenzo Calabrò on 28 Jan 2019
to the best of my knowledge the bug is still there. you should use a different code generator to avoid this issue. check for example this third party addon:

Vincenzo Calabrò
Vincenzo Calabrò on 28 Jan 2019
yes it is a cloud service to generate code from symbolic toolbox into C/C++/C#/Java/Python/Labview.
go to: cybertronics.cloud
to get more info and examples.
  1 Comment
Christophe Glinel
Christophe Glinel on 29 Jan 2019
I got an answer from mathworks support and it is fixed in matlab 2018a

Sign in to comment.


Vincenzo Calabrò
Vincenzo Calabrò on 29 Jan 2019
oh finally :)
good to know. btw sym2code offers more possibilities ;)

Categories

Find more on Signal Integrity Kits for Industry Standards in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!