Jump to content
  • Advertisement
Sign in to follow this  
AshleysBrain

[C++] strangle sin/cos accuracy problems

This topic is 3318 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I've suddenly started getting really weird results with calls to the built-in sin/cos functions in my C++ program. Everything was working fine, but suddenly objects which rotate go all glitchy and weird. I've tracked down the issue to the following line, which the debugger clearly shows as sin() using single precision floats giving the wrong answer:
float sin_a = sin(angle);
With angle being -0.0017453292, it gives sin_a = 0.096280068. According to my pocket calculator, the correct answer is -0.001745328314. Not only is the result wrongly positive (!!) but it's about 55 times larger! Even if I just enter directly the following line and compile:
const float weird = sin(-0.78539819);
The debugger shows the result being -0.63439333, versus my calculator saying -0.7071068, still out by the first digit, surely worse than single precision floats can achieve. In this particular program, my co-developer reported precisely the same wrong results on their computer too. So when anything rotates in my program everything goes all jittery and displays at the wrong angle. Obviously it works fine in a new program, and I have an assembly snippet using the fsincos instruction that doesn't seem to suffer precision problems, and the double precision overloads for sin and cos seem OK. But something must be seriously amiss here. What could cause such serious inaccuracy errors? I've no idea what I might've done to cause this - compiler settings? FPU control flags (I'm not changing any)? Cosmic rays???

Share this post


Link to post
Share on other sites
Advertisement
display glitches could be a radian<->degree mismatch. Did you step over the line in question in debug mode after a full rebuild? (Remember, when the debugger first breaks on that line, sin_a will be uninitialized, because it stops BEFORE executing the highlighted line)

Share this post


Link to post
Share on other sites
Yes, I had stepped over the line, and the calculation is definitely in radians. Even the line with a hard-coded parameter came out wrong.

Share this post


Link to post
Share on other sites
Quote:
Original post by AshleysBrain
With angle being -0.0017453292 [...] it's about 55 times larger!

Quick observations:
- your angle is very small
- for small angles, the sine function is approximately like a straight line
- 180/pi = 57 =~ 55

Share this post


Link to post
Share on other sites
Would you mind posting a small program that shows what you are doing?
#include <cmath>
#include <iostream>

int main() {
const float weird = sin(-0.78539819);
std::cout << weird << '\n'; // prints -0.707107, as it should
}

Share this post


Link to post
Share on other sites
I've ssen such weirdness before wich we eventually blamed on issues with the SSE registers on some windows xp 64 bit only. Try to write a small function that asses the result of a known calculation an see from what point it starts going wrong (easier said than done) How big is your program? On large codebases, a small mistake somewhere can cause very paranormal results at the other end, I have seen that quite a lot...

Share this post


Link to post
Share on other sites
At a random guess, your (or rather your compiler's) sin() function is using some kind of lookup table in its calculations.

As the results are wrong after a while, that suggests something else has overwritten that lookup table, due to an array overrun or other similar bug. If you can find the table by stepping into the sin function (reading of disassembly may be required), then a memory watch breakpoint in the debugger should find you the culprit quickly.

If that's not possible then checking at which point in the program sin() starts misbehaving will tell you when it's been trashed, and you can start narrowing it down by moving the tests.

This may also be a good time to start using of an array template that does bounds checking in debug builds.

Share this post


Link to post
Share on other sites
It's a 100,000+ line program so I can't easy post any of it, and it's Visual Studio 2008. I thought sin() and cos() mapped directly to the fsin and fcos x86 instructions? I am using a little bit of MMX/SSE, and assembly running on startup for CPUID etc, but I've tried turning it all off and it doesn't fix anything...

Share this post


Link to post
Share on other sites
Try to reproduce the problem in a tiny program: It's your best shot at figuring out what the problem is and, even if you don't, you can post it for us to help.

Share this post


Link to post
Share on other sites
Are you able to test your program on another computer or another OS, and see if this happens in the same way?

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!