2016-05-23 9 views
0

То, что я пытаюсь сделать, в конечном счете, умножает два комплексных числа, как это:Compute Mutliplication комплексных чисел

z1 = R1 + I1*j 

z2 = R2 + I2*j 

z3 = z1 * z2 = (R1*R2 - I1*I2) (R1*I2 + R2*I1)*j; 

Но что у меня есть два отдельных векторов для реального и сложной части обоих этих комплексных чисел. Так что-то вроде этого:

v1 = [R1, R2, R3, R4 ... Rn] of z1 

v2 = [I1, I2, I3, I4 ... In] of z1 

v1 = [R1, R2, R3, R4 ... Rn] of z2 

v2 = [I1, I2, I3, I4 ... In] of z2 

Так что, когда я пытаюсь вычислить z3 сейчас, я делаю это:

foo (std::vector<double> real1, std::vector<double> imag1, 
    std::vector<double> real2, std::vector<double> imag2) 
{ 
    std::vector<double> realResult; 
    std::vector<double> imagResult; 

    for (size_t i = 0; i < real1.size(); i++) 
    { 
     realResult.push_back(real1[i]*real2[i] - imag1[i]*imag2[i]); 
     imagResult.push_back(real1[i]*imag2[i] + real2[i]*imag1[i]); 
    } 

    //And so on 
} 

Теперь эта функция есть много времени. Конечно, есть еще один способ сделать это, вы можете думать о чем-то, что я могу использовать?

+2

предварительно выделить результирующие векторы и заполнить их, а не с помощью push_back –

ответ

3

Pass в параметре как const std::vector<double>&, чтобы избежать ненужной копии

Вы можете также рассмотреть вопрос вычисления каждого умножения параллельно, если N достаточно большой, накладные расходы параллельных вычислений стоит

+0

Очевидно. Спасибо! – FreddyKay

4

Вы могли бы быть в состоянии сделать использование std::complex. Это, вероятно, реализует операции, которые вам требуются, по крайней мере, близко, а также они могут быть реализованы.

EDIT (В ответ на комментарий):

Я хотел бы сделать это:

size_t num_items = real1.size(); 
std::vector<double> realResult; 
realResult.reserve(num_items); 
std::vector<double> imagResult; 
imagResult.reserve(num_items); 
for (size_t i = 0; i < num_items; ++i) { 
    // lalala not re-sizeing any vectors yey! 
    realResult.push_back(real1[i] * real2[i] - imag1[i] * imag2[i]); 
    imagResult.push_back(real1[i] * imag2[i] + real2[i] * imag1[i]); 

} 

В противном случае, если у вас есть большой массив ввода и вы делаете много умножения на двойников я боюсь это может быть просто медленным. Лучшее, что вы можете сделать, это беспорядок с получением предметов, смежных в памяти для бонусных кеш-очков. Невозможно действительно сказать, не профилируя код точно, что может работать лучше всего.

+0

Как указано выше. Я дам ему шанс, но мне нужно будет заполнить std :: complex моими векторами. Знаете ли вы способ эффективно это сделать? – FreddyKay

+0

@FreddyKay Я подозреваю, что вы обнаружите, что все было намного быстрее, если вы инициализируете вектор результата до размера, который вы ожидаете, или «зарезервируете» это пространство. Я должен был бы профиль, чтобы быть уверенным, но я бы заподозрил, глядя на этот код, что может быть потрачено достаточно много времени, чтобы перераспределить больше места для векторов результатов. Я отредактирую свой ответ, чтобы показать это предложение. – sji

+0

@FreddyKay, заполняющий комплексные числа, может быть выполнен по тем же идеям, что и резервирование пространства сначала и просто цикл. Я бы предположил, что, если возможно, вы просто инициализируете свои исходные данные как вектор std :: compex, чтобы избежать дополнительной копии. – sji

1

std::valarraystd::complex. Он прост и оптимизирован для арифметических операций

foo(std::valarray<std::complex<double>> & z1, 
    std::valarray<std::complex<double>> & z2) 
{ 
    auto z3 = z1 * z2; // applies to each element of two valarrays, or a valarray and a value 

    // . . . 
} 

EDIT: Преобразование векторов в valarray

std::valarray<std::complex<double>> z1(real1.size()); 
for (size_t i = 0; i < z1.size(); ++i) 
    z1[i] = std::complex<double>(real1[i], imag1[i]); 
+0

Это кажется приятным. Я сделаю это. Хотя мне пришлось бы эффективно заполнять массивы моими векторами. У вас есть предложение? – FreddyKay

+0

@FreddyKay добавил в ответ. – Shreevardhan