If you really need
ceil(12 * log2())
then there will be a very simple calculation of O (1), which will work using a table of 12 values.
Use frexp () to split the value into exponent and mantissa. (This is just a bit of manipulation, so it only takes a few cycles.)
Look at the mantissa in the pre-computed list of powers of the 12th root 2.0 (divided by 2), which you can do with up to four comparisons.
Result 12 * (indicator - 1) + least root index> = mantissa.
Edited to add:
In fact, even the best solution, because the powers of the 12th root of the two are reasonably distributed evenly. If you divide [0.5, 1.0) (the mantissa range returned by frexp) into 17 evenly distributed subbands, each subband falls into one of two possible return values. Therefore, if you associate each subrange with an index in the root vector, you only need to compare the target (within this range) with one root.
It's too late for me to write coherent English, so you have to settle for the code:
int Ceil12TimesLog2(double x) { int exp; double mantissa = std::frexp(x, &exp) * 2; int idx = indexes[int((mantissa - 1.0) * 17)]; return 12 * (exp - 1) + (mantissa <= roots[idx] ? idx : idx + 1); }
I tried this and this led to the fact that the total calculation time was reduced from about 0.5 second (for log2f) to 0.15 second using a loop in OP. The total size of the reference tables is 164 bytes.
source share