I'm coding a function that evaluates binomial coefficients: binom(N, K)
I want to check that both N and K are unsigned-type integers with N >= K at compile time, but having a problem with this.
Here's my code:
template <typename N>
concept Unsigned = std::is_unsigned_v<N>;
template <Unsigned U>
constexpr double binom(U N, U K) {
static_assert(N >= K);
double d = 1.0;
while (K) {
d *= static_cast<double>(N) / static_cast<double>(K);
K--;
N--;
}
return d;
}
template <Unsigned U>
constexpr double binom_pmf(U N, U K, double theta) {
return binom(N, K) * std::pow(theta, K) * std::pow(1 - theta, N - K);
}
Here is the error message from Clang 10:
/mnt/c/programming/ML/2_3_1_binomial_bernoulli.cpp:12:19: error: static_assert expression is not an integral constant expression
static_assert(N >= K);
^~~~~~
/mnt/c/programming/ML/2_3_1_binomial_bernoulli.cpp:24:12: note: in instantiation of function template specialization 'binom<unsigned long>' requested here
return binom(N, K) * std::pow(theta, K) * std::pow(1 - theta, N - K);
^
/mnt/c/programming/ML/2_3_1_binomial_bernoulli.cpp:36:16: note: in instantiation of function template specialization 'binom_pmf<unsigned long>' requested here
y[K] = binom_pmf(N, K, theta);
The problem is static_assert(N >= K)
.
I've declared parameter N as constexpr size_t
, and K is the loop parameter in for (size_t K = 0; K <= N; K++)
, so anyone can conclude that N and K are surely unsigned integers with N >= K, but the compiler doesn't look so happy.
Oh, the compiler is also complaining when I try to insert static_assert(theta >= 0.0 && theta <= 1.0);
in binom_pdf
.
What should I do? Thanks in advance.