From 20c944424159948a547ef26a1e577f7f362e0565 Mon Sep 17 00:00:00 2001
From: Lukas Cejka <lukas.ostatek@gmail.com>
Date: Fri, 30 Nov 2018 08:45:16 +0100
Subject: [PATCH] Added getNonZeroRowLength for backup purposes.

---
 src/TNL/Matrices/CSR.h                        |   2 +
 src/TNL/Matrices/CSR_impl.h                   |   9 +
 src/TNL/Matrices/ChunkedEllpack.h             |   2 +
 src/TNL/Matrices/ChunkedEllpack_impl.h        |  17 +-
 src/TNL/Matrices/Ellpack.h                    |   2 +
 src/TNL/Matrices/Ellpack_impl.h               |   9 +
 src/TNL/Matrices/SlicedEllpack.h              |   2 +
 src/TNL/Matrices/SlicedEllpack_impl.h         |  10 ++
 src/TNL/Matrices/SparseRow.h                  |   3 +
 src/TNL/Matrices/SparseRow_impl.h             |  27 +++
 .../Matrices/SparseMatrixTest_impl.h          | 162 +++++++++++-------
 11 files changed, 181 insertions(+), 64 deletions(-)

diff --git a/src/TNL/Matrices/CSR.h b/src/TNL/Matrices/CSR.h
index ef7ba5d6f9..1ce7d330bb 100644
--- a/src/TNL/Matrices/CSR.h
+++ b/src/TNL/Matrices/CSR.h
@@ -75,6 +75,8 @@ public:
 
    __cuda_callable__
    IndexType getRowLengthFast( const IndexType row ) const;
+   
+   IndexType getNonZeroRowLength( const IndexType row ) const;
 
    template< typename Real2, typename Device2, typename Index2 >
    void setLike( const CSR< Real2, Device2, Index2 >& matrix );
diff --git a/src/TNL/Matrices/CSR_impl.h b/src/TNL/Matrices/CSR_impl.h
index b4dff85470..5849bbaa76 100644
--- a/src/TNL/Matrices/CSR_impl.h
+++ b/src/TNL/Matrices/CSR_impl.h
@@ -131,6 +131,15 @@ Index CSR< Real, Device, Index >::getRowLengthFast( const IndexType row ) const
    return this->rowPointers[ row + 1 ] - this->rowPointers[ row ];
 }
 
+template< typename Real,
+          typename Device,
+          typename Index >
+Index CSR< Real, Device, Index >::getNonZeroRowLength( const IndexType row ) const
+{
+    ConstMatrixRow matrixRow = getRow( row );
+    return matrixRow.getNonZeroElementsCount();
+}
+
 template< typename Real,
           typename Device,
           typename Index >
diff --git a/src/TNL/Matrices/ChunkedEllpack.h b/src/TNL/Matrices/ChunkedEllpack.h
index 35bbfa8979..ff889a49fe 100644
--- a/src/TNL/Matrices/ChunkedEllpack.h
+++ b/src/TNL/Matrices/ChunkedEllpack.h
@@ -104,6 +104,8 @@ public:
 
    __cuda_callable__
    IndexType getRowLengthFast( const IndexType row ) const;
+   
+   IndexType getNonZeroRowLength( const IndexType row ) const;
 
    template< typename Real2, typename Device2, typename Index2 >
    void setLike( const ChunkedEllpack< Real2, Device2, Index2 >& matrix );
diff --git a/src/TNL/Matrices/ChunkedEllpack_impl.h b/src/TNL/Matrices/ChunkedEllpack_impl.h
index 00cee63bb2..56a5114912 100644
--- a/src/TNL/Matrices/ChunkedEllpack_impl.h
+++ b/src/TNL/Matrices/ChunkedEllpack_impl.h
@@ -308,6 +308,15 @@ Index ChunkedEllpack< Real, Device, Index >::getRowLengthFast( const IndexType r
    return rowPointers[ row + 1 ] - rowPointers[ row ];
 }
 
+template< typename Real,
+          typename Device,
+          typename Index >
+Index ChunkedEllpack< Real, Device, Index >::getNonZeroRowLength( const IndexType row ) const
+{
+    ConstMatrixRow matrixRow = getRow( row );
+    return matrixRow.getNonZeroElementsCount();
+}
+
 template< typename Real,
           typename Device,
           typename Index >
