Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cpp14 support #314

Merged
merged 16 commits into from
May 23, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .github/workflows/cmake.yml
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@ jobs:
fail-fast: false
matrix:
compiler_driver: [g++-9, g++-10, clang++, icpx]
stdcxx: [17, 20, 23]
stdcxx: [14, 17, 20, 23]
include:
- compiler_driver: g++-9
compiler_prefix: /usr/bin
@@ -27,6 +27,8 @@ jobs:
# https://www.intel.com/content/www/us/en/developer/articles/tool/oneapi-standalone-components.html#inpage-nav-6-undefined
compiler_url: https://registrationcenter-download.intel.com/akdlm/IRC_NAS/ebf5d9aa-17a7-46a4-b5df-ace004227c0e/l_dpcpp-cpp-compiler_p_2023.2.1.8_offline.sh
- enable_benchmark: ON
- stdcxx: 14
enable_benchmark: OFF
- stdcxx: 23
enable_benchmark: OFF
exclude:
32 changes: 17 additions & 15 deletions include/experimental/__p0009_bits/extents.hpp
Original file line number Diff line number Diff line change
@@ -16,11 +16,13 @@

#pragma once
#include "dynamic_extent.hpp"
#include "utility.hpp"

#ifdef __cpp_lib_span
#include <span>
#endif
#include <array>
#include <type_traits>

#include <cassert>
#include <cinttypes>
@@ -60,8 +62,8 @@ template<class IndexType, class ... Arguments>
MDSPAN_INLINE_FUNCTION
static constexpr bool are_valid_indices() {
return
(std::is_convertible<Arguments, IndexType>::value && ... && true) &&
(std::is_nothrow_constructible<IndexType, Arguments>::value && ... && true);
_MDSPAN_FOLD_AND(std::is_convertible<Arguments, IndexType>::value) &&
_MDSPAN_FOLD_AND(std::is_nothrow_constructible<IndexType, Arguments>::value);
}

// ------------------------------------------------------------------
@@ -539,14 +541,9 @@ template <class IndexType, size_t... Extents> class extents {
MDSPAN_INLINE_FUNCTION friend constexpr bool
operator==(const extents &lhs,
const extents<OtherIndexType, OtherExtents...> &rhs) noexcept {
if constexpr (rank() != extents<OtherIndexType, OtherExtents...>::rank()) {
return false;
} else {
using common_t = std::common_type_t<index_type, OtherIndexType>;
for (size_type r = 0; r < m_rank; r++)
if(static_cast<common_t>(rhs.extent(r)) != static_cast<common_t>(lhs.extent(r))) return false;
}
return true;
return
rank() == extents<OtherIndexType, OtherExtents...>::rank() &&
detail::rankwise_equal(detail::with_rank<rank()>{}, rhs, lhs, detail::extent);
}

#if !(MDSPAN_HAS_CXX_20)
@@ -649,17 +646,21 @@ check_upper_bound(InputIndexType user_index,
#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<class InputIndex, class ExtentsIndexType>
MDSPAN_INLINE_FUNCTION
constexpr void
constexpr bool
check_one_index(InputIndex user_index,
ExtentsIndexType current_extent)
{
check_lower_bound(user_index, current_extent,
std::integral_constant<bool, std::is_signed_v<ExtentsIndexType>>{});
std::integral_constant<bool, std::is_signed<ExtentsIndexType>::value>{});
check_upper_bound(user_index, current_extent);
return true;
}

template<size_t ... RankIndices,
class ExtentsIndexType, size_t ... Exts,
class ... Indices>
@@ -669,7 +670,8 @@ check_all_indices_helper(std::index_sequence<RankIndices...>,
const extents<ExtentsIndexType, Exts...>& exts,
Indices... indices)
{
_MDSPAN_FOLD_COMMA(
// Suppress warning about statement has no effect
(void) _MDSPAN_FOLD_AND(
(check_one_index(indices, exts.extent(RankIndices)))
);
}
@@ -684,6 +686,6 @@ check_all_indices(const extents<ExtentsIndexType, Exts...>& exts,
check_all_indices_helper(std::make_index_sequence<sizeof...(Indices)>(),
exts, indices...);
}

} // namespace detail
} // namespace MDSPAN_IMPL_STANDARD_NAMESPACE
23 changes: 8 additions & 15 deletions include/experimental/__p0009_bits/layout_left.hpp
Original file line number Diff line number Diff line change
@@ -18,8 +18,11 @@
#include "macros.hpp"
#include "trait_backports.hpp"
#include "extents.hpp"
#include "layout_stride.hpp"
#include "utility.hpp"
#if MDSPAN_HAS_CXX_17
#include "../__p2642_bits/layout_padded_fwd.hpp"
#include <cassert>
#endif
#include <type_traits>

