文档章节

2的整次幂长度FFT算法的C++实现

张明
 张明
发布于 2010/04/08 08:39
字数 2551
阅读 1899
收藏 0

头文件:

/*
 * Copyright (c) 2008-2011 Zhang Ming (M. Zhang), zmjerry@163.com
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation, either version 2 or any later version.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details. A copy of the GNU General Public License is available at:
 * http://www.fsf.org/licensing/licenses
 */


/*****************************************************************************
 *                                fftmr.h
 *
 * Fast Fourier Transform with Mixed Radix Algorithm
 *
 * This class is designed for calculating discrete Fourier transform and
 * inverse discrete Fourier transform of 1D signals by using Mixed-Radix
 * Algorithms. The length of signals should equal to powers of 2.
 *
 * The algorithm is modified from "kube-gustavson-fft.c". Which is a pretty
 * fast FFT algorithm. Not super-optimized lightning-fast, but very good
 * considering its age and relative simplicity.
 *
 * Zhang Ming, 2010-04, Xi'an Jiaotong University.
 *****************************************************************************/


#ifndef FFTMR_H
#define FFTMR_H


#include <vector.h>


namespace splab
{

    /**
     * complex node converted from "C" version for this algorithm
     */
    template<typename Type>
    struct Complex
    {
        Type re;
        Type im;
    };


    /**
     * two routines frequently used in FFT algorithm
     */
    bool    isPower2( int );
    int     fastLog2( int );


    /**
     * Radix based FFT class
     */
	template<typename Type>
	class FFTMR
	{

	public:

		FFTMR();
		~FFTMR();

        void fft( Vector< complex<Type> > &xn );
        void ifft( Vector< complex<Type> > &Xk );
		void fft( const Vector<Type> &xn, Vector< complex<Type> > &Xk );
        void ifft( const Vector< complex<Type> > &Xk, Vector<Type> &xn );

	private:

        void bitReverse( Vector<int> &bitrev );
		void radix2( int nthpo, Complex<Type> *c0, Complex<Type> *c1 );
		void radix4( int nthpo, Complex<Type> *c0, Complex<Type> *c1,
                           Complex<Type> *c2, Complex<Type> *c3 );
		void radix8( int nxtlt, int nthpo, int length,
                     Complex<Type> *cc0, Complex<Type> *cc1,
                     Complex<Type> *cc2, Complex<Type> *cc3,
                     Complex<Type> *cc4, Complex<Type> *cc5,
                     Complex<Type> *cc6, Complex<Type> *cc7 );
		void dft( int direction, int n, Complex<Type> *b );
	};
	//	class FFTMR


	#include <fftmr-impl.h>

}
// namespace splab


#endif
// FFTMR_H

实现文件:

/*
 * Copyright (c) 2008-2011 Zhang Ming (M. Zhang), zmjerry@163.com
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation, either version 2 or any later version.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details. A copy of the GNU General Public License is available at:
 * http://www.fsf.org/licensing/licenses
 */


/*****************************************************************************
 *                               fftmr-impl.h
 *
 * Implementation for FFTMR class.
 *
 * Zhang Ming, 2010-04, Xi'an Jiaotong University.
 *****************************************************************************/


/**
 * To determine the input integer is or isn't the power of positive
 * integer of 2. If it is, return true, or return false.
 */
bool isPower2( int n )
{
    int bits = 0;
    while( n )
    {
        bits += n & 1;
        n >>= 1;
    }

    return ( bits == 1 );
}


/**
 * Get binary log of integer argument -- exact if n is a power of 2.
 */
int fastLog2( int n )
{
    int log = -1;
    while( n )
    {
        log++;
        n >>= 1;
    }

    return log;
}


/**
 * constructors and destructor
 */
template<typename Type>
FFTMR<Type>::FFTMR()
{
}

template<typename Type>
FFTMR<Type>::~FFTMR()
{
}


/**
 * Generate the bit reversed array.
 */
template<typename Type>
void FFTMR<Type>::bitReverse( Vector<int> &bitrev )
{
    int i, j;
	bitrev[0] = 0;

	for( j=1; j<bitrev.size(); j<<=1 )
		for( i=0; i<j; ++i )
		{
			bitrev[i] <<= 1;
			bitrev[i+j] = bitrev[i]+1;
		}
}


