431,942 Members | 1,922 Online
Need help? Post your question and get tips & solutions from a community of 431,942 IT Pros & Developers. It's quick & easy.

# find the highest value within an array of complex numbers

 P: 4 I would like to find the highest value within an array of complex numbers. Let assume this is the function I want to modify in order to get the highest values of array y : Expand|Select|Wrap|Line Numbers //iterDelayEst.cpp #include  #include  #include      double iterDelayEst(int n,CArray& x, CArray& y) { /**********************************************constants************************************************ *******************************************************************************************************/ //exit if uncertainty below threshold     double thr_samples = 1e-7;       //exit after fixed number of iterations     double nIter = 25;     fft(x);     fft(y);       //frequency domain representation of signals     std::vector tau;       auto f = binFreq(n);       std::vector e;     Complex nf3(0.0,0.0);       int j;       for ( j = 0 ; j < n ; j++ )       {         auto nf1 = ((x * x.apply(std::conj)) * (y * y.apply(std::conj)));         nf3 += nf1[j];     }           auto nf2 =std::sqrt(nf3);         auto nf =nf2/(double)n;         cout << "nf3" << nf3 < v;                               x = x.apply(std::conj);          y *= x;              ifft(y);              y =std::abs(y);          y=y/nf;            for ( i = 0 ; i < n ; i++ ){                         cout << "y[" << i <<"] =" << y[i] << endl;                         v.push_back(y);                      }                    std::vector::iterator result ;                  const Complex maxim = *max_element(v.begin(), v.end());                  for(result = std::find(v.begin(), v.end(), maxim); result != v.end(); result = std::find(result + 1, v.end(), maxim))                  {                  cout << result - v.begin()+1 << endl;                  //printf("found at index %f\n", result -v.begin() +1 );                  }             /**************************detect peak********************************************************/   } [code]//main.cpp #include #include #include #include #include #include #include #include #include #include #include #include #include "fft.cpp" #include "cs_delay.cpp" #include "iterDelayEst.cpp" using namespace std; char filename[] = "myfile.txt"; char filename2[] = "myfile2.txt"; typedef std::complex Complex; typedef std::valarray CArray; /************************************************** ********************************************* * function declarations ************************** ************************************************** ****** ***********/ void fft(CArray& x); void ifft(CArray& x); std::vector binFreq(int n); void cs_delay(CArray& x, int rate_hz, int delay_s, int n); double iterDelayEst(int n, CArray& x, CArray& x2); int main() { int dTest_samples; int cTest; int n=32; int i; int j; double x [n]; double y [n]; int rate_hz=1; int delay_s=30; /*****************************getting x*******************************/ string line; double Result; ifstream myfile (filename); if (myfile.is_open()) { for ( i = 0 ; (i < n) && (myfile >> x[i]) ; ++i) cout << line << '\n'; stringstream convert(line); if ( !(convert >> Result) ) Result = 0; x[i]=Result; } else cout << "Unable to open file"; /*****************************getting y******************************/ string line2; double Result2; ifstream myfile2 (filename2); if (myfile2.is_open()) { for ( i = 0 ; (i < n) && (myfile2 >> x[i]) ; ++i) cout << line2 << '\n'; stringstream convert(line2); if ( !(convert >> Result2) ) Result2 = 0; y[i]=Result2; } else cout << "Unable to open file2"; /************************************************** *********************/ /*********************for x******************/ Complex test[n]; for ( i = 0 ; i < n ; ++i ) test[i] = x[i]; CArray data(test,n); /*********************for y******************/ Complex test2[n]; for ( j = 0 ; j < n ; ++j ) test2[j] = y[j]; CArray data2(test2,n); // forward fft fft(data); std::cout << "fft" << std::endl; for (int i = 0; i  Complex; typedef std::valarray CArray; // Cooley–Tukey FFT (in-place, divide-and-conquer) // Higher memory requirements and redundancy although more intuitive void fft(CArray& x) {     const size_t N = x.size();     if (N <= 1) return;       // divide     CArray even = x[std::slice(0, N/2, 2)];     CArray  odd = x[std::slice(1, N/2, 2)];       // conquer     fft(even);     fft(odd);       // combine     for (size_t k = 0; k < N/2; ++k)     {         Complex t = std::polar(1.0, -2 * PI * k / N) * odd[k];         x[k    ] = even[k] + t;         x[k+N/2] = even[k] - t;     } } // inverse fft (in-place) void ifft(CArray& x)   {     // conjugate the complex numbers     x = x.apply(std::conj);       // forward fft     fft( x );       // conjugate the complex numbers again     x = x.apply(std::conj);       // scale the numbers     x /= x.size(); }   Expand|Select|Wrap|Line Numbers //cs_delay.cpp using namespace std;   typedef std::complex Complex; typedef std::valarray CArray;   void cs_delay(CArray& x, int rate_hz, int delay_s, int n) {   const size_t N = x.size();     if (N <= 1) return; int j; double cycLen_s; double nCyc; double* f = new double[n]; double* phase = new double[n]; Complex* rot = new Complex[n]; cycLen_s = n/rate_hz; nCyc = delay_s / cycLen_s; /*************************************************************/ for ( j = 0 ; j < n ; j++ ){           f[j] =j+floor(n/2);         f[j] =fmod(f[j], n);         f[j] =f[j]-floor(n/2);         phase[j] = -2 * PI * f[j] * nCyc;         rot[j] = exp(1i*phase[j]);         std::cout << "rot["< binFreq(int n) {    int j;    std::vector f(n);      for ( j = 0 ; j < n ; j++ ){         f[j] =(fmod(j+(floor(n/2)), n)-floor(n/2))/n;    }    return f; } While trying to run the program I am receiving following error messages : Output: Expand|Select|Wrap|Line Numbers serge@ubuntu:~/Downloads/OpenCV/opencv-2.4.9/build\$ g++ -o myfft  myfft.cpp -std=c++14 In file included from myfft.cpp:16:0: iterDelayEst.cpp: In function ‘double iterDelayEst(int, CArray&, CArray&)’: iterDelayEst.cpp:67:38: error: no matching function for call to ‘std::vector >::push_back(CArray&)’                          v.push_back(y);                                       ^ iterDelayEst.cpp:67:38: note: candidates are: In file included from /usr/include/c++/4.9/vector:64:0,                  from /usr/include/c++/4.9/bits/random.h:34,                  from /usr/include/c++/4.9/random:49,                  from /usr/include/c++/4.9/bits/stl_algo.h:66,                  from /usr/include/c++/4.9/algorithm:62,                  from /usr/include/c++/4.9/valarray:38,                  from myfft.cpp:3: /usr/include/c++/4.9/bits/stl_vector.h:913:7: note: void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = std::complex; _Alloc = std::allocator >; std::vector<_Tp, _Alloc>::value_type = std::complex]        push_back(const value_type& __x)        ^ /usr/include/c++/4.9/bits/stl_vector.h:913:7: note:   no known conversion for argument 1 from ‘CArray {aka std::valarray >}’ to ‘const value_type& {aka const std::complex&}’ /usr/include/c++/4.9/bits/stl_vector.h:931:7: note: void std::vector<_Tp, _Alloc>::push_back(std::vector<_Tp, _Alloc>::value_type&&) [with _Tp = std::complex; _Alloc = std::allocator >; std::vector<_Tp, _Alloc>::value_type = std::complex]        push_back(value_type&& __x)        ^ /usr/include/c++/4.9/bits/stl_vector.h:931:7: note:   no known conversion for argument 1 from ‘CArray {aka std::valarray >}’ to ‘std::vector >::value_type&& {aka std::complex&&}’ In file included from /usr/include/c++/4.9/bits/stl_algobase.h:71:0,                  from /usr/include/c++/4.9/bits/char_traits.h:39,                  from /usr/include/c++/4.9/ios:40,                  from /usr/include/c++/4.9/istream:38,                  from /usr/include/c++/4.9/sstream:38,                  from /usr/include/c++/4.9/complex:45,                  from myfft.cpp:1: /usr/include/c++/4.9/bits/predefined_ops.h: In instantiation of ‘bool __gnu_cxx::__ops::_Iter_less_iter::operator()(_Iterator1, _Iterator2) const [with _Iterator1 = __gnu_cxx::__normal_iterator*, std::vector > >; _Iterator2 = __gnu_cxx::__normal_iterator*, std::vector > >]’: /usr/include/c++/4.9/bits/stl_algo.h:5473:30:   required from ‘_ForwardIterator std::__max_element(_ForwardIterator, _ForwardIterator, _Compare) [with _ForwardIterator = __gnu_cxx::__normal_iterator*, std::vector > >; _Compare = __gnu_cxx::__ops::_Iter_less_iter]’ /usr/include/c++/4.9/bits/stl_algo.h:5496:41:   required from ‘_FIter std::max_element(_FIter, _FIter) [with _FIter = __gnu_cxx::__normal_iterator*, std::vector > >]’ iterDelayEst.cpp:71:71:   required from here /usr/include/c++/4.9/bits/predefined_ops.h:42:23: error: no match for ‘operator<’ (operand types are ‘std::complex’ and ‘std::complex’)        { return *__it1 < *__it2; }                        ^ /usr/include/c++/4.9/bits/predefined_ops.h:42:23: note: candidates are: In file included from /usr/include/c++/4.9/bits/stl_algobase.h:67:0,                  from /usr/include/c++/4.9/bits/char_traits.h:39,                  from /usr/include/c++/4.9/ios:40,                  from /usr/include/c++/4.9/istream:38,                  from /usr/include/c++/4.9/sstream:38,                  from /usr/include/c++/4.9/complex:45,                  from myfft.cpp:1: /usr/include/c++/4.9/bits/stl_iterator.h:837:5: note: template bool __gnu_cxx::operator<(const __gnu_cxx::__normal_iterator<_IteratorL, _Container>&, const __gnu_cxx::__normal_iterator<_IteratorR, _Container>&)      operator<(const __normal_iterator<_IteratorL, _Container>& __lhs,      ^ /usr/include/c++/4.9/bits/stl_iterator.h:837:5: note:   template argument deduction/substitution failed: In file included from /usr/include/c++/4.9/bits/stl_algobase.h:71:0,                  from /usr/include/c++/4.9/bits/char_traits.h:39,                  from /usr/include/c++/4.9/ios:40,                  from /usr/include/c++/4.9/istream:38,                  from /usr/include/c++/4.9/sstream:38,                  from /usr/include/c++/4.9/complex:45,                  from myfft.cpp:1: /usr/include/c++/4.9/bits/predefined_ops.h:42:23: note:   ‘std::complex’ is not derived from ‘const __gnu_cxx::__normal_iterator<_IteratorL, _Container>’        { return *__it1 < *__it2; }                        ^ In file included from /usr/include/c++/4.9/bits/stl_algobase.h:67:0,                  from /usr/include/c++/4.9/bits/char_traits.h:39,                  from /usr/include/c++/4.9/ios:40,                  from /usr/include/c++/4.9/istream:38,                  from /usr/include/c++/4.9/sstream:38,                  from /usr/include/c++/4.9/complex:45,                  from myfft.cpp:1: /usr/include/c++/4.9/bits/stl_iterator.h:844:5: note: template bool __gnu_cxx::operator<(const __gnu_cxx::__normal_iterator<_Iterator, _Container>&, const __gnu_cxx::__normal_iterator<_Iterator, _Container>&)      operator<(const __normal_iterator<_Iterator, _Container>& __lhs,      ^ /usr/include/c++/4.9/bits/stl_iterator.h:844:5: note:   template argument deduction/substitution failed: In file included from /usr/include/c++/4.9/bits/stl_algobase.h:71:0,                  from /usr/include/c++/4.9/bits/char_traits.h:39, Can someone help ? Jul 10 '16 #1

