From fcb368b75abc9fbce5a0e4cf8e31c18935fc1fdb Mon Sep 17 00:00:00 2001
From: Tomas Oberhuber <tomas.oberhuber@fjfi.cvut.cz>
Date: Wed, 15 Jan 2020 18:05:53 +0100
Subject: [PATCH] Forwarding dense matrix methods calls to DenseMatrixView.

---
 src/TNL/Containers/Segments/EllpackView.h   |   2 +
 src/TNL/Containers/Segments/EllpackView.hpp |  13 ++
 src/TNL/Matrices/Dense.h                    |   4 +-
 src/TNL/Matrices/Dense.hpp                  | 136 +++++---------------
 src/TNL/Matrices/DenseMatrixView.h          |  10 --
 src/TNL/Matrices/DenseMatrixView.hpp        |  77 ++++-------
 src/UnitTests/Matrices/DenseMatrixTest.h    |   4 +-
 7 files changed, 71 insertions(+), 175 deletions(-)

diff --git a/src/TNL/Containers/Segments/EllpackView.h b/src/TNL/Containers/Segments/EllpackView.h
index 737810498a..f64b04068e 100644
--- a/src/TNL/Containers/Segments/EllpackView.h
+++ b/src/TNL/Containers/Segments/EllpackView.h
@@ -104,6 +104,8 @@ class EllpackView
       template< typename Fetch, typename Reduction, typename ResultKeeper, typename Real, typename... Args >
       void allReduction( Fetch& fetch, Reduction& reduction, ResultKeeper& keeper, const Real& zero, Args... args ) const;
 
+      EllpackView& operator=( const EllpackView& view );
+
       void save( File& file ) const;
 
       void load( File& file );
diff --git a/src/TNL/Containers/Segments/EllpackView.hpp b/src/TNL/Containers/Segments/EllpackView.hpp
index 21be886541..719a349a98 100644
--- a/src/TNL/Containers/Segments/EllpackView.hpp
+++ b/src/TNL/Containers/Segments/EllpackView.hpp
@@ -291,6 +291,19 @@ allReduction( Fetch& fetch, Reduction& reduction, ResultKeeper& keeper, const Re
    this->segmentsReduction( 0, this->getSegmentsCount(), fetch, reduction, keeper, zero, args... );
 }
 
+template< typename Device,
+          typename Index,
+          bool RowMajorOrder,
+          int Alignment >
+EllpackView< Device, Index, RowMajorOrder, Alignment >&
+EllpackView< Device, Index, RowMajorOrder, Alignment >::
+operator=( const EllpackView< Device, Index, RowMajorOrder, Alignment >& view )
+{
+   this->segmentSize = view.segmentSize;
+   this->size = view.size;
+   this->alignedSize = view.alignedSize;
+}
+
 template< typename Device,
           typename Index,
           bool RowMajorOrder,
diff --git a/src/TNL/Matrices/Dense.h b/src/TNL/Matrices/Dense.h
index 485c947010..2e71316e94 100644
--- a/src/TNL/Matrices/Dense.h
+++ b/src/TNL/Matrices/Dense.h
@@ -168,7 +168,7 @@ class Dense : public Matrix< Real, Device, Index >
                                 const RealType& omega = 1.0 ) const;
 
       // copy assignment
-      //Dense& operator=( const Dense& matrix );
+      Dense& operator=( const Dense& matrix );
 
       // cross-device copy assignment
       template< typename Real_, typename Device_, typename Index_, bool RowMajorOrder_, typename RealAlocator_ >
@@ -200,6 +200,8 @@ class Dense : public Matrix< Real, Device, Index >
       friend class DenseDeviceDependentCode< DeviceType >;
 
       SegmentsType segments;
+
+      ViewType view;
 };
 
 } // namespace Matrices
