gpt4 book ai didi

c++ - std::vector>(N).data() 可以安全地重新解释为 fftwq_complex* 吗?

转载 作者:行者123 更新时间:2023-11-28 06:45:37 31 4
gpt4 key购买 nike

我真的没想到下面的例子会起作用,但它确实起作用了(g++ 4.6.4,--std=c++0x):

#include <boost/multiprecision/float128.hpp> 
#include <blitz/array.h>
#include <fftw3.h>


int main(int /*argc*/, char** /*argv*/)
{
//these are the same
std::cout << sizeof(std::complex<boost::multiprecision::float128>) << " " << sizeof(fftwq_complex) << std::endl;


typedef std::vector< std::complex<boost::multiprecision::float128> > boost128cvec;
//typedef std::vector<std::complex<boost::multiprecision::float128> , fftw::allocator< std::complex<boost::multiprecision::float128> > > boost128cvec;

//declare a std::vector consisting of std::complex<boost::multiprecision::float128>
boost128cvec test_vector3(12);

//casting its data storatge to fftwq_complex*
fftwq_complex* test_ptr3 = reinterpret_cast<fftwq_complex*>(test_vector3.data());

//also create a view to the same data as a blitz::Array
blitz::Array<std::complex<boost::multiprecision::float128>, 1> test_array3(test_vector3.data(), blitz::TinyVector<int, 1>(12), blitz::neverDeleteData);

test_vector3[3] = std::complex<boost::multiprecision::float128>(1.23,4.56);

//this line would not work with std::vector
test_array3 = sin(test_array3);

//this line would not work with the built-in type __float128
test_vector3[4] = sin(test_vector3[3]);

//all of those print the same numbers
std::cout << "fftw::vector: " << test_vector3[3].real() << " + i " << test_vector3[3].imag() << std::endl;
std::cout << "fftw_complex: " << (long double)test_ptr3[3][0] << " + i " << (long double)test_ptr3[3][1] << std::endl;
std::cout << "blitz: " << test_array3(3).real() << " + i " << test_array3(3).imag() << std::endl << std::endl;

}

两点说明:

  • 目标是能够对同一数据同时使用 fftwblitz::Array 操作,而无需将它们四处复制,同时能够使用像 sin() 这样的通用函数,也可以用于具有四精度的复杂变量
  • blitz 部分工作正常,这是预期的。但令我惊讶的是,fftwq_complex* 部分也能正常工作。
  • fftw::allocatorstd::allocator 的简单替代品,它将使用 fftwq_malloc 来确保正确的 simd 对齐,但是对这道题不重要,所以我省略了(至少我认为这对这道题不重要)

我的问题是:我踩到的冰有多薄?

最佳答案

你节省了很多:

  • std::vector与 C 数组兼容(您可以通过 vector.data() 访问指向第一个元素的指针,如 this question 中的回答
  • std::complex<T>旨在与 T[2] 形式的数组兼容,与 FFTW 兼容。这在 FFTW documentation 中有描述。

    C++ has its own complex template class, defined in the standard header file. Reportedly, the C++ standards committee has recently agreed to mandate that the storage format used for this type be binary-compatible with the C99 type, i.e. an array T[2] with consecutive real [0] and imaginary [1] parts. (See report http://www.open-std.org/jtc1/sc22/WG21/docs/papers/2002/n1388.pdf WG21/N1388.) Although not part of the official standard as of this writing, the proposal stated that: “This solution has been tested with all current major implementations of the standard library and shown to be working.” To the extent that this is true, if you have a variable complex *x, you can pass it directly to FFTW via reinterpret_cast(x).

唯一要记住的是 data()如果您向 vector 添加值,则会失效。


最后一部分是 boost::multiprecision::float128 之间的兼容性。和 __float128 . boost 文档对此不作任何保证。但是,可以做的是在您的代码中添加一些静态断言,如果无法进行转换,则该断言将失败。这可能看起来像这样:

static_assert(std::is_standard_layout<float128>::value,"no standard type");
static_assert(sizeof(float128) == sizeof(__float128),"size mismatch");

在哪里sizeof保证 boost 类型和 __float128 和 is_standard_layout 的大小相同检查:

A pointer to a standard-layout class may be converted (with reinterpret_cast) to a pointer to its first non-static data member and vice versa.

当然,这只会在最后起作用时提供提示,因为您无法判断该类型是否真的是 __float128。 ,但是 ab boost 声明他们的类型是一个薄包装,应该没问题。如果他们的设计或结构发生变化 float128 ,静态断言应该失败。

关于c++ - std::vector<std::complex<boost:multiprecision::float128>>(N).data() 可以安全地重新解释为 fftwq_complex* 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25061663/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com