zoukankan      html  css  js  c++  java
  • 快速相关

    一、功能

    用快速傅里叶变换计算两个有限长序列的线性相关。

    二、方法简介

    设序列(x(n))的长度为(M),序列(y(n))的长度为(N),序列(x(n))(y(n))的互相关定义为

    [z(n)=sum_{i=0}^{M-1}x(i)y(n+i), n=-(M-1),...,N-1 ]

    序列(x(n))的自相关定义为

    [z(n)=sum_{i=0}^{M-1}x(i)x(n+i), n=-(M-1),...,N-1 ]

    显然,如果(M=N)并且序列(x(n))(y(n))相同,那么互相关就变成了自相关。

    用快速傅里叶变换计算线性相关的算法如下:

    1、选择(L)满足下述条件

    [left{egin{matrix}egin{align*}L &geqslant M + N - 1\ L &= 2^{gamma }, gamma is positive integerend{align*}end{matrix} ight. ]

    2、将序列(x(n))(y(n))按如下方式补零,形成长度为(L=2^{gamma })的序列

    [ar{x}(n)=left{egin{matrix}egin{align*}x(n) & , n=0,1,...,M-1\ 0 & , n=0,1,...,M,M+1,...,L-1end{align*}end{matrix} ight. ]

    [ar{y}(n)=left{egin{matrix}egin{align*}0 & , n = 0,1,...,M-2\ y(n) & , n = M-1, M,...,M+N-2\ 0 & , n = M+N-1, M+N,...,L-1end{align*}end{matrix} ight. ]

    3、用FFT算法分别计算序列(ar{x}(n))(ar{y}(n))的离散傅里叶变换(X(k))(Y(k))

    [X(k)=sum_{n=0}^{L-1}ar{x}(n)e^{-j2pi nk/L} ]

    [Y(k)=sum_{n=0}^{L-1}ar{y}(n)e^{-j2pi nk/L} ]

    4、计算(X(k))(Y(k))的乘积

    [Z(k)=X^*(k)Y(K) ]

    其中(*)表示复共轭;

    5、用FFT算法计算(Z(k))的离散傅里叶反变换,得到线性相关(z(n))

    [z(n)=frac{1}{N}sum_{k=0}^{L-1}Z(k)e^{j2pi nk/L}, n=0,1,...,L-1 ]

    序列(z(n))的前(M+N-1)点的值就是序列(x(n))(y(n))的线性相关。

    三、使用说明

    快速卷积的C语言实现方式如下

    /************************************
    	x 			----双精度实型一维数组,长度为m。开始时存放实序列x(i),最后存放线性相关的值。
    	y 			----双精度实型一维数组,长度为n。开始时存放实序列y(i)。
    	m 			----整型变量。序列x(i)的长度。
    	n 			----整型变量。序列y(i)的长度。
    	len			----整型变量。len>=m+n-1,且必须是2的整数次幂,即len=2^gamma
    ************************************/
    #include "stdlib.h"
    #include "rfft.c"
    #include "irfft.c"
    void correl(double *x, double *y, int m, int n, int len)
    {
    	int i, len2;
    	double t, *z;
    	z = mlloc(len * sizeof(double));
    	for(i = m; i < len; i++)
    		x[i] = 0.0;
    	for(i = 0; i < (m - 1); i++)
    		z[i] = 0.0;
    	for(i = (m - 1); i <= (m + n - 2); i++)
    		z[i] = y[i - m + 1];
    	for(i = (m + n - 1); i < len; i++)
    		z[i] = 0.0;
    	rfft(x, len);
    	rfft(z, len);
    	len2 = len / 2;
    	x[0] = x[0] * z[0];
    	x[len2] = x[len2] * z[len2];
    	for(i = 1; i < len2; i++){
    		t = x[i] * z[i] + x[len - i] * z[len - i];
    		x[len - 1] = x[i] * z[len - i] - x[len - i] * z[i];
    		x[i] = t;
    	}
    	irfft(x, len);
    	free(z);
    }
    

    其中rfft.c文件请参考实序列快速傅里叶变换(一)

    irfft.c在rfft.c的基础上添加系数长度的倒数。

  • 相关阅读:
    前端经典书籍
    D3基本概念
    Array.map和parseInt的用法
    首屏和白屏时间计算
    css换肤总结
    文件上传总结
    js的uuid
    html5 drag事件用法
    shell脚本中的逻辑判断 文件目录属性判断 if特殊用法 case判断
    Mac vim“装逼”配置
  • 原文地址:https://www.cnblogs.com/liam-ji/p/12057279.html
Copyright © 2011-2022 走看看