Как инвертировать двоичный алгоритм с фиксированной запятой для дробной степени 2? - PullRequest
0 голосов
/ 28 апреля 2020

Я нашел быстрый алгоритм двоичного логарифма для фиксированных точек в ответе на этот вопрос: Быстрые фиксированные точки pow, log, exp и sqrt , основанные на алгоритме Клея С. Тернера . Можно ли «повернуть вспять» это, чтобы вычислить дробные степени двух? Например:

// log2(3) = 1.5849609375
log2fix(196608, 16) == 103872
pow2fix(103872, 16) == 196608

Вот код от Дана Молдинга:

#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;
}
...