|
Boost : |
Subject: [boost] constexpr, cmath functions and other functions and distributions
From: Paul A. Bristow (pbristow_at_[hidden])
Date: 2016-07-28 09:24:19
After much head scratching (and some head banging) - against a string of "Computer Says No" inscrutable diagnostic messages.
I believe that I have now produced a (partial) version of Boost.Math normal_distribution that can be a constexpr using GCC6.1.1.
(diagnosis has got to improve if constexprizing existing code is to become popular? )
constexpr normal_distribution<double> n01(0., 1.);
producing this code
960 .loc 1 47 0
961 000d 660FEFC0 pxor %xmm0, %xmm0 # tmp89
962 0011 F20F1145 movsd %xmm0, -32(%rbp) # tmp89, n01.m_mean
962 E0
963 0016 F20F1005 movsd .LC1(%rip), %xmm0 #, tmp90
963 80080000
964 001e F20F1145 movsd %xmm0, -24(%rbp) # tmp90, n01.m_sd
964 E8
and more interestingly, a PDF can be calculated at compile-time
constexpr double p = pdf(n01, 0.5);
965 .loc 1 56 0
966 0023 F20F1005 movsd .LC2(%rip), %xmm0 #, tmp91
966 88080000
967 002b F20F1145 movsd %xmm0, -8(%rbp) # tmp91, p
967 F8
Perhaps the assembler whizzes can confirm that this looks like a compile-time computation?
This relies on lots of C++14 and 17 constexpr features, and
Most crucially it relies on being able to use several cmath functions as constexpr.
For a couple of trivially simple examples: abs(x) and isfinite(x).
constexpr double ax42 = abs(-42.); // Unspecified version of abs.
constexpr double ax42g = ::abs(-42.); // C double version?
constexpr double ax42b = __builtin_abs(-42.); // builtin GCC only
constexpr double ax42s = std::abs(-42.); // std:: version
Without most cmath functions it seems to me impossible to write any reasonable (so-called special or not) mathy function or
statistical
distribution that can be constexpr.
At present, only GCC 6.1.1 authors have foreseen this need and provided these so-called built_in_* cmath function versions that are
constexpr, see
https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html.
(Aside on other compilers:
· Clang 3.8 has some problem deep inside type_traits that I haven't yet investigated.
· VS2015 update 3 still doesn't compile many essential C++17 features from my experiments so far, and doesn't provide any
constexpr cmath functions.
)
The many potential benefits of compiler-time computations are quite enticing to contemplate :-)
* No run-time where possible
* Errors caught at compile-time
* Improved code readability
* Reduce executable footprint
and potentially most important
* Avoid global initialization order issues
* Avoid initialization thread races
See
· Scott Schurr, C++ Developer, Ripple Labs
https://cppnow2015.sched.org/event/2oLK/constexpr-c-at-compile-time
· Dietmar Khul Constant Fun
https://www.youtube.com/watch?list=PL9hrFapz4dsM1B9bI8VmEE4JJlR0m-dvo
<https://www.youtube.com/watch?list=PL9hrFapz4dsM1B9bI8VmEE4JJlR0m-dvo&v=T37ElKPICvo&app=desktop> &v=T37ElKPICvo&app=desktop
Is there any support for making std::abs and friends constexpr where possible in future versions of the C++ Standard?
Paul
PS I can't conceive of any UDT using or providing floating-point without some function like frexp to get and set exponent and
significand.
I also note that making constexpr frexp and ldexp and other functions passing a pointer to a variable to be updated may be more
difficult/impossible,
and is very likely to require at least initialization of the to-be-updated variable before calling frexp.
I've investigated overcoming this by writing a naïve new constexpr version of frexp returning a std::pair (significand and exponent)
but, of course, it can never be a 'drop-in' replacement because it has a different signature, so lots of code changes are
inevitable.
--- Paul A. Bristow Prizet Farmhouse Kendal UK LA8 8AB +44 (0) 1539 561830
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk