Home Dashboard Directory Help
Search

cos(value) gives wrong result when rounding mode is _RC_CHOP by JCAFr


Status: 

Closed
 as By Design Help for as By Design


3
0
Sign in
to vote
Type: Bug
ID: 299211
Opened: 9/22/2007 7:01:23 AM
Access Restriction: Public
0
Workaround(s)
view
0
User(s) can reproduce this bug

Description

Hi there, i found out that with VC++ 2005, with Maximize Speed (/O2) and /fp: precise options, if you set the rouding mode to CHOP with _controlfp, then the cos,sin,tan, functions return very odd results. For example:

_controlfp_s(NULL,_RC_CHOP, _MCW_RC );
double angle1 = -0.961411;
double res = cos(angle1); // res will be = 0.649981

_controlfp_s(NULL,_RC_NEAR, _MCW_RC );
double angle2 = -0.961411;
double res = cos(angle2); // res will be = 0.572364

The same program under VC++ 2003, with same compiler options (without the /fp: precise that didnt exist in 2003) will give a good result in both modes, thas is 0.572364.

Now, in VC++ 2005, if I set the Maximize Speed (/O2) options + the /fp:fast option, then the results are also good in both modes.

The difference lies in the assembly. With Maximize Speed (/O2) and /fp: precise it compiles the following code and the results are wrong:

004014E7 fld qword ptr [esp+20h]
004014EB call _CIcos (401B9Ch)

With Maximize Speed (/O2) and /fp:fast , then the assembly looks like this (same as VC 2003) and it works fine:

004014E1 fld qword ptr [esp+20h]
004014E5 fld st(0)
004014E7 fcos

Now, if you trace the call to _Clcos, there is a jump to a function called cos_pentium4 that seems to be the buggy function. Because, if you unmask the floating point exceptiong _EM_INVALID like this:

_controlfp_s(NULL, _EM_UNDERFLOW+_EM_OVERFLOW+_EM_ZERODIVIDE+_EM_INEXACT, _MCW_EM);

then the _Clcos funtion will call a cos_default function that will end up using fcos and it works fine again.

Is that a bug in the math lib or a undocumented limitation?

PS: my processor is an Intel Core Duo 2
Details
Sign in to post a comment.
Posted by Microsoft on 3/20/2009 at 1:36 PM
The rounding behavior being exposed by calling cos() with the rounding mode of CHOP is caused because of the use of SSE2 instructions to implement the cos() routine.

This behavior can be disabled by using the _set_SSE2_enable() routine documented on msdn: http://msdn.microsoft.com/en-us/library/bb384774.aspx

In may be that in your specific case the values you are using allows the fast transcendental to produce the values you want and you can enable that feature with /Qfast_transcendentals as described on msdn: http://msdn.microsoft.com/en-us/library/e7s85ffb.aspx

If you need further assistance please contact http://support.microsoft.com/
Posted by Microsoft on 1/29/2009 at 11:50 AM
The Visual C++ team has triaged the issue you reported. The issue has been resolved during triage with the following message:

This is by design. We can't guarantee accuracy of math functions when the rounding mode is changed.

For further information, you may want to consult one of these resources:
1. Visual C++ triage guidelines:
        http://blogs.msdn.com/vcblog/articles/621116.aspx
2. MSDN forums:
        http://forums.microsoft.com/msdn/default.aspx

Thank you for taking time to send us feedback,
The Visual C++ Team
Posted by Microsoft on 10/16/2007 at 10:32 PM
Thanks for your feedback.

We are escalating this issue to the appropriate group within the Visual Studio Product Team for triage and resolution. These specialized experts will follow-up with your issue.

Thank you,
Visual Studio Product Team
Posted by Microsoft on 9/24/2007 at 10:21 PM
Thank you for your feedback. We are currently investigating. If this issue is urgent, please call support directly (see http://support.microsoft.com).

Thank you,
Visual Studio Product Team
Posted by Avery Lee on 9/22/2007 at 11:49 AM
I've seen similarly awful results with pow(). What seems to have happened is that Microsoft introduced optimized transcendental functions written in SSE2 which evaluate the result directly with primitive operations than use the built-in FPU operations. Although this may be faster, it can produce terribly inaccurate results if the rounding mode is changed because all of the intermediate results use the suboptimal rounding mode, whereas in the FPU this only happens once.
Sign in to post a workaround.