The CORDIC algorithm
This example examines the implementation of the CORDIC algorithm in the Julia programming language for calculating trigonometric functions (sine and cosine). without using standard functions.
Introduction
The CORDIC algorithm (from COordinate Rotation DIgital Computer) is an iterative numerical method used to calculate trigonometric, hyperbolic, and other mathematical functions. Originally developed for navigation systems, CORDIC is especially useful in conditions of limited computing resources, since it uses only additions, subtractions and shifts, operations that work well both in hardware and software. In this example, CORDIC is used to calculate the values of the sine and cosine of a given angle.
The main part
Installing and connecting packages
import Pkg; Pkg.add("Printf")
using Printf
Function cordic
This is the main function implementing the CORDIC algorithm. She takes the angle alpha in radians and the number of iterations iteration. The number of iterations affects the accuracy of the result. The more iterations, the higher the accuracy, but also the longer the calculations.
function cordic(alpha, iteration = 24)
# If the angle is greater than 2π, there may be a sign failure when defining a new sign.
newsgn = isodd(Int(floor(alpha / 2π))) ? 1 : -1
# Bringing the angle to the range [-π/2, π/2]
alpha < -π/2 && return newsgn * cordic(alpha + π, iteration)
alpha > π/2 && return newsgn * cordic(alpha - π, iteration)
# A table of pre-calculated arctangents 2^(-j), where j = 0, 1, 2, ...
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]
# The table of scaling factors Kn, taken into account at the end
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]
# We select the value of the zoom level depending on the number of iterations.
Kn = Kvalues[min(iteration, length(Kvalues))]
# The initial value of the vector is [cos(0), sin(0)] = [1, 0]
v = [1, 0]
poweroftwo = 1 # the power of two, 2^0=1, varies with each iteration
angle = angles[1] # current rotation angle
# The main iteration cycle of CORDIC
for j = 0:iteration-1
if alpha < 0
sigma = -1 # turn counterclockwise
else
sigma = 1 # turn clockwise
end
factor = sigma * poweroftwo # the coefficient for the rotation matrix
# The rotation matrix for the angle atan(2^(-j)), written in CORDIC form
R = [1 -factor
factor 1]
# Multiply the vector v by the matrix R (rotate the vector)
v = R * v
# Updating the value of the remaining angle for the next iteration
alpha -= sigma * angle
# Moving to the next power of two
poweroftwo /= 2
# Updating the angle for the next iteration
if j + 2 > length(angles)
angle /= 2 # if the table is over, reduce the angle by half.
else
angle = angles[j + 2] # otherwise, we take the following angle from the table
end
end
# We apply a scaling factor to get the true values.
v .*= Kn
return v # we return [cos(alpha), sin(alpha)]
end
Function test_cordic
This function is used to check the operation of the algorithm. It outputs the values of the sine and cosine for various angles (in degrees and radians) and compares them with the built-in Julia functions.
function test_cordic()
println(" x sin(x) Δsin cos(x) Δcos ")
# Checking for angles from -90° to +90° in 15° increments
for θ in -90:15:90
# Convert degrees to radians and run the CORDIC function
cosθ, sinθ = cordic(deg2rad(θ))
# We print the values in the format: angle, sin, sine error, cos, cosine error
@printf("%+05.1f° %+.8f (%+.8f) %+.8f (%+.8f)\n",
θ, sinθ, sinθ - sind(θ), cosθ, cosθ - cosd(θ))
end
println("\nx(rad) sin(x) Δsin cos(x) Δcos ")
# Checking for some angles in radians
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()
Conclusion
In this example, we looked at the implementation of the CORDIC algorithm in Julia for calculating the values of sine and cosine. The algorithm allows you to avoid using complex operations by relying only on simple arithmetic operations. This makes it especially useful in systems with limited computing capabilities. We also tested the implementation, comparing it with the built-in functions, and made sure that the results are close to the reference ones, which confirms the correctness of the implementation.
The example was developed using materials from Rosetta Code