/**
 * Radix-2 iteration subroutine.
 */
template<typename Type>
void FFTMR<Type>::radix2( int nthpo, Complex<Type> *c0, Complex<Type> *c1 )
{
    int     k, kk;
    Type    *cr0, *ci0, *cr1, *ci1, r1, fi1;

    cr0 = &(c0[0].re);
    ci0 = &(c0[0].im);
    cr1 = &(c1[0].re);
    ci1 = &(c1[0].im);

    for( k=0; k<nthpo; k+=2 )
    {
        kk = k*2;

        r1 = cr0[kk] + cr1[kk];
        cr1[kk] = cr0[kk] - cr1[kk];
        cr0[kk] = r1;
        fi1 = ci0[kk] + ci1[kk];
        ci1[kk] = ci0[kk] - ci1[kk];
        ci0[kk] = fi1;
    }
}


/**
 * Radix-4 iteration subroutine.
 */
template<typename Type>
void FFTMR<Type>::radix4( int nthpo, Complex<Type> *c0, Complex<Type> *c1,
                          Complex<Type> *c2, Complex<Type> *c3 )
{
    int     k, kk;
    Type    *cr0, *ci0, *cr1, *ci1, *cr2, *ci2, *cr3, *ci3;
    Type    r1, r2, r3, r4, i1, i2, i3, i4;

    cr0 = &(c0[0].re);
    cr1 = &(c1[0].re);
    cr2 = &(c2[0].re);
    cr3 = &(c3[0].re);
    ci0 = &(c0[0].im);
    ci1 = &(c1[0].im);
    ci2 = &(c2[0].im);
    ci3 = &(c3[0].im);

    for( k=1; k<=nthpo; k+=4 )
    {
        kk = (k-1)*2;

        r1 = cr0[kk] + cr2[kk];
        r2 = cr0[kk] - cr2[kk];
        r3 = cr1[kk] + cr3[kk];
        r4 = cr1[kk] - cr3[kk];
        i1 = ci0[kk] + ci2[kk];
        i2 = ci0[kk] - ci2[kk];
        i3 = ci1[kk] + ci3[kk];
        i4 = ci1[kk] - ci3[kk];
        cr0[kk] = r1 + r3;
        ci0[kk] = i1 + i3;
        cr1[kk] = r1 - r3;
        ci1[kk] = i1 - i3;
        cr2[kk] = r2 - i4;
        ci2[kk] = i2 + r4;
        cr3[kk] = r2 + i4;
        ci3[kk] = i2 - r4;
    }
}


/**
 * Radix-8 iteration subroutine.
 */
