From 0f2800df822320840b136bcacb1a23f000c09aaa Mon Sep 17 00:00:00 2001 From: Tomas Oberhuber <tomas.oberhuber@fjfi.cvut.cz> Date: Tue, 9 Apr 2019 19:52:54 +0200 Subject: [PATCH] [WIP] Restoring renamed ArrayView.hpp. --- src/TNL/Containers/ArrayView.hpp | 460 +++++++++++++++++++++++++++++++ 1 file changed, 460 insertions(+) create mode 100644 src/TNL/Containers/ArrayView.hpp diff --git a/src/TNL/Containers/ArrayView.hpp b/src/TNL/Containers/ArrayView.hpp new file mode 100644 index 0000000000..ad89dd7b61 --- /dev/null +++ b/src/TNL/Containers/ArrayView.hpp @@ -0,0 +1,460 @@ +/*************************************************************************** + ArrayView_impl.h - description + ------------------- + begin : Sep 1, 2018 + copyright : (C) 2018 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +#pragma once + +#include <iostream> + +#include <TNL/param-types.h> +#include <TNL/Containers/Algorithms/ArrayOperations.h> + +#include "ArrayView.h" + +namespace TNL { +namespace Containers { + +template< typename Value, + typename Device, + typename Index > +String +ArrayView< Value, Device, Index >:: +getType() +{ + return String( "Containers::ArrayView< " ) + ", " + + TNL::getType< Value >() + ", " + + Device::getDeviceType() + ", " + + TNL::getType< Index >() + " >"; +} + +// explicit initialization by raw data pointer and size +template< typename Value, + typename Device, + typename Index > +__cuda_callable__ +ArrayView< Value, Device, Index >:: +ArrayView( Value* data, Index size ) : data(data), size(size) +{ + TNL_ASSERT_GE( size, 0, "ArrayView size was initialized with a negative size." ); + TNL_ASSERT_TRUE( (data == nullptr && size == 0) || (data != nullptr && size > 0), + "ArrayView was initialized with a positive address and zero size or zero address and positive size." ); +} + +// initialization from other array containers (using shallow copy) +template< typename Value, + typename Device, + typename Index > + template< typename Value_ > +__cuda_callable__ +ArrayView< Value, Device, Index >:: +ArrayView( Array< Value_, Device, Index >& array ) +{ + this->bind( array.getData(), array.getSize() ); +} + +template< typename Value, + typename Device, + typename Index > + template< int Size, typename Value_ > +__cuda_callable__ +ArrayView< Value, Device, Index >:: +ArrayView( StaticArray< Size, Value_ >& array ) +{ + this->bind( array.getData(), Size ); +} + +template< typename Value, + typename Device, + typename Index > + template< typename Value_ > +__cuda_callable__ +ArrayView< Value, Device, Index >:: +ArrayView( const Array< Value_, Device, Index >& array ) +{ + this->bind( array.getData(), array.getSize() ); +} + +template< typename Value, + typename Device, + typename Index > + template< int Size, typename Value_ > +__cuda_callable__ +ArrayView< Value, Device, Index >:: +ArrayView( const StaticArray< Size, Value_ >& array ) +{ + this->bind( array.getData(), Size ); +} + +// methods for rebinding (reinitialization) +template< typename Value, + typename Device, + typename Index > +__cuda_callable__ +void +ArrayView< Value, Device, Index >:: +bind( Value* data, Index size ) +{ + TNL_ASSERT_GE( size, 0, "ArrayView size was initialized with a negative size." ); + TNL_ASSERT_TRUE( (data == nullptr && size == 0) || (data != nullptr && size > 0), + "ArrayView was initialized with a positive address and zero size or zero address and positive size." ); + + this->data = data; + this->size = size; +} + +template< typename Value, + typename Device, + typename Index > +__cuda_callable__ +void ArrayView< Value, Device, Index >::bind( ArrayView view ) +{ + bind( view.getData(), view.getSize() ); +} + +// Copy-assignment does deep copy, just like regular array, but the sizes +// must match (i.e. copy-assignment cannot resize). +template< typename Value, + typename Device, + typename Index > +ArrayView< Value, Device, Index >& +ArrayView< Value, Device, Index >:: +operator=( const ArrayView& view ) +{ + TNL_ASSERT_EQ( getSize(), view.getSize(), "The sizes of the array views must be equal, views are not resizable." ); + if( getSize() > 0 ) + Algorithms::ArrayOperations< Device >::copyMemory( getData(), view.getData(), getSize() ); + return *this; +} + +template< typename Value, + typename Device, + typename Index > + template< typename T > +ArrayView< Value, Device, Index >& +ArrayView< Value, Device, Index >:: +operator = ( const T& data ) +{ + Algorithms::ArrayAssignment< ThisType, T >::assign( *this, data ); + return *this; +} + +template< typename Value, + typename Device, + typename Index > +__cuda_callable__ +void +ArrayView< Value, Device, Index >:: +swap( ArrayView& array ) +{ + TNL::swap( data, array.data ); + TNL::swap( size, array.size ); +} + +template< typename Value, + typename Device, + typename Index > +__cuda_callable__ +void +ArrayView< Value, Device, Index >:: +reset() +{ + data = nullptr; + size = 0; +} + +template< typename Value, + typename Device, + typename Index > +__cuda_callable__ +const +Value* ArrayView< Value, Device, Index >:: +getData() const +{ + return data; +} + +template< typename Value, + typename Device, + typename Index > +__cuda_callable__ +Value* +ArrayView< Value, Device, Index >:: +getData() +{ + return data; +} + +template< typename Value, + typename Device, + typename Index > +__cuda_callable__ +const +Value* ArrayView< Value, Device, Index >:: +getArrayData() const +{ + return data; +} + +template< typename Value, + typename Device, + typename Index > +__cuda_callable__ +Value* +ArrayView< Value, Device, Index >:: +getArrayData() +{ + return data; +} + +template< typename Value, + typename Device, + typename Index > +__cuda_callable__ +Index +ArrayView< Value, Device, Index >:: +getSize() const +{ + return size; +} + +template< typename Value, + typename Device, + typename Index > +void +ArrayView< Value, Device, Index >:: +setElement( Index i, Value value ) +{ + TNL_ASSERT_GE( i, 0, "Element index must be non-negative." ); + TNL_ASSERT_LT( i, this->getSize(), "Element index is out of bounds." ); + return Algorithms::ArrayOperations< Device >::setMemoryElement( &data[ i ], value ); +} + +template< typename Value, + typename Device, + typename Index > +Value +ArrayView< Value, Device, Index >:: +getElement( Index i ) const +{ + TNL_ASSERT_GE( i, 0, "Element index must be non-negative." ); + TNL_ASSERT_LT( i, this->getSize(), "Element index is out of bounds." ); + return Algorithms::ArrayOperations< Device >::getMemoryElement( &data[ i ] ); +} + +template< typename Value, + typename Device, + typename Index > +__cuda_callable__ +Value& ArrayView< Value, Device, Index >:: +operator[]( Index i ) +{ + TNL_ASSERT_GE( i, 0, "Element index must be non-negative." ); + TNL_ASSERT_LT( i, this->getSize(), "Element index is out of bounds." ); + return data[ i ]; +} + +template< typename Value, + typename Device, + typename Index > +__cuda_callable__ +const +Value& ArrayView< Value, Device, Index >:: +operator[]( Index i ) const +{ + TNL_ASSERT_GE( i, 0, "Element index must be non-negative." ); + TNL_ASSERT_LT( i, this->getSize(), "Element index is out of bounds." ); + return data[ i ]; +} + +template< typename Value, + typename Device, + typename Index > + template< typename Value_, typename Device_, typename Index_ > +bool +ArrayView< Value, Device, Index >:: +operator==( const ArrayView< Value_, Device_, Index_ >& view ) const +{ + if( view.getSize() != getSize() ) + return false; + if( getSize() == 0 ) + return true; + return Algorithms::ArrayOperations< Device, Device_ >::compareMemory( getData(), view.getData(), getSize() ); +} + +template< typename Value_, + typename Device_, + typename Index_ > + template< typename ArrayT > +bool +ArrayView< Value_, Device_, Index_ >:: +operator == ( const ArrayT& array ) const +{ + if( array.getSize() != this->getSize() ) + return false; + if( this->getSize() == 0 ) + return true; + return Algorithms::ArrayOperations< DeviceType, typename ArrayT::DeviceType >:: + compareMemory( this->getData(), + array.getData(), + array.getSize() ); +} + +template< typename Value, + typename Device, + typename Index > + template< typename Value_, typename Device_, typename Index_ > +bool +ArrayView< Value, Device, Index >:: +operator!=( const ArrayView< Value_, Device_, Index_ >& view ) const +{ + return ! ( *this == view ); +} + +template< typename Value_, + typename Device_, + typename Index_ > + template< typename ArrayT > +bool +ArrayView< Value_, Device_, Index_ >:: +operator != ( const ArrayT& array ) const +{ + return ! ( *this == array ); +} + +template< typename Value, + typename Device, + typename Index > +void +ArrayView< Value, Device, Index >:: +setValue( Value value ) +{ + TNL_ASSERT_GT( size, 0, "Attempted to set value to an empty array view." ); + Algorithms::ArrayOperations< Device >::setMemory( getData(), value, getSize() ); +} + +template< typename Value, + typename Device, + typename Index > + template< typename Function > +void ArrayView< Value, Device, Index >:: +evaluate( Function& f, const Index begin, Index end ) +{ + TNL_ASSERT_TRUE( this->getData(), "Attempted to set a value of an empty array view." ); + + ValueType* d = this->data; + auto eval = [=] __cuda_callable__ ( Index i ) + { + d[ i ] = f( i ); + }; + + if( end == -1 ) + end = this->getSize(); + + ParallelFor< DeviceType >::exec( begin, end, eval ); +} + +template< typename Value, + typename Device, + typename Index > +bool +ArrayView< Value, Device, Index >:: +containsValue( Value value ) const +{ + return Algorithms::ArrayOperations< Device >::containsValue( data, size, value ); +} + +template< typename Value, + typename Device, + typename Index > +bool +ArrayView< Value, Device, Index >:: +containsOnlyValue( Value value ) const +{ + return Algorithms::ArrayOperations< Device >::containsOnlyValue( data, size, value ); +} + +template< typename Value, + typename Device, + typename Index > +bool +ArrayView< Value, Device, Index >:: +empty() const +{ + return data; +} + +template< typename Value, + typename Device, + typename Index > +void ArrayView< Value, Device, Index >::save( File& file ) const +{ + saveHeader( file, SerializationType::getType() ); + file.save( &this->size ); + if( this->size != 0 ) + Algorithms::ArrayIO< Value, Device, Index >::save( file, this->data, this->size ); +} + +template< typename Value, + typename Device, + typename Index > +void +ArrayView< Value, Device, Index >:: +load( File& file ) +{ + String type; + loadHeader( file, type ); + if( type != SerializationType::getType() ) + throw Exceptions::ObjectTypeMismatch( SerializationType::getType(), type ); + Index _size; + file.load( &_size ); + if( _size != this->getSize() ) + throw Exceptions::ArrayWrongSize( _size, convertToString( this->getSize() ) ); + Algorithms::ArrayIO< Value, Device, Index >::load( file, this->data, this->size ); +} + +template< typename Value, + typename Device, + typename Index > +void +ArrayView< Value, Device, Index >:: +save( const String& fileName ) const +{ + File file; + file.open( fileName, File::Mode::Out ); + this->save( file ); +} + +template< typename Value, + typename Device, + typename Index > +void +ArrayView< Value, Device, Index >:: +load( const String& fileName ) +{ + File file; + file.open( fileName, File::Mode::In ); + this->load( file ); +} + +template< typename Value, typename Device, typename Index > +std::ostream& operator<<( std::ostream& str, const ArrayView< Value, Device, Index >& v ) +{ + str << "[ "; + if( v.getSize() > 0 ) + { + str << v.getElement( 0 ); + for( Index i = 1; i < v.getSize(); i++ ) + str << ", " << v.getElement( i ); + } + str << " ]"; + return str; +} + +} // namespace Containers +} // namespace TNL -- GitLab