【问题标题】:Fast Sequency-ordered Walsh-Hadamard Transform快速序列有序 Walsh-Hadamard 变换
【发布时间】:2014-05-09 03:09:32
【问题描述】:

编辑你可以在 Github 上查看我的实现:https://github.com/Sheljohn/WalshHadamard


我正在寻找sequency-ordered快速 Walsh Hadamard 变换的实现或有关如何实现的指示(请参阅 thisthis)。

我稍微改编了一个很好的实现 online:

// (a,b) -> (a+b,a-b) without overflow
void rotate( long& a, long& b )
{
    static long t;
    t = a;
    a = a + b;
    b = t - b;
}

// Integer log2
long ilog2( long x )
{
    long l2 = 0;
    for (; x; x >>=1) ++l2;
    return l2;
}

/**
 * Fast Walsh-Hadamard transform
 */
void fwht( std::vector<long>& data )
{
    const long l2 = ilog2(data.size()) - 1;

    for (long i = 0; i < l2; ++i)
    {
        for (long j = 0; j < (1 << l2); j += 1 << (i+1))
        for (long k = 0; k < (1 << i ); ++k)
            rotate( data[j + k], data[j + k + (1<<i)] );
    }
}

但它不按顺序计算 WHT(隐式使用自然 Hadamard 矩阵)。请注意,在上面的代码中(如果您尝试的话),数据的大小需要是 2 的幂。

我的问题是:这个实现是否有一个简单的调整来提供按顺序排列的 FWHT?

一个可能的解决方案是编写一个小函数来动态计算 Hn 的元素(n 阶 Hadamard 矩阵),计算零交叉的数量,并创建行的排名,但我想知道是否存在是一种更聪明的方式。提前感谢您的任何意见!干杯

【问题讨论】:

    标签: c++ c signal-processing


    【解决方案1】:

    here 所示(从your reference 内部链接):

    Walsh 矩阵的行的顺序可以从 Hadamard 矩阵的顺序中推导出来,方法是先应用位反转置换,然后应用格雷码置换。

    位反转算法有多种实现方式,例如:

    // Bit-reversal
    // adapted from http://www.idi.ntnu.no/~elster/pubs/elster-bit-rev-1989.pdf
    void bitrev(int t, std::vector<long>& c)
    {
      long n = 1<<t;
      long L = 1;
      c[0]  = 0;
      for (int q=0; q<t; ++q)
      {
        n /= 2;
        for (long j=0; j<L; ++j)
        {
          c[L+j] = c[j] + n;
        }
        L *= 2;
      }
    }
    

    格雷码可从here获取:

    /*
        The purpose of this function is to convert an unsigned
        binary number to reflected binary Gray code.
    
        The operator >> is shift right. The operator ^ is exclusive or.
    */
    unsigned int binaryToGray(unsigned int num)
    {
        return (num >> 1) ^ num;
    }
    

    这些可以结合起来产生最终的排列:

    // Compute a permutation of size 2^order 
    // to reorder the Fast Walsh-Hadamard transform's output 
    // into the Walsh-ordered (sequency-ordered)
    void sequency_permutation(long order, std::vector<long>& p)
    {
      long n = 1<<order;
    
      std::vector<long> tmp(n);
      bitrev(order, tmp);
      p.resize(n);
      for (long i=0; i<n; ++i)
      {
        p[i] = tmp[binaryToGray(i)];
      }
    }
    

    剩下要做的就是将置换应用到正常的 Walsh-Hadamard 变换输出。

    void permuted_fwht(std::vector<long>& data, const std::vector<long>& permutation)
    {
      std::vector<long> tmp = data;
      fwht(tmp);
    
      for (long i=0; i<data.size(); ++i)
      {
        data[i] = tmp[permutation[i]];
      }
    }
    

    请注意,对于给定的数据大小,排列是固定的,因此只需计算一次(假设您正在处理多个数据块)。所以,把它们放在一起,你会得到这样的东西:

      std::vector<long> p;
    
      const long order = ilog2(data_block_size) - 1;
      sequency_permutation(order, p);
    
      permuted_fwht( data_block_1, p);
      permuted_fwht( data_block_2, p);
      //...
    

    【讨论】:

    • 谢谢 :) 我现在正在工作,但我一定会在我在家的时候给你发帖!期待对此进行测试!
    猜你喜欢
    • 1970-01-01
    • 2014-05-08
    • 2014-08-29
    • 1970-01-01
    • 2020-10-18
    • 2021-07-14
    • 2015-04-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多