CompressedMatrix.h
Go to the documentation of this file.
1 //=================================================================================================
33 //=================================================================================================
34 
35 #ifndef _BLAZE_MATH_SPARSE_COMPRESSEDMATRIX_H_
36 #define _BLAZE_MATH_SPARSE_COMPRESSEDMATRIX_H_
37 
38 
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42 
43 #include <algorithm>
44 #include <utility>
45 #include <vector>
46 #include <blaze/math/Aliases.h>
48 #include <blaze/math/Exception.h>
50 #include <blaze/math/Forward.h>
51 #include <blaze/math/Functions.h>
72 #include <blaze/util/Algorithm.h>
73 #include <blaze/util/Assert.h>
79 #include <blaze/util/EnableIf.h>
80 #include <blaze/util/Memory.h>
81 #include <blaze/util/mpl/If.h>
82 #include <blaze/util/Types.h>
85 
86 
87 namespace blaze {
88 
89 //=================================================================================================
90 //
91 // CLASS DEFINITION
92 //
93 //=================================================================================================
94 
95 //*************************************************************************************************
205 template< typename Type // Data type of the sparse matrix
206  , bool SO = defaultStorageOrder > // Storage order
207 class CompressedMatrix : public SparseMatrix< CompressedMatrix<Type,SO>, SO >
208 {
209  private:
210  //**Type definitions****************************************************************************
212  //**********************************************************************************************
213 
214  //**Private class Element***********************************************************************
218  struct Element : public ElementBase
219  {
220  // This operator is required due to a bug in all versions of the the MSVC compiler.
221  // A simple 'using ElementBase::operator=;' statement results in ambiguity problems.
222  template< typename Other >
223  inline Element& operator=( const Other& rhs )
224  {
225  ElementBase::operator=( rhs );
226  return *this;
227  }
228 
229  friend class CompressedMatrix;
230  };
232  //**********************************************************************************************
233 
234  public:
235  //**Type definitions****************************************************************************
238  typedef This ResultType;
241  typedef Type ElementType;
242  typedef const Type& ReturnType;
243  typedef const This& CompositeType;
245  typedef const Type& ConstReference;
246  typedef Element* Iterator;
247  typedef const Element* ConstIterator;
248  //**********************************************************************************************
249 
250  //**Rebind struct definition********************************************************************
253  template< typename ET > // Data type of the other matrix
254  struct Rebind {
256  };
257  //**********************************************************************************************
258 
259  //**Compilation flags***************************************************************************
261 
264  enum : bool { smpAssignable = !IsSMPAssignable<Type>::value };
265  //**********************************************************************************************
266 
267  //**Constructors********************************************************************************
270  explicit inline CompressedMatrix();
271  explicit inline CompressedMatrix( size_t m, size_t n );
272  explicit inline CompressedMatrix( size_t m, size_t n, size_t nonzeros );
273  explicit CompressedMatrix( size_t m, size_t n, const std::vector<size_t>& nonzeros );
274  inline CompressedMatrix( const CompressedMatrix& sm );
275  inline CompressedMatrix( CompressedMatrix&& sm ) noexcept;
276  template< typename MT, bool SO2 > inline CompressedMatrix( const DenseMatrix<MT,SO2>& dm );
277  template< typename MT, bool SO2 > inline CompressedMatrix( const SparseMatrix<MT,SO2>& sm );
279  //**********************************************************************************************
280 
281  //**Destructor**********************************************************************************
284  inline ~CompressedMatrix();
286  //**********************************************************************************************
287 
288  //**Data access functions***********************************************************************
291  inline Reference operator()( size_t i, size_t j ) noexcept;
292  inline ConstReference operator()( size_t i, size_t j ) const noexcept;
293  inline Reference at( size_t i, size_t j );
294  inline ConstReference at( size_t i, size_t j ) const;
295  inline Iterator begin ( size_t i ) noexcept;
296  inline ConstIterator begin ( size_t i ) const noexcept;
297  inline ConstIterator cbegin( size_t i ) const noexcept;
298  inline Iterator end ( size_t i ) noexcept;
299  inline ConstIterator end ( size_t i ) const noexcept;
300  inline ConstIterator cend ( size_t i ) const noexcept;
302  //**********************************************************************************************
303 
304  //**Assignment operators************************************************************************
307  inline CompressedMatrix& operator=( const CompressedMatrix& rhs );
308  inline CompressedMatrix& operator=( CompressedMatrix&& rhs ) noexcept;
309 
310  template< typename MT, bool SO2 > inline CompressedMatrix& operator= ( const DenseMatrix<MT,SO2>& rhs );
311  template< typename MT, bool SO2 > inline CompressedMatrix& operator= ( const SparseMatrix<MT,SO2>& rhs );
312  template< typename MT, bool SO2 > inline CompressedMatrix& operator+=( const Matrix<MT,SO2>& rhs );
313  template< typename MT, bool SO2 > inline CompressedMatrix& operator-=( const Matrix<MT,SO2>& rhs );
314  template< typename MT, bool SO2 > inline CompressedMatrix& operator*=( const Matrix<MT,SO2>& rhs );
315 
316  template< typename Other >
317  inline EnableIf_< IsNumeric<Other>, CompressedMatrix >& operator*=( Other rhs );
318 
319  template< typename Other >
320  inline EnableIf_< IsNumeric<Other>, CompressedMatrix >& operator/=( Other rhs );
322  //**********************************************************************************************
323 
324  //**Utility functions***************************************************************************
327  inline size_t rows() const noexcept;
328  inline size_t columns() const noexcept;
329  inline size_t capacity() const noexcept;
330  inline size_t capacity( size_t i ) const noexcept;
331  inline size_t nonZeros() const;
332  inline size_t nonZeros( size_t i ) const;
333  inline void reset();
334  inline void reset( size_t i );
335  inline void clear();
336  inline Iterator set ( size_t i, size_t j, const Type& value );
337  inline Iterator insert ( size_t i, size_t j, const Type& value );
338  inline void erase ( size_t i, size_t j );
339  inline Iterator erase ( size_t i, Iterator pos );
340  inline Iterator erase ( size_t i, Iterator first, Iterator last );
341  void resize ( size_t m, size_t n, bool preserve=true );
342  inline void reserve( size_t nonzeros );
343  void reserve( size_t i, size_t nonzeros );
344  inline void trim ();
345  inline void trim ( size_t i );
346  inline CompressedMatrix& transpose();
347  inline CompressedMatrix& ctranspose();
348  template< typename Other > inline CompressedMatrix& scale( const Other& scalar );
349  template< typename Other > inline CompressedMatrix& scaleDiagonal( Other scalar );
350  inline void swap( CompressedMatrix& sm ) noexcept;
352  //**********************************************************************************************
353 
354  //**Lookup functions****************************************************************************
357  inline Iterator find ( size_t i, size_t j );
358  inline ConstIterator find ( size_t i, size_t j ) const;
359  inline Iterator lowerBound( size_t i, size_t j );
360  inline ConstIterator lowerBound( size_t i, size_t j ) const;
361  inline Iterator upperBound( size_t i, size_t j );
362  inline ConstIterator upperBound( size_t i, size_t j ) const;
364  //**********************************************************************************************
365 
366  //**Low-level utility functions*****************************************************************
369  inline void append ( size_t i, size_t j, const Type& value, bool check=false );
370  inline void finalize( size_t i );
372  //**********************************************************************************************
373 
374  //**Expression template evaluation functions****************************************************
377  template< typename Other > inline bool canAlias ( const Other* alias ) const noexcept;
378  template< typename Other > inline bool isAliased( const Other* alias ) const noexcept;
379 
380  inline bool canSMPAssign() const noexcept;
381 
382  template< typename MT, bool SO2 > inline void assign ( const DenseMatrix<MT,SO2>& rhs );
383  template< typename MT > inline void assign ( const SparseMatrix<MT,SO>& rhs );
384  template< typename MT > inline void assign ( const SparseMatrix<MT,!SO>& rhs );
385  template< typename MT, bool SO2 > inline void addAssign( const DenseMatrix<MT,SO2>& rhs );
386  template< typename MT, bool SO2 > inline void addAssign( const SparseMatrix<MT,SO2>& rhs );
387  template< typename MT, bool SO2 > inline void subAssign( const DenseMatrix<MT,SO2>& rhs );
388  template< typename MT, bool SO2 > inline void subAssign( const SparseMatrix<MT,SO2>& rhs );
390  //**********************************************************************************************
391 
392  private:
393  //**Utility functions***************************************************************************
396  Iterator insert( Iterator pos, size_t i, size_t j, const Type& value );
397  inline size_t extendCapacity() const noexcept;
398  void reserveElements( size_t nonzeros );
400  //**********************************************************************************************
401 
402  //**Member variables****************************************************************************
405  size_t m_;
406  size_t n_;
407  size_t capacity_;
408  Iterator* begin_;
409  Iterator* end_;
410 
411  static const Type zero_;
412 
413  //**********************************************************************************************
414 
415  //**Compile time checks*************************************************************************
421  BLAZE_CONSTRAINT_MUST_HAVE_SAME_SIZE ( ElementBase, Element );
423  //**********************************************************************************************
424 };
425 //*************************************************************************************************
426 
427 
428 
429 
430 //=================================================================================================
431 //
432 // DEFINITION AND INITIALIZATION OF THE STATIC MEMBER VARIABLES
433 //
434 //=================================================================================================
435 
436 template< typename Type, bool SO >
437 const Type CompressedMatrix<Type,SO>::zero_ = Type();
438 
439 
440 
441 
442 //=================================================================================================
443 //
444 // CONSTRUCTORS
445 //
446 //=================================================================================================
447 
448 //*************************************************************************************************
451 template< typename Type // Data type of the sparse matrix
452  , bool SO > // Storage order
453 inline CompressedMatrix<Type,SO>::CompressedMatrix()
454  : m_ ( 0UL ) // The current number of rows of the sparse matrix
455  , n_ ( 0UL ) // The current number of columns of the sparse matrix
456  , capacity_( 0UL ) // The current capacity of the pointer array
457  , begin_ ( nullptr ) // Pointers to the first non-zero element of each row
458  , end_ ( nullptr ) // Pointers one past the last non-zero element of each row
459 {}
460 //*************************************************************************************************
461 
462 
463 //*************************************************************************************************
471 template< typename Type // Data type of the sparse matrix
472  , bool SO > // Storage order
474  : m_ ( m ) // The current number of rows of the sparse matrix
475  , n_ ( n ) // The current number of columns of the sparse matrix
476  , capacity_( m ) // The current capacity of the pointer array
477  , begin_( new Iterator[2UL*m+2UL] ) // Pointers to the first non-zero element of each row
478  , end_ ( begin_+(m+1UL) ) // Pointers one past the last non-zero element of each row
479 {
480  for( size_t i=0UL; i<2UL*m_+2UL; ++i )
481  begin_[i] = nullptr;
482 }
483 //*************************************************************************************************
484 
485 
486 //*************************************************************************************************
495 template< typename Type // Data type of the sparse matrix
496  , bool SO > // Storage order
497 inline CompressedMatrix<Type,SO>::CompressedMatrix( size_t m, size_t n, size_t nonzeros )
498  : m_ ( m ) // The current number of rows of the sparse matrix
499  , n_ ( n ) // The current number of columns of the sparse matrix
500  , capacity_( m ) // The current capacity of the pointer array
501  , begin_( new Iterator[2UL*m+2UL] ) // Pointers to the first non-zero element of each row
502  , end_ ( begin_+(m+1UL) ) // Pointers one past the last non-zero element of each row
503 {
504  begin_[0UL] = allocate<Element>( nonzeros );
505  for( size_t i=1UL; i<(2UL*m_+1UL); ++i )
506  begin_[i] = begin_[0UL];
507  end_[m_] = begin_[0UL]+nonzeros;
508 }
509 //*************************************************************************************************
510 
511 
512 //*************************************************************************************************
523 template< typename Type // Data type of the sparse matrix
524  , bool SO > // Storage order
525 CompressedMatrix<Type,SO>::CompressedMatrix( size_t m, size_t n, const std::vector<size_t>& nonzeros )
526  : m_ ( m ) // The current number of rows of the sparse matrix
527  , n_ ( n ) // The current number of columns of the sparse matrix
528  , capacity_( m ) // The current capacity of the pointer array
529  , begin_( new Iterator[2UL*m_+2UL] ) // Pointers to the first non-zero element of each row
530  , end_ ( begin_+(m_+1UL) ) // Pointers one past the last non-zero element of each row
531 {
532  BLAZE_USER_ASSERT( nonzeros.size() == m, "Size of capacity vector and number of rows don't match" );
533 
534  size_t newCapacity( 0UL );
535  for( std::vector<size_t>::const_iterator it=nonzeros.begin(); it!=nonzeros.end(); ++it )
536  newCapacity += *it;
537 
538  begin_[0UL] = end_[0UL] = allocate<Element>( newCapacity );
539  for( size_t i=0UL; i<m_; ++i ) {
540  begin_[i+1UL] = end_[i+1UL] = begin_[i] + nonzeros[i];
541  }
542 }
543 //*************************************************************************************************
544 
545 
546 //*************************************************************************************************
551 template< typename Type // Data type of the sparse matrix
552  , bool SO > // Storage order
554  : m_ ( sm.m_ ) // The current number of rows of the sparse matrix
555  , n_ ( sm.n_ ) // The current number of columns of the sparse matrix
556  , capacity_( sm.m_ ) // The current capacity of the pointer array
557  , begin_( new Iterator[2UL*m_+2UL] ) // Pointers to the first non-zero element of each row
558  , end_ ( begin_+(m_+1UL) ) // Pointers one past the last non-zero element of each row
559 {
560  const size_t nonzeros( sm.nonZeros() );
561 
562  begin_[0UL] = allocate<Element>( nonzeros );
563  for( size_t i=0UL; i<m_; ++i )
564  begin_[i+1UL] = end_[i] = std::copy( sm.begin(i), sm.end(i), begin_[i] );
565  end_[m_] = begin_[0UL]+nonzeros;
566 }
567 //*************************************************************************************************
568 
569 
570 //*************************************************************************************************
575 template< typename Type // Data type of the sparse matrix
576  , bool SO > // Storage order
578  : m_ ( sm.m_ ) // The current number of rows of the sparse matrix
579  , n_ ( sm.n_ ) // The current number of columns of the sparse matrix
580  , capacity_( sm.capacity_ ) // The current capacity of the pointer array
581  , begin_ ( sm.begin_ ) // Pointers to the first non-zero element of each row
582  , end_ ( sm.end_ ) // Pointers one past the last non-zero element of each row
583 {
584  sm.m_ = 0UL;
585  sm.n_ = 0UL;
586  sm.capacity_ = 0UL;
587  sm.begin_ = nullptr;
588  sm.end_ = nullptr;
589 }
590 //*************************************************************************************************
591 
592 
593 //*************************************************************************************************
598 template< typename Type // Data type of the sparse matrix
599  , bool SO > // Storage order
600 template< typename MT // Type of the foreign dense matrix
601  , bool SO2 > // Storage order of the foreign dense matrix
603  : m_ ( (~dm).rows() ) // The current number of rows of the sparse matrix
604  , n_ ( (~dm).columns() ) // The current number of columns of the sparse matrix
605  , capacity_( m_ ) // The current capacity of the pointer array
606  , begin_ ( new Iterator[2UL*m_+2UL] ) // Pointers to the first non-zero element of each row
607  , end_ ( begin_+(m_+1UL) ) // Pointers one past the last non-zero element of each row
608 {
609  using blaze::assign;
610 
611  for( size_t i=0UL; i<2UL*m_+2UL; ++i )
612  begin_[i] = nullptr;
613 
614  assign( *this, ~dm );
615 }
616 //*************************************************************************************************
617 
618 
619 //*************************************************************************************************
624 template< typename Type // Data type of the sparse matrix
625  , bool SO > // Storage order
626 template< typename MT // Type of the foreign sparse matrix
627  , bool SO2 > // Storage order of the foreign sparse matrix
629  : m_ ( (~sm).rows() ) // The current number of rows of the sparse matrix
630  , n_ ( (~sm).columns() ) // The current number of columns of the sparse matrix
631  , capacity_( m_ ) // The current capacity of the pointer array
632  , begin_ ( new Iterator[2UL*m_+2UL] ) // Pointers to the first non-zero element of each row
633  , end_ ( begin_+(m_+1UL) ) // Pointers one past the last non-zero element of each row
634 {
635  using blaze::assign;
636 
637  const size_t nonzeros( (~sm).nonZeros() );
638 
639  begin_[0UL] = allocate<Element>( nonzeros );
640  for( size_t i=0UL; i<m_; ++i )
641  begin_[i+1UL] = end_[i] = begin_[0UL];
642  end_[m_] = begin_[0UL]+nonzeros;
643 
644  assign( *this, ~sm );
645 }
646 //*************************************************************************************************
647 
648 
649 
650 
651 //=================================================================================================
652 //
653 // DESTRUCTOR
654 //
655 //=================================================================================================
656 
657 //*************************************************************************************************
660 template< typename Type // Data type of the sparse matrix
661  , bool SO > // Storage order
663 {
664  if( begin_ != nullptr ) {
665  deallocate( begin_[0UL] );
666  delete[] begin_;
667  }
668 }
669 //*************************************************************************************************
670 
671 
672 
673 
674 //=================================================================================================
675 //
676 // DATA ACCESS FUNCTIONS
677 //
678 //=================================================================================================
679 
680 //*************************************************************************************************
693 template< typename Type // Data type of the sparse matrix
694  , bool SO > // Storage order
696  CompressedMatrix<Type,SO>::operator()( size_t i, size_t j ) noexcept
697 {
698  BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
699  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
700 
701  return Reference( *this, i, j );
702 }
703 //*************************************************************************************************
704 
705 
706 //*************************************************************************************************
716 template< typename Type // Data type of the sparse matrix
717  , bool SO > // Storage order
719  CompressedMatrix<Type,SO>::operator()( size_t i, size_t j ) const noexcept
720 {
721  BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
722  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
723 
724  const ConstIterator pos( lowerBound( i, j ) );
725 
726  if( pos == end_[i] || pos->index_ != j )
727  return zero_;
728  else
729  return pos->value_;
730 }
731 //*************************************************************************************************
732 
733 
734 //*************************************************************************************************
747 template< typename Type // Data type of the sparse matrix
748  , bool SO > // Storage order
750  CompressedMatrix<Type,SO>::at( size_t i, size_t j )
751 {
752  if( i >= m_ ) {
753  BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
754  }
755  if( j >= n_ ) {
756  BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
757  }
758  return (*this)(i,j);
759 }
760 //*************************************************************************************************
761 
762 
763 //*************************************************************************************************
774 template< typename Type // Data type of the sparse matrix
775  , bool SO > // Storage order
777  CompressedMatrix<Type,SO>::at( size_t i, size_t j ) const
778 {
779  if( i >= m_ ) {
780  BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
781  }
782  if( j >= n_ ) {
783  BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
784  }
785  return (*this)(i,j);
786 }
787 //*************************************************************************************************
788 
789 
790 //*************************************************************************************************
801 template< typename Type // Data type of the sparse matrix
802  , bool SO > // Storage order
804  CompressedMatrix<Type,SO>::begin( size_t i ) noexcept
805 {
806  BLAZE_USER_ASSERT( i < m_, "Invalid sparse matrix row access index" );
807  return begin_[i];
808 }
809 //*************************************************************************************************
810 
811 
812 //*************************************************************************************************
823 template< typename Type // Data type of the sparse matrix
824  , bool SO > // Storage order
826  CompressedMatrix<Type,SO>::begin( size_t i ) const noexcept
827 {
828  BLAZE_USER_ASSERT( i < m_, "Invalid sparse matrix row access index" );
829  return begin_[i];
830 }
831 //*************************************************************************************************
832 
833 
834 //*************************************************************************************************
845 template< typename Type // Data type of the sparse matrix
846  , bool SO > // Storage order
848  CompressedMatrix<Type,SO>::cbegin( size_t i ) const noexcept
849 {
850  BLAZE_USER_ASSERT( i < m_, "Invalid sparse matrix row access index" );
851  return begin_[i];
852 }
853 //*************************************************************************************************
854 
855 
856 //*************************************************************************************************
867 template< typename Type // Data type of the sparse matrix
868  , bool SO > // Storage order
870  CompressedMatrix<Type,SO>::end( size_t i ) noexcept
871 {
872  BLAZE_USER_ASSERT( i < m_, "Invalid sparse matrix row access index" );
873  return end_[i];
874 }
875 //*************************************************************************************************
876 
877 
878 //*************************************************************************************************
889 template< typename Type // Data type of the sparse matrix
890  , bool SO > // Storage order
892  CompressedMatrix<Type,SO>::end( size_t i ) const noexcept
893 {
894  BLAZE_USER_ASSERT( i < m_, "Invalid sparse matrix row access index" );
895  return end_[i];
896 }
897 //*************************************************************************************************
898 
899 
900 //*************************************************************************************************
911 template< typename Type // Data type of the sparse matrix
912  , bool SO > // Storage order
914  CompressedMatrix<Type,SO>::cend( size_t i ) const noexcept
915 {
916  BLAZE_USER_ASSERT( i < m_, "Invalid sparse matrix row access index" );
917  return end_[i];
918 }
919 //*************************************************************************************************
920 
921 
922 
923 
924 //=================================================================================================
925 //
926 // ASSIGNMENT OPERATORS
927 //
928 //=================================================================================================
929 
930 //*************************************************************************************************
939 template< typename Type // Data type of the sparse matrix
940  , bool SO > // Storage order
943 {
944  if( &rhs == this ) return *this;
945 
946  const size_t nonzeros( rhs.nonZeros() );
947 
948  if( rhs.m_ > capacity_ || nonzeros > capacity() )
949  {
950  Iterator* newBegin( new Iterator[2UL*rhs.m_+2UL] );
951  Iterator* newEnd ( newBegin+(rhs.m_+1UL) );
952 
953  newBegin[0UL] = allocate<Element>( nonzeros );
954  for( size_t i=0UL; i<rhs.m_; ++i ) {
955  newBegin[i+1UL] = newEnd[i] = std::copy( rhs.begin_[i], rhs.end_[i], newBegin[i] );
956  }
957  newEnd[rhs.m_] = newBegin[0UL]+nonzeros;
958 
959  std::swap( begin_, newBegin );
960  end_ = newEnd;
961  capacity_ = rhs.m_;
962 
963  if( newBegin != nullptr ) {
964  deallocate( newBegin[0UL] );
965  delete[] newBegin;
966  }
967  }
968  else {
969  for( size_t i=0UL; i<rhs.m_; ++i ) {
970  begin_[i+1UL] = end_[i] = std::copy( rhs.begin_[i], rhs.end_[i], begin_[i] );
971  }
972  }
973 
974  m_ = rhs.m_;
975  n_ = rhs.n_;
976 
977  return *this;
978 }
979 //*************************************************************************************************
980 
981 
982 //*************************************************************************************************
988 template< typename Type // Data type of the sparse matrix
989  , bool SO > // Storage order
992 {
993  if( begin_ != nullptr ) {
994  deallocate( begin_[0UL] );
995  delete[] begin_;
996  }
997 
998  m_ = rhs.m_;
999  n_ = rhs.n_;
1000  capacity_ = rhs.capacity_;
1001  begin_ = rhs.begin_;
1002  end_ = rhs.end_;
1003 
1004  rhs.m_ = 0UL;
1005  rhs.n_ = 0UL;
1006  rhs.capacity_ = 0UL;
1007  rhs.begin_ = nullptr;
1008  rhs.end_ = nullptr;
1009 
1010  return *this;
1011 }
1012 //*************************************************************************************************
1013 
1014 
1015 //*************************************************************************************************
1024 template< typename Type // Data type of the sparse matrix
1025  , bool SO > // Storage order
1026 template< typename MT // Type of the right-hand side dense matrix
1027  , bool SO2 > // Storage order of the right-hand side dense matrix
1030 {
1031  using blaze::assign;
1032 
1033  if( (~rhs).canAlias( this ) ) {
1034  CompressedMatrix tmp( ~rhs );
1035  swap( tmp );
1036  }
1037  else {
1038  resize( (~rhs).rows(), (~rhs).columns(), false );
1039  assign( *this, ~rhs );
1040  }
1041 
1042  return *this;
1043 }
1044 //*************************************************************************************************
1045 
1046 
1047 //*************************************************************************************************
1056 template< typename Type // Data type of the sparse matrix
1057  , bool SO > // Storage order
1058 template< typename MT // Type of the right-hand side sparse matrix
1059  , bool SO2 > // Storage order of the right-hand side sparse matrix
1062 {
1063  using blaze::assign;
1064 
1065  if( (~rhs).canAlias( this ) ||
1066  (~rhs).rows() > capacity_ ||
1067  (~rhs).nonZeros() > capacity() ) {
1068  CompressedMatrix tmp( ~rhs );
1069  swap( tmp );
1070  }
1071  else {
1072  resize( (~rhs).rows(), (~rhs).columns(), false );
1073  reset();
1074  assign( *this, ~rhs );
1075  }
1076 
1077  return *this;
1078 }
1079 //*************************************************************************************************
1080 
1081 
1082 //*************************************************************************************************
1092 template< typename Type // Data type of the sparse matrix
1093  , bool SO > // Storage order
1094 template< typename MT // Type of the right-hand side matrix
1095  , bool SO2 > // Storage order of the right-hand side matrix
1098 {
1099  using blaze::addAssign;
1100 
1101  if( (~rhs).rows() != m_ || (~rhs).columns() != n_ ) {
1102  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
1103  }
1104 
1105  addAssign( *this, ~rhs );
1106  return *this;
1107 }
1108 //*************************************************************************************************
1109 
1110 
1111 //*************************************************************************************************
1121 template< typename Type // Data type of the sparse matrix
1122  , bool SO > // Storage order
1123 template< typename MT // Type of the right-hand side matrix
1124  , bool SO2 > // Storage order of the right-hand side matrix
1126 {
1127  using blaze::subAssign;
1128 
1129  if( (~rhs).rows() != m_ || (~rhs).columns() != n_ ) {
1130  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
1131  }
1132 
1133  subAssign( *this, ~rhs );
1134  return *this;
1135 }
1136 //*************************************************************************************************
1137 
1138 
1139 //*************************************************************************************************
1149 template< typename Type // Data type of the sparse matrix
1150  , bool SO > // Storage order
1151 template< typename MT // Type of the right-hand side matrix
1152  , bool SO2 > // Storage order of the right-hand side matrix
1155 {
1156  if( (~rhs).rows() != n_ ) {
1157  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
1158  }
1159 
1160  CompressedMatrix tmp( *this * (~rhs) );
1161  swap( tmp );
1162 
1163  return *this;
1164 }
1165 //*************************************************************************************************
1166 
1167 
1168 //*************************************************************************************************
1175 template< typename Type // Data type of the sparse matrix
1176  , bool SO > // Storage order
1177 template< typename Other > // Data type of the right-hand side scalar
1180 {
1181  for( size_t i=0UL; i<m_; ++i ) {
1182  const Iterator last( end(i) );
1183  for( Iterator element=begin(i); element!=last; ++element )
1184  element->value_ *= rhs;
1185  }
1186  return *this;
1187 }
1188 //*************************************************************************************************
1189 
1190 
1191 //*************************************************************************************************
1198 template< typename Type // Data type of the sparse matrix
1199  , bool SO > // Storage order
1200 template< typename Other > // Data type of the right-hand side scalar
1201 inline EnableIf_< IsNumeric<Other>, CompressedMatrix<Type,SO> >&
1203 {
1204  BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
1205 
1206  typedef DivTrait_<Type,Other> DT;
1207  typedef If_< IsNumeric<DT>, DT, Other > Tmp;
1208 
1209  // Depending on the two involved data types, an integer division is applied or a
1210  // floating point division is selected.
1212  const Tmp tmp( Tmp(1)/static_cast<Tmp>( rhs ) );
1213  for( size_t i=0UL; i<m_; ++i ) {
1214  const Iterator last( end(i) );
1215  for( Iterator element=begin(i); element!=last; ++element )
1216  element->value_ *= tmp;
1217  }
1218  }
1219  else {
1220  for( size_t i=0UL; i<m_; ++i ) {
1221  const Iterator last( end(i) );
1222  for( Iterator element=begin(i); element!=last; ++element )
1223  element->value_ /= rhs;
1224  }
1225  }
1226 
1227  return *this;
1228 }
1229 //*************************************************************************************************
1230 
1231 
1232 
1233 
1234 //=================================================================================================
1235 //
1236 // UTILITY FUNCTIONS
1237 //
1238 //=================================================================================================
1239 
1240 //*************************************************************************************************
1245 template< typename Type // Data type of the sparse matrix
1246  , bool SO > // Storage order
1247 inline size_t CompressedMatrix<Type,SO>::rows() const noexcept
1248 {
1249  return m_;
1250 }
1251 //*************************************************************************************************
1252 
1253 
1254 //*************************************************************************************************
1259 template< typename Type // Data type of the sparse matrix
1260  , bool SO > // Storage order
1261 inline size_t CompressedMatrix<Type,SO>::columns() const noexcept
1262 {
1263  return n_;
1264 }
1265 //*************************************************************************************************
1266 
1267 
1268 //*************************************************************************************************
1273 template< typename Type // Data type of the sparse matrix
1274  , bool SO > // Storage order
1275 inline size_t CompressedMatrix<Type,SO>::capacity() const noexcept
1276 {
1277  if( begin_ != nullptr )
1278  return end_[m_] - begin_[0UL];
1279  else return 0UL;
1280 }
1281 //*************************************************************************************************
1282 
1283 
1284 //*************************************************************************************************
1295 template< typename Type // Data type of the sparse matrix
1296  , bool SO > // Storage order
1297 inline size_t CompressedMatrix<Type,SO>::capacity( size_t i ) const noexcept
1298 {
1299  BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
1300  return begin_[i+1UL] - begin_[i];
1301 }
1302 //*************************************************************************************************
1303 
1304 
1305 //*************************************************************************************************
1310 template< typename Type // Data type of the sparse matrix
1311  , bool SO > // Storage order
1313 {
1314  size_t nonzeros( 0UL );
1315 
1316  for( size_t i=0UL; i<m_; ++i )
1317  nonzeros += nonZeros( i );
1318 
1319  return nonzeros;
1320 }
1321 //*************************************************************************************************
1322 
1323 
1324 //*************************************************************************************************
1335 template< typename Type // Data type of the sparse matrix
1336  , bool SO > // Storage order
1337 inline size_t CompressedMatrix<Type,SO>::nonZeros( size_t i ) const
1338 {
1339  BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
1340  return end_[i] - begin_[i];
1341 }
1342 //*************************************************************************************************
1343 
1344 
1345 //*************************************************************************************************
1350 template< typename Type // Data type of the sparse matrix
1351  , bool SO > // Storage order
1353 {
1354  for( size_t i=0UL; i<m_; ++i )
1355  end_[i] = begin_[i];
1356 }
1357 //*************************************************************************************************
1358 
1359 
1360 //*************************************************************************************************
1371 template< typename Type // Data type of the sparse matrix
1372  , bool SO > // Storage order
1373 inline void CompressedMatrix<Type,SO>::reset( size_t i )
1374 {
1375  BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
1376  end_[i] = begin_[i];
1377 }
1378 //*************************************************************************************************
1379 
1380 
1381 //*************************************************************************************************
1388 template< typename Type // Data type of the sparse matrix
1389  , bool SO > // Storage order
1391 {
1392  end_[0UL] = end_[m_];
1393  m_ = 0UL;
1394  n_ = 0UL;
1395 }
1396 //*************************************************************************************************
1397 
1398 
1399 //*************************************************************************************************
1411 template< typename Type // Data type of the sparse matrix
1412  , bool SO > // Storage order
1414  CompressedMatrix<Type,SO>::set( size_t i, size_t j, const Type& value )
1415 {
1416  BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
1417  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
1418 
1419  const Iterator pos( lowerBound( i, j ) );
1420 
1421  if( pos != end_[i] && pos->index_ == j ) {
1422  pos->value() = value;
1423  return pos;
1424  }
1425  else return insert( pos, i, j, value );
1426 }
1427 //*************************************************************************************************
1428 
1429 
1430 //*************************************************************************************************
1443 template< typename Type // Data type of the sparse matrix
1444  , bool SO > // Storage order
1446  CompressedMatrix<Type,SO>::insert( size_t i, size_t j, const Type& value )
1447 {
1448  BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
1449  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
1450 
1451  const Iterator pos( lowerBound( i, j ) );
1452 
1453  if( pos != end_[i] && pos->index_ == j ) {
1454  BLAZE_THROW_INVALID_ARGUMENT( "Bad access index" );
1455  }
1456 
1457  return insert( pos, i, j, value );
1458 }
1459 //*************************************************************************************************
1460 
1461 
1462 //*************************************************************************************************
1472 template< typename Type // Data type of the sparse matrix
1473  , bool SO > // Storage order
1475  CompressedMatrix<Type,SO>::insert( Iterator pos, size_t i, size_t j, const Type& value )
1476 {
1477  if( begin_[i+1UL] - end_[i] != 0 ) {
1478  std::move_backward( pos, end_[i], end_[i]+1UL );
1479  pos->value_ = value;
1480  pos->index_ = j;
1481  ++end_[i];
1482 
1483  return pos;
1484  }
1485  else if( end_[m_] - begin_[m_] != 0 ) {
1486  std::move_backward( pos, end_[m_-1UL], end_[m_-1UL]+1UL );
1487 
1488  pos->value_ = value;
1489  pos->index_ = j;
1490 
1491  for( size_t k=i+1UL; k<m_+1UL; ++k ) {
1492  ++begin_[k];
1493  ++end_[k-1UL];
1494  }
1495 
1496  return pos;
1497  }
1498  else {
1499  size_t newCapacity( extendCapacity() );
1500 
1501  Iterator* newBegin = new Iterator[2UL*capacity_+2UL];
1502  Iterator* newEnd = newBegin+capacity_+1UL;
1503 
1504  newBegin[0UL] = allocate<Element>( newCapacity );
1505 
1506  for( size_t k=0UL; k<i; ++k ) {
1507  const size_t nonzeros( end_[k] - begin_[k] );
1508  const size_t total( begin_[k+1UL] - begin_[k] );
1509  newEnd [k] = newBegin[k] + nonzeros;
1510  newBegin[k+1UL] = newBegin[k] + total;
1511  }
1512  newEnd [i] = newBegin[i] + ( end_[i] - begin_[i] ) + 1;
1513  newBegin[i+1UL] = newBegin[i] + ( begin_[i+1] - begin_[i] ) + 1;
1514  for( size_t k=i+1UL; k<m_; ++k ) {
1515  const size_t nonzeros( end_[k] - begin_[k] );
1516  const size_t total( begin_[k+1UL] - begin_[k] );
1517  newEnd [k] = newBegin[k] + nonzeros;
1518  newBegin[k+1UL] = newBegin[k] + total;
1519  }
1520 
1521  newEnd[m_] = newEnd[capacity_] = newBegin[0UL]+newCapacity;
1522 
1523  Iterator tmp = std::move( begin_[0UL], pos, newBegin[0UL] );
1524  tmp->value_ = value;
1525  tmp->index_ = j;
1526  std::move( pos, end_[m_-1UL], tmp+1UL );
1527 
1528  std::swap( newBegin, begin_ );
1529  end_ = newEnd;
1530  deallocate( newBegin[0UL] );
1531  delete[] newBegin;
1532 
1533  return tmp;
1534  }
1535 }
1536 //*************************************************************************************************
1537 
1538 
1539 //*************************************************************************************************
1548 template< typename Type // Data type of the sparse matrix
1549  , bool SO > // Storage order
1550 inline void CompressedMatrix<Type,SO>::erase( size_t i, size_t j )
1551 {
1552  BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
1553  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
1554 
1555  const Iterator pos( find( i, j ) );
1556  if( pos != end_[i] )
1557  end_[i] = std::move( pos+1, end_[i], pos );
1558 }
1559 //*************************************************************************************************
1560 
1561 
1562 //*************************************************************************************************
1573 template< typename Type // Data type of the sparse matrix
1574  , bool SO > // Storage order
1576  CompressedMatrix<Type,SO>::erase( size_t i, Iterator pos )
1577 {
1578  BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
1579  BLAZE_USER_ASSERT( pos >= begin_[i] && pos <= end_[i], "Invalid compressed matrix iterator" );
1580 
1581  if( pos != end_[i] )
1582  end_[i] = std::move( pos+1, end_[i], pos );
1583 
1584  return pos;
1585 }
1586 //*************************************************************************************************
1587 
1588 
1589 //*************************************************************************************************
1601 template< typename Type // Data type of the sparse matrix
1602  , bool SO > // Storage order
1604  CompressedMatrix<Type,SO>::erase( size_t i, Iterator first, Iterator last )
1605 {
1606  BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
1607  BLAZE_USER_ASSERT( first <= last, "Invalid iterator range" );
1608  BLAZE_USER_ASSERT( first >= begin_[i] && first <= end_[i], "Invalid compressed matrix iterator" );
1609  BLAZE_USER_ASSERT( last >= begin_[i] && last <= end_[i], "Invalid compressed matrix iterator" );
1610 
1611  if( first != last )
1612  end_[i] = std::move( last, end_[i], first );
1613 
1614  return first;
1615 }
1616 //*************************************************************************************************
1617 
1618 
1619 //*************************************************************************************************
1634 template< typename Type // Data type of the sparse matrix
1635  , bool SO > // Storage order
1636 void CompressedMatrix<Type,SO>::resize( size_t m, size_t n, bool preserve )
1637 {
1638  BLAZE_INTERNAL_ASSERT( end_ >= begin_, "Invalid internal storage detected" );
1639  BLAZE_INTERNAL_ASSERT( begin_ == nullptr || size_t( end_ - begin_ ) == capacity_ + 1UL, "Invalid storage setting detected" );
1640 
1641  if( m == m_ && n == n_ ) return;
1642 
1643  if( begin_ == nullptr )
1644  {
1645  begin_ = new Iterator[2UL*m+2UL];
1646  end_ = begin_+m+1UL;
1647 
1648  for( size_t i=0UL; i<2UL*m+2UL; ++i ) {
1649  begin_[i] = nullptr;
1650  }
1651 
1652  capacity_ = m;
1653  }
1654  else if( m > capacity_ )
1655  {
1656  Iterator* newBegin( new Iterator[2UL*m+2UL] );
1657  Iterator* newEnd ( newBegin+m+1UL );
1658 
1659  newBegin[0UL] = begin_[0UL];
1660 
1661  if( preserve ) {
1662  for( size_t i=0UL; i<m_; ++i ) {
1663  newEnd [i] = end_ [i];
1664  newBegin[i+1UL] = begin_[i+1UL];
1665  }
1666  for( size_t i=m_; i<m; ++i ) {
1667  newBegin[i+1UL] = newEnd[i] = begin_[m_];
1668  }
1669  }
1670  else {
1671  for( size_t i=0UL; i<m; ++i ) {
1672  newBegin[i+1UL] = newEnd[i] = begin_[0UL];
1673  }
1674  }
1675 
1676  newEnd[m] = end_[m_];
1677 
1678  std::swap( newBegin, begin_ );
1679  delete[] newBegin;
1680  end_ = newEnd;
1681  capacity_ = m;
1682  }
1683  else if( m > m_ )
1684  {
1685  end_[m] = end_[m_];
1686 
1687  if( !preserve ) {
1688  for( size_t i=0UL; i<m_; ++i )
1689  end_[i] = begin_[i];
1690  }
1691 
1692  for( size_t i=m_; i<m; ++i ) {
1693  begin_[i+1UL] = end_[i] = begin_[m_];
1694  }
1695  }
1696  else
1697  {
1698  if( preserve ) {
1699  for( size_t i=0UL; i<m; ++i )
1700  end_[i] = lowerBound( i, n );
1701  }
1702  else {
1703  for( size_t i=0UL; i<m; ++i )
1704  end_[i] = begin_[i];
1705  }
1706 
1707  end_[m] = end_[m_];
1708  }
1709 
1710  m_ = m;
1711  n_ = n;
1712 
1713  BLAZE_INTERNAL_ASSERT( end_ >= begin_, "Invalid internal storage detected" );
1714  BLAZE_INTERNAL_ASSERT( size_t( end_ - begin_ ) == capacity_ + 1UL, "Invalid storage setting detected" );
1715 }
1716 //*************************************************************************************************
1717 
1718 
1719 //*************************************************************************************************
1729 template< typename Type // Data type of the sparse matrix
1730  , bool SO > // Storage order
1731 inline void CompressedMatrix<Type,SO>::reserve( size_t nonzeros )
1732 {
1733  if( nonzeros > capacity() )
1734  reserveElements( nonzeros );
1735 }
1736 //*************************************************************************************************
1737 
1738 
1739 //*************************************************************************************************
1753 template< typename Type // Data type of the sparse matrix
1754  , bool SO > // Storage order
1755 void CompressedMatrix<Type,SO>::reserve( size_t i, size_t nonzeros )
1756 {
1757  BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
1758 
1759  BLAZE_INTERNAL_ASSERT( end_ >= begin_, "Invalid internal storage detected" );
1760  BLAZE_INTERNAL_ASSERT( static_cast<size_t>( end_ - begin_ ) == capacity_ + 1UL, "Invalid storage setting detected" );
1761 
1762  const size_t current( capacity(i) );
1763 
1764  if( current >= nonzeros ) return;
1765 
1766  const ptrdiff_t additional( nonzeros - current );
1767 
1768  if( end_[m_] - begin_[m_] < additional )
1769  {
1770  const size_t newCapacity( begin_[m_] - begin_[0UL] + additional );
1771  BLAZE_INTERNAL_ASSERT( newCapacity > capacity(), "Invalid capacity value" );
1772 
1773  Iterator* newBegin( new Iterator[2UL*m_+2UL] );
1774  Iterator* newEnd ( newBegin+m_+1UL );
1775 
1776  newBegin[0UL] = allocate<Element>( newCapacity );
1777  newEnd [m_ ] = newBegin[0UL]+newCapacity;
1778 
1779  for( size_t k=0UL; k<i; ++k ) {
1780  newEnd [k ] = transfer( begin_[k], end_[k], newBegin[k] );
1781  newBegin[k+1UL] = newBegin[k] + capacity(k);
1782  }
1783  newEnd [i ] = transfer( begin_[i], end_[i], newBegin[i] );
1784  newBegin[i+1UL] = newBegin[i] + nonzeros;
1785  for( size_t k=i+1UL; k<m_; ++k ) {
1786  newEnd [k ] = transfer( begin_[k], end_[k], newBegin[k] );
1787  newBegin[k+1UL] = newBegin[k] + capacity(k);
1788  }
1789 
1790  BLAZE_INTERNAL_ASSERT( newBegin[m_] == newEnd[m_], "Invalid pointer calculations" );
1791 
1792  std::swap( newBegin, begin_ );
1793  deallocate( newBegin[0UL] );
1794  delete[] newBegin;
1795  end_ = newEnd;
1796  capacity_ = m_;
1797  }
1798  else
1799  {
1800  begin_[m_] += additional;
1801  for( size_t j=m_-1UL; j>i; --j ) {
1802  begin_[j] = std::move_backward( begin_[j], end_[j], end_[j]+additional );
1803  end_ [j] += additional;
1804  }
1805  }
1806 
1807  BLAZE_INTERNAL_ASSERT( end_ >= begin_, "Invalid internal storage detected" );
1808  BLAZE_INTERNAL_ASSERT( static_cast<size_t>( end_ - begin_ ) == capacity_ + 1UL, "Invalid storage setting detected" );
1809 }
1810 //*************************************************************************************************
1811 
1812 
1813 //*************************************************************************************************
1823 template< typename Type // Data type of the sparse matrix
1824  , bool SO > // Storage order
1826 {
1827  for( size_t i=0UL; i<m_; ++i )
1828  trim( i );
1829 }
1830 //*************************************************************************************************
1831 
1832 
1833 //*************************************************************************************************
1844 template< typename Type // Data type of the sparse matrix
1845  , bool SO > // Storage order
1846 inline void CompressedMatrix<Type,SO>::trim( size_t i )
1847 {
1848  BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
1849 
1850  if( i < ( m_ - 1UL ) )
1851  end_[i+1] = std::move( begin_[i+1], end_[i+1], end_[i] );
1852  begin_[i+1] = end_[i];
1853 }
1854 //*************************************************************************************************
1855 
1856 
1857 //*************************************************************************************************
1862 template< typename Type // Data type of the sparse matrix
1863  , bool SO > // Storage order
1865 {
1866  CompressedMatrix tmp( trans( *this ) );
1867  swap( tmp );
1868  return *this;
1869 }
1870 //*************************************************************************************************
1871 
1872 
1873 //*************************************************************************************************
1878 template< typename Type // Data type of the sparse matrix
1879  , bool SO > // Storage order
1881 {
1882  CompressedMatrix tmp( ctrans( *this ) );
1883  swap( tmp );
1884  return *this;
1885 }
1886 //*************************************************************************************************
1887 
1888 
1889 //*************************************************************************************************
1895 template< typename Type // Data type of the sparse matrix
1896  , bool SO > // Storage order
1897 template< typename Other > // Data type of the scalar value
1899 {
1900  for( size_t i=0UL; i<m_; ++i )
1901  for( Iterator element=begin_[i]; element!=end_[i]; ++element )
1902  element->value_ *= scalar;
1903 
1904  return *this;
1905 }
1906 //*************************************************************************************************
1907 
1908 
1909 //*************************************************************************************************
1915 template< typename Type // Data type of the sparse matrix
1916  , bool SO > // Storage order
1917 template< typename Other > // Data type of the scalar value
1919 {
1920  const size_t size( blaze::min( m_, n_ ) );
1921 
1922  for( size_t i=0UL; i<size; ++i ) {
1923  Iterator pos = lowerBound( i, i );
1924  if( pos != end_[i] && pos->index_ == i )
1925  pos->value_ *= scalar;
1926  }
1927 
1928  return *this;
1929 }
1930 //*************************************************************************************************
1931 
1932 
1933 //*************************************************************************************************
1939 template< typename Type // Data type of the sparse matrix
1940  , bool SO > // Storage order
1942 {
1943  std::swap( m_, sm.m_ );
1944  std::swap( n_, sm.n_ );
1945  std::swap( capacity_, sm.capacity_ );
1946  std::swap( begin_, sm.begin_ );
1947  std::swap( end_ , sm.end_ );
1948 }
1949 //*************************************************************************************************
1950 
1951 
1952 //*************************************************************************************************
1960 template< typename Type // Data type of the sparse matrix
1961  , bool SO > // Storage order
1962 inline size_t CompressedMatrix<Type,SO>::extendCapacity() const noexcept
1963 {
1964  size_t nonzeros( 2UL*capacity()+1UL );
1965  nonzeros = blaze::max( nonzeros, 7UL );
1966 
1967  BLAZE_INTERNAL_ASSERT( nonzeros > capacity(), "Invalid capacity value" );
1968 
1969  return nonzeros;
1970 }
1971 //*************************************************************************************************
1972 
1973 
1974 //*************************************************************************************************
1980 template< typename Type // Data type of the sparse matrix
1981  , bool SO > // Storage order
1983 {
1984  Iterator* newBegin = new Iterator[2UL*capacity_+2UL];
1985  Iterator* newEnd = newBegin+capacity_+1UL;
1986 
1987  newBegin[0UL] = allocate<Element>( nonzeros );
1988 
1989  for( size_t k=0UL; k<m_; ++k ) {
1990  BLAZE_INTERNAL_ASSERT( begin_[k] <= end_[k], "Invalid row pointers" );
1991  newEnd [k] = transfer( begin_[k], end_[k], newBegin[k] );
1992  newBegin[k+1UL] = newBegin[k] + ( begin_[k+1UL] - begin_[k] );
1993  }
1994 
1995  newEnd[m_] = newBegin[0UL]+nonzeros;
1996 
1997  std::swap( newBegin, begin_ );
1998  end_ = newEnd;
1999 
2000  if( newBegin != nullptr ) {
2001  deallocate( newBegin[0UL] );
2002  delete[] newBegin;
2003  }
2004 }
2005 //*************************************************************************************************
2006 
2007 
2008 
2009 
2010 //=================================================================================================
2011 //
2012 // LOOKUP FUNCTIONS
2013 //
2014 //=================================================================================================
2015 
2016 //*************************************************************************************************
2031 template< typename Type // Data type of the sparse matrix
2032  , bool SO > // Storage order
2034  CompressedMatrix<Type,SO>::find( size_t i, size_t j )
2035 {
2036  return const_cast<Iterator>( const_cast<const This&>( *this ).find( i, j ) );
2037 }
2038 //*************************************************************************************************
2039 
2040 
2041 //*************************************************************************************************
2056 template< typename Type // Data type of the sparse matrix
2057  , bool SO > // Storage order
2059  CompressedMatrix<Type,SO>::find( size_t i, size_t j ) const
2060 {
2061  const ConstIterator pos( lowerBound( i, j ) );
2062  if( pos != end_[i] && pos->index_ == j )
2063  return pos;
2064  else return end_[i];
2065 }
2066 //*************************************************************************************************
2067 
2068 
2069 //*************************************************************************************************
2084 template< typename Type // Data type of the sparse matrix
2085  , bool SO > // Storage order
2088 {
2089  return const_cast<Iterator>( const_cast<const This&>( *this ).lowerBound( i, j ) );
2090 }
2091 //*************************************************************************************************
2092 
2093 
2094 //*************************************************************************************************
2109 template< typename Type // Data type of the sparse matrix
2110  , bool SO > // Storage order
2112  CompressedMatrix<Type,SO>::lowerBound( size_t i, size_t j ) const
2113 {
2114  BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
2115  return std::lower_bound( begin_[i], end_[i], j,
2116  []( const Element& element, size_t index )
2117  {
2118  return element.index() < index;
2119  } );
2120 }
2121 //*************************************************************************************************
2122 
2123 
2124 //*************************************************************************************************
2139 template< typename Type // Data type of the sparse matrix
2140  , bool SO > // Storage order
2143 {
2144  return const_cast<Iterator>( const_cast<const This&>( *this ).upperBound( i, j ) );
2145 }
2146 //*************************************************************************************************
2147 
2148 
2149 //*************************************************************************************************
2164 template< typename Type // Data type of the sparse matrix
2165  , bool SO > // Storage order
2167  CompressedMatrix<Type,SO>::upperBound( size_t i, size_t j ) const
2168 {
2169  BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
2170  return std::upper_bound( begin_[i], end_[i], j,
2171  []( size_t index, const Element& element )
2172  {
2173  return index < element.index();
2174  } );
2175 }
2176 //*************************************************************************************************
2177 
2178 
2179 
2180 
2181 //=================================================================================================
2182 //
2183 // LOW-LEVEL UTILITY FUNCTIONS
2184 //
2185 //=================================================================================================
2186 
2187 //*************************************************************************************************
2231 template< typename Type // Data type of the sparse matrix
2232  , bool SO > // Storage order
2233 inline void CompressedMatrix<Type,SO>::append( size_t i, size_t j, const Type& value, bool check )
2234 {
2235  BLAZE_USER_ASSERT( i < m_, "Invalid row access index" );
2236  BLAZE_USER_ASSERT( j < n_, "Invalid column access index" );
2237  BLAZE_USER_ASSERT( end_[i] < end_[m_], "Not enough reserved capacity left" );
2238  BLAZE_USER_ASSERT( begin_[i] == end_[i] || j > ( end_[i]-1UL )->index_, "Index is not strictly increasing" );
2239 
2240  end_[i]->value_ = value;
2241 
2242  if( !check || !isDefault( end_[i]->value_ ) ) {
2243  end_[i]->index_ = j;
2244  ++end_[i];
2245  }
2246 }
2247 //*************************************************************************************************
2248 
2249 
2250 //*************************************************************************************************
2263 template< typename Type // Data type of the sparse matrix
2264  , bool SO > // Storage order
2266 {
2267  BLAZE_USER_ASSERT( i < m_, "Invalid row access index" );
2268 
2269  begin_[i+1UL] = end_[i];
2270  if( i != m_-1UL )
2271  end_[i+1UL] = end_[i];
2272 }
2273 //*************************************************************************************************
2274 
2275 
2276 
2277 
2278 //=================================================================================================
2279 //
2280 // EXPRESSION TEMPLATE EVALUATION FUNCTIONS
2281 //
2282 //=================================================================================================
2283 
2284 //*************************************************************************************************
2294 template< typename Type // Data type of the sparse matrix
2295  , bool SO > // Storage order
2296 template< typename Other > // Data type of the foreign expression
2297 inline bool CompressedMatrix<Type,SO>::canAlias( const Other* alias ) const noexcept
2298 {
2299  return static_cast<const void*>( this ) == static_cast<const void*>( alias );
2300 }
2301 //*************************************************************************************************
2302 
2303 
2304 //*************************************************************************************************
2314 template< typename Type // Data type of the sparse matrix
2315  , bool SO > // Storage order
2316 template< typename Other > // Data type of the foreign expression
2317 inline bool CompressedMatrix<Type,SO>::isAliased( const Other* alias ) const noexcept
2318 {
2319  return static_cast<const void*>( this ) == static_cast<const void*>( alias );
2320 }
2321 //*************************************************************************************************
2322 
2323 
2324 //*************************************************************************************************
2334 template< typename Type // Data type of the sparse matrix
2335  , bool SO > // Storage order
2336 inline bool CompressedMatrix<Type,SO>::canSMPAssign() const noexcept
2337 {
2338  return false;
2339 }
2340 //*************************************************************************************************
2341 
2342 
2343 //*************************************************************************************************
2354 template< typename Type // Data type of the sparse matrix
2355  , bool SO > // Storage order
2356 template< typename MT // Type of the right-hand side dense matrix
2357  , bool SO2 > // Storage order of the right-hand side dense matrix
2359 {
2360  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
2361  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
2362 
2363  if( m_ == 0UL || n_ == 0UL )
2364  return;
2365 
2366  size_t nonzeros( 0UL );
2367 
2368  for( size_t i=1UL; i<=m_; ++i )
2369  begin_[i] = end_[i] = end_[m_];
2370 
2371  for( size_t i=0UL; i<m_; ++i )
2372  {
2373  begin_[i] = end_[i] = begin_[0UL]+nonzeros;
2374 
2375  const size_t jbegin( ( IsUpper<MT>::value )
2376  ?( IsStrictlyUpper<MT>::value ? i+1UL : i )
2377  :( 0UL ) );
2378  const size_t jend ( ( IsLower<MT>::value )
2379  ?( IsStrictlyLower<MT>::value ? i : i+1UL )
2380  :( n_ ) );
2381 
2382  for( size_t j=jbegin; j<jend; ++j )
2383  {
2384  if( nonzeros == capacity() ) {
2385  reserveElements( extendCapacity() );
2386  for( size_t k=i+1UL; k<=m_; ++k )
2387  begin_[k] = end_[k] = end_[m_];
2388  }
2389 
2390  end_[i]->value_ = (~rhs)(i,j);
2391 
2392  if( !isDefault( end_[i]->value_ ) ) {
2393  end_[i]->index_ = j;
2394  ++end_[i];
2395  ++nonzeros;
2396  }
2397  }
2398  }
2399 
2400  begin_[m_] = begin_[0UL]+nonzeros;
2401 }
2402 //*************************************************************************************************
2403 
2404 
2405 //*************************************************************************************************
2416 template< typename Type // Data type of the sparse matrix
2417  , bool SO > // Storage order
2418 template< typename MT > // Type of the right-hand side sparse matrix
2420 {
2421  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
2422  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
2423  BLAZE_INTERNAL_ASSERT( nonZeros() == 0UL, "Invalid non-zero elements detected" );
2424  BLAZE_INTERNAL_ASSERT( capacity() >= (~rhs).nonZeros(), "Invalid capacity detected" );
2425 
2426  if( m_ == 0UL || begin_[0] == nullptr )
2427  return;
2428 
2429  for( size_t i=0UL; i<m_; ++i ) {
2430  begin_[i+1UL] = end_[i] = std::copy( (~rhs).begin(i), (~rhs).end(i), begin_[i] );
2431  }
2432 }
2433 //*************************************************************************************************
2434 
2435 
2436 //*************************************************************************************************
2447 template< typename Type // Data type of the sparse matrix
2448  , bool SO > // Storage order
2449 template< typename MT > // Type of the right-hand side sparse matrix
2451 {
2453 
2454  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
2455  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
2456  BLAZE_INTERNAL_ASSERT( nonZeros() == 0UL, "Invalid non-zero elements detected" );
2457  BLAZE_INTERNAL_ASSERT( capacity() >= (~rhs).nonZeros(), "Invalid capacity detected" );
2458 
2459  typedef ConstIterator_<MT> RhsIterator;
2460 
2461  // Counting the number of elements per row
2462  std::vector<size_t> rowLengths( m_, 0UL );
2463  for( size_t j=0UL; j<n_; ++j ) {
2464  for( RhsIterator element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
2465  ++rowLengths[element->index()];
2466  }
2467 
2468  // Resizing the sparse matrix
2469  for( size_t i=0UL; i<m_; ++i ) {
2470  begin_[i+1UL] = end_[i+1UL] = begin_[i] + rowLengths[i];
2471  }
2472 
2473  // Appending the elements to the rows of the sparse matrix
2474  for( size_t j=0UL; j<n_; ++j ) {
2475  for( RhsIterator element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
2476  append( element->index(), j, element->value() );
2477  }
2478 }
2479 //*************************************************************************************************
2480 
2481 
2482 //*************************************************************************************************
2493 template< typename Type // Data type of the sparse matrix
2494  , bool SO > // Storage order
2495 template< typename MT // Type of the right-hand side dense matrix
2496  , bool SO2 > // Storage order of the right-hand side dense matrix
2498 {
2499  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
2500  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
2501 
2502  CompressedMatrix tmp( serial( *this + (~rhs) ) );
2503  swap( tmp );
2504 }
2505 //*************************************************************************************************
2506 
2507 
2508 //*************************************************************************************************
2519 template< typename Type // Data type of the sparse matrix
2520  , bool SO > // Storage order
2521 template< typename MT // Type of the right-hand side sparse matrix
2522  , bool SO2 > // Storage order of the right-hand side sparse matrix
2524 {
2525  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
2526  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
2527 
2528  CompressedMatrix tmp( serial( *this + (~rhs) ) );
2529  swap( tmp );
2530 }
2531 //*************************************************************************************************
2532 
2533 
2534 //*************************************************************************************************
2545 template< typename Type // Data type of the sparse matrix
2546  , bool SO > // Storage order
2547 template< typename MT // Type of the right-hand side dense matrix
2548  , bool SO2 > // Storage order of the right-hand side dense matrix
2550 {
2551  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
2552  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
2553 
2554  CompressedMatrix tmp( serial( *this - (~rhs) ) );
2555  swap( tmp );
2556 }
2557 //*************************************************************************************************
2558 
2559 
2560 //*************************************************************************************************
2571 template< typename Type // Data type of the sparse matrix
2572  , bool SO > // Storage order
2573 template< typename MT // Type of the right-hand side sparse matrix
2574  , bool SO2 > // Storage order of the right-hand sparse matrix
2576 {
2577  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
2578  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
2579 
2580  CompressedMatrix tmp( serial( *this - (~rhs) ) );
2581  swap( tmp );
2582 }
2583 //*************************************************************************************************
2584 
2585 
2586 
2587 
2588 
2589 
2590 
2591 
2592 //=================================================================================================
2593 //
2594 // CLASS TEMPLATE SPECIALIZATION FOR COLUMN-MAJOR MATRICES
2595 //
2596 //=================================================================================================
2597 
2598 //*************************************************************************************************
2606 template< typename Type > // Data type of the sparse matrix
2607 class CompressedMatrix<Type,true> : public SparseMatrix< CompressedMatrix<Type,true>, true >
2608 {
2609  private:
2610  //**Type definitions****************************************************************************
2612  //**********************************************************************************************
2613 
2614  //**Private class Element***********************************************************************
2618  struct Element : public ElementBase
2619  {
2620  // This operator is required due to a bug in all versions of the the MSVC compiler.
2621  // A simple 'using ElementBase::operator=;' statement results in ambiguity problems.
2622  template< typename Other >
2623  inline Element& operator=( const Other& rhs )
2624  {
2625  ElementBase::operator=( rhs );
2626  return *this;
2627  }
2628 
2629  friend class CompressedMatrix;
2630  };
2632  //**********************************************************************************************
2633 
2634  public:
2635  //**Type definitions****************************************************************************
2638  typedef This ResultType;
2641  typedef Type ElementType;
2642  typedef const Type& ReturnType;
2643  typedef const This& CompositeType;
2645  typedef const Type& ConstReference;
2646  typedef Element* Iterator;
2647  typedef const Element* ConstIterator;
2648  //**********************************************************************************************
2649 
2650  //**Rebind struct definition********************************************************************
2653  template< typename ET > // Data type of the other matrix
2654  struct Rebind {
2656  };
2657  //**********************************************************************************************
2658 
2659  //**Compilation flags***************************************************************************
2661 
2664  enum : bool { smpAssignable = !IsSMPAssignable<Type>::value };
2665  //**********************************************************************************************
2666 
2667  //**Constructors********************************************************************************
2670  explicit inline CompressedMatrix();
2671  explicit inline CompressedMatrix( size_t m, size_t n );
2672  explicit inline CompressedMatrix( size_t m, size_t n, size_t nonzeros );
2673  explicit CompressedMatrix( size_t m, size_t n, const std::vector<size_t>& nonzeros );
2674  inline CompressedMatrix( const CompressedMatrix& sm );
2675  inline CompressedMatrix( CompressedMatrix&& sm ) noexcept;
2676  template< typename MT, bool SO > inline CompressedMatrix( const DenseMatrix<MT,SO>& dm );
2677  template< typename MT, bool SO > inline CompressedMatrix( const SparseMatrix<MT,SO>& sm );
2679  //**********************************************************************************************
2680 
2681  //**Destructor**********************************************************************************
2684  inline ~CompressedMatrix();
2686  //**********************************************************************************************
2687 
2688  //**Data access functions***********************************************************************
2691  inline Reference operator()( size_t i, size_t j ) noexcept;
2692  inline ConstReference operator()( size_t i, size_t j ) const noexcept;
2693  inline Reference at( size_t i, size_t j );
2694  inline ConstReference at( size_t i, size_t j ) const;
2695  inline Iterator begin ( size_t i ) noexcept;
2696  inline ConstIterator begin ( size_t i ) const noexcept;
2697  inline ConstIterator cbegin( size_t i ) const noexcept;
2698  inline Iterator end ( size_t i ) noexcept;
2699  inline ConstIterator end ( size_t i ) const noexcept;
2700  inline ConstIterator cend ( size_t i ) const noexcept;
2702  //**********************************************************************************************
2703 
2704  //**Assignment operators************************************************************************
2707  inline CompressedMatrix& operator=( const CompressedMatrix& rhs );
2708  inline CompressedMatrix& operator=( CompressedMatrix&& rhs ) noexcept;
2709 
2710  template< typename MT, bool SO > inline CompressedMatrix& operator= ( const DenseMatrix<MT,SO>& rhs );
2711  template< typename MT, bool SO > inline CompressedMatrix& operator= ( const SparseMatrix<MT,SO>& rhs );
2712  template< typename MT, bool SO > inline CompressedMatrix& operator+=( const Matrix<MT,SO>& rhs );
2713  template< typename MT, bool SO > inline CompressedMatrix& operator-=( const Matrix<MT,SO>& rhs );
2714  template< typename MT, bool SO > inline CompressedMatrix& operator*=( const Matrix<MT,SO>& rhs );
2715 
2716  template< typename Other >
2717  inline EnableIf_< IsNumeric<Other>, CompressedMatrix >& operator*=( Other rhs );
2718 
2719  template< typename Other >
2720  inline EnableIf_< IsNumeric<Other>, CompressedMatrix >& operator/=( Other rhs );
2722  //**********************************************************************************************
2723 
2724  //**Utility functions***************************************************************************
2727  inline size_t rows() const noexcept;
2728  inline size_t columns() const noexcept;
2729  inline size_t capacity() const noexcept;
2730  inline size_t capacity( size_t j ) const noexcept;
2731  inline size_t nonZeros() const;
2732  inline size_t nonZeros( size_t j ) const;
2733  inline void reset();
2734  inline void reset( size_t j );
2735  inline void clear();
2736  inline Iterator set ( size_t i, size_t j, const Type& value );
2737  inline Iterator insert ( size_t i, size_t j, const Type& value );
2738  inline void erase ( size_t i, size_t j );
2739  inline Iterator erase ( size_t j, Iterator pos );
2740  inline Iterator erase ( size_t j, Iterator first, Iterator last );
2741  void resize ( size_t m, size_t n, bool preserve=true );
2742  inline void reserve( size_t nonzeros );
2743  void reserve( size_t j, size_t nonzeros );
2744  inline void trim ();
2745  inline void trim ( size_t j );
2746  inline CompressedMatrix& transpose();
2747  inline CompressedMatrix& ctranspose();
2748  template< typename Other > inline CompressedMatrix& scale( const Other& scalar );
2749  template< typename Other > inline CompressedMatrix& scaleDiagonal( Other scalar );
2750  inline void swap( CompressedMatrix& sm ) noexcept;
2752  //**********************************************************************************************
2753 
2754  //**Lookup functions****************************************************************************
2757  inline Iterator find ( size_t i, size_t j );
2758  inline ConstIterator find ( size_t i, size_t j ) const;
2759  inline Iterator lowerBound( size_t i, size_t j );
2760  inline ConstIterator lowerBound( size_t i, size_t j ) const;
2761  inline Iterator upperBound( size_t i, size_t j );
2762  inline ConstIterator upperBound( size_t i, size_t j ) const;
2764  //**********************************************************************************************
2765 
2766  //**Low-level utility functions*****************************************************************
2769  inline void append ( size_t i, size_t j, const Type& value, bool check=false );
2770  inline void finalize( size_t j );
2772  //**********************************************************************************************
2773 
2774  //**Expression template evaluation functions****************************************************
2777  template< typename Other > inline bool canAlias ( const Other* alias ) const noexcept;
2778  template< typename Other > inline bool isAliased( const Other* alias ) const noexcept;
2779 
2780  inline bool canSMPAssign() const noexcept;
2781 
2782  template< typename MT, bool SO > inline void assign ( const DenseMatrix<MT,SO>& rhs );
2783  template< typename MT > inline void assign ( const SparseMatrix<MT,true>& rhs );
2784  template< typename MT > inline void assign ( const SparseMatrix<MT,false>& rhs );
2785  template< typename MT, bool SO > inline void addAssign( const DenseMatrix<MT,SO>& rhs );
2786  template< typename MT, bool SO > inline void addAssign( const SparseMatrix<MT,SO>& rhs );
2787  template< typename MT, bool SO > inline void subAssign( const DenseMatrix<MT,SO>& rhs );
2788  template< typename MT, bool SO > inline void subAssign( const SparseMatrix<MT,SO>& rhs );
2790  //**********************************************************************************************
2791 
2792  private:
2793  //**Utility functions***************************************************************************
2796  Iterator insert( Iterator pos, size_t i, size_t j, const Type& value );
2797  inline size_t extendCapacity() const noexcept;
2798  void reserveElements( size_t nonzeros );
2800  //**********************************************************************************************
2801 
2802  //**Member variables****************************************************************************
2805  size_t m_;
2806  size_t n_;
2807  size_t capacity_;
2808  Iterator* begin_;
2809  Iterator* end_;
2810 
2811  static const Type zero_;
2812 
2813  //**********************************************************************************************
2814 
2815  //**Compile time checks*************************************************************************
2821  BLAZE_CONSTRAINT_MUST_HAVE_SAME_SIZE ( ElementBase, Element );
2823  //**********************************************************************************************
2824 };
2826 //*************************************************************************************************
2827 
2828 
2829 
2830 
2831 //=================================================================================================
2832 //
2833 // DEFINITION AND INITIALIZATION OF THE STATIC MEMBER VARIABLES
2834 //
2835 //=================================================================================================
2836 
2837 template< typename Type >
2838 const Type CompressedMatrix<Type,true>::zero_ = Type();
2839 
2840 
2841 
2842 
2843 //=================================================================================================
2844 //
2845 // CONSTRUCTORS
2846 //
2847 //=================================================================================================
2848 
2849 //*************************************************************************************************
2853 template< typename Type > // Data type of the sparse matrix
2854 inline CompressedMatrix<Type,true>::CompressedMatrix()
2855  : m_ ( 0UL ) // The current number of rows of the sparse matrix
2856  , n_ ( 0UL ) // The current number of columns of the sparse matrix
2857  , capacity_( 0UL ) // The current capacity of the pointer array
2858  , begin_ ( nullptr ) // Pointers to the first non-zero element of each column
2859  , end_ ( nullptr ) // Pointers one past the last non-zero element of each column
2860 {}
2862 //*************************************************************************************************
2863 
2864 
2865 //*************************************************************************************************
2874 template< typename Type > // Data type of the sparse matrix
2875 inline CompressedMatrix<Type,true>::CompressedMatrix( size_t m, size_t n )
2876  : m_ ( m ) // The current number of rows of the sparse matrix
2877  , n_ ( n ) // The current number of columns of the sparse matrix
2878  , capacity_( n ) // The current capacity of the pointer array
2879  , begin_( new Iterator[2UL*n+2UL] ) // Pointers to the first non-zero element of each column
2880  , end_ ( begin_+(n+1UL) ) // Pointers one past the last non-zero element of each column
2881 {
2882  for( size_t j=0UL; j<2UL*n_+2UL; ++j )
2883  begin_[j] = nullptr;
2884 }
2886 //*************************************************************************************************
2887 
2888 
2889 //*************************************************************************************************
2899 template< typename Type > // Data type of the sparse matrix
2900 inline CompressedMatrix<Type,true>::CompressedMatrix( size_t m, size_t n, size_t nonzeros )
2901  : m_ ( m ) // The current number of rows of the sparse matrix
2902  , n_ ( n ) // The current number of columns of the sparse matrix
2903  , capacity_( n ) // The current capacity of the pointer array
2904  , begin_( new Iterator[2UL*n+2UL] ) // Pointers to the first non-zero element of each column
2905  , end_ ( begin_+(n+1UL) ) // Pointers one past the last non-zero element of each column
2906 {
2907  begin_[0UL] = allocate<Element>( nonzeros );
2908  for( size_t j=1UL; j<(2UL*n_+1UL); ++j )
2909  begin_[j] = begin_[0UL];
2910  end_[n_] = begin_[0UL]+nonzeros;
2911 }
2913 //*************************************************************************************************
2914 
2915 
2916 //*************************************************************************************************
2927 template< typename Type > // Data type of the sparse matrix
2928 CompressedMatrix<Type,true>::CompressedMatrix( size_t m, size_t n, const std::vector<size_t>& nonzeros )
2929  : m_ ( m ) // The current number of rows of the sparse matrix
2930  , n_ ( n ) // The current number of columns of the sparse matrix
2931  , capacity_( n ) // The current capacity of the pointer array
2932  , begin_( new Iterator[2UL*n_+2UL] ) // Pointers to the first non-zero element of each column
2933  , end_ ( begin_+(n_+1UL) ) // Pointers one past the last non-zero element of each column
2934 {
2935  BLAZE_USER_ASSERT( nonzeros.size() == n, "Size of capacity vector and number of columns don't match" );
2936 
2937  size_t newCapacity( 0UL );
2938  for( std::vector<size_t>::const_iterator it=nonzeros.begin(); it!=nonzeros.end(); ++it )
2939  newCapacity += *it;
2940 
2941  begin_[0UL] = end_[0UL] = allocate<Element>( newCapacity );
2942  for( size_t j=0UL; j<n_; ++j ) {
2943  begin_[j+1UL] = end_[j+1UL] = begin_[j] + nonzeros[j];
2944  }
2945 }
2947 //*************************************************************************************************
2948 
2949 
2950 //*************************************************************************************************
2956 template< typename Type > // Data type of the sparse matrix
2957 inline CompressedMatrix<Type,true>::CompressedMatrix( const CompressedMatrix& sm )
2958  : m_ ( sm.m_ ) // The current number of rows of the sparse matrix
2959  , n_ ( sm.n_ ) // The current number of columns of the sparse matrix
2960  , capacity_( sm.n_ ) // The current capacity of the pointer array
2961  , begin_ ( new Iterator[2UL*n_+2UL] ) // Pointers to the first non-zero element of each column
2962  , end_ ( begin_+(n_+1UL) ) // Pointers one past the last non-zero element of each column
2963 {
2964  const size_t nonzeros( sm.nonZeros() );
2965 
2966  begin_[0UL] = allocate<Element>( nonzeros );
2967  for( size_t j=0UL; j<n_; ++j )
2968  begin_[j+1UL] = end_[j] = std::copy( sm.begin(j), sm.end(j), begin_[j] );
2969  end_[n_] = begin_[0UL]+nonzeros;
2970 }
2972 //*************************************************************************************************
2973 
2974 
2975 //*************************************************************************************************
2981 template< typename Type > // Data type of the sparse matrix
2982 inline CompressedMatrix<Type,true>::CompressedMatrix( CompressedMatrix&& sm ) noexcept
2983  : m_ ( sm.m_ ) // The current number of rows of the sparse matrix
2984  , n_ ( sm.n_ ) // The current number of columns of the sparse matrix
2985  , capacity_( sm.capacity_ ) // The current capacity of the pointer array
2986  , begin_ ( sm.begin_ ) // Pointers to the first non-zero element of each column
2987  , end_ ( sm.end_ ) // Pointers one past the last non-zero element of each column
2988 {
2989  sm.m_ = 0UL;
2990  sm.n_ = 0UL;
2991  sm.capacity_ = 0UL;
2992  sm.begin_ = nullptr;
2993  sm.end_ = nullptr;
2994 }
2996 //*************************************************************************************************
2997 
2998 
2999 //*************************************************************************************************
3005 template< typename Type > // Data type of the sparse matrix
3006 template< typename MT // Type of the foreign dense matrix
3007  , bool SO > // Storage order of the foreign dense matrix
3008 inline CompressedMatrix<Type,true>::CompressedMatrix( const DenseMatrix<MT,SO>& dm )
3009  : m_ ( (~dm).rows() ) // The current number of rows of the sparse matrix
3010  , n_ ( (~dm).columns() ) // The current number of columns of the sparse matrix
3011  , capacity_( n_ ) // The current capacity of the pointer array
3012  , begin_ ( new Iterator[2UL*n_+2UL] ) // Pointers to the first non-zero element of each column
3013  , end_ ( begin_+(n_+1UL) ) // Pointers one past the last non-zero element of each column
3014 {
3015  using blaze::assign;
3016 
3017  for( size_t j=0UL; j<2UL*n_+2UL; ++j )
3018  begin_[j] = nullptr;
3019 
3020  assign( *this, ~dm );
3021 }
3023 //*************************************************************************************************
3024 
3025 
3026 //*************************************************************************************************
3032 template< typename Type > // Data type of the sparse matrix
3033 template< typename MT // Type of the foreign sparse matrix
3034  , bool SO > // Storage order of the foreign sparse matrix
3035 inline CompressedMatrix<Type,true>::CompressedMatrix( const SparseMatrix<MT,SO>& sm )
3036  : m_ ( (~sm).rows() ) // The current number of rows of the sparse matrix
3037  , n_ ( (~sm).columns() ) // The current number of columns of the sparse matrix
3038  , capacity_( n_ ) // The current capacity of the pointer array
3039  , begin_ ( new Iterator[2UL*n_+2UL] ) // Pointers to the first non-zero element of each column
3040  , end_ ( begin_+(n_+1UL) ) // Pointers one past the last non-zero element of each column
3041 {
3042  using blaze::assign;
3043 
3044  const size_t nonzeros( (~sm).nonZeros() );
3045 
3046  begin_[0UL] = allocate<Element>( nonzeros );
3047  for( size_t j=0UL; j<n_; ++j )
3048  begin_[j+1UL] = end_[j] = begin_[0UL];
3049  end_[n_] = begin_[0UL]+nonzeros;
3050 
3051  assign( *this, ~sm );
3052 }
3054 //*************************************************************************************************
3055 
3056 
3057 
3058 
3059 //=================================================================================================
3060 //
3061 // DESTRUCTOR
3062 //
3063 //=================================================================================================
3064 
3065 //*************************************************************************************************
3069 template< typename Type > // Data type of the sparse matrix
3070 inline CompressedMatrix<Type,true>::~CompressedMatrix()
3071 {
3072  if( begin_ != nullptr ) {
3073  deallocate( begin_[0UL] );
3074  delete[] begin_;
3075  }
3076 }
3078 //*************************************************************************************************
3079 
3080 
3081 
3082 
3083 //=================================================================================================
3084 //
3085 // DATA ACCESS FUNCTIONS
3086 //
3087 //=================================================================================================
3088 
3089 //*************************************************************************************************
3103 template< typename Type > // Data type of the sparse matrix
3105  CompressedMatrix<Type,true>::operator()( size_t i, size_t j ) noexcept
3106 {
3107  BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
3108  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
3109 
3110  return Reference( *this, i, j );
3111 }
3113 //*************************************************************************************************
3114 
3115 
3116 //*************************************************************************************************
3127 template< typename Type > // Data type of the sparse matrix
3129  CompressedMatrix<Type,true>::operator()( size_t i, size_t j ) const noexcept
3130 {
3131  BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
3132  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
3133 
3134  const ConstIterator pos( lowerBound( i, j ) );
3135 
3136  if( pos == end_[j] || pos->index_ != i )
3137  return zero_;
3138  else
3139  return pos->value_;
3140 }
3142 //*************************************************************************************************
3143 
3144 
3145 //*************************************************************************************************
3159 template< typename Type > // Data type of the sparse matrix
3161  CompressedMatrix<Type,true>::at( size_t i, size_t j )
3162 {
3163  if( i >= m_ ) {
3164  BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
3165  }
3166  if( j >= n_ ) {
3167  BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
3168  }
3169  return (*this)(i,j);
3170 }
3172 //*************************************************************************************************
3173 
3174 
3175 //*************************************************************************************************
3187 template< typename Type > // Data type of the sparse matrix
3189  CompressedMatrix<Type,true>::at( size_t i, size_t j ) const
3190 {
3191  if( i >= m_ ) {
3192  BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
3193  }
3194  if( j >= n_ ) {
3195  BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
3196  }
3197  return (*this)(i,j);
3198 }
3200 //*************************************************************************************************
3201 
3202 
3203 //*************************************************************************************************
3210 template< typename Type > // Data type of the sparse matrix
3212  CompressedMatrix<Type,true>::begin( size_t j ) noexcept
3213 {
3214  BLAZE_USER_ASSERT( j < n_, "Invalid sparse matrix column access index" );
3215  return begin_[j];
3216 }
3218 //*************************************************************************************************
3219 
3220 
3221 //*************************************************************************************************
3228 template< typename Type > // Data type of the sparse matrix
3230  CompressedMatrix<Type,true>::begin( size_t j ) const noexcept
3231 {
3232  BLAZE_USER_ASSERT( j < n_, "Invalid sparse matrix column access index" );
3233  return begin_[j];
3234 }
3236 //*************************************************************************************************
3237 
3238 
3239 //*************************************************************************************************
3246 template< typename Type > // Data type of the sparse matrix
3248  CompressedMatrix<Type,true>::cbegin( size_t j ) const noexcept
3249 {
3250  BLAZE_USER_ASSERT( j < n_, "Invalid sparse matrix column access index" );
3251  return begin_[j];
3252 }
3254 //*************************************************************************************************
3255 
3256 
3257 //*************************************************************************************************
3264 template< typename Type > // Data type of the sparse matrix
3266  CompressedMatrix<Type,true>::end( size_t j ) noexcept
3267 {
3268  BLAZE_USER_ASSERT( j < n_, "Invalid sparse matrix column access index" );
3269  return end_[j];
3270 }
3272 //*************************************************************************************************
3273 
3274 
3275 //*************************************************************************************************
3282 template< typename Type > // Data type of the sparse matrix
3284  CompressedMatrix<Type,true>::end( size_t j ) const noexcept
3285 {
3286  BLAZE_USER_ASSERT( j < n_, "Invalid sparse matrix column access index" );
3287  return end_[j];
3288 }
3290 //*************************************************************************************************
3291 
3292 
3293 //*************************************************************************************************
3300 template< typename Type > // Data type of the sparse matrix
3302  CompressedMatrix<Type,true>::cend( size_t j ) const noexcept
3303 {
3304  BLAZE_USER_ASSERT( j < n_, "Invalid sparse matrix column access index" );
3305  return end_[j];
3306 }
3308 //*************************************************************************************************
3309 
3310 
3311 
3312 
3313 //=================================================================================================
3314 //
3315 // ASSIGNMENT OPERATORS
3316 //
3317 //=================================================================================================
3318 
3319 //*************************************************************************************************
3329 template< typename Type > // Data type of the sparse matrix
3330 inline CompressedMatrix<Type,true>&
3331  CompressedMatrix<Type,true>::operator=( const CompressedMatrix& rhs )
3332 {
3333  if( &rhs == this ) return *this;
3334 
3335  const size_t nonzeros( rhs.nonZeros() );
3336 
3337  if( rhs.n_ > capacity_ || nonzeros > capacity() )
3338  {
3339  Iterator* newBegin( new Iterator[2UL*rhs.n_+2UL] );
3340  Iterator* newEnd ( newBegin+(rhs.n_+1UL) );
3341 
3342  newBegin[0UL] = allocate<Element>( nonzeros );
3343  for( size_t j=0UL; j<rhs.n_; ++j ) {
3344  newBegin[j+1UL] = newEnd[j] = std::copy( rhs.begin_[j], rhs.end_[j], newBegin[j] );
3345  }
3346  newEnd[rhs.n_] = newBegin[0UL]+nonzeros;
3347 
3348  std::swap( begin_, newBegin );
3349  end_ = newEnd;
3350  capacity_ = rhs.n_;
3351 
3352  if( newBegin != nullptr ) {
3353  deallocate( newBegin[0UL] );
3354  delete[] newBegin;
3355  }
3356  }
3357  else {
3358  for( size_t j=0UL; j<rhs.n_; ++j ) {
3359  begin_[j+1UL] = end_[j] = std::copy( rhs.begin_[j], rhs.end_[j], begin_[j] );
3360  }
3361  }
3362 
3363  m_ = rhs.m_;
3364  n_ = rhs.n_;
3365 
3366  return *this;
3367 }
3369 //*************************************************************************************************
3370 
3371 
3372 //*************************************************************************************************
3379 template< typename Type > // Data type of the sparse matrix
3380 inline CompressedMatrix<Type,true>&
3381  CompressedMatrix<Type,true>::operator=( CompressedMatrix&& rhs ) noexcept
3382 {
3383  if( begin_ != nullptr ) {
3384  deallocate( begin_[0UL] );
3385  delete[] begin_;
3386  }
3387 
3388  m_ = rhs.m_;
3389  n_ = rhs.n_;
3390  capacity_ = rhs.capacity_;
3391  begin_ = rhs.begin_;
3392  end_ = rhs.end_;
3393 
3394  rhs.m_ = 0UL;
3395  rhs.n_ = 0UL;
3396  rhs.capacity_ = 0UL;
3397  rhs.begin_ = nullptr;
3398  rhs.end_ = nullptr;
3399 
3400  return *this;
3401 }
3403 //*************************************************************************************************
3404 
3405 
3406 //*************************************************************************************************
3416 template< typename Type > // Data type of the sparse matrix
3417 template< typename MT // Type of the right-hand side dense matrix
3418  , bool SO > // Storage order of the right-hand side dense matrix
3419 inline CompressedMatrix<Type,true>&
3420  CompressedMatrix<Type,true>::operator=( const DenseMatrix<MT,SO>& rhs )
3421 {
3422  using blaze::assign;
3423 
3424  if( (~rhs).canAlias( this ) ) {
3425  CompressedMatrix tmp( ~rhs );
3426  swap( tmp );
3427  }
3428  else {
3429  resize( (~rhs).rows(), (~rhs).columns(), false );
3430  assign( *this, ~rhs );
3431  }
3432 
3433  return *this;
3434 }
3436 //*************************************************************************************************
3437 
3438 
3439 //*************************************************************************************************
3449 template< typename Type > // Data type of the sparse matrix
3450 template< typename MT // Type of the right-hand side sparse matrix
3451  , bool SO > // Storage order of the right-hand side sparse matrix
3452 inline CompressedMatrix<Type,true>&
3453  CompressedMatrix<Type,true>::operator=( const SparseMatrix<MT,SO>& rhs )
3454 {
3455  using blaze::assign;
3456 
3457  if( (~rhs).canAlias( this ) ||
3458  (~rhs).columns() > capacity_ ||
3459  (~rhs).nonZeros() > capacity() ) {
3460  CompressedMatrix tmp( ~rhs );
3461  swap( tmp );
3462  }
3463  else {
3464  resize( (~rhs).rows(), (~rhs).columns(), false );
3465  reset();
3466  assign( *this, ~rhs );
3467  }
3468 
3469  return *this;
3470 }
3472 //*************************************************************************************************
3473 
3474 
3475 //*************************************************************************************************
3486 template< typename Type > // Data type of the sparse matrix
3487 template< typename MT // Type of the right-hand side matrix
3488  , bool SO > // Storage order of the right-hand side matrix
3489 inline CompressedMatrix<Type,true>& CompressedMatrix<Type,true>::operator+=( const Matrix<MT,SO>& rhs )
3490 {
3491  using blaze::addAssign;
3492 
3493  if( (~rhs).rows() != m_ || (~rhs).columns() != n_ ) {
3494  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
3495  }
3496 
3497  addAssign( *this, ~rhs );
3498  return *this;
3499 }
3501 //*************************************************************************************************
3502 
3503 
3504 //*************************************************************************************************
3515 template< typename Type > // Data type of the sparse matrix
3516 template< typename MT // Type of the right-hand side matrix
3517  , bool SO > // Storage order of the right-hand side matrix
3518 inline CompressedMatrix<Type,true>& CompressedMatrix<Type,true>::operator-=( const Matrix<MT,SO>& rhs )
3519 {
3520  using blaze::subAssign;
3521 
3522  if( (~rhs).rows() != m_ || (~rhs).columns() != n_ ) {
3523  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
3524  }
3525 
3526  subAssign( *this, ~rhs );
3527  return *this;
3528 }
3530 //*************************************************************************************************
3531 
3532 
3533 //*************************************************************************************************
3544 template< typename Type > // Data type of the sparse matrix
3545 template< typename MT // Type of the right-hand side matrix
3546  , bool SO > // Storage order of the right-hand side matrix
3547 inline CompressedMatrix<Type,true>&
3548  CompressedMatrix<Type,true>::operator*=( const Matrix<MT,SO>& rhs )
3549 {
3550  if( (~rhs).rows() != n_ ) {
3551  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
3552  }
3553 
3554  CompressedMatrix tmp( *this * (~rhs) );
3555  swap( tmp );
3556 
3557  return *this;
3558 }
3560 //*************************************************************************************************
3561 
3562 
3563 //*************************************************************************************************
3571 template< typename Type > // Data type of the sparse matrix
3572 template< typename Other > // Data type of the right-hand side scalar
3573 inline EnableIf_< IsNumeric<Other>, CompressedMatrix<Type,true> >&
3574  CompressedMatrix<Type,true>::operator*=( Other rhs )
3575 {
3576  for( size_t j=0UL; j<n_; ++j ) {
3577  const Iterator last( end(j) );
3578  for( Iterator element=begin(j); element!=last; ++element )
3579  element->value_ *= rhs;
3580  }
3581  return *this;
3582 }
3584 //*************************************************************************************************
3585 
3586 
3587 //*************************************************************************************************
3595 template< typename Type > // Data type of the sparse matrix
3596 template< typename Other > // Data type of the right-hand side scalar
3597 inline EnableIf_< IsNumeric<Other>, CompressedMatrix<Type,true> >&
3598  CompressedMatrix<Type,true>::operator/=( Other rhs )
3599 {
3600  BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
3601 
3602  typedef DivTrait_<Type,Other> DT;
3603  typedef If_< IsNumeric<DT>, DT, Other > Tmp;
3604 
3605  // Depending on the two involved data types, an integer division is applied or a
3606  // floating point division is selected.
3607  if( IsNumeric<DT>::value && IsFloatingPoint<DT>::value ) {
3608  const Tmp tmp( Tmp(1)/static_cast<Tmp>( rhs ) );
3609  for( size_t j=0UL; j<n_; ++j ) {
3610  const Iterator last( end(j) );
3611  for( Iterator element=begin(j); element!=last; ++element )
3612  element->value_ *= tmp;
3613  }
3614  }
3615  else {
3616  for( size_t j=0UL; j<n_; ++j ) {
3617  const Iterator last( end(j) );
3618  for( Iterator element=begin(j); element!=last; ++element )
3619  element->value_ /= rhs;
3620  }
3621  }
3622 
3623  return *this;
3624 }
3626 //*************************************************************************************************
3627 
3628 
3629 
3630 
3631 //=================================================================================================
3632 //
3633 // UTILITY FUNCTIONS
3634 //
3635 //=================================================================================================
3636 
3637 //*************************************************************************************************
3643 template< typename Type > // Data type of the sparse matrix
3644 inline size_t CompressedMatrix<Type,true>::rows() const noexcept
3645 {
3646  return m_;
3647 }
3649 //*************************************************************************************************
3650 
3651 
3652 //*************************************************************************************************
3658 template< typename Type > // Data type of the sparse matrix
3659 inline size_t CompressedMatrix<Type,true>::columns() const noexcept
3660 {
3661  return n_;
3662 }
3664 //*************************************************************************************************
3665 
3666 
3667 //*************************************************************************************************
3673 template< typename Type > // Data type of the sparse matrix
3674 inline size_t CompressedMatrix<Type,true>::capacity() const noexcept
3675 {
3676  if( begin_ != nullptr )
3677  return end_[n_] - begin_[0UL];
3678  else return 0UL;
3679 }
3681 //*************************************************************************************************
3682 
3683 
3684 //*************************************************************************************************
3691 template< typename Type > // Data type of the sparse matrix
3692 inline size_t CompressedMatrix<Type,true>::capacity( size_t j ) const noexcept
3693 {
3694  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
3695  return begin_[j+1UL] - begin_[j];
3696 }
3698 //*************************************************************************************************
3699 
3700 
3701 //*************************************************************************************************
3707 template< typename Type > // Data type of the sparse matrix
3708 inline size_t CompressedMatrix<Type,true>::nonZeros() const
3709 {
3710  size_t nonzeros( 0UL );
3711 
3712  for( size_t j=0UL; j<n_; ++j )
3713  nonzeros += nonZeros( j );
3714 
3715  return nonzeros;
3716 }
3718 //*************************************************************************************************
3719 
3720 
3721 //*************************************************************************************************
3728 template< typename Type > // Data type of the sparse matrix
3729 inline size_t CompressedMatrix<Type,true>::nonZeros( size_t j ) const
3730 {
3731  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
3732  return end_[j] - begin_[j];
3733 }
3735 //*************************************************************************************************
3736 
3737 
3738 //*************************************************************************************************
3744 template< typename Type > // Data type of the sparse matrix
3746 {
3747  for( size_t j=0UL; j<n_; ++j )
3748  end_[j] = begin_[j];
3749 }
3751 //*************************************************************************************************
3752 
3753 
3754 //*************************************************************************************************
3764 template< typename Type > // Data type of the sparse matrix
3765 inline void CompressedMatrix<Type,true>::reset( size_t j )
3766 {
3767  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
3768  end_[j] = begin_[j];
3769 }
3771 //*************************************************************************************************
3772 
3773 
3774 //*************************************************************************************************
3782 template< typename Type > // Data type of the sparse matrix
3784 {
3785  end_[0UL] = end_[n_];
3786  m_ = 0UL;
3787  n_ = 0UL;
3788 }
3790 //*************************************************************************************************
3791 
3792 
3793 //*************************************************************************************************
3806 template< typename Type > // Data type of the sparse matrix
3808  CompressedMatrix<Type,true>::set( size_t i, size_t j, const Type& value )
3809 {
3810  BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
3811  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
3812 
3813  const Iterator pos( lowerBound( i, j ) );
3814 
3815  if( pos != end_[j] && pos->index_ == i ) {
3816  pos->value() = value;
3817  return pos;
3818  }
3819  else return insert( pos, i, j, value );
3820 }
3822 //*************************************************************************************************
3823 
3824 
3825 //*************************************************************************************************
3839 template< typename Type > // Data type of the sparse matrix
3841  CompressedMatrix<Type,true>::insert( size_t i, size_t j, const Type& value )
3842 {
3843  BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
3844  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
3845 
3846  const Iterator pos( lowerBound( i, j ) );
3847 
3848  if( pos != end_[j] && pos->index_ == i ) {
3849  BLAZE_THROW_INVALID_ARGUMENT( "Bad access index" );
3850  }
3851 
3852  return insert( pos, i, j, value );
3853 }
3855 //*************************************************************************************************
3856 
3857 
3858 //*************************************************************************************************
3869 template< typename Type > // Data type of the sparse matrix
3871  CompressedMatrix<Type,true>::insert( Iterator pos, size_t i, size_t j, const Type& value )
3872 {
3873  if( begin_[j+1UL] - end_[j] != 0 ) {
3874  std::move_backward( pos, end_[j], end_[j]+1UL );
3875  pos->value_ = value;
3876  pos->index_ = i;
3877  ++end_[j];
3878 
3879  return pos;
3880  }
3881  else if( end_[n_] - begin_[n_] != 0 ) {
3882  std::move_backward( pos, end_[n_-1UL], end_[n_-1]+1UL );
3883 
3884  pos->value_ = value;
3885  pos->index_ = i;
3886 
3887  for( size_t k=j+1UL; k<n_+1UL; ++k ) {
3888  ++begin_[k];
3889  ++end_[k-1UL];
3890  }
3891 
3892  return pos;
3893  }
3894  else {
3895  size_t newCapacity( extendCapacity() );
3896 
3897  Iterator* newBegin = new Iterator[2UL*capacity_+2UL];
3898  Iterator* newEnd = newBegin+capacity_+1UL;
3899 
3900  newBegin[0UL] = allocate<Element>( newCapacity );
3901 
3902  for( size_t k=0UL; k<j; ++k ) {
3903  const size_t nonzeros( end_[k] - begin_[k] );
3904  const size_t total( begin_[k+1UL] - begin_[k] );
3905  newEnd [k] = newBegin[k] + nonzeros;
3906  newBegin[k+1UL] = newBegin[k] + total;
3907  }
3908  newEnd [j] = newBegin[j] + ( end_[j] - begin_[j] ) + 1;
3909  newBegin[j+1UL] = newBegin[j] + ( begin_[j+1UL] - begin_[j] ) + 1;
3910  for( size_t k=j+1UL; k<n_; ++k ) {
3911  const size_t nonzeros( end_[k] - begin_[k] );
3912  const size_t total( begin_[k+1UL] - begin_[k] );
3913  newEnd [k] = newBegin[k] + nonzeros;
3914  newBegin[k+1UL] = newBegin[k] + total;
3915  }
3916 
3917  newEnd[n_] = newEnd[capacity_] = newBegin[0UL]+newCapacity;
3918 
3919  Iterator tmp = std::move( begin_[0UL], pos, newBegin[0UL] );
3920  tmp->value_ = value;
3921  tmp->index_ = i;
3922  std::move( pos, end_[n_-1UL], tmp+1UL );
3923 
3924  std::swap( newBegin, begin_ );
3925  end_ = newEnd;
3926  deallocate( newBegin[0UL] );
3927  delete[] newBegin;
3928 
3929  return tmp;
3930  }
3931 }
3933 //*************************************************************************************************
3934 
3935 
3936 //*************************************************************************************************
3946 template< typename Type > // Data type of the sparse matrix
3947 inline void CompressedMatrix<Type,true>::erase( size_t i, size_t j )
3948 {
3949  BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
3950  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
3951 
3952  const Iterator pos( find( i, j ) );
3953  if( pos != end_[j] )
3954  end_[j] = std::move( pos+1, end_[j], pos );
3955 }
3957 //*************************************************************************************************
3958 
3959 
3960 //*************************************************************************************************
3970 template< typename Type > // Data type of the sparse matrix
3972  CompressedMatrix<Type,true>::erase( size_t j, Iterator pos )
3973 {
3974  BLAZE_USER_ASSERT( j < columns() , "Invalid row access index" );
3975  BLAZE_USER_ASSERT( pos >= begin_[j] && pos <= end_[j], "Invalid compressed matrix iterator" );
3976 
3977  if( pos != end_[j] )
3978  end_[j] = std::move( pos+1, end_[j], pos );
3979 
3980  return pos;
3981 }
3983 //*************************************************************************************************
3984 
3985 
3986 //*************************************************************************************************
3997 template< typename Type > // Data type of the sparse matrix
3999  CompressedMatrix<Type,true>::erase( size_t j, Iterator first, Iterator last )
4000 {
4001  BLAZE_USER_ASSERT( j < columns(), "Invalid row access index" );
4002  BLAZE_USER_ASSERT( first <= last, "Invalid iterator range" );
4003  BLAZE_USER_ASSERT( first >= begin_[j] && first <= end_[j], "Invalid compressed matrix iterator" );
4004  BLAZE_USER_ASSERT( last >= begin_[j] && last <= end_[j], "Invalid compressed matrix iterator" );
4005 
4006  if( first != last )
4007  end_[j] = std::move( last, end_[j], first );
4008 
4009  return first;
4010 }
4012 //*************************************************************************************************
4013 
4014 
4015 //*************************************************************************************************
4031 template< typename Type > // Data type of the sparse matrix
4032 void CompressedMatrix<Type,true>::resize( size_t m, size_t n, bool preserve )
4033 {
4034  BLAZE_INTERNAL_ASSERT( end_ >= begin_, "Invalid internal storage detected" );
4035  BLAZE_INTERNAL_ASSERT( begin_ == nullptr || size_t( end_ - begin_ ) == capacity_ + 1UL, "Invalid storage setting detected" );
4036 
4037  if( m == m_ && n == n_ ) return;
4038 
4039  if( begin_ == nullptr )
4040  {
4041  begin_ = new Iterator[2UL*n+2UL];
4042  end_ = begin_+n+1UL;
4043 
4044  for( size_t j=0UL; j<2UL*n+2UL; ++j ) {
4045  begin_[j] = nullptr;
4046  }
4047 
4048  capacity_ = n;
4049  }
4050  else if( n > capacity_ )
4051  {
4052  Iterator* newBegin( new Iterator[2UL*n+2UL] );
4053  Iterator* newEnd ( newBegin+n+1UL );
4054 
4055  newBegin[0UL] = begin_[0UL];
4056 
4057  if( preserve ) {
4058  for( size_t j=0UL; j<n_; ++j ) {
4059  newEnd [j] = end_ [j];
4060  newBegin[j+1UL] = begin_[j+1UL];
4061  }
4062  for( size_t j=n_; j<n; ++j ) {
4063  newBegin[j+1UL] = newEnd[j] = begin_[n_];
4064  }
4065  }
4066  else {
4067  for( size_t j=0UL; j<n; ++j ) {
4068  newBegin[j+1UL] = newEnd[j] = begin_[0UL];
4069  }
4070  }
4071 
4072  newEnd[n] = end_[n_];
4073 
4074  std::swap( newBegin, begin_ );
4075  delete[] newBegin;
4076  end_ = newEnd;
4077  capacity_ = n;
4078  }
4079  else if( n > n_ )
4080  {
4081  end_[n] = end_[n_];
4082 
4083  if( !preserve ) {
4084  for( size_t j=0UL; j<n_; ++j )
4085  end_[j] = begin_[j];
4086  }
4087 
4088  for( size_t j=n_; j<n; ++j ) {
4089  begin_[j+1UL] = end_[j] = begin_[n_];
4090  }
4091  }
4092  else
4093  {
4094  if( preserve ) {
4095  for( size_t j=0UL; j<n; ++j )
4096  end_[j] = lowerBound( m, j );
4097  }
4098  else {
4099  for( size_t j=0UL; j<n; ++j )
4100  end_[j] = begin_[j];
4101  }
4102 
4103  end_[n] = end_[n_];
4104  }
4105 
4106  m_ = m;
4107  n_ = n;
4108 
4109  BLAZE_INTERNAL_ASSERT( end_ >= begin_, "Invalid internal storage detected" );
4110  BLAZE_INTERNAL_ASSERT( size_t( end_ - begin_ ) == capacity_ + 1UL, "Invalid storage setting detected" );
4111 }
4113 //*************************************************************************************************
4114 
4115 
4116 //*************************************************************************************************
4127 template< typename Type > // Data type of the sparse matrix
4128 inline void CompressedMatrix<Type,true>::reserve( size_t nonzeros )
4129 {
4130  if( nonzeros > capacity() )
4131  reserveElements( nonzeros );
4132 }
4134 //*************************************************************************************************
4135 
4136 
4137 //*************************************************************************************************
4149 template< typename Type > // Data type of the sparse matrix
4150 void CompressedMatrix<Type,true>::reserve( size_t j, size_t nonzeros )
4151 {
4152  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
4153 
4154  BLAZE_INTERNAL_ASSERT( end_ >= begin_, "Invalid internal storage detected" );
4155  BLAZE_INTERNAL_ASSERT( static_cast<size_t>( end_ - begin_ ) == capacity_ + 1UL, "Invalid storage setting detected" );
4156 
4157  const size_t current( capacity(j) );
4158 
4159  if( current >= nonzeros ) return;
4160 
4161  const ptrdiff_t additional( nonzeros - current );
4162 
4163  if( end_[n_] - begin_[n_] < additional )
4164  {
4165  const size_t newCapacity( begin_[n_] - begin_[0UL] + additional );
4166  BLAZE_INTERNAL_ASSERT( newCapacity > capacity(), "Invalid capacity value" );
4167 
4168  Iterator* newBegin( new Iterator[2UL*n_+2UL] );
4169  Iterator* newEnd ( newBegin+n_+1UL );
4170 
4171  newBegin[0UL] = allocate<Element>( newCapacity );
4172  newEnd [n_ ] = newBegin[0UL]+newCapacity;
4173 
4174  for( size_t k=0UL; k<j; ++k ) {
4175  newEnd [k ] = transfer( begin_[k], end_[k], newBegin[k] );
4176  newBegin[k+1UL] = newBegin[k] + capacity(k);
4177  }
4178  newEnd [j ] = transfer( begin_[j], end_[j], newBegin[j] );
4179  newBegin[j+1UL] = newBegin[j] + nonzeros;
4180  for( size_t k=j+1UL; k<n_; ++k ) {
4181  newEnd [k ] = transfer( begin_[k], end_[k], newBegin[k] );
4182  newBegin[k+1UL] = newBegin[k] + capacity(k);
4183  }
4184 
4185  BLAZE_INTERNAL_ASSERT( newBegin[n_] == newEnd[n_], "Invalid pointer calculations" );
4186 
4187  std::swap( newBegin, begin_ );
4188  deallocate( newBegin[0UL] );
4189  delete[] newBegin;
4190  end_ = newEnd;
4191  capacity_ = n_;
4192  }
4193  else
4194  {
4195  begin_[n_] += additional;
4196  for( size_t k=n_-1UL; k>j; --k ) {
4197  begin_[k] = std::move_backward( begin_[k], end_[k], end_[k]+additional );
4198  end_ [k] += additional;
4199  }
4200  }
4201 
4202  BLAZE_INTERNAL_ASSERT( end_ >= begin_, "Invalid internal storage detected" );
4203  BLAZE_INTERNAL_ASSERT( static_cast<size_t>( end_ - begin_ ) == capacity_ + 1UL, "Invalid storage setting detected" );
4204 }
4206 //*************************************************************************************************
4207 
4208 
4209 //*************************************************************************************************
4219 template< typename Type > // Data type of the sparse matrix
4220 void CompressedMatrix<Type,true>::trim()
4221 {
4222  for( size_t j=0UL; j<n_; ++j )
4223  trim( j );
4224 }
4226 //*************************************************************************************************
4227 
4228 
4229 //*************************************************************************************************
4240 template< typename Type > // Data type of the sparse matrix
4241 void CompressedMatrix<Type,true>::trim( size_t j )
4242 {
4243  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
4244 
4245  if( j < ( n_ - 1UL ) )
4246  end_[j+1] = std::move( begin_[j+1], end_[j+1], end_[j] );
4247  begin_[j+1] = end_[j];
4248 }
4250 //*************************************************************************************************
4251 
4252 
4253 //*************************************************************************************************
4259 template< typename Type > // Data type of the sparse matrix
4260 inline CompressedMatrix<Type,true>& CompressedMatrix<Type,true>::transpose()
4261 {
4262  CompressedMatrix tmp( trans( *this ) );
4263  swap( tmp );
4264  return *this;
4265 }
4267 //*************************************************************************************************
4268 
4269 
4270 //*************************************************************************************************
4276 template< typename Type > // Data type of the sparse matrix
4277 inline CompressedMatrix<Type,true>& CompressedMatrix<Type,true>::ctranspose()
4278 {
4279  CompressedMatrix tmp( ctrans( *this ) );
4280  swap( tmp );
4281  return *this;
4282 }
4284 //*************************************************************************************************
4285 
4286 
4287 //*************************************************************************************************
4294 template< typename Type > // Data type of the sparse matrix
4295 template< typename Other > // Data type of the scalar value
4296 inline CompressedMatrix<Type,true>& CompressedMatrix<Type,true>::scale( const Other& scalar )
4297 {
4298  for( size_t j=0UL; j<n_; ++j )
4299  for( Iterator element=begin_[j]; element!=end_[j]; ++element )
4300  element->value_ *= scalar;
4301 
4302  return *this;
4303 }
4305 //*************************************************************************************************
4306 
4307 
4308 //*************************************************************************************************
4315 template< typename Type > // Data type of the sparse matrix
4316 template< typename Other > // Data type of the scalar value
4317 inline CompressedMatrix<Type,true>& CompressedMatrix<Type,true>::scaleDiagonal( Other scalar )
4318 {
4319  const size_t size( blaze::min( m_, n_ ) );
4320 
4321  for( size_t j=0UL; j<size; ++j ) {
4322  Iterator pos = lowerBound( j, j );
4323  if( pos != end_[j] && pos->index_ == j )
4324  pos->value_ *= scalar;
4325  }
4326 
4327  return *this;
4328 }
4330 //*************************************************************************************************
4331 
4332 
4333 //*************************************************************************************************
4340 template< typename Type > // Data type of the sparse matrix
4341 inline void CompressedMatrix<Type,true>::swap( CompressedMatrix& sm ) noexcept
4342 {
4343  std::swap( m_, sm.m_ );
4344  std::swap( n_, sm.n_ );
4345  std::swap( capacity_, sm.capacity_ );
4346  std::swap( begin_, sm.begin_ );
4347  std::swap( end_ , sm.end_ );
4348 }
4350 //*************************************************************************************************
4351 
4352 
4353 //*************************************************************************************************
4362 template< typename Type > // Data type of the sparse matrix
4363 inline size_t CompressedMatrix<Type,true>::extendCapacity() const noexcept
4364 {
4365  size_t nonzeros( 2UL*capacity()+1UL );
4366  nonzeros = blaze::max( nonzeros, 7UL );
4367 
4368  BLAZE_INTERNAL_ASSERT( nonzeros > capacity(), "Invalid capacity value" );
4369 
4370  return nonzeros;
4371 }
4373 //*************************************************************************************************
4374 
4375 
4376 //*************************************************************************************************
4383 template< typename Type > // Data type of the sparse matrix
4384 void CompressedMatrix<Type,true>::reserveElements( size_t nonzeros )
4385 {
4386  Iterator* newBegin = new Iterator[2UL*capacity_+2UL];
4387  Iterator* newEnd = newBegin+capacity_+1UL;
4388 
4389  newBegin[0UL] = allocate<Element>( nonzeros );
4390 
4391  for( size_t k=0UL; k<n_; ++k ) {
4392  BLAZE_INTERNAL_ASSERT( begin_[k] <= end_[k], "Invalid column pointers" );
4393  newEnd [k] = transfer( begin_[k], end_[k], newBegin[k] );
4394  newBegin[k+1UL] = newBegin[k] + ( begin_[k+1UL] - begin_[k] );
4395  }
4396 
4397  newEnd[n_] = newBegin[0UL]+nonzeros;
4398 
4399  std::swap( newBegin, begin_ );
4400  end_ = newEnd;
4401 
4402  if( newBegin != nullptr ) {
4403  deallocate( newBegin[0UL] );
4404  delete[] newBegin;
4405  }
4406 }
4408 //*************************************************************************************************
4409 
4410 
4411 
4412 
4413 //=================================================================================================
4414 //
4415 // LOOKUP FUNCTIONS
4416 //
4417 //=================================================================================================
4418 
4419 //*************************************************************************************************
4434 template< typename Type > // Data type of the sparse matrix
4436  CompressedMatrix<Type,true>::find( size_t i, size_t j )
4437 {
4438  return const_cast<Iterator>( const_cast<const This&>( *this ).find( i, j ) );
4439 }
4441 //*************************************************************************************************
4442 
4443 
4444 //*************************************************************************************************
4459 template< typename Type > // Data type of the sparse matrix
4461  CompressedMatrix<Type,true>::find( size_t i, size_t j ) const
4462 {
4463  const ConstIterator pos( lowerBound( i, j ) );
4464  if( pos != end_[j] && pos->index_ == i )
4465  return pos;
4466  else return end_[j];
4467 }
4469 //*************************************************************************************************
4470 
4471 
4472 //*************************************************************************************************
4486 template< typename Type > // Data type of the sparse matrix
4488  CompressedMatrix<Type,true>::lowerBound( size_t i, size_t j )
4489 {
4490  return const_cast<Iterator>( const_cast<const This&>( *this ).lowerBound( i, j ) );
4491 }
4493 //*************************************************************************************************
4494 
4495 
4496 //*************************************************************************************************
4510 template< typename Type > // Data type of the sparse matrix
4512  CompressedMatrix<Type,true>::lowerBound( size_t i, size_t j ) const
4513 {
4514  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
4515  return std::lower_bound( begin_[j], end_[j], i,
4516  []( const Element& element, size_t index )
4517  {
4518  return element.index() < index;
4519  } );
4520 }
4522 //*************************************************************************************************
4523 
4524 
4525 //*************************************************************************************************
4539 template< typename Type > // Data type of the sparse matrix
4541  CompressedMatrix<Type,true>::upperBound( size_t i, size_t j )
4542 {
4543  return const_cast<Iterator>( const_cast<const This&>( *this ).upperBound( i, j ) );
4544 }
4546 //*************************************************************************************************
4547 
4548 
4549 //*************************************************************************************************
4563 template< typename Type > // Data type of the sparse matrix
4565  CompressedMatrix<Type,true>::upperBound( size_t i, size_t j ) const
4566 {
4567  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
4568  return std::upper_bound( begin_[j], end_[j], i,
4569  []( size_t index, const Element& element )
4570  {
4571  return index < element.index();
4572  } );
4573 }
4575 //*************************************************************************************************
4576 
4577 
4578 
4579 
4580 //=================================================================================================
4581 //
4582 // LOW-LEVEL UTILITY FUNCTIONS
4583 //
4584 //=================================================================================================
4585 
4586 //*************************************************************************************************
4628 template< typename Type > // Data type of the sparse matrix
4629 inline void CompressedMatrix<Type,true>::append( size_t i, size_t j, const Type& value, bool check )
4630 {
4631  BLAZE_USER_ASSERT( i < m_, "Invalid row access index" );
4632  BLAZE_USER_ASSERT( j < n_, "Invalid column access index" );
4633  BLAZE_USER_ASSERT( end_[j] < end_[n_], "Not enough reserved capacity left" );
4634  BLAZE_USER_ASSERT( begin_[j] == end_[j] || i > ( end_[j]-1UL )->index_, "Index is not strictly increasing" );
4635 
4636  end_[j]->value_ = value;
4637 
4638  if( !check || !isDefault( end_[j]->value_ ) ) {
4639  end_[j]->index_ = i;
4640  ++end_[j];
4641  }
4642 }
4644 //*************************************************************************************************
4645 
4646 
4647 //*************************************************************************************************
4661 template< typename Type > // Data type of the sparse matrix
4662 inline void CompressedMatrix<Type,true>::finalize( size_t j )
4663 {
4664  BLAZE_USER_ASSERT( j < n_, "Invalid row access index" );
4665 
4666  begin_[j+1UL] = end_[j];
4667  if( j != n_-1UL )
4668  end_[j+1UL] = end_[j];
4669 }
4671 //*************************************************************************************************
4672 
4673 
4674 
4675 
4676 //=================================================================================================
4677 //
4678 // EXPRESSION TEMPLATE EVALUATION FUNCTIONS
4679 //
4680 //=================================================================================================
4681 
4682 //*************************************************************************************************
4693 template< typename Type > // Data type of the sparse matrix
4694 template< typename Other > // Data type of the foreign expression
4695 inline bool CompressedMatrix<Type,true>::canAlias( const Other* alias ) const noexcept
4696 {
4697  return static_cast<const void*>( this ) == static_cast<const void*>( alias );
4698 }
4700 //*************************************************************************************************
4701 
4702 
4703 //*************************************************************************************************
4714 template< typename Type > // Data type of the sparse matrix
4715 template< typename Other > // Data type of the foreign expression
4716 inline bool CompressedMatrix<Type,true>::isAliased( const Other* alias ) const noexcept
4717 {
4718  return static_cast<const void*>( this ) == static_cast<const void*>( alias );
4719 }
4721 //*************************************************************************************************
4722 
4723 
4724 //*************************************************************************************************
4735 template< typename Type > // Data type of the sparse matrix
4736 inline bool CompressedMatrix<Type,true>::canSMPAssign() const noexcept
4737 {
4738  return false;
4739 }
4741 //*************************************************************************************************
4742 
4743 
4744 //*************************************************************************************************
4756 template< typename Type > // Data type of the sparse matrix
4757 template< typename MT // Type of the right-hand side dense matrix
4758  , bool SO > // Storage order of the right-hand side dense matrix
4759 inline void CompressedMatrix<Type,true>::assign( const DenseMatrix<MT,SO>& rhs )
4760 {
4761  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
4762  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
4763 
4764  if( m_ == 0UL || n_ == 0UL )
4765  return;
4766 
4767  size_t nonzeros( 0UL );
4768 
4769  for( size_t j=1UL; j<=n_; ++j )
4770  begin_[j] = end_[j] = end_[n_];
4771 
4772  for( size_t j=0UL; j<n_; ++j )
4773  {
4774  begin_[j] = end_[j] = begin_[0UL]+nonzeros;
4775 
4776  const size_t ibegin( ( IsLower<MT>::value )
4777  ?( IsStrictlyLower<MT>::value ? j+1UL : j )
4778  :( 0UL ) );
4779  const size_t iend ( ( IsUpper<MT>::value )
4780  ?( IsStrictlyUpper<MT>::value ? j : j+1UL )
4781  :( m_ ) );
4782 
4783  for( size_t i=ibegin; i<iend; ++i )
4784  {
4785  if( nonzeros == capacity() ) {
4786  reserveElements( extendCapacity() );
4787  for( size_t k=j+1UL; k<=n_; ++k )
4788  begin_[k] = end_[k] = end_[n_];
4789  }
4790 
4791  end_[j]->value_ = (~rhs)(i,j);
4792 
4793  if( !isDefault( end_[j]->value_ ) ) {
4794  end_[j]->index_ = i;
4795  ++end_[j];
4796  ++nonzeros;
4797  }
4798  }
4799  }
4800 
4801  begin_[n_] = begin_[0UL]+nonzeros;
4802 }
4804 //*************************************************************************************************
4805 
4806 
4807 //*************************************************************************************************
4819 template< typename Type > // Data type of the sparse matrix
4820 template< typename MT > // Type of the right-hand side sparse matrix
4821 inline void CompressedMatrix<Type,true>::assign( const SparseMatrix<MT,true>& rhs )
4822 {
4823  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
4824  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
4825  BLAZE_INTERNAL_ASSERT( nonZeros() == 0UL, "Invalid non-zero elements detected" );
4826  BLAZE_INTERNAL_ASSERT( capacity() >= (~rhs).nonZeros(), "Invalid capacity detected" );
4827 
4828  if( n_ == 0UL || begin_[0] == nullptr )
4829  return;
4830 
4831  for( size_t j=0UL; j<n_; ++j ) {
4832  begin_[j+1UL] = end_[j] = std::copy( (~rhs).begin(j), (~rhs).end(j), begin_[j] );
4833  }
4834 }
4836 //*************************************************************************************************
4837 
4838 
4839 //*************************************************************************************************
4851 template< typename Type > // Data type of the sparse matrix
4852 template< typename MT > // Type of the right-hand side sparse matrix
4853 inline void CompressedMatrix<Type,true>::assign( const SparseMatrix<MT,false>& rhs )
4854 {
4856 
4857  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
4858  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
4859  BLAZE_INTERNAL_ASSERT( nonZeros() == 0UL, "Invalid non-zero elements detected" );
4860  BLAZE_INTERNAL_ASSERT( capacity() >= (~rhs).nonZeros(), "Invalid capacity detected" );
4861 
4862  typedef ConstIterator_<MT> RhsIterator;
4863 
4864  // Counting the number of elements per column
4865  std::vector<size_t> columnLengths( n_, 0UL );
4866  for( size_t i=0UL; i<m_; ++i ) {
4867  for( RhsIterator element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
4868  ++columnLengths[element->index()];
4869  }
4870 
4871  // Resizing the sparse matrix
4872  for( size_t j=0UL; j<n_; ++j ) {
4873  begin_[j+1UL] = end_[j+1UL] = begin_[j] + columnLengths[j];
4874  }
4875 
4876  // Appending the elements to the columns of the sparse matrix
4877  for( size_t i=0UL; i<m_; ++i ) {
4878  for( RhsIterator element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
4879  append( i, element->index(), element->value() );
4880  }
4881 }
4883 //*************************************************************************************************
4884 
4885 
4886 //*************************************************************************************************
4898 template< typename Type > // Data type of the sparse matrix
4899 template< typename MT // Type of the right-hand side dense matrix
4900  , bool SO > // Storage order of the right-hand side dense matrix
4901 inline void CompressedMatrix<Type,true>::addAssign( const DenseMatrix<MT,SO>& rhs )
4902 {
4903  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
4904  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
4905 
4906  CompressedMatrix tmp( serial( *this + (~rhs) ) );
4907  swap( tmp );
4908 }
4910 //*************************************************************************************************
4911 
4912 
4913 //*************************************************************************************************
4925 template< typename Type > // Data type of the sparse matrix
4926 template< typename MT // Type of the right-hand side sparse matrix
4927  , bool SO > // Storage order of the right-hand side sparse matrix
4928 inline void CompressedMatrix<Type,true>::addAssign( const SparseMatrix<MT,SO>& rhs )
4929 {
4930  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
4931  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
4932 
4933  CompressedMatrix tmp( serial( *this + (~rhs) ) );
4934  swap( tmp );
4935 }
4937 //*************************************************************************************************
4938 
4939 
4940 //*************************************************************************************************
4952 template< typename Type > // Data type of the sparse matrix
4953 template< typename MT // Type of the right-hand side dense matrix
4954  , bool SO > // Storage order of the right-hand side dense matrix
4955 inline void CompressedMatrix<Type,true>::subAssign( const DenseMatrix<MT,SO>& rhs )
4956 {
4957  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
4958  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
4959 
4960  CompressedMatrix tmp( serial( *this - (~rhs) ) );
4961  swap( tmp );
4962 }
4964 //*************************************************************************************************
4965 
4966 
4967 //*************************************************************************************************
4979 template< typename Type > // Data type of the sparse matrix
4980 template< typename MT // Type of the right-hand side sparse matrix
4981  , bool SO > // Storage order of the right-hand side sparse matrix
4982 inline void CompressedMatrix<Type,true>::subAssign( const SparseMatrix<MT,SO>& rhs )
4983 {
4984  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
4985  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
4986 
4987  CompressedMatrix tmp( serial( *this - (~rhs) ) );
4988  swap( tmp );
4989 }
4991 //*************************************************************************************************
4992 
4993 
4994 
4995 
4996 
4997 
4998 
4999 
5000 //=================================================================================================
5001 //
5002 // COMPRESSEDMATRIX OPERATORS
5003 //
5004 //=================================================================================================
5005 
5006 //*************************************************************************************************
5009 template< typename Type, bool SO >
5010 inline void reset( CompressedMatrix<Type,SO>& m );
5011 
5012 template< typename Type, bool SO >
5013 inline void reset( CompressedMatrix<Type,SO>& m, size_t i );
5014 
5015 template< typename Type, bool SO >
5016 inline void clear( CompressedMatrix<Type,SO>& m );
5017 
5018 template< typename Type, bool SO >
5019 inline bool isDefault( const CompressedMatrix<Type,SO>& m );
5020 
5021 template< typename Type, bool SO >
5022 inline bool isIntact( const CompressedMatrix<Type,SO>& m );
5023 
5024 template< typename Type, bool SO >
5025 inline void swap( CompressedMatrix<Type,SO>& a, CompressedMatrix<Type,SO>& b ) noexcept;
5027 //*************************************************************************************************
5028 
5029 
5030 //*************************************************************************************************
5037 template< typename Type // Data type of the sparse matrix
5038  , bool SO > // Storage order
5039 inline void reset( CompressedMatrix<Type,SO>& m )
5040 {
5041  m.reset();
5042 }
5043 //*************************************************************************************************
5044 
5045 
5046 //*************************************************************************************************
5059 template< typename Type // Data type of the sparse matrix
5060  , bool SO > // Storage order
5061 inline void reset( CompressedMatrix<Type,SO>& m, size_t i )
5062 {
5063  m.reset( i );
5064 }
5065 //*************************************************************************************************
5066 
5067 
5068 //*************************************************************************************************
5075 template< typename Type // Data type of the sparse matrix
5076  , bool SO > // Storage order
5077 inline void clear( CompressedMatrix<Type,SO>& m )
5078 {
5079  m.clear();
5080 }
5081 //*************************************************************************************************
5082 
5083 
5084 //*************************************************************************************************
5102 template< typename Type // Data type of the sparse matrix
5103  , bool SO > // Storage order
5104 inline bool isDefault( const CompressedMatrix<Type,SO>& m )
5105 {
5106  return ( m.rows() == 0UL && m.columns() == 0UL );
5107 }
5108 //*************************************************************************************************
5109 
5110 
5111 //*************************************************************************************************
5129 template< typename Type // Data type of the sparse matrix
5130  , bool SO > // Storage order
5131 inline bool isIntact( const CompressedMatrix<Type,SO>& m )
5132 {
5133  return ( m.nonZeros() <= m.capacity() );
5134 }
5135 //*************************************************************************************************
5136 
5137 
5138 //*************************************************************************************************
5146 template< typename Type // Data type of the sparse matrix
5147  , bool SO > // Storage order
5148 inline void swap( CompressedMatrix<Type,SO>& a, CompressedMatrix<Type,SO>& b ) noexcept
5149 {
5150  a.swap( b );
5151 }
5152 //*************************************************************************************************
5153 
5154 
5155 
5156 
5157 //=================================================================================================
5158 //
5159 // ISRESIZABLE SPECIALIZATIONS
5160 //
5161 //=================================================================================================
5162 
5163 //*************************************************************************************************
5165 template< typename T, bool SO >
5166 struct IsResizable< CompressedMatrix<T,SO> > : public TrueType
5167 {};
5169 //*************************************************************************************************
5170 
5171 
5172 
5173 
5174 //=================================================================================================
5175 //
5176 // ADDTRAIT SPECIALIZATIONS
5177 //
5178 //=================================================================================================
5179 
5180 //*************************************************************************************************
5182 template< typename T1, bool SO, typename T2, size_t M, size_t N >
5183 struct AddTrait< CompressedMatrix<T1,SO>, StaticMatrix<T2,M,N,SO> >
5184 {
5185  using Type = StaticMatrix< AddTrait_<T1,T2>, M, N, SO >;
5186 };
5187 
5188 template< typename T1, bool SO1, typename T2, size_t M, size_t N, bool SO2 >
5189 struct AddTrait< CompressedMatrix<T1,SO1>, StaticMatrix<T2,M,N,SO2> >
5190 {
5191  using Type = StaticMatrix< AddTrait_<T1,T2>, M, N, SO2 >;
5192 };
5193 
5194 template< typename T1, size_t M, size_t N, bool SO, typename T2 >
5195 struct AddTrait< StaticMatrix<T1,M,N,SO>, CompressedMatrix<T2,SO> >
5196 {
5197  using Type = StaticMatrix< AddTrait_<T1,T2>, M, N, SO >;
5198 };
5199 
5200 template< typename T1, size_t M, size_t N, bool SO1, typename T2, bool SO2 >
5201 struct AddTrait< StaticMatrix<T1,M,N,SO1>, CompressedMatrix<T2,SO2> >
5202 {
5203  using Type = StaticMatrix< AddTrait_<T1,T2>, M, N, SO1 >;
5204 };
5205 
5206 template< typename T1, bool SO, typename T2, size_t M, size_t N >
5207 struct AddTrait< CompressedMatrix<T1,SO>, HybridMatrix<T2,M,N,SO> >
5208 {
5209  using Type = HybridMatrix< AddTrait_<T1,T2>, M, N, SO >;
5210 };
5211 
5212 template< typename T1, bool SO1, typename T2, size_t M, size_t N, bool SO2 >
5213 struct AddTrait< CompressedMatrix<T1,SO1>, HybridMatrix<T2,M,N,SO2> >
5214 {
5215  using Type = HybridMatrix< AddTrait_<T1,T2>, M, N, SO2 >;
5216 };
5217 
5218 template< typename T1, size_t M, size_t N, bool SO, typename T2 >
5219 struct AddTrait< HybridMatrix<T1,M,N,SO>, CompressedMatrix<T2,SO> >
5220 {
5221  using Type = HybridMatrix< AddTrait_<T1,T2>, M, N, SO >;
5222 };
5223 
5224 template< typename T1, size_t M, size_t N, bool SO1, typename T2, bool SO2 >
5225 struct AddTrait< HybridMatrix<T1,M,N,SO1>, CompressedMatrix<T2,SO2> >
5226 {
5227  using Type = HybridMatrix< AddTrait_<T1,T2>, M, N, SO1 >;
5228 };
5229 
5230 template< typename T1, bool SO, typename T2 >
5231 struct AddTrait< CompressedMatrix<T1,SO>, DynamicMatrix<T2,SO> >
5232 {
5233  using Type = DynamicMatrix< AddTrait_<T1,T2>, SO >;
5234 };
5235 
5236 template< typename T1, bool SO1, typename T2, bool SO2 >
5237 struct AddTrait< CompressedMatrix<T1,SO1>, DynamicMatrix<T2,SO2> >
5238 {
5239  using Type = DynamicMatrix< AddTrait_<T1,T2>, SO2 >;
5240 };
5241 
5242 template< typename T1, bool SO, typename T2 >
5243 struct AddTrait< DynamicMatrix<T1,SO>, CompressedMatrix<T2,SO> >
5244 {
5245  using Type = DynamicMatrix< AddTrait_<T1,T2>, SO >;
5246 };
5247 
5248 template< typename T1, bool SO1, typename T2, bool SO2 >
5249 struct AddTrait< DynamicMatrix<T1,SO1>, CompressedMatrix<T2,SO2> >
5250 {
5251  using Type = DynamicMatrix< AddTrait_<T1,T2>, SO1 >;
5252 };
5253 
5254 template< typename T1, bool SO, typename T2, bool AF, bool PF >
5255 struct AddTrait< CompressedMatrix<T1,SO>, CustomMatrix<T2,AF,PF,SO> >
5256 {
5257  using Type = DynamicMatrix< AddTrait_<T1,T2>, SO >;
5258 };
5259 
5260 template< typename T1, bool SO1, typename T2, bool AF, bool PF, bool SO2 >
5261 struct AddTrait< CompressedMatrix<T1,SO1>, CustomMatrix<T2,AF,PF,SO2> >
5262 {
5263  using Type = DynamicMatrix< AddTrait_<T1,T2>, SO2 >;
5264 };
5265 
5266 template< typename T1, bool AF, bool PF, bool SO, typename T2 >
5267 struct AddTrait< CustomMatrix<T1,AF,PF,SO>, CompressedMatrix<T2,SO> >
5268 {
5269  using Type = DynamicMatrix< AddTrait_<T1,T2>, SO >;
5270 };
5271 
5272 template< typename T1, bool AF, bool PF, bool SO1, typename T2, bool SO2 >
5273 struct AddTrait< CustomMatrix<T1,AF,PF,SO1>, CompressedMatrix<T2,SO2> >
5274 {
5275  using Type = DynamicMatrix< AddTrait_<T1,T2>, SO1 >;
5276 };
5277 
5278 template< typename T1, bool SO, typename T2 >
5279 struct AddTrait< CompressedMatrix<T1,SO>, CompressedMatrix<T2,SO> >
5280 {
5281  using Type = CompressedMatrix< AddTrait_<T1,T2>, SO >;
5282 };
5283 
5284 template< typename T1, bool SO1, typename T2, bool SO2 >
5285 struct AddTrait< CompressedMatrix<T1,SO1>, CompressedMatrix<T2,SO2> >
5286 {
5287  using Type = CompressedMatrix< AddTrait_<T1,T2>, false >;
5288 };
5290 //*************************************************************************************************
5291 
5292 
5293 
5294 
5295 //=================================================================================================
5296 //
5297 // SUBTRAIT SPECIALIZATIONS
5298 //
5299 //=================================================================================================
5300 
5301 //*************************************************************************************************
5303 template< typename T1, bool SO, typename T2, size_t M, size_t N >
5304 struct SubTrait< CompressedMatrix<T1,SO>, StaticMatrix<T2,M,N,SO> >
5305 {
5306  using Type = StaticMatrix< SubTrait_<T1,T2>, M, N, SO >;
5307 };
5308 
5309 template< typename T1, bool SO1, typename T2, size_t M, size_t N, bool SO2 >
5310 struct SubTrait< CompressedMatrix<T1,SO1>, StaticMatrix<T2,M,N,SO2> >
5311 {
5312  using Type = StaticMatrix< SubTrait_<T1,T2>, M, N, SO2 >;
5313 };
5314 
5315 template< typename T1, size_t M, size_t N, bool SO, typename T2 >
5316 struct SubTrait< StaticMatrix<T1,M,N,SO>, CompressedMatrix<T2,SO> >
5317 {
5318  using Type = StaticMatrix< SubTrait_<T1,T2>, M, N, SO >;
5319 };
5320 
5321 template< typename T1, size_t M, size_t N, bool SO1, typename T2, bool SO2 >
5322 struct SubTrait< StaticMatrix<T1,M,N,SO1>, CompressedMatrix<T2,SO2> >
5323 {
5324  using Type = StaticMatrix< SubTrait_<T1,T2>, M, N, SO1 >;
5325 };
5326 
5327 template< typename T1, bool SO, typename T2, size_t M, size_t N >
5328 struct SubTrait< CompressedMatrix<T1,SO>, HybridMatrix<T2,M,N,SO> >
5329 {
5330  using Type = HybridMatrix< SubTrait_<T1,T2>, M, N, SO >;
5331 };
5332 
5333 template< typename T1, bool SO1, typename T2, size_t M, size_t N, bool SO2 >
5334 struct SubTrait< CompressedMatrix<T1,SO1>, HybridMatrix<T2,M,N,SO2> >
5335 {
5336  using Type = HybridMatrix< SubTrait_<T1,T2>, M, N, SO2 >;
5337 };
5338 
5339 template< typename T1, size_t M, size_t N, bool SO, typename T2 >
5340 struct SubTrait< HybridMatrix<T1,M,N,SO>, CompressedMatrix<T2,SO> >
5341 {
5342  using Type = HybridMatrix< SubTrait_<T1,T2>, M, N, SO >;
5343 };
5344 
5345 template< typename T1, size_t M, size_t N, bool SO1, typename T2, bool SO2 >
5346 struct SubTrait< HybridMatrix<T1,M,N,SO1>, CompressedMatrix<T2,SO2> >
5347 {
5348  using Type = HybridMatrix< SubTrait_<T1,T2>, M, N, SO1 >;
5349 };
5350 
5351 template< typename T1, bool SO, typename T2 >
5352 struct SubTrait< CompressedMatrix<T1,SO>, DynamicMatrix<T2,SO> >
5353 {
5354  using Type = DynamicMatrix< SubTrait_<T1,T2>, SO >;
5355 };
5356 
5357 template< typename T1, bool SO1, typename T2, bool SO2 >
5358 struct SubTrait< CompressedMatrix<T1,SO1>, DynamicMatrix<T2,SO2> >
5359 {
5360  using Type = DynamicMatrix< SubTrait_<T1,T2>, SO2 >;
5361 };
5362 
5363 template< typename T1, bool SO, typename T2 >
5364 struct SubTrait< DynamicMatrix<T1,SO>, CompressedMatrix<T2,SO> >
5365 {
5366  using Type = DynamicMatrix< SubTrait_<T1,T2>, SO >;
5367 };
5368 
5369 template< typename T1, bool SO1, typename T2, bool SO2 >
5370 struct SubTrait< DynamicMatrix<T1,SO1>, CompressedMatrix<T2,SO2> >
5371 {
5372  using Type = DynamicMatrix< SubTrait_<T1,T2>, SO1 >;
5373 };
5374 
5375 template< typename T1, bool SO, typename T2, bool AF, bool PF >
5376 struct SubTrait< CompressedMatrix<T1,SO>, CustomMatrix<T2,AF,PF,SO> >
5377 {
5378  using Type = DynamicMatrix< SubTrait_<T1,T2>, SO >;
5379 };
5380 
5381 template< typename T1, bool SO1, typename T2, bool AF, bool PF, bool SO2 >
5382 struct SubTrait< CompressedMatrix<T1,SO1>, CustomMatrix<T2,AF,PF,SO2> >
5383 {
5384  using Type = DynamicMatrix< SubTrait_<T1,T2>, SO2 >;
5385 };
5386 
5387 template< typename T1, bool AF, bool PF, bool SO, typename T2 >
5388 struct SubTrait< CustomMatrix<T1,AF,PF,SO>, CompressedMatrix<T2,SO> >
5389 {
5390  using Type = DynamicMatrix< SubTrait_<T1,T2>, SO >;
5391 };
5392 
5393 template< typename T1, bool AF, bool PF, bool SO1, typename T2, bool SO2 >
5394 struct SubTrait< CustomMatrix<T1,AF,PF,SO1>, CompressedMatrix<T2,SO2> >
5395 {
5396  using Type = DynamicMatrix< SubTrait_<T1,T2>, SO1 >;
5397 };
5398 
5399 template< typename T1, bool SO, typename T2 >
5400 struct SubTrait< CompressedMatrix<T1,SO>, CompressedMatrix<T2,SO> >
5401 {
5402  using Type = CompressedMatrix< SubTrait_<T1,T2> , SO >;
5403 };
5404 
5405 template< typename T1, bool SO1, typename T2, bool SO2 >
5406 struct SubTrait< CompressedMatrix<T1,SO1>, CompressedMatrix<T2,SO2> >
5407 {
5408  using Type = CompressedMatrix< SubTrait_<T1,T2> , false >;
5409 };
5411 //*************************************************************************************************
5412 
5413 
5414 
5415 
5416 //=================================================================================================
5417 //
5418 // MULTTRAIT SPECIALIZATIONS
5419 //
5420 //=================================================================================================
5421 
5422 //*************************************************************************************************
5424 template< typename T1, bool SO, typename T2 >
5425 struct MultTrait< CompressedMatrix<T1,SO>, T2, EnableIf_< IsNumeric<T2> > >
5426 {
5427  using Type = CompressedMatrix< MultTrait_<T1,T2>, SO >;
5428 };
5429 
5430 template< typename T1, typename T2, bool SO >
5431 struct MultTrait< T1, CompressedMatrix<T2,SO>, EnableIf_< IsNumeric<T1> > >
5432 {
5433  using Type = CompressedMatrix< MultTrait_<T1,T2>, SO >;
5434 };
5435 
5436 template< typename T1, bool SO, typename T2, size_t N >
5437 struct MultTrait< CompressedMatrix<T1,SO>, StaticVector<T2,N,false> >
5438 {
5439  using Type = DynamicVector< MultTrait_<T1,T2>, false >;
5440 };
5441 
5442 template< typename T1, size_t N, typename T2, bool SO >
5443 struct MultTrait< StaticVector<T1,N,true>, CompressedMatrix<T2,SO> >
5444 {
5445  using Type = DynamicVector< MultTrait_<T1,T2>, true >;
5446 };
5447 
5448 template< typename T1, bool SO, typename T2, size_t N >
5449 struct MultTrait< CompressedMatrix<T1,SO>, HybridVector<T2,N,false> >
5450 {
5451  using Type = DynamicVector< MultTrait_<T1,T2>, false >;
5452 };
5453 
5454 template< typename T1, size_t N, typename T2, bool SO >
5455 struct MultTrait< HybridVector<T1,N,true>, CompressedMatrix<T2,SO> >
5456 {
5457  using Type = DynamicVector< MultTrait_<T1,T2>, true >;
5458 };
5459 
5460 template< typename T1, bool SO, typename T2 >
5461 struct MultTrait< CompressedMatrix<T1,SO>, DynamicVector<T2,false> >
5462 {
5463  using Type = DynamicVector< MultTrait_<T1,T2>, false >;
5464 };
5465 
5466 template< typename T1, typename T2, bool SO >
5467 struct MultTrait< DynamicVector<T1,true>, CompressedMatrix<T2,SO> >
5468 {
5469  using Type = DynamicVector< MultTrait_<T1,T2>, true >;
5470 };
5471 
5472 template< typename T1, bool SO, typename T2, bool AF, bool PF >
5473 struct MultTrait< CompressedMatrix<T1,SO>, CustomVector<T2,AF,PF,false> >
5474 {
5475  using Type = DynamicVector< MultTrait_<T1,T2>, false >;
5476 };
5477 
5478 template< typename T1, bool AF, bool PF, typename T2, bool SO >
5479 struct MultTrait< CustomVector<T1,AF,PF,true>, CompressedMatrix<T2,SO> >
5480 {
5481  using Type = DynamicVector< MultTrait_<T1,T2>, true >;
5482 };
5483 
5484 template< typename T1, bool SO, typename T2 >
5485 struct MultTrait< CompressedMatrix<T1,SO>, CompressedVector<T2,false> >
5486 {
5487  using Type = CompressedVector< MultTrait_<T1,T2>, false >;
5488 };
5489 
5490 template< typename T1, typename T2, bool SO >
5491 struct MultTrait< CompressedVector<T1,true>, CompressedMatrix<T2,SO> >
5492 {
5493  using Type = CompressedVector< MultTrait_<T1,T2>, true >;
5494 };
5495 
5496 template< typename T1, bool SO1, typename T2, size_t M, size_t N, bool SO2 >
5497 struct MultTrait< CompressedMatrix<T1,SO1>, StaticMatrix<T2,M,N,SO2> >
5498 {
5499  using Type = DynamicMatrix< MultTrait_<T1,T2>, SO1 >;
5500 };
5501 
5502 template< typename T1, size_t M, size_t N, bool SO1, typename T2, bool SO2 >
5503 struct MultTrait< StaticMatrix<T1,M,N,SO1>, CompressedMatrix<T2,SO2> >
5504 {
5505  using Type = DynamicMatrix< MultTrait_<T1,T2>, SO1 >;
5506 };
5507 
5508 template< typename T1, bool SO1, typename T2, size_t M, size_t N, bool SO2 >
5509 struct MultTrait< CompressedMatrix<T1,SO1>, HybridMatrix<T2,M,N,SO2> >
5510 {
5511  using Type = DynamicMatrix< MultTrait_<T1,T2>, SO1 >;
5512 };
5513 
5514 template< typename T1, size_t M, size_t N, bool SO1, typename T2, bool SO2 >
5515 struct MultTrait< HybridMatrix<T1,M,N,SO1>, CompressedMatrix<T2,SO2> >
5516 {
5517  using Type = DynamicMatrix< MultTrait_<T1,T2>, SO1 >;
5518 };
5519 
5520 template< typename T1, bool SO1, typename T2, bool SO2 >
5521 struct MultTrait< CompressedMatrix<T1,SO1>, DynamicMatrix<T2,SO2> >
5522 {
5523  using Type = DynamicMatrix< MultTrait_<T1,T2>, SO1 >;
5524 };
5525 
5526 template< typename T1, bool SO1, typename T2, bool SO2 >
5527 struct MultTrait< DynamicMatrix<T1,SO1>, CompressedMatrix<T2,SO2> >
5528 {
5529  using Type = DynamicMatrix< MultTrait_<T1,T2>, SO1 >;
5530 };
5531 
5532 template< typename T1, bool SO1, typename T2, bool AF, bool PF, bool SO2 >
5533 struct MultTrait< CompressedMatrix<T1,SO1>, CustomMatrix<T2,AF,PF,SO2> >
5534 {
5535  using Type = DynamicMatrix< MultTrait_<T1,T2>, SO1 >;
5536 };
5537 
5538 template< typename T1, bool AF, bool PF, bool SO1, typename T2, bool SO2 >
5539 struct MultTrait< CustomMatrix<T1,AF,PF,SO1>, CompressedMatrix<T2,SO2> >
5540 {
5541  using Type = DynamicMatrix< MultTrait_<T1,T2>, SO1 >;
5542 };
5543 
5544 template< typename T1, bool SO1, typename T2, bool SO2 >
5545 struct MultTrait< CompressedMatrix<T1,SO1>, CompressedMatrix<T2,SO2> >
5546 {
5547  using Type = CompressedMatrix< MultTrait_<T1,T2>, SO1 >;
5548 };
5550 //*************************************************************************************************
5551 
5552 
5553 
5554 
5555 //=================================================================================================
5556 //
5557 // DIVTRAIT SPECIALIZATIONS
5558 //
5559 //=================================================================================================
5560 
5561 //*************************************************************************************************
5563 template< typename T1, bool SO, typename T2 >
5564 struct DivTrait< CompressedMatrix<T1,SO>, T2, EnableIf_< IsNumeric<T2> > >
5565 {
5566  using Type = CompressedMatrix< DivTrait_<T1,T2>, SO >;
5567 };
5569 //*************************************************************************************************
5570 
5571 
5572 
5573 
5574 //=================================================================================================
5575 //
5576 // MATHTRAIT SPECIALIZATIONS
5577 //
5578 //=================================================================================================
5579 
5580 //*************************************************************************************************
5582 template< typename T1, bool SO, typename T2 >
5583 struct MathTrait< CompressedMatrix<T1,SO>, CompressedMatrix<T2,SO> >
5584 {
5585  using HighType = CompressedMatrix< typename MathTrait<T1,T2>::HighType, SO >;
5586  using LowType = CompressedMatrix< typename MathTrait<T1,T2>::LowType , SO >;
5587 };
5589 //*************************************************************************************************
5590 
5591 
5592 
5593 
5594 //=================================================================================================
5595 //
5596 // SUBMATRIXTRAIT SPECIALIZATIONS
5597 //
5598 //=================================================================================================
5599 
5600 //*************************************************************************************************
5602 template< typename T1, bool SO >
5603 struct SubmatrixTrait< CompressedMatrix<T1,SO> >
5604 {
5605  using Type = CompressedMatrix<T1,SO>;
5606 };
5608 //*************************************************************************************************
5609 
5610 
5611 
5612 
5613 //=================================================================================================
5614 //
5615 // ROWTRAIT SPECIALIZATIONS
5616 //
5617 //=================================================================================================
5618 
5619 //*************************************************************************************************
5621 template< typename T1, bool SO >
5622 struct RowTrait< CompressedMatrix<T1,SO> >
5623 {
5624  using Type = CompressedVector<T1,true>;
5625 };
5627 //*************************************************************************************************
5628 
5629 
5630 
5631 
5632 //=================================================================================================
5633 //
5634 // COLUMNTRAIT SPECIALIZATIONS
5635 //
5636 //=================================================================================================
5637 
5638 //*************************************************************************************************
5640 template< typename T1, bool SO >
5641 struct ColumnTrait< CompressedMatrix<T1,SO> >
5642 {
5643  using Type = CompressedVector<T1,false>;
5644 };
5646 //*************************************************************************************************
5647 
5648 } // namespace blaze
5649 
5650 #endif
#define BLAZE_CONSTRAINT_MUST_NOT_BE_CONST(T)
Constraint on the data type.In case the given data type is a const-qualified type, a compilation error is created.
Definition: Const.h:79
#define BLAZE_THROW_INVALID_ARGUMENT(MESSAGE)
Macro for the emission of a std::invalid_argument exception.This macro encapsulates the default way o...
Definition: Exception.h:235
Pointer difference type of the Blaze library.
void reserveElements(size_t nonzeros)
Reserving the specified number of sparse matrix elements.
Definition: CompressedMatrix.h:1982
Header file for auxiliary alias declarations.
bool canAlias(const Other *alias) const noexcept
Returns whether the matrix can alias with the given address alias.
Definition: CompressedMatrix.h:2297
Compile time check for numeric types.This type trait tests whether or not the given template paramete...
Definition: IsNumeric.h:79
Iterator * end_
Pointers one past the last non-zero element of each row.
Definition: CompressedMatrix.h:409
Header file for mathematical functions.
#define BLAZE_USER_ASSERT(expr, msg)
Run time assertion macro for user checks.In case of an invalid run time expression, the program execution is terminated. The BLAZE_USER_ASSERT macro can be disabled by setting the BLAZE_USER_ASSERT flag to zero or by defining NDEBUG during the compilation.
Definition: Assert.h:117
MatrixAccessProxy< This > Reference
Reference to a sparse matrix value.
Definition: CompressedMatrix.h:244
Header file for the subtraction trait.
BLAZE_ALWAYS_INLINE size_t capacity(const Matrix< MT, SO > &matrix) noexcept
Returns the maximum capacity of the matrix.
Definition: Matrix.h:346
Header file for basic type definitions.
const Type & ConstReference
Reference to a constant sparse matrix value.
Definition: CompressedMatrix.h:245
Header file for the row trait.
CompressedMatrix & ctranspose()
In-place conjugate transpose of the matrix.
Definition: CompressedMatrix.h:1880
CompressedMatrix()
The default constructor for CompressedMatrix.
Definition: CompressedMatrix.h:453
Header file for the serial shim.
Efficient implementation of a compressed matrix.The CompressedMatrix class template is the represent...
Definition: CompressedMatrix.h:207
BLAZE_ALWAYS_INLINE size_t size(const Vector< VT, TF > &vector) noexcept
Returns the current size/dimension of the vector.
Definition: Vector.h:258
const CTransExprTrait_< MT > ctrans(const DenseMatrix< MT, SO > &dm)
Returns the conjugate transpose matrix of dm.
Definition: DMatForEachExpr.h:1195
Iterator end(size_t i) noexcept
Returns an iterator just past the last non-zero element of row/column i.
Definition: CompressedMatrix.h:870
Reference operator()(size_t i, size_t j) noexcept
2D-access to the sparse matrix elements.
Definition: CompressedMatrix.h:696
BLAZE_ALWAYS_INLINE MT::Iterator begin(Matrix< MT, SO > &matrix, size_t i)
Returns an iterator to the first element of row/column i.
Definition: Matrix.h:188
void reset(const DiagonalProxy< MT > &proxy)
Resetting the represented element to the default initial values.
Definition: DiagonalProxy.h:533
size_t m_
The current number of rows of the sparse matrix.
Definition: CompressedMatrix.h:2805
void clear()
Clearing the sparse matrix.
Definition: CompressedMatrix.h:1390
Type ElementType
Type of the sparse matrix elements.
Definition: CompressedMatrix.h:241
void clear(CompressedMatrix< Type, SO > &m)
Clearing the given compressed matrix.
Definition: CompressedMatrix.h:5077
OutputIterator transfer(InputIterator first, InputIterator last, OutputIterator dest)
Transfers the elements from the given source range to the destination range.
Definition: Algorithm.h:71
const ElementType_< MT > min(const DenseMatrix< MT, SO > &dm)
Returns the smallest element of the dense matrix.
Definition: DenseMatrix.h:1669
Compile time check for lower triangular matrices.This type trait tests whether or not the given templ...
Definition: IsLower.h:88
CompressedMatrix< ET, SO > Other
The type of the other CompressedMatrix.
Definition: CompressedMatrix.h:255
CompressedMatrix< Type,!SO > OppositeType
Result type with opposite storage order for expression template evaluations.
Definition: CompressedMatrix.h:239
bool canSMPAssign() const noexcept
Returns whether the matrix can be used in SMP assignments.
Definition: CompressedMatrix.h:2336
#define BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE(T)
Constraint on the data type.In case the given data type is a volatile-qualified type, a compilation error is created.
Definition: Volatile.h:79
~CompressedMatrix()
The destructor for CompressedMatrix.
Definition: CompressedMatrix.h:662
const DMatSerialExpr< MT, SO > serial(const DenseMatrix< MT, SO > &dm)
Forces the serial evaluation of the given dense matrix expression dm.
Definition: DMatSerialExpr.h:723
void reset(CompressedMatrix< Type, SO > &m)
Resetting the given compressed matrix.
Definition: CompressedMatrix.h:5039
BLAZE_ALWAYS_INLINE size_t nonZeros(const Matrix< MT, SO > &matrix)
Returns the total number of non-zero elements in the matrix.
Definition: Matrix.h:384
Access proxy for sparse, matrices.The MatrixAccessProxy provides safe access to the elements of a no...
Definition: MatrixAccessProxy.h:100
Compile time check for upper triangular matrices.This type trait tests whether or not the given templ...
Definition: IsUpper.h:88
BoolConstant< true > TrueType
Type traits base class.The TrueType class is used as base class for type traits and value traits that...
Definition: TrueType.h:61
Header file for memory allocation and deallocation functionality.
bool isAliased(const Other *alias) const noexcept
Returns whether the matrix is aliased with the given address alias.
Definition: CompressedMatrix.h:2317
const ElementType_< MT > max(const DenseMatrix< MT, SO > &dm)
Returns the largest element of the dense matrix.
Definition: DenseMatrix.h:1716
static const Type zero_
Neutral element for accesses to zero elements.
Definition: CompressedMatrix.h:411
const Type & ReturnType
Return type for expression template evaluations.
Definition: CompressedMatrix.h:242
Base class for dense matrices.The DenseMatrix class is a base class for all dense matrix classes...
Definition: DenseMatrix.h:70
Base class for sparse matrices.The SparseMatrix class is a base class for all sparse matrix classes...
Definition: Forward.h:109
void swap(CompressedMatrix &sm) noexcept
Swapping the contents of two sparse matrices.
Definition: CompressedMatrix.h:1941
bool isDefault(const DiagonalProxy< MT > &proxy)
Returns whether the represented element is in default state.
Definition: DiagonalProxy.h:573
size_t extendCapacity() const noexcept
Calculating a new matrix capacity.
Definition: CompressedMatrix.h:1962
Constraint on the data type.
size_t nonZeros() const
Returns the number of non-zero elements in the sparse matrix.
Definition: CompressedMatrix.h:1312
size_t capacity_
The current capacity of the pointer array.
Definition: CompressedMatrix.h:2807
Header file for the SparseMatrix base class.
size_t capacity_
The current capacity of the pointer array.
Definition: CompressedMatrix.h:407
void reserve(size_t nonzeros)
Setting the minimum capacity of the sparse matrix.
Definition: CompressedMatrix.h:1731
void reset()
Reset to the default initial values.
Definition: CompressedMatrix.h:1352
const This & CompositeType
Data type for composite expression templates.
Definition: CompressedMatrix.h:243
Header file for the ValueIndexPair class.
bool isDefault(const CompressedMatrix< Type, SO > &m)
Returns whether the given compressed matrix is in default state.
Definition: CompressedMatrix.h:5104
Header file for the multiplication trait.
Header file for the IsStrictlyUpper type trait.
Namespace of the Blaze C++ math library.
Definition: Blaze.h:57
void swap(CompressedMatrix< Type, SO > &a, CompressedMatrix< Type, SO > &b) noexcept
Swapping the contents of two compressed matrices.
Definition: CompressedMatrix.h:5148
Header file for the If class template.
Header file for the IsFloatingPoint type trait.
Iterator set(size_t i, size_t j, const Type &value)
Setting an element of the compressed matrix.
Definition: CompressedMatrix.h:1414
bool isIntact(const CompressedMatrix< Type, SO > &m)
Returns whether the invariants of the given compressed matrix are intact.
Definition: CompressedMatrix.h:5131
Header file for the MatrixAccessProxy class.
Header file for all forward declarations of the math module.
const Element * ConstIterator
Iterator over constant elements.
Definition: CompressedMatrix.h:2647
#define BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE(T)
Constraint on the data type.In case the given data type T is not a pointer type, a compilation error ...
Definition: Pointer.h:79
Header file for the IsSMPAssignable type trait.
void erase(size_t i, size_t j)
Erasing an element from the sparse matrix.
Definition: CompressedMatrix.h:1550
Iterator * end_
Pointers one past the last non-zero element of each column.
Definition: CompressedMatrix.h:2809
#define BLAZE_THROW_OUT_OF_RANGE(MESSAGE)
Macro for the emission of a std::out_of_range exception.This macro encapsulates the default way of Bl...
Definition: Exception.h:331
#define BLAZE_CONSTRAINT_MUST_HAVE_SAME_SIZE(T1, T2)
Constraint on the size of two data types.In case the types T1 and T2 don't have the same size...
Definition: SameSize.h:60
ValueIndexPair< Type > ElementBase
Base class for the sparse matrix element.
Definition: CompressedMatrix.h:211
Constraint on the data type.
Header file for the IsLower type trait.
BLAZE_ALWAYS_INLINE size_t columns(const Matrix< MT, SO > &matrix) noexcept
Returns the current number of columns of the matrix.
Definition: Matrix.h:330
Header file for the default storage order for all vectors of the Blaze library.
ConstIterator cend(size_t i) const noexcept
Returns an iterator just past the last non-zero element of row/column i.
Definition: CompressedMatrix.h:914
Iterator insert(size_t i, size_t j, const Type &value)
Inserting an element into the compressed matrix.
Definition: CompressedMatrix.h:1446
Header file for the exception macros of the math module.
CompressedMatrix< ET, true > Other
The type of the other CompressedMatrix.
Definition: CompressedMatrix.h:2655
Compile time check for strictly upper triangular matrices.This type trait tests whether or not the gi...
Definition: IsStrictlyUpper.h:86
Compile time check for floating point data types.This type trait tests whether or not the given templ...
Definition: IsFloatingPoint.h:75
Compile time check for data types.This type trait tests whether or not the given template parameter i...
Definition: IsSMPAssignable.h:119
BLAZE_ALWAYS_INLINE void resize(Matrix< MT, SO > &matrix, size_t rows, size_t columns, bool preserve=true)
Changing the size of the matrix.
Definition: Matrix.h:538
BLAZE_ALWAYS_INLINE MT::Iterator end(Matrix< MT, SO > &matrix, size_t i)
Returns an iterator just past the last element of row/column i.
Definition: Matrix.h:254
const Type & ConstReference
Reference to a constant matrix value.
Definition: CompressedMatrix.h:2645
Headerfile for generic algorithms.
void subAssign(const DenseMatrix< MT, SO2 > &rhs)
Default implementation of the subtraction assignment of a dense matrix.
Definition: CompressedMatrix.h:2549
Header file for the EnableIf class template.
Header file for the IsStrictlyLower type trait.
size_t columns() const noexcept
Returns the current number of columns of the sparse matrix.
Definition: CompressedMatrix.h:1261
const Element * ConstIterator
Iterator over constant elements.
Definition: CompressedMatrix.h:247
typename DivTrait< T1, T2 >::Type DivTrait_
Auxiliary alias declaration for the DivTrait class template.The DivTrait_ alias declaration provides ...
Definition: DivTrait.h:245
void resize(size_t m, size_t n, bool preserve=true)
Changing the size of the sparse matrix.
Definition: CompressedMatrix.h:1636
Header file for the IsNumeric type trait.
CompressedMatrix & operator=(const CompressedMatrix &rhs)
Copy assignment operator for CompressedMatrix.
Definition: CompressedMatrix.h:942
#define BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is a symmetric matrix type, a compilation error is created.
Definition: Symmetric.h:79
size_t rows() const noexcept
Returns the current number of rows of the sparse matrix.
Definition: CompressedMatrix.h:1247
Header file for run time assertion macros.
Header file for the addition trait.
CompressedMatrix & transpose()
In-place transpose of the matrix.
Definition: CompressedMatrix.h:1864
Header file for the division trait.
void trim()
Removing all excessive capacity from all rows/columns.
Definition: CompressedMatrix.h:1825
Header file for the submatrix trait.
Constraint on the data type.
typename If< T1, T2, T3 >::Type If_
Auxiliary alias declaration for the If class template.The If_ alias declaration provides a convenient...
Definition: If.h:160
#define BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE(T)
Constraint on the data type.In case the given data type T is not a reference type, a compilation error is created.
Definition: Reference.h:79
Element * Iterator
Iterator over non-constant elements.
Definition: CompressedMatrix.h:2646
Header file for the column trait.
Header file for the isDefault shim.
void swap(DiagonalMatrix< MT, SO, DF > &a, DiagonalMatrix< MT, SO, DF > &b) noexcept
Swapping the contents of two matrices.
Definition: DiagonalMatrix.h:258
Base class for matrices.The Matrix class is a base class for all dense and sparse matrix classes with...
Definition: Forward.h:89
Constraint on the data type.
Constraint on the data type.
This ResultType
Result type for expression template evaluations.
Definition: CompressedMatrix.h:238
Iterator * begin_
Pointers to the first non-zero element of each column.
Definition: CompressedMatrix.h:2808
void assign(const DenseMatrix< MT, SO2 > &rhs)
Default implementation of the assignment of a row-major dense matrix.
Definition: CompressedMatrix.h:2358
Element * Iterator
Iterator over non-constant elements.
Definition: CompressedMatrix.h:246
size_t capacity() const noexcept
Returns the maximum capacity of the sparse matrix.
Definition: CompressedMatrix.h:1275
void append(size_t i, size_t j, const Type &value, bool check=false)
Appending an element to the specified row/column of the sparse matrix.
Definition: CompressedMatrix.h:2233
EnableIf_< IsBuiltin< T > > deallocate(T *address) noexcept
Deallocation of memory for built-in data types.
Definition: Memory.h:225
void finalize(size_t i)
Finalizing the element insertion of a row/column.
Definition: CompressedMatrix.h:2265
typename EnableIf< Condition, T >::Type EnableIf_
Auxiliary alias declaration for the EnableIf class template.The EnableIf_ alias declaration provides ...
Definition: EnableIf.h:223
CompressedMatrix< Type, SO > This
Type of this CompressedMatrix instance.
Definition: CompressedMatrix.h:236
Iterator find(size_t i, size_t j)
Searches for a specific matrix element.
Definition: CompressedMatrix.h:2034
Header file for the mathematical trait.
Compile time check for strictly lower triangular matrices.This type trait tests whether or not the gi...
Definition: IsStrictlyLower.h:86
Iterator * begin_
Pointers to the first non-zero element of each row.
Definition: CompressedMatrix.h:408
BLAZE_ALWAYS_INLINE size_t rows(const Matrix< MT, SO > &matrix) noexcept
Returns the current number of rows of the matrix.
Definition: Matrix.h:314
typename T::ConstIterator ConstIterator_
Alias declaration for nested ConstIterator type definitions.The ConstIterator_ alias declaration prov...
Definition: Aliases.h:103
size_t n_
The current number of columns of the sparse matrix.
Definition: CompressedMatrix.h:2806
Index-value-pair for sparse vectors and matrices.The ValueIndexPair class represents a single index-v...
Definition: ValueIndexPair.h:70
Constraint on the size of two data types.
void addAssign(const DenseMatrix< MT, SO2 > &rhs)
Default implementation of the addition assignment of a dense matrix.
Definition: CompressedMatrix.h:2497
const DMatTransExpr< MT,!SO > trans(const DenseMatrix< MT, SO > &dm)
Calculation of the transpose of the given dense matrix.
Definition: DMatTransExpr.h:950
CompressedMatrix< Type,!SO > TransposeType
Transpose type for expression template evaluations.
Definition: CompressedMatrix.h:240
SparseMatrix< This, SO > BaseType
Base type of this CompressedMatrix instance.
Definition: CompressedMatrix.h:237
Iterator lowerBound(size_t i, size_t j)
Returns an iterator to the first index not less then the given index.
Definition: CompressedMatrix.h:2087
static const Type zero_
Neutral element for accesses to zero elements.
Definition: CompressedMatrix.h:2811
Iterator upperBound(size_t i, size_t j)
Returns an iterator to the first index greater then the given index.
Definition: CompressedMatrix.h:2142
MatrixAccessProxy< This > Reference
Reference to a non-constant matrix value.
Definition: CompressedMatrix.h:2644
Rebind mechanism to obtain a CompressedMatrix with different data/element type.
Definition: CompressedMatrix.h:254
ConstIterator cbegin(size_t i) const noexcept
Returns an iterator to the first non-zero element of row/column i.
Definition: CompressedMatrix.h:848
Rebind mechanism to obtain a CompressedMatrix with different data/element type.
Definition: CompressedMatrix.h:2654
Header file for the IsUpper type trait.
size_t n_
The current number of columns of the sparse matrix.
Definition: CompressedMatrix.h:406
Reference at(size_t i, size_t j)
Checked access to the matrix elements.
Definition: CompressedMatrix.h:750
Header file for the IsResizable type trait.
size_t m_
The current number of rows of the sparse matrix.
Definition: CompressedMatrix.h:405
Header file for the thresholds for matrix/vector and matrix/matrix multiplications.
#define BLAZE_INTERNAL_ASSERT(expr, msg)
Run time assertion macro for internal checks.In case of an invalid run time expression, the program execution is terminated. The BLAZE_INTERNAL_ASSERT macro can be disabled by setting the BLAZE_USER_ASSERTION flag to zero or by defining NDEBUG during the compilation.
Definition: Assert.h:101
Iterator begin(size_t i) noexcept
Returns an iterator to the first non-zero element of row/column i.
Definition: CompressedMatrix.h:804
constexpr bool defaultStorageOrder
The default storage order for all matrices of the Blaze library.This value specifies the default stor...
Definition: StorageOrder.h:56