// SPDX-FileComment: This file is part of TNL - Template Numerical Library (https://tnl-project.org/)
// SPDX-License-Identifier: MIT

#pragma once

#include <TNL/Matrices/DenseMatrixRowView.h>

namespace TNL::Matrices {

template< typename SegmentView, typename ValuesView >
__cuda_callable__
DenseMatrixRowView< SegmentView, ValuesView >::DenseMatrixRowView( SegmentViewType segmentView, ValuesViewType values )
: segmentView( std::move( segmentView ) ),
  values( std::move( values ) )
{}

template< typename SegmentView, typename ValuesView >
__cuda_callable__
auto
DenseMatrixRowView< SegmentView, ValuesView >::getSize() const -> IndexType
{
   return segmentView.getSize();
}

template< typename SegmentView, typename ValuesView >
__cuda_callable__
auto
DenseMatrixRowView< SegmentView, ValuesView >::getRowIndex() const -> IndexType
{
   return segmentView.getSegmentIndex();
}

template< typename SegmentView, typename ValuesView >
__cuda_callable__
auto
DenseMatrixRowView< SegmentView, ValuesView >::getValue( const IndexType column ) const -> const RealType&
{
   TNL_ASSERT_LT( column, this->getSize(), "Column index exceeds matrix row size." );
   return values[ segmentView.getGlobalIndex( column ) ];
}

template< typename SegmentView, typename ValuesView >
__cuda_callable__
auto
DenseMatrixRowView< SegmentView, ValuesView >::getValue( const IndexType column ) -> RealType&
{
   TNL_ASSERT_LT( column, this->getSize(), "Column index exceeds matrix row size." );
   return values[ segmentView.getGlobalIndex( column ) ];
}

template< typename SegmentView, typename ValuesView >
__cuda_callable__
auto
DenseMatrixRowView< SegmentView, ValuesView >::getColumnIndex( const IndexType localIdx ) const -> IndexType
{
   TNL_ASSERT_LT( localIdx, this->getSize(), "Column index exceeds matrix row size." );
   return localIdx;
}

template< typename SegmentView, typename ValuesView >
__cuda_callable__
void
DenseMatrixRowView< SegmentView, ValuesView >::setValue( const IndexType column, const RealType& value )
{
   TNL_ASSERT_LT( column, this->getSize(), "Column index exceeds matrix row size." );
   const IndexType globalIdx = segmentView.getGlobalIndex( column );
   values[ globalIdx ] = value;
}

template< typename SegmentView, typename ValuesView >
__cuda_callable__
void
DenseMatrixRowView< SegmentView, ValuesView >::setElement( const IndexType localIdx,
                                                           const IndexType column,
                                                           const RealType& value )
{
   TNL_ASSERT_LT( column, this->getSize(), "Column index exceeds matrix row size." );
   const IndexType globalIdx = segmentView.getGlobalIndex( column );
   values[ globalIdx ] = value;
}

template< typename SegmentView, typename ValuesView >
__cuda_callable__
auto
DenseMatrixRowView< SegmentView, ValuesView >::begin() -> IteratorType
{
   return { *this, 0 };
}

template< typename SegmentView, typename ValuesView >
__cuda_callable__
auto
DenseMatrixRowView< SegmentView, ValuesView >::end() -> IteratorType
{
   return { *this, this->getSize() };
}

template< typename SegmentView, typename ValuesView >
__cuda_callable__
auto
DenseMatrixRowView< SegmentView, ValuesView >::cbegin() const -> ConstIteratorType
{
   return { *this, 0 };
}

template< typename SegmentView, typename ValuesView >
__cuda_callable__
auto
DenseMatrixRowView< SegmentView, ValuesView >::cend() const -> ConstIteratorType
{
   return { *this, this->getSize() };
}

}  // namespace TNL::Matrices
