CORDIC

From Rosetta Code
CORDIC is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.
Introduction

CORDIC is the name of an algorithm for calculating trigonometric, logarithmic and hyperbolic functions, named after its first application on an airborne computer (COordinate Rotation DIgital Computer) in 1959. Unlike a Taylor expansion or polynomial approximation, it converges rapidly on machines with low computing and memory capacities: to calculate a tangent with 10 significant digits, it requires only 6 floating-point constants, and only additions, subtractions and digit shifts in its iterative part.

It is valid for angle values between 0 and π/2 only, but whatever the value of an angle, the calculation of its tangent can always be reduced to that of an angle between 0 and π/2, using trigonometric identities. Similarly, once you know the tangent, you can easily calculate the sine or cosine.

Pseudo code
constant θ[n] = arctan 10^(-n) // or simply 10^(-n) depending on floating point precision 
constant epsilon = 10^-12

function tan(alpha)            // 0 < alpha <= π/2 
  x = 1 ; y = 0 ; k = 0
  while epsilon < alpha
    while alpha < θ[k] 
       k++
    end loop
    alpha -= θ[k]
    x2 = x - 10^(-k)*y
    y2 = y + 10^(-k)*x
    x = x2 ; y = y2
  end loop
  return (y/x)
end function
Task
  • Implement the CORDIC algorithm, using only the 4 arithmetic operations and right shifts in the main loop if possible.
  • Use your implementation to calculate the cosine of the following angles, expressed in radians: -9, 0, 1.5 and 6


See also

CORDIC on Wikipedia


ALGOL 68

Based on the pseudo code, method to calculate cos (and sin) from the XPL0 sample.

BEGIN # implement sin, cos and tan using the CORDIC algorithm                #

    REAL pi by 2 = pi / 2;

    # pre-computed table of arctan(10^-n) values:                            #
    []REAL theta = ( 7.85398163397448e-01, 9.96686524911620e-02
                   , 9.99966668666524e-03, 9.99999666666867e-04
                   , 9.99999996666667e-05, 9.99999999966667e-06
                   , 9.99999999999667e-07, 9.99999999999997e-08
                   , 1.00000000000000e-08, 1.00000000000000e-09
                   , 1.00000000000000e-10, 1.00000000000000e-11
                   , 1.00000000000000e-12, 1.00000000000000e-13
                   , 1.00000000000000e-14, 1.00000000000000e-15
                   , 1.00000000000000e-16
                   );
    REAL epsilon = 1e-16;

    # mode to hold the values returned from the CORDIC procedure             #
    MODE CORDICV = STRUCT( REAL y, x );

    # CORDIC algorithm, finds "y" and "x" for alpha radians                  #
    # signs indicates the sign of the results:                               #
    #     signs[ 1 ] = sign for -π : -π/2, signs[ 1 ] = sign for -π/2 : 0    #
    #     signs[ 3 ] = sign for  0 :  π/2, signs[ 4 ] = sign for  π/2 : π    #
    # sign both = TRUE => sign applied to both y and x, FALSE => sign y only #
    PROC cordic = ( REAL alpha in, []INT signs, BOOL sign both )CORDICV:
         BEGIN
            REAL alpha     := alpha in;            # ensure -π <= alpha <= π #
            BOOL flip sign := FALSE;
            WHILE alpha < - pi DO alpha +:= pi; flip sign := NOT flip sign OD;
            WHILE alpha >   pi DO alpha -:= pi; flip sign := NOT flip sign OD;
            INT    sign;
            IF     alpha < - pi by 2 THEN
                alpha +:= pi;
                sign := signs[ 1 ]
            ELIF   alpha < 0         THEN
                alpha := - alpha;
                sign := signs[ 2 ]
            ELIF   alpha < pi by 2   THEN
                sign := signs[ 3 ]
            ELSE # alpha < pi #
                alpha := pi - alpha;
                sign := signs[ 4 ]
            FI;
            IF flip sign AND sign both THEN sign := -sign FI;
            REAL x := 1, y := 0;
            INT  k := 1;
            REAL ten to minus k := 1;     # NB: ten to minus k = 10.0^-(k-1) #
            WHILE epsilon < alpha DO
                WHILE alpha < theta[ k ] DO
                    k              +:=  1;
                    ten to minus k /:= 10
                OD;
                alpha -:= theta[ k ];
                REAL x2 = x - ten to minus k * y;
                REAL y2 = y + ten to minus k * x;
                x      := x2;
                y      := y2
            OD;
            CORDICV( sign * y, IF sign both THEN sign * x ELSE x FI )
         END # cordic # ;

    # find sin(alpha) using the CORDIC algorithm. alpha in radians           #
    PROC c cos = ( REAL alpha )REAL:
         BEGIN
            CORDICV c = cordic( alpha, ( -1, 1, 1, -1 ), TRUE );
            x OF c / sqrt( ( x OF c * x OF c ) + ( y OF c * y OF c ) )
         END # c cos # ;

    # find sin(alpha) using the CORDIC algorithm. alpha in radians           #
    PROC c sin = ( REAL alpha )REAL:
         BEGIN
            CORDICV c = cordic( alpha, ( -1,-1, 1, 1 ), TRUE );
            y OF c / sqrt( ( x OF c * x OF c ) + ( y OF c * y OF c ) )
         END # c cos # ;

    # find tan(alpha) using the CORDIC algorithm. alpha in radians           #
    PROC c tan = ( REAL alpha )REAL:
         BEGIN
             CORDICV c = cordic( alpha, (  1, -1, 1,-1 ), FALSE );
             IF x OF c = 0 THEN max real ELSE y OF c / x OF c FI
         END # c tan # ;

    PROC show cordic = ( REAL angle )VOID:
         BEGIN
            REAL cosine  = cos( angle ), cordic cosine = c cos( angle );
            REAL sine    = sin( angle ), cordic sine   = c sin( angle );
            REAL tangent = tan( angle ), cordic tan    = c tan( angle );
            REAL c diff  = ABS ( cordic cosine - cosine  );
            REAL s diff  = ABS ( cordic sine   - sine    );
            REAL t diff  = ABS ( cordic tan    - tangent );
            print( ( fixed(         angle,  -8, 4    ), ":  "
                   , fixed( cordic cosine,  -9, 6    ), " "
                   , fixed(        cosine,  -9, 6    ), " "
                   , float(        c diff, -14, 8, 2 ), " | "
                   , fixed(   cordic sine,  -9, 6    ), " "
                   , fixed(          sine,  -9, 6    ), " "
                   , float(        s diff, -14, 8, 2 ), " | "
                   , fixed(    cordic tan,  -9, 6    ), " "
                   , fixed(       tangent,  -9, 6    ), " "
                   , float(        t diff, -14, 8, 2 ), newline
                   )
                 )
         END # show cordic # ;

    []REAL tests = ( -9, 0, 1.5, 6 );
    print( ( "    angle cordic cos       cos     difference" ) );
    print( (         "  cordic sin       sin     difference" ) );
    print( (         "  cordic tan       tan     difference" ) );
    print( ( newline ) );
    FOR i FROM LWB tests TO UPB tests DO
        show cordic( tests[ i ] )
    OD;
    print( ( "    angle cordic cos       cos     difference" ) );
    print( (         "  cordic sin       sin     difference" ) );
    print( (         "  cordic tan       tan     difference" ) );
    print( ( newline ) );
    FOR i FROM 7810 BY 9 TO 7898 DO
        show cordic( i / 10 000 )
    OD

