Реализуйте Log2 с фиксированной точкой с помощью интерполяционной таблицы

В этом примере показано, как реализовать log2 с фиксированной точкой использование интерполяционной таблицы. Интерполяционные таблицы генерируют эффективный код для встраиваемых устройств.

Setup

Чтобы убедиться, что этот пример не изменит ваши предпочтения или настройки, этот код сохраняет исходное состояние.

originalFormat = get(0,'format'); format long g
originalWarningState = warning('off','fixed:fi:underflow');
originalFiprefState = get(fipref); reset(fipref)

Вы восстановите это состояние в конце примера.

Log2 реализации

The log2 алгоритм, реализованный в функции fi_log2lookup_8_bit_byte ниже, результирующие здесь.

  1. Объявите количество бит в байте, B, как константа. В этом примере B=8.

  2. Используйте функцию fi_normalize_unsigned_8_bit_byte() описывается в примере Нормализация данных для интерполяционных таблиц, чтобы нормализовать вход u>0 таким образом u = x*2^n и 1 <= x < 2.

  3. Извлечение верхней B-биты x. Позвольте x_B обозначить верхнюю B-биты x.

  4. Сгенерируйте интерполяционную таблицу, LOG2LUT, так, чтобы целое число i = x_B - 2^(B-1) + 1 используется как индекс, чтобы LOG2LUT так, чтобы log2(x_B) можно оценить, посмотрев вверх по индексу log2(x_B) = LOG2LUT(i).

  5. Используйте оставшуюся часть r = x - x_B, интерпретируемый как дробь, для линейной интерполяции между LOG2LUT(i) и следующее значение в таблице LOG2LUT(i+1). Оставшаяся часть, r, создается путем извлечения нижней w - B биты x, где w обозначает размер слова x. Он интерпретируется как дробь при помощи функции reinterpretcast().

  6. Наконец, вычислите выход с помощью интерполяционной таблицы и линейной интерполяции:

log2(u) = log2(x*2^n)

= n + log2(x)

= n + LOG2LUT(i) + r*(LOG2LUT(i+1) - LOG2LUT(i))

Пример

Использование fi_log2lookup_8_bit_byte() для вычисления журнала с фиксированной точкой 2 с помощью интерполяционной таблицы. Сравните результат интерполяционной таблицы с фиксированной точкой с логарифмом, вычисленным с помощью log2 и двойная точность.

u = fi(linspace(0.001,20,100));
y = fi_log2lookup_8_bit_byte(u);
y_expected = log2(double(u));

Постройте график результатов.

clf
subplot(211)
plot(u,y,u,y_expected)
legend('Output','Expected output','Location','Best')

subplot(212)
plot(u,double(y)-y_expected,'r')
legend('Error')

Figure contains 2 axes. Axes 1 contains 2 objects of type line. These objects represent Output, Expected output. Axes 2 contains an object of type line. This object represents Error.

figure(gcf)

Очистка

Восстановите исходное состояние.

set(0,'format',originalFormat);
warning(originalWarningState);
fipref(originalFiprefState);

fi_log2lookup_8_bit_byte Определение функции

function y = fi_log2lookup_8_bit_byte(u)
    % Load the lookup table
    LOG2LUT = log2_lookup_table();
    % Remove fimath from the input to insulate this function from math
    % settings declared outside this function.
    u = removefimath(u);
    % Declare the output
    y = coder.nullcopy(fi(zeros(size(u)),numerictype(LOG2LUT),fimath(LOG2LUT)));
    B = 8; % Number of bits in a byte
    w = u.WordLength;
    for k = 1:numel(u)
        assert(u(k)>0,'Input must be positive.');
        % Normalize the input such that u = x*2^n and 1 <= x < 2
        [x,n] = fi_normalize_unsigned_8_bit_byte(u(k));
        % Extract the high byte of x
        high_byte = storedInteger(bitsliceget(x, w, w - B + 1));
        % Convert the high byte into an index for LOG2LUT
        i = high_byte - 2^(B-1) + 1;
        % Interpolate between points.
        % The upper byte was used for the index into LOG2LUT
        % The remaining bits make up the fraction between points.
        T_unsigned_fraction = numerictype(0, w-B, w-B);
        r = reinterpretcast(bitsliceget(x,w-B,1), T_unsigned_fraction);
        y(k) = n + LOG2LUT(i) + ...
               r*(LOG2LUT(i+1) - LOG2LUT(i)) ;
    end
    % Remove fimath from the output to insulate the caller from math settings
    % declared inside this function.
    y = removefimath(y);
