В этом примере показано, как нормализовать данные для использования в таблицах подстановки.
Таблицы поиска - это очень эффективный способ записи ресурсоемких функций для встроенных устройств с фиксированной точкой. Например, можно эффективно реализовать логарифм, синус, косинус, касательную и квадратный корень с помощью таблиц поиска. Вы нормализуете входные данные этих функций, чтобы создать таблицу подстановки меньшего размера, а затем масштабируете выходные данные на коэффициент нормализации. В этом примере показано, как реализовать функцию нормализации, которая используется в примерах Реализация квадратного корня с фиксированной точкой с помощью таблицы подстановки и Реализация Log2 с фиксированной точкой с помощью таблицы подстановки.
Чтобы убедиться, что этот пример не изменяет ваши настройки или настройки, этот код сохраняет исходное состояние.
originalFormat = get(0,'format'); format long g originalWarningState = warning('off','fixed:fi:underflow'); originalFiprefState = get(fipref); reset(fipref)
Это состояние будет восстановлено в конце примера.
Использовать функцию нормализации fi_normalize_unsigned_8_bit_byte, определенный ниже, для нормализации данных в u.
u = fi(0.3,1,16,8);
В двоичном формате u = 00000000.01001101_2 = 0.30078125 (значение фиксированной точки не равно ровно 0,3 из-за округления до 8 бит). Цель - нормализовать так, чтобы
u = 1.001101000000000_2 * 2^(-2) = x * 2^n.
Начать с u представлено как целое число без знака.
High byte Low byte
00000000 01001101 Начало: u как целое число без знака.
Старший байт: 0 = 00000000_2. Добавьте 1, чтобы сделать из него индекс: index = 0 + 1 = 1. Таблица поиска по числу начальных нулей в индексе 1 указывает, что имеется 8 начальных нулей: NLZLUT(1) = 8. Сдвиг влево на столько битов.
High byte Low byte
01001101 00000000 Сдвинут влево на 8 бит.
Повторите повторную попытку, чтобы удалить первые нули из следующего байта.
Старший байт: 77 = 01001101_2. Добавьте 1, чтобы сделать из него индекс: index = 77 + 1 = 78. Таблица поиска по количеству нулей начала в индексе 78 указывает, что имеется 1 нуль начала: NLZLUT(78) = 1. Сдвиг влево на столько битов.
High byte Low byte
100110100 0000000 Сдвинут влево на 1 дополнительный бит, всего 9.
Повторно интерпретировать эти биты как неподписанные фиксированные точки с 15 дробными битами.
x = 1.001101000000000_2 = 1.203125
Значение для n - длина слова u, минус длина фракции u, минус количество левых смен, минус 1.
n = 16-8-9-1 = -2
И так ваш результат:
[x,n] = fi_normalize_unsigned_8_bit_byte(u)
x =
1.203125
DataTypeMode: Fixed-point: binary point scaling
Signedness: Unsigned
WordLength: 16
FractionLength: 15
n = int8
-2
Сравнивая двоичные значения, можно увидеть, что x имеет те же биты, что и u, сдвинутый влево на 9 бит.
binary_representation_of_u = bin(u)
binary_representation_of_u = '0000000001001101'
binary_representation_of_x = bin(x)
binary_representation_of_x = '1001101000000000'
Восстановить исходное состояние.
set(0,'format',originalFormat); warning(originalWarningState); fipref(originalFiprefState); %#ok<*NOPTS>
Этот алгоритм нормализует неподписанные данные 8-битными байтами. Данный вход u > 0, выходные данные x нормализовано так, что
u = x*2^n
где 1 <= x < 2 и n - целое число. Обратите внимание, что n может быть положительным, отрицательным или нулевым.
Функция fi_normalize_unsigned_8_bit_byte просматривает 8 самых значащих битов входа за один раз и влево сдвигает биты до тех пор, пока самый значащий бит не будет равен 1. Количество битов для сдвига для каждого 8-битового байта считывается из таблицы поиска количества начальных нулей NLZLUT.
function [x,n] = fi_normalize_unsigned_8_bit_byte(u) assert(isscalar(u),'Input must be scalar'); assert(all(u>0),'Input must be positive.'); assert(isfi(u) && isfixed(u),'Input must be a fi object with fixed-point data type.'); u = removefimath(u); NLZLUT = number_of_leading_zeros_look_up_table(); word_length = u.WordLength; u_fraction_length = u.FractionLength; B = 8; leftshifts=int8(0); % Reinterpret the input as an unsigned integer. T_unsigned_integer = numerictype(0, word_length, 0); v = reinterpretcast(u,T_unsigned_integer); F = fimath('OverflowAction','Wrap',... 'RoundingMethod','Floor',... 'SumMode','KeepLSB',... 'SumWordLength',v.WordLength); v = setfimath(v,F); % Unroll the loop in generated code so there will be no branching. for k = coder.unroll(1:ceil(word_length/B)) % For each iteration, see how many leading zeros are in the high % byte of V, and shift them out to the left. Continue with the % shifted V for as many bytes as it has. % % The index is the high byte of the input plus 1 to make it a % one-based index. index = int32(bitsra(v,word_length-B) + uint8(1)); % Index into the number-of-leading-zeros lookup table. This lookup % table takes in a byte and returns the number of leading zeros in the % binary representation. shiftamount = NLZLUT(index); % Left-shift out all the leading zeros in the high byte. v = bitsll(v,shiftamount); % Update the total number of left-shifts leftshifts = leftshifts+shiftamount; end % The input has been left-shifted so the most-significant-bit is a 1. % Reinterpret the output as unsigned with one integer bit, so % that 1 <= x < 2. T_x = numerictype(0,word_length,word_length-1); x = reinterpretcast(v,T_x); x = removefimath(x); % Let Q = int(u). Then u = Q*2^(-u_fraction_length), % and x = Q*2^leftshifts * 2^(1-word_length). Therefore, % u = x*2^n, where n is defined as: n = word_length - u_fraction_length - leftshifts - 1; end
Функция number_of_leading_zeros_look_up_table используется fi_normalize_unsigned_8_bit_byte и возвращает таблицу количества начальных нулевых битов в 8-битовом слове.
Первый элемент NLZLUT равен 8 и соответствует u=0. В 8-битном значении u = 00000000_2, где нижний индекс 2 указывает base-2, имеется 8 начальных нулевых битов.
Второй элемент NLZLUT равен 7 и соответствует u=1. Имеется 7 начальных нулевых битов в 8-битном значении u = 00000001_2.
И так далее, пока последний элемент NLZLUT не будет равен 0 и соответствует u=255. В 8-битном значении имеется 0 начальных нулевых битов u=11111111_2.
NLZLUT таблица была создана:
>> B = 8; % Number of bits in a byte
>> NLZLUT = int8(B-ceil(log2((1:2^B))))
function NLZLUT = number_of_leading_zeros_look_up_table() % B = 8; % Number of bits in a byte % NLZLUT = int8(B-ceil(log2((1:2^B)))) NLZLUT = int8([8 7 6 6 5 5 5 5 ... 4 4 4 4 4 4 4 4 ... 3 3 3 3 3 3 3 3 ... 3 3 3 3 3 3 3 3 ... 2 2 2 2 2 2 2 2 ... 2 2 2 2 2 2 2 2 ... 2 2 2 2 2 2 2 2 ... 2 2 2 2 2 2 2 2 ... 1 1 1 1 1 1 1 1 ... 1 1 1 1 1 1 1 1 ... 1 1 1 1 1 1 1 1 ... 1 1 1 1 1 1 1 1 ... 1 1 1 1 1 1 1 1 ... 1 1 1 1 1 1 1 1 ... 1 1 1 1 1 1 1 1 ... 1 1 1 1 1 1 1 1 ... 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0]); end