END
Output:
    angle cordic cos       cos     difference  cordic sin       sin     difference  cordic tan       tan     difference
 -9.0000:  -0.911130 -0.911130  1.1102230e-16 | -0.412118 -0.412118  0.00000000e+0 |  0.452316  0.452316  0.00000000e+0
  0.0000:   1.000000  1.000000  0.00000000e+0 |  0.000000  0.000000  0.00000000e+0 |  0.000000  0.000000  0.00000000e+0
  1.5000:   0.070737  0.070737  7.4940054e-16 |  0.997495  0.997495  0.00000000e+0 | 14.101420 14.101420  1.5099033e-13
  6.0000:   0.960170  0.960170  1.1102230e-16 | -0.279415 -0.279415  5.5511151e-16 | -0.291006 -0.291006  6.1062266e-16
    angle cordic cos       cos     difference  cordic sin       sin     difference  cordic tan       tan     difference
  0.7810:   0.710210  0.710210  3.3306691e-16 |  0.703990  0.703990  2.2204460e-16 |  0.991242  0.991242  6.6613381e-16
  0.7819:   0.709576  0.709576  2.2204460e-16 |  0.704629  0.704629  1.1102230e-16 |  0.993028  0.993028  4.4408921e-16
  0.7828:   0.708942  0.708942  3.3306691e-16 |  0.705267  0.705267  4.4408921e-16 |  0.994817  0.994817  9.9920072e-16
  0.7837:   0.708307  0.708307  6.6613381e-16 |  0.705905  0.705905  5.5511151e-16 |  0.996609  0.996609  1.6653345e-15
  0.7846:   0.707671  0.707671  5.5511151e-16 |  0.706542  0.706542  3.3306691e-16 |  0.998405  0.998405  1.3322676e-15
  0.7855:   0.707035  0.707035  1.1102230e-16 |  0.707179  0.707179  1.1102230e-16 |  1.000204  1.000204  2.2204460e-16
  0.7864:   0.706398  0.706398  1.1102230e-16 |  0.707815  0.707815  2.2204460e-16 |  1.002006  1.002006  4.4408921e-16
  0.7873:   0.705761  0.705761  1.1102230e-16 |  0.708450  0.708450  1.1102230e-16 |  1.003811  1.003811  2.2204460e-16
  0.7882:   0.705123  0.705123  3.3306691e-16 |  0.709085  0.709085  5.5511151e-16 |  1.005619  1.005619  1.3322676e-15
  0.7891:   0.704484  0.704484  5.5511151e-16 |  0.709720  0.709720  4.4408921e-16 |  1.007431  1.007431  1.3322676e-15

C

Translation of: Wren

If the M_PI constant is not defined in your math.h, then you can use 4 * atan(1) instead.

#include <stdio.h>
#include <math.h>

/* The following are pre-computed to avoid using atan and sqrt functions. */
const double angles[] = {
    0.78539816339745, 0.46364760900081, 0.24497866312686, 0.12435499454676,
    0.06241880999596, 0.03123983343027, 0.01562372862048, 0.00781234106010,
    0.00390623013197, 0.00195312251648, 0.00097656218956, 0.00048828121119,
    0.00024414062015, 0.00012207031189, 0.00006103515617, 0.00003051757812,
    0.00001525878906, 0.00000762939453, 0.00000381469727, 0.00000190734863,
    0.00000095367432, 0.00000047683716, 0.00000023841858, 0.00000011920929,
    0.00000005960464, 0.00000002980232, 0.00000001490116, 0.00000000745058
};

const double 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
};

double radians(double degrees) { return degrees * M_PI / 180.0; }

void Cordic(double alpha, int n, double *c_cos, double *c_sin) {
    int i, ix, sigma;
    double kn, x, y, atn, t, theta = 0.0, pow2 = 1.0;
    int newsgn = (int)floor(alpha / (2.0 * M_PI)) % 2 == 1 ? 1 : -1;
    if (alpha < -M_PI/2.0 || alpha > M_PI/2.0) {
        if (alpha < 0) {
            Cordic(alpha + M_PI, n, &x, &y);
        } else {
            Cordic(alpha - M_PI, n, &x, &y);
        }
        *c_cos = x * newsgn;
        *c_sin = y * newsgn;
        return;
    }
    ix = n - 1;
    if (ix > 23) ix = 23;
    kn = kvalues[ix];
    x = 1;
    y = 0;
    for (i = 0; i < n; ++i) {
        atn = angles[i];
        sigma = (theta < alpha) ? 1 : -1;
        theta += sigma * atn;
        t = x;
        x -= sigma * y * pow2;
        y += sigma * t * pow2;
        pow2 /= 2.0;
    }
    *c_cos = x * kn;
    *c_sin = y * kn;
}

int main() {
    int i, th;
    double thr, c_cos, c_sin;
    double angles[] = {-9.0, 0.0, 1.5, 6.0 };
    char *f;
    printf("  x       sin(x)     diff. sine     cos(x)    diff. cosine\n");
    f =  "%+03d.0°  %+.8f (%+.8f) %+.8f (%+.8f)\n";
    for (th = -90; th <= +90; th += 15) {
        thr = radians(th);
        Cordic(thr, 24, &c_cos, &c_sin);
        printf(f, th, c_sin, c_sin - sin(thr), c_cos, c_cos - cos(thr));
    }
    printf("\nx(rads)   sin(x)     diff. sine     cos(x)    diff. cosine\n");
    f = "%+4.1f    %+.8f (%+.8f) %+.8f (%+.8f)\n";
    for (i = 0; i < 4; ++i) {
        thr = angles[i];
        Cordic(thr, 24, &c_cos, &c_sin);
        printf(f, thr, c_sin, c_sin - sin(thr), c_cos, c_cos - cos(thr));
    }
    return 0;
}
Output:
  x       sin(x)     diff. sine     cos(x)    diff. cosine
-90.0°  -1.00000000 (+0.00000000) -0.00000007 (-0.00000007)
-75.0°  -0.96592585 (-0.00000003) +0.25881895 (-0.00000009)
-60.0°  -0.86602545 (-0.00000005) +0.49999992 (-0.00000008)
-45.0°  -0.70710684 (-0.00000006) +0.70710672 (-0.00000006)
-30.0°  -0.49999992 (+0.00000008) +0.86602545 (+0.00000005)
-15.0°  -0.25881895 (+0.00000009) +0.96592585 (+0.00000003)
+00.0°  +0.00000007 (+0.00000007) +1.00000000 (-0.00000000)
+15.0°  +0.25881895 (-0.00000009) +0.96592585 (+0.00000003)
+30.0°  +0.49999992 (-0.00000008) +0.86602545 (+0.00000005)
+45.0°  +0.70710684 (+0.00000006) +0.70710672 (-0.00000006)
+60.0°  +0.86602545 (+0.00000005) +0.49999992 (-0.00000008)
+75.0°  +0.96592585 (+0.00000003) +0.25881895 (-0.00000009)
+90.0°  +1.00000000 (-0.00000000) -0.00000007 (-0.00000007)

x(rads)   sin(x)     diff. sine     cos(x)    diff. cosine
-9.0    -0.41211842 (+0.00000006) -0.91113029 (-0.00000003)
+0.0    +0.00000007 (+0.00000007) +1.00000000 (-0.00000000)
+1.5    +0.99749499 (+0.00000000) +0.07073719 (-0.00000002)
+6.0    -0.27941552 (-0.00000002) +0.96017028 (-0.00000001)

FreeBASIC

This example is incorrect. Please fix the code and remove this message.

Details:

The provided function is not used. The answers provided are rather via call to a FreeBASIC library function.

Translation of: Julia
#define min(a, b)  iif((a) < (b), (a), (b))
#define floor(x)  ((x*2.0-0.5) Shr 1)
#define pi  4 * Atn(1)
#define radians(x) ((x) * pi / 180)

Function CORDIC(alfa As Integer, iteracion As Integer = 24) As Double
    Dim As Double v
    ' This function computes v = [cos(alpha), sin(alpha)] (alpha in radians)
    ' using iteration increasing iteration value will increase the precision.
    
    If alfa < -pi/2 Or alfa > pi/2 Then
        v = Iif(alfa < 0, CORDIC(alfa + pi, iteracion), CORDIC(alfa - pi, iteracion))
    End If
    
    ' Initialization of tables of constants used by CORDIC
    ' need a table of arctangents of negative powers of two, in radians:
    ' angles = atan(2.^-(0:27));
    Dim As Double angulos(1 To 28) =  {_
    0.78539816339745, 0.46364760900081, 0.24497866312686, 0.12435499454676, _
    0.06241880999596, 0.03123983343027, 0.01562372862048, 0.00781234106010, _
    0.00390623013197, 0.00195312251648, 0.00097656218956, 0.00048828121119, _
    0.00024414062015, 0.00012207031189, 0.00006103515617, 0.00003051757812, _
    0.00001525878906, 0.00000762939453, 0.00000381469727, 0.00000190734863, _
    0.00000095367432, 0.00000047683716, 0.00000023841858, 0.00000011920929, _
    0.00000005960464, 0.00000002980232, 0.00000001490116, 0.00000000745058}
    
    ' and a table of products of reciprocal lengths of vectors (1, 2^-2j):
    ' Kvalores = cumprod(1./sqrt(1 + 1j*2.^(-(0:23))))
    Dim As Double Kvalores(1 To 28) = { _
    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}
    
    Dim As Double Kn = Kvalores(min(iteracion, Len(Kvalores)))
    ' Initialize loop variables:
    Dim As Integer poderde2 = 1, sigma, factor, R
    Dim As Double angulo = angulos(1)
    
    ' iteracions
    For j As Integer = 0 To iteracion-1
        sigma = Iif(alfa < 0, -1, 1)
        factor = sigma * poderde2
        ' Note the matrix multiplication can be done using scaling by powers of two and addition subtraction
        R = factor
        v *= R                   ' 2-by-2 matrix multiply
        alfa -= sigma * angulo   ' update the remaining angulo
        poderde2 /= 2
        ' update the angulo from table, or eventually by just dividing by two
        If j + 2 > Len(angulos) Then
            angulo /= 2
        Else
            angulo = angulos(j + 2)
        End If
    Next
    
    ' Adjust length of output vector to be (cos(alfa), sin(alfa)):
    v *= Kn
    Return v
