我想用C ++编写FFT程序代码并将其实现为python库。
所以,我使用Boost.Python 1.64并且我用C ++对FFT进行了编码:
1.fft.hpp(标题)
#ifndef _FFT_HPP_
#define _FFT_HPP_
#define BOOST_PYTHON_STATIC_LIB
#include <iostream>
#include <string>
#include <algorithm>
#include <boost/python.hpp>
#include <boost/python/numpy.hpp>
#ifdef _OPENMP
#include <omp.h>
#endif
#include "blas.h"
#include <complex>
#include <fftw3.h>
/* define namespace */
namespace py = boost::python;
namespace npy = boost::python::numpy;
typedef std::complex<double> dcomplex;
/* data format */
typedef struct DATA {
/* define variable of struct */
} data;
extern data uvdata;
/* image format */
typedef struct IMAGE {
/* define variable of struct */
} image;
/* result format */
typedef struct RESULT {
/* define variable of struct */
} result;
/* memmory allocation of matrix and vectors */
template <typename T> T *alloc_vector(int length);
template <typename T> T *alloc_matrix(int width, int height);
/* subroutines for input data */
extern void input_pos(npy::ndarray u, npy::ndarray v, npy::ndarray uidx, npy::ndarray vidx);
extern void input_fcv(npy::ndarray uvidxfcv, npy::ndarray Vfcvr, npy::ndarray Vfcvi, npy::ndarray Varfcv);
extern void input_amp(npy::ndarray uvidxamp, npy::ndarray Vamp, npy::ndarray Varamp);
extern void input_cp(npy::ndarray uvidxcp, npy::ndarray Vcp, npy::ndarray Varcp);
extern void input_ca(npy::ndarray uvidxca, npy::ndarray Vca, npy::ndarray Varca);
/* subroutine for calculating cost */
extern void fft_test(npy::ndarray Iin, npy::ndarray x, npy::ndarray y,
npy::ndarray xidx, npy::ndarray yidx, int NX, int NY);
#endif // _FFT_HPP_
2.ftt.cpp(FFTW)
#include "fft.hpp"
/* redefine struct of data */
data uvdata;
template <typename T> T *transform_c_matrix(npy::ndarray matrix) {
return reinterpret_cast<T *>(matrix.get_data());
}
void fftw_test(image *fitsimage, data *tmpdata);
void input_pos(npy::ndarray u, npy::ndarray v, npy::ndarray uidx, npy::ndarray vidx)
{
/* input position and index of u and v to uvdata */
uvdata.u = transform_c_matrix<double>(u);
uvdata.v = transform_c_matrix<double>(v);
uvdata.uidx = transform_c_matrix<int>(uidx);
uvdata.vidx = transform_c_matrix<int>(vidx);
}
void input_fcv(npy::ndarray uvidxfcv, npy::ndarray Vfcvr, npy::ndarray Vfcvi, npy::ndarray Varfcv)
{
/* input full-comp. visiblity to uvdata */
/* index */
uvdata.Nfcv = int(uvidxfcv.shape(0));
uvdata.uvidxfcv = transform_c_matrix<int>(uvidxfcv);
/* data and variance */
uvdata.Vfcvr = transform_c_matrix<double>(Vfcvr);
uvdata.Vfcvi = transform_c_matrix<double>(Vfcvi);
uvdata.Varfcv = transform_c_matrix<double>(Varfcv);
/* inverse flag */
uvdata.isfcv = true;
}
void input_amp(npy::ndarray uvidxamp, npy::ndarray Vamp, npy::ndarray Varamp)
{
/* input visibility amplitude to uvdata */
/* index */
uvdata.Namp = int(uvidxamp.shape(0));
uvdata.uvidxamp = transform_c_matrix<int>(uvidxamp);
/* data and variance */
uvdata.Vamp = transform_c_matrix<double>(Vamp);
uvdata.Varamp = transform_c_matrix<double>(Varamp);
/* inverse flag */
uvdata.isamp = true;
}
void input_cp(npy::ndarray uvidxcp, npy::ndarray Vcp, npy::ndarray Varcp)
{
/* input closure phase to uvdata */
/* index */
uvdata.Ncp = int(uvidxcp.shape(0));
uvdata.uvidxcp = transform_c_matrix<int>(uvidxcp);
/* data and variance */
uvdata.Vcp = transform_c_matrix<double>(Vcp);
uvdata.Varcp = transform_c_matrix<double>(Varcp);
/* inverse flag */
uvdata.iscp = true;
}
void input_ca(npy::ndarray uvidxca, npy::ndarray Vca, npy::ndarray Varca)
{
/* input closure amplitude to uvdata */
/* index */
uvdata.Nca = int(uvidxca.shape(0));
uvdata.uvidxca = transform_c_matrix<int>(uvidxca);
/* data and variance */
uvdata.Vca = transform_c_matrix<double>(Vca);
uvdata.Varca = transform_c_matrix<double>(Varca);
/* inverse flag */
uvdata.isca = true;
}
void fft_test(npy::ndarray Iin, npy::ndarray x, npy::ndarray y,
npy::ndarray xidx, npy::ndarray yidx, int NX, int NY)
{
data tmpdata;
image fitsimage;
/* input initial image */
fitsimage.Iin = transform_c_matrix<double>(Iin);
fitsimage.x = transform_c_matrix<double>(x);
fitsimage.y = transform_c_matrix<double>(y);
fitsimage.xidx = transform_c_matrix<int>(xidx);
fitsimage.yidx = transform_c_matrix<int>(yidx);
fitsimage.NX = NX;
fitsimage.NY = NY;
fitsimage.Npix = NX*NY;
uvdata.NU = NX/2+1;
uvdata.NV = NY;
uvdata.Nuv = uvdata.NU*uvdata.NV;
tmpdata = uvdata;
fftw(&fitsimage, &tmpdata);
}
void fftw(image *fitsimage, data *tmpdata)
{
int iuv,inc=1;
double *in,*Vreal,*Vimag;
dcomplex *out;
fftw_plan fftplan;
in = alloc_matrix<double>(fitsimage->NX,fitsimage->NY);
out = alloc_matrix<dcomplex>(tmpdata->NU,tmpdata->NV);
Vreal = alloc_matrix<double>(tmpdata->NU,tmpdata->NV);
Vimag = alloc_matrix<double>(tmpdata->NU,tmpdata->NV);
fftplan = fftw_plan_dft_r2c_2d(fitsimage->NX, fitsimage->NY,
in, reinterpret_cast<fftw_complex*>(out), FFTW_MEASURE);
dcopy_(&(fitsimage->Npix), fitsimage->Iin, &inc, in, &inc);
fftw_execute(fftplan);
for (iuv=0; iuv<tmpdata->Nuv; ++iuv) {
Vreal[iuv] = std::real(out[iuv]);
Vimag[iuv] = std::imag(out[iuv]);
printf("%d %f\n",iuv,Vreal[iuv]);
}
delete[] in;
delete[] out;
fftw_destroy_plan(fftplan);
}
3.fft_tools.cpp(用于FFT的工具)
#include "fft.hpp"
template <typename T> T *alloc_vector(int length) {
return new T[length];
}
template <typename T> T *alloc_matrix(int width, int height) {
return new T[width*height];
}
4.libfftw.cpp(python的实现)
#include "fft.hpp"
BOOST_PYTHON_MODULE(libfft)
{
Py_Initialize();
npy::initialize();
py::def("input_pos", &input_pos);
py::def("input_fcv", &input_fcv);
py::def("input_amp", &input_amp);
py::def("input_cp", &input_cp);
py::def("input_ca", &input_ca);
py::def("fft_test", &fft_test);
}
我已使用以下方式遵守此规定:
g++ -fPIC -Wall -O2 -lopenblas -fftw3 -lboost_python -lboost_numpy -I/usr/include/python2.7 -shared -o libfft.so fft.cpp fft_tools.cpp libfftw.cpp
导入时出现以下错误:
import libfft
ImportError: ./libfft.sp: undefined symbol: _Z12alloc_matrixISt7complexIdEEPT_ii
这是什么意思,我该如何解决这个问题?
答案 0 :(得分:0)
链接代码时,链接器无法找到符号alloc_matrix<complex>
。这是因为您已将其实现放在.cpp
文件中,而不是.hpp
文件中。如果你:
fft_tools.cpp
,并将其放入fft.hpp
fft_tools.cpp
文件,它是空的。然后你会发现这个特定的链接错误会消失。