template<typename Type>
void FFTMR<Type>::radix8( int nxtlt, int nthpo, int length,
                          Complex<Type> *cc0, Complex<Type> *cc1,
                          Complex<Type> *cc2, Complex<Type> *cc3,
                          Complex<Type> *cc4, Complex<Type> *cc5,
                          Complex<Type> *cc6, Complex<Type> *cc7 )
{
    int     j, k, kk;
    Type    scale, arg, tr, ti;

    Type    c1, c2, c3, c4, c5, c6, c7,
            s1, s2, s3, s4, s5, s6, s7;
    Type    ar0, ar1, ar2, ar3, ar4, ar5, ar6, ar7,
            ai0, ai1, ai2, ai3, ai4, ai5, ai6, ai7;
    Type    br0, br1, br2, br3, br4, br5, br6, br7,
            bi0, bi1, bi2, bi3, bi4, bi5, bi6, bi7;

    Type    *cr0, *cr1, *cr2, *cr3, *cr4, *cr5, *cr6, *cr7;
    Type    *ci0, *ci1, *ci2, *ci3, *ci4, *ci5, *ci6, *ci7;

    cr0 = &(cc0[0].re);
    cr1 = &(cc1[0].re);
    cr2 = &(cc2[0].re);
    cr3 = &(cc3[0].re);
    cr4 = &(cc4[0].re);
    cr5 = &(cc5[0].re);
    cr6 = &(cc6[0].re);
    cr7 = &(cc7[0].re);

    ci0 = &(cc0[0].im);
    ci1 = &(cc1[0].im);
    ci2 = &(cc2[0].im);
    ci3 = &(cc3[0].im);
    ci4 = &(cc4[0].im);
    ci5 = &(cc5[0].im);
    ci6 = &(cc6[0].im);
    ci7 = &(cc7[0].im);

    scale = Type(TWOPI/length);

    for( j=1; j<=nxtlt; j++ )
    {
        arg = (j-1)*scale;
        c1 = cos(arg);
        s1 = sin(arg);
        c2 = c1*c1 - s1*s1;
        s2 = c1*s1 + c1*s1;
        c3 = c1*c2 - s1*s2;
        s3 = c2*s1 + s2*c1;
        c4 = c2*c2 - s2*s2;
        s4 = c2*s2 + c2*s2;
        c5 = c2*c3 - s2*s3;
        s5 = c3*s2 + s3*c2;
        c6 = c3*c3 - s3*s3;
        s6 = c3*s3 + c3*s3;
        c7 = c3*c4 - s3*s4;
        s7 = c4*s3 + s4*c3;

        for( k=j; k<=nthpo; k+=length )
      	{
            kk = (k-1)*2; /* index by twos; re & im alternate */

            ar0 = cr0[kk] + cr4[kk];
            ar1 = cr1[kk] + cr5[kk];
            ar2 = cr2[kk] + cr6[kk];
            ar3 = cr3[kk] + cr7[kk];
            ar4 = cr0[kk] - cr4[kk];
            ar5 = cr1[kk] - cr5[kk];
            ar6 = cr2[kk] - cr6[kk];
            ar7 = cr3[kk] - cr7[kk];
            ai0 = ci0[kk] + ci4[kk];
            ai1 = ci1[kk] + ci5[kk];
            ai2 = ci2[kk] + ci6[kk];
            ai3 = ci3[kk] + ci7[kk];
            ai4 = ci0[kk] - ci4[kk];
            ai5 = ci1[kk] - ci5[kk];
            ai6 = ci2[kk] - ci6[kk];
            ai7 = ci3[kk] - ci7[kk];
            br0 = ar0 + ar2;
            br1 = ar1 + ar3;
            br2 = ar0 - ar2;
            br3 = ar1 - ar3;
            br4 = ar4 - ai6;
            br5 = ar5 - ai7;
            br6 = ar4 + ai6;
            br7 = ar5 + ai7;
            bi0 = ai0 + ai2;
            bi1 = ai1 + ai3;
            bi2 = ai0 - ai2;
            bi3 = ai1 - ai3;
            bi4 = ai4 + ar6;
            bi5 = ai5 + ar7;
            bi6 = ai4 - ar6;
            bi7 = ai5 - ar7;
            cr0[kk] = br0 + br1;
            ci0[kk] = bi0 + bi1;

            if( j > 1 )
      	    {
                cr1[kk] = c4*(br0-br1) - s4*(bi0-bi1);
                cr2[kk] = c2*(br2-bi3) - s2*(bi2+br3);
                cr3[kk] = c6*(br2+bi3) - s6*(bi2-br3);
                ci1[kk] = c4*(bi0-bi1) + s4*(br0-br1);
                ci2[kk] = c2*(bi2+br3) + s2*(br2-bi3);
                ci3[kk] = c6*(bi2-br3) + s6*(br2+bi3);
                tr = Type(IRT2)*(br5-bi5);
                ti = Type(IRT2)*(br5+bi5);
                cr4[kk] = c1*(br4+tr) - s1*(bi4+ti);
                ci4[kk] = c1*(bi4+ti) + s1*(br4+tr);
                cr5[kk] = c5*(br4-tr) - s5*(bi4-ti);
                ci5[kk] = c5*(bi4-ti) + s5*(br4-tr);
                tr = -Type(IRT2)*(br7+bi7);
                ti = Type(IRT2)*(br7-bi7);
                cr6[kk] = c3*(br6+tr) - s3*(bi6+ti);
                ci6[kk] = c3*(bi6+ti) + s3*(br6+tr);
                cr7[kk] = c7*(br6-tr) - s7*(bi6-ti);
                ci7[kk] = c7*(bi6-ti) + s7*(br6-tr);
      	    }
            else
      	    {
                cr1[kk] = br0 - br1;
                cr2[kk] = br2 - bi3;
                cr3[kk] = br2 + bi3;
                ci1[kk] = bi0 - bi1;
                ci2[kk] = bi2 + br3;
                ci3[kk] = bi2 - br3;
                tr = Type(IRT2)*(br5-bi5);
                ti = Type(IRT2)*(br5+bi5);
                cr4[kk] = br4 + tr;
                ci4[kk] = bi4 + ti;
                cr5[kk] = br4 - tr;
                ci5[kk] = bi4 - ti;
                tr = -Type(IRT2)*(br7+bi7);
                ti = Type(IRT2)*(br7-bi7);
                cr6[kk] = br6 + tr;
                ci6[kk] = bi6 + ti;
                cr7[kk] = br6 - tr;
                ci7[kk] = bi6 - ti;
      	    }
      	}
    }
}