End Function

Dim As Double test(1 To 4) = {-9, 0, 1.5, 6}
Print !"\nx(radians)     cos(x)"
For r As Integer = 1 To 4
    Print Using "   +#.#     +#.########"; test(r); Cos(test(r))
Next

Sleep
Output:
x(radians)     cos(x)
   -9.0     -0.91113026
   +0.0     +1.00000000
   +1.5     +0.07073720
   +6.0     +0.96017029

J

Model implementation:

epsilon=: 10^-12
phin=: (#~ epsilon <: ])~.@(, _3 o. 10^-@#)^:_ ''
tent=: 10^-i.#phin

cordic=: {{alpha=. y
  XY=. 1 0 assert. 0 <: alpha assert. 0.25p1 >: alpha
  while. epsilon < alpha do.
    k=. phin I. alpha
    alpha=. alpha - k{phin
    XY =. XY + (k{tent) * XY +/ .* ((+.0j1 _1))
  end.
  XY
}}

CORDIC=: {{
  'octant angle'=. 8 0.25p1#:y
  select. octant
    case. 0 do.         cordic        angle
    case. 1 do.       |.cordic 0.25p1-angle
    case. 2 do. _1  1*|.cordic        angle
    case. 3 do. _1  1*  cordic 0.25p1-angle
    case. 4 do. _1 _1*  cordic        angle
    case. 5 do. _1 _1*|.cordic 0.25p1-angle
    case. 6 do.  1 _1*|.cordic        angle
    case. 7 do.  1 _1*  cordic 0.25p1-angle
  end.
}}

Task examples (cos is the left value in the result, argument is in radians):

   CORDIC -9
_0.92954 _0.420445
   CORDIC 0
1 0
   CORDIC 1.5
0.070762 0.997844
   CORDIC 6
0.970161 _0.282323

Notes

CAUTION: At the time of this writing, the task description declares that the cordic algorithm is valid in the range 0 .. π/2. But it appears that the algorithm can only be valid in the range 0..π/4.

In this J implementation, we use three constants, two of which are lookup tables (tent gives us negative powers of ten as a lookup table):

   epsilon
1e_12
   phin
0.785398 0.0996687 0.00999967 0.001 0.0001 1e_5 1e_6 1e_7 1e_8 1e_9 1e_10 1e_11 1e_12
   tent
1 0.1 0.01 0.001 0.0001 1e_5 1e_6 1e_7 1e_8 1e_9 1e_10 1e_11 1e_12

By default, J displays the first six digits of floating point numbers (floating point numbers are more precise, but in most circumstances the values being operated on are not more accurate than six digits). But of course, J retains the values at higher precision. For example:

   {&phin
{ &0.785398163397448279 0.0996686524911620381 0.00999966668666523936 0.000999999666666867007 9.99999996666667089e_5 9.99999999966667302e_6 9.99999999999667283e_7 9.9999999999999744e_8 1.00000000000000085e_8 1.00000000000000089e_9 1.00000000000000107e_10 1....

That said, it's not clear that this algorithm can be more accurate than something near 3.5% for the general case.

Also: double parenthesis around a noun phrase tells the interpreter that that expression is a constant which should be evaluated once, ahead of time.

Java

Translation of: C
public class CordicCalculator {

    // Constants
    private static final double[] angles = {
        0.78539816339745, 0.46364760900081, 0.24497866312686, 0.12435499454676,
        0.06241880999596, 0.03123983343027, 0.01562372862048, 0.00781234106010,
        0.00390623013197, 0.00195312251648, 0.00097656218956, 0.00048828121119,
        0.00024414062015, 0.00012207031189, 0.00006103515617, 0.00003051757812,
        0.00001525878906, 0.00000762939453, 0.00000381469727, 0.00000190734863,
        0.00000095367432, 0.00000047683716, 0.00000023841858, 0.00000011920929,
        0.00000005960464, 0.00000002980232, 0.00000001490116, 0.00000000745058
    };

    private static final double[] 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
    };

    // Convert degrees to radians
    private static double radians(double degrees) {
        return degrees * Math.PI / 180.0;
    }

    // Cordic algorithm implementation
    private static void cordic(double alpha, int n, double[] result) {
        int i, ix, sigma;
        double kn, x, y, atn, t, theta = 0.0, pow2 = 1.0;
        int newsgn = (int)Math.floor(alpha / (2.0 * Math.PI)) % 2 == 1 ? 1 : -1;
        if (alpha < -Math.PI/2.0 || alpha > Math.PI/2.0) {
            if (alpha < 0) {
                cordic(alpha + Math.PI, n, result);
            } else {
                cordic(alpha - Math.PI, n, result);
            }
            result[0] = result[0] * newsgn;
            result[1] = result[1] * newsgn;
            return;
        }
        ix = n - 1;
        if (ix > 23) ix = 23;
        kn = kvalues[ix];
        x = 1;
        y = 0;
        for (i = 0; i < n; ++i) {
            atn = angles[i];
            sigma = (theta < alpha) ? 1 : -1;
            theta += sigma * atn;
            t = x;
            x -= sigma * y * pow2;
            y += sigma * t * pow2;
            pow2 /= 2.0;
        }
        result[0] = x * kn;
        result[1] = y * kn;
    }

    // Main method
    public static void main(String[] args) {
        double c_cos, c_sin;
        double[] result = new double[2];
        double[] angles = {-9.0, 0.0, 1.5, 6.0};
        String format;
        
        System.out.println("  x       sin(x)     diff. sine     cos(x)    diff. cosine");
        format = "%+03d.0°  %+.8f (%+.8f) %+.8f (%+.8f)\n";
        for (int th = -90; th <= +90; th += 15) {
            double thr = radians(th);
            cordic(thr, 24, result);
            c_cos = result[0];
            c_sin = result[1];
            System.out.printf(format, th, c_sin, c_sin - Math.sin(thr), c_cos, c_cos - Math.cos(thr));
        }

        System.out.println("\nx(rads)   sin(x)     diff. sine     cos(x)    diff. cosine");
        format = "%+4.1f    %+.8f (%+.8f) %+.8f (%+.8f)\n";
        for (int i = 0; i < angles.length; ++i) {
            double thr = angles[i];
            cordic(thr, 24, result);
            c_cos = result[0];
            c_sin = result[1];
            System.out.printf(format, thr, c_sin, c_sin - Math.sin(thr), c_cos, c_cos - Math.cos(thr));
        }
    }
}
Output:
  x       sin(x)     diff. sine     cos(x)    diff. cosine
-90.0°  -1.00000000 (+0.00000000) -0.00000007 (-0.00000007)
-75.0°  -0.96592585 (-0.00000003) +0.25881895 (-0.00000009)
-60.0°  -0.86602545 (-0.00000005) +0.49999992 (-0.00000008)
-45.0°  -0.70710684 (-0.00000006) +0.70710672 (-0.00000006)
-30.0°  -0.49999992 (+0.00000008) +0.86602545 (+0.00000005)
-15.0°  -0.25881895 (+0.00000009) +0.96592585 (+0.00000003)
+00.0°  +0.00000007 (+0.00000007) +1.00000000 (-0.00000000)
+15.0°  +0.25881895 (-0.00000009) +0.96592585 (+0.00000003)
+30.0°  +0.49999992 (-0.00000008) +0.86602545 (+0.00000005)
+45.0°  +0.70710684 (+0.00000006) +0.70710672 (-0.00000006)
+60.0°  +0.86602545 (+0.00000005) +0.49999992 (-0.00000008)
+75.0°  +0.96592585 (+0.00000003) +0.25881895 (-0.00000009)
+90.0°  +1.00000000 (-0.00000000) -0.00000007 (-0.00000007)

x(rads)   sin(x)     diff. sine     cos(x)    diff. cosine
-9.0    -0.41211842 (+0.00000006) -0.91113029 (-0.00000003)
+0.0    +0.00000007 (+0.00000007) +1.00000000 (-0.00000000)
+1.5    +0.99749499 (+0.00000000) +0.07073719 (-0.00000002)
+6.0    -0.27941552 (-0.00000002) +0.96017028 (-0.00000001)


jq

Adapted from Wren

Works with: jq

Works with gojq, the Go implementation of jq

Preliminaries

# like while/2 but emit the final term rather than the first one
def whilst(cond; update):
  def _whilst:
    if cond then update | (., _whilst) else empty end;
  _whilst;

# Simplistic approach to rounding:
def round($ndec): pow(10;$ndec) as $p | . * $p | round / $p;

def lpad($len): tostring | ($len - length) as $l | (" " * $l) + .;

The task

# The following are pre-computed to avoid using atan and sqrt functions.
def angles: [
    0.78539816339745, 0.46364760900081, 0.24497866312686, 0.12435499454676,
    0.06241880999596, 0.03123983343027, 0.01562372862048, 0.00781234106010,
    0.00390623013197, 0.00195312251648, 0.00097656218956, 0.00048828121119,
    0.00024414062015, 0.00012207031189, 0.00006103515617, 0.00003051757812,
    0.00001525878906, 0.00000762939453, 0.00000381469727, 0.00000190734863,
    0.00000095367432, 0.00000047683716, 0.00000023841858, 0.00000011920929,
    0.00000005960464, 0.00000002980232, 0.00000001490116, 0.00000000745058
];

def 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
];

def PI: (1 | atan * 4);

def radians: . * PI / 180;

def Cordic($alpha; $n):
  PI as $PI
  | (if (($alpha / (2 * $PI))|floor % 2 == 1) then 1 else -1 end) as $newsgn
  | if ($alpha < -$PI/2) 
    then Cordic($alpha + $PI; $n) | map(. * $newsgn)
    elif ($alpha >  $PI/2)
    then Cordic($alpha - $PI; $n) | map(. * $newsgn)
    else kvalues[ [$n-1, (kvalues|length-1)] | min] as $kn
    | reduce angles[0:$n][] as $atan ({ theta: 0, x: 1, y: 0, pow2: 1};
        (if .theta < $alpha then 1 else -1 end) as $sigma
        | .theta += $sigma * $atan
        | .x as $t
        | .x = (.x - $sigma * .y * .pow2)
        | .y = (.y + $sigma * $t * .pow2)
        | .pow2 /= 2 )
    | [.x * $kn, .y * $kn]
    end;

def example:
  def format: map(round(8) | lpad(11)) | join(" ");
  "    x         sin(x)     diff. sine   cos(x)   diff. cosine",
  ({ th: -90 }
   | whilst (.th <= 90;
       (.th | radians) as $thr
       | Cordic($thr; 24) as [ $cos, $sin ]
       | .out = [.th, $sin, $sin - ($thr|sin), $cos, $cos - ($thr|cos) ]
       | .th += 15 )
   | .out
   | format),

  "\n    x(rads)   sin(x)     diff. sine   cos(x)   diff. cosine",
  ((-9, 0, 1.5, 6) as $thr
   | Cordic($thr; 24) as [$cos, $sin]
   | [$thr, $sin, $sin - ($thr|sin), $cos, $cos - ($thr|cos)]
   | format) ;

example

Invocation: jq -ncr -f cordic.jq

Output:
    x         sin(x)     diff. sine   cos(x)   diff. cosine
        -90          -1           0      -7e-08      -7e-08
        -75 -0.96592585      -3e-08  0.25881895      -9e-08
        -60 -0.86602545      -5e-08  0.49999992      -8e-08
        -45 -0.70710684      -6e-08  0.70710672      -6e-08
        -30 -0.49999992       8e-08  0.86602545       5e-08
        -15 -0.25881895       9e-08  0.96592585       3e-08
          0       7e-08       7e-08           1          -0
         15  0.25881895      -9e-08  0.96592585       3e-08
         30  0.49999992      -8e-08  0.86602545       5e-08
         45  0.70710684       6e-08  0.70710672      -6e-08
         60  0.86602545       5e-08  0.49999992      -8e-08
         75  0.96592585       3e-08  0.25881895      -9e-08
         90           1          -0      -7e-08      -7e-08

    x(rads)   sin(x)     diff. sine   cos(x)   diff. cosine
         -9 -0.41211842       6e-08 -0.91113029      -3e-08
          0       7e-08       7e-08           1          -0
        1.5  0.99749499           0  0.07073719      -2e-08
          6 -0.27941552      -2e-08  0.96017028      -1e-08

Julia

""" Modified from MATLAB example code at en.wikipedia.org/wiki/CORDIC """

using Printf

"""
    Compute v = [cos(alpha), sin(alpha)] (alpha in radians).
    Increasing the iteration value will increase the precision.
"""
function cordic(alpha, iteration = 24)
    # Fix for the Wikipedia's MATLAB code bug in sin (sometimes flips sign) when |θ| > 2π
    newsgn = isodd(Int(floor(alpha / 2π))) ? 1 : -1
    alpha < -π/2 && return newsgn * cordic(alpha + π, iteration)
    alpha > π/2 && return newsgn * cordic(alpha - π, iteration)

    # Initialization of tables of constants used by CORDIC
    # need a table of arctangents of negative powers of two, in radians:
    # angles = atan(2.^-(0:27));
    angles =  [
        0.78539816339745,   0.46364760900081,   0.24497866312686,   0.12435499454676,
        0.06241880999596,   0.03123983343027,   0.01562372862048,   0.00781234106010,
        0.00390623013197,   0.00195312251648,   0.00097656218956,   0.00048828121119,
        0.00024414062015,   0.00012207031189,   0.00006103515617,   0.00003051757812,
        0.00001525878906,   0.00000762939453,   0.00000381469727,   0.00000190734863,
        0.00000095367432,   0.00000047683716,   0.00000023841858,   0.00000011920929,
        0.00000005960464,   0.00000002980232,   0.00000001490116,   0.00000000745058, ]
    # and a table of products of reciprocal lengths of vectors [1, 2^-2j]:
    # 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, ]

    Kn = Kvalues[min(iteration, length(Kvalues))]  
    # Initialize loop variables:
    v = [1, 0] # start with 2-vector cosine and sine of zero
    poweroftwo = 1
    angle = angles[1]
    
    # Iterations
    for j = 0:iteration-1
        if alpha < 0
            sigma = -1
        else
            sigma = 1
        end
        factor = sigma * poweroftwo
        # Note the matrix multiplication can be done using scaling by powers of two and addition subtraction
        R = [1 -factor
             factor  1]
        v = R * v # 2-by-2 matrix multiply
        alpha -= sigma * angle # update the remaining angle
        poweroftwo /= 2
        # update the angle from table, or eventually by just dividing by two
        if j + 2 > length(angles)
            angle /= 2
        else
            angle = angles[j + 2]
        end
    end
    
    # Adjust length of output vector to be [cos(alpha), sin(alpha)]:
    v .*= Kn
    return v
end

function test_cordic()
    println("  x       sin(x)     diff. sine     cos(x)    diff. cosine ")
    for θ in -90:15:90 
        cosθ, sinθ = cordic(deg2rad(θ))
        @printf("%+05.1f°  %+.8f (%+.8f) %+.8f (%+.8f)\n",
           θ, sinθ, sinθ - sind(θ), cosθ, cosθ - cosd(θ))
    end
    println("\nx(radians)  sin(x)     diff. sine     cos(x)    diff. cosine ")
    for θr in [-9, 0, 1.5, 6]
        cosθ, sinθ = cordic(θr)
        @printf("%+3.1f      %+.8f (%+.8f) %+.8f (%+.8f)\n",
           θr, sinθ, sinθ - sin(θr), cosθ, cosθ - cos(θr))
    end

end

test_cordic()
Output:
  x       sin(x)     diff. sine     cos(x)    diff. cosine 
-90.0°  -1.00000000 (+0.00000000) -0.00000007 (-0.00000007)
-75.0°  -0.96592585 (-0.00000003) +0.25881895 (-0.00000009)
-60.0°  -0.86602545 (-0.00000005) +0.49999992 (-0.00000008)
-45.0°  -0.70710684 (-0.00000006) +0.70710672 (-0.00000006)
-30.0°  -0.49999992 (+0.00000008) +0.86602545 (+0.00000005)
-15.0°  -0.25881895 (+0.00000009) +0.96592585 (+0.00000003)
+00.0°  -0.00000007 (-0.00000007) +1.00000000 (-0.00000000)
+15.0°  +0.25881895 (-0.00000009) +0.96592585 (+0.00000003)
+30.0°  +0.49999992 (-0.00000008) +0.86602545 (+0.00000005)
+45.0°  +0.70710684 (+0.00000006) +0.70710672 (-0.00000006)
+60.0°  +0.86602545 (+0.00000005) +0.49999992 (-0.00000008)
+75.0°  +0.96592585 (+0.00000003) +0.25881895 (-0.00000009)
+90.0°  +1.00000000 (-0.00000000) -0.00000007 (-0.00000007)

x(radians)  sin(x)     diff. sine     cos(x)    diff. cosine
-9.0      -0.41211842 (+0.00000006) -0.91113029 (-0.00000003)
+0.0      -0.00000007 (-0.00000007) +1.00000000 (-0.00000000)
+1.5      +0.99749499 (+0.00000000) +0.07073719 (-0.00000002)
+6.0      -0.27941552 (-0.00000002) +0.96017028 (-0.00000001)

Lua

Translation of: ALGOL 68
do -- implement sin, cos and tan using the CORDIC algorithm

    local piBy2 = math.pi / 2

    -- pre-computed table of arctan(10^-n) values
    local theta = { 7.85398163397448e-01, 9.96686524911620e-02
                  , 9.99966668666524e-03, 9.99999666666867e-04
                  , 9.99999996666667e-05, 9.99999999966667e-06
                  , 9.99999999999667e-07, 9.99999999999997e-08
                  , 1.00000000000000e-08, 1.00000000000000e-09
                  , 1.00000000000000e-10, 1.00000000000000e-11
                  , 1.00000000000000e-12, 1.00000000000000e-13
                  , 1.00000000000000e-14, 1.00000000000000e-15
                  , 1.00000000000000e-16
                  }
    local epsilon = 1e-16

    --[[ CORDIC algorithm, finds "y" and "x" for alpha radians
         signs indicates the sign of the results:
               signs[ 1 ] = sign for -π : -π/2, signs[ 1 ] = sign for -π/2 : 0
               signs[ 3 ] = sign for  0 :  π/2, signs[ 4 ] = sign for  π/2 : π
         signBoth = TRUE => sign applied to both y and x, FALSE => sign y only
    --]]
    function cordic( alphaIn, signs, signBoth )
        local alpha     = alphaIn
        -- ensure -π <= alpha <= π
        local flipSign = false
        while alpha < - math.pi do alpha = alpha + math.pi flipSign = not flipSign end
        while alpha >   math.pi do alpha = alpha - math.pi flipSign = not flipSign end
        local sign
        if    alpha < - piBy2 then
            alpha = alpha + math.pi
            sign = signs[ 1 ]
        elseif  alpha < 0     then
            alpha = - alpha
            sign = signs[ 2 ]
        elseif  alpha < piBy2 then
            sign = signs[ 3 ]
        else -- alpha <= math.pi
            alpha = math.pi - alpha
            sign = signs[ 4 ]
        end
        if flipSign and signBoth then sign = -sign end
        local x, y, k, tenToMinusK = 1, 0, 1, 1 -- NB: tenToMinusK is 10^-(k-1)
        while epsilon < alpha do
            while alpha < theta[ k ] do
                k           = k +  1
                tenToMinusK = tenToMinusK / 10
            end
            alpha = alpha - theta[ k ]
            x, y = x - tenToMinusK * y, y + tenToMinusK * x
        end
        return sign * y, signBoth and sign * x or x
    end

    -- cos(alpha) using the CORDIC algorithm. alpha in radians
    function cCos( alpha )
        local y, x = cordic( alpha, { -1, 1, 1, -1 }, true )
        return x / math.sqrt( ( x * x ) + ( y * y ) )
    end

    -- sin(alpha) using the CORDIC algorithm. alpha in radians
    function cSin( alpha )
        local y, x = cordic( alpha, { -1,-1, 1, 1 }, true )
        return y / math.sqrt( ( x * x ) + ( y * y ) )
    end

    -- tan(alpha) using the CORDIC algorithm. alpha in radians
    function cTan( alpha )
        local y, x  = cordic( alpha, {  1, -1, 1,-1 }, false )
        return x == 0 and NaN or y / x
    end

    function f6( v ) return string.format( " %9.6f", v ) end
    function g(  v ) return string.format( " %12g",  v ) end

    function showCordic( angle )
        local cosine,  cordicCos = math.cos( angle ), cCos( angle )
        local sine,    cordicSin = math.sin( angle ), cSin( angle )
        local tangent, cordicTan = math.tan( angle ), cTan( angle )
        local cDiff  = cordicCos - cosine  if cDiff < 0 then cDiff = - cDiff end
        local sDiff  = cordicSin - sine    if sDiff < 0 then sDiff = - sDiff end
        local tDiff  = cordicTan - tangent if tDiff < 0 then tDiff = - tDiff end
        io.write( string.format( "%4.1f: ", angle )
                , f6( cordicCos ), f6( cosine  ), g( cDiff ), " |"
                , f6( cordicSin ), f6( sine    ), g( sDiff ), " |"
                , f6( cordicTan ), f6( tangent ), g( tDiff ), "\n"
                )
    end 

    local tests = { -9, 0, 1.5, 6 }
    io.write( "angle cordic cos       cos   difference" )
    io.write(     "  cordic sin       sin   difference" )
    io.write(     "  cordic tan       tan   difference" )
    io.write( "\n" )
    for i = 1, # tests do
        showCordic( tests[ i ] )
    end
    io.write( "angle cordic cos       cos   difference" )
    io.write(     "  cordic sin       sin   difference" )
    io.write(     "  cordic tan       tan   difference" )
    io.write( "\n" )
    for i = 7810, 7891, 9 do
        showCordic( i / 10000 )
    end

end
Output:
angle cordic cos       cos   difference  cordic sin       sin   difference  cordic tan       tan   difference
-9.0:  -0.911130 -0.911130  1.11022e-16 | -0.412118 -0.412118            0 |  0.452316  0.452316            0
 0.0:   1.000000  1.000000            0 |  0.000000  0.000000            0 |  0.000000  0.000000            0
 1.5:   0.070737  0.070737  7.49401e-16 |  0.997495  0.997495            0 | 14.101420 14.101420   1.5099e-13
 6.0:   0.960170  0.960170  1.11022e-16 | -0.279415 -0.279415  5.55112e-16 | -0.291006 -0.291006  6.10623e-16
angle cordic cos       cos   difference  cordic sin       sin   difference  cordic tan       tan   difference
 0.8:   0.710210  0.710210  3.33067e-16 |  0.703990  0.703990  2.22045e-16 |  0.991242  0.991242  6.66134e-16
 0.8:   0.709576  0.709576  2.22045e-16 |  0.704629  0.704629  1.11022e-16 |  0.993028  0.993028  4.44089e-16
 0.8:   0.708942  0.708942  3.33067e-16 |  0.705267  0.705267  4.44089e-16 |  0.994817  0.994817  9.99201e-16
 0.8:   0.708307  0.708307  6.66134e-16 |  0.705905  0.705905  5.55112e-16 |  0.996609  0.996609  1.66533e-15
 0.8:   0.707671  0.707671  5.55112e-16 |  0.706542  0.706542  3.33067e-16 |  0.998405  0.998405  1.33227e-15
 0.8:   0.707035  0.707035  1.11022e-16 |  0.707179  0.707179  1.11022e-16 |  1.000204  1.000204  2.22045e-16
 0.8:   0.706398  0.706398  1.11022e-16 |  0.707815  0.707815  2.22045e-16 |  1.002006  1.002006  4.44089e-16
 0.8:   0.705761  0.705761  1.11022e-16 |  0.708450  0.708450  1.11022e-16 |  1.003811  1.003811  2.22045e-16
 0.8:   0.705123  0.705123  3.33067e-16 |  0.709085  0.709085  5.55112e-16 |  1.005619  1.005619  1.33227e-15
 0.8:   0.704484  0.704484  5.55112e-16 |  0.709720  0.709720  4.44089e-16 |  1.007431  1.007431  1.33227e-15

Perl

Translation of: Raku
use strict;
use warnings;

sub CORDIC {
    my($a) = shift;
    my ($k, $x, $y) = (0, 1, 0);
    my @PoT = (1, 0.1, 0.01, 0.001, 0.0001, 0.00001);
    my @Tbl = <7.853981633e-1 9.966865249e-2 9.999666686e-3 9.999996666e-4 9.999999966e-5 9.999999999e-6 0>;

    while ($a > 1e-5) {
        $k++ while $a < $Tbl[$k];
        $a -= $Tbl[$k];
        ($x,$y) = ($x - $PoT[$k]*$y, $y + $PoT[$k]*$x);
    }
    $x / sqrt($x*$x + $y*$y)
}

print "Angle    CORDIC       Cosine       Error\n";
for my $angle (<-9 0 1.5 6>) {
    my $cordic = CORDIC abs $angle;
    printf "%4.1f %12.8f %12.8f %12.8f\n", $angle, $cordic, cos($angle), cos($angle) - $cordic
}
Output:
Angle    CORDIC       Cosine       Error
-9.0  -0.91112769  -0.91113026  -0.00000257
 0.0   1.00000000   1.00000000   0.00000000
 1.5   0.07073880   0.07073720  -0.00000160
 6.0   0.96016761   0.96017029   0.00000268

Phix

Translation of: Wren
with javascript_semantics
constant angles = {
    0.78539816339745, 0.46364760900081, 0.24497866312686, 0.12435499454676,
    0.06241880999596, 0.03123983343027, 0.01562372862048, 0.00781234106010,
    0.00390623013197, 0.00195312251648, 0.00097656218956, 0.00048828121119,
    0.00024414062015, 0.00012207031189, 0.00006103515617, 0.00003051757812,
    0.00001525878906, 0.00000762939453, 0.00000381469727, 0.00000190734863,
    0.00000095367432, 0.00000047683716, 0.00000023841858, 0.00000011920929,
    0.00000005960464, 0.00000002980232, 0.00000001490116, 0.00000000745058}
constant 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}

function cordic(atom alpha, integer n)
    bool sgn = +1
    while alpha < -PI/2 do alpha += PI sgn *= -1 end while
    while alpha >  PI/2 do alpha -= PI sgn *= -1 end while
    atom kn = sgn * kvalues[min(n,length(kvalues))],
         atan, theta = 0, x = 1, y = 0, pow2 = 1
    for i=1 to n do
        atan = iff(i<=length(angles)?angles[i]:atan/2)
        atom sigma = iff(theta < alpha ? 1 : -1), t = x
--      atom sigma = iff(theta <= alpha ? 1 : -1), t = x -- (matches Julia)
        theta += sigma * atan
        x -= sigma * y * pow2
        y += sigma * t * pow2
        pow2 /= 2
    end for
    return {x * kn, y * kn}
end function

constant fmh = "%n x(%s)  sin(x)       diff.sine    cos(x)      diff.cosine\n",
         fmt = "%+6.1f  %+.8f (%+.8f) %+.8f (%+.8f)\n"
printf(1,fmh,{false,"deg"})
for theta = -90 to 90 by 15 do
    atom r = theta*PI/180,
       {c,s} = cordic(r,24)
    printf(1,fmt,{theta,s,s-sin(r),c,c-cos(r)})
end for
printf(1,fmh,{true,"rad"})
for r in {-9, 0, 1.5, 6} do
    atom {c,s} = cordic(r, 24)
    printf(1,fmt,{r,s,s-sin(r),c,c-cos(r)})
end for
Output:

As noted above in the commented out line, and mentioned in the Wren entry, testing for <= flips the sign of sin(0).

 x(deg)  sin(x)       diff.sine    cos(x)      diff.cosine
 -90.0  -1.00000000 (+0.00000000) -0.00000007 (-0.00000007)
 -75.0  -0.96592585 (-0.00000003) +0.25881895 (-0.00000009)
 -60.0  -0.86602545 (-0.00000005) +0.49999992 (-0.00000008)
 -45.0  -0.70710684 (-0.00000006) +0.70710672 (-0.00000006)
 -30.0  -0.49999992 (+0.00000008) +0.86602545 (+0.00000005)
 -15.0  -0.25881895 (+0.00000009) +0.96592585 (+0.00000003)
  +0.0  +0.00000007 (+0.00000007) +1.00000000 (-0.00000000)
 +15.0  +0.25881895 (-0.00000009) +0.96592585 (+0.00000003)
 +30.0  +0.49999992 (-0.00000008) +0.86602545 (+0.00000005)
 +45.0  +0.70710684 (+0.00000006) +0.70710672 (-0.00000006)
 +60.0  +0.86602545 (+0.00000005) +0.49999992 (-0.00000008)
 +75.0  +0.96592585 (+0.00000003) +0.25881895 (-0.00000009)
 +90.0  +1.00000000 (-0.00000000) -0.00000007 (-0.00000007)

 x(rad)  sin(x)       diff.sine    cos(x)      diff.cosine
  -9.0  -0.41211842 (+0.00000006) -0.91113029 (-0.00000003)
  +0.0  +0.00000007 (+0.00000007) +1.00000000 (-0.00000000)
  +1.5  +0.99749499 (+0.00000000) +0.07073719 (-0.00000002)
  +6.0  -0.27941552 (-0.00000002) +0.96017028 (-0.00000001)

Python

Translation of: C
# CORDIC.py by Xing216
from math import pi, sin, cos, floor

angles = [
    0.78539816339745, 0.46364760900081, 0.24497866312686, 0.12435499454676,
    0.06241880999596, 0.03123983343027, 0.01562372862048, 0.00781234106010,
    0.00390623013197, 0.00195312251648, 0.00097656218956, 0.00048828121119,
    0.00024414062015, 0.00012207031189, 0.00006103515617, 0.00003051757812,
    0.00001525878906, 0.00000762939453, 0.00000381469727, 0.00000190734863,
    0.00000095367432, 0.00000047683716, 0.00000023841858, 0.00000011920929,
    0.00000005960464, 0.00000002980232, 0.00000001490116, 0.00000000745058
]
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
]
radians = lambda degrees: (degrees * pi) / 180

def Cordic(alpha, n, c_cos, c_sin):
    i, ix, sigma = 0, 0, 0
    kn, x, y, atn, t, theta = 0.0, 0.0, 0.0, 0.0, 0.0, 0.0
    pow2 = 1.0
    newsgn = 1 if floor(alpha / (2.0 * pi)) % 2 == 1 else -1
    if alpha < -pi/2.0 or alpha > pi/2.0:
        if alpha < 0:
            Cordic(alpha + pi, n, x, y)
        else:
            Cordic(alpha - pi, n, x, y)
        c_cos = x * newsgn
        c_sin = y * newsgn
        return c_cos, c_sin
    ix = n - 1
    if ix > 23: ix = 23
    kn = kvalues[ix]
    x = 1
    y = 0
    for i in range(n):
        atn = angles[i]
        sigma = 1 if theta < alpha else -1
        theta += sigma * atn
        t = x
        x -= sigma * y * pow2
        y += sigma * t * pow2
        pow2 /= 2.0
    c_cos = x * kn
    c_sin = y * kn
    return c_cos, c_sin

def main():
    i, th = 0, 0
    thr, c_cos, c_sin = 0.0, 0.0, 0.0
    angles = [-9.0, 0.0, 1.5, 6.0]
    print("  x       sin(x)     diff. sine     cos(x)    diff. cosine")
    for th in range(-90,91,15):
        thr = radians(th)
        c_cos, c_sin = Cordic(thr, 24, c_cos, c_sin)
        sin_diff = c_sin - sin(thr)
        cos_diff = c_cos - cos(thr)
        print(f"{th:+03}.0°  {c_sin:+.8f} ({sin_diff:+.8f}) {c_cos:+.8f} ({cos_diff:+.8f})")
    print("\nx(rads)   sin(x)     diff. sine     cos(x)    diff. cosine")
    for i in range(4):
        thr = angles[i]
        c_cos, c_sin = Cordic(thr, 24, c_cos, c_sin)
        sin_diff = c_sin - sin(thr)
        cos_diff = c_cos - cos(thr)
        print(f"{thr:+4.1f}    {c_sin:+.8f} ({c_sin - sin(thr):+.8f}) {c_cos:+.8f} ({c_cos - cos(thr):+.8f})")

if __name__ in "__main__":
    main()
Output:
  x       sin(x)     diff. sine     cos(x)    diff. cosine
-90.0°  -1.00000000 (+0.00000000) -0.00000007 (-0.00000007)
-75.0°  -0.96592585 (-0.00000003) +0.25881895 (-0.00000009)
-60.0°  -0.86602545 (-0.00000005) +0.49999992 (-0.00000008)
-45.0°  -0.70710684 (-0.00000006) +0.70710672 (-0.00000006)
-30.0°  -0.49999992 (+0.00000008) +0.86602545 (+0.00000005)
-15.0°  -0.25881895 (+0.00000009) +0.96592585 (+0.00000003)
+00.0°  +0.00000007 (+0.00000007) +1.00000000 (-0.00000000)
+15.0°  +0.25881895 (-0.00000009) +0.96592585 (+0.00000003)
+30.0°  +0.49999992 (-0.00000008) +0.86602545 (+0.00000005)
+45.0°  +0.70710684 (+0.00000006) +0.70710672 (-0.00000006)
+60.0°  +0.86602545 (+0.00000005) +0.49999992 (-0.00000008)
+75.0°  +0.96592585 (+0.00000003) +0.25881895 (-0.00000009)
+90.0°  +1.00000000 (-0.00000000) -0.00000007 (-0.00000007)

x(rads)   sin(x)     diff. sine     cos(x)    diff. cosine
-9.0    -0.00000000 (+0.41211849) -0.00000000 (+0.91113026)
+0.0    +0.00000007 (+0.00000007) +1.00000000 (-0.00000000)
+1.5    +0.99749499 (+0.00000000) +0.07073719 (-0.00000002)
+6.0    -0.00000000 (+0.27941550) -0.00000000 (-0.96017029)

Raku

Translation of: XPL0
# 2023082 Raku programming solution

sub CORDIC ($A is copy) {

   my (\Ten, $K, $X, $Y) = ( 1, * * 1/10 ... * )[^6], 0, 1, 0;

   my \Tbl = < 7.853981633974480e-1 9.966865249116200e-2 9.999666686665240e-3 
               9.999996666668670e-4 9.999999966666670e-5 9.999999999666670e-6 0.0>;

   while $A > 1e-5 { 
      $K++ while $A < Tbl[$K];
      $A -= Tbl[$K];
      ($X,$Y) = $X - Ten[$K]*$Y, $Y + Ten[$K]*$X;
   }
   return $X, sqrt($X*$X + $Y*$Y)
}

say "Angle    CORDIC       Cosine       Error";
for <-9 0 1.5 6> { 
   my \result = [/] CORDIC .abs;
   printf "% 2.1f  "~"% 2.8f  " x 3~"\n", $_, result, .cos, .cos - result
}
Output:

Same as XPL0 or you may Attempt This Online!

RPL

Works with: HP version 28
≪ RAD { } 1
   DO
      SWAP OVER ATAN + SWAP 10 /
   UNTIL DUP DUP TAN == END        @ memorize constants until precision limit is reached 
   DROP 'THN' STO 
   THN SIZE →STR " constants in memory." *
   1E-12 'EPSILON' STO  
≫ ≫ 'INIT' STO       

≪ IF DUP THEN 
      1 SWAP START 10 / NEXT       @ shift one digit right 
   ELSE DROP END
≫ 'SR10' STO 

≪ IF THN SIZE OVER 1 + <    
   THEN 1 SWAP SR10                @ get arctan(θ[k]) from memory 
   ELSE THN SWAP 1 + GET END       @ arctan(θ[k]) ≈ θ[k]
≫ '→THK' STO 

≪ → alpha
  ≪ 0 1 0                         @ initialize y, x and k
     WHILE alpha EPSILON > REPEAT
        WHILE DUP →THK alpha > REPEAT 
           1 + END
        'alpha' OVER →THK STO-
        DUP2 SR10 4 PICK + 4 ROLLD
        ROT OVER SR10 ROT SWAP -
        SWAP
     END 
     DROP /
≫ ≫ '→TAN' STO    

≪ 1 CF 
   '2*π' →NUM MOD
   IF DUP π / 2 * →NUM IP THEN
      { ≪ π SWAP 1 SF ≫ ≪ π 1 SF ≫ ≪ '2*π' SWAP ≫ }    @ corrections for angles > π/2
      LASTARG GET EVAL →NUM -                              @ apply correction according to quadrant
      END
   →TAN SQ 1 + √ INV
   IF 1 FS? THEN NEG END
≫ '→COS' STO  
     
≪ INIT { -9 0 1.5 6 } { }
   1 3 PICK SIZE FOR j 
      OVER j GET →COS + 
   NEXT SWAP DROP
≫ 'TASK' STO
Output:
2: "6 constants in memory."
1: { -.91113026188 1 7.07372016661E-2 .960170286655 }

Rust

Translation of: C
use std::f64::consts::PI;

// Constants for angles and kvalues
const ANGLES: [f64; 28] = [
    0.78539816339745, 0.46364760900081, 0.24497866312686, 0.12435499454676,
    0.06241880999596, 0.03123983343027, 0.01562372862048, 0.00781234106010,
    0.00390623013197, 0.00195312251648, 0.00097656218956, 0.00048828121119,
    0.00024414062015, 0.00012207031189, 0.00006103515617, 0.00003051757812,
    0.00001525878906, 0.00000762939453, 0.00000381469727, 0.00000190734863,
    0.00000095367432, 0.00000047683716, 0.00000023841858, 0.00000011920929,
    0.00000005960464, 0.00000002980232, 0.00000001490116, 0.00000000745058,
];

const KVALUES: [f64; 24] = [
    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,
];

// Function to convert degrees to radians
fn radians(degrees: f64) -> f64 {
    degrees * PI / 180.0
}

// Cordic algorithm implementation
fn cordic(alpha: f64, n: usize, c_cos: &mut f64, c_sin: &mut f64) {
    let mut theta = 0.0;
    let mut pow2 = 1.0;
    let mut x = 1.0;
    let mut y = 0.0;
    let newsgn = if (alpha / (2.0 * PI)).floor() as i32 % 2 == 1 { 1.0 } else { -1.0 };

    if alpha < -PI / 2.0 || alpha > PI / 2.0 {
        if alpha < 0.0 {
            cordic(alpha + PI, n, &mut x, &mut y);
        } else {
            cordic(alpha - PI, n, &mut x, &mut y);
        }
        *c_cos = x * newsgn;
        *c_sin = y * newsgn;
        return;
    }

    let ix = if n - 1 > 23 { 23 } else { n - 1 };
    let kn = KVALUES[ix];

    for i in 0..n {
        let atn = ANGLES[i];
        let sigma = if theta < alpha { 1.0 } else { -1.0 };
        theta += sigma * atn;
        let t = x;
        x -= sigma * y * pow2;
        y += sigma * t * pow2;
        pow2 /= 2.0;
    }

    *c_cos = x * kn;
    *c_sin = y * kn;
}

fn main() {
    let mut c_cos: f64;
    let mut c_sin: f64;
    let test_angles = [-9.0, 0.0, 1.5, 6.0];

    println!("  x       sin(x)     diff. sine     cos(x)    diff. cosine");
    for th in (-90..=90).step_by(15) {
        let thr = radians(th as f64);
        c_cos = 0.0;
        c_sin = 0.0;
        cordic(thr, 24, &mut c_cos, &mut c_sin);
        println!("{:+03}.0°  {:+.8} ({:+.8}) {:+.8} ({:+.8})", th, c_sin, c_sin - thr.sin(), c_cos, c_cos - thr.cos());
    }

    println!("\nx(rads)   sin(x)     diff. sine     cos(x)    diff. cosine");
    for &angle in &test_angles {
        let thr = angle;
        c_cos = 0.0;
        c_sin = 0.0;
        cordic(thr, 24, &mut c_cos, &mut c_sin);
        println!("{:+4.1}    {:+.8} ({:+.8}) {:+.8} ({:+.8})", thr, c_sin, c_sin - thr.sin(), c_cos, c_cos - thr.cos());
    }
}
Output:
  x       sin(x)     diff. sine     cos(x)    diff. cosine
-90.0°  -1.00000000 (+0.00000000) -0.00000007 (-0.00000007)
-75.0°  -0.96592585 (-0.00000003) +0.25881895 (-0.00000009)
-60.0°  -0.86602545 (-0.00000005) +0.49999992 (-0.00000008)
-45.0°  -0.70710684 (-0.00000006) +0.70710672 (-0.00000006)
-30.0°  -0.49999992 (+0.00000008) +0.86602545 (+0.00000005)
-15.0°  -0.25881895 (+0.00000009) +0.96592585 (+0.00000003)
+00.0°  +0.00000007 (+0.00000007) +1.00000000 (-0.00000000)
+15.0°  +0.25881895 (-0.00000009) +0.96592585 (+0.00000003)
+30.0°  +0.49999992 (-0.00000008) +0.86602545 (+0.00000005)
+45.0°  +0.70710684 (+0.00000006) +0.70710672 (-0.00000006)
+60.0°  +0.86602545 (+0.00000005) +0.49999992 (-0.00000008)
+75.0°  +0.96592585 (+0.00000003) +0.25881895 (-0.00000009)
+90.0°  +1.00000000 (-0.00000000) -0.00000007 (-0.00000007)

x(rads)   sin(x)     diff. sine     cos(x)    diff. cosine
-9.0    -0.41211842 (+0.00000006) -0.91113029 (-0.00000003)
+0.0    +0.00000007 (+0.00000007) +1.00000000 (-0.00000000)
+1.5    +0.99749499 (+0.00000000) +0.07073719 (-0.00000002)
+6.0    -0.27941552 (-0.00000002) +0.96017028 (-0.00000001)

Sidef

Translation of: Perl
func CORDIC(a) {
    var (k, x, y) = (0, 1, 0)
    var PoT = %n(1, 0.1, 0.01, 0.001, 0.0001, 0.00001)
    var Tbl = %n(7.853981633e-1 9.966865249e-2 9.999666686e-3 9.999996666e-4 9.999999966e-5 9.999999999e-6 0)

    for (true; a > 1e-5; a -= Tbl[k]) {
        while (a < Tbl[k]) { ++k }
        (x,y) = (x - PoT[k]*y, y + PoT[k]*x)
    }
    x / hypot(x,y)
}

print("Angle    CORDIC       Cosine       Error\n")
for angle in (%n(-9 0 1.5 6)) {
    var cordic = CORDIC(angle.abs)
    printf("%4.1f %12.8f %12.8f %12.8f\n", angle, cordic, cos(angle), cos(angle) - cordic)
}
Output:
Angle    CORDIC       Cosine       Error
-9.0  -0.91112769  -0.91113026  -0.00000257
 0.0   1.00000000   1.00000000   0.00000000
 1.5   0.07073880   0.07073720  -0.00000160
 6.0   0.96016761   0.96017029   0.00000268

Wren

Library: Wren-fmt

This is based on the Python example in the Wikipedia article except that the constants have been pre-calculated and the angles are adjusted, where necessary, to bring them within the [-π/2, π/2] range. The number of iterations is taken as 24 to try and match the Julia output which it does except for sin(0) which, curiously, has the same magnitude but a different sign.

import "./fmt" for Fmt

// The following are pre-computed to avoid using atan and sqrt functions.
var angles = [
    0.78539816339745, 0.46364760900081, 0.24497866312686, 0.12435499454676,
    0.06241880999596, 0.03123983343027, 0.01562372862048, 0.00781234106010,
    0.00390623013197, 0.00195312251648, 0.00097656218956, 0.00048828121119,
    0.00024414062015, 0.00012207031189, 0.00006103515617, 0.00003051757812,
    0.00001525878906, 0.00000762939453, 0.00000381469727, 0.00000190734863,
    0.00000095367432, 0.00000047683716, 0.00000023841858, 0.00000011920929,
    0.00000005960464, 0.00000002980232, 0.00000001490116, 0.00000000745058
]

var 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
]

