Skip to content

Instantly share code, notes, and snippets.

@westonal
Last active August 29, 2015 14:22
Show Gist options
  • Save westonal/15722186f947be191d73 to your computer and use it in GitHub Desktop.
Save westonal/15722186f947be191d73 to your computer and use it in GitHub Desktop.
CORDIC
/*
============================================================================
Name : SinCosProject.c
Author :
Version :
Copyright : Your copyright notice
Description : Hello World in C, Ansi-style
============================================================================
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
//Cordic in 32 bit signed fixed point math
//Function is valid for arguments in range -pi/2 -- pi/2
//for values pi/2--pi: value = half_pi-(theta-half_pi) and similarly for values -pi---pi/2
//
// 1.0 = 1073741824
// 1/k = 0.6072529350088812561694
// pi = 3.1415926535897932384626
//Constants
#define cordic_1K 0x26DD3B6A
#define half_pi 0x6487ED51
#define MUL 1073741824.000000
#define MUL_RECIP 1.0/MUL
#define CORDIC_NTAB 32
int cordic_ctab[] = { 0x3243F6A8, 0x1DAC6705, 0x0FADBAFC, 0x07F56EA6,
0x03FEAB76, 0x01FFD55B, 0x00FFFAAA, 0x007FFF55, 0x003FFFEA, 0x001FFFFD,
0x000FFFFF, 0x0007FFFF, 0x0003FFFF, 0x0001FFFF, 0x0000FFFF, 0x00007FFF,
0x00003FFF, 0x00001FFF, 0x00000FFF, 0x000007FF, 0x000003FF, 0x000001FF,
0x000000FF, 0x0000007F, 0x0000003F, 0x0000001F, 0x0000000F, 0x00000008,
0x00000004, 0x00000002, 0x00000001, 0x00000000, };
void cordic(int theta, int *s, int *c, int n) {
int k, d, tx, ty, tz;
int x = cordic_1K, y = 0, z = theta;
n = (n > CORDIC_NTAB) ? CORDIC_NTAB : n;
for (k = 0; k < n; ++k) {
d = z >> 31;
//get sign. for other architectures, you might want to use the more portable version
//d = z>=0 ? 0 : -1;
tx = x - (((y >> k) ^ d) - d);
ty = y + (((x >> k) ^ d) - d);
tz = z - ((cordic_ctab[k] ^ d) - d);
x = tx;
y = ty;
z = tz;
}
*c = x;
*s = y;
}
float normalizeRadiansToPlusMinusM_PI(float radians) {
int sign = radians < 0 ? -1 : 1;
radians = sign * radians;
int revolutions = (int) (radians * M_1_PI) + 1;
revolutions = (revolutions >> 1) << 1;
radians = radians - revolutions * M_PI;
return sign * radians;
}
int radiansToPlusMinusM_PI_2(float *radians) {
int flip = 0;
*radians = normalizeRadiansToPlusMinusM_PI(*radians);
if (*radians < -M_PI_2 || *radians > M_PI_2) {
if (*radians < 0) {
*radians += M_PI;
} else {
*radians -= M_PI;
}
flip = 1; //flip the sign for second or third quadrant
}
return flip;
}
void cordicF(float theta, float *s, float *c, int n) {
int sint, cint;
int flip = radiansToPlusMinusM_PI_2(&theta);
cordic(theta * MUL, &sint, &cint, n);
*s = sint * MUL_RECIP;
*c = cint * MUL_RECIP;
if (flip) {
*s = -*s;
*c = -*c;
}
}
void p_sincos_f32(const float *a, float *c, float *z, int n) {
int i;
for (i = 0; i < n; i++) {
const float angle = a[i];
float *pcos = z + i;
float *psin = c + i;
cordicF(angle, psin, pcos, 17);
}
}
int main(void) {
int angle;
int n;
for (n = 10; n <= 30; n++) {
float maxError = 0;
int r;
int repeats = 10;
int max = 72000;
int min = -72000;
for (angle = min; angle <= max; angle++) {
float rads = angle * M_PI / 18000.0;
float sinF, cosF, csinF, ccosF, dc, ds;
cordicF(rads, &sinF, &cosF, n);
csinF = sinf(rads);
ccosF = cosf(rads);
dc = ccosF - cosF;
ds = csinF - sinF;
if (dc < 0)
dc = -dc;
if (ds < 0)
ds = -ds;
//printf("Angle %f, Sin %.4f, Cos %.4f, Sin %.4f, Cos %.4f Delta %.6f/%.6f\n",
//angle / 100.0, sinF, cosF, csinF, ccosF, ds, dc);
maxError = dc > maxError ? dc : maxError;
maxError = ds > maxError ? ds : maxError;
// if (dc > error || ds > error) {
// printf("ERROR %f/%f", ds, dc);
// break;
// }
}
{
int range = max - min + 1;
clock_t begin, end;
double time_spent;
begin = clock();
for (r = 0; r < repeats; r++)
for (angle = min; angle <= max; angle++) {
float rads = angle * M_PI / 18000.0;
float sinF, cosF;
cordicF(rads, &sinF, &cosF, n);
}
end = clock();
time_spent = (double) (end - begin) / CLOCKS_PER_SEC;
printf("n=%d |max error|=%.8f in %f microseconds\n", n, maxError,
1000000 * time_spent / (repeats * range));
}
}
{
float a[4] = { 0, M_PI, M_PI_2, M_PI_4 };
float c[4];
float z[4];
int i;
p_sincos_f32(&a[0], &c[0], &z[0], 4);
for (i = 0; i < 4; i++)
printf("X %.4f = s:%.4f (%.4f), c:%.4f (%.4f)\n", a[i], c[i],
sinf(a[i]), z[i], cosf(a[i]));
}
return EXIT_SUCCESS;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment