Работа с массивами вещественных и комплексных чисел.

Я работаю с массивом комплексных чисел a и массивом действительных чисел b (как двойной).

typedef std::complex<double> Complex;

std::valarray<Complex> a(1024);
std::valarray<double>  b(1024);

std::valarray<double> modulus = std::abs(a);    // problem 1
std::valarray<Complex> modulus2 = std::abs(a);  // this works but uses 2 times more memory :(
std::valarray<Complex> c = a * b;               // problem 2

Я столкнулся с двумя проблемами (живая запускаемая демонстрация здесь):

  1. В целях управления памятью, поскольку абсолютное значение (или "модуль") является действительным числом, должна быть возможность сохранить его как std::valarray<double>. Но тут не работает: ошибка conversion from 'std::_Expr<std::_UnClos<std::_Abs, std::_ValArray, std::complex<double> >, std::complex<double> >' to non-scalar type 'std::valarray<double>' requested. Как сохранить modulus как std::valarray<double>?

  2. Должна быть возможность умножить a на b и сохранить результат в виде массива комплексных чисел. Но есть эта ошибка: no match for 'operator*' (operand types are 'std::valarray<std::complex<double> >' and 'std::valarray<double>'). Как правильно выполнить это умножение массивов?


person Basj    schedule 05.07.2016    source источник
comment
std::valarray не совсем вершина С++. Можно даже сказать, что комитет облажался.   -  person Baum mit Augen    schedule 06.07.2016
comment
@BaummitAugen Я использовал это, потому что хотел иметь возможность делать высокоуровневые вещи, такие как c = a * b, где a и b - массивы, как я сделал бы в Python с numpy ... Как вы думаете, мне следует использовать что-то еще?   -  person Basj    schedule 06.07.2016
comment
На вашем месте я бы искал приличную библиотеку линейной алгебры. Простой поиск с помощью вашей любимой поисковой системы даст вам лучшие альтернативы. (Я полностью согласен с тем, что ваш код должен работать, если valarray был в здравом уме.)   -  person Baum mit Augen    schedule 06.07.2016
comment
@BaummitAugen Дело в том, что за последние несколько лет я использовал Python 99,99% времени и C++ 0,01%, поэтому я не хочу выбирать такую ​​библиотеку массивов случайным образом с помощью поисковой системы... ; ) Может быть, у кого-то есть хорошая идея / или способ сделать это с valarray в любом случае?   -  person Basj    schedule 06.07.2016
comment
В последние годы я делал все в Лос-Анджелесе с помощью Python/Numpy или C/Lapack (да, старый добрый C90 TT), поэтому я не могу рекомендовать библиотеки. (Армадилло выглядит хорошо на первый взгляд, может быть, проверить softwarerecs? (Однако прочитайте правила.)) Вы, конечно, можете сделать это и с valarray тоже , так же, как вы сделали бы это с std::vector.   -  person Baum mit Augen    schedule 06.07.2016
comment
@Basj Во-первых, это невозможно сделать с valarray. std::abs собирается выдать valarray типа ввода, и это complex. Вы можете зациклить его самостоятельно, но вы также можете использовать std::vector в этот момент. Редактировать: вы можете перегрузить std::abs, но опять же, вы можете сделать это с vector.   -  person user4581301    schedule 06.07.2016
comment
Если я использую std::vector, могу ли я по-прежнему делать такие вещи, как c = a * b?   -  person Basj    schedule 06.07.2016
comment
@Basj Нет. std::vector - это просто общий массив вещей, ни в коем случае не знающий математики.   -  person Baum mit Augen    schedule 06.07.2016


Ответы (1)


Вот решение, которое я мог придумать (живая запускаемая демонстрация здесь):

#include <valarray>
#include <complex>

typedef std::complex<double> Complex;

int main()
{
  std::valarray<Complex> a(1024);
  std::valarray<double>  b(1024);

  // Solution to problem 1
  std::valarray<double> modulus(a.size());
  auto mod = std::abs(a);
  for (size_t i=0;i<mod.size();i++) {
      modulus[i] = std::abs(mod[i]);
  }

  std::valarray<Complex> modulus2 = std::abs(a);   // this works but uses 2 times more memory :(
  std::valarray<Complex> c = a * b;                // problem 2

  // Solution to problem 2
  std::valarray<Complex> b2(1024);
  std::valarray<Complex> c2(a);
  c *= b2;                                       
}

К сожалению, @Basj, вы столкнулись с проблемой перехода от простого в использовании Python к C++ (я тоже сталкиваюсь с этой стеной). Но что-то получаешь, что-то теряешь.

  1. std::abs() возвращает абсолютное значение элементов как valarray того же типа. как аргумент. В результате вы не можете напрямую назначить его valarray<double>, так как вы передали аргумент как valarray<Complex>.
  2. Массивы можно умножать, но не независимо. Проверьте эти операторы. Вы можете умножать ваш массив на другой массив (или скаляр), но не на произвольные массивы.
person ilya1725    schedule 06.07.2016