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

Status : 

  By Design<br /><br />
		The product team believes this item works according to its intended design.<br /><br />
		A more detailed explanation for the resolution of this particular item may have been provided in the comments section.

Sign in
to vote
ID 299211 Comments
Status Closed Workarounds
Type Bug Repros 0
Opened 9/22/2007 7:01:23 AM
Access Restriction Public


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:


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
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:

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:

If you need further assistance please contact
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:
2. MSDN forums:

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

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.