I found a much elegant way to do that :

Expand|Select|Wrap|Line Numbers
1. #include <cstddef>
2. #include <numeric>
3. #include <complex>
4. #include <valarray>
5. #include <iostream>
6.
7. using Complex = std::complex<double>;
8. using CArray = std::valarray<Complex>;
9.
10. std::size_t max_index(CArray const& y) {
11.     struct acc_t {
12.         double max_value;
13.         std::size_t max_idx, current_idx;
14.
15.         constexpr acc_t next() const { return {max_value, max_idx, current_idx + 1}; }
16.         constexpr acc_t next_with(Complex const c) const {
17.             return {c.real(), current_idx, current_idx + 1};
18.         }
19.     };
20.
21.     return std::accumulate(
22.         std::begin(y), std::end(y), acc_t{},
23.         [](acc_t const acc, Complex const c) {
24.             return c.real() < acc.max_value
25.               ? acc.next()
26.               : acc.next_with(c);
27.         }
28.     ).max_idx;
29. }
30.
31. void test(CArray const& y) {
32.     auto const max_idx = max_index(y);
33.     std::cout << "The max is " << y[max_idx] << " at index " << max_idx << '\n';
34. }
35.
36. int main() {
37.
38.     test({{1, 2}, {3, 4}, { 2, 0}, {9, 0}, {7, 0}, {9, 0}});
39. }

