So noticed from this page that none of the math functions in c++11 seems to make use of constexpr, whereas I believe all of them could be. So that leaves me with two questions, one is why did they choose not to make the functions constexpr. And two for a function like sqrt
I could probably write my own constexpr, but something like sin or cos would be trickier so is there a way around it.
-
3They didn't choose not to make the functions constexpr. They just didn't make any choice (I believe there are proposals to make them so in the future). – R. Martinho Fernandes Jun 27 '13 at 16:01
-
@R.MartinhoFernandes - there's some discussion, but the problem with making complicated functions `constexpr` is that the compiler then has to do what would otherwise be a runtime computation, and that means having a C++ interpreter built in to the compiler. It's a big job... – Pete Becker Jun 27 '13 at 16:07
-
@PeteBecker not all of them are complex, but I guess by saying that I'm also saying why not just do them on my own – aaronman Jun 27 '13 at 16:09
-
So what should the compiler set the value of `v` for `constexpr double v = tan(1.570796326)`? – Happy Green Kid Naps Jun 27 '13 at 16:40
-
3Note, [gcc has implemented most of the math function as constexpr](http://stackoverflow.com/q/27744079/1708801) although the extension is non-conforming this should change. So definitely doable. – Shafik Yaghmour Jan 12 '15 at 20:23
-
1I think one has to distinguish here: It seems almost impossible to implement the math functions *efficiently* as `constexpr` functions *in pure C++*. At least given the restrictions on `constexpr` functions in C++11. On the other hand, the math functions are a very well-known finite set of functions that a compiler could easily provide as builtins and evaluate at compile-time. This mixing of core language features and library functions might be considered ugly, but also worth the thing. Also see [Alisdair Meredith's talk on CppCon 2014](http://youtu.be/fBU1R7jp_TE?t=31m51s). – 5gon12eder Jan 13 '15 at 03:08
-
@HappyGreenKidNaps of course, to `1258025171.80666637420654296875`, if `double` is the IEEE 754 `binary64`. – Ruslan Jun 03 '19 at 08:33
-
See [link](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1383r0.pdf) for a proposal of adding more constexpr
to the C++ standard. – Holger Strauss Dec 11 '20 at 07:59
3 Answers
Actually, because of old and annoying legacy, almost none of the math functions can be constexpr
, since they all have the side-effect of setting errno
on various error conditions, usually domain errors.

- 69,373
- 8
- 123
- 157
-
So is there any way to get around this short of doing my own functions – aaronman Jun 27 '13 at 16:10
-
1No. That is, I don't think there's a library of constexpr math functions already available, so not even that would work. (Of course, C++14 will make implementing them much more convenient and efficient.) – Sebastian Redl Jun 27 '13 at 16:16
-
@aaronman The [post-Bristol mailing](http://isocpp.org/blog/2013/05/post-bristol-standards-papers-mailing-available) is a good place to start (the list of papers discussed during the April meeting in Bristol). – BoBTFish Jun 28 '13 at 06:46
-
4A function can be constexpr and still sometimes throw, etc. The value of a sum of double may depend on a rounding mode, but accommodations are made for the constexpr case. `errno` is really not a good reason. – Marc Glisse Sep 10 '14 at 11:05
-
5@MarcGlisse Throwing and `errno` are two very different beasts. The C standard math functions are specified to modify `errno`, not throw an exception. So I don't understand your point. – Sebastian Redl Sep 13 '14 at 15:08
-
2@SebastianRedl Addition is specified to set FE_INEXACT if the result is not exact. However, an addition is still allowed to be constexpr. Does this look closer to the `errno` situation to you? – Marc Glisse Sep 13 '14 at 17:49
-
2It comes close, except that nowhere in C99 can I find such a specification, much less in C++11. The closest is there reference to the ISO 60559 operations in Annex F of C99. However, C++ only references the library clauses of C, so this annex has no normative role in C++. I don't think C++ has any requirement that addition has side effects. Note in particular the lack of any "contracted" floating point operations in C++11 section 5 intro, which are there in the equivalent section of C99. – Sebastian Redl Sep 14 '14 at 10:16
From "The C++ Programming Language (4th Edition)", by B. Stroustrup, describing C++11:
"To be evaluated at compile time, a function must be suitably simple: a constexpr function must consist of a single return-statement; no loops, and no local variables are allowed. Also, a constexpr function may not have side effects."
Which means that it must be inline, without for, while and if statements and local variables. Side effects are also forbidden (ex: changing of errno). Another problem is that most of math functions are FPU instructions which are not represented in pure c/c++ (they are written in assembler code). That's why non of cmath function is declared as constexpr.
-
47
-
1Yeah, good point. I gave the answer why those functions can't be constexpr in c++11, because question was about c++11. – Adam Szaj Sep 10 '14 at 11:15
-
The other answer already stated that `errno` was the main reason, not really sure if your answer adds any other important information – aaronman Sep 10 '14 at 13:56
-
1@aaronman, as Marc Glisse said, errno is not a good reason because c++ standard could provide a parallel implementation of those functions which would not modify errno. But even then constexpr implementation would'n be possible without some intrinsic compiler feature. I don't want to argue, but I think, I pointed several good reasons for that. I may be wrong of course. I'm currently writing a library which would gain a lot from constexpr math functions - that's why I'm here - but I think that there are much more problems than just 'errno'. – Adam Szaj Sep 10 '14 at 15:51
-
3@AdamSzaj constexpr functions (even c++11 ones) are turing complete, so I don't see the issue you are bringing up, here is an example of [contexpr sqrt](https://github.com/aaronjosephs/constexpr/blob/master/constexprsqrt.cpp) I wrote a while back – aaronman Sep 10 '14 at 16:02
-
2Quite nice, but try `awsome::sqrt(3e13)` . Have you tried to implement sin, cos, tanh, or similar functions? I know that there are algorithms for such functions, but do you think that `constexpr_sin(x) == sin(x)`? – Adam Szaj Sep 11 '14 at 09:28
So noticed from this page that none of the math functions in c++11 seems to make use of constexpr, whereas I believe all of them could be. So that leaves me with two questions, one is why did they choose not to make the functions constexpr.
This part is very well answered by Sebastian Redl and Adam Szaj so won't be adding anything to it.
And two for a function like sqrt I could probably write my own constexpr, but something like sin or cos would be trickier so is there away around it.
Yes, you can write your own version of constexpr sin, cos by using the taylor series expansions of these functions. Have a look at this super cool github repo which implements several mathematical functions as constexpr functions Morwenn/static_math

- 2,053
- 2
- 20
- 34
-
3Not so super cool: try calculating `smath::cos(20.)`. Cosine greater than 3... It's hard enough to implement a decent non-`constexpr` trig function, let alone `constexpr` one. – Ruslan Nov 23 '17 at 15:46
-
1@Ruslan Thanks for pointing that out. I had never tried that myself. I, however, made my own library for doing some compile-time stuff https://github.com/lakshayg/compile_time/ and I am quite sure that it can handle this case well. Do give it a try and let me know (or open an issue) if you have suggestions (This is still a work in progress). – lakshayg Nov 23 '17 at 16:31
-
1Didn't look at the code, but your version 1) fails to include `
`, thus not compiling without tweaks; 2) seems to do only trivial range reduction, so that e.g. `compile_time::cos(200.)` differs considerably from `std::cos(200.)` on x86_64 gcc, while for argument of `2.` the results are more or less the same. Even worse for `long double`. But yes, it does appear to at least attempt to do range reduction, unlike `static_math`. – Ruslan Nov 23 '17 at 16:56 -
@Ruslan Thanks for the feedback, could you please provide me some details about your platform. On my machine (linux, x86_64, g++5.4) the code compiles without any warnings/errors and the error is less than 0.00001%. Also, we should probably continue this discussion on github. – lakshayg Nov 23 '17 at 17:04
-
Yeah, made an issue report. Anyway, the problem with precision isn't what fraction of percent it is — it's how many ULPs it is. In my test I got the error of `2**17` ULP, which is no good for IEEE754 64-bit `double`. – Ruslan Nov 23 '17 at 20:20
-