#ifndef _MDSPAN_SINGLE_HEADER_INCLUDE_GUARD_ #define _MDSPAN_SINGLE_HEADER_INCLUDE_GUARD_ //BEGIN_FILE_INCLUDE: /home/runner/work/mdspan/mdspan/include/experimental/mdarray //@HEADER // ************************************************************************ // // Kokkos v. 4.0 // Copyright (2022) National Technology & Engineering // Solutions of Sandia, LLC (NTESS). // // Under the terms of Contract DE-NA0003525 with NTESS, // the U.S. Government retains certain rights in this software. // // Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions. // See https://kokkos.org/LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //@HEADER #ifndef MDSPAN_IMPL_STANDARD_NAMESPACE #define MDSPAN_IMPL_STANDARD_NAMESPACE std #endif #ifndef MDSPAN_IMPL_PROPOSED_NAMESPACE #define MDSPAN_IMPL_PROPOSED_NAMESPACE experimental #endif //BEGIN_FILE_INCLUDE: /home/runner/work/mdspan/mdspan/include/experimental/mdspan //@HEADER // ************************************************************************ // // Kokkos v. 4.0 // Copyright (2022) National Technology & Engineering // Solutions of Sandia, LLC (NTESS). // // Under the terms of Contract DE-NA0003525 with NTESS, // the U.S. Government retains certain rights in this software. // // Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions. // See https://kokkos.org/LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //@HEADER #ifndef MDSPAN_IMPL_STANDARD_NAMESPACE #define MDSPAN_IMPL_STANDARD_NAMESPACE std #endif #ifndef MDSPAN_IMPL_PROPOSED_NAMESPACE #define MDSPAN_IMPL_PROPOSED_NAMESPACE experimental #endif //BEGIN_FILE_INCLUDE: /home/runner/work/mdspan/mdspan/include/mdspan/mdspan.hpp //@HEADER // ************************************************************************ // // Kokkos v. 4.0 // Copyright (2022) National Technology & Engineering // Solutions of Sandia, LLC (NTESS). // // Under the terms of Contract DE-NA0003525 with NTESS, // the U.S. Government retains certain rights in this software. // // Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions. // See https://kokkos.org/LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //@HEADER #ifndef MDSPAN_HPP_ #define MDSPAN_HPP_ #ifndef MDSPAN_IMPL_STANDARD_NAMESPACE #define MDSPAN_IMPL_STANDARD_NAMESPACE Kokkos #endif #ifndef MDSPAN_IMPL_PROPOSED_NAMESPACE #define MDSPAN_IMPL_PROPOSED_NAMESPACE Experimental #endif //BEGIN_FILE_INCLUDE: /home/runner/work/mdspan/mdspan/include/experimental/__p0009_bits/default_accessor.hpp //@HEADER // ************************************************************************ // // Kokkos v. 4.0 // Copyright (2022) National Technology & Engineering // Solutions of Sandia, LLC (NTESS). // // Under the terms of Contract DE-NA0003525 with NTESS, // the U.S. Government retains certain rights in this software. // // Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions. // See https://kokkos.org/LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //@HEADER //BEGIN_FILE_INCLUDE: /home/runner/work/mdspan/mdspan/include/experimental/__p0009_bits/macros.hpp //@HEADER // ************************************************************************ // // Kokkos v. 4.0 // Copyright (2022) National Technology & Engineering // Solutions of Sandia, LLC (NTESS). // // Under the terms of Contract DE-NA0003525 with NTESS, // the U.S. Government retains certain rights in this software. // // Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions. // See https://kokkos.org/LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //@HEADER //BEGIN_FILE_INCLUDE: /home/runner/work/mdspan/mdspan/include/experimental/__p0009_bits/config.hpp //@HEADER // ************************************************************************ // // Kokkos v. 4.0 // Copyright (2022) National Technology & Engineering // Solutions of Sandia, LLC (NTESS). // // Under the terms of Contract DE-NA0003525 with NTESS, // the U.S. Government retains certain rights in this software. // // Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions. // See https://kokkos.org/LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //@HEADER #ifndef __has_include # define __has_include(x) 0 #endif #if __has_include() # include #else # include # include #endif #ifdef _MSVC_LANG #define _MDSPAN_CPLUSPLUS _MSVC_LANG #else #define _MDSPAN_CPLUSPLUS __cplusplus #endif #define MDSPAN_CXX_STD_14 201402L #define MDSPAN_CXX_STD_17 201703L #define MDSPAN_CXX_STD_20 202002L // Note GCC has not updated this in version 13 #ifdef __clang__ #define MDSPAN_CXX_STD_23 202302L #else #define MDSPAN_CXX_STD_23 202100L #endif #define MDSPAN_HAS_CXX_14 (_MDSPAN_CPLUSPLUS >= MDSPAN_CXX_STD_14) #define MDSPAN_HAS_CXX_17 (_MDSPAN_CPLUSPLUS >= MDSPAN_CXX_STD_17) #define MDSPAN_HAS_CXX_20 (_MDSPAN_CPLUSPLUS >= MDSPAN_CXX_STD_20) #define MDSPAN_HAS_CXX_23 (_MDSPAN_CPLUSPLUS >= MDSPAN_CXX_STD_23) static_assert(_MDSPAN_CPLUSPLUS >= MDSPAN_CXX_STD_14, "mdspan requires C++14 or later."); #ifndef _MDSPAN_COMPILER_CLANG # if defined(__clang__) # define _MDSPAN_COMPILER_CLANG __clang__ # endif #endif #if !defined(_MDSPAN_COMPILER_MSVC) && !defined(_MDSPAN_COMPILER_MSVC_CLANG) # if defined(_MSC_VER) # if !defined(_MDSPAN_COMPILER_CLANG) # define _MDSPAN_COMPILER_MSVC _MSC_VER # else # define _MDSPAN_COMPILER_MSVC_CLANG _MSC_VER # endif # endif #endif #ifndef _MDSPAN_COMPILER_INTEL # ifdef __INTEL_COMPILER # define _MDSPAN_COMPILER_INTEL __INTEL_COMPILER # endif #endif #ifndef _MDSPAN_COMPILER_APPLECLANG # ifdef __apple_build_version__ # define _MDSPAN_COMPILER_APPLECLANG __apple_build_version__ # endif #endif #ifndef _MDSPAN_HAS_CUDA # if defined(__CUDACC__) # define _MDSPAN_HAS_CUDA __CUDACC__ # endif #endif #ifndef _MDSPAN_HAS_HIP # if defined(__HIPCC__) # define _MDSPAN_HAS_HIP __HIPCC__ # endif #endif #ifndef _MDSPAN_HAS_SYCL # if defined(SYCL_LANGUAGE_VERSION) # define _MDSPAN_HAS_SYCL SYCL_LANGUAGE_VERSION # endif #endif #ifndef __has_cpp_attribute # define __has_cpp_attribute(x) 0 #endif #ifndef _MDSPAN_PRESERVE_STANDARD_LAYOUT // Preserve standard layout by default, but we're not removing the old version // that turns this off until we're sure this doesn't have an unreasonable cost // to the compiler or optimizer. # define _MDSPAN_PRESERVE_STANDARD_LAYOUT 1 #endif #if !defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) # if ((__has_cpp_attribute(no_unique_address) >= 201803L) && \ (!defined(__NVCC__) || MDSPAN_HAS_CXX_20) && \ (!defined(_MDSPAN_COMPILER_MSVC) || MDSPAN_HAS_CXX_20)) # define _MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS 1 # define _MDSPAN_NO_UNIQUE_ADDRESS [[no_unique_address]] # else # define _MDSPAN_NO_UNIQUE_ADDRESS # endif #endif // NVCC older than 11.6 chokes on the no-unique-address-emulation // so just pretend to use it (to avoid the full blown EBO workaround // which NVCC also doesn't like ...), and leave the macro empty #ifndef _MDSPAN_NO_UNIQUE_ADDRESS # if defined(__NVCC__) # define _MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS 1 # define _MDSPAN_USE_FAKE_ATTRIBUTE_NO_UNIQUE_ADDRESS # endif # define _MDSPAN_NO_UNIQUE_ADDRESS #endif // AMDs HIP compiler seems to have issues with concepts // it pretends concepts exist, but doesn't ship #ifndef __HIPCC__ #ifndef _MDSPAN_USE_CONCEPTS # if defined(__cpp_concepts) && __cpp_concepts >= 201507L # define _MDSPAN_USE_CONCEPTS 1 # endif #endif #endif #ifndef _MDSPAN_USE_FOLD_EXPRESSIONS # if (defined(__cpp_fold_expressions) && __cpp_fold_expressions >= 201603L) \ || (!defined(__cpp_fold_expressions) && 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 \ || (!defined(__cpp_inline_variables) && MDSPAN_HAS_CXX_17) # 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) # if !(defined(_MDSPAN_COMPILER_APPLECLANG) && MDSPAN_HAS_CXX_17) # define _MDSPAN_NEEDS_TRAIT_VARIABLE_TEMPLATE_BACKPORTS 1 # endif # endif #endif #ifndef _MDSPAN_USE_VARIABLE_TEMPLATES # if (defined(__cpp_variable_templates) && __cpp_variable_templates >= 201304 && MDSPAN_HAS_CXX_17) \ || (!defined(__cpp_variable_templates) && MDSPAN_HAS_CXX_17) # define _MDSPAN_USE_VARIABLE_TEMPLATES 1 # endif #endif // _MDSPAN_USE_VARIABLE_TEMPLATES #ifndef _MDSPAN_USE_CONSTEXPR_14 # if (defined(__cpp_constexpr) && __cpp_constexpr >= 201304) \ || (!defined(__cpp_constexpr) && MDSPAN_HAS_CXX_14) \ && (!(defined(__INTEL_COMPILER) && __INTEL_COMPILER <= 1700)) # define _MDSPAN_USE_CONSTEXPR_14 1 # endif #endif #ifndef _MDSPAN_USE_INTEGER_SEQUENCE # if defined(_MDSPAN_COMPILER_MSVC) # 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) \ || (!defined(__cpp_lib_integer_sequence) && MDSPAN_HAS_CXX_14) \ /* as far as I can tell, libc++ seems to think this is a C++11 feature... */ \ || (defined(__GLIBCXX__) && __GLIBCXX__ > 20150422 && __GNUC__ < 5 && !defined(__INTEL_CXX11_MODE__)) // 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 # if (defined(__cpp_return_type_deduction) && __cpp_return_type_deduction >= 201304) \ || (!defined(__cpp_return_type_deduction) && MDSPAN_HAS_CXX_14) # define _MDSPAN_USE_RETURN_TYPE_DEDUCTION 1 # endif #endif #ifndef _MDSPAN_USE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION # if (!defined(__NVCC__) || (__CUDACC_VER_MAJOR__ * 100 + __CUDACC_VER_MINOR__ * 10 >= 1170)) && \ ((defined(__cpp_deduction_guides) && __cpp_deduction_guides >= 201703) || \ (!defined(__cpp_deduction_guides) && MDSPAN_HAS_CXX_17)) # define _MDSPAN_USE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION 1 # endif #endif #ifndef _MDSPAN_USE_STANDARD_TRAIT_ALIASES # if (defined(__cpp_lib_transformation_trait_aliases) && __cpp_lib_transformation_trait_aliases >= 201304) \ || (!defined(__cpp_lib_transformation_trait_aliases) && MDSPAN_HAS_CXX_14) # 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 #ifndef _MDSPAN_DEFAULTED_CONSTRUCTORS_INHERITANCE_WORKAROUND # ifdef __GNUC__ # if __GNUC__ < 9 # define _MDSPAN_DEFAULTED_CONSTRUCTORS_INHERITANCE_WORKAROUND 1 # endif # endif #endif #ifndef MDSPAN_CONDITIONAL_EXPLICIT # if MDSPAN_HAS_CXX_20 # define MDSPAN_CONDITIONAL_EXPLICIT(COND) explicit(COND) # else # define MDSPAN_CONDITIONAL_EXPLICIT(COND) # endif #endif #ifndef MDSPAN_USE_BRACKET_OPERATOR # if defined(__cpp_multidimensional_subscript) # define MDSPAN_USE_BRACKET_OPERATOR 1 # else # define MDSPAN_USE_BRACKET_OPERATOR 0 # endif #endif #ifndef MDSPAN_USE_PAREN_OPERATOR # if !MDSPAN_USE_BRACKET_OPERATOR # define MDSPAN_USE_PAREN_OPERATOR 1 # else # define MDSPAN_USE_PAREN_OPERATOR 0 # endif #endif #if MDSPAN_USE_BRACKET_OPERATOR # define __MDSPAN_OP(mds,...) mds[__VA_ARGS__] // Corentins demo compiler for subscript chokes on empty [] call, // though I believe the proposal supports it? #ifdef MDSPAN_NO_EMPTY_BRACKET_OPERATOR # define __MDSPAN_OP0(mds) mds.accessor().access(mds.data_handle(),0) #else # define __MDSPAN_OP0(mds) mds[] #endif # define __MDSPAN_OP1(mds, a) mds[a] # define __MDSPAN_OP2(mds, a, b) mds[a,b] # define __MDSPAN_OP3(mds, a, b, c) mds[a,b,c] # define __MDSPAN_OP4(mds, a, b, c, d) mds[a,b,c,d] # define __MDSPAN_OP5(mds, a, b, c, d, e) mds[a,b,c,d,e] # define __MDSPAN_OP6(mds, a, b, c, d, e, f) mds[a,b,c,d,e,f] #else # define __MDSPAN_OP(mds,...) mds(__VA_ARGS__) # define __MDSPAN_OP0(mds) mds() # define __MDSPAN_OP1(mds, a) mds(a) # define __MDSPAN_OP2(mds, a, b) mds(a,b) # define __MDSPAN_OP3(mds, a, b, c) mds(a,b,c) # define __MDSPAN_OP4(mds, a, b, c, d) mds(a,b,c,d) # define __MDSPAN_OP5(mds, a, b, c, d, e) mds(a,b,c,d,e) # define __MDSPAN_OP6(mds, a, b, c, d, e, f) mds(a,b,c,d,e,f) #endif //END_FILE_INCLUDE: /home/runner/work/mdspan/mdspan/include/experimental/__p0009_bits/config.hpp #include #include #include // std::is_void #if defined(_MDSPAN_HAS_CUDA) || defined(_MDSPAN_HAS_HIP) || defined(_MDSPAN_HAS_SYCL) #include "assert.h" #endif #ifndef _MDSPAN_HOST_DEVICE # if defined(_MDSPAN_HAS_CUDA) || defined(_MDSPAN_HAS_HIP) # define _MDSPAN_HOST_DEVICE __host__ __device__ # else # define _MDSPAN_HOST_DEVICE # endif #endif #ifndef MDSPAN_FORCE_INLINE_FUNCTION # ifdef _MDSPAN_COMPILER_MSVC // Microsoft compilers # define MDSPAN_FORCE_INLINE_FUNCTION __forceinline _MDSPAN_HOST_DEVICE # else # define MDSPAN_FORCE_INLINE_FUNCTION __attribute__((always_inline)) _MDSPAN_HOST_DEVICE # endif #endif #ifndef MDSPAN_INLINE_FUNCTION # define MDSPAN_INLINE_FUNCTION inline _MDSPAN_HOST_DEVICE #endif #ifndef MDSPAN_FUNCTION # define MDSPAN_FUNCTION _MDSPAN_HOST_DEVICE #endif #ifdef _MDSPAN_HAS_HIP # define MDSPAN_DEDUCTION_GUIDE _MDSPAN_HOST_DEVICE #else # define MDSPAN_DEDUCTION_GUIDE #endif // In CUDA defaulted functions do not need host device markup #ifndef MDSPAN_INLINE_FUNCTION_DEFAULTED # define MDSPAN_INLINE_FUNCTION_DEFAULTED #endif //============================================================================== // {{{1 #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 \ /**/ #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__ #define MDSPAN_IMPL_STANDARD_NAMESPACE_STRING MDSPAN_PP_STRINGIFY(MDSPAN_IMPL_STANDARD_NAMESPACE) #define MDSPAN_IMPL_PROPOSED_NAMESPACE_STRING MDSPAN_PP_STRINGIFY(MDSPAN_IMPL_STANDARD_NAMESPACE) "::" MDSPAN_PP_STRINGIFY(MDSPAN_IMPL_PROPOSED_NAMESPACE) namespace MDSPAN_IMPL_STANDARD_NAMESPACE { namespace detail { #if defined(_MDSPAN_HAS_CUDA) || defined(_MDSPAN_HAS_HIP) MDSPAN_FUNCTION inline void default_precondition_violation_handler(const char* cond, const char* file, unsigned line) { printf("%s:%u: precondition failure: `%s`\n", file, line, cond); assert(0); } #elif defined(_MDSPAN_HAS_SYCL) MDSPAN_FUNCTION inline void default_precondition_violation_handler(const char* cond, const char* file, unsigned line) { sycl::ext::oneapi::experimental::printf("%s:%u: precondition failure: `%s`\n", file, line, cond); assert(0); } #else MDSPAN_FUNCTION inline void default_precondition_violation_handler(const char* cond, const char* file, unsigned line) { std::fprintf(stderr, "%s:%u: precondition failure: `%s`\n", file, line, cond); std::abort(); } #endif } // namespace detail } // namespace MDSPAN_IMPL_STANDARD_NAMESPACE #ifndef MDSPAN_IMPL_PRECONDITION_VIOLATION_HANDLER #define MDSPAN_IMPL_PRECONDITION_VIOLATION_HANDLER(cond, file, line) \ MDSPAN_IMPL_STANDARD_NAMESPACE::detail::default_precondition_violation_handler(cond, file, line) #endif #ifndef MDSPAN_IMPL_CHECK_PRECONDITION #ifndef NDEBUG #define MDSPAN_IMPL_CHECK_PRECONDITION 0 #else #define MDSPAN_IMPL_CHECK_PRECONDITION 1 #endif #endif namespace MDSPAN_IMPL_STANDARD_NAMESPACE { namespace detail { template MDSPAN_FUNCTION constexpr void precondition(const char* cond, const char* file, unsigned line) { if (!check) { return; } // in case the macro doesn't use the arguments for custom macros (void) cond; (void) file; (void) line; MDSPAN_IMPL_PRECONDITION_VIOLATION_HANDLER(cond, file, line); } } // namespace detail } // namespace MDSPAN_IMPL_STANDARD_NAMESPACE #define MDSPAN_IMPL_PRECONDITION(...) \ do { \ if (!(__VA_ARGS__)) { \ MDSPAN_IMPL_STANDARD_NAMESPACE::detail::precondition(#__VA_ARGS__, __FILE__, __LINE__); \ } \ } while (0) // end Preprocessor helpers }}}1 //============================================================================== //============================================================================== // {{{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) , typename ::std::enable_if<(REQ), int>::type = 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 #if defined(_MDSPAN_COMPILER_MSVC) && (!defined(_MSVC_TRADITIONAL) || _MSVC_TRADITIONAL) # 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 end Concept emulation }}}1 //============================================================================== //============================================================================== // {{{1 #ifdef _MDSPAN_USE_INLINE_VARIABLES # define _MDSPAN_INLINE_VARIABLE inline #else # define _MDSPAN_INLINE_VARIABLE #endif // end inline variables }}}1 //============================================================================== //============================================================================== // {{{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) \ -> std::remove_cv_t> \ { 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 // end Return type deduction }}}1 //============================================================================== //============================================================================== // {{{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 MDSPAN_IMPL_STANDARD_NAMESPACE { 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 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 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 MDSPAN_FORCE_INLINE_FUNCTION constexpr auto __fold_left_assign_impl(Arg1&& arg1) { return (Arg1&&)arg1; } template 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 MDSPAN_FORCE_INLINE_FUNCTION constexpr auto __fold_right_assign_impl(Arg1&& arg1) { return (Arg1&&)arg1; } template 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 MDSPAN_FORCE_INLINE_FUNCTION constexpr auto __fold_right_plus_impl(Arg1&& arg1) { return (Arg1&&)arg1; } template 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 MDSPAN_FORCE_INLINE_FUNCTION constexpr auto __fold_right_times_impl(Arg1&& arg1) { return (Arg1&&)arg1; } template 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 //------------------------------------------------------------------------------ // {{{2 template 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 struct __fold_right_and_impl_ { using __next_t = __fold_right_and_impl_; using __rv = decltype(std::declval() && std::declval()); MDSPAN_FORCE_INLINE_FUNCTION static constexpr __rv __impl(Arg&& arg, Args&&... args) noexcept { return ((Arg&&)arg) && __next_t::__impl((Args&&)args...); } }; template MDSPAN_FORCE_INLINE_FUNCTION constexpr typename __fold_right_and_impl_::__rv __fold_right_and_impl(Args&&... args) { return __fold_right_and_impl_::__impl((Args&&)args...); } // end right and }}}2 //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ // {{{2 template 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 struct __fold_right_or_impl_ { using __next_t = __fold_right_or_impl_; using __rv = decltype(std::declval() || std::declval()); MDSPAN_FORCE_INLINE_FUNCTION static constexpr __rv __impl(Arg&& arg, Args&&... args) noexcept { return ((Arg&&)arg) || __next_t::__impl((Args&&)args...); } }; template MDSPAN_FORCE_INLINE_FUNCTION constexpr typename __fold_right_or_impl_::__rv __fold_right_or_impl(Args&&... args) { return __fold_right_or_impl_::__impl((Args&&)args...); } // end right or }}}2 //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ // {{{2 template struct __fold_right_plus_impl_; template struct __fold_right_plus_impl_ { using __rv = Arg&&; MDSPAN_FORCE_INLINE_FUNCTION static constexpr __rv __impl(Arg&& arg) noexcept { return (Arg&&)arg; } }; template struct __fold_right_plus_impl_ { using __next_t = __fold_right_plus_impl_; using __rv = decltype(std::declval() + std::declval()); 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 MDSPAN_FORCE_INLINE_FUNCTION constexpr typename __fold_right_plus_impl_::__rv __fold_right_plus_impl(Args&&... args) { return __fold_right_plus_impl_::__impl((Args&&)args...); } // end right plus }}}2 //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ // {{{2 template struct __fold_right_times_impl_; template struct __fold_right_times_impl_ { using __rv = Arg&&; MDSPAN_FORCE_INLINE_FUNCTION static constexpr __rv __impl(Arg&& arg) noexcept { return (Arg&&)arg; } }; template struct __fold_right_times_impl_ { using __next_t = __fold_right_times_impl_; using __rv = decltype(std::declval() * std::declval()); 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 MDSPAN_FORCE_INLINE_FUNCTION constexpr typename __fold_right_times_impl_::__rv __fold_right_times_impl(Args&&... args) { return __fold_right_times_impl_::__impl((Args&&)args...); } // end right times }}}2 //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ // {{{2 template struct __fold_right_assign_impl_; template struct __fold_right_assign_impl_ { using __rv = Arg&&; MDSPAN_FORCE_INLINE_FUNCTION static constexpr __rv __impl(Arg&& arg) noexcept { return (Arg&&)arg; } }; template struct __fold_right_assign_impl_ { using __next_t = __fold_right_assign_impl_; using __rv = decltype(std::declval() = std::declval()); 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 MDSPAN_FORCE_INLINE_FUNCTION constexpr typename __fold_right_assign_impl_::__rv __fold_right_assign_impl(Args&&... args) { return __fold_right_assign_impl_::__impl((Args&&)args...); } // end right assign }}}2 //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ // {{{2 template struct __fold_left_assign_impl_; template struct __fold_left_assign_impl_ { using __rv = Arg&&; MDSPAN_FORCE_INLINE_FUNCTION static constexpr __rv __impl(Arg&& arg) noexcept { return (Arg&&)arg; } }; template struct __fold_left_assign_impl_ { using __assign_result_t = decltype(std::declval() = std::declval()); 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 MDSPAN_FORCE_INLINE_FUNCTION constexpr typename __fold_left_assign_impl_::__rv __fold_left_assign_impl(Args&&... args) { return __fold_left_assign_impl_::__impl((Args&&)args...); } // end left assign }}}2 //------------------------------------------------------------------------------ #endif template constexpr __mdspan_enable_fold_comma __fold_comma_impl(Args&&...) noexcept { return { }; } template struct __bools; } // __fold_compatibility_impl } // end namespace MDSPAN_IMPL_STANDARD_NAMESPACE # define _MDSPAN_FOLD_AND(...) MDSPAN_IMPL_STANDARD_NAMESPACE::__fold_compatibility_impl::__fold_right_and_impl((__VA_ARGS__)...) # define _MDSPAN_FOLD_OR(...) MDSPAN_IMPL_STANDARD_NAMESPACE::__fold_compatibility_impl::__fold_right_or_impl((__VA_ARGS__)...) # define _MDSPAN_FOLD_ASSIGN_LEFT(INIT, ...) MDSPAN_IMPL_STANDARD_NAMESPACE::__fold_compatibility_impl::__fold_left_assign_impl(INIT, (__VA_ARGS__)...) # define _MDSPAN_FOLD_ASSIGN_RIGHT(PACK, ...) MDSPAN_IMPL_STANDARD_NAMESPACE::__fold_compatibility_impl::__fold_right_assign_impl((PACK)..., __VA_ARGS__) # define _MDSPAN_FOLD_TIMES_RIGHT(PACK, ...) MDSPAN_IMPL_STANDARD_NAMESPACE::__fold_compatibility_impl::__fold_right_times_impl((PACK)..., __VA_ARGS__) # define _MDSPAN_FOLD_PLUS_RIGHT(PACK, ...) MDSPAN_IMPL_STANDARD_NAMESPACE::__fold_compatibility_impl::__fold_right_plus_impl((PACK)..., __VA_ARGS__) # define _MDSPAN_FOLD_COMMA(...) MDSPAN_IMPL_STANDARD_NAMESPACE::__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) #endif // end fold expressions }}}1 //============================================================================== //============================================================================== // {{{1 #if _MDSPAN_USE_VARIABLE_TEMPLATES # define _MDSPAN_TRAIT(TRAIT, ...) TRAIT##_v<__VA_ARGS__> #else # define _MDSPAN_TRAIT(TRAIT, ...) TRAIT<__VA_ARGS__>::value #endif // end Variable template compatibility }}}1 //============================================================================== //============================================================================== // {{{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 // end Pre-C++14 constexpr }}}1 //============================================================================== //END_FILE_INCLUDE: /home/runner/work/mdspan/mdspan/include/experimental/__p0009_bits/macros.hpp #include // size_t namespace MDSPAN_IMPL_STANDARD_NAMESPACE { template struct default_accessor { using offset_policy = default_accessor; using element_type = ElementType; using reference = ElementType&; using data_handle_type = ElementType*; MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr default_accessor() noexcept = default; MDSPAN_TEMPLATE_REQUIRES( class OtherElementType, /* requires */ ( _MDSPAN_TRAIT(std::is_convertible, OtherElementType(*)[], element_type(*)[]) ) ) MDSPAN_INLINE_FUNCTION constexpr default_accessor(default_accessor) noexcept {} MDSPAN_INLINE_FUNCTION constexpr data_handle_type offset(data_handle_type p, size_t i) const noexcept { return p + i; } MDSPAN_FORCE_INLINE_FUNCTION constexpr reference access(data_handle_type p, size_t i) const noexcept { return p[i]; } }; } // end namespace MDSPAN_IMPL_STANDARD_NAMESPACE //END_FILE_INCLUDE: /home/runner/work/mdspan/mdspan/include/experimental/__p0009_bits/default_accessor.hpp //BEGIN_FILE_INCLUDE: /home/runner/work/mdspan/mdspan/include/experimental/__p0009_bits/full_extent_t.hpp //@HEADER // ************************************************************************ // // Kokkos v. 4.0 // Copyright (2022) National Technology & Engineering // Solutions of Sandia, LLC (NTESS). // // Under the terms of Contract DE-NA0003525 with NTESS, // the U.S. Government retains certain rights in this software. // // Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions. // See https://kokkos.org/LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //@HEADER namespace MDSPAN_IMPL_STANDARD_NAMESPACE { struct full_extent_t { explicit full_extent_t() = default; }; _MDSPAN_INLINE_VARIABLE constexpr auto full_extent = full_extent_t{ }; } // namespace MDSPAN_IMPL_STANDARD_NAMESPACE //END_FILE_INCLUDE: /home/runner/work/mdspan/mdspan/include/experimental/__p0009_bits/full_extent_t.hpp //BEGIN_FILE_INCLUDE: /home/runner/work/mdspan/mdspan/include/experimental/__p0009_bits/mdspan.hpp //@HEADER // ************************************************************************ // // Kokkos v. 4.0 // Copyright (2022) National Technology & Engineering // Solutions of Sandia, LLC (NTESS). // // Under the terms of Contract DE-NA0003525 with NTESS, // the U.S. Government retains certain rights in this software. // // Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions. // See https://kokkos.org/LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //@HEADER //BEGIN_FILE_INCLUDE: /home/runner/work/mdspan/mdspan/include/experimental/__p0009_bits/layout_right.hpp //@HEADER // ************************************************************************ // // Kokkos v. 4.0 // Copyright (2022) National Technology & Engineering // Solutions of Sandia, LLC (NTESS). // // Under the terms of Contract DE-NA0003525 with NTESS, // the U.S. Government retains certain rights in this software. // // Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions. // See https://kokkos.org/LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //@HEADER //BEGIN_FILE_INCLUDE: /home/runner/work/mdspan/mdspan/include/experimental/__p0009_bits/trait_backports.hpp //@HEADER // ************************************************************************ // // Kokkos v. 4.0 // Copyright (2022) National Technology & Engineering // Solutions of Sandia, LLC (NTESS). // // Under the terms of Contract DE-NA0003525 with NTESS, // the U.S. Government retains certain rights in this software. // // Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions. // See https://kokkos.org/LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //@HEADER #ifndef MDSPAN_INCLUDE_EXPERIMENTAL_BITS_TRAIT_BACKPORTS_HPP_ #define MDSPAN_INCLUDE_EXPERIMENTAL_BITS_TRAIT_BACKPORTS_HPP_ #include #include // integer_sequence //============================================================================== // {{{1 #ifdef _MDSPAN_NEEDS_TRAIT_VARIABLE_TEMPLATE_BACKPORTS #if _MDSPAN_USE_VARIABLE_TEMPLATES namespace MDSPAN_IMPL_STANDARD_NAMESPACE { #define _MDSPAN_BACKPORT_TRAIT(TRAIT) \ template _MDSPAN_INLINE_VARIABLE constexpr auto TRAIT##_v = TRAIT::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_trivially_destructible) _MDSPAN_BACKPORT_TRAIT(is_same) _MDSPAN_BACKPORT_TRAIT(is_empty) _MDSPAN_BACKPORT_TRAIT(is_void) #undef _MDSPAN_BACKPORT_TRAIT } // end namespace MDSPAN_IMPL_STANDARD_NAMESPACE #endif // _MDSPAN_USE_VARIABLE_TEMPLATES #endif // _MDSPAN_NEEDS_TRAIT_VARIABLE_TEMPLATE_BACKPORTS // end Variable template trait backports (e.g., is_void_v) }}}1 //============================================================================== //============================================================================== // {{{1 #if !defined(_MDSPAN_USE_INTEGER_SEQUENCE) || !_MDSPAN_USE_INTEGER_SEQUENCE namespace MDSPAN_IMPL_STANDARD_NAMESPACE { template struct integer_sequence { static constexpr size_t size() noexcept { return sizeof...(Vals); } using value_type = T; }; template using index_sequence = std::integer_sequence; namespace __detail { template struct __make_int_seq_impl; template struct __make_int_seq_impl> { using type = integer_sequence; }; template struct __make_int_seq_impl< T, N, I, integer_sequence > : __make_int_seq_impl> { }; } // end namespace __detail template using make_integer_sequence = typename __detail::__make_int_seq_impl>::type; template using make_index_sequence = typename __detail::__make_int_seq_impl>::type; template using index_sequence_for = make_index_sequence; } // end namespace MDSPAN_IMPL_STANDARD_NAMESPACE #endif // end integer sequence (ugh...) }}}1 //============================================================================== //============================================================================== // {{{1 #if !defined(_MDSPAN_USE_STANDARD_TRAIT_ALIASES) || !_MDSPAN_USE_STANDARD_TRAIT_ALIASES namespace MDSPAN_IMPL_STANDARD_NAMESPACE { #define _MDSPAN_BACKPORT_TRAIT_ALIAS(TRAIT) \ template using TRAIT##_t = typename TRAIT::type; _MDSPAN_BACKPORT_TRAIT_ALIAS(remove_cv) _MDSPAN_BACKPORT_TRAIT_ALIAS(remove_reference) template using enable_if_t = typename enable_if<_B, _T>::type; #undef _MDSPAN_BACKPORT_TRAIT_ALIAS } // end namespace MDSPAN_IMPL_STANDARD_NAMESPACE #endif // end standard trait aliases }}}1 //============================================================================== #endif //MDSPAN_INCLUDE_EXPERIMENTAL_BITS_TRAIT_BACKPORTS_HPP_ //END_FILE_INCLUDE: /home/runner/work/mdspan/mdspan/include/experimental/__p0009_bits/trait_backports.hpp //BEGIN_FILE_INCLUDE: /home/runner/work/mdspan/mdspan/include/experimental/__p0009_bits/extents.hpp //@HEADER // ************************************************************************ // // Kokkos v. 4.0 // Copyright (2022) National Technology & Engineering // Solutions of Sandia, LLC (NTESS). // // Under the terms of Contract DE-NA0003525 with NTESS, // the U.S. Government retains certain rights in this software. // // Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions. // See https://kokkos.org/LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //@HEADER //BEGIN_FILE_INCLUDE: /home/runner/work/mdspan/mdspan/include/experimental/__p0009_bits/dynamic_extent.hpp //@HEADER // ************************************************************************ // // Kokkos v. 4.0 // Copyright (2022) National Technology & Engineering // Solutions of Sandia, LLC (NTESS). // // Under the terms of Contract DE-NA0003525 with NTESS, // the U.S. Government retains certain rights in this software. // // Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions. // See https://kokkos.org/LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //@HEADER #if defined(__cpp_lib_span) #include #endif #include // size_t #include // numeric_limits namespace MDSPAN_IMPL_STANDARD_NAMESPACE { #if defined(__cpp_lib_span) using std::dynamic_extent; #else _MDSPAN_INLINE_VARIABLE constexpr auto dynamic_extent = std::numeric_limits::max(); #endif } // namespace MDSPAN_IMPL_STANDARD_NAMESPACE //============================================================================================================== //END_FILE_INCLUDE: /home/runner/work/mdspan/mdspan/include/experimental/__p0009_bits/dynamic_extent.hpp //BEGIN_FILE_INCLUDE: /home/runner/work/mdspan/mdspan/include/experimental/__p0009_bits/utility.hpp #include #include namespace MDSPAN_IMPL_STANDARD_NAMESPACE { namespace detail { // type alias used for rank-based tag dispatch // // this is used to enable alternatives to constexpr if when building for C++14 // template using with_rank = std::integral_constant; template MDSPAN_INLINE_FUNCTION constexpr bool common_integral_compare(I1 x, I2 y) { static_assert(std::is_integral::value && std::is_integral::value, ""); using I = std::common_type_t; return static_cast(x) == static_cast(y); } template MDSPAN_INLINE_FUNCTION constexpr bool rankwise_equal(with_rank<0>, const T1&, const T2&, F) { return true; } template MDSPAN_INLINE_FUNCTION constexpr bool rankwise_equal(with_rank, const T1& x, const T2& y, F func) { bool match = true; for (std::size_t r = 0; r < N; r++) { match = match && common_integral_compare(func(x, r), func(y, r)); } return match; } constexpr struct { template MDSPAN_INLINE_FUNCTION constexpr auto operator()(const T& x, I i) const { return x.extent(i); } } extent; constexpr struct { template MDSPAN_INLINE_FUNCTION constexpr auto operator()(const T& x, I i) const { return x.stride(i); } } stride; } // namespace detail constexpr struct mdspan_non_standard_tag { } mdspan_non_standard; } // namespace MDSPAN_IMPL_STANDARD_NAMESPACE //END_FILE_INCLUDE: /home/runner/work/mdspan/mdspan/include/experimental/__p0009_bits/utility.hpp #ifdef __cpp_lib_span #include #endif #include #include #include #include namespace MDSPAN_IMPL_STANDARD_NAMESPACE { namespace detail { // Function used to check compatibility of extents in converting constructor // can't be a private member function for some reason. template MDSPAN_INLINE_FUNCTION static constexpr std::integral_constant __check_compatible_extents( std::integral_constant, std::integer_sequence, std::integer_sequence) noexcept { return {}; } // This helper prevents ICE's on MSVC. template struct __compare_extent_compatible : std::integral_constant {}; template MDSPAN_INLINE_FUNCTION static constexpr std::integral_constant< bool, _MDSPAN_FOLD_AND(__compare_extent_compatible::value)> __check_compatible_extents( std::integral_constant, std::integer_sequence, std::integer_sequence) noexcept { return {}; } template MDSPAN_INLINE_FUNCTION static constexpr bool are_valid_indices() { return _MDSPAN_FOLD_AND(std::is_convertible::value) && _MDSPAN_FOLD_AND(std::is_nothrow_constructible::value); } // ------------------------------------------------------------------ // ------------ static_array ---------------------------------------- // ------------------------------------------------------------------ // array like class which provides an array of static values with get // function and operator []. // Implementation of Static Array with recursive implementation of get. template struct static_array_impl; template struct static_array_impl { MDSPAN_INLINE_FUNCTION constexpr static T get(size_t r) { if (r == R) return FirstExt; else return static_array_impl::get(r); } template MDSPAN_INLINE_FUNCTION constexpr static T get() { #if MDSPAN_HAS_CXX_17 if constexpr (r == R) return FirstExt; else return static_array_impl::template get(); #else get(r); #endif } }; // End the recursion template struct static_array_impl { MDSPAN_INLINE_FUNCTION constexpr static T get(size_t) { return FirstExt; } template MDSPAN_INLINE_FUNCTION constexpr static T get() { return FirstExt; } }; // Don't start recursion if size 0 template struct static_array_impl<0, T> { MDSPAN_INLINE_FUNCTION constexpr static T get(size_t) { return T(); } template MDSPAN_INLINE_FUNCTION constexpr static T get() { return T(); } }; // Static array, provides get(), get(r) and operator[r] template struct static_array: public static_array_impl<0, T, Values...> { public: using value_type = T; MDSPAN_INLINE_FUNCTION constexpr static size_t size() { return sizeof...(Values); } }; // ------------------------------------------------------------------ // ------------ index_sequence_scan --------------------------------- // ------------------------------------------------------------------ // index_sequence_scan takes compile time values and provides get(r) // and get() which return the sum of the first r-1 values. // Recursive implementation for get template struct index_sequence_scan_impl; template struct index_sequence_scan_impl { MDSPAN_INLINE_FUNCTION constexpr static size_t get(size_t r) { if (r > R) return FirstVal + index_sequence_scan_impl::get(r); else return 0; } }; template struct index_sequence_scan_impl { #if defined(__NVCC__) || defined(__NVCOMPILER) || \ defined(_MDSPAN_COMPILER_INTEL) // NVCC warns about pointless comparison with 0 for R==0 and r being const // evaluatable and also 0. MDSPAN_INLINE_FUNCTION constexpr static size_t get(size_t r) { return static_cast(R) > static_cast(r) ? FirstVal : 0; } #else MDSPAN_INLINE_FUNCTION constexpr static size_t get(size_t r) { return R > r ? FirstVal : 0; } #endif }; template <> struct index_sequence_scan_impl<0> { MDSPAN_INLINE_FUNCTION constexpr static size_t get(size_t) { return 0; } }; // ------------------------------------------------------------------ // ------------ possibly_empty_array ------------------------------- // ------------------------------------------------------------------ // array like class which provides get function and operator [], and // has a specialization for the size 0 case. // This is needed to make the maybe_static_array be truly empty, for // all static values. template struct possibly_empty_array { T vals[N]{}; MDSPAN_INLINE_FUNCTION constexpr T &operator[](size_t r) { return vals[r]; } MDSPAN_INLINE_FUNCTION constexpr const T &operator[](size_t r) const { return vals[r]; } }; template struct possibly_empty_array { MDSPAN_INLINE_FUNCTION constexpr T operator[](size_t) { return T(); } MDSPAN_INLINE_FUNCTION constexpr const T operator[](size_t) const { return T(); } }; // ------------------------------------------------------------------ // ------------ maybe_static_array ---------------------------------- // ------------------------------------------------------------------ // array like class which has a mix of static and runtime values but // only stores the runtime values. // The type of the static and the runtime values can be different. // The position of a dynamic value is indicated through a tag value. template struct maybe_static_array { static_assert(std::is_convertible::value, "maybe_static_array: TStatic must be convertible to TDynamic"); static_assert(std::is_convertible::value, "maybe_static_array: TDynamic must be convertible to TStatic"); private: // Static values member using static_vals_t = static_array; constexpr static size_t m_size = sizeof...(Values); constexpr static size_t m_size_dynamic = _MDSPAN_FOLD_PLUS_RIGHT((Values == dyn_tag), 0); // Dynamic values member _MDSPAN_NO_UNIQUE_ADDRESS possibly_empty_array m_dyn_vals; // static mapping of indices to the position in the dynamic values array using dyn_map_t = index_sequence_scan_impl<0, static_cast(Values == dyn_tag)...>; public: // two types for static and dynamic values using value_type = TDynamic; using static_value_type = TStatic; // tag value indicating dynamic value constexpr static static_value_type tag_value = dyn_tag; constexpr maybe_static_array() = default; // constructor for all static values // TODO: add precondition check? MDSPAN_TEMPLATE_REQUIRES(class... Vals, /* requires */ ((m_size_dynamic == 0) && (sizeof...(Vals) > 0))) MDSPAN_INLINE_FUNCTION constexpr maybe_static_array(Vals...) : m_dyn_vals{} {} // constructors from dynamic values only MDSPAN_TEMPLATE_REQUIRES(class... DynVals, /* requires */ (sizeof...(DynVals) == m_size_dynamic && m_size_dynamic > 0)) MDSPAN_INLINE_FUNCTION constexpr maybe_static_array(DynVals... vals) : m_dyn_vals{static_cast(vals)...} {} MDSPAN_TEMPLATE_REQUIRES(class T, size_t N, /* requires */ (N == m_size_dynamic && N > 0)) MDSPAN_INLINE_FUNCTION constexpr maybe_static_array(const std::array &vals) { for (size_t r = 0; r < N; r++) m_dyn_vals[r] = static_cast(vals[r]); } MDSPAN_TEMPLATE_REQUIRES(class T, size_t N, /* requires */ (N == m_size_dynamic && N == 0)) MDSPAN_INLINE_FUNCTION constexpr maybe_static_array(const std::array &) : m_dyn_vals{} {} #ifdef __cpp_lib_span MDSPAN_TEMPLATE_REQUIRES(class T, size_t N, /* requires */ (N == m_size_dynamic && N > 0)) MDSPAN_INLINE_FUNCTION constexpr maybe_static_array(const std::span &vals) { for (size_t r = 0; r < N; r++) m_dyn_vals[r] = static_cast(vals[r]); } MDSPAN_TEMPLATE_REQUIRES(class T, size_t N, /* requires */ (N == m_size_dynamic && N == 0)) MDSPAN_INLINE_FUNCTION constexpr maybe_static_array(const std::span &) : m_dyn_vals{} {} #endif // constructors from all values MDSPAN_TEMPLATE_REQUIRES(class... DynVals, /* requires */ (sizeof...(DynVals) != m_size_dynamic && m_size_dynamic > 0)) MDSPAN_INLINE_FUNCTION constexpr maybe_static_array(DynVals... vals) : m_dyn_vals{} { static_assert((sizeof...(DynVals) == m_size), "Invalid number of values."); TDynamic values[m_size]{static_cast(vals)...}; for (size_t r = 0; r < m_size; r++) { TStatic static_val = static_vals_t::get(r); if (static_val == dyn_tag) { m_dyn_vals[dyn_map_t::get(r)] = values[r]; } // Precondition check #ifdef _MDSPAN_DEBUG else { assert(values[r] == static_cast(static_val)); } #endif } } MDSPAN_TEMPLATE_REQUIRES( class T, size_t N, /* requires */ (N != m_size_dynamic && m_size_dynamic > 0)) MDSPAN_INLINE_FUNCTION constexpr maybe_static_array(const std::array &vals) { static_assert((N == m_size), "Invalid number of values."); // Precondition check #ifdef _MDSPAN_DEBUG assert(N == m_size); #endif for (size_t r = 0; r < m_size; r++) { TStatic static_val = static_vals_t::get(r); if (static_val == dyn_tag) { m_dyn_vals[dyn_map_t::get(r)] = static_cast(vals[r]); } // Precondition check #ifdef _MDSPAN_DEBUG else { assert(static_cast(vals[r]) == static_cast(static_val)); } #endif } } #ifdef __cpp_lib_span MDSPAN_TEMPLATE_REQUIRES( class T, size_t N, /* requires */ (N != m_size_dynamic && m_size_dynamic > 0)) MDSPAN_INLINE_FUNCTION constexpr maybe_static_array(const std::span &vals) { static_assert((N == m_size) || (m_size == dynamic_extent)); #ifdef _MDSPAN_DEBUG assert(N == m_size); #endif for (size_t r = 0; r < m_size; r++) { TStatic static_val = static_vals_t::get(r); if (static_val == dyn_tag) { m_dyn_vals[dyn_map_t::get(r)] = static_cast(vals[r]); } #ifdef _MDSPAN_DEBUG else { assert(static_cast(vals[r]) == static_cast(static_val)); } #endif } } #endif // access functions MDSPAN_INLINE_FUNCTION constexpr static TStatic static_value(size_t r) { return static_vals_t::get(r); } MDSPAN_INLINE_FUNCTION constexpr TDynamic value(size_t r) const { TStatic static_val = static_vals_t::get(r); return static_val == dyn_tag ? m_dyn_vals[dyn_map_t::get(r)] : static_cast(static_val); } MDSPAN_INLINE_FUNCTION constexpr TDynamic operator[](size_t r) const { return value(r); } // observers MDSPAN_INLINE_FUNCTION constexpr static size_t size() { return m_size; } MDSPAN_INLINE_FUNCTION constexpr static size_t size_dynamic() { return m_size_dynamic; } }; } // namespace detail } // namespace MDSPAN_IMPL_STANDARD_NAMESPACE namespace MDSPAN_IMPL_STANDARD_NAMESPACE { // ------------------------------------------------------------------ // ------------ extents --------------------------------------------- // ------------------------------------------------------------------ // Class to describe the extents of a multi dimensional array. // Used by mdspan, mdarray and layout mappings. // See ISO C++ standard [mdspan.extents] template class extents { public: // typedefs for integral types used using index_type = IndexType; using size_type = std::make_unsigned_t; using rank_type = size_t; static_assert(std::is_integral::value && !std::is_same::value, MDSPAN_IMPL_STANDARD_NAMESPACE_STRING "::extents::index_type must be a signed or unsigned integer type"); private: constexpr static rank_type m_rank = sizeof...(Extents); constexpr static rank_type m_rank_dynamic = _MDSPAN_FOLD_PLUS_RIGHT((Extents == dynamic_extent), /* + ... + */ 0); // internal storage type using maybe_static_array using vals_t = detail::maybe_static_array; _MDSPAN_NO_UNIQUE_ADDRESS vals_t m_vals; public: // [mdspan.extents.obs], observers of multidimensional index space MDSPAN_INLINE_FUNCTION constexpr static rank_type rank() noexcept { return m_rank; } MDSPAN_INLINE_FUNCTION constexpr static rank_type rank_dynamic() noexcept { return m_rank_dynamic; } MDSPAN_INLINE_FUNCTION constexpr index_type extent(rank_type r) const noexcept { return m_vals.value(r); } MDSPAN_INLINE_FUNCTION constexpr static size_t static_extent(rank_type r) noexcept { return vals_t::static_value(r); } // [mdspan.extents.cons], constructors MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr extents() noexcept = default; // Construction from just dynamic or all values. // Precondition check is deferred to maybe_static_array constructor MDSPAN_TEMPLATE_REQUIRES( class... OtherIndexTypes, /* requires */ ( _MDSPAN_FOLD_AND(_MDSPAN_TRAIT(std::is_convertible, OtherIndexTypes, index_type) /* && ... */) && _MDSPAN_FOLD_AND(_MDSPAN_TRAIT(std::is_nothrow_constructible, index_type, OtherIndexTypes) /* && ... */) && (sizeof...(OtherIndexTypes) == m_rank || sizeof...(OtherIndexTypes) == m_rank_dynamic))) MDSPAN_INLINE_FUNCTION constexpr explicit extents(OtherIndexTypes... dynvals) noexcept : m_vals(static_cast(dynvals)...) {} MDSPAN_TEMPLATE_REQUIRES( class OtherIndexType, size_t N, /* requires */ ( _MDSPAN_TRAIT(std::is_convertible, const OtherIndexType&, index_type) && _MDSPAN_TRAIT(std::is_nothrow_constructible, index_type, const OtherIndexType&) && (N == m_rank || N == m_rank_dynamic))) MDSPAN_INLINE_FUNCTION MDSPAN_CONDITIONAL_EXPLICIT(N != m_rank_dynamic) constexpr extents(const std::array &exts) noexcept : m_vals(std::move(exts)) {} #ifdef __cpp_lib_span MDSPAN_TEMPLATE_REQUIRES( class OtherIndexType, size_t N, /* requires */ (_MDSPAN_TRAIT(std::is_convertible, const OtherIndexType&, index_type) && _MDSPAN_TRAIT(std::is_nothrow_constructible, index_type, const OtherIndexType&) && (N == m_rank || N == m_rank_dynamic))) MDSPAN_INLINE_FUNCTION MDSPAN_CONDITIONAL_EXPLICIT(N != m_rank_dynamic) constexpr extents(const std::span &exts) noexcept : m_vals(std::move(exts)) {} #endif private: // Function to construct extents storage from other extents. // With C++ 17 the first two variants could be collapsed using if constexpr // in which case you don't need all the requires clauses. // in C++ 14 mode that doesn't work due to infinite recursion MDSPAN_TEMPLATE_REQUIRES( size_t DynCount, size_t R, class OtherExtents, class... DynamicValues, /* requires */ ((R < m_rank) && (static_extent(R) == dynamic_extent))) MDSPAN_INLINE_FUNCTION constexpr vals_t __construct_vals_from_extents(std::integral_constant, std::integral_constant, const OtherExtents &exts, DynamicValues... dynamic_values) noexcept { return __construct_vals_from_extents( std::integral_constant(), std::integral_constant(), exts, dynamic_values..., exts.extent(R)); } MDSPAN_TEMPLATE_REQUIRES( size_t DynCount, size_t R, class OtherExtents, class... DynamicValues, /* requires */ ((R < m_rank) && (static_extent(R) != dynamic_extent))) MDSPAN_INLINE_FUNCTION constexpr vals_t __construct_vals_from_extents(std::integral_constant, std::integral_constant, const OtherExtents &exts, DynamicValues... dynamic_values) noexcept { return __construct_vals_from_extents( std::integral_constant(), std::integral_constant(), exts, dynamic_values...); } MDSPAN_TEMPLATE_REQUIRES( size_t DynCount, size_t R, class OtherExtents, class... DynamicValues, /* requires */ ((R == m_rank) && (DynCount == m_rank_dynamic))) MDSPAN_INLINE_FUNCTION constexpr vals_t __construct_vals_from_extents(std::integral_constant, std::integral_constant, const OtherExtents &, DynamicValues... dynamic_values) noexcept { return vals_t{static_cast(dynamic_values)...}; } public: // Converting constructor from other extents specializations MDSPAN_TEMPLATE_REQUIRES( class OtherIndexType, size_t... OtherExtents, /* requires */ ( /* multi-stage check to protect from invalid pack expansion when sizes don't match? */ decltype(detail::__check_compatible_extents( // using: sizeof...(Extents) == sizeof...(OtherExtents) as the second argument fails with MSVC+NVCC with some obscure expansion error // MSVC: 19.38.33133 NVCC: 12.0 std::integral_constant::rank() == extents::rank()>{}, std::integer_sequence{}, std::integer_sequence{}))::value ) ) MDSPAN_INLINE_FUNCTION MDSPAN_CONDITIONAL_EXPLICIT((((Extents != dynamic_extent) && (OtherExtents == dynamic_extent)) || ...) || (std::numeric_limits::max() < std::numeric_limits::max())) constexpr extents(const extents &other) noexcept : m_vals(__construct_vals_from_extents( std::integral_constant(), std::integral_constant(), other)) {} // Comparison operator template MDSPAN_INLINE_FUNCTION friend constexpr bool operator==(const extents &lhs, const extents &rhs) noexcept { return rank() == extents::rank() && detail::rankwise_equal(detail::with_rank{}, rhs, lhs, detail::extent); } #if !(MDSPAN_HAS_CXX_20) template MDSPAN_INLINE_FUNCTION friend constexpr bool operator!=(extents const &lhs, extents const &rhs) noexcept { return !(lhs == rhs); } #endif }; // Recursive helper classes to implement dextents alias for extents namespace detail { template > struct __make_dextents; template struct __make_dextents< IndexType, Rank, ::MDSPAN_IMPL_STANDARD_NAMESPACE::extents> { using type = typename __make_dextents< IndexType, Rank - 1, ::MDSPAN_IMPL_STANDARD_NAMESPACE::extents>::type; }; template struct __make_dextents< IndexType, 0, ::MDSPAN_IMPL_STANDARD_NAMESPACE::extents> { using type = ::MDSPAN_IMPL_STANDARD_NAMESPACE::extents; }; } // end namespace detail // [mdspan.extents.dextents], alias template template using dextents = typename detail::__make_dextents::type; // Deduction guide for extents #if defined(_MDSPAN_USE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION) template extents(IndexTypes...) -> extents; #endif // Helper type traits for identifying a class as extents. namespace detail { template struct __is_extents : ::std::false_type {}; template struct __is_extents<::MDSPAN_IMPL_STANDARD_NAMESPACE::extents> : ::std::true_type {}; template #if MDSPAN_HAS_CXX_17 inline #else static #endif constexpr bool __is_extents_v = __is_extents::value; template MDSPAN_INLINE_FUNCTION constexpr void check_lower_bound(InputIndexType user_index, ExtentsIndexType /* current_extent */, std::true_type /* is_signed */) { (void) user_index; // prevent unused variable warning #ifdef _MDSPAN_DEBUG assert(static_cast(user_index) >= 0); #endif } template MDSPAN_INLINE_FUNCTION constexpr void check_lower_bound(InputIndexType /* user_index */, ExtentsIndexType /* current_extent */, std::false_type /* is_signed */) {} template MDSPAN_INLINE_FUNCTION constexpr void check_upper_bound(InputIndexType user_index, ExtentsIndexType current_extent) { (void) user_index; // prevent unused variable warnings (void) current_extent; #ifdef _MDSPAN_DEBUG assert(static_cast(user_index) < current_extent); #endif } // Returning true to use AND fold instead of comma // CPP14 mode doesn't like the use of void expressions // with the way the _MDSPAN_FOLD_AND is set up template MDSPAN_INLINE_FUNCTION constexpr bool check_one_index(InputIndex user_index, ExtentsIndexType current_extent) { check_lower_bound(user_index, current_extent, std::integral_constant::value>{}); check_upper_bound(user_index, current_extent); return true; } template MDSPAN_INLINE_FUNCTION constexpr void check_all_indices_helper(std::index_sequence, const extents& exts, Indices... indices) { // Suppress warning about statement has no effect (void) _MDSPAN_FOLD_AND( (check_one_index(indices, exts.extent(RankIndices))) ); } template MDSPAN_INLINE_FUNCTION constexpr void check_all_indices(const extents& exts, Indices... indices) { check_all_indices_helper(std::make_index_sequence(), exts, indices...); } } // namespace detail } // namespace MDSPAN_IMPL_STANDARD_NAMESPACE //END_FILE_INCLUDE: /home/runner/work/mdspan/mdspan/include/experimental/__p0009_bits/extents.hpp //BEGIN_FILE_INCLUDE: /home/runner/work/mdspan/mdspan/include/experimental/__p0009_bits/layout_stride.hpp //@HEADER // ************************************************************************ // // Kokkos v. 4.0 // Copyright (2022) National Technology & Engineering // Solutions of Sandia, LLC (NTESS). // // Under the terms of Contract DE-NA0003525 with NTESS, // the U.S. Government retains certain rights in this software. // // Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions. // See https://kokkos.org/LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //@HEADER //BEGIN_FILE_INCLUDE: /home/runner/work/mdspan/mdspan/include/experimental/__p0009_bits/compressed_pair.hpp //@HEADER // ************************************************************************ // // Kokkos v. 4.0 // Copyright (2022) National Technology & Engineering // Solutions of Sandia, LLC (NTESS). // // Under the terms of Contract DE-NA0003525 with NTESS, // the U.S. Government retains certain rights in this software. // // Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions. // See https://kokkos.org/LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //@HEADER #if !defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) //BEGIN_FILE_INCLUDE: /home/runner/work/mdspan/mdspan/include/experimental/__p0009_bits/no_unique_address.hpp //@HEADER // ************************************************************************ // // Kokkos v. 4.0 // Copyright (2022) National Technology & Engineering // Solutions of Sandia, LLC (NTESS). // // Under the terms of Contract DE-NA0003525 with NTESS, // the U.S. Government retains certain rights in this software. // // Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions. // See https://kokkos.org/LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //@HEADER namespace MDSPAN_IMPL_STANDARD_NAMESPACE { namespace detail { //============================================================================== template struct __no_unique_address_emulation { using __stored_type = _T; _T __v; MDSPAN_FORCE_INLINE_FUNCTION constexpr _T const &__ref() const noexcept { return __v; } MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 _T &__ref() noexcept { return __v; } }; // Empty case // This doesn't work if _T is final, of course, but we're not using anything // like that currently. That kind of thing could be added pretty easily though template struct __no_unique_address_emulation< _T, _Disambiguator, std::enable_if_t<_MDSPAN_TRAIT(std::is_empty, _T) && // If the type isn't trivially destructible, its destructor // won't be called at the right time, so don't use this // specialization _MDSPAN_TRAIT(std::is_trivially_destructible, _T)>> : #ifdef _MDSPAN_COMPILER_MSVC // MSVC doesn't allow you to access public static member functions of a type // when you *happen* to privately inherit from that type. protected #else // But we still want this to be private if possible so that we don't accidentally // access members of _T directly rather than calling __ref() first, which wouldn't // work if _T happens to be stateful and thus we're using the unspecialized definition // of __no_unique_address_emulation above. private #endif _T { using __stored_type = _T; MDSPAN_FORCE_INLINE_FUNCTION constexpr _T const &__ref() const noexcept { return *static_cast<_T const *>(this); } MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 _T &__ref() noexcept { return *static_cast<_T *>(this); } MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr __no_unique_address_emulation() noexcept = default; MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr __no_unique_address_emulation( __no_unique_address_emulation const &) noexcept = default; MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr __no_unique_address_emulation( __no_unique_address_emulation &&) noexcept = default; MDSPAN_INLINE_FUNCTION_DEFAULTED _MDSPAN_CONSTEXPR_14_DEFAULTED __no_unique_address_emulation & operator=(__no_unique_address_emulation const &) noexcept = default; MDSPAN_INLINE_FUNCTION_DEFAULTED _MDSPAN_CONSTEXPR_14_DEFAULTED __no_unique_address_emulation & operator=(__no_unique_address_emulation &&) noexcept = default; MDSPAN_INLINE_FUNCTION_DEFAULTED ~__no_unique_address_emulation() noexcept = default; // Explicitly make this not a reference so that the copy or move // constructor still gets called. MDSPAN_INLINE_FUNCTION explicit constexpr __no_unique_address_emulation(_T const& __v) noexcept : _T(__v) {} MDSPAN_INLINE_FUNCTION explicit constexpr __no_unique_address_emulation(_T&& __v) noexcept : _T(::std::move(__v)) {} }; //============================================================================== } // end namespace detail } // end namespace MDSPAN_IMPL_STANDARD_NAMESPACE //END_FILE_INCLUDE: /home/runner/work/mdspan/mdspan/include/experimental/__p0009_bits/no_unique_address.hpp #endif namespace MDSPAN_IMPL_STANDARD_NAMESPACE { namespace detail { // For no unique address emulation, this is the case taken when neither are empty. // For real `[[no_unique_address]]`, this case is always taken. template struct __compressed_pair { _MDSPAN_NO_UNIQUE_ADDRESS _T1 __t1_val{}; _MDSPAN_NO_UNIQUE_ADDRESS _T2 __t2_val{}; MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 _T1 &__first() noexcept { return __t1_val; } MDSPAN_FORCE_INLINE_FUNCTION constexpr _T1 const &__first() const noexcept { return __t1_val; } MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 _T2 &__second() noexcept { return __t2_val; } MDSPAN_FORCE_INLINE_FUNCTION constexpr _T2 const &__second() const noexcept { return __t2_val; } MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr __compressed_pair() = default; MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr __compressed_pair(__compressed_pair const &) = default; MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr __compressed_pair(__compressed_pair &&) = default; MDSPAN_INLINE_FUNCTION_DEFAULTED _MDSPAN_CONSTEXPR_14_DEFAULTED __compressed_pair & operator=(__compressed_pair const &) = default; MDSPAN_INLINE_FUNCTION_DEFAULTED _MDSPAN_CONSTEXPR_14_DEFAULTED __compressed_pair & operator=(__compressed_pair &&) = default; MDSPAN_INLINE_FUNCTION_DEFAULTED ~__compressed_pair() = default; template MDSPAN_INLINE_FUNCTION constexpr __compressed_pair(_T1Like &&__t1, _T2Like &&__t2) : __t1_val((_T1Like &&) __t1), __t2_val((_T2Like &&) __t2) {} }; #if !defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) // First empty. template struct __compressed_pair< _T1, _T2, std::enable_if_t<_MDSPAN_TRAIT(std::is_empty, _T1) && !_MDSPAN_TRAIT(std::is_empty, _T2)>> : private _T1 { _T2 __t2_val{}; MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 _T1 &__first() noexcept { return *static_cast<_T1 *>(this); } MDSPAN_FORCE_INLINE_FUNCTION constexpr _T1 const &__first() const noexcept { return *static_cast<_T1 const *>(this); } MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 _T2 &__second() noexcept { return __t2_val; } MDSPAN_FORCE_INLINE_FUNCTION constexpr _T2 const &__second() const noexcept { return __t2_val; } MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr __compressed_pair() = default; MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr __compressed_pair(__compressed_pair const &) = default; MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr __compressed_pair(__compressed_pair &&) = default; MDSPAN_INLINE_FUNCTION_DEFAULTED _MDSPAN_CONSTEXPR_14_DEFAULTED __compressed_pair & operator=(__compressed_pair const &) = default; MDSPAN_INLINE_FUNCTION_DEFAULTED _MDSPAN_CONSTEXPR_14_DEFAULTED __compressed_pair & operator=(__compressed_pair &&) = default; MDSPAN_INLINE_FUNCTION_DEFAULTED ~__compressed_pair() = default; template MDSPAN_INLINE_FUNCTION constexpr __compressed_pair(_T1Like &&__t1, _T2Like &&__t2) : _T1((_T1Like &&) __t1), __t2_val((_T2Like &&) __t2) {} }; // Second empty. template struct __compressed_pair< _T1, _T2, std::enable_if_t> : private _T2 { _T1 __t1_val{}; MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 _T1 &__first() noexcept { return __t1_val; } MDSPAN_FORCE_INLINE_FUNCTION constexpr _T1 const &__first() const noexcept { return __t1_val; } MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 _T2 &__second() noexcept { return *static_cast<_T2 *>(this); } MDSPAN_FORCE_INLINE_FUNCTION constexpr _T2 const &__second() const noexcept { return *static_cast<_T2 const *>(this); } MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr __compressed_pair() = default; MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr __compressed_pair(__compressed_pair const &) = default; MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr __compressed_pair(__compressed_pair &&) = default; MDSPAN_INLINE_FUNCTION_DEFAULTED _MDSPAN_CONSTEXPR_14_DEFAULTED __compressed_pair & operator=(__compressed_pair const &) = default; MDSPAN_INLINE_FUNCTION_DEFAULTED _MDSPAN_CONSTEXPR_14_DEFAULTED __compressed_pair & operator=(__compressed_pair &&) = default; MDSPAN_INLINE_FUNCTION_DEFAULTED ~__compressed_pair() = default; template MDSPAN_INLINE_FUNCTION constexpr __compressed_pair(_T1Like &&__t1, _T2Like &&__t2) : _T2((_T2Like &&) __t2), __t1_val((_T1Like &&) __t1) {} }; // Both empty. template struct __compressed_pair< _T1, _T2, std::enable_if_t<_MDSPAN_TRAIT(std::is_empty, _T1) && _MDSPAN_TRAIT(std::is_empty, _T2)>> // We need to use the __no_unique_address_emulation wrapper here to avoid // base class ambiguities. #ifdef _MDSPAN_COMPILER_MSVC // MSVC doesn't allow you to access public static member functions of a type // when you *happen* to privately inherit from that type. : protected __no_unique_address_emulation<_T1, 0>, protected __no_unique_address_emulation<_T2, 1> #else : private __no_unique_address_emulation<_T1, 0>, private __no_unique_address_emulation<_T2, 1> #endif { using __first_base_t = __no_unique_address_emulation<_T1, 0>; using __second_base_t = __no_unique_address_emulation<_T2, 1>; MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 _T1 &__first() noexcept { return this->__first_base_t::__ref(); } MDSPAN_FORCE_INLINE_FUNCTION constexpr _T1 const &__first() const noexcept { return this->__first_base_t::__ref(); } MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 _T2 &__second() noexcept { return this->__second_base_t::__ref(); } MDSPAN_FORCE_INLINE_FUNCTION constexpr _T2 const &__second() const noexcept { return this->__second_base_t::__ref(); } MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr __compressed_pair() = default; MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr __compressed_pair(__compressed_pair const &) = default; MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr __compressed_pair(__compressed_pair &&) = default; MDSPAN_INLINE_FUNCTION_DEFAULTED _MDSPAN_CONSTEXPR_14_DEFAULTED __compressed_pair & operator=(__compressed_pair const &) = default; MDSPAN_INLINE_FUNCTION_DEFAULTED _MDSPAN_CONSTEXPR_14_DEFAULTED __compressed_pair & operator=(__compressed_pair &&) = default; MDSPAN_INLINE_FUNCTION_DEFAULTED ~__compressed_pair() = default; template MDSPAN_INLINE_FUNCTION constexpr __compressed_pair(_T1Like &&__t1, _T2Like &&__t2) noexcept : __first_base_t(_T1((_T1Like &&) __t1)), __second_base_t(_T2((_T2Like &&) __t2)) { } }; #endif // !defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) } // end namespace detail } // end namespace MDSPAN_IMPL_STANDARD_NAMESPACE //END_FILE_INCLUDE: /home/runner/work/mdspan/mdspan/include/experimental/__p0009_bits/compressed_pair.hpp #if !defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) #endif #include #include #include #ifdef __cpp_lib_span #include #endif #if defined(_MDSPAN_USE_CONCEPTS) && MDSPAN_HAS_CXX_20 && defined(__cpp_lib_concepts) # include #endif namespace MDSPAN_IMPL_STANDARD_NAMESPACE { struct layout_left { template class mapping; }; struct layout_right { template class mapping; }; namespace detail { template constexpr bool __is_mapping_of = std::is_same, Mapping>::value; #if defined(_MDSPAN_USE_CONCEPTS) && MDSPAN_HAS_CXX_20 # if !defined(__cpp_lib_concepts) namespace internal { namespace detail { template concept __same_as = std::is_same_v<_Tp, _Up>; } // namespace detail template concept __same_as = detail::__same_as && detail::__same_as; } // namespace internal # endif template concept __layout_mapping_alike = requires { requires __is_extents::value; #if defined(__cpp_lib_concepts) { M::is_always_strided() } -> std::same_as; { M::is_always_exhaustive() } -> std::same_as; { M::is_always_unique() } -> std::same_as; #else { M::is_always_strided() } -> internal::__same_as; { M::is_always_exhaustive() } -> internal::__same_as; { M::is_always_unique() } -> internal::__same_as; #endif std::bool_constant::value; std::bool_constant::value; std::bool_constant::value; }; #endif } // namespace detail struct layout_stride { template class mapping #if !defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) : private detail::__no_unique_address_emulation< detail::__compressed_pair< Extents, detail::possibly_empty_array > > #endif { public: using extents_type = Extents; using index_type = typename extents_type::index_type; using size_type = typename extents_type::size_type; using rank_type = typename extents_type::rank_type; using layout_type = layout_stride; // This could be a `requires`, but I think it's better and clearer as a `static_assert`. static_assert(detail::__is_extents_v, MDSPAN_IMPL_STANDARD_NAMESPACE_STRING "::layout_stride::mapping must be instantiated with a specialization of " MDSPAN_IMPL_STANDARD_NAMESPACE_STRING "::extents."); private: //---------------------------------------------------------------------------- using __strides_storage_t = detail::possibly_empty_array; using __member_pair_t = detail::__compressed_pair; #if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) _MDSPAN_NO_UNIQUE_ADDRESS __member_pair_t __members; #else using __base_t = detail::__no_unique_address_emulation<__member_pair_t>; #endif MDSPAN_FORCE_INLINE_FUNCTION constexpr __strides_storage_t const& __strides_storage() const noexcept { #if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) return __members.__second(); #else return this->__base_t::__ref().__second(); #endif } MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 __strides_storage_t& __strides_storage() noexcept { #if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) return __members.__second(); #else return this->__base_t::__ref().__second(); #endif } template _MDSPAN_HOST_DEVICE constexpr index_type __get_size(::MDSPAN_IMPL_STANDARD_NAMESPACE::extents,std::integer_sequence) const { return _MDSPAN_FOLD_TIMES_RIGHT( static_cast(extents().extent(Idx)), 1 ); } //---------------------------------------------------------------------------- template friend class mapping; //---------------------------------------------------------------------------- // Workaround for non-deducibility of the index sequence template parameter if it's given at the top level template struct __deduction_workaround; template struct __deduction_workaround> { template MDSPAN_INLINE_FUNCTION static constexpr bool _eq_impl(mapping const& self, mapping const& other) noexcept { using common_t = std::common_type_t; return _MDSPAN_FOLD_AND((static_cast(self.stride(Idxs)) == static_cast(other.stride(Idxs))) /* && ... */) && _MDSPAN_FOLD_AND((static_cast(self.extents().extent(Idxs)) == static_cast(other.extents().extent(Idxs))) /* || ... */); } template MDSPAN_INLINE_FUNCTION static constexpr bool _not_eq_impl(mapping const& self, mapping const& other) noexcept { using common_t = std::common_type_t; return _MDSPAN_FOLD_OR((static_cast(self.stride(Idxs)) != static_cast(other.stride(Idxs))) /* || ... */) || _MDSPAN_FOLD_OR((static_cast(self.extents().extent(Idxs)) != static_cast(other.extents().extent(Idxs))) /* || ... */); } template MDSPAN_FORCE_INLINE_FUNCTION static constexpr size_t _call_op_impl(mapping const& self, Integral... idxs) noexcept { return _MDSPAN_FOLD_PLUS_RIGHT((idxs * self.stride(Idxs)), /* + ... + */ 0); } MDSPAN_INLINE_FUNCTION static constexpr size_t _req_span_size_impl(mapping 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() - 1)...) + 1; } template MDSPAN_INLINE_FUNCTION static constexpr const __strides_storage_t fill_strides(const OtherMapping& map) { return __strides_storage_t{static_cast(map.stride(Idxs))...}; } MDSPAN_INLINE_FUNCTION static constexpr const __strides_storage_t& fill_strides(const __strides_storage_t& s) { return s; } template MDSPAN_INLINE_FUNCTION static constexpr const __strides_storage_t fill_strides(const std::array& s) { return __strides_storage_t{static_cast(s[Idxs])...}; } MDSPAN_TEMPLATE_REQUIRES( class IntegralType, // The is_convertible condition is added to make sfinae valid // the extents_type::rank() > 0 is added to avoid use of non-standard zero length c-array (std::is_convertible::value && (extents_type::rank() > 0)) ) MDSPAN_INLINE_FUNCTION // despite the requirement some compilers still complain about zero length array during parsing // making it length 1 now, but since the thing can't be instantiated due to requirement the actual // instantiation of strides_storage will not fail despite mismatching length static constexpr const __strides_storage_t fill_strides(mdspan_non_standard_tag, const IntegralType (&s)[extents_type::rank()>0?extents_type::rank():1]) { return __strides_storage_t{static_cast(s[Idxs])...}; } #ifdef __cpp_lib_span template MDSPAN_INLINE_FUNCTION static constexpr const __strides_storage_t fill_strides(const std::span& s) { return __strides_storage_t{static_cast(s[Idxs])...}; } #endif MDSPAN_INLINE_FUNCTION static constexpr std::array return_strides(const __strides_storage_t& s) { return std::array{s[Idxs]...}; } template MDSPAN_INLINE_FUNCTION static constexpr size_t __return_zero() { return 0; } template MDSPAN_INLINE_FUNCTION static constexpr typename Mapping::index_type __OFFSET(const Mapping& m) { return m(__return_zero()...); } }; // Can't use defaulted parameter in the __deduction_workaround template because of a bug in MSVC warning C4348. using __impl = __deduction_workaround>; static constexpr __strides_storage_t strides_storage(detail::with_rank<0>) { return {}; } template static constexpr __strides_storage_t strides_storage(detail::with_rank) { __strides_storage_t s{}; extents_type e; index_type stride = 1; for(int r = static_cast(extents_type::rank() - 1); r >= 0; r--) { s[r] = stride; stride *= e.extent(r); } return s; } //---------------------------------------------------------------------------- #if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) MDSPAN_INLINE_FUNCTION constexpr explicit mapping(__member_pair_t&& __m) : __members(::std::move(__m)) {} #else MDSPAN_INLINE_FUNCTION constexpr explicit mapping(__base_t&& __b) : __base_t(::std::move(__b)) {} #endif public: //-------------------------------------------------------------------------------- MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr mapping() noexcept #if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) : __members{ #else : __base_t(__base_t{__member_pair_t( #endif extents_type(), __strides_storage_t(strides_storage(detail::with_rank{})) #if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) } #else )}) #endif {} MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr mapping(mapping const&) noexcept = default; MDSPAN_TEMPLATE_REQUIRES( class IntegralTypes, /* requires */ ( // MSVC 19.32 does not like using index_type here, requires the typename Extents::index_type // error C2641: cannot deduce template arguments for 'MDSPAN_IMPL_STANDARD_NAMESPACE::layout_stride::mapping' _MDSPAN_TRAIT(std::is_convertible, const std::remove_const_t&, typename Extents::index_type) && _MDSPAN_TRAIT(std::is_nothrow_constructible, typename Extents::index_type, const std::remove_const_t&) ) ) MDSPAN_INLINE_FUNCTION constexpr mapping( extents_type const& e, std::array const& s ) noexcept #if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) : __members{ #else : __base_t(__base_t{__member_pair_t( #endif e, __strides_storage_t(__impl::fill_strides(s)) #if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) } #else )}) #endif { /* * TODO: check preconditions * - s[i] > 0 is true for all i in the range [0, rank_ ). * - REQUIRED-SPAN-SIZE(e, s) is a representable value of type index_type ([basic.fundamental]). * - If rank_ is greater than 0, then there exists a permutation P of the integers in the * range [0, rank_), such that s[ pi ] >= s[ pi − 1 ] * e.extent( pi − 1 ) is true for * all i in the range [1, rank_ ), where pi is the ith element of P. */ } MDSPAN_TEMPLATE_REQUIRES( class IntegralTypes, /* requires */ ( // MSVC 19.32 does not like using index_type here, requires the typename Extents::index_type // error C2641: cannot deduce template arguments for 'MDSPAN_IMPL_STANDARD_NAMESPACE::layout_stride::mapping' _MDSPAN_TRAIT(std::is_convertible, const std::remove_const_t&, typename Extents::index_type) && _MDSPAN_TRAIT(std::is_nothrow_constructible, typename Extents::index_type, const std::remove_const_t&) && (Extents::rank() > 0) ) ) MDSPAN_INLINE_FUNCTION constexpr mapping( mdspan_non_standard_tag, extents_type const& e, // despite the requirement some compilers still complain about zero length array during parsing // making it length 1 now, but since the thing can't be instantiated due to requirement the actual // instantiation of strides_storage will not fail despite mismatching length IntegralTypes (&s)[extents_type::rank()>0?extents_type::rank():1] ) noexcept #if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) : __members{ #else : __base_t(__base_t{__member_pair_t( #endif e, __strides_storage_t(__impl::fill_strides(mdspan_non_standard, s)) #if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) } #else )}) #endif { /* * TODO: check preconditions * - s[i] > 0 is true for all i in the range [0, rank_ ). * - REQUIRED-SPAN-SIZE(e, s) is a representable value of type index_type ([basic.fundamental]). * - If rank_ is greater than 0, then there exists a permutation P of the integers in the * range [0, rank_), such that s[ pi ] >= s[ pi − 1 ] * e.extent( pi − 1 ) is true for * all i in the range [1, rank_ ), where pi is the ith element of P. */ } #ifdef __cpp_lib_span MDSPAN_TEMPLATE_REQUIRES( class IntegralTypes, /* requires */ ( // MSVC 19.32 does not like using index_type here, requires the typename Extents::index_type // error C2641: cannot deduce template arguments for 'MDSPAN_IMPL_STANDARD_NAMESPACE::layout_stride::mapping' _MDSPAN_TRAIT(std::is_convertible, const std::remove_const_t&, typename Extents::index_type) && _MDSPAN_TRAIT(std::is_nothrow_constructible, typename Extents::index_type, const std::remove_const_t&) ) ) MDSPAN_INLINE_FUNCTION constexpr mapping( extents_type const& e, std::span const& s ) noexcept #if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) : __members{ #else : __base_t(__base_t{__member_pair_t( #endif e, __strides_storage_t(__impl::fill_strides(s)) #if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) } #else )}) #endif { /* * TODO: check preconditions * - s[i] > 0 is true for all i in the range [0, rank_ ). * - REQUIRED-SPAN-SIZE(e, s) is a representable value of type index_type ([basic.fundamental]). * - If rank_ is greater than 0, then there exists a permutation P of the integers in the * range [0, rank_), such that s[ pi ] >= s[ pi − 1 ] * e.extent( pi − 1 ) is true for * all i in the range [1, rank_ ), where pi is the ith element of P. */ } #endif // __cpp_lib_span #if !(defined(_MDSPAN_USE_CONCEPTS) && MDSPAN_HAS_CXX_20) MDSPAN_TEMPLATE_REQUIRES( class StridedLayoutMapping, /* requires */ ( _MDSPAN_TRAIT(std::is_constructible, extents_type, typename StridedLayoutMapping::extents_type) && detail::__is_mapping_of && StridedLayoutMapping::is_always_unique() && StridedLayoutMapping::is_always_strided() ) ) #else template requires( detail::__layout_mapping_alike && _MDSPAN_TRAIT(std::is_constructible, extents_type, typename StridedLayoutMapping::extents_type) && StridedLayoutMapping::is_always_unique() && StridedLayoutMapping::is_always_strided() ) #endif MDSPAN_CONDITIONAL_EXPLICIT( !(std::is_convertible::value && (detail::__is_mapping_of || detail::__is_mapping_of || detail::__is_mapping_of)) ) // needs two () due to comma MDSPAN_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 mapping(StridedLayoutMapping const& other) noexcept // NOLINT(google-explicit-constructor) #if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) : __members{ #else : __base_t(__base_t{__member_pair_t( #endif other.extents(), __strides_storage_t(__impl::fill_strides(other)) #if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) } #else )}) #endif { /* * TODO: check preconditions * - other.stride(i) > 0 is true for all i in the range [0, rank_ ). * - other.required_span_size() is a representable value of type index_type ([basic.fundamental]). * - OFFSET(other) == 0 */ } //-------------------------------------------------------------------------------- MDSPAN_INLINE_FUNCTION_DEFAULTED _MDSPAN_CONSTEXPR_14_DEFAULTED mapping& operator=(mapping const&) noexcept = default; MDSPAN_INLINE_FUNCTION constexpr const extents_type& extents() const noexcept { #if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) return __members.__first(); #else return this->__base_t::__ref().__first(); #endif }; MDSPAN_INLINE_FUNCTION constexpr std::array< index_type, extents_type::rank() > strides() const noexcept { return __impl::return_strides(__strides_storage()); } MDSPAN_INLINE_FUNCTION constexpr index_type required_span_size() const noexcept { index_type span_size = 1; for(unsigned r = 0; r < extents_type::rank(); r++) { // Return early if any of the extents are zero if(extents().extent(r)==0) return 0; span_size += ( static_cast(extents().extent(r) - 1 ) * __strides_storage()[r]); } return span_size; } MDSPAN_TEMPLATE_REQUIRES( class... Indices, /* requires */ ( sizeof...(Indices) == Extents::rank() && (detail::are_valid_indices()) ) ) MDSPAN_FORCE_INLINE_FUNCTION constexpr index_type operator()(Indices... idxs) const noexcept { #if ! defined(NDEBUG) detail::check_all_indices(this->extents(), idxs...); #endif // ! NDEBUG return static_cast(__impl::_call_op_impl(*this, static_cast(idxs)...)); } MDSPAN_INLINE_FUNCTION static constexpr bool is_always_unique() noexcept { return true; } MDSPAN_INLINE_FUNCTION static constexpr bool is_always_exhaustive() noexcept { return false; } MDSPAN_INLINE_FUNCTION static constexpr bool is_always_strided() noexcept { return true; } MDSPAN_INLINE_FUNCTION static constexpr bool is_unique() noexcept { return true; } private: constexpr bool exhaustive_for_nonzero_span_size() const { return required_span_size() == __get_size(extents(), std::make_index_sequence()); } constexpr bool is_exhaustive_impl(detail::with_rank<0>) const { return true; } constexpr bool is_exhaustive_impl(detail::with_rank<1>) const { if (required_span_size() != static_cast(0)) { return exhaustive_for_nonzero_span_size(); } return stride(0) == 1; } template constexpr bool is_exhaustive_impl(detail::with_rank) const { if (required_span_size() != static_cast(0)) { return exhaustive_for_nonzero_span_size(); } rank_type r_largest = 0; for (rank_type r = 1; r < extents_type::rank(); r++) { if (stride(r) > stride(r_largest)) { r_largest = r; } } for (rank_type r = 0; r < extents_type::rank(); r++) { if (extents().extent(r) == 0 && r != r_largest) { return false; } } return true; } public: MDSPAN_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 bool is_exhaustive() const noexcept { return is_exhaustive_impl(detail::with_rank{}); } MDSPAN_INLINE_FUNCTION static constexpr bool is_strided() noexcept { return true; } MDSPAN_INLINE_FUNCTION constexpr index_type stride(rank_type r) const noexcept { return __strides_storage()[r]; } #if !(defined(_MDSPAN_USE_CONCEPTS) && MDSPAN_HAS_CXX_20) MDSPAN_TEMPLATE_REQUIRES( class StridedLayoutMapping, /* requires */ ( detail::__is_mapping_of && (extents_type::rank() == StridedLayoutMapping::extents_type::rank()) && StridedLayoutMapping::is_always_strided() ) ) #else template requires( detail::__layout_mapping_alike && (extents_type::rank() == StridedLayoutMapping::extents_type::rank()) && StridedLayoutMapping::is_always_strided() ) #endif MDSPAN_INLINE_FUNCTION friend constexpr bool operator==(const mapping& x, const StridedLayoutMapping& y) noexcept { return (x.extents() == y.extents()) && (__impl::__OFFSET(y) == static_cast(0)) && detail::rankwise_equal(detail::with_rank{}, x, y, detail::stride); } // This one is not technically part of the proposal. Just here to make implementation a bit more optimal hopefully MDSPAN_TEMPLATE_REQUIRES( class OtherExtents, /* requires */ ( (extents_type::rank() == OtherExtents::rank()) ) ) MDSPAN_INLINE_FUNCTION friend constexpr bool operator==(mapping const& lhs, mapping const& rhs) noexcept { return __impl::_eq_impl(lhs, rhs); } #if !MDSPAN_HAS_CXX_20 MDSPAN_TEMPLATE_REQUIRES( class StridedLayoutMapping, /* requires */ ( detail::__is_mapping_of && (extents_type::rank() == StridedLayoutMapping::extents_type::rank()) && StridedLayoutMapping::is_always_strided() ) ) MDSPAN_INLINE_FUNCTION friend constexpr bool operator!=(const mapping& x, const StridedLayoutMapping& y) noexcept { return !(x == y); } MDSPAN_TEMPLATE_REQUIRES( class OtherExtents, /* requires */ ( (extents_type::rank() == OtherExtents::rank()) ) ) MDSPAN_INLINE_FUNCTION friend constexpr bool operator!=(mapping const& lhs, mapping const& rhs) noexcept { return __impl::_not_eq_impl(lhs, rhs); } #endif // [mdspan.submdspan.mapping], submdspan mapping specialization template MDSPAN_INLINE_FUNCTION constexpr auto submdspan_mapping_impl( SliceSpecifiers... slices) const; template friend constexpr auto submdspan_mapping( const mapping& src, SliceSpecifiers... slices) { return src.submdspan_mapping_impl(slices...); } }; }; namespace detail { template constexpr void validate_strides(with_rank<0>, Layout, const Extents&, const Mapping&) {} template constexpr void validate_strides(with_rank, Layout, const Extents& ext, const Mapping& other) { static_assert(std::is_same::value && (std::is_same::value || std::is_same::value) , "This function is only intended to validate construction of " "a layout_left or layout_right mapping from a layout_stride mapping."); constexpr auto is_left = std::is_same::value; typename Extents::index_type expected_stride = 1; for (std::size_t r = 0; r < N; r++) { const std::size_t s = is_left ? r : N - 1 - r; MDSPAN_IMPL_PRECONDITION(common_integral_compare(expected_stride, other.stride(s)) && "invalid strides for layout_{left,right}"); expected_stride *= ext.extent(s); } } } // namespace detail } // end namespace MDSPAN_IMPL_STANDARD_NAMESPACE //END_FILE_INCLUDE: /home/runner/work/mdspan/mdspan/include/experimental/__p0009_bits/layout_stride.hpp #if MDSPAN_HAS_CXX_17 //BEGIN_FILE_INCLUDE: /home/runner/work/mdspan/mdspan/include/experimental/__p2642_bits/layout_padded_fwd.hpp //@HEADER // ************************************************************************ // // Kokkos v. 4.0 // Copyright (2022) National Technology & Engineering // Solutions of Sandia, LLC (NTESS). // // Under the terms of Contract DE-NA0003525 with NTESS, // the U.S. Government retains certain rights in this software. // // Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions. // // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //@HEADER #include namespace MDSPAN_IMPL_STANDARD_NAMESPACE { namespace MDSPAN_IMPL_PROPOSED_NAMESPACE { template struct layout_left_padded { template class mapping; }; template struct layout_right_padded { template class mapping; }; namespace detail { // The layout_padded_constants structs are only useful if rank > 1, otherwise they may wrap template struct layout_padded_constants; template struct layout_padded_constants, _ExtentsType> { using rank_type = typename _ExtentsType::rank_type; static constexpr rank_type padded_stride_idx = 1; static constexpr rank_type extent_to_pad_idx = 0; }; template struct layout_padded_constants, _ExtentsType> { using rank_type = typename _ExtentsType::rank_type; static constexpr rank_type padded_stride_idx = _ExtentsType::rank() - 2; static constexpr rank_type extent_to_pad_idx = _ExtentsType::rank() - 1; }; template struct is_layout_left_padded : std::false_type {}; template struct is_layout_left_padded> : std::true_type {}; template struct is_layout_left_padded_mapping : std::false_type {}; template struct is_layout_left_padded_mapping<_Mapping, std::enable_if_t::template mapping>::value>> : std::true_type {}; template struct is_layout_right_padded : std::false_type {}; template struct is_layout_right_padded> : std::true_type {}; template struct is_layout_right_padded_mapping : std::false_type {}; template struct is_layout_right_padded_mapping<_Mapping, std::enable_if_t::template mapping>::value>> : std::true_type {}; template constexpr void check_padded_layout_converting_constructor_mandates(MDSPAN_IMPL_STANDARD_NAMESPACE::detail::with_rank<0>) {} template constexpr void check_padded_layout_converting_constructor_mandates(MDSPAN_IMPL_STANDARD_NAMESPACE::detail::with_rank<1>) {} template constexpr void check_padded_layout_converting_constructor_mandates(MDSPAN_IMPL_STANDARD_NAMESPACE::detail::with_rank) { using extents_type = typename _PaddedLayoutMappingType::extents_type; constexpr auto padding_value = _PaddedLayoutMappingType::padding_value; constexpr auto idx = layout_padded_constants::extent_to_pad_idx; constexpr auto statically_determinable = (_LayoutExtentsType::static_extent(idx) != dynamic_extent) && (extents_type::static_extent(idx) != dynamic_extent) && (padding_value != dynamic_extent); static_assert(!statically_determinable || (padding_value == 0 ? _LayoutExtentsType::static_extent(idx) == 0 : _LayoutExtentsType::static_extent(idx) % padding_value == 0), ""); } template constexpr void check_padded_layout_converting_constructor_preconditions(MDSPAN_IMPL_STANDARD_NAMESPACE::detail::with_rank<0>, const _OtherMapping&) {} template constexpr void check_padded_layout_converting_constructor_preconditions(MDSPAN_IMPL_STANDARD_NAMESPACE::detail::with_rank<1>, const _OtherMapping&) {} template constexpr void check_padded_layout_converting_constructor_preconditions(MDSPAN_IMPL_STANDARD_NAMESPACE::detail::with_rank, const _OtherMapping &other_mapping) { constexpr auto padded_stride_idx = layout_padded_constants::padded_stride_idx; constexpr auto extent_to_pad_idx = layout_padded_constants::extent_to_pad_idx; MDSPAN_IMPL_PRECONDITION(other_mapping.stride(padded_stride_idx) == other_mapping.extents().extent(extent_to_pad_idx)); } } } } //END_FILE_INCLUDE: /home/runner/work/mdspan/mdspan/include/experimental/__p2642_bits/layout_padded_fwd.hpp #endif namespace MDSPAN_IMPL_STANDARD_NAMESPACE { //============================================================================== template class layout_right::mapping { public: using extents_type = Extents; using index_type = typename extents_type::index_type; using size_type = typename extents_type::size_type; using rank_type = typename extents_type::rank_type; using layout_type = layout_right; private: static_assert(detail::__is_extents_v, MDSPAN_IMPL_STANDARD_NAMESPACE_STRING "::layout_right::mapping must be instantiated with a specialization of " MDSPAN_IMPL_STANDARD_NAMESPACE_STRING "::extents."); template friend class mapping; // i0+(i1 + E(1)*(i2 + E(2)*i3)) template struct __rank_count {}; template _MDSPAN_HOST_DEVICE constexpr index_type __compute_offset( index_type offset, __rank_count, const I& i, Indices... idx) const { return __compute_offset(offset * __extents.extent(r) + i,__rank_count(), idx...); } template _MDSPAN_HOST_DEVICE constexpr index_type __compute_offset( __rank_count<0,extents_type::rank()>, const I& i, Indices... idx) const { return __compute_offset(i,__rank_count<1,extents_type::rank()>(),idx...); } _MDSPAN_HOST_DEVICE constexpr index_type __compute_offset(size_t offset, __rank_count) const { return static_cast(offset); } _MDSPAN_HOST_DEVICE constexpr index_type __compute_offset(__rank_count<0,0>) const { return 0; } public: //-------------------------------------------------------------------------------- MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr mapping() noexcept = default; MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr mapping(mapping const&) noexcept = default; _MDSPAN_HOST_DEVICE constexpr mapping(extents_type const& __exts) noexcept :__extents(__exts) { } MDSPAN_TEMPLATE_REQUIRES( class OtherExtents, /* requires */ ( _MDSPAN_TRAIT(std::is_constructible, extents_type, OtherExtents) ) ) MDSPAN_CONDITIONAL_EXPLICIT((!std::is_convertible::value)) // needs two () due to comma MDSPAN_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 mapping(mapping const& other) noexcept // NOLINT(google-explicit-constructor) :__extents(other.extents()) { /* * TODO: check precondition * other.required_span_size() is a representable value of type index_type */ } MDSPAN_TEMPLATE_REQUIRES( class OtherExtents, /* requires */ ( _MDSPAN_TRAIT(std::is_constructible, extents_type, OtherExtents) && (extents_type::rank() <= 1) ) ) MDSPAN_CONDITIONAL_EXPLICIT((!std::is_convertible::value)) // needs two () due to comma MDSPAN_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 mapping(layout_left::mapping const& other) noexcept // NOLINT(google-explicit-constructor) :__extents(other.extents()) { /* * TODO: check precondition * other.required_span_size() is a representable value of type index_type */ } /** * Converting constructor from `layout_right_padded::mapping`. * * This overload participates in overload resolution only if _Mapping is a layout_right_padded mapping and * extents_type is constructible from _Mapping::extents_type. * * \note There is currently a difference from p2642r2, where this function is specified as taking * `layout_right_padded< padding_value >::mapping< Extents>`. However, this makes `padding_value` non-deducible. */ #if MDSPAN_HAS_CXX_17 MDSPAN_TEMPLATE_REQUIRES( class _Mapping, /* requires */ ( MDSPAN_IMPL_PROPOSED_NAMESPACE::detail::is_layout_right_padded_mapping<_Mapping>::value && std::is_constructible_v)) MDSPAN_CONDITIONAL_EXPLICIT((!std::is_convertible_v)) mapping(const _Mapping &__other) noexcept : __extents(__other.extents()) { MDSPAN_IMPL_PROPOSED_NAMESPACE::detail:: check_padded_layout_converting_constructor_mandates< extents_type, _Mapping>(detail::with_rank{}); MDSPAN_IMPL_PROPOSED_NAMESPACE::detail:: check_padded_layout_converting_constructor_preconditions< extents_type>(detail::with_rank{}, __other); } #endif MDSPAN_TEMPLATE_REQUIRES( class OtherExtents, /* requires */ ( _MDSPAN_TRAIT(std::is_constructible, extents_type, OtherExtents) ) ) MDSPAN_CONDITIONAL_EXPLICIT((extents_type::rank() > 0)) MDSPAN_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 mapping(layout_stride::mapping const& other) noexcept // NOLINT(google-explicit-constructor) :__extents(other.extents()) { /* * TODO: check precondition * other.required_span_size() is a representable value of type index_type */ detail::validate_strides(detail::with_rank{}, layout_right{}, __extents, other); } MDSPAN_INLINE_FUNCTION_DEFAULTED _MDSPAN_CONSTEXPR_14_DEFAULTED mapping& operator=(mapping const&) noexcept = default; MDSPAN_INLINE_FUNCTION constexpr const extents_type& extents() const noexcept { return __extents; } MDSPAN_INLINE_FUNCTION constexpr index_type required_span_size() const noexcept { index_type value = 1; for(rank_type r=0; r != extents_type::rank(); ++r) value*=__extents.extent(r); return value; } //-------------------------------------------------------------------------------- MDSPAN_TEMPLATE_REQUIRES( class ... Indices, /* requires */ ( (sizeof...(Indices) == extents_type::rank()) && (detail::are_valid_indices()) ) ) _MDSPAN_HOST_DEVICE constexpr index_type operator()(Indices... idxs) const noexcept { #if ! defined(NDEBUG) detail::check_all_indices(this->extents(), idxs...); #endif // ! NDEBUG return __compute_offset(__rank_count<0, extents_type::rank()>(), static_cast(idxs)...); } MDSPAN_INLINE_FUNCTION static constexpr bool is_always_unique() noexcept { return true; } MDSPAN_INLINE_FUNCTION static constexpr bool is_always_exhaustive() noexcept { return true; } MDSPAN_INLINE_FUNCTION static constexpr bool is_always_strided() noexcept { return true; } MDSPAN_INLINE_FUNCTION static constexpr bool is_unique() noexcept { return true; } MDSPAN_INLINE_FUNCTION static constexpr bool is_exhaustive() noexcept { return true; } MDSPAN_INLINE_FUNCTION static constexpr bool is_strided() noexcept { return true; } MDSPAN_INLINE_FUNCTION constexpr index_type stride(rank_type i) const noexcept #if MDSPAN_HAS_CXX_20 requires ( Extents::rank() > 0 ) #endif { index_type value = 1; for(rank_type r=extents_type::rank()-1; r>i; r--) value*=__extents.extent(r); return value; } MDSPAN_TEMPLATE_REQUIRES( class OtherExtents, /* requires */ ( Extents::rank() == OtherExtents::rank()) ) MDSPAN_INLINE_FUNCTION friend constexpr bool operator==(mapping const& lhs, mapping const& rhs) noexcept { return lhs.extents() == rhs.extents(); } // In C++ 20 the not equal exists if equal is found #if !(MDSPAN_HAS_CXX_20) MDSPAN_TEMPLATE_REQUIRES( class OtherExtents, /* requires */ (Extents::rank() == OtherExtents::rank()) ) MDSPAN_INLINE_FUNCTION friend constexpr bool operator!=(mapping const& lhs, mapping const& rhs) noexcept { return lhs.extents() != rhs.extents(); } #endif // Not really public, but currently needed to implement fully constexpr useable submdspan: template constexpr index_type __get_stride(MDSPAN_IMPL_STANDARD_NAMESPACE::extents,std::integer_sequence) const { return _MDSPAN_FOLD_TIMES_RIGHT((Idx>N? __extents.template __extent():1),1); } template constexpr index_type __stride() const noexcept { return __get_stride(__extents, std::make_index_sequence()); } private: _MDSPAN_NO_UNIQUE_ADDRESS extents_type __extents{}; // [mdspan.submdspan.mapping], submdspan mapping specialization template MDSPAN_INLINE_FUNCTION constexpr auto submdspan_mapping_impl( SliceSpecifiers... slices) const; template friend constexpr auto submdspan_mapping( const mapping& src, SliceSpecifiers... slices) { return src.submdspan_mapping_impl(slices...); } }; } // end namespace MDSPAN_IMPL_STANDARD_NAMESPACE //END_FILE_INCLUDE: /home/runner/work/mdspan/mdspan/include/experimental/__p0009_bits/layout_right.hpp namespace MDSPAN_IMPL_STANDARD_NAMESPACE { template < class ElementType, class Extents, class LayoutPolicy = layout_right, class AccessorPolicy = default_accessor > class mdspan { private: static_assert(detail::__is_extents_v, MDSPAN_IMPL_STANDARD_NAMESPACE_STRING "::mdspan's Extents template parameter must be a specialization of " MDSPAN_IMPL_STANDARD_NAMESPACE_STRING "::extents."); static_assert(std::is_same::value, MDSPAN_IMPL_STANDARD_NAMESPACE_STRING "::mdspan's ElementType template parameter must be the same as its AccessorPolicy::element_type."); // Workaround for non-deducibility of the index sequence template parameter if it's given at the top level template struct __deduction_workaround; template struct __deduction_workaround> { MDSPAN_FORCE_INLINE_FUNCTION static constexpr size_t __size(mdspan const& __self) noexcept { return _MDSPAN_FOLD_TIMES_RIGHT((__self.__mapping_ref().extents().extent(Idxs)), /* * ... * */ size_t(1)); } MDSPAN_FORCE_INLINE_FUNCTION static constexpr bool __empty(mdspan const& __self) noexcept { return (__self.rank()>0) && _MDSPAN_FOLD_OR((__self.__mapping_ref().extents().extent(Idxs)==index_type(0))); } template MDSPAN_FORCE_INLINE_FUNCTION static constexpr ReferenceType __callop(mdspan const& __self, const std::array& indices) noexcept { return __self.__accessor_ref().access(__self.__ptr_ref(), __self.__mapping_ref()(indices[Idxs]...)); } #ifdef __cpp_lib_span template MDSPAN_FORCE_INLINE_FUNCTION static constexpr ReferenceType __callop(mdspan const& __self, const std::span& indices) noexcept { return __self.__accessor_ref().access(__self.__ptr_ref(), __self.__mapping_ref()(indices[Idxs]...)); } #endif }; public: //-------------------------------------------------------------------------------- // Domain and codomain types using extents_type = Extents; using layout_type = LayoutPolicy; using accessor_type = AccessorPolicy; using mapping_type = typename layout_type::template mapping; using element_type = ElementType; using value_type = std::remove_cv_t; using index_type = typename extents_type::index_type; using size_type = typename extents_type::size_type; using rank_type = typename extents_type::rank_type; using data_handle_type = typename accessor_type::data_handle_type; using reference = typename accessor_type::reference; MDSPAN_INLINE_FUNCTION static constexpr size_t rank() noexcept { return extents_type::rank(); } MDSPAN_INLINE_FUNCTION static constexpr size_t rank_dynamic() noexcept { return extents_type::rank_dynamic(); } MDSPAN_INLINE_FUNCTION static constexpr size_t static_extent(size_t r) noexcept { return extents_type::static_extent(r); } MDSPAN_INLINE_FUNCTION constexpr index_type extent(size_t r) const noexcept { return __mapping_ref().extents().extent(r); }; private: // Can't use defaulted parameter in the __deduction_workaround template because of a bug in MSVC warning C4348. using __impl = __deduction_workaround>; using __map_acc_pair_t = detail::__compressed_pair; public: //-------------------------------------------------------------------------------- // [mdspan.basic.cons], mdspan constructors, assignment, and destructor #if !MDSPAN_HAS_CXX_20 MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr mdspan() = default; #else MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr mdspan() requires( // nvhpc has a bug where using just rank_dynamic() here doesn't work ... (extents_type::rank_dynamic() > 0) && _MDSPAN_TRAIT(std::is_default_constructible, data_handle_type) && _MDSPAN_TRAIT(std::is_default_constructible, mapping_type) && _MDSPAN_TRAIT(std::is_default_constructible, accessor_type) ) = default; #endif MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr mdspan(const mdspan&) = default; MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr mdspan(mdspan&&) = default; MDSPAN_TEMPLATE_REQUIRES( class... SizeTypes, /* requires */ ( ((sizeof...(SizeTypes) == rank()) || (sizeof...(SizeTypes) == rank_dynamic())) && (detail::are_valid_indices()) && _MDSPAN_TRAIT(std::is_constructible, mapping_type, extents_type) && _MDSPAN_TRAIT(std::is_default_constructible, accessor_type) ) ) MDSPAN_INLINE_FUNCTION explicit constexpr mdspan(data_handle_type p, SizeTypes... dynamic_extents) // TODO @proposal-bug shouldn't I be allowed to do `move(p)` here? : __members(std::move(p), __map_acc_pair_t(mapping_type(extents_type(static_cast(std::move(dynamic_extents))...)), accessor_type())) { } MDSPAN_TEMPLATE_REQUIRES( class SizeType, size_t N, /* requires */ ( _MDSPAN_TRAIT(std::is_convertible, const SizeType&, index_type) && _MDSPAN_TRAIT(std::is_nothrow_constructible, index_type, const SizeType&) && ((N == rank()) || (N == rank_dynamic())) && _MDSPAN_TRAIT(std::is_constructible, mapping_type, extents_type) && _MDSPAN_TRAIT(std::is_default_constructible, accessor_type) ) ) MDSPAN_CONDITIONAL_EXPLICIT(N != rank_dynamic()) MDSPAN_INLINE_FUNCTION constexpr mdspan(data_handle_type p, const std::array& dynamic_extents) : __members(std::move(p), __map_acc_pair_t(mapping_type(extents_type(dynamic_extents)), accessor_type())) { } #ifdef __cpp_lib_span MDSPAN_TEMPLATE_REQUIRES( class SizeType, size_t N, /* requires */ ( _MDSPAN_TRAIT(std::is_convertible, const SizeType&, index_type) && _MDSPAN_TRAIT(std::is_nothrow_constructible, index_type, const SizeType&) && ((N == rank()) || (N == rank_dynamic())) && _MDSPAN_TRAIT(std::is_constructible, mapping_type, extents_type) && _MDSPAN_TRAIT(std::is_default_constructible, accessor_type) ) ) MDSPAN_CONDITIONAL_EXPLICIT(N != rank_dynamic()) MDSPAN_INLINE_FUNCTION constexpr mdspan(data_handle_type p, std::span dynamic_extents) : __members(std::move(p), __map_acc_pair_t(mapping_type(extents_type(as_const(dynamic_extents))), accessor_type())) { } #endif MDSPAN_FUNCTION_REQUIRES( (MDSPAN_INLINE_FUNCTION constexpr), mdspan, (data_handle_type p, const extents_type& exts), , /* requires */ (_MDSPAN_TRAIT(std::is_default_constructible, accessor_type) && _MDSPAN_TRAIT(std::is_constructible, mapping_type, const extents_type&)) ) : __members(std::move(p), __map_acc_pair_t(mapping_type(exts), accessor_type())) { } MDSPAN_FUNCTION_REQUIRES( (MDSPAN_INLINE_FUNCTION constexpr), mdspan, (data_handle_type p, const mapping_type& m), , /* requires */ (_MDSPAN_TRAIT(std::is_default_constructible, accessor_type)) ) : __members(std::move(p), __map_acc_pair_t(m, accessor_type())) { } MDSPAN_INLINE_FUNCTION constexpr mdspan(data_handle_type p, const mapping_type& m, const accessor_type& a) : __members(std::move(p), __map_acc_pair_t(m, a)) { } MDSPAN_TEMPLATE_REQUIRES( class OtherElementType, class OtherExtents, class OtherLayoutPolicy, class OtherAccessor, /* requires */ ( _MDSPAN_TRAIT(std::is_constructible, mapping_type, const typename OtherLayoutPolicy::template mapping&) && _MDSPAN_TRAIT(std::is_constructible, accessor_type, const OtherAccessor&) ) ) MDSPAN_CONDITIONAL_EXPLICIT( !_MDSPAN_TRAIT(std::is_convertible, const typename OtherLayoutPolicy::template mapping&, mapping_type) || !_MDSPAN_TRAIT(std::is_convertible, const OtherAccessor&, accessor_type) ) MDSPAN_INLINE_FUNCTION constexpr mdspan(const mdspan& other) : __members(other.__ptr_ref(), __map_acc_pair_t(other.__mapping_ref(), other.__accessor_ref())) { static_assert(_MDSPAN_TRAIT(std::is_constructible, data_handle_type, typename OtherAccessor::data_handle_type),"Incompatible data_handle_type for mdspan construction"); static_assert(_MDSPAN_TRAIT(std::is_constructible, extents_type, OtherExtents),"Incompatible extents for mdspan construction"); /* * TODO: Check precondition * For each rank index r of extents_type, static_extent(r) == dynamic_extent || static_extent(r) == other.extent(r) is true. */ } /* Might need this on NVIDIA? MDSPAN_INLINE_FUNCTION_DEFAULTED ~mdspan() = default; */ MDSPAN_INLINE_FUNCTION_DEFAULTED _MDSPAN_CONSTEXPR_14_DEFAULTED mdspan& operator=(const mdspan&) = default; MDSPAN_INLINE_FUNCTION_DEFAULTED _MDSPAN_CONSTEXPR_14_DEFAULTED mdspan& operator=(mdspan&&) = default; //-------------------------------------------------------------------------------- // [mdspan.basic.mapping], mdspan mapping domain multidimensional index to access codomain element #if MDSPAN_USE_BRACKET_OPERATOR MDSPAN_TEMPLATE_REQUIRES( class... SizeTypes, /* requires */ ( _MDSPAN_FOLD_AND(_MDSPAN_TRAIT(std::is_convertible, SizeTypes, index_type) /* && ... */) && _MDSPAN_FOLD_AND(_MDSPAN_TRAIT(std::is_nothrow_constructible, index_type, SizeTypes) /* && ... */) && (rank() == sizeof...(SizeTypes)) ) ) MDSPAN_FORCE_INLINE_FUNCTION constexpr reference operator[](SizeTypes... indices) const { return __accessor_ref().access(__ptr_ref(), __mapping_ref()(static_cast(std::move(indices))...)); } #endif MDSPAN_TEMPLATE_REQUIRES( class SizeType, /* requires */ ( _MDSPAN_TRAIT(std::is_convertible, const SizeType&, index_type) && _MDSPAN_TRAIT(std::is_nothrow_constructible, index_type, const SizeType&) ) ) MDSPAN_FORCE_INLINE_FUNCTION constexpr reference operator[](const std::array< SizeType, rank()>& indices) const { return __impl::template __callop(*this, indices); } #ifdef __cpp_lib_span MDSPAN_TEMPLATE_REQUIRES( class SizeType, /* requires */ ( _MDSPAN_TRAIT(std::is_convertible, const SizeType&, index_type) && _MDSPAN_TRAIT(std::is_nothrow_constructible, index_type, const SizeType&) ) ) MDSPAN_FORCE_INLINE_FUNCTION constexpr reference operator[](std::span indices) const { return __impl::template __callop(*this, indices); } #endif // __cpp_lib_span #if !MDSPAN_USE_BRACKET_OPERATOR MDSPAN_TEMPLATE_REQUIRES( class Index, /* requires */ ( _MDSPAN_TRAIT(std::is_convertible, Index, index_type) && _MDSPAN_TRAIT(std::is_nothrow_constructible, index_type, Index) && extents_type::rank() == 1 ) ) MDSPAN_FORCE_INLINE_FUNCTION constexpr reference operator[](Index idx) const { return __accessor_ref().access(__ptr_ref(), __mapping_ref()(static_cast(std::move(idx)))); } #endif #if MDSPAN_USE_PAREN_OPERATOR MDSPAN_TEMPLATE_REQUIRES( class... SizeTypes, /* requires */ ( extents_type::rank() == sizeof...(SizeTypes) && (detail::are_valid_indices()) ) ) MDSPAN_FORCE_INLINE_FUNCTION constexpr reference operator()(SizeTypes... indices) const { return __accessor_ref().access(__ptr_ref(), __mapping_ref()(static_cast(std::move(indices))...)); } MDSPAN_TEMPLATE_REQUIRES( class SizeType, /* requires */ ( _MDSPAN_TRAIT(std::is_convertible, const SizeType&, index_type) && _MDSPAN_TRAIT(std::is_nothrow_constructible, index_type, const SizeType&) ) ) MDSPAN_FORCE_INLINE_FUNCTION constexpr reference operator()(const std::array& indices) const { return __impl::template __callop(*this, indices); } #ifdef __cpp_lib_span MDSPAN_TEMPLATE_REQUIRES( class SizeType, /* requires */ ( _MDSPAN_TRAIT(std::is_convertible, const SizeType&, index_type) && _MDSPAN_TRAIT(std::is_nothrow_constructible, index_type, const SizeType&) ) ) MDSPAN_FORCE_INLINE_FUNCTION constexpr reference operator()(std::span indices) const { return __impl::template __callop(*this, indices); } #endif // __cpp_lib_span #endif // MDSPAN_USE_PAREN_OPERATOR MDSPAN_INLINE_FUNCTION constexpr size_type size() const noexcept { return static_cast(__impl::__size(*this)); }; MDSPAN_INLINE_FUNCTION constexpr bool empty() const noexcept { return __impl::__empty(*this); }; MDSPAN_INLINE_FUNCTION friend constexpr void swap(mdspan& x, mdspan& y) noexcept { // can't call the std::swap inside on HIP #if !defined(_MDSPAN_HAS_HIP) && !defined(_MDSPAN_HAS_CUDA) using std::swap; swap(x.__ptr_ref(), y.__ptr_ref()); swap(x.__mapping_ref(), y.__mapping_ref()); swap(x.__accessor_ref(), y.__accessor_ref()); #else mdspan tmp = y; y = x; x = tmp; #endif } //-------------------------------------------------------------------------------- // [mdspan.basic.domobs], mdspan observers of the domain multidimensional index space MDSPAN_INLINE_FUNCTION constexpr const extents_type& extents() const noexcept { return __mapping_ref().extents(); }; MDSPAN_INLINE_FUNCTION constexpr const data_handle_type& data_handle() const noexcept { return __ptr_ref(); }; MDSPAN_INLINE_FUNCTION constexpr const mapping_type& mapping() const noexcept { return __mapping_ref(); }; MDSPAN_INLINE_FUNCTION constexpr const accessor_type& accessor() const noexcept { return __accessor_ref(); }; //-------------------------------------------------------------------------------- // [mdspan.basic.obs], mdspan observers of the mapping MDSPAN_INLINE_FUNCTION static constexpr bool is_always_unique() { return mapping_type::is_always_unique(); }; MDSPAN_INLINE_FUNCTION static constexpr bool is_always_exhaustive() { return mapping_type::is_always_exhaustive(); }; MDSPAN_INLINE_FUNCTION static constexpr bool is_always_strided() { return mapping_type::is_always_strided(); }; MDSPAN_INLINE_FUNCTION constexpr bool is_unique() const { return __mapping_ref().is_unique(); }; MDSPAN_INLINE_FUNCTION constexpr bool is_exhaustive() const { return __mapping_ref().is_exhaustive(); }; MDSPAN_INLINE_FUNCTION constexpr bool is_strided() const { return __mapping_ref().is_strided(); }; MDSPAN_INLINE_FUNCTION constexpr index_type stride(size_t r) const { return __mapping_ref().stride(r); }; private: detail::__compressed_pair __members{}; MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 data_handle_type& __ptr_ref() noexcept { return __members.__first(); } MDSPAN_FORCE_INLINE_FUNCTION constexpr data_handle_type const& __ptr_ref() const noexcept { return __members.__first(); } MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 mapping_type& __mapping_ref() noexcept { return __members.__second().__first(); } MDSPAN_FORCE_INLINE_FUNCTION constexpr mapping_type const& __mapping_ref() const noexcept { return __members.__second().__first(); } MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 accessor_type& __accessor_ref() noexcept { return __members.__second().__second(); } MDSPAN_FORCE_INLINE_FUNCTION constexpr accessor_type const& __accessor_ref() const noexcept { return __members.__second().__second(); } template friend class mdspan; }; #if defined(_MDSPAN_USE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION) MDSPAN_TEMPLATE_REQUIRES( class ElementType, class... SizeTypes, /* requires */ _MDSPAN_FOLD_AND(_MDSPAN_TRAIT(std::is_convertible, SizeTypes, size_t) /* && ... */) && (sizeof...(SizeTypes) > 0) ) MDSPAN_DEDUCTION_GUIDE explicit mdspan(ElementType*, SizeTypes...) -> mdspan>; MDSPAN_TEMPLATE_REQUIRES( class Pointer, (_MDSPAN_TRAIT(std::is_pointer, std::remove_reference_t)) ) MDSPAN_DEDUCTION_GUIDE mdspan(Pointer&&) -> mdspan>, extents>; MDSPAN_TEMPLATE_REQUIRES( class CArray, (_MDSPAN_TRAIT(std::is_array, CArray) && (std::rank_v == 1)) ) MDSPAN_DEDUCTION_GUIDE mdspan(CArray&) -> mdspan, extents>>; template MDSPAN_DEDUCTION_GUIDE mdspan(ElementType*, const ::std::array&) -> mdspan>; #ifdef __cpp_lib_span template MDSPAN_DEDUCTION_GUIDE mdspan(ElementType*, ::std::span) -> mdspan>; #endif // This one is necessary because all the constructors take `data_handle_type`s, not // `ElementType*`s, and `data_handle_type` is taken from `accessor_type::data_handle_type`, which // seems to throw off automatic deduction guides. template MDSPAN_DEDUCTION_GUIDE mdspan(ElementType*, const extents&) -> mdspan>; template MDSPAN_DEDUCTION_GUIDE mdspan(ElementType*, const MappingType&) -> mdspan; template MDSPAN_DEDUCTION_GUIDE mdspan(const typename AccessorType::data_handle_type, const MappingType&, const AccessorType&) -> mdspan; #endif } // end namespace MDSPAN_IMPL_STANDARD_NAMESPACE //END_FILE_INCLUDE: /home/runner/work/mdspan/mdspan/include/experimental/__p0009_bits/mdspan.hpp //BEGIN_FILE_INCLUDE: /home/runner/work/mdspan/mdspan/include/experimental/__p0009_bits/layout_left.hpp //@HEADER // ************************************************************************ // // Kokkos v. 4.0 // Copyright (2022) National Technology & Engineering // Solutions of Sandia, LLC (NTESS). // // Under the terms of Contract DE-NA0003525 with NTESS, // the U.S. Government retains certain rights in this software. // // Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions. // See https://kokkos.org/LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //@HEADER #if MDSPAN_HAS_CXX_17 #endif #include namespace MDSPAN_IMPL_STANDARD_NAMESPACE { //============================================================================== template class layout_left::mapping { public: using extents_type = Extents; using index_type = typename extents_type::index_type; using size_type = typename extents_type::size_type; using rank_type = typename extents_type::rank_type; using layout_type = layout_left; private: static_assert(detail::__is_extents_v, MDSPAN_IMPL_STANDARD_NAMESPACE_STRING "::layout_left::mapping must be instantiated with a specialization of " MDSPAN_IMPL_STANDARD_NAMESPACE_STRING "::extents."); template friend class mapping; // i0+(i1 + E(1)*(i2 + E(2)*i3)) template struct __rank_count {}; template _MDSPAN_HOST_DEVICE constexpr index_type __compute_offset( __rank_count, const I& i, Indices... idx) const { return __compute_offset(__rank_count(), idx...) * __extents.extent(r) + i; } template _MDSPAN_HOST_DEVICE constexpr index_type __compute_offset( __rank_count, const I& i) const { return i; } _MDSPAN_HOST_DEVICE constexpr index_type __compute_offset(__rank_count<0,0>) const { return 0; } public: //-------------------------------------------------------------------------------- MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr mapping() noexcept = default; MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr mapping(mapping const&) noexcept = default; _MDSPAN_HOST_DEVICE constexpr mapping(extents_type const& __exts) noexcept :__extents(__exts) { } MDSPAN_TEMPLATE_REQUIRES( class OtherExtents, /* requires */ ( _MDSPAN_TRAIT(std::is_constructible, extents_type, OtherExtents) ) ) MDSPAN_CONDITIONAL_EXPLICIT((!std::is_convertible::value)) // needs two () due to comma MDSPAN_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 mapping(mapping const& other) noexcept // NOLINT(google-explicit-constructor) :__extents(other.extents()) { /* * TODO: check precondition * other.required_span_size() is a representable value of type index_type */ } MDSPAN_TEMPLATE_REQUIRES( class OtherExtents, /* requires */ ( _MDSPAN_TRAIT(std::is_constructible, extents_type, OtherExtents) && (extents_type::rank() <= 1) ) ) MDSPAN_CONDITIONAL_EXPLICIT((!std::is_convertible::value)) // needs two () due to comma MDSPAN_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 mapping(layout_right::mapping const& other) noexcept // NOLINT(google-explicit-constructor) :__extents(other.extents()) { /* * TODO: check precondition * other.required_span_size() is a representable value of type index_type */ } #if MDSPAN_HAS_CXX_17 /** * Converting constructor from `layout_left_padded::mapping`. * * This overload participates in overload resolution only if _Mapping is a layout_left_padded mapping and * extents_type is constructible from _Mapping::extents_type. * * \note There is currently a difference from p2642r2, where this function is specified as taking * `layout_left_padded< padding_value >::mapping< Extents>`. However, this makes `padding_value` non-deducible. */ MDSPAN_TEMPLATE_REQUIRES( class _Mapping, /* requires */ ( MDSPAN_IMPL_PROPOSED_NAMESPACE::detail::is_layout_left_padded_mapping<_Mapping>::value && std::is_constructible_v ) ) MDSPAN_CONDITIONAL_EXPLICIT((!std::is_convertible_v)) mapping(const _Mapping& __other) noexcept : __extents(__other.extents()) { MDSPAN_IMPL_PROPOSED_NAMESPACE::detail:: check_padded_layout_converting_constructor_mandates< extents_type, _Mapping>(detail::with_rank{}); MDSPAN_IMPL_PROPOSED_NAMESPACE::detail:: check_padded_layout_converting_constructor_preconditions< extents_type>(detail::with_rank{}, __other); } #endif MDSPAN_TEMPLATE_REQUIRES( class OtherExtents, /* requires */ ( _MDSPAN_TRAIT(std::is_constructible, extents_type, OtherExtents) ) ) MDSPAN_CONDITIONAL_EXPLICIT((extents_type::rank() > 0)) MDSPAN_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 mapping(layout_stride::mapping const& other) noexcept // NOLINT(google-explicit-constructor) :__extents(other.extents()) { /* * TODO: check precondition * other.required_span_size() is a representable value of type index_type */ detail::validate_strides(detail::with_rank{}, layout_left{}, __extents, other); } MDSPAN_INLINE_FUNCTION_DEFAULTED _MDSPAN_CONSTEXPR_14_DEFAULTED mapping& operator=(mapping const&) noexcept = default; MDSPAN_INLINE_FUNCTION constexpr const extents_type& extents() const noexcept { return __extents; } MDSPAN_INLINE_FUNCTION constexpr index_type required_span_size() const noexcept { index_type value = 1; for(rank_type r=0; r()) ) ) _MDSPAN_HOST_DEVICE constexpr index_type operator()(Indices... idxs) const noexcept { #if ! defined(NDEBUG) detail::check_all_indices(this->extents(), idxs...); #endif // ! NDEBUG return __compute_offset(__rank_count<0, extents_type::rank()>(), static_cast(idxs)...); } MDSPAN_INLINE_FUNCTION static constexpr bool is_always_unique() noexcept { return true; } MDSPAN_INLINE_FUNCTION static constexpr bool is_always_exhaustive() noexcept { return true; } MDSPAN_INLINE_FUNCTION static constexpr bool is_always_strided() noexcept { return true; } MDSPAN_INLINE_FUNCTION static constexpr bool is_unique() noexcept { return true; } MDSPAN_INLINE_FUNCTION static constexpr bool is_exhaustive() noexcept { return true; } MDSPAN_INLINE_FUNCTION static constexpr bool is_strided() noexcept { return true; } MDSPAN_INLINE_FUNCTION constexpr index_type stride(rank_type i) const noexcept #if MDSPAN_HAS_CXX_20 requires ( Extents::rank() > 0 ) #endif { index_type value = 1; for(rank_type r=0; r const& rhs) noexcept { return lhs.extents() == rhs.extents(); } // In C++ 20 the not equal exists if equal is found #if !(MDSPAN_HAS_CXX_20) MDSPAN_TEMPLATE_REQUIRES( class OtherExtents, /* requires */ ( Extents::rank() == OtherExtents::rank()) ) MDSPAN_INLINE_FUNCTION friend constexpr bool operator!=(mapping const& lhs, mapping const& rhs) noexcept { return lhs.extents() != rhs.extents(); } #endif // Not really public, but currently needed to implement fully constexpr useable submdspan: template constexpr index_type __get_stride(MDSPAN_IMPL_STANDARD_NAMESPACE::extents,std::integer_sequence) const { return _MDSPAN_FOLD_TIMES_RIGHT((Idx():1),1); } template constexpr index_type __stride() const noexcept { return __get_stride(__extents, std::make_index_sequence()); } private: _MDSPAN_NO_UNIQUE_ADDRESS extents_type __extents{}; // [mdspan.submdspan.mapping], submdspan mapping specialization template MDSPAN_INLINE_FUNCTION constexpr auto submdspan_mapping_impl( SliceSpecifiers... slices) const; template friend constexpr auto submdspan_mapping( const mapping& src, SliceSpecifiers... slices) { return src.submdspan_mapping_impl(slices...); } }; } // end namespace MDSPAN_IMPL_STANDARD_NAMESPACE //END_FILE_INCLUDE: /home/runner/work/mdspan/mdspan/include/experimental/__p0009_bits/layout_left.hpp #if MDSPAN_HAS_CXX_17 //BEGIN_FILE_INCLUDE: /home/runner/work/mdspan/mdspan/include/experimental/__p2642_bits/layout_padded.hpp //@HEADER // ************************************************************************ // // Kokkos v. 4.0 // Copyright (2022) National Technology & Engineering // Solutions of Sandia, LLC (NTESS). // // Under the terms of Contract DE-NA0003525 with NTESS, // the U.S. Government retains certain rights in this software. // // Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions. // // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //@HEADER #include namespace MDSPAN_IMPL_STANDARD_NAMESPACE { namespace MDSPAN_IMPL_PROPOSED_NAMESPACE { namespace detail { template MDSPAN_INLINE_FUNCTION constexpr _T find_next_multiple(_T alignment, _T offset) { if ( alignment == 0 ) { return _T(0); } else { return ( ( offset + alignment - 1 ) / alignment) * alignment; } } template MDSPAN_INLINE_FUNCTION constexpr size_t get_actual_static_padding_value() { constexpr auto rank = _ExtentsType::rank(); if constexpr (rank <= typename _ExtentsType::rank_type(1)) { return 0; } else if constexpr (_PaddingValue != dynamic_extent && _ExtentsType::static_extent(_ExtentToPadIdx) != dynamic_extent) { static_assert( (_PaddingValue != 0) || (_ExtentsType::static_extent(_ExtentToPadIdx) == 0), "padding stride can be 0 only if " "extents_type::static_extent(extent-to-pad) is 0 or dynamic_extent"); return find_next_multiple(_PaddingValue, _ExtentsType::static_extent(_ExtentToPadIdx)); } else { return dynamic_extent; } // Missing return statement warning from NVCC and ICC #if defined(__NVCC__) || defined(__INTEL_COMPILER) return 0; #endif } template struct static_array_type_for_padded_extent { static constexpr size_t padding_value = _PaddingValue; using index_type = typename _Extents::index_type; using extents_type = _Extents; using type = ::MDSPAN_IMPL_STANDARD_NAMESPACE::detail::maybe_static_array< index_type, size_t, dynamic_extent, ::MDSPAN_IMPL_STANDARD_NAMESPACE::MDSPAN_IMPL_PROPOSED_NAMESPACE::detail::get_actual_static_padding_value()>; }; template struct static_array_type_for_padded_extent<_PaddingValue, _Extents, _ExtentToPadIdx, Rank, std::enable_if_t> { using index_type = typename _Extents::index_type; using extents_type = _Extents; using type = ::MDSPAN_IMPL_STANDARD_NAMESPACE::detail::maybe_static_array< index_type, size_t, dynamic_extent, 0>; }; template struct padded_extent { static constexpr size_t padding_value = _PaddingValue; using index_type = typename _Extents::index_type; using extents_type = _Extents; using static_array_type = typename static_array_type_for_padded_extent< padding_value, _Extents, _ExtentToPadIdx, _Extents::rank()>::type; static constexpr auto static_value() { return static_array_type::static_value(0); } MDSPAN_INLINE_FUNCTION static constexpr static_array_type init_padding(const _Extents &exts) { if constexpr ((_Extents::rank() > 1) && (padding_value == dynamic_extent)) { return {exts.extent(_ExtentToPadIdx)}; } else { return init_padding(exts, padding_value); } // Missing return statement warning from NVCC and ICC #if defined(__NVCC__) || defined(__INTEL_COMPILER) return {}; #endif } MDSPAN_INLINE_FUNCTION static constexpr static_array_type init_padding([[maybe_unused]] const _Extents &exts, [[maybe_unused]] index_type pv) { if constexpr (_Extents::rank() > 1) { return {find_next_multiple(pv, exts.extent(_ExtentToPadIdx))}; } else { return {}; } // Missing return statement warning from NVCC and ICC #if defined(__NVCC__) || defined(__INTEL_COMPILER) return {}; #endif } template MDSPAN_INLINE_FUNCTION static constexpr static_array_type init_padding([[maybe_unused]] const _Mapping &other_mapping, std::integral_constant) { if constexpr (_Extents::rank() > 1) { return {other_mapping.stride(_PaddingStrideIdx)}; } else { return {}; } // Missing return statement warning from NVCC and ICC #if defined(__NVCC__) || defined(__INTEL_COMPILER) return {}; #endif } }; } // namespace detail template template class layout_left_padded::mapping { public: static constexpr size_t padding_value = PaddingValue; using extents_type = Extents; using index_type = typename extents_type::index_type; using size_type = typename extents_type::size_type; using rank_type = typename extents_type::rank_type; using layout_type = layout_left_padded; #ifndef MDSPAN_INTERNAL_TEST private: #endif // MDSPAN_INTERNAL_TEST static constexpr rank_type padded_stride_idx = detail::layout_padded_constants::padded_stride_idx; static constexpr rank_type extent_to_pad_idx = detail::layout_padded_constants::extent_to_pad_idx; static_assert((padding_value != 0) || (extents_type::static_extent(extent_to_pad_idx) == 0) || (extents_type::static_extent(extent_to_pad_idx) == dynamic_extent), "out of bounds access for rank 0"); using padded_stride_type = detail::padded_extent< padding_value, extents_type, extent_to_pad_idx >; static constexpr size_t static_padding_stride = padded_stride_type::static_value(); typename padded_stride_type::static_array_type padded_stride = {}; extents_type exts = {}; MDSPAN_INLINE_FUNCTION constexpr index_type compute_offset(std::index_sequence<>) const { return 0; } template MDSPAN_INLINE_FUNCTION constexpr index_type compute_offset(std::index_sequence, IndexOffset index_offset) const { return index_offset; } template MDSPAN_INLINE_FUNCTION constexpr index_type compute_offset(std::index_sequence, IndexOffsets... index_offsets) const { index_type indices[] = {static_cast(index_offsets)...}; // self-recursive fold trick from // https://github.com/llvm/llvm-project/blob/96e1914aa2e6d8966acbfbe2f4d184201f1aa318/libcxx/include/mdspan/layout_left.h#L144 index_type res = 0; ((res = indices[extents_type::rank() - 1 - Ranks] + ((extents_type::rank() - 1 - Ranks) == extent_to_pad_idx ? padded_stride.value(0) : exts.extent(extents_type::rank() - 1 - Ranks)) * res), ...); return res; } public: #if !MDSPAN_HAS_CXX_20 MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr mapping() : mapping(extents_type{}) {} #else MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr mapping() requires(static_padding_stride != dynamic_extent) = default; MDSPAN_INLINE_FUNCTION constexpr mapping() requires(static_padding_stride == dynamic_extent) : mapping(extents_type{}) {} #endif MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr mapping(const mapping&) noexcept = default; MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr mapping& operator=(const mapping&) noexcept = default; /** * Initializes the mapping with the given extents. * * \param ext the given extents */ MDSPAN_INLINE_FUNCTION constexpr mapping(const extents_type& ext) : padded_stride(padded_stride_type::init_padding(ext)), exts(ext) {} /** * Initializes the mapping with the given extents and the specified padding value. * * This overload participates in overload resolution only if `is_convertible_v` * is `true` and `is_nothrow_constructible_v` is `true` * * \param ext the given extents * \param padding_value the padding value */ MDSPAN_TEMPLATE_REQUIRES( class _Size, /* requires */ ( std::is_convertible_v<_Size, index_type> && std::is_nothrow_constructible_v ) ) MDSPAN_INLINE_FUNCTION constexpr mapping(const extents_type &ext, _Size dynamic_padding_value) : padded_stride(padded_stride_type::init_padding(ext, dynamic_padding_value)), exts(ext) { assert((padding_value == dynamic_extent) || (static_cast(padding_value) == static_cast(dynamic_padding_value))); } /** * Converting constructor from `layout_left::mapping`. * * This overload participates in overload resolution only if * `is_constructible_v` is true. If * `OtherExtents::rank() > 1` then one of `padding_value`, `static_extent(0)`, * or `OtherExtents::static_extent(0)` must be `dynamic_extent`; otherwise, * `OtherExtents::static_extent(0)` must be equal to the least multiple of * `padding_value` greater than or equal to `extents_type::static_extent(0)` */ MDSPAN_TEMPLATE_REQUIRES( class _OtherExtents, /* requires */ (std::is_constructible_v)) MDSPAN_CONDITIONAL_EXPLICIT( (!std::is_convertible_v<_OtherExtents, extents_type>)) MDSPAN_INLINE_FUNCTION constexpr mapping(const layout_left::mapping<_OtherExtents> &other_mapping) : padded_stride(padded_stride_type::init_padding( other_mapping, std::integral_constant{})), exts(other_mapping.extents()) { static_assert( (_OtherExtents::rank() > 1) || (static_padding_stride != dynamic_extent) || (_OtherExtents::static_extent(extent_to_pad_idx) != dynamic_extent) || (static_padding_stride == _OtherExtents::static_extent(extent_to_pad_idx))); } /** * Converting constructor from `layout_stride::mapping`. * * This overload participates in overload resolution only if * `is_constructible_v` is true */ MDSPAN_TEMPLATE_REQUIRES( class _OtherExtents, /* requires */ (std::is_constructible_v)) MDSPAN_CONDITIONAL_EXPLICIT((extents_type::rank() > 0)) MDSPAN_INLINE_FUNCTION constexpr mapping(const layout_stride::mapping<_OtherExtents> &other_mapping) : padded_stride(padded_stride_type::init_padding( other_mapping, std::integral_constant{})), exts(other_mapping.extents()) {} /** * Converting constructor from `layout_left_padded::mapping`. * * This overload participates in overload resolution only if * `is_constructible_v` is true. Either * `padding_value` or `OtherPaddingStride` must be `std::dynamic_extent`, or * `padding_value == OtherPaddingStride`. */ MDSPAN_TEMPLATE_REQUIRES( class _Mapping, /* requires */ (detail::is_layout_left_padded_mapping<_Mapping>::value &&std::is_constructible_v< extents_type, typename _Mapping::extents_type>)) MDSPAN_CONDITIONAL_EXPLICIT((extents_type::rank() > 1 && (padding_value == dynamic_extent || _Mapping::padding_value == dynamic_extent))) MDSPAN_INLINE_FUNCTION constexpr mapping(const _Mapping &other_mapping) : padded_stride(padded_stride_type::init_padding( other_mapping, std::integral_constant{})), exts(other_mapping.extents()) { static_assert(padding_value == dynamic_extent || _Mapping::padding_value == dynamic_extent || padding_value == _Mapping::padding_value); } /** * Converting constructor from `layout_right_padded::mapping`. * * This overload participates in overload resolution only if * `extents_type::rank()` is 0 or 1 and `is_constructible_v` is `true`. */ MDSPAN_TEMPLATE_REQUIRES( class _Mapping, /* requires */ (detail::is_layout_right_padded_mapping<_Mapping>::value &&extents_type::rank() <= 1 && std::is_constructible_v)) MDSPAN_CONDITIONAL_EXPLICIT( (!std::is_convertible_v)) MDSPAN_INLINE_FUNCTION constexpr mapping(const _Mapping &other_mapping) noexcept : padded_stride(padded_stride_type::init_padding( other_mapping.extents(), other_mapping.extents().extent(extent_to_pad_idx))), exts(other_mapping.extents()) {} MDSPAN_INLINE_FUNCTION constexpr const extents_type & extents() const noexcept { return exts; } MDSPAN_INLINE_FUNCTION constexpr std::array strides() const noexcept { if constexpr (extents_type::rank() == 0) { return {}; } else if constexpr (extents_type::rank() == 1) { return {1}; } else { index_type value = 1; std::array s{}; s[extent_to_pad_idx] = value; value *= padded_stride.value(0); for (rank_type r = extent_to_pad_idx + 1; r < extents_type::rank() - 1; ++r) { s[r] = value; value *= exts.extent(r); } s[extents_type::rank() - 1] = value; return s; } } MDSPAN_INLINE_FUNCTION constexpr index_type required_span_size() const noexcept { if constexpr (extents_type::rank() == 0) { return 1; } else if constexpr (extents_type::rank() == 1) { return exts.extent(0); } else { index_type value = padded_stride.value(0); for (rank_type r = 1; r < extents_type::rank(); ++r) { value *= exts.extent(r); } return value; } } /** * Return the mapping given the provided indices per rank. * * This overload participates in overload resolution only if: * - `sizeof...(Indices) == extents_type::rank()`, * - `(is_convertible_v && ...) is true`, and * - (is_nothrow_constructible_v && ...) is true. */ MDSPAN_TEMPLATE_REQUIRES( class... _Indices, /* requires */ (sizeof...(_Indices) == extents_type::rank() && (::MDSPAN_IMPL_STANDARD_NAMESPACE::detail:: are_valid_indices()))) MDSPAN_INLINE_FUNCTION constexpr size_t operator()(_Indices... idxs) const noexcept { #if !defined(NDEBUG) ::MDSPAN_IMPL_STANDARD_NAMESPACE::detail::check_all_indices(this->extents(), idxs...); #endif // ! NDEBUG return compute_offset(std::index_sequence_for<_Indices...>{}, idxs...); } MDSPAN_INLINE_FUNCTION static constexpr bool is_always_unique() noexcept { return true; } MDSPAN_INLINE_FUNCTION static constexpr bool is_always_exhaustive() noexcept { return (extents_type::rank() <= rank_type(1)) || (extents_type::static_extent(extent_to_pad_idx) != dynamic_extent && extents_type::static_extent(extent_to_pad_idx) == padded_stride_type::static_value()); } MDSPAN_INLINE_FUNCTION static constexpr bool is_always_strided() noexcept { return true; } MDSPAN_INLINE_FUNCTION static constexpr bool is_unique() noexcept { return true; } MDSPAN_INLINE_FUNCTION constexpr bool is_exhaustive() const noexcept { return (extents_type::rank() < 2) || (exts.extent(extent_to_pad_idx) == padded_stride.value(0)); } MDSPAN_INLINE_FUNCTION static constexpr bool is_strided() noexcept { return true; } MDSPAN_INLINE_FUNCTION constexpr index_type stride(rank_type r) const noexcept { assert(r < extents_type::rank()); if (r == 0) return index_type(1); index_type value = padded_stride.value(0); for (rank_type k = 1; k < r; k++) value *= exts.extent(k); return value; } /** * Equality operator between `layout_left_padded`s * * This overload only participates in overload resolution if * `OtherExtents::rank() == extents_type::rank()`. * * \note There is currently a difference from p2642r2, where this function is * specified as taking `layout_left_padded< padding_value >::mapping< * Extents>`. However, this makes `padding_value` non-deducible. */ MDSPAN_TEMPLATE_REQUIRES( class _Mapping, /* requires */ (detail::is_layout_left_padded_mapping<_Mapping>::value && (_Mapping::extents_type::rank() == extents_type::rank()))) MDSPAN_INLINE_FUNCTION friend constexpr bool operator==(const mapping &left, const _Mapping &right) noexcept { // Workaround for some compilers not short-circuiting properly with // compile-time checks i.e. we can't access stride(_padding_stride_idx) of a // rank 0 mapping bool strides_equal = true; if constexpr (extents_type::rank() > rank_type(1)) { strides_equal = left.stride(padded_stride_idx) == right.stride(padded_stride_idx); } return (left.extents() == right.extents()) && strides_equal; } #if !MDSPAN_HAS_CXX_20 /** * Inequality operator between `layout_left_padded`s * * This overload only participates in overload resolution if * `OtherExtents::rank() == extents_type::rank()`. */ MDSPAN_TEMPLATE_REQUIRES( class _Mapping, /* requires */ (detail::is_layout_left_padded_mapping<_Mapping>::value && (_Mapping::extents_type::rank() == extents_type::rank()))) MDSPAN_INLINE_FUNCTION friend constexpr bool operator!=(const mapping &left, const _Mapping &right) noexcept { return !(left == right); } #endif // [mdspan.submdspan.mapping], submdspan mapping specialization template MDSPAN_INLINE_FUNCTION constexpr auto submdspan_mapping_impl( SliceSpecifiers... slices) const; template MDSPAN_INLINE_FUNCTION friend constexpr auto submdspan_mapping( const mapping& src, SliceSpecifiers... slices) { return src.submdspan_mapping_impl(slices...); } }; template template class layout_right_padded::mapping { public: static constexpr size_t padding_value = PaddingValue; using extents_type = Extents; using index_type = typename extents_type::index_type; using size_type = typename extents_type::size_type; using rank_type = typename extents_type::rank_type; using layout_type = layout_right_padded; #ifndef MDSPAN_INTERNAL_TEST private: #endif // MDSPAN_INTERNAL_TEST static constexpr rank_type padded_stride_idx = detail::layout_padded_constants::padded_stride_idx; static constexpr rank_type extent_to_pad_idx = detail::layout_padded_constants::extent_to_pad_idx; static_assert((padding_value != 0) || (extents_type::static_extent(extent_to_pad_idx) == 0) || (extents_type::static_extent(extent_to_pad_idx) == dynamic_extent), "if padding stride is 0, static_extent(extent-to-pad-rank) must also be 0 or dynamic_extent"); using padded_stride_type = detail::padded_extent< padding_value, extents_type, extent_to_pad_idx >; static constexpr size_t static_padding_stride = padded_stride_type::static_value(); typename padded_stride_type::static_array_type padded_stride = {}; extents_type exts = {}; MDSPAN_INLINE_FUNCTION constexpr index_type compute_offset(std::index_sequence<>) const { return 0; } template MDSPAN_INLINE_FUNCTION constexpr index_type compute_offset(std::index_sequence, IndexOffset index_offset) const { return index_offset; } template MDSPAN_INLINE_FUNCTION constexpr index_type compute_offset(std::index_sequence, IndexOffsets... index_offsets) const { // self-recursive fold trick from // https://github.com/llvm/llvm-project/blob/4d9771741d40cc9cfcccb6b033f43689d36b705a/libcxx/include/mdspan/layout_right.h#L141 index_type res = 0; ((res = static_cast(index_offsets) + (Ranks == extent_to_pad_idx ? padded_stride.value(0) : exts.extent(Ranks)) * res), ...); return res; } public: #if !MDSPAN_HAS_CXX_20 MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr mapping() : mapping(extents_type{}) {} #else MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr mapping() requires(static_padding_stride != dynamic_extent) = default; MDSPAN_INLINE_FUNCTION constexpr mapping() requires(static_padding_stride == dynamic_extent) : mapping(extents_type{}) {} #endif MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr mapping(const mapping&) noexcept = default; MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr mapping& operator=(const mapping&) noexcept = default; /** * Initializes the mapping with the given extents. * * \param ext the given extents */ MDSPAN_INLINE_FUNCTION constexpr mapping(const extents_type &ext) : padded_stride(padded_stride_type::init_padding(ext)), exts(ext) {} /** * Initializes the mapping with the given extents and the specified padding value. * * This overload participates in overload resolution only if `is_convertible_v` * is `true` and `is_nothrow_constructible_v` is `true` * * \param ext the given extents * \param padding_value the padding value */ MDSPAN_TEMPLATE_REQUIRES( class _Size, /* requires */ ( std::is_convertible_v<_Size, index_type> && std::is_nothrow_constructible_v ) ) MDSPAN_INLINE_FUNCTION constexpr mapping(const extents_type &ext, _Size dynamic_padding_value) : padded_stride(padded_stride_type::init_padding(ext, static_cast(dynamic_padding_value))), exts(ext) { assert((padding_value == dynamic_extent) || (static_cast(padding_value) == static_cast(dynamic_padding_value))); } /** * Converting constructor from `layout_right::mapping`. * * This overload participates in overload resolution only if `is_constructible_v` is true. * If `OtherExtents::rank() > 1` then one of `padding_value`, `static_extent(0)`, or `OtherExtents::static_extent(0)` must be `dynamic_extent`; * otherwise, `OtherExtents::static_extent(0)` must be equal to the least multiple of `padding_value` greater than or equal to `extents_type::static_extent(0)` */ MDSPAN_TEMPLATE_REQUIRES( class _OtherExtents, /* requires */ (std::is_constructible_v)) MDSPAN_CONDITIONAL_EXPLICIT( (!std::is_convertible_v<_OtherExtents, extents_type>)) MDSPAN_INLINE_FUNCTION constexpr mapping(const layout_right::mapping<_OtherExtents> &other_mapping) : padded_stride(padded_stride_type::init_padding( other_mapping, std::integral_constant{})), exts(other_mapping.extents()) { static_assert( (_OtherExtents::rank() > 1) || (padded_stride_type::static_value() != dynamic_extent) || (_OtherExtents::static_extent(extent_to_pad_idx) != dynamic_extent) || (padded_stride_type::static_value() == _OtherExtents::static_extent(extent_to_pad_idx))); } /** * Converting constructor from `layout_stride::mapping`. * * This overload participates in overload resolution only if * `is_constructible_v` is true */ MDSPAN_TEMPLATE_REQUIRES( class _OtherExtents, /* requires */ (std::is_constructible_v)) MDSPAN_CONDITIONAL_EXPLICIT((extents_type::rank() > 0)) MDSPAN_INLINE_FUNCTION constexpr mapping(const layout_stride::mapping<_OtherExtents> &other_mapping) : padded_stride(padded_stride_type::init_padding( other_mapping, std::integral_constant{})), exts(other_mapping.extents()) {} /** * Converting constructor from `layout_right_padded::mapping`. * * This overload participates in overload resolution only if * `is_constructible_v` is true. Either * `padding_value` or `OtherPaddingStride` must be `std::dynamic_extent`, or * `padding_value == OtherPaddingStride`. */ MDSPAN_TEMPLATE_REQUIRES( class _Mapping, /* requires */ (detail::is_layout_right_padded_mapping<_Mapping>::value &&std::is_constructible_v< extents_type, typename _Mapping::extents_type>)) MDSPAN_CONDITIONAL_EXPLICIT((extents_type::rank() > 1 && (padding_value == dynamic_extent || _Mapping::padding_value == dynamic_extent))) MDSPAN_INLINE_FUNCTION constexpr mapping(const _Mapping &other_mapping) : padded_stride(padded_stride_type::init_padding( other_mapping, std::integral_constant{})), exts(other_mapping.extents()) { static_assert(padding_value == dynamic_extent || _Mapping::padding_value == dynamic_extent || padding_value == _Mapping::padding_value); } /** * Converting constructor from `layout_left_padded::mapping`. * * This overload participates in overload resolution only if * `extents_type::rank()` is 0 or 1 and `is_constructible_v` is `true`. */ MDSPAN_TEMPLATE_REQUIRES( class _Mapping, /* requires */ (detail::is_layout_left_padded_mapping<_Mapping>::value &&extents_type::rank() <= 1 && std::is_constructible_v)) MDSPAN_CONDITIONAL_EXPLICIT( (!std::is_convertible_v)) MDSPAN_INLINE_FUNCTION constexpr mapping(const _Mapping &other_mapping) noexcept : padded_stride(padded_stride_type::init_padding( other_mapping.extents(), other_mapping.extents().extent(extent_to_pad_idx))), exts(other_mapping.extents()) {} MDSPAN_INLINE_FUNCTION constexpr const extents_type & extents() const noexcept { return exts; } MDSPAN_INLINE_FUNCTION constexpr std::array strides() const noexcept { if constexpr (extents_type::rank() == 0) { return {}; } else if constexpr (extents_type::rank() == 1) { return {1}; } else { index_type value = 1; std::array s{}; s[extent_to_pad_idx] = value; value *= padded_stride.value(0); for (rank_type r = extent_to_pad_idx - 1; r > 0; --r) { s[r] = value; value *= exts.extent(r); } s[0] = value; return s; } } MDSPAN_INLINE_FUNCTION constexpr index_type required_span_size() const noexcept { if constexpr (extents_type::rank() == 0) { return 1; } else if constexpr (extents_type::rank() == 1) { return exts.extent(0); } else { index_type value = 1; for (rank_type r = 0; r < extent_to_pad_idx; ++r) { value *= exts.extent(r); } return value * padded_stride.value(0); } } /** * Return the mapping given the provided indices per rank. * * This overload participates in overload resolution only if: * - `sizeof...(Indices) == extents_type::rank()`, * - `(is_convertible_v && ...) is true`, and * - (is_nothrow_constructible_v && ...) is true. */ MDSPAN_TEMPLATE_REQUIRES( class... _Indices, /* requires */ (sizeof...(_Indices) == extents_type::rank() && (::MDSPAN_IMPL_STANDARD_NAMESPACE::detail:: are_valid_indices()))) MDSPAN_INLINE_FUNCTION constexpr size_t operator()(_Indices... idxs) const noexcept { return compute_offset(std::index_sequence_for<_Indices...>{}, idxs...); } MDSPAN_INLINE_FUNCTION static constexpr bool is_always_unique() noexcept { return true; } MDSPAN_INLINE_FUNCTION static constexpr bool is_always_exhaustive() noexcept { return (extents_type::rank() <= rank_type(1)) || (extents_type::static_extent(extent_to_pad_idx) != dynamic_extent && extents_type::static_extent(extent_to_pad_idx) == padded_stride_type::static_value()); } MDSPAN_INLINE_FUNCTION static constexpr bool is_always_strided() noexcept { return true; } MDSPAN_INLINE_FUNCTION static constexpr bool is_unique() noexcept { return true; } MDSPAN_INLINE_FUNCTION constexpr bool is_exhaustive() const noexcept { return (extents_type::rank() < 2) || (exts.extent(extent_to_pad_idx) == padded_stride.value(0)); } MDSPAN_INLINE_FUNCTION static constexpr bool is_strided() noexcept { return true; } MDSPAN_INLINE_FUNCTION constexpr index_type stride(rank_type r) const noexcept { assert(r < extents_type::rank()); if (r == extents_type::rank() - 1) return index_type(1); index_type value = padded_stride.value(0); for (rank_type k = extents_type::rank() - 2; k > r; k--) value *= exts.extent(k); return value; } /** * Equality operator between `layout_right_padded`s * * This overload only participates in overload resolution if * `OtherExtents::rank() == extents_type::rank()`. * * \note There is currently a difference from p2642r2, where this function is * specified as taking `layout_right_padded< padding_value >::mapping< * Extents>`. However, this makes `padding_value` non-deducible. */ MDSPAN_TEMPLATE_REQUIRES( class _Mapping, /* requires */ (detail::is_layout_right_padded_mapping<_Mapping>::value && (_Mapping::extents_type::rank() == extents_type::rank()))) MDSPAN_INLINE_FUNCTION friend constexpr bool operator==(const mapping &left, const _Mapping &right) noexcept { // Workaround for some compilers not short-circuiting properly with // compile-time checks i.e. we can't access stride(_padding_stride_idx) of a // rank 0 mapping bool strides_equal = true; if constexpr (extents_type::rank() > rank_type(1)) { strides_equal = left.stride(padded_stride_idx) == right.stride(padded_stride_idx); } return (left.extents() == right.extents()) && strides_equal; } #if !MDSPAN_HAS_CXX_20 /** * Inequality operator between `layout_right_padded`s * * This overload only participates in overload resolution if * `OtherExtents::rank() == extents_type::rank()`. */ MDSPAN_TEMPLATE_REQUIRES( class _Mapping, /* requires */ (detail::is_layout_right_padded_mapping<_Mapping>::value && (_Mapping::extents_type::rank() == extents_type::rank()))) MDSPAN_INLINE_FUNCTION friend constexpr bool operator!=(const mapping &left, const _Mapping &right) noexcept { return !(left == right); } #endif // [mdspan.submdspan.mapping], submdspan mapping specialization template MDSPAN_INLINE_FUNCTION constexpr auto submdspan_mapping_impl( SliceSpecifiers... slices) const; template MDSPAN_INLINE_FUNCTION friend constexpr auto submdspan_mapping( const mapping& src, SliceSpecifiers... slices) { return src.submdspan_mapping_impl(slices...); } }; } } //END_FILE_INCLUDE: /home/runner/work/mdspan/mdspan/include/experimental/__p2642_bits/layout_padded.hpp //BEGIN_FILE_INCLUDE: /home/runner/work/mdspan/mdspan/include/experimental/__p2630_bits/submdspan.hpp //@HEADER // ************************************************************************ // // Kokkos v. 4.0 // Copyright (2022) National Technology & Engineering // Solutions of Sandia, LLC (NTESS). // // Under the terms of Contract DE-NA0003525 with NTESS, // the U.S. Government retains certain rights in this software. // // Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions. // See https://kokkos.org/LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //@HEADER //BEGIN_FILE_INCLUDE: /home/runner/work/mdspan/mdspan/include/experimental/__p2630_bits/submdspan_extents.hpp //@HEADER // ************************************************************************ // // Kokkos v. 4.0 // Copyright (2022) National Technology & Engineering // Solutions of Sandia, LLC (NTESS). // // Under the terms of Contract DE-NA0003525 with NTESS, // the U.S. Government retains certain rights in this software. // // Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions. // See https://kokkos.org/LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //@HEADER #include //BEGIN_FILE_INCLUDE: /home/runner/work/mdspan/mdspan/include/experimental/__p2630_bits/strided_slice.hpp //@HEADER // ************************************************************************ // // Kokkos v. 4.0 // Copyright (2022) National Technology & Engineering // Solutions of Sandia, LLC (NTESS). // // Under the terms of Contract DE-NA0003525 with NTESS, // the U.S. Government retains certain rights in this software. // // Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions. // See https://kokkos.org/LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //@HEADER #include namespace MDSPAN_IMPL_STANDARD_NAMESPACE { namespace { template struct __mdspan_is_integral_constant: std::false_type {}; template struct __mdspan_is_integral_constant>: std::true_type {}; } // Slice Specifier allowing for strides and compile time extent template struct strided_slice { using offset_type = OffsetType; using extent_type = ExtentType; using stride_type = StrideType; _MDSPAN_NO_UNIQUE_ADDRESS OffsetType offset{}; _MDSPAN_NO_UNIQUE_ADDRESS ExtentType extent{}; _MDSPAN_NO_UNIQUE_ADDRESS StrideType stride{}; static_assert(std::is_integral_v || __mdspan_is_integral_constant::value); static_assert(std::is_integral_v || __mdspan_is_integral_constant::value); static_assert(std::is_integral_v || __mdspan_is_integral_constant::value); }; } // MDSPAN_IMPL_STANDARD_NAMESPACE //END_FILE_INCLUDE: /home/runner/work/mdspan/mdspan/include/experimental/__p2630_bits/strided_slice.hpp namespace MDSPAN_IMPL_STANDARD_NAMESPACE { namespace detail { // Mapping from submapping ranks to srcmapping ranks // InvMapRank is an index_sequence, which we build recursively // to contain the mapped indices. // end of recursion specialization containing the final index_sequence template MDSPAN_INLINE_FUNCTION constexpr auto inv_map_rank(std::integral_constant, std::index_sequence) { return std::index_sequence(); } // specialization reducing rank by one (i.e., integral slice specifier) template MDSPAN_INLINE_FUNCTION constexpr auto inv_map_rank(std::integral_constant, std::index_sequence, Slice, SliceSpecifiers... slices) { using next_idx_seq_t = std::conditional_t, std::index_sequence, std::index_sequence>; return inv_map_rank(std::integral_constant(), next_idx_seq_t(), slices...); } // Helper for identifying strided_slice template struct is_strided_slice : std::false_type {}; template struct is_strided_slice< strided_slice> : std::true_type {}; // first_of(slice): getting begin of slice specifier range MDSPAN_TEMPLATE_REQUIRES( class Integral, /* requires */(std::is_convertible_v) ) MDSPAN_INLINE_FUNCTION constexpr Integral first_of(const Integral &i) { return i; } MDSPAN_INLINE_FUNCTION constexpr std::integral_constant first_of(const ::MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent_t &) { return std::integral_constant(); } MDSPAN_TEMPLATE_REQUIRES( class Slice, /* requires */(std::is_convertible_v>) ) MDSPAN_INLINE_FUNCTION constexpr auto first_of(const Slice &i) { return std::get<0>(i); } template MDSPAN_INLINE_FUNCTION constexpr OffsetType first_of(const strided_slice &r) { return r.offset; } // last_of(slice): getting end of slice specifier range // We need however not just the slice but also the extents // of the original view and which rank from the extents. // This is needed in the case of slice being full_extent_t. MDSPAN_TEMPLATE_REQUIRES( size_t k, class Extents, class Integral, /* requires */(std::is_convertible_v) ) MDSPAN_INLINE_FUNCTION constexpr Integral last_of(std::integral_constant, const Extents &, const Integral &i) { return i; } MDSPAN_TEMPLATE_REQUIRES( size_t k, class Extents, class Slice, /* requires */(std::is_convertible_v>) ) MDSPAN_INLINE_FUNCTION constexpr auto last_of(std::integral_constant, const Extents &, const Slice &i) { return std::get<1>(i); } // Suppress spurious warning with NVCC about no return statement. // This is a known issue in NVCC and NVC++ // Depending on the CUDA and GCC version we need both the builtin // and the diagnostic push. I tried really hard to find something shorter // but no luck ... #if defined __NVCC__ #ifdef __NVCC_DIAG_PRAGMA_SUPPORT__ #pragma nv_diagnostic push #pragma nv_diag_suppress = implicit_return_from_non_void_function #else #ifdef __CUDA_ARCH__ #pragma diagnostic push #pragma diag_suppress implicit_return_from_non_void_function #endif #endif #elif defined __NVCOMPILER #pragma diagnostic push #pragma diag_suppress = implicit_return_from_non_void_function #endif template MDSPAN_INLINE_FUNCTION constexpr auto last_of(std::integral_constant, const Extents &ext, ::MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent_t) { if constexpr (Extents::static_extent(k) == dynamic_extent) { return ext.extent(k); } else { return std::integral_constant(); } #if defined(__NVCC__) && !defined(__CUDA_ARCH__) && defined(__GNUC__) // Even with CUDA_ARCH protection this thing warns about calling host function __builtin_unreachable(); #endif } #if defined __NVCC__ #ifdef __NVCC_DIAG_PRAGMA_SUPPORT__ #pragma nv_diagnostic pop #else #ifdef __CUDA_ARCH__ #pragma diagnostic pop #endif #endif #elif defined __NVCOMPILER #pragma diagnostic pop #endif template MDSPAN_INLINE_FUNCTION constexpr OffsetType last_of(std::integral_constant, const Extents &, const strided_slice &r) { return r.extent; } // get stride of slices template MDSPAN_INLINE_FUNCTION constexpr auto stride_of(const T &) { return std::integral_constant(); } template MDSPAN_INLINE_FUNCTION constexpr auto stride_of(const strided_slice &r) { return r.stride; } // divide which can deal with integral constant preservation template MDSPAN_INLINE_FUNCTION constexpr auto divide(const T0 &v0, const T1 &v1) { return IndexT(v0) / IndexT(v1); } template MDSPAN_INLINE_FUNCTION constexpr auto divide(const std::integral_constant &, const std::integral_constant &) { // cutting short division by zero // this is used for strided_slice with zero extent/stride return std::integral_constant(); } // multiply which can deal with integral constant preservation template MDSPAN_INLINE_FUNCTION constexpr auto multiply(const T0 &v0, const T1 &v1) { return IndexT(v0) * IndexT(v1); } template MDSPAN_INLINE_FUNCTION constexpr auto multiply(const std::integral_constant &, const std::integral_constant &) { return std::integral_constant(); } // compute new static extent from range, preserving static knowledge template struct StaticExtentFromRange { constexpr static size_t value = dynamic_extent; }; template struct StaticExtentFromRange, std::integral_constant> { constexpr static size_t value = val1 - val0; }; // compute new static extent from strided_slice, preserving static // knowledge template struct StaticExtentFromStridedRange { constexpr static size_t value = dynamic_extent; }; template struct StaticExtentFromStridedRange, std::integral_constant> { constexpr static size_t value = val0 > 0 ? 1 + (val0 - 1) / val1 : 0; }; // creates new extents through recursive calls to next_extent member function // next_extent has different overloads for different types of stride specifiers template struct extents_constructor { MDSPAN_TEMPLATE_REQUIRES( class Slice, class... SlicesAndExtents, /* requires */(!std::is_convertible_v && !is_strided_slice::value) ) MDSPAN_INLINE_FUNCTION constexpr static auto next_extent(const Extents &ext, const Slice &sl, SlicesAndExtents... slices_and_extents) { constexpr size_t new_static_extent = StaticExtentFromRange< decltype(first_of(std::declval())), decltype(last_of(std::integral_constant(), std::declval(), std::declval()))>::value; using next_t = extents_constructor; using index_t = typename Extents::index_type; return next_t::next_extent( ext, slices_and_extents..., index_t(last_of(std::integral_constant(), ext, sl)) - index_t(first_of(sl))); } MDSPAN_TEMPLATE_REQUIRES( class Slice, class... SlicesAndExtents, /* requires */ (std::is_convertible_v) ) MDSPAN_INLINE_FUNCTION constexpr static auto next_extent(const Extents &ext, const Slice &, SlicesAndExtents... slices_and_extents) { using next_t = extents_constructor; return next_t::next_extent(ext, slices_and_extents...); } template MDSPAN_INLINE_FUNCTION constexpr static auto next_extent(const Extents &ext, const strided_slice &r, SlicesAndExtents... slices_and_extents) { using index_t = typename Extents::index_type; using new_static_extent_t = StaticExtentFromStridedRange; if constexpr (new_static_extent_t::value == dynamic_extent) { using next_t = extents_constructor; return next_t::next_extent( ext, slices_and_extents..., r.extent > 0 ? 1 + divide(r.extent - 1, r.stride) : 0); } else { constexpr size_t new_static_extent = new_static_extent_t::value; using next_t = extents_constructor; return next_t::next_extent( ext, slices_and_extents..., index_t(divide(ExtentType(), StrideType()))); } } }; template struct extents_constructor<0, Extents, NewStaticExtents...> { template MDSPAN_INLINE_FUNCTION constexpr static auto next_extent(const Extents &, NewExtents... new_exts) { return extents( new_exts...); } }; } // namespace detail // submdspan_extents creates new extents given src extents and submdspan slice // specifiers template MDSPAN_INLINE_FUNCTION constexpr auto submdspan_extents(const extents &src_exts, SliceSpecifiers... slices) { using ext_t = extents; return detail::extents_constructor::next_extent( src_exts, slices...); } } // namespace MDSPAN_IMPL_STANDARD_NAMESPACE //END_FILE_INCLUDE: /home/runner/work/mdspan/mdspan/include/experimental/__p2630_bits/submdspan_extents.hpp //BEGIN_FILE_INCLUDE: /home/runner/work/mdspan/mdspan/include/experimental/__p2630_bits/submdspan_mapping.hpp //@HEADER // ************************************************************************ // // Kokkos v. 4.0 // Copyright (2022) National Technology & Engineering // Solutions of Sandia, LLC (NTESS). // // Under the terms of Contract DE-NA0003525 with NTESS, // the U.S. Government retains certain rights in this software. // // Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions. // See https://kokkos.org/LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //@HEADER #include #include #include #include // index_sequence // Suppress spurious warning with NVCC about no return statement. // This is a known issue in NVCC and NVC++ // Depending on the CUDA and GCC version we need both the builtin // and the diagnostic push. I tried really hard to find something shorter // but no luck ... #if defined __NVCC__ #ifdef __NVCC_DIAG_PRAGMA_SUPPORT__ #pragma nv_diagnostic push #pragma nv_diag_suppress = implicit_return_from_non_void_function #else #ifdef __CUDA_ARCH__ #pragma diagnostic push #pragma diag_suppress implicit_return_from_non_void_function #endif #endif #elif defined __NVCOMPILER #pragma diagnostic push #pragma diag_suppress = implicit_return_from_non_void_function #endif namespace MDSPAN_IMPL_STANDARD_NAMESPACE { //****************************************** // Return type of submdspan_mapping overloads //****************************************** template struct submdspan_mapping_result { _MDSPAN_NO_UNIQUE_ADDRESS LayoutMapping mapping{}; size_t offset; }; namespace detail { // We use const Slice& and not Slice&& because the various // submdspan_mapping_impl overloads use their slices arguments // multiple times. This makes perfect forwarding not useful, but we // still don't want to pass those (possibly of size 64 x 3 bits) // objects by value. template MDSPAN_INLINE_FUNCTION constexpr bool one_slice_out_of_bounds(const IndexType &ext, const Slice &slice) { using common_t = std::common_type_t; return static_cast(detail::first_of(slice)) == static_cast(ext); } template MDSPAN_INLINE_FUNCTION constexpr bool any_slice_out_of_bounds_helper(std::index_sequence, const extents &exts, const Slices &... slices) { return _MDSPAN_FOLD_OR( (one_slice_out_of_bounds(exts.extent(RankIndices), slices))); } template MDSPAN_INLINE_FUNCTION constexpr bool any_slice_out_of_bounds(const extents &exts, const Slices &... slices) { return any_slice_out_of_bounds_helper( std::make_index_sequence(), exts, slices...); } // constructs sub strides template MDSPAN_INLINE_FUNCTION constexpr auto construct_sub_strides( const SrcMapping &src_mapping, std::index_sequence, const std::tuple &slices_stride_factor) { using index_type = typename SrcMapping::index_type; return std::array{ (static_cast(src_mapping.stride(InvMapIdxs)) * static_cast(std::get(slices_stride_factor)))...}; } template struct is_range_slice { constexpr static bool value = std::is_same_v || std::is_convertible_v>; }; template constexpr bool is_range_slice_v = is_range_slice::value; template struct is_index_slice { constexpr static bool value = std::is_convertible_v; }; template constexpr bool is_index_slice_v = is_index_slice::value; } // namespace detail //********************************** // layout_left submdspan_mapping //********************************* namespace detail { // Figure out whether to preserve layout_left template struct deduce_layout_left_submapping; template struct deduce_layout_left_submapping< IndexType, SubRank, std::index_sequence, SliceSpecifiers...> { using count_range = index_sequence_scan_impl< 0u, (is_index_slice_v ? 0u : 1u)...>; constexpr static int gap_len = (((Idx > 0 && count_range::get(Idx) == 1 && is_index_slice_v) ? 1 : 0) + ... + 0); MDSPAN_INLINE_FUNCTION constexpr static bool layout_left_value() { // Use layout_left for rank 0 if constexpr (SubRank == 0) { return true; // Use layout_left for rank 1 result if leftmost slice specifier is range like } else if constexpr (SubRank == 1) { return ((Idx > 0 || is_range_slice_v)&&...); } else { // Preserve if leftmost SubRank-1 slices are full_extent_t and // the slice at idx Subrank - 1 is a range and // for idx > SubRank the slice is an index return ((((Idx < SubRank - 1) && std::is_same_v) || ((Idx == SubRank - 1) && is_range_slice_v) || ((Idx > SubRank - 1) && is_index_slice_v)) && ...); } #if defined(__NVCC__) && !defined(__CUDA_ARCH__) && defined(__GNUC__) __builtin_unreachable(); #endif } MDSPAN_INLINE_FUNCTION constexpr static bool layout_left_padded_value() { // Technically could also keep layout_left_padded for SubRank==0 // and SubRank==1 with leftmost slice specifier being a contiguous range // but we intercept these cases separately // In all other cases: // leftmost slice must be range // then there can be a gap with index slices // then SubRank - 2 full_extent slices // then another range slice // then more index slices // e.g. R I I I F F F R I I for obtaining a rank-5 from a rank-10 return ((((Idx == 0) && is_range_slice_v) || ((Idx > 0 && Idx <= gap_len) && is_index_slice_v) || ((Idx > gap_len && Idx < gap_len + SubRank - 1) && std::is_same_v) || ((Idx == gap_len + SubRank - 1) && is_range_slice_v) || ((Idx > gap_len + SubRank - 1) && is_index_slice_v)) && ... ); } }; // We are reusing the same thing for layout_left and layout_left_padded // For layout_left as source StaticStride is static_extent(0) template struct compute_s_static_layout_left { // Neither StaticStride nor any of the provided extents can be zero. // StaticStride can never be zero, the static_extents we are looking at are associated with // integral slice specifiers - which wouldn't be valid for zero extent template MDSPAN_INLINE_FUNCTION static constexpr size_t value(std::index_sequence) { size_t val = ((Idx>0 && Idx<=NumGaps ? (Extents::static_extent(Idx) == dynamic_extent?0:Extents::static_extent(Idx)) : 1) * ... * (StaticStride == dynamic_extent?0:StaticStride)); return val == 0?dynamic_extent:val; } }; } // namespace detail // Actual submdspan mapping call template template MDSPAN_INLINE_FUNCTION constexpr auto layout_left::mapping::submdspan_mapping_impl( SliceSpecifiers... slices) const { // compute sub extents using src_ext_t = Extents; auto dst_ext = submdspan_extents(extents(), slices...); using dst_ext_t = decltype(dst_ext); // figure out sub layout type using deduce_layout = detail::deduce_layout_left_submapping< typename dst_ext_t::index_type, dst_ext_t::rank(), std::make_index_sequence, SliceSpecifiers...>; // Figure out if any slice's lower bound equals the corresponding extent. // If so, bypass evaluating the layout mapping. This fixes LWG Issue 4060. const bool out_of_bounds = detail::any_slice_out_of_bounds(this->extents(), slices...); auto offset = static_cast( out_of_bounds ? this->required_span_size() : this->operator()(detail::first_of(slices)...)); if constexpr (deduce_layout::layout_left_value()) { // layout_left case using dst_mapping_t = typename layout_left::template mapping; return submdspan_mapping_result{dst_mapping_t(dst_ext), offset}; } else if constexpr (deduce_layout::layout_left_padded_value()) { constexpr size_t S_static = MDSPAN_IMPL_STANDARD_NAMESPACE::detail::compute_s_static_layout_left::value(std::make_index_sequence()); using dst_mapping_t = typename MDSPAN_IMPL_PROPOSED_NAMESPACE::layout_left_padded::template mapping; return submdspan_mapping_result{ dst_mapping_t(dst_ext, stride(1 + deduce_layout::gap_len)), offset}; } else { // layout_stride case using dst_mapping_t = typename layout_stride::mapping; auto inv_map = detail::inv_map_rank(std::integral_constant(), std::index_sequence<>(), slices...); return submdspan_mapping_result { dst_mapping_t(dst_ext, detail::construct_sub_strides( *this, inv_map, // HIP needs deduction guides to have markups so we need to be explicit // NVCC 11.0 has a bug with deduction guide here, tested that 11.2 does not have // the issue But Clang-CUDA also doesn't accept the use of deduction guide so // disable it for CUDA altogether #if defined(_MDSPAN_HAS_HIP) || defined(_MDSPAN_HAS_CUDA) std::tuple{ detail::stride_of(slices)...})), #else std::tuple{detail::stride_of(slices)...})), #endif offset }; } #if defined(__NVCC__) && !defined(__CUDA_ARCH__) && defined(__GNUC__) __builtin_unreachable(); #endif } template template template MDSPAN_INLINE_FUNCTION constexpr auto MDSPAN_IMPL_PROPOSED_NAMESPACE::layout_left_padded::mapping::submdspan_mapping_impl( SliceSpecifiers... slices) const { // compute sub extents using src_ext_t = Extents; auto dst_ext = submdspan_extents(extents(), slices...); using dst_ext_t = decltype(dst_ext); if constexpr (Extents::rank() == 0) { // rank-0 case using dst_mapping_t = typename MDSPAN_IMPL_PROPOSED_NAMESPACE::layout_left_padded::template mapping; return submdspan_mapping_result{*this, 0}; } else { const bool out_of_bounds = MDSPAN_IMPL_STANDARD_NAMESPACE::detail::any_slice_out_of_bounds(this->extents(), slices...); auto offset = static_cast( out_of_bounds ? this->required_span_size() : this->operator()(MDSPAN_IMPL_STANDARD_NAMESPACE::detail::first_of(slices)...)); if constexpr (dst_ext_t::rank() == 0) { // result rank-0 // The following for some reasons leads to compiler error later, while not using a typedef works: // Compilers: CUDA 11.2 with GCC 9.1 // // using dst_mapping_t = typename layout_left::template mapping; // return submdspan_mapping_result{dst_mapping_t{dst_ext}, offset}; // // Error: submdspan_mapping.hpp:299:23: error: 'dst_mapping_t' does not name a type // 299 | using dst_mapping_t = typename layout_left::template mapping; // The same error is given (about dst_mapping_t not naming type) when a different name is used in 299: // using dst_mapping_t2 = typename layout_left::template mapping; return submdspan_mapping_result> {typename layout_left::template mapping{dst_ext}, offset}; } else { // general case // Figure out if any slice's lower bound equals the corresponding extent. // If so, bypass evaluating the layout mapping. This fixes LWG Issue 4060. // figure out sub layout type using deduce_layout = MDSPAN_IMPL_STANDARD_NAMESPACE::detail::deduce_layout_left_submapping< typename dst_ext_t::index_type, dst_ext_t::rank(), decltype(std::make_index_sequence()), SliceSpecifiers...>; if constexpr (deduce_layout::layout_left_value() && dst_ext_t::rank() == 1) { // getting rank-1 from leftmost using dst_mapping_t = typename layout_left::template mapping; return submdspan_mapping_result{dst_mapping_t{dst_ext}, offset}; } else if constexpr (deduce_layout::layout_left_padded_value()) { // can keep layout_left_padded constexpr size_t S_static = MDSPAN_IMPL_STANDARD_NAMESPACE::detail::compute_s_static_layout_left::value(std::make_index_sequence()); using dst_mapping_t = typename MDSPAN_IMPL_PROPOSED_NAMESPACE::layout_left_padded::template mapping; return submdspan_mapping_result{ dst_mapping_t(dst_ext, stride(1 + deduce_layout::gap_len)), offset}; } else { // layout_stride auto inv_map = MDSPAN_IMPL_STANDARD_NAMESPACE::detail::inv_map_rank(std::integral_constant(), std::index_sequence<>(), slices...); using dst_mapping_t = typename layout_stride::template mapping; return submdspan_mapping_result { dst_mapping_t(dst_ext, MDSPAN_IMPL_STANDARD_NAMESPACE::detail::construct_sub_strides( *this, inv_map, // HIP needs deduction guides to have markups so we need to be explicit // NVCC 11.0 has a bug with deduction guide here, tested that 11.2 does not have // the issue But Clang-CUDA also doesn't accept the use of deduction guide so // disable it for CUDA alltogether #if defined(_MDSPAN_HAS_HIP) || defined(_MDSPAN_HAS_CUDA) std::tuple{ MDSPAN_IMPL_STANDARD_NAMESPACE::detail::stride_of(slices)...})), #else std::tuple{MDSPAN_IMPL_STANDARD_NAMESPACE::detail::stride_of(slices)...})), #endif offset }; } } } #if defined(__NVCC__) && !defined(__CUDA_ARCH__) && defined(__GNUC__) __builtin_unreachable(); #endif } //********************************** // layout_right submdspan_mapping //********************************* namespace detail { // Figure out whether to preserve layout_right template struct deduce_layout_right_submapping; template struct deduce_layout_right_submapping< IndexType, SubRank, std::index_sequence, SliceSpecifiers...> { static constexpr size_t Rank = sizeof...(Idx); using count_range = index_sequence_scan_impl< 0u, (std::is_convertible_v ? 0u : 1u)...>; //__static_partial_sums...>; constexpr static int gap_len = (((Idx < Rank - 1 && count_range::get(Idx) == SubRank - 1 && std::is_convertible_v) ? 1 : 0) + ... + 0); MDSPAN_INLINE_FUNCTION constexpr static bool layout_right_value() { // Use layout_right for rank 0 if constexpr (SubRank == 0) { return true; // Use layout_right for rank 1 result if rightmost slice specifier is range like } else if constexpr (SubRank == 1) { return ((Idx < Rank - 1 || is_range_slice_v)&&...); } else { // Preserve if rightmost SubRank-1 slices are full_extent_t and // the slice at idx Rank-Subrank is a range and // for idx < Rank - SubRank the slice is an index return ((((Idx >= Rank - SubRank) && std::is_same_v) || ((Idx == Rank - SubRank) && is_range_slice_v) || ((Idx < Rank - SubRank) && is_index_slice_v)) && ...); } #if defined(__NVCC__) && !defined(__CUDA_ARCH__) && defined(__GNUC__) __builtin_unreachable(); #endif } MDSPAN_INLINE_FUNCTION constexpr static bool layout_right_padded_value() { // Technically could also keep layout_right_padded for SubRank==0 // and SubRank==1 with rightmost slice specifier being a contiguous range // but we intercept these cases separately // In all other cases: // rightmost slice must be range // then there can be a gap with index slices // then SubRank - 2 full_extent slices // then another range slice // then more index slices // e.g. I I R F F F I I I R for obtaining a rank-5 from a rank-10 return ((((Idx == Rank - 1) && is_range_slice_v) || ((Idx >= Rank - gap_len - 1 && Idx < Rank - 1) && is_index_slice_v) || ((Idx > Rank - gap_len - SubRank && Idx < Rank - gap_len - 1) && std::is_same_v) || ((Idx == Rank - gap_len - SubRank) && is_range_slice_v) || ((Idx < Rank - gap_len - SubRank) && is_index_slice_v)) && ... ); } }; // We are reusing the same thing for layout_right and layout_right_padded // For layout_right as source StaticStride is static_extent(Rank-1) template struct compute_s_static_layout_right { // Neither StaticStride nor any of the provided extents can be zero. // StaticStride can never be zero, the static_extents we are looking at are associated with // integral slice specifiers - which wouldn't be valid for zero extent template MDSPAN_INLINE_FUNCTION static constexpr size_t value(std::index_sequence) { size_t val = ((Idx >= Extents::rank() - 1 - NumGaps && Idx < Extents::rank() - 1 ? (Extents::static_extent(Idx) == dynamic_extent?0:Extents::static_extent(Idx)) : 1) * ... * (StaticStride == dynamic_extent?0:StaticStride)); return val == 0?dynamic_extent:val; } }; } // namespace detail // Actual submdspan mapping call template template MDSPAN_INLINE_FUNCTION constexpr auto layout_right::mapping::submdspan_mapping_impl( SliceSpecifiers... slices) const { // compute sub extents using src_ext_t = Extents; auto dst_ext = submdspan_extents(extents(), slices...); using dst_ext_t = decltype(dst_ext); // figure out sub layout type using deduce_layout = detail::deduce_layout_right_submapping< typename dst_ext_t::index_type, dst_ext_t::rank(), std::make_index_sequence, SliceSpecifiers...>; // Figure out if any slice's lower bound equals the corresponding extent. // If so, bypass evaluating the layout mapping. This fixes LWG Issue 4060. const bool out_of_bounds = detail::any_slice_out_of_bounds(this->extents(), slices...); auto offset = static_cast( out_of_bounds ? this->required_span_size() : this->operator()(detail::first_of(slices)...)); if constexpr (deduce_layout::layout_right_value()) { // layout_right case using dst_mapping_t = typename layout_right::mapping; return submdspan_mapping_result{dst_mapping_t(dst_ext), offset}; } else if constexpr (deduce_layout::layout_right_padded_value()) { constexpr size_t S_static = MDSPAN_IMPL_STANDARD_NAMESPACE::detail::compute_s_static_layout_left::value(std::make_index_sequence()); using dst_mapping_t = typename MDSPAN_IMPL_PROPOSED_NAMESPACE::layout_right_padded::template mapping; return submdspan_mapping_result{ dst_mapping_t(dst_ext, stride(src_ext_t::rank() - 2 - deduce_layout::gap_len)), offset}; } else { // layout_stride case using dst_mapping_t = typename layout_stride::mapping; auto inv_map = detail::inv_map_rank(std::integral_constant(), std::index_sequence<>(), slices...); return submdspan_mapping_result { dst_mapping_t(dst_ext, detail::construct_sub_strides( *this, inv_map, // HIP needs deduction guides to have markups so we need to be explicit // NVCC 11.0 has a bug with deduction guide here, tested that 11.2 does not have // the issue But Clang-CUDA also doesn't accept the use of deduction guide so // disable it for CUDA altogether #if defined(_MDSPAN_HAS_HIP) || defined(_MDSPAN_HAS_CUDA) std::tuple{ detail::stride_of(slices)...})), #else std::tuple{detail::stride_of(slices)...})), #endif offset }; } #if defined(__NVCC__) && !defined(__CUDA_ARCH__) && defined(__GNUC__) __builtin_unreachable(); #endif } template template template MDSPAN_INLINE_FUNCTION constexpr auto MDSPAN_IMPL_PROPOSED_NAMESPACE::layout_right_padded::mapping::submdspan_mapping_impl( SliceSpecifiers... slices) const { // compute sub extents using src_ext_t = Extents; auto dst_ext = submdspan_extents(extents(), slices...); using dst_ext_t = decltype(dst_ext); if constexpr (Extents::rank() == 0) { // rank-0 case using dst_mapping_t = typename MDSPAN_IMPL_PROPOSED_NAMESPACE::layout_right_padded::template mapping; return submdspan_mapping_result{*this, 0}; } else { // Figure out if any slice's lower bound equals the corresponding extent. // If so, bypass evaluating the layout mapping. This fixes LWG Issue 4060. // figure out sub layout type const bool out_of_bounds = MDSPAN_IMPL_STANDARD_NAMESPACE::detail::any_slice_out_of_bounds(this->extents(), slices...); auto offset = static_cast( out_of_bounds ? this->required_span_size() : this->operator()(MDSPAN_IMPL_STANDARD_NAMESPACE::detail::first_of(slices)...)); if constexpr (dst_ext_t::rank() == 0) { // result rank-0 // Same issue as in layout_left_padded: see comment there // using dst_mapping_t = typename layout_right::template mapping; // return submdspan_mapping_result{dst_mapping_t{dst_ext}, offset}; return submdspan_mapping_result> {typename layout_right::template mapping{dst_ext}, offset}; } else { // general case using deduce_layout = MDSPAN_IMPL_STANDARD_NAMESPACE::detail::deduce_layout_right_submapping< typename dst_ext_t::index_type, dst_ext_t::rank(), decltype(std::make_index_sequence()), SliceSpecifiers...>; if constexpr (deduce_layout::layout_right_value() && dst_ext_t::rank() == 1) { // getting rank-1 from rightmost using dst_mapping_t = typename layout_right::template mapping; return submdspan_mapping_result{dst_mapping_t{dst_ext}, offset}; } else if constexpr (deduce_layout::layout_right_padded_value()) { // can keep layout_right_padded constexpr size_t S_static = MDSPAN_IMPL_STANDARD_NAMESPACE::detail::compute_s_static_layout_right::value(std::make_index_sequence()); using dst_mapping_t = typename MDSPAN_IMPL_PROPOSED_NAMESPACE::layout_right_padded::template mapping; return submdspan_mapping_result{ dst_mapping_t(dst_ext, stride(Extents::rank() - 2 - deduce_layout::gap_len)), offset}; } else { // layout_stride auto inv_map = MDSPAN_IMPL_STANDARD_NAMESPACE::detail::inv_map_rank(std::integral_constant(), std::index_sequence<>(), slices...); using dst_mapping_t = typename layout_stride::template mapping; return submdspan_mapping_result { dst_mapping_t(dst_ext, MDSPAN_IMPL_STANDARD_NAMESPACE::detail::construct_sub_strides( *this, inv_map, // HIP needs deduction guides to have markups so we need to be explicit // NVCC 11.0 has a bug with deduction guide here, tested that 11.2 does not have // the issue But Clang-CUDA also doesn't accept the use of deduction guide so // disable it for CUDA alltogether #if defined(_MDSPAN_HAS_HIP) || defined(_MDSPAN_HAS_CUDA) std::tuple{ MDSPAN_IMPL_STANDARD_NAMESPACE::detail::stride_of(slices)...})), #else std::tuple{MDSPAN_IMPL_STANDARD_NAMESPACE::detail::stride_of(slices)...})), #endif offset }; } } } #if defined(__NVCC__) && !defined(__CUDA_ARCH__) && defined(__GNUC__) __builtin_unreachable(); #endif } //********************************** // layout_stride submdspan_mapping //********************************* template template MDSPAN_INLINE_FUNCTION constexpr auto layout_stride::mapping::submdspan_mapping_impl( SliceSpecifiers... slices) const { auto dst_ext = submdspan_extents(extents(), slices...); using dst_ext_t = decltype(dst_ext); auto inv_map = detail::inv_map_rank(std::integral_constant(), std::index_sequence<>(), slices...); using dst_mapping_t = typename layout_stride::template mapping; // Figure out if any slice's lower bound equals the corresponding extent. // If so, bypass evaluating the layout mapping. This fixes LWG Issue 4060. const bool out_of_bounds = detail::any_slice_out_of_bounds(this->extents(), slices...); auto offset = static_cast( out_of_bounds ? this->required_span_size() : this->operator()(detail::first_of(slices)...)); return submdspan_mapping_result { dst_mapping_t(dst_ext, detail::construct_sub_strides( *this, inv_map, // HIP needs deduction guides to have markups so we need to be explicit // NVCC 11.0 has a bug with deduction guide here, tested that 11.2 does not have // the issue #if defined(_MDSPAN_HAS_HIP) || \ (defined(__NVCC__) && \ (__CUDACC_VER_MAJOR__ * 100 + __CUDACC_VER_MINOR__ * 10) < 1120) std::tuple( detail::stride_of(slices)...))), #else std::tuple(detail::stride_of(slices)...))), #endif offset }; } } // namespace MDSPAN_IMPL_STANDARD_NAMESPACE #if defined __NVCC__ #ifdef __NVCC_DIAG_PRAGMA_SUPPORT__ #pragma nv_diagnostic pop #else #ifdef __CUDA_ARCH__ #pragma diagnostic pop #endif #endif #elif defined __NVCOMPILER #pragma diagnostic pop #endif //END_FILE_INCLUDE: /home/runner/work/mdspan/mdspan/include/experimental/__p2630_bits/submdspan_mapping.hpp namespace MDSPAN_IMPL_STANDARD_NAMESPACE { template MDSPAN_INLINE_FUNCTION constexpr auto submdspan(const mdspan &src, SliceSpecifiers... slices) { const auto sub_submdspan_mapping_result = submdspan_mapping(src.mapping(), slices...); // NVCC has a problem with the deduction so lets figure out the type using sub_mapping_t = std::remove_cv_t; using sub_extents_t = typename sub_mapping_t::extents_type; using sub_layout_t = typename sub_mapping_t::layout_type; using sub_accessor_t = typename AccessorPolicy::offset_policy; return mdspan( src.accessor().offset(src.data_handle(), sub_submdspan_mapping_result.offset), sub_submdspan_mapping_result.mapping, sub_accessor_t(src.accessor())); } } // namespace MDSPAN_IMPL_STANDARD_NAMESPACE //END_FILE_INCLUDE: /home/runner/work/mdspan/mdspan/include/experimental/__p2630_bits/submdspan.hpp #endif //BEGIN_FILE_INCLUDE: /home/runner/work/mdspan/mdspan/include/experimental/__p2389_bits/dims.hpp //@HEADER // ************************************************************************ // // Kokkos v. 4.0 // Copyright (2022) National Technology & Engineering // Solutions of Sandia, LLC (NTESS). // // Under the terms of Contract DE-NA0003525 with NTESS, // the U.S. Government retains certain rights in this software. // // Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions. // See https://kokkos.org/LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //@HEADER // backward compatibility import into experimental namespace MDSPAN_IMPL_STANDARD_NAMESPACE { namespace MDSPAN_IMPL_PROPOSED_NAMESPACE { template< ::std::size_t Rank, class IndexType = std::size_t> using dims = :: MDSPAN_IMPL_STANDARD_NAMESPACE :: dextents; } // namespace MDSPAN_IMPL_PROPOSED_NAMESPACE } // namespace MDSPAN_IMPL_STANDARD_NAMESPACE //END_FILE_INCLUDE: /home/runner/work/mdspan/mdspan/include/experimental/__p2389_bits/dims.hpp #endif // MDSPAN_HPP_ //END_FILE_INCLUDE: /home/runner/work/mdspan/mdspan/include/mdspan/mdspan.hpp // backward compatibility import into experimental namespace MDSPAN_IMPL_STANDARD_NAMESPACE { namespace MDSPAN_IMPL_PROPOSED_NAMESPACE { using ::MDSPAN_IMPL_STANDARD_NAMESPACE::mdspan; using ::MDSPAN_IMPL_STANDARD_NAMESPACE::extents; using ::MDSPAN_IMPL_STANDARD_NAMESPACE::layout_left; using ::MDSPAN_IMPL_STANDARD_NAMESPACE::layout_right; using ::MDSPAN_IMPL_STANDARD_NAMESPACE::layout_stride; using ::MDSPAN_IMPL_STANDARD_NAMESPACE::default_accessor; } } //END_FILE_INCLUDE: /home/runner/work/mdspan/mdspan/include/experimental/mdspan //BEGIN_FILE_INCLUDE: /home/runner/work/mdspan/mdspan/include/mdspan/mdarray.hpp //@HEADER // ************************************************************************ // // Kokkos v. 4.0 // Copyright (2022) National Technology & Engineering // Solutions of Sandia, LLC (NTESS). // // Under the terms of Contract DE-NA0003525 with NTESS, // the U.S. Government retains certain rights in this software. // // Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions. // See https://kokkos.org/LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //@HEADER #ifndef MDARRAY_HPP_ #define MDARRAY_HPP_ #ifndef MDSPAN_IMPL_STANDARD_NAMESPACE #define MDSPAN_IMPL_STANDARD_NAMESPACE Kokkos #endif #ifndef MDSPAN_IMPL_PROPOSED_NAMESPACE #define MDSPAN_IMPL_PROPOSED_NAMESPACE Experimental #endif //BEGIN_FILE_INCLUDE: /home/runner/work/mdspan/mdspan/include/experimental/__p1684_bits/mdarray.hpp //@HEADER // ************************************************************************ // // Kokkos v. 4.0 // Copyright (2022) National Technology & Engineering // Solutions of Sandia, LLC (NTESS). // // Under the terms of Contract DE-NA0003525 with NTESS, // the U.S. Government retains certain rights in this software. // // Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions. // See https://kokkos.org/LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //@HEADER #include #include namespace MDSPAN_IMPL_STANDARD_NAMESPACE { namespace MDSPAN_IMPL_PROPOSED_NAMESPACE { namespace { template struct size_of_extents; template struct size_of_extents> { constexpr static size_t value() { size_t size = 1; for(size_t r=0; r::rank(); r++) size *= extents::static_extent(r); return size; } }; } namespace { template struct container_is_array : std::false_type { template static constexpr C construct(const M& m) { return C(m.required_span_size()); } }; template struct container_is_array> : std::true_type { template static constexpr std::array construct(const M&) { return std::array(); } }; } template < class ElementType, class Extents, class LayoutPolicy = layout_right, class Container = std::vector > class mdarray { private: static_assert(::MDSPAN_IMPL_STANDARD_NAMESPACE::detail::__is_extents_v, MDSPAN_IMPL_PROPOSED_NAMESPACE_STRING "::mdspan's Extents template parameter must be a specialization of " MDSPAN_IMPL_STANDARD_NAMESPACE_STRING "::extents."); public: //-------------------------------------------------------------------------------- // Domain and codomain types using extents_type = Extents; using layout_type = LayoutPolicy; using container_type = Container; using mapping_type = typename layout_type::template mapping; using element_type = ElementType; using mdspan_type = mdspan; using const_mdspan_type = mdspan; using value_type = std::remove_cv_t; using index_type = typename Extents::index_type; using size_type = typename Extents::size_type; using rank_type = typename Extents::rank_type; using pointer = typename container_type::pointer; using reference = typename container_type::reference; using const_pointer = typename container_type::const_pointer; using const_reference = typename container_type::const_reference; public: //-------------------------------------------------------------------------------- // [mdspan.basic.cons], mdspan constructors, assignment, and destructor #if !(MDSPAN_HAS_CXX_20) MDSPAN_FUNCTION_REQUIRES( (MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr), mdarray, (), , /* requires */ (extents_type::rank_dynamic()!=0)) {} #else MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr mdarray() requires(extents_type::rank_dynamic()!=0) = default; #endif MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr mdarray(const mdarray&) = default; MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr mdarray(mdarray&&) = default; // Constructors for container types constructible from a size MDSPAN_TEMPLATE_REQUIRES( class... SizeTypes, /* requires */ ( (::MDSPAN_IMPL_STANDARD_NAMESPACE::detail::are_valid_indices()) && _MDSPAN_TRAIT( std::is_constructible, extents_type, SizeTypes...) && _MDSPAN_TRAIT( std::is_constructible, mapping_type, extents_type) && (_MDSPAN_TRAIT( std::is_constructible, container_type, size_t) || container_is_array::value) && (extents_type::rank()>0 || extents_type::rank_dynamic()==0) ) ) MDSPAN_INLINE_FUNCTION explicit constexpr mdarray(SizeTypes... dynamic_extents) : map_(extents_type(dynamic_extents...)), ctr_(container_is_array::construct(map_)) { } MDSPAN_FUNCTION_REQUIRES( (MDSPAN_INLINE_FUNCTION constexpr), mdarray, (const extents_type& exts), , /* requires */ ((_MDSPAN_TRAIT( std::is_constructible, container_type, size_t) || container_is_array::value) && _MDSPAN_TRAIT( std::is_constructible, mapping_type, extents_type)) ) : map_(exts), ctr_(container_is_array::construct(map_)) { } MDSPAN_FUNCTION_REQUIRES( (MDSPAN_INLINE_FUNCTION constexpr), mdarray, (const mapping_type& m), , /* requires */ (_MDSPAN_TRAIT( std::is_constructible, container_type, size_t) || container_is_array::value) ) : map_(m), ctr_(container_is_array::construct(map_)) { } MDSPAN_FUNCTION_REQUIRES( (MDSPAN_INLINE_FUNCTION constexpr), mdarray, (const extents_type& exts, const container_type& ctr), , /* requires */ (_MDSPAN_TRAIT( std::is_constructible, mapping_type, extents_type)) ) : map_(exts), ctr_(ctr) { assert(ctr.size() >= static_cast(map_.required_span_size())); } constexpr mdarray(const mapping_type& m, const container_type& ctr) : map_(m), ctr_(ctr) { assert(ctr.size() >= static_cast(map_.required_span_size())); } MDSPAN_FUNCTION_REQUIRES( (MDSPAN_INLINE_FUNCTION constexpr), mdarray, (const extents_type& exts, container_type&& ctr), , /* requires */ (_MDSPAN_TRAIT( std::is_constructible, mapping_type, extents_type)) ) : map_(exts), ctr_(std::move(ctr)) { assert(ctr_.size() >= static_cast(map_.required_span_size())); } constexpr mdarray(const mapping_type& m, container_type&& ctr) : map_(m), ctr_(std::move(ctr)) { assert(ctr_.size() >= static_cast(map_.required_span_size())); } MDSPAN_TEMPLATE_REQUIRES( class OtherElementType, class OtherExtents, class OtherLayoutPolicy, class OtherContainer, /* requires */ ( _MDSPAN_TRAIT( std::is_constructible, mapping_type, typename OtherLayoutPolicy::template mapping) && _MDSPAN_TRAIT( std::is_constructible, container_type, OtherContainer) ) ) MDSPAN_INLINE_FUNCTION constexpr mdarray(const mdarray& other) : map_(other.mapping()), ctr_(other.container()) { static_assert( std::is_constructible::value, ""); } // Constructors for container types constructible from a size and allocator MDSPAN_TEMPLATE_REQUIRES( class Alloc, /* requires */ (_MDSPAN_TRAIT( std::is_constructible, container_type, size_t, Alloc) && _MDSPAN_TRAIT( std::is_constructible, mapping_type, extents_type)) ) MDSPAN_INLINE_FUNCTION constexpr mdarray(const extents_type& exts, const Alloc& a) : map_(exts), ctr_(map_.required_span_size(), a) { } MDSPAN_TEMPLATE_REQUIRES( class Alloc, /* requires */ (_MDSPAN_TRAIT( std::is_constructible, container_type, size_t, Alloc)) ) MDSPAN_INLINE_FUNCTION constexpr mdarray(const mapping_type& map, const Alloc& a) : map_(map), ctr_(map_.required_span_size(), a) { } // Constructors for container types constructible from a container and allocator MDSPAN_TEMPLATE_REQUIRES( class Alloc, /* requires */ (_MDSPAN_TRAIT( std::is_constructible, container_type, container_type, Alloc) && _MDSPAN_TRAIT( std::is_constructible, mapping_type, extents_type)) ) MDSPAN_INLINE_FUNCTION constexpr mdarray(const extents_type& exts, const container_type& ctr, const Alloc& a) : map_(exts), ctr_(ctr, a) { assert(ctr_.size() >= static_cast(map_.required_span_size())); } MDSPAN_TEMPLATE_REQUIRES( class Alloc, /* requires */ (_MDSPAN_TRAIT( std::is_constructible, container_type, size_t, Alloc)) ) MDSPAN_INLINE_FUNCTION constexpr mdarray(const mapping_type& map, const container_type& ctr, const Alloc& a) : map_(map), ctr_(ctr, a) { assert(ctr_.size() >= static_cast(map_.required_span_size())); } MDSPAN_TEMPLATE_REQUIRES( class Alloc, /* requires */ (_MDSPAN_TRAIT( std::is_constructible, container_type, container_type, Alloc) && _MDSPAN_TRAIT( std::is_constructible, mapping_type, extents_type)) ) MDSPAN_INLINE_FUNCTION constexpr mdarray(const extents_type& exts, container_type&& ctr, const Alloc& a) : map_(exts), ctr_(std::move(ctr), a) { assert(ctr_.size() >= static_cast(map_.required_span_size())); } MDSPAN_TEMPLATE_REQUIRES( class Alloc, /* requires */ (_MDSPAN_TRAIT( std::is_constructible, container_type, size_t, Alloc)) ) MDSPAN_INLINE_FUNCTION constexpr mdarray(const mapping_type& map, container_type&& ctr, const Alloc& a) : map_(map), ctr_(std::move(ctr), a) { assert(ctr_.size() >= map_.required_span_size()); } MDSPAN_TEMPLATE_REQUIRES( class OtherElementType, class OtherExtents, class OtherLayoutPolicy, class OtherContainer, class Alloc, /* requires */ ( _MDSPAN_TRAIT( std::is_constructible, mapping_type, typename OtherLayoutPolicy::template mapping) && _MDSPAN_TRAIT( std::is_constructible, container_type, OtherContainer, Alloc) ) ) MDSPAN_INLINE_FUNCTION constexpr mdarray(const mdarray& other, const Alloc& a) : map_(other.mapping()), ctr_(other.container(), a) { static_assert( std::is_constructible::value, ""); } MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr mdarray& operator= (const mdarray&) = default; MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr mdarray& operator= (mdarray&&) = default; MDSPAN_INLINE_FUNCTION_DEFAULTED ~mdarray() = default; //-------------------------------------------------------------------------------- // [mdspan.basic.mapping], mdspan mapping domain multidimensional index to access codomain element #if MDSPAN_USE_BRACKET_OPERATOR MDSPAN_TEMPLATE_REQUIRES( class... SizeTypes, /* requires */ ( _MDSPAN_FOLD_AND(_MDSPAN_TRAIT( std::is_convertible, SizeTypes, index_type) /* && ... */) && extents_type::rank() == sizeof...(SizeTypes) ) ) MDSPAN_FORCE_INLINE_FUNCTION constexpr const_reference operator[](SizeTypes... indices) const noexcept { return ctr_[map_(static_cast(std::move(indices))...)]; } MDSPAN_TEMPLATE_REQUIRES( class... SizeTypes, /* requires */ ( _MDSPAN_FOLD_AND(_MDSPAN_TRAIT( std::is_convertible, SizeTypes, index_type) /* && ... */) && extents_type::rank() == sizeof...(SizeTypes) ) ) MDSPAN_FORCE_INLINE_FUNCTION constexpr reference operator[](SizeTypes... indices) noexcept { return ctr_[map_(static_cast(std::move(indices))...)]; } #endif #if 0 MDSPAN_TEMPLATE_REQUIRES( class SizeType, size_t N, /* requires */ ( _MDSPAN_TRAIT( std::is_convertible, SizeType, index_type) && N == extents_type::rank() ) ) MDSPAN_FORCE_INLINE_FUNCTION constexpr const_reference operator[](const std::array& indices) const noexcept { return __impl::template __callop(*this, indices); } MDSPAN_TEMPLATE_REQUIRES( class SizeType, size_t N, /* requires */ ( _MDSPAN_TRAIT( std::is_convertible, SizeType, index_type) && N == extents_type::rank() ) ) MDSPAN_FORCE_INLINE_FUNCTION constexpr reference operator[](const std::array& indices) noexcept { return __impl::template __callop(*this, indices); } #endif #if MDSPAN_USE_PAREN_OPERATOR MDSPAN_TEMPLATE_REQUIRES( class... SizeTypes, /* requires */ ( (::MDSPAN_IMPL_STANDARD_NAMESPACE::detail::are_valid_indices()) && extents_type::rank() == sizeof...(SizeTypes) ) ) MDSPAN_FORCE_INLINE_FUNCTION constexpr const_reference operator()(SizeTypes... indices) const noexcept { return ctr_[map_(static_cast(std::move(indices))...)]; } MDSPAN_TEMPLATE_REQUIRES( class... SizeTypes, /* requires */ ( (::MDSPAN_IMPL_STANDARD_NAMESPACE::detail::are_valid_indices()) && extents_type::rank() == sizeof...(SizeTypes) ) ) MDSPAN_FORCE_INLINE_FUNCTION constexpr reference operator()(SizeTypes... indices) noexcept { return ctr_[map_(static_cast(std::move(indices))...)]; } #if 0 MDSPAN_TEMPLATE_REQUIRES( class SizeType, size_t N, /* requires */ ( _MDSPAN_TRAIT( std::is_convertible, SizeType, index_type) && N == extents_type::rank() ) ) MDSPAN_FORCE_INLINE_FUNCTION constexpr const_reference operator()(const std::array& indices) const noexcept { return __impl::template __callop(*this, indices); } MDSPAN_TEMPLATE_REQUIRES( class SizeType, size_t N, /* requires */ ( _MDSPAN_TRAIT( std::is_convertible, SizeType, index_type) && N == extents_type::rank() ) ) MDSPAN_FORCE_INLINE_FUNCTION constexpr reference operator()(const std::array& indices) noexcept { return __impl::template __callop(*this, indices); } #endif #endif MDSPAN_INLINE_FUNCTION constexpr pointer data() noexcept { return ctr_.data(); }; MDSPAN_INLINE_FUNCTION constexpr const_pointer data() const noexcept { return ctr_.data(); }; MDSPAN_INLINE_FUNCTION constexpr container_type& container() noexcept { return ctr_; }; MDSPAN_INLINE_FUNCTION constexpr const container_type& container() const noexcept { return ctr_; }; //-------------------------------------------------------------------------------- // [mdspan.basic.domobs], mdspan observers of the domain multidimensional index space MDSPAN_INLINE_FUNCTION static constexpr rank_type rank() noexcept { return extents_type::rank(); } MDSPAN_INLINE_FUNCTION static constexpr rank_type rank_dynamic() noexcept { return extents_type::rank_dynamic(); } MDSPAN_INLINE_FUNCTION static constexpr size_t static_extent(size_t r) noexcept { return extents_type::static_extent(r); } MDSPAN_INLINE_FUNCTION constexpr const 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); return ctr_.size(); }; //-------------------------------------------------------------------------------- // [mdspan.basic.obs], 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_exhaustive() noexcept { return mapping_type::is_always_exhaustive(); }; MDSPAN_INLINE_FUNCTION static constexpr bool is_always_strided() noexcept { return mapping_type::is_always_strided(); }; MDSPAN_INLINE_FUNCTION constexpr const 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_exhaustive() const noexcept { return map_.is_exhaustive(); }; 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); }; // Converstion to mdspan MDSPAN_TEMPLATE_REQUIRES( class OtherElementType, class OtherExtents, class OtherLayoutType, class OtherAccessorType, /* requires */ ( _MDSPAN_TRAIT(std::is_assignable, mdspan, mdspan_type) ) ) constexpr operator mdspan () { return mdspan_type(data(), map_); } MDSPAN_TEMPLATE_REQUIRES( class OtherElementType, class OtherExtents, class OtherLayoutType, class OtherAccessorType, /* requires */ ( _MDSPAN_TRAIT(std::is_assignable, mdspan, const_mdspan_type) ) ) constexpr operator mdspan () const { return const_mdspan_type(data(), map_); } MDSPAN_TEMPLATE_REQUIRES( class OtherAccessorType = default_accessor, /* requires */ ( _MDSPAN_TRAIT(std::is_assignable, mdspan_type, mdspan) ) ) constexpr mdspan to_mdspan(const OtherAccessorType& a = default_accessor()) { return mdspan(data(), map_, a); } MDSPAN_TEMPLATE_REQUIRES( class OtherAccessorType = default_accessor, /* requires */ ( _MDSPAN_TRAIT(std::is_assignable, const_mdspan_type, mdspan) ) ) constexpr mdspan to_mdspan(const OtherAccessorType& a = default_accessor()) const { return mdspan(data(), map_, a); } private: mapping_type map_; container_type ctr_; template friend class mdarray; }; } // end namespace MDSPAN_IMPL_PROPOSED_NAMESPACE } // end namespace MDSPAN_IMPL_STANDARD_NAMESPACE //END_FILE_INCLUDE: /home/runner/work/mdspan/mdspan/include/experimental/__p1684_bits/mdarray.hpp #endif // MDARRAY_HPP_ //END_FILE_INCLUDE: /home/runner/work/mdspan/mdspan/include/mdspan/mdarray.hpp //END_FILE_INCLUDE: /home/runner/work/mdspan/mdspan/include/experimental/mdarray #endif // _MDSPAN_SINGLE_HEADER_INCLUDE_GUARD_