end

Log2 интерполяционная таблица

Функция log2_lookup_table загружает интерполяционную таблицу log2 значения. Вы можете создать таблицу, запустив:

B = 8;

log2_table = log2((2^(B-1):2^(B))/2^(B-1))

function LOG2LUT = log2_lookup_table()
    B = 8;  % Number of bits in a byte
    % log2_table = log2((2^(B-1) : 2^(B)) / 2^(B - 1))
    log2_table = [0.000000000000000   0.011227255423254   0.022367813028454   0.033423001537450 ...
                  0.044394119358453   0.055282435501190   0.066089190457773   0.076815597050831 ...
                  0.087462841250339   0.098032082960527   0.108524456778169   0.118941072723507 ...
                  0.129283016944966   0.139551352398794   0.149747119504682   0.159871336778389 ...
                  0.169925001442312   0.179909090014934   0.189824558880017   0.199672344836364 ...
                  0.209453365628950   0.219168520462162   0.228818690495881   0.238404739325079 ...
                  0.247927513443586   0.257387842692652   0.266786540694901   0.276124405274238 ...
                  0.285402218862248   0.294620748891627   0.303780748177103   0.312882955284355 ...
                  0.321928094887362   0.330916878114617   0.339850002884625   0.348728154231078 ...
                  0.357552004618084   0.366322214245816   0.375039431346925   0.383704292474052 ...
                  0.392317422778760   0.400879436282184   0.409390936137702   0.417852514885898 ...
                  0.426264754702098   0.434628227636725   0.442943495848728   0.451211111832329 ...
                  0.459431618637297   0.467605550082997   0.475733430966398   0.483815777264256 ...
                  0.491853096329675   0.499845887083205   0.507794640198696   0.515699838284042 ...
                  0.523561956057013   0.531381460516312   0.539158811108031   0.546894459887637 ...
                  0.554588851677637   0.562242424221073   0.569855608330948   0.577428828035749 ...
                  0.584962500721156   0.592457037268080   0.599912842187128   0.607330313749611 ...
                  0.614709844115208   0.622051819456376   0.629356620079610   0.636624620543649 ...
                  0.643856189774725   0.651051691178929   0.658211482751795   0.665335917185176 ...
                  0.672425341971496   0.679480099505446   0.686500527183218   0.693486957499325 ...
                  0.700439718141092   0.707359132080883   0.714245517666123   0.721099188707185 ...
                  0.727920454563199   0.734709620225838   0.741466986401147   0.748192849589460 ...
                  0.754887502163469   0.761551232444479   0.768184324776926   0.774787059601173 ...
                  0.781359713524660   0.787902559391432   0.794415866350106   0.800899899920305 ...
                  0.807354922057604   0.813781191217037   0.820178962415188   0.826548487290915 ...
                  0.832890014164742   0.839203788096944   0.845490050944375   0.851749041416058 ...
                  0.857980995127572   0.864186144654280   0.870364719583405   0.876516946565000 ...
                  0.882643049361841   0.888743248898259   0.894817763307943   0.900866807980749 ...
                  0.906890595608518   0.912889336229962   0.918863237274595   0.924812503605781 ...
                  0.930737337562886   0.936637939002571   0.942514505339240   0.948367231584678 ...
                  0.954196310386875   0.960001932068081   0.965784284662087   0.971543553950772 ...
                  0.977279923499916   0.982993574694310   0.988684686772166   0.994353436858858 ...
                  1.000000000000000];
     % Cast to fixed point with the most accurate rounding method
     WL = 4*B;  % Word length
     FL = 2*B;  % Fraction length
     LOG2LUT = fi(log2_table,1,WL,FL,'RoundingMethod','Nearest');
     % Set fimath for the most efficient math operations
     F = fimath('OverflowAction','Wrap',...
                'RoundingMethod','Floor',...
                'SumMode','SpecifyPrecision',...
                'SumWordLength',WL,...
                'SumFractionLength',FL,...
                'ProductMode','SpecifyPrecision',...
                'ProductWordLength',WL,...
                'ProductFractionLength',2*FL);
     LOG2LUT = setfimath(LOG2LUT,F);
 end