@@ -979,10 +988,10 @@ getRow( const IndexType rowIndex ) const
 {
    const IndexType rowOffset = this->rowPointers[ rowIndex ];
    const IndexType rowLength = this->rowPointers[ rowIndex + 1 ] - rowOffset;
-   return MatrixRow( &this->columnIndexes[ rowOffset ],
-                     &this->values[ rowOffset ],
-                     rowLength,
-                     1 );
+   return ConstMatrixRow( &this->columnIndexes[ rowOffset ],
+                          &this->values[ rowOffset ],
+                          rowLength,
+                          1 );
 }
 
 
diff --git a/src/TNL/Matrices/Ellpack.h b/src/TNL/Matrices/Ellpack.h
index 1646db1c5c..7d17ff07e8 100644
--- a/src/TNL/Matrices/Ellpack.h
+++ b/src/TNL/Matrices/Ellpack.h
@@ -67,6 +67,8 @@ public:
 
    __cuda_callable__
    IndexType getRowLengthFast( const IndexType row ) const;
+   
+   IndexType getNonZeroRowLength( const IndexType row ) const;
 
    template< typename Real2, typename Device2, typename Index2 >
    void setLike( const Ellpack< Real2, Device2, Index2 >& matrix );
diff --git a/src/TNL/Matrices/Ellpack_impl.h b/src/TNL/Matrices/Ellpack_impl.h
index 6186206439..bf3063cd60 100644
--- a/src/TNL/Matrices/Ellpack_impl.h
+++ b/src/TNL/Matrices/Ellpack_impl.h
@@ -123,6 +123,15 @@ Index Ellpack< Real, Device, Index >::getRowLengthFast( const IndexType row ) co
    return this->rowLengths;
 }
 
+template< typename Real,
+          typename Device,
+          typename Index >
+Index Ellpack< Real, Device, Index >::getNonZeroRowLength( const IndexType row ) const
+{
+    ConstMatrixRow matrixRow = getRow( row );
+    return matrixRow.getNonZeroElementsCount();
+}
+
 template< typename Real,
           typename Device,
           typename Index >
diff --git a/src/TNL/Matrices/SlicedEllpack.h b/src/TNL/Matrices/SlicedEllpack.h
index 6f68f2fa8a..0fc9ccb0b2 100644
--- a/src/TNL/Matrices/SlicedEllpack.h
+++ b/src/TNL/Matrices/SlicedEllpack.h
@@ -95,6 +95,8 @@ public:
 
    __cuda_callable__
    IndexType getRowLengthFast( const IndexType row ) const;
+   
+   IndexType getNonZeroRowLength( const IndexType row ) const;
 
    template< typename Real2, typename Device2, typename Index2 >
    void setLike( const SlicedEllpack< Real2, Device2, Index2, SliceSize >& matrix );
diff --git a/src/TNL/Matrices/SlicedEllpack_impl.h b/src/TNL/Matrices/SlicedEllpack_impl.h
index d186bc0471..59b548ade4 100644
--- a/src/TNL/Matrices/SlicedEllpack_impl.h
+++ b/src/TNL/Matrices/SlicedEllpack_impl.h
@@ -121,6 +121,16 @@ Index SlicedEllpack< Real, Device, Index, SliceSize >::getRowLengthFast( const I
    return this->sliceCompressedRowLengths[ slice ];
 }
 
+template< typename Real,
+          typename Device,
+          typename Index ,
+          int SliceSize >
+Index SlicedEllpack< Real, Device, Index, SliceSize >::getNonZeroRowLength( const IndexType row ) const
+{
+    ConstMatrixRow matrixRow = getRow( row );
+    return matrixRow.getNonZeroElementsCount();
+}
+
 template< typename Real,
           typename Device,
           typename Index,
diff --git a/src/TNL/Matrices/SparseRow.h b/src/TNL/Matrices/SparseRow.h
index e7547ee679..4f8efbdb50 100644
--- a/src/TNL/Matrices/SparseRow.h
+++ b/src/TNL/Matrices/SparseRow.h
@@ -51,6 +51,9 @@ class SparseRow
 
       __cuda_callable__
       Index getLength() const;
