3

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: enter image description here

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.

Christoph
  • 1,040
  • 3
  • 14
  • 29
  • Not reproducible for me with gcc-4.4.3 or clang-3.5 with gcc's stdlib. – Benjamin Bannier Feb 04 '14 at 13:23
  • Just to clarify *not reproducible*: I see a mostly smooth deviation of libfixmath's `atan2` as a function `phi` which is about 20% above the stdlib version at the very lowest `phi`. That deviation drops below 1% above `phi=0.4`. – Benjamin Bannier Feb 04 '14 at 13:31
  • hm....I'll try to produce a file using the Cortex-M4 code later and see how that actually looks. How are those 20% defined? – Christoph Feb 04 '14 at 13:34
  • Relative to the stdlib version, `(fixed-stdlib)/stdlib`. Note that that 20% is a small absolute number. – Benjamin Bannier Feb 04 '14 at 13:35
  • So in terms of the above you calculated `((double)af-a)/a`? To me it's kinda scary that this behavior couldn't be reproduced by you. Could any compiler flags have caused this? – Christoph Feb 04 '14 at 13:46
  • Yes, that's what I calculated. I used the standard C(XX)FLAGS in `libfixmath/Makefile`, both to build the archive and the test case. – Benjamin Bannier Feb 04 '14 at 14:08
  • I'm using Code::Blocks 13.12 and the compiler is executed with `gcc -Wextra -Wall -DFIXMATH_NO_CACHE -O2`, so the only difference compared to the makefile is no caching (can't do that on my actual target due to limited RAM). – Christoph Feb 04 '14 at 14:14
  • Did you ever come right with this? I've been planning to use libfixmath for a while, across different platforms. Don't need things like this biting me! – Engineer Jun 11 '16 at 15:19

0 Answers0