Skip to content

Instantly share code, notes, and snippets.

@parsa
Created November 22, 2019 18:34
Show Gist options
  • Save parsa/382f5e0729f95d225c3f6f57463eafae to your computer and use it in GitHub Desktop.
Save parsa/382f5e0729f95d225c3f6f57463eafae to your computer and use it in GitHub Desktop.
Single-Header distribution of https://github.com/kokkos/mdspan
#pragma once
#include <type_traits> // std::is_void
#include <cstddef>
#include <type_traits>
#include <utility> // integer_sequence
#include <type_traits>
#include <array>
#include <utility>
#include <cstddef>
#include <cstddef> // ptrdiff_t
#include <utility> // integer_sequence
#include <array>
#include <cstddef>
#include <type_traits>
#include <utility>
#include <cstddef>
#include <array>
#include <utility> // make_index_sequence
#include <tuple> // std::apply
#include <algorithm>
#include <numeric>
#include <array>
#include <tuple> // std::apply
#include <utility> // std::pair
/*
//@HEADER
// ************************************************************************
//
// Kokkos v. 2.0
// Copyright (2019) 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 Christian R. Trott ([email protected])
//
// ************************************************************************
//@HEADER
*/
/*
//@HEADER
// ************************************************************************
//
// Kokkos v. 2.0
// Copyright (2019) 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 Christian R. Trott ([email protected])
//
// ************************************************************************
//@HEADER
*/
/*
//@HEADER
// ************************************************************************
//
// Kokkos v. 2.0
// Copyright (2019) 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 Christian R. Trott ([email protected])
//
// ************************************************************************
//@HEADER
*/
/*
//@HEADER
// ************************************************************************
//
// Kokkos v. 2.0
// Copyright (2019) 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 Christian R. Trott ([email protected])
//
// ************************************************************************
//@HEADER
*/
#ifndef _MDSPAN_INCLUDE_EXPERIMENTAL_BITS_CONFIG_HPP_
#define _MDSPAN_INCLUDE_EXPERIMENTAL_BITS_CONFIG_HPP_
#ifndef __has_include
# define __has_include(x) 0
#endif
#if __has_include(<version>)
# include <version>
#else
# include <type_traits>
# include <utility>
#endif
#define MDSPAN_CXX_STD_14 201402L
#define MDSPAN_CXX_STD_17 201703L
#define MDSPAN_HAS_CXX_14 (__cplusplus >= MDSPAN_CXX_STD_14)
#define MDSPAN_HAS_CXX_17 (__cplusplus >= MDSPAN_CXX_STD_17)
#ifdef __apple_build_version__
# define _MDSPAN_COMPILER_APPLECLANG
#endif
#ifndef __has_cpp_attribute
# define __has_cpp_attribute(x) 0
#endif
#ifndef _MDSPAN_NO_UNIQUE_ADDRESS
# if __has_cpp_attribute(no_unique_address) >= 201803L
# define _MDSPAN_NO_UNIQUE_ADDRESS [[no_unique_address]]
# else
# define _MDSPAN_NO_UNIQUE_ADDRESS
# endif
#endif
#ifndef _MDSPAN_USE_CONCEPTS
# if defined(__cpp_concepts) && __cpp_concepts >= 201507L
# define _MDSPAN_USE_CONCEPTS 1
# endif
#endif
#ifndef _MDSPAN_USE_FOLD_EXPRESSIONS
# if (defined(__cpp_fold_expressions) && __cpp_fold_expressions >= 201603L) || MDSPAN_HAS_CXX_17
# define _MDSPAN_USE_FOLD_EXPRESSIONS 1
# endif
#endif
#ifndef _MDSPAN_USE_INLINE_VARIABLES
# if defined(__cpp_inline_variables) && __cpp_inline_variables >= 201606L
# define _MDSPAN_USE_INLINE_VARIABLES 1
# endif
#endif
#ifndef _MDSPAN_NEEDS_TRAIT_VARIABLE_TEMPLATE_BACKPORTS
# if !(defined(__cpp_lib_type_trait_variable_templates) && __cpp_lib_type_trait_variable_templates >= 201510L) \
&& !MDSPAN_HAS_CXX_17
# define _MDSPAN_NEEDS_TRAIT_VARIABLE_TEMPLATE_BACKPORTS 1
# endif
#endif
#ifndef _MDSPAN_USE_VARIABLE_TEMPLATES
# if (defined(__cpp_variable_templates) && __cpp_variable_templates >= 201304) && MDSPAN_HAS_CXX_14
# define _MDSPAN_USE_VARIABLE_TEMPLATES 1
# endif
#endif // _MDSPAN_USE_VARIABLE_TEMPLATES
#ifndef _MDSPAN_USE_CONSTEXPR_14
# if (defined(__cpp_constexpr) && __cpp_constexpr >= 201304) && MDSPAN_HAS_CXX_14
# define _MDSPAN_USE_CONSTEXPR_14 1
# endif
#endif
#ifndef _MDSPAN_USE_INTEGER_SEQUENCE
# ifdef _MSC_VER
# if (defined(__cpp_lib_integer_sequence) && __cpp_lib_integer_sequence >= 201304)
# define _MDSPAN_USE_INTEGER_SEQUENCE 1
# endif
# endif
#endif
#ifndef _MDSPAN_USE_INTEGER_SEQUENCE
# if (defined(__cpp_lib_integer_sequence) && __cpp_lib_integer_sequence >= 201304) && MDSPAN_HAS_CXX_14
// several compilers lie about integer_sequence working properly unless the C++14 standard is used
# define _MDSPAN_USE_INTEGER_SEQUENCE 1
# elif defined(_MDSPAN_COMPILER_APPLECLANG) && MDSPAN_HAS_CXX_14
// appleclang seems to be missing the __cpp_lib_... macros, but doesn't seem to lie about C++14 making
// integer_sequence work
# define _MDSPAN_USE_INTEGER_SEQUENCE 1
# endif
#endif
#ifndef _MDSPAN_USE_RETURN_TYPE_DEDUCTION
# ifdef _MSC_VER
# if !(defined(__cpp_lib_integer_sequence) && __cpp_lib_integer_sequence >= 201304) && MDSPAN_HAS_CXX_14
# define _MDSPAN_USE_RETURN_TYPE_DEDUCTION 1
# endif
# endif
#endif
#ifndef _MDSPAN_USE_RETURN_TYPE_DEDUCTION
# if (defined(__cpp_return_type_deduction) && __cpp_return_type_deduction >= 201304) && MDSPAN_HAS_CXX_14
# define _MDSPAN_USE_RETURN_TYPE_DEDUCTION 1
# endif
#endif
#ifndef _MDSPAN_USE_STANDARD_TRAIT_ALIASES
# if (defined(__cpp_lib_transformation_trait_aliases) && __cpp_lib_transformation_trait_aliases >= 201304)
# define _MDSPAN_USE_STANDARD_TRAIT_ALIASES 1
# elif defined(_MDSPAN_COMPILER_APPLECLANG) && MDSPAN_HAS_CXX_14
// appleclang seems to be missing the __cpp_lib_... macros, but doesn't seem to lie about C++14
# define _MDSPAN_USE_STANDARD_TRAIT_ALIASES 1
# endif
#endif
#endif // _MDSPAN_INCLUDE_EXPERIMENTAL_BITS_CONFIG_HPP_
#ifndef MDSPAN_FORCE_INLINE_FUNCTION
# ifdef _MSC_VER // Microsoft compilers
# define MDSPAN_FORCE_INLINE_FUNCTION __forceinline
# elif defined(__CUDA_ARCH__)
# define MDSPAN_FORCE_INLINE_FUNCTION __attribute__((always_inline)) __host__ __device__
# else
# define MDSPAN_FORCE_INLINE_FUNCTION __attribute__((always_inline))
# endif
#endif
#ifndef MDSPAN_INLINE_FUNCTION
# if defined(__CUDA_ARCH__)
# define MDSPAN_INLINE_FUNCTION inline __host__ __device__
# else
# define MDSPAN_INLINE_FUNCTION inline
# endif
#endif
#ifndef MDSPAN_INLINE_FUNCTION_DEFAULTED
# define MDSPAN_INLINE_FUNCTION_DEFAULTED inline
#endif
//==============================================================================
// <editor-fold desc="Preprocessor helpers"> {{{1
#ifdef _MSC_VER // Microsoft compilers
#define MDSPAN_PP_COUNT(...) \
_MDSPAN_PP_INTERNAL_EXPAND_ARGS_PRIVATE( \
_MDSPAN_PP_INTERNAL_ARGS_AUGMENTER(__VA_ARGS__) \
)
#define _MDSPAN_PP_INTERNAL_ARGS_AUGMENTER(...) unused, __VA_ARGS__
#define _MDSPAN_PP_INTERNAL_EXPAND(x) x
#define _MDSPAN_PP_INTERNAL_EXPAND_ARGS_PRIVATE(...) \
_MDSPAN_PP_INTERNAL_EXPAND( \
_MDSPAN_PP_INTERNAL_COUNT_PRIVATE( \
__VA_ARGS__, 69, 68, 67, 66, 65, 64, 63, 62, 61, \
60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, \
48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, \
36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, \
24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, \
12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 \
) \
)
# define _MDSPAN_PP_INTERNAL_COUNT_PRIVATE( \
_1_, _2_, _3_, _4_, _5_, _6_, _7_, _8_, _9_, \
_10, _11, _12, _13, _14, _15, _16, _17, _18, _19, \
_20, _21, _22, _23, _24, _25, _26, _27, _28, _29, \
_30, _31, _32, _33, _34, _35, _36, _37, _38, _39, \
_40, _41, _42, _43, _44, _45, _46, _47, _48, _49, \
_50, _51, _52, _53, _54, _55, _56, _57, _58, _59, \
_60, _61, _62, _63, _64, _65, _66, _67, _68, _69, \
_70, count, ...) count \
/**/
#else // Non-Microsoft compilers
# define MDSPAN_PP_COUNT(...) \
_MDSPAN_PP_INTERNAL_COUNT_PRIVATE( \
0, ## __VA_ARGS__, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, \
60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, \
45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, \
30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, \
15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) \
/**/
# define _MDSPAN_PP_INTERNAL_COUNT_PRIVATE( \
_0_, _1_, _2_, _3_, _4_, _5_, _6_, _7_, _8_, _9_, \
_10, _11, _12, _13, _14, _15, _16, _17, _18, _19, \
_20, _21, _22, _23, _24, _25, _26, _27, _28, _29, \
_30, _31, _32, _33, _34, _35, _36, _37, _38, _39, \
_40, _41, _42, _43, _44, _45, _46, _47, _48, _49, \
_50, _51, _52, _53, _54, _55, _56, _57, _58, _59, \
_60, _61, _62, _63, _64, _65, _66, _67, _68, _69, \
_70, count, ...) count \
/**/
#endif
#define MDSPAN_PP_STRINGIFY_IMPL(x) #x
#define MDSPAN_PP_STRINGIFY(x) MDSPAN_PP_STRINGIFY_IMPL(x)
#define MDSPAN_PP_CAT_IMPL(x, y) x ## y
#define MDSPAN_PP_CAT(x, y) MDSPAN_PP_CAT_IMPL(x, y)
#define MDSPAN_PP_EVAL(X, ...) X(__VA_ARGS__)
#define MDSPAN_PP_REMOVE_PARENS_IMPL(...) __VA_ARGS__
#define MDSPAN_PP_REMOVE_PARENS(...) MDSPAN_PP_REMOVE_PARENS_IMPL __VA_ARGS__
// </editor-fold> end Preprocessor helpers }}}1
//==============================================================================
//==============================================================================
// <editor-fold desc="Concept emulation"> {{{1
// These compatibility macros don't help with partial ordering, but they should do the trick
// for what we need to do with concepts in mdspan
#ifdef _MDSPAN_USE_CONCEPTS
# define MDSPAN_CLOSE_ANGLE_REQUIRES(REQ) > requires REQ
# define MDSPAN_FUNCTION_REQUIRES(PAREN_PREQUALS, FNAME, PAREN_PARAMS, QUALS, REQ) \
MDSPAN_PP_REMOVE_PARENS(PAREN_PREQUALS) FNAME PAREN_PARAMS QUALS requires REQ \
/**/
#else
# define MDSPAN_CLOSE_ANGLE_REQUIRES(REQ) , int=std::enable_if_t<(REQ), int>(0)>
# define MDSPAN_FUNCTION_REQUIRES(PAREN_PREQUALS, FNAME, PAREN_PARAMS, QUALS, REQ) \
MDSPAN_TEMPLATE_REQUIRES( \
class __function_requires_ignored=void, \
(std::is_void<__function_requires_ignored>::value && REQ) \
) MDSPAN_PP_REMOVE_PARENS(PAREN_PREQUALS) FNAME PAREN_PARAMS QUALS \
/**/
#endif
#ifdef _MSC_VER
# define MDSPAN_TEMPLATE_REQUIRES(...) \
MDSPAN_PP_CAT( \
MDSPAN_PP_CAT(MDSPAN_TEMPLATE_REQUIRES_, MDSPAN_PP_COUNT(__VA_ARGS__))\
(__VA_ARGS__), \
) \
/**/
#else
# define MDSPAN_TEMPLATE_REQUIRES(...) \
MDSPAN_PP_EVAL( \
MDSPAN_PP_CAT(MDSPAN_TEMPLATE_REQUIRES_, MDSPAN_PP_COUNT(__VA_ARGS__)), \
__VA_ARGS__ \
) \
/**/
#endif
#define MDSPAN_TEMPLATE_REQUIRES_2(TP1, REQ) \
template<TP1 \
MDSPAN_CLOSE_ANGLE_REQUIRES(REQ) \
/**/
#define MDSPAN_TEMPLATE_REQUIRES_3(TP1, TP2, REQ) \
template<TP1, TP2 \
MDSPAN_CLOSE_ANGLE_REQUIRES(REQ) \
/**/
#define MDSPAN_TEMPLATE_REQUIRES_4(TP1, TP2, TP3, REQ) \
template<TP1, TP2, TP3 \
MDSPAN_CLOSE_ANGLE_REQUIRES(REQ) \
/**/
#define MDSPAN_TEMPLATE_REQUIRES_5(TP1, TP2, TP3, TP4, REQ) \
template<TP1, TP2, TP3, TP4 \
MDSPAN_CLOSE_ANGLE_REQUIRES(REQ) \
/**/
#define MDSPAN_TEMPLATE_REQUIRES_6(TP1, TP2, TP3, TP4, TP5, REQ) \
template<TP1, TP2, TP3, TP4, TP5 \
MDSPAN_CLOSE_ANGLE_REQUIRES(REQ) \
/**/
#define MDSPAN_INSTANTIATE_ONLY_IF_USED \
MDSPAN_TEMPLATE_REQUIRES( \
class __instantiate_only_if_used_tparam=void, \
( _MDSPAN_TRAIT(std::is_void, __instantiate_only_if_used_tparam) ) \
) \
/**/
// </editor-fold> end Concept emulation }}}1
//==============================================================================
//==============================================================================
// <editor-fold desc="inline variables"> {{{1
#if _MDSPAN_USE_INLINE_VARIABLES
# define _MDSPAN_INLINE_VARIABLE inline
#else
# define _MDSPAN_INLINE_VARIABLE
#endif
// </editor-fold> end inline variables }}}1
//==============================================================================
//==============================================================================
// <editor-fold desc="Return type deduction"> {{{1
#if _MDSPAN_USE_RETURN_TYPE_DEDUCTION
# define _MDSPAN_DEDUCE_RETURN_TYPE_SINGLE_LINE(SIGNATURE, BODY) \
auto MDSPAN_PP_REMOVE_PARENS(SIGNATURE) { return MDSPAN_PP_REMOVE_PARENS(BODY); }
# define _MDSPAN_DEDUCE_DECLTYPE_AUTO_RETURN_TYPE_SINGLE_LINE(SIGNATURE, BODY) \
decltype(auto) MDSPAN_PP_REMOVE_PARENS(SIGNATURE) { return MDSPAN_PP_REMOVE_PARENS(BODY); }
#else
# define _MDSPAN_DEDUCE_RETURN_TYPE_SINGLE_LINE(SIGNATURE, BODY) \
auto MDSPAN_PP_REMOVE_PARENS(SIGNATURE) \
-> typename std::remove_cv<typename std::remove_reference<decltype(BODY)>::type>::type \
{ return MDSPAN_PP_REMOVE_PARENS(BODY); }
# define _MDSPAN_DEDUCE_DECLTYPE_AUTO_RETURN_TYPE_SINGLE_LINE(SIGNATURE, BODY) \
auto MDSPAN_PP_REMOVE_PARENS(SIGNATURE) \
-> decltype(BODY) \
{ return MDSPAN_PP_REMOVE_PARENS(BODY); }
#endif
// </editor-fold> end Return type deduction }}}1
//==============================================================================
//==============================================================================
// <editor-fold desc="fold expressions"> {{{1
struct __mdspan_enable_fold_comma { };
#ifdef _MDSPAN_USE_FOLD_EXPRESSIONS
# define _MDSPAN_FOLD_AND(...) ((__VA_ARGS__) && ...)
# define _MDSPAN_FOLD_AND_TEMPLATE(...) ((__VA_ARGS__) && ...)
# define _MDSPAN_FOLD_OR(...) ((__VA_ARGS__) || ...)
# define _MDSPAN_FOLD_ASSIGN_LEFT(INIT, ...) (INIT = ... = (__VA_ARGS__))
# define _MDSPAN_FOLD_ASSIGN_RIGHT(PACK, ...) (PACK = ... = (__VA_ARGS__))
# define _MDSPAN_FOLD_TIMES_RIGHT(PACK, ...) (PACK * ... * (__VA_ARGS__))
# define _MDSPAN_FOLD_PLUS_RIGHT(PACK, ...) (PACK + ... + (__VA_ARGS__))
# define _MDSPAN_FOLD_COMMA(...) ((__VA_ARGS__), ...)
#else
namespace std {
namespace __fold_compatibility_impl {
// We could probably be more clever here, but at the (small) risk of losing some compiler understanding. For the
// few operations we need, it's not worth generalizing over the operation
#if _MDSPAN_USE_RETURN_TYPE_DEDUCTION
MDSPAN_FORCE_INLINE_FUNCTION
constexpr decltype(auto) __fold_right_and_impl() {
return true;
}
template <class Arg, class... Args>
MDSPAN_FORCE_INLINE_FUNCTION
constexpr decltype(auto) __fold_right_and_impl(Arg&& arg, Args&&... args) {
return ((Arg&&)arg) && __fold_compatibility_impl::__fold_right_and_impl((Args&&)args...);
}
MDSPAN_FORCE_INLINE_FUNCTION
constexpr decltype(auto) __fold_right_or_impl() {
return false;
}
template <class Arg, class... Args>
MDSPAN_FORCE_INLINE_FUNCTION
constexpr auto __fold_right_or_impl(Arg&& arg, Args&&... args) {
return ((Arg&&)arg) || __fold_compatibility_impl::__fold_right_or_impl((Args&&)args...);
}
template <class Arg1>
MDSPAN_FORCE_INLINE_FUNCTION
constexpr auto __fold_left_assign_impl(Arg1&& arg1) {
return (Arg1&&)arg1;
}
template <class Arg1, class Arg2, class... Args>
MDSPAN_FORCE_INLINE_FUNCTION
constexpr auto __fold_left_assign_impl(Arg1&& arg1, Arg2&& arg2, Args&&... args) {
return __fold_compatibility_impl::__fold_left_assign_impl((((Arg1&&)arg1) = ((Arg2&&)arg2)), (Args&&)args...);
}
template <class Arg1>
MDSPAN_FORCE_INLINE_FUNCTION
constexpr auto __fold_right_assign_impl(Arg1&& arg1) {
return (Arg1&&)arg1;
}
template <class Arg1, class Arg2, class... Args>
MDSPAN_FORCE_INLINE_FUNCTION
constexpr auto __fold_right_assign_impl(Arg1&& arg1, Arg2&& arg2, Args&&... args) {
return ((Arg1&&)arg1) = __fold_compatibility_impl::__fold_right_assign_impl((Arg2&&)arg2, (Args&&)args...);
}
template <class Arg1>
MDSPAN_FORCE_INLINE_FUNCTION
constexpr auto __fold_right_plus_impl(Arg1&& arg1) {
return (Arg1&&)arg1;
}
template <class Arg1, class Arg2, class... Args>
MDSPAN_FORCE_INLINE_FUNCTION
constexpr auto __fold_right_plus_impl(Arg1&& arg1, Arg2&& arg2, Args&&... args) {
return ((Arg1&&)arg1) + __fold_compatibility_impl::__fold_right_plus_impl((Arg2&&)arg2, (Args&&)args...);
}
template <class Arg1>
MDSPAN_FORCE_INLINE_FUNCTION
constexpr auto __fold_right_times_impl(Arg1&& arg1) {
return (Arg1&&)arg1;
}
template <class Arg1, class Arg2, class... Args>
MDSPAN_FORCE_INLINE_FUNCTION
constexpr auto __fold_right_times_impl(Arg1&& arg1, Arg2&& arg2, Args&&... args) {
return ((Arg1&&)arg1) * __fold_compatibility_impl::__fold_right_times_impl((Arg2&&)arg2, (Args&&)args...);
}
#else
//------------------------------------------------------------------------------
// <editor-fold desc="right and"> {{{2
template <class... Args>
struct __fold_right_and_impl_;
template <>
struct __fold_right_and_impl_<> {
using __rv = bool;
MDSPAN_FORCE_INLINE_FUNCTION
static constexpr __rv
__impl() noexcept {
return true;
}
};
template <class Arg, class... Args>
struct __fold_right_and_impl_<Arg, Args...> {
using __next_t = __fold_right_and_impl_<Args...>;
using __rv = decltype(std::declval<Arg>() && std::declval<typename __next_t::__rv>());
MDSPAN_FORCE_INLINE_FUNCTION
static constexpr __rv
__impl(Arg&& arg, Args&&... args) noexcept {
return ((Arg&&)arg) && __next_t::__impl((Args&&)args...);
}
};
template <class... Args>
MDSPAN_FORCE_INLINE_FUNCTION
constexpr typename __fold_right_and_impl_<Args...>::__rv
__fold_right_and_impl(Args&&... args) {
return __fold_right_and_impl_<Args...>::__impl((Args&&)args...);
}
// </editor-fold> end right and }}}2
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// <editor-fold desc="right or"> {{{2
template <class... Args>
struct __fold_right_or_impl_;
template <>
struct __fold_right_or_impl_<> {
using __rv = bool;
MDSPAN_FORCE_INLINE_FUNCTION
static constexpr __rv
__impl() noexcept {
return false;
}
};
template <class Arg, class... Args>
struct __fold_right_or_impl_<Arg, Args...> {
using __next_t = __fold_right_or_impl_<Args...>;
using __rv = decltype(std::declval<Arg>() || std::declval<typename __next_t::__rv>());
MDSPAN_FORCE_INLINE_FUNCTION
static constexpr __rv
__impl(Arg&& arg, Args&&... args) noexcept {
return ((Arg&&)arg) || __next_t::__impl((Args&&)args...);
}
};
template <class... Args>
MDSPAN_FORCE_INLINE_FUNCTION
constexpr typename __fold_right_or_impl_<Args...>::__rv
__fold_right_or_impl(Args&&... args) {
return __fold_right_or_impl_<Args...>::__impl((Args&&)args...);
}
// </editor-fold> end right or }}}2
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// <editor-fold desc="right plus"> {{{2
template <class... Args>
struct __fold_right_plus_impl_;
template <class Arg>
struct __fold_right_plus_impl_<Arg> {
using __rv = Arg&&;
MDSPAN_FORCE_INLINE_FUNCTION
static constexpr __rv
__impl(Arg&& arg) noexcept {
return (Arg&&)arg;
}
};
template <class Arg1, class Arg2, class... Args>
struct __fold_right_plus_impl_<Arg1, Arg2, Args...> {
using __next_t = __fold_right_plus_impl_<Arg2, Args...>;
using __rv = decltype(std::declval<Arg1>() + std::declval<typename __next_t::__rv>());
MDSPAN_FORCE_INLINE_FUNCTION
static constexpr __rv
__impl(Arg1&& arg, Arg2&& arg2, Args&&... args) noexcept {
return ((Arg1&&)arg) + __next_t::__impl((Arg2&&)arg2, (Args&&)args...);
}
};
template <class... Args>
MDSPAN_FORCE_INLINE_FUNCTION
constexpr typename __fold_right_plus_impl_<Args...>::__rv
__fold_right_plus_impl(Args&&... args) {
return __fold_right_plus_impl_<Args...>::__impl((Args&&)args...);
}
// </editor-fold> end right plus }}}2
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// <editor-fold desc="right times"> {{{2
template <class... Args>
struct __fold_right_times_impl_;
template <class Arg>
struct __fold_right_times_impl_<Arg> {
using __rv = Arg&&;
MDSPAN_FORCE_INLINE_FUNCTION
static constexpr __rv
__impl(Arg&& arg) noexcept {
return (Arg&&)arg;
}
};
template <class Arg1, class Arg2, class... Args>
struct __fold_right_times_impl_<Arg1, Arg2, Args...> {
using __next_t = __fold_right_times_impl_<Arg2, Args...>;
using __rv = decltype(std::declval<Arg1>() * std::declval<typename __next_t::__rv>());
MDSPAN_FORCE_INLINE_FUNCTION
static constexpr __rv
__impl(Arg1&& arg, Arg2&& arg2, Args&&... args) noexcept {
return ((Arg1&&)arg) * __next_t::__impl((Arg2&&)arg2, (Args&&)args...);
}
};
template <class... Args>
MDSPAN_FORCE_INLINE_FUNCTION
constexpr typename __fold_right_times_impl_<Args...>::__rv
__fold_right_times_impl(Args&&... args) {
return __fold_right_times_impl_<Args...>::__impl((Args&&)args...);
}
// </editor-fold> end right times }}}2
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// <editor-fold desc="right assign"> {{{2
template <class... Args>
struct __fold_right_assign_impl_;
template <class Arg>
struct __fold_right_assign_impl_<Arg> {
using __rv = Arg&&;
MDSPAN_FORCE_INLINE_FUNCTION
static constexpr __rv
__impl(Arg&& arg) noexcept {
return (Arg&&)arg;
}
};
template <class Arg1, class Arg2, class... Args>
struct __fold_right_assign_impl_<Arg1, Arg2, Args...> {
using __next_t = __fold_right_assign_impl_<Arg2, Args...>;
using __rv = decltype(std::declval<Arg1>() = std::declval<typename __next_t::__rv>());
MDSPAN_FORCE_INLINE_FUNCTION
static constexpr __rv
__impl(Arg1&& arg, Arg2&& arg2, Args&&... args) noexcept {
return ((Arg1&&)arg) = __next_t::__impl((Arg2&&)arg2, (Args&&)args...);
}
};
template <class... Args>
MDSPAN_FORCE_INLINE_FUNCTION
constexpr typename __fold_right_assign_impl_<Args...>::__rv
__fold_right_assign_impl(Args&&... args) {
return __fold_right_assign_impl_<Args...>::__impl((Args&&)args...);
}
// </editor-fold> end right assign }}}2
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// <editor-fold desc="left assign"> {{{2
template <class... Args>
struct __fold_left_assign_impl_;
template <class Arg>
struct __fold_left_assign_impl_<Arg> {
using __rv = Arg&&;
MDSPAN_FORCE_INLINE_FUNCTION
static constexpr __rv
__impl(Arg&& arg) noexcept {
return (Arg&&)arg;
}
};
template <class Arg1, class Arg2, class... Args>
struct __fold_left_assign_impl_<Arg1, Arg2, Args...> {
using __assign_result_t = decltype(std::declval<Arg1>() = std::declval<Arg2>());
using __next_t = __fold_left_assign_impl_<__assign_result_t, Args...>;
using __rv = typename __next_t::__rv;
MDSPAN_FORCE_INLINE_FUNCTION
static constexpr __rv
__impl(Arg1&& arg, Arg2&& arg2, Args&&... args) noexcept {
return __next_t::__impl(((Arg1&&)arg) = (Arg2&&)arg2, (Args&&)args...);
}
};
template <class... Args>
MDSPAN_FORCE_INLINE_FUNCTION
constexpr typename __fold_left_assign_impl_<Args...>::__rv
__fold_left_assign_impl(Args&&... args) {
return __fold_left_assign_impl_<Args...>::__impl((Args&&)args...);
}
// </editor-fold> end left assign }}}2
//------------------------------------------------------------------------------
#endif
template <class... Args>
constexpr __mdspan_enable_fold_comma __fold_comma_impl(Args&&... args) noexcept { return { }; }
template <bool... Bs>
struct __bools;
} // __fold_compatibility_impl
} // end namespace std
# define _MDSPAN_FOLD_AND(...) std::__fold_compatibility_impl::__fold_right_and_impl((__VA_ARGS__)...)
# define _MDSPAN_FOLD_OR(...) std::__fold_compatibility_impl::__fold_right_or_impl((__VA_ARGS__)...)
# define _MDSPAN_FOLD_ASSIGN_LEFT(INIT, ...) std::__fold_compatibility_impl::__fold_left_assign_impl(INIT, (__VA_ARGS__)...)
# define _MDSPAN_FOLD_ASSIGN_RIGHT(PACK, ...) std::__fold_compatibility_impl::__fold_right_assign_impl((PACK)..., __VA_ARGS__)
# define _MDSPAN_FOLD_TIMES_RIGHT(PACK, ...) std::__fold_compatibility_impl::__fold_right_times_impl((PACK)..., __VA_ARGS__)
# define _MDSPAN_FOLD_PLUS_RIGHT(PACK, ...) std::__fold_compatibility_impl::__fold_right_plus_impl((PACK)..., __VA_ARGS__)
# define _MDSPAN_FOLD_COMMA(...) std::__fold_compatibility_impl::__fold_comma_impl((__VA_ARGS__)...)
# define _MDSPAN_FOLD_AND_TEMPLATE(...) \
_MDSPAN_TRAIT(std::is_same, __fold_compatibility_impl::__bools<(__VA_ARGS__)..., true>, __fold_compatibility_impl::__bools<true, (__VA_ARGS__)...>)
#endif
// </editor-fold> end fold expressions }}}1
//==============================================================================
//==============================================================================
// <editor-fold desc="Variable template compatibility"> {{{1
#if _MDSPAN_USE_VARIABLE_TEMPLATES
# define _MDSPAN_TRAIT(TRAIT, ...) TRAIT##_v<__VA_ARGS__>
#else
# define _MDSPAN_TRAIT(TRAIT, ...) TRAIT<__VA_ARGS__>::value
#endif
// </editor-fold> end Variable template compatibility }}}1
//==============================================================================
//==============================================================================
// <editor-fold desc="Pre-C++14 constexpr"> {{{1
#if _MDSPAN_USE_CONSTEXPR_14
# define _MDSPAN_CONSTEXPR_14 constexpr
// Workaround for a bug (I think?) in EDG frontends
# ifdef __EDG__
# define _MDSPAN_CONSTEXPR_14_DEFAULTED
# else
# define _MDSPAN_CONSTEXPR_14_DEFAULTED constexpr
# endif
#else
# define _MDSPAN_CONSTEXPR_14
# define _MDSPAN_CONSTEXPR_14_DEFAULTED
#endif
// </editor-fold> end Pre-C++14 constexpr }}}1
//==============================================================================
namespace std {
namespace experimental {
template <class ElementType>
struct accessor_basic {
using offset_policy = accessor_basic;
using element_type = ElementType;
using reference = ElementType&;
using pointer = ElementType*;
MDSPAN_INLINE_FUNCTION
constexpr pointer
offset(pointer p, ptrdiff_t i) const noexcept {
return p + i;
}
MDSPAN_FORCE_INLINE_FUNCTION
constexpr reference access(pointer p, ptrdiff_t i) const noexcept {
return p[i];
}
MDSPAN_INLINE_FUNCTION
constexpr pointer decay(pointer p) const noexcept {
return p;
}
};
} // end namespace experimental
} // end namespace std
/*
//@HEADER
// ************************************************************************
//
// Kokkos v. 2.0
// Copyright (2019) 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 Christian R. Trott ([email protected])
//
// ************************************************************************
//@HEADER
*/
namespace std {
namespace experimental {
struct all_type { };
_MDSPAN_INLINE_VARIABLE constexpr auto all = all_type{ };
} // end namespace experimental
} // namespace std
/*
//@HEADER
// ************************************************************************
//
// Kokkos v. 2.0
// Copyright (2019) 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 Christian R. Trott ([email protected])
//
// ************************************************************************
//@HEADER
*/
#ifndef MDSPAN_INCLUDE_EXPERIMENTAL___P0009_BITS_ARRAY_WORKAROUND_HPP_
#define MDSPAN_INCLUDE_EXPERIMENTAL___P0009_BITS_ARRAY_WORKAROUND_HPP_
/*
//@HEADER
// ************************************************************************
//
// Kokkos v. 2.0
// Copyright (2019) 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 Christian R. Trott ([email protected])
//
// ************************************************************************
//@HEADER
*/
#ifndef MDSPAN_INCLUDE_EXPERIMENTAL_BITS_TRAIT_BACKPORTS_HPP_
#define MDSPAN_INCLUDE_EXPERIMENTAL_BITS_TRAIT_BACKPORTS_HPP_
//==============================================================================
// <editor-fold desc="Variable template trait backports (e.g., is_void_v)"> {{{1
#if _MDSPAN_NEEDS_TRAIT_VARIABLE_TEMPLATE_BACKPORTS
#if _MDSPAN_USE_VARIABLE_TEMPLATES
namespace std {
#define _MDSPAN_BACKPORT_TRAIT(TRAIT) \
template <class... Args> _MDSPAN_INLINE_VARIABLE constexpr auto TRAIT##_v = TRAIT<Args...>::value;
_MDSPAN_BACKPORT_TRAIT(is_assignable)
_MDSPAN_BACKPORT_TRAIT(is_constructible)
_MDSPAN_BACKPORT_TRAIT(is_convertible)
_MDSPAN_BACKPORT_TRAIT(is_default_constructible)
_MDSPAN_BACKPORT_TRAIT(is_same)
_MDSPAN_BACKPORT_TRAIT(is_void)
#undef _MDSPAN_BACKPORT_TRAIT
} // end namespace std
#endif // _MDSPAN_USE_VARIABLE_TEMPLATES
#endif // _MDSPAN_NEEDS_TRAIT_VARIABLE_TEMPLATE_BACKPORTS
// </editor-fold> end Variable template trait backports (e.g., is_void_v) }}}1
//==============================================================================
//==============================================================================
// <editor-fold desc="integer sequence (ugh...)"> {{{1
#if !defined(_MDSPAN_USE_INTEGER_SEQUENCE) || !_MDSPAN_USE_INTEGER_SEQUENCE
namespace std {
template <class T, T... Vals>
struct integer_sequence {
static constexpr std::size_t size() noexcept { return sizeof...(Vals); }
using value_type = T;
};
template <std::size_t... Vals>
using index_sequence = std::integer_sequence<std::size_t, Vals...>;
namespace __detail {
template <class T, T N, T I, class Result>
struct __make_int_seq_impl;
template <class T, T N, T... Vals>
struct __make_int_seq_impl<T, N, N, integer_sequence<T, Vals...>>
{
using type = integer_sequence<T, Vals...>;
};
template <class T, T N, T I, T... Vals>
struct __make_int_seq_impl<
T, N, I, integer_sequence<T, Vals...>
> : __make_int_seq_impl<T, N, I+1, integer_sequence<T, Vals..., I>>
{ };
} // end namespace __detail
template <class T, T N>
using make_integer_sequence = typename __detail::__make_int_seq_impl<T, N, 0, integer_sequence<T>>::type;
template <std::size_t N>
using make_index_sequence = typename __detail::__make_int_seq_impl<size_t, N, 0, integer_sequence<size_t>>::type;
template <class... T>
using index_sequence_for = make_index_sequence<sizeof...(T)>;
} // end namespace std
#endif
// </editor-fold> end integer sequence (ugh...) }}}1
//==============================================================================
//==============================================================================
// <editor-fold desc="standard trait aliases"> {{{1
#if !defined(_MDSPAN_USE_STANDARD_TRAIT_ALIASES) || !_MDSPAN_USE_STANDARD_TRAIT_ALIASES
namespace std {
#define _MDSPAN_BACKPORT_TRAIT_ALIAS(TRAIT) \
template <class... Args> using TRAIT##_t = typename TRAIT<Args...>::type;
_MDSPAN_BACKPORT_TRAIT_ALIAS(remove_cv)
_MDSPAN_BACKPORT_TRAIT_ALIAS(remove_reference)
template <bool _B, class _T=void>
using enable_if_t = typename enable_if<_B, _T>::type;
#undef _MDSPAN_BACKPORT_TRAIT_ALIAS
} // end namespace std
#endif
// </editor-fold> end standard trait aliases }}}1
//==============================================================================
#endif //MDSPAN_INCLUDE_EXPERIMENTAL_BITS_TRAIT_BACKPORTS_HPP_
namespace std {
namespace experimental {
// nvcc itself and icc's optimizer both don't play well with std::array :-/
namespace __array_workaround {
// Assumes T is integral, which works for our use case
template <class T, size_t Idx>
struct __array_entry_impl {
T __value = { };
#if !MDSPAN_HAS_CXX_14
MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr __array_entry_impl() noexcept = default;
MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr __array_entry_impl(__array_entry_impl const&) noexcept = default;
MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr __array_entry_impl(__array_entry_impl&&) noexcept = default;
MDSPAN_INLINE_FUNCTION_DEFAULTED _MDSPAN_CONSTEXPR_14 __array_entry_impl& operator=(__array_entry_impl const&) noexcept = default;
MDSPAN_INLINE_FUNCTION_DEFAULTED _MDSPAN_CONSTEXPR_14 __array_entry_impl& operator=(__array_entry_impl&&) noexcept = default;
MDSPAN_FORCE_INLINE_FUNCTION constexpr __array_entry_impl(T&& val) noexcept : __value(std::move(val)) { }
#endif
MDSPAN_FORCE_INLINE_FUNCTION
constexpr T __iget(ptrdiff_t i) const noexcept {
return (i == Idx) ? __value : T(0);
}
MDSPAN_FORCE_INLINE_FUNCTION
_MDSPAN_CONSTEXPR_14 __mdspan_enable_fold_comma __iset(ptrdiff_t i, T val) noexcept {
if(i == Idx) __value = val;
return { };
}
};
template <class T, size_t N, class>
struct __array_impl;
template <class T, size_t I>
using __repeated = T;
template <class T, size_t N, size_t... Idxs>
struct __array_impl<T, N, integer_sequence<size_t, Idxs...>>
: __array_entry_impl<T, Idxs>...
{
static constexpr size_t __size = N;
MDSPAN_INLINE_FUNCTION_DEFAULTED
constexpr __array_impl(__array_impl const&) noexcept = default;
MDSPAN_INLINE_FUNCTION_DEFAULTED
constexpr __array_impl(__array_impl&&) noexcept = default;
MDSPAN_INLINE_FUNCTION_DEFAULTED
_MDSPAN_CONSTEXPR_14_DEFAULTED __array_impl& operator=(__array_impl const&) noexcept = default;
MDSPAN_INLINE_FUNCTION_DEFAULTED
_MDSPAN_CONSTEXPR_14_DEFAULTED __array_impl& operator=(__array_impl&&) noexcept = default;
MDSPAN_INLINE_FUNCTION_DEFAULTED
~__array_impl() noexcept = default;
MDSPAN_FUNCTION_REQUIRES(
(MDSPAN_FORCE_INLINE_FUNCTION constexpr),
__array_impl, (), noexcept,
/* requires */ N != 0
) : __array_entry_impl<T, Idxs>()...
{ }
MDSPAN_FORCE_INLINE_FUNCTION
constexpr
__array_impl(__repeated<T, Idxs>... vals) noexcept
: __array_entry_impl<T, Idxs>({T{vals}})...
{ }
MDSPAN_FUNCTION_REQUIRES(
(MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr),
__array_impl, (array<T, N> vals), noexcept,
/* requires */ N != 0
) : __array_entry_impl<T, Idxs>({T{vals[Idxs]}})...
{ }
MDSPAN_FORCE_INLINE_FUNCTION
constexpr
__array_impl(array<T, 0> vals) noexcept
{ }
// TODO remove this, it's unused
MDSPAN_FORCE_INLINE_FUNCTION
constexpr T
__get(ptrdiff_t i) const noexcept {
// For N > 0, this should work:
// (static_cast<__array_entry_impl<T, 0>>(this) + i)->__value;
return _MDSPAN_FOLD_PLUS_RIGHT((this->__array_entry_impl<T, Idxs>::__iget(i)), /* + ... + */ 0);
}
template <ptrdiff_t I>
MDSPAN_FORCE_INLINE_FUNCTION
constexpr T const&
__get_n() const noexcept {
return this->__array_entry_impl<T, I>::__value;
}
// TODO remove this, it's unused
MDSPAN_FORCE_INLINE_FUNCTION
_MDSPAN_CONSTEXPR_14 void
__set(ptrdiff_t i, T val) noexcept {
_MDSPAN_FOLD_COMMA(this->__array_entry_impl<T, Idxs>::__iset(i, val) /*, ... */);
}
template <ptrdiff_t I>
MDSPAN_FORCE_INLINE_FUNCTION
_MDSPAN_CONSTEXPR_14 void
__set_n(T val) noexcept {
this->__array_entry_impl<T, I>::__value = val;
}
};
template <class T, size_t N>
struct __array : __array_impl<T, N, make_index_sequence<N>>
{
using base_t = __array_impl<T, N, make_index_sequence<N>>;
using base_t::base_t;
};
} // end namespace __array_workaround
} // end namespace experimental
} // end namespace std
#endif //MDSPAN_INCLUDE_EXPERIMENTAL___P0009_BITS_ARRAY_WORKAROUND_HPP_
/*
//@HEADER
// ************************************************************************
//
// Kokkos v. 2.0
// Copyright (2019) 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 Christian R. Trott ([email protected])
//
// ************************************************************************
//@HEADER
*/
/*
//@HEADER
// ************************************************************************
//
// Kokkos v. 2.0
// Copyright (2019) 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 Christian R. Trott ([email protected])
//
// ************************************************************************
//@HEADER
*/
/*
//@HEADER
// ************************************************************************
//
// Kokkos v. 2.0
// Copyright (2019) 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 Christian R. Trott ([email protected])
//
// ************************************************************************
//@HEADER
*/
/*
//@HEADER
// ************************************************************************
//
// Kokkos v. 2.0
// Copyright (2019) 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 Christian R. Trott ([email protected])
//
// ************************************************************************
//@HEADER
*/
/*
//@HEADER
// ************************************************************************
//
// Kokkos v. 2.0
// Copyright (2019) 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 Christian R. Trott ([email protected])
//
// ************************************************************************
//@HEADER
*/
namespace std {
namespace experimental {
_MDSPAN_INLINE_VARIABLE constexpr ptrdiff_t dynamic_extent = -1;
} // end namespace experimental
} // namespace std
//==============================================================================================================
namespace std {
namespace experimental {
namespace detail {
_MDSPAN_INLINE_VARIABLE constexpr struct construct_mixed_storage_from_sizes_tag_t { } construct_mixed_storage_from_sizes_tag = { };
template <class SizesSeq, class, class=make_index_sequence<SizesSeq::size()>>
class mixed_static_and_dynamic_size_storage;
template <
ptrdiff_t... Sizes,
ptrdiff_t... DynamicOffsets,
size_t... Idxs
>
class mixed_static_and_dynamic_size_storage<
integer_sequence<ptrdiff_t, Sizes...>,
integer_sequence<ptrdiff_t, DynamicOffsets...>,
integer_sequence<size_t, Idxs...>
>
{
public:
static constexpr auto size_dynamic =
_MDSPAN_FOLD_PLUS_RIGHT(static_cast<int>((Sizes == dynamic_extent)), /* + ... + */ 0);
private:
_MDSPAN_NO_UNIQUE_ADDRESS __array_workaround::__array<ptrdiff_t, size_dynamic> dynamic_sizes = { };
template <ptrdiff_t Size, ptrdiff_t DynamicOffset>
MDSPAN_FORCE_INLINE_FUNCTION
constexpr ptrdiff_t _select(true_type) const noexcept { return dynamic_sizes.template __get_n<DynamicOffset>(); }
template <ptrdiff_t Size, ptrdiff_t DynamicOffset>
MDSPAN_FORCE_INLINE_FUNCTION
constexpr ptrdiff_t _select(false_type) const noexcept { return Size; }
template <ptrdiff_t Size, ptrdiff_t DynamicOffset>
MDSPAN_FORCE_INLINE_FUNCTION
_MDSPAN_CONSTEXPR_14 ptrdiff_t _select_set(true_type, ptrdiff_t value) noexcept { dynamic_sizes.template __set_n<DynamicOffset>(value); return 0; }
template <ptrdiff_t Size, ptrdiff_t DynamicOffset>
MDSPAN_FORCE_INLINE_FUNCTION
_MDSPAN_CONSTEXPR_14 ptrdiff_t _select_set(false_type, ptrdiff_t) noexcept { return 0; }
public:
template <ptrdiff_t Size, ptrdiff_t DynamicOffset>
MDSPAN_FORCE_INLINE_FUNCTION
constexpr ptrdiff_t select() const noexcept {
return _select<Size, DynamicOffset>(integral_constant<bool, Size == dynamic_extent>{});
}
template <ptrdiff_t Size, ptrdiff_t DynamicOffset, size_t Idx, ptrdiff_t N, ptrdiff_t Default=dynamic_extent>
MDSPAN_FORCE_INLINE_FUNCTION
constexpr ptrdiff_t select_n() const noexcept {
return Idx == N ? _select<Size, DynamicOffset>(integral_constant<bool, Size == dynamic_extent>{}) : Default;
}
template <ptrdiff_t Size, ptrdiff_t DynamicOffset, ptrdiff_t Default=dynamic_extent>
MDSPAN_FORCE_INLINE_FUNCTION
static constexpr ptrdiff_t select_static() noexcept {
return Size == dynamic_extent ? Default : Size;
}
template <ptrdiff_t Size, ptrdiff_t DynamicOffset, size_t Idx, size_t N, ptrdiff_t Default=dynamic_extent, ptrdiff_t DefaultWrongIdx=Default>
MDSPAN_FORCE_INLINE_FUNCTION
static constexpr ptrdiff_t select_static_n() noexcept {
return (Idx == N) ? ((Size == dynamic_extent) ? Default : Size) : DefaultWrongIdx;
}
template <ptrdiff_t Size, ptrdiff_t DynamicOffset, size_t Idx, ptrdiff_t N>
MDSPAN_FORCE_INLINE_FUNCTION
_MDSPAN_CONSTEXPR_14 ptrdiff_t select_set(ptrdiff_t value) noexcept {
return _select_set<Size, DynamicOffset>(integral_constant<bool, Size == dynamic_extent && Idx == N>{}, value);
}
template <size_t N>
MDSPAN_FORCE_INLINE_FUNCTION
constexpr ptrdiff_t get() const noexcept {
return _MDSPAN_FOLD_PLUS_RIGHT((select_n<Sizes, DynamicOffsets, Idxs, N, 0>()), /* + ... + */ 0);
}
template <size_t N, ptrdiff_t Default=dynamic_extent>
MDSPAN_FORCE_INLINE_FUNCTION
static constexpr ptrdiff_t get_static() noexcept {
return _MDSPAN_FOLD_PLUS_RIGHT((select_static_n<Sizes, DynamicOffsets, Idxs, N, Default, 0>()), /* + ... + */ 0);
}
MDSPAN_FORCE_INLINE_FUNCTION
constexpr ptrdiff_t get(size_t n) const noexcept {
return _MDSPAN_FOLD_PLUS_RIGHT(((Idxs == n) ? select<Sizes, DynamicOffsets>() : 0), /* + ... + */ 0);
}
template <size_t N>
MDSPAN_FORCE_INLINE_FUNCTION
_MDSPAN_CONSTEXPR_14 __mdspan_enable_fold_comma
set(ptrdiff_t value) noexcept {
_MDSPAN_FOLD_COMMA(select_set<Sizes, DynamicOffsets, Idxs, N>(value) /* , ... */);
return { };
}
MDSPAN_INLINE_FUNCTION_DEFAULTED
constexpr mixed_static_and_dynamic_size_storage() = default;
MDSPAN_INLINE_FUNCTION_DEFAULTED
constexpr mixed_static_and_dynamic_size_storage(mixed_static_and_dynamic_size_storage const&) noexcept = default;
MDSPAN_INLINE_FUNCTION_DEFAULTED
constexpr mixed_static_and_dynamic_size_storage(mixed_static_and_dynamic_size_storage&&) noexcept = default;
MDSPAN_INLINE_FUNCTION_DEFAULTED
_MDSPAN_CONSTEXPR_14_DEFAULTED mixed_static_and_dynamic_size_storage& operator=(mixed_static_and_dynamic_size_storage const&) noexcept = default;
MDSPAN_INLINE_FUNCTION_DEFAULTED
_MDSPAN_CONSTEXPR_14_DEFAULTED mixed_static_and_dynamic_size_storage& operator=(mixed_static_and_dynamic_size_storage&&) noexcept = default;
MDSPAN_INLINE_FUNCTION_DEFAULTED
~mixed_static_and_dynamic_size_storage() noexcept = default;
template <class... Integral>
MDSPAN_INLINE_FUNCTION
constexpr mixed_static_and_dynamic_size_storage(construct_mixed_storage_from_sizes_tag_t, Integral... dyn_sizes)
: dynamic_sizes(ptrdiff_t{dyn_sizes}...)
{ }
template <ptrdiff_t... USizes, ptrdiff_t... UDynOffs, size_t... UIdxs>
MDSPAN_INLINE_FUNCTION
_MDSPAN_CONSTEXPR_14 mixed_static_and_dynamic_size_storage(
mixed_static_and_dynamic_size_storage<
std::integer_sequence<ptrdiff_t, USizes...>,
std::integer_sequence<ptrdiff_t, UDynOffs...>,
std::integer_sequence<size_t, UIdxs...>
> const& other
) : dynamic_sizes()
{
_MDSPAN_FOLD_COMMA(set<Idxs>(other.template get<Idxs>()) /* , ... */);
}
template <class Integral>
MDSPAN_INLINE_FUNCTION
constexpr mixed_static_and_dynamic_size_storage(std::array<Integral, size_dynamic> const& dyn)
: dynamic_sizes(dyn)
{ }
};
//================================================================================
template <size_t N, class, class> struct _make_mixed_impl_helper;
template <size_t N, size_t... Idxs, ptrdiff_t... Sizes>
struct _make_mixed_impl_helper<N, integer_sequence<size_t, Idxs...>, integer_sequence<ptrdiff_t, Sizes...>> {
static constexpr ptrdiff_t value =
_MDSPAN_FOLD_PLUS_RIGHT((int(Idxs < size_t(N) && Sizes == dynamic_extent)), /* + ... + */ 0);
};
template <class Sequence, class=void>
struct _make_mixed_impl;
template <class T, T... Sizes>
struct _make_mixed_impl<integer_sequence<T, Sizes...>, void>
: _make_mixed_impl<integer_sequence<T, Sizes...>, std::make_index_sequence<sizeof...(Sizes)>>
{ };
template <class T, T... Sizes, size_t... Idxs>
struct _make_mixed_impl<integer_sequence<T, Sizes...>, integer_sequence<size_t, Idxs...>> {
using type = mixed_static_and_dynamic_size_storage<
integer_sequence<ptrdiff_t, Sizes...>,
integer_sequence<ptrdiff_t,
_make_mixed_impl_helper<
Idxs, std::index_sequence<Idxs...>, std::integer_sequence<ptrdiff_t, Sizes...>
>::value...
>
>;
};
} // namespace detail
} // end namespace experimental
} // namespace std
/*
//@HEADER
// ************************************************************************
//
// Kokkos v. 2.0
// Copyright (2019) 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 Christian R. Trott ([email protected])
//
// ************************************************************************
//@HEADER
*/
namespace std {
namespace experimental {
namespace detail {
template <ptrdiff_t... Extents, ptrdiff_t... OtherExtents>
static constexpr std::false_type _check_compatible_extents(
std::false_type, std::integer_sequence<ptrdiff_t, Extents...>, std::integer_sequence<ptrdiff_t, OtherExtents...>
) noexcept { return { }; }
template <ptrdiff_t... Extents, ptrdiff_t... OtherExtents>
static std::integral_constant<
bool,
_MDSPAN_FOLD_AND(
(
Extents == dynamic_extent
|| OtherExtents == dynamic_extent
|| Extents == OtherExtents
) /* && ... */
)
>
_check_compatible_extents(
std::true_type, std::integer_sequence<ptrdiff_t, Extents...>, std::integer_sequence<ptrdiff_t, OtherExtents...>
) noexcept { return { }; }
} // end namespace detail
template <ptrdiff_t... Extents>
class extents
{
public:
using index_type = ptrdiff_t;
private:
using storage_type = typename detail::_make_mixed_impl<integer_sequence<ptrdiff_t, Extents...>>::type;
template <size_t... Idxs>
MDSPAN_FORCE_INLINE_FUNCTION
static constexpr
index_type _static_extent_impl(size_t n, std::integer_sequence<size_t, Idxs...>) noexcept {
return _MDSPAN_FOLD_PLUS_RIGHT(((Idxs == n) ? Extents : 0), /* + ... + */ 0);
}
template <ptrdiff_t...>
friend class extents;
template <ptrdiff_t... OtherExtents, size_t... Idxs>
MDSPAN_INLINE_FUNCTION
constexpr bool _eq_impl(std::experimental::extents<OtherExtents...>, false_type, index_sequence<Idxs...>) const noexcept { return false; }
template <ptrdiff_t... OtherExtents, size_t... Idxs>
MDSPAN_INLINE_FUNCTION
constexpr bool _eq_impl(
std::experimental::extents<OtherExtents...> other,
true_type, index_sequence<Idxs...>
) const noexcept {
return _MDSPAN_FOLD_AND((_storage.template get<Idxs>() == other._storage.template get<Idxs>()) /* && ... */);
}
template <ptrdiff_t... OtherExtents, size_t... Idxs>
MDSPAN_INLINE_FUNCTION
constexpr bool _not_eq_impl(std::experimental::extents<OtherExtents...>, false_type, index_sequence<Idxs...>) const noexcept { return true; }
template <ptrdiff_t... OtherExtents, size_t... Idxs>
MDSPAN_INLINE_FUNCTION
constexpr bool _not_eq_impl(
std::experimental::extents<OtherExtents...> other,
true_type, index_sequence<Idxs...>
) const noexcept {
return _MDSPAN_FOLD_OR((_storage.template get<Idxs>() != other._storage.template get<Idxs>()) /* || ... */);
}
public:
MDSPAN_INLINE_FUNCTION
static constexpr size_t rank() noexcept { return sizeof...(Extents); }
MDSPAN_INLINE_FUNCTION
static constexpr size_t rank_dynamic() noexcept { return _MDSPAN_FOLD_PLUS_RIGHT((int(Extents == dynamic_extent)), /* + ... + */ 0); }
//--------------------------------------------------------------------------------
// Constructors, Destructors, and Assignment
MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr extents() noexcept = default;
MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr extents(extents const&) noexcept = default;
MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr extents(extents&&) noexcept = default;
MDSPAN_INLINE_FUNCTION_DEFAULTED _MDSPAN_CONSTEXPR_14_DEFAULTED extents& operator=(extents const&) noexcept = default;
MDSPAN_INLINE_FUNCTION_DEFAULTED _MDSPAN_CONSTEXPR_14_DEFAULTED extents& operator=(extents&&) noexcept = default;
MDSPAN_INLINE_FUNCTION_DEFAULTED ~extents() noexcept = default;
MDSPAN_TEMPLATE_REQUIRES(
ptrdiff_t... OtherExtents,
/* requires */ (
/* multi-stage check to protect from invalid pack expansion when sizes don't match? */
decltype(detail::_check_compatible_extents(
std::integral_constant<bool, sizeof...(Extents) == sizeof...(OtherExtents)>{},
std::integer_sequence<ptrdiff_t, Extents...>{},
std::integer_sequence<ptrdiff_t, OtherExtents...>{}
))::value
)
)
MDSPAN_INLINE_FUNCTION
constexpr extents(const extents<OtherExtents...>& other)
noexcept
: _storage(other._storage)
{ }
MDSPAN_TEMPLATE_REQUIRES(
class... Integral,
/* requires */ (
_MDSPAN_FOLD_AND(std::_MDSPAN_TRAIT(is_convertible, Integral, index_type) /* && ... */) && sizeof...(Integral) == rank_dynamic()
)
)
MDSPAN_INLINE_FUNCTION
constexpr explicit extents(Integral... dyn) noexcept
: _storage(detail::construct_mixed_storage_from_sizes_tag, dyn...)
{ }
// TODO @proposal-bug this constructor should be explicit
MDSPAN_TEMPLATE_REQUIRES(
class IndexType,
/* requires */ (
_MDSPAN_TRAIT(is_convertible, IndexType, index_type)
)
)
MDSPAN_INLINE_FUNCTION
constexpr extents(std::array<IndexType, storage_type::size_dynamic> const& dyn) noexcept
: _storage(dyn)
{ }
MDSPAN_TEMPLATE_REQUIRES(
ptrdiff_t... OtherExtents,
/* requires */ (
/* multi-stage check to protect from invalid pack expansion when sizes don't match? */
decltype(detail::_check_compatible_extents(
std::integral_constant<bool, sizeof...(Extents) == sizeof...(OtherExtents)>{},
std::integer_sequence<ptrdiff_t, Extents...>{},
std::integer_sequence<ptrdiff_t, OtherExtents...>{}
))::value
)
)
MDSPAN_INLINE_FUNCTION
_MDSPAN_CONSTEXPR_14 extents& operator=(const extents<OtherExtents...>& other) noexcept
{
_storage = other._storage;
return *this;
}
//--------------------------------------------------------------------------------
MDSPAN_INLINE_FUNCTION
static constexpr
index_type static_extent(size_t n) noexcept {
return _static_extent_impl(n, std::make_integer_sequence<size_t, sizeof...(Extents)>{});
}
MDSPAN_INLINE_FUNCTION
constexpr
index_type extent(size_t n) const noexcept {
return _storage.get(n);
}
//--------------------------------------------------------------------------------
template<ptrdiff_t... RHS>
MDSPAN_INLINE_FUNCTION
friend constexpr bool operator==(extents const& lhs, extents<RHS...> const& rhs) noexcept {
return lhs._eq_impl(
rhs, std::integral_constant<bool, (sizeof...(Extents) == sizeof...(RHS))>{},
make_index_sequence<sizeof...(RHS)>{}
);
}
template<ptrdiff_t... RHS>
MDSPAN_INLINE_FUNCTION
friend constexpr bool operator!=(extents const& lhs, extents<RHS...> const& rhs) noexcept {
return lhs._not_eq_impl(
rhs, std::integral_constant<bool, (sizeof...(Extents) == sizeof...(RHS))>{},
make_index_sequence<sizeof...(RHS)>{}
);
}
public: // (but not really)
template <size_t N>
MDSPAN_FORCE_INLINE_FUNCTION
constexpr
index_type __extent() const noexcept {
return _storage.template get<N>();
}
template <size_t N, ptrdiff_t Default=dynamic_extent>
MDSPAN_INLINE_FUNCTION
static constexpr
index_type __static_extent() noexcept {
return storage_type::template get_static<N, Default>();
}
private:
_MDSPAN_NO_UNIQUE_ADDRESS storage_type _storage = { };
};
} // end namespace experimental
} // namespace std
//==============================================================================================================
namespace std {
namespace experimental {
namespace detail {
//==============================================================================================================
template <class Extents>
struct extents_storage
{
public:
using extents_type = Extents;
protected:
_MDSPAN_NO_UNIQUE_ADDRESS extents_type __extents = {};
public:
MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr extents_storage() noexcept = default;
MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr extents_storage(extents_storage const&) noexcept = default;
MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr extents_storage(extents_storage&&) noexcept = default;
MDSPAN_INLINE_FUNCTION_DEFAULTED _MDSPAN_CONSTEXPR_14_DEFAULTED extents_storage& operator=(extents_storage const&) noexcept = default;
MDSPAN_INLINE_FUNCTION_DEFAULTED _MDSPAN_CONSTEXPR_14_DEFAULTED extents_storage& operator=(extents_storage&&) noexcept = default;
MDSPAN_INLINE_FUNCTION_DEFAULTED ~extents_storage() noexcept = default;
MDSPAN_INLINE_FUNCTION
constexpr extents_storage(extents_type const& exts)
: __extents(exts)
{ }
};
//==============================================================================================================
template <class, class, class> struct stride_storage_impl;
template <ptrdiff_t... Exts, size_t... Idxs, class IdxConditional>
struct stride_storage_impl<std::experimental::extents<Exts...>, integer_sequence<size_t, Idxs...>, IdxConditional>
: extents_storage<std::experimental::extents<Exts...>>
{
protected:
using base_t = extents_storage<std::experimental::extents<Exts...>>;
public:
MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr stride_storage_impl() noexcept = default;
MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr stride_storage_impl(stride_storage_impl const&) noexcept = default;
MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr stride_storage_impl(stride_storage_impl&&) noexcept = default;
MDSPAN_INLINE_FUNCTION_DEFAULTED _MDSPAN_CONSTEXPR_14_DEFAULTED stride_storage_impl& operator=(stride_storage_impl const&) noexcept = default;
MDSPAN_INLINE_FUNCTION_DEFAULTED _MDSPAN_CONSTEXPR_14_DEFAULTED stride_storage_impl& operator=(stride_storage_impl&&) noexcept = default;
MDSPAN_INLINE_FUNCTION_DEFAULTED ~stride_storage_impl() noexcept = default;
using base_t::base_t;
template <size_t N>
MDSPAN_FORCE_INLINE_FUNCTION
constexpr ptrdiff_t get_stride() const noexcept {
return _MDSPAN_FOLD_TIMES_RIGHT((IdxConditional{}(Idxs, N) ? base_t::__extents.template __extent<Idxs>() : 1), /* * ... * */ 1);
}
MDSPAN_INLINE_FUNCTION
constexpr ptrdiff_t get_stride(size_t n) const noexcept {
return _MDSPAN_FOLD_TIMES_RIGHT((IdxConditional{}(Idxs, n) ? base_t::__extents.template __extent<Idxs>() : 1), /* * ... * */ 1);
}
};
//==============================================================================================================
template <class, class, class>
class fixed_layout_common_impl;
template <ptrdiff_t... Exts, size_t... Idxs, class IdxConditional>
class fixed_layout_common_impl<std::experimental::extents<Exts...>, integer_sequence<size_t, Idxs...>, IdxConditional>
: protected stride_storage_impl<std::experimental::extents<Exts...>, integer_sequence<size_t, Idxs...>, IdxConditional>
{
private:
using base_t = stride_storage_impl<std::experimental::extents<Exts...>, integer_sequence<size_t, Idxs...>, IdxConditional>;
public:
MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr fixed_layout_common_impl() noexcept = default;
MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr fixed_layout_common_impl(fixed_layout_common_impl const&) noexcept = default;
MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr fixed_layout_common_impl(fixed_layout_common_impl&&) noexcept = default;
MDSPAN_INLINE_FUNCTION_DEFAULTED _MDSPAN_CONSTEXPR_14_DEFAULTED fixed_layout_common_impl& operator=(fixed_layout_common_impl const&) noexcept = default;
MDSPAN_INLINE_FUNCTION_DEFAULTED _MDSPAN_CONSTEXPR_14_DEFAULTED fixed_layout_common_impl& operator=(fixed_layout_common_impl&&) noexcept = default;
MDSPAN_INLINE_FUNCTION_DEFAULTED ~fixed_layout_common_impl() noexcept = default;
using base_t::base_t;
MDSPAN_INLINE_FUNCTION constexpr typename base_t::extents_type extents() const noexcept { return this->base_t::base_t::__extents; };
template <class... Integral>
MDSPAN_FORCE_INLINE_FUNCTION
constexpr ptrdiff_t operator()(Integral... idxs) const noexcept {
return _MDSPAN_FOLD_PLUS_RIGHT((idxs * this->base_t::template get_stride<Idxs>()), /* + ... + */ 0);
}
MDSPAN_INLINE_FUNCTION
constexpr ptrdiff_t required_span_size() const noexcept {
return _MDSPAN_FOLD_TIMES_RIGHT((base_t::__extents.template __extent<Idxs>()), /* * ... * */ 1);
}
MDSPAN_INLINE_FUNCTION constexpr bool is_unique() const noexcept { return true; }
MDSPAN_INLINE_FUNCTION constexpr bool is_contiguous() const noexcept { return true; }
MDSPAN_INLINE_FUNCTION constexpr bool is_strided() const noexcept { return true; }
MDSPAN_INLINE_FUNCTION
constexpr ptrdiff_t stride(size_t r) const noexcept {
return this->base_t::get_stride(r);
}
//--------------------------------------------------------------------------------
public: // (but not really)
template <size_t R>
MDSPAN_INLINE_FUNCTION
constexpr ptrdiff_t __stride() const noexcept {
return this->base_t::template get_stride<R>();
}
template <size_t N>
struct __static_stride_workaround {
static constexpr ptrdiff_t __result = _MDSPAN_FOLD_TIMES_RIGHT(
(IdxConditional{}(Idxs, N) ? base_t::extents_type::template __static_extent<Idxs, 0>() : 1), /* * ... * */ 1
);
static constexpr ptrdiff_t value = __result == 0 ? dynamic_extent : __result;
};
template <size_t N>
MDSPAN_INLINE_FUNCTION
static constexpr ptrdiff_t __static_stride() noexcept
{
return __static_stride_workaround<N>::value;
}
};
//==============================================================================================================
} // namespace detail
} // end namespace experimental
} // namespace std
namespace std {
namespace experimental {
//==============================================================================
namespace detail {
struct layout_right_idx_conditional {
MDSPAN_INLINE_FUNCTION_DEFAULTED
constexpr layout_right_idx_conditional() noexcept = default;
MDSPAN_FORCE_INLINE_FUNCTION
constexpr inline bool operator()(size_t Idx, size_t N) const noexcept {
return Idx > N;
};
};
template <class> class layout_right_impl;
template <ptrdiff_t... Exts>
class layout_right_impl<std::experimental::extents<Exts...>>
: public fixed_layout_common_impl<std::experimental::extents<Exts...>, make_index_sequence<sizeof...(Exts)>, layout_right_idx_conditional>
{
private:
using idx_seq = make_index_sequence<sizeof...(Exts)>;
using base_t = fixed_layout_common_impl<std::experimental::extents<Exts...>, make_index_sequence<sizeof...(Exts)>, layout_right_idx_conditional>;
template <class>
friend class layout_right_impl;
public:
//--------------------------------------------------------------------------------
MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr layout_right_impl() noexcept = default;
MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr layout_right_impl(layout_right_impl const&) noexcept = default;
MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr layout_right_impl(layout_right_impl&&) noexcept = default;
MDSPAN_INLINE_FUNCTION_DEFAULTED _MDSPAN_CONSTEXPR_14_DEFAULTED layout_right_impl& operator=(layout_right_impl const&) noexcept = default;
MDSPAN_INLINE_FUNCTION_DEFAULTED _MDSPAN_CONSTEXPR_14_DEFAULTED layout_right_impl& operator=(layout_right_impl&&) noexcept = default;
MDSPAN_INLINE_FUNCTION_DEFAULTED ~layout_right_impl() noexcept = default;
using base_t::base_t;
// TODO noexcept specification
MDSPAN_TEMPLATE_REQUIRES(
class OtherExtents,
/* requires */ (
_MDSPAN_TRAIT(is_convertible, OtherExtents, std::experimental::extents<Exts...>)
)
)
MDSPAN_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14
layout_right_impl(layout_right_impl<OtherExtents> const& other) // NOLINT(google-explicit-constructor)
: base_t(other.extents())
{ }
// TODO noexcept specification
MDSPAN_TEMPLATE_REQUIRES(
class OtherExtents,
/* requires */ (
_MDSPAN_TRAIT(is_convertible, OtherExtents, std::experimental::extents<Exts...>)
)
)
MDSPAN_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14
layout_right_impl& operator=(layout_right_impl<OtherExtents> const& other)
{
this->__extents = other.extents();
return *this;
}
//--------------------------------------------------------------------------------
MDSPAN_INLINE_FUNCTION static constexpr bool is_always_unique() noexcept { return true; }
MDSPAN_INLINE_FUNCTION static constexpr bool is_always_contiguous() noexcept { return true; }
MDSPAN_INLINE_FUNCTION static constexpr bool is_always_strided() noexcept { return true; }
// TODO @proposal-bug these (and other analogous operators) should be non-member functions
template<class OtherExtents>
MDSPAN_INLINE_FUNCTION
constexpr bool operator==(layout_right_impl<OtherExtents> const& other) const noexcept {
return this->base_t::extents() == other.extents();
}
template<class OtherExtents>
MDSPAN_INLINE_FUNCTION
constexpr bool operator!=(layout_right_impl<OtherExtents> const& other) const noexcept {
return this->base_t::extents() != other.extents();
}
};
} // namespace detail
//==============================================================================
struct layout_right {
template <class Extents>
using mapping = detail::layout_right_impl<Extents>;
};
} // end namespace experimental
} // end namespace std
namespace std {
namespace experimental {
template <
class ElementType,
class Extents,
class LayoutPolicy = layout_right,
class AccessorPolicy = accessor_basic<ElementType>
>
class basic_mdspan;
template <
class ElementType,
ptrdiff_t... Exts,
class LayoutPolicy,
class AccessorPolicy
>
class basic_mdspan<
ElementType,
std::experimental::extents<Exts...>,
LayoutPolicy,
AccessorPolicy
>
{
private:
// Workaround for non-deducibility of the index sequence template parameter if it's given at the top level
template <class=make_index_sequence<sizeof...(Exts)>>
struct __impl;
template <size_t... Idxs>
struct __impl<index_sequence<Idxs...>>
{
MDSPAN_FORCE_INLINE_FUNCTION static constexpr
ptrdiff_t __size(basic_mdspan const& __self) noexcept {
return _MDSPAN_FOLD_TIMES_RIGHT((__self.map_.extents().template __extent<Idxs>()), /* * ... * */ 1);
}
template <class ReferenceType, class IndexType, size_t N>
MDSPAN_FORCE_INLINE_FUNCTION static constexpr
ReferenceType __callop(basic_mdspan const& __self, const array<IndexType, N>& indices) noexcept {
return __self.acc_.access(__self.ptr_, __self.map_(indices[Idxs]...));
}
};
public:
//--------------------------------------------------------------------------------
// Domain and codomain types
using extents_type = std::experimental::extents<Exts...>;
using layout_type = LayoutPolicy;
using accessor_type = AccessorPolicy;
using mapping_type = typename layout_type::template mapping<extents_type>;
using element_type = ElementType;
using value_type = remove_cv_t<element_type>;
using index_type = ptrdiff_t;
using difference_type = ptrdiff_t;
using pointer = typename accessor_type::pointer;
using reference = typename accessor_type::reference;
//--------------------------------------------------------------------------------
// [mdspan.basic.cons], basic_mdspan constructors, assignment, and destructor
MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr basic_mdspan() noexcept = default;
MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr basic_mdspan(const basic_mdspan&) noexcept = default;
MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr basic_mdspan(basic_mdspan&&) noexcept = default;
// TODO noexcept specification
MDSPAN_TEMPLATE_REQUIRES(
class... IndexType,
/* requires */ (
_MDSPAN_FOLD_AND(_MDSPAN_TRAIT(is_convertible, IndexType, index_type) /* && ... */) &&
(sizeof...(IndexType) == extents_type::rank_dynamic()) &&
_MDSPAN_TRAIT(is_constructible, mapping_type, extents_type) &&
_MDSPAN_TRAIT(is_default_constructible, accessor_type)
)
)
MDSPAN_INLINE_FUNCTION
explicit constexpr basic_mdspan(pointer p, IndexType... dynamic_extents)
noexcept
// TODO @proposal-bug shouldn't I be allowed to do `move(p)` here?
: ptr_(p),
map_(extents_type(dynamic_extents...)),
acc_()
{ }
// TODO noexcept specification
MDSPAN_TEMPLATE_REQUIRES(
class IndexType, size_t N,
/* requires */ (
_MDSPAN_TRAIT(is_convertible, IndexType, index_type) &&
(N == extents_type::rank_dynamic()) &&
_MDSPAN_TRAIT(is_constructible, mapping_type, extents_type) &&
_MDSPAN_TRAIT(is_default_constructible, accessor_type)
)
)
MDSPAN_INLINE_FUNCTION
explicit constexpr basic_mdspan(pointer p, const array<IndexType, N>& dynamic_extents)
noexcept
: ptr_(p),
map_(extents_type(dynamic_extents)),
acc_()
{ }
// TODO noexcept specification
MDSPAN_FUNCTION_REQUIRES(
(MDSPAN_INLINE_FUNCTION constexpr),
basic_mdspan, (pointer p, const mapping_type& m), noexcept,
/* requires */ (_MDSPAN_TRAIT(is_default_constructible, accessor_type))
) : ptr_(p),
map_(m),
acc_()
{ }
// TODO noexcept specification
MDSPAN_INLINE_FUNCTION
constexpr basic_mdspan(pointer p, const mapping_type& m, const accessor_type& a) noexcept
: ptr_(p),
map_(m),
acc_(a)
{ }
// TODO noexcept specification
MDSPAN_TEMPLATE_REQUIRES(
class OtherElementType, class OtherExtents, class OtherLayoutPolicy, class OtherAccessor,
/* requires */ (
_MDSPAN_TRAIT(is_convertible, typename OtherLayoutPolicy::template mapping<OtherExtents>, mapping_type) &&
_MDSPAN_TRAIT(is_convertible, OtherAccessor, accessor_type) &&
_MDSPAN_TRAIT(is_convertible, typename OtherAccessor::pointer, pointer) &&
// TODO @proposal-bug there is a redundant constraint in the proposal; the convertibility of the extents is effectively stated twice
_MDSPAN_TRAIT(is_convertible, OtherExtents, extents_type)
)
)
MDSPAN_INLINE_FUNCTION
constexpr basic_mdspan(const basic_mdspan<OtherElementType, OtherExtents, OtherLayoutPolicy, OtherAccessor>& other)
: ptr_(other.ptr_),
map_(other.map_),
acc_(other.acc_)
{ }
MDSPAN_INLINE_FUNCTION_DEFAULTED
~basic_mdspan() noexcept = default;
MDSPAN_INLINE_FUNCTION_DEFAULTED _MDSPAN_CONSTEXPR_14_DEFAULTED basic_mdspan& operator=(const basic_mdspan&) noexcept = default;
MDSPAN_INLINE_FUNCTION_DEFAULTED _MDSPAN_CONSTEXPR_14_DEFAULTED basic_mdspan& operator=(basic_mdspan&&) noexcept = default;
MDSPAN_TEMPLATE_REQUIRES(
class OtherElementType, ptrdiff_t... OtherExtents, class OtherLayoutPolicy, class OtherAccessorPolicy,
/* requires */ (
_MDSPAN_TRAIT(is_assignable, mapping_type, typename OtherLayoutPolicy::template mapping<std::experimental::extents<OtherExtents...>>) &&
_MDSPAN_TRAIT(is_assignable, accessor_type, OtherAccessorPolicy) &&
_MDSPAN_TRAIT(is_assignable, pointer, typename OtherAccessorPolicy::pointer) &&
sizeof...(OtherExtents) == extents_type::rank() &&
// "For all r in the range [0, rank()), if other.static_extent(r) != dynamic_extent
// && static_extent(r) != dynamic_extent is true, then
// other.static_extent(r) == static_extent(r) is true."
// (this is just the convertiblity constraint on extents...)
_MDSPAN_TRAIT(is_convertible, std::experimental::extents<Exts...>, std::experimental::extents<OtherExtents...>)
)
)
MDSPAN_INLINE_FUNCTION
_MDSPAN_CONSTEXPR_14 basic_mdspan& operator=(
const basic_mdspan<OtherElementType, std::experimental::extents<OtherExtents...>, OtherLayoutPolicy, OtherAccessorPolicy>& other
) noexcept(/* TODO noexcept specification */ true)
{
ptr_ = other.ptr_;
map_ = other.map_;
acc_ = other.acc_;
return *this;
}
//--------------------------------------------------------------------------------
// [mdspan.basic.mapping], basic_mdspan mapping domain multidimensional index to access codomain element
MDSPAN_TEMPLATE_REQUIRES(
class Index,
/* requires */ (
_MDSPAN_TRAIT(is_convertible, Index, index_type) &&
sizeof...(Exts) == 1
)
)
MDSPAN_FORCE_INLINE_FUNCTION
constexpr reference operator[](Index idx) const noexcept
{
return acc_.access(ptr_, map_(index_type(idx)));
}
MDSPAN_TEMPLATE_REQUIRES(
class... IndexType,
/* requires */ (
_MDSPAN_FOLD_AND(_MDSPAN_TRAIT(is_convertible, IndexType, index_type) /* && ... */) &&
sizeof...(Exts) == extents_type::rank()
)
)
MDSPAN_FORCE_INLINE_FUNCTION
constexpr reference operator()(IndexType... indices) const noexcept
{
return acc_.access(ptr_, map_(index_type(indices)...));
}
MDSPAN_TEMPLATE_REQUIRES(
class IndexType, size_t N,
/* requires */ (
_MDSPAN_TRAIT(is_convertible, IndexType, index_type) &&
N == extents_type::rank()
)
)
MDSPAN_FORCE_INLINE_FUNCTION
constexpr reference operator()(const array<IndexType, N>& indices) const noexcept
{
return __impl<>::template __callop<reference>(*this, indices);
}
MDSPAN_INLINE_FUNCTION
accessor_type accessor() const { return acc_; };
//--------------------------------------------------------------------------------
// [mdspan.basic.domobs], basic_mdspan observers of the domain multidimensional index space
MDSPAN_INLINE_FUNCTION static constexpr int rank() noexcept { return extents_type::rank(); }
MDSPAN_INLINE_FUNCTION static constexpr int rank_dynamic() noexcept { return extents_type::rank_dynamic(); }
MDSPAN_INLINE_FUNCTION static constexpr index_type static_extent(size_t r) noexcept { return extents_type::static_extent(r); }
MDSPAN_INLINE_FUNCTION constexpr extents_type extents() const noexcept { return map_.extents(); };
MDSPAN_INLINE_FUNCTION constexpr index_type extent(size_t r) const noexcept { return map_.extents().extent(r); };
MDSPAN_INLINE_FUNCTION constexpr index_type size() const noexcept {
return __impl<>::__size(*this);
};
// TODO @proposal-bug for non-unique, non-contiguous mappings this is unimplementable
MDSPAN_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 index_type unique_size() const noexcept {
if(map_.is_unique()) {
return size();
}
else if(map_.is_contiguous()) {
return map_.required_span_size();
}
else {
// ??? guess, for now, until this gets fixed in the proposal ???
return map_.required_span_size();
}
}
// [mdspan.basic.codomain], basic_mdspan observers of the codomain
// TODO span (or just `codomain` function, as discussed)
// constexpr span<element_type> span() const noexcept;
MDSPAN_INLINE_FUNCTION constexpr pointer data() const noexcept { return ptr_; };
//--------------------------------------------------------------------------------
// [mdspan.basic.obs], basic_mdspan observers of the mapping
MDSPAN_INLINE_FUNCTION static constexpr bool is_always_unique() noexcept { return mapping_type::is_always_unique(); };
MDSPAN_INLINE_FUNCTION static constexpr bool is_always_contiguous() noexcept { return mapping_type::is_always_contiguous(); };
MDSPAN_INLINE_FUNCTION static constexpr bool is_always_strided() noexcept { return mapping_type::is_always_strided(); };
MDSPAN_INLINE_FUNCTION constexpr mapping_type mapping() const noexcept { return map_; };
MDSPAN_INLINE_FUNCTION constexpr bool is_unique() const noexcept { return map_.is_unique(); };
MDSPAN_INLINE_FUNCTION constexpr bool is_contiguous() const noexcept { return map_.is_contiguous(); };
MDSPAN_INLINE_FUNCTION constexpr bool is_strided() const noexcept { return map_.is_strided(); };
MDSPAN_INLINE_FUNCTION constexpr index_type stride(size_t r) const { return map_.stride(r); };
private:
pointer ptr_ = nullptr;
_MDSPAN_NO_UNIQUE_ADDRESS mapping_type map_;
_MDSPAN_NO_UNIQUE_ADDRESS accessor_type acc_;
template <class, class, class, class>
friend class basic_mdspan;
};
template <class T, ptrdiff_t... Exts>
using mdspan = basic_mdspan<T, std::experimental::extents<Exts...>>;
} // end namespace experimental
} // end namespace std
/*
//@HEADER
// ************************************************************************
//
// Kokkos v. 2.0
// Copyright (2019) 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 Christian R. Trott ([email protected])
//
// ************************************************************************
//@HEADER
*/
namespace std {
namespace experimental {
//==============================================================================
namespace detail {
struct layout_left_idx_conditional {
MDSPAN_INLINE_FUNCTION_DEFAULTED
constexpr layout_left_idx_conditional() noexcept = default;
MDSPAN_FORCE_INLINE_FUNCTION
constexpr bool operator()(size_t Idx, size_t N) const noexcept {
return Idx < N;
};
};
template <class> class layout_left_impl;
template <ptrdiff_t... Exts>
class layout_left_impl<std::experimental::extents<Exts...>>
: public fixed_layout_common_impl<std::experimental::extents<Exts...>, make_index_sequence<sizeof...(Exts)>, layout_left_idx_conditional>
{
private:
using idx_seq = make_index_sequence<sizeof...(Exts)>;
using base_t = fixed_layout_common_impl<std::experimental::extents<Exts...>, make_index_sequence<sizeof...(Exts)>, layout_left_idx_conditional>;
template <class>
friend class layout_left_impl;
public:
//--------------------------------------------------------------------------------
MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr layout_left_impl() noexcept = default;
MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr layout_left_impl(layout_left_impl const&) noexcept = default;
MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr layout_left_impl(layout_left_impl&&) noexcept = default;
MDSPAN_INLINE_FUNCTION_DEFAULTED _MDSPAN_CONSTEXPR_14_DEFAULTED layout_left_impl& operator=(layout_left_impl const&) noexcept = default;
MDSPAN_INLINE_FUNCTION_DEFAULTED _MDSPAN_CONSTEXPR_14_DEFAULTED layout_left_impl& operator=(layout_left_impl&&) noexcept = default;
MDSPAN_INLINE_FUNCTION_DEFAULTED ~layout_left_impl() noexcept = default;
using base_t::base_t;
// TODO noexcept specification
MDSPAN_TEMPLATE_REQUIRES(
class OtherExtents,
/* requires */ (
_MDSPAN_TRAIT(is_convertible, OtherExtents, std::experimental::extents<Exts...>)
)
)
MDSPAN_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14
layout_left_impl(layout_left_impl<OtherExtents> const& other) // NOLINT(google-explicit-constructor)
: base_t(other.extents())
{ }
// TODO noexcept specification
MDSPAN_TEMPLATE_REQUIRES(
class OtherExtents,
/* requires */ (
_MDSPAN_TRAIT(is_convertible, OtherExtents, std::experimental::extents<Exts...>)
)
)
MDSPAN_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14
layout_left_impl& operator=(layout_left_impl<OtherExtents> const& other)
{
this->__extents = other.extents();
return *this;
}
//--------------------------------------------------------------------------------
MDSPAN_INLINE_FUNCTION static constexpr bool is_always_unique() noexcept { return true; }
MDSPAN_INLINE_FUNCTION static constexpr bool is_always_contiguous() noexcept { return true; }
MDSPAN_INLINE_FUNCTION static constexpr bool is_always_strided() noexcept { return true; }
// TODO @proposal-bug these (and other analogous operators) should be non-member functions
template<class OtherExtents>
MDSPAN_INLINE_FUNCTION
constexpr bool operator==(layout_left_impl<OtherExtents> const& other) const noexcept {
return this->base_t::extents() == other.extents();
}
template<class OtherExtents>
MDSPAN_INLINE_FUNCTION
constexpr bool operator!=(layout_left_impl<OtherExtents> const& other) const noexcept {
return this->base_t::extents() != other.extents();
}
};
} // namespace detail
//==============================================================================
struct layout_left {
template <class Extents>
using mapping = detail::layout_left_impl<Extents>;
};
} // end namespace experimental
} // end namespace std
/*
//@HEADER
// ************************************************************************
//
// Kokkos v. 2.0
// Copyright (2019) 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 Christian R. Trott ([email protected])
//
// ************************************************************************
//@HEADER
*/
namespace std {
namespace experimental {
//==============================================================================
namespace detail {
template <class, ptrdiff_t...> class layout_stride_impl;
template <ptrdiff_t... Exts, ptrdiff_t... Strides>
class layout_stride_impl<
std::experimental::extents<Exts...>, Strides...
>
: public extents_storage<std::experimental::extents<Exts...>>
{
private:
using base_t = extents_storage<std::experimental::extents<Exts...>>;
using idx_seq = make_index_sequence<sizeof...(Exts)>;
using stride_storage_t = typename _make_mixed_impl<integer_sequence<ptrdiff_t, Strides...>>::type;
template <class, ptrdiff_t...>
friend class layout_stride_impl;
// Workaround for non-deducibility of the index sequence template parameter if it's given at the top level
template <class=make_index_sequence<sizeof...(Exts)>>
struct __impl;
template <size_t... Idxs>
struct __impl<index_sequence<Idxs...>>
{
template <class OtherExtents, ptrdiff_t... OtherStrides>
MDSPAN_INLINE_FUNCTION
static constexpr bool _eq_impl(layout_stride_impl const& self, layout_stride_impl<OtherExtents, OtherStrides...> const& other) noexcept {
return _MDSPAN_FOLD_AND((self.template __stride<Idxs>() == other.template __stride<Idxs>()) /* && ... */);
}
template <class OtherExtents, ptrdiff_t... OtherStrides>
MDSPAN_INLINE_FUNCTION
static constexpr bool _not_eq_impl(layout_stride_impl const& self, layout_stride_impl<OtherExtents, OtherStrides...> const& other) noexcept {
return _MDSPAN_FOLD_OR((self.template __stride<Idxs>() != other.template __stride<Idxs>()) /* || ... */);
}
template <class... Integral>
MDSPAN_FORCE_INLINE_FUNCTION
static constexpr ptrdiff_t _call_op_impl(layout_stride_impl const& self, Integral... idxs) noexcept {
return _MDSPAN_FOLD_PLUS_RIGHT((idxs * self.template __stride<Idxs>()), /* + ... + */ 0);
}
MDSPAN_INLINE_FUNCTION
static constexpr size_t _req_span_size_impl(layout_stride_impl const& self) noexcept {
// assumes no negative strides; not sure if I'm allowed to assume that or not
return __impl::_call_op_impl(self, (self.extents().template __extent<Idxs>() - 1)...) + 1;
}
};
public: // (but not really)
template <size_t N>
MDSPAN_FORCE_INLINE_FUNCTION
constexpr ptrdiff_t __stride() const noexcept {
return _strides.template get<N>();
}
template <size_t N>
struct __static_stride_workaround {
static constexpr ptrdiff_t value = stride_storage_t::template get_static<N, dynamic_extent>();
};
template <size_t N>
MDSPAN_INLINE_FUNCTION
static constexpr ptrdiff_t __static_stride() noexcept
{
return stride_storage_t::template get_static<N>();
}
public:
//--------------------------------------------------------------------------------
MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr layout_stride_impl() noexcept = default;
MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr layout_stride_impl(layout_stride_impl const&) noexcept = default;
MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr layout_stride_impl(layout_stride_impl&&) noexcept = default;
// TODO @proposal-bug layout stride needs this constructor
MDSPAN_INLINE_FUNCTION
constexpr
layout_stride_impl(
std::experimental::extents<Exts...> const& e,
array<ptrdiff_t, stride_storage_t::size_dynamic> const& strides
) noexcept
: base_t(e),
_strides(strides)
{ }
MDSPAN_INLINE_FUNCTION_DEFAULTED _MDSPAN_CONSTEXPR_14_DEFAULTED layout_stride_impl& operator=(layout_stride_impl const&) noexcept = default;
MDSPAN_INLINE_FUNCTION_DEFAULTED _MDSPAN_CONSTEXPR_14_DEFAULTED layout_stride_impl& operator=(layout_stride_impl&&) noexcept = default;
MDSPAN_INLINE_FUNCTION_DEFAULTED ~layout_stride_impl() noexcept = default;
using base_t::base_t;
// TODO conversion constructors and assignment
//--------------------------------------------------------------------------------
MDSPAN_INLINE_FUNCTION constexpr typename base_t::extents_type extents() const noexcept { return this->base_t::__extents; };
MDSPAN_INLINE_FUNCTION constexpr bool is_unique() const noexcept { return true; }
// TODO @proposal-bug this wording for this is (at least slightly) broken (should at least be "... stride(p[0]) == 1...")
MDSPAN_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 bool is_contiguous() const noexcept {
// TODO @testing test layout_stride is_contiguous()
auto rem = std::array<ptrdiff_t, sizeof...(Exts)>{ };
std::iota(rem.begin(), rem.end(), ptrdiff_t(0));
auto next_idx_iter = std::find_if(
rem.begin(), rem.end(),
[&](ptrdiff_t i) { _strides.get(i) == 1; }
);
if(next_idx_iter != rem.end()) {
ptrdiff_t prev_stride_times_prev_extent =
this->extents().extent(*next_idx_iter) * _strides.get(*next_idx_iter);
// "remove" the index
constexpr ptrdiff_t removed_index_sentinel = -1;
*next_idx_iter = removed_index_sentinel;
int found_count = 1;
while (found_count != sizeof...(Exts)) {
next_idx_iter = std::find_if(
rem.begin(), rem.end(),
[&](ptrdiff_t i) {
return i != removed_index_sentinel
&& _strides.get(i) * this->extents().extent(i) == prev_stride_times_prev_extent;
}
);
if (next_idx_iter != rem.end()) {
// "remove" the index
*next_idx_iter = removed_index_sentinel;
++found_count;
prev_stride_times_prev_extent = _strides.get(*next_idx_iter) * this->extents().extent(*next_idx_iter);
} else { break; }
}
return found_count == sizeof...(Exts);
}
return false;
}
MDSPAN_INLINE_FUNCTION constexpr bool is_strided() const noexcept { return true; }
MDSPAN_INLINE_FUNCTION static constexpr bool is_always_unique() noexcept { return true; }
MDSPAN_INLINE_FUNCTION static constexpr bool is_always_contiguous() noexcept {
// TODO @proposal-bug this will need to be updated with the incorporation of static strides into the layout stride definition
// TODO this should actually check whether we know statically from the strides if this is always contiguous
return false;
}
MDSPAN_INLINE_FUNCTION static constexpr bool is_always_strided() noexcept { return true; }
MDSPAN_TEMPLATE_REQUIRES(
class... Indices,
/* requires */ (
sizeof...(Indices) == sizeof...(Exts) &&
_MDSPAN_FOLD_AND(_MDSPAN_TRAIT(is_constructible, Indices, ptrdiff_t) /*&& ...*/)
)
)
MDSPAN_FORCE_INLINE_FUNCTION
constexpr ptrdiff_t operator()(Indices... idxs) const noexcept {
return __impl<>::_call_op_impl(*this, idxs...);
}
MDSPAN_INLINE_FUNCTION
constexpr ptrdiff_t stride(size_t r) const noexcept {
return _strides.get(r);
}
MDSPAN_INLINE_FUNCTION
constexpr ptrdiff_t required_span_size() const noexcept {
// assumes no negative strides; not sure if I'm allowed to assume that or not
return __impl<>::_req_span_size_impl(*this);
}
// TODO @proposal-bug these (and other analogous operators) should be non-member functions
// TODO @proposal-bug these should do more than just compare extents!
template<class OtherExtents, ptrdiff_t... OtherStaticStrides>
MDSPAN_INLINE_FUNCTION
constexpr bool operator==(layout_stride_impl<OtherExtents, OtherStaticStrides...> const& other) const noexcept {
return __impl<>::_eq_impl(*this, other);
}
template<class OtherExtents, ptrdiff_t... OtherStaticStrides>
MDSPAN_INLINE_FUNCTION
constexpr bool operator!=(layout_stride_impl<OtherExtents, OtherStaticStrides...> const& other) const noexcept {
return __impl<>::_not_eq_impl(*this, other);
}
private:
_MDSPAN_NO_UNIQUE_ADDRESS stride_storage_t _strides = { };
};
} // namespace detail
//==============================================================================
// TODO @proposal-bug layout_stride needs these non-type template parameters
template <ptrdiff_t... StaticStrides>
struct layout_stride {
template <class Extents>
using mapping = detail::layout_stride_impl<
Extents, StaticStrides...
>;
};
} // end namespace experimental
} // end namespace std
/*
//@HEADER
// ************************************************************************
//
// Kokkos v. 2.0
// Copyright (2019) 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 Christian R. Trott ([email protected])
//
// ************************************************************************
//@HEADER
*/
namespace std {
namespace experimental {
namespace detail {
template <ptrdiff_t OldExtent, ptrdiff_t OldStaticStride, class T>
struct _slice_wrap {
T slice;
ptrdiff_t old_extent;
ptrdiff_t old_stride;
};
//--------------------------------------------------------------------------------
template <ptrdiff_t OldExtent, ptrdiff_t OldStaticStride>
MDSPAN_INLINE_FUNCTION
_slice_wrap<OldExtent, OldStaticStride, ptrdiff_t>
_wrap_slice(ptrdiff_t val, ptrdiff_t ext, ptrdiff_t stride) { return { val, ext, stride }; }
template <ptrdiff_t OldExtent, ptrdiff_t OldStaticStride>
MDSPAN_INLINE_FUNCTION
_slice_wrap<OldExtent, OldStaticStride, all_type>
_wrap_slice(all_type val, ptrdiff_t ext, ptrdiff_t stride) { return { val, ext, stride }; }
// TODO generalize this to anything that works with std::get<0> and std::get<1>
template <ptrdiff_t OldExtent, ptrdiff_t OldStaticStride>
MDSPAN_INLINE_FUNCTION
_slice_wrap<OldExtent, OldStaticStride, std::pair<ptrdiff_t, ptrdiff_t>>
_wrap_slice(std::pair<ptrdiff_t, ptrdiff_t> const& val, ptrdiff_t ext, ptrdiff_t stride)
{
return { val, ext, stride };
}
//--------------------------------------------------------------------------------
template <
bool result=true,
bool encountered_first_all=false,
bool encountered_first_pair=false
>
struct preserve_layout_right_analysis : std::integral_constant<bool, result> {
using layout_type_if_preserved = layout_right;
using encounter_pair = preserve_layout_right_analysis<
// If the pair isn't the right-most slice (i.e., if there was a previous pair),
// we can't preserve any contiguous layout. Nothing else should matter
(encountered_first_pair ? false : result),
// Whether or not we've encountered the first all doesn't change, though it
// doesn't really matter, since anything to the right of this leads to a false
// result
encountered_first_all,
// This is a pair, so we've encountered at least one
true
>;
using encounter_all = preserve_layout_right_analysis<
// encountering an all changes nothing unless we've already encountered a pair
(encountered_first_pair ? false : result),
// This is an all, so we've encountered at least one
true,
// nothing changes about this last one
encountered_first_pair
>;
using encounter_scalar = preserve_layout_right_analysis<
// if there's a scalar to the right of any non-scalar slice, we can't preserve
// any contiguous layout:
(encountered_first_all || encountered_first_pair) ? false : result,
// nothing else changes (though if they're true, it doesn't matter)
encountered_first_all,
encountered_first_pair
>;
};
template <
bool result=true,
bool encountered_first_scalar=false,
bool encountered_first_all=false,
bool encountered_first_pair=false
>
struct preserve_layout_left_analysis : std::integral_constant<bool, result> {
using layout_type_if_preserved = layout_left;
using encounter_pair = preserve_layout_left_analysis<
// Only the left-most slice can be a pair. If we've encountered anything else,
// we can't preserve any contiguous layout
(encountered_first_scalar || encountered_first_all || encountered_first_pair) ? false : result,
// These change in the expected ways
encountered_first_scalar,
encountered_first_all,
true
>;
using encounter_all = preserve_layout_left_analysis<
// If there's a scalar to the left of us, we can't preserve contiguous
encountered_first_scalar ? false : result,
// These change in the expected ways
encountered_first_scalar,
true,
encountered_first_pair
>;
using encounter_scalar = preserve_layout_left_analysis<
// If there's a scalar to the left of us, we can't preserve contiguous
result,
// These change in the expected ways
true,
encountered_first_all,
encountered_first_pair
>;
};
struct ignore_layout_preservation : std::integral_constant<bool, false> {
using layout_type_if_preserved = void;
using encounter_pair = ignore_layout_preservation;
using encounter_all = ignore_layout_preservation;
using encounter_scalar = ignore_layout_preservation;
};
//--------------------------------------------------------------------------------
template <
class Extents, class StaticStrides, class PreserveLayoutAnalysis,
class Offsets = __array_workaround::__array<ptrdiff_t, 0>,
class ExtentInitializers = __array_workaround::__array<ptrdiff_t, 0>,
class DynamicStrides = __array_workaround::__array<ptrdiff_t, 0>,
class=std::make_index_sequence<Offsets::__size>,
class=std::make_index_sequence<ExtentInitializers::__size>,
class=std::make_index_sequence<DynamicStrides::__size>
>
struct _assign_op_slice_handler;
template <
ptrdiff_t... Extents,
ptrdiff_t... StaticStrides,
class PreserveLayoutAnalysis,
size_t NOffsets,
size_t NDynamicExtents,
size_t NDynamicStrides,
size_t... OffsetIdxs,
size_t... ExtentInitIdxs,
size_t... DynamicStrideIdxs
>
struct _assign_op_slice_handler<
integer_sequence<ptrdiff_t, Extents...>,
integer_sequence<ptrdiff_t, StaticStrides...>,
PreserveLayoutAnalysis,
__array_workaround::__array<ptrdiff_t, NOffsets>,
__array_workaround::__array<ptrdiff_t, NDynamicExtents>,
__array_workaround::__array<ptrdiff_t, NDynamicStrides>,
integer_sequence<size_t, OffsetIdxs...>,
integer_sequence<size_t, ExtentInitIdxs...>,
integer_sequence<size_t, DynamicStrideIdxs...>
>
{
static_assert(
_MDSPAN_FOLD_AND((StaticStrides == dynamic_extent || StaticStrides > 0) /* && ... */),
" "
);
__array_workaround::__array<ptrdiff_t, NOffsets> offsets = { };
__array_workaround::__array<ptrdiff_t, NDynamicExtents> dynamic_extents = { };
__array_workaround::__array<ptrdiff_t, NDynamicStrides> dynamic_strides = { };
// Some old compilers don't like aggregate initialization, so we have to do this. It shouldn't hurt other compilers
#if !MDSPAN_HAS_CXX_14
MDSPAN_INLINE_FUNCTION
_assign_op_slice_handler(
__array_workaround::__array<ptrdiff_t, NOffsets> arg_offsets,
__array_workaround::__array<ptrdiff_t, NDynamicExtents> arg_dynamic_extents,
__array_workaround::__array<ptrdiff_t, NDynamicStrides> arg_dynamic_strides
) noexcept
: offsets(std::move(arg_offsets)),
dynamic_extents(std::move(arg_dynamic_extents)),
dynamic_strides(std::move(arg_dynamic_strides))
{ }
MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr _assign_op_slice_handler() noexcept = default;
MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr _assign_op_slice_handler(_assign_op_slice_handler const&) noexcept = default;
MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr _assign_op_slice_handler(_assign_op_slice_handler&&) noexcept = default;
#endif
#if !defined(_MDSPAN_USE_RETURN_TYPE_DEDUCTION) || !_MDSPAN_USE_RETURN_TYPE_DEDUCTION
using extents_type = std::experimental::extents<Extents...>;
#endif
// TODO defer instantiation of this?
using layout_type = typename conditional<
PreserveLayoutAnalysis::value,
typename PreserveLayoutAnalysis::layout_type_if_preserved,
layout_stride<StaticStrides...>
>::type;
// TODO noexcept specification
template <class NewLayout>
MDSPAN_INLINE_FUNCTION
_MDSPAN_DEDUCE_RETURN_TYPE_SINGLE_LINE(
(
constexpr /* auto */
_make_layout_mapping_impl(NewLayout) const noexcept
),
(
/* not layout stride, so don't pass dynamic_strides */
/* return */ typename NewLayout::template mapping<std::experimental::extents<Extents...>>(
std::experimental::extents<Extents...>(dynamic_extents.template __get_n<ExtentInitIdxs>()...)
) /* ; */
)
)
MDSPAN_INLINE_FUNCTION
_MDSPAN_DEDUCE_RETURN_TYPE_SINGLE_LINE(
(
constexpr /* auto */
_make_layout_mapping_impl(layout_stride<StaticStrides...>) const noexcept
),
(
/* return */ typename layout_stride<StaticStrides...>::template mapping<std::experimental::extents<Extents...>>(
std::experimental::extents<Extents...>(dynamic_extents.template __get_n<ExtentInitIdxs>()...),
std::array<ptrdiff_t, NDynamicStrides>{dynamic_strides.template __get_n<DynamicStrideIdxs>()...}
) /* ; */
)
)
template <class OldLayoutMapping> // mostly for deferred instantiation, but maybe we'll use this in the future
MDSPAN_INLINE_FUNCTION
_MDSPAN_DEDUCE_RETURN_TYPE_SINGLE_LINE(
(
constexpr /* auto */
make_layout_mapping(OldLayoutMapping const&) const noexcept
),
(
/* return */ this->_make_layout_mapping_impl(layout_type{}) /* ; */
)
)
template <ptrdiff_t OldStaticExtent, ptrdiff_t OldStaticStride, class T>
MDSPAN_INLINE_FUNCTION
constexpr auto fwd_extent(_slice_wrap<OldStaticExtent, OldStaticStride, T> const& slice) const noexcept
-> decltype(dynamic_extents)
{
return dynamic_extents;
}
template <ptrdiff_t OldStaticStride, class T>
MDSPAN_INLINE_FUNCTION
constexpr auto fwd_extent(_slice_wrap<dynamic_extent, OldStaticStride, T> const& slice) const noexcept
-> __array_workaround::__array<ptrdiff_t, sizeof...(ExtentInitIdxs) + 1>
{
return { dynamic_extents.template __get_n<ExtentInitIdxs>()..., slice.old_extent };
}
template <ptrdiff_t OldStaticExtent, ptrdiff_t OldStaticStride, class T>
MDSPAN_INLINE_FUNCTION
constexpr auto fwd_stride(_slice_wrap<OldStaticExtent, OldStaticStride, T> const& slice) const noexcept
-> decltype(dynamic_strides)
{
return dynamic_strides;
}
template <ptrdiff_t OldStaticExtent, class T>
MDSPAN_INLINE_FUNCTION
constexpr auto fwd_stride(_slice_wrap<OldStaticExtent, dynamic_extent, T> const& slice) const noexcept
-> __array_workaround::__array<ptrdiff_t, sizeof...(DynamicStrideIdxs) + 1>
{
return { dynamic_strides.template __get_n<DynamicStrideIdxs>()..., slice.old_stride };
}
// For ptrdiff_t slice, skip the extent and stride, but add an offset corresponding to the value
template <ptrdiff_t OldStaticExtent, ptrdiff_t OldStaticStride>
MDSPAN_FORCE_INLINE_FUNCTION // NOLINT (misc-unconventional-assign-operator)
_MDSPAN_CONSTEXPR_14 auto
operator=(_slice_wrap<OldStaticExtent, OldStaticStride, ptrdiff_t> slice) noexcept
-> _assign_op_slice_handler<
integer_sequence<ptrdiff_t, Extents...>,
integer_sequence<ptrdiff_t, StaticStrides...>,
typename PreserveLayoutAnalysis::encounter_scalar,
__array_workaround::__array<ptrdiff_t, NOffsets + 1>,
__array_workaround::__array<ptrdiff_t, NDynamicExtents>,
__array_workaround::__array<ptrdiff_t, NDynamicStrides>
>
{
return {
__array_workaround::__array<ptrdiff_t, NOffsets + 1>( offsets.template __get_n<OffsetIdxs>()..., slice.slice ),
dynamic_extents,
dynamic_strides
};
}
// For a std::all, offset 0 and old extent
template <ptrdiff_t OldStaticExtent, ptrdiff_t OldStaticStride>
MDSPAN_FORCE_INLINE_FUNCTION // NOLINT (misc-unconventional-assign-operator)
_MDSPAN_CONSTEXPR_14 auto
operator=(_slice_wrap<OldStaticExtent, OldStaticStride, all_type> slice) noexcept
-> _assign_op_slice_handler<
integer_sequence<ptrdiff_t, Extents..., OldStaticExtent>,
integer_sequence<ptrdiff_t, StaticStrides..., OldStaticStride>,
typename PreserveLayoutAnalysis::encounter_all,
__array_workaround::__array<ptrdiff_t, NOffsets + 1>,
decltype(this->fwd_extent(slice)),
decltype(this->fwd_stride(slice))
>
{
return {
__array_workaround::__array<ptrdiff_t, NOffsets + 1>(offsets.template __get_n<OffsetIdxs>()..., ptrdiff_t(0)),
this->fwd_extent(slice),
this->fwd_stride(slice)
};
}
// For a std::pair, add an offset and add a new dynamic extent (strides still preserved)
template <ptrdiff_t OldStaticExtent, ptrdiff_t OldStaticStride>
MDSPAN_FORCE_INLINE_FUNCTION // NOLINT (misc-unconventional-assign-operator)
_MDSPAN_CONSTEXPR_14 auto
operator=(_slice_wrap<OldStaticExtent, OldStaticStride, std::pair<ptrdiff_t, ptrdiff_t>> slice) noexcept
-> _assign_op_slice_handler<
integer_sequence<ptrdiff_t, Extents..., dynamic_extent>,
integer_sequence<ptrdiff_t, StaticStrides..., OldStaticStride>,
typename PreserveLayoutAnalysis::encounter_pair,
__array_workaround::__array<ptrdiff_t, NOffsets + 1>,
__array_workaround::__array<ptrdiff_t, NDynamicExtents + 1>,
decltype(this->fwd_stride(slice))
>
{
return {
__array_workaround::__array<ptrdiff_t, NOffsets + 1>(offsets.template __get_n<OffsetIdxs>()..., std::get<0>(slice.slice)),
__array_workaround::__array<ptrdiff_t, NDynamicExtents + 1>(dynamic_extents.template __get_n<ExtentInitIdxs>()..., std::get<1>(slice.slice) - std::get<0>(slice.slice)),
this->fwd_stride(slice)
};
}
};
#if _MDSPAN_USE_RETURN_TYPE_DEDUCTION
// Forking this because the C++11 version will be *completely* unreadable
template <class ET, ptrdiff_t... Exts, class LP, class AP, class... SliceSpecs, size_t... Idxs>
MDSPAN_INLINE_FUNCTION
constexpr auto _subspan_impl(
std::integer_sequence<size_t, Idxs...>,
basic_mdspan<ET, std::experimental::extents<Exts...>, LP, AP> const& src,
SliceSpecs&&... slices
) noexcept
{
auto _handled =
_MDSPAN_FOLD_ASSIGN_LEFT(
(
detail::_assign_op_slice_handler<
integer_sequence<ptrdiff_t>,
integer_sequence<ptrdiff_t>,
typename std::conditional<
std::is_same<LP, layout_right>::value,
detail::preserve_layout_right_analysis<>,
typename std::conditional<
std::is_same<LP, layout_left>::value,
detail::preserve_layout_left_analysis<>,
detail::ignore_layout_preservation
>::type
>::type
>{std::array<ptrdiff_t, 0>{}, std::array<ptrdiff_t, 0>{}, std::array<ptrdiff_t, 0>{}}
),
/* = ... = */
detail::_wrap_slice<
Exts, decltype(src.mapping())::template __static_stride_workaround<Idxs>::value
>(
slices, src.extents().template __extent<Idxs>(), src.mapping().stride(Idxs)
)
);
ptrdiff_t offset_size = src.mapping()(_handled.offsets.template __get_n<Idxs>()...);
auto offset_ptr = src.accessor().offset(src.data(), offset_size);
auto map = _handled.make_layout_mapping(src.mapping());
auto acc_pol = typename AP::offset_policy(src.accessor());
return basic_mdspan<
ET, decltype(map.extents()), typename decltype(_handled)::layout_type, decltype(acc_pol)
>(
std::move(offset_ptr), std::move(map), std::move(acc_pol)
);
}
#else
template <class ET, class AP, class Src, class Handled, size_t... Idxs>
auto _subspan_impl_helper(Src&& src, Handled&& h, std::integer_sequence<size_t, Idxs...>)
-> basic_mdspan<
ET, typename Handled::extents_type, typename Handled::layout_type, typename AP::offset_policy
>
{
return {
src.accessor().offset(src.data(), src.mapping()(h.offsets.template __get_n<Idxs>()...)),
h.make_layout_mapping(src.mapping()),
typename AP::offset_policy(src.accessor())
};
}
template <class ET, ptrdiff_t... Exts, class LP, class AP, class... SliceSpecs, size_t... Idxs>
MDSPAN_INLINE_FUNCTION
_MDSPAN_DEDUCE_RETURN_TYPE_SINGLE_LINE(
(
constexpr /* auto */ _subspan_impl(
std::integer_sequence<size_t, Idxs...> seq,
basic_mdspan<ET, std::experimental::extents<Exts...>, LP, AP> const& src,
SliceSpecs&&... slices
) noexcept
),
(
/* return */ _subspan_impl_helper<ET, AP>(
src,
_MDSPAN_FOLD_ASSIGN_LEFT(
(
detail::_assign_op_slice_handler<
integer_sequence<ptrdiff_t>,
integer_sequence<ptrdiff_t>,
typename std::conditional<
std::is_same<LP, layout_right>::value,
detail::preserve_layout_right_analysis<>,
typename std::conditional<
std::is_same<LP, layout_left>::value,
detail::preserve_layout_left_analysis<>,
detail::ignore_layout_preservation
>::type
>::type
>{std::array<ptrdiff_t, 0>{}, std::array<ptrdiff_t, 0>{}, std::array<ptrdiff_t, 0>{}}
),
/* = ... = */
detail::_wrap_slice<
Exts, decltype(src.mapping())::template __static_stride_workaround<Idxs>::value
>(
slices, src.extents().template __extent<Idxs>(), src.mapping().stride(Idxs)
)
),
seq
) /* ; */
)
)
#endif
template <class T> struct _is_layout_stride : std::false_type { };
template <ptrdiff_t... StaticStrides> struct _is_layout_stride<
layout_stride<StaticStrides...>
> : std::true_type
{ };
} // namespace detail
// TODO @proposal-bug sizeof...(SliceSpecs) == sizeof...(Exts) should be a constraint, not a requirement
MDSPAN_TEMPLATE_REQUIRES(
class ET, ptrdiff_t... Exts, class LP, class AP, class... SliceSpecs,
/* requires */ (
(
_MDSPAN_TRAIT(is_same, LP, layout_left)
|| _MDSPAN_TRAIT(is_same, LP, layout_right)
|| detail::_is_layout_stride<LP>::value
) &&
_MDSPAN_FOLD_OR((
_MDSPAN_TRAIT(is_convertible, SliceSpecs, ptrdiff_t)
|| _MDSPAN_TRAIT(is_convertible, SliceSpecs, pair<ptrdiff_t, ptrdiff_t>)
|| _MDSPAN_TRAIT(is_convertible, SliceSpecs, all_type)
) /* && ... */) &&
sizeof...(SliceSpecs) == sizeof...(Exts)
)
)
MDSPAN_INLINE_FUNCTION
_MDSPAN_DEDUCE_RETURN_TYPE_SINGLE_LINE(
(
constexpr subspan(
basic_mdspan<ET, std::experimental::extents<Exts...>, LP, AP> const& src, SliceSpecs... slices
) noexcept
),
(
/* return */
detail::_subspan_impl(std::make_index_sequence<sizeof...(SliceSpecs)>{}, src, slices...) /*;*/
)
)
} // end namespace experimental
} // namespace std
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment