Newer
Older
/***************************************************************************
Array_impl.h - description
-------------------
begin : Nov 8, 2012
copyright : (C) 2012 by Tomas Oberhuber
email : tomas.oberhuber@fjfi.cvut.cz
***************************************************************************/
/* See Copyright Notice in tnl/Copyright */
#include <TNL/Assert.h>
#include <TNL/File.h>
#include <TNL/Math.h>
#include <TNL/param-types.h>
Jakub Klinkovský
committed
#include <TNL/Containers/Algorithms/ArrayOperations.h>
#include <TNL/Containers/Algorithms/ArrayIO.h>
#include <TNL/Exceptions/ArrayWrongSize.h>
template< typename Value,
typename Device,
typename Index >
Array< Value, Device, Index >::
: size( 0 ),
data( 0 ),
allocationPointer( 0 ),
referenceCounter( 0 )
template< typename Value,
typename Device,
typename Index >
Array< Value, Device, Index >::
Array( const IndexType& size )
: size( 0 ),
data( 0 ),
allocationPointer( 0 ),
referenceCounter( 0 )
{
this->setSize( size );
}
template< typename Value,
typename Device,
typename Index >
Array< Value, Device, Index >::
Array( Value* data,
: size( size ),
data( data ),
allocationPointer( 0 ),
referenceCounter( 0 )
template< typename Value,
typename Device,
typename Index >
Array< Value, Device, Index >::
Array( Array< Value, Device, Index >& array,
const IndexType& begin,
const IndexType& size )
: size( size ),
data( &array.getData()[ begin ] ),
allocationPointer( array.allocationPointer ),
referenceCounter( 0 )
{
TNL_ASSERT_TRUE( array.getData(), "Empty arrays cannot be bound." );
TNL_ASSERT_LT( begin, array.getSize(), "Begin of array is out of bounds." );
TNL_ASSERT_LE( begin + size, array.getSize(), "End of array is out of bounds." );
if( ! this->size )
this->size = array.getSize() - begin;
if( array.allocationPointer )
{
if( array.referenceCounter )
{
this->referenceCounter = array.referenceCounter;
this->referenceCounter = array.referenceCounter = new int( 2 );
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
template< typename Value,
typename Device,
typename Index >
Array< Value, Device, Index >::
Array( const std::initializer_list< Value >& list )
: size( 0 ),
data( 0 ),
allocationPointer( 0 ),
referenceCounter( 0 )
{
this->setSize( list.size() );
}
template< typename Value,
typename Device,
typename Index >
Array< Value, Device, Index >::
Array( const std::list< Value >& list )
: size( 0 ),
data( 0 ),
allocationPointer( 0 ),
referenceCounter( 0 )
{
this->setSize( list.size() );
}
template< typename Value,
typename Device,
typename Index >
Array< Value, Device, Index >::
Array( const std::vector< Value >& vector )
: size( 0 ),
data( 0 ),
allocationPointer( 0 ),
referenceCounter( 0 )
{
this->setSize( vector.size() );
}
template< typename Value,
typename Device,
typename Index >
Array< Value, Device, Index >::
return String( "Containers::Array< " ) +
TNL::getType< Value >() + ", " +
Device::getDeviceType() + ", " +
TNL::getType< Index >() + " >";
template< typename Value,
typename Device,
typename Index >
Array< Value, Device, Index >::
{
return this->getType();
template< typename Value,
typename Device,
typename Index >
Array< Value, Device, Index >::
{
return HostType::getType();
template< typename Value,
typename Device,
typename Index >
Array< Value, Device, Index >::
getSerializationTypeVirtual() const
{
return this->getSerializationType();
template< typename Value,
typename Device,
typename Index >
Array< Value, Device, Index >::
releaseData() const
{
if( this->referenceCounter )
{
if( --*this->referenceCounter == 0 )
{
Jakub Klinkovský
committed
Algorithms::ArrayOperations< Device >::freeMemory( this->allocationPointer );
delete this->referenceCounter;
//std::cerr << "Deallocating reference counter " << this->referenceCounter << std::endl;
Jakub Klinkovský
committed
Algorithms::ArrayOperations< Device >::freeMemory( this->allocationPointer );
this->allocationPointer = 0;
this->data = 0;
this->size = 0;
this->referenceCounter = 0;
}
template< typename Value,
typename Device,
typename Index >
Jakub Klinkovský
committed
void
Array< Value, Device, Index >::
Jakub Klinkovský
committed
TNL_ASSERT_GE( size, (Index) 0, "Array size must be non-negative." );
Jakub Klinkovský
committed
if( this->size == size && allocationPointer && ! referenceCounter )
return;
// Allocating zero bytes is useless. Moreover, the allocators don't behave the same way:
// "operator new" returns some non-zero address, the latter returns a null pointer.
if( size > 0 ) {
Algorithms::ArrayOperations< Device >::allocateMemory( this->allocationPointer, size );
this->data = this->allocationPointer;
this->size = size;
TNL_ASSERT_TRUE( this->allocationPointer,
"This should never happen - allocator did not throw on an error." );
Jakub Klinkovský
committed
}
template< typename Value,
typename Device,
typename Index >
__cuda_callable__
Index
Array< Value, Device, Index >::
getSize() const
{
return this -> size;
}
template< typename Value,
typename Device,
typename Index >
template< typename ArrayT >
Jakub Klinkovský
committed
void
Array< Value, Device, Index >::
setLike( const ArrayT& array )
Jakub Klinkovský
committed
setSize( array.getSize() );
}
template< typename Value,
typename Device,
typename Index >
Array< Value, Device, Index >::
bind( Value* data,
TNL_ASSERT_TRUE( data, "Null pointer cannot be bound." );
this->releaseData();
this->data = data;
template< typename Value,
typename Device,
typename Index >
template< typename ArrayT >
Array< Value, Device, Index >::
bind( const ArrayT& array,
const IndexType& begin,
const IndexType& size )
{
// all template parameters of Array must match, otherwise binding does not make sense
static_assert( std::is_same< Value, typename ArrayT::ValueType >::value, "ValueType of both arrays must be the same." );
static_assert( std::is_same< Device, typename ArrayT::DeviceType >::value, "DeviceType of both arrays must be the same." );
static_assert( std::is_same< Index, typename ArrayT::IndexType >::value, "IndexType of both arrays must be the same." );
TNL_ASSERT_TRUE( array.getData(), "Empty array cannot be bound." );
TNL_ASSERT_LT( begin, array.getSize(), "Begin of array is out of bounds." );
TNL_ASSERT_LE( begin + size, array.getSize(), "End of array is out of bounds." );
this->releaseData();
if( size )
this->size = size;
else
this->size = array.getSize() - begin;
this->data = const_cast< Value* >( &array.getData()[ begin ] );
this->allocationPointer = array.allocationPointer;
if( array.allocationPointer )
{
if( array.referenceCounter )
{
this->referenceCounter = array.referenceCounter;
this->referenceCounter = array.referenceCounter = new int( 2 );
//std::cerr << "Allocating reference counter " << this->referenceCounter << std::endl;
template< typename Value,
typename Device,
typename Index >
template< int Size >
void
Array< Value, Device, Index >::
bind( StaticArray< Size, Value >& array )
{
this->releaseData();
this->size = Size;
this->data = array.getData();
}
template< typename Value,
typename Device,
typename Index >
Array< Value, Device, Index >::
swap( Array< Value, Device, Index >& array )
TNL::swap( this->size, array.size );
TNL::swap( this->data, array.data );
TNL::swap( this->allocationPointer, array.allocationPointer );
TNL::swap( this->referenceCounter, array.referenceCounter );
Jakub Klinkovský
committed
}
template< typename Value,
typename Device,
typename Index >
Array< Value, Device, Index >::
Jakub Klinkovský
committed
}
template< typename Value,
typename Device,
typename Index >
__cuda_callable__
const Value* Array< Value, Device, Index >::getData() const
return this->data;
Jakub Klinkovský
committed
}
template< typename Value,
typename Device,
typename Index >
__cuda_callable__
Value* Array< Value, Device, Index >::getData()
return this->data;
Jakub Klinkovský
committed
}
template< typename Value,
Tomáš Oberhuber
committed
typename Device,
typename Index >
Array< Value, Device, Index >::
setElement( const Index& i, const Value& x )
Tomáš Oberhuber
committed
{
Jakub Klinkovský
committed
TNL_ASSERT_GE( i, (Index) 0, "Element index must be non-negative." );
TNL_ASSERT_LT( i, this->getSize(), "Element index is out of bounds." );
return Algorithms::ArrayOperations< Device >::setMemoryElement( &( this->data[ i ] ), x );
template< typename Value,
typename Device,
typename Index >
Array< Value, Device, Index >::
getElement( const Index& i ) const
Jakub Klinkovský
committed
TNL_ASSERT_GE( i, (Index) 0, "Element index must be non-negative." );
TNL_ASSERT_LT( i, this->getSize(), "Element index is out of bounds." );
return Algorithms::ArrayOperations< Device >::getMemoryElement( & ( this->data[ i ] ) );
Tomáš Oberhuber
committed
}
template< typename Value,
typename Device,
typename Index >
inline Value&
Array< Value, Device, Index >::
operator[] ( const Index& i )
Jakub Klinkovský
committed
TNL_ASSERT_GE( i, (Index) 0, "Element index must be non-negative." );
TNL_ASSERT_LT( i, this->getSize(), "Element index is out of bounds." );
return this->data[ i ];
Jakub Klinkovský
committed
}
template< typename Value,
typename Device,
typename Index >
inline const Value&
Array< Value, Device, Index >::
operator[] ( const Index& i ) const
Jakub Klinkovský
committed
TNL_ASSERT_GE( i, (Index) 0, "Element index must be non-negative." );
TNL_ASSERT_LT( i, this->getSize(), "Element index is out of bounds." );
return this->data[ i ];
Jakub Klinkovský
committed
}
template< typename Value,
typename Device,
typename Index >
Array< Value, Device, Index >&
Array< Value, Device, Index >::
operator = ( const Array< Value, Device, Index >& array )
//TNL_ASSERT_EQ( array.getSize(), this->getSize(), "Array sizes must be the same." );
if( this->getSize() != array.getSize() )
this->setLike( array );
if( this->getSize() > 0 )
Algorithms::ArrayOperations< Device >::
copyMemory( this->getData(),
array.getData(),
array.getSize() );
Jakub Klinkovský
committed
}
template< typename Value,
typename Device,
typename Index >
template< typename ArrayT >
Array< Value, Device, Index >&
Array< Value, Device, Index >::
operator = ( const ArrayT& array )
//TNL_ASSERT_EQ( array.getSize(), this->getSize(), "Array sizes must be the same." );
if( this->getSize() != array.getSize() )
this->setLike( array );
if( this->getSize() > 0 )
Algorithms::ArrayOperations< Device, typename ArrayT::DeviceType >::
copyMemory( this->getData(),
array.getData(),
array.getSize() );
Jakub Klinkovský
committed
}
template< typename Value,
typename Device,
typename Index >
template< typename ArrayT >
Array< Value, Device, Index >::
operator == ( const ArrayT& array ) const
if( this->getSize() == 0 )
return true;
Jakub Klinkovský
committed
return Algorithms::ArrayOperations< Device, typename ArrayT::DeviceType >::
compareMemory( this->getData(),
array.getData(),
array.getSize() );
template< typename Value,
typename Device,
typename Index >
template< typename ArrayT >
bool Array< Value, Device, Index >::operator != ( const ArrayT& array ) const
{
return ! ( ( *this ) == array );
}
template< typename Value,
void Array< Value, Device, Index >::setValue( const Value& e,
const Index begin,
const Index end )
TNL_ASSERT_TRUE( this->getData(), "Attempted to set a value of an empty array." );
Algorithms::ArrayOperations< Device >::setMemory( &this->getData()[ begin ], e, end - begin );
}
template< typename Value,
typename Device,
typename Index >
template< typename Function >
void Array< Value, Device, Index >::setValues( Function& f,
const Index begin,
const Index end )
{
TNL_ASSERT_TRUE( this->getData(), "Attempted to set a value of an empty array." );
auto evaluate = [=] __cuda_callable__ ( Index i )
{
this->data[ i ] = f( i );
}
ParallelFor< DeviceType >( begin, end, evaluate );
template< typename Value,
typename Device,
typename Index >
bool
Array< Value, Device, Index >::
containsValue( const Value& v,
const Index begin,
const Index end ) const
return Algorithms::ArrayOperations< Device >::containsValue( &this->getData()[ begin ], end - begin, v );
template< typename Value,
typename Device,
typename Index >
bool
Array< Value, Device, Index >::
containsOnlyValue( const Value& v,
const Index begin,
const Index end ) const
return Algorithms::ArrayOperations< Device >::containsOnlyValue( &this->getData()[ begin ], end - begin, v );
template< typename Value,
typename Device,
typename Index >
Array< Value, Device, Index >::operator bool() const
{
return data != 0;
Jakub Klinkovský
committed
}
template< typename Value,
typename Device,
typename Index >
void Array< Value, Device, Index >::save( File& file ) const
file.save( &this->size );
if( this->size != 0 )
Algorithms::ArrayIO< Value, Device, Index >::save( file, this->data, this->size );
Jakub Klinkovský
committed
}
template< typename Value,
typename Device,
typename Index >
Array< Value, Device, Index >::
file.load( &_size );
throw Exceptions::ArrayWrongSize( _size, "positive" );
Algorithms::ArrayIO< Value, Device, Index >::load( file, this->data, this->size );
template< typename Value,
typename Device,
typename Index >
Array< Value, Device, Index >::
boundLoad( File& file )
Index _size;
file.load( &_size );
if( _size < 0 )
throw Exceptions::ArrayWrongSize( _size, "Positive is expected," );
if( this->getSize() != 0 )
{
if( this->getSize() != _size )
throw Exceptions::ArrayWrongSize( _size, convertToString( this->getSize() ) + " is expected." );
}
else setSize( _size );
if( _size )
Algorithms::ArrayIO< Value, Device, Index >::load( file, this->data, this->size );

Vít Hanousek
committed
template< typename Value,
Array< Value, Device, Index >::
template< typename Value, typename Device, typename Index >
std::ostream& operator << ( std::ostream& str, const Array< 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 );