Created
November 22, 2019 18:34
-
-
Save parsa/382f5e0729f95d225c3f6f57463eafae to your computer and use it in GitHub Desktop.
Single-Header distribution of https://github.com/kokkos/mdspan
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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