Hi,
I’m trying to generate random numbers using the C++ standard library mt19937 engine after setting the x87 rounding mode to strict double precision mode. With gcc/gfortran this works, but with pgcc/pgfortran I get a SIGFPE in the generate_canonical function, which seems to depend on long doubles(?).
Naively this looks like a bug to me somewhere, no?
Best wishes,
Tobias
fpufix.cpp
#include <random>
#include <iostream>
static std::mt19937_64 engine(123);
static std::uniform_real_distribution<double> distrib (0.0,1.0);
extern "C" {
double cxx11_random_number_()
{
return (distrib)(engine);
}
#ifndef _FPU_GETCW
#define _FPU_GETCW(x) asm volatile ("fnstcw %0":"=m" (x));
#endif
#ifndef _FPU_SETCW
#define _FPU_SETCW(x) asm volatile ("fldcw %0": :"m" (x));
#endif
#ifndef _FPU_EXTENDED
#define _FPU_EXTENDED 0x0300
#endif
#ifndef _FPU_DOUBLE
#define _FPU_DOUBLE 0x0200
#endif
void fpu_fix_() {
/* Linux */
volatile unsigned short cw, new_cw;
_FPU_GETCW(cw);
new_cw = (cw & ~_FPU_EXTENDED) | _FPU_DOUBLE;
_FPU_SETCW(new_cw);
}
}
test.f
program main
implicit none
double precision :: rand, cxx11_random_number
rand = cxx11_random_number()
write (*,*) "random ", rand
call fpu_fix()
rand = cxx11_random_number()
write (*,*) "random ", rand
end program
pgc++ -c -std=c++11 fpufix.cpp && pgfortran -lstdc++ -o test test.f fpufix.o && ./test[/code]
0x00000000004015df in std::generate_canonical<double, 53ul, std::mersenne_twister_engine<unsigned long, 64ul, 312ul, 156ul, 31ul, 13043109905998158313ul, 29ul, 6148914691236517205ul, 17ul, 8202884508482404352ul, 37ul, 18444473444759240704ul, 43ul, 6364136223846793005ul> > () at /usr/include/c++/4.8.5/bits/random.tcc:3467