diff --git a/src/TNL/Matrices/Dense.hpp b/src/TNL/Matrices/Dense.hpp
index 7e6f379486..b8fa969074 100644
--- a/src/TNL/Matrices/Dense.hpp
+++ b/src/TNL/Matrices/Dense.hpp
@@ -76,10 +76,7 @@ String
 Dense< Real, Device, Index, RowMajorOrder, RealAllocator >::
 getSerializationType()
 {
-   return String( "Matrices::Dense< " ) +
-          TNL::getSerializationType< RealType >() + ", [any_device], " +
-          TNL::getSerializationType< IndexType >() + ", " +
-          ( RowMajorOrder ? "true" : "false" ) + ", [any_allocator] >";
+   return ViewType::getSerializationType();
 }
 
 template< typename Real,
@@ -108,6 +105,7 @@ setDimensions( const IndexType rows,
    this->segments.setSegmentsSizes( rows, columns );
    this->values.setSize( rows * columns );
    this->values = 0.0;
+   this->view = this->getView();
 }
 
 template< typename Real,
@@ -145,19 +143,7 @@ void
 Dense< Real, Device, Index, RowMajorOrder, RealAllocator >::
 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 );
+   this->view.getCompressedRowLengths( rowLengths );
 }
 
 template< typename Real,
@@ -197,11 +183,7 @@ template< typename Real,
           typename RealAllocator >
 Index Dense< Real, Device, Index, RowMajorOrder, RealAllocator >::getNumberOfNonzeroMatrixElements() const
 {
-   const auto values_view = this->values.getConstView();
-   auto fetch = [=] __cuda_callable__ ( const IndexType i ) -> IndexType {
-      return ( values_view[ i ] != 0.0 );
-   };
-   return Algorithms::Reduction< DeviceType >::reduce( this->values.getSize(), std::plus<>{}, fetch, 0 );
+   return this->view.getNumberOfNonzeroMatrixElements();
 }
 
 template< typename Real,
@@ -221,7 +203,7 @@ template< typename Real,
           typename RealAllocator >
 void Dense< Real, Device, Index, RowMajorOrder, RealAllocator >::setValue( const Real& value )
 {
-   this->values = value;
+   this->view.setValue( value );
 }
 
 template< typename Real,
@@ -233,8 +215,7 @@ __cuda_callable__ auto
 Dense< Real, Device, Index, RowMajorOrder, RealAllocator >::
 getRow( const IndexType& rowIdx ) const -> const RowView
 {
-   TNL_ASSERT_LT( rowIdx, this->getRows(), "Row index is larger than number of matrix rows." );
-   return RowView( this->segments.getSegmentView( rowIdx ), this->values.getView() );
+   return this->view.getRow( rowIdx );
 }
 
 template< typename Real,
@@ -246,8 +227,7 @@ __cuda_callable__ auto
 Dense< Real, Device, Index, RowMajorOrder, RealAllocator >::
 getRow( const IndexType& rowIdx ) -> RowView
 {
-   TNL_ASSERT_LT( rowIdx, this->getRows(), "Row index is larger than number of matrix rows." );
-   return RowView( this->segments.getSegmentView( rowIdx ), this->values.getView() );
+   return this->view.getRow( rowIdx );
 }
 
 template< typename Real,
@@ -259,12 +239,7 @@ __cuda_callable__
 Real& Dense< Real, Device, Index, RowMajorOrder, RealAllocator >::operator()( const IndexType row,
                                                 const IndexType column )
 {
-   TNL_ASSERT_GE( row, 0, "Row index must be non-negative." );
-   TNL_ASSERT_LT( row, this->getRows(), "Row index is out of bounds." );
-   TNL_ASSERT_GE( column, 0, "Column index must be non-negative." );
-   TNL_ASSERT_LT( column, this->getColumns(), "Column index is out of bounds." );
-
-   return this->values.operator[]( this->getElementIndex( row, column ) );
+   return this->view.operator()( row, column );
 }
 
 template< typename Real,
@@ -276,12 +251,7 @@ __cuda_callable__
 const Real& Dense< Real, Device, Index, RowMajorOrder, RealAllocator >::operator()( const IndexType row,
                                                       const IndexType column ) const
 {
-   TNL_ASSERT_GE( row, 0, "Row index must be non-negative." );
-   TNL_ASSERT_LT( row, this->getRows(), "Row index is out of bounds." );
-   TNL_ASSERT_GE( column, 0, "Column index must be non-negative." );
-   TNL_ASSERT_LT( column, this->getColumns(), "Column index is out of bounds." );
-
-   return this->values.operator[]( this->getElementIndex( row, column ) );
+   return this->view.operator()( row, column );
 }
 
 template< typename Real,
