0

I'm working with an array of complex numbers a and an array of real numbers b (as double).

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

I encounter two problems (live runnable demo here) :

  1. For memory management purpose, as the absolute value (or "modulus") is a real number, it should be possible to store it as a std::valarray<double>. But here it doesn't work : there is an error conversion from 'std::_Expr<std::_UnClos<std::_Abs, std::_ValArray, std::complex<double> >, std::complex<double> >' to non-scalar type 'std::valarray<double>' requested. How to store modulus as a std::valarray<double>?

  2. It should be possible to multiply a by b and store the result as an array of complex numbers. But there is this error : no match for 'operator*' (operand types are 'std::valarray<std::complex<double> >' and 'std::valarray<double>'). How to do this multiplication of arrays properly?

Basj
  • 41,386
  • 99
  • 383
  • 673
  • 2
    `std::valarray` is not quite the pinnacle of C++. One could even say, the committee screwed that up. – Baum mit Augen Jul 05 '16 at 23:21
  • @BaummitAugen I used that because I wanted to be able to do high-level things like `c = a * b` where a and b are arrays, like I would do in Python with numpy... Do you think I should use something else? – Basj Jul 05 '16 at 23:25
  • If I were you, I'd look for a decent linear algebra library. Simple searching with your favorite search engine will give you better alternatives. (I fully agree that your code should work if `valarray` was sane.) – Baum mit Augen Jul 05 '16 at 23:28
  • @BaummitAugen The fact is: in the last few years, I used Python 99,99% of the time and C++ 0,01% so I don't want to choose such an array library by random with a search engine... ;) Maybe someone has a good idea / or a way to do it with `valarray` anyway? – Basj Jul 05 '16 at 23:33
  • In the last years I did all LA stuff with Python/Numpy or C/Lapack (yes, good old C90 TT), so I cannot comfortably recommend libraries. (Armadillo looks good at first glance, maybe checkout [softwarerecs](https://softwarerecs.stackexchange.com/)? (Read the rules though.)) You can of course do it with `valarray` too, same way you would do it with `std::vector`. – Baum mit Augen Jul 05 '16 at 23:38
  • 1
    @Basj First one can't be done with `valarray`. `std::abs` is going to spit out a `valarray` of the input type, and that's `complex`. You can loop it yourself, but you might as well use `std::vector` at that point. Edit: You could overload `std::abs`, but again back to you might as well do it with `vector`. – user4581301 Jul 05 '16 at 23:39
  • If using `std::vector`, could I still do things like `c = a * b` ? – Basj Jul 05 '16 at 23:45
  • @Basj Nope. `std::vector` is just a generic array of stuff, not math aware in any sense. – Baum mit Augen Jul 05 '16 at 23:46

1 Answers1

0

Here is the solution I could come up with (live runnable demo here) :

#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;                                       
}

Unfortunately @Basj you ran into the problem of going from easy to use Python to C++ (I run into this wall too). But you get some, you loose some.

  1. std::abs() returns the absolute value of the elements as the valarray of the same type as the argument. As a result, you can't assign it directly to valarray<double> since you've passed the argument as valarray<Complex>.
  2. Arrays could be multiplied, but not independently. Check these operators. You can multiply your array by a different array (or scalar), but not some arbitrary arrays.
ilya1725
  • 4,496
  • 7
  • 43
  • 68