inline void smat_smat_mult(const MatrixA& a, const MatrixB& b, MatrixC& c, Assign, tag::col_major, // orientation a tag::row_major) // orientation b { if (Assign::init_to_zero) set_to_zero(c); // Average numbers of non-zeros per row double ava= double(a.nnz()) / num_rows(a), avb= double(b.nnz()) / num_rows(b); // Define Updater type corresponding to assign mode typedef typename Collection<MatrixC>::value_type c_value_type; typedef typename operations::update_assign_mode<Assign, c_value_type>::type Updater; // Reserve 20% over the average's product for entries in c matrix::inserter<MatrixC, Updater> ins(c, int( ava * avb * 1.2 )); typename traits::row<MatrixA>::type row_a(a); typename traits::col<MatrixA>::type col_a(a); typename traits::const_value<MatrixA>::type value_a(a); typename traits::row<MatrixB>::type row_b(b); typename traits::col<MatrixB>::type col_b(b); typename traits::const_value<MatrixB>::type value_b(b); typedef typename traits::range_generator<tag::col, MatrixA>::type a_cursor_type; a_cursor_type a_cursor = begin<tag::col>(a), a_cend = end<tag::col>(a); typedef typename traits::range_generator<tag::row, MatrixB>::type b_cursor_type; b_cursor_type b_cursor = begin<tag::row>(b); for (unsigned ca= 0; a_cursor != a_cend; ++ca, ++a_cursor, ++b_cursor) { // Iterate over non-zeros of A's column typedef typename traits::range_generator<tag::nz, a_cursor_type>::type ia_cursor_type; for (ia_cursor_type ia_cursor = begin<tag::nz>(a_cursor), ia_cend = end<tag::nz>(a_cursor); ia_cursor != ia_cend; ++ia_cursor) { typename Collection<MatrixA>::size_type ra= row_a(*ia_cursor); // row of non-zero typename Collection<MatrixA>::value_type va= value_a(*ia_cursor); // value of non-zero // Iterate over non-zeros of B's row typedef typename traits::range_generator<tag::nz, b_cursor_type>::type ib_cursor_type; for (ib_cursor_type ib_cursor = begin<tag::nz>(b_cursor), ib_cend = end<tag::nz>(b_cursor); ib_cursor != ib_cend; ++ib_cursor) { typename Collection<MatrixB>::size_type cb= col_b(*ib_cursor); // column of non-zero typename Collection<MatrixB>::value_type vb= value_b(*ib_cursor); // value of non-zero ins(ra, cb) << va * vb; } } } }
inline void smat_smat_mult(const MatrixA& A, const MatrixB& B, MatrixC& C, Assign, tag::col_major, // orientation A tag::row_major) // orientation B { if (Assign::init_to_zero) set_to_zero(C); // Average numbers of non-zeros per row double ava= double(A.nnz()) / num_rows(A), avb= double(B.nnz()) / num_rows(B); // Define Updater type corresponding to assign mode typedef typename Collection<MatrixC>::value_type C_value_type; typedef typename operations::update_assign_mode<Assign, C_value_type>::type Updater; // Reserve 20% over the average's product for entries in C matrix::inserter<MatrixC, Updater> ins(C, int( ava * avb * 1.2 )); typename traits::row<MatrixA>::type row_A(A); typename traits::col<MatrixA>::type col_A(A); typename traits::const_value<MatrixA>::type value_A(A); typename traits::row<MatrixB>::type row_B(B); typename traits::col<MatrixB>::type col_B(B); typename traits::const_value<MatrixB>::type value_B(B); typedef typename traits::range_generator<tag::col, MatrixA>::type A_cursor_type; A_cursor_type A_cursor = begin<tag::col>(A), A_cend = end<tag::col>(A); typedef typename traits::range_generator<tag::row, MatrixB>::type B_cursor_type; B_cursor_type B_cursor = begin<tag::row>(B); for (unsigned ca= 0; A_cursor != A_cend; ++ca, ++A_cursor, ++B_cursor) { // Iterate over non-zeros of A's column typedef typename traits::range_generator<tag::nz, A_cursor_type>::type ia_cursor_type; for (ia_cursor_type ia_cursor = begin<tag::nz>(A_cursor), ia_cend = end<tag::nz>(A_cursor); ia_cursor != ia_cend; ++ia_cursor) { typename Collection<MatrixA>::size_type ra= row_A(*ia_cursor); // row of non-zero typename Collection<MatrixA>::value_type va= value_A(*ia_cursor); // value of non-zero // Iterate over non-zeros of B's row typedef typename traits::range_generator<tag::nz, B_cursor_type>::type ib_cursor_type; for (ib_cursor_type ib_cursor = begin<tag::nz>(B_cursor), ib_cend = end<tag::nz>(B_cursor); ib_cursor != ib_cend; ++ib_cursor) { typename Collection<MatrixB>::size_type cb= col_B(*ib_cursor); // column of non-zero typename Collection<MatrixB>::value_type vb= value_B(*ib_cursor); // value of non-zero ins(ra, cb) << va * vb; } } } }
inline void smat_smat_mult(const MatrixA& A, const MatrixB& B, MatrixC& C, Assign, tag::row_major, // orientation A tag::row_major) // orientation B { if (Assign::init_to_zero) set_to_zero(C); // Average numbers of non-zeros per row double ava= num_cols(A) ? double(A.nnz()) / num_cols(A) : 0, avb= num_rows(B) ? double(B.nnz()) / num_rows(B) : 0; // Define Updater type corresponding to assign mode typedef typename Collection<MatrixC>::value_type C_value_type; typedef typename operations::update_assign_mode<Assign, C_value_type>::type Updater; // Reserve 20% over the average's product for entries in C matrix::inserter<MatrixC, Updater> ins(C, int( ava * avb * 1.4 )); typename traits::row<MatrixA>::type row_A(A); typename traits::col<MatrixA>::type col_A(A); typename traits::const_value<MatrixA>::type value_A(A); typename traits::col<MatrixB>::type col_B(B); typename traits::const_value<MatrixB>::type value_B(B); typedef typename traits::range_generator<tag::row, MatrixA>::type cursor_type; cursor_type cursor = begin<tag::row>(A), cend = end<tag::row>(A); for (unsigned ra= 0; cursor != cend; ++ra, ++cursor) { // Iterate over non-zeros of each row of A typedef typename traits::range_generator<tag::nz, cursor_type>::type icursor_type; for (icursor_type icursor = begin<tag::nz>(cursor), icend = end<tag::nz>(cursor); icursor != icend; ++icursor) { typename Collection<MatrixA>::size_type ca= col_A(*icursor); // column of non-zero typename Collection<MatrixA>::value_type va= value_A(*icursor); // value of non-zero // Get cursor corresponding to row 'ca' in matrix B typedef typename traits::range_generator<tag::row, MatrixB>::type B_cursor_type; B_cursor_type B_cursor = begin<tag::row>(B); B_cursor+= ca; // Iterate over non-zeros of this row typedef typename traits::range_generator<tag::nz, B_cursor_type>::type ib_cursor_type; for (ib_cursor_type ib_cursor = begin<tag::nz>(B_cursor), ib_cend = end<tag::nz>(B_cursor); ib_cursor != ib_cend; ++ib_cursor) { typename Collection<MatrixB>::size_type cb= col_B(*ib_cursor); // column of non-zero typename Collection<MatrixB>::value_type vb= value_B(*ib_cursor); // value of non-zero ins(ra, cb) << va * vb; } } } }