<< >>
justin = { main feed , music , code , askjf , pubkey };
[ <<< last (older) article | view in index | next (newer) article >>> ]

July 13, 2010
Buggy fmod() with Visual C++ 2005/2008 targeting x64

I am posting this in case anybody debugging something needs to find it -- I did find mention of it on some Java related site, but nothing conclusive. This may affect VC2010, too, but I haven't tested it.

While VC 2005/2008 targeting x64 generates SSE code for floating point code, fmod() still uses the x87 FPU, and more importantly it assumes that the divide by 0 exception flag is clear going in (meaning if it is set prior to the call, the call will throw an exception or return #.IND regardless of the input). Apparently they assume that since the compiler won't possibly generate code that would cause the divide by 0 floating point exception flag to be set, then it would safe to assume that flag will always be clear. Or it could be a typo. If you use assembly code, or load a module compiled with another compiler that generates x87 code, this can be a huge problem.

Take this example (hi.cpp):

#include <stdio.h>
#include <math.h>

extern "C" void asmfunc();

int main() {
  asmfunc();
  printf("%f\n",fmod(1.0,2.0));
  return 0;
}

and hihi.asm (compile with nasm -f win64):

SECTION .text

global asmfunc
asmfunc:
  fld1
  fldz
  fdivp
  fstp st0
  ret

Compiling this (cl.exe hi.cpp hihi.obj) and running it does not print 1.0, as it should.

The solution we use is to call 'fclex' after any code that might use the FPU. Or not use fmod(). Or call fclex before fmod() every time. I should note that if you use ICC with VC200x, it doesn't have this problem (it presumably has a faster, correct fmod() implementation).






6 Comments:
Posted by schwa on Wed 14 Jul 2010 at 12:50 from 24.168.45.x
VC2010 appears to work correctly. A related bug (where fmod fails if the denormal flag is set) is described here: support.microsoft.com/kb/972497


Posted by schwa on Wed 14 Jul 2010 at 12:52 from 24.168.45.x
(so the bug lasted 5 years through 2 MSVC versions)


Posted by lubo on Thu 15 Jul 2010 at 18:21 from 79.100.60.x
here are a couple of fast fmod() variations:
sites.google.com/site/neolit123/fm...

the first method uses the "partial reminder". it has a little check in there and will work even if the Z bit is set. however, it will still return .IND for 0 as the denominator (has to be tweaked to do otherwise).

the second method is faster than the first and both were (last time i've checked) much faster than the fmod that i see linked by mingw.

but the FPU could have supported a "reset" only on a specific of the lower FPU status word bits. if i'm not wrong, this would mean at least something in the lines of "one-gate" operation, instead of a fclex: "seven-gate" operation + the "wait" instruction.

possibly the best solution (and if possible) is for one to write a custom fmod().


Posted by lubo on Sat 17 Jul 2010 at 15:58 from 79.100.60.x
actually to clarify / correct, since my post above is misleading.

testing the speeds with some random values shows that "fprem" (first method) is much faster than the arithmetic method (second method). (possible improvement in eel2 ?)

when i try math.h's "fmod" i can also see a "fprem" in there which means that "fmod" might be implemented in the same lines at least on mingw-gcc-4.4.1-tdm with -O3. the speeds with random values are relatively the same.

here is how glibc is doing it (at the bottom):
cboard.cprogramming.com/c-programm...

i doubt that all these branches, bitshift and loops will be faster than "fprem" could be wrong though.. :)


Posted by Timothy on Sat 17 Jul 2010 at 16:53 from 41.177.63.x
(Sorry all for the off-topic comment but, based on a quick Google, this seems like the most reliable way of reaching JF.)

Justin, thank you for Winamp series 2. This joe still digs and uses highly functional, lightweight, tight-scope software. Winamp 2.76 FTW!


Posted by Abdorreza Joe Afshany on Sun 18 Jul 2010 at 02:04 from 95.38.39.x
hi dear justin
i like you :) i use always WinAmp for listen musics :)
im Male/32/From Iran
im computer programmer
can i ADD you in May Yahoo Friends List?
my Yahoo ID is : joe_afshany@yahoo.com
thanx


Add comment:
Name:
Human?: (no or yes, patented anti crap stuff here)
Comment:
search : rss : recent comments : Copyright © 2024 Justin Frankel