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

📄 pi_fft.c

📁 This is a package to calculate Discrete Fourier/Cosine/Sine Transforms of 1-dimensional sequences of
💻 C
📖 第 1 页 / 共 3 页
字号:
    }    return -carry;}int mp_unexp_sub(int n, int radix, int expdif,         int in1[], int in2[], int out[]){    int j, x, borrow, ncancel;        if (expdif > n) {        expdif = n;    }    borrow = 0;    for (j = n - 1; j >= expdif; j--) {        x = in1[j] - in2[j - expdif] + borrow;        borrow = x < 0 ? -1 : 0;        out[j] = x + (radix & borrow);    }    for (j = expdif - 1; j >= 0; j--) {        x = in1[j] + borrow;        borrow = x < 0 ? -1 : 0;        out[j] = x + (radix & borrow);    }    ncancel = 0;    for (j = 0; j < n && out[j] == 0; j++) {        ncancel = j + 1;    }    if (ncancel > 0 && ncancel < n) {        for (j = 0; j < n - ncancel; j++) {            out[j] = out[j + ncancel];        }        for (j = n - ncancel; j < n; j++) {            out[j] = 0;        }    }    return ncancel;}/* -------- mp_imul routines -------- */void mp_imul(int n, int radix, int in1[], int in2, int out[]){    void mp_unsgn_imul(int n, double dradix, int in1[], double din2,             int out[]);        if (in2 > 0) {        out[0] = in1[0];    } else if (in2 < 0) {        out[0] = -in1[0];        in2 = -in2;    } else {        out[0] = 0;    }    mp_unsgn_imul(n, radix, &in1[1], in2, &out[1]);    if (out[0] == 0) {        out[1] = 0;    }}int mp_idiv(int n, int radix, int in1[], int in2, int out[]){    void mp_load_0(int n, int radix, int out[]);    void mp_unsgn_idiv(int n, double dradix, int in1[], double din2,             int out[]);        if (in2 == 0) {        return -1;    }    if (in2 > 0) {        out[0] = in1[0];    } else {        out[0] = -in1[0];        in2 = -in2;    }    if (in1[0] == 0) {        mp_load_0(n, radix, out);        return 0;    }    mp_unsgn_idiv(n, radix, &in1[1], in2, &out[1]);    return 0;}void mp_idiv_2(int n, int radix, int in[], int out[]){    int j, ix, carry, shift;        out[0] = in[0];    shift = 0;    if (in[2] == 1) {        shift = 1;    }    out[1] = in[1] - shift;    carry = -shift;    for (j = 2; j <= n + 1 - shift; j++) {        ix = in[j + shift] + (radix & carry);        carry = -(ix & 1);        out[j] = ix >> 1;    }    if (shift > 0) {        out[n + 1] = (radix & carry) >> 1;    }}/* -------- mp_imul child routines -------- */void mp_unsgn_imul(int n, double dradix, int in1[], double din2,         int out[]){    int j, carry, shift;    double x, d1_radix;        d1_radix = 1.0 / dradix;    carry = 0;    for (j = n; j >= 1; j--) {        x = din2 * in1[j] + carry + 0.5;        carry = (int) (d1_radix * x);        out[j] = (int) (x - dradix * carry);    }    shift = 0;    x = carry + 0.5;    while (x > 1) {        x *= d1_radix;        shift++;    }    out[0] = in1[0] + shift;    if (shift > 0) {        while (shift > n) {            carry = (int) (d1_radix * carry + 0.5);            shift--;        }        for (j = n; j >= shift + 1; j--) {            out[j] = out[j - shift];        }        for (j = shift; j >= 1; j--) {            x = carry + 0.5;            carry = (int) (d1_radix * x);            out[j] = (int) (x - dradix * carry);        }    }}void mp_unsgn_idiv(int n, double dradix, int in1[], double din2,         int out[]){    int j, ix, carry, shift;    double x, d1_in2;        d1_in2 = 1.0 / din2;    shift = 0;    x = 0;    do {        shift++;        x *= dradix;        if (shift <= n) {            x += in1[shift];        }    } while (x < din2 - 0.5);    x += 0.5;    ix = (int) (d1_in2 * x);    carry = (int) (x - din2 * ix);    out[1] = ix;    shift--;    out[0] = in1[0] - shift;    if (shift >= n) {        shift = n - 1;    }    for (j = 2; j <= n - shift; j++) {        x = in1[j + shift] + dradix * carry + 0.5;        ix = (int) (d1_in2 * x);        carry = (int) (x - din2 * ix);        out[j] = ix;    }    for (j = n - shift + 1; j <= n; j++) {        x = dradix * carry + 0.5;        ix = (int) (d1_in2 * x);        carry = (int) (x - din2 * ix);        out[j] = ix;    }}/* -------- mp_mul routines -------- */double mp_mul_radix_test(int n, int radix, int nfft,         double tmpfft[], int ip[], double w[]){    void rdft(int n, int isgn, double *a, int *ip, double *w);    void mp_mul_csqu(int nfft, double dinout[]);    double mp_mul_d2i_test(int radix, int nfft, double din[]);    int j, ndata, radix_2;        ndata = (nfft >> 1) + 1;    if (ndata > n) {        ndata = n;    }    tmpfft[nfft + 1] = radix - 1;    for (j = nfft; j > ndata; j--) {        tmpfft[j] = 0;    }    radix_2 = (radix + 1) / 2;    for (j = ndata; j > 2; j--) {        tmpfft[j] = radix_2;    }    tmpfft[2] = radix;    tmpfft[1] = radix - 1;    tmpfft[0] = 0;    rdft(nfft, 1, &tmpfft[1], ip, w);    mp_mul_csqu(nfft, tmpfft);    rdft(nfft, -1, &tmpfft[1], ip, w);    return 2 * mp_mul_d2i_test(radix, nfft, tmpfft);}void mp_mul(int n, int radix, int in1[], int in2[], int out[],         int tmp[], int nfft, double tmp1fft[], double tmp2fft[],         double tmp3fft[], int ip[], double w[]){    void mp_copy(int n, int radix, int in[], int out[]);    void mp_add(int n, int radix, int in1[], int in2[], int out[]);    void rdft(int n, int isgn, double *a, int *ip, double *w);    void mp_mul_i2d(int n, int radix, int nfft, int shift,             int in[], double dout[]);    void mp_mul_cmul(int nfft, double din[], double dinout[]);    void mp_mul_cmuladd(int nfft, double din1[], double din2[],             double dinout[]);    void mp_mul_d2i(int n, int radix, int nfft, double din[], int out[]);    int n_h, shift;        shift = (nfft >> 1) + 1;    while (n > shift) {        if (in1[shift + 2] + in2[shift + 2] != 0) {            break;        }        shift++;    }    n_h = n / 2 + 1;    if (n_h < n - shift) {        n_h = n - shift;    }    /* ---- tmp3fft = (upper) in1 * (lower) in2 ---- */    mp_mul_i2d(n, radix, nfft, 0, in1, tmp1fft);    rdft(nfft, 1, &tmp1fft[1], ip, w);    mp_mul_i2d(n, radix, nfft, shift, in2, tmp3fft);    rdft(nfft, 1, &tmp3fft[1], ip, w);    mp_mul_cmul(nfft, tmp1fft, tmp3fft);    /* ---- tmp = (upper) in1 * (upper) in2 ---- */    mp_mul_i2d(n, radix, nfft, 0, in2, tmp2fft);    rdft(nfft, 1, &tmp2fft[1], ip, w);    mp_mul_cmul(nfft, tmp2fft, tmp1fft);    rdft(nfft, -1, &tmp1fft[1], ip, w);    mp_mul_d2i(n, radix, nfft, tmp1fft, tmp);    /* ---- tmp3fft += (upper) in2 * (lower) in1 ---- */    mp_mul_i2d(n, radix, nfft, shift, in1, tmp1fft);    rdft(nfft, 1, &tmp1fft[1], ip, w);    mp_mul_cmuladd(nfft, tmp1fft, tmp2fft, tmp3fft);    /* ---- out = tmp + tmp3fft ---- */    rdft(nfft, -1, &tmp3fft[1], ip, w);    mp_mul_d2i(n_h, radix, nfft, tmp3fft, out);    if (out[0] != 0) {        mp_add(n, radix, out, tmp, out);    } else {        mp_copy(n, radix, tmp, out);    }}void mp_squ(int n, int radix, int in[], int out[], int tmp[],         int nfft, double tmp1fft[], double tmp2fft[],         int ip[], double w[]){    void mp_add(int n, int radix, int in1[], int in2[], int out[]);    void rdft(int n, int isgn, double *a, int *ip, double *w);    void mp_mul_i2d(int n, int radix, int nfft, int shift,             int in[], double dout[]);    void mp_mul_cmul(int nfft, double din[], double dinout[]);    void mp_mul_csqu(int nfft, double dinout[]);    void mp_mul_d2i(int n, int radix, int nfft, double din[], int out[]);    int n_h, shift;        shift = (nfft >> 1) + 1;    while (n > shift) {        if (in[shift + 2] != 0) {            break;        }        shift++;    }    n_h = n / 2 + 1;    if (n_h < n - shift) {        n_h = n - shift;    }    /* ---- tmp = (upper) in * (lower) in ---- */    mp_mul_i2d(n, radix, nfft, 0, in, tmp1fft);    rdft(nfft, 1, &tmp1fft[1], ip, w);    mp_mul_i2d(n, radix, nfft, shift, in, tmp2fft);    rdft(nfft, 1, &tmp2fft[1], ip, w);    mp_mul_cmul(nfft, tmp1fft, tmp2fft);    rdft(nfft, -1, &tmp2fft[1], ip, w);    mp_mul_d2i(n_h, radix, nfft, tmp2fft, tmp);    /* ---- out = 2 * tmp + ((upper) in)^2 ---- */    mp_mul_csqu(nfft, tmp1fft);    rdft(nfft, -1, &tmp1fft[1], ip, w);    mp_mul_d2i(n, radix, nfft, tmp1fft, out);    if (tmp[0] != 0) {        mp_add(n_h, radix, tmp, tmp, tmp);        mp_add(n, radix, out, tmp, out);    }}void mp_mulh(int n, int radix, int in1[], int in2[], int out[],         int nfft, double in1fft[], double outfft[], int ip[], double w[]){    void rdft(int n, int isgn, double *a, int *ip, double *w);    void mp_mul_i2d(int n, int radix, int nfft, int shift,             int in[], double dout[]);    void mp_mul_cmul(int nfft, double din[], double dinout[]);    void mp_mul_d2i(int n, int radix, int nfft, double din[], int out[]);        mp_mul_i2d(n, radix, nfft, 0, in1, in1fft);    rdft(nfft, 1, &in1fft[1], ip, w);    mp_mul_i2d(n, radix, nfft, 0, in2, outfft);    rdft(nfft, 1, &outfft[1], ip, w);    mp_mul_cmul(nfft, in1fft, outfft);    rdft(nfft, -1, &outfft[1], ip, w);    mp_mul_d2i(n, radix, nfft, outfft, out);}void mp_mulh_use_in1fft(int n, int radix, double in1fft[],         int shift, int in2[], int out[], int nfft, double outfft[],         int ip[], double w[]){    void rdft(int n, int isgn, double *a, int *ip, double *w);    void mp_mul_i2d(int n, int radix, int nfft, int shift,             int in[], double dout[]);    void mp_mul_cmul(int nfft, double din[], double dinout[]);    void mp_mul_d2i(int n, int radix, int nfft, double din[], int out[]);    int n_h;        while (n > shift) {        if (in2[shift + 2] != 0) {            break;        }        shift++;    }    n_h = n / 2 + 1;    if (n_h < n - shift) {        n_h = n - shift;    }    mp_mul_i2d(n, radix, nfft, shift, in2, outfft);    rdft(nfft, 1, &outfft[1], ip, w);    mp_mul_cmul(nfft, in1fft, outfft);    rdft(nfft, -1, &outfft[1], ip, w);    mp_mul_d2i(n_h, radix, nfft, outfft, out);}void mp_squh(int n, int radix, int in[], int out[],         int nfft, double inoutfft[], int ip[], double w[]){    void rdft(int n, int isgn, double *a, int *ip, double *w);    void mp_mul_i2d(int n, int radix, int nfft, int shift,             int in[], double dout[]);    void mp_mul_csqu(int nfft, double dinout[]);    void mp_mul_d2i(int n, int radix, int nfft, double din[], int out[]);        mp_mul_i2d(n, radix, nfft, 0, in, inoutfft);    rdft(nfft, 1, &inoutfft[1], ip, w);    mp_mul_csqu(nfft, inoutfft);    rdft(nfft, -1, &inoutfft[1], ip, w);    mp_mul_d2i(n, radix, nfft, inoutfft, out);}void mp_squh_use_in1fft(int n, int radix, double inoutfft[], int out[],         int nfft, int ip[], double w[]){    void rdft(int n, int isgn, double *a, int *ip, double *w);    void mp_mul_csqu(int nfft, double dinout[]);    void mp_mul_d2i(int n, int radix, int nfft, double din[], int out[]);        mp_mul_csqu(nfft, inoutfft);    rdft(nfft, -1, &inoutfft[1], ip, w);    mp_mul_d2i(n, radix, nfft, inoutfft, out);}/* -------- mp_mul child routines -------- */void mp_mul_i2d(int n, int radix, int nfft, int shift,         int in[], double dout[]){    int j, x, carry, ndata, radix_2, topdgt;        ndata = 0;    topdgt = 0;    if (n > shift) {        topdgt = in[shift + 2];        ndata = (nfft >> 1) + 1;        if (ndata > n - shift) {            ndata = n - shift;        }    }    dout[nfft + 1] = in[0] * topdgt;    for (j = nfft; j > ndata; j--) {        dout[j] = 0;    }    /* ---- abs(dout[j]) <= radix/2 (to keep FFT precision) ---- */    if (ndata > 1) {        radix_2 = radix / 2;        carry = 0;        for (j = ndata + 1; j > 3; j--) {            x = in[j + shift] - carry;            carry = x >= radix_2 ? -1 : 0;            dout[j - 1] = x - (radix & carry);        }        dout[2] = in[shift + 3] - carry;    }    dout[1] = topdgt;    dout[0] = in[1] - shift;}void mp_mul_cmul(int nfft, double din[], double dinout[]){    int j;    double xr, xi, yr, yi;        dinout[0] += din[0];    dinout[1] *= din[1];    dinout[2] *= din[2];    for (j = 3; j < nfft; j += 2) {        xr = din[j];        xi = din[j + 1];        yr = dinout[j];        yi = dinout[j + 1];        dinout[j] = xr * yr - xi * yi;        dinout[j + 1] = xr * yi + xi * yr;    }    dinout[nfft + 1] *= din[nfft + 1];}void mp_mul_cmuladd(int nfft, double din1[], double din2[],         double dinout[]){    int j;    double xr, xi, yr, yi;        dinout[1] += din1[1] * din2[1];    dinout[2] += din1[2] * din2[2];    for (j = 3; j < nfft; j += 2) {        xr = din1[j];        xi = din1[j + 1];        yr = din2[j];        yi = din2[j + 1];        dinout[j] += xr * yr - xi * yi;        dinout[j + 1] += xr * yi + xi * yr;    }    dinout[nfft + 1] += din1[nfft + 1] * din2[nfft + 1];}void mp_mul_csqu(int nfft, double dinout[]){    int j;    double xr, xi;        dinout[0] *= 2;    dinout[1] *= dinout[1];    dinout[2] *= dinout[2];    for (j = 3; j < nfft; j += 2) {        xr = dinout[j];        xi = dinout[j + 1];        dinout[j] = xr * xr - xi * xi;        dinout[j + 1] = 2 * xr * xi;    }    dinout[nfft + 1] *= dinout[nfft + 1];}void mp_mul_d2i(int n, int radix, int nfft, double din[], int out[]){    int j, carry, carry1, carry2, shift, ndata;    double x, scale, d1_radix, d1_radix2, pow_radix, topdgt;        scale = 2.0 / nfft;    d1_radix = 1.0 / radix;    d1_radix2 = d1_radix * d1_radix;    topdgt = din[nfft + 1];    x = topdgt < 0 ? -topdgt : topdgt;    shift = x + 0.5 >= radix ? 1 : 0;    /* ---- correction of cyclic convolution of din[1] ---- */    x *= nfft * 0.5;    din[nfft + 1] = din[1] - x;    din[1] = x;    /* ---- output of digits ---- */    ndata = n;    if (n > nfft + 1 + shift) {        ndata = nfft + 1 + shift;        for (j = n + 1; j > ndata + 1; j--) {            out[j] = 0;        }    }    x = 0;    pow_radix = 1;    for (j = ndata + 1 - shift; j <= nfft + 1; j++) {        x += pow_radix * din[j];        pow_radix *= d1_radix;        if (pow_radix < DBL_EPSILON) {            break;        }    }    x = d1_radix2 * (scale * x + 0.5);    carry2 = ((int) x) - 1;    carry = (int) (radix * (x - carry2) + 0.5);    for (j = ndata; j > 1; j--) {        x = d1_radix2 * (scale * din[j - shift] + carry + 0.5);        carry = carry2;        carry2 = ((int) x) - 1;        x = radix * (x - carry2);        carry1 = (int) x;        out[j + 1] = (int) (radix * (x - carry1));        carry += carry1;    }    x = carry + ((double) radix) * carry2 + 0.5;    if (shift == 0) {        x += scale * din[1];    }

⌨️ 快捷键说明

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