有人可以用更好的逻辑编写这段代码吗?

时间:2011-09-29 16:49:40

标签: c++ algorithm dft

我坚持这个问题2天了。有人能用这个逻辑来帮助我吗?

我正在研究C ++程序以获得良好的算法。我现在正在研究Danielson-Lanczos算法来计算序列的FFT。

看着

mmax=2;
while (n>mmax) {
    istep = mmax<<1;
    theta = -(2*M_PI/mmax);
    wtemp = sin(0.5*theta);
    wpr = -2.0*wtemp*wtemp;
    wpi = sin(theta);
    wr = 1.0;
    wi = 0.0;

    for (m=1; m < mmax; m += 2) {
        for (i=m; i <= n; i += istep) {
            j=i+mmax;
            tempr = wr*data[j-1] - wi*data[j];
            tempi = wr * data[j] + wi*data[j-1];

            data[j-1] = data[i-1] - tempr;
            data[j] = data[i] - tempi;
            data[i-1] += tempr;
            data[i] += tempi;
        }
        wtemp=wr;
        wr += wr*wpr - wi*wpi;
        wi += wi*wpr + wtemp*wpi;
    }
    mmax=istep;
}

来源:http://www.eetimes.com/design/signal-processing-dsp/4017495/A-Simple-and-Efficient-FFT-Implementation-in-C--Part-I

有没有办法逻辑地编写代码,使整个for-loop部分减少到只有4行代码(甚至更好)?

4 个答案:

答案 0 :(得分:8)

更好的缩进会有很长的路要走。我为你解决了这个问题。而且,这似乎要求更好的变量局部性。我不清楚变量名,但这可能是因为我不知道这个算法所属的域。

通常,如果您想使复杂代码更容易理解,请确定子算法并将它们放入自己的(内联)函数中。 (将代码片段有效地放入函数中会给它起一个名称,并使变量进出代码变得更加明显。通常,这会使代码更容易消化。)
不过,我不确定这段代码是否必要。

然而,仅仅凝聚代码不会使其更具可读性。相反,它只会使它更加浓缩。

答案 1 :(得分:5)

压缩您的代码。请?好吗?樱桃顶上?

除非你能创建一个更好的算法,否则压缩现有的代码片段只会使它看起来像是直接来自地狱之门的东西。没有人能够理解它。 甚至几天后也无法理解它。

即使是编译器也可能会被所有分支混淆,无法正确优化它。

如果您正在尝试提高性能,请考虑以下事项:

  1. 过早优化是所有邪恶的源头。

  2. 首先处理算法,然后处理代码。

  3. 行数可能与生成的可执行代码的大小完全无关。

  4. 编译器不喜欢纠缠的代码路径和复杂的表达式。真的...

  5. 除非代码确实性能至关重要,否则可读性胜过所有其他。

  6. 如果 性能至关重要,请首先进行配置,然后开始优化。

答案 2 :(得分:4)

您可以使用复数类来反映所涉及的数学。

代码的很大一部分由两个复数乘法组成。

您可以将代码重写为:

unsigned long mmax=2;
while (n>mmax)
{
    unsigned long istep = mmax<<1;
    const complex wp = coef( mmax );
    complex w( 1. , 0. );
    for (unsigned long m=1; m < mmax; m += 2)
    {
        for (unsigned long i=m; i <= n; i += istep)
        {
            j=i+mmax;
            complex temp = w * complex( data[j-1] , data[j] );
            complexref( data[j-1] , data[j] ) = complex( data[i-1] , data[i] ) - temp ;
            complexref( data[i-1] , data[i] ) += temp ;
        }
        w += w * wp ;
    }
    mmax=istep;
}

使用:

struct complex
{
    double r , i ;
    complex( double r , double i ) : r( r ) , i( i ) {}

    inline complex & operator+=( complex const& ref )
    {
        r += ref.r ;
        i += ref.i ;
        return *this ;
    }
};

struct complexref
{
    double & r , & i ;
    complexref( double & r , double & i ) : r( r ) , i( i ) {}

    inline complexref & operator=( complex const& ref )
    {
        r = ref.r ;
        i = ref.i ;
        return *this ;
    }

    inline complexref & operator+=( complex const& ref )
    {
        r += ref.r ;
        i += ref.i ;
        return *this ;
    }
}    ;

inline complex operator*( complex const& w , complex const& b )
{
    return complex(
        w.r * b.r - w.i * b.i ,
        w.r * b.i + w.i * b.r
    );
}

inline complex operator-( complex const& w , complex const& b )
{
    return complex( w.r - b.r , w.i - b.i );
}
inline complex coef( unsigned long mmax )
{
    double theta = -(2*M_PI/mmax);
    double wtemp = sin(0.5*theta);
    return complex( -2.0*wtemp*wtemp , sin(theta) );
}

答案 3 :(得分:2)

  1. 我不相信你能够缩短它。
  2. 如果这段代码变得更短,我猜它会大大降低可读性。
  3. 由于逻辑相对清晰,行数并不重要 - 除非您计划在codegolf.stackexchange.com上使用它,否则您应该信任编译器来帮助您(因为它会)
  4. 这让我觉得过早优化。