В этом примере показано, как вычислить квадратный корень с помощью алгоритма ядра CORDIC в MATLAB ®. Основанные на CORDIC алгоритмы имеют решающее значение для многих встраиваемых приложений, включая управление двигателем, навигацию, обработку сигналов и беспроводную связь.
CORDIC - это аббревиатура для COordinate Rotation DIgital Computer. Алгоритм CORDIC на основе вращения Givens (см. [1,2]) является одним из наиболее аппаратно эффективных алгоритмов, потому что он требует только итерационных операций shift-add. Алгоритм CORDIC устраняет необходимость в явных умножителях и подходит для вычисления множества функций, таких как синус, косинус, арксин, арксозин, арктангенс, векторные величины, деление, квадратный корень, гиперболические и логарифмические функции.
Алгоритм CORDIC с фиксированной точкой требует следующих операций:
Поиск по 1 таблице на итерацию
2 сдвиги на итерацию
3 сложения за итерацию
Обратите внимание, что для гиперболических алгоритмов, основанных на CORDIC, таких как квадратный корень, некоторые итерации (i = 4, 13, 40, 121,..., k, 3k + 1,...) повторяются, чтобы достичь сходимости результатов.
Можно использовать алгоритм режима вычисления CORDIC, чтобы вычислить гиперболические функции, такие как гиперболическая тригонометрия, квадратный корень, журнал, exp и т.д.
КОРДИЧЕСКИЕ УРАВНЕНИЯ В РЕЖИМЕ ГИПЕРБОЛИЧЕСКОГО ВЕКТОРИРОВАНИЯ.
Гиперболический режим векторизации используется для вычисления квадратного корня.
Для режима векторизации уравнения CORDIC следующие:
где
если, и в противном случае.
Этот режим обеспечивает следующий результат при подходах:
где
.
Обычно выбирается как достаточно большое постоянное значение. Таким образом, могут быть предварительно вычислены.
Обратите внимание также, что для квадратного корня мы будем использовать только результат.
Пример реализации кода MATLAB алгоритма CORDIC Hyperbolic Vectoring Kernel следует (для случая скаляра x
, y
, и z
). Этот же код может использоваться как для типов данных с фиксированной точкой, так и для данных с плавающей точкой.
Гиперболическое ядро векторизации CORDIC
k = 4; % Used for the repeated (3*k + 1) iteration steps for idx = 1:n xtmp = bitsra(x, idx); % multiply by 2^(-idx) ytmp = bitsra(y, idx); % multiply by 2^(-idx) if y < 0 x(:) = x + ytmp; y(:) = y + xtmp; z(:) = z - atanhLookupTable(idx); else x(:) = x - ytmp; y(:) = y - xtmp; z(:) = z + atanhLookupTable(idx); end if idx==k xtmp = bitsra(x, idx); % multiply by 2^(-idx) ytmp = bitsra(y, idx); % multiply by 2^(-idx) if y < 0 x(:) = x + ytmp; y(:) = y + xtmp; z(:) = z - atanhLookupTable(idx); else x(:) = x - ytmp; y(:) = y - xtmp; z(:) = z + atanhLookupTable(idx); end k = 3*k + 1; end end % idx loop
Квадратный корень Расчета с использованием гиперболического ядра векторизации CORDIC
Разумный выбор начальных значений позволяет алгоритму режима гиперболического векторизации ядра CORDIC вычислять квадратный корень.
Во-первых, выполняются следующие шаги инициализации:
установлено в.
установлено в.
После итераций эти начальные значения приводят к следующему выходу при приближении:
Это может быть дополнительно упрощено следующим образом:
где - коэффициент усиления CORDIC, заданный выше.
Примечание: для квадратного корня, и atanhLookupTable
не влияют на результат. Отсюда и atanhLookupTable
не используются.
Пример реализации кода MATLAB алгоритма CORDIC Square Root Kernel следует (для случая скаляра x
и y
). Этот же код может использоваться как для типов данных с фиксированной точкой, так и для данных с плавающей точкой.
Ядро Квадратного корня CORDIC
k = 4; % Used for the repeated (3*k + 1) iteration steps
for idx = 1:n xtmp = bitsra(x, idx); % multiply by 2^(-idx) ytmp = bitsra(y, idx); % multiply by 2^(-idx) if y < 0 x(:) = x + ytmp; y(:) = y + xtmp; else x(:) = x - ytmp; y(:) = y - xtmp; end
if idx==k xtmp = bitsra(x, idx); % multiply by 2^(-idx) ytmp = bitsra(y, idx); % multiply by 2^(-idx) if y < 0 x(:) = x + ytmp; y(:) = y + xtmp; else x(:) = x - ytmp; y(:) = y - xtmp; end k = 3*k + 1; end end % idx loop
Этот код идентичен реализации CORDIC Hyperbolic Vectoring Kernel выше, кроме того z
и atanhLookupTable
не используются. Это сокращение затрат на 1 поиск таблицы и 1 сложение за итерацию.
Пример
Используйте функцию CORDICSQRT, чтобы вычислить приблизительный квадратный корень v_fix
использование десяти итераций ядра CORDIC:
step = 2^-7; v_fix = fi(0.5:step:(2-step), 1, 20); % fixed-point inputs in range [.5, 2) niter = 10; % number of CORDIC iterations x_sqr = cordicsqrt(v_fix, niter); % Get the Real World Value (RWV) of the CORDIC outputs for comparison % and plot the error between the MATLAB reference and CORDIC sqrt values x_cdc = double(x_sqr); % CORDIC results (scaled by An_hp) v_ref = double(v_fix); % Reference floating-point input values x_ref = sqrt(v_ref); % MATLAB reference floating-point results figure; subplot(211); plot(v_ref, x_cdc, 'r.', v_ref, x_ref, 'b-'); legend('CORDIC', 'Reference', 'Location', 'SouthEast'); title('CORDIC Square Root (In-Range) and MATLAB Reference Results'); subplot(212); absErr = abs(x_ref - x_cdc); plot(v_ref, absErr); title('Absolute Error (vs. MATLAB SQRT Reference Results)');
Преодоление ограничений входной области значений алгоритма
Многие алгоритмы квадратного корня нормализуют входное значение, в пределах области значений [0,5, 2). Эта предварительная обработка обычно выполняется с использованием нормализации фиксированного размера слова и может использоваться для поддержки небольших а также больших областей значений входных значений.
Реализация алгоритма квадратного корня на основе CORDIC особенно чувствительна к входам за пределами этой области значений. Функция CORDICSQRT преодолевает это ограничение области значений алгоритма с помощью подхода нормализации, основанного на следующих математических отношениях:
, для некоторых и некоторых даже целое число.
Таким образом:
В функции CORDICSQRT значения для и, описанные выше, обнаруживаются во время нормализации входа. - количество начальных нулевых самых значащих битов (MSB) в двоичном представлении входов. Эти значения найдены через ряд побитовой логики и сдвигов. Примечание: поскольку должно быть четным, если количество начальных нулевых MSB является нечетным, делается один дополнительный сдвиг бита, чтобы сделать четным. Получившееся значение после этих сдвигов является значением.
становится входом базирующегося на CORDIC квадратного корневого ядра, где вычисляется приближение к. Результат затем масштабируется так, чтобы он вернулся в правильную выходную область значений. Это достигается посредством простого битового сдвига на биты. Направление сдвига (слева или справа) зависит от знака.
Пример
Вычислите квадратный корень 10-битных входных данных с фиксированной точкой с небольшой неотрицательной областью значений с помощью CORDIC. Сравните результаты алгоритма на основе CORDIC с эталонными результатами MATLAB с плавающей точкой в той же входной области значений.
step = 2^-8; u_ref = 0:step:(0.5-step); % Input array (small range of values) u_in_arb = fi(u_ref,0,10); % 10-bit unsigned fixed-point input data values u_len = numel(u_ref); sqrt_ref = sqrt(double(u_in_arb)); % MATLAB sqrt reference results niter = 10; results = zeros(u_len, 2); results(:,2) = sqrt_ref(:); % Compute the equivalent Real World Value result for plotting. % Plot the Real World Value (RWV) of CORDIC and MATLAB reference results. x_out = cordicsqrt(u_in_arb, niter); results(:,1) = double(x_out); figure; subplot(211); plot(u_ref, results(:,1), 'r.', u_ref, results(:,2), 'b-'); legend('CORDIC', 'Reference', 'Location', 'SouthEast'); title('CORDIC Square Root (Small Input Range) and MATLAB Reference Results'); axis([0 0.5 0 0.75]); subplot(212); absErr = abs(results(:,2) - results(:,1)); plot(u_ref, absErr); title('Absolute Error (vs. MATLAB SQRT Reference Results)');
Пример
Вычислите квадратный корень 16-битных входных данных с фиксированной точкой с большой положительной областью значений с помощью CORDIC. Сравните результаты алгоритма на основе CORDIC с эталонными результатами MATLAB с плавающей точкой в той же входной области значений.
u_ref = 0:5:2500; % Input array (larger range of values) u_in_arb = fi(u_ref,0,16); % 16-bit unsigned fixed-point input data values u_len = numel(u_ref); sqrt_ref = sqrt(double(u_in_arb)); % MATLAB sqrt reference results niter = 16; results = zeros(u_len, 2); results(:,2) = sqrt_ref(:); % Compute the equivalent Real World Value result for plotting. % Plot the Real World Value (RWV) of CORDIC and MATLAB reference results. x_out = cordicsqrt(u_in_arb, niter); results(:,1) = double(x_out); figure; subplot(211); plot(u_ref, results(:,1), 'r.', u_ref, results(:,2), 'b-'); legend('CORDIC', 'Reference', 'Location', 'SouthEast'); title('CORDIC Square Root (Large Input Range) and MATLAB Reference Results'); axis([0 2500 0 55]); subplot(212); absErr = abs(results(:,2) - results(:,1)); plot(u_ref, absErr); title('Absolute Error (vs. MATLAB SQRT Reference Results)');
Jack E. Volder, «The CORDIC Trigonometric Computing Technique», IRE Transactions on Electronic Computers, Volume EC-8, September 1959, pp. 330-334.
J.S. Walther, «A Unified Algorithm for Elementary Functions», Conference Proceedings, Spring Joint Computer Conference, May 1971, pp. 379-385.