mat_vec_mult.hpp

来自「矩阵运算源码最新版本」· HPP 代码 · 共 207 行

HPP
207
字号
// Software License for MTL// // Copyright (c) 2007 The Trustees of Indiana University. All rights reserved.// Authors: Peter Gottschling and Andrew Lumsdaine// // This file is part of the Matrix Template Library// // See also license.mtl.txt in the distribution.#ifndef MTL_MAT_VEC_MULT_INCLUDE#define MTL_MAT_VEC_MULT_INCLUDE#include <boost/numeric/mtl/utility/property_map.hpp>#include <boost/numeric/mtl/utility/tag.hpp>#include <boost/numeric/mtl/detail/index.hpp>#include <boost/numeric/mtl/utility/tag.hpp>#include <boost/numeric/mtl/operation/set_to_zero.hpp>#include <boost/numeric/linear_algebra/identity.hpp>#include <iostream>namespace mtl {// Dense matrix vector multiplicationtemplate <typename Matrix, typename VectorIn, typename VectorOut, typename Assign>inline void mat_cvec_mult(const Matrix& a, const VectorIn& v, VectorOut& w, Assign, tag::dense){    // Naive implementation, will be moved to a functor and complemented with more efficient ones    using math::zero;    if (size(w) == 0) return;    if (Assign::init_to_zero) set_to_zero(w);    typedef typename Collection<VectorOut>::value_type value_type;    value_type                                         ref= w[0], z= zero(ref);    for (unsigned i= 0; i < num_rows(a); i++) {	value_type tmp= z;	for (unsigned j= 0; j < num_cols(a); j++) 	    tmp+= a[i][j] * v[j];	Assign::update(w[i], tmp);    }}// Sparse matrix vector multiplicationtemplate <typename Matrix, typename VectorIn, typename VectorOut, typename Assign>inline void mat_cvec_mult(const Matrix& a, const VectorIn& v, VectorOut& w, Assign, tag::sparse){    smat_cvec_mult(a, v, w, Assign(), typename OrientedCollection<Matrix>::orientation());}// Sparse row-major matrix vector multiplicationtemplate <typename Matrix, typename VectorIn, typename VectorOut, typename Assign>inline void smat_cvec_mult(const Matrix& a, const VectorIn& v, VectorOut& w, Assign, tag::row_major){    using namespace tag;     using traits::range_generator;      using math::zero;    typedef typename range_generator<row, Matrix>::type       a_cur_type;        typedef typename range_generator<nz, a_cur_type>::type    a_icur_type;                typename traits::col<Matrix>::type                        col_a(a);     typename traits::const_value<Matrix>::type                value_a(a);     if (Assign::init_to_zero) set_to_zero(w);    typedef typename Collection<VectorOut>::value_type        value_type;    value_type                                                ref= w[0], z= zero(ref);    a_cur_type ac= begin<row>(a), aend= end<row>(a);    for (unsigned i= 0; ac != aend; ++ac, ++i) {	value_type tmp= z;	for (a_icur_type aic= begin<nz>(ac), aiend= end<nz>(ac); aic != aiend; ++aic) 	    tmp+= value_a(*aic) * v[col_a(*aic)];		Assign::update(w[i], tmp);    }}// Sparse column-major matrix vector multiplicationtemplate <typename Matrix, typename VectorIn, typename VectorOut, typename Assign>inline void smat_cvec_mult(const Matrix& a, const VectorIn& v, VectorOut& w, Assign, tag::col_major){	using namespace tag;	using traits::range_generator;          typedef typename range_generator<col, Matrix>::type       a_cur_type;                     typedef typename range_generator<nz, a_cur_type>::type    a_icur_type;            	typename traits::row<Matrix>::type                        row_a(a); 	typename traits::const_value<Matrix>::type                value_a(a); 	if (Assign::init_to_zero) set_to_zero(w);	unsigned rv= 0; // traverse all rows of v	for (a_cur_type ac= begin<col>(a), aend= end<col>(a); ac != aend; ++ac, ++rv) {	    typename Collection<VectorIn>::value_type    vv= v[rv]; 	    for (a_icur_type aic= begin<nz>(ac), aiend= end<nz>(ac); aic != aiend; ++aic) 		Assign::update(w[row_a(*aic)], value_a(*aic) * vv);	}}} // namespace mtl#if 0// obselete code -> to be deleted soonnamespace mtl {  using std::size_t;  // general matrix vector product for dense matrices (might be slow)  // for dense2D: row major ~ 4 times faster, column major ~ 3 times slower  template <class Matrix, class Vector_in, class Vector_out>   void dense_mat_vec_mult(const Matrix& ma, const Vector_in& vin, Vector_out& vout)   {    // if (ma.num_rows() != vout.size()) throw something;    // if (ma.num_cols() != vin.size()) throw something else;    typename index::which_index<Matrix>::type m    atrix_index;    typename index::which_index<Vector_in>::type   vin_index;    typename index::which_index<Vector_out>::type  vout_index;    size_t mi= 0, mrows= ma.num_rows(), mj_start= 0, mcols= ma.num_cols(), vi= 0, vj_start= 0;        if (is_fortran_indexed<Matrix>::value) mi++, mj_start++, mrows++, mcols++;    if (is_fortran_indexed<Vector_in>::value) vj_start++;    if (is_fortran_indexed<Vector_out>::value) vi++;  #   ifdef NO_TMP_ACCUMULATE      std::cout << "not_tmp_accumulate\n";      for (; mi != mrows; mi++, vi++) {	vout[vi]= (typename Vector_out::value_type) 0;	for (size_t mj= mj_start, vj= vj_start; mj != mcols; mj++, vj++)	  vout[vi]+= ma(mi, mj) * vin[vj]; }#   else // use temporary in hope compiler uses register for summation      for (; mi != mrows; mi++, vi++) {	typename Vector_out::value_type tmp(0);	for (size_t mj= mj_start, vj= vj_start; mj != mcols; mj++, vj++)	  tmp+= ma(mi, mj) * vin[vj]; 	vout[vi]= tmp;  }#   endif  }  // general matrix vector product that iterates over matrix elements (might be slow)  template <class Matrix, class Vector_in, class Vector_out>   void mat_vec_mult(const Matrix& ma, const Vector_in& vin, Vector_out& vout) {    // if (ma.num_rows() != vout.size()) throw something;    // if (ma.num_cols() != vin.size()) throw something else;    typename indexing<Matrix>::type      mind;    typename indexing<Vector_in>::type   viind;    typename indexing<Vector_out>::type  voind;    // vout= reinterpret_cast<typename Vector_out::value_type>(0);    // ugly hack, only for testing    for (size_t i= 0; i < vout.size(); i++)      vout[iinc(i, voind)]= (typename Vector_out::value_type) 0;    typename Matrix::el_cursor_type cursor= ma.ebegin(), end= ma.eend();    for (; cursor != end; ++cursor)      vout[idec_wrt(row(ma, *cursor), mind, voind)]+=        // corrected index	value(ma, *cursor) * vin[idec_wrt(col(ma, *cursor), mind, viind)];  }  template <class ELT, size_t NF, class Vector_in, class Vector_out>   void mat_vec_mult(const fractalu<ELT, NF>& ma, const Vector_in& vin, Vector_out& vout) {    // if (ma.num_rows() != vout.size()) throw something;    // if (ma.num_cols() != vin.size()) throw something else;    typedef fractalu<ELT, NF>            Matrix;    typedef typename Vector_out::value_type ovalue_type;    typedef typename Matrix::el_cursor_type el_cursor_type;    c_index                              mind;    typename indexing<Vector_in>::type   viind;    typename indexing<Vector_out>::type  voind;    // ugly hack, only for testing    for (size_t i= 0; i < vout.size(); i++)      vout[iinc(i, voind)]= (ovalue_type) 0;    typename Matrix::block_cursor_type cursor= ma.bbegin(), end= ma.bend();    for (; cursor != end; ++cursor) {      size_t row= cursor.get_r(), col= cursor.get_c(), a= cursor.get_a(), b= cursor.get_b();      for (size_t r= row; r < row+a; r++) {	el_cursor_type el_cursor(cursor.el_cursor());	ovalue_type tmp= vout[idec_wrt(r, mind, voind)]; // try to sum in register	for (size_t c= col; c < col+b; c++)	  tmp+= value(ma, *el_cursor++) * vin[idec_wrt(c, mind, viind)];	vout[idec_wrt(r, mind, voind)]= tmp; } }  }} // namespace mtl#endif#endif // MTL_MAT_VEC_MULT_INCLUDE

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?