@@ -295,7 +265,7 @@ setElement( const IndexType row,
             const IndexType column,
             const RealType& value )
 {
-   this->values.setElement( this->getElementIndex( row, column ), value );
+   this->view.setElement( row, column, value );
 }
 
 template< typename Real,
@@ -310,13 +280,7 @@ addElement( const IndexType row,
             const RealType& value,
             const RealType& thisElementMultiplicator )
 {
-   const IndexType elementIndex = this->getElementIndex( row, column );
-   if( thisElementMultiplicator == 1.0 )
-      this->values.setElement( elementIndex,
-                               this->values.getElement( elementIndex ) + value );
-   else
-      this->values.setElement( elementIndex,
-                               thisElementMultiplicator * this->values.getElement( elementIndex ) + value );
+   this->view.addElement( row, column, value, thisElementMultiplicator );
 }
 
 template< typename Real,
@@ -329,7 +293,7 @@ Dense< Real, Device, Index, RowMajorOrder, RealAllocator >::
 getElement( const IndexType row,
             const IndexType column ) const
 {
-   return this->values.getElement( this->getElementIndex( row, column ) );
+   return this->view.getElement( row, column );
 }
 
 template< typename Real,
@@ -342,12 +306,7 @@ void
 Dense< Real, Device, Index, RowMajorOrder, RealAllocator >::
 rowsReduction( IndexType first, IndexType last, Fetch& fetch, Reduce& reduce, Keep& keep, const FetchValue& zero ) const
 {
-   const auto values_view = this->values.getConstView();
-   auto fetch_ = [=] __cuda_callable__ ( IndexType rowIdx, IndexType columnIdx, IndexType globalIdx, bool& compute ) mutable -> decltype( fetch( IndexType(), IndexType(), RealType() ) ) {
-         return fetch( rowIdx, columnIdx, values_view[ globalIdx ] );
-      return zero;
-   };
-   this->segments.segmentsReduction( first, last, fetch_, reduce, keep, zero );
+   this->view.rowsReduction( first, last, fetch, reduce, keep, zero );
 }
 
 template< typename Real,
@@ -373,12 +332,7 @@ void
 Dense< Real, Device, Index, RowMajorOrder, RealAllocator >::
 forRows( IndexType first, IndexType last, Function& function ) const
 {
-   const auto values_view = this->values.getConstView();
-   auto f = [=] __cuda_callable__ ( IndexType rowIdx, IndexType columnIdx, IndexType globalIdx ) mutable -> bool {
-      function( rowIdx, columnIdx, globalIdx, values_view[ globalIdx ] );
-      return true;
-   };
-   this->segments.forSegments( first, last, f );
+   this->view.forRows( first, last, function );
 }
 
 template< typename Real,
@@ -391,12 +345,7 @@ void
 Dense< Real, Device, Index, RowMajorOrder, RealAllocator >::
 forRows( IndexType first, IndexType last, Function& function )
 {
-   auto values_view = this->values.getView();
-   auto f = [=] __cuda_callable__ ( IndexType rowIdx, IndexType columnIdx, IndexType globalIdx ) mutable -> bool {
-      function( rowIdx, columnIdx, globalIdx, values_view[ globalIdx ] );
-      return true;
-   };
-   this->segments.forSegments( first, last, f );
+   this->view.forRows( first, last, function );
 }
 
 template< typename Real,
@@ -435,11 +384,7 @@ __cuda_callable__
 typename Vector::RealType Dense< Real, Device, Index, RowMajorOrder, RealAllocator >::rowVectorProduct( const IndexType row,
                                                                                    const Vector& vector ) const
 {
-   RealType sum( 0.0 );
-   // TODO: Fix this
-   //for( IndexType column = 0; column < this->getColumns(); column++ )
-   //   sum += this->getElementFast( row, column ) * vector[ column ];
-   return sum;
+   return this->view.rowVectorProduct( row, vector );
 }
 
 template< typename Real,
