All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CompressedMatrix.h
Go to the documentation of this file.
1 //=================================================================================================
20 //=================================================================================================
21 
22 #ifndef _BLAZE_MATH_SPARSE_COMPRESSEDMATRIX_H_
23 #define _BLAZE_MATH_SPARSE_COMPRESSEDMATRIX_H_
24 
25 
26 //*************************************************************************************************
27 // Includes
28 //*************************************************************************************************
29 
30 #include <algorithm>
31 #include <functional>
32 #include <stdexcept>
33 #include <vector>
35 #include <blaze/math/Functions.h>
36 #include <blaze/math/shims/Equal.h>
38 #include <blaze/math/shims/IsNaN.h>
46 #include <blaze/math/Types.h>
50 #include <blaze/system/Precision.h>
52 #include <blaze/util/Assert.h>
59 #include <blaze/util/EnableIf.h>
60 #include <blaze/util/mpl/If.h>
61 #include <blaze/util/Null.h>
62 #include <blaze/util/Types.h>
65 
66 
67 namespace blaze {
68 
69 //=================================================================================================
70 //
71 // CLASS DEFINITION
72 //
73 //=================================================================================================
74 
75 //*************************************************************************************************
180 template< typename Type // Data type of the sparse matrix
181  , bool SO = defaultStorageOrder > // Storage order
182 class CompressedMatrix : public SparseMatrix< CompressedMatrix<Type,SO>, SO >
183 {
184  private:
185  //**Type definitions****************************************************************************
187  //**********************************************************************************************
188 
189  //**Private class Element***********************************************************************
193  struct Element : public ElementBase
194  {
195  using ElementBase::operator=;
196  friend class CompressedMatrix;
197  };
199  //**********************************************************************************************
200 
201  //**Private class FindIndex*********************************************************************
205  struct FindIndex : public std::binary_function<Element,size_t,bool>
206  {
207  inline bool operator()( const Element& element, size_t index ) const {
208  return element.index() < index;
209  }
210  inline bool operator()( size_t index, const Element& element ) const {
211  return index < element.index();
212  }
213  inline bool operator()( const Element& element1, const Element& element2 ) const {
214  return element1.index() < element2.index();
215  }
216  };
218  //**********************************************************************************************
219 
220  public:
221  //**Type definitions****************************************************************************
223  typedef This ResultType;
226  typedef Type ElementType;
227  typedef const Type& ReturnType;
228  typedef const This& CompositeType;
230  typedef const Type& ConstReference;
231  typedef Element* Iterator;
232  typedef const Element* ConstIterator;
233  //**********************************************************************************************
234 
235  //**Compilation flags***************************************************************************
237 
240  enum { canAlias = 0 };
241  //**********************************************************************************************
242 
243  //**Constructors********************************************************************************
246  explicit inline CompressedMatrix();
247  explicit inline CompressedMatrix( size_t m, size_t n );
248  explicit inline CompressedMatrix( size_t m, size_t n, size_t nonzeros );
249  explicit CompressedMatrix( size_t m, size_t n, const std::vector<size_t>& nonzeros );
250  inline CompressedMatrix( const CompressedMatrix& sm );
251  template< typename MT, bool SO2 > inline CompressedMatrix( const DenseMatrix<MT,SO2>& dm );
252  template< typename MT, bool SO2 > inline CompressedMatrix( const SparseMatrix<MT,SO2>& sm );
254  //**********************************************************************************************
255 
256  //**Destructor**********************************************************************************
259  inline ~CompressedMatrix();
261  //**********************************************************************************************
262 
263  //**Data access functions***********************************************************************
266  inline Reference operator()( size_t i, size_t j );
267  inline ConstReference operator()( size_t i, size_t j ) const;
268  inline Iterator begin ( size_t i );
269  inline ConstIterator begin ( size_t i ) const;
270  inline ConstIterator cbegin( size_t i ) const;
271  inline Iterator end ( size_t i );
272  inline ConstIterator end ( size_t i ) const;
273  inline ConstIterator cend ( size_t i ) const;
275  //**********************************************************************************************
276 
277  //**Assignment operators************************************************************************
280  inline CompressedMatrix& operator= ( const CompressedMatrix& rhs );
281  template< typename MT, bool SO2 > inline CompressedMatrix& operator= ( const DenseMatrix<MT,SO2>& rhs );
282  template< typename MT, bool SO2 > inline CompressedMatrix& operator= ( const SparseMatrix<MT,SO2>& rhs );
283  template< typename MT, bool SO2 > inline CompressedMatrix& operator+=( const Matrix<MT,SO2>& rhs );
284  template< typename MT, bool SO2 > inline CompressedMatrix& operator-=( const Matrix<MT,SO2>& rhs );
285  template< typename MT, bool SO2 > inline CompressedMatrix& operator*=( const Matrix<MT,SO2>& rhs );
286 
287  template< typename Other >
288  inline typename EnableIf< IsNumeric<Other>, CompressedMatrix >::Type&
289  operator*=( Other rhs );
290 
291  template< typename Other >
292  inline typename EnableIf< IsNumeric<Other>, CompressedMatrix >::Type&
293  operator/=( Other rhs );
295  //**********************************************************************************************
296 
297  //**Utility functions***************************************************************************
300  inline size_t rows() const;
301  inline size_t columns() const;
302  inline size_t capacity() const;
303  inline size_t capacity( size_t i ) const;
304  inline size_t nonZeros() const;
305  inline size_t nonZeros( size_t i ) const;
306  inline void reset();
307  inline void clear();
308  Iterator insert ( size_t i, size_t j, const Type& value );
309  inline Iterator find ( size_t i, size_t j );
310  inline ConstIterator find ( size_t i, size_t j ) const;
311  void resize ( size_t m, size_t n, bool preserve=true );
312  inline void reserve( size_t nonzeros );
313  void reserve( size_t i, size_t nonzeros );
314  inline CompressedMatrix& transpose();
315  bool isDiagonal() const;
316  bool isSymmetric() const;
317  template< typename Other > inline CompressedMatrix& scale( Other scalar );
318  template< typename Other > inline CompressedMatrix& scaleDiagonal( Other scalar );
319  inline void swap( CompressedMatrix& sm ) /* throw() */;
321  //**********************************************************************************************
322 
323  //**Low-level utility functions*****************************************************************
326  inline void append ( size_t i, size_t j, const Type& value );
327  inline void finalize( size_t i );
329  //**********************************************************************************************
330 
331  //**Expression template evaluation functions****************************************************
334  template< typename Other > inline bool isAliased ( const Other* alias ) const;
335  template< typename MT, bool SO2 > inline void assign ( const DenseMatrix<MT,SO2>& rhs );
336  template< typename MT > inline void assign ( const SparseMatrix<MT,SO>& rhs );
337  template< typename MT > inline void assign ( const SparseMatrix<MT,!SO>& rhs );
338  template< typename MT, bool SO2 > inline void addAssign( const DenseMatrix<MT,SO2>& rhs );
339  template< typename MT, bool SO2 > inline void addAssign( const SparseMatrix<MT,SO2>& rhs );
340  template< typename MT, bool SO2 > inline void subAssign( const DenseMatrix<MT,SO2>& rhs );
341  template< typename MT, bool SO2 > inline void subAssign( const SparseMatrix<MT,SO2>& rhs );
343  //**********************************************************************************************
344 
345  private:
346  //**Utility functions***************************************************************************
349  inline size_t extendCapacity() const;
350  inline void reserveElements( size_t nonzeros );
352  //**********************************************************************************************
353 
354  //**Member variables****************************************************************************
357  size_t m_;
358  size_t n_;
359  size_t capacity_;
362 
363  static const Type zero_;
364 
365  //**********************************************************************************************
366 
367  //**Compile time checks*************************************************************************
375  //**********************************************************************************************
376 };
377 //*************************************************************************************************
378 
379 
380 
381 
382 //=================================================================================================
383 //
384 // DEFINITION AND INITIALIZATION OF THE STATIC MEMBER VARIABLES
385 //
386 //=================================================================================================
387 
388 template< typename Type, bool SO >
389 const Type CompressedMatrix<Type,SO>::zero_ = Type();
390 
391 
392 
393 
394 //=================================================================================================
395 //
396 // CONSTRUCTORS
397 //
398 //=================================================================================================
399 
400 //*************************************************************************************************
403 template< typename Type // Data type of the sparse matrix
404  , bool SO > // Storage order
406  : m_ ( 0UL ) // The current number of rows of the sparse matrix
407  , n_ ( 0UL ) // The current number of columns of the sparse matrix
408  , capacity_( 0UL ) // The current capacity of the pointer array
409  , begin_( new Iterator[2] ) // Pointers to the first non-zero element of each row
410  , end_ ( begin_+1 ) // Pointers one past the last non-zero element of each row
411 {
412  begin_[0] = end_[0] = NULL;
413 }
414 //*************************************************************************************************
415 
416 
417 //*************************************************************************************************
425 template< typename Type // Data type of the sparse matrix
426  , bool SO > // Storage order
428  : m_ ( m ) // The current number of rows of the sparse matrix
429  , n_ ( n ) // The current number of columns of the sparse matrix
430  , capacity_( m ) // The current capacity of the pointer array
431  , begin_( new Iterator[2UL*m+2UL] ) // Pointers to the first non-zero element of each row
432  , end_ ( begin_+(m+1UL) ) // Pointers one past the last non-zero element of each row
433 {
434  for( size_t i=0UL; i<2UL*m_+2UL; ++i )
435  begin_[i] = NULL;
436 }
437 //*************************************************************************************************
438 
439 
440 //*************************************************************************************************
449 template< typename Type // Data type of the sparse matrix
450  , bool SO > // Storage order
451 inline CompressedMatrix<Type,SO>::CompressedMatrix( size_t m, size_t n, size_t nonzeros )
452  : m_ ( m ) // The current number of rows of the sparse matrix
453  , n_ ( n ) // The current number of columns of the sparse matrix
454  , capacity_( m ) // The current capacity of the pointer array
455  , begin_( new Iterator[2UL*m+2UL] ) // Pointers to the first non-zero element of each row
456  , end_ ( begin_+(m+1UL) ) // Pointers one past the last non-zero element of each row
457 {
458  begin_[0UL] = new Element[nonzeros];
459  for( size_t i=1UL; i<(2UL*m_+1UL); ++i )
460  begin_[i] = begin_[0UL];
461  end_[m_] = begin_[0UL]+nonzeros;
462 }
463 //*************************************************************************************************
464 
465 
466 //*************************************************************************************************
475 template< typename Type // Data type of the sparse matrix
476  , bool SO > // Storage order
477 CompressedMatrix<Type,SO>::CompressedMatrix( size_t m, size_t n, const std::vector<size_t>& nonzeros )
478  : m_ ( m ) // The current number of rows of the sparse matrix
479  , n_ ( n ) // The current number of columns of the sparse matrix
480  , capacity_( m ) // The current capacity of the pointer array
481  , begin_( new Iterator[2UL*m_+2UL] ) // Pointers to the first non-zero element of each row
482  , end_ ( begin_+(m_+1UL) ) // Pointers one past the last non-zero element of each row
483 {
484  BLAZE_USER_ASSERT( nonzeros.size() == m, "Size of capacity vector and number of rows don't match" );
485 
486  size_t newCapacity( 0UL );
487  for( std::vector<size_t>::const_iterator it=nonzeros.begin(); it!=nonzeros.end(); ++it )
488  newCapacity += *it;
489 
490  begin_[0UL] = end_[0UL] = new Element[newCapacity];
491  for( size_t i=0UL; i<m_; ++i ) {
492  begin_[i+1UL] = end_[i+1UL] = begin_[i] + nonzeros[i];
493  }
494 }
495 //*************************************************************************************************
496 
497 
498 //*************************************************************************************************
503 template< typename Type // Data type of the sparse matrix
504  , bool SO > // Storage order
506  : m_ ( sm.m_ ) // The current number of rows of the sparse matrix
507  , n_ ( sm.n_ ) // The current number of columns of the sparse matrix
508  , capacity_( sm.m_ ) // The current capacity of the pointer array
509  , begin_ ( new Iterator[2UL*m_+2UL] ) // Pointers to the first non-zero element of each row
510  , end_ ( begin_+(m_+1UL) ) // Pointers one past the last non-zero element of each row
511 {
512  const size_t nonzeros( sm.nonZeros() );
513 
514  begin_[0UL] = new Element[nonzeros];
515  for( size_t i=0UL; i<m_; ++i )
516  begin_[i+1UL] = end_[i] = std::copy( sm.begin(i), sm.end(i), begin_[i] );
517  end_[m_] = begin_[0UL]+nonzeros;
518 }
519 //*************************************************************************************************
520 
521 
522 //*************************************************************************************************
527 template< typename Type // Data type of the sparse matrix
528  , bool SO > // Storage order
529 template< typename MT // Type of the foreign dense matrix
530  , bool SO2 > // Storage order of the foreign dense matrix
532  : m_ ( (~dm).rows() ) // The current number of rows of the sparse matrix
533  , n_ ( (~dm).columns() ) // The current number of columns of the sparse matrix
534  , capacity_( m_ ) // The current capacity of the pointer array
535  , begin_ ( new Iterator[2UL*m_+2UL] ) // Pointers to the first non-zero element of each row
536  , end_ ( begin_+(m_+1UL) ) // Pointers one past the last non-zero element of each row
537 {
538  using blaze::assign;
539 
540  for( size_t i=0UL; i<2UL*m_+2UL; ++i )
541  begin_[i] = NULL;
542 
543  assign( *this, ~dm );
544 }
545 //*************************************************************************************************
546 
547 
548 //*************************************************************************************************
553 template< typename Type // Data type of the sparse matrix
554  , bool SO > // Storage order
555 template< typename MT // Type of the foreign sparse matrix
556  , bool SO2 > // Storage order of the foreign sparse matrix
558  : m_ ( (~sm).rows() ) // The current number of rows of the sparse matrix
559  , n_ ( (~sm).columns() ) // The current number of columns of the sparse matrix
560  , capacity_( m_ ) // The current capacity of the pointer array
561  , begin_ ( new Iterator[2UL*m_+2UL] ) // Pointers to the first non-zero element of each row
562  , end_ ( begin_+(m_+1UL) ) // Pointers one past the last non-zero element of each row
563 {
564  using blaze::assign;
565 
566  const size_t nonzeros( (~sm).nonZeros() );
567 
568  begin_[0UL] = new Element[nonzeros];
569  for( size_t i=0UL; i<m_; ++i )
570  begin_[i+1UL] = end_[i] = begin_[0UL];
571  end_[m_] = begin_[0UL]+nonzeros;
572 
573  assign( *this, ~sm );
574 }
575 //*************************************************************************************************
576 
577 
578 
579 
580 //=================================================================================================
581 //
582 // DESTRUCTOR
583 //
584 //=================================================================================================
585 
586 //*************************************************************************************************
589 template< typename Type // Data type of the sparse matrix
590  , bool SO > // Storage order
592 {
593  delete [] begin_[0UL];
594  delete [] begin_;
595 }
596 //*************************************************************************************************
597 
598 
599 
600 
601 //=================================================================================================
602 //
603 // DATA ACCESS FUNCTIONS
604 //
605 //=================================================================================================
606 
607 //*************************************************************************************************
614 template< typename Type // Data type of the sparse matrix
615  , bool SO > // Storage order
618 {
619  BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
620  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
621 
622  return Reference( *this, i, j );
623 }
624 //*************************************************************************************************
625 
626 
627 //*************************************************************************************************
634 template< typename Type // Data type of the sparse matrix
635  , bool SO > // Storage order
637  CompressedMatrix<Type,SO>::operator()( size_t i, size_t j ) const
638 {
639  BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
640  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
641 
642  const ConstIterator pos( std::lower_bound( begin_[i], end_[i], j, FindIndex() ) );
643 
644  if( pos == end_[i] || pos->index_ != j )
645  return zero_;
646  else
647  return pos->value_;
648 }
649 //*************************************************************************************************
650 
651 
652 //*************************************************************************************************
663 template< typename Type // Data type of the sparse matrix
664  , bool SO > // Storage order
667 {
668  BLAZE_USER_ASSERT( i < m_, "Invalid sparse matrix row access index" );
669  return begin_[i];
670 }
671 //*************************************************************************************************
672 
673 
674 //*************************************************************************************************
685 template< typename Type // Data type of the sparse matrix
686  , bool SO > // Storage order
689 {
690  BLAZE_USER_ASSERT( i < m_, "Invalid sparse matrix row access index" );
691  return begin_[i];
692 }
693 //*************************************************************************************************
694 
695 
696 //*************************************************************************************************
707 template< typename Type // Data type of the sparse matrix
708  , bool SO > // Storage order
711 {
712  BLAZE_USER_ASSERT( i < m_, "Invalid sparse matrix row access index" );
713  return begin_[i];
714 }
715 //*************************************************************************************************
716 
717 
718 //*************************************************************************************************
729 template< typename Type // Data type of the sparse matrix
730  , bool SO > // Storage order
733 {
734  BLAZE_USER_ASSERT( i < m_, "Invalid sparse matrix row access index" );
735  return end_[i];
736 }
737 //*************************************************************************************************
738 
739 
740 //*************************************************************************************************
751 template< typename Type // Data type of the sparse matrix
752  , bool SO > // Storage order
755 {
756  BLAZE_USER_ASSERT( i < m_, "Invalid sparse matrix row access index" );
757  return end_[i];
758 }
759 //*************************************************************************************************
760 
761 
762 //*************************************************************************************************
773 template< typename Type // Data type of the sparse matrix
774  , bool SO > // Storage order
777 {
778  BLAZE_USER_ASSERT( i < m_, "Invalid sparse matrix row access index" );
779  return end_[i];
780 }
781 //*************************************************************************************************
782 
783 
784 
785 
786 //=================================================================================================
787 //
788 // ASSIGNMENT OPERATORS
789 //
790 //=================================================================================================
791 
792 //*************************************************************************************************
801 template< typename Type // Data type of the sparse matrix
802  , bool SO > // Storage order
805 {
806  if( &rhs == this ) return *this;
807 
808  const size_t nonzeros( rhs.nonZeros() );
809 
810  if( rhs.m_ > capacity_ || nonzeros > capacity() )
811  {
812  Iterator* newBegin( new Iterator[2UL*rhs.m_+2UL] );
813  Iterator* newEnd ( newBegin+(rhs.m_+1UL) );
814 
815  newBegin[0UL] = new Element[nonzeros];
816  for( size_t i=0UL; i<rhs.m_; ++i ) {
817  newBegin[i+1UL] = newEnd[i] = std::copy( rhs.begin_[i], rhs.end_[i], newBegin[i] );
818  }
819  newEnd[rhs.m_] = newBegin[0UL]+nonzeros;
820 
821  std::swap( begin_, newBegin );
822  end_ = newEnd;
823  delete [] newBegin[0UL];
824  delete [] newBegin;
825  capacity_ = rhs.m_;
826  }
827  else {
828  for( size_t i=0UL; i<rhs.m_; ++i ) {
829  begin_[i+1UL] = end_[i] = std::copy( rhs.begin_[i], rhs.end_[i], begin_[i] );
830  }
831  }
832 
833  m_ = rhs.m_;
834  n_ = rhs.n_;
835 
836  return *this;
837 }
838 //*************************************************************************************************
839 
840 
841 //*************************************************************************************************
850 template< typename Type // Data type of the sparse matrix
851  , bool SO > // Storage order
852 template< typename MT // Type of the right-hand side dense matrix
853  , bool SO2 > // Storage order of the right-hand side dense matrix
856 {
857  using blaze::assign;
858 
859  if( CanAlias<MT>::value && (~rhs).isAliased( this ) ) {
860  CompressedMatrix tmp( rhs );
861  swap( tmp );
862  }
863  else {
864  resize( (~rhs).rows(), (~rhs).columns(), false );
865  assign( *this, ~rhs );
866  }
867 
868  return *this;
869 }
870 //*************************************************************************************************
871 
872 
873 //*************************************************************************************************
882 template< typename Type // Data type of the sparse matrix
883  , bool SO > // Storage order
884 template< typename MT // Type of the right-hand side sparse matrix
885  , bool SO2 > // Storage order of the right-hand side sparse matrix
888 {
889  using blaze::assign;
890 
891  if( ( CanAlias<MT>::value && (~rhs).isAliased( this ) ) ||
892  (~rhs).rows() > capacity_ ||
893  (~rhs).nonZeros() > capacity() ) {
894  CompressedMatrix tmp( rhs );
895  swap( tmp );
896  }
897  else {
898  resize( (~rhs).rows(), (~rhs).columns(), false );
899  reset();
900  assign( *this, ~rhs );
901  }
902 
903  return *this;
904 }
905 //*************************************************************************************************
906 
907 
908 //*************************************************************************************************
918 template< typename Type // Data type of the sparse matrix
919  , bool SO > // Storage order
920 template< typename MT // Type of the right-hand side matrix
921  , bool SO2 > // Storage order of the right-hand side matrix
924 {
925  using blaze::addAssign;
926 
927  if( (~rhs).rows() != m_ || (~rhs).columns() != n_ )
928  throw std::invalid_argument( "Matrix sizes do not match" );
929 
930  addAssign( *this, ~rhs );
931  return *this;
932 }
933 //*************************************************************************************************
934 
935 
936 //*************************************************************************************************
946 template< typename Type // Data type of the sparse matrix
947  , bool SO > // Storage order
948 template< typename MT // Type of the right-hand side matrix
949  , bool SO2 > // Storage order of the right-hand side matrix
951 {
952  using blaze::subAssign;
953 
954  if( (~rhs).rows() != m_ || (~rhs).columns() != n_ )
955  throw std::invalid_argument( "Matrix sizes do not match" );
956 
957  subAssign( *this, ~rhs );
958  return *this;
959 }
960 //*************************************************************************************************
961 
962 
963 //*************************************************************************************************
973 template< typename Type // Data type of the sparse matrix
974  , bool SO > // Storage order
975 template< typename MT // Type of the right-hand side matrix
976  , bool SO2 > // Storage order of the right-hand side matrix
979 {
980  if( (~rhs).rows() != n_ )
981  throw std::invalid_argument( "Matrix sizes do not match" );
982 
983  CompressedMatrix tmp( *this * (~rhs) );
984  swap( tmp );
985 
986  return *this;
987 }
988 //*************************************************************************************************
989 
990 
991 //*************************************************************************************************
998 template< typename Type // Data type of the sparse matrix
999  , bool SO > // Storage order
1000 template< typename Other > // Data type of the right-hand side scalar
1001 inline typename EnableIf< IsNumeric<Other>, CompressedMatrix<Type,SO> >::Type&
1003 {
1004  for( size_t i=0UL; i<m_; ++i ) {
1005  const Iterator endElem( end(i) );
1006  for( Iterator elem=begin(i); elem<endElem; ++elem )
1007  elem->value_ *= rhs;
1008  }
1009 
1010  return *this;
1011 }
1012 //*************************************************************************************************
1013 
1014 
1015 //*************************************************************************************************
1022 template< typename Type // Data type of the sparse matrix
1023  , bool SO > // Storage order
1024 template< typename Other > // Data type of the right-hand side scalar
1025 inline typename EnableIf< IsNumeric<Other>, CompressedMatrix<Type,SO> >::Type&
1027 {
1028  BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
1029 
1030  typedef typename DivTrait<Type,Other>::Type DT;
1031  typedef typename If< IsNumeric<DT>, DT, Other >::Type Tmp;
1032 
1033  // Depending on the two involved data types, an integer division is applied or a
1034  // floating point division is selected.
1036  const Tmp tmp( Tmp(1)/static_cast<Tmp>( rhs ) );
1037  for( size_t i=0UL; i<m_; ++i ) {
1038  const Iterator endElem( end(i) );
1039  for( Iterator elem=begin(i); elem<endElem; ++elem )
1040  elem->value_ *= tmp;
1041  }
1042  }
1043  else {
1044  for( size_t i=0UL; i<m_; ++i ) {
1045  const Iterator endElem( end(i) );
1046  for( Iterator elem=begin(i); elem<endElem; ++elem )
1047  elem->value_ /= rhs;
1048  }
1049  }
1050 
1051  return *this;
1052 }
1053 //*************************************************************************************************
1054 
1055 
1056 
1057 
1058 //=================================================================================================
1059 //
1060 // UTILITY FUNCTIONS
1061 //
1062 //=================================================================================================
1063 
1064 //*************************************************************************************************
1069 template< typename Type // Data type of the sparse matrix
1070  , bool SO > // Storage order
1071 inline size_t CompressedMatrix<Type,SO>::rows() const
1072 {
1073  return m_;
1074 }
1075 //*************************************************************************************************
1076 
1077 
1078 //*************************************************************************************************
1083 template< typename Type // Data type of the sparse matrix
1084  , bool SO > // Storage order
1086 {
1087  return n_;
1088 }
1089 //*************************************************************************************************
1090 
1091 
1092 //*************************************************************************************************
1097 template< typename Type // Data type of the sparse matrix
1098  , bool SO > // Storage order
1100 {
1101  return end_[m_] - begin_[0UL];
1102 }
1103 //*************************************************************************************************
1104 
1105 
1106 //*************************************************************************************************
1117 template< typename Type // Data type of the sparse matrix
1118  , bool SO > // Storage order
1119 inline size_t CompressedMatrix<Type,SO>::capacity( size_t i ) const
1120 {
1121  BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
1122  return begin_[i+1UL] - begin_[i];
1123 }
1124 //*************************************************************************************************
1125 
1126 
1127 //*************************************************************************************************
1132 template< typename Type // Data type of the sparse matrix
1133  , bool SO > // Storage order
1135 {
1136  size_t nonzeros( 0UL );
1137 
1138  for( size_t i=0UL; i<m_; ++i )
1139  nonzeros += nonZeros( i );
1140 
1141  return nonzeros;
1142 }
1143 //*************************************************************************************************
1144 
1145 
1146 //*************************************************************************************************
1157 template< typename Type // Data type of the sparse matrix
1158  , bool SO > // Storage order
1159 inline size_t CompressedMatrix<Type,SO>::nonZeros( size_t i ) const
1160 {
1161  BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
1162  return end_[i] - begin_[i];
1163 }
1164 //*************************************************************************************************
1165 
1166 
1167 //*************************************************************************************************
1172 template< typename Type // Data type of the sparse matrix
1173  , bool SO > // Storage order
1175 {
1176  for( size_t i=0UL; i<m_; ++i )
1177  end_[i] = begin_[i];
1178 }
1179 //*************************************************************************************************
1180 
1181 
1182 //*************************************************************************************************
1189 template< typename Type // Data type of the sparse matrix
1190  , bool SO > // Storage order
1192 {
1193  end_[0UL] = end_[m_];
1194  m_ = 0UL;
1195  n_ = 0UL;
1196 }
1197 //*************************************************************************************************
1198 
1199 
1200 //*************************************************************************************************
1213 template< typename Type // Data type of the sparse matrix
1214  , bool SO > // Storage order
1216  CompressedMatrix<Type,SO>::insert( size_t i, size_t j, const Type& value )
1217 {
1218  BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
1219  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
1220 
1221  const Iterator pos( std::lower_bound( begin_[i], end_[i], j, FindIndex() ) );
1222 
1223  if( pos != end_[i] && pos->index_ == j )
1224  throw std::invalid_argument( "Bad access index" );
1225 
1226  if( begin_[i+1UL] - end_[i] != 0 ) {
1227  std::copy_backward( pos, end_[i], end_[i]+1 );
1228  pos->value_ = value;
1229  pos->index_ = j;
1230  ++end_[i];
1231 
1232  return pos;
1233  }
1234  else if( end_[m_] - begin_[m_] != 0 ) {
1235  std::copy_backward( pos, end_[m_-1UL], end_[m_-1UL]+1 );
1236 
1237  pos->value_ = value;
1238  pos->index_ = j;
1239 
1240  for( size_t k=i+1UL; k<m_+1UL; ++k ) {
1241  ++begin_[k];
1242  ++end_[k-1UL];
1243  }
1244 
1245  return pos;
1246  }
1247  else {
1248  size_t newCapacity( extendCapacity() );
1249 
1250  Iterator* newBegin = new Iterator[2UL*capacity_+2UL];
1251  Iterator* newEnd = newBegin+capacity_+1UL;
1252 
1253  newBegin[0UL] = new Element[newCapacity];
1254 
1255  for( size_t k=0UL; k<i; ++k ) {
1256  const size_t nonzeros( end_[k] - begin_[k] );
1257  const size_t total( begin_[k+1UL] - begin_[k] );
1258  newEnd [k] = newBegin[k] + nonzeros;
1259  newBegin[k+1UL] = newBegin[k] + total;
1260  }
1261  newEnd [i] = newBegin[i] + ( end_[i] - begin_[i] ) + 1;
1262  newBegin[i+1UL] = newBegin[i] + ( begin_[i+1] - begin_[i] ) + 1;
1263  for( size_t k=i+1UL; k<m_; ++k ) {
1264  const size_t nonzeros( end_[k] - begin_[k] );
1265  const size_t total( begin_[k+1UL] - begin_[k] );
1266  newEnd [k] = newBegin[k] + nonzeros;
1267  newBegin[k+1UL] = newBegin[k] + total;
1268  }
1269 
1270  newEnd[m_] = newEnd[capacity_] = newBegin[0UL]+newCapacity;
1271 
1272  Iterator tmp = std::copy( begin_[0UL], pos, newBegin[0UL] );
1273  tmp->value_ = value;
1274  tmp->index_ = j;
1275  std::copy( pos, end_[m_-1UL], tmp+1UL );
1276 
1277  std::swap( newBegin, begin_ );
1278  end_ = newEnd;
1279  delete [] newBegin[0UL];
1280  delete [] newBegin;
1281 
1282  return tmp;
1283  }
1284 }
1285 //*************************************************************************************************
1286 
1287 
1288 //*************************************************************************************************
1302 template< typename Type // Data type of the sparse matrix
1303  , bool SO > // Storage order
1305  CompressedMatrix<Type,SO>::find( size_t i, size_t j )
1306 {
1307  return const_cast<Iterator>( const_cast<const This&>( *this ).find( i, j ) );
1308 }
1309 //*************************************************************************************************
1310 
1311 
1312 //*************************************************************************************************
1326 template< typename Type // Data type of the sparse matrix
1327  , bool SO > // Storage order
1329  CompressedMatrix<Type,SO>::find( size_t i, size_t j ) const
1330 {
1331  const Iterator pos( std::lower_bound( begin_[i], end_[i], j, FindIndex() ) );
1332  if( pos != end_[i] && pos->index_ == j )
1333  return pos;
1334  else return end_[i];
1335 }
1336 //*************************************************************************************************
1337 
1338 
1339 //*************************************************************************************************
1352 template< typename Type // Data type of the sparse matrix
1353  , bool SO > // Storage order
1354 void CompressedMatrix<Type,SO>::resize( size_t m, size_t n, bool preserve )
1355 {
1356  if( m == m_ && n == n_ ) return;
1357 
1358  if( m > capacity_ )
1359  {
1360  Iterator* newBegin( new Iterator[2*m+2] );
1361  Iterator* newEnd ( newBegin+m+1 );
1362 
1363  newBegin[0UL] = begin_[0UL];
1364 
1365  if( preserve ) {
1366  for( size_t i=0UL; i<m_; ++i ) {
1367  newEnd [i] = end_ [i];
1368  newBegin[i+1UL] = begin_[i+1UL];
1369  }
1370  for( size_t i=m_; i<m; ++i ) {
1371  newBegin[i+1UL] = newEnd[i] = begin_[m_];
1372  }
1373  }
1374  else {
1375  for( size_t i=0UL; i<m; ++i ) {
1376  newBegin[i+1UL] = newEnd[i] = begin_[0UL];
1377  }
1378  }
1379 
1380  newEnd[m] = end_[m_];
1381 
1382  std::swap( newBegin, begin_ );
1383  delete [] newBegin;
1384 
1385  end_ = newEnd;
1386  capacity_ = m;
1387  }
1388  else if( m > m_ )
1389  {
1390  end_[m] = end_[m_];
1391 
1392  if( !preserve ) {
1393  for( size_t i=0UL; i<m_; ++i )
1394  end_[i] = begin_[i];
1395  }
1396 
1397  for( size_t i=m_; i<m; ++i )
1398  begin_[i+1UL] = end_[i] = begin_[m_];
1399  }
1400  else
1401  {
1402  if( preserve ) {
1403  for( size_t i=0UL; i<m; ++i )
1404  end_[i] = std::lower_bound( begin_[i], end_[i], n, FindIndex() );
1405  }
1406  else {
1407  for( size_t i=0UL; i<m; ++i )
1408  end_[i] = begin_[i];
1409  }
1410 
1411  end_[m] = end_[m_];
1412  }
1413 
1414  m_ = m;
1415  n_ = n;
1416 }
1417 //*************************************************************************************************
1418 
1419 
1420 //*************************************************************************************************
1430 template< typename Type // Data type of the sparse matrix
1431  , bool SO > // Storage order
1432 void CompressedMatrix<Type,SO>::reserve( size_t nonzeros )
1433 {
1434  if( nonzeros > capacity() )
1435  reserveElements( nonzeros );
1436 }
1437 //*************************************************************************************************
1438 
1439 
1440 //*************************************************************************************************
1454 template< typename Type // Data type of the sparse matrix
1455  , bool SO > // Storage order
1456 void CompressedMatrix<Type,SO>::reserve( size_t i, size_t nonzeros )
1457 {
1458  BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
1459 
1460  const size_t current( capacity(i) );
1461 
1462  if( current >= nonzeros ) return;
1463 
1464  const ptrdiff_t additional( nonzeros - current );
1465 
1466  if( end_[m_] - begin_[m_] < additional )
1467  {
1468  const size_t newCapacity( begin_[m_] - begin_[0UL] + additional );
1469  BLAZE_INTERNAL_ASSERT( newCapacity > capacity(), "Invalid capacity value" );
1470 
1471  Iterator* newBegin( new Iterator[2UL*m_+2UL] );
1472  Iterator* newEnd ( newBegin+m_+1UL );
1473 
1474  newBegin[0UL] = new Element[newCapacity];
1475  newEnd [m_ ] = newBegin[0UL]+newCapacity;
1476 
1477  for( size_t k=0UL; k<i; ++k ) {
1478  newEnd [k ] = std::copy( begin_[k], end_[k], newBegin[k] );
1479  newBegin[k+1UL] = newBegin[k] + capacity(k);
1480  }
1481  newEnd [i ] = std::copy( begin_[i], end_[i], newBegin[i] );
1482  newBegin[i+1UL] = newBegin[i] + nonzeros;
1483  for( size_t k=i+1UL; k<m_; ++k ) {
1484  newEnd [k ] = std::copy( begin_[k], end_[k], newBegin[k] );
1485  newBegin[k+1UL] = newBegin[k] + capacity(k);
1486  }
1487 
1488  BLAZE_INTERNAL_ASSERT( newBegin[m_] == newEnd[m_], "Invalid pointer calculations" );
1489 
1490  std::swap( newBegin, begin_ );
1491  delete [] newBegin[0UL];
1492  delete [] newBegin;
1493  end_ = newEnd;
1494  }
1495  else
1496  {
1497  begin_[m_] += additional;
1498  for( size_t j=m_-1UL; j>i; --j ) {
1499  begin_[j] = std::copy_backward( begin_[j], end_[j], end_[j]+additional );
1500  end_ [j] += additional;
1501  }
1502  }
1503 }
1504 //*************************************************************************************************
1505 
1506 
1507 //*************************************************************************************************
1512 template< typename Type // Data type of the sparse matrix
1513  , bool SO > // Storage order
1515 {
1516  CompressedMatrix tmp( trans( *this ) );
1517  swap( tmp );
1518  return *this;
1519 }
1520 //*************************************************************************************************
1521 
1522 
1523 //*************************************************************************************************
1540 template< typename Type // Data type of the sparse matrix
1541  , bool SO > // Storage order
1543 {
1544  for( size_t i=0UL; i<rows(); ++i ) {
1545  for( ConstIterator element=begin_[i]; element!=end_[i]; ++element )
1546  if( element->index_ != i && !isDefault( element->value_ ) )
1547  return false;
1548  }
1549 
1550  return true;
1551 }
1552 //*************************************************************************************************
1553 
1554 
1555 //*************************************************************************************************
1560 template< typename Type // Data type of the sparse matrix
1561  , bool SO > // Storage order
1563 {
1564  if( m_ != n_ ) return false;
1565 
1566  for( size_t i=0UL; i<rows(); ++i ) {
1567  for( ConstIterator element=begin_[i]; element!=end_[i]; ++element )
1568  {
1569  const size_t index( element->index_ );
1570 
1571  if( isDefault( element->value_ ) )
1572  continue;
1573 
1574  const Iterator pos( std::lower_bound( begin_[index], end_[index], i, FindIndex() ) );
1575  if( pos == end_[index] || pos->index_ != i || !equal( pos->value_, element->value_ ) )
1576  return false;
1577  }
1578  }
1579 
1580  return true;
1581 }
1582 //*************************************************************************************************
1583 
1584 
1585 //*************************************************************************************************
1591 template< typename Type // Data type of the sparse matrix
1592  , bool SO > // Storage order
1593 template< typename Other > // Data type of the scalar value
1595 {
1596  for( size_t i=0UL; i<m_; ++i )
1597  for( Iterator element=begin_[i]; element!=end_[i]; ++element )
1598  element->value_ *= scalar;
1599 
1600  return *this;
1601 }
1602 //*************************************************************************************************
1603 
1604 
1605 //*************************************************************************************************
1611 template< typename Type // Data type of the sparse matrix
1612  , bool SO > // Storage order
1613 template< typename Other > // Data type of the scalar value
1615 {
1616  const size_t size( blaze::min( m_, n_ ) );
1617 
1618  for( size_t i=0UL; i<size; ++i ) {
1619  Iterator pos = std::lower_bound( begin_[i], end_[i], i, FindIndex() );
1620  if( pos != end_[i] && pos->index_ == i )
1621  pos->value_ *= scalar;
1622  }
1623 
1624  return *this;
1625 }
1626 //*************************************************************************************************
1627 
1628 
1629 //*************************************************************************************************
1636 template< typename Type // Data type of the sparse matrix
1637  , bool SO > // Storage order
1638 inline void CompressedMatrix<Type,SO>::swap( CompressedMatrix& sm ) /* throw() */
1639 {
1640  std::swap( m_, sm.m_ );
1641  std::swap( n_, sm.n_ );
1642  std::swap( capacity_, sm.capacity_ );
1643  std::swap( begin_, sm.begin_ );
1644  std::swap( end_ , sm.end_ );
1645 }
1646 //*************************************************************************************************
1647 
1648 
1649 //*************************************************************************************************
1657 template< typename Type // Data type of the sparse matrix
1658  , bool SO > // Storage order
1660 {
1661  size_t nonzeros( 2UL*capacity()+1UL );
1662  nonzeros = blaze::max( nonzeros, 7UL );
1663  nonzeros = blaze::min( nonzeros, m_*n_ );
1664 
1665  BLAZE_INTERNAL_ASSERT( nonzeros > capacity(), "Invalid capacity value" );
1666 
1667  return nonzeros;
1668 }
1669 //*************************************************************************************************
1670 
1671 
1672 //*************************************************************************************************
1678 template< typename Type // Data type of the sparse matrix
1679  , bool SO > // Storage order
1681 {
1682  Iterator* newBegin = new Iterator[2UL*m_+2UL];
1683  Iterator* newEnd = newBegin+m_+1UL;
1684 
1685  newBegin[0UL] = new Element[nonzeros];
1686 
1687  for( size_t k=0UL; k<m_; ++k ) {
1688  BLAZE_INTERNAL_ASSERT( begin_[k] <= end_[k], "Invalid row pointers" );
1689  newEnd [k] = std::copy( begin_[k], end_[k], newBegin[k] );
1690  newBegin[k+1UL] = newBegin[k] + ( begin_[k+1UL] - begin_[k] );
1691  }
1692 
1693  newEnd[m_] = newBegin[0UL]+nonzeros;
1694 
1695  std::swap( newBegin, begin_ );
1696  delete [] newBegin[0UL];
1697  delete [] newBegin;
1698  end_ = newEnd;
1699 }
1700 //*************************************************************************************************
1701 
1702 
1703 
1704 
1705 //=================================================================================================
1706 //
1707 // LOW-LEVEL UTILITY FUNCTIONS
1708 //
1709 //=================================================================================================
1710 
1711 //*************************************************************************************************
1748 template< typename Type // Data type of the sparse matrix
1749  , bool SO > // Storage order
1750 inline void CompressedMatrix<Type,SO>::append( size_t i, size_t j, const Type& value )
1751 {
1752  BLAZE_USER_ASSERT( i < m_, "Invalid row access index" );
1753  BLAZE_USER_ASSERT( j < n_, "Invalid column access index" );
1754  BLAZE_USER_ASSERT( end_[i] < end_[m_], "Not enough reserved space left" );
1755  BLAZE_USER_ASSERT( begin_[i] == end_[i] || j > ( end_[i]-1UL )->index_, "Index is not strictly increasing" );
1756 
1757  end_[i]->value_ = value;
1758  end_[i]->index_ = j;
1759  ++end_[i];
1760 }
1761 //*************************************************************************************************
1762 
1763 
1764 //*************************************************************************************************
1777 template< typename Type // Data type of the sparse matrix
1778  , bool SO > // Storage order
1780 {
1781  BLAZE_USER_ASSERT( i < m_, "Invalid row access index" );
1782 
1783  begin_[i+1UL] = end_[i];
1784  if( i != m_-1UL )
1785  end_[i+1UL] = end_[i];
1786 }
1787 //*************************************************************************************************
1788 
1789 
1790 
1791 
1792 //=================================================================================================
1793 //
1794 // EXPRESSION TEMPLATE EVALUATION FUNCTIONS
1795 //
1796 //=================================================================================================
1797 
1798 //*************************************************************************************************
1804 template< typename Type // Data type of the sparse matrix
1805  , bool SO > // Storage order
1806 template< typename Other > // Data type of the foreign expression
1807 inline bool CompressedMatrix<Type,SO>::isAliased( const Other* alias ) const
1808 {
1809  return static_cast<const void*>( this ) == static_cast<const void*>( alias );
1810 }
1811 //*************************************************************************************************
1812 
1813 
1814 //*************************************************************************************************
1825 template< typename Type // Data type of the sparse matrix
1826  , bool SO > // Storage order
1827 template< typename MT // Type of the right-hand side dense matrix
1828  , bool SO2 > // Storage order of the right-hand side dense matrix
1830 {
1831  size_t nonzeros( 0UL );
1832 
1833  for( size_t i=1UL; i<=m_; ++i )
1834  begin_[i] = end_[i] = end_[m_];
1835 
1836  for( size_t i=0UL; i<m_; ++i )
1837  {
1838  begin_[i] = end_[i] = begin_[0UL]+nonzeros;
1839 
1840  for( size_t j=0UL; j<n_; ++j )
1841  {
1842  if( nonzeros == capacity() ) {
1843  reserveElements( extendCapacity() );
1844  for( size_t k=i+1UL; k<=m_; ++k )
1845  begin_[k] = end_[k] = end_[m_];
1846  }
1847 
1848  end_[i]->value_ = (~rhs)(i,j);
1849 
1850  if( !isDefault( end_[i]->value_ ) ) {
1851  end_[i]->index_ = j;
1852  ++end_[i];
1853  ++nonzeros;
1854  }
1855  }
1856  }
1857 
1858  begin_[m_] = begin_[0UL]+nonzeros;
1859 }
1860 //*************************************************************************************************
1861 
1862 
1863 //*************************************************************************************************
1874 template< typename Type // Data type of the sparse matrix
1875  , bool SO > // Storage order
1876 template< typename MT > // Type of the right-hand side sparse matrix
1878 {
1879  for( size_t i=0UL; i<(~rhs).rows(); ++i ) {
1880  begin_[i+1UL] = end_[i] = std::copy( (~rhs).begin(i), (~rhs).end(i), begin_[i] );
1881  }
1882 }
1883 //*************************************************************************************************
1884 
1885 
1886 //*************************************************************************************************
1897 template< typename Type // Data type of the sparse matrix
1898  , bool SO > // Storage order
1899 template< typename MT > // Type of the right-hand side sparse matrix
1901 {
1902  typedef typename MT::ConstIterator RhsIterator;
1903 
1904  // Counting the number of elements per row
1905  std::vector<size_t> rowLengths( m_, 0UL );
1906  for( size_t j=0UL; j<n_; ++j ) {
1907  for( RhsIterator element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
1908  ++rowLengths[element->index()];
1909  }
1910 
1911  // Resizing the sparse matrix
1912  for( size_t i=0UL; i<m_; ++i ) {
1913  begin_[i+1UL] = end_[i+1UL] = begin_[i] + rowLengths[i];
1914  }
1915 
1916  // Appending the elements to the rows of the sparse matrix
1917  for( size_t j=0UL; j<n_; ++j ) {
1918  for( RhsIterator element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
1919  append( element->index(), j, element->value() );
1920  }
1921 }
1922 //*************************************************************************************************
1923 
1924 
1925 //*************************************************************************************************
1936 template< typename Type // Data type of the sparse matrix
1937  , bool SO > // Storage order
1938 template< typename MT // Type of the right-hand side dense matrix
1939  , bool SO2 > // Storage order of the right-hand side dense matrix
1941 {
1942  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
1943  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
1944 
1945  CompressedMatrix tmp( *this + (~rhs) );
1946  swap( tmp );
1947 }
1948 //*************************************************************************************************
1949 
1950 
1951 //*************************************************************************************************
1962 template< typename Type // Data type of the sparse matrix
1963  , bool SO > // Storage order
1964 template< typename MT // Type of the right-hand side sparse matrix
1965  , bool SO2 > // Storage order of the right-hand side sparse matrix
1967 {
1968  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
1969  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
1970 
1971  CompressedMatrix tmp( *this + (~rhs) );
1972  swap( tmp );
1973 }
1974 //*************************************************************************************************
1975 
1976 
1977 //*************************************************************************************************
1988 template< typename Type // Data type of the sparse matrix
1989  , bool SO > // Storage order
1990 template< typename MT // Type of the right-hand side dense matrix
1991  , bool SO2 > // Storage order of the right-hand side dense matrix
1993 {
1994  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
1995  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
1996 
1997  CompressedMatrix tmp( *this - (~rhs) );
1998  swap( tmp );
1999 }
2000 //*************************************************************************************************
2001 
2002 
2003 //*************************************************************************************************
2014 template< typename Type // Data type of the sparse matrix
2015  , bool SO > // Storage order
2016 template< typename MT // Type of the right-hand side sparse matrix
2017  , bool SO2 > // Storage order of the right-hand sparse matrix
2019 {
2020  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
2021  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
2022 
2023  CompressedMatrix tmp( *this - (~rhs) );
2024  swap( tmp );
2025 }
2026 //*************************************************************************************************
2027 
2028 
2029 
2030 
2031 
2032 
2033 
2034 
2035 //=================================================================================================
2036 //
2037 // CLASS TEMPLATE SPECIALIZATION FOR COLUMN-MAJOR MATRICES
2038 //
2039 //=================================================================================================
2040 
2041 //*************************************************************************************************
2049 template< typename Type > // Data type of the sparse matrix
2050 class CompressedMatrix<Type,true> : public SparseMatrix< CompressedMatrix<Type,true>, true >
2051 {
2052  private:
2053  //**Type definitions****************************************************************************
2055  //**********************************************************************************************
2056 
2057  //**Private class Element***********************************************************************
2061  struct Element : public ElementBase
2062  {
2063  using ElementBase::operator=;
2064  friend class CompressedMatrix;
2065  };
2067  //**********************************************************************************************
2068 
2069  //**Private class FindIndex*********************************************************************
2073  struct FindIndex : public std::binary_function<Element,size_t,bool>
2074  {
2075  inline bool operator()( const Element& element, size_t index ) const {
2076  return element.index() < index;
2077  }
2078  inline bool operator()( size_t index, const Element& element ) const {
2079  return index < element.index();
2080  }
2081  inline bool operator()( const Element& element1, const Element& element2 ) const {
2082  return element1.index() < element2.index();
2083  }
2084  };
2086  //**********************************************************************************************
2087 
2088  public:
2089  //**Type definitions****************************************************************************
2090  typedef CompressedMatrix<Type,true> This;
2091  typedef This ResultType;
2092  typedef CompressedMatrix<Type,false> OppositeType;
2093  typedef CompressedMatrix<Type,false> TransposeType;
2094  typedef Type ElementType;
2095  typedef const Type& ReturnType;
2096  typedef const This& CompositeType;
2097  typedef MatrixAccessProxy<This> Reference;
2098  typedef const Type& ConstReference;
2099  typedef Element* Iterator;
2100  typedef const Element* ConstIterator;
2101  //**********************************************************************************************
2102 
2103  //**Compilation flags***************************************************************************
2105 
2108  enum { canAlias = 0 };
2109  //**********************************************************************************************
2110 
2111  //**Constructors********************************************************************************
2114  explicit inline CompressedMatrix();
2115  explicit inline CompressedMatrix( size_t m, size_t n );
2116  explicit inline CompressedMatrix( size_t m, size_t n, size_t nonzeros );
2117  explicit CompressedMatrix( size_t m, size_t n, const std::vector<size_t>& nonzeros );
2118  inline CompressedMatrix( const CompressedMatrix& sm );
2119  template< typename MT, bool SO > inline CompressedMatrix( const DenseMatrix<MT,SO>& dm );
2120  template< typename MT, bool SO > inline CompressedMatrix( const SparseMatrix<MT,SO>& sm );
2122  //**********************************************************************************************
2123 
2124  //**Destructor**********************************************************************************
2127  inline ~CompressedMatrix();
2129  //**********************************************************************************************
2130 
2131  //**Data access functions***********************************************************************
2134  inline Reference operator()( size_t i, size_t j );
2135  inline ConstReference operator()( size_t i, size_t j ) const;
2136  inline Iterator begin ( size_t i );
2137  inline ConstIterator begin ( size_t i ) const;
2138  inline ConstIterator cbegin( size_t i ) const;
2139  inline Iterator end ( size_t i );
2140  inline ConstIterator end ( size_t i ) const;
2141  inline ConstIterator cend ( size_t i ) const;
2143  //**********************************************************************************************
2144 
2145  //**Assignment operators************************************************************************
2148  inline CompressedMatrix& operator= ( const CompressedMatrix& rhs );
2149  template< typename MT, bool SO > inline CompressedMatrix& operator= ( const DenseMatrix<MT,SO>& rhs );
2150  template< typename MT, bool SO > inline CompressedMatrix& operator= ( const SparseMatrix<MT,SO>& rhs );
2151  template< typename MT, bool SO > inline CompressedMatrix& operator+=( const Matrix<MT,SO>& rhs );
2152  template< typename MT, bool SO > inline CompressedMatrix& operator-=( const Matrix<MT,SO>& rhs );
2153  template< typename MT, bool SO > inline CompressedMatrix& operator*=( const Matrix<MT,SO>& rhs );
2154 
2155  template< typename Other >
2156  inline typename EnableIf< IsNumeric<Other>, CompressedMatrix >::Type&
2157  operator*=( Other rhs );
2158 
2159  template< typename Other >
2160  inline typename EnableIf< IsNumeric<Other>, CompressedMatrix >::Type&
2161  operator/=( Other rhs );
2163  //**********************************************************************************************
2164 
2165  //**Utility functions***************************************************************************
2168  inline size_t rows() const;
2169  inline size_t columns() const;
2170  inline size_t capacity() const;
2171  inline size_t capacity( size_t j ) const;
2172  inline size_t nonZeros() const;
2173  inline size_t nonZeros( size_t j ) const;
2174  inline void reset();
2175  inline void clear();
2176  Iterator insert ( size_t i, size_t j, const Type& value );
2177  inline Iterator find ( size_t i, size_t j );
2178  inline ConstIterator find ( size_t i, size_t j ) const;
2179  void resize ( size_t m, size_t n, bool preserve=true );
2180  inline void reserve( size_t nonzeros );
2181  void reserve( size_t j, size_t nonzeros );
2182  inline CompressedMatrix& transpose();
2183  bool isDiagonal() const;
2184  bool isSymmetric() const;
2185  template< typename Other > inline CompressedMatrix& scale( Other scalar );
2186  template< typename Other > inline CompressedMatrix& scaleDiagonal( Other scalar );
2187  inline void swap( CompressedMatrix& sm ) /* throw() */;
2189  //**********************************************************************************************
2190 
2191  //**Utility functions***************************************************************************
2194  inline void append ( size_t i, size_t j, const Type& value );
2195  inline void finalize( size_t j );
2197  //**********************************************************************************************
2198 
2199  //**Expression template evaluation functions****************************************************
2202  template< typename Other > inline bool isAliased ( const Other* alias ) const;
2203  template< typename MT, bool SO > inline void assign ( const DenseMatrix<MT,SO>& rhs );
2204  template< typename MT > inline void assign ( const SparseMatrix<MT,true>& rhs );
2205  template< typename MT > inline void assign ( const SparseMatrix<MT,false>& rhs );
2206  template< typename MT, bool SO > inline void addAssign( const DenseMatrix<MT,SO>& rhs );
2207  template< typename MT, bool SO > inline void addAssign( const SparseMatrix<MT,SO>& rhs );
2208  template< typename MT, bool SO > inline void subAssign( const DenseMatrix<MT,SO>& rhs );
2209  template< typename MT, bool SO > inline void subAssign( const SparseMatrix<MT,SO>& rhs );
2211  //**********************************************************************************************
2212 
2213  private:
2214  //**Utility functions***************************************************************************
2217  inline size_t extendCapacity() const;
2218  inline void reserveElements( size_t nonzeros );
2220  //**********************************************************************************************
2221 
2222  //**Member variables****************************************************************************
2225  size_t m_;
2226  size_t n_;
2227  size_t capacity_;
2228  Iterator* begin_;
2229  Iterator* end_;
2230 
2231  static const Type zero_;
2232 
2233  //**********************************************************************************************
2234 
2235  //**Compile time checks*************************************************************************
2243  //**********************************************************************************************
2244 };
2246 //*************************************************************************************************
2247 
2248 
2249 
2250 
2251 //=================================================================================================
2252 //
2253 // DEFINITION AND INITIALIZATION OF THE STATIC MEMBER VARIABLES
2254 //
2255 //=================================================================================================
2256 
2257 template< typename Type >
2258 const Type CompressedMatrix<Type,true>::zero_ = Type();
2259 
2260 
2261 
2262 
2263 //=================================================================================================
2264 //
2265 // CONSTRUCTORS
2266 //
2267 //=================================================================================================
2268 
2269 //*************************************************************************************************
2273 template< typename Type > // Data type of the sparse matrix
2275  : m_ ( 0UL ) // The current number of rows of the sparse matrix
2276  , n_ ( 0UL ) // The current number of columns of the sparse matrix
2277  , capacity_( 0UL ) // The current capacity of the pointer array
2278  , begin_( new Iterator[2UL] ) // Pointers to the first non-zero element of each column
2279  , end_ ( begin_+1UL ) // Pointers one past the last non-zero element of each column
2280 {
2281  begin_[0UL] = end_[0UL] = NULL;
2282 }
2284 //*************************************************************************************************
2285 
2286 
2287 //*************************************************************************************************
2296 template< typename Type > // Data type of the sparse matrix
2297 inline CompressedMatrix<Type,true>::CompressedMatrix( size_t m, size_t n )
2298  : m_ ( m ) // The current number of rows of the sparse matrix
2299  , n_ ( n ) // The current number of columns of the sparse matrix
2300  , capacity_( n ) // The current capacity of the pointer array
2301  , begin_( new Iterator[2UL*n+2UL] ) // Pointers to the first non-zero element of each column
2302  , end_ ( begin_+(n+1UL) ) // Pointers one past the last non-zero element of each column
2303 {
2304  for( size_t j=0UL; j<2UL*n_+2UL; ++j )
2305  begin_[j] = NULL;
2306 }
2308 //*************************************************************************************************
2309 
2310 
2311 //*************************************************************************************************
2321 template< typename Type > // Data type of the sparse matrix
2322 inline CompressedMatrix<Type,true>::CompressedMatrix( size_t m, size_t n, size_t nonzeros )
2323  : m_ ( m ) // The current number of rows of the sparse matrix
2324  , n_ ( n ) // The current number of columns of the sparse matrix
2325  , capacity_( n ) // The current capacity of the pointer array
2326  , begin_( new Iterator[2UL*n+2UL] ) // Pointers to the first non-zero element of each column
2327  , end_ ( begin_+(n+1UL) ) // Pointers one past the last non-zero element of each column
2328 {
2329  begin_[0UL] = new Element[nonzeros];
2330  for( size_t j=1UL; j<(2UL*n_+1UL); ++j )
2331  begin_[j] = begin_[0UL];
2332  end_[n_] = begin_[0UL]+nonzeros;
2333 }
2335 //*************************************************************************************************
2336 
2337 
2338 //*************************************************************************************************
2348 template< typename Type > // Data type of the sparse matrix
2349 CompressedMatrix<Type,true>::CompressedMatrix( size_t m, size_t n, const std::vector<size_t>& nonzeros )
2350  : m_ ( m ) // The current number of rows of the sparse matrix
2351  , n_ ( n ) // The current number of columns of the sparse matrix
2352  , capacity_( n ) // The current capacity of the pointer array
2353  , begin_( new Iterator[2UL*n_+2UL] ) // Pointers to the first non-zero element of each column
2354  , end_ ( begin_+(n_+1UL) ) // Pointers one past the last non-zero element of each column
2355 {
2356  BLAZE_USER_ASSERT( nonzeros.size() == n, "Size of capacity vector and number of columns don't match" );
2357 
2358  size_t newCapacity( 0UL );
2359  for( std::vector<size_t>::const_iterator it=nonzeros.begin(); it!=nonzeros.end(); ++it )
2360  newCapacity += *it;
2361 
2362  begin_[0UL] = end_[0UL] = new Element[newCapacity];
2363  for( size_t j=0UL; j<n_; ++j ) {
2364  begin_[j+1UL] = end_[j+1UL] = begin_[j] + nonzeros[j];
2365  }
2366 }
2368 //*************************************************************************************************
2369 
2370 
2371 //*************************************************************************************************
2377 template< typename Type > // Data type of the sparse matrix
2378 inline CompressedMatrix<Type,true>::CompressedMatrix( const CompressedMatrix& sm )
2379  : m_ ( sm.m_ ) // The current number of rows of the sparse matrix
2380  , n_ ( sm.n_ ) // The current number of columns of the sparse matrix
2381  , capacity_( sm.n_ ) // The current capacity of the pointer array
2382  , begin_ ( new Iterator[2UL*n_+2UL] ) // Pointers to the first non-zero element of each column
2383  , end_ ( begin_+(n_+1UL) ) // Pointers one past the last non-zero element of each column
2384 {
2385  const size_t nonzeros( sm.nonZeros() );
2386 
2387  begin_[0UL] = new Element[nonzeros];
2388  for( size_t j=0UL; j<n_; ++j )
2389  begin_[j+1UL] = end_[j] = std::copy( sm.begin(j), sm.end(j), begin_[j] );
2390  end_[n_] = begin_[0UL]+nonzeros;
2391 }
2393 //*************************************************************************************************
2394 
2395 
2396 //*************************************************************************************************
2402 template< typename Type > // Data type of the sparse matrix
2403 template< typename MT // Type of the foreign dense matrix
2404  , bool SO > // Storage order of the foreign dense matrix
2405 inline CompressedMatrix<Type,true>::CompressedMatrix( const DenseMatrix<MT,SO>& dm )
2406  : m_ ( (~dm).rows() ) // The current number of rows of the sparse matrix
2407  , n_ ( (~dm).columns() ) // The current number of columns of the sparse matrix
2408  , capacity_( n_ ) // The current capacity of the pointer array
2409  , begin_ ( new Iterator[2UL*n_+2UL] ) // Pointers to the first non-zero element of each column
2410  , end_ ( begin_+(n_+1UL) ) // Pointers one past the last non-zero element of each column
2411 {
2412  using blaze::assign;
2413 
2414  for( size_t j=0UL; j<2UL*n_+2UL; ++j )
2415  begin_[j] = NULL;
2416 
2417  assign( *this, ~dm );
2418 }
2420 //*************************************************************************************************
2421 
2422 
2423 //*************************************************************************************************
2429 template< typename Type > // Data type of the sparse matrix
2430 template< typename MT // Type of the foreign sparse matrix
2431  , bool SO > // Storage order of the foreign sparse matrix
2433  : m_ ( (~sm).rows() ) // The current number of rows of the sparse matrix
2434  , n_ ( (~sm).columns() ) // The current number of columns of the sparse matrix
2435  , capacity_( n_ ) // The current capacity of the pointer array
2436  , begin_ ( new Iterator[2UL*n_+2UL] ) // Pointers to the first non-zero element of each column
2437  , end_ ( begin_+(n_+1UL) ) // Pointers one past the last non-zero element of each column
2438 {
2439  using blaze::assign;
2440 
2441  const size_t nonzeros( (~sm).nonZeros() );
2442 
2443  begin_[0UL] = new Element[nonzeros];
2444  for( size_t j=0UL; j<n_; ++j )
2445  begin_[j+1UL] = end_[j] = begin_[0UL];
2446  end_[n_] = begin_[0UL]+nonzeros;
2447 
2448  assign( *this, ~sm );
2449 }
2451 //*************************************************************************************************
2452 
2453 
2454 
2455 
2456 //=================================================================================================
2457 //
2458 // DESTRUCTOR
2459 //
2460 //=================================================================================================
2461 
2462 //*************************************************************************************************
2466 template< typename Type > // Data type of the sparse matrix
2468 {
2469  delete [] begin_[0UL];
2470  delete [] begin_;
2471 }
2473 //*************************************************************************************************
2474 
2475 
2476 
2477 
2478 //=================================================================================================
2479 //
2480 // DATA ACCESS FUNCTIONS
2481 //
2482 //=================================================================================================
2483 
2484 //*************************************************************************************************
2492 template< typename Type > // Data type of the sparse matrix
2493 inline typename CompressedMatrix<Type,true>::Reference
2494  CompressedMatrix<Type,true>::operator()( size_t i, size_t j )
2495 {
2496  BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
2497  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
2498 
2499  return Reference( *this, i, j );
2500 }
2502 //*************************************************************************************************
2503 
2504 
2505 //*************************************************************************************************
2513 template< typename Type > // Data type of the sparse matrix
2514 inline typename CompressedMatrix<Type,true>::ConstReference
2515  CompressedMatrix<Type,true>::operator()( size_t i, size_t j ) const
2516 {
2517  BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
2518  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
2519 
2520  const ConstIterator pos( std::lower_bound( begin_[j], end_[j], i, FindIndex() ) );
2521 
2522  if( pos == end_[j] || pos->index_ != i )
2523  return zero_;
2524  else
2525  return pos->value_;
2526 }
2528 //*************************************************************************************************
2529 
2530 
2531 //*************************************************************************************************
2538 template< typename Type > // Data type of the sparse matrix
2539 inline typename CompressedMatrix<Type,true>::Iterator
2541 {
2542  BLAZE_USER_ASSERT( j < n_, "Invalid sparse matrix column access index" );
2543  return begin_[j];
2544 }
2546 //*************************************************************************************************
2547 
2548 
2549 //*************************************************************************************************
2556 template< typename Type > // Data type of the sparse matrix
2557 inline typename CompressedMatrix<Type,true>::ConstIterator
2558  CompressedMatrix<Type,true>::begin( size_t j ) const
2559 {
2560  BLAZE_USER_ASSERT( j < n_, "Invalid sparse matrix column access index" );
2561  return begin_[j];
2562 }
2564 //*************************************************************************************************
2565 
2566 
2567 //*************************************************************************************************
2574 template< typename Type > // Data type of the sparse matrix
2575 inline typename CompressedMatrix<Type,true>::ConstIterator
2576  CompressedMatrix<Type,true>::cbegin( size_t j ) const
2577 {
2578  BLAZE_USER_ASSERT( j < n_, "Invalid sparse matrix column access index" );
2579  return begin_[j];
2580 }
2582 //*************************************************************************************************
2583 
2584 
2585 //*************************************************************************************************
2592 template< typename Type > // Data type of the sparse matrix
2593 inline typename CompressedMatrix<Type,true>::Iterator
2595 {
2596  BLAZE_USER_ASSERT( j < n_, "Invalid sparse matrix column access index" );
2597  return end_[j];
2598 }
2600 //*************************************************************************************************
2601 
2602 
2603 //*************************************************************************************************
2610 template< typename Type > // Data type of the sparse matrix
2611 inline typename CompressedMatrix<Type,true>::ConstIterator
2612  CompressedMatrix<Type,true>::end( size_t j ) const
2613 {
2614  BLAZE_USER_ASSERT( j < n_, "Invalid sparse matrix column access index" );
2615  return end_[j];
2616 }
2618 //*************************************************************************************************
2619 
2620 
2621 //*************************************************************************************************
2628 template< typename Type > // Data type of the sparse matrix
2629 inline typename CompressedMatrix<Type,true>::ConstIterator
2630  CompressedMatrix<Type,true>::cend( size_t j ) const
2631 {
2632  BLAZE_USER_ASSERT( j < n_, "Invalid sparse matrix column access index" );
2633  return end_[j];
2634 }
2636 //*************************************************************************************************
2637 
2638 
2639 
2640 
2641 //=================================================================================================
2642 //
2643 // ASSIGNMENT OPERATORS
2644 //
2645 //=================================================================================================
2646 
2647 //*************************************************************************************************
2657 template< typename Type > // Data type of the sparse matrix
2658 inline CompressedMatrix<Type,true>&
2659  CompressedMatrix<Type,true>::operator=( const CompressedMatrix& rhs )
2660 {
2661  if( &rhs == this ) return *this;
2662 
2663  const size_t nonzeros( rhs.nonZeros() );
2664 
2665  if( rhs.n_ > capacity_ || nonzeros > capacity() )
2666  {
2667  Iterator* newBegin( new Iterator[2UL*rhs.n_+2UL] );
2668  Iterator* newEnd ( newBegin+(rhs.n_+1UL) );
2669 
2670  newBegin[0UL] = new Element[nonzeros];
2671  for( size_t j=0UL; j<rhs.n_; ++j ) {
2672  newBegin[j+1UL] = newEnd[j] = std::copy( rhs.begin_[j], rhs.end_[j], newBegin[j] );
2673  }
2674  newEnd[rhs.n_] = newBegin[0UL]+nonzeros;
2675 
2676  std::swap( begin_, newBegin );
2677  end_ = newEnd;
2678  delete [] newBegin[0UL];
2679  delete [] newBegin;
2680  capacity_ = rhs.n_;
2681  }
2682  else {
2683  for( size_t j=0UL; j<rhs.n_; ++j ) {
2684  begin_[j+1UL] = end_[j] = std::copy( rhs.begin_[j], rhs.end_[j], begin_[j] );
2685  }
2686  }
2687 
2688  m_ = rhs.m_;
2689  n_ = rhs.n_;
2690 
2691  return *this;
2692 }
2694 //*************************************************************************************************
2695 
2696 
2697 //*************************************************************************************************
2707 template< typename Type > // Data type of the sparse matrix
2708 template< typename MT // Type of the right-hand side dense matrix
2709  , bool SO > // Storage order of the right-hand side dense matrix
2710 inline CompressedMatrix<Type,true>&
2711  CompressedMatrix<Type,true>::operator=( const DenseMatrix<MT,SO>& rhs )
2712 {
2713  using blaze::assign;
2714 
2715  if( CanAlias<MT>::value && (~rhs).isAliased( this ) ) {
2716  CompressedMatrix tmp( rhs );
2717  swap( tmp );
2718  }
2719  else {
2720  resize( (~rhs).rows(), (~rhs).columns(), false );
2721  assign( *this, ~rhs );
2722  }
2723 
2724  return *this;
2725 }
2727 //*************************************************************************************************
2728 
2729 
2730 //*************************************************************************************************
2740 template< typename Type > // Data type of the sparse matrix
2741 template< typename MT // Type of the right-hand side sparse matrix
2742  , bool SO > // Storage order of the right-hand side sparse matrix
2743 inline CompressedMatrix<Type,true>&
2745 {
2746  using blaze::assign;
2747 
2748  if( ( CanAlias<MT>::value && (~rhs).isAliased( this ) ) ||
2749  (~rhs).columns() > capacity_ ||
2750  (~rhs).nonZeros() > capacity() ) {
2751  CompressedMatrix tmp( rhs );
2752  swap( tmp );
2753  }
2754  else {
2755  resize( (~rhs).rows(), (~rhs).columns(), false );
2756  reset();
2757  assign( *this, ~rhs );
2758  }
2759 
2760  return *this;
2761 }
2763 //*************************************************************************************************
2764 
2765 
2766 //*************************************************************************************************
2777 template< typename Type > // Data type of the sparse matrix
2778 template< typename MT // Type of the right-hand side matrix
2779  , bool SO > // Storage order of the right-hand side matrix
2780 inline CompressedMatrix<Type,true>& CompressedMatrix<Type,true>::operator+=( const Matrix<MT,SO>& rhs )
2781 {
2782  using blaze::addAssign;
2783 
2784  if( (~rhs).rows() != m_ || (~rhs).columns() != n_ )
2785  throw std::invalid_argument( "Matrix sizes do not match" );
2786 
2787  addAssign( *this, ~rhs );
2788  return *this;
2789 }
2791 //*************************************************************************************************
2792 
2793 
2794 //*************************************************************************************************
2805 template< typename Type > // Data type of the sparse matrix
2806 template< typename MT // Type of the right-hand side matrix
2807  , bool SO > // Storage order of the right-hand side matrix
2808 inline CompressedMatrix<Type,true>& CompressedMatrix<Type,true>::operator-=( const Matrix<MT,SO>& rhs )
2809 {
2810  using blaze::subAssign;
2811 
2812  if( (~rhs).rows() != m_ || (~rhs).columns() != n_ )
2813  throw std::invalid_argument( "Matrix sizes do not match" );
2814 
2815  subAssign( *this, ~rhs );
2816  return *this;
2817 }
2819 //*************************************************************************************************
2820 
2821 
2822 //*************************************************************************************************
2833 template< typename Type > // Data type of the sparse matrix
2834 template< typename MT // Type of the right-hand side matrix
2835  , bool SO > // Storage order of the right-hand side matrix
2836 inline CompressedMatrix<Type,true>&
2838 {
2839  if( (~rhs).rows() != n_ )
2840  throw std::invalid_argument( "Matrix sizes do not match" );
2841 
2842  CompressedMatrix tmp( *this * (~rhs) );
2843  swap( tmp );
2844 
2845  return *this;
2846 }
2848 //*************************************************************************************************
2849 
2850 
2851 //*************************************************************************************************
2859 template< typename Type > // Data type of the sparse matrix
2860 template< typename Other > // Data type of the right-hand side scalar
2861 inline typename EnableIf< IsNumeric<Other>, CompressedMatrix<Type,true> >::Type&
2863 {
2864  for( size_t j=0UL; j<n_; ++j ) {
2865  const Iterator endElem( end(j) );
2866  for( Iterator elem=begin(j); elem<endElem; ++elem )
2867  elem->value_ *= rhs;
2868  }
2869 
2870  return *this;
2871 }
2873 //*************************************************************************************************
2874 
2875 
2876 //*************************************************************************************************
2884 template< typename Type > // Data type of the sparse matrix
2885 template< typename Other > // Data type of the right-hand side scalar
2886 inline typename EnableIf< IsNumeric<Other>, CompressedMatrix<Type,true> >::Type&
2888 {
2889  BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
2890 
2891  typedef typename DivTrait<Type,Other>::Type DT;
2892  typedef typename If< IsNumeric<DT>, DT, Other >::Type Tmp;
2893 
2894  // Depending on the two involved data types, an integer division is applied or a
2895  // floating point division is selected.
2896  if( IsNumeric<DT>::value && IsFloatingPoint<DT>::value ) {
2897  const Tmp tmp( Tmp(1)/static_cast<Tmp>( rhs ) );
2898  for( size_t j=0UL; j<n_; ++j ) {
2899  const Iterator endElem( end(j) );
2900  for( Iterator elem=begin(j); elem<endElem; ++elem )
2901  elem->value_ *= tmp;
2902  }
2903  }
2904  else {
2905  for( size_t j=0UL; j<n_; ++j ) {
2906  const Iterator endElem( end(j) );
2907  for( Iterator elem=begin(j); elem<endElem; ++elem )
2908  elem->value_ /= rhs;
2909  }
2910  }
2911 
2912  return *this;
2913 }
2915 //*************************************************************************************************
2916 
2917 
2918 
2919 
2920 //=================================================================================================
2921 //
2922 // UTILITY FUNCTIONS
2923 //
2924 //=================================================================================================
2925 
2926 //*************************************************************************************************
2932 template< typename Type > // Data type of the sparse matrix
2933 inline size_t CompressedMatrix<Type,true>::rows() const
2934 {
2935  return m_;
2936 }
2938 //*************************************************************************************************
2939 
2940 
2941 //*************************************************************************************************
2947 template< typename Type > // Data type of the sparse matrix
2948 inline size_t CompressedMatrix<Type,true>::columns() const
2949 {
2950  return n_;
2951 }
2953 //*************************************************************************************************
2954 
2955 
2956 //*************************************************************************************************
2962 template< typename Type > // Data type of the sparse matrix
2963 inline size_t CompressedMatrix<Type,true>::capacity() const
2964 {
2965  return end_[n_] - begin_[0UL];
2966 }
2968 //*************************************************************************************************
2969 
2970 
2971 //*************************************************************************************************
2978 template< typename Type > // Data type of the sparse matrix
2979 inline size_t CompressedMatrix<Type,true>::capacity( size_t j ) const
2980 {
2981  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
2982  return begin_[j+1UL] - begin_[j];
2983 }
2985 //*************************************************************************************************
2986 
2987 
2988 //*************************************************************************************************
2994 template< typename Type > // Data type of the sparse matrix
2995 inline size_t CompressedMatrix<Type,true>::nonZeros() const
2996 {
2997  size_t nonzeros( 0UL );
2998 
2999  for( size_t j=0UL; j<n_; ++j )
3000  nonzeros += nonZeros( j );
3001 
3002  return nonzeros;
3003 }
3005 //*************************************************************************************************
3006 
3007 
3008 //*************************************************************************************************
3015 template< typename Type > // Data type of the sparse matrix
3016 inline size_t CompressedMatrix<Type,true>::nonZeros( size_t j ) const
3017 {
3018  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
3019  return end_[j] - begin_[j];
3020 }
3022 //*************************************************************************************************
3023 
3024 
3025 //*************************************************************************************************
3031 template< typename Type > // Data type of the sparse matrix
3033 {
3034  for( size_t j=0UL; j<n_; ++j )
3035  end_[j] = begin_[j];
3036 }
3038 //*************************************************************************************************
3039 
3040 
3041 //*************************************************************************************************
3049 template< typename Type > // Data type of the sparse matrix
3051 {
3052  end_[0UL] = end_[n_];
3053  m_ = 0UL;
3054  n_ = 0UL;
3055 }
3057 //*************************************************************************************************
3058 
3059 
3060 //*************************************************************************************************
3074 template< typename Type > // Data type of the sparse matrix
3075 inline typename CompressedMatrix<Type,true>::Iterator
3076  CompressedMatrix<Type,true>::insert( size_t i, size_t j, const Type& value )
3077 {
3078  BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
3079  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
3080 
3081  const Iterator pos( std::lower_bound( begin_[j], end_[j], i, FindIndex() ) );
3082 
3083  if( pos != end_[j] && pos->index_ == i )
3084  throw std::invalid_argument( "Bad access index" );
3085 
3086  if( begin_[j+1UL] - end_[j] != 0 ) {
3087  std::copy_backward( pos, end_[j], end_[j]+1 );
3088  pos->value_ = value;
3089  pos->index_ = i;
3090  ++end_[j];
3091 
3092  return pos;
3093  }
3094  else if( end_[n_] - begin_[n_] != 0 ) {
3095  std::copy_backward( pos, end_[n_-1UL], end_[n_-1]+1 );
3096 
3097  pos->value_ = value;
3098  pos->index_ = i;
3099 
3100  for( size_t k=j+1UL; k<n_+1UL; ++k ) {
3101  ++begin_[k];
3102  ++end_[k-1UL];
3103  }
3104 
3105  return pos;
3106  }
3107  else {
3108  size_t newCapacity( extendCapacity() );
3109 
3110  Iterator* newBegin = new Iterator[2UL*capacity_+2UL];
3111  Iterator* newEnd = newBegin+capacity_+1UL;
3112 
3113  newBegin[0UL] = new Element[newCapacity];
3114 
3115  for( size_t k=0UL; k<j; ++k ) {
3116  const size_t nonzeros( end_[k] - begin_[k] );
3117  const size_t total( begin_[k+1UL] - begin_[k] );
3118  newEnd [k] = newBegin[k] + nonzeros;
3119  newBegin[k+1UL] = newBegin[k] + total;
3120  }
3121  newEnd [j] = newBegin[j] + ( end_[j] - begin_[j] ) + 1;
3122  newBegin[j+1UL] = newBegin[j] + ( begin_[j+1UL] - begin_[j] ) + 1;
3123  for( size_t k=j+1UL; k<n_; ++k ) {
3124  const size_t nonzeros( end_[k] - begin_[k] );
3125  const size_t total( begin_[k+1UL] - begin_[k] );
3126  newEnd [k] = newBegin[k] + nonzeros;
3127  newBegin[k+1UL] = newBegin[k] + total;
3128  }
3129 
3130  newEnd[n_] = newEnd[capacity_] = newBegin[0UL]+newCapacity;
3131 
3132  Iterator tmp = std::copy( begin_[0UL], pos, newBegin[0UL] );
3133  tmp->value_ = value;
3134  tmp->index_ = i;
3135  std::copy( pos, end_[n_-1UL], tmp+1UL );
3136 
3137  std::swap( newBegin, begin_ );
3138  end_ = newEnd;
3139  delete [] newBegin[0UL];
3140  delete [] newBegin;
3141 
3142  return tmp;
3143  }
3144 }
3146 //*************************************************************************************************
3147 
3148 
3149 //*************************************************************************************************
3164 template< typename Type > // Data type of the sparse matrix
3165 inline typename CompressedMatrix<Type,true>::Iterator
3166  CompressedMatrix<Type,true>::find( size_t i, size_t j )
3167 {
3168  return const_cast<Iterator>( const_cast<const This&>( *this ).find( i, j ) );
3169 }
3171 //*************************************************************************************************
3172 
3173 
3174 //*************************************************************************************************
3189 template< typename Type > // Data type of the sparse matrix
3190 inline typename CompressedMatrix<Type,true>::ConstIterator
3191  CompressedMatrix<Type,true>::find( size_t i, size_t j ) const
3192 {
3193  const Iterator pos( std::lower_bound( begin_[j], end_[j], i, FindIndex() ) );
3194  if( pos != end_[j] && pos->index_ == i )
3195  return pos;
3196  else return end_[j];
3197 }
3199 //*************************************************************************************************
3200 
3201 
3202 //*************************************************************************************************
3216 template< typename Type > // Data type of the sparse matrix
3217 void CompressedMatrix<Type,true>::resize( size_t m, size_t n, bool preserve )
3218 {
3219  if( m == m_ && n == n_ ) return;
3220 
3221  if( n > capacity_ )
3222  {
3223  Iterator* newBegin( new Iterator[2UL*n+2UL] );
3224  Iterator* newEnd ( newBegin+n+1 );
3225 
3226  newBegin[0UL] = begin_[0UL];
3227 
3228  if( preserve ) {
3229  for( size_t j=0UL; j<n_; ++j ) {
3230  newEnd [j] = end_ [j];
3231  newBegin[j+1UL] = begin_[j+1UL];
3232  }
3233  for( size_t j=n_; j<n; ++j ) {
3234  newBegin[j+1UL] = newEnd[j] = begin_[n_];
3235  }
3236  }
3237  else {
3238  for( size_t j=0UL; j<n; ++j ) {
3239  newBegin[j+1UL] = newEnd[j] = begin_[0UL];
3240  }
3241  }
3242 
3243  newEnd[n] = end_[n_];
3244 
3245  std::swap( newBegin, begin_ );
3246  delete [] newBegin;
3247 
3248  end_ = newEnd;
3249  capacity_ = n;
3250  }
3251  else if( n > n_ )
3252  {
3253  end_[n] = end_[n_];
3254 
3255  if( !preserve ) {
3256  for( size_t j=0UL; j<n_; ++j )
3257  end_[j] = begin_[j];
3258  }
3259 
3260  for( size_t j=n_; j<n; ++j )
3261  begin_[j+1UL] = end_[j] = begin_[n_];
3262  }
3263  else
3264  {
3265  if( preserve ) {
3266  for( size_t j=0UL; j<n; ++j )
3267  end_[j] = std::lower_bound( begin_[j], end_[j], m, FindIndex() );
3268  }
3269  else {
3270  for( size_t j=0UL; j<n; ++j )
3271  end_[j] = begin_[j];
3272  }
3273 
3274  end_[n] = end_[n_];
3275  }
3276 
3277  m_ = m;
3278  n_ = n;
3279 }
3281 //*************************************************************************************************
3282 
3283 
3284 //*************************************************************************************************
3295 template< typename Type > // Data type of the sparse matrix
3296 void CompressedMatrix<Type,true>::reserve( size_t nonzeros )
3297 {
3298  if( nonzeros > capacity() )
3299  reserveElements( nonzeros );
3300 }
3302 //*************************************************************************************************
3303 
3304 
3305 //*************************************************************************************************
3317 template< typename Type > // Data type of the sparse matrix
3318 void CompressedMatrix<Type,true>::reserve( size_t j, size_t nonzeros )
3319 {
3320  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
3321 
3322  const size_t current( capacity(j) );
3323 
3324  if( current >= nonzeros ) return;
3325 
3326  const ptrdiff_t additional( nonzeros - current );
3327 
3328  if( end_[n_] - begin_[n_] < additional )
3329  {
3330  const size_t newCapacity( begin_[n_] - begin_[0UL] + additional );
3331  BLAZE_INTERNAL_ASSERT( newCapacity > capacity(), "Invalid capacity value" );
3332 
3333  Iterator* newBegin( new Iterator[2UL*n_+2UL] );
3334  Iterator* newEnd ( newBegin+n_+1UL );
3335 
3336  newBegin[0UL] = new Element[newCapacity];
3337  newEnd [n_ ] = newBegin[0UL]+newCapacity;
3338 
3339  for( size_t k=0UL; k<j; ++k ) {
3340  newEnd [k ] = std::copy( begin_[k], end_[k], newBegin[k] );
3341  newBegin[k+1UL] = newBegin[k] + capacity(k);
3342  }
3343  newEnd [j ] = std::copy( begin_[j], end_[j], newBegin[j] );
3344  newBegin[j+1UL] = newBegin[j] + nonzeros;
3345  for( size_t k=j+1UL; k<n_; ++k ) {
3346  newEnd [k ] = std::copy( begin_[k], end_[k], newBegin[k] );
3347  newBegin[k+1UL] = newBegin[k] + capacity(k);
3348  }
3349 
3350  BLAZE_INTERNAL_ASSERT( newBegin[n_] == newEnd[n_], "Invalid pointer calculations" );
3351 
3352  std::swap( newBegin, begin_ );
3353  delete [] newBegin[0UL];
3354  delete [] newBegin;
3355  end_ = newEnd;
3356  }
3357  else
3358  {
3359  begin_[n_] += additional;
3360  for( size_t k=n_-1UL; k>j; --k ) {
3361  begin_[k] = std::copy_backward( begin_[k], end_[k], end_[k]+additional );
3362  end_ [k] += additional;
3363  }
3364  }
3365 }
3367 //*************************************************************************************************
3368 
3369 
3370 //*************************************************************************************************
3376 template< typename Type > // Data type of the sparse matrix
3377 CompressedMatrix<Type,true>& CompressedMatrix<Type,true>::transpose()
3378 {
3379  CompressedMatrix tmp( trans( *this ) );
3380  swap( tmp );
3381  return *this;
3382 }
3384 //*************************************************************************************************
3385 
3386 
3387 //*************************************************************************************************
3405 template< typename Type > // Data type of the sparse matrix
3407 {
3408  for( size_t j=0UL; j<columns(); ++j ) {
3409  for( ConstIterator element=begin_[j]; element!=end_[j]; ++element )
3410  if( element->index_ != j && !isDefault( element->value_ ) )
3411  return false;
3412  }
3413 
3414  return true;
3415 }
3417 //*************************************************************************************************
3418 
3419 
3420 //*************************************************************************************************
3426 template< typename Type > // Data type of the sparse matrix
3427 inline bool CompressedMatrix<Type,true>::isSymmetric() const
3428 {
3429  if( m_ != n_ ) return false;
3430 
3431  for( size_t j=0UL; j<rows(); ++j ) {
3432  for( ConstIterator element=begin_[j]; element!=end_[j]; ++element )
3433  {
3434  const size_t index( element->index_ );
3435 
3436  if( isDefault( element->value_ ) )
3437  continue;
3438 
3439  const Iterator pos( std::lower_bound( begin_[index], end_[index], j, FindIndex() ) );
3440  if( pos == end_[index] || pos->index_ != j || !equal( pos->value_, element->value_ ) )
3441  return false;
3442  }
3443  }
3444 
3445  return true;
3446 }
3448 //*************************************************************************************************
3449 
3450 
3451 //*************************************************************************************************
3458 template< typename Type > // Data type of the sparse matrix
3459 template< typename Other > // Data type of the scalar value
3460 inline CompressedMatrix<Type,true>& CompressedMatrix<Type,true>::scale( Other scalar )
3461 {
3462  for( size_t j=0UL; j<n_; ++j )
3463  for( Iterator element=begin_[j]; element!=end_[j]; ++element )
3464  element->value_ *= scalar;
3465 
3466  return *this;
3467 }
3469 //*************************************************************************************************
3470 
3471 
3472 //*************************************************************************************************
3479 template< typename Type > // Data type of the sparse matrix
3480 template< typename Other > // Data type of the scalar value
3481 inline CompressedMatrix<Type,true>& CompressedMatrix<Type,true>::scaleDiagonal( Other scalar )
3482 {
3483  const size_t size( blaze::min( m_, n_ ) );
3484 
3485  for( size_t j=0UL; j<size; ++j ) {
3486  Iterator pos = std::lower_bound( begin_[j], end_[j], j, FindIndex() );
3487  if( pos != end_[j] && pos->index_ == j )
3488  pos->value_ *= scalar;
3489  }
3490 
3491  return *this;
3492 }
3494 //*************************************************************************************************
3495 
3496 
3497 //*************************************************************************************************
3505 template< typename Type > // Data type of the sparse matrix
3506 inline void CompressedMatrix<Type,true>::swap( CompressedMatrix& sm ) /* throw() */
3507 {
3508  std::swap( m_, sm.m_ );
3509  std::swap( n_, sm.n_ );
3510  std::swap( capacity_, sm.capacity_ );
3511  std::swap( begin_, sm.begin_ );
3512  std::swap( end_ , sm.end_ );
3513 }
3515 //*************************************************************************************************
3516 
3517 
3518 //*************************************************************************************************
3527 template< typename Type > // Data type of the sparse matrix
3528 inline size_t CompressedMatrix<Type,true>::extendCapacity() const
3529 {
3530  size_t nonzeros( 2UL*capacity()+1UL );
3531  nonzeros = blaze::max( nonzeros, 7UL );
3532  nonzeros = blaze::min( nonzeros, m_*n_ );
3533 
3534  BLAZE_INTERNAL_ASSERT( nonzeros > capacity(), "Invalid capacity value" );
3535 
3536  return nonzeros;
3537 }
3539 //*************************************************************************************************
3540 
3541 
3542 //*************************************************************************************************
3549 template< typename Type > // Data type of the sparse matrix
3550 void CompressedMatrix<Type,true>::reserveElements( size_t nonzeros )
3551 {
3552  Iterator* newBegin = new Iterator[2UL*n_+2UL];
3553  Iterator* newEnd = newBegin+n_+1UL;
3554 
3555  newBegin[0UL] = new Element[nonzeros];
3556 
3557  for( size_t k=0UL; k<n_; ++k ) {
3558  BLAZE_INTERNAL_ASSERT( begin_[k] <= end_[k], "Invalid column pointers" );
3559  newEnd [k] = std::copy( begin_[k], end_[k], newBegin[k] );
3560  newBegin[k+1UL] = newBegin[k] + ( begin_[k+1UL] - begin_[k] );
3561  }
3562 
3563  newEnd[n_] = newBegin[0UL]+nonzeros;
3564 
3565  std::swap( newBegin, begin_ );
3566  delete [] newBegin[0UL];
3567  delete [] newBegin;
3568  end_ = newEnd;
3569 }
3571 //*************************************************************************************************
3572 
3573 
3574 
3575 
3576 //=================================================================================================
3577 //
3578 // LOW-LEVEL UTILITY FUNCTIONS
3579 //
3580 //=================================================================================================
3581 
3582 //*************************************************************************************************
3620 template< typename Type > // Data type of the sparse matrix
3621 inline void CompressedMatrix<Type,true>::append( size_t i, size_t j, const Type& value )
3622 {
3623  BLAZE_USER_ASSERT( i < m_, "Invalid row access index" );
3624  BLAZE_USER_ASSERT( j < n_, "Invalid column access index" );
3625  BLAZE_USER_ASSERT( end_[j] < end_[n_], "Not enough reserved space left" );
3626  BLAZE_USER_ASSERT( begin_[j] == end_[j] || i > ( end_[j]-1UL )->index_, "Index is not strictly increasing" );
3627 
3628  end_[j]->value_ = value;
3629  end_[j]->index_ = i;
3630  ++end_[j];
3631 }
3633 //*************************************************************************************************
3634 
3635 
3636 //*************************************************************************************************
3650 template< typename Type > // Data type of the sparse matrix
3651 inline void CompressedMatrix<Type,true>::finalize( size_t j )
3652 {
3653  BLAZE_USER_ASSERT( j < n_, "Invalid row access index" );
3654 
3655  begin_[j+1UL] = end_[j];
3656  if( j != n_-1UL )
3657  end_[j+1UL] = end_[j];
3658 }
3660 //*************************************************************************************************
3661 
3662 
3663 
3664 
3665 //=================================================================================================
3666 //
3667 // EXPRESSION TEMPLATE EVALUATION FUNCTIONS
3668 //
3669 //=================================================================================================
3670 
3671 //*************************************************************************************************
3678 template< typename Type > // Data type of the sparse matrix
3679 template< typename Other > // Data type of the foreign expression
3680 inline bool CompressedMatrix<Type,true>::isAliased( const Other* alias ) const
3681 {
3682  return static_cast<const void*>( this ) == static_cast<const void*>( alias );
3683 }
3685 //*************************************************************************************************
3686 
3687 
3688 //*************************************************************************************************
3700 template< typename Type > // Data type of the sparse matrix
3701 template< typename MT // Type of the right-hand side dense matrix
3702  , bool SO > // Storage order of the right-hand side dense matrix
3703 inline void CompressedMatrix<Type,true>::assign( const DenseMatrix<MT,SO>& rhs )
3704 {
3705  size_t nonzeros( 0UL );
3706 
3707  for( size_t j=1UL; j<=n_; ++j )
3708  begin_[j] = end_[j] = end_[n_];
3709 
3710  for( size_t j=0UL; j<n_; ++j )
3711  {
3712  begin_[j] = end_[j] = begin_[0UL]+nonzeros;
3713 
3714  for( size_t i=0UL; i<m_; ++i )
3715  {
3716  if( nonzeros == capacity() ) {
3717  reserveElements( extendCapacity() );
3718  for( size_t k=j+1UL; k<=n_; ++k )
3719  begin_[k] = end_[k] = end_[n_];
3720  }
3721 
3722  end_[j]->value_ = (~rhs)(i,j);
3723 
3724  if( !isDefault( end_[j]->value_ ) ) {
3725  end_[j]->index_ = i;
3726  ++end_[j];
3727  ++nonzeros;
3728  }
3729  }
3730  }
3731 
3732  begin_[n_] = begin_[0UL]+nonzeros;
3733 }
3735 //*************************************************************************************************
3736 
3737 
3738 //*************************************************************************************************
3750 template< typename Type > // Data type of the sparse matrix
3751 template< typename MT > // Type of the right-hand side sparse matrix
3753 {
3754  for( size_t j=0UL; j<(~rhs).columns(); ++j ) {
3755  begin_[j+1UL] = end_[j] = std::copy( (~rhs).begin(j), (~rhs).end(j), begin_[j] );
3756  }
3757 }
3759 //*************************************************************************************************
3760 
3761 
3762 //*************************************************************************************************
3774 template< typename Type > // Data type of the sparse matrix
3775 template< typename MT > // Type of the right-hand side sparse matrix
3777 {
3778  typedef typename MT::ConstIterator RhsIterator;
3779 
3780  // Counting the number of elements per column
3781  std::vector<size_t> columnLengths( n_, 0UL );
3782  for( size_t i=0UL; i<m_; ++i ) {
3783  for( RhsIterator element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
3784  ++columnLengths[element->index()];
3785  }
3786 
3787  // Resizing the sparse matrix
3788  for( size_t j=0UL; j<n_; ++j ) {
3789  begin_[j+1UL] = end_[j+1UL] = begin_[j] + columnLengths[j];
3790  }
3791 
3792  // Appending the elements to the columns of the sparse matrix
3793  for( size_t i=0UL; i<m_; ++i ) {
3794  for( RhsIterator element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
3795  append( i, element->index(), element->value() );
3796  }
3797 }
3799 //*************************************************************************************************
3800 
3801 
3802 //*************************************************************************************************
3814 template< typename Type > // Data type of the sparse matrix
3815 template< typename MT // Type of the right-hand side dense matrix
3816  , bool SO > // Storage order of the right-hand side dense matrix
3817 inline void CompressedMatrix<Type,true>::addAssign( const DenseMatrix<MT,SO>& rhs )
3818 {
3819  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
3820  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
3821 
3822  CompressedMatrix tmp( *this + (~rhs) );
3823  swap( tmp );
3824 }
3826 //*************************************************************************************************
3827 
3828 
3829 //*************************************************************************************************
3841 template< typename Type > // Data type of the sparse matrix
3842 template< typename MT // Type of the right-hand side sparse matrix
3843  , bool SO > // Storage order of the right-hand side sparse matrix
3845 {
3846  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
3847  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
3848 
3849  CompressedMatrix tmp( *this + (~rhs) );
3850  swap( tmp );
3851 }
3853 //*************************************************************************************************
3854 
3855 
3856 //*************************************************************************************************
3868 template< typename Type > // Data type of the sparse matrix
3869 template< typename MT // Type of the right-hand side dense matrix
3870  , bool SO > // Storage order of the right-hand side dense matrix
3871 inline void CompressedMatrix<Type,true>::subAssign( const DenseMatrix<MT,SO>& rhs )
3872 {
3873  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
3874  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
3875 
3876  CompressedMatrix tmp( *this - (~rhs) );
3877  swap( tmp );
3878 }
3880 //*************************************************************************************************
3881 
3882 
3883 //*************************************************************************************************
3895 template< typename Type > // Data type of the sparse matrix
3896 template< typename MT // Type of the right-hand side sparse matrix
3897  , bool SO > // Storage order of the right-hand side sparse matrix
3899 {
3900  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
3901  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
3902 
3903  CompressedMatrix tmp( *this - (~rhs) );
3904  swap( tmp );
3905 }
3907 //*************************************************************************************************
3908 
3909 
3910 
3911 
3912 
3913 
3914 
3915 
3916 //=================================================================================================
3917 //
3918 // GLOBAL OPERATORS
3919 //
3920 //=================================================================================================
3921 
3922 //*************************************************************************************************
3925 template< typename Type, bool SO >
3926 inline bool isnan( const CompressedMatrix<Type,SO>& m );
3927 
3928 template< typename Type, bool SO >
3929 inline void reset( CompressedMatrix<Type,SO>& m );
3930 
3931 template< typename Type, bool SO >
3932 inline void clear( CompressedMatrix<Type,SO>& m );
3933 
3934 template< typename Type, bool SO >
3935 inline bool isDefault( const CompressedMatrix<Type,SO>& m );
3936 
3937 template< typename Type, bool SO >
3938 inline const CompressedMatrix<Type,SO> inv( const CompressedMatrix<Type,SO>& m );
3939 
3940 template< typename Type, bool SO >
3941 inline void swap( CompressedMatrix<Type,SO>& a, CompressedMatrix<Type,SO>& b ) /* throw() */;
3943 //*************************************************************************************************
3944 
3945 
3946 //*************************************************************************************************
3953 template< typename Type // Data type of the sparse matrix
3954  , bool SO > // Storage order
3955 inline bool isnan( const CompressedMatrix<Type,SO>& m )
3956 {
3957  typedef typename CompressedMatrix<Type,SO>::ConstIterator ConstIterator;
3958 
3959  for( size_t i=0UL; i<m.rows(); ++i ) {
3960  for( ConstIterator element=m.begin(i); element!=m.end(i); ++element )
3961  if( isnan( *element ) ) return true;
3962  }
3963  return false;
3964 }
3965 //*************************************************************************************************
3966 
3967 
3968 //*************************************************************************************************
3975 template< typename Type // Data type of the sparse matrix
3976  , bool SO > // Storage order
3978 {
3979  m.reset();
3980 }
3981 //*************************************************************************************************
3982 
3983 
3984 //*************************************************************************************************
3991 template< typename Type // Data type of the sparse matrix
3992  , bool SO > // Storage order
3994 {
3995  m.clear();
3996 }
3997 //*************************************************************************************************
3998 
3999 
4000 //*************************************************************************************************
4018 template< typename Type // Data type of the sparse matrix
4019  , bool SO > // Storage order
4020 inline bool isDefault( const CompressedMatrix<Type,SO>& m )
4021 {
4022  typedef typename CompressedMatrix<Type,SO>::ConstIterator ConstIterator;
4023 
4024  if( SO == rowMajor ) {
4025  for( size_t i=0UL; i<m.rows(); ++i ) {
4026  for( ConstIterator element=m.begin(i); element!=m.end(i); ++element )
4027  if( !isDefault( element->value() ) ) return false;
4028  }
4029  }
4030  else {
4031  for( size_t j=0UL; j<m.columns(); ++j ) {
4032  for( ConstIterator element=m.begin(j); element!=m.end(j); ++element )
4033  if( !isDefault( element->value() ) ) return false;
4034  }
4035  }
4036 
4037  return true;
4038 }
4039 //*************************************************************************************************
4040 
4041 
4042 //*************************************************************************************************
4051 template< typename Type // Data type of the sparse matrix
4052  , bool SO > // Storage order
4054 {
4055  return CompressedMatrix<Type,SO>();
4056 }
4057 //*************************************************************************************************
4058 
4059 
4060 //*************************************************************************************************
4069 template< typename Type // Data type of the sparse matrix
4070  , bool SO > // Storage order
4071 inline void swap( CompressedMatrix<Type,SO>& a, CompressedMatrix<Type,SO>& b ) /* throw() */
4072 {
4073  a.swap( b );
4074 }
4075 //*************************************************************************************************
4076 
4077 
4078 
4079 
4080 //=================================================================================================
4081 //
4082 // ISRESIZABLE SPECIALIZATIONS
4083 //
4084 //=================================================================================================
4085 
4086 //*************************************************************************************************
4088 template< typename T, bool SO >
4089 struct IsResizable< CompressedMatrix<T,SO> > : public TrueType
4090 {
4091  enum { value = 1 };
4092  typedef TrueType Type;
4093 };
4094 
4095 template< typename T, bool SO >
4096 struct IsResizable< const CompressedMatrix<T,SO> > : public TrueType
4097 {
4098  enum { value = 1 };
4099  typedef TrueType Type;
4100 };
4101 
4102 template< typename T, bool SO >
4103 struct IsResizable< volatile CompressedMatrix<T,SO> > : public TrueType
4104 {
4105  enum { value = 1 };
4106  typedef TrueType Type;
4107 };
4108 
4109 template< typename T, bool SO >
4110 struct IsResizable< const volatile CompressedMatrix<T,SO> > : public TrueType
4111 {
4112  enum { value = 1 };
4113  typedef TrueType Type;
4114 };
4116 //*************************************************************************************************
4117 
4118 
4119 
4120 
4121 //=================================================================================================
4122 //
4123 // ADDTRAIT SPECIALIZATIONS
4124 //
4125 //=================================================================================================
4126 
4127 //*************************************************************************************************
4129 template< typename T1, bool SO, typename T2, size_t M, size_t N >
4130 struct AddTrait< CompressedMatrix<T1,SO>, StaticMatrix<T2,M,N,SO> >
4131 {
4132  typedef StaticMatrix< typename AddTrait<T1,T2>::Type, M, N, SO > Type;
4133 };
4134 
4135 template< typename T1, bool SO1, typename T2, size_t M, size_t N, bool SO2 >
4136 struct AddTrait< CompressedMatrix<T1,SO1>, StaticMatrix<T2,M,N,SO2> >
4137 {
4138  typedef StaticMatrix< typename AddTrait<T1,T2>::Type, M, N, false > Type;
4139 };
4140 
4141 template< typename T1, size_t M, size_t N, bool SO, typename T2 >
4142 struct AddTrait< StaticMatrix<T1,M,N,SO>, CompressedMatrix<T2,SO> >
4143 {
4144  typedef StaticMatrix< typename AddTrait<T1,T2>::Type, M, N, SO > Type;
4145 };
4146 
4147 template< typename T1, size_t M, size_t N, bool SO1, typename T2, bool SO2 >
4148 struct AddTrait< StaticMatrix<T1,M,N,SO1>, CompressedMatrix<T2,SO2> >
4149 {
4150  typedef StaticMatrix< typename AddTrait<T1,T2>::Type, M, N, false > Type;
4151 };
4152 
4153 template< typename T1, bool SO, typename T2 >
4154 struct AddTrait< CompressedMatrix<T1,SO>, DynamicMatrix<T2,SO> >
4155 {
4156  typedef DynamicMatrix< typename AddTrait<T1,T2>::Type , SO > Type;
4157 };
4158 
4159 template< typename T1, bool SO1, typename T2, bool SO2 >
4160 struct AddTrait< CompressedMatrix<T1,SO1>, DynamicMatrix<T2,SO2> >
4161 {
4162  typedef DynamicMatrix< typename AddTrait<T1,T2>::Type , false > Type;
4163 };
4164 
4165 template< typename T1, bool SO, typename T2 >
4166 struct AddTrait< DynamicMatrix<T1,SO>, CompressedMatrix<T2,SO> >
4167 {
4168  typedef DynamicMatrix< typename AddTrait<T1,T2>::Type , SO > Type;
4169 };
4170 
4171 template< typename T1, bool SO1, typename T2, bool SO2 >
4172 struct AddTrait< DynamicMatrix<T1,SO1>, CompressedMatrix<T2,SO2> >
4173 {
4174  typedef DynamicMatrix< typename AddTrait<T1,T2>::Type , false > Type;
4175 };
4176 
4177 template< typename T1, bool SO, typename T2 >
4178 struct AddTrait< CompressedMatrix<T1,SO>, CompressedMatrix<T2,SO> >
4179 {
4180  typedef CompressedMatrix< typename AddTrait<T1,T2>::Type , SO > Type;
4181 };
4182 
4183 template< typename T1, bool SO1, typename T2, bool SO2 >
4184 struct AddTrait< CompressedMatrix<T1,SO1>, CompressedMatrix<T2,SO2> >
4185 {
4186  typedef CompressedMatrix< typename AddTrait<T1,T2>::Type , false > Type;
4187 };
4189 //*************************************************************************************************
4190 
4191 
4192 
4193 
4194 //=================================================================================================
4195 //
4196 // SUBTRAIT SPECIALIZATIONS
4197 //
4198 //=================================================================================================
4199 
4200 //*************************************************************************************************
4202 template< typename T1, bool SO, typename T2, size_t M, size_t N >
4203 struct SubTrait< CompressedMatrix<T1,SO>, StaticMatrix<T2,M,N,SO> >
4204 {
4205  typedef StaticMatrix< typename SubTrait<T1,T2>::Type, M, N, SO > Type;
4206 };
4207 
4208 template< typename T1, bool SO1, typename T2, size_t M, size_t N, bool SO2 >
4209 struct SubTrait< CompressedMatrix<T1,SO1>, StaticMatrix<T2,M,N,SO2> >
4210 {
4211  typedef StaticMatrix< typename SubTrait<T1,T2>::Type, M, N, false > Type;
4212 };
4213 
4214 template< typename T1, size_t M, size_t N, bool SO, typename T2 >
4215 struct SubTrait< StaticMatrix<T1,M,N,SO>, CompressedMatrix<T2,SO> >
4216 {
4217  typedef StaticMatrix< typename SubTrait<T1,T2>::Type, M, N, SO > Type;
4218 };
4219 
4220 template< typename T1, size_t M, size_t N, bool SO1, typename T2, bool SO2 >
4221 struct SubTrait< StaticMatrix<T1,M,N,SO1>, CompressedMatrix<T2,SO2> >
4222 {
4223  typedef StaticMatrix< typename SubTrait<T1,T2>::Type, M, N, false > Type;
4224 };
4225 
4226 template< typename T1, bool SO, typename T2 >
4227 struct SubTrait< CompressedMatrix<T1,SO>, DynamicMatrix<T2,SO> >
4228 {
4229  typedef DynamicMatrix< typename SubTrait<T1,T2>::Type , SO > Type;
4230 };
4231 
4232 template< typename T1, bool SO1, typename T2, bool SO2 >
4233 struct SubTrait< CompressedMatrix<T1,SO1>, DynamicMatrix<T2,SO2> >
4234 {
4235  typedef DynamicMatrix< typename SubTrait<T1,T2>::Type , false > Type;
4236 };
4237 
4238 template< typename T1, bool SO, typename T2 >
4239 struct SubTrait< DynamicMatrix<T1,SO>, CompressedMatrix<T2,SO> >
4240 {
4241  typedef DynamicMatrix< typename SubTrait<T1,T2>::Type , SO > Type;
4242 };
4243 
4244 template< typename T1, bool SO1, typename T2, bool SO2 >
4245 struct SubTrait< DynamicMatrix<T1,SO1>, CompressedMatrix<T2,SO2> >
4246 {
4247  typedef DynamicMatrix< typename SubTrait<T1,T2>::Type , false > Type;
4248 };
4249 
4250 template< typename T1, bool SO, typename T2 >
4251 struct SubTrait< CompressedMatrix<T1,SO>, CompressedMatrix<T2,SO> >
4252 {
4253  typedef CompressedMatrix< typename SubTrait<T1,T2>::Type , SO > Type;
4254 };
4255 
4256 template< typename T1, bool SO1, typename T2, bool SO2 >
4257 struct SubTrait< CompressedMatrix<T1,SO1>, CompressedMatrix<T2,SO2> >
4258 {
4259  typedef CompressedMatrix< typename SubTrait<T1,T2>::Type , false > Type;
4260 };
4262 //*************************************************************************************************
4263 
4264 
4265 
4266 
4267 //=================================================================================================
4268 //
4269 // MULTTRAIT SPECIALIZATIONS
4270 //
4271 //=================================================================================================
4272 
4273 //*************************************************************************************************
4275 template< typename T1, bool SO, typename T2 >
4276 struct MultTrait< CompressedMatrix<T1,SO>, T2 >
4277 {
4278  typedef CompressedMatrix< typename MultTrait<T1,T2>::Type, SO > Type;
4280 };
4281 
4282 template< typename T1, typename T2, bool SO >
4283 struct MultTrait< T1, CompressedMatrix<T2,SO> >
4284 {
4285  typedef CompressedMatrix< typename MultTrait<T1,T2>::Type, SO > Type;
4287 };
4288 
4289 template< typename T1, bool SO, typename T2, size_t N >
4290 struct MultTrait< CompressedMatrix<T1,SO>, StaticVector<T2,N,false> >
4291 {
4292  typedef DynamicVector< typename MultTrait<T1,T2>::Type, false > Type;
4293 };
4294 
4295 template< typename T1, size_t N, typename T2, bool SO >
4296 struct MultTrait< StaticVector<T1,N,true>, CompressedMatrix<T2,SO> >
4297 {
4298  typedef DynamicVector< typename MultTrait<T1,T2>::Type, true > Type;
4299 };
4300 
4301 template< typename T1, bool SO, typename T2 >
4302 struct MultTrait< CompressedMatrix<T1,SO>, DynamicVector<T2,false> >
4303 {
4304  typedef DynamicVector< typename MultTrait<T1,T2>::Type, false > Type;
4305 };
4306 
4307 template< typename T1, typename T2, bool SO >
4308 struct MultTrait< DynamicVector<T1,true>, CompressedMatrix<T2,SO> >
4309 {
4310  typedef DynamicVector< typename MultTrait<T1,T2>::Type, true > Type;
4311 };
4312 
4313 template< typename T1, bool SO, typename T2 >
4314 struct MultTrait< CompressedMatrix<T1,SO>, CompressedVector<T2,false> >
4315 {
4316  typedef CompressedVector< typename MultTrait<T1,T2>::Type, false > Type;
4317 };
4318 
4319 template< typename T1, typename T2, bool SO >
4320 struct MultTrait< CompressedVector<T1,true>, CompressedMatrix<T2,SO> >
4321 {
4322  typedef CompressedVector< typename MultTrait<T1,T2>::Type, true > Type;
4323 };
4324 
4325 template< typename T1, bool SO1, typename T2, size_t M, size_t N, bool SO2 >
4326 struct MultTrait< CompressedMatrix<T1,SO1>, StaticMatrix<T2,M,N,SO2> >
4327 {
4328  typedef DynamicMatrix< typename MultTrait<T1,T2>::Type, SO1 > Type;
4329 };
4330 
4331 template< typename T1, size_t M, size_t N, bool SO1, typename T2, bool SO2 >
4332 struct MultTrait< StaticMatrix<T1,M,N,SO1>, CompressedMatrix<T2,SO2> >
4333 {
4334  typedef DynamicMatrix< typename MultTrait<T1,T2>::Type, SO1 > Type;
4335 };
4336 
4337 template< typename T1, bool SO1, typename T2, bool SO2 >
4338 struct MultTrait< CompressedMatrix<T1,SO1>, DynamicMatrix<T2,SO2> >
4339 {
4340  typedef DynamicMatrix< typename MultTrait<T1,T2>::Type, SO1 > Type;
4341 };
4342 
4343 template< typename T1, bool SO1, typename T2, bool SO2 >
4344 struct MultTrait< DynamicMatrix<T1,SO1>, CompressedMatrix<T2,SO2> >
4345 {
4346  typedef DynamicMatrix< typename MultTrait<T1,T2>::Type, SO1 > Type;
4347 };
4348 
4349 template< typename T1, bool SO1, typename T2, bool SO2 >
4350 struct MultTrait< CompressedMatrix<T1,SO1>, CompressedMatrix<T2,SO2> >
4351 {
4352  typedef CompressedMatrix< typename MultTrait<T1,T2>::Type, SO1 > Type;
4353 };
4355 //*************************************************************************************************
4356 
4357 
4358 
4359 
4360 //=================================================================================================
4361 //
4362 // DIVTRAIT SPECIALIZATIONS
4363 //
4364 //=================================================================================================
4365 
4366 //*************************************************************************************************
4368 template< typename T1, bool SO, typename T2 >
4369 struct DivTrait< CompressedMatrix<T1,SO>, T2 >
4370 {
4371  typedef CompressedMatrix< typename DivTrait<T1,T2>::Type, SO > Type;
4373 };
4375 //*************************************************************************************************
4376 
4377 
4378 
4379 
4380 //=================================================================================================
4381 //
4382 // MATHTRAIT SPECIALIZATIONS
4383 //
4384 //=================================================================================================
4385 
4386 //*************************************************************************************************
4388 template< typename T1, bool SO, typename T2 >
4389 struct MathTrait< CompressedMatrix<T1,SO>, CompressedMatrix<T2,SO> >
4390 {
4391  typedef CompressedMatrix< typename MathTrait<T1,T2>::HighType, SO > HighType;
4392  typedef CompressedMatrix< typename MathTrait<T1,T2>::LowType , SO > LowType;
4393 };
4395 //*************************************************************************************************
4396 
4397 } // namespace blaze
4398 
4399 #endif