Boost logo

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