Bug 479025
| Summary: | rint() returns incorrect values on x86_64 | ||||||
|---|---|---|---|---|---|---|---|
| Product: | Red Hat Enterprise Linux 5 | Reporter: | Tru Huynh <pasteur> | ||||
| Component: | glibc | Assignee: | Carlos O'Donell <codonell> | ||||
| Status: | CLOSED WORKSFORME | QA Contact: | BaseOS QE <qe-baseos-auto> | ||||
| Severity: | medium | Docs Contact: | |||||
| Priority: | low | ||||||
| Version: | 5.2 | CC: | drepper, fweimer, spenser | ||||
| Target Milestone: | rc | ||||||
| Target Release: | --- | ||||||
| Hardware: | All | ||||||
| OS: | Linux | ||||||
| Whiteboard: | |||||||
| Fixed In Version: | Doc Type: | Bug Fix | |||||
| Doc Text: | Story Points: | --- | |||||
| Clone Of: | Environment: | ||||||
| Last Closed: | 2009-03-16 21:55:36 UTC | Type: | --- | ||||
| Regression: | --- | Mount Type: | --- | ||||
| Documentation: | --- | CRM: | |||||
| Verified Versions: | Category: | --- | |||||
| oVirt Team: | --- | RHEL 7.3 requirements from Atomic Host: | |||||
| Cloudforms Team: | --- | Target Upstream Version: | |||||
| Embargoed: | |||||||
| Attachments: |
|
||||||
could this be cloned to version 3 and 4 too? or should I fill it again. I don't see any problems with RHEL5.4. 289440.590000000026 289441.000000000000 289440.750000000000 289441.000000000000 289441.590000000026 289442.000000000000 289441.750000000000 289442.000000000000 289442.590000000026 289443.000000000000 289442.750000000000 289443.000000000000 I have a similar bug on x86_64
$ gcc -m32 -std=gnu99 tests.c -o tests -lm
$ ./tests
FE_TONEAREST
rint(-524096.750000000000) = -524097.000000000000
$ gcc -std=gnu99 tests.c -o tests -lm
$ ./tests
FE_TONEAREST
rint(-524096.750000000000) = -524096.000000000000
This occurs on the following hosts
$ lsb_release -a
LSB Version: :core-4.0-amd64:core-4.0-ia32:core-4.0-noarch:graphics-4.0-amd64:graphics-4.0-ia32:graphics-4.0-noarch:printing-4.0-amd64:printing-4.0-ia32:printing-4.0-noarch
Distributor ID: RedHatEnterpriseServer
Description: Red Hat Enterprise Linux Server release 5.6 (Tikanga)
Release: 5.6
Codename: Tikanga
$ lsb_release -a
LSB Version: :core-4.0-amd64:core-4.0-ia32:core-4.0-noarch:graphics-4.0-amd64:graphics-4.0-ia32:graphics-4.0-noarch:printing-4.0-amd64:printing-4.0-ia32:printing-4.0-noarch
Distributor ID: RedHatEnterpriseClient
Description: Red Hat Enterprise Linux Client release 5.9 (Tikanga)
Release: 5.9
Codename: Tikanga
$ cat tests.c
#include <math.h>
#include <fenv.h>
#include <stdio.h>
int main() {
switch(fegetround()) {
case FE_DOWNWARD:
printf("FE_DOWNWARD\n");
break;
case FE_TONEAREST:
printf("FE_TONEAREST\n");
break;
case FE_TOWARDZERO:
printf("FE_TOWARDZERO\n");
break;
case FE_UPWARD:
printf("FE_UPWARD\n");
break;
default:
printf("unknown rounding mode\n");
}
union {
unsigned int i;
float f;
} val = {0xc8ffe818};
printf("rint(%.12f) = %.12f\n", val.f, rint(val.f));
}
Additionaly, I can confirm this bug is not present in RHEL 6.1 and above. NV(In reply to Spenser Gilliland from comment #4) > Additionaly, I can confirm this bug is not present in RHEL 6.1 and above. I retract this previous statement. There is a bug in the RHEL 6.1 rintf function. (I was attempting to use rintf as a workaround and found this issue) $ gcc tests.c -lm -o tests $ ./tests FE_TONEAREST rintf(2899846.750000000000) = 2899846.000000000000 $ gcc -m32 tests.c -lm -o tests $ ./tests FE_TONEAREST rintf(2899846.750000000000) = 2899847.000000000000 $ lsb_release -a LSB Version: :core-4.0-amd64:core-4.0-ia32:core-4.0-noarch:graphics-4.0-amd64:graphics-4.0-ia32:graphics-4.0-noarch:printing-4.0-amd64:printing-4.0-ia32:printing-4.0-noarch Distributor ID: RedHatEnterpriseWorkstation Description: Red Hat Enterprise Linux Workstation release 6.1 (Santiago) Release: 6.1 Codename: Santiago $ cat tests.c #include <math.h> #include <fenv.h> #include <stdio.h> int main() { switch(fegetround()) { case FE_DOWNWARD: printf("FE_DOWNWARD\n"); break; case FE_TONEAREST: printf("FE_TONEAREST\n"); break; case FE_TOWARDZERO: printf("FE_TOWARDZERO\n"); break; case FE_UPWARD: printf("FE_UPWARD\n"); break; default: printf("unknown rounding mode\n"); } union { unsigned int i; float f; } val = {0x4a30fe1b}; printf("rintf(%.12f) = %.12f\n", val.f, rintf(val.f)); } My current work around for RHEL5/6 compatibility is to use rintl. According to exhaustive test runs rintl provides correct results for all single precision floating point numbers. Ahh yet another issue, when using rintl you cannot enable -O1-3 as the compiler will try to optimize it to rint (which fails.) Alright, finally figured out a workaround to enable optimization. The following wrapper will run properly for -O3.
double rint_wrap(double x) {
long double xx = x;
long double val = rintl(xx);
return val;
}
|
Created attachment 328290 [details] test case Description of problem: rint() returns incorrect values on x86_64 Version-Release number of selected component (if applicable): RHEL 3 4 and 5 with gcc How reproducible: always Steps to Reproduce: 1. compile the attached program 2. run it 3. Actual results: wrong results for the 64 bits version, ok with -m32 Expected results: correct results for 32 and 64 bits versions Additional info: