I want to do fixed point math in C++, so I looked for a suitable library. libfixmath
has been suggested here a couple of times, but I have difficulties with the atan2
function it provides. My test code calculates sine and cosine of an angle and then recalculates that angle using atan2
:
#include <cmath>
#include <fstream>
#include <iostream>
#include <fix16.h>
#include <fix16.hpp>
int main()
{
unsigned int n = 1000;
std::ofstream atan2File("atan2.dat");
for(unsigned int i = 0; i <= n; i++)
{
double d = M_PI/2.*i/n;
double s = sin(d);
double c = cos(d);
double a = atan2(s,c);
Fix16 df(d);
Fix16 sf(df.sin());
Fix16 cf(df.cos());
Fix16 af(sf.atan2(cf));
atan2File << d
<< " " << a
<< " " << (double)af
<< std::endl;
}
return 0;
}
Here is the plotted result:
It was generated with gnuplot
using
plot "atan2.dat" u 1:2 w l title 'double', "atan2.dat" u 1:3 w l title 'Fix16'
Some values near zero and pi/2 are reasonable, but a lot are not. The code seems to use this algorithm for calculating atan2
, but I couldn't spot where it might fail in the way shown above.
- Does anyone know of a possible bug in the
libfixmath
code? - Is there an alternative library that provides trigonometric functions for fixed point values? I need sine, cosine, tangent and their inverse.
I could, of course, try to add the missing functions to other suggested fixed point libraries, but I don't have any experience in writing code for fixed point types.
gcc -v: gcc version 4.7.2 20130108 [gcc-4_7-branch revision 195012] (SUSE Linux)
I need fixed point because I want to do these calculations on a Cortex-M4 (no FPU). Actually I already had libfixmath
in my Cortex-M4 code, but it has shown errors like those described above. OTOH, it was about 10 times as fast as the float
version. I'd like to add more or less correct results to that speed.