我知道处理 std::vectors 时最好使用 std::copy,但是我想知道如何将 fftw_malloc 数组复制到 std::vector 中?如果我应该使用 std::copy 还是 memcpy?
示例代码:
static const int nx = 8;
static const int ny = 8;
static const int nyk = ny/2 + 1;
static const int Mx = 3*nx/2, My= 3*ny/2;
double M[2] = {Mx,My};
fftw_complex *array1;
array1= (fftw_complex*) fftw_malloc(nx*nyk* sizeof(fftw_complex));
memset(array1, 42, nx*nyk* sizeof(fftw_complex));
std::vector<std::complex<double>> array2(Mx*My,0.0);
std::copy( array1, array1+(nx*nyk) , array2); //std::copy( src, src + size, dest );
我正在尝试将 array1 复制到 array2 中,其中 array2 > array1 然后想使用 std::vector 运算符来附加值等等。
这并没有真正起作用,我不确定我的向量语法是否已关闭,或者
std::copy
不是正确的方法。我应该使用 memcpy
来代替吗?谢谢
我首先会围绕
ComplexArray
返回的原始指针编写一个包装器,我们称之为 fftw_malloc
,并且我会使用 fftw_alloc_complex
而不是更通用的 fftw_malloc
。包装器应该为您作为 C++ 程序员提供处理数据的可能性,以便它可以与 C++ 标准库中的算法一起使用。
我仍然会使用
fftw
分配函数,而不是直接使用 std::vector<std::complex<double>>
(这完全没问题),因为它们 ”保证返回的指针遵守 FFTW 中任何算法施加的任何特殊对齐限制(例如用于 SIMD 加速)”.
通过为该包装器提供迭代器支持,将数据复制到
std::vector<std::complex<double>>
变得与使用任何 C++ 容器一样简单。您甚至可以直接从包装器的迭代器创建 vector
。
目标是可以像这样编写
main
函数:
int main() {
static const int nx = 8;
static const int ny = 8;
static const int nyk = ny / 2 + 1;
static const int Mx = 3 * nx / 2, My = 3 * ny / 2;
ComplexArray array1(nx * nyk); // the new C++ container
array1.fill(std::complex<double>{42, 42}); // no more memset
// create a vector from your ComplexArray
std::vector<std::complex<double>> array2(array1.begin(), array1.end());
}
ComplexArray
的示例实现可能如下所示,并且在您使用std::vector<std::complex<double>>
时所需的大多数情况下可以替代fftw
,因此您甚至可能不需要将其复制到vector
,您可以如果需要,可以添加复制并从迭代器和其他有用的东西创建它。这是一个开始:
#include <algorithm>
#include <complex>
#include <iterator>
class ComplexArray {
public:
using value_type = std::complex<double>;
using pointer = value_type*;
using const_pointer = const value_type*;
using reference = value_type&;
using const_reference = const value_type&;
using iterator = value_type*;
using const_iterator = const value_type*;
using reverse_iterator = std::reverse_iterator<iterator>;
using reverse_const_iterator = std::reverse_iterator<const_iterator>;
ComplexArray() = default;
ComplexArray(std::size_t size) : m_data(fftw_alloc_complex(size)) {}
// move semantics comes for free, copying does not:
ComplexArray(ComplexArray&&) = default;
ComplexArray& operator=(ComplexArray&&) = default;
// misc ...
std::size_t size() const { return m_size; }
void fill(const std::complex<double>& val) { std::fill(begin(), end(), val); }
// access
const_pointer data() const {
return reinterpret_cast<const_pointer>(m_data.get());
}
pointer data() { return reinterpret_cast<pointer>(m_data.get()); }
const_reference operator[](std::size_t idx) const { return data()[idx]; }
reference operator[](std::size_t idx) { return data()[idx]; }
// functions to provide fftw functions direct access to the data
const fftw_complex* fftw_data() const { return m_data.get(); }
fftw_complex* fftw_data() { return m_data.get(); }
// iterators ...
const_iterator cbegin() const { return data(); }
const_iterator cend() const { return data() + m_size * sizeof(value_type); }
const_iterator begin() const { return cbegin(); }
const_iterator end() const { return cend(); }
iterator begin() { return data(); }
iterator end() { return data() + m_size * sizeof(value_type); }
// reverse iterators ...
reverse_const_iterator crbegin() const {
return std::make_reverse_iterator(cend());
}
reverse_const_iterator crend() const {
return std::make_reverse_iterator(cbegin());
}
reverse_const_iterator rbegin() const { return crbegin(); }
reverse_const_iterator rend() const { return crend(); }
reverse_iterator rbegin() { return std::make_reverse_iterator(end()); }
reverse_iterator rend() { return std::make_reverse_iterator(begin()); }
private:
struct fftw_freer {
void operator()(fftw_complex* cplx) const noexcept { fftw_free(cplx); }
};
std::unique_ptr<fftw_complex, fftw_freer> m_data;
std::size_t m_size = 0;
};