Search code examples
calgorithmmatlabtrigonometrycordic

How can I generate the sequence of Kvalues for CORDIC?


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?


Solution

  • 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