Bug 15010

Summary: std::sin produces wrong results when rounding mode set
Product: glibc Reporter: Joshua Hopp <JoshuaHopp>
Component: mathAssignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED DUPLICATE    
Severity: normal CC: aj
Priority: P2 Flags: fweimer: security-
Version: 2.15   
Target Milestone: ---   
Host: x86_64 Target: x86_64
Build: Last reconfirmed:

Description Joshua Hopp 2013-01-10 19:07:48 UTC
If the rounding mode is set (other than FE_TONEAREST), the sine function gives wrong results for some input values. In fact, the results are not even in the interval of [-1, 1] but in the dimension of ±1e50. Try this:

//--- snip ---
#include <random>
#include <limits>
#include <cmath>
#include <iostream>
#include <cfenv>

const unsigned ROUNDS = 1000000;

int main () {
	std::fesetround(FE_DOWNWARD); // or FE_UPWARD

	// initialize random number generator
	std::random_device rd;
	std::mt19937 rand(rd());

	// set bounds for input value "x"
	double limit_min = -10;
	double limit_max = 10;
	std::uniform_real_distribution<double> dis(limit_min, limit_max);

	for (int i=0; i<ROUNDS; i++) {

		// create a random number "x"
		double input_value = dis(rand);

		// calculate "sin(x)"
		double output_value = std::sin(input_value);

		// if "sin(x)" is out of bounds, print 
		if (output_value < -1 || output_value > 1) {
			std::cout << "sin(" << input_value << ") != " << output_value << std::endl;
		}
	}
	return 0;
}
//--- snap ---

Output:
sin(6.28305) != -1.0016
sin(-6.98816) != 1.91558e+53
sin(-5.40876) != -1.38604e+51
...

Compile with "g++ -std=c++11". Other functions in cmath (such as exp()) might be affected as well, but harder to test.

----
architecturex86_64
Kernel version: 3.2.0-29-generic
gcc version: gcc version 4.7.2 (Ubuntu/Linaro 4.7.2-11precise2) 
ld version: GNU ld (GNU Binutils for Ubuntu) 2.22
Comment 1 Andreas Jaeger 2013-01-10 19:22:58 UTC
I run your program with glibc 2.17 and this seems to be fixed:
aj@byrd:/tmp> g++ t.cc -lm -O2 -std=gnu++11
aj@byrd:/tmp> ./a.out 
aj@byrd:/tmp> 

This should have been fixed already for glibc 2.16 - it's a duplicate of bug 3976.

*** This bug has been marked as a duplicate of bug 3976 ***