Page MenuHomec4science

Kokkos_ViewMapping.hpp
No OneTemporary

File Metadata

Created
Sat, Aug 10, 20:01

Kokkos_ViewMapping.hpp

/*
//@HEADER
// ************************************************************************
//
// Kokkos v. 2.0
// Copyright (2014) Sandia Corporation
//
// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
// the U.S. Government retains certain rights in this software.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// 3. Neither the name of the Corporation nor the names of the
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Questions? Contact H. Carter Edwards (hcedwar@sandia.gov)
//
// ************************************************************************
//@HEADER
*/
#ifndef KOKKOS_EXPERIMENTAL_VIEW_MAPPING_HPP
#define KOKKOS_EXPERIMENTAL_VIEW_MAPPING_HPP
#include <type_traits>
#include <initializer_list>
#include <Kokkos_Core_fwd.hpp>
#include <Kokkos_Pair.hpp>
#include <Kokkos_Layout.hpp>
#include <impl/Kokkos_Error.hpp>
#include <impl/Kokkos_Traits.hpp>
#include <impl/Kokkos_ViewCtor.hpp>
#include <impl/Kokkos_Atomic_View.hpp>
#if defined(KOKKOS_ENABLE_PROFILING)
#include <impl/Kokkos_Profiling_Interface.hpp>
#endif
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
namespace Kokkos {
namespace Impl {
template< unsigned I , size_t ... Args >
struct variadic_size_t
{ enum { value = ~size_t(0) }; };
template< size_t Val , size_t ... Args >
struct variadic_size_t< 0 , Val , Args ... >
{ enum { value = Val }; };
template< unsigned I , size_t Val , size_t ... Args >
struct variadic_size_t< I , Val , Args ... >
{ enum { value = variadic_size_t< I - 1 , Args ... >::value }; };
template< size_t ... Args >
struct rank_dynamic ;
template<>
struct rank_dynamic<> { enum { value = 0 }; };
template< size_t Val , size_t ... Args >
struct rank_dynamic< Val , Args... >
{
enum { value = ( Val == 0 ? 1 : 0 ) + rank_dynamic< Args... >::value };
};
#define KOKKOS_IMPL_VIEW_DIMENSION( R ) \
template< size_t V , unsigned > struct ViewDimension ## R \
{ \
enum { ArgN ## R = ( V != ~size_t(0) ? V : 1 ) }; \
enum { N ## R = ( V != ~size_t(0) ? V : 1 ) }; \
KOKKOS_INLINE_FUNCTION explicit ViewDimension ## R ( size_t ) {} \
ViewDimension ## R () = default ; \
ViewDimension ## R ( const ViewDimension ## R & ) = default ; \
ViewDimension ## R & operator = ( const ViewDimension ## R & ) = default ; \
}; \
template< unsigned RD > struct ViewDimension ## R < 0 , RD > \
{ \
enum { ArgN ## R = 0 }; \
typename std::conditional<( RD < 3 ), size_t , unsigned >::type N ## R ; \
ViewDimension ## R () = default ; \
ViewDimension ## R ( const ViewDimension ## R & ) = default ; \
ViewDimension ## R & operator = ( const ViewDimension ## R & ) = default ; \
KOKKOS_INLINE_FUNCTION explicit ViewDimension ## R ( size_t V ) : N ## R ( V ) {} \
};
KOKKOS_IMPL_VIEW_DIMENSION( 0 )
KOKKOS_IMPL_VIEW_DIMENSION( 1 )
KOKKOS_IMPL_VIEW_DIMENSION( 2 )
KOKKOS_IMPL_VIEW_DIMENSION( 3 )
KOKKOS_IMPL_VIEW_DIMENSION( 4 )
KOKKOS_IMPL_VIEW_DIMENSION( 5 )
KOKKOS_IMPL_VIEW_DIMENSION( 6 )
KOKKOS_IMPL_VIEW_DIMENSION( 7 )
#undef KOKKOS_IMPL_VIEW_DIMENSION
template< size_t ... Vals >
struct ViewDimension
: public ViewDimension0< variadic_size_t<0,Vals...>::value
, rank_dynamic< Vals... >::value >
, public ViewDimension1< variadic_size_t<1,Vals...>::value
, rank_dynamic< Vals... >::value >
, public ViewDimension2< variadic_size_t<2,Vals...>::value
, rank_dynamic< Vals... >::value >
, public ViewDimension3< variadic_size_t<3,Vals...>::value
, rank_dynamic< Vals... >::value >
, public ViewDimension4< variadic_size_t<4,Vals...>::value
, rank_dynamic< Vals... >::value >
, public ViewDimension5< variadic_size_t<5,Vals...>::value
, rank_dynamic< Vals... >::value >
, public ViewDimension6< variadic_size_t<6,Vals...>::value
, rank_dynamic< Vals... >::value >
, public ViewDimension7< variadic_size_t<7,Vals...>::value
, rank_dynamic< Vals... >::value >
{
typedef ViewDimension0< variadic_size_t<0,Vals...>::value
, rank_dynamic< Vals... >::value > D0 ;
typedef ViewDimension1< variadic_size_t<1,Vals...>::value
, rank_dynamic< Vals... >::value > D1 ;
typedef ViewDimension2< variadic_size_t<2,Vals...>::value
, rank_dynamic< Vals... >::value > D2 ;
typedef ViewDimension3< variadic_size_t<3,Vals...>::value
, rank_dynamic< Vals... >::value > D3 ;
typedef ViewDimension4< variadic_size_t<4,Vals...>::value
, rank_dynamic< Vals... >::value > D4 ;
typedef ViewDimension5< variadic_size_t<5,Vals...>::value
, rank_dynamic< Vals... >::value > D5 ;
typedef ViewDimension6< variadic_size_t<6,Vals...>::value
, rank_dynamic< Vals... >::value > D6 ;
typedef ViewDimension7< variadic_size_t<7,Vals...>::value
, rank_dynamic< Vals... >::value > D7 ;
using D0::ArgN0 ;
using D1::ArgN1 ;
using D2::ArgN2 ;
using D3::ArgN3 ;
using D4::ArgN4 ;
using D5::ArgN5 ;
using D6::ArgN6 ;
using D7::ArgN7 ;
using D0::N0 ;
using D1::N1 ;
using D2::N2 ;
using D3::N3 ;
using D4::N4 ;
using D5::N5 ;
using D6::N6 ;
using D7::N7 ;
enum { rank = sizeof...(Vals) };
enum { rank_dynamic = Impl::rank_dynamic< Vals... >::value };
ViewDimension() = default ;
ViewDimension( const ViewDimension & ) = default ;
ViewDimension & operator = ( const ViewDimension & ) = default ;
KOKKOS_INLINE_FUNCTION
constexpr
ViewDimension( size_t n0 , size_t n1 , size_t n2 , size_t n3
, size_t n4 , size_t n5 , size_t n6 , size_t n7 )
: D0( n0 )
, D1( n1 )
, D2( n2 )
, D3( n3 )
, D4( n4 )
, D5( n5 )
, D6( n6 )
, D7( n7 )
{}
KOKKOS_INLINE_FUNCTION
constexpr size_t extent( const unsigned r ) const
{
return r == 0 ? N0 : (
r == 1 ? N1 : (
r == 2 ? N2 : (
r == 3 ? N3 : (
r == 4 ? N4 : (
r == 5 ? N5 : (
r == 6 ? N6 : (
r == 7 ? N7 : 0 )))))));
}
template< size_t N >
struct prepend { typedef ViewDimension< N , Vals... > type ; };
template< size_t N >
struct append { typedef ViewDimension< Vals... , N > type ; };
};
template< class A , class B >
struct ViewDimensionJoin ;
template< size_t ... A , size_t ... B >
struct ViewDimensionJoin< ViewDimension< A... > , ViewDimension< B... > > {
typedef ViewDimension< A... , B... > type ;
};
//----------------------------------------------------------------------------
template< class DstDim , class SrcDim >
struct ViewDimensionAssignable ;
template< size_t ... DstArgs , size_t ... SrcArgs >
struct ViewDimensionAssignable< ViewDimension< DstArgs ... >
, ViewDimension< SrcArgs ... > >
{
typedef ViewDimension< DstArgs... > dst ;
typedef ViewDimension< SrcArgs... > src ;
enum { value =
unsigned(dst::rank) == unsigned(src::rank) && (
//Compile time check that potential static dimensions match
( ( 1 > dst::rank_dynamic && 1 > src::rank_dynamic ) ? (size_t(dst::ArgN0) == size_t(src::ArgN0)) : true ) &&
( ( 2 > dst::rank_dynamic && 2 > src::rank_dynamic ) ? (size_t(dst::ArgN1) == size_t(src::ArgN1)) : true ) &&
( ( 3 > dst::rank_dynamic && 3 > src::rank_dynamic ) ? (size_t(dst::ArgN2) == size_t(src::ArgN2)) : true ) &&
( ( 4 > dst::rank_dynamic && 4 > src::rank_dynamic ) ? (size_t(dst::ArgN3) == size_t(src::ArgN3)) : true ) &&
( ( 5 > dst::rank_dynamic && 5 > src::rank_dynamic ) ? (size_t(dst::ArgN4) == size_t(src::ArgN4)) : true ) &&
( ( 6 > dst::rank_dynamic && 6 > src::rank_dynamic ) ? (size_t(dst::ArgN5) == size_t(src::ArgN5)) : true ) &&
( ( 7 > dst::rank_dynamic && 7 > src::rank_dynamic ) ? (size_t(dst::ArgN6) == size_t(src::ArgN6)) : true ) &&
( ( 8 > dst::rank_dynamic && 8 > src::rank_dynamic ) ? (size_t(dst::ArgN7) == size_t(src::ArgN7)) : true )
)};
};
}} // namespace Kokkos::Impl
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
namespace Kokkos {
namespace Impl {
struct ALL_t {
KOKKOS_INLINE_FUNCTION
constexpr const ALL_t & operator()() const { return *this ; }
};
}} // namespace Kokkos::Impl
namespace Kokkos {
namespace Impl {
template< class T >
struct is_integral_extent_type
{ enum { value = std::is_same<T,Kokkos::Impl::ALL_t>::value ? 1 : 0 }; };
template< class iType >
struct is_integral_extent_type< std::pair<iType,iType> >
{ enum { value = std::is_integral<iType>::value ? 1 : 0 }; };
template< class iType >
struct is_integral_extent_type< Kokkos::pair<iType,iType> >
{ enum { value = std::is_integral<iType>::value ? 1 : 0 }; };
// Assuming '2 == initializer_list<iType>::size()'
template< class iType >
struct is_integral_extent_type< std::initializer_list<iType> >
{ enum { value = std::is_integral<iType>::value ? 1 : 0 }; };
template < unsigned I , class ... Args >
struct is_integral_extent
{
// get_type is void when sizeof...(Args) <= I
typedef typename std::remove_cv<
typename std::remove_reference<
typename Kokkos::Impl::get_type<I,Args...
>::type >::type >::type type ;
enum { value = is_integral_extent_type<type>::value };
static_assert( value ||
std::is_integral<type>::value ||
std::is_same<type,void>::value
, "subview argument must be either integral or integral extent" );
};
// Rules for subview arguments and layouts matching
template<class LayoutDest, class LayoutSrc, int RankDest, int RankSrc, int CurrentArg, class ... SubViewArgs>
struct SubviewLegalArgsCompileTime;
// Rules which allow LayoutLeft to LayoutLeft assignment
template<int RankDest, int RankSrc, int CurrentArg, class Arg, class ... SubViewArgs>
struct SubviewLegalArgsCompileTime<Kokkos::LayoutLeft, Kokkos::LayoutLeft, RankDest, RankSrc, CurrentArg, Arg, SubViewArgs...> {
enum { value =(((CurrentArg==RankDest-1) && (Kokkos::Impl::is_integral_extent_type<Arg>::value)) ||
((CurrentArg>=RankDest) && (std::is_integral<Arg>::value)) ||
((CurrentArg<RankDest) && (std::is_same<Arg,Kokkos::Impl::ALL_t>::value)) ||
((CurrentArg==0) && (Kokkos::Impl::is_integral_extent_type<Arg>::value))
) && (SubviewLegalArgsCompileTime<Kokkos::LayoutLeft, Kokkos::LayoutLeft, RankDest, RankSrc, CurrentArg+1, SubViewArgs...>::value)};
};
template<int RankDest, int RankSrc, int CurrentArg, class Arg>
struct SubviewLegalArgsCompileTime<Kokkos::LayoutLeft, Kokkos::LayoutLeft, RankDest, RankSrc, CurrentArg, Arg> {
enum { value = ((CurrentArg==RankDest-1) || (std::is_integral<Arg>::value)) &&
(CurrentArg==RankSrc-1) };
};
// Rules which allow LayoutRight to LayoutRight assignment
template<int RankDest, int RankSrc, int CurrentArg, class Arg, class ... SubViewArgs>
struct SubviewLegalArgsCompileTime<Kokkos::LayoutRight, Kokkos::LayoutRight, RankDest, RankSrc, CurrentArg, Arg, SubViewArgs...> {
enum { value =(((CurrentArg==RankSrc-RankDest) && (Kokkos::Impl::is_integral_extent_type<Arg>::value)) ||
((CurrentArg<RankSrc-RankDest) && (std::is_integral<Arg>::value)) ||
((CurrentArg>=RankSrc-RankDest) && (std::is_same<Arg,Kokkos::Impl::ALL_t>::value))
) && (SubviewLegalArgsCompileTime<Kokkos::LayoutRight, Kokkos::LayoutRight, RankDest, RankSrc, CurrentArg+1, SubViewArgs...>::value)};
};
template<int RankDest, int RankSrc, int CurrentArg, class Arg>
struct SubviewLegalArgsCompileTime<Kokkos::LayoutRight, Kokkos::LayoutRight, RankDest, RankSrc, CurrentArg, Arg> {
enum { value = ((CurrentArg==RankSrc-1) && (std::is_same<Arg,Kokkos::Impl::ALL_t>::value)) };
};
// Rules which allow assignment to LayoutStride
template<int RankDest, int RankSrc, int CurrentArg, class ... SubViewArgs>
struct SubviewLegalArgsCompileTime<Kokkos::LayoutStride,Kokkos::LayoutLeft,RankDest,RankSrc,CurrentArg,SubViewArgs...> {
enum { value = true };
};
template<int RankDest, int RankSrc, int CurrentArg, class ... SubViewArgs>
struct SubviewLegalArgsCompileTime<Kokkos::LayoutStride,Kokkos::LayoutRight,RankDest,RankSrc,CurrentArg,SubViewArgs...> {
enum { value = true };
};
template<int RankDest, int RankSrc, int CurrentArg, class ... SubViewArgs>
struct SubviewLegalArgsCompileTime<Kokkos::LayoutStride,Kokkos::LayoutStride,RankDest,RankSrc,CurrentArg,SubViewArgs...> {
enum { value = true };
};
template< unsigned DomainRank , unsigned RangeRank >
struct SubviewExtents {
private:
// Cannot declare zero-length arrays
enum { InternalRangeRank = RangeRank ? RangeRank : 1u };
size_t m_begin[ DomainRank ];
size_t m_length[ InternalRangeRank ];
unsigned m_index[ InternalRangeRank ];
template< size_t ... DimArgs >
KOKKOS_FORCEINLINE_FUNCTION
bool set( unsigned domain_rank
, unsigned range_rank
, const ViewDimension< DimArgs ... > & dim )
{ return true ; }
template< class T , size_t ... DimArgs , class ... Args >
KOKKOS_FORCEINLINE_FUNCTION
bool set( unsigned domain_rank
, unsigned range_rank
, const ViewDimension< DimArgs ... > & dim
, const T & val
, Args ... args )
{
const size_t v = static_cast<size_t>(val);
m_begin[ domain_rank ] = v ;
return set( domain_rank + 1 , range_rank , dim , args... )
#if defined( KOKKOS_ENABLE_DEBUG_BOUNDS_CHECK )
&& ( v < dim.extent( domain_rank ) )
#endif
;
}
// ALL_t
template< size_t ... DimArgs , class ... Args >
KOKKOS_FORCEINLINE_FUNCTION
bool set( unsigned domain_rank
, unsigned range_rank
, const ViewDimension< DimArgs ... > & dim
, const Kokkos::Impl::ALL_t
, Args ... args )
{
m_begin[ domain_rank ] = 0 ;
m_length[ range_rank ] = dim.extent( domain_rank );
m_index[ range_rank ] = domain_rank ;
return set( domain_rank + 1 , range_rank + 1 , dim , args... );
}
// std::pair range
template< class T , size_t ... DimArgs , class ... Args >
KOKKOS_FORCEINLINE_FUNCTION
bool set( unsigned domain_rank
, unsigned range_rank
, const ViewDimension< DimArgs ... > & dim
, const std::pair<T,T> & val
, Args ... args )
{
const size_t b = static_cast<size_t>( val.first );
const size_t e = static_cast<size_t>( val.second );
m_begin[ domain_rank ] = b ;
m_length[ range_rank ] = e - b ;
m_index[ range_rank ] = domain_rank ;
return set( domain_rank + 1 , range_rank + 1 , dim , args... )
#if defined( KOKKOS_ENABLE_DEBUG_BOUNDS_CHECK )
&& ( e <= b + dim.extent( domain_rank ) )
#endif
;
}
// Kokkos::pair range
template< class T , size_t ... DimArgs , class ... Args >
KOKKOS_FORCEINLINE_FUNCTION
bool set( unsigned domain_rank
, unsigned range_rank
, const ViewDimension< DimArgs ... > & dim
, const Kokkos::pair<T,T> & val
, Args ... args )
{
const size_t b = static_cast<size_t>( val.first );
const size_t e = static_cast<size_t>( val.second );
m_begin[ domain_rank ] = b ;
m_length[ range_rank ] = e - b ;
m_index[ range_rank ] = domain_rank ;
return set( domain_rank + 1 , range_rank + 1 , dim , args... )
#if defined( KOKKOS_ENABLE_DEBUG_BOUNDS_CHECK )
&& ( e <= b + dim.extent( domain_rank ) )
#endif
;
}
// { begin , end } range
template< class T , size_t ... DimArgs , class ... Args >
KOKKOS_FORCEINLINE_FUNCTION
bool set( unsigned domain_rank
, unsigned range_rank
, const ViewDimension< DimArgs ... > & dim
, const std::initializer_list< T > & val
, Args ... args )
{
const size_t b = static_cast<size_t>( val.begin()[0] );
const size_t e = static_cast<size_t>( val.begin()[1] );
m_begin[ domain_rank ] = b ;
m_length[ range_rank ] = e - b ;
m_index[ range_rank ] = domain_rank ;
return set( domain_rank + 1 , range_rank + 1 , dim , args... )
#if defined( KOKKOS_ENABLE_DEBUG_BOUNDS_CHECK )
&& ( val.size() == 2 )
&& ( e <= b + dim.extent( domain_rank ) )
#endif
;
}
//------------------------------
#if defined( KOKKOS_ENABLE_DEBUG_BOUNDS_CHECK )
template< size_t ... DimArgs >
void error( char *
, int
, unsigned
, unsigned
, const ViewDimension< DimArgs ... > & ) const
{}
template< class T , size_t ... DimArgs , class ... Args >
void error( char * buf , int buf_len
, unsigned domain_rank
, unsigned range_rank
, const ViewDimension< DimArgs ... > & dim
, const T & val
, Args ... args ) const
{
const int n = std::min( buf_len ,
snprintf( buf , buf_len
, " %lu < %lu %c"
, static_cast<unsigned long>(val)
, static_cast<unsigned long>( dim.extent( domain_rank ) )
, int( sizeof...(Args) ? ',' : ')' ) ) );
error( buf+n, buf_len-n, domain_rank + 1 , range_rank , dim , args... );
}
// std::pair range
template< size_t ... DimArgs , class ... Args >
void error( char * buf , int buf_len
, unsigned domain_rank
, unsigned range_rank
, const ViewDimension< DimArgs ... > & dim
, const Kokkos::Impl::ALL_t
, Args ... args ) const
{
const int n = std::min( buf_len ,
snprintf( buf , buf_len
, " Kokkos::ALL %c"
, int( sizeof...(Args) ? ',' : ')' ) ) );
error( buf+n , buf_len-n , domain_rank + 1 , range_rank + 1 , dim , args... );
}
// std::pair range
template< class T , size_t ... DimArgs , class ... Args >
void error( char * buf , int buf_len
, unsigned domain_rank
, unsigned range_rank
, const ViewDimension< DimArgs ... > & dim
, const std::pair<T,T> & val
, Args ... args ) const
{
// d <= e - b
const int n = std::min( buf_len ,
snprintf( buf , buf_len
, " %lu <= %lu - %lu %c"
, static_cast<unsigned long>( dim.extent( domain_rank ) )
, static_cast<unsigned long>( val.second )
, static_cast<unsigned long>( val.first )
, int( sizeof...(Args) ? ',' : ')' ) ) );
error( buf+n , buf_len-n , domain_rank + 1 , range_rank + 1 , dim , args... );
}
// Kokkos::pair range
template< class T , size_t ... DimArgs , class ... Args >
void error( char * buf , int buf_len
, unsigned domain_rank
, unsigned range_rank
, const ViewDimension< DimArgs ... > & dim
, const Kokkos::pair<T,T> & val
, Args ... args ) const
{
// d <= e - b
const int n = std::min( buf_len ,
snprintf( buf , buf_len
, " %lu <= %lu - %lu %c"
, static_cast<unsigned long>( dim.extent( domain_rank ) )
, static_cast<unsigned long>( val.second )
, static_cast<unsigned long>( val.first )
, int( sizeof...(Args) ? ',' : ')' ) ) );
error( buf+n , buf_len-n , domain_rank + 1 , range_rank + 1 , dim , args... );
}
// { begin , end } range
template< class T , size_t ... DimArgs , class ... Args >
void error( char * buf , int buf_len
, unsigned domain_rank
, unsigned range_rank
, const ViewDimension< DimArgs ... > & dim
, const std::initializer_list< T > & val
, Args ... args ) const
{
// d <= e - b
int n = 0 ;
if ( val.size() == 2 ) {
n = std::min( buf_len ,
snprintf( buf , buf_len
, " %lu <= %lu - %lu %c"
, static_cast<unsigned long>( dim.extent( domain_rank ) )
, static_cast<unsigned long>( val.begin()[0] )
, static_cast<unsigned long>( val.begin()[1] )
, int( sizeof...(Args) ? ',' : ')' ) ) );
}
else {
n = std::min( buf_len ,
snprintf( buf , buf_len
, " { ... }.size() == %u %c"
, unsigned(val.size())
, int( sizeof...(Args) ? ',' : ')' ) ) );
}
error( buf+n , buf_len-n , domain_rank + 1 , range_rank + 1 , dim , args... );
}
template< size_t ... DimArgs , class ... Args >
KOKKOS_FORCEINLINE_FUNCTION
void error( const ViewDimension< DimArgs ... > & dim , Args ... args ) const
{
#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
enum { LEN = 1024 };
char buffer[ LEN ];
const int n = snprintf(buffer,LEN,"Kokkos::subview bounds error (");
error( buffer+n , LEN-n , 0 , 0 , dim , args... );
Kokkos::Impl::throw_runtime_exception(std::string(buffer));
#else
Kokkos::abort("Kokkos::subview bounds error");
#endif
}
#else
template< size_t ... DimArgs , class ... Args >
KOKKOS_FORCEINLINE_FUNCTION
void error( const ViewDimension< DimArgs ... > & , Args ... ) const {}
#endif
public:
template< size_t ... DimArgs , class ... Args >
KOKKOS_INLINE_FUNCTION
SubviewExtents( const ViewDimension< DimArgs ... > & dim , Args ... args )
{
static_assert( DomainRank == sizeof...(DimArgs) , "" );
static_assert( DomainRank == sizeof...(Args) , "" );
// Verifies that all arguments, up to 8, are integral types,
// integral extents, or don't exist.
static_assert( RangeRank ==
unsigned( is_integral_extent<0,Args...>::value ) +
unsigned( is_integral_extent<1,Args...>::value ) +
unsigned( is_integral_extent<2,Args...>::value ) +
unsigned( is_integral_extent<3,Args...>::value ) +
unsigned( is_integral_extent<4,Args...>::value ) +
unsigned( is_integral_extent<5,Args...>::value ) +
unsigned( is_integral_extent<6,Args...>::value ) +
unsigned( is_integral_extent<7,Args...>::value ) , "" );
if ( RangeRank == 0 ) { m_length[0] = 0 ; m_index[0] = ~0u ; }
if ( ! set( 0 , 0 , dim , args... ) ) error( dim , args... );
}
template < typename iType >
KOKKOS_FORCEINLINE_FUNCTION
constexpr size_t domain_offset( const iType i ) const
{ return unsigned(i) < DomainRank ? m_begin[i] : 0 ; }
template < typename iType >
KOKKOS_FORCEINLINE_FUNCTION
constexpr size_t range_extent( const iType i ) const
{ return unsigned(i) < InternalRangeRank ? m_length[i] : 0 ; }
template < typename iType >
KOKKOS_FORCEINLINE_FUNCTION
constexpr unsigned range_index( const iType i ) const
{ return unsigned(i) < InternalRangeRank ? m_index[i] : ~0u ; }
};
}} // namespace Kokkos::Impl
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
namespace Kokkos {
namespace Impl {
/** \brief Given a value type and dimension generate the View data type */
template< class T , class Dim >
struct ViewDataType ;
template< class T >
struct ViewDataType< T , ViewDimension<> >
{
typedef T type ;
};
template< class T , size_t ... Args >
struct ViewDataType< T , ViewDimension< 0 , Args... > >
{
typedef typename ViewDataType<T*,ViewDimension<Args...> >::type type ;
};
template< class T , size_t N , size_t ... Args >
struct ViewDataType< T , ViewDimension< N , Args... > >
{
typedef typename ViewDataType<T,ViewDimension<Args...> >::type type[N] ;
};
/**\brief Analysis of View data type.
*
* Data type conforms to one of the following patterns :
* {const} value_type [][#][#][#]
* {const} value_type ***[#][#][#]
* Where the sum of counts of '*' and '[#]' is at most ten.
*
* Provide typedef for the ViewDimension<...> and value_type.
*/
template< class T >
struct ViewArrayAnalysis
{
typedef T value_type ;
typedef typename std::add_const< T >::type const_value_type ;
typedef typename std::remove_const< T >::type non_const_value_type ;
typedef ViewDimension<> static_dimension ;
typedef ViewDimension<> dynamic_dimension ;
typedef ViewDimension<> dimension ;
};
template< class T , size_t N >
struct ViewArrayAnalysis< T[N] >
{
private:
typedef ViewArrayAnalysis< T > nested ;
public:
typedef typename nested::value_type value_type ;
typedef typename nested::const_value_type const_value_type ;
typedef typename nested::non_const_value_type non_const_value_type ;
typedef typename nested::static_dimension::template prepend<N>::type
static_dimension ;
typedef typename nested::dynamic_dimension dynamic_dimension ;
typedef typename
ViewDimensionJoin< dynamic_dimension , static_dimension >::type
dimension ;
};
template< class T >
struct ViewArrayAnalysis< T[] >
{
private:
typedef ViewArrayAnalysis< T > nested ;
typedef typename nested::dimension nested_dimension ;
public:
typedef typename nested::value_type value_type ;
typedef typename nested::const_value_type const_value_type ;
typedef typename nested::non_const_value_type non_const_value_type ;
typedef typename nested::dynamic_dimension::template prepend<0>::type
dynamic_dimension ;
typedef typename nested::static_dimension static_dimension ;
typedef typename
ViewDimensionJoin< dynamic_dimension , static_dimension >::type
dimension ;
};
template< class T >
struct ViewArrayAnalysis< T* >
{
private:
typedef ViewArrayAnalysis< T > nested ;
public:
typedef typename nested::value_type value_type ;
typedef typename nested::const_value_type const_value_type ;
typedef typename nested::non_const_value_type non_const_value_type ;
typedef typename nested::dynamic_dimension::template prepend<0>::type
dynamic_dimension ;
typedef typename nested::static_dimension static_dimension ;
typedef typename
ViewDimensionJoin< dynamic_dimension , static_dimension >::type
dimension ;
};
template< class DataType , class ArrayLayout , class ValueType >
struct ViewDataAnalysis
{
private:
typedef ViewArrayAnalysis< DataType > array_analysis ;
// ValueType is opportunity for partial specialization.
// Must match array analysis when this default template is used.
static_assert( std::is_same< ValueType , typename array_analysis::non_const_value_type >::value , "" );
public:
typedef void specialize ; // No specialization
typedef typename array_analysis::dimension dimension ;
typedef typename array_analysis::value_type value_type ;
typedef typename array_analysis::const_value_type const_value_type ;
typedef typename array_analysis::non_const_value_type non_const_value_type ;
// Generate analogous multidimensional array specification type.
typedef typename ViewDataType< value_type , dimension >::type type ;
typedef typename ViewDataType< const_value_type , dimension >::type const_type ;
typedef typename ViewDataType< non_const_value_type , dimension >::type non_const_type ;
// Generate "flattened" multidimensional array specification type.
typedef type scalar_array_type ;
typedef const_type const_scalar_array_type ;
typedef non_const_type non_const_scalar_array_type ;
};
}} // namespace Kokkos::Impl
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
namespace Kokkos {
namespace Impl {
template < class Dimension , class Layout , typename Enable = void >
struct ViewOffset {
using is_mapping_plugin = std::false_type ;
};
//----------------------------------------------------------------------------
// LayoutLeft AND ( 1 >= rank OR 0 == rank_dynamic ) : no padding / striding
template < class Dimension >
struct ViewOffset< Dimension , Kokkos::LayoutLeft
, typename std::enable_if<( 1 >= Dimension::rank
||
0 == Dimension::rank_dynamic
)>::type >
{
using is_mapping_plugin = std::true_type ;
using is_regular = std::true_type ;
typedef size_t size_type ;
typedef Dimension dimension_type ;
typedef Kokkos::LayoutLeft array_layout ;
dimension_type m_dim ;
//----------------------------------------
// rank 1
template< typename I0 >
KOKKOS_INLINE_FUNCTION constexpr
size_type operator()( I0 const & i0 ) const { return i0 ; }
// rank 2
template < typename I0 , typename I1 >
KOKKOS_INLINE_FUNCTION constexpr
size_type operator()( I0 const & i0 , I1 const & i1 ) const
{ return i0 + m_dim.N0 * i1 ; }
//rank 3
template < typename I0, typename I1, typename I2 >
KOKKOS_INLINE_FUNCTION constexpr
size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2 ) const
{
return i0 + m_dim.N0 * ( i1 + m_dim.N1 * i2 );
}
//rank 4
template < typename I0, typename I1, typename I2, typename I3 >
KOKKOS_INLINE_FUNCTION constexpr
size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2, I3 const & i3 ) const
{
return i0 + m_dim.N0 * (
i1 + m_dim.N1 * (
i2 + m_dim.N2 * i3 ));
}
//rank 5
template < typename I0, typename I1, typename I2, typename I3
, typename I4 >
KOKKOS_INLINE_FUNCTION constexpr
size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2, I3 const & i3
, I4 const & i4 ) const
{
return i0 + m_dim.N0 * (
i1 + m_dim.N1 * (
i2 + m_dim.N2 * (
i3 + m_dim.N3 * i4 )));
}
//rank 6
template < typename I0, typename I1, typename I2, typename I3
, typename I4, typename I5 >
KOKKOS_INLINE_FUNCTION constexpr
size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2, I3 const & i3
, I4 const & i4, I5 const & i5 ) const
{
return i0 + m_dim.N0 * (
i1 + m_dim.N1 * (
i2 + m_dim.N2 * (
i3 + m_dim.N3 * (
i4 + m_dim.N4 * i5 ))));
}
//rank 7
template < typename I0, typename I1, typename I2, typename I3
, typename I4, typename I5, typename I6 >
KOKKOS_INLINE_FUNCTION constexpr
size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2, I3 const & i3
, I4 const & i4, I5 const & i5, I6 const & i6 ) const
{
return i0 + m_dim.N0 * (
i1 + m_dim.N1 * (
i2 + m_dim.N2 * (
i3 + m_dim.N3 * (
i4 + m_dim.N4 * (
i5 + m_dim.N5 * i6 )))));
}
//rank 8
template < typename I0, typename I1, typename I2, typename I3
, typename I4, typename I5, typename I6, typename I7 >
KOKKOS_INLINE_FUNCTION constexpr
size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2, I3 const & i3
, I4 const & i4, I5 const & i5, I6 const & i6, I7 const & i7 ) const
{
return i0 + m_dim.N0 * (
i1 + m_dim.N1 * (
i2 + m_dim.N2 * (
i3 + m_dim.N3 * (
i4 + m_dim.N4 * (
i5 + m_dim.N5 * (
i6 + m_dim.N6 * i7 ))))));
}
//----------------------------------------
KOKKOS_INLINE_FUNCTION
constexpr array_layout layout() const
{
return array_layout( m_dim.N0 , m_dim.N1 , m_dim.N2 , m_dim.N3
, m_dim.N4 , m_dim.N5 , m_dim.N6 , m_dim.N7 );
}
KOKKOS_INLINE_FUNCTION constexpr size_type dimension_0() const { return m_dim.N0 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type dimension_1() const { return m_dim.N1 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type dimension_2() const { return m_dim.N2 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type dimension_3() const { return m_dim.N3 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type dimension_4() const { return m_dim.N4 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type dimension_5() const { return m_dim.N5 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type dimension_6() const { return m_dim.N6 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type dimension_7() const { return m_dim.N7 ; }
/* Cardinality of the domain index space */
KOKKOS_INLINE_FUNCTION
constexpr size_type size() const
{ return m_dim.N0 * m_dim.N1 * m_dim.N2 * m_dim.N3 * m_dim.N4 * m_dim.N5 * m_dim.N6 * m_dim.N7 ; }
/* Span of the range space */
KOKKOS_INLINE_FUNCTION
constexpr size_type span() const
{ return m_dim.N0 * m_dim.N1 * m_dim.N2 * m_dim.N3 * m_dim.N4 * m_dim.N5 * m_dim.N6 * m_dim.N7 ; }
KOKKOS_INLINE_FUNCTION constexpr bool span_is_contiguous() const { return true ; }
/* Strides of dimensions */
KOKKOS_INLINE_FUNCTION constexpr size_type stride_0() const { return 1 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type stride_1() const { return m_dim.N0 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type stride_2() const { return m_dim.N0 * m_dim.N1 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type stride_3() const { return m_dim.N0 * m_dim.N1 * m_dim.N2 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type stride_4() const { return m_dim.N0 * m_dim.N1 * m_dim.N2 * m_dim.N3 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type stride_5() const { return m_dim.N0 * m_dim.N1 * m_dim.N2 * m_dim.N3 * m_dim.N4 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type stride_6() const { return m_dim.N0 * m_dim.N1 * m_dim.N2 * m_dim.N3 * m_dim.N4 * m_dim.N5 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type stride_7() const { return m_dim.N0 * m_dim.N1 * m_dim.N2 * m_dim.N3 * m_dim.N4 * m_dim.N5 * m_dim.N6 ; }
// Stride with [ rank ] value is the total length
template< typename iType >
KOKKOS_INLINE_FUNCTION
void stride( iType * const s ) const
{
s[0] = 1 ;
if ( 0 < dimension_type::rank ) { s[1] = m_dim.N0 ; }
if ( 1 < dimension_type::rank ) { s[2] = s[1] * m_dim.N1 ; }
if ( 2 < dimension_type::rank ) { s[3] = s[2] * m_dim.N2 ; }
if ( 3 < dimension_type::rank ) { s[4] = s[3] * m_dim.N3 ; }
if ( 4 < dimension_type::rank ) { s[5] = s[4] * m_dim.N4 ; }
if ( 5 < dimension_type::rank ) { s[6] = s[5] * m_dim.N5 ; }
if ( 6 < dimension_type::rank ) { s[7] = s[6] * m_dim.N6 ; }
if ( 7 < dimension_type::rank ) { s[8] = s[7] * m_dim.N7 ; }
}
//----------------------------------------
ViewOffset() = default ;
ViewOffset( const ViewOffset & ) = default ;
ViewOffset & operator = ( const ViewOffset & ) = default ;
template< unsigned TrivialScalarSize >
KOKKOS_INLINE_FUNCTION
constexpr ViewOffset
( std::integral_constant<unsigned,TrivialScalarSize> const &
, Kokkos::LayoutLeft const & arg_layout
)
: m_dim( arg_layout.dimension[0], 0, 0, 0, 0, 0, 0, 0 )
{}
template< class DimRHS >
KOKKOS_INLINE_FUNCTION
constexpr ViewOffset( const ViewOffset< DimRHS , Kokkos::LayoutLeft , void > & rhs )
: m_dim( rhs.m_dim.N0 , rhs.m_dim.N1 , rhs.m_dim.N2 , rhs.m_dim.N3
, rhs.m_dim.N4 , rhs.m_dim.N5 , rhs.m_dim.N6 , rhs.m_dim.N7 )
{
static_assert( int(DimRHS::rank) == int(dimension_type::rank) , "ViewOffset assignment requires equal rank" );
// Also requires equal static dimensions ...
}
template< class DimRHS >
KOKKOS_INLINE_FUNCTION
constexpr ViewOffset( const ViewOffset< DimRHS , Kokkos::LayoutRight , void > & rhs )
: m_dim( rhs.m_dim.N0, 0, 0, 0, 0, 0, 0, 0 )
{
static_assert( DimRHS::rank == 1 && dimension_type::rank == 1 && dimension_type::rank_dynamic == 1
, "ViewOffset LayoutLeft and LayoutRight are only compatible when rank == 1" );
}
template< class DimRHS >
KOKKOS_INLINE_FUNCTION
ViewOffset( const ViewOffset< DimRHS , Kokkos::LayoutStride , void > & rhs )
: m_dim( rhs.m_dim.N0, 0, 0, 0, 0, 0, 0, 0 )
{
static_assert( DimRHS::rank == 1 && dimension_type::rank == 1 && dimension_type::rank_dynamic == 1
, "ViewOffset LayoutLeft and LayoutStride are only compatible when rank == 1" );
if ( rhs.m_stride.S0 != 1 ) {
Kokkos::abort("Kokkos::Impl::ViewOffset assignment of LayoutLeft from LayoutStride requires stride == 1" );
}
}
//----------------------------------------
// Subview construction
template< class DimRHS >
KOKKOS_INLINE_FUNCTION
constexpr ViewOffset(
const ViewOffset< DimRHS , Kokkos::LayoutLeft , void > & rhs ,
const SubviewExtents< DimRHS::rank , dimension_type::rank > & sub )
: m_dim( sub.range_extent(0), 0, 0, 0, 0, 0, 0, 0 )
{
static_assert( ( 0 == dimension_type::rank ) ||
( 1 == dimension_type::rank && 1 == dimension_type::rank_dynamic && 1 <= DimRHS::rank )
, "ViewOffset subview construction requires compatible rank" );
}
};
//----------------------------------------------------------------------------
// LayoutLeft AND ( 1 < rank AND 0 < rank_dynamic ) : has padding / striding
template < class Dimension >
struct ViewOffset< Dimension , Kokkos::LayoutLeft
, typename std::enable_if<( 1 < Dimension::rank
&&
0 < Dimension::rank_dynamic
)>::type >
{
using is_mapping_plugin = std::true_type ;
using is_regular = std::true_type ;
typedef size_t size_type ;
typedef Dimension dimension_type ;
typedef Kokkos::LayoutLeft array_layout ;
dimension_type m_dim ;
size_type m_stride ;
//----------------------------------------
// rank 1
template< typename I0 >
KOKKOS_INLINE_FUNCTION constexpr
size_type operator()( I0 const & i0 ) const { return i0 ; }
// rank 2
template < typename I0 , typename I1 >
KOKKOS_INLINE_FUNCTION constexpr
size_type operator()( I0 const & i0 , I1 const & i1 ) const
{ return i0 + m_stride * i1 ; }
//rank 3
template < typename I0, typename I1, typename I2 >
KOKKOS_INLINE_FUNCTION constexpr
size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2 ) const
{
return i0 + m_stride * ( i1 + m_dim.N1 * i2 );
}
//rank 4
template < typename I0, typename I1, typename I2, typename I3 >
KOKKOS_INLINE_FUNCTION constexpr
size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2, I3 const & i3 ) const
{
return i0 + m_stride * (
i1 + m_dim.N1 * (
i2 + m_dim.N2 * i3 ));
}
//rank 5
template < typename I0, typename I1, typename I2, typename I3
, typename I4 >
KOKKOS_INLINE_FUNCTION constexpr
size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2, I3 const & i3
, I4 const & i4 ) const
{
return i0 + m_stride * (
i1 + m_dim.N1 * (
i2 + m_dim.N2 * (
i3 + m_dim.N3 * i4 )));
}
//rank 6
template < typename I0, typename I1, typename I2, typename I3
, typename I4, typename I5 >
KOKKOS_INLINE_FUNCTION constexpr
size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2, I3 const & i3
, I4 const & i4, I5 const & i5 ) const
{
return i0 + m_stride * (
i1 + m_dim.N1 * (
i2 + m_dim.N2 * (
i3 + m_dim.N3 * (
i4 + m_dim.N4 * i5 ))));
}
//rank 7
template < typename I0, typename I1, typename I2, typename I3
, typename I4, typename I5, typename I6 >
KOKKOS_INLINE_FUNCTION constexpr
size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2, I3 const & i3
, I4 const & i4, I5 const & i5, I6 const & i6 ) const
{
return i0 + m_stride * (
i1 + m_dim.N1 * (
i2 + m_dim.N2 * (
i3 + m_dim.N3 * (
i4 + m_dim.N4 * (
i5 + m_dim.N5 * i6 )))));
}
//rank 8
template < typename I0, typename I1, typename I2, typename I3
, typename I4, typename I5, typename I6, typename I7 >
KOKKOS_INLINE_FUNCTION constexpr
size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2, I3 const & i3
, I4 const & i4, I5 const & i5, I6 const & i6, I7 const & i7 ) const
{
return i0 + m_stride * (
i1 + m_dim.N1 * (
i2 + m_dim.N2 * (
i3 + m_dim.N3 * (
i4 + m_dim.N4 * (
i5 + m_dim.N5 * (
i6 + m_dim.N6 * i7 ))))));
}
//----------------------------------------
KOKKOS_INLINE_FUNCTION
constexpr array_layout layout() const
{
return array_layout( m_dim.N0 , m_dim.N1 , m_dim.N2 , m_dim.N3
, m_dim.N4 , m_dim.N5 , m_dim.N6 , m_dim.N7 );
}
KOKKOS_INLINE_FUNCTION constexpr size_type dimension_0() const { return m_dim.N0 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type dimension_1() const { return m_dim.N1 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type dimension_2() const { return m_dim.N2 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type dimension_3() const { return m_dim.N3 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type dimension_4() const { return m_dim.N4 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type dimension_5() const { return m_dim.N5 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type dimension_6() const { return m_dim.N6 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type dimension_7() const { return m_dim.N7 ; }
/* Cardinality of the domain index space */
KOKKOS_INLINE_FUNCTION
constexpr size_type size() const
{ return m_dim.N0 * m_dim.N1 * m_dim.N2 * m_dim.N3 * m_dim.N4 * m_dim.N5 * m_dim.N6 * m_dim.N7 ; }
/* Span of the range space */
KOKKOS_INLINE_FUNCTION
constexpr size_type span() const
{ return m_stride * m_dim.N1 * m_dim.N2 * m_dim.N3 * m_dim.N4 * m_dim.N5 * m_dim.N6 * m_dim.N7 ; }
KOKKOS_INLINE_FUNCTION constexpr bool span_is_contiguous() const { return m_stride == m_dim.N0 ; }
/* Strides of dimensions */
KOKKOS_INLINE_FUNCTION constexpr size_type stride_0() const { return 1 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type stride_1() const { return m_stride ; }
KOKKOS_INLINE_FUNCTION constexpr size_type stride_2() const { return m_stride * m_dim.N1 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type stride_3() const { return m_stride * m_dim.N1 * m_dim.N2 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type stride_4() const { return m_stride * m_dim.N1 * m_dim.N2 * m_dim.N3 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type stride_5() const { return m_stride * m_dim.N1 * m_dim.N2 * m_dim.N3 * m_dim.N4 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type stride_6() const { return m_stride * m_dim.N1 * m_dim.N2 * m_dim.N3 * m_dim.N4 * m_dim.N5 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type stride_7() const { return m_stride * m_dim.N1 * m_dim.N2 * m_dim.N3 * m_dim.N4 * m_dim.N5 * m_dim.N6 ; }
// Stride with [ rank ] value is the total length
template< typename iType >
KOKKOS_INLINE_FUNCTION
void stride( iType * const s ) const
{
s[0] = 1 ;
if ( 0 < dimension_type::rank ) { s[1] = m_stride ; }
if ( 1 < dimension_type::rank ) { s[2] = s[1] * m_dim.N1 ; }
if ( 2 < dimension_type::rank ) { s[3] = s[2] * m_dim.N2 ; }
if ( 3 < dimension_type::rank ) { s[4] = s[3] * m_dim.N3 ; }
if ( 4 < dimension_type::rank ) { s[5] = s[4] * m_dim.N4 ; }
if ( 5 < dimension_type::rank ) { s[6] = s[5] * m_dim.N5 ; }
if ( 6 < dimension_type::rank ) { s[7] = s[6] * m_dim.N6 ; }
if ( 7 < dimension_type::rank ) { s[8] = s[7] * m_dim.N7 ; }
}
//----------------------------------------
private:
template< unsigned TrivialScalarSize >
struct Padding {
enum { div = TrivialScalarSize == 0 ? 0 : Kokkos::Impl::MEMORY_ALIGNMENT / ( TrivialScalarSize ? TrivialScalarSize : 1 ) };
enum { mod = TrivialScalarSize == 0 ? 0 : Kokkos::Impl::MEMORY_ALIGNMENT % ( TrivialScalarSize ? TrivialScalarSize : 1 ) };
// If memory alignment is a multiple of the trivial scalar size then attempt to align.
enum { align = 0 != TrivialScalarSize && 0 == mod ? div : 0 };
enum { div_ok = (div != 0) ? div : 1 }; // To valid modulo zero in constexpr
KOKKOS_INLINE_FUNCTION
static constexpr size_t stride( size_t const N )
{
return ( (align != 0) && ((Kokkos::Impl::MEMORY_ALIGNMENT_THRESHOLD * align) < N) && ((N % div_ok) != 0) )
? N + align - ( N % div_ok ) : N ;
}
};
public:
ViewOffset() = default ;
ViewOffset( const ViewOffset & ) = default ;
ViewOffset & operator = ( const ViewOffset & ) = default ;
/* Enable padding for trivial scalar types with non-zero trivial scalar size */
template< unsigned TrivialScalarSize >
KOKKOS_INLINE_FUNCTION
constexpr ViewOffset
( std::integral_constant<unsigned,TrivialScalarSize> const & padding_type_size
, Kokkos::LayoutLeft const & arg_layout
)
: m_dim( arg_layout.dimension[0] , arg_layout.dimension[1]
, arg_layout.dimension[2] , arg_layout.dimension[3]
, arg_layout.dimension[4] , arg_layout.dimension[5]
, arg_layout.dimension[6] , arg_layout.dimension[7]
)
, m_stride( Padding<TrivialScalarSize>::stride( arg_layout.dimension[0] ) )
{}
template< class DimRHS >
KOKKOS_INLINE_FUNCTION
constexpr ViewOffset( const ViewOffset< DimRHS , Kokkos::LayoutLeft , void > & rhs )
: m_dim( rhs.m_dim.N0 , rhs.m_dim.N1 , rhs.m_dim.N2 , rhs.m_dim.N3
, rhs.m_dim.N4 , rhs.m_dim.N5 , rhs.m_dim.N6 , rhs.m_dim.N7 )
, m_stride( rhs.stride_1() )
{
static_assert( int(DimRHS::rank) == int(dimension_type::rank) , "ViewOffset assignment requires equal rank" );
// Also requires equal static dimensions ...
}
//----------------------------------------
// Subview construction
// This subview must be 2 == rank and 2 == rank_dynamic
// due to only having stride #0.
// The source dimension #0 must be non-zero for stride-one leading dimension.
// At most subsequent dimension can be non-zero.
template< class DimRHS >
KOKKOS_INLINE_FUNCTION
constexpr ViewOffset
( const ViewOffset< DimRHS , Kokkos::LayoutLeft , void > & rhs ,
const SubviewExtents< DimRHS::rank , dimension_type::rank > & sub )
: m_dim( sub.range_extent(0)
, sub.range_extent(1)
, sub.range_extent(2)
, sub.range_extent(3)
, sub.range_extent(4)
, sub.range_extent(5)
, sub.range_extent(6)
, sub.range_extent(7))
, m_stride( ( 1 == sub.range_index(1) ? rhs.stride_1() :
( 2 == sub.range_index(1) ? rhs.stride_2() :
( 3 == sub.range_index(1) ? rhs.stride_3() :
( 4 == sub.range_index(1) ? rhs.stride_4() :
( 5 == sub.range_index(1) ? rhs.stride_5() :
( 6 == sub.range_index(1) ? rhs.stride_6() :
( 7 == sub.range_index(1) ? rhs.stride_7() : 0 ))))))))
{
//static_assert( ( 2 == dimension_type::rank ) &&
// ( 2 == dimension_type::rank_dynamic ) &&
// ( 2 <= DimRHS::rank )
// , "ViewOffset subview construction requires compatible rank" );
}
};
//----------------------------------------------------------------------------
// LayoutRight AND ( 1 >= rank OR 0 == rank_dynamic ) : no padding / striding
template < class Dimension >
struct ViewOffset< Dimension , Kokkos::LayoutRight
, typename std::enable_if<( 1 >= Dimension::rank
||
0 == Dimension::rank_dynamic
)>::type >
{
using is_mapping_plugin = std::true_type ;
using is_regular = std::true_type ;
typedef size_t size_type ;
typedef Dimension dimension_type ;
typedef Kokkos::LayoutRight array_layout ;
dimension_type m_dim ;
//----------------------------------------
// rank 1
template< typename I0 >
KOKKOS_INLINE_FUNCTION constexpr
size_type operator()( I0 const & i0 ) const { return i0 ; }
// rank 2
template < typename I0 , typename I1 >
KOKKOS_INLINE_FUNCTION constexpr
size_type operator()( I0 const & i0 , I1 const & i1 ) const
{ return i1 + m_dim.N1 * i0 ; }
//rank 3
template < typename I0, typename I1, typename I2 >
KOKKOS_INLINE_FUNCTION constexpr
size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2 ) const
{
return i2 + m_dim.N2 * ( i1 + m_dim.N1 * ( i0 ));
}
//rank 4
template < typename I0, typename I1, typename I2, typename I3 >
KOKKOS_INLINE_FUNCTION constexpr
size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2, I3 const & i3 ) const
{
return i3 + m_dim.N3 * (
i2 + m_dim.N2 * (
i1 + m_dim.N1 * ( i0 )));
}
//rank 5
template < typename I0, typename I1, typename I2, typename I3
, typename I4 >
KOKKOS_INLINE_FUNCTION constexpr
size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2, I3 const & i3
, I4 const & i4 ) const
{
return i4 + m_dim.N4 * (
i3 + m_dim.N3 * (
i2 + m_dim.N2 * (
i1 + m_dim.N1 * ( i0 ))));
}
//rank 6
template < typename I0, typename I1, typename I2, typename I3
, typename I4, typename I5 >
KOKKOS_INLINE_FUNCTION constexpr
size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2, I3 const & i3
, I4 const & i4, I5 const & i5 ) const
{
return i5 + m_dim.N5 * (
i4 + m_dim.N4 * (
i3 + m_dim.N3 * (
i2 + m_dim.N2 * (
i1 + m_dim.N1 * ( i0 )))));
}
//rank 7
template < typename I0, typename I1, typename I2, typename I3
, typename I4, typename I5, typename I6 >
KOKKOS_INLINE_FUNCTION constexpr
size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2, I3 const & i3
, I4 const & i4, I5 const & i5, I6 const & i6 ) const
{
return i6 + m_dim.N6 * (
i5 + m_dim.N5 * (
i4 + m_dim.N4 * (
i3 + m_dim.N3 * (
i2 + m_dim.N2 * (
i1 + m_dim.N1 * ( i0 ))))));
}
//rank 8
template < typename I0, typename I1, typename I2, typename I3
, typename I4, typename I5, typename I6, typename I7 >
KOKKOS_INLINE_FUNCTION constexpr
size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2, I3 const & i3
, I4 const & i4, I5 const & i5, I6 const & i6, I7 const & i7 ) const
{
return i7 + m_dim.N7 * (
i6 + m_dim.N6 * (
i5 + m_dim.N5 * (
i4 + m_dim.N4 * (
i3 + m_dim.N3 * (
i2 + m_dim.N2 * (
i1 + m_dim.N1 * ( i0 )))))));
}
//----------------------------------------
KOKKOS_INLINE_FUNCTION
constexpr array_layout layout() const
{
return array_layout( m_dim.N0 , m_dim.N1 , m_dim.N2 , m_dim.N3
, m_dim.N4 , m_dim.N5 , m_dim.N6 , m_dim.N7 );
}
KOKKOS_INLINE_FUNCTION constexpr size_type dimension_0() const { return m_dim.N0 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type dimension_1() const { return m_dim.N1 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type dimension_2() const { return m_dim.N2 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type dimension_3() const { return m_dim.N3 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type dimension_4() const { return m_dim.N4 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type dimension_5() const { return m_dim.N5 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type dimension_6() const { return m_dim.N6 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type dimension_7() const { return m_dim.N7 ; }
/* Cardinality of the domain index space */
KOKKOS_INLINE_FUNCTION
constexpr size_type size() const
{ return m_dim.N0 * m_dim.N1 * m_dim.N2 * m_dim.N3 * m_dim.N4 * m_dim.N5 * m_dim.N6 * m_dim.N7 ; }
/* Span of the range space */
KOKKOS_INLINE_FUNCTION
constexpr size_type span() const
{ return m_dim.N0 * m_dim.N1 * m_dim.N2 * m_dim.N3 * m_dim.N4 * m_dim.N5 * m_dim.N6 * m_dim.N7 ; }
KOKKOS_INLINE_FUNCTION constexpr bool span_is_contiguous() const { return true ; }
/* Strides of dimensions */
KOKKOS_INLINE_FUNCTION constexpr size_type stride_7() const { return 1 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type stride_6() const { return m_dim.N7 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type stride_5() const { return m_dim.N7 * m_dim.N6 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type stride_4() const { return m_dim.N7 * m_dim.N6 * m_dim.N5 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type stride_3() const { return m_dim.N7 * m_dim.N6 * m_dim.N5 * m_dim.N4 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type stride_2() const { return m_dim.N7 * m_dim.N6 * m_dim.N5 * m_dim.N4 * m_dim.N3 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type stride_1() const { return m_dim.N7 * m_dim.N6 * m_dim.N5 * m_dim.N4 * m_dim.N3 * m_dim.N2 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type stride_0() const { return m_dim.N7 * m_dim.N6 * m_dim.N5 * m_dim.N4 * m_dim.N3 * m_dim.N2 * m_dim.N1 ; }
// Stride with [ rank ] value is the total length
template< typename iType >
KOKKOS_INLINE_FUNCTION
void stride( iType * const s ) const
{
size_type n = 1 ;
if ( 7 < dimension_type::rank ) { s[7] = n ; n *= m_dim.N7 ; }
if ( 6 < dimension_type::rank ) { s[6] = n ; n *= m_dim.N6 ; }
if ( 5 < dimension_type::rank ) { s[5] = n ; n *= m_dim.N5 ; }
if ( 4 < dimension_type::rank ) { s[4] = n ; n *= m_dim.N4 ; }
if ( 3 < dimension_type::rank ) { s[3] = n ; n *= m_dim.N3 ; }
if ( 2 < dimension_type::rank ) { s[2] = n ; n *= m_dim.N2 ; }
if ( 1 < dimension_type::rank ) { s[1] = n ; n *= m_dim.N1 ; }
if ( 0 < dimension_type::rank ) { s[0] = n ; }
s[dimension_type::rank] = n * m_dim.N0 ;
}
//----------------------------------------
ViewOffset() = default ;
ViewOffset( const ViewOffset & ) = default ;
ViewOffset & operator = ( const ViewOffset & ) = default ;
template< unsigned TrivialScalarSize >
KOKKOS_INLINE_FUNCTION
constexpr ViewOffset
( std::integral_constant<unsigned,TrivialScalarSize> const &
, Kokkos::LayoutRight const & arg_layout
)
: m_dim( arg_layout.dimension[0], 0, 0, 0, 0, 0, 0, 0 )
{}
template< class DimRHS >
KOKKOS_INLINE_FUNCTION
constexpr ViewOffset( const ViewOffset< DimRHS , Kokkos::LayoutRight , void > & rhs )
: m_dim( rhs.m_dim.N0 , rhs.m_dim.N1 , rhs.m_dim.N2 , rhs.m_dim.N3
, rhs.m_dim.N4 , rhs.m_dim.N5 , rhs.m_dim.N6 , rhs.m_dim.N7 )
{
static_assert( int(DimRHS::rank) == int(dimension_type::rank) , "ViewOffset assignment requires equal rank" );
// Also requires equal static dimensions ...
}
template< class DimRHS >
KOKKOS_INLINE_FUNCTION
constexpr ViewOffset( const ViewOffset< DimRHS , Kokkos::LayoutLeft , void > & rhs )
: m_dim( rhs.m_dim.N0, 0, 0, 0, 0, 0, 0, 0 )
{
static_assert( DimRHS::rank == 1 && dimension_type::rank == 1 && dimension_type::rank_dynamic == 1
, "ViewOffset LayoutRight and LayoutLeft are only compatible when rank == 1" );
}
template< class DimRHS >
KOKKOS_INLINE_FUNCTION
ViewOffset( const ViewOffset< DimRHS , Kokkos::LayoutStride , void > & rhs )
: m_dim( rhs.m_dim.N0, 0, 0, 0, 0, 0, 0, 0 )
{
static_assert( DimRHS::rank == 1 && dimension_type::rank == 1 && dimension_type::rank_dynamic == 1
, "ViewOffset LayoutLeft/Right and LayoutStride are only compatible when rank == 1" );
if ( rhs.m_stride.S0 != 1 ) {
Kokkos::abort("Kokkos::Impl::ViewOffset assignment of LayoutLeft/Right from LayoutStride requires stride == 1" );
}
}
//----------------------------------------
// Subview construction
template< class DimRHS >
KOKKOS_INLINE_FUNCTION
constexpr ViewOffset
( const ViewOffset< DimRHS , Kokkos::LayoutRight , void > & rhs
, const SubviewExtents< DimRHS::rank , dimension_type::rank > & sub
)
: m_dim( sub.range_extent(0) , 0, 0, 0, 0, 0, 0, 0 )
{
static_assert( ( 0 == dimension_type::rank_dynamic ) ||
( 1 == dimension_type::rank && 1 == dimension_type::rank_dynamic && 1 <= DimRHS::rank )
, "ViewOffset subview construction requires compatible rank" );
}
};
//----------------------------------------------------------------------------
// LayoutRight AND ( 1 < rank AND 0 < rank_dynamic ) : has padding / striding
template < class Dimension >
struct ViewOffset< Dimension , Kokkos::LayoutRight
, typename std::enable_if<( 1 < Dimension::rank
&&
0 < Dimension::rank_dynamic
)>::type >
{
using is_mapping_plugin = std::true_type ;
using is_regular = std::true_type ;
typedef size_t size_type ;
typedef Dimension dimension_type ;
typedef Kokkos::LayoutRight array_layout ;
dimension_type m_dim ;
size_type m_stride ;
//----------------------------------------
// rank 1
template< typename I0 >
KOKKOS_INLINE_FUNCTION constexpr
size_type operator()( I0 const & i0 ) const { return i0 ; }
// rank 2
template < typename I0 , typename I1 >
KOKKOS_INLINE_FUNCTION constexpr
size_type operator()( I0 const & i0 , I1 const & i1 ) const
{ return i1 + i0 * m_stride ; }
//rank 3
template < typename I0, typename I1, typename I2 >
KOKKOS_INLINE_FUNCTION constexpr
size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2 ) const
{ return i2 + m_dim.N2 * ( i1 ) + i0 * m_stride ; }
//rank 4
template < typename I0, typename I1, typename I2, typename I3 >
KOKKOS_INLINE_FUNCTION constexpr
size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2, I3 const & i3 ) const
{
return i3 + m_dim.N3 * (
i2 + m_dim.N2 * ( i1 )) +
i0 * m_stride ;
}
//rank 5
template < typename I0, typename I1, typename I2, typename I3
, typename I4 >
KOKKOS_INLINE_FUNCTION constexpr
size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2, I3 const & i3
, I4 const & i4 ) const
{
return i4 + m_dim.N4 * (
i3 + m_dim.N3 * (
i2 + m_dim.N2 * ( i1 ))) +
i0 * m_stride ;
}
//rank 6
template < typename I0, typename I1, typename I2, typename I3
, typename I4, typename I5 >
KOKKOS_INLINE_FUNCTION constexpr
size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2, I3 const & i3
, I4 const & i4, I5 const & i5 ) const
{
return i5 + m_dim.N5 * (
i4 + m_dim.N4 * (
i3 + m_dim.N3 * (
i2 + m_dim.N2 * ( i1 )))) +
i0 * m_stride ;
}
//rank 7
template < typename I0, typename I1, typename I2, typename I3
, typename I4, typename I5, typename I6 >
KOKKOS_INLINE_FUNCTION constexpr
size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2, I3 const & i3
, I4 const & i4, I5 const & i5, I6 const & i6 ) const
{
return i6 + m_dim.N6 * (
i5 + m_dim.N5 * (
i4 + m_dim.N4 * (
i3 + m_dim.N3 * (
i2 + m_dim.N2 * ( i1 ))))) +
i0 * m_stride ;
}
//rank 8
template < typename I0, typename I1, typename I2, typename I3
, typename I4, typename I5, typename I6, typename I7 >
KOKKOS_INLINE_FUNCTION constexpr
size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2, I3 const & i3
, I4 const & i4, I5 const & i5, I6 const & i6, I7 const & i7 ) const
{
return i7 + m_dim.N7 * (
i6 + m_dim.N6 * (
i5 + m_dim.N5 * (
i4 + m_dim.N4 * (
i3 + m_dim.N3 * (
i2 + m_dim.N2 * ( i1 )))))) +
i0 * m_stride ;
}
//----------------------------------------
KOKKOS_INLINE_FUNCTION
constexpr array_layout layout() const
{
return array_layout( m_dim.N0 , m_dim.N1 , m_dim.N2 , m_dim.N3
, m_dim.N4 , m_dim.N5 , m_dim.N6 , m_dim.N7 );
}
KOKKOS_INLINE_FUNCTION constexpr size_type dimension_0() const { return m_dim.N0 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type dimension_1() const { return m_dim.N1 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type dimension_2() const { return m_dim.N2 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type dimension_3() const { return m_dim.N3 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type dimension_4() const { return m_dim.N4 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type dimension_5() const { return m_dim.N5 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type dimension_6() const { return m_dim.N6 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type dimension_7() const { return m_dim.N7 ; }
/* Cardinality of the domain index space */
KOKKOS_INLINE_FUNCTION
constexpr size_type size() const
{ return m_dim.N0 * m_dim.N1 * m_dim.N2 * m_dim.N3 * m_dim.N4 * m_dim.N5 * m_dim.N6 * m_dim.N7 ; }
/* Span of the range space */
KOKKOS_INLINE_FUNCTION
constexpr size_type span() const
{ return m_dim.N0 * m_stride ; }
KOKKOS_INLINE_FUNCTION constexpr bool span_is_contiguous() const
{ return m_stride == m_dim.N7 * m_dim.N6 * m_dim.N5 * m_dim.N4 * m_dim.N3 * m_dim.N2 * m_dim.N1 ; }
/* Strides of dimensions */
KOKKOS_INLINE_FUNCTION constexpr size_type stride_7() const { return 1 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type stride_6() const { return m_dim.N7 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type stride_5() const { return m_dim.N7 * m_dim.N6 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type stride_4() const { return m_dim.N7 * m_dim.N6 * m_dim.N5 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type stride_3() const { return m_dim.N7 * m_dim.N6 * m_dim.N5 * m_dim.N4 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type stride_2() const { return m_dim.N7 * m_dim.N6 * m_dim.N5 * m_dim.N4 * m_dim.N3 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type stride_1() const { return m_dim.N7 * m_dim.N6 * m_dim.N5 * m_dim.N4 * m_dim.N3 * m_dim.N2 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type stride_0() const { return m_stride ; }
// Stride with [ rank ] value is the total length
template< typename iType >
KOKKOS_INLINE_FUNCTION
void stride( iType * const s ) const
{
size_type n = 1 ;
if ( 7 < dimension_type::rank ) { s[7] = n ; n *= m_dim.N7 ; }
if ( 6 < dimension_type::rank ) { s[6] = n ; n *= m_dim.N6 ; }
if ( 5 < dimension_type::rank ) { s[5] = n ; n *= m_dim.N5 ; }
if ( 4 < dimension_type::rank ) { s[4] = n ; n *= m_dim.N4 ; }
if ( 3 < dimension_type::rank ) { s[3] = n ; n *= m_dim.N3 ; }
if ( 2 < dimension_type::rank ) { s[2] = n ; n *= m_dim.N2 ; }
if ( 1 < dimension_type::rank ) { s[1] = n ; }
if ( 0 < dimension_type::rank ) { s[0] = m_stride ; }
s[dimension_type::rank] = m_stride * m_dim.N0 ;
}
//----------------------------------------
private:
template< unsigned TrivialScalarSize >
struct Padding {
enum { div = TrivialScalarSize == 0 ? 0 : Kokkos::Impl::MEMORY_ALIGNMENT / ( TrivialScalarSize ? TrivialScalarSize : 1 ) };
enum { mod = TrivialScalarSize == 0 ? 0 : Kokkos::Impl::MEMORY_ALIGNMENT % ( TrivialScalarSize ? TrivialScalarSize : 1 ) };
// If memory alignment is a multiple of the trivial scalar size then attempt to align.
enum { align = 0 != TrivialScalarSize && 0 == mod ? div : 0 };
enum { div_ok = (div != 0) ? div : 1 }; // To valid modulo zero in constexpr
KOKKOS_INLINE_FUNCTION
static constexpr size_t stride( size_t const N )
{
return ( (align != 0) && ((Kokkos::Impl::MEMORY_ALIGNMENT_THRESHOLD * align) < N) && ((N % div_ok) != 0) )
? N + align - ( N % div_ok ) : N ;
}
};
public:
ViewOffset() = default ;
ViewOffset( const ViewOffset & ) = default ;
ViewOffset & operator = ( const ViewOffset & ) = default ;
/* Enable padding for trivial scalar types with non-zero trivial scalar size. */
template< unsigned TrivialScalarSize >
KOKKOS_INLINE_FUNCTION
constexpr ViewOffset
( std::integral_constant<unsigned,TrivialScalarSize> const & padding_type_size
, Kokkos::LayoutRight const & arg_layout
)
: m_dim( arg_layout.dimension[0] , arg_layout.dimension[1]
, arg_layout.dimension[2] , arg_layout.dimension[3]
, arg_layout.dimension[4] , arg_layout.dimension[5]
, arg_layout.dimension[6] , arg_layout.dimension[7]
)
, m_stride( Padding<TrivialScalarSize>::
stride( /* 2 <= rank */
m_dim.N1 * ( dimension_type::rank == 2 ? 1 :
m_dim.N2 * ( dimension_type::rank == 3 ? 1 :
m_dim.N3 * ( dimension_type::rank == 4 ? 1 :
m_dim.N4 * ( dimension_type::rank == 5 ? 1 :
m_dim.N5 * ( dimension_type::rank == 6 ? 1 :
m_dim.N6 * ( dimension_type::rank == 7 ? 1 : m_dim.N7 )))))) ))
{}
template< class DimRHS >
KOKKOS_INLINE_FUNCTION
constexpr ViewOffset( const ViewOffset< DimRHS , Kokkos::LayoutRight , void > & rhs )
: m_dim( rhs.m_dim.N0 , rhs.m_dim.N1 , rhs.m_dim.N2 , rhs.m_dim.N3
, rhs.m_dim.N4 , rhs.m_dim.N5 , rhs.m_dim.N6 , rhs.m_dim.N7 )
, m_stride( rhs.stride_0() )
{
static_assert( int(DimRHS::rank) == int(dimension_type::rank) , "ViewOffset assignment requires equal rank" );
// Also requires equal static dimensions ...
}
//----------------------------------------
// Subview construction
// Last dimension must be non-zero
template< class DimRHS >
KOKKOS_INLINE_FUNCTION
constexpr ViewOffset
( const ViewOffset< DimRHS , Kokkos::LayoutRight , void > & rhs
, const SubviewExtents< DimRHS::rank , dimension_type::rank > & sub
)
: m_dim( sub.range_extent(0)
, sub.range_extent(1)
, sub.range_extent(2)
, sub.range_extent(3)
, sub.range_extent(4)
, sub.range_extent(5)
, sub.range_extent(6)
, sub.range_extent(7))
, m_stride( 0 == sub.range_index(0) ? rhs.stride_0() : (
1 == sub.range_index(0) ? rhs.stride_1() : (
2 == sub.range_index(0) ? rhs.stride_2() : (
3 == sub.range_index(0) ? rhs.stride_3() : (
4 == sub.range_index(0) ? rhs.stride_4() : (
5 == sub.range_index(0) ? rhs.stride_5() : (
6 == sub.range_index(0) ? rhs.stride_6() : 0 )))))))
{
/* // This subview must be 2 == rank and 2 == rank_dynamic
// due to only having stride #0.
// The source dimension #0 must be non-zero for stride-one leading dimension.
// At most subsequent dimension can be non-zero.
static_assert( (( 2 == dimension_type::rank ) &&
( 2 <= DimRHS::rank )) ||
()
, "ViewOffset subview construction requires compatible rank" );
*/
}
};
//----------------------------------------------------------------------------
/* Strided array layout only makes sense for 0 < rank */
/* rank = 0 included for DynRankView case */
template< unsigned Rank >
struct ViewStride ;
template<>
struct ViewStride<0> {
enum { S0 = 0 , S1 = 0 , S2 = 0 , S3 = 0 , S4 = 0 , S5 = 0 , S6 = 0 , S7 = 0 };
ViewStride() = default ;
ViewStride( const ViewStride & ) = default ;
ViewStride & operator = ( const ViewStride & ) = default ;
KOKKOS_INLINE_FUNCTION
constexpr ViewStride( size_t , size_t , size_t , size_t
, size_t , size_t , size_t , size_t )
{}
};
template<>
struct ViewStride<1> {
size_t S0 ;
enum { S1 = 0 , S2 = 0 , S3 = 0 , S4 = 0 , S5 = 0 , S6 = 0 , S7 = 0 };
ViewStride() = default ;
ViewStride( const ViewStride & ) = default ;
ViewStride & operator = ( const ViewStride & ) = default ;
KOKKOS_INLINE_FUNCTION
constexpr ViewStride( size_t aS0 , size_t , size_t , size_t
, size_t , size_t , size_t , size_t )
: S0( aS0 )
{}
};
template<>
struct ViewStride<2> {
size_t S0 , S1 ;
enum { S2 = 0 , S3 = 0 , S4 = 0 , S5 = 0 , S6 = 0 , S7 = 0 };
ViewStride() = default ;
ViewStride( const ViewStride & ) = default ;
ViewStride & operator = ( const ViewStride & ) = default ;
KOKKOS_INLINE_FUNCTION
constexpr ViewStride( size_t aS0 , size_t aS1 , size_t , size_t
, size_t , size_t , size_t , size_t )
: S0( aS0 ) , S1( aS1 )
{}
};
template<>
struct ViewStride<3> {
size_t S0 , S1 , S2 ;
enum { S3 = 0 , S4 = 0 , S5 = 0 , S6 = 0 , S7 = 0 };
ViewStride() = default ;
ViewStride( const ViewStride & ) = default ;
ViewStride & operator = ( const ViewStride & ) = default ;
KOKKOS_INLINE_FUNCTION
constexpr ViewStride( size_t aS0 , size_t aS1 , size_t aS2 , size_t
, size_t , size_t , size_t , size_t )
: S0( aS0 ) , S1( aS1 ) , S2( aS2 )
{}
};
template<>
struct ViewStride<4> {
size_t S0 , S1 , S2 , S3 ;
enum { S4 = 0 , S5 = 0 , S6 = 0 , S7 = 0 };
ViewStride() = default ;
ViewStride( const ViewStride & ) = default ;
ViewStride & operator = ( const ViewStride & ) = default ;
KOKKOS_INLINE_FUNCTION
constexpr ViewStride( size_t aS0 , size_t aS1 , size_t aS2 , size_t aS3
, size_t , size_t , size_t , size_t )
: S0( aS0 ) , S1( aS1 ) , S2( aS2 ) , S3( aS3 )
{}
};
template<>
struct ViewStride<5> {
size_t S0 , S1 , S2 , S3 , S4 ;
enum { S5 = 0 , S6 = 0 , S7 = 0 };
ViewStride() = default ;
ViewStride( const ViewStride & ) = default ;
ViewStride & operator = ( const ViewStride & ) = default ;
KOKKOS_INLINE_FUNCTION
constexpr ViewStride( size_t aS0 , size_t aS1 , size_t aS2 , size_t aS3
, size_t aS4 , size_t , size_t , size_t )
: S0( aS0 ) , S1( aS1 ) , S2( aS2 ) , S3( aS3 )
, S4( aS4 )
{}
};
template<>
struct ViewStride<6> {
size_t S0 , S1 , S2 , S3 , S4 , S5 ;
enum { S6 = 0 , S7 = 0 };
ViewStride() = default ;
ViewStride( const ViewStride & ) = default ;
ViewStride & operator = ( const ViewStride & ) = default ;
KOKKOS_INLINE_FUNCTION
constexpr ViewStride( size_t aS0 , size_t aS1 , size_t aS2 , size_t aS3
, size_t aS4 , size_t aS5 , size_t , size_t )
: S0( aS0 ) , S1( aS1 ) , S2( aS2 ) , S3( aS3 )
, S4( aS4 ) , S5( aS5 )
{}
};
template<>
struct ViewStride<7> {
size_t S0 , S1 , S2 , S3 , S4 , S5 , S6 ;
enum { S7 = 0 };
ViewStride() = default ;
ViewStride( const ViewStride & ) = default ;
ViewStride & operator = ( const ViewStride & ) = default ;
KOKKOS_INLINE_FUNCTION
constexpr ViewStride( size_t aS0 , size_t aS1 , size_t aS2 , size_t aS3
, size_t aS4 , size_t aS5 , size_t aS6 , size_t )
: S0( aS0 ) , S1( aS1 ) , S2( aS2 ) , S3( aS3 )
, S4( aS4 ) , S5( aS5 ) , S6( aS6 )
{}
};
template<>
struct ViewStride<8> {
size_t S0 , S1 , S2 , S3 , S4 , S5 , S6 , S7 ;
ViewStride() = default ;
ViewStride( const ViewStride & ) = default ;
ViewStride & operator = ( const ViewStride & ) = default ;
KOKKOS_INLINE_FUNCTION
constexpr ViewStride( size_t aS0 , size_t aS1 , size_t aS2 , size_t aS3
, size_t aS4 , size_t aS5 , size_t aS6 , size_t aS7 )
: S0( aS0 ) , S1( aS1 ) , S2( aS2 ) , S3( aS3 )
, S4( aS4 ) , S5( aS5 ) , S6( aS6 ) , S7( aS7 )
{}
};
template < class Dimension >
struct ViewOffset< Dimension , Kokkos::LayoutStride
, void >
{
private:
typedef ViewStride< Dimension::rank > stride_type ;
public:
using is_mapping_plugin = std::true_type ;
using is_regular = std::true_type ;
typedef size_t size_type ;
typedef Dimension dimension_type ;
typedef Kokkos::LayoutStride array_layout ;
dimension_type m_dim ;
stride_type m_stride ;
//----------------------------------------
// rank 1
template< typename I0 >
KOKKOS_INLINE_FUNCTION constexpr
size_type operator()( I0 const & i0 ) const
{
return i0 * m_stride.S0 ;
}
// rank 2
template < typename I0 , typename I1 >
KOKKOS_INLINE_FUNCTION constexpr
size_type operator()( I0 const & i0 , I1 const & i1 ) const
{
return i0 * m_stride.S0 +
i1 * m_stride.S1 ;
}
//rank 3
template < typename I0, typename I1, typename I2 >
KOKKOS_INLINE_FUNCTION constexpr
size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2 ) const
{
return i0 * m_stride.S0 +
i1 * m_stride.S1 +
i2 * m_stride.S2 ;
}
//rank 4
template < typename I0, typename I1, typename I2, typename I3 >
KOKKOS_INLINE_FUNCTION constexpr
size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2, I3 const & i3 ) const
{
return i0 * m_stride.S0 +
i1 * m_stride.S1 +
i2 * m_stride.S2 +
i3 * m_stride.S3 ;
}
//rank 5
template < typename I0, typename I1, typename I2, typename I3
, typename I4 >
KOKKOS_INLINE_FUNCTION constexpr
size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2, I3 const & i3
, I4 const & i4 ) const
{
return i0 * m_stride.S0 +
i1 * m_stride.S1 +
i2 * m_stride.S2 +
i3 * m_stride.S3 +
i4 * m_stride.S4 ;
}
//rank 6
template < typename I0, typename I1, typename I2, typename I3
, typename I4, typename I5 >
KOKKOS_INLINE_FUNCTION constexpr
size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2, I3 const & i3
, I4 const & i4, I5 const & i5 ) const
{
return i0 * m_stride.S0 +
i1 * m_stride.S1 +
i2 * m_stride.S2 +
i3 * m_stride.S3 +
i4 * m_stride.S4 +
i5 * m_stride.S5 ;
}
//rank 7
template < typename I0, typename I1, typename I2, typename I3
, typename I4, typename I5, typename I6 >
KOKKOS_INLINE_FUNCTION constexpr
size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2, I3 const & i3
, I4 const & i4, I5 const & i5, I6 const & i6 ) const
{
return i0 * m_stride.S0 +
i1 * m_stride.S1 +
i2 * m_stride.S2 +
i3 * m_stride.S3 +
i4 * m_stride.S4 +
i5 * m_stride.S5 +
i6 * m_stride.S6 ;
}
//rank 8
template < typename I0, typename I1, typename I2, typename I3
, typename I4, typename I5, typename I6, typename I7 >
KOKKOS_INLINE_FUNCTION constexpr
size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2, I3 const & i3
, I4 const & i4, I5 const & i5, I6 const & i6, I7 const & i7 ) const
{
return i0 * m_stride.S0 +
i1 * m_stride.S1 +
i2 * m_stride.S2 +
i3 * m_stride.S3 +
i4 * m_stride.S4 +
i5 * m_stride.S5 +
i6 * m_stride.S6 +
i7 * m_stride.S7 ;
}
//----------------------------------------
KOKKOS_INLINE_FUNCTION
constexpr array_layout layout() const
{
return array_layout( m_dim.N0 , m_stride.S0
, m_dim.N1 , m_stride.S1
, m_dim.N2 , m_stride.S2
, m_dim.N3 , m_stride.S3
, m_dim.N4 , m_stride.S4
, m_dim.N5 , m_stride.S5
, m_dim.N6 , m_stride.S6
, m_dim.N7 , m_stride.S7
);
}
KOKKOS_INLINE_FUNCTION constexpr size_type dimension_0() const { return m_dim.N0 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type dimension_1() const { return m_dim.N1 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type dimension_2() const { return m_dim.N2 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type dimension_3() const { return m_dim.N3 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type dimension_4() const { return m_dim.N4 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type dimension_5() const { return m_dim.N5 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type dimension_6() const { return m_dim.N6 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type dimension_7() const { return m_dim.N7 ; }
/* Cardinality of the domain index space */
KOKKOS_INLINE_FUNCTION
constexpr size_type size() const
{ return m_dim.N0 * m_dim.N1 * m_dim.N2 * m_dim.N3 * m_dim.N4 * m_dim.N5 * m_dim.N6 * m_dim.N7 ; }
private:
KOKKOS_INLINE_FUNCTION
static constexpr size_type Max( size_type lhs , size_type rhs )
{ return lhs < rhs ? rhs : lhs ; }
public:
/* Span of the range space, largest stride * dimension */
KOKKOS_INLINE_FUNCTION
constexpr size_type span() const
{
return Max( m_dim.N0 * m_stride.S0 ,
Max( m_dim.N1 * m_stride.S1 ,
Max( m_dim.N2 * m_stride.S2 ,
Max( m_dim.N3 * m_stride.S3 ,
Max( m_dim.N4 * m_stride.S4 ,
Max( m_dim.N5 * m_stride.S5 ,
Max( m_dim.N6 * m_stride.S6 ,
m_dim.N7 * m_stride.S7 )))))));
}
KOKKOS_INLINE_FUNCTION constexpr bool span_is_contiguous() const { return span() == size(); }
/* Strides of dimensions */
KOKKOS_INLINE_FUNCTION constexpr size_type stride_0() const { return m_stride.S0 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type stride_1() const { return m_stride.S1 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type stride_2() const { return m_stride.S2 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type stride_3() const { return m_stride.S3 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type stride_4() const { return m_stride.S4 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type stride_5() const { return m_stride.S5 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type stride_6() const { return m_stride.S6 ; }
KOKKOS_INLINE_FUNCTION constexpr size_type stride_7() const { return m_stride.S7 ; }
// Stride with [ rank ] value is the total length
template< typename iType >
KOKKOS_INLINE_FUNCTION
void stride( iType * const s ) const
{
if ( 0 < dimension_type::rank ) { s[0] = m_stride.S0 ; }
if ( 1 < dimension_type::rank ) { s[1] = m_stride.S1 ; }
if ( 2 < dimension_type::rank ) { s[2] = m_stride.S2 ; }
if ( 3 < dimension_type::rank ) { s[3] = m_stride.S3 ; }
if ( 4 < dimension_type::rank ) { s[4] = m_stride.S4 ; }
if ( 5 < dimension_type::rank ) { s[5] = m_stride.S5 ; }
if ( 6 < dimension_type::rank ) { s[6] = m_stride.S6 ; }
if ( 7 < dimension_type::rank ) { s[7] = m_stride.S7 ; }
s[dimension_type::rank] = span();
}
//----------------------------------------
ViewOffset() = default ;
ViewOffset( const ViewOffset & ) = default ;
ViewOffset & operator = ( const ViewOffset & ) = default ;
KOKKOS_INLINE_FUNCTION
constexpr ViewOffset( std::integral_constant<unsigned,0> const &
, Kokkos::LayoutStride const & rhs )
: m_dim( rhs.dimension[0] , rhs.dimension[1] , rhs.dimension[2] , rhs.dimension[3]
, rhs.dimension[4] , rhs.dimension[5] , rhs.dimension[6] , rhs.dimension[7] )
, m_stride( rhs.stride[0] , rhs.stride[1] , rhs.stride[2] , rhs.stride[3]
, rhs.stride[4] , rhs.stride[5] , rhs.stride[6] , rhs.stride[7] )
{}
template< class DimRHS , class LayoutRHS >
KOKKOS_INLINE_FUNCTION
constexpr ViewOffset( const ViewOffset< DimRHS , LayoutRHS , void > & rhs )
: m_dim( rhs.m_dim.N0 , rhs.m_dim.N1 , rhs.m_dim.N2 , rhs.m_dim.N3
, rhs.m_dim.N4 , rhs.m_dim.N5 , rhs.m_dim.N6 , rhs.m_dim.N7 )
, m_stride( rhs.stride_0() , rhs.stride_1() , rhs.stride_2() , rhs.stride_3()
, rhs.stride_4() , rhs.stride_5() , rhs.stride_6() , rhs.stride_7() )
{
static_assert( int(DimRHS::rank) == int(dimension_type::rank) , "ViewOffset assignment requires equal rank" );
// Also requires equal static dimensions ...
}
//----------------------------------------
// Subview construction
private:
template< class DimRHS , class LayoutRHS >
KOKKOS_INLINE_FUNCTION static
constexpr size_t stride
( unsigned r , const ViewOffset< DimRHS , LayoutRHS , void > & rhs )
{
return r > 7 ? 0 : (
r == 0 ? rhs.stride_0() : (
r == 1 ? rhs.stride_1() : (
r == 2 ? rhs.stride_2() : (
r == 3 ? rhs.stride_3() : (
r == 4 ? rhs.stride_4() : (
r == 5 ? rhs.stride_5() : (
r == 6 ? rhs.stride_6() : rhs.stride_7() )))))));
}
public:
template< class DimRHS , class LayoutRHS >
KOKKOS_INLINE_FUNCTION
constexpr ViewOffset
( const ViewOffset< DimRHS , LayoutRHS , void > & rhs
, const SubviewExtents< DimRHS::rank , dimension_type::rank > & sub
)
// range_extent(r) returns 0 when dimension_type::rank <= r
: m_dim( sub.range_extent(0)
, sub.range_extent(1)
, sub.range_extent(2)
, sub.range_extent(3)
, sub.range_extent(4)
, sub.range_extent(5)
, sub.range_extent(6)
, sub.range_extent(7)
)
// range_index(r) returns ~0u when dimension_type::rank <= r
, m_stride( stride( sub.range_index(0), rhs )
, stride( sub.range_index(1), rhs )
, stride( sub.range_index(2), rhs )
, stride( sub.range_index(3), rhs )
, stride( sub.range_index(4), rhs )
, stride( sub.range_index(5), rhs )
, stride( sub.range_index(6), rhs )
, stride( sub.range_index(7), rhs )
)
{}
};
}} // namespace Kokkos::Impl
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
namespace Kokkos {
namespace Impl {
/** \brief ViewDataHandle provides the type of the 'data handle' which the view
* uses to access data with the [] operator. It also provides
* an allocate function and a function to extract a raw ptr from the
* data handle. ViewDataHandle also defines an enum ReferenceAble which
* specifies whether references/pointers to elements can be taken and a
* 'return_type' which is what the view operators will give back.
* Specialisation of this object allows three things depending
* on ViewTraits and compiler options:
* (i) Use special allocator (e.g. huge pages/small pages and pinned memory)
* (ii) Use special data handle type (e.g. add Cuda Texture Object)
* (iii) Use special access intrinsics (e.g. texture fetch and non-caching loads)
*/
template< class Traits , class Enable = void >
struct ViewDataHandle {
typedef typename Traits::value_type value_type ;
typedef typename Traits::value_type * handle_type ;
typedef typename Traits::value_type & return_type ;
typedef Kokkos::Impl::SharedAllocationTracker track_type ;
KOKKOS_INLINE_FUNCTION
static handle_type assign( value_type * arg_data_ptr
, track_type const & /*arg_tracker*/ )
{
return handle_type( arg_data_ptr );
}
KOKKOS_INLINE_FUNCTION
static handle_type assign( handle_type const arg_data_ptr
, size_t offset )
{
return handle_type( arg_data_ptr + offset );
}
};
template< class Traits >
struct ViewDataHandle< Traits ,
typename std::enable_if<( std::is_same< typename Traits::non_const_value_type
, typename Traits::value_type >::value
&&
std::is_same< typename Traits::specialize , void >::value
&&
Traits::memory_traits::Atomic
)>::type >
{
typedef typename Traits::value_type value_type ;
typedef typename Kokkos::Impl::AtomicViewDataHandle< Traits > handle_type ;
typedef typename Kokkos::Impl::AtomicDataElement< Traits > return_type ;
typedef Kokkos::Impl::SharedAllocationTracker track_type ;
KOKKOS_INLINE_FUNCTION
static handle_type assign( value_type * arg_data_ptr
, track_type const & /*arg_tracker*/ )
{
return handle_type( arg_data_ptr );
}
template<class SrcHandleType>
KOKKOS_INLINE_FUNCTION
static handle_type assign( const SrcHandleType& arg_handle
, size_t offset )
{
return handle_type( arg_handle.ptr + offset );
}
};
template< class Traits >
struct ViewDataHandle< Traits ,
typename std::enable_if<(
std::is_same< typename Traits::specialize , void >::value
&&
(!Traits::memory_traits::Aligned)
&&
Traits::memory_traits::Restrict
#ifdef KOKKOS_ENABLE_CUDA
&&
(!( std::is_same< typename Traits::memory_space,Kokkos::CudaSpace>::value ||
std::is_same< typename Traits::memory_space,Kokkos::CudaUVMSpace>::value ))
#endif
&&
(!Traits::memory_traits::Atomic)
)>::type >
{
typedef typename Traits::value_type value_type ;
typedef typename Traits::value_type * KOKKOS_RESTRICT handle_type ;
typedef typename Traits::value_type & KOKKOS_RESTRICT return_type ;
typedef Kokkos::Impl::SharedAllocationTracker track_type ;
KOKKOS_INLINE_FUNCTION
static handle_type assign( value_type * arg_data_ptr
, track_type const & /*arg_tracker*/ )
{
return handle_type( arg_data_ptr );
}
KOKKOS_INLINE_FUNCTION
static handle_type assign( handle_type const arg_data_ptr
, size_t offset )
{
return handle_type( arg_data_ptr + offset );
}
};
template< class Traits >
struct ViewDataHandle< Traits ,
typename std::enable_if<(
std::is_same< typename Traits::specialize , void >::value
&&
Traits::memory_traits::Aligned
&&
(!Traits::memory_traits::Restrict)
#ifdef KOKKOS_ENABLE_CUDA
&&
(!( std::is_same< typename Traits::memory_space,Kokkos::CudaSpace>::value ||
std::is_same< typename Traits::memory_space,Kokkos::CudaUVMSpace>::value ))
#endif
&&
(!Traits::memory_traits::Atomic)
)>::type >
{
typedef typename Traits::value_type value_type ;
typedef typename Traits::value_type * KOKKOS_ALIGN_PTR(KOKKOS_ALIGN_SIZE) handle_type ;
typedef typename Traits::value_type & return_type ;
typedef Kokkos::Impl::SharedAllocationTracker track_type ;
KOKKOS_INLINE_FUNCTION
static handle_type assign( value_type * arg_data_ptr
, track_type const & /*arg_tracker*/ )
{
if ( reinterpret_cast<uintptr_t>(arg_data_ptr) % KOKKOS_ALIGN_SIZE ) {
Kokkos::abort("Assigning NonAligned View or Pointer to Kokkos::View with Aligned attribute");
}
return handle_type( arg_data_ptr );
}
KOKKOS_INLINE_FUNCTION
static handle_type assign( handle_type const arg_data_ptr
, size_t offset )
{
if ( reinterpret_cast<uintptr_t>(arg_data_ptr+offset) % KOKKOS_ALIGN_SIZE ) {
Kokkos::abort("Assigning NonAligned View or Pointer to Kokkos::View with Aligned attribute");
}
return handle_type( arg_data_ptr + offset );
}
};
template< class Traits >
struct ViewDataHandle< Traits ,
typename std::enable_if<(
std::is_same< typename Traits::specialize , void >::value
&&
Traits::memory_traits::Aligned
&&
Traits::memory_traits::Restrict
#ifdef KOKKOS_ENABLE_CUDA
&&
(!( std::is_same< typename Traits::memory_space,Kokkos::CudaSpace>::value ||
std::is_same< typename Traits::memory_space,Kokkos::CudaUVMSpace>::value ))
#endif
&&
(!Traits::memory_traits::Atomic)
)>::type >
{
typedef typename Traits::value_type value_type ;
typedef typename Traits::value_type * KOKKOS_RESTRICT KOKKOS_ALIGN_PTR(KOKKOS_ALIGN_SIZE) handle_type ;
typedef typename Traits::value_type & return_type ;
typedef Kokkos::Impl::SharedAllocationTracker track_type ;
KOKKOS_INLINE_FUNCTION
static handle_type assign( value_type * arg_data_ptr
, track_type const & /*arg_tracker*/ )
{
if ( reinterpret_cast<uintptr_t>(arg_data_ptr) % KOKKOS_ALIGN_SIZE ) {
Kokkos::abort("Assigning NonAligned View or Pointer to Kokkos::View with Aligned attribute");
}
return handle_type( arg_data_ptr );
}
KOKKOS_INLINE_FUNCTION
static handle_type assign( handle_type const arg_data_ptr
, size_t offset )
{
if ( reinterpret_cast<uintptr_t>(arg_data_ptr+offset) % KOKKOS_ALIGN_SIZE ) {
Kokkos::abort("Assigning NonAligned View or Pointer to Kokkos::View with Aligned attribute");
}
return handle_type( arg_data_ptr + offset );
}
};
}} // namespace Kokkos::Impl
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
namespace Kokkos {
namespace Impl {
//----------------------------------------------------------------------------
/*
* The construction, assignment to default, and destruction
* are merged into a single functor.
* Primarily to work around an unresolved CUDA back-end bug
* that would lose the destruction cuda device function when
* called from the shared memory tracking destruction.
* Secondarily to have two fewer partial specializations.
*/
template< class ExecSpace
, class ValueType
, bool IsScalar = std::is_scalar< ValueType >::value
>
struct ViewValueFunctor ;
template< class ExecSpace , class ValueType >
struct ViewValueFunctor< ExecSpace , ValueType , false /* is_scalar */ >
{
typedef Kokkos::RangePolicy< ExecSpace > PolicyType ;
typedef typename ExecSpace::execution_space Exec;
Exec space ;
ValueType * ptr ;
size_t n ;
bool destroy ;
KOKKOS_INLINE_FUNCTION
void operator()( const size_t i ) const
{
if ( destroy ) { (ptr+i)->~ValueType(); } //KOKKOS_IMPL_CUDA_CLANG_WORKAROUND this line causes ptax error __cxa_begin_catch in nested_view unit-test
else { new (ptr+i) ValueType(); }
}
ViewValueFunctor() = default ;
ViewValueFunctor( const ViewValueFunctor & ) = default ;
ViewValueFunctor & operator = ( const ViewValueFunctor & ) = default ;
ViewValueFunctor( ExecSpace const & arg_space
, ValueType * const arg_ptr
, size_t const arg_n )
: space( arg_space )
, ptr( arg_ptr )
, n( arg_n )
, destroy( false )
{}
void execute( bool arg )
{
destroy = arg ;
if ( ! space.in_parallel() ) {
#if defined(KOKKOS_ENABLE_PROFILING)
uint64_t kpID = 0;
if(Kokkos::Profiling::profileLibraryLoaded()) {
Kokkos::Profiling::beginParallelFor("Kokkos::View::initialization", 0, &kpID);
}
#endif
const Kokkos::Impl::ParallelFor< ViewValueFunctor , PolicyType >
closure( *this , PolicyType( 0 , n ) );
closure.execute();
space.fence();
#if defined(KOKKOS_ENABLE_PROFILING)
if(Kokkos::Profiling::profileLibraryLoaded()) {
Kokkos::Profiling::endParallelFor(kpID);
}
#endif
}
else {
for ( size_t i = 0 ; i < n ; ++i ) operator()(i);
}
}
void construct_shared_allocation()
{ execute( false ); }
void destroy_shared_allocation()
{ execute( true ); }
};
template< class ExecSpace , class ValueType >
struct ViewValueFunctor< ExecSpace , ValueType , true /* is_scalar */ >
{
typedef Kokkos::RangePolicy< ExecSpace > PolicyType ;
ExecSpace space ;
ValueType * ptr ;
size_t n ;
KOKKOS_INLINE_FUNCTION
void operator()( const size_t i ) const
{ ptr[i] = ValueType(); }
ViewValueFunctor() = default ;
ViewValueFunctor( const ViewValueFunctor & ) = default ;
ViewValueFunctor & operator = ( const ViewValueFunctor & ) = default ;
ViewValueFunctor( ExecSpace const & arg_space
, ValueType * const arg_ptr
, size_t const arg_n )
: space( arg_space )
, ptr( arg_ptr )
, n( arg_n )
{}
void construct_shared_allocation()
{
if ( ! space.in_parallel() ) {
#if defined(KOKKOS_ENABLE_PROFILING)
uint64_t kpID = 0;
if(Kokkos::Profiling::profileLibraryLoaded()) {
Kokkos::Profiling::beginParallelFor("Kokkos::View::initialization", 0, &kpID);
}
#endif
const Kokkos::Impl::ParallelFor< ViewValueFunctor , PolicyType >
closure( *this , PolicyType( 0 , n ) );
closure.execute();
space.fence();
#if defined(KOKKOS_ENABLE_PROFILING)
if(Kokkos::Profiling::profileLibraryLoaded()) {
Kokkos::Profiling::endParallelFor(kpID);
}
#endif
}
else {
for ( size_t i = 0 ; i < n ; ++i ) operator()(i);
}
}
void destroy_shared_allocation() {}
};
//----------------------------------------------------------------------------
/** \brief View mapping for non-specialized data type and standard layout */
template< class Traits >
class ViewMapping< Traits ,
typename std::enable_if<(
std::is_same< typename Traits::specialize , void >::value
&&
ViewOffset< typename Traits::dimension
, typename Traits::array_layout
, void >::is_mapping_plugin::value
)>::type >
{
private:
template< class , class ... > friend class ViewMapping ;
template< class , class ... > friend class Kokkos::View ;
typedef ViewOffset< typename Traits::dimension
, typename Traits::array_layout
, void
> offset_type ;
typedef typename ViewDataHandle< Traits >::handle_type handle_type ;
handle_type m_handle ;
offset_type m_offset ;
KOKKOS_INLINE_FUNCTION
ViewMapping( const handle_type & arg_handle , const offset_type & arg_offset )
: m_handle( arg_handle )
, m_offset( arg_offset )
{}
public:
typedef void printable_label_typedef;
enum { is_managed = Traits::is_managed };
//----------------------------------------
// Domain dimensions
enum { Rank = Traits::dimension::rank };
template< typename iType >
KOKKOS_INLINE_FUNCTION constexpr size_t extent( const iType & r ) const
{ return m_offset.m_dim.extent(r); }
KOKKOS_INLINE_FUNCTION constexpr
typename Traits::array_layout layout() const
{ return m_offset.layout(); }
KOKKOS_INLINE_FUNCTION constexpr size_t dimension_0() const { return m_offset.dimension_0(); }
KOKKOS_INLINE_FUNCTION constexpr size_t dimension_1() const { return m_offset.dimension_1(); }
KOKKOS_INLINE_FUNCTION constexpr size_t dimension_2() const { return m_offset.dimension_2(); }
KOKKOS_INLINE_FUNCTION constexpr size_t dimension_3() const { return m_offset.dimension_3(); }
KOKKOS_INLINE_FUNCTION constexpr size_t dimension_4() const { return m_offset.dimension_4(); }
KOKKOS_INLINE_FUNCTION constexpr size_t dimension_5() const { return m_offset.dimension_5(); }
KOKKOS_INLINE_FUNCTION constexpr size_t dimension_6() const { return m_offset.dimension_6(); }
KOKKOS_INLINE_FUNCTION constexpr size_t dimension_7() const { return m_offset.dimension_7(); }
// Is a regular layout with uniform striding for each index.
using is_regular = typename offset_type::is_regular ;
KOKKOS_INLINE_FUNCTION constexpr size_t stride_0() const { return m_offset.stride_0(); }
KOKKOS_INLINE_FUNCTION constexpr size_t stride_1() const { return m_offset.stride_1(); }
KOKKOS_INLINE_FUNCTION constexpr size_t stride_2() const { return m_offset.stride_2(); }
KOKKOS_INLINE_FUNCTION constexpr size_t stride_3() const { return m_offset.stride_3(); }
KOKKOS_INLINE_FUNCTION constexpr size_t stride_4() const { return m_offset.stride_4(); }
KOKKOS_INLINE_FUNCTION constexpr size_t stride_5() const { return m_offset.stride_5(); }
KOKKOS_INLINE_FUNCTION constexpr size_t stride_6() const { return m_offset.stride_6(); }
KOKKOS_INLINE_FUNCTION constexpr size_t stride_7() const { return m_offset.stride_7(); }
template< typename iType >
KOKKOS_INLINE_FUNCTION void stride( iType * const s ) const { m_offset.stride(s); }
//----------------------------------------
// Range span
/** \brief Span of the mapped range */
KOKKOS_INLINE_FUNCTION constexpr size_t span() const { return m_offset.span(); }
/** \brief Is the mapped range span contiguous */
KOKKOS_INLINE_FUNCTION constexpr bool span_is_contiguous() const { return m_offset.span_is_contiguous(); }
typedef typename ViewDataHandle< Traits >::return_type reference_type ;
typedef typename Traits::value_type * pointer_type ;
/** \brief Query raw pointer to memory */
KOKKOS_INLINE_FUNCTION constexpr pointer_type data() const
{
return m_handle;
}
//----------------------------------------
// The View class performs all rank and bounds checking before
// calling these element reference methods.
KOKKOS_FORCEINLINE_FUNCTION
reference_type reference() const { return m_handle[0]; }
template< typename I0 >
KOKKOS_FORCEINLINE_FUNCTION
typename
std::enable_if< std::is_integral<I0>::value &&
! std::is_same< typename Traits::array_layout , Kokkos::LayoutStride >::value
, reference_type >::type
reference( const I0 & i0 ) const { return m_handle[i0]; }
template< typename I0 >
KOKKOS_FORCEINLINE_FUNCTION
typename
std::enable_if< std::is_integral<I0>::value &&
std::is_same< typename Traits::array_layout , Kokkos::LayoutStride >::value
, reference_type >::type
reference( const I0 & i0 ) const { return m_handle[ m_offset(i0) ]; }
template< typename I0 , typename I1 >
KOKKOS_FORCEINLINE_FUNCTION
reference_type reference( const I0 & i0 , const I1 & i1 ) const
{ return m_handle[ m_offset(i0,i1) ]; }
template< typename I0 , typename I1 , typename I2 >
KOKKOS_FORCEINLINE_FUNCTION
reference_type reference( const I0 & i0 , const I1 & i1 , const I2 & i2 ) const
{ return m_handle[ m_offset(i0,i1,i2) ]; }
template< typename I0 , typename I1 , typename I2 , typename I3 >
KOKKOS_FORCEINLINE_FUNCTION
reference_type reference( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3 ) const
{ return m_handle[ m_offset(i0,i1,i2,i3) ]; }
template< typename I0 , typename I1 , typename I2 , typename I3
, typename I4 >
KOKKOS_FORCEINLINE_FUNCTION
reference_type reference( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3
, const I4 & i4 ) const
{ return m_handle[ m_offset(i0,i1,i2,i3,i4) ]; }
template< typename I0 , typename I1 , typename I2 , typename I3
, typename I4 , typename I5 >
KOKKOS_FORCEINLINE_FUNCTION
reference_type reference( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3
, const I4 & i4 , const I5 & i5 ) const
{ return m_handle[ m_offset(i0,i1,i2,i3,i4,i5) ]; }
template< typename I0 , typename I1 , typename I2 , typename I3
, typename I4 , typename I5 , typename I6 >
KOKKOS_FORCEINLINE_FUNCTION
reference_type reference( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3
, const I4 & i4 , const I5 & i5 , const I6 & i6 ) const
{ return m_handle[ m_offset(i0,i1,i2,i3,i4,i5,i6) ]; }
template< typename I0 , typename I1 , typename I2 , typename I3
, typename I4 , typename I5 , typename I6 , typename I7 >
KOKKOS_FORCEINLINE_FUNCTION
reference_type reference( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3
, const I4 & i4 , const I5 & i5 , const I6 & i6 , const I7 & i7 ) const
{ return m_handle[ m_offset(i0,i1,i2,i3,i4,i5,i6,i7) ]; }
//----------------------------------------
private:
enum { MemorySpanMask = 8 - 1 /* Force alignment on 8 byte boundary */ };
enum { MemorySpanSize = sizeof(typename Traits::value_type) };
public:
/** \brief Span, in bytes, of the referenced memory */
KOKKOS_INLINE_FUNCTION constexpr size_t memory_span() const
{
return ( m_offset.span() * sizeof(typename Traits::value_type) + MemorySpanMask ) & ~size_t(MemorySpanMask);
}
//----------------------------------------
KOKKOS_INLINE_FUNCTION ~ViewMapping() {}
KOKKOS_INLINE_FUNCTION ViewMapping() : m_handle(), m_offset() {}
KOKKOS_INLINE_FUNCTION ViewMapping( const ViewMapping & rhs )
: m_handle( rhs.m_handle ), m_offset( rhs.m_offset ) {}
KOKKOS_INLINE_FUNCTION ViewMapping & operator = ( const ViewMapping & rhs )
{ m_handle = rhs.m_handle ; m_offset = rhs.m_offset ; return *this ; }
KOKKOS_INLINE_FUNCTION ViewMapping( ViewMapping && rhs )
: m_handle( rhs.m_handle ), m_offset( rhs.m_offset ) {}
KOKKOS_INLINE_FUNCTION ViewMapping & operator = ( ViewMapping && rhs )
{ m_handle = rhs.m_handle ; m_offset = rhs.m_offset ; return *this ; }
//----------------------------------------
/**\brief Span, in bytes, of the required memory */
KOKKOS_INLINE_FUNCTION
static constexpr size_t memory_span( typename Traits::array_layout const & arg_layout )
{
typedef std::integral_constant< unsigned , 0 > padding ;
return ( offset_type( padding(), arg_layout ).span() * MemorySpanSize + MemorySpanMask ) & ~size_t(MemorySpanMask);
}
/**\brief Wrap a span of memory */
template< class ... P >
KOKKOS_INLINE_FUNCTION
ViewMapping( Kokkos::Impl::ViewCtorProp< P ... > const & arg_prop
, typename Traits::array_layout const & arg_layout
)
: m_handle( ( (Kokkos::Impl::ViewCtorProp<void,pointer_type> const &) arg_prop ).value )
, m_offset( std::integral_constant< unsigned , 0 >() , arg_layout )
{}
//----------------------------------------
/* Allocate and construct mapped array.
* Allocate via shared allocation record and
* return that record for allocation tracking.
*/
template< class ... P >
Kokkos::Impl::SharedAllocationRecord<> *
allocate_shared( Kokkos::Impl::ViewCtorProp< P... > const & arg_prop
, typename Traits::array_layout const & arg_layout )
{
typedef Kokkos::Impl::ViewCtorProp< P... > alloc_prop ;
typedef typename alloc_prop::execution_space execution_space ;
typedef typename Traits::memory_space memory_space ;
typedef typename Traits::value_type value_type ;
typedef ViewValueFunctor< execution_space , value_type > functor_type ;
typedef Kokkos::Impl::SharedAllocationRecord< memory_space , functor_type > record_type ;
// Query the mapping for byte-size of allocation.
// If padding is allowed then pass in sizeof value type
// for padding computation.
typedef std::integral_constant
< unsigned
, alloc_prop::allow_padding ? sizeof(value_type) : 0
> padding ;
m_offset = offset_type( padding(), arg_layout );
const size_t alloc_size =
( m_offset.span() * MemorySpanSize + MemorySpanMask ) & ~size_t(MemorySpanMask);
// Create shared memory tracking record with allocate memory from the memory space
record_type * const record =
record_type::allocate( ( (Kokkos::Impl::ViewCtorProp<void,memory_space> const &) arg_prop ).value
, ( (Kokkos::Impl::ViewCtorProp<void,std::string> const &) arg_prop ).value
, alloc_size );
// Only set the the pointer and initialize if the allocation is non-zero.
// May be zero if one of the dimensions is zero.
if ( alloc_size ) {
m_handle = handle_type( reinterpret_cast< pointer_type >( record->data() ) );
if ( alloc_prop::initialize ) {
// Assume destruction is only required when construction is requested.
// The ViewValueFunctor has both value construction and destruction operators.
record->m_destroy = functor_type( ( (Kokkos::Impl::ViewCtorProp<void,execution_space> const &) arg_prop).value
, (value_type *) m_handle
, m_offset.span()
);
// Construct values
record->m_destroy.construct_shared_allocation();
}
}
return record ;
}
};
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
/** \brief Assign compatible default mappings */
template< class DstTraits , class SrcTraits >
class ViewMapping< DstTraits , SrcTraits ,
typename std::enable_if<(
/* default mappings */
std::is_same< typename DstTraits::specialize , void >::value
&&
std::is_same< typename SrcTraits::specialize , void >::value
&&
(
/* same layout */
std::is_same< typename DstTraits::array_layout , typename SrcTraits::array_layout >::value
||
/* known layout */
(
(
std::is_same< typename DstTraits::array_layout , Kokkos::LayoutLeft >::value ||
std::is_same< typename DstTraits::array_layout , Kokkos::LayoutRight >::value ||
std::is_same< typename DstTraits::array_layout , Kokkos::LayoutStride >::value
)
&&
(
std::is_same< typename SrcTraits::array_layout , Kokkos::LayoutLeft >::value ||
std::is_same< typename SrcTraits::array_layout , Kokkos::LayoutRight >::value ||
std::is_same< typename SrcTraits::array_layout , Kokkos::LayoutStride >::value
)
)
)
)>::type >
{
private:
enum { is_assignable_space =
#if 1
Kokkos::Impl::MemorySpaceAccess
< typename DstTraits::memory_space
, typename SrcTraits::memory_space >::assignable };
#else
std::is_same< typename DstTraits::memory_space
, typename SrcTraits::memory_space >::value };
#endif
enum { is_assignable_value_type =
std::is_same< typename DstTraits::value_type
, typename SrcTraits::value_type >::value ||
std::is_same< typename DstTraits::value_type
, typename SrcTraits::const_value_type >::value };
enum { is_assignable_dimension =
ViewDimensionAssignable< typename DstTraits::dimension
, typename SrcTraits::dimension >::value };
enum { is_assignable_layout =
std::is_same< typename DstTraits::array_layout
, typename SrcTraits::array_layout >::value ||
std::is_same< typename DstTraits::array_layout
, Kokkos::LayoutStride >::value ||
( DstTraits::dimension::rank == 0 ) ||
( DstTraits::dimension::rank == 1 &&
DstTraits::dimension::rank_dynamic == 1 )
};
public:
enum { is_assignable = is_assignable_space &&
is_assignable_value_type &&
is_assignable_dimension &&
is_assignable_layout };
typedef Kokkos::Impl::SharedAllocationTracker TrackType ;
typedef ViewMapping< DstTraits , void > DstType ;
typedef ViewMapping< SrcTraits , void > SrcType ;
KOKKOS_INLINE_FUNCTION
static void assign( DstType & dst , const SrcType & src , const TrackType & src_track )
{
static_assert( is_assignable_space
, "View assignment must have compatible spaces" );
static_assert( is_assignable_value_type
, "View assignment must have same value type or const = non-const" );
static_assert( is_assignable_dimension
, "View assignment must have compatible dimensions" );
static_assert( is_assignable_layout
, "View assignment must have compatible layout or have rank <= 1" );
typedef typename DstType::offset_type dst_offset_type ;
if ( size_t(DstTraits::dimension::rank_dynamic) < size_t(SrcTraits::dimension::rank_dynamic) ) {
typedef typename DstTraits::dimension dst_dim;
bool assignable =
( ( 1 > DstTraits::dimension::rank_dynamic && 1 <= SrcTraits::dimension::rank_dynamic ) ?
dst_dim::ArgN0 == src.dimension_0() : true ) &&
( ( 2 > DstTraits::dimension::rank_dynamic && 2 <= SrcTraits::dimension::rank_dynamic ) ?
dst_dim::ArgN1 == src.dimension_1() : true ) &&
( ( 3 > DstTraits::dimension::rank_dynamic && 3 <= SrcTraits::dimension::rank_dynamic ) ?
dst_dim::ArgN2 == src.dimension_2() : true ) &&
( ( 4 > DstTraits::dimension::rank_dynamic && 4 <= SrcTraits::dimension::rank_dynamic ) ?
dst_dim::ArgN3 == src.dimension_3() : true ) &&
( ( 5 > DstTraits::dimension::rank_dynamic && 5 <= SrcTraits::dimension::rank_dynamic ) ?
dst_dim::ArgN4 == src.dimension_4() : true ) &&
( ( 6 > DstTraits::dimension::rank_dynamic && 6 <= SrcTraits::dimension::rank_dynamic ) ?
dst_dim::ArgN5 == src.dimension_5() : true ) &&
( ( 7 > DstTraits::dimension::rank_dynamic && 7 <= SrcTraits::dimension::rank_dynamic ) ?
dst_dim::ArgN6 == src.dimension_6() : true ) &&
( ( 8 > DstTraits::dimension::rank_dynamic && 8 <= SrcTraits::dimension::rank_dynamic ) ?
dst_dim::ArgN7 == src.dimension_7() : true )
;
if(!assignable)
Kokkos::abort("View Assignment: trying to assign runtime dimension to non matching compile time dimension.");
}
dst.m_offset = dst_offset_type( src.m_offset );
dst.m_handle = Kokkos::Impl::ViewDataHandle< DstTraits >::assign( src.m_handle , src_track );
}
};
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
// Subview mapping.
// Deduce destination view type from source view traits and subview arguments
template< class SrcTraits , class ... Args >
struct ViewMapping
< typename std::enable_if<(
std::is_same< typename SrcTraits::specialize , void >::value
&&
(
std::is_same< typename SrcTraits::array_layout
, Kokkos::LayoutLeft >::value ||
std::is_same< typename SrcTraits::array_layout
, Kokkos::LayoutRight >::value ||
std::is_same< typename SrcTraits::array_layout
, Kokkos::LayoutStride >::value
)
)>::type
, SrcTraits
, Args ... >
{
private:
static_assert( SrcTraits::rank == sizeof...(Args) ,
"Subview mapping requires one argument for each dimension of source View" );
enum
{ RZ = false
, R0 = bool(is_integral_extent<0,Args...>::value)
, R1 = bool(is_integral_extent<1,Args...>::value)
, R2 = bool(is_integral_extent<2,Args...>::value)
, R3 = bool(is_integral_extent<3,Args...>::value)
, R4 = bool(is_integral_extent<4,Args...>::value)
, R5 = bool(is_integral_extent<5,Args...>::value)
, R6 = bool(is_integral_extent<6,Args...>::value)
, R7 = bool(is_integral_extent<7,Args...>::value)
};
enum { rank = unsigned(R0) + unsigned(R1) + unsigned(R2) + unsigned(R3)
+ unsigned(R4) + unsigned(R5) + unsigned(R6) + unsigned(R7) };
// Whether right-most rank is a range.
enum { R0_rev = ( 0 == SrcTraits::rank ? RZ : (
1 == SrcTraits::rank ? R0 : (
2 == SrcTraits::rank ? R1 : (
3 == SrcTraits::rank ? R2 : (
4 == SrcTraits::rank ? R3 : (
5 == SrcTraits::rank ? R4 : (
6 == SrcTraits::rank ? R5 : (
7 == SrcTraits::rank ? R6 : R7 )))))))) };
// Subview's layout
typedef typename std::conditional<
( /* Same array layout IF */
( rank == 0 ) /* output rank zero */
||
SubviewLegalArgsCompileTime<typename SrcTraits::array_layout, typename SrcTraits::array_layout,
rank, SrcTraits::rank, 0, Args...>::value
||
// OutputRank 1 or 2, InputLayout Left, Interval 0
// because single stride one or second index has a stride.
( rank <= 2 && R0 && std::is_same< typename SrcTraits::array_layout , Kokkos::LayoutLeft >::value ) //replace with input rank
||
// OutputRank 1 or 2, InputLayout Right, Interval [InputRank-1]
// because single stride one or second index has a stride.
( rank <= 2 && R0_rev && std::is_same< typename SrcTraits::array_layout , Kokkos::LayoutRight >::value ) //replace input rank
), typename SrcTraits::array_layout , Kokkos::LayoutStride
>::type array_layout ;
typedef typename SrcTraits::value_type value_type ;
typedef typename std::conditional< rank == 0 , value_type ,
typename std::conditional< rank == 1 , value_type * ,
typename std::conditional< rank == 2 , value_type ** ,
typename std::conditional< rank == 3 , value_type *** ,
typename std::conditional< rank == 4 , value_type **** ,
typename std::conditional< rank == 5 , value_type ***** ,
typename std::conditional< rank == 6 , value_type ****** ,
typename std::conditional< rank == 7 , value_type ******* ,
value_type ********
>::type >::type >::type >::type >::type >::type >::type >::type
data_type ;
public:
typedef Kokkos::ViewTraits
< data_type
, array_layout
, typename SrcTraits::device_type
, typename SrcTraits::memory_traits > traits_type ;
typedef Kokkos::View
< data_type
, array_layout
, typename SrcTraits::device_type
, typename SrcTraits::memory_traits > type ;
template< class MemoryTraits >
struct apply {
static_assert( Kokkos::Impl::is_memory_traits< MemoryTraits >::value , "" );
typedef Kokkos::ViewTraits
< data_type
, array_layout
, typename SrcTraits::device_type
, MemoryTraits > traits_type ;
typedef Kokkos::View
< data_type
, array_layout
, typename SrcTraits::device_type
, MemoryTraits > type ;
};
// The presumed type is 'ViewMapping< traits_type , void >'
// However, a compatible ViewMapping is acceptable.
template< class DstTraits >
KOKKOS_INLINE_FUNCTION
static void assign( ViewMapping< DstTraits , void > & dst
, ViewMapping< SrcTraits , void > const & src
, Args ... args )
{
static_assert(
ViewMapping< DstTraits , traits_type , void >::is_assignable ,
"Subview destination type must be compatible with subview derived type" );
typedef ViewMapping< DstTraits , void > DstType ;
typedef typename DstType::offset_type dst_offset_type ;
const SubviewExtents< SrcTraits::rank , rank >
extents( src.m_offset.m_dim , args... );
dst.m_offset = dst_offset_type( src.m_offset , extents );
dst.m_handle = ViewDataHandle< DstTraits >::assign(src.m_handle,
src.m_offset( extents.domain_offset(0)
, extents.domain_offset(1)
, extents.domain_offset(2)
, extents.domain_offset(3)
, extents.domain_offset(4)
, extents.domain_offset(5)
, extents.domain_offset(6)
, extents.domain_offset(7)
));
}
};
//----------------------------------------------------------------------------
}} // namespace Kokkos::Impl
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
namespace Kokkos {
namespace Impl {
template< unsigned , class MapType >
KOKKOS_INLINE_FUNCTION
bool view_verify_operator_bounds( const MapType & )
{ return true ; }
template< unsigned R , class MapType , class iType , class ... Args >
KOKKOS_INLINE_FUNCTION
bool view_verify_operator_bounds
( const MapType & map
, const iType & i
, Args ... args
)
{
return ( size_t(i) < map.extent(R) )
&& view_verify_operator_bounds<R+1>( map , args ... );
}
template< unsigned , class MapType >
inline
void view_error_operator_bounds( char * , int , const MapType & )
{}
template< unsigned R , class MapType , class iType , class ... Args >
inline
void view_error_operator_bounds
( char * buf
, int len
, const MapType & map
, const iType & i
, Args ... args
)
{
const int n =
snprintf(buf,len," %ld < %ld %c"
, static_cast<unsigned long>(i)
, static_cast<unsigned long>( map.extent(R) )
, ( sizeof...(Args) ? ',' : ')' )
);
view_error_operator_bounds<R+1>(buf+n,len-n,map,args...);
}
#if ! defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
/* Check #3: is the View managed as determined by the MemoryTraits? */
template< class MapType,
bool is_managed = (MapType::is_managed != 0) >
struct OperatorBoundsErrorOnDevice;
template< class MapType >
struct OperatorBoundsErrorOnDevice< MapType, false > {
KOKKOS_INLINE_FUNCTION
static void run(MapType const&) {
Kokkos::abort("View bounds error");
}
};
template< class MapType >
struct OperatorBoundsErrorOnDevice< MapType, true > {
KOKKOS_INLINE_FUNCTION
static void run(MapType const& map) {
char const* const user_alloc_start = reinterpret_cast<char const*>(map.data());
char const* const header_start = user_alloc_start - sizeof(SharedAllocationHeader);
SharedAllocationHeader const* const header =
reinterpret_cast<SharedAllocationHeader const*>(header_start);
char const* const label = header->label();
enum { LEN = 128 };
char msg[LEN];
char const* const first_part = "View bounds error of view ";
char* p = msg;
char* const end = msg + LEN - 1;
for (char const* p2 = first_part; (*p2 != '\0') && (p < end); ++p, ++p2) {
*p = *p2;
}
for (char const* p2 = label; (*p2 != '\0') && (p < end); ++p, ++p2) {
*p = *p2;
}
*p = '\0';
Kokkos::abort(msg);
}
};
/* Check #2: does the ViewMapping have the printable_label_typedef defined?
See above that only the non-specialized standard-layout ViewMapping has
this defined by default.
The existence of this typedef indicates the existence of MapType::is_managed */
template< class T, class Enable = void >
struct has_printable_label_typedef : public std::false_type {};
template<class T>
struct has_printable_label_typedef<
T, typename enable_if_type<typename T::printable_label_typedef>::type>
: public std::true_type
{};
template< class MapType >
KOKKOS_INLINE_FUNCTION
void operator_bounds_error_on_device(
MapType const&,
std::false_type) {
Kokkos::abort("View bounds error");
}
template< class MapType >
KOKKOS_INLINE_FUNCTION
void operator_bounds_error_on_device(
MapType const& map,
std::true_type) {
OperatorBoundsErrorOnDevice< MapType >::run(map);
}
#endif // ! defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
template< class MemorySpace , class MapType , class ... Args >
KOKKOS_INLINE_FUNCTION
void view_verify_operator_bounds
( Kokkos::Impl::SharedAllocationTracker const & tracker
, const MapType & map , Args ... args )
{
if ( ! view_verify_operator_bounds<0>( map , args ... ) ) {
#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
enum { LEN = 1024 };
char buffer[ LEN ];
const std::string label = tracker.template get_label<MemorySpace>();
int n = snprintf(buffer,LEN,"View bounds error of view %s (",label.c_str());
view_error_operator_bounds<0>( buffer + n , LEN - n , map , args ... );
Kokkos::Impl::throw_runtime_exception(std::string(buffer));
#else
/* Check #1: is there a SharedAllocationRecord?
(we won't use it, but if its not there then there isn't
a corresponding SharedAllocationHeader containing a label).
This check should cover the case of Views that don't
have the Unmanaged trait but were initialized by pointer. */
if (tracker.has_record()) {
operator_bounds_error_on_device<MapType>(
map, has_printable_label_typedef<MapType>());
} else {
Kokkos::abort("View bounds error");
}
#endif
}
}
} /* namespace Impl */
} /* namespace Kokkos */
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
#endif /* #ifndef KOKKOS_EXPERIMENTAL_VIEW_MAPPING_HPP */

Event Timeline