var PI = Num.pi

var radians = Fn.new { |d| d * PI / 180 }

var Cordic = Fn.new { |alpha, n|
    var newsgn = ((alpha / (2 * PI)).floor % 2 == 1) ? 1 : -1
    if (alpha < -PI/2) {
        var res = Cordic.call(alpha + PI, n)
        return [newsgn * res[0], newsgn * res[1]]
    }
    if (alpha >  PI/2) {
        var res = Cordic.call(alpha - PI, n)
        return [newsgn * res[0], newsgn * res[1]]
    }
    var kn = kvalues[(n-1).min(kvalues.count-1)]
    var theta = 0
    var x = 1
    var y = 0
    var pow2 = 1
    for (atan in angles[0...n]) {
        var sigma = (theta < alpha) ? 1 : -1
        theta = theta + sigma * atan
        var t = x
        x = x - sigma * y * pow2
        y = y + sigma * t * pow2
        pow2 = pow2 / 2
    }
    return [x * kn, y * kn]
}

Fmt.print("  x       sin(x)     diff. sine     cos(x)    diff. cosine")
var f = "$+5.1f°  $+.8f ($+.8f) $+.8f ($+.8f)"

var th = -90
while (th <= 90) {
    var thr = radians.call(th)
    var res = Cordic.call(thr, 24)
    var cos = res[0]
    var sin = res[1]
    Fmt.print(f, th, sin, sin - thr.sin, cos, cos - thr.cos)
    th = th + 15
}
f = "$+5.1f°  $+.8f ($+.8f) $+.8f ($+.8f)"
Fmt.print("\nx(rads)   sin(x)     diff. sine     cos(x)    diff. cosine ")
f = "$+4.1f    $+.8f ($+.8f) $+.8f ($+.8f)"
for (thr in [-9, 0, 1.5, 6]) {
    var res = Cordic.call(thr, 24)
    var cos = res[0]
    var sin = res[1]
    Fmt.print(f, thr, sin, sin - thr.sin, cos, cos - thr.cos)
}
Output:
  x       sin(x)     diff. sine     cos(x)    diff. cosine
