コード例 #1
0
ファイル: fft_rader.c プロジェクト: Clivia/liquid-dsp
// create FFT plan for regular DFT
//  _nfft   :   FFT size
//  _x      :   input array [size: _nfft x 1]
//  _y      :   output array [size: _nfft x 1]
//  _dir    :   fft direction: {LIQUID_FFT_FORWARD, LIQUID_FFT_BACKWARD}
//  _method :   fft method
FFT(plan) FFT(_create_plan_rader)(unsigned int _nfft,
                                  TC *         _x,
                                  TC *         _y,
                                  int          _dir,
                                  int          _flags)
{
    // allocate plan and initialize all internal arrays to NULL
    FFT(plan) q = (FFT(plan)) malloc(sizeof(struct FFT(plan_s)));

    q->nfft      = _nfft;
    q->x         = _x;
    q->y         = _y;
    q->flags     = _flags;
    q->type      = (_dir == LIQUID_FFT_FORWARD) ? LIQUID_FFT_FORWARD : LIQUID_FFT_BACKWARD;
    q->direction = (_dir == LIQUID_FFT_FORWARD) ? LIQUID_FFT_FORWARD : LIQUID_FFT_BACKWARD;
    q->method    = LIQUID_FFT_METHOD_RADER;

    q->execute   = FFT(_execute_rader);

    // allocate memory for sub-transforms
    q->data.rader.x_prime = (TC*)malloc((q->nfft-1)*sizeof(TC));
    q->data.rader.X_prime = (TC*)malloc((q->nfft-1)*sizeof(TC));

    // create sub-FFT of size nfft-1
    q->data.rader.fft = FFT(_create_plan)(q->nfft-1,
                                          q->data.rader.x_prime,
                                          q->data.rader.X_prime,
                                          LIQUID_FFT_FORWARD,
                                          q->flags);

    // create sub-IFFT of size nfft-1
    q->data.rader.ifft = FFT(_create_plan)(q->nfft-1,
                                           q->data.rader.X_prime,
                                           q->data.rader.x_prime,
                                           LIQUID_FFT_BACKWARD,
                                           q->flags);

    // compute primitive root of nfft
    unsigned int g = liquid_primitive_root_prime(q->nfft);

    // create and initialize sequence
    q->data.rader.seq = (unsigned int *)malloc((q->nfft-1)*sizeof(unsigned int));
    unsigned int i;
    for (i=0; i<q->nfft-1; i++)
        q->data.rader.seq[i] = liquid_modpow(g, i+1, q->nfft);
    
    // compute DFT of sequence { exp(-j*2*pi*g^i/nfft }, size: nfft-1
    // NOTE: R[0] = -1, |R[k]| = sqrt(nfft) for k != 0
    // (use newly-created FFT plan of length nfft-1)
    T d = (q->direction == LIQUID_FFT_FORWARD) ? -1.0 : 1.0;
    for (i=0; i<q->nfft-1; i++)
        q->data.rader.x_prime[i] = cexpf(_Complex_I*d*2*M_PI*q->data.rader.seq[i]/(T)(q->nfft));
    FFT(_execute)(q->data.rader.fft);

    // copy result to R
    q->data.rader.R = (TC*)malloc((q->nfft-1)*sizeof(TC));
    memmove(q->data.rader.R, q->data.rader.X_prime, (q->nfft-1)*sizeof(TC));
    
    // return main object
    return q;
}
コード例 #2
0
ファイル: fft_rader2.c プロジェクト: Sangstbk/liquid-dsp
// create FFT plan
//  _nfft   :   FFT size
//  _x      :   input array [size: _nfft x 1]
//  _y      :   output array [size: _nfft x 1]
//  _dir    :   fft direction: {LIQUID_FFT_FORWARD, LIQUID_FFT_BACKWARD}
//  _method :   fft method
FFT(plan) FFT(_create_plan_rader2)(unsigned int _nfft,
                                         TC *         _x,
                                         TC *         _y,
                                         int          _dir,
                                         int          _flags)
{
    // allocate plan and initialize all internal arrays to NULL
    FFT(plan) q = (FFT(plan)) malloc(sizeof(struct FFT(plan_s)));

    q->nfft      = _nfft;
    q->x         = _x;
    q->y         = _y;
    q->flags     = _flags;
    q->type      = (_dir == LIQUID_FFT_FORWARD) ? LIQUID_FFT_FORWARD : LIQUID_FFT_BACKWARD;
    q->direction = (_dir == LIQUID_FFT_FORWARD) ? LIQUID_FFT_FORWARD : LIQUID_FFT_BACKWARD;
    q->method    = LIQUID_FFT_METHOD_RADER2;

    q->execute   = FFT(_execute_rader2);

    unsigned int i;

    // compute primitive root of nfft
    unsigned int g = liquid_primitive_root_prime(q->nfft);

    // create and initialize sequence
    q->data.rader2.seq = (unsigned int *)malloc((q->nfft-1)*sizeof(unsigned int));
    for (i=0; i<q->nfft-1; i++)
        q->data.rader2.seq[i] = liquid_modpow(g, i+1, q->nfft);

#if 0
    // compute larger FFT length greater than 2*nfft-4
    // NOTE: while any length greater than 2*nfft-4 will work, use
    //       nfft_prime as smallest 'simple' FFT (mostly small factors)
    //
    // TODO: devise better score (fewer factors is better)
    //       score(n) = n / sum(factors(n).^2)
    float gamma_max = 0.0f; // score
    unsigned int nfft_prime_opt = 0;
    unsigned int num_steps = 10;// + q->nfft;
    for (i=1; i<=num_steps; i++) {
        unsigned int n_hat = 2*q->nfft - 4 + i;

        // compute factors
        unsigned int k;
        unsigned int num_factors = 0;
        unsigned int m = n_hat;
        float gamma = 0.0f;
        do {
            for (k=2; k<=m; k++) {
                if ( (m % k) == 0) {
                    m /= k;
                    num_factors++;
                    gamma += k*k;
                    break;
                }
            }
        } while (m > 1);

        // compute score:
        //float gamma = (float)n_hat / (float)num_factors;
        //float gamma = 1e3f * (float)num_factors / (float)n_hat;
        gamma = (float)n_hat / gamma;

        if (gamma > gamma_max) {
            gamma_max = gamma;
            nfft_prime_opt = n_hat;
        }
    }
    q->data.rader2.nfft_prime = nfft_prime_opt;
#else
    // compute larger FFT length greater than 2*nfft-4
    // NOTE: while any length greater than 2*nfft-4 will work, use
    //       nfft_prime = 2 ^ nextpow2( 2*nfft - 4 ) to enable
    //       radix-2 transform
    unsigned int m=0;
    q->data.rader2.nfft_prime = (2*q->nfft-4)-1;
    while (q->data.rader2.nfft_prime > 0) {
        q->data.rader2.nfft_prime >>= 1;
        m++;
    }
    q->data.rader2.nfft_prime = 1 << m;
#endif
    //printf("nfft_prime = %u\n", q->data.rader2.nfft_prime);
    // assert(nfft_prime > 2*nfft-4)

    // allocate memory for sub-transforms
    q->data.rader2.x_prime = (TC*)malloc((q->data.rader2.nfft_prime)*sizeof(TC));
    q->data.rader2.X_prime = (TC*)malloc((q->data.rader2.nfft_prime)*sizeof(TC));

    // create sub-FFT of size nfft-1
    q->data.rader2.fft = FFT(_create_plan)(q->data.rader2.nfft_prime,
                                           q->data.rader2.x_prime,
                                           q->data.rader2.X_prime,
                                           LIQUID_FFT_FORWARD,
                                           q->flags);

    // create sub-IFFT of size nfft-1
    q->data.rader2.ifft = FFT(_create_plan)(q->data.rader2.nfft_prime,
                                            q->data.rader2.X_prime,
                                            q->data.rader2.x_prime,
                                            LIQUID_FFT_BACKWARD,
                                            q->flags);

    // compute DFT of sequence { exp(-j*2*pi*g^i/nfft }, size: nfft_prime
    // NOTE: R[0] = -1, |R[k]| = sqrt(nfft) for k != 0
    // (use newly-created FFT plan of length nfft_prime)
    T d = (q->direction == LIQUID_FFT_FORWARD) ? -1.0 : 1.0;
    for (i=0; i<q->data.rader2.nfft_prime; i++)
        q->data.rader2.x_prime[i] = cexpf(_Complex_I*d*2*M_PI*q->data.rader2.seq[i%(q->nfft-1)]/(T)(q->nfft));
    FFT(_execute)(q->data.rader2.fft);
    
    // copy result to R
    q->data.rader2.R = (TC*)malloc(q->data.rader2.nfft_prime*sizeof(TC));
    memmove(q->data.rader2.R, q->data.rader2.X_prime, q->data.rader2.nfft_prime*sizeof(TC));

    // return main object
    return q;
}