/**
 * This routine replaces the input Complex<Type> vector by its
 * finite discrete Fourier transform if direction == FORWARD.
 * It replaces the input Complex<Type> vector by its finite discrete
 * inverse Fourier transform if direction == INVERSE.
 */
template<typename Type>
void FFTMR<Type>::dft( int direction, int n, Complex<Type> *b )
{
    int     i, j;
    int     n2pow, n8pow, nthpo, ipass, nxtlt, length;
    Complex<Type> tmp;

    n2pow = fastLog2(n);
    nthpo = n;

    // Conjugate the input
    if( direction == FORWARD )
        for( i=0; i<n; i++ )
            b[i].im = -b[i].im;

    n8pow = n2pow/3;
    if( n8pow )
    {
        // radix 8 iterations
        for( ipass=1; ipass<=n8pow; ipass++ )
      	{
            nxtlt = 0x1 << ( n2pow - 3*ipass );
            length = 8*nxtlt;
            radix8( nxtlt, nthpo, length,
                    b, b+nxtlt, b+2*nxtlt, b+3*nxtlt,
                    b+4*nxtlt, b+5*nxtlt, b+6*nxtlt, b+7*nxtlt );
      	}
    }

    // A final radix 2 or radix 4 iteration is needed.
    if( n2pow%3 == 1 )
    	radix2( nthpo, b, b+1 );
    if( n2pow%3 == 2 )
        radix4( nthpo, b, b+1, b+2, b+3 );

     // scale outputs
    if( direction == FORWARD )
        for( i=0; i<n; i++ )
            b[i].im *= -1;

    if( direction == INVERSE )
    {
        for( i=0; i<nthpo; i++ )
        {
            b[i].re /= n;
            b[i].im /= n;
        }
    }

    // bit reverse
    Vector<int> bitrev(n);
    bitReverse( bitrev );
	for( i=0; i<n; ++i )
	{
		j = bitrev[i];
		if( i < j )
		{
            tmp = b[i];
            b[i] = b[j];
            b[j] = tmp;
		}
	}
}


/**
 * Forward Transform
 */
template<typename Type>
void FFTMR<Type>::fft( Vector<complex<Type> > &xn )
{
    int nFFT = xn.size();
    if( isPower2(nFFT)  )
        dft( FORWARD, nFFT, reinterpret_cast<Complex<Type>*>(xn.begin()) );
    else
        cerr << "The length of signal must abe power of 2!" ;
}

template<typename Type>
void FFTMR<Type>::fft( const Vector<Type> &xn, Vector< complex<Type> > &Xk )
{
    int nFFT = xn.size();
    if( isPower2(nFFT)  )
    {
        if( Xk.size() != nFFT )
            Xk.resize(nFFT);
        for( int i=0; i<nFFT; ++i )
            Xk[i] = xn[i];

        dft( FORWARD, nFFT, reinterpret_cast<Complex<Type>*>(Xk.begin()) );
    }
    else
        cerr << "The length of signal must abe power of 2!" ;
}


