Moyshe
Moyshe

Reputation: 1122

How to get Vector of Complex numbers from two vectors (real & imag)

I have two vectors of floats and i want them to become one vector of Complex numbers. I'm stuck. I don't mind using iterators, but i am sure it'd be rediscovering the wheel i'm not informed about. Is my code leading me in the right direction?

typedef std::vector<float> CVFloat;
CVFloat vA, vB;
//fil vectors
typedef std::complex<CVFloat> myComplexVector;
myComplexVector* vA_Complex = new myComplexVector(vA, vB);

The code above is going through the compiler correctly, but when i want to get single numbers from myComplexVector using iterator i get error "Undefined symbol 'const_iterator'" (Borland C++)

myComplexVector::const_iterator it = vA_Complex->begin();

Upvotes: 1

Views: 16213

Answers (8)

Namascar
Namascar

Reputation: 13

With c++23, this is easy.

#include <vector>
#include <ranges>
#include <complex>

int main()
{
    const std::vector<float> real { 1.0f, 2.0f, 3.0f};
    const std::vector<float> imaginary { 4.0f, 5.0f, 6.0f};

    const auto toComplex = [](const float& real, const float& imaginary) 
        { 
            return std::complex<float>(real, imaginary); 
        };

    const std::vector<std::complex<float>> myComplexVector = 
        std::views::zip_transform(toComplex, real, imaginary) 
            | std::ranges::to<std::vector>();

    return 0;
}

Upvotes: 0

anon
anon

Reputation:

This doesn't make any sense:

typedef std::complex<CVFloat> myComplexVector;

surely you mean

typedef std::complex <float> ComplexFloat;
typedef std::vector <ComplexFloat> CFVector;

or something similar?

Once ou have it you can simply iterate over the float vectors (assuming they contain matching values) and add to your complex vector using push_back():

CFVector v;

for ( int i = 0; i < vA.size(); i++ ) {
  v.push_back( ComplexFloat( vA[i], vB[i] ) );
}

Upvotes: 1

MartinStettner
MartinStettner

Reputation: 29164

I understand your question that you want to combine a vector of real parts with a vector of imaginary parts into a vector of complex numbers.

std::complex has one template parameter which lets you chose the numerical represenation of the parts of the complex (i.e. if you want complex values based on double or float or even some custom number type...). The complex type then defines basic complex algebra in terms of the underlying type.

In your code you are trying to construct a complex type based on a vector of floats (i.e. a single complex value having a real and imaginary part being a vector), which is obviously wrong. Instead you want a vector of complex numbers of type float

You'd have to do something like:

// ...
typedef std::vector<std::complex<float> > floatComplexVector;
floatComplexVector vA_Complex; // No need to 'new' !?

for (CVFLoat::const_iterator itA = vA.begin(), itB = vB.begin(); 
     itA != vA.end() && itB != vB.end(); 
     ++itA,++itB)
  vA_Complex.push_back(std::complex<float>(*itA, *itB));

Remarks:

  • In most cases it isn't necessary to create containers such as vectors on the heap (i.e. using new) Try to avoid this.

  • Unfortunately the C++ standard library doesnt contain a combining iterator (i.e. one that "automatically" combines two sequences) which would allow a more elegant solution (see Boost Zip iterator for a general idea).

Upvotes: 0

sharptooth
sharptooth

Reputation: 170499

Whay not do it much much easier?

vector< complex<float> > result;
for( int i = 0; i < vA.size(); i++ ) {
    result.push_back( complex<float>( vA[i], vB[i] ) );
}

Upvotes: 3

Paolo Tedesco
Paolo Tedesco

Reputation: 57202

Here you are creating a "complex" object whose real and imaginary parts are vectors of floats.
Maybe what you actually want to do is creating a vector of complex objects whose real and imaginary parts are floats?

EDIT: myComplexVector is not a vector, is a complex. That's why a const_iterator for it is not defined.

Upvotes: 5

xtofl
xtofl

Reputation: 41509

You can create a general "zip" function taking iterators to both vectors, and a convertor functor and an output iterator:

template< typename at_It1, typename at_It2, typename at_Transform, typename at_Out >
void zip( at_It1 from1, const at_It1 to1, 
          at_It2 from2, const at_It2 to2,
          at_Transform  tranformer,
          at_Out& av_Out ) {
    while( from1 != to1 ) {
        av_Out = transformer( *from1, *from2 );
        ++av_Out; ++from1; ++from2;
    }
}

struct DoubleToComplex {
     complex<double> operator()( const double d1, const double d2 ) const {
         return complex<double>( d1, d2 );
     }
};



zip( vA.begin(), vA.end(),
     vB.begin(), vB.end(),
     DoubleToComplex(),
     std::back_inserter( vTarget ) );

And I wish there were such a function in the STL...

Upvotes: 1

jpalecek
jpalecek

Reputation: 47762

The easiest way is just write the loop

myComplexVector cv;
for(CVFloat::iterator it1=vA.begin(), end1=vA.end(), 
      it2=vB.begin(), end2=vB.end();
    it1!=end1 && it2 != end2; ++it1, ++it2)
  cv.push_back(std::complex(*it1, *it2));

Edit: ... and follow Neil's advice to declare myComplexVector type properly.

Upvotes: 1

Yuval Adam
Yuval Adam

Reputation: 165232

A complex number is simply a pair of two real numbers a and b which denote the complex number a+bi. What exactly are you trying to do with the two vectors?

Upvotes: 0

Related Questions