views:

345

answers:

4

I have my own, very fast cos function:

float sine(float x)
{
    const float B = 4/pi;
    const float C = -4/(pi*pi);

    float y = B * x + C * x * abs(x);

    //  const float Q = 0.775;
    const float P = 0.225;

    y = P * (y * abs(y) - y) + y;   // Q * y + P * y * abs(y)


    return y;
}

float cosine(float x)
{
    return sine(x + (pi / 2));
}

But now when I profile, I see that acos() is killing the processor. I don't need instense precision. What is a fast way to calculate acos(x) Thanks.

+13  A: 

Got spare memory? A lookup table (with interpolation, if required) is gonna be fastest.

spender
How could I implement this as a C function?
Milo
@Jex: bounds-check your argument (it must be between -1 and 1). Then multiply by a nice power of 2, say 64, yielding the range (-64, 64). Add 64 to make it non-negative (0, 128). Use the integer part to index a lookup table, if desired use the fractional part for interpolation between the two closest entries. If you don't want interpolation, try adding 64.5 and take the floor, this is the same as round-to-nearest.
Ben Voigt
Lookup tables require an index, which is going to require a float to int conversion, which will probably kill performance.
phkahler
A: 

It really depends what you mean by "not intense precision"...

You could do it extremely roughly:

float arccos(float x)
{
    return pi * (-x) / 2;
}

Which is a straight-line function

This is very similar to arcsin:

float arcsin(float x)
{
    return -pi * x;
}

In fact, arc-cosine is just arc-sin flipped and shifted up by π/2.

So you could also write your arccos function as:

float arccos(float x) {
    return(pi * 1.5 - arcsin(x));
}
Vincent McNabb
You should include a comment indicating how this is different from `return -pi * x;`
Gabe
Adding that comment would be A Really Cruel SIN
Vincent McNabb
Actually, I meant `-pi/2 * x` (you should explain the reason for `x = 1 - (x + 1);`).
Gabe
Sanity check. Please do a sanity check before upvoting (and especially before accepting an answer).
Ben Voigt
Tringonometric function implementations set aside, why `x = 1 - (x + 1)` and not `x = -x`?
David Weng
Wasn't that the point of your question here? (http://stackoverflow.com/questions/3380827/tricky-arithmetic-or-sleight-of-hand/3380840#3380840) If so, let's not discuss it in two places.
Ben Voigt
This [this answer](http://stackoverflow.com/questions/3380827/tricky-arithmetic-or-sleight-of-hand/3380840#3380840) (already posted by Ben) for why this has so many downvotes, and for a better linear approximation (my comment)
BlueRaja - Danny Pflughoeft
+16  A: 

A simple cubic approximation, the Lagrange polynomial for x ∈ {-1, -½, 0, ½, 1}, is:

double acos(x) {
   return (-0.69813170079773212 * x * x - 0.87266462599716477) * x + 1.5707963267948966;
}

It has a maximum error of about 0.18 rad.

dan04
A: 

I see approximate routines for sine and cosine that could, as @dan04 says, be done better.

I don't see acos.

Besides, what do you mean "killing the processor"? No matter how fast you make it, it is going to take 100% of processor time if you do nothing else.

Mike Dunlavey