Debugging Sensitivity to C math library and mingw-w64 v12



C math library functions, such as exp or sin, are not guaranteed to be “precise”. The results might be slightly different on different platforms. A recent change in mingw-w64 v12, which is a core dependency of compilers we use on Windows (both GCC and LLVM), resulted in failures in about 20 CRAN packages. Rtools45 uses mingw-w64 v11, the same version as Rtools44, to allow time for resolving the issues. The change in mingw-w64 v12 switched about 90 math functions from internal implementations to UCRT, the Windows C runtime provided by Microsoft and shipped with the OS. The goal of the change was improving performance and reducing maintenance cost of mingw-w64.

Interested readers should first read the previous blog posts on the topic from April and May. This post presents a tool which allows interested package authors to debug any potential issues in their package.

Wrapping Math library calls

The tool (mdebug) implements configurable wrappers for the C Math library functions, which were switched from an internal representation to UCRT in ming-w64 v12. With the tool comes a patch for R, which causes R and R packages to be linked dynamically (not statically) to wrappers of the corresponding Math library functions. The configurable wrappers allow to unconditionally use UCRT (and hence mimic mingw-w64 v12), to always use internal implementations (and hence mimic mingw-w64 v11 - the wrappers themselves are to be built with mingw-w64 v11), or to do something more (some diagnostic, loggging, etc). In principle, one might also provide an implementation that would give correctly rounded results using mpfr (or some other library), but I’ve not done that.

In the previous posts I have mentioned problems found in packages, I wrote to precisions of which Math function they were overly sensitive to, and whether inaccuracies within 1 ULP were enough to trigger the problem. All of this can be found using the tool.

Limitations

The tool isn’t very user friendly - it is suited to people who are used to building R from source on Windows and who know the C programming language. In addition to the configuration exposed via environment variables, I’ve sometimes modified the generated C code of the concrete wrappers (e.g. to confirm that the problem was caused only by inaccurate results within some range - I would modify the wrapper to use UCRT when the result was within 1 ULP of the internal code result, or use the internal code, instead).

One should keep in mind, as reported in one of the earlier posts, that UCRT results are OS-specific, they differ between Windows versions.

The tool is only usable on Windows and would not discover over-sensititivity to C Math functions where it doesn’t make the program break with mingw-w64-v12. Also, one might argue - why not simply test with an experimental version of Rtools that would already use mingw-w64 v12. Such testing, would, however require a lot of re-compilations to isolate the potential problems (one would have to keep re-compiling package dependencies, R itself, possibly also some external libraries, etc). Still, it is inevitable that at some point some such testing will have to be done, and then this tool may help narrowing down the causes of any numerical problems found.