Add fftshift ,fft with size ,and their test.
This commit is contained in:
@@ -578,23 +578,34 @@ Matrix Aurora::median(const Matrix &aMatrix) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Matrix Aurora::fft(const Matrix &aMatrix) {
|
Matrix Aurora::fft(const Matrix &aMatrix, long aFFTSize) {
|
||||||
double *output = nullptr;
|
double *output = nullptr;
|
||||||
mkl_free_buffers();
|
mkl_free_buffers();
|
||||||
output = malloc(aMatrix.getDataSize(), true);
|
MKL_LONG rowSize = (aFFTSize>0)?aFFTSize:aMatrix.getDimSize(0);
|
||||||
|
//实际需要copy赋值的非0值
|
||||||
|
MKL_LONG needCopySize = (rowSize<aMatrix.getDimSize(0))?rowSize:aMatrix.getDimSize(0);
|
||||||
|
MKL_LONG bufferSize = rowSize*aMatrix.getDimSize(1);
|
||||||
|
output = malloc(bufferSize, true);
|
||||||
|
double zero = 0.0;
|
||||||
|
//先全部置为0
|
||||||
|
cblas_dcopy(bufferSize*2, &zero, 0, output, 1);
|
||||||
if (!aMatrix.isComplex()) {
|
if (!aMatrix.isComplex()) {
|
||||||
cblas_dcopy(aMatrix.getDataSize(), aMatrix.getData(), 1, output, 2);
|
//按列copy原值
|
||||||
double zero = 0.0;
|
for (int i = 0 ; i < aMatrix.getDimSize(1); ++i) {
|
||||||
cblas_dcopy(aMatrix.getDataSize(), &zero, 0, output+1, 2);
|
cblas_dcopy(needCopySize, aMatrix.getData()+i*aMatrix.getDimSize(0), 1, output+i*rowSize*2, 2);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
cblas_zcopy(aMatrix.getDataSize(), aMatrix.getData(), 1, output, 1);
|
//按列copy原值
|
||||||
|
for (int i = 0 ; i < aMatrix.getDimSize(1); ++i) {
|
||||||
|
cblas_zcopy(needCopySize, aMatrix.getData()+i*aMatrix.getDimSize(0)*2, 1, output+i*rowSize*2, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DFTI_DESCRIPTOR_HANDLE my_desc_handle = NULL;
|
DFTI_DESCRIPTOR_HANDLE my_desc_handle = NULL;
|
||||||
MKL_LONG status;
|
MKL_LONG status;
|
||||||
|
|
||||||
//创建 Descriptor, 精度 double , 输入类型实数, 维度1
|
//创建 Descriptor, 精度 double , 输入类型实数, 维度1
|
||||||
status = DftiCreateDescriptor(&my_desc_handle, DFTI_DOUBLE, DFTI_COMPLEX, 1, aMatrix.getDimSize(0));
|
status = DftiCreateDescriptor(&my_desc_handle, DFTI_DOUBLE, DFTI_COMPLEX, 1, rowSize);
|
||||||
if (status != DFTI_NO_ERROR) goto error;
|
if (status != DFTI_NO_ERROR) goto error;
|
||||||
|
|
||||||
//通过 setValue 配置Descriptor
|
//通过 setValue 配置Descriptor
|
||||||
@@ -603,11 +614,11 @@ Matrix Aurora::fft(const Matrix &aMatrix) {
|
|||||||
if (status != DFTI_NO_ERROR) goto error;
|
if (status != DFTI_NO_ERROR) goto error;
|
||||||
|
|
||||||
//每个傅里叶变换的输入距离
|
//每个傅里叶变换的输入距离
|
||||||
status = DftiSetValue(my_desc_handle,DFTI_INPUT_DISTANCE,aMatrix.getDimSize(0));
|
status = DftiSetValue(my_desc_handle,DFTI_INPUT_DISTANCE,rowSize);
|
||||||
if (status != DFTI_NO_ERROR) goto error;
|
if (status != DFTI_NO_ERROR) goto error;
|
||||||
|
|
||||||
//每个傅里叶变换的输出距离
|
//每个傅里叶变换的输出距离
|
||||||
status = DftiSetValue(my_desc_handle,DFTI_OUTPUT_DISTANCE,aMatrix.getDimSize(0));
|
status = DftiSetValue(my_desc_handle,DFTI_OUTPUT_DISTANCE,rowSize);
|
||||||
if (status != DFTI_NO_ERROR) goto error;
|
if (status != DFTI_NO_ERROR) goto error;
|
||||||
|
|
||||||
//傅里叶变换的数量
|
//傅里叶变换的数量
|
||||||
@@ -626,7 +637,7 @@ Matrix Aurora::fft(const Matrix &aMatrix) {
|
|||||||
status = DftiFreeDescriptor(&my_desc_handle);
|
status = DftiFreeDescriptor(&my_desc_handle);
|
||||||
if (status != DFTI_NO_ERROR) goto error;
|
if (status != DFTI_NO_ERROR) goto error;
|
||||||
mkl_free_buffers();
|
mkl_free_buffers();
|
||||||
return Matrix::New(output, aMatrix.getDimSize(0), aMatrix.getDimSize(1), aMatrix.getDimSize(2), Complex);
|
return Matrix::New(output, rowSize, aMatrix.getDimSize(1), aMatrix.getDimSize(2), Complex);
|
||||||
error:
|
error:
|
||||||
std::cerr<<"FFT fail, error message:"<<DftiErrorMessage(status)<<std::endl;
|
std::cerr<<"FFT fail, error message:"<<DftiErrorMessage(status)<<std::endl;
|
||||||
return Matrix();
|
return Matrix();
|
||||||
@@ -710,6 +721,19 @@ Matrix Aurora::ifft_symmetric(const Matrix &aMatrix,long length)
|
|||||||
return real(ifft(Matrix::New(calcData,length,1,1,Complex)));
|
return real(ifft(Matrix::New(calcData,length,1,1,Complex)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Aurora::fftshift(Matrix &aMatrix){
|
||||||
|
int backwardLength = aMatrix.getDimSize(0)/2;
|
||||||
|
int forwardLength = aMatrix.getDimSize(0) - backwardLength;
|
||||||
|
double* buffer = malloc(forwardLength,true);
|
||||||
|
for (int i = 0; i<aMatrix.getDimSize(1); ++i) {
|
||||||
|
double* dataPtr = aMatrix.getData()+aMatrix.getDimSize(0)*i*2;
|
||||||
|
cblas_dcopy(forwardLength*2, dataPtr+backwardLength*2, 1, buffer, 1);
|
||||||
|
cblas_dcopy(backwardLength*2, dataPtr, 1, dataPtr+forwardLength*2, 1);
|
||||||
|
cblas_dcopy(forwardLength*2, buffer, 1, dataPtr, 1);
|
||||||
|
}
|
||||||
|
Aurora::free(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
Matrix Aurora::hilbert(const Matrix &aMatrix) {
|
Matrix Aurora::hilbert(const Matrix &aMatrix) {
|
||||||
auto x = fft(aMatrix);
|
auto x = fft(aMatrix);
|
||||||
auto h = malloc(aMatrix.getDimSize(0));
|
auto h = malloc(aMatrix.getDimSize(0));
|
||||||
|
|||||||
@@ -103,9 +103,16 @@ namespace Aurora
|
|||||||
/**
|
/**
|
||||||
* FFT,支持到2维,输入可以是常数可以是复数,输出必是复数
|
* FFT,支持到2维,输入可以是常数可以是复数,输出必是复数
|
||||||
* @param aMatrix 目标矩阵
|
* @param aMatrix 目标矩阵
|
||||||
|
* @param aFFTSize 目标矩阵需要处理的长度,默认为-1即全部
|
||||||
* @return fft后的复数矩阵
|
* @return fft后的复数矩阵
|
||||||
*/
|
*/
|
||||||
Matrix fft(const Matrix &aMatrix);
|
Matrix fft(const Matrix &aMatrix, long aFFTSize = -1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fftshift,在原有数据上进行修改,将fft的数据的前半部分和后半部分交换,支持2D数据
|
||||||
|
* @param aMatrix
|
||||||
|
*/
|
||||||
|
void fftshift(Matrix &aMatrix);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 逆fft,支持到2维,输入必须是复数,输出必是复数
|
* 逆fft,支持到2维,输入必须是复数,输出必是复数
|
||||||
|
|||||||
@@ -334,8 +334,8 @@ TEST_F(Function2D_Test, median) {
|
|||||||
TEST_F(Function2D_Test, fftAndComplexAndIfft){
|
TEST_F(Function2D_Test, fftAndComplexAndIfft){
|
||||||
double *input = new double[20]{1,1,0,2,2,0,1,1,0,2,1,1,0,2,2,0,1,1,0,2};
|
double *input = new double[20]{1,1,0,2,2,0,1,1,0,2,1,1,0,2,2,0,1,1,0,2};
|
||||||
auto ma = Aurora::Matrix::fromRawData(input,10,2);
|
auto ma = Aurora::Matrix::fromRawData(input,10,2);
|
||||||
auto ret = Aurora::fft(ma);
|
auto fftrett = Aurora::fft(ma);
|
||||||
std::complex<double>* result = (std::complex<double>*)ret.getData();
|
std::complex<double>* result = (std::complex<double>*)fftrett.getData();
|
||||||
//检验fft结果与matlab是否对应
|
//检验fft结果与matlab是否对应
|
||||||
EXPECT_DOUBLE_EQ(0.0729, fourDecimalRound(result[1].real()));
|
EXPECT_DOUBLE_EQ(0.0729, fourDecimalRound(result[1].real()));
|
||||||
EXPECT_DOUBLE_EQ(2.4899, fourDecimalRound(result[2].imag()));
|
EXPECT_DOUBLE_EQ(2.4899, fourDecimalRound(result[2].imag()));
|
||||||
@@ -344,12 +344,33 @@ TEST_F(Function2D_Test, fftAndComplexAndIfft){
|
|||||||
//检验fft的结果是否共轭
|
//检验fft的结果是否共轭
|
||||||
EXPECT_DOUBLE_EQ(0, result[4].imag()+result[6].imag());
|
EXPECT_DOUBLE_EQ(0, result[4].imag()+result[6].imag());
|
||||||
EXPECT_DOUBLE_EQ(0, result[4].real()-result[6].real());
|
EXPECT_DOUBLE_EQ(0, result[4].real()-result[6].real());
|
||||||
ret= Aurora::ifft(ret);
|
auto ret= Aurora::ifft(fftrett);
|
||||||
std::complex<double>* ifftResult = (std::complex<double>*)ret.getData();
|
std::complex<double>* ifftResult = (std::complex<double>*)ret.getData();
|
||||||
EXPECT_DOUBLE_EQ(fourDecimalRound(ifftResult[1].real()),1.0);
|
EXPECT_DOUBLE_EQ(fourDecimalRound(ifftResult[1].real()),1.0);
|
||||||
EXPECT_DOUBLE_EQ(fourDecimalRound(ifftResult[3].real()),2.0);
|
EXPECT_DOUBLE_EQ(fourDecimalRound(ifftResult[3].real()),2.0);
|
||||||
EXPECT_DOUBLE_EQ(fourDecimalRound(ifftResult[11].real()),1.0);
|
EXPECT_DOUBLE_EQ(fourDecimalRound(ifftResult[11].real()),1.0);
|
||||||
EXPECT_DOUBLE_EQ(fourDecimalRound(ifftResult[13].real()),2.0);
|
EXPECT_DOUBLE_EQ(fourDecimalRound(ifftResult[13].real()),2.0);
|
||||||
|
Aurora::fftshift(fftrett);
|
||||||
|
EXPECT_DOUBLE_EQ(0.0729, fourDecimalRound(result[6].real()));
|
||||||
|
EXPECT_DOUBLE_EQ(2.4899, fourDecimalRound(result[7].imag()));
|
||||||
|
EXPECT_DOUBLE_EQ(-2., fourDecimalRound(result[10].real()));
|
||||||
|
EXPECT_DOUBLE_EQ(-0.2245, fourDecimalRound(result[11].imag()));
|
||||||
|
|
||||||
|
auto fftrett2 = Aurora::fft(ma,5);
|
||||||
|
auto result2 = (std::complex<double>*)fftrett2.getData();
|
||||||
|
//检验fft结果与matlab是否对应
|
||||||
|
EXPECT_DOUBLE_EQ(0.3090, fourDecimalRound(result2[1].real()));
|
||||||
|
EXPECT_DOUBLE_EQ(-1.3143, fourDecimalRound(result2[2].imag()));
|
||||||
|
EXPECT_DOUBLE_EQ(-0.8090, fourDecimalRound(result2[7].real()));
|
||||||
|
EXPECT_DOUBLE_EQ(1.3143, fourDecimalRound(result2[8].imag()));
|
||||||
|
|
||||||
|
auto fftrett3 = Aurora::fft(ma,12);
|
||||||
|
auto result3 = (std::complex<double>*)fftrett3.getData();
|
||||||
|
//检验fft结果与matlab是否对应
|
||||||
|
EXPECT_DOUBLE_EQ(-1.0, fourDecimalRound(result3[1].real()));
|
||||||
|
EXPECT_DOUBLE_EQ(-3.4641, fourDecimalRound(result3[4].imag()));
|
||||||
|
EXPECT_DOUBLE_EQ(-1.0, fourDecimalRound(result3[13].real()));
|
||||||
|
EXPECT_DOUBLE_EQ(-3.4641, fourDecimalRound(result3[16].imag()));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(Function2D_Test, hilbert) {
|
TEST_F(Function2D_Test, hilbert) {
|
||||||
|
|||||||
Reference in New Issue
Block a user