{"id":36865,"date":"2026-09-10T21:19:59","date_gmt":"2026-09-10T21:19:59","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/cppblog\/?p=36865"},"modified":"2026-09-10T21:19:59","modified_gmt":"2026-09-10T21:19:59","slug":"msvc-c23-constexpr-cmath-with-llvm-libc","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/cppblog\/msvc-c23-constexpr-cmath-with-llvm-libc\/","title":{"rendered":"MSVC C++23: constexpr cmath with LLVM Libc"},"content":{"rendered":"<p><a href=\"https:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2021\/p0533r9.pdf\">Proposal P0533R9<\/a> made numerous math functions in the standard library compile-time evaluable in C++23. Implementing the feature required a good bit of time and effort, but MSVC is preparing its experimental implementation for the 14.52 build tools (compiler version 19.52)! We are still refining the feature, so expect the dust to settle only when this has shipped for production.<\/p>\n<p>The feature is enabled with a combination of the <code>\/std:c++23<\/code>\u00a0or later and\u00a0<code>\/Zc:cmath<\/code>\u00a0compiler options. It is initially shipping as experimental and off by default because our implementation is powered by a new math library at compile-time\u00a0<em>and<\/em>\u00a0runtime, which can change performance and accuracy characteristics for existing programs. Our aim is to collect user feedback before making decisions about default behaviors, so please try the feature and give us feedback on <a href=\"https:\/\/developercommunity.visualstudio.com\/cpp\">Visual Studio Developer Community<\/a>.<\/p>\n<p>We&#8217;re publishing an accompanying series of blog posts to explain why we opted for a new math library, what the new math library has to offer users, and an explanation of what we did to implement the feature in the compiler, starting with this post!<\/p>\n<h2>Today&#8217;s Situation<\/h2>\n<p>Since 2015, the math functions in cmath and cstdlib are supplied by the C runtime via math.h and stdlib.h, which Microsoft ships as part of the Universal C Runtime (UCRT). The UCRT is maintained and deployed by the Windows operating system (OS) team, rather than the C++ tools team. This allows stable portions of the C runtime to be serviced in-place with OS updates, while portions tied to the toolset are shipped with the C++ build tools. Thanks to the immortal nature of the C++ Team Blog, you can travel back to 2015 and read\u00a0<a href=\"https:\/\/devblogs.microsoft.com\/cppblog\/introducing-the-universal-crt\/\">Introducing the Universal CRT<\/a>\u00a0for more information on this CRT restructuring.<\/p>\n<p>In the modern day, the UCRT math functions have known mathematical inaccuracies. See\u00a0<a href=\"https:\/\/members.loria.fr\/PZimmermann\/papers\/accuracy.pdf\">Accuracy of Mathematical Functions in Single, Double, Double Extended, and Quadruple Precision<\/a>\u00a0by Gladman, et al. for more info (it&#8217;s hot off the press). These inaccuracies stem from implementations that are quite old, dating to times when accuracy was often computationally infeasible. These implementations today are infrequently changed to maintain backwards compatibility, though they do receive occasional accuracy updates by the OS group.<\/p>\n<p>Inaccurate but changing math functions that are deployed by the OS result in mathematical computations that depend on the OS version and hardware architecture on which they are executed. OS upgrades or porting a program to another architecture (such as x64 to arm64) can quietly and surprisingly impact the results of some UCRT math functions.<\/p>\n<h2>Why a New Math Library<\/h2>\n<p>This situation seemed untenable to us in C++23 because compile-time evaluation of math functions can become part of an application binary interface (ABI) in surprising ways, such as being supplied as an argument to a template. After much discussion, we narrowed on criteria that we found customers care about:<\/p>\n<ul>\n<li><strong>Accuracy<\/strong>. Numerical results are as mathematically accurate as possible.<\/li>\n<li><strong>Stability<\/strong>. Numerical results do not change over time due to implementation changes.<\/li>\n<li><strong>Consistency<\/strong>. Numerical results do not change based on where they are executed.<\/li>\n<li><strong>Performance<\/strong>. Numbers go brrr.<\/li>\n<\/ul>\n<p>The UCRT failed to meet these lofty requirements, so we sought alternatives. We first entertained authoring a new library ourselves but quickly realized that would require years of monk-like study. We instead turned to the open-source community, focusing exclusively on solving the compile-time portion of C++23&#8217;s cmath feature (and thereby leaving the runtime execution to the UCRT) because we felt that delivering accuracy at runtime would still be computationally infeasible.<\/p>\n<p>We found that the\u00a0<a href=\"https:\/\/libc.llvm.org\/\">LLVM C Library<\/a>\u00a0had already made incredible progress tackling the\u00a0<a href=\"https:\/\/libc.llvm.org\/headers\/math\/index.html\">math portions<\/a>\u00a0of the C runtime. The project upholds accuracy as the primary goal, aiming for correct rounding in all rounding modes, with Gladman, et al. confirming the project&#8217;s success. By targeting mathematical accuracy, the library effectively codifies a stable interface that allows for implementation flexibility and optimization. The library is actively maintained and has a healthy community supporting it.<\/p>\n<p>Peeking into the code showed a cogent, composable codebase that could easily be adapted to build with MSVC. Once we did, we were pleasantly surprised that the performance numbers often rivaled those of the UCRT. This made shipping the library for use at compile-time\u00a0<em>and<\/em>\u00a0runtime viable. This enables us to offer our users consistent, stable, accurate, and performant mathematical results everywhere their programs run.<\/p>\n<h2>What\u2019s Next<\/h2>\n<p>We believe that mathematical accuracy in floating-point libraries is an idea whose time has come. We are sure libc gives us the means to offer a stable ground for our users to build upon, but feedback is key for us in deciding how and when to roll the feature out. Please try the experimental implementation by adding\u00a0<code>\/Zc:cmath<\/code>\u00a0to your build and reporting any issues you find to us on <a href=\"https:\/\/developercommunity.visualstudio.com\/cpp\">Visual Studio Developer Community<\/a>. It is intended to be usable independently of <code>\/std:c++23<\/code> to enable the new runtime, though compile-time evaluation is only available in C++23. Support down-level has not yet shipped but has been merged internally. See <a href=\"https:\/\/github.com\/microsoft\/STL\/pull\/6425\" target=\"_blank\" rel=\"noopener\">microsoft\/STL#6425<\/a> for more information.<\/p>\n<p>Building and integrating LLVM libc into the toolset has been the lion&#8217;s share of this feature. Because we&#8217;ve done that work for C++23, C++26 can build upon that base without upheaval. LLVM libc has not yet implemented all of the functions that became constexpr in C++26, but we have already added support for the functions that are ready (such as <code>sin<\/code>, <code>cos<\/code>, <code>tan<\/code>, and <code>pow<\/code>). We&#8217;re keeping an eye on those that aren&#8217;t yet (such as <code>lgamma<\/code>).<\/p>\n<p>We aimed to keep this post relatively short, but we have some upcoming blog posts discussing details of this feature. The first is a guest post authored by libc maintainers that digs into the incredible research and engineering that has gone into producing libc. The second is a post that explains some of the tricks we pulled in the C++ build tools to ship the feature.<\/p>\n<p>Stay tuned!<\/p>\n<p>Cody Miller<\/p>\n<p>Microsoft C++ Compiler Frontend Engineer<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Proposal P0533R9 made numerous math functions in the standard library compile-time evaluable in C++23. Implementing the feature required a good bit of time and effort, but MSVC is preparing its experimental implementation for the 14.52 build tools (compiler version 19.52)! We are still refining the feature, so expect the dust to settle only when this [&hellip;]<\/p>\n","protected":false},"author":220230,"featured_media":35994,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-36865","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-cplusplus"],"acf":[],"blog_post_summary":"<p>Proposal P0533R9 made numerous math functions in the standard library compile-time evaluable in C++23. Implementing the feature required a good bit of time and effort, but MSVC is preparing its experimental implementation for the 14.52 build tools (compiler version 19.52)! We are still refining the feature, so expect the dust to settle only when this [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts\/36865","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/users\/220230"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/comments?post=36865"}],"version-history":[{"count":1,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts\/36865\/revisions"}],"predecessor-version":[{"id":36876,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts\/36865\/revisions\/36876"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/media\/35994"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/media?parent=36865"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/categories?post=36865"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/tags?post=36865"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}