2
votes

I have program in C++. If I run same part of code, Linux and Windows are giving different results.

#include <cmath>
#include <cfloat>
#include <cstdio>



#define MPI 3.141592653589793238462
#define DEG_TO_RAD(x) ((x) * 0.0174532925)
#define cot(x)  (1.0 / tan(x))
#define sec(x)  (1.0 / cos(x))

double p1 = DEG_TO_RAD(35);
double p2 = DEG_TO_RAD(65);

double lambertN = log(cos(p1) * sec(p2));
lambertN /= (log(tan(0.25 * MPI + 0.5 * p2) * cot(0.25 * MPI + 0.5 * p1)));


double t = tan(0.25 * MPI + 0.5 * p1);
double lambertF = cos(p1) * pow(t, lambertN);

//---------------------------

//specify input coordinates in degrees
double lon = 160.25;
double lat = 245.75;

double longitude = DEG_TO_RAD(lon - 10);
double latitude  = DEG_TO_RAD(lat);

double c = cot(0.25 * MPI + 0.5 * latitude);
double lambertPhi = lambertF * pow(c, lambertN);

printf("%f", lambertPhi); // here I got different results on Win and Linux

On Windows, I got correct result (or it seems so, because final result is OK). On Linux, I got NaN or some very small numbers in comaprison to Windows.

What am I missing ?

EDIT #1:

Windows - Visual Studio 2010 - build via GUI

Linux - gcc version 4.4.7 20120313 (Red Hat 4.4.7-4) (GCC) - built with makefile, flags: CFLAGS = -lm -lstdc++ -Wall -O2

Both systems are 64bit

PS: If anyone is interested, this is part of Lambert-Conic projection equation.

2
You should tell what compiler you are using. Also, this snippet is not enough to compile and try. What you can do yourself is stepping through this part of your program and compare values on both platforms to find out where both versions start to diverge. - Axel
I think we need a proper SSCCE, and precise details of the two environments. Compiler version, 32/64 bit etc. - David Heffernan
@MartinPerry What are the types and values of lon and lat and please add the <cstdio> header for compilable code. - hetepeperfan
I just chose the values 120 and 45 for lon and lat, respectively, and got a valid 0.686144 as output. No NaN for me. Please provide the lon and lat values for which you got your problem. - Alfe
Why can't we have an SSCCE? Don't you want an answer? Don't you want to be sure that we are compiling exactly the same code as you? - David Heffernan

2 Answers

5
votes

First, there is no real reason to expect the same results, unless you take active steps to ensure specific results. The C++ language definition allows intermediate results to use extended precision. Typically, if a compiler does this (and doing it is very frequent on an Intel architectures), The extended precision will be truncated to standard double precision when the compiler stores to memory. And when it stores to memory will depend on the internals of the compiler (and probably even on the degree of optimization).

In the case of Intel, modern chips contain several floating point processors: the older FPU uses extended precision, where as the newer SSE variants don't. But the newer SSE variants aren't available on older processors. By default, g++ (the Linux compiler) uses the older FPU, to work everywhere, but Visual C++, as far as I can tell, uses SSE. This means that by default, you will get different results. Both compilers have extensive options for changing this, but if you're running the default configuration, I would not expect g++ and Visual to give the same results.

1
votes

I get nans for lat values between 90 and 270. That seems reasonable because in that range the cot() will return a negative number which later cannot simply be raised to a fractional power with pow.

The question remains why you get different results on Windows for this. But unless you provide information about the concrete input values I cannot say more.