I am trying to implement CORDIC in C. I have to generate the constant values that the algorithm uses. The first list of arctangent values was straightforward but I am having trouble with the second list of 'Kvalues.'
% Kvalues = cumprod(1./sqrt(1 + 1j*2.^(-(0:23)))) Kvalues = [ ... 0.70710678118655 0.63245553203368 0.61357199107790 0.60883391251775 ... 0.60764825625617 0.60735177014130 0.60727764409353 0.60725911229889 ... 0.60725447933256 0.60725332108988 0.60725303152913 0.60725295913894 ... 0.60725294104140 0.60725293651701 0.60725293538591 0.60725293510314 ... 0.60725293503245 0.60725293501477 0.60725293501035 0.60725293500925 ... 0.60725293500897 0.60725293500890 0.60725293500889 0.60725293500888 ];
However I am not very familiar with this notation and I am having a hard time making sense of this and producing a simple formula that would produce the same results. I do not want to just paste these values into my CORDIC implementation because I would like to generate them myself with the appropriate amount of precision.
Here is what I came up with based on what I could understand but this does not produce the correct results:
float prev = 1;
for (int i = 0; i < PRECISION; i++)
printf("%f\n", prev = prev/sqrt(1+pow(2, -i)));
I am expecting the same values I saw in the list from Wikipedia:
0.707106
0.632455
0.613571
0.608833
0.607648
0.607351
But with my formula they converge to 0.457942...
instead of 0.607252...
:
0.707107
0.577350
0.516398
0.486864
0.472328
0.465116
What is the correct formula in C to generate PRECISION
'Kvalues' for CORDIC?
I tried a number of variations [not shown] by doing a websearch on CORDIC
and looking at various pages.
From here: https://nonagon.org/ExLibris/cordic-c-javascript I got the formula:
prev = prev / sqrt(1 + (1.0 / pow(2, 2.0 * i)))
Ultimately, for your code, it was change:
pow(2, -i)
Into:
pow(2, -2.0 * i)
Here is the modified code that works:
#include <stdio.h>
#include <math.h>
#define PRECISION 6
#define CALL(_fnc) \
do { \
printf("\n" #_fnc "\n"); \
_fnc(); \
} while (0)
void
orig(void)
{
double prev = 1.0;
for (int i = 0; i < PRECISION; i++)
printf("%f\n", prev = prev / sqrt(1 + pow(2, -i)));
}
void
fix1(void)
{
float prev = 1;
for (int i = 0; i < PRECISION; i++)
printf("%f\n",prev = prev / sqrt(1 + pow(2, -2.0 * i)));
}
int
main(void)
{
CALL(orig);
CALL(fix1);
return 0;
}
Here is the program output:
orig
0.707107
0.577350
0.516398
0.486864
0.472328
0.465116
fix1
0.707107
0.632456
0.613572
0.608834
0.607648
0.607352
I recommend using double
instead of float
and increasing the precision of the printf
format (e.g. %.14f
):
#include <stdio.h>
#include <math.h>
#define PRECISION 6
#define CALL(_fnc) \
do { \
printf("\n" #_fnc "\n"); \
_fnc(); \
} while (0)
void
orig(void)
{
double prev = 1.0;
for (int i = 0; i < PRECISION; i++)
printf("%.14f\n", prev = prev / sqrt(1 + pow(2, -i)));
}
void
fix1(void)
{
double prev = 1;
for (int i = 0; i < PRECISION; i++)
printf("%.14f\n",prev = prev / sqrt(1 + pow(2, -2.0 * i)));
}
int
main(void)
{
CALL(orig);
CALL(fix1);
return 0;
}
Here is the enhanced output:
orig
0.70710678118655
0.57735026918963
0.51639777949432
0.48686449556015
0.47232793895472
0.46511640189705
fix1
0.70710678118655
0.63245553203368
0.61357199107790
0.60883391251775
0.60764825625617
0.60735177014130