clinuxvisual-studio-2019winecrt

How can I get wine/Linux to use the same accuracy for trascendental functions as Windows?


I would want wine/Linux run programs (i.e. Windows exe/dll running on Linux through wine) to use the same accuracy for Trascendental functions as implemented by Microsoft (i.e. VS2019 etc etc).

The challenge I have is that some software I need to run through wine does call such functions and I'm afraid the accuracy/implementation provided through glibc yields to different numbers and makes the code eventually follow different paths.

I have found a workaround, which is to load ucrtbase.dll as native,builtin as in

WINEDLLOVERRIDES="ucrtbase=n,b" wine <my program>

This works excellent when I run my software through interactive terminal.

Unfortunately if I then run such process as a sub-process (i.e. stdout and stderr redirected to memory/files) then the program crashes because I guess it still believes it's on a terminal and tries to print special color characters, but of course it should not. Of course if I leave the builtin ucrtbase.dll it all works as sub-process, but then I lose accuracy/results.

Any idea how I could proceed next? I would also be ok to recompile some transcendental functions myself inside the builtin wine ucrtbase.dll to be the same as VS2019 (and further) alas not sure the source code is publicly available?


Solution

  • The most effective and efficient way is to use an original ucrtbase.dll (which contains all the transcendental functions) coming from a Windows install (which of course requires you to have a licensed copy) and add to your wine options such as:

    WINEDLLOVERRIDES="ucrtbase=n,b" wine <your program>
    

    This is heavily caveated, because when <your program> will run everything will work as long as it's running from a terminal (or terminal emulator). If instead you have to redirect its output to a file, you will experience memory corruption and/or crashes.

    In order to work around this issue, one will have fundamentally two options:

    1. soft-close std::cout and/or std::cerr by calling std::cout.setstate(std::ios_base::eofbit) - nothing will be printed
    2. changing where to output content of std::cout and/or std::cerr by redirecting the same (along the lines of this answer) seems like now this library understands it's not printing to a terminal hence it won't corrupt stream/memory

    This should happen inside <your program> and can be easily implemented in via wine by changing one of core DLLs so that the same can get executed upon program startup via DllMain/DLL_PROCESS_ATTACH.

    This has been verified with wine 8.0.1 on RHEL 7.9.