math - Why we use CORDIC gain? -
i'm studying cordic. , found cordic gain. k=0.607xxx.
from cordic, k_i = cos(tan^-1(2^i)).
as know k approched 0.607xxx.when going infinity
this value come k multiplying.
i understand reason of exist each k. curioused used ? why use value k=0.607xx?
the scale factor rotation mode of circular variant of cordic can established first principles. idea behind cordic take point on unit circle , rotate it, in steps, through angle u sine , cosine want determine.
to end define set of incremental angles a0, ..., an-1, such ak = atan(0.5k). sum these incremental angles appropriately partial sum of angles sk, such sn ~= u. let yk = cos(sk) , xk = sin(sk). if in given step k rotate ak, have
yk+1 = cos (sk+1) = cos (sk + ak)
xk+1 = sin (sk+1) = sin (sk + ak)
we can compute xk+1 , yk+1 xk , yk follows:
yk+1 = yk * cos (ak) - xk * sin (ak)
xk+1 = xk * cos (ak) + yk * sin (ak)
considering may both add , subtract ak, , tan(ak) = sin(ak)/cos(ak), get:
yk+1 = cos (ak) * (yk ∓ xk * tan(ak)) = cos (sk+1)
xk+1 = cos (ak) * (xk ± yk * tan(ak)) = sin (sk+1)
to simplify computation, can leave out multiplication cos(ak) in every step, gives our cordic iteration scheme:
yk+1 = y ∓ xk * tan(ak)
xk+1 = x ± yk * tan(ak)
because of our choice of ak, multiplications tan(ak) turn simple right shifts if compute in fixed-point arithmetic. because left off factors cos(ak), wind with
yn ~= cos(u) * (1 / (cos (a0) * cos (a1) * ... * cos (an))
xn ~= sin(u) * (1 / (cos (a0) * cos (a1) * ... * cos (an))
the factor f = cos (a0) * cos (a1) * ... * cos (an) 0.607..., noted. incorporate computation setting starting values
y0 = f * cos(0) = f
x0 = f * sin(0) = 0
here c code shows entire computation in action, using 16-bit fixed-point arithmetic. input angles scaled such 360 degrees correspond 216, while sine , cosine outputs scaled such 1 corresponds 215.
#include <stdio.h> #include <stdlib.h> #include <math.h> /* round (atand (0.5**i) * 65536/360) */ static const short a[15] = { 0x2000, 0x12e4, 0x09fb, 0x0511, 0x028b, 0x0146, 0x00a3, 0x0051, 0x0029, 0x0014, 0x000a, 0x0005, 0x0003, 0x0001, 0x0001 }; #define swap(a,b){a=a^b; b=b^a; a=a^b;} void cordic (unsigned short u, short *s, short *c) { short x, y, oldx, oldy, q; int i; x = 0; y = 0x4dba; /* 0.60725 */ oldx = x; oldy = y; q = u >> 14; /* quadrant */ u = u & 0x3fff; /* reduced angle */ u = -(short)u; = 0; { if ((short)u < 0) { x = x + oldy; y = y - oldx; u = u + a[i]; } else { x = x - oldy; y = y + oldx; u = u - a[i]; } oldx = x; oldy = y; i++; /* right shift of signed negative number implementation defined in c */ oldx = (oldx < 0) ? (-((-oldx) >> i)) : (oldx >> i); oldy = (oldy < 0) ? (-((-oldy) >> i)) : (oldy >> i); } while (i < 15); (i = 0; < q; i++) { swap (x, y); y = -y; } *s = x; *c = y; } int main (void) { float angle; unsigned short u; short s, c; printf ("angle in degrees [0,360): "); scanf ("%f", &angle); u = (unsigned short)(angle * 65536.0f / 360.0f + 0.5f); cordic (u, &s, &c); printf ("sin = % f (ref: % f) cos = % f (ref: % f)\n", s/32768.0f, sinf(angle/360*2*3.14159265f), c/32768.0f, cosf(angle/360*2*3.14159265f)); return exit_success; }
Comments
Post a Comment