1 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 // vi: set et ts=4 sw=2 sts=2: 3 #ifndef DUNE_ISTL_MATRIXMATRIX_HH 4 #define DUNE_ISTL_MATRIXMATRIX_HH 5 6 #include <tuple> 7 8 #include <dune/istl/bcrsmatrix.hh> 9 #include <dune/common/fmatrix.hh> 10 #include <dune/common/timer.hh> 11 namespace Dune 12 { 13 14 /** 15 * @addtogroup ISTL_SPMV 16 * 17 * @{ 18 */ 19 /** @file 20 * @author Markus Blatt 21 * @brief provides functions for sparse matrix matrix multiplication. 22 */ 23 24 namespace 25 { 26 27 /** 28 * @brief Traverses over the nonzero pattern of the matrix-matrix product. 29 * 30 * Template parameter b is used to select the matrix product: 31 * <dt>0</dt><dd>\f$A\cdot B\f$</dd> 32 * <dt>1</dt><dd>\f$A^T\cdot B\f$</dd> 33 * <dt>2</dt><dd>\f$A\cdot B^T\f$</dd> 34 */ 35 template<int b> 36 struct NonzeroPatternTraverser 37 {}; 38 39 40 template<> 41 struct NonzeroPatternTraverser<0> 42 { 43 template<class T,class A1, class A2, class F, int n, int m, int k> traverseDune::__anonfffd6b010111::NonzeroPatternTraverser44 static void traverse(const Dune::BCRSMatrix<Dune::FieldMatrix<T,n,k>,A1>& A, 45 const Dune::BCRSMatrix<Dune::FieldMatrix<T,k,m>,A2>& B, 46 F& func) 47 { 48 if(A.M()!=B.N()) 49 DUNE_THROW(ISTLError, "The sizes of the matrices do not match: "<<A.M()<<"!="<<B.N()); 50 51 typedef typename Dune::BCRSMatrix<Dune::FieldMatrix<T,n,k>,A1>::ConstRowIterator Row; 52 typedef typename Dune::BCRSMatrix<Dune::FieldMatrix<T,n,k>,A1>::ConstColIterator Col; 53 typedef typename Dune::BCRSMatrix<Dune::FieldMatrix<T,k,m>,A2>::ConstColIterator BCol; 54 for(Row row= A.begin(); row != A.end(); ++row) { 55 // Loop over all column entries 56 for(Col col = row->begin(); col != row->end(); ++col) { 57 // entry at i,k 58 // search for all nonzeros in row k 59 for(BCol bcol = B[col.index()].begin(); bcol != B[col.index()].end(); ++bcol) { 60 func(*col, *bcol, row.index(), bcol.index()); 61 } 62 } 63 } 64 } 65 66 }; 67 68 template<> 69 struct NonzeroPatternTraverser<1> 70 { 71 template<class T, class A1, class A2, class F, int n, int m, int k> traverseDune::__anonfffd6b010111::NonzeroPatternTraverser72 static void traverse(const Dune::BCRSMatrix<Dune::FieldMatrix<T,k,n>,A1>& A, 73 const Dune::BCRSMatrix<Dune::FieldMatrix<T,k,m>,A2>& B, 74 F& func) 75 { 76 77 if(A.N()!=B.N()) 78 DUNE_THROW(ISTLError, "The sizes of the matrices do not match: "<<A.N()<<"!="<<B.N()); 79 80 typedef typename Dune::BCRSMatrix<Dune::FieldMatrix<T,k,n>,A1>::ConstRowIterator Row; 81 typedef typename Dune::BCRSMatrix<Dune::FieldMatrix<T,k,n>,A1>::ConstColIterator Col; 82 typedef typename Dune::BCRSMatrix<Dune::FieldMatrix<T,k,m>,A2>::ConstColIterator BCol; 83 84 for(Row row=A.begin(); row!=A.end(); ++row) { 85 for(Col col=row->begin(); col!=row->end(); ++col) { 86 for(BCol bcol = B[row.index()].begin(); bcol != B[row.index()].end(); ++bcol) { 87 func(*col, *bcol, col.index(), bcol.index()); 88 } 89 } 90 } 91 } 92 }; 93 94 template<> 95 struct NonzeroPatternTraverser<2> 96 { 97 template<class T, class A1, class A2, class F, int n, int m, int k> traverseDune::__anonfffd6b010111::NonzeroPatternTraverser98 static void traverse(const BCRSMatrix<FieldMatrix<T,n,m>,A1>& mat, 99 const BCRSMatrix<FieldMatrix<T,k,m>,A2>& matt, 100 F& func) 101 { 102 if(mat.M()!=matt.M()) 103 DUNE_THROW(ISTLError, "The sizes of the matrices do not match: "<<mat.M()<<"!="<<matt.M()); 104 105 typedef typename BCRSMatrix<FieldMatrix<T,n,m>,A1>::ConstRowIterator row_iterator; 106 typedef typename BCRSMatrix<FieldMatrix<T,n,m>,A1>::ConstColIterator col_iterator; 107 typedef typename BCRSMatrix<FieldMatrix<T,k,m>,A2>::ConstRowIterator row_iterator_t; 108 typedef typename BCRSMatrix<FieldMatrix<T,k,m>,A2>::ConstColIterator col_iterator_t; 109 110 for(row_iterator mrow=mat.begin(); mrow != mat.end(); ++mrow) { 111 //iterate over the column entries 112 // mt is a transposed matrix crs therefore it is treated as a ccs matrix 113 // and the row_iterator iterates over the columns of the transposed matrix. 114 // search the row of the transposed matrix for an entry with the same index 115 // as the mcol iterator 116 117 for(row_iterator_t mtcol=matt.begin(); mtcol != matt.end(); ++mtcol) { 118 //Search for col entries in mat that have a corrsponding row index in matt 119 // (i.e. corresponding col index in the as this is the transposed matrix 120 col_iterator_t mtrow=mtcol->begin(); 121 bool funcCalled = false; 122 for(col_iterator mcol=mrow->begin(); mcol != mrow->end(); ++mcol) { 123 // search 124 // TODO: This should probably be substituted by a binary search 125 for( ; mtrow != mtcol->end(); ++mtrow) 126 if(mtrow.index()>=mcol.index()) 127 break; 128 if(mtrow != mtcol->end() && mtrow.index()==mcol.index()) { 129 func(*mcol, *mtrow, mtcol.index()); 130 funcCalled = true; 131 // In some cases we only search for one pair, then we break here 132 // and continue with the next column. 133 if(F::do_break) 134 break; 135 } 136 } 137 // move on with func only if func was called, otherwise they might 138 // get out of sync 139 if (funcCalled) 140 func.nextCol(); 141 } 142 func.nextRow(); 143 } 144 } 145 }; 146 147 148 149 template<class T, class A, int n, int m> 150 class SparsityPatternInitializer 151 { 152 public: 153 enum {do_break=true}; 154 typedef typename BCRSMatrix<FieldMatrix<T,n,m>,A>::CreateIterator CreateIterator; 155 typedef typename BCRSMatrix<FieldMatrix<T,n,m>,A>::size_type size_type; 156 SparsityPatternInitializer(CreateIterator iter)157 SparsityPatternInitializer(CreateIterator iter) 158 : rowiter(iter) 159 {} 160 161 template<class T1, class T2> operator ()(const T1 &,const T2 &,size_type j)162 void operator()(const T1&, const T2&, size_type j) 163 { 164 rowiter.insert(j); 165 } 166 nextRow()167 void nextRow() 168 { 169 ++rowiter; 170 } nextCol()171 void nextCol() 172 {} 173 174 private: 175 CreateIterator rowiter; 176 }; 177 178 179 template<int transpose, class T, class TA, int n, int m> 180 class MatrixInitializer 181 { 182 public: 183 enum {do_break=true}; 184 typedef typename Dune::BCRSMatrix<FieldMatrix<T,n,m>,TA> Matrix; 185 typedef typename Matrix::CreateIterator CreateIterator; 186 typedef typename Matrix::size_type size_type; 187 MatrixInitializer(Matrix & A_,size_type)188 MatrixInitializer(Matrix& A_, size_type) 189 : count(0), A(A_) 190 {} 191 template<class T1, class T2> operator ()(const T1 &,const T2 &,int)192 void operator()(const T1&, const T2&, int) 193 { 194 ++count; 195 } 196 nextCol()197 void nextCol() 198 {} 199 nextRow()200 void nextRow() 201 {} 202 nonzeros()203 std::size_t nonzeros() 204 { 205 return count; 206 } 207 208 template<class A1, class A2, int n2, int m2, int n3, int m3> initPattern(const BCRSMatrix<FieldMatrix<T,n2,m2>,A1> & mat1,const BCRSMatrix<FieldMatrix<T,n3,m3>,A2> & mat2)209 void initPattern(const BCRSMatrix<FieldMatrix<T,n2,m2>,A1>& mat1, 210 const BCRSMatrix<FieldMatrix<T,n3,m3>,A2>& mat2) 211 { 212 SparsityPatternInitializer<T, TA, n, m> sparsity(A.createbegin()); 213 NonzeroPatternTraverser<transpose>::traverse(mat1,mat2,sparsity); 214 } 215 216 private: 217 std::size_t count; 218 Matrix& A; 219 }; 220 221 template<class T, class TA, int n, int m> 222 class MatrixInitializer<1,T,TA,n,m> 223 { 224 public: 225 enum {do_break=false}; 226 typedef Dune::BCRSMatrix<Dune::FieldMatrix<T,n,m>,TA> Matrix; 227 typedef typename Matrix::CreateIterator CreateIterator; 228 typedef typename Matrix::size_type size_type; 229 MatrixInitializer(Matrix & A_,size_type rows)230 MatrixInitializer(Matrix& A_, size_type rows) 231 : A(A_), entries(rows) 232 {} 233 234 template<class T1, class T2> operator ()(const T1 &,const T2 &,size_type i,size_type j)235 void operator()(const T1&, const T2&, size_type i, size_type j) 236 { 237 entries[i].insert(j); 238 } 239 nextCol()240 void nextCol() 241 {} 242 nonzeros()243 size_type nonzeros() 244 { 245 size_type nnz=0; 246 typedef typename std::vector<std::set<size_t> >::const_iterator Iter; 247 for(Iter iter = entries.begin(); iter != entries.end(); ++iter) 248 nnz+=(*iter).size(); 249 return nnz; 250 } 251 template<class A1, class A2, int n2, int m2, int n3, int m3> initPattern(const BCRSMatrix<FieldMatrix<T,n2,m2>,A1> &,const BCRSMatrix<FieldMatrix<T,n3,m3>,A2> &)252 void initPattern(const BCRSMatrix<FieldMatrix<T,n2,m2>,A1>&, 253 const BCRSMatrix<FieldMatrix<T,n3,m3>,A2>&) 254 { 255 typedef typename std::vector<std::set<size_t> >::const_iterator Iter; 256 CreateIterator citer = A.createbegin(); 257 for(Iter iter = entries.begin(); iter != entries.end(); ++iter, ++citer) { 258 typedef std::set<size_t>::const_iterator SetIter; 259 for(SetIter index=iter->begin(); index != iter->end(); ++index) 260 citer.insert(*index); 261 } 262 } 263 264 private: 265 Matrix& A; 266 std::vector<std::set<size_t> > entries; 267 }; 268 269 template<class T, class TA, int n, int m> 270 struct MatrixInitializer<0,T,TA,n,m> 271 : public MatrixInitializer<1,T,TA,n,m> 272 { MatrixInitializerDune::__anonfffd6b010111::MatrixInitializer273 MatrixInitializer(Dune::BCRSMatrix<Dune::FieldMatrix<T,n,m>,TA>& A_, 274 typename Dune::BCRSMatrix<Dune::FieldMatrix<T,n,m>,TA>::size_type rows) 275 : MatrixInitializer<1,T,TA,n,m>(A_,rows) 276 {} 277 }; 278 279 280 template<class T, class T1, class T2, int n, int m, int k> addMatMultTransposeMat(FieldMatrix<T,n,k> & res,const FieldMatrix<T1,n,m> & mat,const FieldMatrix<T2,k,m> & matt)281 void addMatMultTransposeMat(FieldMatrix<T,n,k>& res, const FieldMatrix<T1,n,m>& mat, 282 const FieldMatrix<T2,k,m>& matt) 283 { 284 typedef typename FieldMatrix<T,n,k>::size_type size_type; 285 286 for(size_type row=0; row<n; ++row) 287 for(size_type col=0; col<k; ++col) { 288 for(size_type i=0; i < m; ++i) 289 res[row][col]+=mat[row][i]*matt[col][i]; 290 } 291 } 292 293 template<class T, class T1, class T2, int n, int m, int k> addTransposeMatMultMat(FieldMatrix<T,n,k> & res,const FieldMatrix<T1,m,n> & mat,const FieldMatrix<T2,m,k> & matt)294 void addTransposeMatMultMat(FieldMatrix<T,n,k>& res, const FieldMatrix<T1,m,n>& mat, 295 const FieldMatrix<T2,m,k>& matt) 296 { 297 typedef typename FieldMatrix<T,n,k>::size_type size_type; 298 for(size_type i=0; i<m; ++i) 299 for(size_type row=0; row<n; ++row) { 300 for(size_type col=0; col < k; ++col) 301 res[row][col]+=mat[i][row]*matt[i][col]; 302 } 303 } 304 305 template<class T, class T1, class T2, int n, int m, int k> addMatMultMat(FieldMatrix<T,n,m> & res,const FieldMatrix<T1,n,k> & mat,const FieldMatrix<T2,k,m> & matt)306 void addMatMultMat(FieldMatrix<T,n,m>& res, const FieldMatrix<T1,n,k>& mat, 307 const FieldMatrix<T2,k,m>& matt) 308 { 309 typedef typename FieldMatrix<T,n,k>::size_type size_type; 310 for(size_type row=0; row<n; ++row) 311 for(size_type col=0; col<m; ++col) { 312 for(size_type i=0; i < k; ++i) 313 res[row][col]+=mat[row][i]*matt[i][col]; 314 } 315 } 316 317 318 template<class T, class A, int n, int m> 319 class EntryAccumulatorFather 320 { 321 public: 322 enum {do_break=false}; 323 typedef BCRSMatrix<FieldMatrix<T,n,m>,A> Matrix; 324 typedef typename Matrix::RowIterator Row; 325 typedef typename Matrix::ColIterator Col; 326 EntryAccumulatorFather(Matrix & mat_)327 EntryAccumulatorFather(Matrix& mat_) 328 : mat(mat_), row(mat.begin()) 329 { 330 mat=0; 331 col=row->begin(); 332 } nextRow()333 void nextRow() 334 { 335 ++row; 336 if(row!=mat.end()) 337 col=row->begin(); 338 } 339 nextCol()340 void nextCol() 341 { 342 ++this->col; 343 } 344 protected: 345 Matrix& mat; 346 private: 347 Row row; 348 protected: 349 Col col; 350 }; 351 352 template<class T, class A, int n, int m, int transpose> 353 class EntryAccumulator 354 : public EntryAccumulatorFather<T,A,n,m> 355 { 356 public: 357 typedef BCRSMatrix<FieldMatrix<T,n,m>,A> Matrix; 358 typedef typename Matrix::size_type size_type; 359 EntryAccumulator(Matrix & mat_)360 EntryAccumulator(Matrix& mat_) 361 : EntryAccumulatorFather<T,A,n,m>(mat_) 362 {} 363 364 template<class T1, class T2> operator ()(const T1 & t1,const T2 & t2,size_type i)365 void operator()(const T1& t1, const T2& t2, size_type i) 366 { 367 assert(this->col.index()==i); 368 addMatMultMat(*(this->col),t1,t2); 369 } 370 }; 371 372 template<class T, class A, int n, int m> 373 class EntryAccumulator<T,A,n,m,0> 374 : public EntryAccumulatorFather<T,A,n,m> 375 { 376 public: 377 typedef BCRSMatrix<FieldMatrix<T,n,m>,A> Matrix; 378 typedef typename Matrix::size_type size_type; 379 EntryAccumulator(Matrix & mat_)380 EntryAccumulator(Matrix& mat_) 381 : EntryAccumulatorFather<T,A,n,m>(mat_) 382 {} 383 384 template<class T1, class T2> operator ()(const T1 & t1,const T2 & t2,size_type i,size_type j)385 void operator()(const T1& t1, const T2& t2, size_type i, size_type j) 386 { 387 addMatMultMat(this->mat[i][j], t1, t2); 388 } 389 }; 390 391 template<class T, class A, int n, int m> 392 class EntryAccumulator<T,A,n,m,1> 393 : public EntryAccumulatorFather<T,A,n,m> 394 { 395 public: 396 typedef BCRSMatrix<FieldMatrix<T,n,m>,A> Matrix; 397 typedef typename Matrix::size_type size_type; 398 EntryAccumulator(Matrix & mat_)399 EntryAccumulator(Matrix& mat_) 400 : EntryAccumulatorFather<T,A,n,m>(mat_) 401 {} 402 403 template<class T1, class T2> operator ()(const T1 & t1,const T2 & t2,size_type i,size_type j)404 void operator()(const T1& t1, const T2& t2, size_type i, size_type j) 405 { 406 addTransposeMatMultMat(this->mat[i][j], t1, t2); 407 } 408 }; 409 410 template<class T, class A, int n, int m> 411 class EntryAccumulator<T,A,n,m,2> 412 : public EntryAccumulatorFather<T,A,n,m> 413 { 414 public: 415 typedef BCRSMatrix<FieldMatrix<T,n,m>,A> Matrix; 416 typedef typename Matrix::size_type size_type; 417 EntryAccumulator(Matrix & mat_)418 EntryAccumulator(Matrix& mat_) 419 : EntryAccumulatorFather<T,A,n,m>(mat_) 420 {} 421 422 template<class T1, class T2> operator ()(const T1 & t1,const T2 & t2,size_type i)423 void operator()(const T1& t1, const T2& t2, [[maybe_unused]] size_type i) 424 { 425 assert(this->col.index()==i); 426 addMatMultTransposeMat(*this->col,t1,t2); 427 } 428 }; 429 430 431 template<int transpose> 432 struct SizeSelector 433 {}; 434 435 template<> 436 struct SizeSelector<0> 437 { 438 template<class M1, class M2> 439 static std::tuple<typename M1::size_type, typename M2::size_type> sizeDune::__anonfffd6b010111::SizeSelector440 size(const M1& m1, const M2& m2) 441 { 442 return std::make_tuple(m1.N(), m2.M()); 443 } 444 }; 445 446 template<> 447 struct SizeSelector<1> 448 { 449 template<class M1, class M2> 450 static std::tuple<typename M1::size_type, typename M2::size_type> sizeDune::__anonfffd6b010111::SizeSelector451 size(const M1& m1, const M2& m2) 452 { 453 return std::make_tuple(m1.M(), m2.M()); 454 } 455 }; 456 457 458 template<> 459 struct SizeSelector<2> 460 { 461 template<class M1, class M2> 462 static std::tuple<typename M1::size_type, typename M2::size_type> sizeDune::__anonfffd6b010111::SizeSelector463 size(const M1& m1, const M2& m2) 464 { 465 return std::make_tuple(m1.N(), m2.N()); 466 } 467 }; 468 469 template<int transpose, class T, class A, class A1, class A2, int n1, int m1, int n2, int m2, int n3, int m3> matMultMat(BCRSMatrix<FieldMatrix<T,n1,m1>,A> & res,const BCRSMatrix<FieldMatrix<T,n2,m2>,A1> & mat1,const BCRSMatrix<FieldMatrix<T,n3,m3>,A2> & mat2)470 void matMultMat(BCRSMatrix<FieldMatrix<T,n1,m1>,A>& res, const BCRSMatrix<FieldMatrix<T,n2,m2>,A1>& mat1, 471 const BCRSMatrix<FieldMatrix<T,n3,m3>,A2>& mat2) 472 { 473 // First step is to count the number of nonzeros 474 typename BCRSMatrix<FieldMatrix<T,n1,m1>,A>::size_type rows, cols; 475 std::tie(rows,cols)=SizeSelector<transpose>::size(mat1, mat2); 476 MatrixInitializer<transpose,T,A,n1,m1> patternInit(res, rows); 477 Timer timer; 478 NonzeroPatternTraverser<transpose>::traverse(mat1,mat2,patternInit); 479 res.setSize(rows, cols, patternInit.nonzeros()); 480 res.setBuildMode(BCRSMatrix<FieldMatrix<T,n1,m1>,A>::row_wise); 481 482 //std::cout<<"Counting nonzeros took "<<timer.elapsed()<<std::endl; 483 timer.reset(); 484 485 // Second step is to allocate the storage for the result and initialize the nonzero pattern 486 patternInit.initPattern(mat1, mat2); 487 488 //std::cout<<"Setting up sparsity pattern took "<<timer.elapsed()<<std::endl; 489 timer.reset(); 490 // As a last step calculate the entries 491 res = 0.0; 492 EntryAccumulator<T,A,n1,m1, transpose> entriesAccu(res); 493 NonzeroPatternTraverser<transpose>::traverse(mat1,mat2,entriesAccu); 494 //std::cout<<"Calculating entries took "<<timer.elapsed()<<std::endl; 495 } 496 497 } 498 499 /** 500 * @brief Helper TMP to get the result type of a sparse matrix matrix multiplication (\f$C=A*B\f$) 501 * 502 * The type of matrix C will be stored as the associated type MatMultMatResult::type. 503 * @tparam M1 The type of matrix A. 504 * @tparam M2 The type of matrix B. 505 */ 506 template<typename M1, typename M2> 507 struct MatMultMatResult 508 {}; 509 510 template<typename T, int n, int k, int m> 511 struct MatMultMatResult<FieldMatrix<T,n,k>,FieldMatrix<T,k,m> > 512 { 513 typedef FieldMatrix<T,n,m> type; 514 }; 515 516 template<typename T, typename A, typename A1, int n, int k, int m> 517 struct MatMultMatResult<BCRSMatrix<FieldMatrix<T,n,k>,A >,BCRSMatrix<FieldMatrix<T,k,m>,A1 > > 518 { 519 typedef BCRSMatrix<typename MatMultMatResult<FieldMatrix<T,n,k>,FieldMatrix<T,k,m> >::type, 520 std::allocator<typename MatMultMatResult<FieldMatrix<T,n,k>,FieldMatrix<T,k,m> >::type> > type; 521 }; 522 523 524 /** 525 * @brief Helper TMP to get the result type of a sparse matrix matrix multiplication (\f$C=A*B\f$) 526 * 527 * The type of matrix C will be stored as the associated type MatMultMatResult::type. 528 * @tparam M1 The type of matrix A. 529 * @tparam M2 The type of matrix B. 530 */ 531 template<typename M1, typename M2> 532 struct TransposedMatMultMatResult 533 {}; 534 535 template<typename T, int n, int k, int m> 536 struct TransposedMatMultMatResult<FieldMatrix<T,k,n>,FieldMatrix<T,k,m> > 537 { 538 typedef FieldMatrix<T,n,m> type; 539 }; 540 541 template<typename T, typename A, typename A1, int n, int k, int m> 542 struct TransposedMatMultMatResult<BCRSMatrix<FieldMatrix<T,k,n>,A >,BCRSMatrix<FieldMatrix<T,k,m>,A1 > > 543 { 544 typedef BCRSMatrix<typename MatMultMatResult<FieldMatrix<T,n,k>,FieldMatrix<T,k,m> >::type, 545 std::allocator<typename MatMultMatResult<FieldMatrix<T,n,k>,FieldMatrix<T,k,m> >::type> > type; 546 }; 547 548 549 /** 550 * @brief Calculate product of a sparse matrix with a transposed sparse matrices (\f$C=A*B^T\f$). 551 * 552 * @param res Matrix for the result of the computation. 553 * @param mat Matrix A. 554 * @param matt Matrix B, which will be transposed before the multiplication. 555 * @param tryHard <i>ignored</i> 556 */ 557 template<class T, class A, class A1, class A2, int n, int m, int k> matMultTransposeMat(BCRSMatrix<FieldMatrix<T,n,k>,A> & res,const BCRSMatrix<FieldMatrix<T,n,m>,A1> & mat,const BCRSMatrix<FieldMatrix<T,k,m>,A2> & matt,bool tryHard=false)558 void matMultTransposeMat(BCRSMatrix<FieldMatrix<T,n,k>,A>& res, const BCRSMatrix<FieldMatrix<T,n,m>,A1>& mat, 559 const BCRSMatrix<FieldMatrix<T,k,m>,A2>& matt, [[maybe_unused]] bool tryHard=false) 560 { 561 matMultMat<2>(res,mat, matt); 562 } 563 564 /** 565 * @brief Calculate product of two sparse matrices (\f$C=A*B\f$). 566 * 567 * @param res Matrix for the result of the computation. 568 * @param mat Matrix A. 569 * @param matt Matrix B. 570 * @param tryHard <i>ignored</i> 571 */ 572 template<class T, class A, class A1, class A2, int n, int m, int k> matMultMat(BCRSMatrix<FieldMatrix<T,n,m>,A> & res,const BCRSMatrix<FieldMatrix<T,n,k>,A1> & mat,const BCRSMatrix<FieldMatrix<T,k,m>,A2> & matt,bool tryHard=false)573 void matMultMat(BCRSMatrix<FieldMatrix<T,n,m>,A>& res, const BCRSMatrix<FieldMatrix<T,n,k>,A1>& mat, 574 const BCRSMatrix<FieldMatrix<T,k,m>,A2>& matt, bool tryHard=false) 575 { 576 matMultMat<0>(res,mat, matt); 577 } 578 579 /** 580 * @brief Calculate product of a transposed sparse matrix with another sparse matrices (\f$C=A^T*B\f$). 581 * 582 * @param res Matrix for the result of the computation. 583 * @param mat Matrix A, which will be transposed before the multiplication. 584 * @param matt Matrix B. 585 * @param tryHard <i>ignored</i> 586 */ 587 template<class T, class A, class A1, class A2, int n, int m, int k> transposeMatMultMat(BCRSMatrix<FieldMatrix<T,n,m>,A> & res,const BCRSMatrix<FieldMatrix<T,k,n>,A1> & mat,const BCRSMatrix<FieldMatrix<T,k,m>,A2> & matt,bool tryHard=false)588 void transposeMatMultMat(BCRSMatrix<FieldMatrix<T,n,m>,A>& res, const BCRSMatrix<FieldMatrix<T,k,n>,A1>& mat, 589 const BCRSMatrix<FieldMatrix<T,k,m>,A2>& matt, [[maybe_unused]] bool tryHard=false) 590 { 591 matMultMat<1>(res,mat, matt); 592 } 593 594 } 595 #endif 596