I found a fast binary logarithm algorithm for fixed points in an answer to this question: Fast fixed point pow, log, exp and sqrt, based on an algorithm by Clay S. Turner. Is it possible to "reverse" this to calculate fractional powers of two? e.g:
// log2(3) = 1.5849609375
log2fix(196608, 16) == 103872
pow2fix(103872, 16) == 196608
Here's the code from Dan Moulding:
#include <errno.h>
#include <stddef.h>
#include "log2fix.h"
int32_t log2fix (uint32_t x, size_t precision)
{
int32_t b = 1U << (precision - 1);
int32_t y = 0;
if (precision < 1 || precision > 31) {
errno = EINVAL;
return INT32_MAX; // indicates an error
}
if (x == 0) {
return INT32_MIN; // represents negative infinity
}
while (x < 1U << precision) {
x <<= 1;
y -= 1U << precision;
}
while (x >= 2U << precision) {
x >>= 1;
y += 1U << precision;
}
uint64_t z = x;
for (size_t i = 0; i < precision; i++) {
z = z * z >> precision;
if (z >= 2U << (uint64_t)precision) {
z >>= 1;
y += b;
}
b >>= 1;
}
return y;
}
z >= 2U << (uint64_t)precision
makes little sense. Suggestz >= 2ULL << precision
. – Sebastiansebastianopow2fix(103872)
, which is2^(103872 * 2^(-16))
, which is close to3
. But the exponent is scaled by2^(-16)
so it's not an integer. You could regroup it as(2^(2^(-16)))^103872
, or as(2^103872)^(2^(-16))
, but I don't think either will help. In both cases, you'd end up having to deal with an exponent of2^(-16)
, which is fractional. – Famed