Constexpr Math Functions

Constexpr Math Functions

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.

Why doesn't the C++ standard library provide constexpr versions of the cmath functions?

It hasn't been standardized yet. An initial proposal was submitted just last week, but only covering utility and linear operations and not any transcendental functions. Math is hard and floating-point math is complicated. For example, implementations don't allow overflows to infinity in constexpr, but this isn't yet clearly standardized.

The compiler's constexpr interpreter would have to special-case the math library interface, since unlike the rest of the standard library, it can't see its implementation.

GCC does offer constant evaluation of math functions as a nonconforming extension.

Getting constexpr to work with pow in C++17 on OSX

First, you can't initialize constexpr class members with functions that aren't constexpr and std::pow isn't constepxr in standard C++17 . The workaround is to declare them const. While they can't be used in places that require a compile time const they are immutable. A traditional approach is declaring them in header which you include as needed in source files. Then you hneed one implementation file that defines the static const members.

If your code requires compile time const's or constexpr your only option is to write your own pow.

Here's one way to initialize const statics with functions that are not constexpr prior to executing the main() using a portion of your question that shows the technique:

Create a header, constinit.h, that declares the class

// include header guards
// declare the static consts
struct ClassName {
static double DEFAULT_TARGET_TINITIAL_DIGITS_FROM_1; // represents 0.99
static double DEFAULT_TARGET_INITIAL_PBAD; // to be initialized by pow
};

Create an implementation file that initializes the statics:

#include "constinit.h"
#include <cmath>

double ClassName::DEFAULT_TARGET_TINITIAL_DIGITS_FROM_1{ 2 }; // represents 0.99
double ClassName::DEFAULT_TARGET_INITIAL_PBAD = (1 - std::pow(10, -DEFAULT_TARGET_TINITIAL_DIGITS_FROM_1));

To use the statics:

#include <iostream>
#include "constinit.h"

int main()
{
std::cout << ClassName::DEFAULT_TARGET_INITIAL_PBAD << std::endl;
}

If constexpr for compile time initialization is required you need to define your own constexpr pow function. This works in C++17:

    #pragma once // or header guards per your preference

constexpr double my_pow(double x, int exp)
{
int sign = 1;
if (exp < 0)
{
sign = -1;
exp = -exp;
}
if (exp == 0)
return x < 0 ? -1.0 : 1.0;
double ret = x;
while (--exp)
ret *= x;
return sign > 0 ? ret : 1.0/ret;
}
class ClassName {
public:
static constexpr double DEFAULT_TARGET_TINITIAL_DIGITS_FROM_1 = 2; // represents 0.99
static constexpr double DEFAULT_TARGET_TFINAL_DIGITS_FROM_0 = 10; // represents 1e-10
static constexpr double DEFAULT_TARGET_INITIAL_PBAD = (1 - my_pow(10, -DEFAULT_TARGET_TINITIAL_DIGITS_FROM_1));
static constexpr double DEFAULT_TARGET_FINAL_PBAD = my_pow(10, -DEFAULT_TARGET_TFINAL_DIGITS_FROM_0);
static constexpr double DEFAULT_ERROR_TOL_DIGITS = 0.9; // as a fraction of digits in the last place from the above.
static constexpr double DEFAULT_SAMPLE_TIME = 1;

// more unrelated code
};

Is there a constexpr alternative to modf

Is there a constexpr alternative to modf

There is no standard constexpr alternative to modf or related math functions.

but the function is not constexpr. What is the reason for this

Those functions pre-exist constexpr. They even pre-exist C++. As such, when those founctions were specified, they couldn't have been constexpr.

There are no standard constexpr alternatives because such proposal hasn't been accepted into the standard. Such change has been proposed, so this may potentially change in a future standard: P1383

what is the alternative?

Wait for the potential future standard, or do the math without using standard functions.

Why aren't standard library common mathematical functions constant expressions?

I think the only reason is nobody wrote a proposal to make them constexpr. In general it is possible as they are pure functions. Implementations can use compiler intrinsics to implement them for theier lib, so no "real" implementation is needed. But without proposal you can not count on constexpr implementations of these features.

In C++11 is sqrt defined as constexpr?

std::sqrt is not defined as constexpr, according to section 26.8 of N3291: the C++11 FDIS (and I doubt they added it to the final standard after that). One could possibly write such a version, but the standard library version is not constexpr.



Related Topics



Leave a reply



Submit