2

In Matlab, we can get the max, min, and also the position of the complex vector:

[mag_x idx_x] = max(abs(X));
[mag_y idx_y] = max(abs(Y));

I know that we can do the similar with C++ because Matlab is build from C++. But I could not figure it out. I also have incomplete code, and still working on it:

#include <iostream>     // std::cout
#include <algorithm>    // std::min_element, std::max_element
#include <vector>
#include <complex>
#include <iostream>
int main()
{

//typedef std::complex < double > C
vector <complex<short> > vec;

vec.push_back ( complex <short> (1,1));
vec.push_back ( complex <short> (1,2));
vec.push_back ( complex <short> (3,4));
vec.push_back ( complex <short> (0,0));
vec.push_back ( complex <short> (4,8));
vec.push_back ( complex <short> (0,0));
vec.push_back ( complex <short> (2,3));
vec.push_back ( complex <short> (1,1));

int size = sizeof(x_vec)/sizeof(x_vec[0]);
for(int i =0; i < size; i++)
{
    cout << x_vec[i] << endl;
}
 ...

return 0;
}

I also look at the sample code from this link: http://www.cplusplus.com/reference/algorithm/max_element/ but it work only for vector.

Also when I calculate the size = sizeof(x_vec)/sizeof(x_vec[0]); I am expecting size = 8 (because of 8 vector complex above) but I gave me only size = 6.

halfer
  • 19,824
  • 17
  • 99
  • 186
long khong
  • 73
  • 1
  • 2
  • 9
  • 1
    when finding the size of the vector, use `vec.size()`. The sizeof calculation is a c-style method, and you're applying it to a vector object (which holds three pointers, usually, and is thus the size of three pointers) and its first element (which will have the size of whatever type the vector stores) – jaggedSpire Dec 12 '16 at 22:43
  • Additionally, it's unclear exactly what you mean by minimum maximum and position in this context--you could be referring to the entry in the vector with the smallest/biggest magnitude, and getting the index of that element. Or you could be asking for the smaller/bigger of the real and imaginary numbers that make up each complex number, and an indication of which is which. – jaggedSpire Dec 12 '16 at 22:47
  • 1
    In fact, if you want to visit every element in `vec`, use a `range-based for` instead: `for(const auto& c : vec) { cout << c << endl; }` – Jack Deeth Dec 12 '16 at 22:55

1 Answers1

4

To use vector<complex> with std::max_element, you need to provide a function which compares the values of two complex objects. You need to do this as there's multiple ways to compare them.

One way is to write a lambda function which compares two complexes using std::abs. You can write this in your call to max_element:

// C++14
auto maxelem = max_element(vec.begin(), vec.end(),
                           [](auto a, auto b) { return abs(a) < abs(b); });
// C++11
auto maxelem = max_element(vec.begin(), vec.end(),
                           [](const complex<short>& a, const complex<short>& b)
                             { return abs(a) < abs(b); });

cout << "Max: " << *maxelem << endl;

max_element produces an iterator containing the maximum value found. The index of that iterator in the vector can be found using std::distance:

cout << "Max position: " << std::distance(vec.begin(), maxelem) << endl;

The complex comparator function can be stored in an auto for reuse:

// C++14
auto absLess = [](auto a, auto b) { return abs(a) < abs(b); };
// C++11
auto csAbsLess = [](const complex<short> &a,
                    const complex<short> &b) { return abs(a) < abs(b); };

We can use it with various other Standard Library algorithms like min_element and sort.

auto maxelem = max_element(vec.begin(), vec.end(), absLess);
cout << "Max: " << *maxelem << endl;
cout << "Max position: " << std::distance(vec.begin(), maxelem) << endl;

auto minelem = min_element(vec.begin(), vec.end(), absLess);
cout << "Min: " << *minelem << endl;
cout << "Min position: " << std::distance(vec.begin(), minelem) << endl;

sort(vec.begin(), vec.end(), absLess);

for (const auto &c : vec) {
  cout << c << endl;
}

Outputs:

Max: (4,8)
Max position: 4
Min: (0,0)
Min position: 3
(0,0)
(0,0)
(1,1)
(1,1)
(1,2)
(2,3)
(3,4)
(4,8)

Granted, it's not as eloquent as [mag_x idx_x] = max(abs(X));!

An online demonstration is on Wandbox here.

Jack Deeth
  • 3,062
  • 3
  • 24
  • 39
  • The [`max_element' documentation](http://en.cppreference.com/w/cpp/algorithm/max_element) shows how to find the position of the max element within the vector - is that what you meant by "Position"? – Jack Deeth Dec 12 '16 at 23:30
  • Jack Deeth : my answer is "yes". I am trying to convert code from Matlab to C++, it's complicated but it will help me to reduce time process. – long khong Dec 13 '16 at 02:43
  • Jack Deeth : I am sorry for the lacking of knowledge, but I would like to ask you a question regarding to the ideal you just suggested. I am using Eclipse platform in Ubuntu OS. when I tried to test with: auto absLess = [](auto a, auto b) { return abs(a) < abs(b); }; inside "int main(){...}" but it shows the error: ‘absLess’ does not name a type, with warning ‘auto’ changes meaning in C++11; please remove it [-Wc++0x-compat]. is that compatible with this platform? Thank you, Jack Deeth. – long khong Dec 13 '16 at 02:50
  • That means your compiler isn't running in C++11 / C++14 mode. You need to pass `-std=c++11` or `-std=c++14` to your compiler. There's instructions on how to do this with Eclipse [here](http://stackoverflow.com/a/9135135/2449857). (If it's an old compiler, try `-std=c++0x`, which was the working title for what became C++11.) – Jack Deeth Dec 13 '16 at 02:57
  • 1
    still working on it, thank you very much, Jack Deeth . – long khong Dec 13 '16 at 16:36
  • My experience with C++: writing the code is fun. Understanding why the compiler won't compile? INFURIATING. And then you figure it out and everything's fine. – Jack Deeth Dec 13 '16 at 16:39
  • Maybe you should look at fortran, as it has MINLOC, MINVAL etc as intrinsics, and the indexing is MATLAB like. MATLAB shares a lot with Fortran. – Holmz Dec 14 '16 at 22:20