<div dir="rtl"><div dir="ltr">Hi,</div><div dir="ltr"><br></div><div dir="ltr">Long ago Microsoft had decided (<a href="http://msdn.microsoft.com/en-us/library/9cx8xs15.aspx" target="_blank">http://msdn.microsoft.com/en-us/library/9cx8xs15.aspx</a>) to make the long double type in Visual C++ same as double, 64 bit. This was an incredibly stupid decision, at least for those of us who actually care about numeric accuracy.</div>





<div dir="ltr"><br></div><div dir="ltr">MingW, gcc-based port for Windows, had kept 80-bit long doubles and so does clang. This is a good decision which enable using these compilers in numeric code where 80 bit long doubles are required.</div>

<div dir="ltr"><br></div><div dir="ltr">However, MingW uses the Microsoft runtime DLL msvcrt.dll. Here lies a problem: while gcc creates 80 bits long doubles, the MS runtime accepts 64 bit long doubles only. The problem is usually not obvious since the long double is casted to a double, as in:</div>





<div dir="ltr"><br></div><div dir="ltr"><font face="courier new, monospace"> exp(10.0L)</font></div><div dir="ltr"><br></div><div dir="ltr">where the 10.0L will be silently cast to 10.0 and the routine will seem to work.</div>

<div dir="ltr"><br></div>



<div dir="ltr">However, in the *printf and *scanf family of functions arguments are not downcasted from long double to double (float does cast to double). For instance, naively compiling</div><div dir="ltr"><br></div><div dir="ltr">


<div dir="ltr"><font face="courier new, monospace"> printf("%Lf\n",2345.0L);</font></div>


<div><br></div></div><div dir="ltr">with gcc or clang with the MingW runtime will print garbage results.<br></div><div dir="ltr"><br></div><div dir="ltr">The MingW developers did develop a solution to the problem, namely alternative __mingw_printf and __mingw_scanf family of functions that accept long double 80 bit arguments properly.  In order to use the correct rotuines, one has to</div>




<div dir="ltr"><br></div><div dir="ltr"><font face="courier new, monospace">#define __USE_MINGW_ANSI_STDIO 1<br></font></div><div dir="ltr"><br></div><div dir="ltr">which is not the default in libc but it is defined in gcc libstdc++ library header "os_defines.h" as default.</div>

<div dir="ltr"><br></div><div dir="ltr">So, the first patch to make libcxx print long doubles is to define <span style="font-family:'courier new',monospace">__USE_MINGW_ANSI_STDIO </span>in __config. This will get the *printf and *scanf functions working back on long doubles at least when libcxx is #included (not in programs which do not include it, of course).</div>

<div dir="ltr"><br></div><div dir="ltr">However, it will not make std::cout<<long_double work correctly. Why?</div><div dir="ltr">std::cout calls do_put which uses snprintf_l and asprintf_l to actually do the work. </div>


<div dir="ltr"><br></div><div dir="ltr">asprintf_l is implemented to call vasprintf_l which calls MingW vasprintf which can handle long doubles if __USE_MINGW_ANSI_STDIO is defined. OK.<br></div><div dir="ltr">snprintf_l however is #defined to _snprintf_l, a function from msvcrt.dll which does not support 80 bit long doubles. Problem.</div>


<div dir="ltr"><br></div><div dir="ltr">Therefore, the second part of the patch implements snprintf_l  function in a way similar to the other functions in src/support/win32/locale_win32.cpp and locale_win32.h, calling upon vsnprintf for which there is a MingW correct version.</div>


<div dir="ltr"><br></div><div dir="ltr">Yaron<br></div><div dir="ltr"><br></div></div>