您应该将沃尔什代码的生成视为递归问题。首先你生成 2x2;从中生成 4x4 等。每次,下一个块都是通过在右上角和左下角添加两个低阶块的副本,在右下角添加两个副本,从前一个块生成下一个块象限。您可以通过创建一次矩阵并通过增加块大小来完成此操作。这是它的工作原理
已更新,因此它会生成您在 wiki 上看到的代码的 1 -1 版本;
再次更新使其能够接受矩阵大小的输入并生成任意大小的沃尔什矩阵;包括各种错误检查和其他很酷的技巧:
FINAL(?) UPDATE Ryyker 指出我的代码中存在内存错误。我找到并修复了它 - 并使用valgrind 进行检查以确保。它现在似乎工作正常。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int **twoDmatrix(int m, int n) {
// create a 2D matrix of arbitrary dimensions
int ii, **M;
M = malloc(m * sizeof(int**));
M[0] = malloc(m*n*sizeof(int*));
for(ii=1; ii<m; ii++) {
M[ii] = M[0] + ii * n;
}
return M;
}
void free2D(int** M) {
// free memory allocated by twoDmatrix()
free(M[0]);
free(M);
}
int isPow2(int n) {
// return 1 if the argument is a valid (positive) power of 2
if(n<=1) return 0;
while(n>1) {
if (n%2==1) return 0;
n = n/2;
}
return 1;
}
void emptyBuf(void) {
while(getchar()!='\n');
return;
}
int main(void) {
int **W;
int N;
int power = 1;
int i,j,k,l,p=0;
while(1==1) {
printf("enter the size of the matrix - must be a positive power of 2\n");
if(scanf("%d", &N)!=1) {
printf("unable to scan input\n");
emptyBuf();
continue;
}
if (!isPow2(N)) {
printf("%d is not a valid power of 2\n", N);
continue;
}
break; // valid input: go on
}
W = twoDmatrix(N,N); // allocate memory for 2D matrix
W[0][0]=1; // this is the 1x1 Walsh code...
while (power < N) {
for(i=0; i<2; i++) {
for(j=0; j<2; j++) {
if (!(i==0 && j==0)) {
for(k=0; k<power; k++) {
for(l=0; l<power; l++) {
if (i==1 && j == 1) {
W[i*power+k][j*power+l] = -W[k][l]; // invert signal
}
else {
W[i*power+k][j*power+l] = W[k][l]; // copy signal
}
}
}
}
}
}
power *=2; // double matrix and repeat
}
// print out result
for(i=0; i<N; i++) {
for(j=0; j<N; j++) {
printf("%2d ", W[i][j]); // <<<<< updated
}
printf("\n");
}
free2D(W); // always remember to free your memory...
}
输出:
enter the size of the matrix - must be a positive power of 2
5
5 is not a valid power of 2
enter the size of the matrix - must be a positive power of 2
3
3 is not a valid power of 2
enter the size of the matrix - must be a positive power of 2
0
0 is not a valid power of 2
enter the size of the matrix - must be a positive power of 2
-4
-4 is not a valid power of 2
enter the size of the matrix - must be a positive power of 2
asdf
unable to scan input
enter the size of the matrix - must be a positive power of 2
asdfasdfasdfasdf
unable to scan input
enter the size of the matrix - must be a positive power of 2
16
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1
1 1 -1 -1 1 1 -1 -1 1 1 -1 -1 1 1 -1 -1
1 -1 -1 1 1 -1 -1 1 1 -1 -1 1 1 -1 -1 1
1 1 1 1 -1 -1 -1 -1 1 1 1 1 -1 -1 -1 -1
1 -1 1 -1 -1 1 -1 1 1 -1 1 -1 -1 1 -1 1
1 1 -1 -1 -1 -1 1 1 1 1 -1 -1 -1 -1 1 1
1 -1 -1 1 -1 1 1 -1 1 -1 -1 1 -1 1 1 -1
1 1 1 1 1 1 1 1 -1 -1 -1 -1 -1 -1 -1 -1
1 -1 1 -1 1 -1 1 -1 -1 1 -1 1 -1 1 -1 1
1 1 -1 -1 1 1 -1 -1 -1 -1 1 1 -1 -1 1 1
1 -1 -1 1 1 -1 -1 1 -1 1 1 -1 -1 1 1 -1
1 1 1 1 -1 -1 -1 -1 -1 -1 -1 -1 1 1 1 1
1 -1 1 -1 -1 1 -1 1 -1 1 -1 1 1 -1 1 -1
1 1 -1 -1 -1 -1 1 1 -1 -1 1 1 1 1 -1 -1
1 -1 -1 1 -1 1 1 -1 -1 1 1 -1 1 -1 -1 1
参考http://my.fit.edu/~kostanic/Personal%20Communication%20Systems/ECE%205221%20-%20Lecture14.pptx - 我从中获取了以下内容:
后记
关于twoDmatrix() 函数的注释。我写了这个函数,因为在 C 中没有直接的方法来分配一个未知大小的二维矩阵。所以这个函数创建了一个指向int 的指针数组——矩阵中的每一行都有一个指针;它还分配一块内存 - 为数组中的每个元素分配一块内存。然后它将一个指针与矩阵中每一行的开头相关联,以便您可以使用通常的W[i][j] 索引来访问元素。这使得数组的第一行看起来很长(它指向整个 NxN 块),第二行有点短,等等。但这只是一个技巧,因此您可以使用常用语法。想象一下,您有一个 3x3 数组,其中填充了数字 0 到 8 - 然后看起来像这样:
pointer values
W[0] 0 1 2
W[1] 3 4 5
W[2] 6 7 8
但另一种看待它的方式是:
0 1 2 3 4 5 6 7 8
^ W[0]
^W[1]
^W[2]
这意味着您可以访问元素W[0][6] - 它的值将与W[1][3] 相同,而W[2][0] 又与W[2][0] 相同。
当你不再需要这个函数时,你必须释放两个内存块——首先是数据块,然后是指针块。这就是free2D()函数的作用。