-90.0°  -1.00000000 (+0.00000000) -0.00000007 (-0.00000007)
-75.0°  -0.96592585 (-0.00000003) +0.25881895 (-0.00000009)
-60.0°  -0.86602545 (-0.00000005) +0.49999992 (-0.00000008)
-45.0°  -0.70710684 (-0.00000006) +0.70710672 (-0.00000006)
-30.0°  -0.49999992 (+0.00000008) +0.86602545 (+0.00000005)
-15.0°  -0.25881895 (+0.00000009) +0.96592585 (+0.00000003)
 +0.0°  +0.00000007 (+0.00000007) +1.00000000 (-0.00000000)
+15.0°  +0.25881895 (-0.00000009) +0.96592585 (+0.00000003)
+30.0°  +0.49999992 (-0.00000008) +0.86602545 (+0.00000005)
+45.0°  +0.70710684 (+0.00000006) +0.70710672 (-0.00000006)
+60.0°  +0.86602545 (+0.00000005) +0.49999992 (-0.00000008)
+75.0°  +0.96592585 (+0.00000003) +0.25881895 (-0.00000009)
+90.0°  +1.00000000 (-0.00000000) -0.00000007 (-0.00000007)

x(rads)   sin(x)     diff. sine     cos(x)    diff. cosine 
-9.0    -0.41211842 (+0.00000006) -0.91113029 (-0.00000003)
+0.0    +0.00000007 (+0.00000007) +1.00000000 (-0.00000000)
+1.5    +0.99749499 (+0.00000000) +0.07073719 (-0.00000002)
+6.0    -0.27941552 (-0.00000002) +0.96017028 (-0.00000001)

