//should be optimized const complex_matrix_type make_new_a() const { auto A = make_a(); auto gs = make_gscale(); auto gy = make_gyvec(); auto const gd = make_gd(make_beam_vector()); auto const Gm = make_gm(gd); auto gm = make_unique_beams(Gm); array_type gxu = scale_multiply( gx, gs ); array_type gyu = scale_multiply( gy, gs ); array_type gu = array_type( gxu.norm(), gyu.norm(), 0 ); array_vector_type gxy( gd ); std::for_each( gxy.begin(), gxy.end(), [gu](array_type& a){ a[0]*=gu[1]; a[1]*=gu[0]; a[2]=0; } ); vector_type gxy2( gxy.size() ); feng::for_each( gxy2.begin(), gxy2.end(), gxy.begin(), [](value_type& v, const array_type& a){ v = a.norm(); v*=v; } ); feng::for_each( A.diag_begin(), A.diag_end(), gxy2.begin(), [](complex_type& c, const value_type& v){ c = complex_type(-v, 0); } ); std::cout << "\nA=\n" << A; return A; }
std::size_t cyclic_eigen_jacobi( const Matrix1& A, Matrix2& V, Otor o, std::size_t max_rot = 80, const T eps = T( 1.0e-10 ) ) { typedef typename Matrix1::value_type value_type; typedef typename Matrix1::size_type size_type; auto const compare_func = [eps]( const value_type lhs, const value_type rhs ) { return std::abs(lhs-rhs) < eps; }; assert( A.row() == A.col() ); //assert( is_symmetric( A, compare_func ) ); size_type i = 0; auto a = A; auto const n = a.row(); auto const one = value_type( 1 ); auto const zero = value_type( 0 ); // @V = diag{1, 1, ..., 1} V.resize( n, n ); V = zero; std::fill( V.diag_begin(), V.diag_end(), one ); for ( ; i != max_rot; ++i ) { if ( !(i&7) && eigen_jacobi_private::norm(a) == zero ) { break; } for ( size_type p = 0; p != n; ++p ) for ( size_type q = p+1; q != n; ++q ) eigen_jacobi_private::rotate(a, V, p, q); } std::copy( a.diag_begin(), a.diag_end(), o ); return i*n*n; }
bool is_orthogonal( const matrix<T,N,A>& m, F f ) { if ( m.row() != m.col() ) return false; auto mm = m.transpose() * m; std::for_each( mm.diag_begin(), mm.diag_end(), [](T& v){ v -= T(1); } ); return std::all_of( mm.begin(), mm.end(), f ); }
typename Matrix::value_type norm( const Matrix& A ) { typedef typename Matrix::value_type value_type; //typedef typename Matrix::size_type size_type; auto A_ = feng::abs(A); std::fill( A_.diag_begin(), A_.diag_end(), value_type(0) ); //diag element set to 0 auto const max_elem = *( std::max_element( A_.cbegin(), A_.cend() )); //find the max element if ( value_type(0) == max_elem ) return value_type(0); //return 0 if all elements are 0 A_ /= max_elem; //in case of round-off error auto const sum = std::inner_product( A_.cbegin(), A_.cend(), A_.cbegin(), value_type(0) ); //\sum A_{i,j}^2 return std::sqrt(sum) * max_elem; }
const array_matrix_type make_gm( const array_vector_type& gd ) const { auto const N = gd.size(); array_matrix_type gr( N, N ); array_matrix_type gc( N, N ); for ( size_type i = 0; i != N; ++i ) { std::fill( gr.row_begin( i ), gr.row_end( i ), gd[i] ); std::fill( gc.col_begin( i ), gc.col_end( i ), gd[i] ); } auto gm = gr - gc; //std::copy( gd.begin(), gd.end(), gm.diag_begin() ); std::fill( gm.diag_begin(), gm.diag_end(), gm[0][1] ); return gm; }
std::size_t eigen_jacobi( const Matrix1& A, Matrix2& V, Otor o, const T eps = T( 1.0e-10 ) ) { typedef typename Matrix1::value_type value_type; typedef typename Matrix1::size_type size_type; assert( A.row() == A.col() ); //assert( is_symmetric( A ) ); auto a = A; auto const n = a.row(); auto const one = value_type( 1 ); auto const zero = value_type( 0 ); // @V = diag{1, 1, ..., 1} V.resize( n, n ); V = zero; std::fill( V.diag_begin(), V.diag_end(), one ); #if 1 for ( size_type i = 0; i != size_type( -1 ); ++i ) { // @find max non-diag value in A size_type p = 0; size_type q = 1; value_type current_max = std::abs( a[p][q] ); for ( size_type ip = 0; ip != n; ++ip ) for ( size_type iq = ip + 1; iq != n; ++iq ) { auto const tmp = std::abs( a[ip][iq] ); if ( current_max > tmp ) continue; current_max = tmp; p = ip; q = iq; } // @if all non-diag value small, then break iteration with success if ( current_max < eps ) { std::copy( a.diag_begin(), a.diag_end(), o ); return i; } // a and V iterations eigen_jacobi_private::rotate(a, V, p, q); }//end for #endif // @just to kill warnings, should never reach here return size_type( -1 ); }//eigen_jacobi