CORDIC Implementations
From https://github.com/suyashmahar/cordic-algorithm-python
circular = 1
linear = 0
hyperbolic = -1
def ROM_lookup(iteration, coord_mode):
if (coord_mode == circular):
return math.degrees(math.atan(2**(-1*iteration)))
elif (coord_mode == linear):
return 2**(-1*iteration)
elif (coord_mode == hyperbolic):
return (math.atanh(2**(-1*iteration)))
def rotation_mode(x, y, z, coord_mode, iterations):
a = 0.607252935; # = 1/K
x_val_list = []
y_val_list = []
z_val_list = []
iterations_list = []
i = 0; # Keeps count on number of iterations
current_x = x # Value of X on ith iteration
current_y = y # Value of Y on ith iteration
current_z = z # Value of Z on ith iteration
di = 0
if (coord_mode == hyperbolic):
i = 1
else:
i = 0
flag = 0
if (iterations > 0):
while (i < iterations):
if (current_z < 0):
di = -1
else:
di = +1
next_z = current_z - di * ROM_lookup(i, coord_mode)
next_x = current_x - coord_mode * di * current_y * (2**(-1*i))
next_y = current_y + di * current_x * 2**(-1*i)
current_x = next_x
current_y = next_y
current_z = next_z
x_val_list.append(current_x)
y_val_list.append(current_y)
z_val_list.append(current_z)
iterations_list.append(i)
if (coord_mode == hyperbolic):
if ((i != 4) & (i != 13) & (i!=40)):
i = i+1
elif (flag == 0):
flag = 1
elif (flag == 1):
flag = 0
i = i+1
else:
i = i+1
return { 'x':x_val_list, 'y':y_val_list, 'z':z_val_list,
'iteration':iterations_list, }
def vector_mode(x, y, z, coord_mode, iterations):
a = 1.2075; # = 1/K
x_val_list = []
y_val_list = []
z_val_list = []
iterations_list = []
i = 0; # Keeps count on number of iterations
current_x = x # Value of X on ith iteration
current_y = y # Value of Y on ith iteration
current_z = z # Value of Z on ith iteration
di = 0
# This is neccesary since result for i=0 doesn't exists for hyperbolic
# co-ordinate system.
if (coord_mode == hyperbolic):
i = 1
else:
i = 0
flag = 0
if (iterations > 0):
while (i < iterations):
di = -1*math.copysign(1, current_y);#*current_x);
next_x = current_x - coord_mode * di * current_y * (2**(-1*i))
next_y = current_y + di * current_x * 2**(-1*i)
next_z = current_z - di * ROM_lookup(i, coord_mode)
current_x = next_x
current_y = next_y
current_z = next_z
x_val_list.append(current_x)
y_val_list.append(current_y)
z_val_list.append(current_z)
iterations_list.append(i)
if (coord_mode == hyperbolic):
if ((i != 4) & (i != 13) & (i!=40)):
i = i+1
elif (flag == 0):
flag = 1
elif (flag == 1):
flag = 0
i = i+1
else:
i = i+1
return { 'x':x_val_list, 'y':y_val_list, 'z':z_val_list,
'iteration':iterations_list }
Alternative in c:
int i = 0;
int iterations = 0; // Number of times to run the algorithm
float arctanTable[iterations]; // in Radians
float K = 0.6073; // K
float v_x,v_y; // Vector v; x and y components
for(i=0; i < iterations; i++) {
arctanTable[i] = atan(pow(2,-i));
}
float vnew_x; // To store the new value of x;
for(i = 0; i < iterations; i++) {
// If beta is negative, we need to do a counter-clockwise rotation:
if( beta < 0) {
vnew_x = v_x + (v_y*pow(2,-i));
v_y -= (v_x*pow(2,-i));
beta += arctanTable[i];
}
// If beta is positive, we need to do a clockwise rotation:
else {
vnew_x = v_x - (v_y*pow(2,-i));
v_y += (v_x*pow(2,-i));
beta -= arctanTable[i];
}
v_x = vnew_x;
}
v_x *= K;
v_y *= K;
Vector Length
http://lists.libre-riscv.org/pipermail/libre-riscv-dev/2019-October/002982.html
With VLENGTH being also expressible as dotproduct followed by scalar sqrt, is it reasonable to have both normalisation as well as VLENGTH as macro op fused sequences?
Vector length would presumably involve dotting a vector with itself. The potential advantage I see is that the dot product might be tempted to read that vector twice; whereas the length would only read it once. If some other mechanism eliminates the duplicate read, they would be pretty well equivalent.