Newer
Older
/***************************************************************************
ArrayOperationsHost_impl.h - description
-------------------
begin : Jul 16, 2013
copyright : (C) 2013 by Tomas Oberhuber
email : tomas.oberhuber@fjfi.cvut.cz
***************************************************************************/
/* See Copyright Notice in tnl/Copyright */
#pragma once
#include <type_traits>
#include <string.h>
Jakub Klinkovský
committed
#include <TNL/Containers/Algorithms/ArrayOperations.h>
Tomáš Oberhuber
committed
#include <TNL/Containers/Algorithms/Reduction.h>
#include <TNL/Containers/Algorithms/ReductionOperations.h>
Jakub Klinkovský
committed
Jakub Klinkovský
committed
namespace Algorithms {
static constexpr int OpenMPArrayOperationsThreshold = 512; // TODO: check this threshold
template< typename Element, typename Index >
ArrayOperations< Devices::Host >::
allocateMemory( Element*& data,
const Index size )
data = new Element[ size ];
// According to the standard, new either throws, or returns non-nullptr.
// Some (old) compilers don't comply:
// https://stackoverflow.com/questions/550451/will-new-return-null-in-any-case
TNL_ASSERT_TRUE( data, "Operator 'new' returned a nullptr. This should never happen - there is "
"either a bug or the compiler does not comply to the standard." );
}
template< typename Element >
ArrayOperations< Devices::Host >::
freeMemory( Element* data )
{
delete[] data;
}
template< typename Element >
void
ArrayOperations< Devices::Host >::
setMemoryElement( Element* data,
const Element& value )
Jakub Klinkovský
committed
}
template< typename Element >
Element
ArrayOperations< Devices::Host >::
Jakub Klinkovský
committed
getMemoryElement( const Element* data )
Jakub Klinkovský
committed
}
template< typename Element, typename Index >
Jakub Klinkovský
committed
void
ArrayOperations< Devices::Host >::
setMemory( Element* data,
const Element& value,
const Index size )
#ifdef HAVE_OPENMP
#pragma omp parallel for if( Devices::Host::isOMPEnabled() && size > OpenMPArrayOperationsThreshold )
#endif
for( Index i = 0; i < size; i++ )
data[ i ] = value;
}
template< typename DestinationElement,
typename SourceElement,
typename Index >
Jakub Klinkovský
committed
void
ArrayOperations< Devices::Host >::
copyMemory( DestinationElement* destination,
const SourceElement* source,
const Index size )
if( std::is_same< DestinationElement, SourceElement >::value &&
( std::is_fundamental< DestinationElement >::value ||
std::is_pointer< DestinationElement >::value ) )
{
// GCC 8.1 complains that we bypass a non-trivial copy-constructor
// (in C++17 we could use constexpr if to avoid compiling this branch in that case)
#if defined(__GNUC__) && ( __GNUC__ > 8 || ( __GNUC__ == 8 && __GNUC_MINOR__ > 0 ) ) && !defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wclass-memaccess"
#endif
memcpy( destination, source, size * sizeof( DestinationElement ) );
#if defined(__GNUC__) && !defined(__clang__) && !defined(__NVCC__)
#pragma GCC diagnostic pop
#endif
}
#ifdef HAVE_OPENMP
#pragma omp parallel for if( Devices::Host::isOMPEnabled() && size > OpenMPArrayOperationsThreshold )
#endif
for( Index i = 0; i < size; i++ )
destination[ i ] = source[ i ];
template< typename DestinationElement,
typename SourceElement >
Tomáš Oberhuber
committed
void
ArrayOperations< Devices::Host >::
Tomáš Oberhuber
committed
copySTLList( DestinationElement* destination,
const std::list< SourceElement >& source )
Tomáš Oberhuber
committed
for( const SourceElement& e : source )
template< typename DestinationElement,
typename SourceElement,
typename Index >
bool
ArrayOperations< Devices::Host >::
compareMemory( const DestinationElement* destination,
const SourceElement* source,
const Index size )
Tomáš Oberhuber
committed
TNL_ASSERT_TRUE( destination, "Attempted to compare data through a nullptr." );
TNL_ASSERT_TRUE( source, "Attempted to compare data through a nullptr." );
if( std::is_same< DestinationElement, SourceElement >::value &&
( std::is_fundamental< DestinationElement >::value ||
std::is_pointer< DestinationElement >::value ) )
{
if( memcmp( destination, source, size * sizeof( DestinationElement ) ) != 0 )
return false;
}
else
if( ! ( destination[ i ] == source[ i ] ) )
return false;
return true;
}
Tomáš Oberhuber
committed
template< typename Element,
typename Index >
bool
ArrayOperations< Devices::Host >::
containsValue( const Element* data,
const Index size,
const Element& value )
{
TNL_ASSERT_TRUE( data, "Attempted to check data through a nullptr." );
TNL_ASSERT_GE( size, 0, "" );
if( data[ i ] == value )
return true;
return false;
Tomáš Oberhuber
committed
template< typename Element,
typename Index >
bool
ArrayOperations< Devices::Host >::
containsOnlyValue( const Element* data,
const Index size,
const Element& value )
Tomáš Oberhuber
committed
{
TNL_ASSERT_TRUE( data, "Attempted to check data through a nullptr." );
TNL_ASSERT_GE( size, 0, "" );
Tomáš Oberhuber
committed
if( size == 0 ) return false;
if( ! ( data[ i ] == value ) )
return false;
return true;
Tomáš Oberhuber
committed
}
Jakub Klinkovský
committed
} // namespace Algorithms