/**
 * Inverse Transform
 */
template<typename Type>
void FFTMR<Type>::ifft( Vector<complex<Type> > &Xk )
{
    int nFFT = Xk.size();
    if( isPower2(nFFT)  )
        dft( INVERSE, nFFT, reinterpret_cast<Complex<Type>*>(Xk.begin()) );
    else
        cerr << "The length of signal must abe power of 2!" ;
}

template<typename Type>
void FFTMR<Type>::ifft( const Vector< complex<Type> > &Xk, Vector<Type> &xn )
{
    int nFFT = Xk.size();
    Vector< complex<Type> > tmp(Xk);
    if( isPower2(nFFT)  )
    {
        dft( INVERSE, nFFT, reinterpret_cast<Complex<Type>*>(tmp.begin()) );

        if( xn.size() != nFFT )
            xn.resize(nFFT);
        for( int i=0; i<nFFT; ++i )
            xn[i] = tmp[i].real();
    }
    else
        cerr << "The length of signal must abe power of 2!" ;
}

测试代码:

/*****************************************************************************
 *                               fftmr_test.cpp
 *
 * Mixed Radix Algorithm FFT testing.
 *
 * Zhang Ming, 2010-04, Xi'an Jiaotong University.
 *****************************************************************************/


#include <iostream>
#include <iomanip>
#include <fftmr.h>


using namespace std;
using namespace splab;


typedef double  Type;
const   int     LENGTH = 32;


int main()
{
    int     i, j, index, rows = LENGTH/4;

    Vector<Type> xn(LENGTH);
    Vector< complex<Type> > yn(LENGTH),
                              Xk(LENGTH);
    FFTMR<Type> Fourier;

    cout << "The original signal is: " << endl;
    for( i=0; i<rows; i++ )
    {
        cout << endl;
        for( j=0; j<3; j++ )
        {
            index = 3*i+j;
            xn[index] = i+j;
            cout << setiosflags(ios::fixed) << setprecision(6);
            cout << "\t" << xn[index];
        }
    }
    cout << endl << endl;

    Fourier.fft( xn, Xk );

    cout << "The Fourier transform of original signal is:" << endl;
    for( i=0; i<rows; i++ )
    {
        cout << endl;
        for( j=0; j<3; j++ )
        {
            index = 3*i+j;
            cout << setiosflags(ios::fixed) << setprecision(6);
            cout << "\t" << Xk[index];
        }
    }
    cout << endl << endl;

    Fourier.ifft( Xk, xn );
    cout << "The inverse Fourier transform is" << endl;
    for( i=0; i<rows; i++ )
    {
        cout << endl;
        for( j=0; j<3; j++ )
        {
            index = 3*i+j;
            cout << setiosflags(ios::fixed) << setprecision(6);
            cout << "\t" << xn[index];
        }
    }
    cout << endl << endl;

    cout << "The original signal is: " << endl;
    for( i=0; i<rows; i++ )
    {
        cout << endl;
        for( j=0; j<3; j++ )
        {
            index = 3*i+j;
            yn[index] = complex<double>(i,j);
            cout << setiosflags(ios::fixed) << setprecision(6);
            cout << "\t" << yn[index];
        }
    }
    cout << endl << endl;

    Fourier.fft( yn );
    cout << "The Fourier transform of original signal is:" << endl;
    for( i=0; i<rows; i++ )
    {
        cout << endl;
        for( j=0; j<3; j++ )
        {
            index = 3*i+j;
            cout << setiosflags(ios::fixed) << setprecision(6);
            cout << "\t" << yn[index];
        }
    }
    cout << endl << endl;

    Fourier.ifft( yn );
    cout << "The inverse Fourier transform is" << endl;
    for( i=0; i<rows; i++ )
    {
        cout << endl;
        for( j=0; j<3; j++ )
        {
            index = 3*i+j;
            cout << setiosflags(ios::fixed) << setprecision(6);
            cout << "\t" << yn[index];
        }
    }

    cout << endl << endl;
    return 0;
}

运行结果:

