Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the right way to compute integral base-2 logarithms at compile-time?

I have some positive constant value that comes from a different library than mine, call it the_val. Now, I want log_of_the_val to be floor(log_2(the_val)) - not speaking in C++ code - and I want that to happen at compile time, of course.

Now, with gcc, I could do something like

decltype(the_val) log_of_the_val = sizeof(the_val) * CHAR_BIT - __builtin_clz(the_val) - 1;

and that should work, I think (length - number of heading zeros). Otherwise, I could implement a constexpr function myself for it, but I'm betting that there's something else, and simpler, and portable, that I could use at compile-time. ... question is, what would that be?

like image 436
einpoklum Avatar asked Mar 13 '23 08:03

einpoklum


1 Answers

The most straightforward solution is to use std::log2 from <cmath>, but that isn't specified to be constexpr - it is under gcc, but not under clang. (Actually, libstdc++ std::log2 calls __builtin_log2, which is constexpr under gcc.)

__builtin_clz is constexpr under both gcc and clang, so you may want to use that.

The fully portable solution is to write a recursive constexpr integral log2:

constexpr unsigned cilog2(unsigned val) { return val ? 1 + cilog2(val >> 1) : -1; }
like image 164
ecatmur Avatar answered Apr 06 '23 18:04

ecatmur