namespace MDSPAN_IMPL_STANDARD_NAMESPACE {
@@ -133,11 +136,11 @@ class layout_left::mapping {
: __extents(__other.extents())
{
crtrott marked this conversation as resolved.
Show resolved Hide resolved
MDSPAN_IMPL_PROPOSED_NAMESPACE::detail::
check_padded_layout_converting_constructor_mandates<extents_type,
_Mapping>();
check_padded_layout_converting_constructor_mandates<
extents_type, _Mapping>(detail::with_rank<extents_type::rank()>{});
MDSPAN_IMPL_PROPOSED_NAMESPACE::detail::
check_padded_layout_converting_constructor_preconditions<
extents_type>(__other);
extents_type>(detail::with_rank<extents_type::rank()>{}, __other);
}
#endif

@@ -156,17 +159,7 @@ class layout_left::mapping {
* TODO: check precondition
* other.required_span_size() is a representable value of type index_type
*/
#if !defined(_MDSPAN_HAS_CUDA) && !defined(_MDSPAN_HAS_HIP) && !defined(NDEBUG)
if constexpr (extents_type::rank() > 0) {
index_type stride = 1;
using common_t = std::common_type_t<index_type, typename OtherExtents::index_type>;
for(rank_type r=0; r<__extents.rank(); r++) {
if(static_cast<common_t>(stride) != static_cast<common_t>(other.stride(r)))
std::abort(); // ("Assigning layout_stride to layout_left with invalid strides.");
stride *= __extents.extent(r);
}
}
#endif
detail::validate_strides(detail::with_rank<extents_type::rank()>{}, layout_left{}, __extents, other);
}

MDSPAN_INLINE_FUNCTION_DEFAULTED _MDSPAN_CONSTEXPR_14_DEFAULTED mapping& operator=(mapping const&) noexcept = default;
22 changes: 7 additions & 15 deletions include/experimental/__p0009_bits/layout_right.hpp
Original file line number Diff line number Diff line change
@@ -18,9 +18,11 @@
#include "macros.hpp"
#include "trait_backports.hpp"
#include "extents.hpp"
#include <stdexcept>
#include "layout_stride.hpp"
#include "utility.hpp"
#if MDSPAN_HAS_CXX_17
#include "../__p2642_bits/layout_padded_fwd.hpp"
crtrott marked this conversation as resolved.
Show resolved Hide resolved
#endif

namespace MDSPAN_IMPL_STANDARD_NAMESPACE {

@@ -134,11 +136,11 @@ class layout_right::mapping {
: __extents(__other.extents())
{
MDSPAN_IMPL_PROPOSED_NAMESPACE::detail::
check_padded_layout_converting_constructor_mandates<extents_type,
_Mapping>();
check_padded_layout_converting_constructor_mandates<
extents_type, _Mapping>(detail::with_rank<extents_type::rank()>{});
MDSPAN_IMPL_PROPOSED_NAMESPACE::detail::
check_padded_layout_converting_constructor_preconditions<
extents_type>(__other);
extents_type>(detail::with_rank<extents_type::rank()>{}, __other);
}
#endif

@@ -157,17 +159,7 @@ class layout_right::mapping {
* TODO: check precondition
* other.required_span_size() is a representable value of type index_type
*/
#if !defined(_MDSPAN_HAS_CUDA) && !defined(_MDSPAN_HAS_HIP) && !defined(NDEBUG)
if constexpr (extents_type::rank() > 0) {
index_type stride = 1;
using common_t = std::common_type_t<index_type, typename OtherExtents::index_type>;
for(rank_type r=__extents.rank(); r>0; r--) {
if(static_cast<common_t>(stride) != static_cast<common_t>(other.stride(r-1)))
std::abort(); // ("Assigning layout_stride to layout_right with invalid strides.");
stride *= __extents.extent(r-1);
}
}
#endif
detail::validate_strides(detail::with_rank<extents_type::rank()>{}, layout_right{}, __extents, other);
}

MDSPAN_INLINE_FUNCTION_DEFAULTED _MDSPAN_CONSTEXPR_14_DEFAULTED mapping& operator=(mapping const&) noexcept = default;
124 changes: 84 additions & 40 deletions include/experimental/__p0009_bits/layout_stride.hpp
Original file line number Diff line number Diff line change
@@ -19,14 +19,16 @@
#include "extents.hpp"
#include "trait_backports.hpp"
#include "compressed_pair.hpp"
#include "utility.hpp"

#if !defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS)
# include "no_unique_address.hpp"
#endif

#include <algorithm>
#include <numeric>
#include <array>
#include <type_traits>
#include <utility>

#ifdef __cpp_lib_span
#include <span>
#endif
@@ -38,11 +40,11 @@ namespace MDSPAN_IMPL_STANDARD_NAMESPACE {

struct layout_left {
template<class Extents>
class mapping;
class mapping;
};
struct layout_right {
template<class Extents>
class mapping;
class mapping;
};

namespace detail {
@@ -79,6 +81,7 @@ namespace detail {
std::bool_constant<M::is_always_unique()>::value;
};
#endif

} // namespace detail

struct layout_stride {
@@ -225,7 +228,11 @@ struct layout_stride {
// Can't use defaulted parameter in the __deduction_workaround template because of a bug in MSVC warning C4348.
using __impl = __deduction_workaround<std::make_index_sequence<Extents::rank()>>;

static constexpr __strides_storage_t strides_storage(std::true_type) {
static constexpr __strides_storage_t strides_storage(detail::with_rank<0>) {
return {};
}
template <std::size_t N>
static constexpr __strides_storage_t strides_storage(detail::with_rank<N>) {
__strides_storage_t s{};

extents_type e;
@@ -237,9 +244,6 @@ struct layout_stride {

return s;
}
static constexpr __strides_storage_t strides_storage(std::false_type) {
return {};
}

//----------------------------------------------------------------------------

@@ -262,7 +266,7 @@ struct layout_stride {
: __base_t(__base_t{__member_pair_t(
#endif
extents_type(),
__strides_storage_t(strides_storage(std::integral_constant<bool, (extents_type::rank() > 0)>{}))
__strides_storage_t(strides_storage(detail::with_rank<extents_type::rank()>{}))
#if defined(_MDSPAN_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS)
}
#else
@@ -447,32 +451,48 @@ struct layout_stride {
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 _MDSPAN_CONSTEXPR_14 bool is_exhaustive() const noexcept {
if constexpr (extents_type::rank() == 0)
return true;
else {
index_type span_size = required_span_size();
if (span_size == static_cast<index_type>(0)) {
if constexpr (extents_type::rank() == 1) {
return stride(0) == 1;
} else {
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;
}
} else {
return required_span_size() == __get_size(extents(), std::make_index_sequence<extents_type::rank()>());

private:
constexpr bool exhaustive_for_nonzero_span_size() const
{
return required_span_size() == __get_size(extents(), std::make_index_sequence<extents_type::rank()>());
}

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<index_type>(0)) {
return exhaustive_for_nonzero_span_size();
}
return stride(0) == 1;
}
template <std::size_t N>
constexpr bool is_exhaustive_impl(detail::with_rank<N>) const
{
if (required_span_size() != static_cast<index_type>(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<extents_type::rank()>{});
dalg24 marked this conversation as resolved.
Show resolved Hide resolved
}
MDSPAN_INLINE_FUNCTION static constexpr bool is_strided() noexcept { return true; }

@@ -501,15 +521,9 @@ struct layout_stride {
#endif
MDSPAN_INLINE_FUNCTION
friend constexpr bool operator==(const mapping& x, const StridedLayoutMapping& y) noexcept {
bool strides_match = true;
if constexpr (extents_type::rank() > 0) {
using common_t = std::common_type_t<index_type, typename StridedLayoutMapping::index_type>;
for(rank_type r = 0; r < extents_type::rank(); r++)
strides_match = strides_match && (static_cast<common_t>(x.stride(r)) == static_cast<common_t>(y.stride(r)));
}
return (x.extents() == y.extents()) &&
(__impl::__OFFSET(y) == static_cast<typename StridedLayoutMapping::index_type>(0)) &&
strides_match;
detail::rankwise_equal(detail::with_rank<extents_type::rank()>{}, x, y, detail::stride);
}

// This one is not technically part of the proposal. Just here to make implementation a bit more optimal hopefully
@@ -564,4 +578,34 @@ struct layout_stride {
};
};

namespace detail {

template <class Layout, class Extents, class Mapping>
constexpr void validate_strides(with_rank<0>, Layout, const Extents&, const Mapping&)
{}

template <std::size_t N, class Layout, class Extents, class Mapping>
constexpr void validate_strides(with_rank<N>, Layout, const Extents& ext, const Mapping& other)
{
static_assert(std::is_same<typename Mapping::layout_type, layout_stride>::value and
(std::is_same<Layout, layout_left>::value or
std::is_same<Layout, layout_right>::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<Layout, layout_left>::value;

typename Extents::index_type 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(stride, other.stride(s))
and "invalid strides for layout_{left,right}");

stride *= ext.extent(s);
}
}

} // namespace detail
} // end namespace MDSPAN_IMPL_STANDARD_NAMESPACE
Loading
Loading