From 256e89f0dd80a852d21432985511887440148b85 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Oberhuber?= <oberhuber.tomas@gmail.com>
Date: Sat, 28 Dec 2019 15:17:35 +0100
Subject: [PATCH] Added SparseMatrixView.

---
 src/TNL/Matrices/SparseMatrix.h       |   1 +
 src/TNL/Matrices/SparseMatrix.hpp     |   2 +-
 src/TNL/Matrices/SparseMatrixView.h   | 196 ++++++++
 src/TNL/Matrices/SparseMatrixView.hpp | 647 ++++++++++++++++++++++++++
 4 files changed, 845 insertions(+), 1 deletion(-)
 create mode 100644 src/TNL/Matrices/SparseMatrixView.h
 create mode 100644 src/TNL/Matrices/SparseMatrixView.hpp

diff --git a/src/TNL/Matrices/SparseMatrix.h b/src/TNL/Matrices/SparseMatrix.h
index 0d8527daf3..5f02e9fdec 100644
--- a/src/TNL/Matrices/SparseMatrix.h
+++ b/src/TNL/Matrices/SparseMatrix.h
@@ -14,6 +14,7 @@
 #include <TNL/Matrices/MatrixType.h>
 #include <TNL/Allocators/Default.h>
 #include <TNL/Containers/Segments/CSR.h>
