22 #ifndef _BLAZE_MATH_EXPRESSIONS_SMATSMATMULTEXPR_H_
23 #define _BLAZE_MATH_EXPRESSIONS_SMATSMATMULTEXPR_H_
33 #include <boost/type_traits/remove_reference.hpp>
86 template<
typename MT1
88 class SMatSMatMultExpr :
public SparseMatrix< SMatSMatMultExpr<MT1,MT2>, false >
94 typedef typename MT1::ResultType
RT1;
95 typedef typename MT2::ResultType
RT2;
96 typedef typename MT1::CompositeType
CT1;
97 typedef typename MT2::CompositeType
CT2;
142 typedef typename boost::remove_reference<CT1>::type::ConstIterator ConstIterator;
147 if(
lhs_.columns() == 0UL )
156 const ConstIterator end( A.end(i) );
157 ConstIterator element( A.begin(i) );
164 tmp = element->value() *
rhs_(element->index(),j);
166 for( ; element!=end; ++element )
167 tmp += element->value() *
rhs_(element->index(),j);
173 for(
size_t k=1UL; k<
lhs_.columns(); ++k ) {
198 return rhs_.columns();
250 template<
typename T >
252 return (
lhs_.isAliased( alias ) ||
rhs_.isAliased( alias ) );
262 template<
typename T >
264 return (
lhs_.isAliased( alias ) ||
rhs_.isAliased( alias ) );
287 template<
typename MT
297 typedef typename boost::remove_reference<CT1>::type::ConstIterator LeftIterator;
298 typedef typename boost::remove_reference<CT2>::type::ConstIterator RightIterator;
310 for(
size_t i=0UL; i<(~lhs).
rows(); ++i ) {
311 const LeftIterator lend( A.end(i) );
312 for( LeftIterator lelem=A.begin(i); lelem!=lend; ++lelem ) {
313 const RightIterator rend( B.end( lelem->index() ) );
314 for( RightIterator relem=B.begin( lelem->index() ); relem!=rend; ++relem )
316 if(
isDefault( (~lhs)(i,relem->index()) ) ) {
317 (~lhs)(i,relem->index()) = lelem->value() * relem->value();
320 (~lhs)(i,relem->index()) += lelem->value() * relem->value();
342 template<
typename MT
352 typedef typename boost::remove_reference<CT1>::type::ConstIterator LeftIterator;
353 typedef typename boost::remove_reference<CT2>::type::ConstIterator RightIterator;
365 for(
size_t i=0UL; i<(~lhs).
rows(); ++i ) {
366 const LeftIterator lend( A.end(i) );
367 for( LeftIterator lelem=A.begin(i); lelem!=lend; ++lelem ) {
368 const RightIterator rend( B.end( lelem->index() ) );
369 for( RightIterator relem=B.begin( lelem->index() ); relem!=rend; ++relem ) {
370 (~lhs)(i,relem->index()) += lelem->value() * relem->value();
390 template<
typename MT >
398 typedef typename boost::remove_reference<CT1>::type::ConstIterator LeftIterator;
399 typedef typename boost::remove_reference<CT2>::type::ConstIterator RightIterator;
412 size_t nonzeros( 0UL );
414 for(
size_t i=0UL; i<(~lhs).
rows(); ++i ) {
415 const LeftIterator lend( A.end(i) );
416 for( LeftIterator lelem=A.begin(i); lelem!=lend; ++lelem ) {
417 nonzeros += B.nonZeros( lelem->index() );
421 if( nonzeros > (~lhs).rows() * (~lhs).
columns() ) {
425 (~lhs).reserve( nonzeros );
430 std::vector<byte> valid ( (~lhs).
columns(), 0 );
431 std::vector<size_t> indices( (~lhs).
columns(), 0UL );
432 size_t minIndex(
inf ), maxIndex( 0UL );
434 for(
size_t i=0UL; i<(~lhs).
rows(); ++i )
436 const LeftIterator lend( A.end(i) );
437 for( LeftIterator lelem=A.begin(i); lelem!=lend; ++lelem )
439 const RightIterator rend( B.end( lelem->index() ) );
440 for( RightIterator relem=B.begin( lelem->index() ); relem!=rend; ++relem )
442 if( !valid[relem->index()] ) {
443 values[relem->index()] = lelem->value() * relem->value();
444 valid [relem->index()] = 1;
445 indices[nonzeros] = relem->index();
447 if( relem->index() < minIndex ) minIndex = relem->index();
448 if( relem->index() > maxIndex ) maxIndex = relem->index();
451 values[relem->index()] += lelem->value() * relem->value();
462 if( ( nonzeros + nonzeros ) < ( maxIndex - minIndex ) )
464 std::sort( indices.begin(), indices.begin() + nonzeros );
466 for(
size_t j=0UL; j<nonzeros; ++j )
468 const size_t index( indices[j] );
470 (~lhs).append( i, index, values[index] );
471 reset( values[index] );
474 reset( valid [index] );
478 for(
size_t j=minIndex; j<=maxIndex; ++j )
481 (~lhs).append( i, j, values[j] );
494 (~lhs).finalize( i );
512 template<
typename MT >
523 const typename MT1::OppositeType A( rhs.lhs_ );
524 const typename MT2::OppositeType B( rhs.rhs_ );
542 template<
typename MT
551 typedef typename boost::remove_reference<CT1>::type::ConstIterator LeftIterator;
552 typedef typename boost::remove_reference<CT2>::type::ConstIterator RightIterator;
564 for(
size_t i=0UL; i<(~lhs).
rows(); ++i ) {
565 const LeftIterator lend( A.end(i) );
566 for( LeftIterator lelem=A.begin(i); lelem!=lend; ++lelem ) {
567 const RightIterator rend( B.end( lelem->index() ) );
568 for( RightIterator relem=B.begin( lelem->index() ); relem!=rend; ++relem ) {
569 (~lhs)(i,relem->index()) += lelem->value() * relem->value();
594 template<
typename MT
603 typedef typename boost::remove_reference<CT1>::type::ConstIterator LeftIterator;
604 typedef typename boost::remove_reference<CT2>::type::ConstIterator RightIterator;
616 for(
size_t i=0UL; i<(~lhs).
rows(); ++i ) {
617 const LeftIterator lend( A.end(i) );
618 for( LeftIterator lelem=A.begin(i); lelem!=lend; ++lelem ) {
619 const RightIterator rend( B.end( lelem->index() ) );
620 for( RightIterator relem=B.begin( lelem->index() ); relem!=rend; ++relem ) {
621 (~lhs)(i,relem->index()) -= lelem->value() * relem->value();
688 template<
typename T1
690 inline const SMatSMatMultExpr<T1,T2>
696 throw std::invalid_argument(
"Matrix sizes do not match" );
724 template<
typename T1
726 inline typename RowExprTrait< SMatSMatMultExpr<T1,T2> >::Type
727 row(
const SMatSMatMultExpr<T1,T2>& sm,
size_t index )
731 return row( sm.leftOperand(), index ) * sm.rightOperand();
750 template<
typename T1
752 inline typename ColumnExprTrait< SMatSMatMultExpr<T1,T2> >::Type
753 column(
const SMatSMatMultExpr<T1,T2>& sm,
size_t index )
757 return sm.leftOperand() *
column( sm.rightOperand(), index );
773 template<
typename MT1,
typename MT2,
typename VT >
774 struct SMatDVecMultExprTrait< SMatSMatMultExpr<MT1,MT2>, VT >
778 typedef typename SelectType< IsSparseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
779 IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value &&
780 IsDenseVector<VT>::value && !IsTransposeVector<VT>::value
781 ,
typename SMatDVecMultExprTrait< MT1, typename SMatDVecMultExprTrait<MT2,VT>::Type >::Type
782 , INVALID_TYPE >::Type Type;
791 template<
typename MT1,
typename MT2,
typename VT >
792 struct SMatSVecMultExprTrait< SMatSMatMultExpr<MT1,MT2>, VT >
796 typedef typename SelectType< IsSparseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
797 IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value &&
798 IsSparseVector<VT>::value && !IsTransposeVector<VT>::value
799 ,
typename SMatSVecMultExprTrait< MT1, typename SMatSVecMultExprTrait<MT2,VT>::Type >::Type
800 , INVALID_TYPE >::Type Type;
809 template<
typename VT,
typename MT1,
typename MT2 >
810 struct TDVecSMatMultExprTrait< VT, SMatSMatMultExpr<MT1,MT2> >
814 typedef typename SelectType< IsDenseVector<VT>::value && IsTransposeVector<VT>::value &&
815 IsSparseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
816 IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value
817 ,
typename TDVecSMatMultExprTrait< typename TDVecSMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
818 , INVALID_TYPE >::Type Type;
827 template<
typename VT,
typename MT1,
typename MT2 >
828 struct TSVecSMatMultExprTrait< VT, SMatSMatMultExpr<MT1,MT2> >
832 typedef typename SelectType< IsSparseVector<VT>::value && IsTransposeVector<VT>::value &&
833 IsSparseMatrix<MT1>::value && IsRowMajorMatrix<MT1>::value &&
834 IsSparseMatrix<MT2>::value && IsRowMajorMatrix<MT2>::value
835 ,
typename TSVecSMatMultExprTrait< typename TSVecSMatMultExprTrait<VT,MT1>::Type, MT2 >::Type
836 , INVALID_TYPE >::Type Type;
845 template<
typename MT1,
typename MT2 >
846 struct RowExprTrait< SMatSMatMultExpr<MT1,MT2> >
850 typedef typename MultExprTrait< typename RowExprTrait<const MT1>::Type, MT2 >::Type Type;
859 template<
typename MT1,
typename MT2 >
860 struct ColumnExprTrait< SMatSMatMultExpr<MT1,MT2> >
864 typedef typename MultExprTrait< MT1, typename ColumnExprTrait<const MT2>::Type >::Type Type;