如何从真实双打的std :: vector中填充复杂双精度的std :: vector

时间:2017-01-18 16:05:01

标签: c++ c++11 vector complex-numbers

我正在研究一种数学代码,它很大程度上依赖于通过实际数据的inplace-FFT进行卷积。

由于我的数据是真实的,直到它进入卷积并且在卷积完成时才是真实的,我在任何地方都使用std::vector<double>

所以在我的卷积中,我必须将我的真实数据复制到我的复杂数据中。我没有找到任何方法使用std::fill()或任何其他比循环所有条目更复杂的方法。

此外:在测量使用原始指针与unique_ptrstd::vector相比所花费的时间时,第一个获胜的时间大约是所花费时间的一半,通过许多get()操作包装。 我的编译器是否缺少某些优化,还是我必须使用原始指针和内存的麻烦?

工作示例:我现在无法对此进行测试,但我过去曾经大力支持我的主张。这些时间是通过使用Build-Dropdown中的(Build Solution)使用Visual Studio Community 2015构建解决方案而完成的。 性能分析显示,从包装器到数据花费了大量时间。

#include <chrono>
#include <complex>
#include <vector>

void FFT();
void IFFT();

int main() {
    unsigned int N=1024;

    std::vector<double> real;
    real.resize(N);
    std::vector<double> imag;
    imag.resize(N);
    for (unsigned int i = 0; i < N; ++i) {
        real[i] = i;
        imag[i] = i;
    }

    std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();

    std::complex<double> I = std::complex<double> (0, 1);
    std::vector<std::complex<double>> data;
    data.resize(2048);
    for (unsigned int i = 0; i < N; ++i) {
        data[i] = real[i] + I*imag[i];
    }
    FFT();

    data[0] = 0.25*I*(conj(data[0] * data[0]) - data[0]*data[0]);
    for (unsigned int r = 1; r < 2 * N - r; ++r) {
        std::complex<double> z1 = data[2 * N - r];
        std::complex<double> z2 = data[r];
        std::complex<double> res = 0.25*I*(conj(z1 * z1) - z2*z2);
        data[r]=res;
        data[2*N - r]= conj(res);
    }
    IFFT();

    std::vector<double> result;
    result.resize(2 * N);
    for (unsigned int i = 0; i < 2 * N; ++i) {
        result[i] = data[i].real();
    }

    std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
    return std::chrono::duration_cast<std::chrono::milliseconds>(end - begin).count();
}

1 个答案:

答案 0 :(得分:2)

  

我没有找到任何方法使用std :: fill或任何其他比循环遍历所有条目更复杂的方法。

只需将std::transform与lambda:

一起使用即可
std::vector<double> a{ 1.0, 2.0, 3.0 };
std::vector<double> b{ 4.0, 5.0, 6.0 };
std::vector<std::complex<double>> cvec( a.size() );
std::transform( a.begin(), a.end(), b.begin(), cvec.begin(), []( double da, double db ) {
    return std::complex<double>( da, db );
} );

您必须确保bcvec至少与a一样大,但对于cvec,您可以使用std::back_inserter,但这可能会稍微如果你没有为它预留保留,那就慢一些。