XPL0

include xpllib;         \for Print

real X, Y, R;

proc CORDIC(A);
real A;
real Tbl, Ten, T;
int  K;
[Ten:= [1E0, 1E-1, 1E-2, 1E-3, 1E-4, 1E-5];
Tbl:= [7.853981633974480E-001,
       9.966865249116200E-002,
       9.999666686665240E-003,
       9.999996666668670E-004,
       9.999999966666670E-005,
       9.999999999666670E-006,
       0.0];
X:= 1.;  Y:= 0.;  K:= 0;
while A > 1E-5 do
        [while A < Tbl(K) do K:= K+1;
        A:= A - Tbl(K);
        T:= X - Ten(K)*Y;
        Y:= Y + Ten(K)*X;
        X:= T;
        ];
R:= sqrt(X*X + Y*Y);
];

real Angles, A;
int  I;
[Print("Angle    CORDIC       Cosine       Error\n");
Angles:= [-9., 0., 1.5, 6.];
for I:= 0 to 3 do
        [A:= Angles(I);
        CORDIC(abs(A));
        Print("%2.1f  %2.8f  %2.8f  %2.8f\n", A, X/R, Cos(A), Cos(A)-X/R);
        ];
]
Output:
Angle    CORDIC       Cosine       Error
-9.0  -0.91112769  -0.91113026  -0.00000257
 0.0   1.00000000   1.00000000   0.00000000
 1.5   0.07073880   0.07073720  -0.00000160
 6.0   0.96016761   0.96017029   0.00000268