@@ -453,27 +398,7 @@ void
 Dense< Real, Device, Index, RowMajorOrder, RealAllocator >::
 vectorProduct( const InVector& inVector, OutVector& outVector ) const
 {
-   TNL_ASSERT( this->getColumns() == inVector.getSize(),
-            std::cerr << "Matrix columns: " << this->getColumns() << std::endl
-                 << "Vector size: " << inVector.getSize() << std::endl );
-   TNL_ASSERT( this->getRows() == outVector.getSize(),
-               std::cerr << "Matrix rows: " << this->getRows() << std::endl
-                    << "Vector size: " << outVector.getSize() << std::endl );
-
-   //DeviceDependentCode::vectorProduct( *this, inVector, outVector );
-   const auto inVectorView = inVector.getConstView();
-   auto outVectorView = outVector.getView();
-   const auto valuesView = this->values.getConstView();
-   auto fetch = [=] __cuda_callable__ ( IndexType row, IndexType column, IndexType offset, bool& compute ) -> RealType {
-      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 );
+   this->view.vectorProduct( inVector, outVector );
 }
 
 template< typename Real,
@@ -959,7 +884,7 @@ void Dense< Real, Device, Index, RowMajorOrder, RealAllocator >::performSORItera
    x[ row ] = ( 1.0 - omega ) * x[ row ] + omega / diagonalValue * ( b[ row ] - sum );
 }
 
-/*template< typename Real,
+template< typename Real,
           typename Device,
           typename Index,
           bool RowMajorOrder,
@@ -968,7 +893,9 @@ Dense< Real, Device, Index, RowMajorOrder, RealAllocator >&
 Dense< Real, Device, Index, RowMajorOrder, RealAllocator >::
 operator=( const Dense< Real, Device, Index, RowMajorOrder, RealAllocator >& matrix )
 {
-   const IndexType bufferRowsCount( 128 );
+   setLike( matrix );
+   this->values = matrix.values;
+   /*const IndexType bufferRowsCount( 128 );
    const IndexType columns = this->getColumns();
    const size_t bufferSize = bufferRowsCount * columns;
    Containers::Vector< RealType, Device, IndexType, RealAllocatorType > sourceValuesBuffer( bufferSize );
@@ -1000,8 +927,8 @@ operator=( const Dense< Real, Device, Index, RowMajorOrder, RealAllocator >& mat
       this->forRows( baseRow, lastRow, f2 );
       baseRow += bufferRowsCount;
    }
-   return *this;
-}*/
+   return *this;*/
+}
 
 template< typename Real,
           typename Device,
@@ -1101,7 +1028,7 @@ template< typename Real,
           typename RealAllocator >
 void Dense< Real, Device, Index, RowMajorOrder, RealAllocator >::save( const String& fileName ) const
 {
-   Object::save( fileName );
+   this->view.save( fileName );
 }
 
 template< typename Real,
@@ -1121,7 +1048,7 @@ template< typename Real,
           typename RealAllocator >
 void Dense< Real, Device, Index, RowMajorOrder, RealAllocator >::save( File& file ) const
 {
-   Matrix< Real, Device, Index >::save( file );
+   this->view.save( file );
 }
 
 template< typename Real,
@@ -1141,13 +1068,7 @@ template< typename Real,
           typename RealAllocator >
 void Dense< Real, Device, Index, RowMajorOrder, RealAllocator >::print( std::ostream& str ) const
 {
-   for( IndexType row = 0; row < this->getRows(); row++ )
-   {
-      str <<"Row: " << row << " -> ";
-      for( IndexType column = 0; column < this->getColumns(); column++ )
-         str << " Col:" << column << "->" << this->getElement( row, column ) << "\t";
-      str << std::endl;
-   }
+   this->view.print( str );
 }
 
 template< typename Real,
@@ -1156,8 +1077,9 @@ template< typename Real,
           bool RowMajorOrder,
           typename RealAllocator >
 __cuda_callable__