6 Replies

 Expert Mod 5K+ P: 9,197 I'm not sure exactly what you are doing. To find the max complex number in an array should look like: Expand|Select|Wrap|Line Numbers class Complex {     double X;     double Y; public:     bool operator<(Complex& first); };   int main() {     vector array;       vector::iterator itr  = array.begin();       Complex Max = array[0];       while (itr != array.end())     {         if (Max < *itr)         {             Max = *itr;         }                 ++itr;       }       //Max has the highest value   } What am I missing? Jul 10 '16 #2

 P: 4 Sorry, I am a beginner in c++, Indeed,the title should be "How to find indices corresponding to the highest value in an array of complex numbers" I would like to translate the following matlab code into C++: ix = find(xcorr == max(xcorr)); the matlab code returns indices of elements corresponding to the highest value xcorr is an array of complex numbers I have tried to put your example in practice but it seems like I can't print that highest element: Expand|Select|Wrap|Line Numbers #include  #include  #include  #include  #include  #include  #include    using namespace std;   class Complex {     double X;     double Y; public:     bool operator<(Complex& first);   };   std::ostream& operator<<(std::ostream& os, const Complex& obj) {     os << obj;     return os; }   int main() {     vector array;     array.push_back((1,1));     array.push_back((-1,-1));     array.push_back((7,7));     array.push_back((3,3));     array.push_back((10,10));       vector::iterator itr  = array.begin();       Complex Max = array[0];       while (itr != array.end())     {         if (Max < *itr)         {             Max = *itr;           }          ++itr;          //printf("found at index %f\n", Max );       }       //Max has the highest value   }   Output : Jul 10 '16 #3

 Expert Mod 5K+ P: 9,197 You can't print your element because obj is a user-defined type. The std::operator<< only works with built-in types. You would write member functions to access the X and Y of the class Complex and then call those functions: Expand|Select|Wrap|Line Numbers class Complex {     double X;     double Y; public:     bool operator<(Complex& first);     double GetReal() { return X; };     double GetImaginary() { return Y; };     };   and then in main(): Expand|Select|Wrap|Line Numbers cout << Max.GetReal() << Max.GetImaginary() << endl; Jul 10 '16 #4

 P: 4 Hi, it seems to not work : Expand|Select|Wrap|Line Numbers #include  #include  #include  #include  #include  #include      using namespace std;   class Complex {     double X;     double Y; public:     bool operator<<(Complex& first);     double GetReal() { return X; };     double GetImaginary() { return Y; };  };     int main() {     vector array;     array.push_back((1,1));     array.push_back((-1,-1));     array.push_back((7,7));     array.push_back((3,3));     array.push_back((10,10));       vector::iterator itr  = array.begin();       Complex Max = array[0];       while (itr != array.end())     {         if (Max << *itr)         {             Max = *itr;           }          ++itr;          cout << Max.GetReal() << Max.GetImaginary() << endl;       }   } I am getting following error messages : Expand|Select|Wrap|Line Numbers main.cpp: In function 'int main()': main.cpp:25:24: warning: left operand of comma operator has no effect [-Wunused-value]      array.push_back((1,1));                         ^ main.cpp:25:26: error: no matching function for call to 'std::vector::push_back(int)'      array.push_back((1,1));                           ^ In file included from /usr/local/include/c++/6.1.0/vector:64:0,                  from main.cpp:3: /usr/local/include/c++/6.1.0/bits/stl_vector.h:914:7: note: candidate: void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = Complex; _Alloc = std::allocator std::vector<_Tp, _Alloc>::value_type = Complex]        push_back(const value_type& __x)        ^~~~~~~~~ /usr/local/include/c++/6.1.0/bits/stl_vector.h:914:7: note:   no known conversion for argument 1 from 'int' to 'const value_type& {aka const Complex&}' /usr/local/include/c++/6.1.0/bits/stl_vector.h:932:7: note: candidate: void std::vector<_Tp, _Alloc>::push_back(std::vector<_Tp, _Alloc>::value_type&&) [with _Tp = Complex; _Alloc = std::allocator std::vector<_Tp, _Alloc>::value_type = Complex]        push_back(value_type&& __x)        ^~~~~~~~~ /usr/local/include/c++/6.1.0/bits/stl_vector.h:932:7: note:   no known conversion for argument 1 from 'int' to 'std::vector::value_type&& {aka Complex&&}' main.cpp:26:26: warning: left operand of comma operator has no effect [-Wunused-value]      array.push_back((-1,-1));                           ^ main.cpp:26:28: error: no matching function for call to 'std::vector::push_back(int)'      array.push_back((-1,-1));                             ^ In file included from /usr/local/include/c++/6.1.0/vector:64:0,                  from main.cpp:3: /usr/local/include/c++/6.1.0/bits/stl_vector.h:914:7: note: candidate: void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = Complex; _Alloc = std::allocator std::vector<_Tp, _Alloc>::value_type = Complex]        push_back(const value_type& __x)        ^~~~~~~~~ /usr/local/include/c++/6.1.0/bits/stl_vector.h:914:7: note:   no known conversion for argument 1 from 'int' to 'const value_type& {aka const Complex&}' /usr/local/include/c++/6.1.0/bits/stl_vector.h:932:7: note: candidate: void std::vector<_Tp, _Alloc>::push_back(std::vector<_Tp, _Alloc>::value_type&&) [with _Tp = Complex; _Alloc = std::allocator std::vector<_Tp, _Alloc>::value_type = Complex]        push_back(value_type&& __x)        ^~~~~~~~~ /usr/local/include/c++/6.1.0/bits/stl_vector.h:932:7: note:   no known conversion for argument 1 from 'int' to 'std::vector::value_type&& {aka Complex&&}' main.cpp:27:24: warning: left operand of comma operator has no effect [-Wunused-value]      array.push_back((7,7));                         ^ main.cpp:27:26: error: no matching function for call to 'std::vector::push_back(int)'      array.push_back((7,7));                           ^ In file included from /usr/local/include/c++/6.1.0/vector:64:0,                  from main.cpp:3: /usr/local/include/c++/6.1.0/bits/stl_vector.h:914:7: note: candidate: void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = Complex; _Alloc = std::allocator std::vector<_Tp, _Alloc>::value_type = Complex]        push_back(const value_type& __x)        ^~~~~~~~~ /usr/local/include/c++/6.1.0/bits/stl_vector.h:914:7: note:   no known conversion for argument 1 from 'int' to 'const value_type& {aka const Complex&}' /usr/local/include/c++/6.1.0/bits/stl_vector.h:932:7: note: candidate: void std::vector<_Tp, _Alloc>::push_back(std::vector<_Tp, _Alloc>::value_type&&) [with _Tp = Complex; _Alloc = std::allocator std::vector<_Tp, _Alloc>::value_type = Complex]        push_back(value_type&& __x)        ^~~~~~~~~ /usr/local/include/c++/6.1.0/bits/stl_vector.h:932:7: note:   no known conversion for argument 1 from 'int' to 'std::vector::value_type&& {aka Complex&&}' main.cpp:28:24: warning: left operand of comma operator has no effect [-Wunused-value]      array.push_back((3,3));                         ^ main.cpp:28:26: error: no matching function for call to 'std::vector::push_back(int)'      array.push_back((3,3));                           ^ In file included from /usr/local/include/c++/6.1.0/vector:64:0,                  from main.cpp:3: /usr/local/include/c++/6.1.0/bits/stl_vector.h:914:7: note: candidate: void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = Complex; _Alloc = std::allocator std::vector<_Tp, _Alloc>::value_type = Complex]        push_back(const value_type& __x)        ^~~~~~~~~ /usr/local/include/c++/6.1.0/bits/stl_vector.h:914:7: note:   no known conversion for argument 1 from 'int' to 'const value_type& {aka const Complex&}' /usr/local/include/c++/6.1.0/bits/stl_vector.h:932:7: note: candidate: void std::vector<_Tp, _Alloc>::push_back(std::vector<_Tp, _Alloc>::value_type&&) [with _Tp = Complex; _Alloc = std::allocator std::vector<_Tp, _Alloc>::value_type = Complex]        push_back(value_type&& __x)        ^~~~~~~~~ /usr/local/include/c++/6.1.0/bits/stl_vector.h:932:7: note:   no known conversion for argument 1 from 'int' to 'std::vector::value_type&& {aka Complex&&}' main.cpp:29:25: warning: left operand of comma operator has no effect [-Wunused-value]      array.push_back((10,10));                          ^~ main.cpp:29:28: error: no matching function for call to 'std::vector::push_back(int)'      array.push_back((10,10));                             ^ In file included from /usr/local/include/c++/6.1.0/vector:64:0,                  from main.cpp:3: /usr/local/include/c++/6.1.0/bits/stl_vector.h:914:7: note: candidate: void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = Complex; _Alloc = std::allocator std::vector<_Tp, _Alloc>::value_type = Complex]        push_back(const value_type& __x)        ^~~~~~~~~ /usr/local/include/c++/6.1.0/bits/stl_vector.h:914:7: note:   no known conversion for argument 1 from 'int' to 'const value_type& {aka const Complex&}' /usr/local/include/c++/6.1.0/bits/stl_vector.h:932:7: note: candidate: void std::vector<_Tp, _Alloc>::push_back(std::vector<_Tp, _Alloc>::value_type&&) [with _Tp = Complex; _Alloc = std::allocator std::vector<_Tp, _Alloc>::value_type = Complex]        push_back(value_type&& __x)        ^~~~~~~~~ /usr/local/include/c++/6.1.0/bits/stl_vector.h:932:7: note:   no known conversion for argument 1 from 'int' to 'std::vector::value_type&& {aka Complex&&}' Jul 11 '16 #5

 Expert Mod 5K+ P: 9,197 You must use functions the way they were designed. This code: Expand|Select|Wrap|Line Numbers array.push_back((1,1));   needs a push_back function that has integer arguments, In this program the push_back requires a Complex argument. You must build the Complex object then you can do the push_back: Expand|Select|Wrap|Line Numbers Complex obj;         obj.SetReal(1);         obj.SetImaginary(1);   array.push_back(obj);   You will need to write the SetReal SetImaginary member function s of Complex. Just follow the pattern for the GetReal and GetImaginary. You can use a constructor instead. Keep posting. You are making progress. I did not go through the whole code. Fix these errors and repost Jul 11 '16 #6

 P: 4 I found a much elegant way to do that : Expand|Select|Wrap|Line Numbers #include  #include  #include  #include  #include    using Complex = std::complex; using CArray = std::valarray;   std::size_t max_index(CArray const& y) {     struct acc_t {         double max_value;         std::size_t max_idx, current_idx;           constexpr acc_t next() const { return {max_value, max_idx, current_idx + 1}; }         constexpr acc_t next_with(Complex const c) const {             return {c.real(), current_idx, current_idx + 1};         }     };       return std::accumulate(         std::begin(y), std::end(y), acc_t{},         [](acc_t const acc, Complex const c) {             return c.real() < acc.max_value               ? acc.next()               : acc.next_with(c);         }     ).max_idx; }   void test(CArray const& y) {     auto const max_idx = max_index(y);     std::cout << "The max is " << y[max_idx] << " at index " << max_idx << '\n'; }   int main() {       test({{1, 2}, {3, 4}, { 2, 0}, {9, 0}, {7, 0}, {9, 0}}); } Jul 23 '16 #7