bool DenseLinAlgPack::comp(const DMatrixSlice& gms1, BLAS_Cpp::Transp trans1 , const DMatrixSlice& gms2, BLAS_Cpp::Transp trans2) { for(size_type i = 1; i < my_min(gms1.cols(),gms2.cols()); ++i) if( !comp( col(gms1,trans1,i) , col( gms2, trans2, i ) ) ) return false; return true; }
void DenseLinAlgPack::Vp_StMtV(DVectorSlice* vs_lhs, value_type alpha, const DMatrixSlice& gms_rhs1 , BLAS_Cpp::Transp trans_rhs1, const DVectorSlice& vs_rhs2, value_type beta) { Vp_MtV_assert_sizes(vs_lhs->dim(), gms_rhs1.rows() , gms_rhs1.cols(), trans_rhs1 , vs_rhs2.dim()); BLAS_Cpp::gemv(trans_rhs1,gms_rhs1.rows(),gms_rhs1.cols(),alpha,gms_rhs1.col_ptr(1) ,gms_rhs1.max_rows(), vs_rhs2.raw_ptr(),vs_rhs2.stride(),beta,vs_lhs->raw_ptr() ,vs_lhs->stride()); }
void DenseLinAlgPack::M_StMtInvM(DMatrix* gm_lhs, value_type alpha, const DMatrixSlice& gms_rhs1 , BLAS_Cpp::Transp trans_rhs1, const DMatrixSliceTri& tri_rhs2 , BLAS_Cpp::Transp trans_rhs2) { MtM_assert_sizes( gms_rhs1.rows(), gms_rhs1.cols(), trans_rhs1 , tri_rhs2.gms().rows(), tri_rhs2.gms().cols(), trans_rhs2 ); gm_lhs->resize( rows(gms_rhs1.rows(), gms_rhs1.cols(), trans_rhs1) , cols(tri_rhs2.gms().rows(), tri_rhs2.gms().cols(), trans_rhs2) ); i_trsm_alt(BLAS_Cpp::right,alpha,tri_rhs2,trans_rhs2,gms_rhs1,trans_rhs1,&(*gm_lhs)()); }
void DenseLinAlgPack::syrk(BLAS_Cpp::Transp trans, value_type alpha, const DMatrixSlice& gms_rhs , value_type beta, DMatrixSliceSym* sym_lhs) { Mp_MtM_assert_sizes( sym_lhs->gms().rows(), sym_lhs->gms().cols(), BLAS_Cpp::no_trans , gms_rhs.rows(), gms_rhs.cols(), trans , gms_rhs.rows(), gms_rhs.cols(), trans_not(trans) ); BLAS_Cpp::syrk(sym_lhs->uplo(),trans,sym_lhs->gms().rows() ,cols(gms_rhs.rows(), gms_rhs.cols(), trans),alpha ,gms_rhs.col_ptr(1),gms_rhs.max_rows(),beta ,sym_lhs->gms().col_ptr(1),sym_lhs->gms().max_rows() ); }
void DenseLinAlgPack::Mp_StMtM(DMatrixSlice* gms_lhs, value_type alpha, const DMatrixSlice& gms_rhs1 , BLAS_Cpp::Transp trans_rhs1, const DMatrixSlice& gms_rhs2 , BLAS_Cpp::Transp trans_rhs2, value_type beta) { Mp_MtM_assert_sizes( gms_lhs->rows(), gms_lhs->cols(), BLAS_Cpp::no_trans , gms_rhs1.rows(), gms_rhs1.cols(), trans_rhs1 , gms_rhs2.rows(), gms_rhs2.cols(), trans_rhs2); BLAS_Cpp::gemm(trans_rhs1,trans_rhs2,gms_lhs->rows(),gms_lhs->cols() ,cols(gms_rhs1.rows(),gms_rhs1.cols(),trans_rhs1) ,alpha,gms_rhs1.col_ptr(1),gms_rhs1.max_rows() ,gms_rhs2.col_ptr(1),gms_rhs2.max_rows() ,beta,gms_lhs->col_ptr(1),gms_lhs->max_rows() ); }
// gm_lhs = op(gms_rhs) void DenseLinAlgPack::assign(DMatrix* gm_lhs, const DMatrixSlice& gms_rhs, BLAS_Cpp::Transp trans_rhs) { if(gm_lhs->overlap(gms_rhs) == SAME_MEM && trans_rhs == BLAS_Cpp::no_trans) return; // assignment to self if(gm_lhs->overlap(gms_rhs) != NO_OVERLAP) { // some overlap so we must create a copy DMatrix tmp(gms_rhs); resize_gm_lhs(gm_lhs,gms_rhs.rows(),gms_rhs.cols(),trans_rhs); i_assign(&(*gm_lhs)(), tmp(), trans_rhs); } else { // no overlap so just assign resize_gm_lhs(gm_lhs,gms_rhs.rows(),gms_rhs.cols(),trans_rhs); i_assign(&(*gm_lhs)(), gms_rhs, trans_rhs); } }
void DenseLinAlgPack::Mp_StM(DMatrixSlice* gms_lhs, value_type alpha, const DMatrixSlice& gms_rhs , BLAS_Cpp::Transp trans_rhs) { Mp_M_assert_sizes(gms_lhs->rows(), gms_lhs->cols(), BLAS_Cpp::no_trans , gms_rhs.rows(), gms_rhs.cols(), trans_rhs); for(DMatrixSlice::size_type j = 1; j <= gms_lhs->cols(); ++j) Vp_StV( &gms_lhs->col(j), alpha, col(gms_rhs,trans_rhs,j) ); }
void DenseLinAlgPack::M_diagVtM( DMatrixSlice* gms_lhs, const DVectorSlice& vs_rhs , const DMatrixSlice& gms_rhs, BLAS_Cpp::Transp trans_rhs ) { Mp_M_assert_sizes(gms_lhs->rows(), gms_lhs->cols(), BLAS_Cpp::no_trans , gms_rhs.rows(), gms_rhs.cols(), trans_rhs); for(DMatrixSlice::size_type j = 1; j <= gms_lhs->cols(); ++j) prod( &gms_lhs->col(j), vs_rhs, col(gms_rhs,trans_rhs,j) ); }
inline /// Assert a matrix is square and throws length_error if it is not (LINALGPACK_CHECK_SLICE_SETUP). void assert_gms_square(const DMatrixSlice& gms) { #ifdef LINALGPACK_CHECK_SLICE_SETUP if(gms.rows() != gms.cols()) throw std::length_error("Matrix must be square"); #endif }
void DenseLinAlgPack::M_StInvMtM(DMatrixSlice* gms_lhs, value_type alpha, const DMatrixSliceTri& tri_rhs1 , BLAS_Cpp::Transp trans_rhs1, const DMatrixSlice& gms_rhs2 , BLAS_Cpp::Transp trans_rhs2) { Mp_MtM_assert_sizes( gms_lhs->rows(), gms_lhs->cols(), BLAS_Cpp::no_trans , tri_rhs1.gms().rows(), tri_rhs1.gms().cols(), trans_rhs1 , gms_rhs2.rows(), gms_rhs2.cols(), trans_rhs2 ); i_trsm_alt(BLAS_Cpp::left,alpha,tri_rhs1,trans_rhs1,gms_rhs2,trans_rhs2,gms_lhs); }
void DenseLinAlgPack::Mp_StMtM(DMatrixSlice* gms_lhs, value_type alpha, const DMatrixSlice& gms_rhs1 , BLAS_Cpp::Transp trans_rhs1, const DMatrixSliceSym& sym_rhs2 , BLAS_Cpp::Transp trans_rhs2, value_type beta) { Mp_MtM_assert_sizes( gms_lhs->rows(), gms_lhs->cols(), BLAS_Cpp::no_trans , gms_rhs1.rows(), gms_rhs1.cols(), trans_rhs1 , sym_rhs2.gms().rows(), sym_rhs2.gms().cols(), trans_rhs2 ); if(trans_rhs1 == BLAS_Cpp::no_trans) { i_symm(BLAS_Cpp::right,alpha,sym_rhs2,gms_rhs1,beta,gms_lhs); } else { // must make a temporary copy to call the BLAS DMatrix tmp; assign(&tmp,gms_rhs1,trans_rhs1); i_symm(BLAS_Cpp::right,alpha,sym_rhs2,tmp(),beta,gms_lhs); } }
inline /** \brief . */ /* * Utility to check if a lhs matrix slice is the same size as a rhs matrix slice. * * A DMatrixSlice can not be resized since the rows_ property of the * DMatrix it came from will not be updated. Allowing a DMatrixSlice * to resize from unsized would require that the DMatrixSlice carry * a reference to the DMatrix it was created from. If this is needed * then it will be added. */ void assert_gms_lhs(const DMatrixSlice& gms_lhs, size_type rows, size_type cols , BLAS_Cpp::Transp trans_rhs = BLAS_Cpp::no_trans) { if(trans_rhs == BLAS_Cpp::trans) std::swap(rows,cols); if(gms_lhs.rows() == rows && gms_lhs.cols() == cols) return; // same size // not the same size so is an error throw std::length_error("assert_gms_lhs(...): lhs DMatrixSlice dim does not match rhs dim"); }
bool DenseLinAlgPack::assert_print_nan_inf( const DMatrixSlice& m , const std::string & name, bool throw_excpt, std::ostream* out ) { bool has_nan_or_inf = false; bool printed_header = false; for( size_type j = 1; j <= m.cols(); ++j ) { const DVectorSlice& v = m.col(j); for( DVectorSlice::const_iterator v_itr = v.begin(); v_itr != v.end(); ++v_itr ) { if( RTOp_is_nan_inf(*v_itr) ) { if(out) { if(!printed_header) { *out << "The matrix \"" << name << "\" has the following NaN or Inf entries\n"; printed_header = true; } *out << name << "(" << v_itr - v.begin() + 1 << "," << j << ") = " << *v_itr << std::endl; } has_nan_or_inf = true; } } } if( has_nan_or_inf && throw_excpt ) { if(out) out->flush(); std::ostringstream omsg; omsg << "assert_print_nan_inf(...) : Error, the matrix named " << name << " has at least one element which is NaN or Inf"; throw NaNInfException( omsg.str() ); } return has_nan_or_inf; }
bool DenseLinAlgPack::comp(const DMatrixSlice& gms, value_type alpha) { for(size_type i = 1; i < gms.cols(); ++i) if( !comp( gms.col(i) , alpha ) ) return false; return true; }
// gms_lhs = op(gms_rhs) void DenseLinAlgPack::assign(DMatrixSlice* gms_lhs, const DMatrixSlice& gms_rhs, BLAS_Cpp::Transp trans_rhs) { assert_gms_lhs(*gms_lhs,gms_rhs.rows(),gms_rhs.cols(),trans_rhs); i_assign(gms_lhs, gms_rhs, trans_rhs); }
inline DMatrix::DMatrix(const DMatrixSlice& gms) : v_(gms.rows() * gms.cols()), rows_(gms.rows()) { assign(this, gms, BLAS_Cpp::no_trans); }