-Index Dense< Real, Device, Index, RowMajorOrder, RealAllocator >::getElementIndex( const IndexType row,
-                                                              const IndexType column ) const
+Index
+Dense< Real, Device, Index, RowMajorOrder, RealAllocator >::
+getElementIndex( const IndexType row, const IndexType column ) const
 {
    return this->segments.getGlobalIndex( row, column );
 }
diff --git a/src/TNL/Matrices/DenseMatrixView.h b/src/TNL/Matrices/DenseMatrixView.h
index 9bad424b2a..d963dd7c3e 100644
--- a/src/TNL/Matrices/DenseMatrixView.h
+++ b/src/TNL/Matrices/DenseMatrixView.h
@@ -171,22 +171,12 @@ class DenseMatrixView : public MatrixView< Real, Device, Index >
                                 Vector2& x,
                                 const RealType& omega = 1.0 ) const;
 
-      // copy assignment
       DenseMatrixView& operator=( const DenseMatrixView& matrix );
 
-      // cross-device copy assignment
-      template< typename Real2, typename Device2, typename Index2,
-                typename = typename Enabler< Device2 >::type >
-      DenseMatrixView& operator=( const DenseMatrixView< Real2, Device2, Index2 >& matrix );
-
       void save( const String& fileName ) const;
 
-      void load( const String& fileName );
-
       void save( File& file ) const;
 
-      void load( File& file );
-
       void print( std::ostream& str ) const;
 
    protected:
diff --git a/src/TNL/Matrices/DenseMatrixView.hpp b/src/TNL/Matrices/DenseMatrixView.hpp
index 21f6d79ef5..527915d55f 100644
--- a/src/TNL/Matrices/DenseMatrixView.hpp
+++ b/src/TNL/Matrices/DenseMatrixView.hpp
@@ -83,7 +83,7 @@ getSerializationType()
 {
    return String( "Matrices::Dense< " ) +
           TNL::getSerializationType< RealType >() + ", [any_device], " +
-          TNL::getSerializationType< IndexType >() +
+          TNL::getSerializationType< IndexType >() + ", " +
           ( RowMajorOrder ? "true" : "false" ) + ", [any_allocator] >";
 }
 
