13

I've reached the point in a project where it makes more sense to start building some support classes for vectors and misc trigonometry than keep using ad-hoc functions. I expect there to be many C++ libraries for this, but I don't want to sacrifice speed and features I am used to.

Specifically, I want to be able to use integer angles, and I want to keep the blazing speed afforded by approximations like this:

static inline int32_t sin_approx(int32_t angle)
//Angle is -32768 to 32767: Return -32768 to 32767
{
    return (angle<<1) - ((angle*abs(angle))>>14);
}

So, before I needlessly roll my own, are there any really fast fixed point libraries for c++ with template classes such as vectors where I can specify the width of the integer used and that has fast approximations such as the one above that I should look at?

porgarmingduod
  • 7,070
  • 7
  • 41
  • 76
  • How is that an approximation for sin? – TonyK Nov 18 '11 at 14:30
  • I honestly don't know. I wrote it a year ago based on a floating point sin approximation using, I'm guessing, some parabolic function. After wrangling it into integer, the above resulted. Having forgot the original function I have no idea how it works anymore. It draws an almost perfect circle though. – porgarmingduod Nov 18 '11 at 15:40
  • 2
    Oh, I see it now. It approximates each half of the range as a parabola with zeroes at 0 and 2, and max/min value +/-1. Nice! – TonyK Nov 18 '11 at 16:24
  • The comment in that code says it returns -32768 to 32767, but it actually returns more like -16384 to 16384. – James Clark Dec 17 '14 at 04:00

1 Answers1

4

I went down this path a few years ago when I had to convert some audio fingerprinting code from floating-point to fixed-point. The hard parts were the DCT (which used a large cosine table) and a high-precision logarithm. I found surprisingly little in the way of existing libraries. Since then, I have heard that the original Sony PlayStation (PS1) had no floating-point support, so development forums (fori?) for it, if they still exist, might have what you are looking for.

Some people I have worked with have had good luck with the NewMat library, though it is geared toward linear algebra rather than trigonometry, and seems to focus on floating-point numbers. Still, its site leads to this list, which looks to be worth checking out. I also found spuc, a signal processing library that might be good for fixed-point support. And years ago I saw a signal processing template library (sptl) from Fraunhofer. I think it was proprietary, but may be available somehow.

All that being said, I think you are pretty close with what you have already. Since you have a sine function, you basically also have a cosine function, provided you transform the input appropriately (cos(x) == sin(x + pi/2)). Since the tangent is the quotient of the sine and cosine (tan(x) = sin(x) / cos(x)) you are basically there for the trigonometry.

Regarding vectors, don't the STL vector and valarray classes combined with STL algorithms get you pretty close, too? If not, there's always Boost's math libraries.

Sorry I can't point you to the silver bullet you are looking for, but what you are trying to do is rather uncommon these days. People who want precision usually go straight to floating-point, which has decent performance on modern processors, and lots of library support. Those who want speed on resource-constrained hardware usually don't need precision and aren't doing trig by the vector, and probably aren't doing C++ either. I think your best option is to roll your own. Try to think of it as applying the wheel design pattern in a new context, rather than reinventing it. :)

Randall Cook
  • 6,320
  • 4
  • 28
  • 65
  • Lots of good information, really. I am shocked to see I missed boost's geometry library (although it might be overkill in any case) – porgarmingduod Nov 22 '11 at 09:52