The original signal is:

        0.000000        1.000000        2.000000
        1.000000        2.000000        3.000000
        2.000000        3.000000        4.000000
        3.000000        4.000000        5.000000
        4.000000        5.000000        6.000000
        5.000000        6.000000        7.000000
        6.000000        7.000000        8.000000
        7.000000        8.000000        9.000000

The Fourier transform of original signal is:

        (108.000000,0.000000)   (-52.827446,1.358153)   (-0.613126,-23.640092)
        (13.310056,1.647944)    (-4.000000,9.656854)    (-8.902567,-4.353284)
        (3.082392,-7.681941)    (5.303682,2.676653)     (-4.000000,4.000000)
        (-5.314558,-4.659704)   (0.917608,-8.368233)    (0.220781,11.701395)
        (-4.000000,1.656854)    (-0.343999,-3.954231)   (4.613126,-0.326383)
        (0.554051,4.364941)     (-4.000000,-0.000000)   (0.554051,-4.364941)
        (4.613126,0.326383)     (-0.343999,3.954231)    (-4.000000,-1.656854)
        (0.220781,-11.701395)   (0.917608,8.368233)     (-5.314558,4.659704)

The inverse Fourier transform is

        0.000000        1.000000        2.000000
        1.000000        2.000000        3.000000
        2.000000        3.000000        4.000000
        3.000000        4.000000        5.000000
        4.000000        5.000000        6.000000
        5.000000        6.000000        7.000000
        6.000000        7.000000        8.000000
        7.000000        8.000000        9.000000

The original signal is:

        (0.000000,0.000000)     (0.000000,1.000000)     (0.000000,2.000000)
        (1.000000,0.000000)     (1.000000,1.000000)     (1.000000,2.000000)
        (2.000000,0.000000)     (2.000000,1.000000)     (2.000000,2.000000)
        (3.000000,0.000000)     (3.000000,1.000000)     (3.000000,2.000000)
        (4.000000,0.000000)     (4.000000,1.000000)     (4.000000,2.000000)
        (5.000000,0.000000)     (5.000000,1.000000)     (5.000000,2.000000)
        (6.000000,0.000000)     (6.000000,1.000000)     (6.000000,2.000000)
        (7.000000,0.000000)     (7.000000,1.000000)     (7.000000,2.000000)

The Fourier transform of original signal is:

        (84.000000,24.000000)   (-42.542528,1.020494)   (5.034128,-18.695144)
        (13.685581,5.361763)    (-4.000000,9.656854)    (-6.244002,-4.826961)
        (6.192124,-5.705118)    (6.023013,5.306175)     (-4.000000,4.000000)
        (-1.277237,-6.299534)   (13.722858,-4.086928)   (-8.776842,-2.726593)
        (-4.000000,1.656854)    (-1.716734,-2.445797)   (2.729646,0.149298)
        (-0.485914,4.057658)    (-4.000000,-0.000000)   (0.861334,-3.324976)
        (4.137445,2.209863)     (-1.852433,5.326967)    (-4.000000,-1.656854)
        (14.648770,-2.703773)   (-3.363697,-4.437017)   (-3.674728,0.622383)

The inverse Fourier transform is

        (-0.000000,0.000000)    (0.000000,1.000000)     (0.000000,2.000000)
        (1.000000,-0.000000)    (1.000000,1.000000)     (1.000000,2.000000)
        (2.000000,0.000000)     (2.000000,1.000000)     (2.000000,2.000000)
        (3.000000,-0.000000)    (3.000000,1.000000)     (3.000000,2.000000)
        (4.000000,-0.000000)    (4.000000,1.000000)     (4.000000,2.000000)
        (5.000000,-0.000000)    (5.000000,1.000000)     (5.000000,2.000000)
        (6.000000,-0.000000)    (6.000000,1.000000)     (6.000000,2.000000)
        (7.000000,0.000000)     (7.000000,1.000000)     (7.000000,2.000000)


Process returned 0 (0x0)   execution time : 0.109 s
Press any key to continue.

© 著作权归作者所有

张明
粉丝 320
博文 78
码字总数 135696
作品 0
西安
私信 提问
加载中

评论(6)

