- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Compiling a simple application with /Qlong-double (IA32, 12.1, integrated in MSVC on Win7 64-bit) and the two code lines below gives me a linker error on using std::numeric_limits<> when linking to multi-threaded debug DLLs (/MDd). Everything is fine if I link statically (/MTd). I suppose this is not intentional?
typedef long double real_type;
std::cout << std::numeric_limits
error LNK2019: unresolved external symbol "__declspec(dllimport) public: static UNKNOWN __cdecl std::numeric_limits
Moreover, when using operator >> to read-in values with a long double variable as target, it reads rubbish or crashes.
real_type x;
std::cin >> x;
std::cout << x;
Entering '2.2' as input gives '-5.1488e-247' as output, which is quite different. I am not linking to any other file. Whether Intel links to a wrong MSVC-lib or not, I don't know, but I suppose Intel should get it right to linking to the correct lib as it has all the relevant info hany. Otherwise what runtime libs do I need to specify?
And finally: If linking to boost libraries, I strongly suppose that boost libraries must be built with the /Qlong-double option on to ensure binary compatibility - is that correct?
Any help appreciated !
Thanks.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
AFAIK 80 bit long double support is not really supported in Microsoft Libraries - only very limited support is available:
http://msdn.microsoft.com/de-de/library/9cx8xs15.aspx
Please also refer to this thread here:
http://software.intel.com/en-us/forums/showthread.php?t=105429
Best regards,
Georg Zitzlsberger
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Georg,
The problem isnot related to 80-bit precision of the 'long double' type. User'firespot71' could not link his test-case and
it is related to some problem with STL. I'll follow up with more technical details.
Best regards,
Sergey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
In order tounderstand what is wrong you need to do independent verifications with CRT functions, like printf andscanf.
Here a couple of test-cases:
>> Test-Case #1 <<
...
int iMaxValue = std::numeric_limits< int >::max();
int fMaxValue = std::numeric_limits
int dMaxValue = std::numeric_limits
int ldMaxValue = std::numeric_limits
...
>> Test-Case #2 <<
...
unsigned int uiControlWordx87 = 0UL;
//uiControlWordx87 = _control87( _PC_24, _MCW_PC );
//uiControlWordx87 = _control87( _PC_53, _MCW_PC );
//uiControlWordx87 = _control87( _PC_64, _MCW_PC );
uiControlWordx87 = _control87( _CW_DEFAULT, _MCW_PC );
printf( "Epsilon for float : %.16f\n", numeric_limits< float >::epsilon() );
printf( "Epsilon for double : %.32f\n", numeric_limits< double >::epsilon() );
printf( "Epsilon for long double : %.32f\n", numeric_limits< long double >::epsilon() );
...
>> Test-Case #3 ( Yourmodified test) <<
...
typedef long double real_type;
std::cout << "Test 1 - Epsilon for 'long double': " << numeric_limits< real_type >::epsilon() << endl;
printf( "Test 2 - Epsilon for 'long double': %.21f\n", numeric_limits< real_type >::epsilon() );
real_type x;
std::cout << "Enter a floating-point value: ";
std::cin >> x;
std::cout << x << endl;
printf( "Test 3 - Value for 'long double': %.21f\n", x );
...
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
>> Test-Case #3 ( Yourmodified test) <<
...
typedef long double real_type;
std::cout << "Test 1 - Epsilon for 'long double': " << numeric_limits< real_type >::epsilon() << endl;
printf( "Test 2 - Epsilon for 'long double': %.21f\n", numeric_limits< real_type >::epsilon() );
real_type x;
std::cout << "Enter a floating-point value: ";
std::cin >> x;
std::cout << x << endl;
printf( "Test 3 - Value for 'long double': %.21f\n", x );
...
Here is output with Microsoft C++ compiler ( Visual Studio 2005 ):
...
Test 1 - Epsilon for 'long double': 2.22045e-016
Test 2 - Epsilon for 'long double': 0.000000000000000222045
Enter a floating-point value: 1.234567890
1.23457
Test 3 - Value for 'long double': 1.234567889999999900000
...
I don't see any problems.
Best regards,
Sergey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Epsilon for long double: -1.#QNAN000000000000000000000000000
Test 1 - Epsilon for 'long double': -0
Test 2 - Epsilon for 'long double': 0.000000000000000000000
Enter a floating point-value: 2.2
-5.1488e-247
Test 3 - Value for 'long double': 0.000000000000000000000
This applies to debug mode (setting up a new console project app on MSVC9, leaving options by default and using C++ Compiler XE 12.1.5.344 (IA-32); the command line is:
/c /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /EHsc /RTC1 /MTd /GS /fp:fast /Fo"Debug/" /Fd"Debug/vc90.pdb" /W3 /nologo /ZI /Qlong-double
If I compile in release mode the command line is
/c /O2 /Oi /Qipo /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /EHsc /MD /GS /Gy /fp:fast /Fo"Release/" /Fd"Release/vc90.pdb" /W3 /nologo /Zi /Qlong-double
and results get even weirder as the first printf of numeric_limits
So ... ???
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
As always the best option to understand what is going under the hood could be a reversing of library printf and scanf functions coupled with dynamic analysis under debugger.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
It is unclear what you mean by changing contents numeric_limits. That's a std component and I don't intend to change there anything at all (I presume the implementation provides it to me as it must if conforming; indeed IIRC the standard I am not allowed to modify anything in namespace std).
Good, let's tackle this form a different, practical perspective:
Why does the debug DLL not provide the template specialization for long double, but the static does?
I am using only std C++. Why does the Intel compiler simply link to an MSVC runtime library that seems to be binary incompatible as you suggest? There are various alternatives (the best being simply that intel provides correct libs themselves, or provides a wrapper that converts long double to double prior to invoking msvc libs, to issuing a compile-time error if incompatibilities are detected, or simply disallowing the /Qlong-double option for Windoes at all). Frankly, just messing things up at runtime is not a particular good solution.
How am I supposed to know which parts of std C++ I may use and which not? That printf relies on some precompiled libs makes sense and is not difficult to guess. That std::numeric_limits seems to rely on some lib (see debug DLL issue) is much harder to guess as it could be easily implemented throughout a a plain header file. So using std functionalities seems risky whether they work or not. But how would I know whether ordinary maths ops like exp,log, or taking it to the extreme actually also even a plain + or *, would work correctly? After all, these could also link to an incompatible lib?
In summary, ss there any somewhat reliable use for long double on Windows at all?
thanks!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
we're re-using the system libraries from the different platforms for increased compatibility. It's extremely hard (practically almost impossible) to provide an own implementation with the very same semantics; also deviations from the standard & bugs need to be "emulated". That's tedious and expensive... and the benefit?
The downside is, however, that we depend on 3rd party implementations that might cause some head-scratching in rare cases. Apparently you found one of those.
Only Microsoft can answer the question why static libraries work here but DLLs don't. I guess they implemented it half-ways for some kind of internal testing... or realized that there were some glitches with DLLs and stopped any further implementation. Anyways, it's not there and won't ever be.
Bottom line is that even Microsoft guarantees the use of "long double" with a limited set of functions only (see my link above).
Why is it still there... the option?
Well, if you're writing a numerical library and really need 80 bit precision (internally) you still can do it. The option "/Qlong-double" is for the very few who implement such libraries.
We've lots of options where you can "shoot yourself into your own foot" if you're not exactly knowing the details behind the scenes. We provide them to provide maximum flexibility. They're not meant for day-to-day use.
Btw.: In our latest documentation "/Qlong-double" is not prominently documented (anymore). Only found two examples were we still use it for good reason.
I hope I clarified your concerns.
Best regards,
Georg Zitzlsberger
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
the command line is:
/c /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /EHsc /RTC1 /MTd /GS /fp:fast /Fo"Debug/" /Fd"Debug/vc90.pdb" /W3 /nologo /ZI /Qlong-double
...
Regarding a linking error. Please try to compile with '_MBCS' / 'MBCS'macrosinstead of '_UNICODE' / 'UNICODE' macros. I had lots of
similar problems with STL and new C++ operators when I was trying to compile with 'UNICODE' defined.
Best regards,
Sergey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The _MBCS / MBCS does not solve the linker problem, unfortunately.
OK Georg I understand you by now, so the functions stated in your link are the _only_ ones that I can expect to safely use with 80-bit long double out of everything that is provided in the whole of Standard C++ (I assume I may, of course, also use built-in operators such as +,-,*,/, <, >= etc.); for anything else all bets are off. Hm, quite restrictive.
cheers
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Here is another set of results from MinGW and Borland C++ compilers:
Application - MgwTestApp - WIN32_MGW
Tests: Start
> Test1017 Start <
Sub-Test 48
Test 1 - Epsilon for 'long double': 1.0842e-019
Test 2 - Epsilon for 'long double': 0.000000000000000000000
Enter a floating-point value: 1.234567890
1.23457
Test 3 - Value for 'long double': -0.000000000000000000000
> Test1017 End <
Tests: Completed
Application - BccTestApp - WIN32_BCC
Tests: Start
> Test1017 Start <
Sub-Test 48
Test 1 - Epsilon for 'long double': 1.0842e-19
Test 2 - Epsilon for 'long double': -0.000000000000000000000
Enter a floating-point value: 1.234567890
1.23457
Test 3 - Value for 'long double': -0.000000000000000000000
> Test1017 End <
Tests: Completed
As you can see in both casesthe C++ operator >> returned a correct roundedvalue'1.23457'.
Sorry guys, butI don't understand the point of all these fuzzy explanations from Georg. Three C++ compilers,
that is Microsoft, MinGW and Borland,passed the test and only Intel C++ compiler failed.
Best regards,
Sergey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
did you check the size of "long double"? It's still 64 bit for the Microsoft Visual Studio* compiler (for the others I assume that's also true). AFAIK you cannot change it to 80 bit unless you're using some old 16 bit versions...?
From the Microsoft Visual Studio* documentation:
Type longdouble is a floating type that is equal to type double.
So, what you're testing is 64 bit FP (type "double").
Best regards,
Georg Zitzlsberger
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
did you check the size of "long double"?...
Yes, I did and I'll provide you with a report for 4 different C++ compilers. However, the problem is not related to
the double-precision data type 'long double'. There is a linker error described in the 1st post of the thread and by some
reason you're ignoring this. Am I wrong? Also, 'firespot71' had a problem with the C++ operator >> and you're ignoring this and
pressing that the problem is related to the 'long double'.
Georg, did you try to reproduce it? If Yes,did you try tostep into >> C++ operator in order to understand why some wrong value is returned?
Unfortunately, I can't explain what is wrong withthat really simple test case.
Guys, you're trying to blame Microsoft without a completedinvestigation on your side. Please, take a look at it and I appreciate your feedback.
I'll follow up some time later because we had apower outage and everybody is busy with recovering some lost pieces of data.
Best regards,
Sergey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
it works well if you omit the option "/Qlong-double". Then data types of "long double" will be 64 bit (double precision), same as for current Microsoft Visual Studio* compilers (and the others). That's the standard on the Windows* platform.
The option "/Qlong-double" is only available for the Intel C++ Compiler and not (well) documented. It extends the size of type "long double" to 80 bit (extended double precision) and hence conflicts with the ABI of existing libraries (some exceptions, though). That's why there are linker errors and your FP variables are not printed correctly.
The use of this option is neither required for using "long double" types, nor should it be used in normal applications. It's something like the options for changing the calling convention - they for sure can break things but can also be useful in very rare cases.
Hence, don't use "/Qlong-double" unless you have very good reasons.
Best regards,
Georg Zitzlsberger
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I verified it and please take a look at aPost #4.
Here is output with Microsoft C++ compiler ( Visual Studio 2005 ):
...
Test 1 - Epsilon for 'long double': 2.22045e-016
Test 2 - Epsilon for 'long double': 0.000000000000000222045
Enter a floating-point value: 1.234567890
1.23457
Test 3 - Value for 'long double': 1.234567889999999900000
...
Best regards,
Sergey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
it works well if you omit the option "/Qlong-double". Then data types of "long double" will be 64 bit (double precision), same as for current Microsoft Visual Studio* compilers (and the others). That's the standard on the Windows* platform.
[SergeyK] Thank you for the explanations.It would be nice toinvestigatewhy it createsthat problem. Aren'tIntel Software Engineersinterested in that?
I simply wanted to tell that if there is some problem with Intel C++ compiler when the option "/Qlong-double" is used and
it is not fixed or disabled completelythat"bad-piece-of-codes"looks like a "time bomb".
Best regards,
Sergey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
typedef long double real_type;
std::cout << std::numeric_limits
error
I've looked at 'limits' header file ( VS 2005 /
[cpp]... // TEMPLATE CLASS numeric_limits template
My question is: Why Intel C++ compileruses 'UNKNOWN' data type when the 'real_type' ( 'long double' ) is explicitly declared?
Also, take a look inside of 'limits' header file and you will see thattemplate classesforthe following data types are declared:
...
// CLASS numeric_limits
// CLASS numeric_limits
// CLASS numeric_limits<_Bool>
// CLASS numeric_limits
// CLASS numeric_limits
// CLASS numeric_limits
// CLASS numeric_limits
// CLASS numeric_limits
// CLASS numeric_limits
// CLASS numeric_limits
// CLASS numeric_limits
// CLASS numeric_limits<_LONGLONG>
// CLASS numeric_limits<_ULONGLONG>
// CLASS numeric_limits
// CLASS numeric_limits
// CLASS numeric_limits
...
including 'long double' data type. Of course, there will bea linker error because there is nodeclaration for atemplate class 'numeric_limits
Best regards,
Sergey

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page