Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F122055203
Kokkos_ViewMapping.hpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Tue, Jul 15, 12:30
Size
120 KB
Mime Type
text/x-c
Expires
Thu, Jul 17, 12:30 (2 d)
Engine
blob
Format
Raw Data
Handle
27428357
Attached To
rLAMMPS lammps
Kokkos_ViewMapping.hpp
View Options
/*
//@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
Log In to Comment