⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cordic.txt

📁 cordic methods describe essentially the same algorithm that with suitably chosen inputs can be used
💻 TXT
字号:
#include <stdio.h>
#include <math.h>
/* working with IEEE doubles, means there are 53 bits
 * of mantissa
 */
#define MAXBITS         53
/* define this to perform all (non 2power) multiplications
 * and divisions with the cordic linear method.
 */
#define CORDIC_LINEARx
/* these are the constants needed */
static double invGain1;
static double invGain2;
static double atanTable[MAXBITS];
static double atanhTable[MAXBITS];
static double gain1Cordic();
static double gain2Cordic();
void initCordic()
{
    /* must call this first to initialise the constants.
     * of course, here i use the maths library, but the
     * values would be precomputed.
     */
    double t = 1;
    int i;
    for (i = 0; i < MAXBITS; ++i) {
        atanTable[i] = atan(t);
        t /= 2;
        atanhTable[i] = 0.5*log((1+t)/(1-t));
    }
    /* set constants */
    invGain1 = 1/gain1Cordic();
    invGain2 = 1/gain2Cordic();
}
void cordit1(double* x0, double* y0, double* z0, double vecmode)
{
    /* this is the circular method. 
     * one slight change from the other methods is the y < vecmode 
     * test. this is to implement arcsin, otherwise it can be
     * y < 0 and you can compute arcsin from arctan using
     * trig identities, so its not essential.
     */
    double t;
    double x, y, z;
    int i;
    t = 1;
    x = *x0; y = *y0; z = *z0;
    for (i = 0; i < MAXBITS; ++i) {
        double x1;
        if (vecmode >= 0 && y < vecmode || vecmode<0  && z >= 0) {
            x1 = x - y*t;
            y = y + x*t;
            z = z - atanTable[i];
        }
        else {
            x1 = x + y*t;
            y = y - x*t;
            z = z + atanTable[i];
        }
        x = x1;
        t /= 2;
    }
    *x0 = x;
    *y0 = y;
    *z0 = z;
}
void cordit2(double* x0, double* y0, double* z0, double vecmode)
{
    /* here's the hyperbolic methods. its very similar to
     * the circular methods, but with some small differences.
     *
     * the `x' iteration have the opposite sign.
     * iterations 4, 7, .. 3k+1 are repeated.
     * iteration 0 is not performed.
     */
    double t;
    double x, y, z;
    int i;
    t = 0.5;
    x = *x0; y = *y0; z = *z0;
    int k = 3;
    for (i = 0; i < MAXBITS; ++i) {
        double x1;
        int j;
        for (j = 0; j < 2; ++j) {
            if (vecmode >= 0 && y < 0 || vecmode<0  && z >= 0) {
                x1 = x + y*t;
                y = y + x*t;
                z = z - atanhTable[i];
            }
            else {
                x1 = x - y*t;
                y = y - x*t;
                z = z + atanhTable[i];
            }
            x = x1;
            if (k) {
                --k;
                break;
            }
            else k = 3;
        }
        t /= 2;
    }
    *x0 = x;
    *y0 = y;
    *z0 = z;
}
void cordit0(double* x0, double* y0, double* z0, double vecmode)
{
    /* the linear methods is the same as the circular but
     * ive simplified out the x iteration as it doesnt change.
     */
    double t;
    double x, y, z;
    int i;
    t = 1;
    x = *x0; y = *y0; z = *z0;
    for (i = 0; i < MAXBITS; ++i) {
        if (vecmode >= 0 && y < 0 || vecmode<0  && z >= 0) {
            y = y + x*t;
            z = z - t;
        }
        else {
            y = y - x*t;
            z = z + t;
        }
        t /= 2;
    }
    *x0 = x;
    *y0 = y;
    *z0 = z;
}
/** Linear features ***********************************************/
double mulCordic(double a, double b)
{
    double x, y, z;
    x = a;
    y = 0;
    z = b;
    cordit0(&x, &y, &z, -1);
    return y;
}
double divCordic(double a, double b)
{
    double x, y, z;
    x = b;
    y = a;
    z = 0;
    cordit0(&x, &y, &z, 0);
    return z;
}
#ifdef CORDIC_LINEAR
#define MULT(_a, _b)    mulCordic(_a, _b)
#define DIVD(_a, _b)    divCordic(_a, _b)
#else
#define MULT(_a, _b)    (_a)*(_b)
#define DIVD(_a, _b)    (_a)/(_b)
#endif 
/** circular features ***********************************************/
static double gain1Cordic()
{
    /* compute gain by evaluating cos(0) without inv gain */
    double x, y, z;
    x = 1;
    y = 0;
    z = 0;
    cordit1(&x, &y, &z, -1);
    return x;
}
double atanCordic(double a)
{
    /* domain: all a */
    double x = 1;
    double z = 0;
    cordit1(&x, &a, &z, 0);
    return z;
}
double sincosCordic(double a, double* cosp)
{
    /* |a| < 1.74 */
    double sinp = 0;
    *cosp = invGain1;
    cordit1(cosp, &sinp, &a, -1);
    return sinp;
}
double tanCordic(double a)
{
    /* |a| < 1.74 */
    double sinp = 0;
    double cosp = invGain1;
    cordit1(&cosp, &sinp, &a, -1);
    return DIVD(sinp, cosp);
}
double asinCordic(double a)
{
    /* |a| < 0.98 */
    double x, y, z;
    
    x = invGain1;
    y = 0;
    z = 0;
    int neg = 1;
    if (a < 0) {
        a = -a;
        neg = 0;
    }
        
    cordit1(&x, &y, &z, a);
    if (neg) z = -z;
    return z;
}
/** hyperbolic features ********************************************/
double gain2Cordic()
{
    /* calculate hyperbolic gain */
    double x, y, z;
    x = 1;
    y = 0;
    z = 0;
    cordit2(&x, &y, &z, -1);
    return x;
}
double sinhcoshCordic(double a, double* coshp)
{
    /* |a| < 1.13 */
    double y;
    *coshp = invGain2;
    y = 0;
    cordit2(coshp, &y, &a, -1);
    return y;
}
double tanhCordic(double a)
{
    /* |a| < 1.13 */
   double sinhp, coshp;
   coshp = invGain2;
   sinhp = 0;
   cordit2(&coshp, &sinhp, &a, -1);
   return DIVD(sinhp,coshp);
}
double atanhCordic(double a)
{
    /* |a| < 1.13 */
    double x, z;
    x = 1;
    z = 0;
    cordit2(&x, &a, &z, 0);
    return z;
}
double logCordic(double a)
{
    /* 0.1 < a < 9.58 */
    double x, y, z;
    x = a + 1;
    y = a - 1;
    z = 0;
    cordit2(&x, &y, &z, 0);
    return 2*z;
}
double sqrtCordic(double a)
{
    /* 0.03 < a < 2 */
    double x, y, z;
    x = a + 0.25;
    y = a - 0.25;
    z = 0;
    cordit2(&x, &y, &z, 0);
    return MULT(x, invGain2);
}
double expCordic(double a)
{
    double sinhp, coshp;
    coshp = invGain2;
    sinhp = 0;
    cordit2(&coshp, &sinhp, &a, -1);
    return sinhp + coshp;
}
main()
{
    /* just run a few tests */
    double v;
    double x;
    double c;
    initCordic();
    x = 1;
    v = atanCordic(x);
    printf("atan %f = %.18e\n", x, v);
    x = 1;
    v = sincosCordic(x, &c);
    printf("sin %f = %.18e\n", x, v);
    printf("cos %f = %.18e\n", x, c);
    x = 1;
    v = tanCordic(x);
    printf("tan %f = %.18e\n", x, v);
    x = 0.5;
    v = asinCordic(x);
    printf("asin %f = %.18e\n", x, v);
    x = 1;
    v = sinhcoshCordic(x, &c);
    printf("sinh %f = %.18e\n", x, v);
    printf("cosh %f = %.18e\n", x, c);
    x = 1;
    v = tanhCordic(x);
    printf("tanhh %f = %.18e\n", x, v);
    x = 0.5;
    v = atanhCordic(x);
    printf("atanh %f = %.18e\n", x, v);
    x = 0.8;
    v = logCordic(x);
    printf("log %f = %.18e\n", x, v);
    x = 2;
    v = sqrtCordic(x);
    printf("sqrt %f = %.18e\n", x, v);
    x = 1;
    v = expCordic(x);
    printf("exp %f = %.18e\n", x, v);
    return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -