Преобразуйте декартов в полярный Используя CORDIC векторизация ядра

В этом примере показано, как преобразовать Декартов в полярные координаты с помощью CORDIC векторизация алгоритма ядра в MATLAB®. Основанные на CORDIC алгоритмы очень важны для многих встраиваемых приложений, включая блоки управления приводом, навигацию, обработку сигналов и радиосвязи.

Введение

CORDIC является акронимом для Координатного Компьютера Вращения. Основанный на вращении алгоритм CORDIC Givens (см. [1,2]) является одним из большей части оборудования эффективные алгоритмы, потому что это только требует итеративных операций shift-add. Алгоритм CORDIC избавляет от необходимости явные множители и подходит для вычисления множества функций, таков как синус, косинус, arcsine, arccosine, арктангенс, векторная величина, разделитесь, квадратный корень, гиперболические и логарифмические функции.

Фиксированная точка алгоритм CORDIC требует следующих операций:

  • 1 поиск по таблице на итерацию

  • 2 сдвига на итерацию

  • 3 сложения на итерацию

Алгоритм ядра CORDIC Используя режим расчета векторизации

Можно использовать CORDIC, векторизовавший вычислительный алгоритм режима, чтобы вычислить atan(y/x), вычислите декартов полярный к декартовым преобразованиям, и для других операций. В векторизации режима вращающее устройство CORDIC вращает входной вектор к положительной Оси X, чтобы минимизировать$$ y $$ компонент вектора невязок. Для каждой итерации, если$$ y $$ координата вектора невязок положительна, вращающее устройство CORDIC вращается по часовой стрелке (использующий отрицательный угол); в противном случае это вращается против часовой стрелки (использующий положительный угол). Каждое вращение использует прогрессивно меньшее угловое значение. Если угловой аккумулятор инициализируется к 0, в конце итераций, накопленный угол поворота является углом исходного входного вектора.

В векторизации режима уравнения CORDIC:

$$ x_{i+1} = x_{i} - y_{i}*d_{i}*2^{-i} $$

$$ y_{i+1} = y_{i} + x_{i}*d_{i}*2^{-i} $$

$$ z_{i+1} = z_{i} + d_{i}*\mbox{atan}(2^{-i}) $$ угловой аккумулятор

где$$ d_{i} = +1 $$, если$$ y_{i} < 0 $$, и$$ -1 $$ в противном случае;

$$ i = 0, 1, ..., N-1 $$, и$$ N $$ общее количество итераций.

Как$$ N $$ подходы$$ +\infty $$:

$$ x_{N} = A_{N}\sqrt{x_{0}^2+y_{0}^2} $$

$$ y_{N} = 0 $$

$$ z_{N} = z_{0} + \mbox{atan}(y_{0}/x_{0}) $$

Где:

$$ A_{N} = \prod_{i=0}^{N-1}{\sqrt{1+2^{-2i}}} $$.

Обычно$$ N $$ выбирается, чтобы быть достаточно большим постоянным значением. Таким образом,$$ A_{N} $$ может быть предварительно вычислен.

Эффективная реализация MATLAB CORDIC векторизация алгоритма ядра

Пример реализации кода MATLAB CORDIC Векторизация алгоритма Ядра следует (для случая скалярного xY, и z). Этот тот же код может использоваться и для фиксированной точки и для операции с плавающей точкой.

CORDIC векторизация ядра

function [x, y, z] = cordic_vectoring_kernel(x, y, z, inpLUT, n)
% Perform CORDIC vectoring kernel algorithm for N iterations.
xtmp = x;
ytmp = y;
for idx = 1:n
    if y < 0
        x(:) = accumneg(x, ytmp);
        y(:) = accumpos(y, xtmp);
        z(:) = accumneg(z, inpLUT(idx));
    else
        x(:) = accumpos(x, ytmp);
        y(:) = accumneg(y, xtmp);
        z(:) = accumpos(z, inpLUT(idx));
    end
    xtmp = bitsra(x, idx); % bit-shift-right for multiply by 2^(-idx)
    ytmp = bitsra(y, idx); % bit-shift-right for multiply by 2^(-idx)
end

CORDIC-Based, декартов к полярному преобразованию Используя нормированные входные модули

Декартов к полярному расчету Используя CORDIC векторизация ядра

Разумный выбор начальных значений позволяет алгоритму режима векторизации ядра CORDIC непосредственно вычислять величину$$ R = \sqrt{x_{0}^2+y_{0}^2} $$ и угол$$ \theta = \mbox{atan}(y_{0}/x_{0}) $$.

