CORDIC(Coordinate Rotation Digital Computer)座標旋轉數字計算機,是數學與計算機技術交叉產生的一種機器算法,用於解決計算機的數學計算問題。發展到如今,CORDIC算法及其擴展算法大體有三種計算模式:圓周旋轉模式、線性旋轉模式和雙曲線旋轉模式,分別用來實現不一樣的數學運算。 git
本文介紹圓周旋轉模式下的CORDIC算法原理及實現過程,另兩種模式將分期介紹。算法
簡單來說,CORDIC利用近似逼近的思想,將計算機中三角函數、開根號、求對數等複雜運算,轉化爲簡單的加減和移位操做。微信
對於實際只會識別0和1的計算機來講,加減和移位是它能輕鬆實現的操做,所以利用CORDIC算法將大大提高計算機對複雜運算的計算效率。目前,儘管計算機的運行速度已經足夠使得大多數開發者不用太多考慮計算效率的問題,但在一些實時數據流比較大的場合(如通訊、多媒體處理等),CORDIC算法依然是實現高速運算的關鍵。併發
相似CORDIC實現的數學思想早在1624年就由Henry Briggs提出並發表,但直到1956年,CORDIC算法才真正被美國工程師Jack E.Volder發現並運用,當時他正在尋找提升計算器計算精度和實時性的算法。直到1959年,Volder的算法才爲公衆所知,並在計算器上大行其道。函數
算法描述 性能
1. 數學背景spa
如圖,XY平面中一點(x1,y1)經圓周旋轉θ角度,獲得點(x2,y2)。經簡單的三角函數關係,可獲得:.net
經過提出因數cosθ,可得:3d
若是不考慮cosθ,獲得「僞旋轉」方程:code
僞旋轉僅實現了正確的角度旋轉,但向量模值變爲原來的1/cosθ。
2. CORDIC方法
若使得tanθ = 2^(-i),i爲天然數,則上式變爲:
注意!上式已經僅剩加減和移位運算。
若是咱們把全部tanθi = 2^(-i)對應的角度和正切值製成一張表,以下所示:
……
能夠肯定的是,任意旋轉角度θ,均可以由上表中的大小不一樣θi進行屢次旋轉獲得。CORDIC正是利用這一點,將θ角度的旋轉分解爲從大到小、逐次逼近真實旋轉角度的一組旋轉,而這些旋轉的實現又均可以由加減和移位運算來完成。θi能夠預先製成表格,供計算機查找使用。
算法實現
1. 已知座標(x,y),求其向量對應的相角θ(反正切)和模值
思想: 把原向量逐次向X正軸進行僞旋轉逼近,整個過程的累計旋轉角度即爲θ,而旋轉後的x座標補償模值增益K後即爲原向量模值。
每次迭代的方程爲:
模值總增益K爲:
其中d決定旋轉方向爲逆時針仍是順時針,z爲角度累加值。
注意!查找表中全部θi的總和約爲99度,所以能實現計算的角度在-99~99度之間。實際算法實現時,咱們可預先判斷座標象限,人爲將其轉化爲第一象限內的計算,並在過後補償爲真實值。
如圖:(x,y)=(3,sqrt(3)),迭代深度=16,CORDIC算法實現過程
matlab代碼以下:
%% *********************************************************************************** % 已知座標,用cordic算法計算相角和幅值。基本公式以下: % x(k+1) = x(k) - d(k)*y(k)*2^(-k) % y(k+1) = y(k) + d(k)*x(k)*2^(-k) % z(k) = z(k) - d(k)*actan(2^(-k)) %% *********************************************************************************** clear;close all;clc; % 初始化---------------------------------------- N = 16; %迭代次數 tan_table = 2.^-(0 : N-1); angle_LUT = atan(tan_table); K = 1; for k = 0 : N-1 K = K*(1/sqrt(1 + 2^(-2*k))); end x = 3; y = sqrt(3); angle_accumulate = 0; % cordic算法計算------------------------------- if (x==0 && y==0) radian_out = 0; amplitude_out = 0; else % 先作象限判斷,獲得相位補償值 if (x > 0) phase_shift = 0; elseif (y < 0) phase_shift = -pi; else phase_shift = pi; end for k = 0 : N-1 % 迭代開始 x_temp = x; if (y < 0) % d(k)=1,逆時針旋轉 x = x_temp - y*2^(-k); y = y + x_temp*2^(-k); angle_accumulate = angle_accumulate - angle_LUT(k+1); else % d(k)=-1,順時針旋轉 x = x_temp + y*2^(-k); y = y - x_temp*2^(-k); angle_accumulate = angle_accumulate + angle_LUT(k+1); end radian_out = angle_accumulate + phase_shift; %弧度輸出 end amplitude_out = x*K; %幅值輸出 end angle_out = radian_out*180/pi; %相角輸出
2. 已知角度θ,求正弦sinθ和餘弦cosθ
思想: 若向量模值爲1,則其x座標就是餘弦值,y座標就是正弦值。利用這一點,從(K,0)處迭代旋轉至θ處的單位矢量便可。
迭代方程及K的計算同第一小節。同時也要注意預先對象限的判斷和補償。
如圖:θ=60度,迭代深度=16,CORDIC算法實現過程
matlab代碼以下:
%% *********************************************************************************** % 已知相角theta,計算其正弦和餘弦值。基本公式以下: % x(k+1) = x(k) - d(k)*y(k)*2^(-k) % y(k+1) = y(k) + d(k)*x(k)*2^(-k) % z(k) = z(k) - d(k)*actan(2^(-k)) %% *********************************************************************************** clear;close all;clc; % 初始化---------------------------------------- N = 16; %迭代次數 tan_table = 2.^-(0 : N-1); angle_LUT = atan(tan_table); K = 1; for k = 0 : N-1 K = K*(1/sqrt(1 + 2^(-2*k))); end theta = -90; x = 1; y = 0; phase_accumulate = theta/180*pi; %轉化爲弧度 % cordic算法計算------------------------------- if (phase_accumulate > pi/2) % 先作象限判斷,獲得相位補償值 phase_accumulate = phase_accumulate - pi; sign_x = -1; sign_y = -1; elseif (phase_accumulate < -pi/2) phase_accumulate = phase_accumulate + pi; sign_x = -1; sign_y = -1; else sign_x = 1; sign_y = 1; end for k = 0 : N-1 % 迭代開始 x_temp = x; if (phase_accumulate > 0) % d(k)=1,逆時針旋轉 x = x_temp - y*2^(-k); y = y + x_temp*2^(-k); phase_accumulate = phase_accumulate - angle_LUT(k+1); else % d(k)=-1,順時針旋轉 x = x_temp + y*2^(-k); y = y - x_temp*2^(-k); phase_accumulate = phase_accumulate + angle_LUT(k+1); end end cos_out = sign_x*x*K; %餘弦輸出 sin_out = sign_y*y*K; %正弦輸出
參考文獻/資料
【1】https://en.wikipedia.org/wiki/CORDIC
【2】Xilinx CORDIC算法(很是經典)——百度文庫
【3】ANDRAKA R. A Survey of CORDIC Algorithms for FPGA Based Computers[C] ,1998
·END·
歡迎來個人微信公衆號作客:信號君
專一於信號處理知識、高性能計算、現代處理器&計算機體系
技術成長 | 讀書筆記 | 認知升級
幸會~