В этом примере показано, как преобразовать декартовы координаты в полярные с помощью алгоритма ядра векторизации CORDIC в MATLAB ®. Алгоритмы на основе CORDIC имеют решающее значение для многих встроенных приложений, включая управление двигателями, навигацию, обработку сигналов и беспроводную связь.
CORDIC - аббревиатура от COORDinate Rotation DIgital Computer. Алгоритм CORDIC на основе ротации Givens (см. [1,2]) является одним из наиболее аппаратных эффективных алгоритмов, поскольку требует только итеративных операций добавления сдвига. Алгоритм CORDIC исключает необходимость явных умножителей и подходит для вычисления множества функций, таких как синус, косинус, арксинус, арккосинус, арктангенс, векторная величина, деление, квадратный корень, гиперболические и логарифмические функции.
Алгоритм CORDIC с фиксированной точкой требует выполнения следующих операций:
1 поиск в таблице за одну итерацию
2 сдвига на итерацию
3 добавления на одну итерацию
Для вычисления можно использовать алгоритм вычисления векторного режима CORDIC atan(y/x)вычислять декартово-полярные преобразования в декартовы и для других операций. В режиме векторизации вращатель CORDIC поворачивает входной вектор в направлении положительной оси X для минимизации
составляющей остаточного вектора. Для каждой итерации, если
координата остаточного вектора положительна, вращатель CORDIC поворачивается по часовой стрелке (с использованием отрицательного угла); в противном случае он поворачивается против часовой стрелки (с использованием положительного угла). Каждый поворот использует постепенно меньшее значение угла. Если угловой аккумулятор инициализирован равным 0, в конце итераций накопленный угол поворота является углом исходного входного вектора.
В режиме векторизации уравнения CORDIC:


- угловой аккумулятор
где если
, и 
иначе;
и
является общим числом итераций.
по мере
приближения:



Где:
.
Обычно
выбирается как достаточно большое постоянное значение. Таким образом,
может быть предварительно вычислено.
Ниже приведен пример реализации кода MATLAB алгоритма CORDIC Vectoring Kernel (для случая скаляра x, y, и 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
Разумный выбор начальных значений позволяет алгоритму режима векторизации ядра CORDIC непосредственно вычислять величину
и угол.
Входные аккумуляторы инициализируются по значениям входных координат:


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

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


Другие аппроксимации функций на основе векторизации-ядра возможны посредством предварительной и последующей обработки и с использованием других исходных условий (см. [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');

Jack E. Volder, The CORDIC Trigonometric Computing Technique, IRE Transactions on Electronic Computers, том EC-8, сентябрь 1959, pp330-334.
Рэй Андрака, обзор алгоритма CORDIC для компьютеров на основе FPGA, Труды ACM/SIGDA 1998 года шестой международный симпозиум по полевым программируемым матрицам затворов, 22-24 февраля 1998 года, pp191-200