Search code examples
cfloating-pointdirect3dogre3dfpu

Pow implementation for double


I am developing a code that will be used for motion control and I am having a issue with the pow function. I am using VS2010 as IDE.

Here is my issue: I have:

    double p = 100.0000;
    double d = 1000.0000;
    t1 = pow((p/(8.0000*d),1.00/4.000);

When evaluating this last function, I don't get the better approximation as result. I am getting a 7 decimal digits correct, and the consequent digits are all trash. I am guessing that pow function only casts any input variable as float and proceds with calculation.

  1. Am I right?
  2. If so, is there any code I can get "inspired" with to reimplement pow for a better precision?

Edit: Solved.

After all, I was having problems with FPU config bits, caused by Direct3D which was being used by OGRE 3D framework.

If using OGRE, on the config GUI, just set "Floating-point mode=Consistent".

If using raw Direct3D, when calling CreateDevice, make sure to pass "D3DCREATE_FPU_PRESERVE" flag to it.

Original post:

You may be using a libray that is changing the default precision of the FPU to single-precision. Then all floating-point operations, even on doubles, will actually be performed as single-precision operations.

As a test, you can try calling _controlfp( _CW_DEFAULT, 0xfffff ); (you need to include ) before performing the calculation to see if you get the correct result. This will reset the floating-point control word to default values. Note that it will reset other settings as well, which may cause issues.

One common library that changes the floating-point precision is Direct3D 9 (and maybe other versions too): By default, it changes the FPU to single-precision when creating a device. If you use it, specify the flag D3DCREATE_FPU_PRESERVE when creating the device to prevent it from changing the FPU precision.


Solution

  • You may be using a libray that is changing the default precision of the FPU to single-precision. Then all floating-point operations, even on doubles, will actually be performed as single-precision operations.

    As a test, you can try calling _controlfp( _CW_DEFAULT, 0xfffff ); (you need to include <float.h>) before performing the calculation to see if you get the correct result. This will reset the floating-point control word to default values. Note that it will reset other settings as well, which may cause issues.

    One common library that changes the floating-point precision is Direct3D 9 (and maybe other versions too): By default, it changes the FPU to single-precision when creating a device. If you use it, specify the flag D3DCREATE_FPU_PRESERVE when creating the device to prevent it from changing the FPU precision.