Входные аккумуляторы инициализируются к входным значениям координаты:

  • $$ x_{0} = X $$

  • $$ y_{0} = Y $$

Угловой аккумулятор инициализируется, чтобы обнулить:

  • $$ z_{0} = 0 $$

После$$ N $$ итераций эти начальные значения приводят к следующим выходным параметрам как$$ N $$ подходы$$ +\infty $$:

  • $$ x_{N} \approx A_{N}\sqrt{x_{0}^2+y_{0}^2} $$

  • $$ z_{N} \approx \mbox{atan}(y_{0}/x_{0}) $$

Другие основанные на векторизации-ядром функциональные приближения возможны через пред - и последующая обработка и использование других начальных условий (см. [1,2]).

Пример

Предположим, что у вас есть некоторые измерения Декартовых (X, Y) данные, нормированные к значениям между [-1, 1), что вы хотите преобразовать в полярный (величина, угол) координаты. Также предположите, что у вас есть 16-битный целочисленный арифметический модуль, который может выполнить, добавляют, вычитают, переключают, и операции памяти. С таким устройством вы могли реализовать CORDIC векторизация ядра, чтобы эффективно вычислить величину и угол от входа (X, Y), координатные значения, без использования умножается или большие интерполяционные таблицы.

sumWL  = 16; % CORDIC sum word length
thNorm = -1.0:(2^-8):1.0; % Also using normalized [-1.0, 1.0] angle values
theta  = fi(thNorm, 1, sumWL); % Fixed-point angle values (best precision)
z_NT   = numerictype(theta);   % Data type for Z
xyCPNT = numerictype(1,16,15); % Using normalized X-Y range [-1.0, 1.0)
thetaRadians = pi/2 .* thNorm; % real-world range [-pi/2 pi/2] angle values
inXfix = fi(0.50 .* cos(thetaRadians), xyCPNT); % X coordinate values
inYfix = fi(0.25 .* sin(thetaRadians), xyCPNT); % Y coordinate values

niters = 13; % Number of CORDIC iterations
inpLUT = fi(atan(2 .^ (-((0:(niters-1))'))) .* (2/pi), z_NT); % Normalized
z_c2p  = fi(zeros(size(theta)), z_NT);   % Z array pre-allocation
x_c2p  = fi(zeros(size(theta)), xyCPNT); % X array pre-allocation
y_c2p  = fi(zeros(size(theta)), xyCPNT); % Y array pre-allocation

for idx = 1:length(inXfix)
    % CORDIC vectoring kernel iterations
    [x_c2p(idx), y_c2p(idx), z_c2p(idx)] = ...
        fidemo.cordic_vectoring_kernel(...
            inXfix(idx), inYfix(idx), fi(0, z_NT), inpLUT, niters);
end

% Get the Real World Value (RWV) of the CORDIC outputs for comparison
% and plot the error between the (magnitude, angle) values
AnGain       = prod(sqrt(1+2.^(-2*(0:(niters-1))))); % CORDIC gain
x_c2p_RWV    = (1/AnGain) .* double(x_c2p); % Magnitude (scaled by CORDIC gain)
z_c2p_RWV    =   (pi/2)   .* double(z_c2p); % Angles (in radian units)
[thRWV,rRWV] = cart2pol(double(inXfix), double(inYfix)); % MATLAB reference
magnitudeErr = rRWV - x_c2p_RWV;
angleErr     = thRWV - z_c2p_RWV;
figure;
subplot(411);
plot(thNorm, x_c2p_RWV);
axis([-1 1 0.25 0.5]);
title('CORDIC Magnitude (X) Values');
subplot(412);
plot(thNorm, magnitudeErr);
title('Error between Magnitude Reference Values and X Values');
subplot(413);
plot(thNorm, z_c2p_RWV);
title('CORDIC Angle (Z) Values');
subplot(414);
plot(thNorm, angleErr);
title('Error between Angle Reference Values and Z Values');

Ссылки

  1. Джек Э. Волдер, Тригонометрический Вычислительный Метод CORDIC, Транзакции IRE на Электронно-вычислительных машинах, Volume EC 8, сентябрь 1959, pp330-334.

  2. Рэй Андрэка, обзор алгоритма CORDIC для основанных на FPGA компьютеров, Продолжений 1998 шестых международных симпозиумов ACM/SIGDA по Программируемым пользователем вентильным матрицам, 22-24 февраля 1998, pp191-200