Bug 66736 - float rounding differences when using constant literal versus variable
Summary: float rounding differences when using constant literal versus variable
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: c (show other bugs)
Version: 5.1.1
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2015-07-02 09:24 UTC by dhekir
Modified: 2023-03-27 15:21 UTC (History)
0 users

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description dhekir 2015-07-02 09:24:02 UTC
Calling function "log10f(3)" with a constant literal or via a variable, such as "float f = 3; log10f(f)" gives different rounding results, which are incorrect in the latter case.

Note that the bug is not about imprecision in the result, but inconsistency between two statements which should be equivalent.

The difference only appears with no optimization flag or with -O0; activating -O1 or greater makes the difference disappear.

It is especially annoying (although not forbidden) that the rounding differences in this case do not respect usual order (i.e. changing the rounding mode allows one to see that FE_DOWNWARD is larger than FE_TONEAREST in the version using the variable).

This behavior has been observed in several GCCs, from 4.8.4 (Ubuntu) to 5.1.1 (Fedora), including a 5.0.0 compiled from trunk, and using different versions of glibc (2.19, and also tried compiling 2.21). All of them produced the same result.

Also, there are several constants for which this happen, but 3 would be one of the most notable ones.

#include <math.h>
#include <stdio.h>

int main() {
  float r = log10f(3);
  printf("literal constant: %g (%a)\n", r, r);
  float x = 3;
  r = log10f(x);
  printf("with variable:    %g (%a)\n", r, r);
  return 0;
}
Comment 1 Richard Biener 2015-07-02 09:45:08 UTC
This means the math library implementation of log10f is not exact which isn't a
GCC bug.
Comment 2 dhekir 2015-07-02 11:32:19 UTC
Isn't the library implementation of log10f used to compute the literal constants generated in the assembly code? Would it then be a double precision result that would be precomputed and rounded to single precision in this case?

Well, sorry for the noise, I compared the results with other compilers and, even if the numerical results themselves were different, they were consistent between precomputed constant literals and the underlying libc, therefore such surprising situations do not arrive. I assumed that it was not intented in GCC and so it would be useful to report it, but if it's not the same library function used in both cases, that explains the issue.
Comment 3 Richard Biener 2015-07-02 12:32:45 UTC
(In reply to dhekir from comment #2)
> Isn't the library implementation of log10f used to compute the literal
> constants generated in the assembly code? Would it then be a double
> precision result that would be precomputed and rounded to single precision
> in this case?

No, GCC uses the GMP / mpfr / mpc libraries to constant fold math functions.
The library implementation is for example not available when cross-compiling.

> Well, sorry for the noise, I compared the results with other compilers and,
> even if the numerical results themselves were different, they were
> consistent between precomputed constant literals and the underlying libc,
> therefore such surprising situations do not arrive. I assumed that it was
> not intented in GCC and so it would be useful to report it, but if it's not
> the same library function used in both cases, that explains the issue.

Yes, that explains it.  GCC produces exact results for constant folding.

Note that with other compilers you may fall into the trap of not executing
the library function in any case so I suggest to make the 'float r' variable
global and volatile.