d
drawha
您好,这里面有个常量“IRT2”是什么?
j
jackcin
比对了许久,和这两种所述的都不一样啊,这到底事什么啊
j
jackcin
这是DIT-FFT还是DIF-FFT
liushigang
liushigang

引用来自“celery”的评论

你的计算结果有问题吧,实数序列的FFT是中心共轭对称的,你的结果貌似不对称啊

没有问题,你没有看清他是怎么计算的,原始数据量只有24个,而他的算法需要32个,后面应该是补零计算的
c
celery
你的计算结果有问题吧,实数序列的FFT是中心共轭对称的,你的结果貌似不对称啊
王刘旺
你好,我按照你的说明文件的例子在VC++6.0上编译时,出现诸如
d:\program files\sp++3.0\include\usingdeclare.h(53) : error C2039: 'min' : is not a member of 'std'
这类的错误,是怎么回事啊?
SP++3.0 发布,欢迎大家使用

消息来自 Jerry 的博客: SP++ (Signal Processing in C++) 是一个关于信号处理与数值计算的开源C++程序库,该库提供了信号处理与数值计算中常用算法的C++实现。SP++中所有算法都以C++类模板...

红薯
2011/02/12
5.3K
4
SP++3.0已发布,欢迎大家使用(同心协力,共创开源)

SP++ (Signal Processing in C++) 是一个关于信号处理与数值计算的开源C++程序库,该库提供了信号处理与数值计算中常用算法的C++实现。SP++中所有算法都以C++类模板方法实现,以头文件形式组...

张明
2011/02/12
11.5K
56
【广州】我想应聘一个C/C++/java软件开发职位

本人预计六月底七月初将去广州生活。希望在广州找到一份c/c++/java方面的软件开发职位。 以下 是我的简历,希望广州地区的it企业可以联系我。 周西的个人简历 姓  名: 周西 性  别: 男...

numcpp
2012/06/07
530
1
C语言/C++程序设计编程基础学习—经典算法

C语言是面向过程的,而C++是面向对象的 C和C++的区别: C是一个结构化语言,它的重点在于算法和数据结构。C程序的设计首要考虑的是如何通过一个过程,对输入(或环境条件)进行运算处理得到...

小辰带你看世界
2018/03/24
0
0
mina服务端和C++客户端的通信问题?

有没有大侠在项目中用到过mina服务端和C++客户端的数据包传输,协议数据包格式包括包头和数据,包头中有几个属性信息,比如包头标示、协议类型、数据类型、数据长度,数据信息是用到protoco...

多乐乐
2011/05/08
3.3K
7

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周六乱弹 —— 早上儿子问我他是怎么来的

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @凉小生 :#今日歌曲推荐# 少点戾气,愿你和这个世界温柔以待。中岛美嘉的单曲《僕が死のうと思ったのは (曾经我也想过一了百了)》 《僕が死の...

小小编辑
今天
2.4K
15
Excption与Error包结构,OOM 你遇到过哪些情况,SOF 你遇到过哪些情况

Throwable 是 Java 中所有错误与异常的超类,Throwable 包含两个子类,Error 与 Exception 。用于指示发生了异常情况。 Java 抛出的 Throwable 可以分成三种类型。 被检查异常(checked Exc...

Garphy
今天
41
0
计算机实现原理专题--二进制减法器(二)

在计算机实现原理专题--二进制减法器(一)中说明了基本原理,现准备说明如何来实现。 首先第一步255-b运算相当于对b进行按位取反,因此可将8个非门组成如下图的形式: 由于每次做减法时,我...

FAT_mt
昨天
40
0
好程序员大数据学习路线分享函数+map映射+元祖

好程序员大数据学习路线分享函数+map映射+元祖,大数据各个平台上的语言实现 hadoop 由java实现,2003年至今,三大块:数据处理,数据存储,数据计算 存储: hbase --> 数据成表 处理: hive --> 数...

好程序员官方
昨天
61
0
tabel 中含有复选框的列 数据理解

1、el-ui中实现某一列为复选框 实现多选非常简单: 手动添加一个el-table-column,设type属性为selction即可; 2、@selection-change事件:选项发生勾选状态变化时触发该事件 <el-table @sel...

everthing
昨天
21
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部