Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ library for integer trigonometry, speed optimized with optional approximations?

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?

like image 317
porgarmingduod Avatar asked Nov 18 '11 13:11

porgarmingduod


1 Answers

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. :)

like image 74
Randall Cook Avatar answered Oct 20 '22 13:10

Randall Cook