DXMath library bug: XMVectorATan2[Est] yields wrong result in one special case RRS feed

  • Question

  • XMVectorATan2[Est] return zero instead of negative zero (0x80000000) for input x == INFINITY and y finite and y < 0 when running with SSE2.

    <XMath code>
        XMVECTOR R0 = XMVectorATanEst(V);
        R1 = XMVectorSelect( Pi, Zero, XIsPositive );
        R2 = XMVectorAdd(R0, R1);
    </XMath code>

    For stated input we get R0[-0.0,-0.0,-0.0-0.0] and R1[0.0,0.0,0.0,0.0]. On SSE2 the add that produces R2 is _mm_add_ps which adds zeroes as:
         0.0 + 0.0 -> 0.0
        -0.0 + 0.0 -> 0.0
         0.0 + (-0.0) -> 0.0
        -0.0 + (-0.0) -> -0.0
    Therefore R2<-[0.0,0.0,0.0,0.0] instead of the wanted negative zero.

    Fix: Selecting R1 <- XMVectorSelect( Pi, NegativeZero, XIsPositive ) produces the correct result in this special case and does not cause harm in other atan2 special cases.

    Saturday, February 22, 2014 1:32 PM


All replies

  • Are you using DirectXMath from the Windows 8.0 SDK/VS2012 or the Windows 8.1 SDK/VS 2013?
    Sunday, February 23, 2014 7:09 AM
  • Windows 8.1 SDK/VS 2013
    Sunday, February 23, 2014 4:29 PM
  • Thanks. I'll file a bug for this issue.
    • Marked as answer by Dirk Steenpass Monday, February 24, 2014 7:25 AM
    Sunday, February 23, 2014 10:55 PM
  • Note that even with the proposed fix, the exact results can change with the VS 2013 compiler with /fp:fast.

    In fact, applying the recommended fix does break the sign on a number of other cases: 0/0, 0/1, and it doesn't fix the original case in my tests.

    Monday, February 24, 2014 7:44 PM
  • Surprises me because I am running a test suite for atan2 and all special cases with /fp:fast and /fp:precise both with and without optimizations. However, /fp:fast and /fp:precise affect x87 operation only. In other words, while the atan2 SSE implementation will not be affected the behavior of the code you use to check it may change with those settings.

    But, I had to do translation of XMVectorATan2 into plain C and I am testing with the VS2013 C compiler. Both my translation and the C-compiler could affect the result.

    I found testing a bit tricky for two reasons:

    a) the optimizer may transform -0.0 float/double into +0.0 float/double, I had to be a careful about using bit patterns in all the right places...

    b) when comparing XMVectorATan2 results against the c-runtime atan2 I realized that the c-runtime also exhibits behavior that may be a bug. I filed a bug report to MS connect for this one: atan2 c-runtime bug. Attached to the report is a little c-program that illustrates the bug.

    I you feel that the actual code I ran (atan2 and tests) is helpful I'll gladly post it.

    Monday, February 24, 2014 10:44 PM
  • Sorry, I realized after looking at this more closely that I mis-understood your proposed fix.

    See this post.

    Wednesday, December 10, 2014 9:16 PM