+#include <TNL/Matrices/SparseMatrixView.h>
 
 namespace TNL {
 namespace Matrices {
diff --git a/src/TNL/Matrices/SparseMatrix.hpp b/src/TNL/Matrices/SparseMatrix.hpp
index b8091d3078..08eae92b45 100644
--- a/src/TNL/Matrices/SparseMatrix.hpp
+++ b/src/TNL/Matrices/SparseMatrix.hpp
@@ -1,5 +1,5 @@
 /***************************************************************************
-                          SparseMatrix.h -  description
+                          SparseMatrix.hpp -  description
                              -------------------
     begin                : Nov 29, 2019
     copyright            : (C) 2019 by Tomas Oberhuber
diff --git a/src/TNL/Matrices/SparseMatrixView.h b/src/TNL/Matrices/SparseMatrixView.h
new file mode 100644
index 0000000000..b40d9c0c2d
--- /dev/null
+++ b/src/TNL/Matrices/SparseMatrixView.h
@@ -0,0 +1,196 @@
+/***************************************************************************
+                          SparseMatrixView.h -  description
+                             -------------------
+    begin                : Dec 28, 2019
+    copyright            : (C) 2019 by Tomas Oberhuber
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+#pragma once
+
+#include <TNL/Matrices/Matrix.h>
+#include <TNL/Matrices/MatrixType.h>
+#include <TNL/Allocators/Default.h>
+#include <TNL/Containers/Segments/CSR.h>
+
+namespace TNL {
+namespace Matrices {
+
+template< typename Real,
+          typename Device = Devices::Host,
+          typename Index = int,
+          typename MatrixType = GeneralMatrix,
+          template< typename Device_, typename Index_ > class SegmentsView = Containers::Segments::CSRView >
+class SparseMatrixView : public MatrixView< Real, Device, Index >
+{
+   public:
+
+      using RealType = Real;
+      template< typename Device_, typename Index_ >
+      using SegmentsViewTemplate = SegmentsView< Device_, Index_ >;
+      using SegmentsViewType = SegmentsView< Device, Index >;
+      using DeviceType = Device;
+      using IndexType = Index;
+      using RowsCapacitiesView = Containers::VectorView< IndexType, DeviceType, IndexType >;
+      using ConstRowsCapacitiesView = typename RowsCapacitiesView::ConstViewType;
+      using ValuesViewType = typename MatrixView< Real, Device, Index >::ValuesView;
+      using ColumnsViewType = Containers::VectorView< IndexType, DeviceType, IndexType >;
+
+      // TODO: remove this - it is here only for compatibility with original matrix implementation
+      typedef Containers::Vector< IndexType, DeviceType, IndexType > CompressedRowLengthsVector;
+      typedef Containers::VectorView< IndexType, DeviceType, IndexType > CompressedRowLengthsVectorView;
+      typedef typename CompressedRowLengthsVectorView::ConstViewType ConstCompressedRowLengthsVectorView;
+
+      static constexpr bool isSymmetric() { return MatrixType::isSymmetric(); };
+
+      __cuda_callable__
+      SparseMatrixView();
+
+      __cuda_callable__
+      SparseMatrixView( const IndexType rows,
+                        const IndexType columns,
+                        ValuesViewType& values,
+                        ColumnsViewType& columnIndexes,
+                        SegmentsViewType& segments );
+
+      __cuda_callable__
+      SparseMatrixView( const SparseMatrixView& m ) = default;
+
+      //__cuda_callable__
+      //SparseMatrixView( const SparseMatrixView&& m ) = default;
+
+      static String getSerializationType();
+
+      virtual String getSerializationTypeVirtual() const;
+
+      template< typename Vector >
+      void getCompressedRowLengths( Vector& rowLengths ) const;
+
+      IndexType getRowLength( const IndexType row ) const;
+
+      __cuda_callable__
+      IndexType getRowLengthFast( const IndexType row ) const;
+
+      IndexType getNonZeroRowLength( const IndexType row ) const;
+
+      __cuda_callable__
+      IndexType getNonZeroRowLengthFast( const IndexType row ) const;
+
+      IndexType getNumberOfNonzeroMatrixElements() const;
+
+      void reset();
+
+      __cuda_callable__
+      bool setElementFast( const IndexType row,
+                           const IndexType column,
+                           const RealType& value );
+
+      bool setElement( const IndexType row,
+                       const IndexType column,
+                       const RealType& value );
+
+      __cuda_callable__
+      bool addElementFast( const IndexType row,
+                           const IndexType column,
+                           const RealType& value,
+                           const RealType& thisElementMultiplicator = 1.0 );
+
+      bool addElement( const IndexType row,
+                       const IndexType column,
+                       const RealType& value,
+                       const RealType& thisElementMultiplicator = 1.0 );
+
+
+      __cuda_callable__
+      bool setRowFast( const IndexType row,
+                       const IndexType* columnIndexes,
+                       const RealType* values,
+                       const IndexType elements );
+
+      bool setRow( const IndexType row,
+                   const IndexType* columnIndexes,
+                   const RealType* values,
+                   const IndexType elements );
+
+
+      __cuda_callable__
+      bool addRowFast( const IndexType row,
+                       const IndexType* columns,
+                       const RealType* values,
+                       const IndexType numberOfElements,
+                       const RealType& thisElementMultiplicator = 1.0 );
+
+      bool addRow( const IndexType row,
+                   const IndexType* columns,
+                   const RealType* values,
+                   const IndexType numberOfElements,
+                   const RealType& thisElementMultiplicator = 1.0 );
+
+
+      __cuda_callable__
+      RealType getElementFast( const IndexType row,
+                               const IndexType column ) const;
+
+      RealType getElement( const IndexType row,
+                           const IndexType column ) const;
+
+      __cuda_callable__
+      void getRowFast( const IndexType row,
+                       IndexType* columns,
+                       RealType* values ) const;
+
+      template< typename Vector >
+      __cuda_callable__
+      typename Vector::RealType rowVectorProduct( const IndexType row,
+                                                  const Vector& vector ) const;
+
+      /***
+       * \brief This method computes outVector = matrixMultiplicator * ( *this ) * inVector + inVectorAddition * inVector
+       */
+      template< typename InVector,
+                typename OutVector >
+      void vectorProduct( const InVector& inVector,
+                          OutVector& outVector,
+                          const RealType& matrixMultiplicator = 1.0,
+                          const RealType& inVectorAddition = 0.0 ) const;
+
+      template< typename Fetch, typename Reduce, typename Keep, typename FetchReal >
+      void rowsReduction( IndexType first, IndexType last, Fetch& fetch, Reduce& reduce, Keep& keep, const FetchReal& zero ) const;
+
+      template< typename Fetch, typename Reduce, typename Keep, typename FetchReal >
+      void allRowsReduction( Fetch& fetch, Reduce& reduce, Keep& keep, const FetchReal& zero ) const;
+
+      template< typename Function >
+      void forRows( IndexType first, IndexType last, Function& function ) const;
+
+      template< typename Function >
+      void forAllRows( Function& function ) const;
+
+      template< typename Vector1, typename Vector2 >
+      bool performSORIteration( const Vector1& b,
+                                const IndexType row,
+                                Vector2& x,
+                                const RealType& omega = 1.0 ) const;
+
+      void save( File& file ) const;
+
+      void save( const String& fileName ) const;
+
+      void print( std::ostream& str ) const;
+
+      __cuda_callable__
+      IndexType getPaddingIndex() const;
+
+   protected:
+
+      ColumnsViewType columnIndexes;
+
+      SegmentsViewType segments;
+};
+
+}  // namespace Conatiners
+} // namespace TNL
+
+#include <TNL/Matrices/SparseMatrixView.hpp>
diff --git a/src/TNL/Matrices/SparseMatrixView.hpp b/src/TNL/Matrices/SparseMatrixView.hpp
new file mode 100644
index 0000000000..0c49cd58d2
--- /dev/null
+++ b/src/TNL/Matrices/SparseMatrixView.hpp
@@ -0,0 +1,647 @@
+/***************************************************************************
+                          SparseMatrixView.hpp -  description
+                             -------------------
+    begin                : Dec 28, 2019
+    copyright            : (C) 2019 by Tomas Oberhuber
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+#pragma once
+
+#include <functional>
+#include <TNL/Matrices/SparseMatrixView.h>
+#include <TNL/Algorithms/Reduction.h>
+
+namespace TNL {
+namespace Matrices {
+
+template< typename Real,
+          typename Device,
+          typename Index,
+          typename MatrixType,
+          template< typename, typename > class SegmentsView >
+__cuda_callable__
+SparseMatrixView< Real, Device, Index, MatrixType, SegmentsView >::
+SparseMatrixView()
+{
+}
+
+template< typename Real,
+          typename Device,
+          typename Index,
+          typename MatrixType,
+          template< typename, typename > class SegmentsView >
+__cuda_callable__
+SparseMatrixView< Real, Device, Index, MatrixType, SegmentsView >::
+SparseMatrixView( const IndexType rows,
+                  const IndexType columns,
+                  ValuesViewType& values,
+                  ColumnsViewType& columnIndexes,
+                  SegmentsViewType& segments )
+ : MatrixView< Real, Device, Index >( rows, columns, values ), columnIndexes( columnIndexes ), segments( segments )
+{  
+}
+
+template< typename Real,
+          typename Device,
+          typename Index,
+          typename MatrixType,
+          template< typename, typename > class SegmentsView >
+String
+SparseMatrixView< Real, Device, Index, MatrixType, SegmentsView >::
+getSerializationType()
+{
+   return String( "Matrices::SparseMatrix< " ) +
+             TNL::getSerializationType< RealType >() + ", " +
+             TNL::getSerializationType< SegmentsView >() + ", [any_device], " +
+             TNL::getSerializationType< IndexType >() + ", [any_allocator] >";
+}
+
+template< typename Real,
+          typename Device,
+          typename Index,
+          typename MatrixType,
+          template< typename, typename > class SegmentsView >
+String
+SparseMatrixView< Real, Device, Index, MatrixType, SegmentsView >::
+getSerializationTypeVirtual() const
+{
+   return this->getSerializationType();
+}
+
+template< typename Real,
+          typename Device,
+          typename Index,
+          typename MatrixType,
+          template< typename, typename > class SegmentsView >
+   template< typename Vector >
+void
+SparseMatrixView< Real, Device, Index, MatrixType, SegmentsView >::
+getCompressedRowLengths( Vector& rowLengths ) const
+{
+   rowLengths.setSize( this->getRows() );
+   rowLengths = 0;
+   auto rowLengths_view = rowLengths.getView();
+   auto fetch = [] __cuda_callable__ ( IndexType row, IndexType column, const RealType& value ) -> IndexType {
+      return ( value != 0.0 );
+   };
+   auto reduce = [] __cuda_callable__ ( IndexType& aux, const IndexType a ) {
+      aux += a;
+   };
+   auto keep = [=] __cuda_callable__ ( const IndexType rowIdx, const IndexType value ) mutable {
+      rowLengths_view[ rowIdx ] = value;
+   };
+   this->allRowsReduction( fetch, reduce, keep, 0 );
+}
+
+template< typename Real,
+          typename Device,
+          typename Index,
+          typename MatrixType,
+          template< typename, typename > class SegmentsView >
+Index
+SparseMatrixView< Real, Device, Index, MatrixType, SegmentsView >::
+getRowLength( const IndexType row ) const
+{
+
+}
+
+template< typename Real,
+          typename Device,
+          typename Index,
+          typename MatrixType,
+          template< typename, typename > class SegmentsView >
+__cuda_callable__
+Index
+SparseMatrixView< Real, Device, Index, MatrixType, SegmentsView >::
+getRowLengthFast( const IndexType row ) const
+{
+
+}
+
+template< typename Real,
+          typename Device,
+          typename Index,
+          typename MatrixType,
+          template< typename, typename > class SegmentsView >
+Index
+SparseMatrixView< Real, Device, Index, MatrixType, SegmentsView >::
+getNonZeroRowLength( const IndexType row ) const
+{
+
+}
+
+template< typename Real,
+          typename Device,
+          typename Index,
+          typename MatrixType,
+          template< typename, typename > class SegmentsView >
+__cuda_callable__
+Index
+SparseMatrixView< Real, Device, Index, MatrixType, SegmentsView >::
+getNonZeroRowLengthFast( const IndexType row ) const
+{
+
+}
+
+template< typename Real,
+          typename Device,
+          typename Index,
+          typename MatrixType,
+          template< typename, typename > class SegmentsView >
+Index
+SparseMatrixView< Real, Device, Index, MatrixType, SegmentsView >::
+getNumberOfNonzeroMatrixElements() const
+{
+   const auto columns_view = this->columnIndexes.getConstView();
+   const IndexType paddingIndex = this->getPaddingIndex();
+   auto fetch = [=] __cuda_callable__ ( const IndexType i ) -> IndexType {
+      return ( columns_view[ i ] != paddingIndex );
+   };
+   return Algorithms::Reduction< DeviceType >::reduce( this->columnIndexes.getSize(), std::plus<>{}, fetch, 0 );
+}
+
+template< typename Real,
+          typename Device,
+          typename Index,
+          typename MatrixType,
+          template< typename, typename > class SegmentsView >
+void
+SparseMatrixView< Real, Device, Index, MatrixType, SegmentsView >::
+reset()
+{
+   Matrix< Real, Device, Index >::reset();
+   this->columnIndexes.reset();
+
+}
+
+template< typename Real,
+          typename Device,
+          typename Index,
+          typename MatrixType,
+          template< typename, typename > class SegmentsView >
+__cuda_callable__
+bool
+SparseMatrixView< Real, Device, Index, MatrixType, SegmentsView >::
+setElementFast( const IndexType row,
+                const IndexType column,
+                const RealType& value )
+{
+   return this->addElementFast( row, column, value, 0.0 );
+}
+
+template< typename Real,
+          typename Device,
+          typename Index,
+          typename MatrixType,
+          template< typename, typename > class SegmentsView >
+bool
+SparseMatrixView< Real, Device, Index, MatrixType, SegmentsView >::
+setElement( const IndexType row,
+            const IndexType column,
+            const RealType& value )
+{
+   return this->addElement( row, column, value, 0.0 );
+}
+
+template< typename Real,
+          typename Device,
+          typename Index,
+          typename MatrixType,
+          template< typename, typename > class SegmentsView >
+__cuda_callable__
+bool
+SparseMatrixView< Real, Device, Index, MatrixType, SegmentsView >::
+addElementFast( const IndexType row,
+                const IndexType column,
+                const RealType& value,
+                const RealType& thisElementMultiplicator )
+{
+
+}
+
+template< typename Real,
+          typename Device,
+          typename Index,
+          typename MatrixType,
+          template< typename, typename > class SegmentsView >
+bool
+SparseMatrixView< Real, Device, Index, MatrixType, SegmentsView >::
+addElement( const IndexType row,
+            const IndexType column,
+            const RealType& value,
+            const RealType& thisElementMultiplicator )
+{
+   TNL_ASSERT( row >= 0 && row < this->rows &&
+               column >= 0 && column < this->columns,
+               std::cerr << " row = " << row
+                    << " column = " << column
+                    << " this->rows = " << this->rows
+                    << " this->columns = " << this->columns );
+
+   const IndexType rowSize = this->segments.getSegmentSize( row );
+   IndexType col( this->getPaddingIndex() );
+   IndexType i;
+   IndexType globalIdx;
+   for( i = 0; i < rowSize; i++ )
+   {
+      globalIdx = this->segments.getGlobalIndex( row, i );
+      TNL_ASSERT_LT( globalIdx, this->columnIndexes.getSize(), "" );
+      col = this->columnIndexes.getElement( globalIdx );
+      if( col == column )
+      {
+         this->values.setElement( globalIdx, thisElementMultiplicator * this->values.getElement( globalIdx ) + value );
+         return true;
+      }
+      if( col == this->getPaddingIndex() || col > column )
+         break;
+   }
+   if( i == rowSize )
+      return false;
+   if( col == this->getPaddingIndex() )
+   {
+      this->columnIndexes.setElement( globalIdx, column );
+      this->values.setElement( globalIdx, value );
+      return true;
+   }
+   else
+   {
+      IndexType j = rowSize - 1;
+      while( j > i )
+      {
+         const IndexType globalIdx1 = this->segments.getGlobalIndex( row, j );
+         const IndexType globalIdx2 = this->segments.getGlobalIndex( row, j - 1 );
+         TNL_ASSERT_LT( globalIdx1, this->columnIndexes.getSize(), "" );
+         TNL_ASSERT_LT( globalIdx2, this->columnIndexes.getSize(), "" );
+         this->columnIndexes.setElement( globalIdx1, this->columnIndexes.getElement( globalIdx2 ) );
+         this->values.setElement( globalIdx1, this->values.getElement( globalIdx2 ) );
+         j--;
+      }
+
+      this->columnIndexes.setElement( globalIdx, column );
+      this->values.setElement( globalIdx, value );
+      return true;
+   }
+}
+
+
+template< typename Real,
+          typename Device,
+          typename Index,
+          typename MatrixType,
+          template< typename, typename > class SegmentsView >
+__cuda_callable__
+bool
+SparseMatrixView< Real, Device, Index, MatrixType, SegmentsView >::
+setRowFast( const IndexType row,
+            const IndexType* columnIndexes,
+            const RealType* values,
+            const IndexType elements )
+{
+}
+
+template< typename Real,
+          typename Device,
+          typename Index,
+          typename MatrixType,
+          template< typename, typename > class SegmentsView >
+bool
+SparseMatrixView< Real, Device, Index, MatrixType, SegmentsView >::
+setRow( const IndexType row,
+        const IndexType* columnIndexes,
+        const RealType* values,
+        const IndexType elements )
+{
+   const IndexType rowLength = this->segments.getSegmentSize( row );
+   if( elements > rowLength )
+      return false;
+
+   for( IndexType i = 0; i < elements; i++ )
+   {
+      const IndexType globalIdx = this->segments.getGlobalIndex( row, i );
+      this->columnIndexes.setElement( globalIdx, columnIndexes[ i ] );
+      this->values.setElement( globalIdx, values[ i ] );
+   }
+   for( IndexType i = elements; i < rowLength; i++ )
+      this->columnIndexes.setElement( this->segments.getGlobalIndex( row, i ), this->getPaddingIndex() );
+   return true;
+}
+
+
+template< typename Real,
+          typename Device,
+          typename Index,
+          typename MatrixType,
+          template< typename, typename > class SegmentsView >
+__cuda_callable__
+bool
+SparseMatrixView< Real, Device, Index, MatrixType, SegmentsView >::
+addRowFast( const IndexType row,
+            const IndexType* columns,
+            const RealType* values,
+            const IndexType numberOfElements,
+            const RealType& thisElementMultiplicator )
+{
+
+}
+
+template< typename Real,
+          typename Device,
+          typename Index,
+          typename MatrixType,
+          template< typename, typename > class SegmentsView >
+bool
+SparseMatrixView< Real, Device, Index, MatrixType, SegmentsView >::
+addRow( const IndexType row,
+        const IndexType* columns,
+        const RealType* values,
+        const IndexType numberOfElements,
+        const RealType& thisElementMultiplicator )
+{
+
+}
+
+template< typename Real,
+          typename Device,
+          typename Index,
+          typename MatrixType,
+          template< typename, typename > class SegmentsView >
+__cuda_callable__
+Real
+SparseMatrixView< Real, Device, Index, MatrixType, SegmentsView >::
+getElementFast( const IndexType row,
+                const IndexType column ) const
+{
+
+}
+
+template< typename Real,
+          typename Device,
+          typename Index,
+          typename MatrixType,
+          template< typename, typename > class SegmentsView >
+Real
+SparseMatrixView< Real, Device, Index, MatrixType, SegmentsView >::
+getElement( const IndexType row,
+            const IndexType column ) const
+{
+   const IndexType rowSize = this->segments.getSegmentSize( row );
+   for( IndexType i = 0; i < rowSize; i++ )
+   {
+      const IndexType globalIdx = this->segments.getGlobalIndex( row, i );
+      TNL_ASSERT_LT( globalIdx, this->columnIndexes.getSize(), "" );
+      const IndexType col = this->columnIndexes.getElement( globalIdx );
+      if( col == column )
+         return this->values.getElement( globalIdx );
+   }
+   return 0.0;
+}
+
+template< typename Real,
+          typename Device,
+          typename Index,
+          typename MatrixType,
+          template< typename, typename > class SegmentsView >
+__cuda_callable__
+void
+SparseMatrixView< Real, Device, Index, MatrixType, SegmentsView >::
+getRowFast( const IndexType row,
+            IndexType* columns,
+            RealType* values ) const
+{
+
+}
+
+template< typename Real,
+          typename Device,
+          typename Index,
+          typename MatrixType,
+          template< typename, typename > class SegmentsView >
+   template< typename Vector >
+__cuda_callable__
+typename Vector::RealType
+SparseMatrixView< Real, Device, Index, MatrixType, SegmentsView >::
+rowVectorProduct( const IndexType row,
+                  const Vector& vector ) const
+{
+
+}
+
+template< typename Real,
+          typename Device,
+          typename Index,
+          typename MatrixType,
+          template< typename, typename > class SegmentsView >
+template< typename InVector,
+       typename OutVector >
+void
+SparseMatrixView< Real, Device, Index, MatrixType, SegmentsView >::
+vectorProduct( const InVector& inVector,
+               OutVector& outVector,
+               const RealType& matrixMultiplicator,
+               const RealType& inVectorAddition ) const
+{
+   const auto inVectorView = inVector.getConstView();
+   auto outVectorView = outVector.getView();
+   const auto valuesView = this->values.getConstView();
+   const auto columnIndexesView = this->columnIndexes.getConstView();
+   const IndexType paddingIndex = this->getPaddingIndex();
+   auto fetch = [=] __cuda_callable__ ( IndexType row, IndexType offset ) -> RealType {
+      const IndexType column = columnIndexesView[ offset ];
+      if( column == paddingIndex )
+         return 0.0;
+      return valuesView[ offset ] * inVectorView[ column ];
+   };
+   auto reduction = [] __cuda_callable__ ( RealType& sum, const RealType& value ) {
+      sum += value;
+   };
+   auto keeper = [=] __cuda_callable__ ( IndexType row, const RealType& value ) mutable {
+      outVectorView[ row ] = value;
+   };
+   this->segments.segmentsReduction( 0, this->getRows(), fetch, reduction, keeper, ( RealType ) 0.0 );
+}
+
+template< typename Real,
+          typename Device,
+          typename Index,
+          typename MatrixType,
+          template< typename, typename > class SegmentsView >
+   template< typename Fetch, typename Reduce, typename Keep, typename FetchValue >
+void
+SparseMatrixView< Real, Device, Index, MatrixType, SegmentsView >::
+rowsReduction( IndexType first, IndexType last, Fetch& fetch, Reduce& reduce, Keep& keep, const FetchValue& zero ) const
+{
+   const auto columns_view = this->columnIndexes.getConstView();
+   const auto values_view = this->values.getConstView();
+   const IndexType paddingIndex_ = this->getPaddingIndex();
+   auto fetch_ = [=] __cuda_callable__ ( IndexType rowIdx, IndexType globalIdx ) mutable -> decltype( fetch( IndexType(), IndexType(), RealType() ) ) {
+      IndexType columnIdx = columns_view[ globalIdx ];
+      if( columnIdx != paddingIndex_ )
+         return fetch( rowIdx, columnIdx, values_view[ globalIdx ] );
+      return zero;
+   };
+   this->segments.segmentsReduction( first, last, fetch_, reduce, keep, zero );
+}
+
+template< typename Real,
+          typename Device,
+          typename Index,
+          typename MatrixType,
+          template< typename, typename > class SegmentsView >
+   template< typename Fetch, typename Reduce, typename Keep, typename FetchReal >
+void
+SparseMatrixView< Real, Device, Index, MatrixType, SegmentsView >::
+allRowsReduction( Fetch& fetch, Reduce& reduce, Keep& keep, const FetchReal& zero ) const
+{
+   this->rowsReduction( 0, this->getRows(), fetch, reduce, keep, zero );
+}
+
+template< typename Real,
+          typename Device,
+          typename Index,
+          typename MatrixType,
+          template< typename, typename > class SegmentsView >
+   template< typename Function >
+void
+SparseMatrixView< Real, Device, Index, MatrixType, SegmentsView >::
+forRows( IndexType first, IndexType last, Function& function ) const
+{
+   const auto columns_view = this->columnIndexes.getConstView();
+   const auto values_view = this->values.getConstView();
+   const IndexType paddingIndex_ = this->getPaddingIndex();
+   auto f = [=] __cuda_callable__ ( IndexType rowIdx, IndexType localIdx, IndexType globalIdx ) mutable -> bool {
+      function( rowIdx, localIdx, globalIdx );
+      return true;
+   };
+   this->segments.forSegments( first, last, f );
+
+}
+
+template< typename Real,
+          typename Device,
+          typename Index,
+          typename MatrixType,
+          template< typename, typename > class SegmentsView >
+   template< typename Function >
+void
+SparseMatrixView< Real, Device, Index, MatrixType, SegmentsView >::
+forAllRows( Function& function ) const
+{
+   this->forRows( 0, this->getRows(), function );
+}
+
+/*template< typename Real,
+          template< typename, typename > class SegmentsView,
+          typename Device,
+          typename Index,
+          typename RealAllocator,
+          typename IndexAllocator >
+template< typename Real2, template< typename, typename > class Segments2, typename Index2, typename RealAllocator2, typename IndexAllocator2 >
+void
+SparseMatrixView< Real, Device, Index, MatrixType, SegmentsView >::
+addMatrix( const SparseMatrixView< Real2, Segments2, Device, Index2, RealAllocator2, IndexAllocator2 >& matrix,
+           const RealType& matrixMultiplicator,
+           const RealType& thisMatrixMultiplicator )
+{
+
+}
+
+template< typename Real,
+          template< typename, typename > class SegmentsView,
+          typename Device,
+          typename Index,
+          typename RealAllocator,
+          typename IndexAllocator >
+template< typename Real2, typename Index2 >
+void
+SparseMatrixView< Real, Device, Index, MatrixType, SegmentsView >::
+getTransposition( const SparseMatrixView< Real2, Device, Index2 >& matrix,
+                  const RealType& matrixMultiplicator )
+{
+
+}*/
+
+template< typename Real,
+          typename Device,
+          typename Index,
+          typename MatrixType,
+          template< typename, typename > class SegmentsView >
+template< typename Vector1, typename Vector2 >
+bool
+SparseMatrixView< Real, Device, Index, MatrixType, SegmentsView >::
+performSORIteration( const Vector1& b,
+                     const IndexType row,
+                     Vector2& x,
+                     const RealType& omega ) const
+{
+
+}
+
+template< typename Real,
+          typename Device,
+          typename Index,
+          typename MatrixType,
+          template< typename, typename > class SegmentsView >
+void
+SparseMatrixView< Real, Device, Index, MatrixType, SegmentsView >::
+save( File& file ) const
+{
+   Matrix< RealType, DeviceType, IndexType >::save( file );
+   file << this->columnIndexes;
+   this->segments.save( file );
+}
+
+template< typename Real,
+          typename Device,
+          typename Index,
+          typename MatrixType,
+          template< typename, typename > class SegmentsView >
+void
+SparseMatrixView< Real, Device, Index, MatrixType, SegmentsView >::
+save( const String& fileName ) const
+{
+   Object::save( fileName );
+}
+
+template< typename Real,
+          typename Device,
+          typename Index,
+          typename MatrixType,
+          template< typename, typename > class SegmentsView >
+void
+SparseMatrixView< Real, Device, Index, MatrixType, SegmentsView >::
+print( std::ostream& str ) const
+{
+   for( IndexType row = 0; row < this->getRows(); row++ )
+   {
+      str <<"Row: " << row << " -> ";
+      const IndexType rowLength = this->segments.getSegmentSize( row );
+      for( IndexType i = 0; i < rowLength; i++ )
+      {
+         const IndexType globalIdx = this->segments.getGlobalIndex( row, i );
+         const IndexType column = this->columnIndexes.getElement( globalIdx );
+         if( column == this->getPaddingIndex() )
+            break;
+         str << " Col:" << column << "->" << this->values.getElement( globalIdx ) << "\t";
+      }
+      str << std::endl;
+   }
+}
+
+template< typename Real,
+          typename Device,
+          typename Index,
+          typename MatrixType,
+          template< typename, typename > class SegmentsView >
+__cuda_callable__
+Index
+SparseMatrixView< Real, Device, Index, MatrixType, SegmentsView >::
+getPaddingIndex() const
+{
+   return -1;
+}
+
+   } //namespace Matrices
+} // namespace  TNL
-- 
GitLab