+      
+      __cuda_callable__
+      Index getNonZeroElementsCount() const;
 
       void print( std::ostream& str ) const;
 
diff --git a/src/TNL/Matrices/SparseRow_impl.h b/src/TNL/Matrices/SparseRow_impl.h
index f6921b15bb..2f0d87d5eb 100644
--- a/src/TNL/Matrices/SparseRow_impl.h
+++ b/src/TNL/Matrices/SparseRow_impl.h
@@ -11,6 +11,7 @@
 #pragma once
 
 #include <TNL/Matrices/SparseRow.h>
+#include <TNL/ParallelFor.h>
 
 namespace TNL {
 namespace Matrices {   
@@ -107,6 +108,32 @@ getLength() const
    return length;
 }
 
+template< typename Real, typename Index >
+__cuda_callable__
+Index
+SparseRow< Real, Index >::
+getNonZeroElementsCount() const
+{
+    using NonConstIndex = typename std::remove_const< Index >::type;
+    
+    NonConstIndex elementCount ( 0 );
+    
+//    auto computeNonzeros = [this, &elementCount] /*__cuda_callable__*/ ( NonConstIndex i ) mutable
+//    {
+//        if( getElementValue( i ) != ( Real ) 0 )
+//            elementCount++;
+//    };
+   
+//    ParallelFor< Device >::exec( ( NonConstIndex ) 0, length, computeNonzeros );
+//    The ParallelFor::exec() function needs a < DeviceType >, how to get this into SparseRow?
+   
+    for( NonConstIndex i = 0; i < length; i++ )
+        if( getElementValue( i ) != 0 ) // This returns the same amount of elements in a row as does getRowLength(). WHY?
+            elementCount++;
+    
+    return elementCount;
+}
+
 template< typename Real, typename Index >
 void
 SparseRow< Real, Index >::
diff --git a/src/UnitTests/Matrices/SparseMatrixTest_impl.h b/src/UnitTests/Matrices/SparseMatrixTest_impl.h
index 0c1ccbbdd9..d2dae912e6 100644
--- a/src/UnitTests/Matrices/SparseMatrixTest_impl.h
+++ b/src/UnitTests/Matrices/SparseMatrixTest_impl.h
@@ -136,66 +136,108 @@ void test_SetCompressedRowLengths()
     
     m.setCompressedRowLengths( rowLengths );
     
-    
-    if( m.getType() == TNL::String( TNL::String( "Matrices::CSR< ") +
-                       TNL::String( TNL::getType< RealType >() ) +
-                       TNL::String( ", " ) +
-                       TNL::String( Matrix::DeviceType::getDeviceType() ) +
-                       TNL::String( ", " ) +
-                       TNL::String( TNL::getType< IndexType >() ) +
-                       TNL::String( " >" ) )
-      )
-    {
-        EXPECT_EQ( m.getRowLength( 0 ), 3 );
-        EXPECT_EQ( m.getRowLength( 1 ), 3 );
-        EXPECT_EQ( m.getRowLength( 2 ), 1 );
-        EXPECT_EQ( m.getRowLength( 3 ), 2 );
-        EXPECT_EQ( m.getRowLength( 4 ), 3 );
-        EXPECT_EQ( m.getRowLength( 5 ), 4 );
-        EXPECT_EQ( m.getRowLength( 6 ), 5 );
-        EXPECT_EQ( m.getRowLength( 7 ), 6 );
-        EXPECT_EQ( m.getRowLength( 8 ), 7 );
-        EXPECT_EQ( m.getRowLength( 9 ), 8 );
-    }
-    else if( m.getType() == TNL::String( TNL::String( "Matrices::Ellpack< ") +
-                            TNL::String( TNL::getType< RealType >() ) +
-                            TNL::String( ", " ) +
-                            TNL::String( Matrix::DeviceType::getDeviceType() ) +
-                            TNL::String( ", " ) +
-                            TNL::String( TNL::getType< IndexType >() ) +
-                            TNL::String( " >" ) ) 
-                            || 
-             m.getType() == TNL::String( TNL::String( "Matrices::SlicedEllpack< ") +
-                            TNL::String( TNL::getType< RealType >() ) +
-                            TNL::String( ", " ) +
-                            TNL::String( Matrix::DeviceType::getDeviceType() ) +
-                            TNL::String( " >" ) )
-           )
-    {
-        EXPECT_EQ( m.getRowLength( 0 ), 8 );
-        EXPECT_EQ( m.getRowLength( 1 ), 8 );
-        EXPECT_EQ( m.getRowLength( 2 ), 8 );
-        EXPECT_EQ( m.getRowLength( 3 ), 8 );
-        EXPECT_EQ( m.getRowLength( 4 ), 8 );
-        EXPECT_EQ( m.getRowLength( 5 ), 8 );
-        EXPECT_EQ( m.getRowLength( 6 ), 8 );
-        EXPECT_EQ( m.getRowLength( 7 ), 8 );
-        EXPECT_EQ( m.getRowLength( 8 ), 8 );
-        EXPECT_EQ( m.getRowLength( 9 ), 8 );
-    }
-    else
-    {
-        EXPECT_EQ( m.getRowLength( 0 ), 3 );
-        EXPECT_EQ( m.getRowLength( 1 ), 3 );
-        EXPECT_EQ( m.getRowLength( 2 ), 1 );
-        EXPECT_EQ( m.getRowLength( 3 ), 2 );
-        EXPECT_EQ( m.getRowLength( 4 ), 3 );
-        EXPECT_EQ( m.getRowLength( 5 ), 4 );
-        EXPECT_EQ( m.getRowLength( 6 ), 5 );
-        EXPECT_EQ( m.getRowLength( 7 ), 6 );
-        EXPECT_EQ( m.getRowLength( 8 ), 7 );
-        EXPECT_EQ( m.getRowLength( 9 ), 8 );
-    }
+    RealType realValue = 1; // Do this for every individual row, to assure that non-zero values are not assigned where they're not supposed to be, aka, outside of compressed Row Length
+    for( IndexType i = 0; i < rows; i++ )
+        for( IndexType j = 0; j < cols; j++ )
+            m.setElement( i, j, realValue++ );
+    
+    
+    EXPECT_EQ( m.getNonZeroRowLength( 0 ), 3 );
+    EXPECT_EQ( m.getNonZeroRowLength( 1 ), 3 );
+    EXPECT_EQ( m.getNonZeroRowLength( 2 ), 1 );
+    EXPECT_EQ( m.getNonZeroRowLength( 3 ), 2 );
+    EXPECT_EQ( m.getNonZeroRowLength( 4 ), 3 );
+    EXPECT_EQ( m.getNonZeroRowLength( 5 ), 4 );
+    EXPECT_EQ( m.getNonZeroRowLength( 6 ), 5 );
+    EXPECT_EQ( m.getNonZeroRowLength( 7 ), 6 );
+    EXPECT_EQ( m.getNonZeroRowLength( 8 ), 7 );
+    EXPECT_EQ( m.getNonZeroRowLength( 9 ), 8 );
+    
+//    if( m.getType() == TNL::String( TNL::String( "Matrices::CSR< ") +
+//                       TNL::String( TNL::getType< RealType >() ) +
+//                       TNL::String( ", " ) +
+//                       TNL::String( Matrix::DeviceType::getDeviceType() ) +
+//                       //TNL::String( ", " ) +
+//                       //TNL::String( TNL::getType< IndexType >() ) +
+//                       TNL::String( " >" ) )
+//      )
+//    {
+//        EXPECT_EQ( m.getRowLength( 0 ), 3 );
+//        EXPECT_EQ( m.getRowLength( 1 ), 3 );
+//        EXPECT_EQ( m.getRowLength( 2 ), 1 );
+//        EXPECT_EQ( m.getRowLength( 3 ), 2 );
+//        EXPECT_EQ( m.getRowLength( 4 ), 3 );
+//        EXPECT_EQ( m.getRowLength( 5 ), 4 );
+//        EXPECT_EQ( m.getRowLength( 6 ), 5 );
+//        EXPECT_EQ( m.getRowLength( 7 ), 6 );
+//        EXPECT_EQ( m.getRowLength( 8 ), 7 );
+//        EXPECT_EQ( m.getRowLength( 9 ), 8 );
+//    }
+//    else if( m.getType() == TNL::String( TNL::String( "Matrices::AdEllpack< ") +
+//                            TNL::String( TNL::getType< RealType >() ) +
+//                            TNL::String( ", " ) +
+//                            TNL::String( Matrix::DeviceType::getDeviceType() ) +
+//                            TNL::String( ", " ) +
+//                            TNL::String( TNL::getType< IndexType >() ) +
+//                            TNL::String( " >" ) ) 
+//                            || 
+//             m.getType() == TNL::String( TNL::String( "Matrices::SlicedEllpack< ") +
+//                            TNL::String( TNL::getType< RealType >() ) +
+//                            TNL::String( ", " ) +
+//                            TNL::String( Matrix::DeviceType::getDeviceType() ) +
+//                            TNL::String( " >" ) )
+//           )
+//    {
+//        EXPECT_EQ( m.getRowLength( 0 ), 8 );
+//        EXPECT_EQ( m.getRowLength( 1 ), 8 );
+//        EXPECT_EQ( m.getRowLength( 2 ), 8 );
+//        EXPECT_EQ( m.getRowLength( 3 ), 8 );
+//        EXPECT_EQ( m.getRowLength( 4 ), 8 );
+//        EXPECT_EQ( m.getRowLength( 5 ), 8 );
+//        EXPECT_EQ( m.getRowLength( 6 ), 8 );
+//        EXPECT_EQ( m.getRowLength( 7 ), 8 );
+//        EXPECT_EQ( m.getRowLength( 8 ), 8 );
+//        EXPECT_EQ( m.getRowLength( 9 ), 8 );
+//    }
+//    else if( m.getType() == TNL::String( TNL::String( "Matrices::Ellpack< ") +
+//                            TNL::String( TNL::getType< RealType >() ) +
+//                            TNL::String( ", " ) +
+//                            TNL::String( Matrix::DeviceType::getDeviceType() ) +
+//                            TNL::String( ", " ) +
+//                            TNL::String( TNL::getType< IndexType >() ) +
+//                            TNL::String( " >" ) ) 
+//                            ||
+//             m.getType() == TNL::String( TNL::String( "Matrices::ChunkedEllpack< ") +
+//                            TNL::String( TNL::getType< RealType >() ) +
+//                            TNL::String( ", " ) +
+//                            TNL::String( Matrix::DeviceType::getDeviceType() ) +
+//                            TNL::String( " >" ) )
+//           )
+//    {
+//        EXPECT_EQ( m.getNonZeroRowLength( 0 ), 3 );
+//        EXPECT_EQ( m.getNonZeroRowLength( 1 ), 3 );
+//        EXPECT_EQ( m.getNonZeroRowLength( 2 ), 1 );
+//        EXPECT_EQ( m.getNonZeroRowLength( 3 ), 2 );
+//        EXPECT_EQ( m.getNonZeroRowLength( 4 ), 3 );
+//        EXPECT_EQ( m.getNonZeroRowLength( 5 ), 4 );
+//        EXPECT_EQ( m.getNonZeroRowLength( 6 ), 5 );
+//        EXPECT_EQ( m.getNonZeroRowLength( 7 ), 6 );
+//        EXPECT_EQ( m.getNonZeroRowLength( 8 ), 7 );
+//        EXPECT_EQ( m.getNonZeroRowLength( 9 ), 8 );
+//    }
+//    else
+//    {
+//        EXPECT_EQ( m.getRowLength( 0 ), 3 );
+//        EXPECT_EQ( m.getRowLength( 1 ), 3 );
+//        EXPECT_EQ( m.getRowLength( 2 ), 1 );
+//        EXPECT_EQ( m.getRowLength( 3 ), 2 );
+//        EXPECT_EQ( m.getRowLength( 4 ), 3 );
+//        EXPECT_EQ( m.getRowLength( 5 ), 4 );
+//        EXPECT_EQ( m.getRowLength( 6 ), 5 );
+//        EXPECT_EQ( m.getRowLength( 7 ), 6 );
+//        EXPECT_EQ( m.getRowLength( 8 ), 7 );
+//        EXPECT_EQ( m.getRowLength( 9 ), 8 );
+//    }
 }
 
 template< typename Matrix1, typename Matrix2 >
-- 
GitLab