40

I'd like to use constexpr versions of standard <cmath> functions like exp, log, pow in a portable way. I currently have a non-portable solution g++ treats these functions as constexpr - a non-compliant extension of C++, but I am concerned about portability and future-proofing (I imagine that this extension might one day be removed from g++).

I am interested in constexpr versions of these functions, not template metaprograms - I want the same functionality to be available both at compile time and runtime. I do not need C compatibility, but I do need fast implementations - naive implementations such as Taylor Series expansions would be too slow.

How can I implement such functionalities? I am specifically interested in exp, log, and pow

Some tangentially related things I've learned from my research

  • The standard-compliant versions of these functions aren't technically constexpr because they must have side-effects (e.g. setting errno) to maintain C compatibility
  • In C++11, an implementation was allowed to make these functions constexpr, but as of C++14, this is prohibited (per the first answer to this question and the answer to this question). This is part of the reason that I am concerned that the functions may not be constexpr in future versions of g++
  • g++'s implementation of each math function foo just calls a built-in function __builtin_foo, which is treated as constexpr. I could perhaps start calling the __builtin_foo functions rather than the foo functions - these might remain constexpr in future versions of g++ even if the corresponding foo functions are made compliant - but this only helps with future-proofing, not with portability.
user1476176
  • 1,045
  • 1
  • 7
  • 15
  • 1
    My question is more specific - I want constexpr implementations because I want the exact same functionality at both compile time and runtime. The accepted answer to the linked question is a template metaprogram, which wouldn't work here. – user1476176 May 23 '18 at 00:18
  • @user1476176 I've taken the liberty and edited the question to make it better suited for the site, please check if it still reflects what you mean. Note this still might not be accepted due to being a bit broad, you might want to narrow down specific functions you need – Passer By May 23 '18 at 02:44
  • 1
    *"I want the same functionality to be available both at compile time and runtime."* - do the runtime and compile-time functions need to have the same name? If so, why? – John Zwinck May 23 '18 at 12:20
  • Possible duplicate of [this question](https://stackoverflow.com/questions/17347935/constexpr-math-functions). I know the answers there do not talking about implementation (maybe because writing an implementation is too broad) but the question is indeed a duplicate. – xskxzr May 23 '18 at 12:53
  • @JohnZwinck If the functions are constexpr then I can make unit testing part of the compilation: `static_assert(foo(x) == knownResult)` – user1476176 May 23 '18 at 16:01
  • @xskxzr the linked question has two parts. The answers there mostly address the part which is not the same as this question – user1476176 May 23 '18 at 16:01
  • @JohnZwinck Thinking about this further, I suppose that it would be acceptable to give the functions different names (I assume your thinking is that I could have a `constexpr` version which works inefficiently, and a non-`constexpr` version which just calls the standard math functions, and switch between them depending on the situation). Since the point is compile-time validation of run-time performance, however, it would be important that the compile-time and run-time results never differ by much more than floating point imprecision. – user1476176 May 23 '18 at 16:29
  • 1
    Another obstacle to these being `constexpr` is that they require rounding, which might differ between compile and run time (partly because of configurable rounding mode). – Davis Herring May 24 '18 at 00:37
  • @user1476176: Yes, if they have different names you are free to use a less efficient but usable method for constexpr. – John Zwinck May 24 '18 at 08:18
  • 1
    @DavisHerring the same is true for the built-in operators `+` `-` `*` `/`, but the standard allows them to be evaluated as `constexpr` – user1476176 May 24 '18 at 15:57
  • 2
    @user1476176: True: that issue (and which functions to make `constexpr`) is [under discussion](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0533r2.pdf). – Davis Herring May 25 '18 at 13:18
  • This is a current shortcoming of the c++ standard. Most of the functions (especially in `` and ``) could be `constexpr`, but no one came around to fix the wording in the standard, and the corresponding libraries yet. By the way, have a look at [constexpr ALL the Things](https://www.youtube.com/watch?v=PJwd4JLYJJY), they don't solve your problem, but discuss general solutions to `constexpr` stuff. – jan.sende Aug 15 '18 at 19:16
  • Also duplicate of https://stackoverflow.com/questions/17347935/constexpr-math-functions – gast128 Oct 19 '18 at 11:59
  • @gast128 the question you link has two parts: why are the functions not constexpr, and how can one get around it. Part 2 is the same as this question, but the only answer which addresses it suggests a Taylor series. I asked for solutions other than Taylor series to make sure that my question was different. – user1476176 Oct 22 '18 at 06:50
  • 1
    You implement a constexpr `exp` the same way you implement a non-constexpr `exp`, or possibly in a more sophisticated manner. How to implement a fast portable perecise `exp` in C++? This is not a question that could possibly have a single concise authoritative answer. Too broad! – n. m. could be an AI Nov 04 '18 at 14:32

2 Answers2

15

Have you ever watch Sprout's implementaion?

Sprout is header-only library that provide C++11/14 constexpr based Containers, Algorithms, Random numbers, Parsing, Ray tracing, Synthesizer, and others.

https://github.com/bolero-MURAKAMI/Sprout/tree/master/sprout/math

yumetodo
  • 1,147
  • 7
  • 19
  • 13
    occasionally i think i'm pretty clever and a decent programmer. then i see something like sprout and am completely humbled. – Nick Strupat Feb 05 '19 at 05:55
5

Check out gcem which provides compile time mathematical functions. They can be called just like the ones in std but using the gcem prefix.

BullyWiiPlaza
  • 17,329
  • 10
  • 113
  • 185