Derived& SparseBlockMatrixBase< Derived >::prune( const Scalar precision ) { MajorIndexType oldIndex = m_majorIndex ; typename Traits::BlocksArrayType old_blocks ; old_blocks.swap( m_blocks ) ; reserve( old_blocks.size() ) ; clear() ; for( Index outer = 0 ; outer < oldIndex.outerSize() ; ++outer ) { for( typename MajorIndexType::InnerIterator it( oldIndex, outer ) ; it ; ++it ) { if( ! is_zero( old_blocks[ it.ptr() ], precision ) ) { m_majorIndex.insertBack( outer, it.inner(), m_blocks.size() ) ; m_blocks.push_back( old_blocks[ it.ptr() ] ) ; } } } m_minorIndex.valid = empty() ; finalize() ; return derived() ; }
Derived& SparseBlockMatrixBase<Derived>::add( const SparseBlockMatrixBase< OtherDerived > &rhs, Scalar alpha ) { BOGUS_STATIC_ASSERT( !Transpose || IsTransposable< typename OtherDerived::BlockType >::Value, TRANSPOSE_IS_NOT_DEFINED_FOR_THIS_BLOCK_TYPE ) ; typedef typename SparseBlockMatrixBase< OtherDerived >::Traits OtherTraits ; typedef std::pair< BlockPtr, typename OtherTraits::BlockPtr > PtrPair ; typedef std::pair< Index, PtrPair > NonZero ; std::vector< std::vector< NonZero > > nonZeros ; // I - Compute non-zeros { SparseBlockIndexComputer< OtherDerived, Traits::is_col_major, Transpose > indexComputer( rhs ) ; typedef typename SparseBlockIndexComputer< OtherDerived, Traits::is_col_major, Transpose >::ReturnType SourceIndexType ; const SourceIndexType &rhsIndex = indexComputer.get() ; const MajorIndexType &lhsIndex = majorIndex() ; assert( rhsIndex.outerSize() == lhsIndex.outerSize() ) ; assert( rhsIndex.innerSize() == lhsIndex.innerSize() ) ; nonZeros.resize( lhsIndex.outerSize() ) ; #ifndef BOGUS_DONT_PARALLELIZE #pragma omp parallel for #endif for ( Index i = 0 ; i < lhsIndex.outerSize() ; ++i ) { typename MajorIndexType::InnerIterator lhs_it ( lhsIndex, i ) ; typename SourceIndexType::InnerIterator rhs_it ( rhsIndex, i ) ; NonZero nz ; while( lhs_it || rhs_it ) { if( lhs_it && ( !rhs_it || lhs_it.inner() < rhs_it.inner() ) ) { nz.first = lhs_it.inner() ; nz.second.first = lhs_it.ptr() ; nz.second.second = OtherDerived::InvalidBlockPtr ; ++ lhs_it ; } else if ( rhs_it && ( !lhs_it || rhs_it.inner() < lhs_it.inner() ) ) { nz.first = rhs_it.inner() ; nz.second.first = InvalidBlockPtr ; nz.second.second = rhs_it.ptr() ; ++ rhs_it ; } else { nz.first = lhs_it.inner() ; nz.second.first = lhs_it.ptr() ; nz.second.second = rhs_it.ptr() ; ++lhs_it ; ++rhs_it ; } if( Traits::is_symmetric && nz.first > i ) break ; nonZeros[i].push_back( nz ) ; } } } std::vector< BlockPtr > offsets( nonZeros.size() + 1 ) ; MajorIndexType resIndex ; resIndex.resizeOuter( nonZeros.size() ) ; offsets[0] = 0 ; for( unsigned i = 0 ; i < nonZeros.size() ; ++i ) { offsets[i+1] = offsets[i] + nonZeros[i].size() ; } resIndex.reserve( offsets.back() ) ; for( unsigned i = 0 ; i < nonZeros.size() ; ++i ) { for( unsigned j = 0 ; j < nonZeros[i].size() ; ++j ) { const BlockPtr ptr = offsets[i]+j ; const NonZero &nz = nonZeros[i][j] ; resIndex.insertBack( i, nz.first, ptr ) ; } } typename Traits::BlocksArrayType resBlocks( offsets.back() ) ; typedef BlockTransposeOption< OtherTraits::is_symmetric && !( BlockTraits< typename OtherTraits::BlockType >::is_self_transpose ), Transpose > RhsGetter ; // II - Proper addition #ifndef BOGUS_DONT_PARALLELIZE #pragma omp parallel for #endif for( std::ptrdiff_t i = 0 ; i < (std::ptrdiff_t) nonZeros.size() ; ++i ) { for( unsigned j = 0 ; j < nonZeros[i].size() ; ++j ) { const BlockPtr ptr = offsets[i]+j ; const NonZero &nz = nonZeros[i][j] ; BlockType &res = resBlocks[ptr] ; const bool afterDiag = ( (bool) Traits::is_col_major ) == ( (bool) OtherTraits::is_col_major ) ? (nz.first > i) : (nz.first < i) ; if( nz.second.first == InvalidBlockPtr ) { RhsGetter::assign( rhs.block( nz.second.second ), res, alpha, afterDiag ) ; } else if( nz.second.second == OtherDerived::InvalidBlockPtr ) { res = block( nz.second.first ) ; } else { RhsGetter::assign( rhs.block( nz.second.second ), res, alpha, afterDiag ) ; res += block( nz.second.first) ; } } } resIndex.finalize() ; clear() ; m_majorIndex.move( resIndex ); resBlocks.swap( m_blocks ) ; m_minorIndex.valid = false ; Finalizer::finalize( *this ) ; return derived() ; }