Search code examples
c++visual-c++visual-studio-2013ieee-754

sin(<minus zero>) does not return the expected result on Visual Studio 2013 64bit


In the engineering application that I develop for, I stumbled over a difference in the result of sin(-0) between 32bit and 64bit. Due to the nature of the computations, this propagates into some phase differences.

We are developing on Windows with MSVC 2013.

Apparently the floating point standard specifies that sin(-0) returns the argument unchanged - according to cppreference/sin at least.

I've done some investigation and these are some other results I got:

// Visual Studio 2013 32 bit on Win7 - default arguments
std::sin( -0 ) = -0
std::sin( 0 ) = 0

// Visual Studio 2013 64 bit on Win7 - default arguments
std::sin( -0 ) = 0 // the faulty one
std::sin( 0 ) = 0

// g++ (GCC) 5.1.0 : g++ -std=c++11 -O2 -Wall -pedantic -mfpmath=387 -m64 main.cpp && ./a.out
std::sin( -0 ) = -0
std::sin( 0 ) = 0

// g++ (GCC) 5.1.0 : g++ -std=c++11 -O2 -Wall -pedantic -mfpmath=sse -m64 main.cpp && ./a.out
std::sin( -0 ) = -0
std::sin( 0 ) = 0

I also know that the Intel math libraries (libm*.dll) also return sin(-0)=-0.

Looking into the disassembly, the implementation of std::sin directs into msvcr120d.dll.

The questions:

  • is this an error in Microsoft's sin routine implementation on 64bit?
  • should I have used some specific compiler argument that I do not know about?

The code to use for the above output:

#include <cmath>
#include <iostream>

void printSin( const double dfPh )
{
  const auto dfSinPh = std::sin( dfPh );
  std::cout.precision( 16 );
  std::cout << "std::sin( " << dfPh << " ) = " << dfSinPh << std::endl;
}

int main()
{
  printSin( -0.00000000000000000000 );
  printSin( +0.00000000000000000000 );
  return 0;
}

Solution

  • In the end I resorted to a poor man's solution. I specifically check for -0 using std::signbit and closeness to zero, and consider sin(-0) = -0. Slow? Perhaps, but correct for our needs.