How to get rid of scale factor from CORDIC

1.5k views Asked by At

From CORDIC, K_i = cos(tan^-1(2^i)). As I know the K is approached 0.607xxx. How do I approach to 0.607xxx?

Also does it mean that I can use 0.607xxx instead of cos(tan^-1(2^I))? I am citing from this article.

I am trying to implement hyperbolic tanh function. And so far I understand (6) equation. I'm not sure about how to make the K and how to use it?

Update :

I want to know where the total scaling concept apply in progress to get sine, cos angle. Here some example, I set that the specified angle is 20. And I want to know sine, cos angle. The the process as follows.

n d x y angle K arctan value

0 1 0.7071 0.7071 0.7854 0.7071 0.785398

....

10 -1 0.9395 0.3426 0.3497 1 0.000976

We can get if specified angle is 20 degree(0.3491) Then we get sine (20) = 0.9395 Cos(20) = 0.3497

Done.

But I have still curious about where is the total scaling concept(0.607) apply? Where total scaling concept(0.607 ) used in progress to get sin, cos angle ?

2

There are 2 answers

8
Jonathan Drolet On BEST ANSWER

Each step in the CORDIC algorithm add a scaling of cos(arctan(2^-i)) (or 1/sqrt(1+2^-2i)), so for a 4 steps CORDIC, the total scaling is:

cos(arctan(2^-0))*cos(arctan(2^-1))*cos(arctan(2^-2))*cos(arctan(2^-3)) = 0.60883

If you add more iterations, it gets to 0.607252935 and some. As to what to do with that factor, it's up to you and the function you implement. You may want to remove it and give unscaled result, or your consumer may be able to deal it it more easily.

In the case of tanh, I think there is a division of two values with the same scaling, so it would cancel out in that case. I'm really not that sure on that one, since I didn't use CORDIC in this mode, so you will have to figure that out by yourself.

Update

The advantage of CORDIC is that each iteration is a shift+add on X and Y. In your example your incorporated the scale factor, which gives the right answer, but isn't necessary and disallow the simple shift + add operation. Thus, we leave the scaling as a post-operation (or initialization), or out entirely if the subsequent module can deal with a scaled answer.

The way to get sin/cos of 20 is, starting with X = 1; Y = 0; Z = 20:

Z0 = 20 - 45.00 = -25.00; X0 = 1 - 0 = 1; Y0 = 0 + 2^-0 = 1
Z1 = Z0 + 26.57 =   1.57; X1 = X0 + Y0*2^-1 = 1.5000; Y1 = Y0 - X0*2^-1 = 0.5000
Z2 = Z1 - 14.04 = -12.47; X2 = X1 - Y1*2^-2 = 1.3750; Y2 = Y1 + X1*2^-2 = 0.8750
Z3 = Z2 +  7.13 = - 5.35; X3 = X2 + Y2*2^-3 = 1.4844; Y3 = Y2 - X2*2^-3 = 0.7031
Z4 = Z3 +  3.58 = - 1.77; X4 = X3 + Y3*2^-4 = 1.5283; Y4 = Y3 - X3*2^-4 = 0.6104
Z5 = Z4 +  1.79 =   0.02; X5 = X4 + Y4*2^-5 = 1.5474; Y5 = Y4 - X4*2^-5 = 0.5626
Z6 = Z5 -  0.90 = - 0.88; X6 = X5 - Y5*2^-6 = 1.5386; Y6 = Y5 + X5*2^-6 = 0.5868

The final answer is scaled: cos(20) = X6*0.607 = 0.9339 and sin(20) = Y6*0.607 = 0.3562. The advantage of ignoring the scaling factor should be obvious, each iteration is Xi = Xi-1 +- Yi-1 * 2^-i, which is a shift and add. You also don't need to store the scaling factor in a ROM or somewhere else; the only memory you need is for the arctan(2^-i).

Note that you can get an unscaled result by starting with X = 0.607 instead of X = 1.

3
Kevin Thibedeau On

When using CORDIC you calculate tan and tanh by taking the ratio of sin to cos or sinh to cosh. Since both terms have the scale factor applied to them the K's cancel out and you don't have to do any correction. You do need to be aware of potential issues with overflow and ensure that enough bits are present in the X and Y registers to hold the scaled values. Another option is to prescale the X and Y input values (multiply by 0.607) so that the gain is 1 after running the algorighm.