Question

Immediately warn you that this is a difficult task.

There is a test. The test was the result of parsing a large problem to a bug in which we encountered at work. Construction __ attribute__((noinline)) prohibits the compiler to do the substitution function (for optimizations to something there not imploded). This is the easiest way to optimize guaranteed not to kill an interesting situation.

#include <stdio.h>

double d = 5436277361664796672.000000;
long long ll = 5436277361664796253LL;

int __attribute__((noinline))
func1 (void)
{
  double d1 = (double)ll;

  if (d > d1)
    return 1;
  else
    return 0;
}

int __attribute__((noinline))
func2 (void)
{
  if (d > (double)ll)
    return 1;
  else
    return 0;
}

int
main (void)
{
  printf ("%d %d\n", func1(), func2());
  return 0;
}

I ran this test on intel and sparc. Gcc used in a mode with optimizations and without optimizations. Obtained the following results:

sparc: "gcc" printed "0 0"
sparc: "gcc -O2" printed "0 0"
intel: "gcc" printed "0 1"
intel: "gcc -O2" printed "1 1"

What is the cause differences? Anyway in the analysis situation would be useful to be able to repeat it all myself, but, of course, almost no one has the possibility to run this code on sparc. Instead sparc can try to run under Windows using microsoft or borland C compiler. I do not know what they will be given the results, but in any case something does not match with anything (because we see three different results)

Edit 1 _attribute_ ((noinline)) - an extension of the compiler gcc (forgot to write about it). Therefore VisualStudio can not compile it.

Was it helpful?

Solution 2

Seems solved the problem. In general, all written correctly. But actually works correctly sparc version. Because standard to convert int64-> float64 must be a loss of precision. And in the code when you convert (for intel) int64-> float80 loss occurs. Ie intel-based code works with higher accuracy , but it is in contradiction with the standard.

Perhaps it is some sort of agreement for the platform Intel, which is permissible by default to work this way. Surely there are some options on which the code runs in strict accordance with the standard (but becomes slower)

OTHER TIPS

I note that the declaration of the double constant has 19 significant figures which is more precision than can be represented by a IEEE double (which allows 15 to 17 significant figures). So d cannot hold 5436277361664796672.000000 exactly.

The two constant definition strings become different at the 16th digit, so you are in the region where the inaccuracies in the double are of the same magnitude as the difference between these two numbers. Hence the comparison cannot be relied upon.

I do not know if the C++ standard specifies what happens when an over-precise string is converted to a double, but I would not be surprised if the exact result was either undefined or implementation-dependent.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top