我是EE,不是代码专家,所以请在这里忍受。
我正在使用Embarcadero C ++ Builder(XE3)。
我有一个FFT算法,可以对复数进行相当多的操作。我发现如果我绕过Embarcadero的复杂数学库,并在我自己的代码中进行所有计算,我的FFT运行速度将快4.5倍。这里显示的4个操作都需要过多的时间。
#include <dinkumware\complex>
#define ComplexD std::complex<double>
ComplexD X, Y, Z, FFTInput[1024];
double x, y;
Z = X * Y;
x = X.real();
y = X.imag();
Z = ComplexD(x,y);
用我自己的交叉乘法替换乘法将我的执行时间减半。然而,我关心的是我访问输入数组的实部和虚部的方式。我这样做:
double *Input;
Input = reinterpret_cast<double *>(FFTInput);
// Then these statements are equivalent.
x = FFTInput[n].real();
y = FFTInput[n].imag();
x = Input[2*n];
y = Input[2*n+1];
这样做可以将执行时间再缩短一半,但我不知道这种reinterpret_cast是否是明智之举。我可以将输入数组更改为两个双精度而不是复数,但我在许多程序中使用此FFT并且不想重写所有内容。
这是reinterpret_cast好吗,还是我有记忆问题?另外,有没有办法让Embarcadero复杂的数学函数运行得更快?最后,虽然它对我来说并不是非常重要,但是这个reinterpret_cast是否便携?
答案 0 :(得分:4)
这是允许的。虽然这不是标准报价,但cppreference有这样的说法:
对于任何指向复数
p
数组元素的指针 有效数组索引i
,reinterpret_cast<T*>(p)[2*i]
是真正的部分 复数p[i]
和reinterpret_cast<T*>(p)[2*i + 1]
是 复数p[i]
的虚部。
我很快就会从实际标准中寻找引用。
答案 1 :(得分:2)
来自页面底部的here:
对于任何复数z,
reinterpret_cast<T(&)[2]>(z)[0]
是z的真实部分,reinterpret_cast<T(&)[2]>(z)[1]
是z的虚部。对于任何指向复数p和任何有效数组索引i的元素的指针,
reinterpret_cast<T*>(p)[2*i]
是复数p [i]的实部,并且< strong>reinterpret_cast<T*>(p)[2*i + 1]
是复数p [i]的虚部。 (自C ++ 11以来)这些要求实质上限制了std :: complex的三个特化中的每一个的实现,以声明两个且只有两个类型为value_type的非静态数据成员,它们具有相同的成员访问权限,包含实部和虚部,分别
所以你所做的是保证在C ++ 11中工作,但在此之前不行。它可能仍然适用于您的库的实现,但您需要检查您的库的实现没有按照第三段定义任何更多的非静态数据成员。
答案 2 :(得分:0)
如果没有使用std::complex
的定义并且知道编译器如何实现此定义,我们就无法回答这个问题。实际上,reinterpret_case
是否正确取决于std::complex
类型的内存布局。据我所知,这里没有任何指定。所以它肯定不便携。所以答案是:它可能适用于某些编译器/架构,而不适用于其他一些编译器/架构。