@@ -321,7 +321,7 @@ forRows( IndexType first, IndexType last, Function& function ) const
 {
    const auto values_view = this->values.getConstView();
    auto f = [=] __cuda_callable__ ( IndexType rowIdx, IndexType columnIdx, IndexType globalIdx ) mutable -> bool {
-      function( rowIdx, columnIdx, values_view[ globalIdx ] );
+      function( rowIdx, columnIdx, columnIdx, values_view[ globalIdx ] );
       return true;
    };
    this->segments.forSegments( first, last, f );
@@ -339,7 +339,7 @@ forRows( IndexType first, IndexType last, Function& function )
 {
    auto values_view = this->values.getView();
    auto f = [=] __cuda_callable__ ( IndexType rowIdx, IndexType columnIdx, IndexType globalIdx ) mutable -> bool {
-      function( rowIdx, columnIdx, values_view[ globalIdx ] );
+      function( rowIdx, columnIdx, globalIdx, values_view[ globalIdx ] );
       return true;
    };
    this->segments.forSegments( first, last, f );
@@ -395,14 +395,22 @@ template< typename Real,
 void DenseMatrixView< Real, Device, Index, RowMajorOrder >::vectorProduct( const InVector& inVector,
                                                            OutVector& outVector ) const
 {
-   TNL_ASSERT( this->getColumns() == inVector.getSize(),
-            std::cerr << "Matrix columns: " << this->getColumns() << std::endl
-                 << "Vector size: " << inVector.getSize() << std::endl );
-   TNL_ASSERT( this->getRows() == outVector.getSize(),
-               std::cerr << "Matrix rows: " << this->getRows() << std::endl
-                    << "Vector size: " << outVector.getSize() << std::endl );
-
-   //DeviceDependentCode::vectorProduct( *this, inVector, outVector );
+   TNL_ASSERT_EQ( this->getColumns(), inVector.getSize(), "Matrix columns count differs with input vector size." );
+   TNL_ASSERT_EQ( this->getRows(), outVector.getSize(), "Matrix rows count differs with output vector size." );
+
+   const auto inVectorView = inVector.getConstView();
+   auto outVectorView = outVector.getView();
+   const auto valuesView = this->values.getConstView();
+   auto fetch = [=] __cuda_callable__ ( IndexType row, IndexType column, IndexType offset, bool& compute ) -> RealType {
+      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,
@@ -885,39 +893,18 @@ void DenseMatrixView< Real, Device, Index, RowMajorOrder >::performSORIteration(
 }
 
 
-// copy assignment
 template< typename Real,
           typename Device,
           typename Index,
           bool RowMajorOrder >
 DenseMatrixView< Real, Device, Index, RowMajorOrder >&
-DenseMatrixView< Real, Device, Index, RowMajorOrder >::operator=( const DenseMatrixView& matrix )
-{
-   this->setLike( matrix );
-   this->values = matrix.values;
-   return *this;
-}
-
-// cross-device copy assignment
-template< typename Real,
-          typename Device,
-          typename Index,
-          bool RowMajorOrder >
-   template< typename Real2, typename Device2, typename Index2, typename >
-DenseMatrixView< Real, Device, Index, RowMajorOrder >&
-DenseMatrixView< Real, Device, Index, RowMajorOrder >::operator=( const DenseMatrixView< Real2, Device2, Index2 >& matrix )
+DenseMatrixView< Real, Device, Index, RowMajorOrder >::
+operator=( const DenseMatrixView& matrix )
 {
-   static_assert( std::is_same< Device, Devices::Host >::value || std::is_same< Device, Devices::Cuda >::value,
-                  "unknown device" );
-   static_assert( std::is_same< Device2, Devices::Host >::value || std::is_same< Device2, Devices::Cuda >::value,
-                  "unknown device" );
-
-   this->setLike( matrix );
-
-   throw Exceptions::NotImplementedError("Cross-device assignment for the Dense format is not implemented yet.");
+   MatrixView< Real, Device, Index >::operator=( matrix );
+   this->segments = matrix.segments;
 }
 
-
 template< typename Real,
           typename Device,
           typename Index,
@@ -927,15 +914,6 @@ void DenseMatrixView< Real, Device, Index, RowMajorOrder >::save( const String&
    Object::save( fileName );
 }
 
-template< typename Real,
-          typename Device,
-          typename Index,
-          bool RowMajorOrder >
-void DenseMatrixView< Real, Device, Index, RowMajorOrder >::load( const String& fileName )
-{
-   Object::load( fileName );
-}
-
 template< typename Real,
           typename Device,
           typename Index,
@@ -945,15 +923,6 @@ void DenseMatrixView< Real, Device, Index, RowMajorOrder >::save( File& file ) c
    MatrixView< Real, Device, Index >::save( file );
 }
 
-template< typename Real,
-          typename Device,
-          typename Index,
-          bool RowMajorOrder >
-void DenseMatrixView< Real, Device, Index, RowMajorOrder >::load( File& file )
-{
-   MatrixView< Real, Device, Index >::load( file );
-}
-
 template< typename Real,
           typename Device,
           typename Index,
diff --git a/src/UnitTests/Matrices/DenseMatrixTest.h b/src/UnitTests/Matrices/DenseMatrixTest.h
index 0f71580100..a3e7e8f61e 100644
--- a/src/UnitTests/Matrices/DenseMatrixTest.h
+++ b/src/UnitTests/Matrices/DenseMatrixTest.h
@@ -1234,9 +1234,7 @@ void test_SaveAndLoad()
 
     ASSERT_NO_THROW( savedMatrix.save( TEST_FILE_NAME ) );
 
-    Matrix loadedMatrix;
-    loadedMatrix.reset();
-    loadedMatrix.setDimensions( rows, cols );
+    Matrix loadedMatrix( rows, cols );
 
     ASSERT_NO_THROW( loadedMatrix.load( TEST_FILE_NAME ) );
 
-- 
GitLab