Here is what happens (experiments repeated with identical results
with OpenBSD 5.1 both on x86_64 and sparc64):

-bash-4.2$ cat bug.cc
#include <cmath>
#include <cstdlib>
#include <cstdio>

int main(int argc, char **argv) {
  long double x = strtold(argv[1], 0);
  long double y = std::floor(x);
  printf("%.1000Lg\n%.1000Lg\n", x, y);
}
-bash-4.2$ g++ bug.cc
-bash-4.2$ ./a.out  13311002825915415087
13311002825915415087
13311002825915414528
-bash-4.2$

As you can see, std::floor(x) returns a wrong result.
An equivalent C program does the right thing:

-bash-4.2$ cat bug.c
#include <math.h>
#include <stdlib.h>
#include <stdio.h>

int main(int argc, char **argv) {
  long double x = strtold(argv[1], 0);
  long double y = floorl(x);
  printf("%.1000Lg\n%.1000Lg\n", x, y);
}
-bash-4.2$ gcc bug.c -lm
-bash-4.2$ ./a.out  13311002825915415087
13311002825915415087
13311002825915415087
-bash-4.2$

But not if it is linked with -lstdc++ instead of -lm:

-bash-4.2$ gcc bug.c -lstdc++
-bash-4.2$ ./a.out  13311002825915415087
13311002825915415087
13311002825915414528
-bash-4.2$

The reason why libstdc++ on OpenBSD exports a
bogus version of floorl() probably lies with the
following piece of code:

#ifndef HAVE_FLOORL
long double
floorl(long double x)
{
  return floor((double) x);
}
#endif

It would seem that, on OpenBSD, libstdc++ is compiled
with HAVE_FLOORL not defined.

--
Roberto Bagnara

BUGSENG srl
http://bugseng.com
mailto:roberto.bagn...@bugseng.com

Reply via email to