diff --git a/.clang-format b/.clang-format new file mode 100644 index 00000000..090edc2c --- /dev/null +++ b/.clang-format @@ -0,0 +1,6 @@ +#Official Tool: clang-format version 16.0.0 +BasedOnStyle: google +SortIncludes: false +AlignConsecutiveAssignments: true +AllowShortCaseLabelsOnASingleLine: true +AllowShortIfStatementsOnASingleLine: true diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 9e91a0e5..39d2dae8 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -11,3 +11,8 @@ repos: - '//' files: '\.(hh|hpp|cc|cpp|cppm|hip|cuh|cu)$' exclude: '^tests/libcxx-backports/' + + - repo: https://github.com/pre-commit/mirrors-clang-format + rev: 579d9fe3b1ee34ddd6ebc5def531f2f1acce622e # v16.0.0 + hooks: + - id: clang-format diff --git a/benchmarks/copy/copy_layout_stride.cpp b/benchmarks/copy/copy_layout_stride.cpp index 17d926f2..7397bfaa 100644 --- a/benchmarks/copy/copy_layout_stride.cpp +++ b/benchmarks/copy/copy_layout_stride.cpp @@ -14,19 +14,17 @@ MDSPAN_IMPL_INLINE_VARIABLE constexpr auto dyn = Kokkos::dynamic_extent; template void BM_MDSpan_Copy_2D_right(benchmark::State& state, MDSpan, DynSizes... dyn) { using value_type = typename MDSpan::value_type; - auto buffer = std::make_unique( - MDSpan{nullptr, dyn...}.mapping().required_span_size() - ); + auto buffer = std::make_unique( + MDSpan{nullptr, dyn...}.mapping().required_span_size()); auto buffer2 = std::make_unique( - MDSpan{nullptr, dyn...}.mapping().required_span_size() - ); + MDSpan{nullptr, dyn...}.mapping().required_span_size()); auto s = MDSpan{buffer.get(), dyn...}; mdspan_benchmark::fill_random(s); auto dest = MDSpan{buffer2.get(), dyn...}; for (auto _ : state) { - for(index_type i = 0; i < s.extent(0); ++i) { + for (index_type i = 0; i < s.extent(0); ++i) { for (index_type j = 0; j < s.extent(1); ++j) { - dest(i, j) = s(i, j); + dest(i, j) = s(i, j); } } auto sdata = s.data_handle(); @@ -38,32 +36,29 @@ void BM_MDSpan_Copy_2D_right(benchmark::State& state, MDSpan, DynSizes... dyn) { } BENCHMARK_CAPTURE( - BM_MDSpan_Copy_2D_right, size_100_100, Kokkos::mdspan>(nullptr) -); -BENCHMARK_CAPTURE( - BM_MDSpan_Copy_2D_right, size_100_dyn, Kokkos::mdspan>(), 100 -); -BENCHMARK_CAPTURE( - BM_MDSpan_Copy_2D_right, size_dyn_dyn, Kokkos::mdspan>(), 100, 100 -); + BM_MDSpan_Copy_2D_right, size_100_100, + Kokkos::mdspan>(nullptr)); +BENCHMARK_CAPTURE(BM_MDSpan_Copy_2D_right, size_100_dyn, + Kokkos::mdspan>(), + 100); +BENCHMARK_CAPTURE(BM_MDSpan_Copy_2D_right, size_dyn_dyn, + Kokkos::mdspan>(), 100, + 100); //================================================================================ template -void BM_MDSpan_Copy_2D_stride(benchmark::State& state, MDSpan, LayoutMapping map) { +void BM_MDSpan_Copy_2D_stride(benchmark::State& state, MDSpan, + LayoutMapping map) { benchmark::DoNotOptimize(map); using value_type = typename MDSpan::value_type; - auto buffer = std::make_unique( - map.required_span_size() - ); - auto buffer2 = std::make_unique( - map.required_span_size() - ); - auto s = MDSpan{buffer.get(), map}; + auto buffer = std::make_unique(map.required_span_size()); + auto buffer2 = std::make_unique(map.required_span_size()); + auto s = MDSpan{buffer.get(), map}; mdspan_benchmark::fill_random(s); auto dest = MDSpan{buffer2.get(), map}; for (auto _ : state) { - for(index_type i = 0; i < s.extent(0); ++i) { + for (index_type i = 0; i < s.extent(0); ++i) { for (index_type j = 0; j < s.extent(1); ++j) { dest(i, j) = s(i, j); } @@ -76,64 +71,57 @@ void BM_MDSpan_Copy_2D_stride(benchmark::State& state, MDSpan, LayoutMapping map state.SetBytesProcessed(s.size() * sizeof(value_type) * state.iterations()); } -BENCHMARK_CAPTURE( - BM_MDSpan_Copy_2D_stride, size_100_100, - Kokkos::mdspan, Kokkos::layout_stride>(nullptr, - Kokkos::layout_stride::mapping>()), - Kokkos::layout_stride::template mapping>( - Kokkos::extents{}, - // layout right - std::array{100, 1} - ) -); -BENCHMARK_CAPTURE( - BM_MDSpan_Copy_2D_stride, size_100_100d, - Kokkos::mdspan, Kokkos::layout_stride>(), - Kokkos::layout_stride::template mapping>( - Kokkos::extents{100}, - // layout right - std::array{100, 1} - ) -); -BENCHMARK_CAPTURE( - BM_MDSpan_Copy_2D_stride, size_100d_100, - Kokkos::mdspan, Kokkos::layout_stride>(), - Kokkos::layout_stride::template mapping>( - Kokkos::extents{100}, - // layout right - std::array{100, 1} - ) -); -BENCHMARK_CAPTURE( - BM_MDSpan_Copy_2D_stride, size_100d_100d, - Kokkos::mdspan, Kokkos::layout_stride>(), - Kokkos::layout_stride::template mapping>( - Kokkos::extents{100, 100}, - // layout right - std::array{100, 1} - ) -); +BENCHMARK_CAPTURE(BM_MDSpan_Copy_2D_stride, size_100_100, + Kokkos::mdspan, + Kokkos::layout_stride>( + nullptr, Kokkos::layout_stride::mapping< + Kokkos::extents>()), + Kokkos::layout_stride::template mapping< + Kokkos::extents>( + Kokkos::extents{}, + // layout right + std::array{100, 1})); +BENCHMARK_CAPTURE(BM_MDSpan_Copy_2D_stride, size_100_100d, + Kokkos::mdspan, + Kokkos::layout_stride>(), + Kokkos::layout_stride::template mapping< + Kokkos::extents>( + Kokkos::extents{100}, + // layout right + std::array{100, 1})); +BENCHMARK_CAPTURE(BM_MDSpan_Copy_2D_stride, size_100d_100, + Kokkos::mdspan, + Kokkos::layout_stride>(), + Kokkos::layout_stride::template mapping< + Kokkos::extents>( + Kokkos::extents{100}, + // layout right + std::array{100, 1})); +BENCHMARK_CAPTURE(BM_MDSpan_Copy_2D_stride, size_100d_100d, + Kokkos::mdspan, + Kokkos::layout_stride>(), + Kokkos::layout_stride::template mapping< + Kokkos::extents>( + Kokkos::extents{100, 100}, + // layout right + std::array{100, 1})); //================================================================================ template -void BM_MDSpan_Copy_2D_stride_diff_map(benchmark::State& state, - T, Extents, MapSrc map_src, MapDst map_dest -) { +void BM_MDSpan_Copy_2D_stride_diff_map(benchmark::State& state, T, Extents, + MapSrc map_src, MapDst map_dest) { using value_type = T; - auto buff_src = std::make_unique( - map_src.required_span_size() - ); - auto buff_dest = std::make_unique( - map_dest.required_span_size() - ); + auto buff_src = std::make_unique(map_src.required_span_size()); + auto buff_dest = + std::make_unique(map_dest.required_span_size()); using map_stride_dyn = Kokkos::layout_stride; - using mdspan_type = Kokkos::mdspan; - auto src = mdspan_type{buff_src.get(), map_src}; + using mdspan_type = Kokkos::mdspan; + auto src = mdspan_type{buff_src.get(), map_src}; mdspan_benchmark::fill_random(src); auto dest = mdspan_type{buff_dest.get(), map_dest}; for (auto _ : state) { - for(index_type i = 0; i < src.extent(0); ++i) { + for (index_type i = 0; i < src.extent(0); ++i) { for (index_type j = 0; j < src.extent(1); ++j) { dest(i, j) = src(i, j); } @@ -143,54 +131,48 @@ void BM_MDSpan_Copy_2D_stride_diff_map(benchmark::State& state, benchmark::DoNotOptimize(sdata); benchmark::DoNotOptimize(ddata); } - state.SetBytesProcessed(src.extent(0) * src.extent(1) * sizeof(value_type) * state.iterations()); + state.SetBytesProcessed(src.extent(0) * src.extent(1) * sizeof(value_type) * + state.iterations()); } -BENCHMARK_CAPTURE( - BM_MDSpan_Copy_2D_stride_diff_map, size_100d_100d_bcast_0, int(), - Kokkos::extents{100, 100}, - Kokkos::layout_stride::template mapping>( - Kokkos::extents{100, 100}, - // layout right - std::array{0, 1} - ), - Kokkos::layout_stride::template mapping>( - Kokkos::extents{100, 100}, - // layout right - std::array{100, 1} - ) -); - -BENCHMARK_CAPTURE( - BM_MDSpan_Copy_2D_stride_diff_map, size_100d_100d_bcast_1, int(), - Kokkos::extents{100, 100}, - Kokkos::layout_stride::template mapping>( - Kokkos::extents{100, 100}, - // layout right - std::array{1, 0} - ), - Kokkos::layout_stride::template mapping>( - Kokkos::extents{100, 100}, - // layout right - std::array{100, 1} - ) -); - -BENCHMARK_CAPTURE( - BM_MDSpan_Copy_2D_stride_diff_map, size_100d_100d_bcast_both, int(), - Kokkos::extents{100, 100}, - Kokkos::layout_stride::template mapping>( - Kokkos::extents{100, 100}, - // layout right - std::array{0, 0} - ), - Kokkos::layout_stride::template mapping>( - Kokkos::extents{100, 100}, - // layout right - std::array{100, 1} - ) -); - +BENCHMARK_CAPTURE(BM_MDSpan_Copy_2D_stride_diff_map, size_100d_100d_bcast_0, + int(), Kokkos::extents{100, 100}, + Kokkos::layout_stride::template mapping< + Kokkos::extents>( + Kokkos::extents{100, 100}, + // layout right + std::array{0, 1}), + Kokkos::layout_stride::template mapping< + Kokkos::extents>( + Kokkos::extents{100, 100}, + // layout right + std::array{100, 1})); + +BENCHMARK_CAPTURE(BM_MDSpan_Copy_2D_stride_diff_map, size_100d_100d_bcast_1, + int(), Kokkos::extents{100, 100}, + Kokkos::layout_stride::template mapping< + Kokkos::extents>( + Kokkos::extents{100, 100}, + // layout right + std::array{1, 0}), + Kokkos::layout_stride::template mapping< + Kokkos::extents>( + Kokkos::extents{100, 100}, + // layout right + std::array{100, 1})); + +BENCHMARK_CAPTURE(BM_MDSpan_Copy_2D_stride_diff_map, size_100d_100d_bcast_both, + int(), Kokkos::extents{100, 100}, + Kokkos::layout_stride::template mapping< + Kokkos::extents>( + Kokkos::extents{100, 100}, + // layout right + std::array{0, 0}), + Kokkos::layout_stride::template mapping< + Kokkos::extents>( + Kokkos::extents{100, 100}, + // layout right + std::array{100, 1})); //================================================================================ @@ -198,17 +180,18 @@ template void BM_Raw_Copy_1D(benchmark::State& state, T, size_t size) { benchmark::DoNotOptimize(size); using value_type = T; - auto buffer = std::make_unique(size); + auto buffer = std::make_unique(size); { // just for setup... - auto wrapped = Kokkos::mdspan>{buffer.get(), size}; + auto wrapped = + Kokkos::mdspan>{buffer.get(), size}; mdspan_benchmark::fill_random(wrapped); } - value_type* src = buffer.get(); - auto buffer2 = std::make_unique(size); + value_type* src = buffer.get(); + auto buffer2 = std::make_unique(size); value_type* dest = buffer2.get(); for (auto _ : state) { - for(size_t i = 0; i < size; ++i) { + for (size_t i = 0; i < size; ++i) { dest[i] = src[i]; } benchmark::DoNotOptimize(src); @@ -217,28 +200,27 @@ void BM_Raw_Copy_1D(benchmark::State& state, T, size_t size) { state.SetBytesProcessed(size * sizeof(value_type) * state.iterations()); } -BENCHMARK_CAPTURE( - BM_Raw_Copy_1D, size_10000, int(), 10000 -); +BENCHMARK_CAPTURE(BM_Raw_Copy_1D, size_10000, int(), 10000); //================================================================================ template void BM_Raw_Copy_2D(benchmark::State& state, T, size_t x, size_t y) { using value_type = T; - auto buffer = std::make_unique(x * y); + auto buffer = std::make_unique(x * y); { // just for setup... - auto wrapped = Kokkos::mdspan>{buffer.get(), x * y}; + auto wrapped = + Kokkos::mdspan>{buffer.get(), x * y}; mdspan_benchmark::fill_random(wrapped); } - value_type* src = buffer.get(); - auto buffer2 = std::make_unique(x * y); + value_type* src = buffer.get(); + auto buffer2 = std::make_unique(x * y); value_type* dest = buffer2.get(); for (auto _ : state) { - for(size_t i = 0; i < x; ++i) { - for(size_t j = 0; j < y; ++j) { - dest[i*y + j] = src[i*y + j]; + for (size_t i = 0; i < x; ++i) { + for (size_t j = 0; j < y; ++j) { + dest[i * y + j] = src[i * y + j]; } } benchmark::DoNotOptimize(src); @@ -247,9 +229,7 @@ void BM_Raw_Copy_2D(benchmark::State& state, T, size_t x, size_t y) { state.SetBytesProcessed(x * y * sizeof(value_type) * state.iterations()); } -BENCHMARK_CAPTURE( - BM_Raw_Copy_2D, size_100_100, int(), 100, 100 -); +BENCHMARK_CAPTURE(BM_Raw_Copy_2D, size_100_100, int(), 100, 100); //================================================================================ diff --git a/benchmarks/fill.hpp b/benchmarks/fill.hpp index 26bf3ad2..18c68516 100644 --- a/benchmarks/fill.hpp +++ b/benchmarks/fill.hpp @@ -11,9 +11,8 @@ #include #include - - -#if !(defined(__cpp_lib_make_unique) && __cpp_lib_make_unique >= 201304) && !MDSPAN_HAS_CXX_14 +#if !(defined(__cpp_lib_make_unique) && __cpp_lib_make_unique >= 201304) && \ + !MDSPAN_HAS_CXX_14 // Not actually conforming, but it works for the purposes of this file namespace std { template @@ -26,16 +25,14 @@ struct __unique_ptr_new_impl { template struct __unique_ptr_new_impl { - static T* __impl(size_t size) { - return new T[size]; - } + static T* __impl(size_t size) { return new T[size]; } }; template std::unique_ptr make_unique(Args&&... args) { return std::unique_ptr(__unique_ptr_new_impl::__impl((Args&&)args...)); } -} // end namespace std +} // end namespace std #endif namespace mdspan_benchmark { @@ -43,31 +40,30 @@ namespace mdspan_benchmark { namespace _impl { template -T&& _repeated_with(T&& v) noexcept { return std::forward(v); } +T&& _repeated_with(T&& v) noexcept { + return std::forward(v); +} template -void _do_fill_random( - Kokkos::mdspan, Rest...> s, - RNG& gen, - Dist& dist -) -{ +void _do_fill_random(Kokkos::mdspan, Rest...> s, + RNG& gen, Dist& dist) { s() = dist(gen); } -template +template void _do_fill_random( - Kokkos::mdspan, Rest...> s, - RNG& gen, - Dist& dist -) -{ - for(SizeT i = 0; i < s.extent(0); ++i) { - _do_fill_random(Kokkos::submdspan(s, i, _repeated_with(Kokkos::full_extent)...), gen, dist); + Kokkos::mdspan, Rest...> s, RNG& gen, + Dist& dist) { + for (SizeT i = 0; i < s.extent(0); ++i) { + _do_fill_random( + Kokkos::submdspan(s, i, + _repeated_with(Kokkos::full_extent)...), + gen, dist); } } -} // end namespace _impl +} // end namespace _impl template void fill_random(Kokkos::mdspan s, long long seed = 1234) { @@ -76,8 +72,9 @@ void fill_random(Kokkos::mdspan s, long long seed = 1234) { _impl::_do_fill_random(s, gen, val_dist); } -} // namespace mdspan_benchmark +} // namespace mdspan_benchmark +// clang-format off //============================================================================== // {{{1 @@ -161,5 +158,6 @@ BENCHMARK_CAPTURE( \ // end A helpful template for instantiating all 3D combinations }}}1 //============================================================================== +// clang-format on -#endif // MDSPAN_BENCHMARKS_FILL_HPP +#endif // MDSPAN_BENCHMARKS_FILL_HPP diff --git a/benchmarks/matvec/cuda/matvec_cuda.cu b/benchmarks/matvec/cuda/matvec_cuda.cu index 6cdb7894..52a33bd2 100644 --- a/benchmarks/matvec/cuda/matvec_cuda.cu +++ b/benchmarks/matvec/cuda/matvec_cuda.cu @@ -13,7 +13,7 @@ //================================================================================ -static constexpr int global_delta = 1; +static constexpr int global_delta = 1; static constexpr int global_repeat = 16; //================================================================================ @@ -21,18 +21,20 @@ static constexpr int global_repeat = 16; using size_type = int; template -using lmdspan = Kokkos::mdspan, Kokkos::layout_left>; +using lmdspan = + Kokkos::mdspan, Kokkos::layout_left>; template -using rmdspan = Kokkos::mdspan, Kokkos::layout_right>; +using rmdspan = + Kokkos::mdspan, Kokkos::layout_right>; -void throw_runtime_exception(const std::string &msg) { +void throw_runtime_exception(const std::string& msg) { std::ostringstream o; o << msg; throw std::runtime_error(o.str()); } void cuda_internal_error_throw(cudaError e, const char* name, - const char* file = NULL, const int line = 0) { + const char* file = NULL, const int line = 0) { std::ostringstream out; out << name << " error( " << cudaGetErrorName(e) << "): " << cudaGetErrorString(e); @@ -43,8 +45,8 @@ void cuda_internal_error_throw(cudaError e, const char* name, } inline void cuda_internal_safe_call(cudaError e, const char* name, - const char* file = NULL, - const int line = 0) { + const char* file = NULL, + const int line = 0) { if (cudaSuccess != e) { cuda_internal_error_throw(e, name, file, line); } @@ -55,10 +57,8 @@ inline void cuda_internal_safe_call(cudaError e, const char* name, //================================================================================ - template -__global__ -void do_run_kernel(F f, Args... args) { +__global__ void do_run_kernel(F f, Args... args) { f(args...); } @@ -69,9 +69,7 @@ float run_kernel_timed(size_t N, size_t M, F&& f, Args&&... args) { CUDA_SAFE_CALL(cudaEventCreate(&stop)); CUDA_SAFE_CALL(cudaEventRecord(start)); - do_run_kernel<<<(N+255)/256,256>>>( - (F&&)f, ((Args&&) args)... - ); + do_run_kernel<<<(N + 255) / 256, 256>>>((F&&)f, ((Args&&)args)...); CUDA_SAFE_CALL(cudaEventRecord(stop)); CUDA_SAFE_CALL(cudaEventSynchronize(stop)); float milliseconds = 0; @@ -81,54 +79,52 @@ float run_kernel_timed(size_t N, size_t M, F&& f, Args&&... args) { template MDSpan fill_device_mdspan(MDSpan, DynSizes... dyn) { - using value_type = typename MDSpan::value_type; auto buffer_size = MDSpan{nullptr, dyn...}.mapping().required_span_size(); auto host_buffer = std::make_unique( - MDSpan{nullptr, dyn...}.mapping().required_span_size() - ); + MDSpan{nullptr, dyn...}.mapping().required_span_size()); auto host_mdspan = MDSpan{host_buffer.get(), dyn...}; mdspan_benchmark::fill_random(host_mdspan); value_type* device_buffer = nullptr; CUDA_SAFE_CALL(cudaMalloc(&device_buffer, buffer_size * sizeof(value_type))); - CUDA_SAFE_CALL(cudaMemcpy( - device_buffer, host_buffer.get(), buffer_size * sizeof(value_type), cudaMemcpyHostToDevice - )); + CUDA_SAFE_CALL(cudaMemcpy(device_buffer, host_buffer.get(), + buffer_size * sizeof(value_type), + cudaMemcpyHostToDevice)); return MDSpan{device_buffer, dyn...}; } //================================================================================ template -void BM_MDSpan_CUDA_MatVec(benchmark::State& state, MDSpanMatrix, DynSizes... dyn) { - - using value_type = typename MDSpanMatrix::value_type; - using MDSpanVector = lmdspan; +void BM_MDSpan_CUDA_MatVec(benchmark::State& state, MDSpanMatrix, + DynSizes... dyn) { + using value_type = typename MDSpanMatrix::value_type; + using MDSpanVector = lmdspan; auto A = fill_device_mdspan(MDSpanMatrix{}, dyn...); auto x = fill_device_mdspan(MDSpanVector{}, A.extent(1)); auto y = fill_device_mdspan(MDSpanVector{}, A.extent(0)); - auto lambda = - [=] __device__ { - const size_t i = blockIdx.x * blockDim.x + threadIdx.x; - if(i>=A.extent(0)) return; - value_type y_i = 0; - for(size_t j = 0; j < A.extent(1); j ++) { - y_i += A(i,j) * x(j); - } - y(i) = y_i; - }; - run_kernel_timed(A.extent(0),A.extent(1),lambda); + auto lambda = [=] __device__ { + const size_t i = blockIdx.x * blockDim.x + threadIdx.x; + if (i >= A.extent(0)) return; + value_type y_i = 0; + for (size_t j = 0; j < A.extent(1); j++) { + y_i += A(i, j) * x(j); + } + y(i) = y_i; + }; + run_kernel_timed(A.extent(0), A.extent(1), lambda); for (auto _ : state) { - auto timed = run_kernel_timed(A.extent(0),A.extent(1),lambda); + auto timed = run_kernel_timed(A.extent(0), A.extent(1), lambda); // units of cuda timer is milliseconds, units of iteration timer is seconds state.SetIterationTime(timed * 1e-3); } size_t num_elements = 2 * A.extent(0) * A.extent(1) + 2 * A.extent(0); - state.SetBytesProcessed( num_elements * sizeof(value_type) * state.iterations() ); + state.SetBytesProcessed(num_elements * sizeof(value_type) * + state.iterations()); CUDA_SAFE_CALL(cudaDeviceSynchronize()); CUDA_SAFE_CALL(cudaFree(A.data_handle())); @@ -136,15 +132,16 @@ void BM_MDSpan_CUDA_MatVec(benchmark::State& state, MDSpanMatrix, DynSizes... dy CUDA_SAFE_CALL(cudaFree(y.data_handle())); } +// clang-format off BENCHMARK_CAPTURE(BM_MDSpan_CUDA_MatVec, left, lmdspan(), 100000, 5000); BENCHMARK_CAPTURE(BM_MDSpan_CUDA_MatVec, right, rmdspan(), 100000, 5000); - +// clang-format on template -void BM_MDSpan_CUDA_MatVec_Raw_Right(benchmark::State& state, MDSpanMatrix, DynSizes... dyn) { - - using value_type = typename MDSpanMatrix::value_type; - using MDSpanVector = lmdspan; +void BM_MDSpan_CUDA_MatVec_Raw_Right(benchmark::State& state, MDSpanMatrix, + DynSizes... dyn) { + using value_type = typename MDSpanMatrix::value_type; + using MDSpanVector = lmdspan; auto A = fill_device_mdspan(MDSpanMatrix{}, dyn...); auto x = fill_device_mdspan(MDSpanVector{}, A.extent(1)); @@ -157,26 +154,26 @@ void BM_MDSpan_CUDA_MatVec_Raw_Right(benchmark::State& state, MDSpanMatrix, DynS value_type* p_x = x.data_handle(); value_type* p_y = y.data_handle(); - auto lambda = - [=] __device__ { - const size_t i = blockIdx.x * blockDim.x + threadIdx.x; - if(i>=N) return; - value_type y_i = 0; + auto lambda = [=] __device__ { + const size_t i = blockIdx.x * blockDim.x + threadIdx.x; + if (i >= N) return; + value_type y_i = 0; - for(size_t j = 0; j < M; j ++) { - y_i += p_A[i*M+j] * p_x[j]; - } - p_y[i] = y_i; - }; - run_kernel_timed(N,M,lambda); + for (size_t j = 0; j < M; j++) { + y_i += p_A[i * M + j] * p_x[j]; + } + p_y[i] = y_i; + }; + run_kernel_timed(N, M, lambda); for (auto _ : state) { - auto timed = run_kernel_timed(N,M,lambda); + auto timed = run_kernel_timed(N, M, lambda); // units of cuda timer is milliseconds, units of iteration timer is seconds state.SetIterationTime(timed * 1e-3); } size_t num_elements = 2 * A.extent(0) * A.extent(1) + 2 * A.extent(0); - state.SetBytesProcessed( num_elements * sizeof(value_type) * state.iterations() ); + state.SetBytesProcessed(num_elements * sizeof(value_type) * + state.iterations()); CUDA_SAFE_CALL(cudaDeviceSynchronize()); CUDA_SAFE_CALL(cudaFree(A.data_handle())); @@ -184,14 +181,16 @@ void BM_MDSpan_CUDA_MatVec_Raw_Right(benchmark::State& state, MDSpanMatrix, DynS CUDA_SAFE_CALL(cudaFree(y.data_handle())); } -BENCHMARK_CAPTURE(BM_MDSpan_CUDA_MatVec_Raw_Right, right, rmdspan(), 100000, 5000); - +BENCHMARK_CAPTURE( + BM_MDSpan_CUDA_MatVec_Raw_Right, right, + rmdspan(), 100000, + 5000); template -void BM_MDSpan_CUDA_MatVec_Raw_Left(benchmark::State& state, MDSpanMatrix, DynSizes... dyn) { - - using value_type = typename MDSpanMatrix::value_type; - using MDSpanVector = lmdspan; +void BM_MDSpan_CUDA_MatVec_Raw_Left(benchmark::State& state, MDSpanMatrix, + DynSizes... dyn) { + using value_type = typename MDSpanMatrix::value_type; + using MDSpanVector = lmdspan; auto A = fill_device_mdspan(MDSpanMatrix{}, dyn...); auto x = fill_device_mdspan(MDSpanVector{}, A.extent(1)); @@ -204,26 +203,26 @@ void BM_MDSpan_CUDA_MatVec_Raw_Left(benchmark::State& state, MDSpanMatrix, DynSi value_type* p_x = x.data_handle(); value_type* p_y = y.data_handle(); - auto lambda = - [=] __device__ { - const size_t i = blockIdx.x * blockDim.x + threadIdx.x; - if(i>=N) return; - value_type y_i = 0; + auto lambda = [=] __device__ { + const size_t i = blockIdx.x * blockDim.x + threadIdx.x; + if (i >= N) return; + value_type y_i = 0; - for(size_t j = 0; j < M; j ++) { - y_i += p_A[i+j*N] * p_x[j]; - } - p_y[i] = y_i; - }; - run_kernel_timed(N,M,lambda); + for (size_t j = 0; j < M; j++) { + y_i += p_A[i + j * N] * p_x[j]; + } + p_y[i] = y_i; + }; + run_kernel_timed(N, M, lambda); for (auto _ : state) { - auto timed = run_kernel_timed(N,M,lambda); + auto timed = run_kernel_timed(N, M, lambda); // units of cuda timer is milliseconds, units of iteration timer is seconds state.SetIterationTime(timed * 1e-3); } size_t num_elements = 2 * A.extent(0) * A.extent(1) + 2 * A.extent(0); - state.SetBytesProcessed( num_elements * sizeof(value_type) * state.iterations()); + state.SetBytesProcessed(num_elements * sizeof(value_type) * + state.iterations()); CUDA_SAFE_CALL(cudaDeviceSynchronize()); CUDA_SAFE_CALL(cudaFree(A.data_handle())); @@ -231,5 +230,8 @@ void BM_MDSpan_CUDA_MatVec_Raw_Left(benchmark::State& state, MDSpanMatrix, DynSi CUDA_SAFE_CALL(cudaFree(y.data_handle())); } -BENCHMARK_CAPTURE(BM_MDSpan_CUDA_MatVec_Raw_Left, left, lmdspan(), 100000, 5000); +BENCHMARK_CAPTURE( + BM_MDSpan_CUDA_MatVec_Raw_Left, left, + lmdspan(), 100000, + 5000); BENCHMARK_MAIN(); diff --git a/benchmarks/matvec/openmp/matvec_openmp.cpp b/benchmarks/matvec/openmp/matvec_openmp.cpp index 0da3fcd9..0ea27d75 100644 --- a/benchmarks/matvec/openmp/matvec_openmp.cpp +++ b/benchmarks/matvec/openmp/matvec_openmp.cpp @@ -18,30 +18,32 @@ static constexpr int global_repeat = 1; using index_type = int; template -using lmdspan = Kokkos::mdspan, Kokkos::layout_left>; +using lmdspan = + Kokkos::mdspan, Kokkos::layout_left>; template -using rmdspan = Kokkos::mdspan, Kokkos::layout_right>; +using rmdspan = + Kokkos::mdspan, Kokkos::layout_right>; -void throw_runtime_exception(const std::string &msg) { +void throw_runtime_exception(const std::string& msg) { std::ostringstream o; o << msg; throw std::runtime_error(o.str()); } -template +template void OpenMP_first_touch_2D(MDSpan s) { - #pragma omp parallel for - for(index_type i = 0; i < s.extent(0); i ++) { - for(index_type j = 0; j < s.extent(1); j ++) { - s(i,j) = 0; +#pragma omp parallel for + for (index_type i = 0; i < s.extent(0); i++) { + for (index_type j = 0; j < s.extent(1); j++) { + s(i, j) = 0; } } } -template +template void OpenMP_first_touch_1D(MDSpan s) { - #pragma omp parallel for - for(index_type i = 0; i < s.extent(0); i ++) { +#pragma omp parallel for + for (index_type i = 0; i < s.extent(0); i++) { s(i) = 0; } } @@ -49,34 +51,37 @@ void OpenMP_first_touch_1D(MDSpan s) { //================================================================================ template -void BM_MDSpan_OpenMP_MatVec(benchmark::State& state, MDSpanMatrix, DynSizes... dyn) { +void BM_MDSpan_OpenMP_MatVec(benchmark::State& state, MDSpanMatrix, + DynSizes... dyn) { + using value_type = typename MDSpanMatrix::value_type; + using MDSpanVector = lmdspan; - using value_type = typename MDSpanMatrix::value_type; - using MDSpanVector = lmdspan; - - auto buffer_size_A = MDSpanMatrix{nullptr, dyn...}.mapping().required_span_size(); + auto buffer_size_A = + MDSpanMatrix{nullptr, dyn...}.mapping().required_span_size(); auto buffer_A = std::make_unique(buffer_size_A); - auto A = MDSpanMatrix{buffer_A.get(), dyn...}; + auto A = MDSpanMatrix{buffer_A.get(), dyn...}; OpenMP_first_touch_2D(A); mdspan_benchmark::fill_random(A); - auto buffer_size_x = MDSpanVector{nullptr, A.extent(1)}.mapping().required_span_size(); + auto buffer_size_x = + MDSpanVector{nullptr, A.extent(1)}.mapping().required_span_size(); auto buffer_x = std::make_unique(buffer_size_x); - auto x = MDSpanVector{buffer_x.get(), A.extent(1)}; + auto x = MDSpanVector{buffer_x.get(), A.extent(1)}; OpenMP_first_touch_1D(x); mdspan_benchmark::fill_random(x); - auto buffer_size_y = MDSpanVector{nullptr, A.extent(0)}.mapping().required_span_size(); + auto buffer_size_y = + MDSpanVector{nullptr, A.extent(0)}.mapping().required_span_size(); auto buffer_y = std::make_unique(buffer_size_y); - auto y = MDSpanVector{buffer_y.get(), A.extent(0)}; + auto y = MDSpanVector{buffer_y.get(), A.extent(0)}; OpenMP_first_touch_1D(y); mdspan_benchmark::fill_random(y); - #pragma omp parallel for - for(index_type i = 0; i < A.extent(0); i ++) { +#pragma omp parallel for + for (index_type i = 0; i < A.extent(0); i++) { value_type y_i = 0; - for(index_type j = 0; j < A.extent(1); j ++) { - y_i += A(i,j) * x(j); + for (index_type j = 0; j < A.extent(1); j++) { + y_i += A(i, j) * x(j); } y(i) = y_i; } @@ -89,48 +94,53 @@ void BM_MDSpan_OpenMP_MatVec(benchmark::State& state, MDSpanMatrix, DynSizes... benchmark::DoNotOptimize(ah); benchmark::DoNotOptimize(yh); benchmark::DoNotOptimize(xh); - for(int r=0; r(), 100000, 5000); BENCHMARK_CAPTURE(BM_MDSpan_OpenMP_MatVec, right, rmdspan(), 100000, 5000); - +// clang-format on template -void BM_MDSpan_OpenMP_MatVec_Raw_Left(benchmark::State& state, MDSpanMatrix, DynSizes... dyn) { - - using value_type = typename MDSpanMatrix::value_type; - using MDSpanVector = lmdspan; +void BM_MDSpan_OpenMP_MatVec_Raw_Left(benchmark::State& state, MDSpanMatrix, + DynSizes... dyn) { + using value_type = typename MDSpanMatrix::value_type; + using MDSpanVector = lmdspan; - auto buffer_size_A = MDSpanMatrix{nullptr, dyn...}.mapping().required_span_size(); + auto buffer_size_A = + MDSpanMatrix{nullptr, dyn...}.mapping().required_span_size(); auto buffer_A = std::make_unique(buffer_size_A); - auto A = MDSpanMatrix{buffer_A.get(), dyn...}; + auto A = MDSpanMatrix{buffer_A.get(), dyn...}; OpenMP_first_touch_2D(A); mdspan_benchmark::fill_random(A); - auto buffer_size_x = MDSpanVector{nullptr, A.extent(1)}.mapping().required_span_size(); + auto buffer_size_x = + MDSpanVector{nullptr, A.extent(1)}.mapping().required_span_size(); auto buffer_x = std::make_unique(buffer_size_x); - auto x = MDSpanVector{buffer_x.get(), A.extent(1)}; + auto x = MDSpanVector{buffer_x.get(), A.extent(1)}; OpenMP_first_touch_1D(x); mdspan_benchmark::fill_random(x); - auto buffer_size_y = MDSpanVector{nullptr, A.extent(0)}.mapping().required_span_size(); + auto buffer_size_y = + MDSpanVector{nullptr, A.extent(0)}.mapping().required_span_size(); auto buffer_y = std::make_unique(buffer_size_y); - auto y = MDSpanVector{buffer_y.get(), A.extent(0)}; + auto y = MDSpanVector{buffer_y.get(), A.extent(0)}; OpenMP_first_touch_1D(y); mdspan_benchmark::fill_random(y); @@ -141,10 +151,10 @@ void BM_MDSpan_OpenMP_MatVec_Raw_Left(benchmark::State& state, MDSpanMatrix, Dyn value_type* p_x = x.data_handle(); value_type* p_y = y.data_handle(); - #pragma omp parallel for - for(index_type i = 0; i < N; i ++) { +#pragma omp parallel for + for (index_type i = 0; i < N; i++) { value_type y_i = 0; - for(index_type j = 0; j < M; j ++) { + for (index_type j = 0; j < M; j++) { y_i += p_A[i + j * N] * x[j]; } y[i] = y_i; @@ -158,46 +168,53 @@ void BM_MDSpan_OpenMP_MatVec_Raw_Left(benchmark::State& state, MDSpanMatrix, Dyn benchmark::DoNotOptimize(ah); benchmark::DoNotOptimize(yh); benchmark::DoNotOptimize(xh); - for(int r=0; r(), 100000, 5000); +BENCHMARK_CAPTURE( + BM_MDSpan_OpenMP_MatVec_Raw_Left, left, + lmdspan(), 100000, + 5000); template -void BM_MDSpan_OpenMP_MatVec_Raw_Right(benchmark::State& state, MDSpanMatrix, DynSizes... dyn) { - - using value_type = typename MDSpanMatrix::value_type; - using MDSpanVector = lmdspan; +void BM_MDSpan_OpenMP_MatVec_Raw_Right(benchmark::State& state, MDSpanMatrix, + DynSizes... dyn) { + using value_type = typename MDSpanMatrix::value_type; + using MDSpanVector = lmdspan; - auto buffer_size_A = MDSpanMatrix{nullptr, dyn...}.mapping().required_span_size(); + auto buffer_size_A = + MDSpanMatrix{nullptr, dyn...}.mapping().required_span_size(); auto buffer_A = std::make_unique(buffer_size_A); - auto A = MDSpanMatrix{buffer_A.get(), dyn...}; + auto A = MDSpanMatrix{buffer_A.get(), dyn...}; OpenMP_first_touch_2D(A); mdspan_benchmark::fill_random(A); - auto buffer_size_x = MDSpanVector{nullptr, A.extent(1)}.mapping().required_span_size(); + auto buffer_size_x = + MDSpanVector{nullptr, A.extent(1)}.mapping().required_span_size(); auto buffer_x = std::make_unique(buffer_size_x); - auto x = MDSpanVector{buffer_x.get(), A.extent(1)}; + auto x = MDSpanVector{buffer_x.get(), A.extent(1)}; OpenMP_first_touch_1D(x); mdspan_benchmark::fill_random(x); - auto buffer_size_y = MDSpanVector{nullptr, A.extent(0)}.mapping().required_span_size(); + auto buffer_size_y = + MDSpanVector{nullptr, A.extent(0)}.mapping().required_span_size(); auto buffer_y = std::make_unique(buffer_size_y); - auto y = MDSpanVector{buffer_y.get(), A.extent(0)}; + auto y = MDSpanVector{buffer_y.get(), A.extent(0)}; OpenMP_first_touch_1D(y); mdspan_benchmark::fill_random(y); @@ -208,10 +225,10 @@ void BM_MDSpan_OpenMP_MatVec_Raw_Right(benchmark::State& state, MDSpanMatrix, Dy value_type* p_x = x.data_handle(); value_type* p_y = y.data_handle(); - #pragma omp parallel for - for(index_type i = 0; i < N; i ++) { +#pragma omp parallel for + for (index_type i = 0; i < N; i++) { value_type y_i = 0; - for(index_type j = 0; j < M; j ++) { + for (index_type j = 0; j < M; j++) { y_i += p_A[i * M + j] * x[j]; } y[i] = y_i; @@ -225,24 +242,28 @@ void BM_MDSpan_OpenMP_MatVec_Raw_Right(benchmark::State& state, MDSpanMatrix, Dy benchmark::DoNotOptimize(ah); benchmark::DoNotOptimize(yh); benchmark::DoNotOptimize(xh); - for(int r=0; r(), 100000, 5000); +BENCHMARK_CAPTURE( + BM_MDSpan_OpenMP_MatVec_Raw_Right, right, + rmdspan(), 100000, + 5000); //================================================================================ diff --git a/benchmarks/stencil/cuda/stencil_3d_cuda.cu b/benchmarks/stencil/cuda/stencil_3d_cuda.cu index cc295735..a52db08f 100644 --- a/benchmarks/stencil/cuda/stencil_3d_cuda.cu +++ b/benchmarks/stencil/cuda/stencil_3d_cuda.cu @@ -9,9 +9,9 @@ // Whether to let mapping convert index calculation to the type used // to index into the mdspan -//#define MDSPAN_IMPL_USE_MAPPING_ARG_CAST +// #define MDSPAN_IMPL_USE_MAPPING_ARG_CAST // Overwrite what extents.extent() returns and what the actual storage type is -//#define MDSPAN_IMPL_OVERWRITE_EXTENTS_SIZE_TYPE int +// #define MDSPAN_IMPL_OVERWRITE_EXTENTS_SIZE_TYPE int // Choose the index type used by the code using idx_t = size_t; @@ -19,25 +19,26 @@ using idx_t = size_t; #include //================================================================================ -static constexpr int global_delta = 1; +static constexpr int global_delta = 1; static constexpr int global_repeat = 16; //================================================================================ template -using lmdspan = Kokkos::mdspan, Kokkos::layout_left>; +using lmdspan = + Kokkos::mdspan, Kokkos::layout_left>; template -using rmdspan = Kokkos::mdspan, Kokkos::layout_right>; +using rmdspan = + Kokkos::mdspan, Kokkos::layout_right>; - -void throw_runtime_exception(const std::string &msg) { +void throw_runtime_exception(const std::string& msg) { std::ostringstream o; o << msg; throw std::runtime_error(o.str()); } void cuda_internal_error_throw(cudaError e, const char* name, - const char* file = NULL, const int line = 0) { + const char* file = NULL, const int line = 0) { std::ostringstream out; out << name << " error( " << cudaGetErrorName(e) << "): " << cudaGetErrorString(e); @@ -48,8 +49,8 @@ void cuda_internal_error_throw(cudaError e, const char* name, } inline void cuda_internal_safe_call(cudaError e, const char* name, - const char* file = NULL, - const int line = 0) { + const char* file = NULL, + const int line = 0) { if (cudaSuccess != e) { cuda_internal_error_throw(e, name, file, line); } @@ -60,20 +61,19 @@ inline void cuda_internal_safe_call(cudaError e, const char* name, //================================================================================ -dim3 get_bench_thread_block(size_t y,size_t z) { +dim3 get_bench_thread_block(size_t y, size_t z) { cudaDeviceProp cudaProp; size_t dim_z = 1; - while(dim_z*3(dim_y), static_cast(dim_z)); } template -__global__ -void do_run_kernel(F f, Args... args) { +__global__ void do_run_kernel(F f, Args... args) { f(args...); } @@ -84,9 +84,7 @@ float run_kernel_timed(size_t N, size_t M, size_t K, F&& f, Args&&... args) { CUDA_SAFE_CALL(cudaEventCreate(&stop)); CUDA_SAFE_CALL(cudaEventRecord(start)); - do_run_kernel<<>>( - (F&&)f, ((Args&&) args)... - ); + do_run_kernel<<>>((F&&)f, ((Args&&)args)...); CUDA_SAFE_CALL(cudaEventRecord(stop)); CUDA_SAFE_CALL(cudaEventSynchronize(stop)); float milliseconds = 0; @@ -96,198 +94,221 @@ float run_kernel_timed(size_t N, size_t M, size_t K, F&& f, Args&&... args) { template MDSpan fill_device_mdspan(MDSpan, DynSizes... dyn) { - using value_type = typename MDSpan::value_type; auto buffer_size = MDSpan{nullptr, dyn...}.mapping().required_span_size(); auto host_buffer = std::make_unique( - MDSpan{nullptr, dyn...}.mapping().required_span_size() - ); + MDSpan{nullptr, dyn...}.mapping().required_span_size()); auto host_mdspan = MDSpan{host_buffer.get(), dyn...}; mdspan_benchmark::fill_random(host_mdspan); value_type* device_buffer = nullptr; CUDA_SAFE_CALL(cudaMalloc(&device_buffer, buffer_size * sizeof(value_type))); - CUDA_SAFE_CALL(cudaMemcpy( - device_buffer, host_buffer.get(), buffer_size * sizeof(value_type), cudaMemcpyHostToDevice - )); + CUDA_SAFE_CALL(cudaMemcpy(device_buffer, host_buffer.get(), + buffer_size * sizeof(value_type), + cudaMemcpyHostToDevice)); return MDSpan{device_buffer, dyn...}; } //================================================================================ template -void BM_MDSpan_Cuda_Stencil_3D(benchmark::State& state, MDSpan, DynSizes... dyn) { - +void BM_MDSpan_Cuda_Stencil_3D(benchmark::State& state, MDSpan, + DynSizes... dyn) { using value_type = typename MDSpan::value_type; - auto s = fill_device_mdspan(MDSpan{}, dyn...); - auto o = fill_device_mdspan(MDSpan{}, dyn...); + auto s = fill_device_mdspan(MDSpan{}, dyn...); + auto o = fill_device_mdspan(MDSpan{}, dyn...); idx_t d = static_cast(global_delta); - int repeats = global_repeat==0? (s.extent(0)*s.extent(1)*s.extent(2) > (100*100*100) ? 50 : 1000) : global_repeat; - - auto lambda = - [=] __device__ { - for(int r = 0; r < repeats; ++r) { - for(idx_t i = blockIdx.x+d; i < static_cast(s.extent(0))-d; i += gridDim.x) { - for(idx_t j = threadIdx.z+d; j < static_cast(s.extent(1))-d; j += blockDim.z) { - for(idx_t k = threadIdx.y+d; k < static_cast(s.extent(2))-d; k += blockDim.y) { - for(int q=0; q<128; q++) { - value_type sum_local = o(i,j,k); - for(idx_t di = i-d; di < i+d+1; di++) { - for(idx_t dj = j-d; dj < j+d+1; dj++) { - for(idx_t dk = k-d; dk < k+d+1; dk++) { - sum_local += s(di, dj, dk); - }}} - o(i,j,k) = sum_local; + int repeats = + global_repeat == 0 + ? (s.extent(0) * s.extent(1) * s.extent(2) > (100 * 100 * 100) ? 50 + : 1000) + : global_repeat; + + auto lambda = [=] __device__ { + for (int r = 0; r < repeats; ++r) { + for (idx_t i = blockIdx.x + d; i < static_cast(s.extent(0)) - d; + i += gridDim.x) { + for (idx_t j = threadIdx.z + d; j < static_cast(s.extent(1)) - d; + j += blockDim.z) { + for (idx_t k = threadIdx.y + d; + k < static_cast(s.extent(2)) - d; k += blockDim.y) { + for (int q = 0; q < 128; q++) { + value_type sum_local = o(i, j, k); + for (idx_t di = i - d; di < i + d + 1; di++) { + for (idx_t dj = j - d; dj < j + d + 1; dj++) { + for (idx_t dk = k - d; dk < k + d + 1; dk++) { + sum_local += s(di, dj, dk); + } } } + o(i, j, k) = sum_local; } } } - }; - run_kernel_timed(s.extent(0),s.extent(1),s.extent(2),lambda); + } + } + }; + run_kernel_timed(s.extent(0), s.extent(1), s.extent(2), lambda); for (auto _ : state) { - auto timed = run_kernel_timed(s.extent(0),s.extent(1),s.extent(2),lambda); + auto timed = + run_kernel_timed(s.extent(0), s.extent(1), s.extent(2), lambda); // units of cuda timer is milliseconds, units of iteration timer is seconds state.SetIterationTime(timed * 1e-3); } - size_t num_inner_elements = (s.extent(0)-d) * (s.extent(1)-d) * (s.extent(2)-d); - size_t stencil_num = (2*d+1) * (2*d+1) * (2*d+1); - state.SetBytesProcessed( num_inner_elements * stencil_num * sizeof(value_type) * state.iterations() * repeats); + size_t num_inner_elements = + (s.extent(0) - d) * (s.extent(1) - d) * (s.extent(2) - d); + size_t stencil_num = (2 * d + 1) * (2 * d + 1) * (2 * d + 1); + state.SetBytesProcessed(num_inner_elements * stencil_num * + sizeof(value_type) * state.iterations() * repeats); state.counters["repeats"] = repeats; CUDA_SAFE_CALL(cudaDeviceSynchronize()); CUDA_SAFE_CALL(cudaFree(s.data_handle())); } + +// clang-format off MDSPAN_BENCHMARK_ALL_3D_MANUAL(BM_MDSpan_Cuda_Stencil_3D, right_, rmdspan, 80, 80, 80); //MDSPAN_BENCHMARK_ALL_3D_MANUAL(BM_MDSpan_Cuda_Stencil_3D, left_, lmdspan, 80, 80, 80); //MDSPAN_BENCHMARK_ALL_3D_MANUAL(BM_MDSpan_Cuda_Stencil_3D, right_, rmdspan, 400, 400, 400); //MDSPAN_BENCHMARK_ALL_3D_MANUAL(BM_MDSpan_Cuda_Stencil_3D, left_, lmdspan, 400, 400, 400); +// clang-format on //================================================================================ template -void BM_Raw_Cuda_Stencil_3D_right(benchmark::State& state, T, SizeX x_, SizeY y_, SizeZ z_) { - +void BM_Raw_Cuda_Stencil_3D_right(benchmark::State& state, T, SizeX x_, + SizeY y_, SizeZ z_) { idx_t d = static_cast(global_delta); idx_t x = static_cast(x_); idx_t y = static_cast(y_); idx_t z = static_cast(z_); - using value_type = T; - value_type* data = nullptr; + using value_type = T; + value_type* data = nullptr; value_type* data_o = nullptr; { // just for setup... auto wrapped = Kokkos::mdspan>{}; - auto s = fill_device_mdspan(wrapped, x*y*z); - data = s.data_handle(); - auto o = fill_device_mdspan(wrapped, x*y*z); - data_o = o.data_handle(); + auto s = fill_device_mdspan(wrapped, x * y * z); + data = s.data_handle(); + auto o = fill_device_mdspan(wrapped, x * y * z); + data_o = o.data_handle(); } - int repeats = global_repeat==0? (x*y*z > (100*100*100) ? 50 : 1000) : global_repeat; - - auto lambda = - [=] __device__ { - for(int r = 0; r < repeats; ++r) { - for(idx_t i = blockIdx.x+d; i < x-d; i += gridDim.x) { - for(idx_t j = threadIdx.z+d; j < y-d; j += blockDim.z) { - for(idx_t k = threadIdx.y+d; k < z-d; k += blockDim.y) { - for(int q=0; q<128; q++) { - value_type sum_local = data_o[k + j*z + i*z*y]; - for(idx_t di = i-d; di < i+d+1; di++) { - for(idx_t dj = j-d; dj < j+d+1; dj++) { - for(idx_t dk = k-d; dk < k+d+1; dk++) { - sum_local += data[dk + dj*z + di*z*y]; - }}} - data_o[k + j*z + i*z*y] = sum_local; + int repeats = global_repeat == 0 ? (x * y * z > (100 * 100 * 100) ? 50 : 1000) + : global_repeat; + + auto lambda = [=] __device__ { + for (int r = 0; r < repeats; ++r) { + for (idx_t i = blockIdx.x + d; i < x - d; i += gridDim.x) { + for (idx_t j = threadIdx.z + d; j < y - d; j += blockDim.z) { + for (idx_t k = threadIdx.y + d; k < z - d; k += blockDim.y) { + for (int q = 0; q < 128; q++) { + value_type sum_local = data_o[k + j * z + i * z * y]; + for (idx_t di = i - d; di < i + d + 1; di++) { + for (idx_t dj = j - d; dj < j + d + 1; dj++) { + for (idx_t dk = k - d; dk < k + d + 1; dk++) { + sum_local += data[dk + dj * z + di * z * y]; + } } } + data_o[k + j * z + i * z * y] = sum_local; } } } - }; - run_kernel_timed(x,y,z,lambda); + } + } + }; + run_kernel_timed(x, y, z, lambda); for (auto _ : state) { - auto timed = run_kernel_timed(x,y,z,lambda); + auto timed = run_kernel_timed(x, y, z, lambda); // units of cuda timer is milliseconds, units of iteration timer is seconds state.SetIterationTime(timed * 1e-3); } - size_t num_inner_elements = (x-d) * (y-d) * (z-d); - size_t stencil_num = (2*d+1) * (2*d+1) * (2*d+1); - state.SetBytesProcessed( num_inner_elements * stencil_num * sizeof(value_type) * state.iterations() * repeats); + size_t num_inner_elements = (x - d) * (y - d) * (z - d); + size_t stencil_num = (2 * d + 1) * (2 * d + 1) * (2 * d + 1); + state.SetBytesProcessed(num_inner_elements * stencil_num * + sizeof(value_type) * state.iterations() * repeats); state.counters["repeats"] = repeats; CUDA_SAFE_CALL(cudaDeviceSynchronize()); CUDA_SAFE_CALL(cudaFree(data)); } -BENCHMARK_CAPTURE(BM_Raw_Cuda_Stencil_3D_right, size_80_80_80, int(), 80, 80, 80); -BENCHMARK_CAPTURE(BM_Raw_Cuda_Stencil_3D_right, size_400_400_400, int(), 400, 400, 400); +BENCHMARK_CAPTURE(BM_Raw_Cuda_Stencil_3D_right, size_80_80_80, int(), 80, 80, + 80); +BENCHMARK_CAPTURE(BM_Raw_Cuda_Stencil_3D_right, size_400_400_400, int(), 400, + 400, 400); //================================================================================ template -void BM_Raw_Cuda_Stencil_3D_left(benchmark::State& state, T, SizeX x_, SizeY y_, SizeZ z_) { - +void BM_Raw_Cuda_Stencil_3D_left(benchmark::State& state, T, SizeX x_, SizeY y_, + SizeZ z_) { idx_t d = static_cast(global_delta); idx_t x = static_cast(x_); idx_t y = static_cast(y_); idx_t z = static_cast(z_); - using value_type = T; - value_type* data = nullptr; + using value_type = T; + value_type* data = nullptr; value_type* data_o = nullptr; { // just for setup... - auto wrapped = Kokkos::mdspan>{}; - auto s = fill_device_mdspan(wrapped, x*y*z); - data = s.data_handle(); - auto o = fill_device_mdspan(wrapped, x*y*z); - data_o = o.data_handle(); + auto wrapped = Kokkos::mdspan>{}; + auto s = fill_device_mdspan(wrapped, x * y * z); + data = s.data_handle(); + auto o = fill_device_mdspan(wrapped, x * y * z); + data_o = o.data_handle(); } - int repeats = global_repeat==0? (x*y*z > (100*100*100) ? 50 : 1000) : global_repeat; - auto lambda = - [=] __device__ { - for(int r = 0; r < repeats; ++r) { - for(idx_t i = blockIdx.x+d; i < x-d; i += gridDim.x) { - for(idx_t j = threadIdx.z+d; j < y-d; j += blockDim.z) { - for(idx_t k = threadIdx.y+d; k < z-d; k += blockDim.y) { - for(int q=0; q<128; q++) { - value_type sum_local = data_o[k*x*y + j*x + i]; - for(idx_t di = i-d; di < i+d+1; di++) { - for(idx_t dj = j-d; dj < j+d+1; dj++) { - for(idx_t dk = k-d; dk < k+d+1; dk++) { - sum_local += data[dk*x*y + dj*x + di]; - }}} - data_o[k*x*y + j*x + i] = sum_local; + int repeats = global_repeat == 0 ? (x * y * z > (100 * 100 * 100) ? 50 : 1000) + : global_repeat; + auto lambda = [=] __device__ { + for (int r = 0; r < repeats; ++r) { + for (idx_t i = blockIdx.x + d; i < x - d; i += gridDim.x) { + for (idx_t j = threadIdx.z + d; j < y - d; j += blockDim.z) { + for (idx_t k = threadIdx.y + d; k < z - d; k += blockDim.y) { + for (int q = 0; q < 128; q++) { + value_type sum_local = data_o[k * x * y + j * x + i]; + for (idx_t di = i - d; di < i + d + 1; di++) { + for (idx_t dj = j - d; dj < j + d + 1; dj++) { + for (idx_t dk = k - d; dk < k + d + 1; dk++) { + sum_local += data[dk * x * y + dj * x + di]; + } } + } + data_o[k * x * y + j * x + i] = sum_local; } } } } - }; + } + }; - run_kernel_timed(x,y,z,lambda); + run_kernel_timed(x, y, z, lambda); for (auto _ : state) { - auto timed = run_kernel_timed(x,y,z,lambda); + auto timed = run_kernel_timed(x, y, z, lambda); // units of cuda timer is milliseconds, units of iteration timer is seconds state.SetIterationTime(timed * 1e-3); } - size_t num_inner_elements = (x-d) * (y-d) * (z-d); - size_t stencil_num = (2*d+1) * (2*d+1) * (2*d+1); - state.SetBytesProcessed( num_inner_elements * stencil_num * sizeof(value_type) * state.iterations() * repeats); + size_t num_inner_elements = (x - d) * (y - d) * (z - d); + size_t stencil_num = (2 * d + 1) * (2 * d + 1) * (2 * d + 1); + state.SetBytesProcessed(num_inner_elements * stencil_num * + sizeof(value_type) * state.iterations() * repeats); state.counters["repeats"] = repeats; CUDA_SAFE_CALL(cudaDeviceSynchronize()); CUDA_SAFE_CALL(cudaFree(data)); } + +// clang-format off BENCHMARK_CAPTURE(BM_Raw_Cuda_Stencil_3D_left, size_80_80_80, int(), 80, 80, 80); //BENCHMARK_CAPTURE(BM_Raw_Cuda_Stencil_3D_left, size_400_400_400, int(), 400, 400, 400); +// clang-format on //================================================================================ diff --git a/benchmarks/stencil/openmp/stencil_3d_openmp.cpp b/benchmarks/stencil/openmp/stencil_3d_openmp.cpp index 0810e045..7bc89956 100644 --- a/benchmarks/stencil/openmp/stencil_3d_openmp.cpp +++ b/benchmarks/stencil/openmp/stencil_3d_openmp.cpp @@ -23,23 +23,25 @@ static constexpr int global_delta = 1; using index_type = int; template -using lmdspan = Kokkos::mdspan, Kokkos::layout_left>; +using lmdspan = + Kokkos::mdspan, Kokkos::layout_left>; template -using rmdspan = Kokkos::mdspan, Kokkos::layout_right>; +using rmdspan = + Kokkos::mdspan, Kokkos::layout_right>; -void throw_runtime_exception(const std::string &msg) { +void throw_runtime_exception(const std::string& msg) { std::ostringstream o; o << msg; throw std::runtime_error(o.str()); } -template +template void OpenMP_first_touch_3D(MDSpan s) { - #pragma omp parallel for - for(index_type i = 0; i < s.extent(0); i ++) { - for(index_type j = 0; j < s.extent(1); j ++) { - for(index_type k = 0; k < s.extent(2); k ++) { - s(i,j,k) = 0; +#pragma omp parallel for + for (index_type i = 0; i < s.extent(0); i++) { + for (index_type j = 0; j < s.extent(1); j++) { + for (index_type k = 0; k < s.extent(2); k++) { + s(i, j, k) = 0; } } } @@ -48,266 +50,298 @@ void OpenMP_first_touch_3D(MDSpan s) { //================================================================================ template -void BM_MDSpan_OpenMP_Stencil_3D(benchmark::State& state, MDSpan, DynSizes... dyn) { - +void BM_MDSpan_OpenMP_Stencil_3D(benchmark::State& state, MDSpan, + DynSizes... dyn) { using value_type = typename MDSpan::value_type; auto buffer_size = MDSpan{nullptr, dyn...}.mapping().required_span_size(); auto buffer_s = std::make_unique(buffer_size); - auto s = MDSpan{buffer_s.get(), dyn...}; + auto s = MDSpan{buffer_s.get(), dyn...}; OpenMP_first_touch_3D(s); mdspan_benchmark::fill_random(s); auto buffer_o = std::make_unique(buffer_size); - auto o = MDSpan{buffer_o.get(), dyn...}; + auto o = MDSpan{buffer_o.get(), dyn...}; OpenMP_first_touch_3D(o); mdspan_benchmark::fill_random(o); int d = global_delta; - #pragma omp parallel for - for(index_type i = d; i < s.extent(0)-d; i ++) { - for(index_type j = d; j < s.extent(1)-d; j ++) { - for(index_type k = d; k < s.extent(2)-d; k ++) { +#pragma omp parallel for + for (index_type i = d; i < s.extent(0) - d; i++) { + for (index_type j = d; j < s.extent(1) - d; j++) { + for (index_type k = d; k < s.extent(2) - d; k++) { value_type sum_local = 0; - for(index_type di = i-d; di < i+d+1; di++) { - for(index_type dj = j-d; dj < j+d+1; dj++) { - for(index_type dk = k-d; dk < k+d+1; dk++) { - sum_local += s(di, dj, dk); - }}} - o(i,j,k) = sum_local; + for (index_type di = i - d; di < i + d + 1; di++) { + for (index_type dj = j - d; dj < j + d + 1; dj++) { + for (index_type dk = k - d; dk < k + d + 1; dk++) { + sum_local += s(di, dj, dk); + } + } + } + o(i, j, k) = sum_local; } } } for (auto _ : state) { - #pragma omp parallel for - for(index_type i = d; i < s.extent(0)-d; i ++) { - for(index_type j = d; j < s.extent(1)-d; j ++) { - for(index_type k = d; k < s.extent(2)-d; k ++) { +#pragma omp parallel for + for (index_type i = d; i < s.extent(0) - d; i++) { + for (index_type j = d; j < s.extent(1) - d; j++) { + for (index_type k = d; k < s.extent(2) - d; k++) { value_type sum_local = 0; - for(index_type di = i-d; di < i+d+1; di++) { - for(index_type dj = j-d; dj < j+d+1; dj++) { - for(index_type dk = k-d; dk < k+d+1; dk++) { - sum_local += s(di, dj, dk); - }}} - o(i,j,k) = sum_local; + for (index_type di = i - d; di < i + d + 1; di++) { + for (index_type dj = j - d; dj < j + d + 1; dj++) { + for (index_type dk = k - d; dk < k + d + 1; dk++) { + sum_local += s(di, dj, dk); + } + } + } + o(i, j, k) = sum_local; } } } } - size_t num_inner_elements = (s.extent(0)-d) * (s.extent(1)-d) * (s.extent(2)-d); - size_t stencil_num = (2*d+1) * (2*d+1) * (2*d+1); - state.SetBytesProcessed( num_inner_elements * stencil_num * sizeof(value_type) * state.iterations()); + size_t num_inner_elements = + (s.extent(0) - d) * (s.extent(1) - d) * (s.extent(2) - d); + size_t stencil_num = (2 * d + 1) * (2 * d + 1) * (2 * d + 1); + state.SetBytesProcessed(num_inner_elements * stencil_num * + sizeof(value_type) * state.iterations()); } +// clang-format off MDSPAN_BENCHMARK_ALL_3D(BM_MDSpan_OpenMP_Stencil_3D, right_, rmdspan, 80, 80, 80); MDSPAN_BENCHMARK_ALL_3D(BM_MDSpan_OpenMP_Stencil_3D, left_, lmdspan, 80, 80, 80); MDSPAN_BENCHMARK_ALL_3D(BM_MDSpan_OpenMP_Stencil_3D, right_, rmdspan, 400, 400, 400); MDSPAN_BENCHMARK_ALL_3D(BM_MDSpan_OpenMP_Stencil_3D, left_, lmdspan, 400, 400, 400); +// clang-format on //================================================================================ template -void BM_Raw_OpenMP_Stencil_3D_right(benchmark::State& state, T, SizeX x, SizeY y, SizeZ z) { - - using MDSpan = Kokkos::mdspan>; +void BM_Raw_OpenMP_Stencil_3D_right(benchmark::State& state, T, SizeX x, + SizeY y, SizeZ z) { + using MDSpan = Kokkos::mdspan>; using value_type = typename MDSpan::value_type; - auto buffer_size = MDSpan{nullptr, x,y,z}.mapping().required_span_size(); + auto buffer_size = MDSpan{nullptr, x, y, z}.mapping().required_span_size(); auto buffer_s = std::make_unique(buffer_size); - auto s = MDSpan{buffer_s.get(), x,y,z}; + auto s = MDSpan{buffer_s.get(), x, y, z}; OpenMP_first_touch_3D(s); mdspan_benchmark::fill_random(s); T* s_ptr = s.data_handle(); auto buffer_o = std::make_unique(buffer_size); - auto o = MDSpan{buffer_o.get(), x,y,z}; + auto o = MDSpan{buffer_o.get(), x, y, z}; OpenMP_first_touch_3D(o); mdspan_benchmark::fill_random(o); T* o_ptr = o.data_handle(); int d = global_delta; - #pragma omp parallel for - for(index_type i = d; i < x-d; i ++) { - for(index_type j = d; j < y-d; j ++) { - for(index_type k = d; k < z-d; k ++) { +#pragma omp parallel for + for (index_type i = d; i < x - d; i++) { + for (index_type j = d; j < y - d; j++) { + for (index_type k = d; k < z - d; k++) { value_type sum_local = 0; - for(index_type di = i-d; di < i+d+1; di++) { - for(index_type dj = j-d; dj < j+d+1; dj++) { - for(index_type dk = k-d; dk < k+d+1; dk++) { - sum_local += s_ptr[dk + dj*z + di*z*y]; - }}} - o_ptr[k + j*z + i*z*y] = sum_local; + for (index_type di = i - d; di < i + d + 1; di++) { + for (index_type dj = j - d; dj < j + d + 1; dj++) { + for (index_type dk = k - d; dk < k + d + 1; dk++) { + sum_local += s_ptr[dk + dj * z + di * z * y]; + } + } + } + o_ptr[k + j * z + i * z * y] = sum_local; } } } for (auto _ : state) { - #pragma omp parallel for - for(index_type i = d; i < x-d; i ++) { - for(index_type j = d; j < y-d; j ++) { - for(index_type k = d; k < z-d; k ++) { +#pragma omp parallel for + for (index_type i = d; i < x - d; i++) { + for (index_type j = d; j < y - d; j++) { + for (index_type k = d; k < z - d; k++) { value_type sum_local = 0; - for(index_type di = i-d; di < i+d+1; di++) { - for(index_type dj = j-d; dj < j+d+1; dj++) { - for(index_type dk = k-d; dk < k+d+1; dk++) { - sum_local += s_ptr[dk + dj*z + di*z*y]; - }}} - o_ptr[k + j*z + i*z*y] = sum_local; + for (index_type di = i - d; di < i + d + 1; di++) { + for (index_type dj = j - d; dj < j + d + 1; dj++) { + for (index_type dk = k - d; dk < k + d + 1; dk++) { + sum_local += s_ptr[dk + dj * z + di * z * y]; + } + } + } + o_ptr[k + j * z + i * z * y] = sum_local; } } } } - size_t num_inner_elements = (s.extent(0)-d) * (s.extent(1)-d) * (s.extent(2)-d); - size_t stencil_num = (2*d+1) * (2*d+1) * (2*d+1); - state.SetBytesProcessed( num_inner_elements * stencil_num * sizeof(value_type) * state.iterations()); + size_t num_inner_elements = + (s.extent(0) - d) * (s.extent(1) - d) * (s.extent(2) - d); + size_t stencil_num = (2 * d + 1) * (2 * d + 1) * (2 * d + 1); + state.SetBytesProcessed(num_inner_elements * stencil_num * + sizeof(value_type) * state.iterations()); } +// clang-format off BENCHMARK_CAPTURE(BM_Raw_OpenMP_Stencil_3D_right, size_80_80_80, int(), 80, 80, 80); BENCHMARK_CAPTURE(BM_Raw_OpenMP_Stencil_3D_right, size_400_400_400, int(), 400, 400, 400); +// clang-format on //================================================================================ template -void BM_Raw_OpenMP_Stencil_3D_left(benchmark::State& state, T, SizeX x, SizeY y, SizeZ z) { - - using MDSpan = Kokkos::mdspan>; +void BM_Raw_OpenMP_Stencil_3D_left(benchmark::State& state, T, SizeX x, SizeY y, + SizeZ z) { + using MDSpan = Kokkos::mdspan>; using value_type = typename MDSpan::value_type; - auto buffer_size = MDSpan{nullptr, x,y,z}.mapping().required_span_size(); + auto buffer_size = MDSpan{nullptr, x, y, z}.mapping().required_span_size(); auto buffer_s = std::make_unique(buffer_size); - auto s = MDSpan{buffer_s.get(), x,y,z}; + auto s = MDSpan{buffer_s.get(), x, y, z}; OpenMP_first_touch_3D(s); mdspan_benchmark::fill_random(s); T* s_ptr = s.data_handle(); auto buffer_o = std::make_unique(buffer_size); - auto o = MDSpan{buffer_o.get(), x,y,z}; + auto o = MDSpan{buffer_o.get(), x, y, z}; OpenMP_first_touch_3D(o); mdspan_benchmark::fill_random(o); T* o_ptr = o.data_handle(); int d = global_delta; - #pragma omp parallel for - for(index_type i = d; i < x-d; i ++) { - for(index_type j = d; j < y-d; j ++) { - for(index_type k = d; k < z-d; k ++) { +#pragma omp parallel for + for (index_type i = d; i < x - d; i++) { + for (index_type j = d; j < y - d; j++) { + for (index_type k = d; k < z - d; k++) { value_type sum_local = 0; - for(index_type di = i-d; di < i+d+1; di++) { - for(index_type dj = j-d; dj < j+d+1; dj++) { - for(index_type dk = k-d; dk < k+d+1; dk++) { - sum_local += s_ptr[dk*x*y + dj*x + di]; - }}} - o_ptr[k*x*y + j*x + i] = sum_local; + for (index_type di = i - d; di < i + d + 1; di++) { + for (index_type dj = j - d; dj < j + d + 1; dj++) { + for (index_type dk = k - d; dk < k + d + 1; dk++) { + sum_local += s_ptr[dk * x * y + dj * x + di]; + } + } + } + o_ptr[k * x * y + j * x + i] = sum_local; } } } for (auto _ : state) { - #pragma omp parallel for - for(index_type i = d; i < x-d; i ++) { - for(index_type j = d; j < y-d; j ++) { - for(index_type k = d; k < z-d; k ++) { +#pragma omp parallel for + for (index_type i = d; i < x - d; i++) { + for (index_type j = d; j < y - d; j++) { + for (index_type k = d; k < z - d; k++) { value_type sum_local = 0; - for(index_type di = i-d; di < i+d+1; di++) { - for(index_type dj = j-d; dj < j+d+1; dj++) { - for(index_type dk = k-d; dk < k+d+1; dk++) { - sum_local += s_ptr[dk*x*y + dj*x + di]; - }}} - o_ptr[k*x*y + j*x + i] = sum_local; + for (index_type di = i - d; di < i + d + 1; di++) { + for (index_type dj = j - d; dj < j + d + 1; dj++) { + for (index_type dk = k - d; dk < k + d + 1; dk++) { + sum_local += s_ptr[dk * x * y + dj * x + di]; + } + } + } + o_ptr[k * x * y + j * x + i] = sum_local; } } } } - size_t num_inner_elements = (s.extent(0)-d) * (s.extent(1)-d) * (s.extent(2)-d); - size_t stencil_num = (2*d+1) * (2*d+1) * (2*d+1); - state.SetBytesProcessed( num_inner_elements * stencil_num * sizeof(value_type) * state.iterations()); + size_t num_inner_elements = + (s.extent(0) - d) * (s.extent(1) - d) * (s.extent(2) - d); + size_t stencil_num = (2 * d + 1) * (2 * d + 1) * (2 * d + 1); + state.SetBytesProcessed(num_inner_elements * stencil_num * + sizeof(value_type) * state.iterations()); } +// clang-format off BENCHMARK_CAPTURE(BM_Raw_OpenMP_Stencil_3D_left, size_80_80_80, int(), 80, 80, 80); BENCHMARK_CAPTURE(BM_Raw_OpenMP_Stencil_3D_left, size_400_400_400, int(), 400, 400, 400); +// clang-format on template typename MDSpan::value_type*** make_3d_ptr_array(MDSpan s) { - static_assert(std::is_same::value,"Creating MD Ptr only works from mdspan with layout_right"); - using value_type = typename MDSpan::value_type; - value_type*** ptr= new value_type**[s.extent(0)]; - for(index_type i = 0; i::value, + "Creating MD Ptr only works from mdspan with layout_right"); + using value_type = typename MDSpan::value_type; + value_type*** ptr = new value_type**[s.extent(0)]; + for (index_type i = 0; i < s.extent(0); i++) { ptr[i] = new value_type*[s.extent(1)]; - for(index_type j = 0; j void free_3d_ptr_array(T*** ptr, size_t extent_0) { - for(size_t i=0; i -void BM_RawMDPtr_OpenMP_Stencil_3D_right(benchmark::State& state, T, SizeX x, SizeY y, SizeZ z) { - - using MDSpan = Kokkos::mdspan>; +void BM_RawMDPtr_OpenMP_Stencil_3D_right(benchmark::State& state, T, SizeX x, + SizeY y, SizeZ z) { + using MDSpan = Kokkos::mdspan>; using value_type = typename MDSpan::value_type; - auto buffer_size = MDSpan{nullptr, x,y,z}.mapping().required_span_size(); + auto buffer_size = MDSpan{nullptr, x, y, z}.mapping().required_span_size(); auto buffer_s = std::make_unique(buffer_size); - auto s = MDSpan{buffer_s.get(), x,y,z}; + auto s = MDSpan{buffer_s.get(), x, y, z}; OpenMP_first_touch_3D(s); mdspan_benchmark::fill_random(s); T*** s_ptr = make_3d_ptr_array(s); auto buffer_o = std::make_unique(buffer_size); - auto o = MDSpan{buffer_o.get(), x,y,z}; + auto o = MDSpan{buffer_o.get(), x, y, z}; OpenMP_first_touch_3D(o); mdspan_benchmark::fill_random(o); T*** o_ptr = make_3d_ptr_array(o); int d = global_delta; - #pragma omp parallel for - for(index_type i = d; i < x-d; i ++) { - for(index_type j = d; j < y-d; j ++) { - for(index_type k = d; k < z-d; k ++) { +#pragma omp parallel for + for (index_type i = d; i < x - d; i++) { + for (index_type j = d; j < y - d; j++) { + for (index_type k = d; k < z - d; k++) { value_type sum_local = 0; - for(index_type di = i-d; di < i+d+1; di++) { - for(index_type dj = j-d; dj < j+d+1; dj++) { - for(index_type dk = k-d; dk < k+d+1; dk++) { - sum_local += s_ptr[0][0][0]; - }}} + for (index_type di = i - d; di < i + d + 1; di++) { + for (index_type dj = j - d; dj < j + d + 1; dj++) { + for (index_type dk = k - d; dk < k + d + 1; dk++) { + sum_local += s_ptr[0][0][0]; + } + } + } o_ptr[i][j][k] = sum_local; } } } for (auto _ : state) { - #pragma omp parallel for - for(index_type i = d; i < x-d; i ++) { - for(index_type j = d; j < y-d; j ++) { - for(index_type k = d; k < z-d; k ++) { +#pragma omp parallel for + for (index_type i = d; i < x - d; i++) { + for (index_type j = d; j < y - d; j++) { + for (index_type k = d; k < z - d; k++) { value_type sum_local = 0; - for(index_type di = i-d; di < i+d+1; di++) { - for(index_type dj = j-d; dj < j+d+1; dj++) { - for(index_type dk = k-d; dk < k+d+1; dk++) { - sum_local += s_ptr[di][dj][dk]; - }}} + for (index_type di = i - d; di < i + d + 1; di++) { + for (index_type dj = j - d; dj < j + d + 1; dj++) { + for (index_type dk = k - d; dk < k + d + 1; dk++) { + sum_local += s_ptr[di][dj][dk]; + } + } + } o_ptr[i][j][k] = sum_local; } } } } - size_t num_inner_elements = (s.extent(0)-d) * (s.extent(1)-d) * (s.extent(2)-d); - size_t stencil_num = (2*d+1) * (2*d+1) * (2*d+1); - state.SetBytesProcessed( num_inner_elements * stencil_num * sizeof(value_type) * state.iterations()); - free_3d_ptr_array(s_ptr,s.extent(0)); - free_3d_ptr_array(o_ptr,o.extent(0)); + size_t num_inner_elements = + (s.extent(0) - d) * (s.extent(1) - d) * (s.extent(2) - d); + size_t stencil_num = (2 * d + 1) * (2 * d + 1) * (2 * d + 1); + state.SetBytesProcessed(num_inner_elements * stencil_num * + sizeof(value_type) * state.iterations()); + free_3d_ptr_array(s_ptr, s.extent(0)); + free_3d_ptr_array(o_ptr, o.extent(0)); } +// clang-format off BENCHMARK_CAPTURE(BM_RawMDPtr_OpenMP_Stencil_3D_right, size_80_80_80, int(), 80, 80, 80); BENCHMARK_CAPTURE(BM_RawMDPtr_OpenMP_Stencil_3D_right, size_400_400_400, int(), 400, 400, 400); +// clang-format on //================================================================================ BENCHMARK_MAIN(); diff --git a/benchmarks/stencil/stencil_3d.cpp b/benchmarks/stencil/stencil_3d.cpp index b884dc9f..2fe47507 100644 --- a/benchmarks/stencil/stencil_3d.cpp +++ b/benchmarks/stencil/stencil_3d.cpp @@ -21,24 +21,25 @@ static constexpr int global_delta = 1; using index_type = int; template -using lmdspan = Kokkos::mdspan, Kokkos::layout_left>; +using lmdspan = + Kokkos::mdspan, Kokkos::layout_left>; template -using rmdspan = Kokkos::mdspan, Kokkos::layout_right>; +using rmdspan = + Kokkos::mdspan, Kokkos::layout_right>; //================================================================================ template void BM_MDSpan_Stencil_3D(benchmark::State& state, MDSpan, DynSizes... dyn) { - using value_type = typename MDSpan::value_type; auto buffer_size = MDSpan{nullptr, dyn...}.mapping().required_span_size(); auto buffer_s = std::make_unique(buffer_size); - auto s = MDSpan{buffer_s.get(), dyn...}; + auto s = MDSpan{buffer_s.get(), dyn...}; mdspan_benchmark::fill_random(s); auto buffer_o = std::make_unique(buffer_size); - auto o = MDSpan{buffer_o.get(), dyn...}; + auto o = MDSpan{buffer_o.get(), dyn...}; mdspan_benchmark::fill_random(o); int d = global_delta; @@ -46,40 +47,47 @@ void BM_MDSpan_Stencil_3D(benchmark::State& state, MDSpan, DynSizes... dyn) { using index_type = typename MDSpan::index_type; for (auto _ : state) { benchmark::DoNotOptimize(o); - for(index_type i = d; i < s.extent(0)-d; i ++) { - for(index_type j = d; j < s.extent(1)-d; j ++) { - for(index_type k = d; k < s.extent(2)-d; k ++) { + for (index_type i = d; i < s.extent(0) - d; i++) { + for (index_type j = d; j < s.extent(1) - d; j++) { + for (index_type k = d; k < s.extent(2) - d; k++) { value_type sum_local = 0; - for(index_type di = i-d; di < i+d+1; di++) { - for(index_type dj = j-d; dj < j+d+1; dj++) { - for(index_type dk = k-d; dk < k+d+1; dk++) { - sum_local += s(di, dj, dk); - }}} - o(i,j,k) = sum_local; + for (index_type di = i - d; di < i + d + 1; di++) { + for (index_type dj = j - d; dj < j + d + 1; dj++) { + for (index_type dk = k - d; dk < k + d + 1; dk++) { + sum_local += s(di, dj, dk); + } + } + } + o(i, j, k) = sum_local; } } } benchmark::ClobberMemory(); } - size_t num_inner_elements = (s.extent(0)-d) * (s.extent(1)-d) * (s.extent(2)-d); - size_t stencil_num = (2*d+1) * (2*d+1) * (2*d+1); - state.SetBytesProcessed( num_inner_elements * stencil_num * sizeof(value_type) * state.iterations()); + size_t num_inner_elements = + (s.extent(0) - d) * (s.extent(1) - d) * (s.extent(2) - d); + size_t stencil_num = (2 * d + 1) * (2 * d + 1) * (2 * d + 1); + state.SetBytesProcessed(num_inner_elements * stencil_num * + sizeof(value_type) * state.iterations()); } + +// clang-format off MDSPAN_BENCHMARK_ALL_3D(BM_MDSpan_Stencil_3D, right_, rmdspan, 80, 80, 80); MDSPAN_BENCHMARK_ALL_3D(BM_MDSpan_Stencil_3D, left_, lmdspan, 80, 80, 80); MDSPAN_BENCHMARK_ALL_3D(BM_MDSpan_Stencil_3D, right_, rmdspan, 400, 400, 400); MDSPAN_BENCHMARK_ALL_3D(BM_MDSpan_Stencil_3D, left_, lmdspan, 400, 400, 400); +// clang-format on //================================================================================ template -void BM_Raw_Stencil_3D_right(benchmark::State& state, T, SizeX x, SizeY y, SizeZ z) { - - using MDSpan = Kokkos::mdspan>; +void BM_Raw_Stencil_3D_right(benchmark::State& state, T, SizeX x, SizeY y, + SizeZ z) { + using MDSpan = Kokkos::mdspan>; using value_type = typename MDSpan::value_type; - auto buffer_size = MDSpan{nullptr, x,y,z}.mapping().required_span_size(); + auto buffer_size = MDSpan{nullptr, x, y, z}.mapping().required_span_size(); - T* s_ptr = nullptr; + T* s_ptr = nullptr; auto buffer_s = std::make_unique(buffer_size); { auto s = MDSpan{buffer_s.get(), x, y, z}; @@ -87,7 +95,7 @@ void BM_Raw_Stencil_3D_right(benchmark::State& state, T, SizeX x, SizeY y, SizeZ s_ptr = s.data_handle(); } - T* o_ptr = nullptr; + T* o_ptr = nullptr; auto buffer_o = std::make_unique(buffer_size); { auto o = MDSpan{buffer_o.get(), x, y, z}; @@ -99,27 +107,32 @@ void BM_Raw_Stencil_3D_right(benchmark::State& state, T, SizeX x, SizeY y, SizeZ for (auto _ : state) { benchmark::DoNotOptimize(o_ptr); - for(size_t i = d; i < x-d; i ++) { - for(size_t j = d; j < y-d; j ++) { - for(size_t k = d; k < z-d; k ++) { + for (size_t i = d; i < x - d; i++) { + for (size_t j = d; j < y - d; j++) { + for (size_t k = d; k < z - d; k++) { value_type sum_local = 0; - for(size_t di = i-d; di < i+d+1; di++) { - for(size_t dj = j-d; dj < j+d+1; dj++) { - for(size_t dk = k-d; dk < k+d+1; dk++) { - sum_local += s_ptr[dk + dj*z + di*z*y]; - }}} - o_ptr[k + j*z + i*z*y] = sum_local; + for (size_t di = i - d; di < i + d + 1; di++) { + for (size_t dj = j - d; dj < j + d + 1; dj++) { + for (size_t dk = k - d; dk < k + d + 1; dk++) { + sum_local += s_ptr[dk + dj * z + di * z * y]; + } + } + } + o_ptr[k + j * z + i * z * y] = sum_local; } } } benchmark::ClobberMemory(); } - size_t num_inner_elements = (x-d) * (y-d) * (z-d); - size_t stencil_num = (2*d+1) * (2*d+1) * (2*d+1); - state.SetBytesProcessed( num_inner_elements * stencil_num * sizeof(value_type) * state.iterations()); + size_t num_inner_elements = (x - d) * (y - d) * (z - d); + size_t stencil_num = (2 * d + 1) * (2 * d + 1) * (2 * d + 1); + state.SetBytesProcessed(num_inner_elements * stencil_num * + sizeof(value_type) * state.iterations()); } +// clang-format off BENCHMARK_CAPTURE(BM_Raw_Stencil_3D_right, size_80_80_80, int(), size_t(80), size_t(80), size_t(80)); BENCHMARK_CAPTURE(BM_Raw_Stencil_3D_right, size_400_400_400, int(), size_t(400), size_t(400), size_t(400)); +// clang-format on //================================================================================ diff --git a/benchmarks/sum/cuda/sum_3d_cuda.cu b/benchmarks/sum/cuda/sum_3d_cuda.cu index 1d3d37e0..12d05445 100644 --- a/benchmarks/sum/cuda/sum_3d_cuda.cu +++ b/benchmarks/sum/cuda/sum_3d_cuda.cu @@ -18,36 +18,36 @@ static constexpr int warpsPerBlock = 4; //================================================================================ template -using lmdspan = Kokkos::mdspan, Kokkos::layout_left>; +using lmdspan = + Kokkos::mdspan, Kokkos::layout_left>; template -using rmdspan = Kokkos::mdspan, Kokkos::layout_right>; +using rmdspan = + Kokkos::mdspan, Kokkos::layout_right>; //================================================================================ template -MDSPAN_FORCE_INLINE_FUNCTION inline -void DoNotOptimize(Tp const& value) { +MDSPAN_FORCE_INLINE_FUNCTION inline void DoNotOptimize(Tp const& value) { // Can't have m constraints on device asm volatile("" : : "r"(value) : "memory"); } template -MDSPAN_FORCE_INLINE_FUNCTION inline -void DoNotOptimize(Tp& value) { +MDSPAN_FORCE_INLINE_FUNCTION inline void DoNotOptimize(Tp& value) { // Can't have m constraints on device asm volatile("" : "+r"(value) : : "memory"); } //================================================================================ -void throw_runtime_exception(const std::string &msg) { +void throw_runtime_exception(const std::string& msg) { std::ostringstream o; o << msg; throw std::runtime_error(o.str()); } void cuda_internal_error_throw(cudaError e, const char* name, - const char* file = NULL, const int line = 0) { + const char* file = NULL, const int line = 0) { std::ostringstream out; out << name << " error( " << cudaGetErrorName(e) << "): " << cudaGetErrorString(e); @@ -58,8 +58,8 @@ void cuda_internal_error_throw(cudaError e, const char* name, } inline void cuda_internal_safe_call(cudaError e, const char* name, - const char* file = NULL, - const int line = 0) { + const char* file = NULL, + const int line = 0) { if (cudaSuccess != e) { cuda_internal_error_throw(e, name, file, line); } @@ -83,8 +83,7 @@ dim3 get_bench_thread_block() { } template -__global__ -void do_run_kernel(F f, Args... args) { +__global__ void do_run_kernel(F f, Args... args) { f(args...); } @@ -96,8 +95,7 @@ float run_kernel_timed(F&& f, Args&&... args) { CUDA_SAFE_CALL(cudaEventRecord(start)); do_run_kernel<<>>( - (F&&)f, ((Args&&) args)... - ); + (F&&)f, ((Args&&)args)...); CUDA_SAFE_CALL(cudaEventRecord(stop)); CUDA_SAFE_CALL(cudaEventSynchronize(stop)); float milliseconds = 0; @@ -107,20 +105,18 @@ float run_kernel_timed(F&& f, Args&&... args) { template MDSpan fill_device_mdspan(MDSpan, DynSizes... dyn) { - using value_type = typename MDSpan::value_type; auto buffer_size = MDSpan{nullptr, dyn...}.mapping().required_span_size(); auto host_buffer = std::make_unique( - MDSpan{nullptr, dyn...}.mapping().required_span_size() - ); + MDSpan{nullptr, dyn...}.mapping().required_span_size()); auto host_mdspan = MDSpan{host_buffer.get(), dyn...}; mdspan_benchmark::fill_random(host_mdspan); value_type* device_buffer = nullptr; CUDA_SAFE_CALL(cudaMalloc(&device_buffer, buffer_size * sizeof(value_type))); - CUDA_SAFE_CALL(cudaMemcpy( - device_buffer, host_buffer.get(), buffer_size * sizeof(value_type), cudaMemcpyHostToDevice - )); + CUDA_SAFE_CALL(cudaMemcpy(device_buffer, host_buffer.get(), + buffer_size * sizeof(value_type), + cudaMemcpyHostToDevice)); return MDSpan{device_buffer, dyn...}; } @@ -128,132 +124,134 @@ MDSpan fill_device_mdspan(MDSpan, DynSizes... dyn) { template void BM_MDSpan_Cuda_Sum_3D(benchmark::State& state, MDSpan, DynSizes... dyn) { - using value_type = typename MDSpan::value_type; - auto s = fill_device_mdspan(MDSpan{}, dyn...); + auto s = fill_device_mdspan(MDSpan{}, dyn...); - int repeats = s.size() > (100*100*100) ? 50 : 1000; + int repeats = s.size() > (100 * 100 * 100) ? 50 : 1000; for (auto _ : state) { - auto timed = run_kernel_timed( - [=] __device__ { - for(int r = 0; r < repeats; ++r) { - value_type sum_local = 0; - for(size_t i = blockIdx.x; i < s.extent(0); i += gridDim.x) { - for(size_t j = threadIdx.z; j < s.extent(1); j += blockDim.z) { - for(size_t k = threadIdx.y; k < s.extent(2); k += blockDim.y) { - sum_local += s(i, j, k); - } + auto timed = run_kernel_timed([=] __device__ { + for (int r = 0; r < repeats; ++r) { + value_type sum_local = 0; + for (size_t i = blockIdx.x; i < s.extent(0); i += gridDim.x) { + for (size_t j = threadIdx.z; j < s.extent(1); j += blockDim.z) { + for (size_t k = threadIdx.y; k < s.extent(2); k += blockDim.y) { + sum_local += s(i, j, k); } } - DoNotOptimize(*(volatile value_type*)(&s(0,0,0)) = sum_local); - asm volatile ("": : :"memory"); } + DoNotOptimize(*(volatile value_type*)(&s(0, 0, 0)) = sum_local); + asm volatile("" : : : "memory"); } - ); + }); // units of cuda timer is milliseconds, units of iteration timer is seconds state.SetIterationTime(timed * 1e-3); } - state.SetBytesProcessed(s.size() * sizeof(value_type) * state.iterations() * repeats); + state.SetBytesProcessed(s.size() * sizeof(value_type) * state.iterations() * + repeats); state.counters["repeats"] = repeats; CUDA_SAFE_CALL(cudaDeviceSynchronize()); CUDA_SAFE_CALL(cudaFree(s.data_handle())); } +// clang-format off MDSPAN_BENCHMARK_ALL_3D_MANUAL(BM_MDSpan_Cuda_Sum_3D, right_, rmdspan, 80, 80, 80); MDSPAN_BENCHMARK_ALL_3D_MANUAL(BM_MDSpan_Cuda_Sum_3D, left_, lmdspan, 80, 80, 80); MDSPAN_BENCHMARK_ALL_3D_MANUAL(BM_MDSpan_Cuda_Sum_3D, right_, rmdspan, 400, 400, 400); MDSPAN_BENCHMARK_ALL_3D_MANUAL(BM_MDSpan_Cuda_Sum_3D, left_, lmdspan, 400, 400, 400); +// clang-format on //================================================================================ template -void BM_Raw_Cuda_Sum_3D_right(benchmark::State& state, T, SizeX x, SizeY y, SizeZ z) { - +void BM_Raw_Cuda_Sum_3D_right(benchmark::State& state, T, SizeX x, SizeY y, + SizeZ z) { using value_type = T; value_type* data = nullptr; { // just for setup... auto wrapped = Kokkos::mdspan>{}; - auto s = fill_device_mdspan(wrapped, x*y*z); - data = s.data_handle(); + auto s = fill_device_mdspan(wrapped, x * y * z); + data = s.data_handle(); } - int repeats = x*y*z > (100*100*100) ? 50 : 1000; + int repeats = x * y * z > (100 * 100 * 100) ? 50 : 1000; for (auto _ : state) { - auto timed = run_kernel_timed( - [=] __device__ { - for(int r = 0; r < repeats; ++r) { - value_type sum_local = 0; - for(size_t i = blockIdx.x; i < x; i += gridDim.x) { - for(size_t j = threadIdx.z; j < y; j += blockDim.z) { - for(size_t k = threadIdx.y; k < z; k += blockDim.y) { - sum_local += data[k + j*z + i*z*y]; - } + auto timed = run_kernel_timed([=] __device__ { + for (int r = 0; r < repeats; ++r) { + value_type sum_local = 0; + for (size_t i = blockIdx.x; i < x; i += gridDim.x) { + for (size_t j = threadIdx.z; j < y; j += blockDim.z) { + for (size_t k = threadIdx.y; k < z; k += blockDim.y) { + sum_local += data[k + j * z + i * z * y]; } } - DoNotOptimize(*(volatile value_type*)(&data[0]) = sum_local); - asm volatile ("": : :"memory"); } + DoNotOptimize(*(volatile value_type*)(&data[0]) = sum_local); + asm volatile("" : : : "memory"); } - ); + }); // units of cuda timer is milliseconds, units of iteration timer is seconds state.SetIterationTime(timed * 1e-3); } - state.SetBytesProcessed(x * y * z * sizeof(value_type) * state.iterations() * repeats); + state.SetBytesProcessed(x * y * z * sizeof(value_type) * state.iterations() * + repeats); state.counters["repeats"] = repeats; CUDA_SAFE_CALL(cudaDeviceSynchronize()); CUDA_SAFE_CALL(cudaFree(data)); } +// clang-format off BENCHMARK_CAPTURE(BM_Raw_Cuda_Sum_3D_right, size_80_80_80, int(), 80, 80, 80); BENCHMARK_CAPTURE(BM_Raw_Cuda_Sum_3D_right, size_400_400_400, int(), 400, 400, 400); +// clang-format on //================================================================================ template -void BM_Raw_Cuda_Sum_3D_left(benchmark::State& state, T, SizeX x, SizeY y, SizeZ z) { - +void BM_Raw_Cuda_Sum_3D_left(benchmark::State& state, T, SizeX x, SizeY y, + SizeZ z) { using value_type = T; value_type* data = nullptr; { // just for setup... auto wrapped = Kokkos::mdspan>{}; - auto s = fill_device_mdspan(wrapped, x*y*z); - data = s.data_handle(); + auto s = fill_device_mdspan(wrapped, x * y * z); + data = s.data_handle(); } - int repeats = x*y*z > (100*100*100) ? 50 : 1000; + int repeats = x * y * z > (100 * 100 * 100) ? 50 : 1000; for (auto _ : state) { - auto timed = run_kernel_timed( - [=] __device__ { - for(int r = 0; r < repeats; ++r) { + auto timed = run_kernel_timed([=] __device__ { + for (int r = 0; r < repeats; ++r) { value_type sum_local = 0; - for(size_t i = blockIdx.x; i < x; i += gridDim.x) { - for(size_t j = threadIdx.z; j < y; j += blockDim.z) { - for(size_t k = threadIdx.y; k < z; k += blockDim.y) { - sum_local += data[k*x*y + j*x + i]; + for (size_t i = blockIdx.x; i < x; i += gridDim.x) { + for (size_t j = threadIdx.z; j < y; j += blockDim.z) { + for (size_t k = threadIdx.y; k < z; k += blockDim.y) { + sum_local += data[k * x * y + j * x + i]; } } } DoNotOptimize(*(volatile value_type*)(&data[0]) = sum_local); - asm volatile ("": : :"memory"); + asm volatile("" : : : "memory"); } - } - ); + }); // units of cuda timer is milliseconds, units of iteration timer is seconds state.SetIterationTime(timed * 1e-3); } - state.SetBytesProcessed(x * y * z * sizeof(value_type) * state.iterations() * repeats); + state.SetBytesProcessed(x * y * z * sizeof(value_type) * state.iterations() * + repeats); state.counters["repeats"] = repeats; CUDA_SAFE_CALL(cudaDeviceSynchronize()); CUDA_SAFE_CALL(cudaFree(data)); } +// clang-format off BENCHMARK_CAPTURE(BM_Raw_Cuda_Sum_3D_left, size_80_80_80, int(), 80, 80, 80); BENCHMARK_CAPTURE(BM_Raw_Cuda_Sum_3D_left, size_400_400_400, int(), 400, 400, 400); +// clang-format on //================================================================================ diff --git a/benchmarks/sum/openmp/sum_3d_openmp.cpp b/benchmarks/sum/openmp/sum_3d_openmp.cpp index 768ed4ac..3a26da96 100644 --- a/benchmarks/sum/openmp/sum_3d_openmp.cpp +++ b/benchmarks/sum/openmp/sum_3d_openmp.cpp @@ -15,29 +15,31 @@ using index_type = int; template -using lmdspan = Kokkos::mdspan, Kokkos::layout_left>; +using lmdspan = + Kokkos::mdspan, Kokkos::layout_left>; template -using rmdspan = Kokkos::mdspan, Kokkos::layout_right>; +using rmdspan = + Kokkos::mdspan, Kokkos::layout_right>; //================================================================================ template void BM_MDSpan_Sum_3D_OpenMP(benchmark::State& state, MDSpan, DynSizes... dyn) { using value_type = typename MDSpan::value_type; - auto buffer = std::make_unique( - MDSpan{nullptr, dyn...}.mapping().required_span_size() - ); + auto buffer = std::make_unique( + MDSpan{nullptr, dyn...}.mapping().required_span_size()); auto s = MDSpan{buffer.get(), dyn...}; - int repeats = s.size() > (100*100*100) ? 50 : 1000; + int repeats = s.size() > (100 * 100 * 100) ? 50 : 1000; mdspan_benchmark::fill_random(s); for (auto _ : state) { - #pragma omp parallel default(none) shared(repeats, s) +#pragma omp parallel default(none) shared(repeats, s) { for (int r = 0; r < repeats; ++r) { value_type sum = 0; - for (index_type i = omp_get_thread_num(); i < s.extent(0); i += omp_get_num_threads()) { + for (index_type i = omp_get_thread_num(); i < s.extent(0); + i += omp_get_num_threads()) { for (index_type j = 0; j < s.extent(1); ++j) { for (index_type k = 0; k < s.extent(2); ++k) { sum += s(i, j, k); @@ -50,33 +52,36 @@ void BM_MDSpan_Sum_3D_OpenMP(benchmark::State& state, MDSpan, DynSizes... dyn) { } } } - state.SetBytesProcessed(s.size() * sizeof(value_type) * state.iterations() * repeats); + state.SetBytesProcessed(s.size() * sizeof(value_type) * state.iterations() * + repeats); state.counters["repeats"] = repeats; } +// clang-format off MDSPAN_BENCHMARK_ALL_3D(BM_MDSpan_Sum_3D_OpenMP, left_, lmdspan, 20, 20, 20); MDSPAN_BENCHMARK_ALL_3D(BM_MDSpan_Sum_3D_OpenMP, right_, rmdspan, 20, 20, 20); MDSPAN_BENCHMARK_ALL_3D(BM_MDSpan_Sum_3D_OpenMP, left_, lmdspan, 200, 200, 200); MDSPAN_BENCHMARK_ALL_3D(BM_MDSpan_Sum_3D_OpenMP, right_, rmdspan, 200, 200, 200); +// clang-format on //================================================================================ template -void BM_MDSpan_Sum_3D_loop_OpenMP(benchmark::State& state, MDSpan, DynSizes... dyn) { +void BM_MDSpan_Sum_3D_loop_OpenMP(benchmark::State& state, MDSpan, + DynSizes... dyn) { using value_type = typename MDSpan::value_type; - auto buffer = std::make_unique( - MDSpan{nullptr, dyn...}.mapping().required_span_size() - ); + auto buffer = std::make_unique( + MDSpan{nullptr, dyn...}.mapping().required_span_size()); auto s = MDSpan{buffer.get(), dyn...}; mdspan_benchmark::fill_random(s); auto sums_buffer = std::make_unique(omp_get_max_threads()); - auto* sum = sums_buffer.get(); + auto* sum = sums_buffer.get(); for (auto _ : state) { auto sbv = sums_buffer.get(); - auto sh = s.data_handle(); + auto sh = s.data_handle(); benchmark::DoNotOptimize(sbv); benchmark::DoNotOptimize(sh); - #pragma omp parallel for default(none) shared(s, sum) +#pragma omp parallel for default(none) shared(s, sum) for (index_type i = 0; i < s.extent(0); ++i) { for (index_type j = 0; j < s.extent(1); ++j) { for (index_type k = 0; k < s.extent(2); ++k) { @@ -88,34 +93,39 @@ void BM_MDSpan_Sum_3D_loop_OpenMP(benchmark::State& state, MDSpan, DynSizes... d } state.SetBytesProcessed(s.size() * sizeof(value_type) * state.iterations()); } +// clang-format off MDSPAN_BENCHMARK_ALL_3D(BM_MDSpan_Sum_3D_loop_OpenMP, right_, rmdspan, 200, 200, 200); MDSPAN_BENCHMARK_ALL_3D(BM_MDSpan_Sum_3D_loop_OpenMP, left_, lmdspan, 200, 200, 200); +// clang-format on //================================================================================ template -void BM_Raw_Sum_3D_OpenMP(benchmark::State& state, T, SizeX x, SizeY y, SizeZ z) { +void BM_Raw_Sum_3D_OpenMP(benchmark::State& state, T, SizeX x, SizeY y, + SizeZ z) { auto buffer = std::make_unique(x * y * z); { // just for setup... - auto wrapped = Kokkos::mdspan>{buffer.get(), x*y*z}; + auto wrapped = Kokkos::mdspan>{ + buffer.get(), x * y * z}; mdspan_benchmark::fill_random(wrapped); } - int repeats = x*y*z > (100*100*100) ? 50 : 1000; + int repeats = x * y * z > (100 * 100 * 100) ? 50 : 1000; T* data = buffer.get(); for (auto _ : state) { - #pragma omp parallel default(none) shared(data,x,y,z,repeats) +#pragma omp parallel default(none) shared(data, x, y, z, repeats) { for (int r = 0; r < repeats; ++r) { T sum = 0; benchmark::DoNotOptimize(sum); benchmark::DoNotOptimize(data); - for (index_type i = omp_get_thread_num(); i < x; i += omp_get_num_threads()) { + for (index_type i = omp_get_thread_num(); i < x; + i += omp_get_num_threads()) { for (index_type j = 0; j < y; ++j) { for (index_type k = 0; k < z; ++k) { - sum += data[k + j*z + i*z*y]; + sum += data[k + j * z + i * z * y]; } } } @@ -126,13 +136,10 @@ void BM_Raw_Sum_3D_OpenMP(benchmark::State& state, T, SizeX x, SizeY y, SizeZ z) state.SetBytesProcessed(x * y * z * sizeof(T) * state.iterations() * repeats); state.counters["repeats"] = repeats; } -BENCHMARK_CAPTURE( - BM_Raw_Sum_3D_OpenMP, size_20_20_20, int(), 20, 20, 20 -); -BENCHMARK_CAPTURE( - BM_Raw_Sum_3D_OpenMP, size_200_200_200, int(), 200, 200, 200 -); - +// clang-format off +BENCHMARK_CAPTURE(BM_Raw_Sum_3D_OpenMP, size_20_20_20, int(), 20, 20, 20); +BENCHMARK_CAPTURE(BM_Raw_Sum_3D_OpenMP, size_200_200_200, int(), 200, 200, 200); +// clang-format on //================================================================================ diff --git a/benchmarks/sum/sum_3d_common.hpp b/benchmarks/sum/sum_3d_common.hpp index c101e00d..354015b4 100644 --- a/benchmarks/sum/sum_3d_common.hpp +++ b/benchmarks/sum/sum_3d_common.hpp @@ -13,13 +13,14 @@ void BM_Raw_Sum_1D(benchmark::State& state, T, Size size) { auto buffer = std::make_unique(size); { // just for setup... - auto wrapped = Kokkos::mdspan>{buffer.get(), size}; + auto wrapped = + Kokkos::mdspan>{buffer.get(), size}; mdspan_benchmark::fill_random(wrapped); } T* data = buffer.get(); for (auto _ : state) { T sum = 0; - for(Size i = 0; i < size; ++i) { + for (Size i = 0; i < size; ++i) { sum += data[i]; } benchmark::DoNotOptimize(sum); @@ -31,8 +32,8 @@ void BM_Raw_Sum_1D(benchmark::State& state, T, Size size) { //============================================================================== template -void BM_Raw_Sum_3D_right(benchmark::State& state, T, SizeX x, SizeY y, SizeZ z) { - +void BM_Raw_Sum_3D_right(benchmark::State& state, T, SizeX x, SizeY y, + SizeZ z) { benchmark::DoNotOptimize(x); benchmark::DoNotOptimize(y); benchmark::DoNotOptimize(z); @@ -40,19 +41,19 @@ void BM_Raw_Sum_3D_right(benchmark::State& state, T, SizeX x, SizeY y, SizeZ z) auto buffer = std::make_unique(x * y * z); { // just for setup... - auto wrapped = Kokkos::mdspan>{buffer.get(), x*y*z}; + auto wrapped = + Kokkos::mdspan>{buffer.get(), x * y * z}; mdspan_benchmark::fill_random(wrapped); } T* data = buffer.get(); - for (auto _ : state) { benchmark::DoNotOptimize(data); T sum = 0; - for(SizeX i = 0; i < x; ++i) { - for(SizeY j = 0; j < y; ++j) { - for(SizeZ k = 0; k < z; ++k) { - sum += data[k + j*z + i*z*y]; + for (SizeX i = 0; i < x; ++i) { + for (SizeY j = 0; j < y; ++j) { + for (SizeZ k = 0; k < z; ++k) { + sum += data[k + j * z + i * z * y]; } } } @@ -69,17 +70,18 @@ void BM_Raw_Sum_3D_left(benchmark::State& state, T, SizeX x, SizeY y, SizeZ z) { auto buffer = std::make_unique(x * y * z); { // just for setup... - auto wrapped = Kokkos::mdspan>{buffer.get(), x*y*z}; + auto wrapped = + Kokkos::mdspan>{buffer.get(), x * y * z}; mdspan_benchmark::fill_random(wrapped); } T* data = buffer.get(); for (auto _ : state) { benchmark::DoNotOptimize(data); T sum = 0; - for(SizeZ k = 0; k < z; ++k) { - for(SizeY j = 0; j < y; ++j) { - for(SizeX i = 0; i < x; ++i) { - sum += data[i + j*x + k*x*y]; + for (SizeZ k = 0; k < z; ++k) { + for (SizeY j = 0; j < y; ++j) { + for (SizeX i = 0; i < x; ++i) { + sum += data[i + j * x + k * x * y]; } } } @@ -92,11 +94,13 @@ void BM_Raw_Sum_3D_left(benchmark::State& state, T, SizeX x, SizeY y, SizeZ z) { //================================================================================ template -void BM_Raw_Sum_3D_right_iter_left(benchmark::State& state, T, SizeX x, SizeY y, SizeZ z) { +void BM_Raw_Sum_3D_right_iter_left(benchmark::State& state, T, SizeX x, SizeY y, + SizeZ z) { auto buffer = std::make_unique(x * y * z); { // just for setup... - auto wrapped = Kokkos::mdspan>{buffer.get(), x*y*z}; + auto wrapped = + Kokkos::mdspan>{buffer.get(), x * y * z}; mdspan_benchmark::fill_random(wrapped); } @@ -109,10 +113,10 @@ void BM_Raw_Sum_3D_right_iter_left(benchmark::State& state, T, SizeX x, SizeY y, for (auto _ : state) { benchmark::DoNotOptimize(data); T sum = 0; - for(SizeZ k = 0; k < z; ++k) { - for(SizeY j = 0; j < y; ++j) { - for(SizeX i = 0; i < x; ++i) { - sum += data[k + j*z + i*z*y]; + for (SizeZ k = 0; k < z; ++k) { + for (SizeY j = 0; j < y; ++j) { + for (SizeX i = 0; i < x; ++i) { + sum += data[k + j * z + i * z * y]; } } } @@ -128,24 +132,24 @@ void BM_Raw_Sum_3D_right_iter_left(benchmark::State& state, T, SizeX x, SizeY y, template void BM_Raw_Static_Sum_3D_right(benchmark::State& state, T, - std::integral_constant, - std::integral_constant, - std::integral_constant -) { + std::integral_constant, + std::integral_constant, + std::integral_constant) { auto buffer = std::make_unique(x * y * z); { // just for setup... - auto wrapped = Kokkos::mdspan>{buffer.get(), x*y*z}; + auto wrapped = + Kokkos::mdspan>{buffer.get(), x * y * z}; mdspan_benchmark::fill_random(wrapped); } T* data = buffer.get(); for (auto _ : state) { benchmark::DoNotOptimize(data); T sum = 0; - for(size_t i = 0; i < x; ++i) { - for(size_t j = 0; j < y; ++j) { - for(size_t k = 0; k < z; ++k) { - sum += data[k + j*z + i*z*y]; + for (size_t i = 0; i < x; ++i) { + for (size_t j = 0; j < y; ++j) { + for (size_t k = 0; k < z; ++k) { + sum += data[k + j * z + i * z * y]; } } } @@ -159,24 +163,24 @@ void BM_Raw_Static_Sum_3D_right(benchmark::State& state, T, template void BM_Raw_Static_Sum_3D_left(benchmark::State& state, T, - std::integral_constant, - std::integral_constant, - std::integral_constant -) { + std::integral_constant, + std::integral_constant, + std::integral_constant) { auto buffer = std::make_unique(x * y * z); { // just for setup... - auto wrapped = Kokkos::mdspan>{buffer.get(), x*y*z}; + auto wrapped = + Kokkos::mdspan>{buffer.get(), x * y * z}; mdspan_benchmark::fill_random(wrapped); } T* data = buffer.get(); for (auto _ : state) { benchmark::DoNotOptimize(data); T sum = 0; - for(size_t k = 0; k < z; ++k) { - for(size_t j = 0; j < y; ++j) { - for(size_t i = 0; i < x; ++i) { - sum += data[i + j*x + k*x*y]; + for (size_t k = 0; k < z; ++k) { + for (size_t j = 0; j < y; ++j) { + for (size_t i = 0; i < x; ++i) { + sum += data[i + j * x + k * x * y]; } } } @@ -190,24 +194,24 @@ void BM_Raw_Static_Sum_3D_left(benchmark::State& state, T, template void BM_Raw_Static_Sum_3D_right_iter_left(benchmark::State& state, T, - std::integral_constant, - std::integral_constant, - std::integral_constant -) { + std::integral_constant, + std::integral_constant, + std::integral_constant) { auto buffer = std::make_unique(x * y * z); { // just for setup... - auto wrapped = Kokkos::mdspan>{buffer.get(), x*y*z}; + auto wrapped = + Kokkos::mdspan>{buffer.get(), x * y * z}; mdspan_benchmark::fill_random(wrapped); } T* data = buffer.get(); for (auto _ : state) { benchmark::DoNotOptimize(data); T sum = 0; - for(size_t k = 0; k < z; ++k) { - for(size_t j = 0; j < y; ++j) { - for(size_t i = 0; i < x; ++i) { - sum += data[k + j*z + i*z*y]; + for (size_t k = 0; k < z; ++k) { + for (size_t j = 0; j < y; ++j) { + for (size_t i = 0; i < x; ++i) { + sum += data[k + j * z + i * z * y]; } } } @@ -217,5 +221,4 @@ void BM_Raw_Static_Sum_3D_right_iter_left(benchmark::State& state, T, state.SetBytesProcessed(x * y * z * sizeof(T) * state.iterations()); } - -#endif // MDSPAN_BENCHMARKS_SUM_SUM_3D_COMMON_HPP +#endif // MDSPAN_BENCHMARKS_SUM_SUM_3D_COMMON_HPP diff --git a/benchmarks/sum/sum_3d_left.cpp b/benchmarks/sum/sum_3d_left.cpp index fcbf20ae..5f5fdcd3 100644 --- a/benchmarks/sum/sum_3d_left.cpp +++ b/benchmarks/sum/sum_3d_left.cpp @@ -13,25 +13,26 @@ using index_type = int; //================================================================================ template -using lmdspan = Kokkos::mdspan, Kokkos::layout_left>; +using lmdspan = + Kokkos::mdspan, Kokkos::layout_left>; template -using rmdspan = Kokkos::mdspan, Kokkos::layout_right>; +using rmdspan = + Kokkos::mdspan, Kokkos::layout_right>; //================================================================================ template void BM_MDSpan_Sum_3D_left(benchmark::State& state, MDSpan, DynSizes... dyn) { using value_type = typename MDSpan::value_type; - auto buffer = std::make_unique( - MDSpan{nullptr, dyn...}.mapping().required_span_size() - ); + auto buffer = std::make_unique( + MDSpan{nullptr, dyn...}.mapping().required_span_size()); auto s = MDSpan{buffer.get(), dyn...}; mdspan_benchmark::fill_random(s); for (auto _ : state) { value_type sum = 0; for (index_type k = 0; k < s.extent(2); ++k) { for (index_type j = 0; j < s.extent(1); ++j) { - for(index_type i = 0; i < s.extent(0); ++i) { + for (index_type i = 0; i < s.extent(0); ++i) { sum += s(i, j, k); } } @@ -42,42 +43,31 @@ void BM_MDSpan_Sum_3D_left(benchmark::State& state, MDSpan, DynSizes... dyn) { } state.SetBytesProcessed(s.size() * sizeof(value_type) * state.iterations()); } +// clang-format off MDSPAN_BENCHMARK_ALL_3D(BM_MDSpan_Sum_3D_left, left_, lmdspan, 20, 20, 20); MDSPAN_BENCHMARK_ALL_3D(BM_MDSpan_Sum_3D_left, right_, rmdspan, 20, 20, 20); MDSPAN_BENCHMARK_ALL_3D(BM_MDSpan_Sum_3D_left, left_, lmdspan, 200, 200, 200); MDSPAN_BENCHMARK_ALL_3D(BM_MDSpan_Sum_3D_left, right_, rmdspan, 200, 200, 200); +// clang-format on //================================================================================ -BENCHMARK_CAPTURE( - BM_Raw_Sum_1D, size_8000, int(), 8000 -); -BENCHMARK_CAPTURE( - BM_Raw_Sum_1D, size_8000000, int(), 8000000 -); +BENCHMARK_CAPTURE(BM_Raw_Sum_1D, size_8000, int(), 8000); +BENCHMARK_CAPTURE(BM_Raw_Sum_1D, size_8000000, int(), 8000000); -BENCHMARK_CAPTURE( - BM_Raw_Sum_3D_left, size_20_20_20, int(), 20, 20, 20 -); -BENCHMARK_CAPTURE( - BM_Raw_Sum_3D_left, size_200_200_200, int(), 200, 200, 200 -); +BENCHMARK_CAPTURE(BM_Raw_Sum_3D_left, size_20_20_20, int(), 20, 20, 20); +BENCHMARK_CAPTURE(BM_Raw_Sum_3D_left, size_200_200_200, int(), 200, 200, 200); //================================================================================ -BENCHMARK_CAPTURE( - BM_Raw_Static_Sum_3D_left, size_20_20_20, int(), - std::integral_constant{}, - std::integral_constant{}, - std::integral_constant{} -); -BENCHMARK_CAPTURE( - BM_Raw_Static_Sum_3D_left, size_200_200_200, int(), - std::integral_constant{}, - std::integral_constant{}, - std::integral_constant{} -); - +BENCHMARK_CAPTURE(BM_Raw_Static_Sum_3D_left, size_20_20_20, int(), + std::integral_constant{}, + std::integral_constant{}, + std::integral_constant{}); +BENCHMARK_CAPTURE(BM_Raw_Static_Sum_3D_left, size_200_200_200, int(), + std::integral_constant{}, + std::integral_constant{}, + std::integral_constant{}); //================================================================================ diff --git a/benchmarks/sum/sum_3d_right.cpp b/benchmarks/sum/sum_3d_right.cpp index 10cdf86a..2e78885e 100644 --- a/benchmarks/sum/sum_3d_right.cpp +++ b/benchmarks/sum/sum_3d_right.cpp @@ -14,19 +14,19 @@ using index_type = int; template -using lmdspan = Kokkos::mdspan, Kokkos::layout_left>; +using lmdspan = + Kokkos::mdspan, Kokkos::layout_left>; template -using rmdspan = Kokkos::mdspan, Kokkos::layout_right>; +using rmdspan = + Kokkos::mdspan, Kokkos::layout_right>; //================================================================================ template void BM_MDSpan_Sum_3D_right(benchmark::State& state, MDSpan, DynSizes... dyn) { - using value_type = typename MDSpan::value_type; - auto buffer = std::make_unique( - MDSpan{nullptr, dyn...}.mapping().required_span_size() - ); + auto buffer = std::make_unique( + MDSpan{nullptr, dyn...}.mapping().required_span_size()); auto s = MDSpan{buffer.get(), dyn...}; mdspan_benchmark::fill_random(s); @@ -36,7 +36,7 @@ void BM_MDSpan_Sum_3D_right(benchmark::State& state, MDSpan, DynSizes... dyn) { auto sdata = s.data_handle(); benchmark::DoNotOptimize(sdata); value_type sum = 0; - for(index_type i = 0; i < s.extent(0); ++i) { + for (index_type i = 0; i < s.extent(0); ++i) { for (index_type j = 0; j < s.extent(1); ++j) { for (index_type k = 0; k < s.extent(2); ++k) { sum += s(i, j, k); @@ -48,41 +48,34 @@ void BM_MDSpan_Sum_3D_right(benchmark::State& state, MDSpan, DynSizes... dyn) { } state.SetBytesProcessed(s.size() * sizeof(value_type) * state.iterations()); } +// clang-format on MDSPAN_BENCHMARK_ALL_3D(BM_MDSpan_Sum_3D_right, right_, rmdspan, 20, 20, 20); MDSPAN_BENCHMARK_ALL_3D(BM_MDSpan_Sum_3D_right, left_, lmdspan, 20, 20, 20); MDSPAN_BENCHMARK_ALL_3D(BM_MDSpan_Sum_3D_right, right_, rmdspan, 200, 200, 200); MDSPAN_BENCHMARK_ALL_3D(BM_MDSpan_Sum_3D_right, left_, lmdspan, 200, 200, 200); +// clang-format on //================================================================================ -BENCHMARK_CAPTURE( - BM_Raw_Sum_3D_right, size_20_20_20, int(), size_t(20), size_t(20), size_t(20) -); -BENCHMARK_CAPTURE( - BM_Raw_Sum_3D_right, size_200_200_200, int(), size_t(200), size_t(200), size_t(200) -); +BENCHMARK_CAPTURE(BM_Raw_Sum_3D_right, size_20_20_20, int(), size_t(20), + size_t(20), size_t(20)); +BENCHMARK_CAPTURE(BM_Raw_Sum_3D_right, size_200_200_200, int(), size_t(200), + size_t(200), size_t(200)); //================================================================================ -BENCHMARK_CAPTURE( - BM_Raw_Static_Sum_3D_right, size_20_20_20, int(), - std::integral_constant{}, - std::integral_constant{}, - std::integral_constant{} -); -BENCHMARK_CAPTURE( - BM_Raw_Static_Sum_3D_right, size_200_200_200, int(), - std::integral_constant{}, - std::integral_constant{}, - std::integral_constant{} -); - +BENCHMARK_CAPTURE(BM_Raw_Static_Sum_3D_right, size_20_20_20, int(), + std::integral_constant{}, + std::integral_constant{}, + std::integral_constant{}); +BENCHMARK_CAPTURE(BM_Raw_Static_Sum_3D_right, size_200_200_200, int(), + std::integral_constant{}, + std::integral_constant{}, + std::integral_constant{}); //================================================================================ -BENCHMARK_CAPTURE( - BM_Raw_Sum_1D, size_8000, int(), 8000 -); +BENCHMARK_CAPTURE(BM_Raw_Sum_1D, size_8000, int(), 8000); //================================================================================ diff --git a/benchmarks/sum/sum_submdspan_right.cpp b/benchmarks/sum/sum_submdspan_right.cpp index 93973126..1a830527 100644 --- a/benchmarks/sum/sum_submdspan_right.cpp +++ b/benchmarks/sum/sum_submdspan_right.cpp @@ -14,19 +14,20 @@ using index_type = int; template -using lmdspan = Kokkos::mdspan, Kokkos::layout_left>; +using lmdspan = + Kokkos::mdspan, Kokkos::layout_left>; template -using rmdspan = Kokkos::mdspan, Kokkos::layout_right>; +using rmdspan = + Kokkos::mdspan, Kokkos::layout_right>; //================================================================================ template -void BM_MDSpan_Sum_Subspan_3D_right(benchmark::State& state, MDSpan, DynSizes... dyn) { - +void BM_MDSpan_Sum_Subspan_3D_right(benchmark::State& state, MDSpan, + DynSizes... dyn) { using value_type = typename MDSpan::value_type; - auto buffer = std::make_unique( - MDSpan{nullptr, dyn...}.mapping().required_span_size() - ); + auto buffer = std::make_unique( + MDSpan{nullptr, dyn...}.mapping().required_span_size()); auto s = MDSpan{buffer.get(), dyn...}; mdspan_benchmark::fill_random(s); @@ -35,10 +36,11 @@ void BM_MDSpan_Sum_Subspan_3D_right(benchmark::State& state, MDSpan, DynSizes... benchmark::DoNotOptimize(s); auto sdata = s.data_handle(); benchmark::DoNotOptimize(sdata); - value_type sum = 0; + value_type sum = 0; using index_type = typename MDSpan::index_type; - for(index_type i = 0; i < s.extent(0); ++i) { - auto sub_i = Kokkos::submdspan(s, i, Kokkos::full_extent, Kokkos::full_extent); + for (index_type i = 0; i < s.extent(0); ++i) { + auto sub_i = + Kokkos::submdspan(s, i, Kokkos::full_extent, Kokkos::full_extent); for (index_type j = 0; j < s.extent(1); ++j) { auto sub_i_j = Kokkos::submdspan(sub_i, j, Kokkos::full_extent); for (index_type k = 0; k < s.extent(2); ++k) { @@ -51,92 +53,76 @@ void BM_MDSpan_Sum_Subspan_3D_right(benchmark::State& state, MDSpan, DynSizes... } state.SetBytesProcessed(s.size() * sizeof(value_type) * state.iterations()); } +// clang-format off MDSPAN_BENCHMARK_ALL_3D(BM_MDSpan_Sum_Subspan_3D_right, right_, rmdspan, 20, 20, 20); MDSPAN_BENCHMARK_ALL_3D(BM_MDSpan_Sum_Subspan_3D_right, left_, lmdspan, 20, 20, 20); MDSPAN_BENCHMARK_ALL_3D(BM_MDSpan_Sum_Subspan_3D_right, right_, rmdspan, 200, 200, 200); MDSPAN_BENCHMARK_ALL_3D(BM_MDSpan_Sum_Subspan_3D_right, left_, lmdspan, 200, 200, 200); +// clang-format on //================================================================================ -BENCHMARK_CAPTURE( - BM_Raw_Sum_3D_right, size_20_20_20, int(), size_t(20), size_t(20), size_t(20) -); -BENCHMARK_CAPTURE( - BM_Raw_Sum_3D_right, size_200_200_200, int(), size_t(200), size_t(200), size_t(200) -); - -BENCHMARK_CAPTURE( - BM_Raw_Static_Sum_3D_right, size_20_20_20, int(), - std::integral_constant{}, - std::integral_constant{}, - std::integral_constant{} -); -BENCHMARK_CAPTURE( - BM_Raw_Static_Sum_3D_right, size_200_200_200, int(), - std::integral_constant{}, - std::integral_constant{}, - std::integral_constant{} -); - -BENCHMARK_CAPTURE( - BM_Raw_Sum_3D_right_iter_left, size_20_20_20, int(), 20, 20, 20 -); -BENCHMARK_CAPTURE( - BM_Raw_Sum_3D_right_iter_left, size_200_200_200, int(), 200, 200, 200 -); -BENCHMARK_CAPTURE( - BM_Raw_Static_Sum_3D_right_iter_left, size_20_20_20, int(), - std::integral_constant{}, - std::integral_constant{}, - std::integral_constant{} -); -BENCHMARK_CAPTURE( - BM_Raw_Static_Sum_3D_right_iter_left, size_200_200_200, int(), - std::integral_constant{}, - std::integral_constant{}, - std::integral_constant{} -); +BENCHMARK_CAPTURE(BM_Raw_Sum_3D_right, size_20_20_20, int(), size_t(20), + size_t(20), size_t(20)); +BENCHMARK_CAPTURE(BM_Raw_Sum_3D_right, size_200_200_200, int(), size_t(200), + size_t(200), size_t(200)); + +BENCHMARK_CAPTURE(BM_Raw_Static_Sum_3D_right, size_20_20_20, int(), + std::integral_constant{}, + std::integral_constant{}, + std::integral_constant{}); +BENCHMARK_CAPTURE(BM_Raw_Static_Sum_3D_right, size_200_200_200, int(), + std::integral_constant{}, + std::integral_constant{}, + std::integral_constant{}); + +BENCHMARK_CAPTURE(BM_Raw_Sum_3D_right_iter_left, size_20_20_20, int(), 20, 20, + 20); +BENCHMARK_CAPTURE(BM_Raw_Sum_3D_right_iter_left, size_200_200_200, int(), 200, + 200, 200); +BENCHMARK_CAPTURE(BM_Raw_Static_Sum_3D_right_iter_left, size_20_20_20, int(), + std::integral_constant{}, + std::integral_constant{}, + std::integral_constant{}); +BENCHMARK_CAPTURE(BM_Raw_Static_Sum_3D_right_iter_left, size_200_200_200, int(), + std::integral_constant{}, + std::integral_constant{}, + std::integral_constant{}); //================================================================================ namespace _impl { template -MDSPAN_FORCE_INLINE_FUNCTION -constexpr T&& _repeated_with(T&& v) noexcept { return std::forward(v); } +MDSPAN_FORCE_INLINE_FUNCTION constexpr T&& _repeated_with(T&& v) noexcept { + return std::forward(v); +} template -MDSPAN_FORCE_INLINE_FUNCTION -MDSPAN_IMPL_CONSTEXPR_14 void _do_sum_submdspan( - T& sum, - Kokkos::mdspan, Rest...> s -) -{ +MDSPAN_FORCE_INLINE_FUNCTION MDSPAN_IMPL_CONSTEXPR_14 void _do_sum_submdspan( + T& sum, Kokkos::mdspan, Rest...> s) { sum += s(); } template -MDSPAN_FORCE_INLINE_FUNCTION -MDSPAN_IMPL_CONSTEXPR_14 void _do_sum_submdspan( - T& sum, - Kokkos::mdspan, Rest...> s -) -{ - for(index_type i = 0; i < s.extent(0); ++i) { - _impl::_do_sum_submdspan(sum, Kokkos::submdspan( - s, i, _repeated_with(Kokkos::full_extent)...) - ); +MDSPAN_FORCE_INLINE_FUNCTION MDSPAN_IMPL_CONSTEXPR_14 void _do_sum_submdspan( + T& sum, + Kokkos::mdspan, Rest...> s) { + for (index_type i = 0; i < s.extent(0); ++i) { + _impl::_do_sum_submdspan( + sum, Kokkos::submdspan( + s, i, _repeated_with(Kokkos::full_extent)...)); } } -} // end namespace _impl +} // end namespace _impl template -void BM_MDSpan_Sum_Subspan_MD_right(benchmark::State& state, MDSpan, DynSizes... dyn) { +void BM_MDSpan_Sum_Subspan_MD_right(benchmark::State& state, MDSpan, + DynSizes... dyn) { using value_type = typename MDSpan::value_type; - auto buffer = std::make_unique( - MDSpan{nullptr, dyn...}.mapping().required_span_size() - ); + auto buffer = std::make_unique( + MDSpan{nullptr, dyn...}.mapping().required_span_size()); auto s = MDSpan{buffer.get(), dyn...}; mdspan_benchmark::fill_random(s); for (auto _ : state) { @@ -149,38 +135,33 @@ void BM_MDSpan_Sum_Subspan_MD_right(benchmark::State& state, MDSpan, DynSizes... state.SetBytesProcessed(s.size() * sizeof(value_type) * state.iterations()); } +BENCHMARK_CAPTURE(BM_MDSpan_Sum_Subspan_MD_right, fixed_10D_size_1024, + Kokkos::mdspan>{nullptr}); +BENCHMARK_CAPTURE(BM_MDSpan_Sum_Subspan_MD_right, dyn_10D_size_1024, + Kokkos::mdspan>{}, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2); BENCHMARK_CAPTURE( - BM_MDSpan_Sum_Subspan_MD_right, fixed_10D_size_1024, - Kokkos::mdspan>{nullptr} -); -BENCHMARK_CAPTURE( - BM_MDSpan_Sum_Subspan_MD_right, dyn_10D_size_1024, - Kokkos::mdspan>{}, - 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2 -); -BENCHMARK_CAPTURE( - BM_MDSpan_Sum_Subspan_MD_right, fixed5_dyn5_10D_alternate_size_1024, - Kokkos::mdspan>{}, - 2, 2, 2, 2, 2 -); -BENCHMARK_CAPTURE( - BM_MDSpan_Sum_Subspan_MD_right, fixed8_dyn2_10D_alternate_size_1024, - Kokkos::mdspan>{}, - 2, 2 -); -BENCHMARK_CAPTURE( - BM_MDSpan_Sum_Subspan_MD_right, fixed_5D_size_1024, - Kokkos::mdspan>{nullptr} -); + BM_MDSpan_Sum_Subspan_MD_right, fixed5_dyn5_10D_alternate_size_1024, + Kokkos::mdspan< + int, + Kokkos::extents>{}, + 2, 2, 2, 2, 2); BENCHMARK_CAPTURE( - BM_MDSpan_Sum_Subspan_MD_right, dyn_5D_size_1024, - Kokkos::mdspan>{}, - 4, 4, 4, 4, 4 -); + BM_MDSpan_Sum_Subspan_MD_right, fixed8_dyn2_10D_alternate_size_1024, + Kokkos::mdspan< + int, Kokkos::extents>{}, + 2, 2); BENCHMARK_CAPTURE( - BM_Raw_Sum_1D, size_1024, int(), 1024 -); + BM_MDSpan_Sum_Subspan_MD_right, fixed_5D_size_1024, + Kokkos::mdspan>{nullptr}); +BENCHMARK_CAPTURE(BM_MDSpan_Sum_Subspan_MD_right, dyn_5D_size_1024, + Kokkos::mdspan>{}, 4, 4, + 4, 4, 4); +BENCHMARK_CAPTURE(BM_Raw_Sum_1D, size_1024, int(), 1024); //================================================================================ diff --git a/benchmarks/tiny_matrix_add/openmp/tiny_matrix_add_openmp.cpp b/benchmarks/tiny_matrix_add/openmp/tiny_matrix_add_openmp.cpp index fe9d96f6..ac60f6f5 100644 --- a/benchmarks/tiny_matrix_add/openmp/tiny_matrix_add_openmp.cpp +++ b/benchmarks/tiny_matrix_add/openmp/tiny_matrix_add_openmp.cpp @@ -20,23 +20,25 @@ static constexpr int global_repeat = 1; using index_type = int; template -using lmdspan = Kokkos::mdspan, Kokkos::layout_left>; +using lmdspan = + Kokkos::mdspan, Kokkos::layout_left>; template -using rmdspan = Kokkos::mdspan, Kokkos::layout_right>; +using rmdspan = + Kokkos::mdspan, Kokkos::layout_right>; -void throw_runtime_exception(const std::string &msg) { +void throw_runtime_exception(const std::string& msg) { std::ostringstream o; o << msg; throw std::runtime_error(o.str()); } -template +template void OpenMP_first_touch_3D(MDSpan s) { - #pragma omp parallel for - for(index_type i = 0; i < s.extent(0); i ++) { - for(index_type j = 0; j < s.extent(1); j ++) { - for(index_type k = 0; k < s.extent(2); k ++) { - s(i,j,k) = 0; +#pragma omp parallel for + for (index_type i = 0; i < s.extent(0); i++) { + for (index_type j = 0; j < s.extent(1); j++) { + for (index_type k = 0; k < s.extent(2); k++) { + s(i, j, k) = 0; } } } @@ -45,22 +47,21 @@ void OpenMP_first_touch_3D(MDSpan s) { //================================================================================ template -void BM_MDSpan_OpenMP_noloop_TinyMatrixSum(benchmark::State& state, MDSpan, DynSizes... dyn) { - +void BM_MDSpan_OpenMP_noloop_TinyMatrixSum(benchmark::State& state, MDSpan, + DynSizes... dyn) { using value_type = typename MDSpan::value_type; auto buffer_size = MDSpan{nullptr, dyn...}.mapping().required_span_size(); auto buffer_s = std::make_unique(buffer_size); - auto s = MDSpan{buffer_s.get(), dyn...}; + auto s = MDSpan{buffer_s.get(), dyn...}; OpenMP_first_touch_3D(s); mdspan_benchmark::fill_random(s); auto buffer_o = std::make_unique(buffer_size); - auto o = MDSpan{buffer_o.get(), dyn...}; + auto o = MDSpan{buffer_o.get(), dyn...}; OpenMP_first_touch_3D(o); mdspan_benchmark::fill_random(o); - for (auto _ : state) { auto oh = o.data_handle(); auto sh = s.data_handle(); @@ -68,9 +69,9 @@ void BM_MDSpan_OpenMP_noloop_TinyMatrixSum(benchmark::State& state, MDSpan, DynS benchmark::DoNotOptimize(sh); #pragma omp parallel { - auto chunk_size = s.extent(0) / omp_get_num_threads(); + auto chunk_size = s.extent(0) / omp_get_num_threads(); auto chunk_start = chunk_size * omp_get_thread_num(); - auto extra = s.extent(0) % chunk_size; + auto extra = s.extent(0) % chunk_size; if (omp_get_thread_num() < extra) { chunk_size += 1; chunk_start += omp_get_thread_num(); @@ -91,37 +92,40 @@ void BM_MDSpan_OpenMP_noloop_TinyMatrixSum(benchmark::State& state, MDSpan, DynS benchmark::ClobberMemory(); } size_t num_elements = (s.extent(0) * s.extent(1) * s.extent(2)); - state.SetBytesProcessed( num_elements * 3 * sizeof(value_type) * state.iterations() * global_repeat); + state.SetBytesProcessed(num_elements * 3 * sizeof(value_type) * + state.iterations() * global_repeat); state.counters["repeats"] = global_repeat; } +// clang-format off MDSPAN_BENCHMARK_ALL_3D(BM_MDSpan_OpenMP_noloop_TinyMatrixSum, right_, rmdspan, 1000000, 3, 3); MDSPAN_BENCHMARK_ALL_3D(BM_MDSpan_OpenMP_noloop_TinyMatrixSum, left_, lmdspan, 1000000, 3, 3); +// clang-format on //================================================================================ template -void BM_MDSpan_OpenMP_TinyMatrixSum(benchmark::State& state, MDSpan, DynSizes... dyn) { - +void BM_MDSpan_OpenMP_TinyMatrixSum(benchmark::State& state, MDSpan, + DynSizes... dyn) { using value_type = typename MDSpan::value_type; using index_type = typename MDSpan::index_type; auto buffer_size = MDSpan{nullptr, dyn...}.mapping().required_span_size(); auto buffer_s = std::make_unique(buffer_size); - auto s = MDSpan{buffer_s.get(), dyn...}; + auto s = MDSpan{buffer_s.get(), dyn...}; OpenMP_first_touch_3D(s); mdspan_benchmark::fill_random(s); auto buffer_o = std::make_unique(buffer_size); - auto o = MDSpan{buffer_o.get(), dyn...}; + auto o = MDSpan{buffer_o.get(), dyn...}; OpenMP_first_touch_3D(o); mdspan_benchmark::fill_random(o); - #pragma omp parallel for - for(index_type i = 0; i < s.extent(0); i ++) { - for(int r = 0; r -void BM_Raw_Static_OpenMP_TinyMatrixSum_right(benchmark::State& state, T, SizeX x, SizeY y, SizeZ z) { - - using MDSpan = Kokkos::mdspan>; +void BM_Raw_Static_OpenMP_TinyMatrixSum_right(benchmark::State& state, T, + SizeX x, SizeY y, SizeZ z) { + using MDSpan = Kokkos::mdspan>; using value_type = typename MDSpan::value_type; - auto buffer_size = MDSpan{nullptr, x,y,z}.mapping().required_span_size(); + auto buffer_size = MDSpan{nullptr, x, y, z}.mapping().required_span_size(); auto buffer_s = std::make_unique(buffer_size); - auto s = MDSpan{buffer_s.get(), x,y,z}; + auto s = MDSpan{buffer_s.get(), x, y, z}; OpenMP_first_touch_3D(s); mdspan_benchmark::fill_random(s); T* s_ptr = s.data_handle(); auto buffer_o = std::make_unique(buffer_size); - auto o = MDSpan{buffer_o.get(), x,y,z}; + auto o = MDSpan{buffer_o.get(), x, y, z}; OpenMP_first_touch_3D(o); mdspan_benchmark::fill_random(o); T* o_ptr = o.data_handle(); - #pragma omp parallel for - for(SizeX i = 0; i < x; i ++) { - for(int r = 0; rUseRealTime(); +BENCHMARK_CAPTURE(BM_Raw_Static_OpenMP_TinyMatrixSum_right, size_1000000_3_3, + int(), 1000000, 3, 3) + ->UseRealTime(); template -void BM_Raw_OpenMP_TinyMatrixSum_right(benchmark::State& state, T, SizeX x, SizeY y, SizeZ z) { - - using MDSpan = Kokkos::mdspan>; +void BM_Raw_OpenMP_TinyMatrixSum_right(benchmark::State& state, T, SizeX x, + SizeY y, SizeZ z) { + using MDSpan = Kokkos::mdspan>; using value_type = typename MDSpan::value_type; - auto buffer_size = MDSpan{nullptr, x,y,z}.mapping().required_span_size(); + auto buffer_size = MDSpan{nullptr, x, y, z}.mapping().required_span_size(); auto buffer_s = std::make_unique(buffer_size); - auto s = MDSpan{buffer_s.get(), x,y,z}; + auto s = MDSpan{buffer_s.get(), x, y, z}; OpenMP_first_touch_3D(s); mdspan_benchmark::fill_random(s); T* s_ptr = s.data_handle(); auto buffer_o = std::make_unique(buffer_size); - auto o = MDSpan{buffer_o.get(), x,y,z}; + auto o = MDSpan{buffer_o.get(), x, y, z}; OpenMP_first_touch_3D(o); mdspan_benchmark::fill_random(o); T* o_ptr = o.data_handle(); #pragma omp parallel for - for(SizeX i = 0; i < x; i ++) { - for(int r = 0; rUseRealTime(); +BENCHMARK_CAPTURE(BM_Raw_OpenMP_TinyMatrixSum_right, size_1000000_3_3, int(), + 1000000, 3, 3) + ->UseRealTime(); //================================================================================ template -void BM_Raw_Static_OpenMP_TinyMatrixSum_left(benchmark::State& state, T, SizeX x, SizeY y, SizeZ z) { - - using MDSpan = Kokkos::mdspan>; +void BM_Raw_Static_OpenMP_TinyMatrixSum_left(benchmark::State& state, T, + SizeX x, SizeY y, SizeZ z) { + using MDSpan = + Kokkos::mdspan>; using value_type = typename MDSpan::value_type; auto buffer_size = MDSpan{nullptr, x}.mapping().required_span_size(); auto buffer_s = std::make_unique(buffer_size); - auto s = MDSpan{buffer_s.get(), x}; + auto s = MDSpan{buffer_s.get(), x}; OpenMP_first_touch_3D(s); mdspan_benchmark::fill_random(s); T* s_ptr = s.data_handle(); auto buffer_o = std::make_unique(buffer_size); - auto o = MDSpan{buffer_o.get(), x}; + auto o = MDSpan{buffer_o.get(), x}; OpenMP_first_touch_3D(o); mdspan_benchmark::fill_random(o); T* o_ptr = o.data_handle(); - #pragma omp parallel for - for(SizeX i = 0; i < x; i ++) { - for(int r = 0; rUseRealTime(); +BENCHMARK_CAPTURE(BM_Raw_Static_OpenMP_TinyMatrixSum_left, size_1000000_3_3, + int(), 1000000, 3, 3) + ->UseRealTime(); //================================================================================ template -void BM_Raw_OpenMP_TinyMatrixSum_left(benchmark::State& state, T, SizeX x, SizeY y, SizeZ z) { - - using MDSpan = Kokkos::mdspan>; +void BM_Raw_OpenMP_TinyMatrixSum_left(benchmark::State& state, T, SizeX x, + SizeY y, SizeZ z) { + using MDSpan = + Kokkos::mdspan>; using value_type = typename MDSpan::value_type; auto buffer_size = MDSpan{nullptr, x}.mapping().required_span_size(); auto buffer_s = std::make_unique(buffer_size); - auto s = MDSpan{buffer_s.get(), x}; + auto s = MDSpan{buffer_s.get(), x}; OpenMP_first_touch_3D(s); mdspan_benchmark::fill_random(s); T* s_ptr = s.data_handle(); auto buffer_o = std::make_unique(buffer_size); - auto o = MDSpan{buffer_o.get(), x}; + auto o = MDSpan{buffer_o.get(), x}; OpenMP_first_touch_3D(o); mdspan_benchmark::fill_random(o); T* o_ptr = o.data_handle(); - #pragma omp parallel for - for(SizeX i = 0; i < x; i ++) { - for(int r = 0; rUseRealTime(); +BENCHMARK_CAPTURE(BM_Raw_OpenMP_TinyMatrixSum_left, size_1000000_3_3, int(), + 1000000, 3, 3) + ->UseRealTime(); template typename MDSpan::value_type*** make_3d_ptr_array(MDSpan s) { - static_assert(std::is_same::value,"Creating MD Ptr only works from mdspan with layout_right"); + static_assert( + std::is_same::value, + "Creating MD Ptr only works from mdspan with layout_right"); using value_type = typename MDSpan::value_type; using index_type = typename MDSpan::index_type; - value_type*** ptr= new value_type**[s.extent(0)]; - for(index_type i = 0; i void free_3d_ptr_array(T*** ptr, size_t extent_0) { - for(size_t i=0; i -void BM_RawMDPtr_OpenMP_TinyMatrixSum_right(benchmark::State& state, T, SizeX x, SizeY y, SizeZ z) { - - using MDSpan = Kokkos::mdspan>; +void BM_RawMDPtr_OpenMP_TinyMatrixSum_right(benchmark::State& state, T, SizeX x, + SizeY y, SizeZ z) { + using MDSpan = + Kokkos::mdspan>; using value_type = typename MDSpan::value_type; auto buffer_size = MDSpan{nullptr, x}.mapping().required_span_size(); auto buffer_s = std::make_unique(buffer_size); - auto s = MDSpan{buffer_s.get(), x}; + auto s = MDSpan{buffer_s.get(), x}; OpenMP_first_touch_3D(s); mdspan_benchmark::fill_random(s); T*** s_ptr = make_3d_ptr_array(s); auto buffer_o = std::make_unique(buffer_size); - auto o = MDSpan{buffer_o.get(), x}; + auto o = MDSpan{buffer_o.get(), x}; OpenMP_first_touch_3D(o); mdspan_benchmark::fill_random(o); T*** o_ptr = make_3d_ptr_array(o); - #pragma omp parallel for - for(SizeX i = 0; i < x; i ++) { - for(int r = 0; rUseRealTime(); - +BENCHMARK_CAPTURE(BM_RawMDPtr_OpenMP_TinyMatrixSum_right, size_1000000_3_3, + int(), 1000000, 3, 3) + ->UseRealTime(); //================================================================================ diff --git a/benchmarks/tiny_matrix_add/tiny_matrix_add.cpp b/benchmarks/tiny_matrix_add/tiny_matrix_add.cpp index 6634516d..742aab90 100644 --- a/benchmarks/tiny_matrix_add/tiny_matrix_add.cpp +++ b/benchmarks/tiny_matrix_add/tiny_matrix_add.cpp @@ -13,24 +13,26 @@ using index_type = int; template -using lmdspan = Kokkos::mdspan, Kokkos::layout_left>; +using lmdspan = + Kokkos::mdspan, Kokkos::layout_left>; template -using rmdspan = Kokkos::mdspan, Kokkos::layout_right>; +using rmdspan = + Kokkos::mdspan, Kokkos::layout_right>; //================================================================================ template -void BM_MDSpan_TinyMatrixSum_right(benchmark::State& state, MDSpan, DynSizes... dyn) { - +void BM_MDSpan_TinyMatrixSum_right(benchmark::State& state, MDSpan, + DynSizes... dyn) { using value_type = typename MDSpan::value_type; auto buffer_size = MDSpan{nullptr, dyn...}.mapping().required_span_size(); auto buffer_s = std::make_unique(buffer_size); - auto s = MDSpan{buffer_s.get(), dyn...}; + auto s = MDSpan{buffer_s.get(), dyn...}; mdspan_benchmark::fill_random(s); auto buffer_o = std::make_unique(buffer_size); - auto o = MDSpan{buffer_o.get(), dyn...}; + auto o = MDSpan{buffer_o.get(), dyn...}; mdspan_benchmark::fill_random(o); for (auto _ : state) { @@ -40,67 +42,72 @@ void BM_MDSpan_TinyMatrixSum_right(benchmark::State& state, MDSpan, DynSizes... benchmark::DoNotOptimize(s); auto sdata = s.data_handle(); benchmark::DoNotOptimize(sdata); - for(index_type i = 0; i < s.extent(0); i ++) { - for(index_type j = 0; j < s.extent(1); j ++) { - for(index_type k = 0; k < s.extent(2); k ++) { - o(i,j,k) += s(i,j,k); + for (index_type i = 0; i < s.extent(0); i++) { + for (index_type j = 0; j < s.extent(1); j++) { + for (index_type k = 0; k < s.extent(2); k++) { + o(i, j, k) += s(i, j, k); } } } benchmark::ClobberMemory(); } size_t num_elements = (s.extent(0) * s.extent(1) * s.extent(2)); - state.SetBytesProcessed( num_elements * 3 * sizeof(value_type) * state.iterations() ); + state.SetBytesProcessed(num_elements * 3 * sizeof(value_type) * + state.iterations()); } +// clang-format off MDSPAN_BENCHMARK_ALL_3D(BM_MDSpan_TinyMatrixSum_right, right_, lmdspan, 1000000, 3, 3); MDSPAN_BENCHMARK_ALL_3D(BM_MDSpan_TinyMatrixSum_right, left_, lmdspan, 1000000, 3, 3); +// clang-format on //================================================================================ template -void BM_Raw_Static_TinyMatrixSum_right(benchmark::State& state, T, SizeX x, SizeY y, SizeZ z) { - - using MDSpan = Kokkos::mdspan>; +void BM_Raw_Static_TinyMatrixSum_right(benchmark::State& state, T, SizeX x, + SizeY y, SizeZ z) { + using MDSpan = Kokkos::mdspan>; using value_type = typename MDSpan::value_type; - auto buffer_size = MDSpan{nullptr, x,y,z}.mapping().required_span_size(); + auto buffer_size = MDSpan{nullptr, x, y, z}.mapping().required_span_size(); auto buffer_s = std::make_unique(buffer_size); - auto s = MDSpan{buffer_s.get(), x,y,z}; + auto s = MDSpan{buffer_s.get(), x, y, z}; mdspan_benchmark::fill_random(s); T* s_ptr = s.data_handle(); auto buffer_o = std::make_unique(buffer_size); - auto o = MDSpan{buffer_o.get(), x,y,z}; + auto o = MDSpan{buffer_o.get(), x, y, z}; mdspan_benchmark::fill_random(o); T* o_ptr = o.data_handle(); for (auto _ : state) { benchmark::DoNotOptimize(o_ptr); benchmark::DoNotOptimize(s_ptr); - for(index_type i = 0; i < 1000000; i ++) { - for(index_type j = 0; j < 3; j ++) { - for(index_type k = 0; k < 3; k ++) { - o_ptr[k + j*3 + i*3*3] += s_ptr[k + j*3 + i*3*3]; + for (index_type i = 0; i < 1000000; i++) { + for (index_type j = 0; j < 3; j++) { + for (index_type k = 0; k < 3; k++) { + o_ptr[k + j * 3 + i * 3 * 3] += s_ptr[k + j * 3 + i * 3 * 3]; } } } benchmark::ClobberMemory(); } size_t num_inner_elements = x * y * z; - state.SetBytesProcessed( num_inner_elements * 3 * sizeof(value_type) * state.iterations()); + state.SetBytesProcessed(num_inner_elements * 3 * sizeof(value_type) * + state.iterations()); } -BENCHMARK_CAPTURE(BM_Raw_Static_TinyMatrixSum_right, size_1000000_3_3, int(), 1000000, 3, 3); +BENCHMARK_CAPTURE(BM_Raw_Static_TinyMatrixSum_right, size_1000000_3_3, int(), + 1000000, 3, 3); //================================================================================ template -void BM_Raw_TinyMatrixSum_right(benchmark::State& state, T, SizeX x, SizeY y, SizeZ z) { - +void BM_Raw_TinyMatrixSum_right(benchmark::State& state, T, SizeX x, SizeY y, + SizeZ z) { benchmark::DoNotOptimize(x); benchmark::DoNotOptimize(y); benchmark::DoNotOptimize(z); - using MDSpan = Kokkos::mdspan>; + using MDSpan = Kokkos::mdspan>; using value_type = typename MDSpan::value_type; auto buffer_s = std::make_unique(x * y * z); @@ -120,19 +127,21 @@ void BM_Raw_TinyMatrixSum_right(benchmark::State& state, T, SizeX x, SizeY y, Si for (auto _ : state) { benchmark::DoNotOptimize(o_ptr); benchmark::DoNotOptimize(s_ptr); - for(SizeX i = 0; i < x; i ++) { - for(SizeY j = 0; j < y; j ++) { - for(SizeZ k = 0; k < z; k ++) { - o_ptr[k + j*z + i*z*y] += s_ptr[k + j*z + i*z*y]; + for (SizeX i = 0; i < x; i++) { + for (SizeY j = 0; j < y; j++) { + for (SizeZ k = 0; k < z; k++) { + o_ptr[k + j * z + i * z * y] += s_ptr[k + j * z + i * z * y]; } } } benchmark::ClobberMemory(); } size_t num_inner_elements = x * y * z; - state.SetBytesProcessed( num_inner_elements * y * sizeof(value_type) * state.iterations()); + state.SetBytesProcessed(num_inner_elements * y * sizeof(value_type) * + state.iterations()); } -BENCHMARK_CAPTURE(BM_Raw_TinyMatrixSum_right, size_1000000_3_3, int(), size_t(1000000), size_t(3), size_t(3)); +BENCHMARK_CAPTURE(BM_Raw_TinyMatrixSum_right, size_1000000_3_3, int(), + size_t(1000000), size_t(3), size_t(3)); //================================================================================ diff --git a/compilation_tests/ctest_common.hpp b/compilation_tests/ctest_common.hpp index ff1c6dd8..2d572789 100644 --- a/compilation_tests/ctest_common.hpp +++ b/compilation_tests/ctest_common.hpp @@ -10,6 +10,7 @@ #define MDSPAN_ENABLE_EXPENSIVE_COMPILATION_TESTS 0 +// clang-format off #define MDSPAN_STATIC_TEST(...) \ static_assert(__VA_ARGS__, "MDSpan compile time test failed at " __FILE__ ":" MDSPAN_PP_STRINGIFY(__LINE__)) @@ -35,6 +36,7 @@ char a[] = { 0 }; char b[] = { 0 }; char c[] = { 0 }; \ return b[(a[0] + c[0] + -!(checker(__val, _exp)))]; #endif +// clang-format on // More sugar around the compiler output to print some values of things struct _____constexpr_assertion_failed_ { @@ -46,25 +48,34 @@ struct _____constexpr_assertion_failed_ { const char* __str; template constexpr char but_actual_value_was_(U __val) const { - // Put this macro here so that failures are easy to find in compiler output + // Put this macro here so that failures are easy to find in compiler + // output __________CONSTEXPR_ASSERTION_FAILED__________ } }; struct _check_eq { template - constexpr bool operator()(T val, U exp) const { return val == exp; } + constexpr bool operator()(T val, U exp) const { + return val == exp; + } }; struct _check_not_eq { template - constexpr bool operator()(T val, U exp) const { return val != exp; } + constexpr bool operator()(T val, U exp) const { + return val != exp; + } }; struct _check_less { template - constexpr bool operator()(T val, U exp) const { return val != exp; } + constexpr bool operator()(T val, U exp) const { + return val != exp; + } }; struct _check_greater { template - constexpr bool operator()(T val, U exp) const { return val != exp; } + constexpr bool operator()(T val, U exp) const { + return val != exp; + } }; template @@ -77,7 +88,8 @@ struct _____constexpr_assertion_failed_ { } template constexpr auto _rhs_expected_to_not_be_(T _exp) const { - return _expected_impl{_exp, _check_not_eq{}, _expr_string}; + return _expected_impl{_exp, _check_not_eq{}, + _expr_string}; } template constexpr auto _expected_to_be_less_than_(T _exp) const { @@ -85,30 +97,41 @@ struct _____constexpr_assertion_failed_ { } template constexpr auto _expected_to_be_greater_than_(T _exp) const { - return _expected_impl{_exp, _check_greater{}, _expr_string}; + return _expected_impl{_exp, _check_greater{}, + _expr_string}; } }; // Macros for the assertions themselves -#define constexpr_assert(...) \ - _____constexpr_assertion_failed_{#__VA_ARGS__}._expected_to_be_(true).but_actual_value_was_(__VA_ARGS__); - -#define constexpr_assert_equal(expr, ...) \ - _____constexpr_assertion_failed_{#__VA_ARGS__ "==" #expr}._rhs_expected_to_be_(expr).but_actual_value_was_((__VA_ARGS__)); - -#define constexpr_assert_not_equal(expr, ...) \ - _____constexpr_assertion_failed_{#__VA_ARGS__ "!=" #expr}._rhs_expected_to_not_be_(expr).but_actual_value_was_((__VA_ARGS__)); - -#define constexpr_assert_less_than(expr, ...) \ - _____constexpr_assertion_failed_{#__VA_ARGS__}._expected_to_be_less_than_(expr).but_actual_value_was_((__VA_ARGS__)); +#define constexpr_assert(...) \ + _____constexpr_assertion_failed_{#__VA_ARGS__} \ + ._expected_to_be_(true) \ + .but_actual_value_was_(__VA_ARGS__); + +#define constexpr_assert_equal(expr, ...) \ + _____constexpr_assertion_failed_{#__VA_ARGS__ "==" #expr} \ + ._rhs_expected_to_be_(expr) \ + .but_actual_value_was_((__VA_ARGS__)); + +#define constexpr_assert_not_equal(expr, ...) \ + _____constexpr_assertion_failed_{#__VA_ARGS__ "!=" #expr} \ + ._rhs_expected_to_not_be_(expr) \ + .but_actual_value_was_((__VA_ARGS__)); + +#define constexpr_assert_less_than(expr, ...) \ + _____constexpr_assertion_failed_{#__VA_ARGS__} \ + ._expected_to_be_less_than_(expr) \ + .but_actual_value_was_((__VA_ARGS__)); #define constexpr_assert_greater_than(expr, ...) \ - _____constexpr_assertion_failed_{#__VA_ARGS__}._expected_to_be_greater_than_(expr).but_actual_value_was_((__VA_ARGS__)); + _____constexpr_assertion_failed_{#__VA_ARGS__} \ + ._expected_to_be_greater_than_(expr) \ + .but_actual_value_was_((__VA_ARGS__)); -#endif // MDSPAN_IMPL_USE_CONSTEXPR_14 +#endif // MDSPAN_IMPL_USE_CONSTEXPR_14 // end assert-like macros that don't break constexpr }}}1 //============================================================================== // All tests need a main so that they'll link -int main() { } +int main() {} diff --git a/compilation_tests/ctest_compressed_pair_layout.cpp b/compilation_tests/ctest_compressed_pair_layout.cpp index a5069e28..0ec33d1f 100644 --- a/compilation_tests/ctest_compressed_pair_layout.cpp +++ b/compilation_tests/ctest_compressed_pair_layout.cpp @@ -7,11 +7,7 @@ #include - -enum emptyness { - non_empty = false, - empty = true -}; +enum emptyness { non_empty = false, empty = true }; enum standard_layoutness { non_standard_layout = false, @@ -23,15 +19,14 @@ enum trivially_copyableness { trivially_copyable = true }; -template void test() { MDSPAN_STATIC_TEST(sizeof(T) == Size); MDSPAN_STATIC_TEST(std::is_empty::value == Empty); -#if (!defined(__INTEL_COMPILER) || (__INTEL_COMPILER>=1900)) && \ - (!defined(__clang__) || (defined(__GNUC__) && (__GNUC__> 10))) +#if (!defined(__INTEL_COMPILER) || (__INTEL_COMPILER >= 1900)) && \ + (!defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 10))) MDSPAN_STATIC_TEST(std::is_standard_layout::value == StandardLayout); #endif MDSPAN_STATIC_TEST(std::is_trivially_copyable::value == TriviallyCopyable); @@ -45,6 +40,7 @@ struct E1 {}; struct E2 {}; struct E3 {}; +// clang-format off void instantiate_tests() { //============================================================================== // {{{1 @@ -129,3 +125,4 @@ test, CP>, 4 * sizeof(int*), non_empty>(); // end compressed pair layout: 2 nested pairs, 4 leaf elements }}}1 //============================================================================== } +// clang-format on diff --git a/compilation_tests/ctest_constexpr_dereference.cpp b/compilation_tests/ctest_constexpr_dereference.cpp index 460b4987..e2ef8f55 100644 --- a/compilation_tests/ctest_constexpr_dereference.cpp +++ b/compilation_tests/ctest_constexpr_dereference.cpp @@ -5,23 +5,17 @@ #include - // Only works with newer constexpr #if defined(MDSPAN_IMPL_USE_CONSTEXPR_14) && MDSPAN_IMPL_USE_CONSTEXPR_14 //============================================================================== -constexpr int -simple_static_sum_test_1(int add_to_row) { - int data[] = { - 1, 2, 3, - 4, 5, 6, - 7, 8, 9 - }; - auto s = Kokkos::mdspan>(data); +constexpr int simple_static_sum_test_1(int add_to_row) { + int data[] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; + auto s = Kokkos::mdspan>(data); int result = 0; - for(int col = 0; col < 3; ++col) { - for(int row = 0; row < 3; ++row) { + for (int col = 0; col < 3; ++col) { + for (int row = 0; row < 3; ++row) { result += MDSPAN_IMPL_OP(s, row, col) * (row + add_to_row); } } @@ -29,52 +23,42 @@ simple_static_sum_test_1(int add_to_row) { } MDSPAN_STATIC_TEST( - // 1 + 2 + 3 + 2*(4 + 5 + 6) + 3*(7 + 8 + 9) = 108 - simple_static_sum_test_1(1) == 108 -); + // 1 + 2 + 3 + 2*(4 + 5 + 6) + 3*(7 + 8 + 9) = 108 + simple_static_sum_test_1(1) == 108); MDSPAN_STATIC_TEST( - // -1 - 2 - 3 + 7 + 8 + 9 = 18 - simple_static_sum_test_1(-1) == 18 -); + // -1 - 2 - 3 + 7 + 8 + 9 = 18 + simple_static_sum_test_1(-1) == 18); -#if !defined(__INTEL_COMPILER) || (__INTEL_COMPILER>=1800) +#if !defined(__INTEL_COMPILER) || (__INTEL_COMPILER >= 1800) MDSPAN_STATIC_TEST( - // -1 - 2 - 3 + 7 + 8 + 9 = 18 - Kokkos::mdspan>{nullptr}.extent(0) == 18 -); + // -1 - 2 - 3 + 7 + 8 + 9 = 18 + Kokkos::mdspan>{ + nullptr} + .extent(0) == 18); #endif //============================================================================== -constexpr int -simple_test_1d_constexpr_in_type() { - int data[] = { - 1, 2, 3, 4, 5, 6, 7, 8, 9, - 10, 11, 12, 13, 14, 15, 16, 17, 18 - }; - auto s = Kokkos::mdspan>(data); +constexpr int simple_test_1d_constexpr_in_type() { + int data[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18}; + auto s = Kokkos::mdspan< + int, Kokkos::extents>(data); // 4 + 14 + 18 + 1 = 37 return s[3] + s[13] + s[17] + s[0]; } -MDSPAN_STATIC_TEST( - simple_test_1d_constexpr_in_type() == 37 -); +MDSPAN_STATIC_TEST(simple_test_1d_constexpr_in_type() == 37); //============================================================================== -constexpr int -simple_dynamic_sum_test_2(int add_to_row) { - int data[] = { - 1, 2, 3, 0, - 4, 5, 6, 0, - 7, 8, 9, 0 - }; - auto s = Kokkos::mdspan>(data, 3, 4); +constexpr int simple_dynamic_sum_test_2(int add_to_row) { + int data[] = {1, 2, 3, 0, 4, 5, 6, 0, 7, 8, 9, 0}; + auto s = Kokkos::mdspan>(data, 3, 4); int result = 0; - for(int col = 0; col < 3; ++col) { - for(int row = 0; row < 3; ++row) { + for (int col = 0; col < 3; ++col) { + for (int row = 0; row < 3; ++row) { result += MDSPAN_IMPL_OP(s, row, col) * (row + add_to_row); } } @@ -82,32 +66,24 @@ simple_dynamic_sum_test_2(int add_to_row) { } MDSPAN_STATIC_TEST( - // 1 + 2 + 3 + 2*(4 + 5 + 6) + 3*(7 + 8 + 9) = 108 - simple_dynamic_sum_test_2(1) == 108 -); + // 1 + 2 + 3 + 2*(4 + 5 + 6) + 3*(7 + 8 + 9) = 108 + simple_dynamic_sum_test_2(1) == 108); MDSPAN_STATIC_TEST( - // -1 - 2 - 3 + 7 + 8 + 9 = 18 - simple_dynamic_sum_test_2(-1) == 18 -); + // -1 - 2 - 3 + 7 + 8 + 9 = 18 + simple_dynamic_sum_test_2(-1) == 18); //============================================================================== -constexpr int -simple_mixed_layout_left_sum_test_3(int add_to_row) { - int data[] = { - 1, 4, 7, - 2, 5, 8, - 3, 6, 9, - 0, 0, 0 - }; - auto s = Kokkos::mdspan< - int, Kokkos::extents, - Kokkos::layout_left - >(data, 3, 4); +constexpr int simple_mixed_layout_left_sum_test_3(int add_to_row) { + int data[] = {1, 4, 7, 2, 5, 8, 3, 6, 9, 0, 0, 0}; + auto s = Kokkos::mdspan< + int, + Kokkos::extents, + Kokkos::layout_left>(data, 3, 4); int result = 0; - for(int col = 0; col < 3; ++col) { - for(int row = 0; row < 3; ++row) { + for (int col = 0; col < 3; ++col) { + for (int row = 0; row < 3; ++row) { result += MDSPAN_IMPL_OP(s, row, col) * (row + add_to_row); } } @@ -115,30 +91,31 @@ simple_mixed_layout_left_sum_test_3(int add_to_row) { } MDSPAN_STATIC_TEST( - // 1 + 2 + 3 + 2*(4 + 5 + 6) + 3*(7 + 8 + 9) = 108 - simple_mixed_layout_left_sum_test_3(1) == 108 -); + // 1 + 2 + 3 + 2*(4 + 5 + 6) + 3*(7 + 8 + 9) = 108 + simple_mixed_layout_left_sum_test_3(1) == 108); //============================================================================== -#if defined(MDSPAN_ENABLE_EXPENSIVE_COMPILATION_TESTS) && MDSPAN_ENABLE_EXPENSIVE_COMPILATION_TESTS +#if defined(MDSPAN_ENABLE_EXPENSIVE_COMPILATION_TESTS) && \ + MDSPAN_ENABLE_EXPENSIVE_COMPILATION_TESTS template constexpr auto _repeated_ptrdiff_t = Val; template -constexpr bool -multidimensional_single_element_stress_test_impl_2( - std::integer_sequence -) { +constexpr bool multidimensional_single_element_stress_test_impl_2( + std::integer_sequence) { using mdspan_t = Kokkos::mdspan< - int, Kokkos::extents...>, Layout>; + int, Kokkos::extents...>, Layout>; using dyn_mdspan_t = Kokkos::mdspan< - int, Kokkos::extents...>, Layout>; - int data[] = { 42 }; - auto s = mdspan_t(data); - auto s_dyn = dyn_mdspan_t(data, _repeated_ptrdiff_t<1, Idxs>...); - auto val = MDSPAN_IMPL_OP(s, _repeated_ptrdiff_t<0, Idxs>...); + int, + Kokkos::extents...>, + Layout>; + int data[] = {42}; + auto s = mdspan_t(data); + auto s_dyn = dyn_mdspan_t(data, _repeated_ptrdiff_t<1, Idxs>...); + auto val = MDSPAN_IMPL_OP(s, _repeated_ptrdiff_t<0, Idxs>...); auto val_dyn = MDSPAN_IMPL_OP(s_dyn, _repeated_ptrdiff_t<0, Idxs>...); constexpr_assert_equal(42, val); constexpr_assert_equal(42, val_dyn); @@ -146,116 +123,99 @@ multidimensional_single_element_stress_test_impl_2( } template -constexpr bool -multidimensional_single_element_stress_test_impl_1( - std::integer_sequence -) { +constexpr bool multidimensional_single_element_stress_test_impl_1( + std::integer_sequence) { return MDSPAN_IMPL_FOLD_AND( - multidimensional_single_element_stress_test_impl_2( - std::make_index_sequence{} - ) /* && ... */ + multidimensional_single_element_stress_test_impl_2( + std::make_index_sequence{}) /* && ... */ ); } template -constexpr bool -multidimensional_single_element_stress_test() { +constexpr bool multidimensional_single_element_stress_test() { return multidimensional_single_element_stress_test_impl_1( - std::make_index_sequence{} - ); + std::make_index_sequence{}); } MDSPAN_STATIC_TEST( - multidimensional_single_element_stress_test() -); + multidimensional_single_element_stress_test()); MDSPAN_STATIC_TEST( - multidimensional_single_element_stress_test() -); + multidimensional_single_element_stress_test()); template -constexpr bool -stress_test_2d_single_element_stress_test_impl_2( - std::integral_constant, - std::integral_constant -) { - using mdspan_t = Kokkos::mdspan< - int, Kokkos::extents, Layout>; - using dyn_mdspan_1_t = Kokkos::mdspan< - int, Kokkos::extents, Layout>; - using dyn_mdspan_2_t = Kokkos::mdspan< - int, Kokkos::extents, Layout>; +constexpr bool stress_test_2d_single_element_stress_test_impl_2( + std::integral_constant, + std::integral_constant) { + using mdspan_t = + Kokkos::mdspan, Layout>; + using dyn_mdspan_1_t = + Kokkos::mdspan, + Layout>; + using dyn_mdspan_2_t = + Kokkos::mdspan, + Layout>; using dyn_mdspan_t = Kokkos::mdspan< - int, Kokkos::extents, Layout>; - int data[Idx1*Idx2] = { }; - auto s = mdspan_t(data); - auto s1 = dyn_mdspan_1_t(data, Idx1); - auto s2 = dyn_mdspan_2_t(data, Idx2); - auto s12 = dyn_mdspan_t(data, Idx1, Idx2); - for(ptrdiff_t i = 0; i < Idx1; ++i) { - for(ptrdiff_t j = 0; j < Idx2; ++j) { - MDSPAN_IMPL_OP(s, i, j) = MDSPAN_IMPL_OP(s1, i, j) = MDSPAN_IMPL_OP(s2, i, j) = MDSPAN_IMPL_OP(s12, i, j) = 1; + int, + Kokkos::extents, + Layout>; + int data[Idx1 * Idx2] = {}; + auto s = mdspan_t(data); + auto s1 = dyn_mdspan_1_t(data, Idx1); + auto s2 = dyn_mdspan_2_t(data, Idx2); + auto s12 = dyn_mdspan_t(data, Idx1, Idx2); + for (ptrdiff_t i = 0; i < Idx1; ++i) { + for (ptrdiff_t j = 0; j < Idx2; ++j) { + MDSPAN_IMPL_OP(s, i, j) = MDSPAN_IMPL_OP(s1, i, j) = + MDSPAN_IMPL_OP(s2, i, j) = MDSPAN_IMPL_OP(s12, i, j) = 1; } } int result = 0; - for(ptrdiff_t i = 0; i < Idx1; ++i) { - for(ptrdiff_t j = 0; j < Idx2; ++j) { - result += MDSPAN_IMPL_OP(s, i, j) + MDSPAN_IMPL_OP(s1, i, j) + MDSPAN_IMPL_OP(s2, i, j) + MDSPAN_IMPL_OP(s12, i, j); + for (ptrdiff_t i = 0; i < Idx1; ++i) { + for (ptrdiff_t j = 0; j < Idx2; ++j) { + result += MDSPAN_IMPL_OP(s, i, j) + MDSPAN_IMPL_OP(s1, i, j) + + MDSPAN_IMPL_OP(s2, i, j) + MDSPAN_IMPL_OP(s12, i, j); } } result /= 4; - constexpr_assert_equal(Idx1*Idx2, result); + constexpr_assert_equal(Idx1 * Idx2, result); return result == Idx1 * Idx2; } template -constexpr bool -stress_test_2d_single_element_stress_test_impl_1( - std::integral_constant idx1, - std::integer_sequence -) -{ +constexpr bool stress_test_2d_single_element_stress_test_impl_1( + std::integral_constant idx1, + std::integer_sequence) { return MDSPAN_IMPL_FOLD_AND( - stress_test_2d_single_element_stress_test_impl_2( - idx1, std::integral_constant{} - ) /* && ... */ + stress_test_2d_single_element_stress_test_impl_2( + idx1, std::integral_constant{}) /* && ... */ ); } template -constexpr bool -stress_test_2d_single_element_stress_test_impl_0( - std::integer_sequence, - std::integer_sequence idxs2 -) -{ +constexpr bool stress_test_2d_single_element_stress_test_impl_0( + std::integer_sequence, + std::integer_sequence idxs2) { return MDSPAN_IMPL_FOLD_AND( - stress_test_2d_single_element_stress_test_impl_1( - std::integral_constant{}, idxs2 - ) /* && ... */ + stress_test_2d_single_element_stress_test_impl_1( + std::integral_constant{}, idxs2) /* && ... */ ); } template -constexpr bool -stress_test_2d_single_element_stress_test() { +constexpr bool stress_test_2d_single_element_stress_test() { return stress_test_2d_single_element_stress_test_impl_0( - std::make_index_sequence{}, - std::make_index_sequence{} - ); + std::make_index_sequence{}, std::make_index_sequence{}); } MDSPAN_STATIC_TEST( - stress_test_2d_single_element_stress_test() -); + stress_test_2d_single_element_stress_test()); MDSPAN_STATIC_TEST( - stress_test_2d_single_element_stress_test() -); + stress_test_2d_single_element_stress_test()); // Not evaluated at constexpr time to get around limits, but still compiled static bool _stress_2d_result = - stress_test_2d_single_element_stress_test() - && stress_test_2d_single_element_stress_test(); - -#endif // MDSPAN_DISABLE_EXPENSIVE_COMPILATION_TESTS + stress_test_2d_single_element_stress_test() && + stress_test_2d_single_element_stress_test(); +#endif // MDSPAN_DISABLE_EXPENSIVE_COMPILATION_TESTS -#endif //defined(MDSPAN_IMPL_USE_CONSTEXPR_14) && MDSPAN_IMPL_USE_CONSTEXPR_14 +#endif // defined(MDSPAN_IMPL_USE_CONSTEXPR_14) && MDSPAN_IMPL_USE_CONSTEXPR_14 diff --git a/compilation_tests/ctest_constexpr_layouts.cpp b/compilation_tests/ctest_constexpr_layouts.cpp index 7db67a32..60801810 100644 --- a/compilation_tests/ctest_constexpr_layouts.cpp +++ b/compilation_tests/ctest_constexpr_layouts.cpp @@ -5,23 +5,16 @@ #include - // Only works with newer constexpr #if defined(MDSPAN_IMPL_USE_CONSTEXPR_14) && MDSPAN_IMPL_USE_CONSTEXPR_14 -constexpr std::ptrdiff_t -layout_stride_simple(int i) { - using map_t = Kokkos::layout_stride::template mapping< - Kokkos::extents - >; - return map_t(Kokkos::extents{}, std::array{1})(i); +constexpr std::ptrdiff_t layout_stride_simple(int i) { + using map_t = + Kokkos::layout_stride::template mapping >; + return map_t(Kokkos::extents{}, std::array{1})(i); } -MDSPAN_STATIC_TEST( - layout_stride_simple(0) == 0 -); -MDSPAN_STATIC_TEST( - layout_stride_simple(1) == 1 -); +MDSPAN_STATIC_TEST(layout_stride_simple(0) == 0); +MDSPAN_STATIC_TEST(layout_stride_simple(1) == 1); -#endif // MDSPAN_IMPL_USE_CONSTEXPR_14 +#endif // MDSPAN_IMPL_USE_CONSTEXPR_14 diff --git a/compilation_tests/ctest_constexpr_submdspan.cpp b/compilation_tests/ctest_constexpr_submdspan.cpp index c8bbdf6c..874e9398 100644 --- a/compilation_tests/ctest_constexpr_submdspan.cpp +++ b/compilation_tests/ctest_constexpr_submdspan.cpp @@ -11,11 +11,10 @@ //============================================================================== // {{{1 -template -constexpr bool -dynamic_extent_1d() { +template +constexpr bool dynamic_extent_1d() { int data[] = {1, 2, 3, 4, 5}; - auto s = Kokkos::mdspan, Layout>(data, 5); + auto s = Kokkos::mdspan, Layout>(data, 5); int result = 0; for (size_t i = 0; i < s.extent(0); ++i) { auto ss = Kokkos::submdspan(s, i); @@ -29,21 +28,19 @@ dynamic_extent_1d() { MDSPAN_STATIC_TEST(dynamic_extent_1d()); MDSPAN_STATIC_TEST(dynamic_extent_1d()); - // end 1D dynamic extent ptrdiff_t submdspan }}}1 //============================================================================== //============================================================================== // {{{1 -template -constexpr bool -dynamic_extent_1d_all_slice() { +template +constexpr bool dynamic_extent_1d_all_slice() { int data[] = {1, 2, 3, 4, 5}; - auto s = Kokkos::mdspan< - int, Kokkos::extents, Layout>(data, 5); + auto s = Kokkos::mdspan, + Layout>(data, 5); int result = 0; - auto ss = Kokkos::submdspan(s, Kokkos::full_extent); + auto ss = Kokkos::submdspan(s, Kokkos::full_extent); for (size_t i = 0; i < s.extent(0); ++i) { result += MDSPAN_IMPL_OP(ss, i); } @@ -61,14 +58,14 @@ MDSPAN_STATIC_TEST(dynamic_extent_1d_all_slice()); //============================================================================== // {{{1 -template -constexpr bool -dynamic_extent_1d_pair_full() { +template +constexpr bool dynamic_extent_1d_pair_full() { int data[] = {1, 2, 3, 4, 5}; - auto s = Kokkos::mdspan< - int, Kokkos::extents, Layout>(data, 5); + auto s = Kokkos::mdspan, + Layout>(data, 5); int result = 0; - auto ss = Kokkos::submdspan(s, std::pair{0, 5}); + auto ss = + Kokkos::submdspan(s, std::pair{0, 5}); for (size_t i = 0; i < s.extent(0); ++i) { result += MDSPAN_IMPL_OP(ss, i); } @@ -79,16 +76,15 @@ dynamic_extent_1d_pair_full() { MDSPAN_STATIC_TEST(dynamic_extent_1d_pair_full()); MDSPAN_STATIC_TEST(dynamic_extent_1d_pair_full()); -template -constexpr bool -dynamic_extent_1d_pair_each() { +template +constexpr bool dynamic_extent_1d_pair_each() { int data[] = {1, 2, 3, 4, 5}; - auto s = Kokkos::mdspan< - int, Kokkos::extents, Layout>(data, 5); + auto s = Kokkos::mdspan, + Layout>(data, 5); int result = 0; for (size_t i = 0; i < s.extent(0); ++i) { - auto ss = Kokkos::submdspan(s, - std::pair{i, i+1}); + auto ss = Kokkos::submdspan( + s, std::pair{i, i + 1}); result += MDSPAN_IMPL_OP(ss, 0); } constexpr_assert_equal(15, result); @@ -107,14 +103,14 @@ MDSPAN_STATIC_TEST(dynamic_extent_1d_pair_each()); //============================================================================== // {{{1 -template -constexpr bool -dynamic_extent_1d_all_three() { +template +constexpr bool dynamic_extent_1d_all_three() { int data[] = {1, 2, 3, 4, 5}; - auto s = Kokkos::mdspan< - int, Kokkos::extents, Layout>(data, 5); - auto s1 = Kokkos::submdspan(s, std::pair{0, 5}); - auto s2 = Kokkos::submdspan(s1, Kokkos::full_extent); + auto s = Kokkos::mdspan, + Layout>(data, 5); + auto s1 = + Kokkos::submdspan(s, std::pair{0, 5}); + auto s2 = Kokkos::submdspan(s1, Kokkos::full_extent); int result = 0; for (size_t i = 0; i < s.extent(0); ++i) { auto ss = Kokkos::submdspan(s2, i); @@ -133,16 +129,16 @@ MDSPAN_STATIC_TEST(dynamic_extent_1d_all_three()); // end 1D dynamic extent pair, all, ptrdifft slice }}}1 //============================================================================== -template -constexpr bool -dynamic_extent_2d_idx_idx() { - int data[] = { 1, 2, 3, 4, 5, 6 }; - auto s = Kokkos::mdspan< - int, Kokkos::extents, Layout>( - data, 2, 3); +template +constexpr bool dynamic_extent_2d_idx_idx() { + int data[] = {1, 2, 3, 4, 5, 6}; + auto s = Kokkos::mdspan< + int, + Kokkos::extents, + Layout>(data, 2, 3); int result = 0; - for(size_t row = 0; row < s.extent(0); ++row) { - for(size_t col = 0; col < s.extent(1); ++col) { + for (size_t row = 0; row < s.extent(0); ++row) { + for (size_t col = 0; col < s.extent(1); ++col) { auto ss = Kokkos::submdspan(s, row, col); result += MDSPAN_IMPL_OP0(ss); } @@ -153,17 +149,17 @@ dynamic_extent_2d_idx_idx() { MDSPAN_STATIC_TEST(dynamic_extent_2d_idx_idx()); MDSPAN_STATIC_TEST(dynamic_extent_2d_idx_idx()); -template -constexpr bool -dynamic_extent_2d_idx_all_idx() { - int data[] = { 1, 2, 3, 4, 5, 6 }; - auto s = Kokkos::mdspan< - int, Kokkos::extents, Layout>( - data, 2, 3); +template +constexpr bool dynamic_extent_2d_idx_all_idx() { + int data[] = {1, 2, 3, 4, 5, 6}; + auto s = Kokkos::mdspan< + int, + Kokkos::extents, + Layout>(data, 2, 3); int result = 0; - for(size_t row = 0; row < s.extent(0); ++row) { + for (size_t row = 0; row < s.extent(0); ++row) { auto srow = Kokkos::submdspan(s, row, Kokkos::full_extent); - for(size_t col = 0; col < s.extent(1); ++col) { + for (size_t col = 0; col < s.extent(1); ++col) { auto scol = Kokkos::submdspan(srow, col); constexpr_assert_equal(MDSPAN_IMPL_OP0(scol), MDSPAN_IMPL_OP(srow, col)); result += MDSPAN_IMPL_OP0(scol); @@ -181,18 +177,13 @@ MDSPAN_STATIC_TEST(dynamic_extent_2d_idx_all_idx()); //============================================================================== -constexpr int -simple_static_submdspan_test_1(int add_to_row) { - int data[] = { - 1, 2, 3, - 4, 5, 6, - 7, 8, 9 - }; - auto s = Kokkos::mdspan>(data); +constexpr int simple_static_submdspan_test_1(int add_to_row) { + int data[] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; + auto s = Kokkos::mdspan>(data); int result = 0; - for(int col = 0; col < 3; ++col) { + for (int col = 0; col < 3; ++col) { auto scol = Kokkos::submdspan(s, Kokkos::full_extent, col); - for(int row = 0; row < 3; ++row) { + for (int row = 0; row < 3; ++row) { auto srow = Kokkos::submdspan(scol, row); result += MDSPAN_IMPL_OP0(srow) * (row + add_to_row); } @@ -201,49 +192,44 @@ simple_static_submdspan_test_1(int add_to_row) { } // MSVC ICE -#if !defined(MDSPAN_IMPL_COMPILER_MSVC) && (!defined(__GNUC__) || (__GNUC__>=6 && __GNUC_MINOR__>=4)) +#if !defined(MDSPAN_IMPL_COMPILER_MSVC) && \ + (!defined(__GNUC__) || (__GNUC__ >= 6 && __GNUC_MINOR__ >= 4)) MDSPAN_STATIC_TEST( - // 1 + 2 + 3 + 2*(4 + 5 + 6) + 3*(7 + 8 + 9) = 108 - simple_static_submdspan_test_1(1) == 108 -); + // 1 + 2 + 3 + 2*(4 + 5 + 6) + 3*(7 + 8 + 9) = 108 + simple_static_submdspan_test_1(1) == 108); MDSPAN_STATIC_TEST( - // -1 - 2 - 3 + 7 + 8 + 9 = 18 - simple_static_submdspan_test_1(-1) == 18 -); + // -1 - 2 - 3 + 7 + 8 + 9 = 18 + simple_static_submdspan_test_1(-1) == 18); MDSPAN_STATIC_TEST( - // -1 - 2 - 3 + 7 + 8 + 9 = 18 - Kokkos::mdspan>{nullptr}.extent(0) == 18 -); + // -1 - 2 - 3 + 7 + 8 + 9 = 18 + Kokkos::mdspan>{ + nullptr} + .extent(0) == 18); #endif //============================================================================== -constexpr bool -mixed_submdspan_left_test_2() { - int data[] = { - 1, 4, 7, - 2, 5, 8, - 3, 6, 9, - 0, 0, 0, - 0, 0, 0 - }; - auto s = Kokkos::mdspan, Kokkos::layout_left>(data, 5); +constexpr bool mixed_submdspan_left_test_2() { + int data[] = {1, 4, 7, 2, 5, 8, 3, 6, 9, 0, 0, 0, 0, 0, 0}; + auto s = + Kokkos::mdspan, + Kokkos::layout_left>(data, 5); int result = 0; - for(int col = 0; col < 5; ++col) { + for (int col = 0; col < 5; ++col) { auto scol = Kokkos::submdspan(s, Kokkos::full_extent, col); - for(int row = 0; row < 3; ++row) { + for (int row = 0; row < 3; ++row) { auto srow = Kokkos::submdspan(scol, row); result += MDSPAN_IMPL_OP0(srow) * (row + 1); } } // 1 + 2 + 3 + 2*(4 + 5 + 6) + 3*(7 + 8 + 9)= 108 constexpr_assert_equal(108, result); - for(int row = 0; row < 3; ++row) { + for (int row = 0; row < 3; ++row) { auto srow = Kokkos::submdspan(s, row, Kokkos::full_extent); - for(int col = 0; col < 5; ++col) { + for (int col = 0; col < 5; ++col) { auto scol = Kokkos::submdspan(srow, col); result += MDSPAN_IMPL_OP0(scol) * (row + 1); } @@ -255,37 +241,33 @@ mixed_submdspan_left_test_2() { } // MSVC ICE -#if !defined(MDSPAN_IMPL_COMPILER_MSVC) && (!defined(__GNUC__) || (__GNUC__>=6 && __GNUC_MINOR__>=4)) +#if !defined(MDSPAN_IMPL_COMPILER_MSVC) && \ + (!defined(__GNUC__) || (__GNUC__ >= 6 && __GNUC_MINOR__ >= 4)) MDSPAN_STATIC_TEST( - // 2 * (1 + 2 + 3 + 2*(4 + 5 + 6) + 3*(7 + 8 + 9)) / 2 = 108 - mixed_submdspan_left_test_2() -); + // 2 * (1 + 2 + 3 + 2*(4 + 5 + 6) + 3*(7 + 8 + 9)) / 2 = 108 + mixed_submdspan_left_test_2()); #endif //============================================================================== template -constexpr bool -mixed_submdspan_test_3() { - int data[] = { - 1, 4, 7, 2, 5, - 8, 3, 6, 9, 0, - 0, 0, 0, 0, 0 - }; - auto s = Kokkos::mdspan< - int, Kokkos::extents, Layout>(data, 5); +constexpr bool mixed_submdspan_test_3() { + int data[] = {1, 4, 7, 2, 5, 8, 3, 6, 9, 0, 0, 0, 0, 0, 0}; + auto s = + Kokkos::mdspan, + Layout>(data, 5); int result = 0; - for(int col = 0; col < 5; ++col) { + for (int col = 0; col < 5; ++col) { auto scol = Kokkos::submdspan(s, Kokkos::full_extent, col); - for(int row = 0; row < 3; ++row) { + for (int row = 0; row < 3; ++row) { auto srow = Kokkos::submdspan(scol, row); result += MDSPAN_IMPL_OP0(srow) * (row + 1); } } constexpr_assert_equal(71, result); - for(int row = 0; row < 3; ++row) { + for (int row = 0; row < 3; ++row) { auto srow = Kokkos::submdspan(s, row, Kokkos::full_extent); - for(int col = 0; col < 5; ++col) { + for (int col = 0; col < 5; ++col) { auto scol = Kokkos::submdspan(srow, col); result += MDSPAN_IMPL_OP0(scol) * (row + 1); } @@ -298,14 +280,13 @@ mixed_submdspan_test_3() { // MSVC ICE #ifndef MDSPAN_IMPL_COMPILER_MSVC -MDSPAN_STATIC_TEST( - mixed_submdspan_test_3() -); +MDSPAN_STATIC_TEST(mixed_submdspan_test_3()); #endif //============================================================================== -#if defined(MDSPAN_ENABLE_EXPENSIVE_COMPILATION_TESTS) && MDSPAN_ENABLE_EXPENSIVE_COMPILATION_TESTS +#if defined(MDSPAN_ENABLE_EXPENSIVE_COMPILATION_TESTS) && \ + MDSPAN_ENABLE_EXPENSIVE_COMPILATION_TESTS template constexpr auto _repeated_ptrdiff_t = Val; @@ -313,63 +294,64 @@ template using _repeated_with_idxs_t = T; template -constexpr bool -submdspan_single_element_stress_test_impl_2( - std::integer_sequence -) { +constexpr bool submdspan_single_element_stress_test_impl_2( + std::integer_sequence) { using mdspan_t = Kokkos::mdspan< - int, Kokkos::extents...>, Layout>; + int, Kokkos::extents...>, Layout>; using dyn_mdspan_t = Kokkos::mdspan< - int, Kokkos::extents...>, Layout>; - int data[] = { 42 }; - auto s = mdspan_t(data); - auto s_dyn = dyn_mdspan_t(data, _repeated_ptrdiff_t<1, Idxs>...); - auto ss = Kokkos::submdspan(s, _repeated_ptrdiff_t<0, Idxs>...); + int, + Kokkos::extents...>, + Layout>; + int data[] = {42}; + auto s = mdspan_t(data); + auto s_dyn = dyn_mdspan_t(data, _repeated_ptrdiff_t<1, Idxs>...); + auto ss = Kokkos::submdspan(s, _repeated_ptrdiff_t<0, Idxs>...); auto ss_dyn = Kokkos::submdspan(s_dyn, _repeated_ptrdiff_t<0, Idxs>...); - auto ss_all = Kokkos::submdspan(s, _repeated_with_idxs_t{}...); - auto ss_all_dyn = Kokkos::submdspan(s_dyn, _repeated_with_idxs_t{}...); - auto val = MDSPAN_IMPL_OP(ss_all, (_repeated_ptrdiff_t<0, Idxs>...)); + auto ss_all = Kokkos::submdspan( + s, _repeated_with_idxs_t{}...); + auto ss_all_dyn = Kokkos::submdspan( + s_dyn, _repeated_with_idxs_t{}...); + auto val = MDSPAN_IMPL_OP(ss_all, (_repeated_ptrdiff_t<0, Idxs>...)); auto val_dyn = MDSPAN_IMPL_OP(ss_all_dyn, (_repeated_ptrdiff_t<0, Idxs>...)); - auto ss_pair = Kokkos::submdspan(s, _repeated_with_idxs_t, Idxs>{0, 1}...); - auto ss_pair_dyn = Kokkos::submdspan(s_dyn, _repeated_with_idxs_t, Idxs>{0, 1}...); + auto ss_pair = Kokkos::submdspan( + s, _repeated_with_idxs_t, Idxs>{0, 1}...); + auto ss_pair_dyn = Kokkos::submdspan( + s_dyn, + _repeated_with_idxs_t, Idxs>{0, 1}...); auto val_pair = MDSPAN_IMPL_OP(ss_pair, (_repeated_ptrdiff_t<0, Idxs>...)); - auto val_pair_dyn = MDSPAN_IMPL_OP(ss_pair_dyn, (_repeated_ptrdiff_t<0, Idxs>...)); + auto val_pair_dyn = + MDSPAN_IMPL_OP(ss_pair_dyn, (_repeated_ptrdiff_t<0, Idxs>...)); constexpr_assert_equal(42, ss()); constexpr_assert_equal(42, ss_dyn()); constexpr_assert_equal(42, val); constexpr_assert_equal(42, val_dyn); constexpr_assert_equal(42, val_pair); constexpr_assert_equal(42, val_pair_dyn); - return MDSPAN_IMPL_OP0(ss) == 42 && MDSPAN_IMPL_OP0(ss_dyn) == 42 && val == 42 && val_dyn == 42 && val_pair == 42 && val_pair_dyn == 42; + return MDSPAN_IMPL_OP0(ss) == 42 && MDSPAN_IMPL_OP0(ss_dyn) == 42 && + val == 42 && val_dyn == 42 && val_pair == 42 && val_pair_dyn == 42; } template -constexpr bool -submdspan_single_element_stress_test_impl_1( - std::integer_sequence -) { +constexpr bool submdspan_single_element_stress_test_impl_1( + std::integer_sequence) { return MDSPAN_IMPL_FOLD_AND( - submdspan_single_element_stress_test_impl_2( - std::make_index_sequence{} - ) /* && ... */ + submdspan_single_element_stress_test_impl_2( + std::make_index_sequence{}) /* && ... */ ); } template -constexpr bool -submdspan_single_element_stress_test() { +constexpr bool submdspan_single_element_stress_test() { return submdspan_single_element_stress_test_impl_1( - std::make_index_sequence{} - ); + std::make_index_sequence{}); } MDSPAN_STATIC_TEST( - submdspan_single_element_stress_test() -); + submdspan_single_element_stress_test()); MDSPAN_STATIC_TEST( - submdspan_single_element_stress_test() -); + submdspan_single_element_stress_test()); -#endif // MDSPAN_DISABLE_EXPENSIVE_COMPILATION_TESTS +#endif // MDSPAN_DISABLE_EXPENSIVE_COMPILATION_TESTS -#endif // defined(MDSPAN_IMPL_USE_CONSTEXPR_14) && MDSPAN_IMPL_USE_CONSTEXPR_14 +#endif // defined(MDSPAN_IMPL_USE_CONSTEXPR_14) && MDSPAN_IMPL_USE_CONSTEXPR_14 diff --git a/compilation_tests/ctest_constructor_sfinae.cpp b/compilation_tests/ctest_constructor_sfinae.cpp index 857888a8..59c5fcf8 100644 --- a/compilation_tests/ctest_constructor_sfinae.cpp +++ b/compilation_tests/ctest_constructor_sfinae.cpp @@ -7,7 +7,7 @@ #include - +// clang-format off //============================================================================== // {{{1 @@ -165,6 +165,7 @@ MDSPAN_STATIC_TEST( int*, Kokkos::dextents >::value ); +// clang-format on // end Test forbidden pointer + extents ctors }}}1 //============================================================================== diff --git a/compilation_tests/ctest_extents_ctors.cpp b/compilation_tests/ctest_extents_ctors.cpp index 12565989..612b14b9 100644 --- a/compilation_tests/ctest_extents_ctors.cpp +++ b/compilation_tests/ctest_extents_ctors.cpp @@ -5,7 +5,7 @@ #include - +// clang-format off MDSPAN_STATIC_TEST( std::is_constructible< @@ -289,3 +289,5 @@ MDSPAN_STATIC_TEST( MDSPAN_STATIC_TEST( Kokkos::extents{Kokkos::extents{}}.extent(0) == 0 ); + +// clang-format on diff --git a/compilation_tests/ctest_extents_type_check.cpp b/compilation_tests/ctest_extents_type_check.cpp index 58a90ea6..93df44f8 100644 --- a/compilation_tests/ctest_extents_type_check.cpp +++ b/compilation_tests/ctest_extents_type_check.cpp @@ -5,9 +5,9 @@ #include - using E1 = Kokkos::extents; +// clang-format off MDSPAN_STATIC_TEST( std::is_same::value && std::is_same::value && @@ -65,3 +65,4 @@ MDSPAN_STATIC_TEST( (E3::static_extent(1) == 3) && (E3::static_extent(2) == Kokkos::dynamic_extent) ); +// clang-format on diff --git a/compilation_tests/ctest_layout_convertible.cpp b/compilation_tests/ctest_layout_convertible.cpp index 27cee0c8..6f17ac12 100644 --- a/compilation_tests/ctest_layout_convertible.cpp +++ b/compilation_tests/ctest_layout_convertible.cpp @@ -5,42 +5,45 @@ #include - struct NotARealLayout { - template + template struct mapping { using extents_type = Extents; - using rank_type = typename extents_type::rank_type; - using index_type = typename extents_type::index_type; - using layout_type = NotARealLayout; + using rank_type = typename extents_type::rank_type; + using index_type = typename extents_type::index_type; + using layout_type = NotARealLayout; constexpr extents_type& extents() const { return ext; } - template - index_type operator()(Idx ...) const { return 0; } + template + index_type operator()(Idx...) const { + return 0; + } index_type required_span_size() const { return 0; } index_type stride(rank_type) const { return 1; } - private: - extents_type ext; + private: + extents_type ext; }; }; -template +template struct AStridedLayout { - template + template struct mapping { using extents_type = Extents; - using rank_type = typename extents_type::rank_type; - using index_type = typename extents_type::index_type; - using layout_type = AStridedLayout; + using rank_type = typename extents_type::rank_type; + using index_type = typename extents_type::index_type; + using layout_type = AStridedLayout; constexpr extents_type& extents() const { return ext; } - template - index_type operator()(Idx ...) const { return 0; } + template + index_type operator()(Idx...) const { + return 0; + } index_type required_span_size() const { return 0; } @@ -53,16 +56,17 @@ struct AStridedLayout { constexpr bool is_unique() { return unique; } constexpr bool is_exhaustive() { return true; } - private: - extents_type ext; + private: + extents_type ext; }; }; -using E1 = Kokkos::extents; -using E2 = Kokkos::extents; +using E1 = Kokkos::extents; +using E2 = Kokkos::extents; using LS1 = Kokkos::layout_stride::mapping; using LS2 = Kokkos::layout_stride::mapping; +// clang-format off MDSPAN_STATIC_TEST( !std::is_constructible::mapping>::value && !std::is_convertible::mapping, LS1>::value @@ -100,3 +104,4 @@ MDSPAN_STATIC_TEST(std::is_constructible::m MDSPAN_STATIC_TEST(std::is_convertible::mapping, LS1>::value); MDSPAN_STATIC_TEST(std::is_assignable::mapping>::value); #endif +// clang-format on diff --git a/compilation_tests/ctest_layout_type_check.cpp b/compilation_tests/ctest_layout_type_check.cpp index 88067f19..28bbd517 100644 --- a/compilation_tests/ctest_layout_type_check.cpp +++ b/compilation_tests/ctest_layout_type_check.cpp @@ -5,7 +5,7 @@ #include - +// clang-format off using E1 = Kokkos::extents; using MLR1 = Kokkos::layout_right::mapping; // Note we already separately tested that the extents interface is correct @@ -73,3 +73,4 @@ MDSPAN_STATIC_TEST( (MLS1::is_always_exhaustive()== false) && (MLS1::is_always_strided() == true) ); +// clang-format on diff --git a/compilation_tests/ctest_mdarray_type_check.cpp b/compilation_tests/ctest_mdarray_type_check.cpp index 1b8fea2c..e97f979d 100644 --- a/compilation_tests/ctest_mdarray_type_check.cpp +++ b/compilation_tests/ctest_mdarray_type_check.cpp @@ -10,23 +10,24 @@ #include #endif -namespace KokkosEx = MDSPAN_IMPL_STANDARD_NAMESPACE::MDSPAN_IMPL_PROPOSED_NAMESPACE; +namespace KokkosEx = + MDSPAN_IMPL_STANDARD_NAMESPACE::MDSPAN_IMPL_PROPOSED_NAMESPACE; using E1 = Kokkos::extents; using M1 = KokkosEx::mdarray; #if defined(MDSPAN_IMPL_USE_CONCEPTS) && MDSPAN_HAS_CXX_20 -template +template constexpr bool is_copyable = std::copyable; #else -template +template constexpr bool is_copyable = - std::is_assignable::value && - std::is_move_assignable::value && - std::is_copy_constructible::value && - std::is_move_constructible::value; + std::is_assignable::value && std::is_move_assignable::value && + std::is_copy_constructible::value && + std::is_move_constructible::value; #endif +// clang-format off MDSPAN_STATIC_TEST( std::is_same::value && std::is_same::value && @@ -101,3 +102,4 @@ MDSPAN_STATIC_TEST( is_copyable && std::is_default_constructible::value ); +// clang-format on diff --git a/compilation_tests/ctest_mdspan_convertible.cpp b/compilation_tests/ctest_mdspan_convertible.cpp index d9397819..69a39997 100644 --- a/compilation_tests/ctest_mdspan_convertible.cpp +++ b/compilation_tests/ctest_mdspan_convertible.cpp @@ -7,7 +7,7 @@ #include - +// clang-format off //============================================================================== // {{{1 @@ -27,4 +27,4 @@ MDSPAN_STATIC_TEST( // end mdspan }}}1 //============================================================================== - +// clang-format on diff --git a/compilation_tests/ctest_namespace_std.cpp b/compilation_tests/ctest_namespace_std.cpp index 6cdf737a..7a0da88c 100644 --- a/compilation_tests/ctest_namespace_std.cpp +++ b/compilation_tests/ctest_namespace_std.cpp @@ -8,5 +8,5 @@ #include "ctest_common.hpp" using test_extents_type = std::extents; -using test_mdspan_type = std::mdspan; +using test_mdspan_type = std::mdspan; using test_mdarray_type = std::experimental::mdarray; diff --git a/compilation_tests/ctest_no_unique_address.cpp b/compilation_tests/ctest_no_unique_address.cpp index d31f0b32..248f01f6 100644 --- a/compilation_tests/ctest_no_unique_address.cpp +++ b/compilation_tests/ctest_no_unique_address.cpp @@ -7,7 +7,7 @@ #include - +// clang-format off //============================================================================== // {{{1 @@ -66,7 +66,7 @@ MDSPAN_STATIC_TEST( Kokkos::extents >) == 4 * sizeof(size_t) ); - +// clang-format on // end layouts }}}1 //============================================================================== diff --git a/compilation_tests/ctest_standard_layout.cpp b/compilation_tests/ctest_standard_layout.cpp index 8aa3e4d3..bbb89f35 100644 --- a/compilation_tests/ctest_standard_layout.cpp +++ b/compilation_tests/ctest_standard_layout.cpp @@ -7,52 +7,32 @@ #include - - //============================================================================== // {{{1 MDSPAN_STATIC_TEST( - std::is_standard_layout< - Kokkos::extents - >::value -); + std::is_standard_layout< + Kokkos::extents>::value); -MDSPAN_STATIC_TEST( - std::is_standard_layout< - Kokkos::extents - >::value -); +MDSPAN_STATIC_TEST(std::is_standard_layout< + Kokkos::extents>::value); MDSPAN_STATIC_TEST( - std::is_standard_layout< - Kokkos::extents - >::value -); + std::is_standard_layout>::value); MDSPAN_STATIC_TEST( - std::is_standard_layout< - Kokkos::extents - >::value -); + std::is_standard_layout< + Kokkos::extents>::value); MDSPAN_STATIC_TEST( - std::is_standard_layout< - Kokkos::extents - >::value -); + std::is_standard_layout< + Kokkos::extents>::value); MDSPAN_STATIC_TEST( - std::is_standard_layout< - Kokkos::extents - >::value -); + std::is_standard_layout>::value); -MDSPAN_STATIC_TEST( - std::is_standard_layout< - Kokkos::extents - >::value -); +MDSPAN_STATIC_TEST(std::is_standard_layout>::value); // end extents }}}1 //============================================================================== @@ -61,52 +41,30 @@ MDSPAN_STATIC_TEST( // {{{1 MDSPAN_STATIC_TEST( - std::is_standard_layout< - Kokkos::layout_left::template mapping< - Kokkos::extents - > - >::value -); + std::is_standard_layout>>::value); MDSPAN_STATIC_TEST( - std::is_standard_layout< - Kokkos::layout_right::template mapping< - Kokkos::extents - > - >::value -); + std::is_standard_layout>>::value); MDSPAN_STATIC_TEST( - std::is_standard_layout< - Kokkos::layout_right::template mapping< - Kokkos::extents - > - >::value -); + std::is_standard_layout< + Kokkos::layout_right::template mapping>>::value); MDSPAN_STATIC_TEST( - std::is_standard_layout< - Kokkos::layout_stride::template mapping< - Kokkos::extents - > - >::value -); + std::is_standard_layout>>::value); MDSPAN_STATIC_TEST( - std::is_standard_layout< - Kokkos::layout_stride::template mapping< - Kokkos::extents - > - >::value -); + std::is_standard_layout>>::value); MDSPAN_STATIC_TEST( - std::is_standard_layout< - Kokkos::layout_stride::template mapping< - Kokkos::extents - > - >::value -); + std::is_standard_layout< + Kokkos::layout_stride::template mapping>>::value); // TODO: Remove this test alltogether? // CT: Fails with GCC too after I removed the template parameter @@ -134,25 +92,16 @@ MDSPAN_STATIC_TEST( // {{{1 MDSPAN_STATIC_TEST( - std::is_standard_layout< - Kokkos::mdspan> - >::value -); + std::is_standard_layout< + Kokkos::mdspan>>::value); -MDSPAN_STATIC_TEST( - std::is_standard_layout< - Kokkos::mdspan> - >::value -); +MDSPAN_STATIC_TEST(std::is_standard_layout< + Kokkos::mdspan>>::value); MDSPAN_STATIC_TEST( - std::is_standard_layout< - Kokkos::mdspan< - double, Kokkos::dextents, - Kokkos::layout_left, Kokkos::default_accessor - > - >::value -); + std::is_standard_layout< + Kokkos::mdspan, Kokkos::layout_left, + Kokkos::default_accessor>>::value); // end mdspan }}}1 //============================================================================== diff --git a/compilation_tests/ctest_trivially_copyable.cpp b/compilation_tests/ctest_trivially_copyable.cpp index e2e528c5..d273616e 100644 --- a/compilation_tests/ctest_trivially_copyable.cpp +++ b/compilation_tests/ctest_trivially_copyable.cpp @@ -7,52 +7,33 @@ #include - - //============================================================================== // {{{1 MDSPAN_STATIC_TEST( - std::is_trivially_copyable< - Kokkos::extents - >::value -); + std::is_trivially_copyable< + Kokkos::extents>::value); -MDSPAN_STATIC_TEST( - std::is_trivially_copyable< - Kokkos::extents - >::value -); +MDSPAN_STATIC_TEST(std::is_trivially_copyable< + Kokkos::extents>::value); MDSPAN_STATIC_TEST( - std::is_trivially_copyable< - Kokkos::extents - >::value -); + std::is_trivially_copyable>::value); MDSPAN_STATIC_TEST( - std::is_trivially_copyable< - Kokkos::extents - >::value -); + std::is_trivially_copyable< + Kokkos::extents>::value); MDSPAN_STATIC_TEST( - std::is_trivially_copyable< - Kokkos::extents - >::value -); + std::is_trivially_copyable< + Kokkos::extents>::value); MDSPAN_STATIC_TEST( - std::is_trivially_copyable< - Kokkos::extents - >::value -); + std::is_trivially_copyable>::value); MDSPAN_STATIC_TEST( - std::is_trivially_copyable< - Kokkos::extents - >::value -); + std::is_trivially_copyable>::value); // end extents }}}1 //============================================================================== @@ -61,66 +42,41 @@ MDSPAN_STATIC_TEST( // {{{1 MDSPAN_STATIC_TEST( - std::is_trivially_copyable< - Kokkos::layout_left::template mapping< - Kokkos::extents - > - >::value -); + std::is_trivially_copyable>>::value); MDSPAN_STATIC_TEST( - std::is_trivially_copyable< - Kokkos::layout_right::template mapping< - Kokkos::extents - > - >::value -); + std::is_trivially_copyable>>::value); MDSPAN_STATIC_TEST( - std::is_trivially_copyable< - Kokkos::layout_right::template mapping< - Kokkos::extents - > - >::value -); + std::is_trivially_copyable< + Kokkos::layout_right::template mapping>>::value); MDSPAN_STATIC_TEST( - std::is_trivially_copyable< - Kokkos::layout_stride::template mapping< - Kokkos::extents - > - >::value -); + std::is_trivially_copyable>>::value); MDSPAN_STATIC_TEST( - std::is_trivially_copyable< - Kokkos::layout_stride::template mapping< - Kokkos::extents - > - >::value -); + std::is_trivially_copyable>>::value); MDSPAN_STATIC_TEST( - std::is_trivially_copyable< - Kokkos::layout_stride::template mapping< - Kokkos::extents - > - >::value -); - -struct layout_stride_as_member_should_be_standard_layout : - Kokkos::layout_stride::template mapping< - Kokkos::extents - > -{ + std::is_trivially_copyable< + Kokkos::layout_stride::template mapping>>::value); + +struct layout_stride_as_member_should_be_standard_layout + : Kokkos::layout_stride::template mapping< + Kokkos::extents> { int foo; }; // Fails with MSVC which adds some padding #ifndef MDSPAN_IMPL_COMPILER_MSVC -MDSPAN_STATIC_TEST( - std::is_trivially_copyable::value -); +MDSPAN_STATIC_TEST(std::is_trivially_copyable< + layout_stride_as_member_should_be_standard_layout>::value); #endif // end layouts }}}1 @@ -130,25 +86,17 @@ MDSPAN_STATIC_TEST( // {{{1 MDSPAN_STATIC_TEST( - std::is_trivially_copyable< - Kokkos::mdspan> - >::value -); + std::is_trivially_copyable< + Kokkos::mdspan>>::value); -MDSPAN_STATIC_TEST( - std::is_trivially_copyable< - Kokkos::mdspan> - >::value -); +MDSPAN_STATIC_TEST(std::is_trivially_copyable< + Kokkos::mdspan>>::value); MDSPAN_STATIC_TEST( - std::is_trivially_copyable< - Kokkos::mdspan< - double, Kokkos::extents, - Kokkos::layout_left, Kokkos::default_accessor - > - >::value -); + std::is_trivially_copyable, + Kokkos::layout_left, Kokkos::default_accessor>>::value); // end mdspan }}}1 //============================================================================== diff --git a/examples/aligned_accessor/aligned_accessor.cpp b/examples/aligned_accessor/aligned_accessor.cpp index 4745121e..c48c9d60 100644 --- a/examples/aligned_accessor/aligned_accessor.cpp +++ b/examples/aligned_accessor/aligned_accessor.cpp @@ -6,76 +6,88 @@ // Just checking __cpp_lib_int_pow2 isn't enough for some GCC versions. // The header exists, but std::has_single_bit does not. #if defined(__cpp_lib_int_pow2) && __cplusplus >= 202002L -# include +#include #endif #include #include -#include // aligned_alloc, posix_memalign (if applicable) +#include // aligned_alloc, posix_memalign (if applicable) #include #include #include #include #include -#include // stoi +#include // stoi // mfh 2022/08/08: This is based on my comment on RAPIDS RAFT issue 725: // https://github.com/rapidsai/raft/pull/725#discussion_r937991701 namespace { -using test_value_type = float; +using test_value_type = float; constexpr std::size_t min_overalignment_factor = 8; -constexpr std::size_t min_byte_alignment = min_overalignment_factor * sizeof(float); +constexpr std::size_t min_byte_alignment = + min_overalignment_factor * sizeof(float); // Use int, not size_t, as the index_type. -// Some compilers have trouble optimizing loops with unsigned or 64-bit index types. +// Some compilers have trouble optimizing loops with unsigned or 64-bit index +// types. using index_type = int; - // Prefer std::assume_aligned if available, as it is in the C++ Standard. // Otherwise, use a compiler-specific equivalent if available. // NOTE (mfh 2022/08/08) BYTE_ALIGNMENT must be unsigned and a power of 2. #if defined(__cpp_lib_assume_aligned) -# define MDSPAN_IMPL_ASSUME_ALIGNED( ELEMENT_TYPE, POINTER, BYTE_ALIGNMENT ) (std::assume_aligned< BYTE_ALIGNMENT >( POINTER )) - constexpr char assume_aligned_method[] = "std::assume_aligned"; +#define MDSPAN_IMPL_ASSUME_ALIGNED(ELEMENT_TYPE, POINTER, BYTE_ALIGNMENT) \ + (std::assume_aligned(POINTER)) +constexpr char assume_aligned_method[] = "std::assume_aligned"; #elif defined(__ICL) -# define MDSPAN_IMPL_ASSUME_ALIGNED( ELEMENT_TYPE, POINTER, BYTE_ALIGNMENT ) POINTER - constexpr char assume_aligned_method[] = "(none)"; +#define MDSPAN_IMPL_ASSUME_ALIGNED(ELEMENT_TYPE, POINTER, BYTE_ALIGNMENT) \ + POINTER +constexpr char assume_aligned_method[] = "(none)"; #elif defined(__ICC) -# define MDSPAN_IMPL_ASSUME_ALIGNED( ELEMENT_TYPE, POINTER, BYTE_ALIGNMENT ) POINTER - constexpr char assume_aligned_method[] = "(none)"; +#define MDSPAN_IMPL_ASSUME_ALIGNED(ELEMENT_TYPE, POINTER, BYTE_ALIGNMENT) \ + POINTER +constexpr char assume_aligned_method[] = "(none)"; #elif defined(__clang__) -# define MDSPAN_IMPL_ASSUME_ALIGNED( ELEMENT_TYPE, POINTER, BYTE_ALIGNMENT ) POINTER - constexpr char assume_aligned_method[] = "(none)"; +#define MDSPAN_IMPL_ASSUME_ALIGNED(ELEMENT_TYPE, POINTER, BYTE_ALIGNMENT) \ + POINTER +constexpr char assume_aligned_method[] = "(none)"; #elif defined(__GNUC__) - // __builtin_assume_aligned returns void* -# define MDSPAN_IMPL_ASSUME_ALIGNED( ELEMENT_TYPE, POINTER, BYTE_ALIGNMENT ) reinterpret_cast< ELEMENT_TYPE* >(__builtin_assume_aligned( POINTER, BYTE_ALIGNMENT )) - constexpr char assume_aligned_method[] = "__builtin_assume_aligned"; +// __builtin_assume_aligned returns void* +#define MDSPAN_IMPL_ASSUME_ALIGNED(ELEMENT_TYPE, POINTER, BYTE_ALIGNMENT) \ + reinterpret_cast( \ + __builtin_assume_aligned(POINTER, BYTE_ALIGNMENT)) +constexpr char assume_aligned_method[] = "__builtin_assume_aligned"; #else -# define MDSPAN_IMPL_ASSUME_ALIGNED( ELEMENT_TYPE, POINTER, BYTE_ALIGNMENT ) POINTER - constexpr char assume_aligned_method[] = "(none)"; +#define MDSPAN_IMPL_ASSUME_ALIGNED(ELEMENT_TYPE, POINTER, BYTE_ALIGNMENT) \ + POINTER +constexpr char assume_aligned_method[] = "(none)"; #endif // Some compilers other than Clang or GCC like to define __clang__ or __GNUC__. // Thus, we order the tests from most to least specific. #if defined(__ICL) -# define MDSPAN_IMPL_ALIGN_VALUE_ATTRIBUTE( BYTE_ALIGNMENT ) __declspec(align_value( BYTE_ALIGNMENT )) - constexpr char align_attribute_method[] = "__declspec(align_value(BYTE_ALIGNMENT))"; +#define MDSPAN_IMPL_ALIGN_VALUE_ATTRIBUTE(BYTE_ALIGNMENT) \ + __declspec(align_value(BYTE_ALIGNMENT)) +constexpr char align_attribute_method[] = + "__declspec(align_value(BYTE_ALIGNMENT))"; #elif defined(__ICC) -# define MDSPAN_IMPL_ALIGN_VALUE_ATTRIBUTE( BYTE_ALIGNMENT ) __attribute__((align_value( BYTE_ALIGNMENT ))) - constexpr char align_attribute_method[] = "__attribute__((align_value(BYTE_ALIGNMENT)))"; +#define MDSPAN_IMPL_ALIGN_VALUE_ATTRIBUTE(BYTE_ALIGNMENT) \ + __attribute__((align_value(BYTE_ALIGNMENT))) +constexpr char align_attribute_method[] = + "__attribute__((align_value(BYTE_ALIGNMENT)))"; #elif defined(__clang__) -# define MDSPAN_IMPL_ALIGN_VALUE_ATTRIBUTE( BYTE_ALIGNMENT ) __attribute__((align_value( BYTE_ALIGNMENT ))) - constexpr char align_attribute_method[] = "__attribute__((align_value(BYTE_ALIGNMENT)))"; +#define MDSPAN_IMPL_ALIGN_VALUE_ATTRIBUTE(BYTE_ALIGNMENT) \ + __attribute__((align_value(BYTE_ALIGNMENT))) +constexpr char align_attribute_method[] = + "__attribute__((align_value(BYTE_ALIGNMENT)))"; #else -# define MDSPAN_IMPL_ALIGN_VALUE_ATTRIBUTE( BYTE_ALIGNMENT ) - constexpr char align_attribute_method[] = "(none)"; +#define MDSPAN_IMPL_ALIGN_VALUE_ATTRIBUTE(BYTE_ALIGNMENT) +constexpr char align_attribute_method[] = "(none)"; #endif -constexpr bool -is_nonzero_power_of_two(const std::size_t x) -{ +constexpr bool is_nonzero_power_of_two(const std::size_t x) { // Just checking __cpp_lib_int_pow2 isn't enough for some GCC versions. // The header exists, but std::has_single_bit does not. #if defined(__cpp_lib_int_pow2) && __cplusplus >= 202002L @@ -85,76 +97,78 @@ is_nonzero_power_of_two(const std::size_t x) #endif } -template -constexpr bool -valid_byte_alignment(const std::size_t byte_alignment) -{ - return is_nonzero_power_of_two(byte_alignment) && byte_alignment >= alignof(ElementType); +template +constexpr bool valid_byte_alignment(const std::size_t byte_alignment) { + return is_nonzero_power_of_two(byte_alignment) && + byte_alignment >= alignof(ElementType); } // We define aligned_pointer_t through a struct // so we can check whether the byte alignment is valid. // This makes it impossible to use the alias // with an invalid byte alignment. -template +template struct aligned_pointer { static_assert(valid_byte_alignment(byte_alignment), - "byte_alignment must be a power of two no less than " - "the minimum required alignment of ElementType."); + "byte_alignment must be a power of two no less than " + "the minimum required alignment of ElementType."); #if defined(__ICC) - // x86-64 ICC 2021.5.0 emits warning #3186 ("expected typedef declaration") here. - // No other compiler (including Clang, which has a similar type attribute) has this issue. -# pragma warning push -# pragma warning disable 3186 + // x86-64 ICC 2021.5.0 emits warning #3186 ("expected typedef declaration") + // here. No other compiler (including Clang, which has a similar type + // attribute) has this issue. +#pragma warning push +#pragma warning disable 3186 #endif - using type = ElementType* MDSPAN_IMPL_ALIGN_VALUE_ATTRIBUTE( byte_alignment ); + using type = ElementType* MDSPAN_IMPL_ALIGN_VALUE_ATTRIBUTE(byte_alignment); #if defined(__ICC) -# pragma warning pop +#pragma warning pop #endif }; -template -using aligned_pointer_t = typename aligned_pointer::type; +template +using aligned_pointer_t = + typename aligned_pointer::type; -template -aligned_pointer_t -bless(ElementType* ptr, std::integral_constant /* ba */ ) -{ - return MDSPAN_IMPL_ASSUME_ALIGNED( ElementType, ptr, byte_alignment ); +template +aligned_pointer_t bless( + ElementType* ptr, + std::integral_constant /* ba */) { + return MDSPAN_IMPL_ASSUME_ALIGNED(ElementType, ptr, byte_alignment); } -template +template struct aligned_accessor { - using offset_policy = Kokkos::default_accessor; - using element_type = ElementType; - using reference = ElementType&; + using offset_policy = Kokkos::default_accessor; + using element_type = ElementType; + using reference = ElementType&; using data_handle_type = aligned_pointer_t; constexpr aligned_accessor() noexcept = default; MDSPAN_TEMPLATE_REQUIRES( - class OtherElementType, - std::size_t other_byte_alignment, - /* requires */ (std::is_convertible::value && other_byte_alignment == byte_alignment) - ) - constexpr aligned_accessor(aligned_accessor) noexcept {} + class OtherElementType, std::size_t other_byte_alignment, + /* requires */ + (std::is_convertible::value&& + other_byte_alignment == byte_alignment)) + constexpr aligned_accessor( + aligned_accessor) noexcept {} constexpr reference access(data_handle_type p, size_t i) const noexcept { // This may declare alignment twice, depending on // if we have an attribute for marking pointer types. - return MDSPAN_IMPL_ASSUME_ALIGNED( ElementType, p, byte_alignment )[i]; + return MDSPAN_IMPL_ASSUME_ALIGNED(ElementType, p, byte_alignment)[i]; } - constexpr typename offset_policy::data_handle_type - offset(data_handle_type p, size_t i) const noexcept { + constexpr typename offset_policy::data_handle_type offset( + data_handle_type p, size_t i) const noexcept { return p + i; } }; -template +template struct delete_raw { void operator()(ElementType* p) const { if (p != nullptr) { @@ -166,39 +180,38 @@ struct delete_raw { } }; -template -using allocation_t = std::unique_ptr< - ElementType[], - delete_raw - >; +template +using allocation_t = std::unique_ptr>; -template -allocation_t -allocate_raw(const std::size_t num_elements) -{ +template +allocation_t allocate_raw(const std::size_t num_elements) { static_assert(byte_alignment >= sizeof(ElementType), - "byte_alignment must be at least sizeof(ElementType)."); - static constexpr std::size_t overalignment = byte_alignment / sizeof(ElementType); - static_assert(overalignment * sizeof(ElementType) == byte_alignment, - "overalignment * sizeof(ElementType) must equal byte_alignment."); + "byte_alignment must be at least sizeof(ElementType)."); + static constexpr std::size_t overalignment = + byte_alignment / sizeof(ElementType); + static_assert( + overalignment * sizeof(ElementType) == byte_alignment, + "overalignment * sizeof(ElementType) must equal byte_alignment."); const std::size_t num_bytes = num_elements * sizeof(ElementType); - auto deleter = delete_raw{}; + auto deleter = delete_raw{}; void* ptr = nullptr; #ifdef _MSC_VER // MSVC 19.32 (or "latest" on godbolt.org) does NOT have aligned_alloc, // even with /std:c++latest. Instead, we use MSVC-specific _aligned_malloc. ptr = _aligned_malloc(num_bytes, byte_alignment); -#elif __cplusplus < 201703L || (defined(__APPLE__) && defined(__apple_build_version__)) - // aligned_alloc is a C11 function. Apple Clang and GCC do not provide it with - // -std=c++14. We have coverage for the Windows case (at least with MSVC) above, - // so we can resort to the POSIX function posix_memalign. +#elif __cplusplus < 201703L || \ + (defined(__APPLE__) && defined(__apple_build_version__)) + // aligned_alloc is a C11 function. Apple Clang and GCC do not provide it + // with -std=c++14. We have coverage for the Windows case (at least with + // MSVC) above, so we can resort to the POSIX function posix_memalign. const int err = posix_memalign(&ptr, byte_alignment, num_bytes); - if(err != 0) { - if(err == EINVAL) { - throw std::runtime_error("posix_memalign failed: alignment not a power of two"); - } else if(err == ENOMEM) { + if (err != 0) { + if (err == EINVAL) { + throw std::runtime_error( + "posix_memalign failed: alignment not a power of two"); + } else if (err == ENOMEM) { throw std::runtime_error("posix_memalign failed: insufficient memory"); } else { throw std::runtime_error("posix_memalign failed: unknown error"); @@ -219,26 +232,28 @@ allocate_raw(const std::size_t num_elements) // // This needs to be a class in order to preserve the invariant that // "pointer" points to the allocation. -template +template class aligned_array_allocation { static_assert(byte_alignment >= sizeof(ElementType), - "byte_alignment must be at least sizeof(ElementType)."); - static constexpr std::size_t overalignment = byte_alignment / sizeof(ElementType); - static_assert(overalignment * sizeof(ElementType) == byte_alignment, - "overalignment * sizeof(ElementType) must equal byte_alignment."); -public: - aligned_array_allocation(std::size_t number_of_elements) : - allocation(allocate_raw(number_of_elements)), - pointer(allocation.get()), - num_elements(number_of_elements) - {} - - aligned_pointer_t data() const - { - return MDSPAN_IMPL_ASSUME_ALIGNED( ElementType, pointer, byte_alignment ); + "byte_alignment must be at least sizeof(ElementType)."); + static constexpr std::size_t overalignment = + byte_alignment / sizeof(ElementType); + static_assert( + overalignment * sizeof(ElementType) == byte_alignment, + "overalignment * sizeof(ElementType) must equal byte_alignment."); + + public: + aligned_array_allocation(std::size_t number_of_elements) + : allocation( + allocate_raw(number_of_elements)), + pointer(allocation.get()), + num_elements(number_of_elements) {} + + aligned_pointer_t data() const { + return MDSPAN_IMPL_ASSUME_ALIGNED(ElementType, pointer, byte_alignment); } -private: + private: allocation_t allocation{nullptr, delete_raw{}}; aligned_pointer_t pointer{nullptr}; std::size_t num_elements{0}; @@ -254,33 +269,30 @@ class aligned_array_allocation { // 2-wide SIMD code without needing a loop prelude or postlude to // handle the "unaligned remainder." Forcing "unalignment" will thus // give us a better performance comparison with the aligned case. -template +template class deliberately_unaligned_array_allocation { -public: - deliberately_unaligned_array_allocation(std::size_t number_of_elements) : - allocation(allocate_raw(number_of_elements + 1)), - pointer(unaligned_pointer(allocation.get())), - num_elements(number_of_elements) - {} - - ElementType* data() const { - return pointer; - } + public: + deliberately_unaligned_array_allocation(std::size_t number_of_elements) + : allocation(allocate_raw( + number_of_elements + 1)), + pointer(unaligned_pointer(allocation.get())), + num_elements(number_of_elements) {} + + ElementType* data() const { return pointer; } -private: + private: // Just asking for the minimum alignment of sizeof(ElementType) // bytes isn't enough, because the allocator might overalign that // allocation. Instead, we ask for an extra element, check whether // the allocation is "odd" or "even," and add one if needed. - static ElementType* - unaligned_pointer(ElementType* allocation_pointer) - { - if(allocation_pointer == nullptr) { + static ElementType* unaligned_pointer(ElementType* allocation_pointer) { + if (allocation_pointer == nullptr) { return nullptr; } - const auto ptr_as_uint = reinterpret_cast(allocation_pointer); + const auto ptr_as_uint = + reinterpret_cast(allocation_pointer); const auto bias = ptr_as_uint % std::uintptr_t(2 * sizeof(ElementType)); - if(bias == 0) { + if (bias == 0) { // It's aligned to sizeof(ElementType) times 2^k for integer k > 0. // Add one (that is, sizeof(ElementType) bytes) to make it "odd" again. return allocation_pointer + 1; @@ -294,45 +306,42 @@ class deliberately_unaligned_array_allocation { std::size_t num_elements{0}; }; -template +template using aligned_mdspan_1d = - Kokkos::mdspan, - Kokkos::layout_right, - aligned_accessor>; + Kokkos::mdspan, + Kokkos::layout_right, + aligned_accessor>; -template +template using mdspan_1d = - Kokkos::mdspan, - Kokkos::layout_right, - Kokkos::default_accessor>; + Kokkos::mdspan, + Kokkos::layout_right, Kokkos::default_accessor>; #define TICK() const auto tick = std::chrono::steady_clock::now() using double_seconds = std::chrono::duration>; -#define TOCK() std::chrono::duration_cast(std::chrono::steady_clock::now() - tick).count() +#define TOCK() \ + std::chrono::duration_cast( \ + std::chrono::steady_clock::now() - tick) \ + .count() -template -void add_aligned_mdspan_1d(aligned_mdspan_1d x, - aligned_mdspan_1d y, - aligned_mdspan_1d z) -{ +template +void add_aligned_mdspan_1d( + aligned_mdspan_1d x, + aligned_mdspan_1d y, + aligned_mdspan_1d z) { const index_type n = z.extent(0); for (index_type i = 0; i < n; ++i) { z[i] = x[i] + y[i]; } } -template -auto benchmark_add_aligned_mdspan_1d(const std::size_t num_trials, - const index_type n, - const ElementType x[], - const ElementType y[], - ElementType z[], - std::integral_constant /* ba */ ) -{ +template +auto benchmark_add_aligned_mdspan_1d( + const std::size_t num_trials, const index_type n, const ElementType x[], + const ElementType y[], ElementType z[], + std::integral_constant /* ba */) { TICK(); aligned_mdspan_1d x2{x, n}; aligned_mdspan_1d y2{y, n}; @@ -343,24 +352,19 @@ auto benchmark_add_aligned_mdspan_1d(const std::size_t num_trials, return TOCK(); } -template +template void add_mdspan_1d(mdspan_1d x, - mdspan_1d y, - mdspan_1d z) -{ + mdspan_1d y, mdspan_1d z) { const index_type n = z.extent(0); for (index_type i = 0; i < n; ++i) { z[i] = x[i] + y[i]; } } -template -auto benchmark_add_mdspan_1d(const std::size_t num_trials, - const index_type n, - const ElementType x[], - const ElementType y[], - ElementType z[]) -{ +template +auto benchmark_add_mdspan_1d(const std::size_t num_trials, const index_type n, + const ElementType x[], const ElementType y[], + ElementType z[]) { TICK(); mdspan_1d x2{x, n}; mdspan_1d y2{y, n}; @@ -371,24 +375,18 @@ auto benchmark_add_mdspan_1d(const std::size_t num_trials, return TOCK(); } -template -void add_raw_1d(const index_type n, - const ElementType x[], - const ElementType y[], - ElementType z[]) -{ +template +void add_raw_1d(const index_type n, const ElementType x[], + const ElementType y[], ElementType z[]) { for (index_type i = 0; i < n; ++i) { z[i] = x[i] + y[i]; } } -template -auto benchmark_add_raw_1d(const std::size_t num_trials, - const index_type n, - const ElementType x[], - const ElementType y[], - ElementType z[]) -{ +template +auto benchmark_add_raw_1d(const std::size_t num_trials, const index_type n, + const ElementType x[], const ElementType y[], + ElementType z[]) { TICK(); for (std::size_t trial = 0; trial < num_trials; ++trial) { add_raw_1d(n, x, y, z); @@ -397,42 +395,39 @@ auto benchmark_add_raw_1d(const std::size_t num_trials, } // Assume that x, y, and z all have the same alignment. -template +template void add_aligned_raw_1d(const index_type n, - aligned_pointer_t x, - aligned_pointer_t y, - aligned_pointer_t z) -{ + aligned_pointer_t x, + aligned_pointer_t y, + aligned_pointer_t z) { for (index_type i = 0; i < n; ++i) { z[i] = x[i] + y[i]; } } // Assume that x, y, and z all have the same alignment. -template -auto benchmark_add_aligned_raw_1d(const std::size_t num_trials, - const index_type n, - const ElementType x[], - const ElementType y[], - ElementType z[], - std::integral_constant ba) -{ +template +auto benchmark_add_aligned_raw_1d( + const std::size_t num_trials, const index_type n, const ElementType x[], + const ElementType y[], ElementType z[], + std::integral_constant ba) { TICK(); auto x_blessed = bless(x, ba); auto y_blessed = bless(y, ba); auto z_blessed = bless(z, ba); for (std::size_t trial = 0; trial < num_trials; ++trial) { - add_aligned_raw_1d(n, x_blessed, y_blessed, z_blessed); + add_aligned_raw_1d(n, x_blessed, y_blessed, + z_blessed); } return TOCK(); } #ifdef _OPENMP -template -void add_omp_simd_aligned_mdspan_1d(aligned_mdspan_1d x, - aligned_mdspan_1d y, - aligned_mdspan_1d z) -{ +template +void add_omp_simd_aligned_mdspan_1d( + aligned_mdspan_1d x, + aligned_mdspan_1d y, + aligned_mdspan_1d z) { const index_type n = z.extent(0); // Test whether OpenMP can figure out that the pointers are aligned. #pragma omp simd @@ -441,14 +436,11 @@ void add_omp_simd_aligned_mdspan_1d(aligned_mdspan_1d -auto benchmark_add_omp_simd_aligned_mdspan_1d(const std::size_t num_trials, - const index_type n, - const ElementType x[], - const ElementType y[], - ElementType z[], - std::integral_constant /* ba */ ) -{ +template +auto benchmark_add_omp_simd_aligned_mdspan_1d( + const std::size_t num_trials, const index_type n, const ElementType x[], + const ElementType y[], ElementType z[], + std::integral_constant /* ba */) { TICK(); aligned_mdspan_1d x2{x, n}; aligned_mdspan_1d y2{y, n}; @@ -459,11 +451,10 @@ auto benchmark_add_omp_simd_aligned_mdspan_1d(const std::size_t num_trials, return TOCK(); } -template +template void add_omp_simd_mdspan_1d(mdspan_1d x, - mdspan_1d y, - mdspan_1d z) -{ + mdspan_1d y, + mdspan_1d z) { const index_type n = z.extent(0); #pragma omp simd for (index_type i = 0; i < n; ++i) { @@ -471,13 +462,10 @@ void add_omp_simd_mdspan_1d(mdspan_1d x, } } -template +template auto benchmark_add_omp_simd_mdspan_1d(const std::size_t num_trials, - const index_type n, - const ElementType x[], - const ElementType y[], - ElementType z[]) -{ + const index_type n, const ElementType x[], + const ElementType y[], ElementType z[]) { TICK(); mdspan_1d x2{x, n}; mdspan_1d y2{y, n}; @@ -488,25 +476,19 @@ auto benchmark_add_omp_simd_mdspan_1d(const std::size_t num_trials, return TOCK(); } -template -void add_omp_simd_raw_1d(const index_type n, - const ElementType x[], - const ElementType y[], - ElementType z[]) -{ +template +void add_omp_simd_raw_1d(const index_type n, const ElementType x[], + const ElementType y[], ElementType z[]) { #pragma omp simd for (index_type i = 0; i < n; ++i) { z[i] = x[i] + y[i]; } } -template +template auto benchmark_add_omp_simd_raw_1d(const std::size_t num_trials, - const index_type n, - const ElementType x[], - const ElementType y[], - ElementType z[]) -{ + const index_type n, const ElementType x[], + const ElementType y[], ElementType z[]) { TICK(); for (std::size_t trial = 0; trial < num_trials; ++trial) { add_omp_simd_raw_1d(n, x, y, z); @@ -514,31 +496,26 @@ auto benchmark_add_omp_simd_raw_1d(const std::size_t num_trials, return TOCK(); } -template -void add_omp_aligned_simd_raw_1d(const index_type n, - const ElementType x[], - const ElementType y[], - ElementType z[], - std::integral_constant /* ba */ ) -{ +template +void add_omp_aligned_simd_raw_1d( + const index_type n, const ElementType x[], const ElementType y[], + ElementType z[], + std::integral_constant /* ba */) { // The "aligned" clause might only work // for pointers or (raw) arrays. // C++23 adopting mdspan might change that, // at least for the default layout and accessor. -#pragma omp simd aligned(z,x,y:byte_alignment) +#pragma omp simd aligned(z, x, y : byte_alignment) for (index_type i = 0; i < n; ++i) { z[i] = x[i] + y[i]; } } -template -auto benchmark_add_omp_aligned_simd_raw_1d(const std::size_t num_trials, - const index_type n, - const ElementType x[], - const ElementType y[], - ElementType z[], - std::integral_constant ba) -{ +template +auto benchmark_add_omp_aligned_simd_raw_1d( + const std::size_t num_trials, const index_type n, const ElementType x[], + const ElementType y[], ElementType z[], + std::integral_constant ba) { TICK(); for (std::size_t trial = 0; trial < num_trials; ++trial) { add_omp_aligned_simd_raw_1d(n, x, y, z, ba); @@ -546,12 +523,11 @@ auto benchmark_add_omp_aligned_simd_raw_1d(const std::size_t num_trials, return TOCK(); } -template -void add_omp_simd_aligned_raw_1d(const index_type n, - aligned_pointer_t x, - aligned_pointer_t y, - aligned_pointer_t z) -{ +template +void add_omp_simd_aligned_raw_1d( + const index_type n, aligned_pointer_t x, + aligned_pointer_t y, + aligned_pointer_t z) { #pragma omp simd for (index_type i = 0; i < n; ++i) { z[i] = x[i] + y[i]; @@ -559,46 +535,39 @@ void add_omp_simd_aligned_raw_1d(const index_type n, } // Assume that x, y, and z all have the same alignment. -template -auto benchmark_add_omp_simd_aligned_raw_1d(const std::size_t num_trials, - const index_type n, - const ElementType x[], - const ElementType y[], - ElementType z[], - std::integral_constant ba) -{ +template +auto benchmark_add_omp_simd_aligned_raw_1d( + const std::size_t num_trials, const index_type n, const ElementType x[], + const ElementType y[], ElementType z[], + std::integral_constant ba) { TICK(); auto x_blessed = bless(x, ba); auto y_blessed = bless(y, ba); auto z_blessed = bless(z, ba); for (std::size_t trial = 0; trial < num_trials; ++trial) { - add_omp_simd_aligned_raw_1d(n, x_blessed, y_blessed, z_blessed); + add_omp_simd_aligned_raw_1d( + n, x_blessed, y_blessed, z_blessed); } return TOCK(); } -template -void add_omp_aligned_simd_aligned_raw_1d(const index_type n, - aligned_pointer_t x, - aligned_pointer_t y, - aligned_pointer_t z) -{ -#pragma omp simd aligned(z,x,y:byte_alignment) +template +void add_omp_aligned_simd_aligned_raw_1d( + const index_type n, aligned_pointer_t x, + aligned_pointer_t y, + aligned_pointer_t z) { +#pragma omp simd aligned(z, x, y : byte_alignment) for (index_type i = 0; i < n; ++i) { z[i] = x[i] + y[i]; } } // Assume that x, y, and z all have the same alignment. -template +template auto benchmark_add_omp_aligned_simd_aligned_raw_1d( - const std::size_t num_trials, - const index_type n, - const ElementType x[], - const ElementType y[], - ElementType z[], - std::integral_constant ba) -{ + const std::size_t num_trials, const index_type n, const ElementType x[], + const ElementType y[], ElementType z[], + std::integral_constant ba) { TICK(); auto x_blessed = bless(x, ba); auto y_blessed = bless(y, ba); @@ -607,18 +576,16 @@ auto benchmark_add_omp_aligned_simd_aligned_raw_1d( // Passing in ba doesn't help the compiler // deduce the template parameters, // so we just specify them explicitly. - add_omp_aligned_simd_aligned_raw_1d(n, x_blessed, y_blessed, z_blessed); + add_omp_aligned_simd_aligned_raw_1d( + n, x_blessed, y_blessed, z_blessed); } return TOCK(); } -#endif // _OPENMP - -template -void set_elements_of_arrays(const index_type n, - ElementType x[], - ElementType y[], - ElementType z[]) -{ +#endif // _OPENMP + +template +void set_elements_of_arrays(const index_type n, ElementType x[], + ElementType y[], ElementType z[]) { for (index_type i = 0; i < n; ++i) { x[i] = 1.0; y[i] = 2.0; @@ -626,75 +593,73 @@ void set_elements_of_arrays(const index_type n, } } -} // namespace (anonymous) +} // namespace -int main(int argc, char* argv[]) -{ - using std::cout; +int main(int argc, char* argv[]) { using std::cerr; + using std::cout; using std::endl; - constexpr std::integral_constant byte_alignment; + constexpr std::integral_constant + byte_alignment; - if(argc != 3) { + if (argc != 3) { cerr << "Usage: main " << endl; return -1; } - const int n = std::stoi(argv[1]); + const int n = std::stoi(argv[1]); const int num_trials = std::stoi(argv[2]); aligned_array_allocation x_aligned(n); aligned_array_allocation y_aligned(n); aligned_array_allocation z_aligned(n); - set_elements_of_arrays(n, x_aligned.data(), y_aligned.data(), z_aligned.data()); - - auto aligned_mdspan_result = - benchmark_add_aligned_mdspan_1d(num_trials, n, x_aligned.data(), - y_aligned.data(), z_aligned.data(), - byte_alignment); - auto aligned_raw_result = - benchmark_add_aligned_raw_1d(num_trials, n, x_aligned.data(), - y_aligned.data(), z_aligned.data(), - byte_alignment); + set_elements_of_arrays(n, x_aligned.data(), y_aligned.data(), + z_aligned.data()); + + auto aligned_mdspan_result = benchmark_add_aligned_mdspan_1d( + num_trials, n, x_aligned.data(), y_aligned.data(), z_aligned.data(), + byte_alignment); + auto aligned_raw_result = benchmark_add_aligned_raw_1d( + num_trials, n, x_aligned.data(), y_aligned.data(), z_aligned.data(), + byte_alignment); #ifdef _OPENMP auto omp_simd_aligned_mdspan_result = - benchmark_add_omp_simd_aligned_mdspan_1d(num_trials, n, x_aligned.data(), - y_aligned.data(), z_aligned.data(), - byte_alignment); - auto omp_aligned_simd_raw_result = - benchmark_add_omp_aligned_simd_raw_1d(num_trials, n, - x_aligned.data(), y_aligned.data(), - z_aligned.data(), byte_alignment); - auto omp_simd_aligned_raw_result = - benchmark_add_omp_simd_aligned_raw_1d(num_trials, n, - x_aligned.data(), y_aligned.data(), - z_aligned.data(), byte_alignment); + benchmark_add_omp_simd_aligned_mdspan_1d( + num_trials, n, x_aligned.data(), y_aligned.data(), z_aligned.data(), + byte_alignment); + auto omp_aligned_simd_raw_result = benchmark_add_omp_aligned_simd_raw_1d( + num_trials, n, x_aligned.data(), y_aligned.data(), z_aligned.data(), + byte_alignment); + auto omp_simd_aligned_raw_result = benchmark_add_omp_simd_aligned_raw_1d( + num_trials, n, x_aligned.data(), y_aligned.data(), z_aligned.data(), + byte_alignment); auto omp_aligned_simd_aligned_raw_result = - benchmark_add_omp_aligned_simd_aligned_raw_1d(num_trials, n, - x_aligned.data(), y_aligned.data(), - z_aligned.data(), byte_alignment); -#endif // _OPENMP + benchmark_add_omp_aligned_simd_aligned_raw_1d( + num_trials, n, x_aligned.data(), y_aligned.data(), z_aligned.data(), + byte_alignment); +#endif // _OPENMP deliberately_unaligned_array_allocation x_unaligned(n); deliberately_unaligned_array_allocation y_unaligned(n); deliberately_unaligned_array_allocation z_unaligned(n); - set_elements_of_arrays(n, x_unaligned.data(), y_unaligned.data(), z_unaligned.data()); + set_elements_of_arrays(n, x_unaligned.data(), y_unaligned.data(), + z_unaligned.data()); auto mdspan_result = - benchmark_add_mdspan_1d(num_trials, n, x_unaligned.data(), - y_unaligned.data(), z_unaligned.data()); + benchmark_add_mdspan_1d(num_trials, n, x_unaligned.data(), + y_unaligned.data(), z_unaligned.data()); auto raw_result = - benchmark_add_raw_1d(num_trials, n, x_unaligned.data(), - y_unaligned.data(), z_unaligned.data()); + benchmark_add_raw_1d(num_trials, n, x_unaligned.data(), + y_unaligned.data(), z_unaligned.data()); #ifdef _OPENMP auto omp_simd_mdspan_result = - benchmark_add_omp_simd_mdspan_1d(num_trials, n, x_unaligned.data(), - y_unaligned.data(), z_unaligned.data()); + benchmark_add_omp_simd_mdspan_1d(num_trials, n, x_unaligned.data(), + y_unaligned.data(), z_unaligned.data()); auto omp_simd_raw_result = - benchmark_add_omp_simd_raw_1d(num_trials, n, x_unaligned.data(), - y_unaligned.data(), z_unaligned.data()); -#endif // _OPENMP + benchmark_add_omp_simd_raw_1d(num_trials, n, x_unaligned.data(), + y_unaligned.data(), z_unaligned.data()); +#endif // _OPENMP cout << "Number of trials: " << num_trials << endl << "Number of loop iterations per trial: " << n << endl @@ -710,7 +675,8 @@ int main(int argc, char* argv[]) #ifdef _OPENMP cout << "Total time in seconds for OpenMP (omp simd) loops:" << endl - << " omp_simd_aligned_mdspan: " << omp_simd_aligned_mdspan_result << endl + << " omp_simd_aligned_mdspan: " << omp_simd_aligned_mdspan_result + << endl << " omp_simd_mdspan: " << omp_simd_mdspan_result << endl << " omp_simd_raw: " << omp_simd_raw_result << endl << " omp_aligned_simd_raw (aligned clause): " @@ -719,6 +685,6 @@ int main(int argc, char* argv[]) << omp_simd_aligned_raw_result << endl << " omp_aligned_simd_aligned_raw (both): " << omp_aligned_simd_aligned_raw_result << endl; -#endif // _OPENMP +#endif // _OPENMP return 0; } diff --git a/examples/dot_product/dot_product.cpp b/examples/dot_product/dot_product.cpp index 3d21f6a1..df2ec092 100644 --- a/examples/dot_product/dot_product.cpp +++ b/examples/dot_product/dot_product.cpp @@ -7,8 +7,8 @@ #include #include - -#if !(defined(__cpp_lib_make_unique) && __cpp_lib_make_unique >= 201304) && !MDSPAN_HAS_CXX_14 +#if !(defined(__cpp_lib_make_unique) && __cpp_lib_make_unique >= 201304) && \ + !MDSPAN_HAS_CXX_14 // Not actually conforming, but it works for the purposes of this file namespace std { template @@ -20,33 +20,28 @@ struct __unique_ptr_new_impl { }; template struct __unique_ptr_new_impl { - static T* __impl(size_t size) { - return new T[size]; - } + static T* __impl(size_t size) { return new T[size]; } }; template std::unique_ptr make_unique(Args&&... args) { return std::unique_ptr(__unique_ptr_new_impl::__impl((Args&&)args...)); } -} // end namespace std +} // end namespace std #endif //================================================================================ -template < - class T, - class ExtsA, class LayA, class AccA, - class ExtsB, class LayB, class AccB -> +template T dot_product( - Kokkos::mdspan a, - Kokkos::mdspan b -) //requires ExtsA::rank() == ExtsB::rank() && ExtsA::rank() == 2 + Kokkos::mdspan a, + Kokkos::mdspan + b) // requires ExtsA::rank() == ExtsB::rank() && ExtsA::rank() == 2 { using int_t = typename ExtsA::index_type; - T result = 0; - for(int_t i = 0; i < a.extent(0); ++i) { - for(int_t j = 0; j < a.extent(1); ++j) { + T result = 0; + for (int_t i = 0; i < a.extent(0); ++i) { + for (int_t j = 0; j < a.extent(1); ++j) { #if MDSPAN_USE_BRACKET_OPERATOR result += a[i, j] * b[i, j]; #else @@ -59,18 +54,14 @@ T dot_product( //================================================================================ -template < - class T, - class ExtsA, class LayA, class AccA -> +template void fill_in_order( - Kokkos::mdspan a -) // requires ExtsA::rank() == 2 + Kokkos::mdspan a) // requires ExtsA::rank() == 2 { using int_t = typename ExtsA::index_type; - T count = 0; - for(int_t i = 0; i < a.extent(0); ++i) { - for(int_t j = 0; j < a.extent(1); ++j) { + T count = 0; + for (int_t i = 0; i < a.extent(0); ++i) { + for (int_t j = 0; j < a.extent(1); ++j) { #if MDSPAN_USE_BRACKET_OPERATOR a[i, j] = count++; #else @@ -89,8 +80,10 @@ constexpr int cols = 3; int main() { { - using span_2d_dynamic = Kokkos::mdspan, Kokkos::layout_right>; - using span_2d_dynamic_left = Kokkos::mdspan, Kokkos::layout_left>; + using span_2d_dynamic = + Kokkos::mdspan, Kokkos::layout_right>; + using span_2d_dynamic_left = + Kokkos::mdspan, Kokkos::layout_left>; auto data_a = std::make_unique(rows * cols); auto data_b = std::make_unique(rows * cols); @@ -104,8 +97,12 @@ int main() { } { - using span_2d_10_10 = Kokkos::mdspan, Kokkos::layout_right>; - using span_2d_10_10_left = Kokkos::mdspan, Kokkos::layout_right>; + using span_2d_10_10 = + Kokkos::mdspan, + Kokkos::layout_right>; + using span_2d_10_10_left = + Kokkos::mdspan, + Kokkos::layout_right>; auto data_a = std::make_unique(100); auto data_b = std::make_unique(100); @@ -117,5 +114,4 @@ int main() { std::cout << dot_product(a, b) << std::endl; } - } diff --git a/examples/godbolt_starter/godbolt_starter.cpp b/examples/godbolt_starter/godbolt_starter.cpp index 395eb3ad..90f1fac4 100644 --- a/examples/godbolt_starter/godbolt_starter.cpp +++ b/examples/godbolt_starter/godbolt_starter.cpp @@ -6,12 +6,9 @@ #include #include - int main() { std::array d{ - 0, 5, 1, - 3, 8, 4, - 2, 7, 6, + 0, 5, 1, 3, 8, 4, 2, 7, 6, }; Kokkos::mdspan m{d.data(), Kokkos::extents{3, 3}}; diff --git a/examples/restrict_accessor/restrict_accessor.cpp b/examples/restrict_accessor/restrict_accessor.cpp index 05f95c67..3a9f7413 100644 --- a/examples/restrict_accessor/restrict_accessor.cpp +++ b/examples/restrict_accessor/restrict_accessor.cpp @@ -8,23 +8,23 @@ #include #include #include -#include // stoi +#include // stoi // mfh 2022/08/04: This is based on my comments on reference mdspan // implementation issue https://github.com/kokkos/mdspan/issues/169. namespace { - #if defined(MDSPAN_IMPL_COMPILER_MSVC) || defined(__INTEL_COMPILER) -# define MDSPAN_IMPL_RESTRICT_KEYWORD __restrict +#define MDSPAN_IMPL_RESTRICT_KEYWORD __restrict #elif defined(__GNUC__) || defined(__clang__) -# define MDSPAN_IMPL_RESTRICT_KEYWORD __restrict__ +#define MDSPAN_IMPL_RESTRICT_KEYWORD __restrict__ #else -# define MDSPAN_IMPL_RESTRICT_KEYWORD +#define MDSPAN_IMPL_RESTRICT_KEYWORD #endif -#define MDSPAN_IMPL_RESTRICT_POINTER( ELEMENT_TYPE ) ELEMENT_TYPE * MDSPAN_IMPL_RESTRICT_KEYWORD +#define MDSPAN_IMPL_RESTRICT_POINTER(ELEMENT_TYPE) \ + ELEMENT_TYPE* MDSPAN_IMPL_RESTRICT_KEYWORD // https://en.cppreference.com/w/c/language/restrict gives examples // of the kinds of optimizations that may apply to restrict. For instance, @@ -34,79 +34,88 @@ namespace { // // void f(int n, float * restrict r, float * restrict s) { // float * p = r, * q = s; // OK -// while(n-- > 0) *p++ = *q++; // almost certainly optimized just like *r++ = *s++ +// while(n-- > 0) *p++ = *q++; // almost certainly optimized just like *r++ = +// *s++ // } // -// This is relevant because restrict_accessor::reference is _not_ restrict. -// (It's not formally correct to apply C restrict wording to C++ references. -// However, GCC defines this extension: +// This is relevant because restrict_accessor::reference is _not_ +// restrict. (It's not formally correct to apply C restrict wording to C++ +// references. However, GCC defines this extension: // // https://gcc.gnu.org/onlinedocs/gcc/Restricted-Pointers.html // // In what follows, I'll assume that this has a reasonable definition.) -// The idea is that even though p[i] has type ElementType& and not ElementType& restrict, -// the compiler can figure out that the reference comes from a pointer based on p, -// which is marked restrict. +// The idea is that even though p[i] has type ElementType& and not ElementType& +// restrict, the compiler can figure out that the reference comes from a pointer +// based on p, which is marked restrict. // // Note that any performance improvements can only be determined by experiment. // Compilers are not required to do anything with restrict. // Any use of this keyword is not Standard C++, // so you'll have to refer to the compiler's documentation, // look at the assembler output, and do performance experiments. -template +template struct restrict_accessor { - using offset_policy = Kokkos::default_accessor; - using element_type = ElementType; - using reference = ElementType&; - using data_handle_type = MDSPAN_IMPL_RESTRICT_POINTER( ElementType ); + using offset_policy = Kokkos::default_accessor; + using element_type = ElementType; + using reference = ElementType&; + using data_handle_type = MDSPAN_IMPL_RESTRICT_POINTER(ElementType); constexpr restrict_accessor() noexcept = default; MDSPAN_TEMPLATE_REQUIRES( - class OtherElementType, - /* requires */ (std::is_convertible::value) - ) + class OtherElementType, + /* requires */ (std::is_convertible::value)) constexpr restrict_accessor(restrict_accessor) noexcept {} constexpr reference access(data_handle_type p, size_t i) const noexcept { return p[i]; } - constexpr typename offset_policy::data_handle_type - offset(data_handle_type p, size_t i) const noexcept { + constexpr typename offset_policy::data_handle_type offset( + data_handle_type p, size_t i) const noexcept { return p + i; } }; // Use int, not size_t, as the index_type. -// Some compilers have trouble optimizing loops with unsigned or 64-bit index types. +// Some compilers have trouble optimizing loops with unsigned or 64-bit index +// types. using index_type = int; -template +template using restrict_mdspan_1d = - Kokkos::mdspan, Kokkos::layout_right, restrict_accessor>; + Kokkos::mdspan, + Kokkos::layout_right, restrict_accessor>; -template +template using mdspan_1d = - Kokkos::mdspan, Kokkos::layout_right, Kokkos::default_accessor>; + Kokkos::mdspan, + Kokkos::layout_right, Kokkos::default_accessor>; #define TICK() const auto tick = std::chrono::steady_clock::now() using double_seconds = std::chrono::duration>; -#define TOCK() std::chrono::duration_cast(std::chrono::steady_clock::now() - tick).count() +#define TOCK() \ + std::chrono::duration_cast( \ + std::chrono::steady_clock::now() - tick) \ + .count() -template -void add_restrict_mdspan_1d(restrict_mdspan_1d x, restrict_mdspan_1d y, restrict_mdspan_1d z) -{ +template +void add_restrict_mdspan_1d(restrict_mdspan_1d x, + restrict_mdspan_1d y, + restrict_mdspan_1d z) { const index_type n = z.extent(0); for (index_type i = 0; i < n; ++i) { z[i] = x[i] + y[i]; } } -template -auto benchmark_add_restrict_mdspan_1d(const std::size_t num_trials, const index_type n, const ElementType* x, const ElementType* y, ElementType* z) -{ +template +auto benchmark_add_restrict_mdspan_1d(const std::size_t num_trials, + const index_type n, const ElementType* x, + const ElementType* y, ElementType* z) { TICK(); restrict_mdspan_1d x2{x, n}; restrict_mdspan_1d y2{y, n}; @@ -117,18 +126,19 @@ auto benchmark_add_restrict_mdspan_1d(const std::size_t num_trials, const index_ return TOCK(); } -template -void add_mdspan_1d(mdspan_1d x, mdspan_1d y, mdspan_1d z) -{ +template +void add_mdspan_1d(mdspan_1d x, + mdspan_1d y, mdspan_1d z) { const index_type n = z.extent(0); for (index_type i = 0; i < n; ++i) { z[i] = x[i] + y[i]; } } -template -auto benchmark_add_mdspan_1d(const std::size_t num_trials, const index_type n, const ElementType* x, const ElementType* y, ElementType* z) -{ +template +auto benchmark_add_mdspan_1d(const std::size_t num_trials, const index_type n, + const ElementType* x, const ElementType* y, + ElementType* z) { TICK(); mdspan_1d x2{x, n}; mdspan_1d y2{y, n}; @@ -139,17 +149,18 @@ auto benchmark_add_mdspan_1d(const std::size_t num_trials, const index_type n, c return TOCK(); } -template -void add_raw_1d(const index_type n, const ElementType x[], const ElementType y[], ElementType z[]) -{ +template +void add_raw_1d(const index_type n, const ElementType x[], + const ElementType y[], ElementType z[]) { for (index_type i = 0; i < n; ++i) { z[i] = x[i] + y[i]; } } -template -auto benchmark_add_raw_1d(const std::size_t num_trials, const index_type n, const ElementType* x, const ElementType* y, ElementType* z) -{ +template +auto benchmark_add_raw_1d(const std::size_t num_trials, const index_type n, + const ElementType* x, const ElementType* y, + ElementType* z) { TICK(); for (std::size_t trial = 0; trial < num_trials; ++trial) { add_raw_1d(n, x, y, z); @@ -157,24 +168,24 @@ auto benchmark_add_raw_1d(const std::size_t num_trials, const index_type n, cons return TOCK(); } -template +template void add_restrict_raw_1d(const index_type n, - MDSPAN_IMPL_RESTRICT_POINTER(const ElementType) x, - MDSPAN_IMPL_RESTRICT_POINTER(const ElementType) y, - MDSPAN_IMPL_RESTRICT_POINTER(ElementType) z) -{ + MDSPAN_IMPL_RESTRICT_POINTER(const ElementType) x, + MDSPAN_IMPL_RESTRICT_POINTER(const ElementType) y, + MDSPAN_IMPL_RESTRICT_POINTER(ElementType) z) { for (index_type i = 0; i < n; ++i) { z[i] = x[i] + y[i]; } } -template -auto benchmark_add_restrict_raw_1d(const std::size_t num_trials, const index_type n, const ElementType* x, const ElementType* y, ElementType* z) -{ +template +auto benchmark_add_restrict_raw_1d(const std::size_t num_trials, + const index_type n, const ElementType* x, + const ElementType* y, ElementType* z) { TICK(); MDSPAN_IMPL_RESTRICT_POINTER(const ElementType) x2 = x; MDSPAN_IMPL_RESTRICT_POINTER(const ElementType) y2 = y; - MDSPAN_IMPL_RESTRICT_POINTER(ElementType) z2 = z; + MDSPAN_IMPL_RESTRICT_POINTER(ElementType) z2 = z; for (std::size_t trial = 0; trial < num_trials; ++trial) { add_restrict_raw_1d(n, x2, y2, z2); } @@ -183,65 +194,69 @@ auto benchmark_add_restrict_raw_1d(const std::size_t num_trials, const index_typ // Start with restrict pointers, then assign to nonrestrict pointers. // This checks whether the compiler's alias analysis suffices. -template +template void add_unrestrict_raw_1d(const index_type n, - MDSPAN_IMPL_RESTRICT_POINTER(const ElementType) x, - MDSPAN_IMPL_RESTRICT_POINTER(const ElementType) y, - MDSPAN_IMPL_RESTRICT_POINTER(ElementType) z) -{ + MDSPAN_IMPL_RESTRICT_POINTER(const ElementType) x, + MDSPAN_IMPL_RESTRICT_POINTER(const ElementType) y, + MDSPAN_IMPL_RESTRICT_POINTER(ElementType) z) { const ElementType* x2 = x; const ElementType* y2 = y; - ElementType* z2 = z; + ElementType* z2 = z; add_raw_1d(n, x2, y2, z2); } -template -auto benchmark_add_unrestrict_raw_1d(const std::size_t num_trials, const index_type n, const ElementType* x, const ElementType* y, ElementType* z) -{ +template +auto benchmark_add_unrestrict_raw_1d(const std::size_t num_trials, + const index_type n, const ElementType* x, + const ElementType* y, ElementType* z) { TICK(); MDSPAN_IMPL_RESTRICT_POINTER(const ElementType) x2 = x; MDSPAN_IMPL_RESTRICT_POINTER(const ElementType) y2 = y; - MDSPAN_IMPL_RESTRICT_POINTER(ElementType) z2 = z; + MDSPAN_IMPL_RESTRICT_POINTER(ElementType) z2 = z; for (std::size_t trial = 0; trial < num_trials; ++trial) { add_unrestrict_raw_1d(n, x2, y2, z2); } return TOCK(); } -template -auto warmup(const std::size_t num_trials, const index_type n, const ElementType* x, const ElementType* y, ElementType* z) -{ +template +auto warmup(const std::size_t num_trials, const index_type n, + const ElementType* x, const ElementType* y, ElementType* z) { return benchmark_add_raw_1d(num_trials, n, x, y, z); } -} // namespace (anonymous) +} // namespace -int main(int argc, char* argv[]) -{ - using std::cout; +int main(int argc, char* argv[]) { using std::cerr; + using std::cout; using std::endl; - if(argc != 3) { + if (argc != 3) { cerr << "Usage: main " << endl; return -1; } - int n = 10000; + int n = 10000; int num_trials = 100; - n = std::stoi(argv[1]); - num_trials = std::stoi(argv[2]); + n = std::stoi(argv[1]); + num_trials = std::stoi(argv[2]); std::vector x(n); std::vector y(n); std::vector z(n); auto warmup_result = warmup(num_trials, n, x.data(), y.data(), z.data()); - auto restrict_mdspan_result = benchmark_add_restrict_mdspan_1d(num_trials, n, x.data(), y.data(), z.data()); - auto mdspan_result = benchmark_add_mdspan_1d(num_trials, n, x.data(), y.data(), z.data()); - auto raw_result = benchmark_add_raw_1d(num_trials, n, x.data(), y.data(), z.data()); - auto restrict_raw_result = benchmark_add_restrict_raw_1d(num_trials, n, x.data(), y.data(), z.data()); - auto unrestrict_raw_result = benchmark_add_unrestrict_raw_1d(num_trials, n, x.data(), y.data(), z.data()); + auto restrict_mdspan_result = benchmark_add_restrict_mdspan_1d( + num_trials, n, x.data(), y.data(), z.data()); + auto mdspan_result = + benchmark_add_mdspan_1d(num_trials, n, x.data(), y.data(), z.data()); + auto raw_result = + benchmark_add_raw_1d(num_trials, n, x.data(), y.data(), z.data()); + auto restrict_raw_result = benchmark_add_restrict_raw_1d( + num_trials, n, x.data(), y.data(), z.data()); + auto unrestrict_raw_result = benchmark_add_unrestrict_raw_1d( + num_trials, n, x.data(), y.data(), z.data()); cout << "num_trials: " << num_trials << ", n: " << n << endl << "Total time (unit: second):" << endl diff --git a/examples/tiled_layout/simple_tiled_layout.cpp b/examples/tiled_layout/simple_tiled_layout.cpp index 0981d40e..17956a65 100644 --- a/examples/tiled_layout/simple_tiled_layout.cpp +++ b/examples/tiled_layout/simple_tiled_layout.cpp @@ -7,35 +7,28 @@ #include #include - // Simple tiled layout. // Hard-coded for 2D, column-major across tiles // and row-major within each tile struct SimpleTileLayout2D { template struct mapping { - // for simplicity - static_assert(Extents::rank() == 2, "SimpleTileLayout2D is hard-coded for 2D layout"); + static_assert(Extents::rank() == 2, + "SimpleTileLayout2D is hard-coded for 2D layout"); using extents_type = Extents; - using rank_type = typename Extents::rank_type; - using size_type = typename Extents::size_type; - using layout_type = SimpleTileLayout2D; + using rank_type = typename Extents::rank_type; + using size_type = typename Extents::size_type; + using layout_type = SimpleTileLayout2D; - mapping() noexcept = default; - mapping(const mapping&) noexcept = default; + mapping() noexcept = default; + mapping(const mapping&) noexcept = default; mapping& operator=(const mapping&) noexcept = default; - mapping( - Extents const& exts, - size_type row_tile, - size_type col_tile - ) noexcept - : extents_(exts), - row_tile_size_(row_tile), - col_tile_size_(col_tile) - { + mapping(Extents const& exts, size_type row_tile, + size_type col_tile) noexcept + : extents_(exts), row_tile_size_(row_tile), col_tile_size_(col_tile) { // For simplicity, don't worry about negatives/zeros/etc. assert(row_tile > 0); assert(col_tile > 0); @@ -44,38 +37,34 @@ struct SimpleTileLayout2D { } MDSPAN_TEMPLATE_REQUIRES( - class OtherExtents, - /* requires */ (::std::is_constructible::value) - ) + class OtherExtents, + /* requires */ ( + ::std::is_constructible::value)) MDSPAN_CONDITIONAL_EXPLICIT( - (!::std::is_convertible::value) - ) - constexpr mapping(const mapping& input_mapping) noexcept : - extents_(input_mapping.extents()), - row_tile_size_(input_mapping.row_tile_size_), - col_tile_size_(input_mapping.col_tile_size_) - {} + (!::std::is_convertible::value)) + constexpr mapping(const mapping& input_mapping) noexcept + : extents_(input_mapping.extents()), + row_tile_size_(input_mapping.row_tile_size_), + col_tile_size_(input_mapping.col_tile_size_) {} //------------------------------------------------------------ // Helper members (not part of the layout concept) - constexpr size_type - n_row_tiles() const noexcept { - return extents_.extent(0) / row_tile_size_ + size_type((extents_.extent(0) % row_tile_size_) != 0); + constexpr size_type n_row_tiles() const noexcept { + return extents_.extent(0) / row_tile_size_ + + size_type((extents_.extent(0) % row_tile_size_) != 0); } - constexpr size_type - n_column_tiles() const noexcept { - return extents_.extent(1) / col_tile_size_ + size_type((extents_.extent(1) % col_tile_size_) != 0); + constexpr size_type n_column_tiles() const noexcept { + return extents_.extent(1) / col_tile_size_ + + size_type((extents_.extent(1) % col_tile_size_) != 0); } - constexpr size_type - tile_size() const noexcept { + constexpr size_type tile_size() const noexcept { return row_tile_size_ * col_tile_size_; } - size_type - tile_offset(size_type row, size_type col) const noexcept { + size_type tile_offset(size_type row, size_type col) const noexcept { // This could probably be more efficient, but for example purposes... auto col_tile = col / col_tile_size_; auto row_tile = row / row_tile_size_; @@ -83,8 +72,7 @@ struct SimpleTileLayout2D { return (col_tile * n_row_tiles() + row_tile) * tile_size(); } - size_type - offset_in_tile(size_type row, size_type col) const noexcept { + size_type offset_in_tile(size_type row, size_type col) const noexcept { auto t_row = row % row_tile_size_; auto t_col = col % col_tile_size_; // We're hard-coding this to *row-major* within tiles @@ -94,79 +82,81 @@ struct SimpleTileLayout2D { //------------------------------------------------------------ // Required members - constexpr const extents_type& extents() const { - return extents_; - } + constexpr const extents_type& extents() const { return extents_; } - constexpr size_type - required_span_size() const noexcept { + constexpr size_type required_span_size() const noexcept { return n_row_tiles() * n_column_tiles() * tile_size(); } - template + template // requires(is_convertible_v && // is_convertible_v && // is_nothrow_constructible_v && // is_nothrow_constructible_v) - constexpr size_type - operator()(RowIndex row, ColIndex col) const noexcept { + constexpr size_type operator()(RowIndex row, ColIndex col) const noexcept { // TODO (mfh 2022/08/04 check precondition that // extents_type::index-cast(row, col) // is a multidimensional index in extents_. return tile_offset(row, col) + offset_in_tile(row, col); } - // Mapping is always unique static constexpr bool is_always_unique() noexcept { return true; } - // Only exhaustive if extents_.extent(0) % column_tile_size == 0, so not always + // Only exhaustive if extents_.extent(0) % column_tile_size == 0, so not + // always static constexpr bool is_always_exhaustive() noexcept { return false; } - // There is not always a regular stride between elements in a given dimension + // There is not always a regular stride between elements in a given + // dimension static constexpr bool is_always_strided() noexcept { return false; } static constexpr bool is_unique() noexcept { return true; } constexpr bool is_exhaustive() const noexcept { // Only exhaustive if extents fit exactly into tile sizes... - return (extents_.extent(0) % row_tile_size_ == 0) && (extents_.extent(1) % col_tile_size_ == 0); + return (extents_.extent(0) % row_tile_size_ == 0) && + (extents_.extent(1) % col_tile_size_ == 0); } // There are some circumstances where this is strided, but we're not - // concerned about that optimization, so we're allowed to just return false here + // concerned about that optimization, so we're allowed to just return false + // here constexpr bool is_strided() const noexcept { return false; } - private: + private: Extents extents_; size_type row_tile_size_ = 1; size_type col_tile_size_ = 1; }; }; - - int main() { //---------------------------------------- // 5x2 example, tiled as 3x3 constexpr int n_rows = 2; constexpr int n_cols = 5; int data_row_major[] = { - 1, 2, 3, /*|*/ 4, 5, /* X | */ - 6, 7, 8, /*|*/ 9, 10 /* X | */ - /*X, X, X, | X X X | - *------------------------------------ */ + 1, 2, 3, + /*|*/ 4, 5, /* X | */ + 6, 7, 8, + /*|*/ 9, 10 /* X | */ + /*X, X, X, | X X X | + *------------------------------------ */ }; // manually tiling the above, using -1 as filler static constexpr int X = -1; - int data_tiled[] = { - /* tile 0, 0 */ 1, 2, 3, 6, 7, 8, X, X, X, - /* tile 0, 1 */ 4, 5, X, 9, 10, X, X, X, X, + int data_tiled[] = { + /* tile 0, 0 */ 1, 2, 3, 6, 7, 8, X, X, X, + /* tile 0, 1 */ 4, 5, X, 9, 10, X, X, X, X, }; //---------------------------------------- // Just use dynamic extents for the purposes of demonstration using extents_type = Kokkos::dextents; using tiled_mdspan = Kokkos::mdspan; - using tiled_layout_type = typename SimpleTileLayout2D::template mapping; - using row_major_mdspan = Kokkos::mdspan; + using tiled_layout_type = + typename SimpleTileLayout2D::template mapping; + using row_major_mdspan = + Kokkos::mdspan; //---------------------------------------- - auto tiled = tiled_mdspan(data_tiled, tiled_layout_type(extents_type(n_rows, n_cols), 3, 3)); + auto tiled = tiled_mdspan( + data_tiled, tiled_layout_type(extents_type(n_rows, n_cols), 3, 3)); auto row_major = row_major_mdspan(data_row_major, n_rows, n_cols); //---------------------------------------- // Check that we did things correctly @@ -174,27 +164,27 @@ int main() { for (int irow = 0; irow < n_rows; ++irow) { for (int icol = 0; icol < n_cols; ++icol) { #if MDSPAN_USE_BRACKET_OPERATOR - if(tiled[irow, icol] != row_major[irow, icol]) { - std::cout << "Mismatch for entry " << irow << ", " << icol << ":" << std::endl; - std::cout << " tiled(" << irow << ", " << icol << ") = " - << tiled[irow, icol] << std::endl; - std::cout << " row_major(" << irow << ", " << icol << ") = " - << row_major[irow, icol] << std::endl; + if (tiled[irow, icol] != row_major[irow, icol]) { + std::cout << "Mismatch for entry " << irow << ", " << icol << ":" + << std::endl; + std::cout << " tiled(" << irow << ", " << icol + << ") = " << tiled[irow, icol] << std::endl; + std::cout << " row_major(" << irow << ", " << icol + << ") = " << row_major[irow, icol] << std::endl; #else - if(tiled(irow, icol) != row_major(irow, icol)) { - std::cout << "Mismatch for entry " << irow << ", " << icol << ":" << std::endl; - std::cout << " tiled(" << irow << ", " << icol << ") = " - << tiled(irow, icol) << std::endl; - std::cout << " row_major(" << irow << ", " << icol << ") = " - << row_major(irow, icol) << std::endl; + if (tiled(irow, icol) != row_major(irow, icol)) { + std::cout << "Mismatch for entry " << irow << ", " << icol << ":" + << std::endl; + std::cout << " tiled(" << irow << ", " << icol + << ") = " << tiled(irow, icol) << std::endl; + std::cout << " row_major(" << irow << ", " << icol + << ") = " << row_major(irow, icol) << std::endl; #endif ++failures; - } - } } - if(failures == 0) { + if (failures == 0) { std::cout << "Success! SimpleTiledLayout2D works as expected." << std::endl; } } diff --git a/include/mdspan/impl/compressed_pair.hpp b/include/mdspan/impl/compressed_pair.hpp index 9b666ca3..c0de250a 100644 --- a/include/mdspan/impl/compressed_pair.hpp +++ b/include/mdspan/impl/compressed_pair.hpp @@ -7,22 +7,27 @@ #include "trait_backports.hpp" #if !defined(MDSPAN_IMPL_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) -# include "no_unique_address.hpp" +#include "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 impl_compressed_pair { +// 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 impl_compressed_pair { MDSPAN_IMPL_NO_UNIQUE_ADDRESS T1 m_t1_val{}; MDSPAN_IMPL_NO_UNIQUE_ADDRESS T2 m_t2_val{}; - MDSPAN_FORCE_INLINE_FUNCTION MDSPAN_IMPL_CONSTEXPR_14 T1 &first() noexcept { return m_t1_val; } + MDSPAN_FORCE_INLINE_FUNCTION MDSPAN_IMPL_CONSTEXPR_14 T1 &first() noexcept { + return m_t1_val; + } MDSPAN_FORCE_INLINE_FUNCTION constexpr T1 const &first() const noexcept { return m_t1_val; } - MDSPAN_FORCE_INLINE_FUNCTION MDSPAN_IMPL_CONSTEXPR_14 T2 &second() noexcept { return m_t2_val; } + MDSPAN_FORCE_INLINE_FUNCTION MDSPAN_IMPL_CONSTEXPR_14 T2 &second() noexcept { + return m_t2_val; + } MDSPAN_FORCE_INLINE_FUNCTION constexpr T2 const &second() const noexcept { return m_t2_val; } @@ -34,16 +39,17 @@ template struct impl_compressed_pair { MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr impl_compressed_pair(impl_compressed_pair &&) = default; MDSPAN_INLINE_FUNCTION_DEFAULTED - MDSPAN_IMPL_CONSTEXPR_14_DEFAULTED impl_compressed_pair & - operator=(impl_compressed_pair const &) = default; + MDSPAN_IMPL_CONSTEXPR_14_DEFAULTED impl_compressed_pair &operator=( + impl_compressed_pair const &) = default; MDSPAN_INLINE_FUNCTION_DEFAULTED - MDSPAN_IMPL_CONSTEXPR_14_DEFAULTED impl_compressed_pair & - operator=(impl_compressed_pair &&) = default; + MDSPAN_IMPL_CONSTEXPR_14_DEFAULTED impl_compressed_pair &operator=( + impl_compressed_pair &&) = default; MDSPAN_INLINE_FUNCTION_DEFAULTED ~impl_compressed_pair() = default; template - MDSPAN_INLINE_FUNCTION constexpr impl_compressed_pair(T1Like &&t1, T2Like &&t2) - : m_t1_val((T1Like &&) t1), m_t2_val((T2Like &&) t2) {} + MDSPAN_INLINE_FUNCTION constexpr impl_compressed_pair(T1Like &&t1, + T2Like &&t2) + : m_t1_val((T1Like &&)t1), m_t2_val((T2Like &&)t2) {} }; #if !defined(MDSPAN_IMPL_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) @@ -52,8 +58,8 @@ template struct impl_compressed_pair { template struct impl_compressed_pair< T1, T2, - std::enable_if_t> - : private T1 { + std::enable_if_t> : private T1 { T2 m_t2_val{}; MDSPAN_FORCE_INLINE_FUNCTION MDSPAN_IMPL_CONSTEXPR_14 T1 &first() noexcept { return *static_cast(this); @@ -61,7 +67,9 @@ struct impl_compressed_pair< MDSPAN_FORCE_INLINE_FUNCTION constexpr T1 const &first() const noexcept { return *static_cast(this); } - MDSPAN_FORCE_INLINE_FUNCTION MDSPAN_IMPL_CONSTEXPR_14 T2 &second() noexcept { return m_t2_val; } + MDSPAN_FORCE_INLINE_FUNCTION MDSPAN_IMPL_CONSTEXPR_14 T2 &second() noexcept { + return m_t2_val; + } MDSPAN_FORCE_INLINE_FUNCTION constexpr T2 const &second() const noexcept { return m_t2_val; } @@ -73,26 +81,29 @@ struct impl_compressed_pair< MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr impl_compressed_pair(impl_compressed_pair &&) = default; MDSPAN_INLINE_FUNCTION_DEFAULTED - MDSPAN_IMPL_CONSTEXPR_14_DEFAULTED impl_compressed_pair & - operator=(impl_compressed_pair const &) = default; + MDSPAN_IMPL_CONSTEXPR_14_DEFAULTED impl_compressed_pair &operator=( + impl_compressed_pair const &) = default; MDSPAN_INLINE_FUNCTION_DEFAULTED - MDSPAN_IMPL_CONSTEXPR_14_DEFAULTED impl_compressed_pair & - operator=(impl_compressed_pair &&) = default; + MDSPAN_IMPL_CONSTEXPR_14_DEFAULTED impl_compressed_pair &operator=( + impl_compressed_pair &&) = default; MDSPAN_INLINE_FUNCTION_DEFAULTED ~impl_compressed_pair() = default; template - MDSPAN_INLINE_FUNCTION constexpr impl_compressed_pair(T1Like &&t1, T2Like &&t2) - : T1((T1Like &&) t1), m_t2_val((T2Like &&) t2) {} + MDSPAN_INLINE_FUNCTION constexpr impl_compressed_pair(T1Like &&t1, + T2Like &&t2) + : T1((T1Like &&)t1), m_t2_val((T2Like &&)t2) {} }; // Second empty. template struct impl_compressed_pair< T1, T2, - std::enable_if_t> - : private T2 { + std::enable_if_t> : private T2 { T1 m_t1_val{}; - MDSPAN_FORCE_INLINE_FUNCTION MDSPAN_IMPL_CONSTEXPR_14 T1 &first() noexcept { return m_t1_val; } + MDSPAN_FORCE_INLINE_FUNCTION MDSPAN_IMPL_CONSTEXPR_14 T1 &first() noexcept { + return m_t1_val; + } MDSPAN_FORCE_INLINE_FUNCTION constexpr T1 const &first() const noexcept { return m_t1_val; } @@ -110,29 +121,31 @@ struct impl_compressed_pair< MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr impl_compressed_pair(impl_compressed_pair &&) = default; MDSPAN_INLINE_FUNCTION_DEFAULTED - MDSPAN_IMPL_CONSTEXPR_14_DEFAULTED impl_compressed_pair & - operator=(impl_compressed_pair const &) = default; + MDSPAN_IMPL_CONSTEXPR_14_DEFAULTED impl_compressed_pair &operator=( + impl_compressed_pair const &) = default; MDSPAN_INLINE_FUNCTION_DEFAULTED - MDSPAN_IMPL_CONSTEXPR_14_DEFAULTED impl_compressed_pair & - operator=(impl_compressed_pair &&) = default; + MDSPAN_IMPL_CONSTEXPR_14_DEFAULTED impl_compressed_pair &operator=( + impl_compressed_pair &&) = default; MDSPAN_INLINE_FUNCTION_DEFAULTED ~impl_compressed_pair() = default; template - MDSPAN_INLINE_FUNCTION constexpr impl_compressed_pair(T1Like &&t1, T2Like &&t2) - : T2((T2Like &&) t2), m_t1_val((T1Like &&) t1) {} + MDSPAN_INLINE_FUNCTION constexpr impl_compressed_pair(T1Like &&t1, + T2Like &&t2) + : T2((T2Like &&)t2), m_t1_val((T1Like &&)t1) {} }; // Both empty. template struct impl_compressed_pair< T1, T2, - std::enable_if_t> - // We need to use the no_unique_address_emulation wrapper here to avoid - // base class ambiguities. + std::enable_if_t> +// We need to use the no_unique_address_emulation wrapper here to avoid +// base class ambiguities. #ifdef MDSPAN_IMPL_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. + // 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, protected no_unique_address_emulation #else @@ -140,7 +153,7 @@ struct impl_compressed_pair< private no_unique_address_emulation #endif { - using first_base_t = no_unique_address_emulation; + using first_base_t = no_unique_address_emulation; using second_base_t = no_unique_address_emulation; MDSPAN_FORCE_INLINE_FUNCTION MDSPAN_IMPL_CONSTEXPR_14 T1 &first() noexcept { @@ -163,21 +176,20 @@ struct impl_compressed_pair< MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr impl_compressed_pair(impl_compressed_pair &&) = default; MDSPAN_INLINE_FUNCTION_DEFAULTED - MDSPAN_IMPL_CONSTEXPR_14_DEFAULTED impl_compressed_pair & - operator=(impl_compressed_pair const &) = default; + MDSPAN_IMPL_CONSTEXPR_14_DEFAULTED impl_compressed_pair &operator=( + impl_compressed_pair const &) = default; MDSPAN_INLINE_FUNCTION_DEFAULTED - MDSPAN_IMPL_CONSTEXPR_14_DEFAULTED impl_compressed_pair & - operator=(impl_compressed_pair &&) = default; + MDSPAN_IMPL_CONSTEXPR_14_DEFAULTED impl_compressed_pair &operator=( + impl_compressed_pair &&) = default; MDSPAN_INLINE_FUNCTION_DEFAULTED ~impl_compressed_pair() = default; template - MDSPAN_INLINE_FUNCTION constexpr impl_compressed_pair(T1Like &&t1, T2Like &&t2) noexcept - : first_base_t(T1((T1Like &&) t1)), - second_base_t(T2((T2Like &&) t2)) - { } + MDSPAN_INLINE_FUNCTION constexpr impl_compressed_pair(T1Like &&t1, + T2Like &&t2) noexcept + : first_base_t(T1((T1Like &&)t1)), second_base_t(T2((T2Like &&)t2)) {} }; -#endif // !defined(MDSPAN_IMPL_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) +#endif // !defined(MDSPAN_IMPL_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) -} // end namespace detail -} // end namespace MDSPAN_IMPL_STANDARD_NAMESPACE +} // end namespace detail +} // end namespace MDSPAN_IMPL_STANDARD_NAMESPACE diff --git a/include/mdspan/impl/config.hpp b/include/mdspan/impl/config.hpp index b61a5247..3f957360 100644 --- a/include/mdspan/impl/config.hpp +++ b/include/mdspan/impl/config.hpp @@ -4,18 +4,18 @@ #pragma once #ifndef MDSPAN_IMPL_HAS_INCLUDE -# ifndef __has_include -# define MDSPAN_IMPL_HAS_INCLUDE(x) 0 -# else -# define MDSPAN_IMPL_HAS_INCLUDE(x) __has_include(x) -# endif +#ifndef __has_include +#define MDSPAN_IMPL_HAS_INCLUDE(x) 0 +#else +#define MDSPAN_IMPL_HAS_INCLUDE(x) __has_include(x) +#endif #endif #if MDSPAN_IMPL_HAS_INCLUDE() -# include +#include #else -# include -# include +#include +#include #endif #ifdef _MSVC_LANG @@ -41,265 +41,281 @@ #define MDSPAN_HAS_CXX_23 (MDSPAN_IMPL_CPLUSPLUS >= MDSPAN_CXX_STD_23) #define MDSPAN_HAS_CXX_26 (MDSPAN_IMPL_CPLUSPLUS >= MDSPAN_CXX_STD_26) -static_assert(MDSPAN_IMPL_CPLUSPLUS >= MDSPAN_CXX_STD_14, "mdspan requires C++14 or later."); +static_assert(MDSPAN_IMPL_CPLUSPLUS >= MDSPAN_CXX_STD_14, + "mdspan requires C++14 or later."); #ifndef MDSPAN_IMPL_COMPILER_CLANG -# if defined(__clang__) -# define MDSPAN_IMPL_COMPILER_CLANG __clang__ -# endif +#if defined(__clang__) +#define MDSPAN_IMPL_COMPILER_CLANG __clang__ +#endif #endif -#if !defined(MDSPAN_IMPL_COMPILER_MSVC) && !defined(MDSPAN_IMPL_COMPILER_MSVC_CLANG) -# if defined(_MSC_VER) -# if !defined(MDSPAN_IMPL_COMPILER_CLANG) -# define MDSPAN_IMPL_COMPILER_MSVC _MSC_VER -# else -# define MDSPAN_IMPL_COMPILER_MSVC_CLANG _MSC_VER -# endif -# endif +#if !defined(MDSPAN_IMPL_COMPILER_MSVC) && \ + !defined(MDSPAN_IMPL_COMPILER_MSVC_CLANG) +#if defined(_MSC_VER) +#if !defined(MDSPAN_IMPL_COMPILER_CLANG) +#define MDSPAN_IMPL_COMPILER_MSVC _MSC_VER +#else +#define MDSPAN_IMPL_COMPILER_MSVC_CLANG _MSC_VER +#endif +#endif #endif #ifndef MDSPAN_IMPL_COMPILER_INTEL -# ifdef __INTEL_COMPILER -# define MDSPAN_IMPL_COMPILER_INTEL __INTEL_COMPILER -# endif +#ifdef __INTEL_COMPILER +#define MDSPAN_IMPL_COMPILER_INTEL __INTEL_COMPILER +#endif #endif #ifndef MDSPAN_IMPL_COMPILER_APPLECLANG -# ifdef __apple_build_version__ -# define MDSPAN_IMPL_COMPILER_APPLECLANG __apple_build_version__ -# endif +#ifdef __apple_build_version__ +#define MDSPAN_IMPL_COMPILER_APPLECLANG __apple_build_version__ +#endif #endif #ifndef MDSPAN_IMPL_HAS_CUDA -# if defined(__CUDACC__) -# define MDSPAN_IMPL_HAS_CUDA __CUDACC__ -# endif +#if defined(__CUDACC__) +#define MDSPAN_IMPL_HAS_CUDA __CUDACC__ +#endif #endif #ifndef MDSPAN_IMPL_HAS_HIP -# if defined(__HIPCC__) -# define MDSPAN_IMPL_HAS_HIP __HIPCC__ -# endif +#if defined(__HIPCC__) +#define MDSPAN_IMPL_HAS_HIP __HIPCC__ +#endif #endif #ifndef MDSPAN_IMPL_HAS_SYCL -# if defined(SYCL_LANGUAGE_VERSION) -# define MDSPAN_IMPL_HAS_SYCL SYCL_LANGUAGE_VERSION -# endif +#if defined(SYCL_LANGUAGE_VERSION) +#define MDSPAN_IMPL_HAS_SYCL SYCL_LANGUAGE_VERSION +#endif #endif #ifndef MDSPAN_IMPL_HAS_OPENACC -# if defined(_OPENACC) -# define MDSPAN_IMPL_HAS_OPENACC _OPENACC -# endif +#if defined(_OPENACC) +#define MDSPAN_IMPL_HAS_OPENACC _OPENACC +#endif #endif #ifndef MDSPAN_IMPL_HAS_CPP_ATTRIBUTE -# ifndef __has_cpp_attribute -# define MDSPAN_IMPL_HAS_CPP_ATTRIBUTE(x) 0 -# else -# define MDSPAN_IMPL_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x) -# endif +#ifndef __has_cpp_attribute +#define MDSPAN_IMPL_HAS_CPP_ATTRIBUTE(x) 0 +#else +#define MDSPAN_IMPL_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x) +#endif #endif #ifndef MDSPAN_IMPL_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_IMPL_PRESERVE_STANDARD_LAYOUT 1 +#define MDSPAN_IMPL_PRESERVE_STANDARD_LAYOUT 1 #endif #if !defined(MDSPAN_IMPL_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) -# if ((MDSPAN_IMPL_HAS_CPP_ATTRIBUTE(no_unique_address) >= 201803L) && \ - (!defined(__NVCC__) || ((__CUDACC_VER_MAJOR__ * 100 + __CUDACC_VER_MINOR__ * 10 < 1290) && MDSPAN_HAS_CXX_20)) && \ - (!defined(MDSPAN_IMPL_COMPILER_MSVC) || MDSPAN_HAS_CXX_20)) -# define MDSPAN_IMPL_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS 1 -# define MDSPAN_IMPL_NO_UNIQUE_ADDRESS [[no_unique_address]] -# else -# define MDSPAN_IMPL_NO_UNIQUE_ADDRESS -# endif +#if ((MDSPAN_IMPL_HAS_CPP_ATTRIBUTE(no_unique_address) >= 201803L) && \ + (!defined(__NVCC__) || \ + ((__CUDACC_VER_MAJOR__ * 100 + __CUDACC_VER_MINOR__ * 10 < 1290) && \ + MDSPAN_HAS_CXX_20)) && \ + (!defined(MDSPAN_IMPL_COMPILER_MSVC) || MDSPAN_HAS_CXX_20)) +#define MDSPAN_IMPL_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS 1 +#define MDSPAN_IMPL_NO_UNIQUE_ADDRESS [[no_unique_address]] +#else +#define MDSPAN_IMPL_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_IMPL_NO_UNIQUE_ADDRESS -# if defined(__NVCC__) -# define MDSPAN_IMPL_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS 1 -# define MDSPAN_IMPL_USE_FAKE_ATTRIBUTE_NO_UNIQUE_ADDRESS -# endif -# define MDSPAN_IMPL_NO_UNIQUE_ADDRESS +#if defined(__NVCC__) +#define MDSPAN_IMPL_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS 1 +#define MDSPAN_IMPL_USE_FAKE_ATTRIBUTE_NO_UNIQUE_ADDRESS +#endif +#define MDSPAN_IMPL_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_IMPL_USE_CONCEPTS -# if defined(__cpp_concepts) && __cpp_concepts >= 201507L -# define MDSPAN_IMPL_USE_CONCEPTS 1 -# endif +#if defined(__cpp_concepts) && __cpp_concepts >= 201507L +#define MDSPAN_IMPL_USE_CONCEPTS 1 +#endif #endif #endif #ifndef MDSPAN_IMPL_USE_FOLD_EXPRESSIONS -# if (defined(__cpp_fold_expressions) && __cpp_fold_expressions >= 201603L) \ - || (!defined(__cpp_fold_expressions) && MDSPAN_HAS_CXX_17) -# define MDSPAN_IMPL_USE_FOLD_EXPRESSIONS 1 -# endif +#if (defined(__cpp_fold_expressions) && __cpp_fold_expressions >= 201603L) || \ + (!defined(__cpp_fold_expressions) && MDSPAN_HAS_CXX_17) +#define MDSPAN_IMPL_USE_FOLD_EXPRESSIONS 1 +#endif #endif #ifndef MDSPAN_IMPL_USE_INLINE_VARIABLES -# if defined(__cpp_inline_variables) && __cpp_inline_variables >= 201606L \ - || (!defined(__cpp_inline_variables) && MDSPAN_HAS_CXX_17) -# define MDSPAN_IMPL_USE_INLINE_VARIABLES 1 -# endif +#if defined(__cpp_inline_variables) && __cpp_inline_variables >= 201606L || \ + (!defined(__cpp_inline_variables) && MDSPAN_HAS_CXX_17) +#define MDSPAN_IMPL_USE_INLINE_VARIABLES 1 +#endif #endif #ifndef MDSPAN_IMPL_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_IMPL_COMPILER_APPLECLANG) && MDSPAN_HAS_CXX_17) -# define MDSPAN_IMPL_NEEDS_TRAIT_VARIABLE_TEMPLATE_BACKPORTS 1 -# endif -# endif +#if (!(defined(__cpp_lib_type_trait_variable_templates) && \ + __cpp_lib_type_trait_variable_templates >= 201510L) || \ + !MDSPAN_HAS_CXX_17) +#if !(defined(MDSPAN_IMPL_COMPILER_APPLECLANG) && MDSPAN_HAS_CXX_17) +#define MDSPAN_IMPL_NEEDS_TRAIT_VARIABLE_TEMPLATE_BACKPORTS 1 +#endif +#endif #endif #ifndef MDSPAN_IMPL_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_IMPL_USE_VARIABLE_TEMPLATES 1 -# endif -#endif // MDSPAN_IMPL_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_IMPL_USE_VARIABLE_TEMPLATES 1 +#endif +#endif // MDSPAN_IMPL_USE_VARIABLE_TEMPLATES #ifndef MDSPAN_IMPL_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_IMPL_USE_CONSTEXPR_14 1 -# endif +#if (defined(__cpp_constexpr) && __cpp_constexpr >= 201304) || \ + (!defined(__cpp_constexpr) && MDSPAN_HAS_CXX_14) && \ + (!(defined(__INTEL_COMPILER) && __INTEL_COMPILER <= 1700)) +#define MDSPAN_IMPL_USE_CONSTEXPR_14 1 +#endif #endif #ifndef MDSPAN_IMPL_USE_IF_CONSTEXPR_17 -# if (defined(__cpp_if_constexpr) && __cpp_if_constexpr >= 201606) \ - || (!defined(__cpp_constexpr) && MDSPAN_HAS_CXX_17) -# define MDSPAN_IMPL_USE_IF_CONSTEXPR_17 1 -# endif +#if (defined(__cpp_if_constexpr) && __cpp_if_constexpr >= 201606) || \ + (!defined(__cpp_constexpr) && MDSPAN_HAS_CXX_17) +#define MDSPAN_IMPL_USE_IF_CONSTEXPR_17 1 +#endif #endif #ifndef MDSPAN_IMPL_USE_INTEGER_SEQUENCE_14 -# if defined(MDSPAN_IMPL_COMPILER_MSVC) -# if (defined(__cpp_lib_integer_sequence) && __cpp_lib_integer_sequence >= 201304) -# define MDSPAN_IMPL_USE_INTEGER_SEQUENCE_14 1 -# endif -# endif +#if defined(MDSPAN_IMPL_COMPILER_MSVC) +#if (defined(__cpp_lib_integer_sequence) && \ + __cpp_lib_integer_sequence >= 201304) +#define MDSPAN_IMPL_USE_INTEGER_SEQUENCE_14 1 +#endif +#endif #endif #ifndef MDSPAN_IMPL_USE_INTEGER_SEQUENCE_14 -# 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_IMPL_USE_INTEGER_SEQUENCE_14 1 -# elif defined(MDSPAN_IMPL_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_IMPL_USE_INTEGER_SEQUENCE_14 1 -# endif +#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_IMPL_USE_INTEGER_SEQUENCE_14 1 +#elif defined(MDSPAN_IMPL_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_IMPL_USE_INTEGER_SEQUENCE_14 1 +#endif #endif #ifndef MDSPAN_IMPL_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_IMPL_USE_RETURN_TYPE_DEDUCTION 1 -# endif +#if (defined(__cpp_return_type_deduction) && \ + __cpp_return_type_deduction >= 201304) || \ + (!defined(__cpp_return_type_deduction) && MDSPAN_HAS_CXX_14) +#define MDSPAN_IMPL_USE_RETURN_TYPE_DEDUCTION 1 +#endif #endif #ifndef MDSPAN_IMPL_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_IMPL_USE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION 1 -# endif +#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_IMPL_USE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION 1 +#endif #endif #ifndef MDSPAN_IMPL_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_IMPL_USE_STANDARD_TRAIT_ALIASES 1 -# elif defined(MDSPAN_IMPL_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_IMPL_USE_STANDARD_TRAIT_ALIASES 1 -# endif +#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_IMPL_USE_STANDARD_TRAIT_ALIASES 1 +#elif defined(MDSPAN_IMPL_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_IMPL_USE_STANDARD_TRAIT_ALIASES 1 +#endif #endif #ifndef MDSPAN_IMPL_DEFAULTED_CONSTRUCTORS_INHERITANCE_WORKAROUND -# ifdef __GNUC__ -# if __GNUC__ < 9 -# define MDSPAN_IMPL_DEFAULTED_CONSTRUCTORS_INHERITANCE_WORKAROUND 1 -# endif -# endif +#ifdef __GNUC__ +#if __GNUC__ < 9 +#define MDSPAN_IMPL_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 +#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) +#if defined(__cpp_multidimensional_subscript) // The following if/else is necessary to workaround a clang issue -// relative to using a parameter pack inside a bracket operator in C++2b/C++23 mode -# if defined(MDSPAN_IMPL_COMPILER_CLANG) && \ - ((__clang_major__ < 17) || \ - (__clang_major__ == 17 && __clang_minor__ == 0 && \ - __clang_patchlevel__ == 0)) -# define MDSPAN_USE_BRACKET_OPERATOR 0 -# else -# define MDSPAN_USE_BRACKET_OPERATOR 1 -# endif -# else -# define MDSPAN_USE_BRACKET_OPERATOR 0 -# endif +// relative to using a parameter pack inside a bracket operator in C++2b/C++23 +// mode +#if defined(MDSPAN_IMPL_COMPILER_CLANG) && \ + ((__clang_major__ < 17) || \ + (__clang_major__ == 17 && __clang_minor__ == 0 && \ + __clang_patchlevel__ == 0)) +#define MDSPAN_USE_BRACKET_OPERATOR 0 +#else +#define MDSPAN_USE_BRACKET_OPERATOR 1 +#endif +#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 +#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_IMPL_OP(mds,...) mds[__VA_ARGS__] +#define MDSPAN_IMPL_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_IMPL_OP0(mds) mds.accessor().access(mds.data_handle(),0) +#define MDSPAN_IMPL_OP0(mds) mds.accessor().access(mds.data_handle(), 0) #else -# define MDSPAN_IMPL_OP0(mds) mds[] -#endif -# define MDSPAN_IMPL_OP1(mds, a) mds[a] -# define MDSPAN_IMPL_OP2(mds, a, b) mds[a,b] -# define MDSPAN_IMPL_OP3(mds, a, b, c) mds[a,b,c] -# define MDSPAN_IMPL_OP4(mds, a, b, c, d) mds[a,b,c,d] -# define MDSPAN_IMPL_OP5(mds, a, b, c, d, e) mds[a,b,c,d,e] -# define MDSPAN_IMPL_OP6(mds, a, b, c, d, e, f) mds[a,b,c,d,e,f] +#define MDSPAN_IMPL_OP0(mds) mds[] +#endif +#define MDSPAN_IMPL_OP1(mds, a) mds[a] +#define MDSPAN_IMPL_OP2(mds, a, b) mds[a, b] +#define MDSPAN_IMPL_OP3(mds, a, b, c) mds[a, b, c] +#define MDSPAN_IMPL_OP4(mds, a, b, c, d) mds[a, b, c, d] +#define MDSPAN_IMPL_OP5(mds, a, b, c, d, e) mds[a, b, c, d, e] +#define MDSPAN_IMPL_OP6(mds, a, b, c, d, e, f) mds[a, b, c, d, e, f] #else -# define MDSPAN_IMPL_OP(mds,...) mds(__VA_ARGS__) -# define MDSPAN_IMPL_OP0(mds) mds() -# define MDSPAN_IMPL_OP1(mds, a) mds(a) -# define MDSPAN_IMPL_OP2(mds, a, b) mds(a,b) -# define MDSPAN_IMPL_OP3(mds, a, b, c) mds(a,b,c) -# define MDSPAN_IMPL_OP4(mds, a, b, c, d) mds(a,b,c,d) -# define MDSPAN_IMPL_OP5(mds, a, b, c, d, e) mds(a,b,c,d,e) -# define MDSPAN_IMPL_OP6(mds, a, b, c, d, e, f) mds(a,b,c,d,e,f) -#endif - -#if ! defined(MDSPAN_IMPL_ENABLE_P3663) -# define MDSPAN_IMPL_ENABLE_P3663 1 +#define MDSPAN_IMPL_OP(mds, ...) mds(__VA_ARGS__) +#define MDSPAN_IMPL_OP0(mds) mds() +#define MDSPAN_IMPL_OP1(mds, a) mds(a) +#define MDSPAN_IMPL_OP2(mds, a, b) mds(a, b) +#define MDSPAN_IMPL_OP3(mds, a, b, c) mds(a, b, c) +#define MDSPAN_IMPL_OP4(mds, a, b, c, d) mds(a, b, c, d) +#define MDSPAN_IMPL_OP5(mds, a, b, c, d, e) mds(a, b, c, d, e) +#define MDSPAN_IMPL_OP6(mds, a, b, c, d, e, f) mds(a, b, c, d, e, f) +#endif + +#if !defined(MDSPAN_IMPL_ENABLE_P3663) +#define MDSPAN_IMPL_ENABLE_P3663 1 #endif diff --git a/include/mdspan/impl/constant_wrapper.hpp b/include/mdspan/impl/constant_wrapper.hpp index 5cf9755f..ed80eb4e 100644 --- a/include/mdspan/impl/constant_wrapper.hpp +++ b/include/mdspan/impl/constant_wrapper.hpp @@ -18,62 +18,58 @@ namespace detail { using std::constant_wrapper; using std::cw; -template +template constexpr bool is_constant_wrapper = false; -template +template constexpr bool is_constant_wrapper = is_constant_wrapper; -template +template constexpr bool is_constant_wrapper> = true; -#else // back-port: constant_wrapper = detail::integral_constant +#else // back-port: constant_wrapper = detail::integral_constant -template +template using constant_wrapper = integral_constant; -template - constexpr auto cw = constant_wrapper{}; +template +constexpr auto cw = constant_wrapper{}; -template +template constexpr bool is_constant_wrapper = false; -template +template constexpr bool is_constant_wrapper = is_constant_wrapper; // integral_constant is the underlying type of the back-port constant_wrapper // (alias templates can't be used in partial specialization patterns) -template +template constexpr bool is_constant_wrapper> = true; -#endif // __cpp_lib_constant_wrapper +#endif // __cpp_lib_constant_wrapper // ============================================================ // increment function for constant wrapper // ============================================================ -template -MDSPAN_INLINE_FUNCTION -constexpr auto -increment([[maybe_unused]] constant_wrapper x) { +template +MDSPAN_INLINE_FUNCTION constexpr auto increment( + [[maybe_unused]] constant_wrapper x) { using value_type = typename decltype(x)::value_type; - return cw< value_type(Value) + value_type(1) >; + return cw; } - // ============================================================ // Generic divide / multiply (scalar fall-through) // ============================================================ template -MDSPAN_INLINE_FUNCTION -constexpr auto divide(const T0 &v0, const T1 &v1) { +MDSPAN_INLINE_FUNCTION constexpr auto divide(const T0 &v0, const T1 &v1) { return IndexT(v0) / IndexT(v1); } template -MDSPAN_INLINE_FUNCTION -constexpr auto multiply(const T0 &v0, const T1 &v1) { +MDSPAN_INLINE_FUNCTION constexpr auto multiply(const T0 &v0, const T1 &v1) { return IndexT(v0) * IndexT(v1); } @@ -83,18 +79,18 @@ constexpr auto multiply(const T0 &v0, const T1 &v1) { // ============================================================ template -MDSPAN_INLINE_FUNCTION -constexpr auto divide(const std::integral_constant &, - const std::integral_constant &) { +MDSPAN_INLINE_FUNCTION constexpr auto divide( + const std::integral_constant &, + const std::integral_constant &) { // Short-circuit division by zero // (used for strided_slice with zero extent/stride) - return integral_constant(); + return integral_constant < IndexT, v0 == 0 ? 0 : v0 / v1 > (); } template -MDSPAN_INLINE_FUNCTION -constexpr auto multiply(const std::integral_constant &, - const std::integral_constant &) { +MDSPAN_INLINE_FUNCTION constexpr auto multiply( + const std::integral_constant &, + const std::integral_constant &) { return integral_constant(); } @@ -106,39 +102,35 @@ constexpr auto multiply(const std::integral_constant &, // std::constant_wrapper takes a single NTTP template -MDSPAN_INLINE_FUNCTION -constexpr auto divide(const constant_wrapper &, - const constant_wrapper &) { +MDSPAN_INLINE_FUNCTION constexpr auto divide(const constant_wrapper &, + const constant_wrapper &) { constexpr IndexT result = IndexT(v0) == IndexT(0) ? IndexT(0) : IndexT(v0) / IndexT(v1); return cw; } template -MDSPAN_INLINE_FUNCTION -constexpr auto multiply(const constant_wrapper &, - const constant_wrapper &) { +MDSPAN_INLINE_FUNCTION constexpr auto multiply(const constant_wrapper &, + const constant_wrapper &) { constexpr IndexT result = IndexT(v0) * IndexT(v1); return cw; } -#else // back-port: constant_wrapper = integral_constant +#else // back-port: constant_wrapper = integral_constant template -MDSPAN_INLINE_FUNCTION -constexpr auto divide(const constant_wrapper &, - const constant_wrapper &) { - return integral_constant(); +MDSPAN_INLINE_FUNCTION constexpr auto divide(const constant_wrapper &, + const constant_wrapper &) { + return integral_constant < IndexT, v0 == 0 ? 0 : v0 / v1 > (); } template -MDSPAN_INLINE_FUNCTION -constexpr auto multiply(const constant_wrapper &, - const constant_wrapper &) { +MDSPAN_INLINE_FUNCTION constexpr auto multiply( + const constant_wrapper &, const constant_wrapper &) { return integral_constant(); } -#endif // __cpp_lib_constant_wrapper +#endif // __cpp_lib_constant_wrapper -} // namespace detail -} // namespace MDSPAN_IMPL_STANDARD_NAMESPACE +} // namespace detail +} // namespace MDSPAN_IMPL_STANDARD_NAMESPACE diff --git a/include/mdspan/impl/default_accessor.hpp b/include/mdspan/impl/default_accessor.hpp index 99e0891e..a6449fd6 100644 --- a/include/mdspan/impl/default_accessor.hpp +++ b/include/mdspan/impl/default_accessor.hpp @@ -5,32 +5,30 @@ #include "macros.hpp" -#include // size_t +#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 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_INLINE_FUNCTION_DEFAULTED constexpr default_accessor() noexcept = + default; - MDSPAN_TEMPLATE_REQUIRES( - class OtherElementType, - /* requires */ ( - MDSPAN_IMPL_TRAIT(std::is_convertible, OtherElementType(*)[], element_type(*)[]) - ) - ) + MDSPAN_TEMPLATE_REQUIRES(class OtherElementType, + /* requires */ (MDSPAN_IMPL_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 { + constexpr data_handle_type offset(data_handle_type p, + size_t i) const noexcept { return p + i; } @@ -38,7 +36,6 @@ struct default_accessor { constexpr reference access(data_handle_type p, size_t i) const noexcept { return p[i]; } - }; -} // end namespace MDSPAN_IMPL_STANDARD_NAMESPACE +} // end namespace MDSPAN_IMPL_STANDARD_NAMESPACE diff --git a/include/mdspan/impl/dims.hpp b/include/mdspan/impl/dims.hpp index fbac7703..781f438e 100644 --- a/include/mdspan/impl/dims.hpp +++ b/include/mdspan/impl/dims.hpp @@ -5,8 +5,7 @@ namespace MDSPAN_IMPL_STANDARD_NAMESPACE { -template< ::std::size_t Rank, class IndexType = std::size_t> -using dims = - :: MDSPAN_IMPL_STANDARD_NAMESPACE :: dextents; +template < ::std::size_t Rank, class IndexType = std::size_t> +using dims = ::MDSPAN_IMPL_STANDARD_NAMESPACE ::dextents; -} // namespace MDSPAN_IMPL_STANDARD_NAMESPACE +} // namespace MDSPAN_IMPL_STANDARD_NAMESPACE diff --git a/include/mdspan/impl/dynamic_extent.hpp b/include/mdspan/impl/dynamic_extent.hpp index 847fed18..820e9d21 100644 --- a/include/mdspan/impl/dynamic_extent.hpp +++ b/include/mdspan/impl/dynamic_extent.hpp @@ -16,8 +16,9 @@ namespace MDSPAN_IMPL_STANDARD_NAMESPACE { #if defined(__cpp_lib_span) using std::dynamic_extent; #else -MDSPAN_IMPL_INLINE_VARIABLE constexpr auto dynamic_extent = std::numeric_limits::max(); +MDSPAN_IMPL_INLINE_VARIABLE constexpr auto dynamic_extent = + std::numeric_limits::max(); #endif -} // namespace MDSPAN_IMPL_STANDARD_NAMESPACE +} // namespace MDSPAN_IMPL_STANDARD_NAMESPACE //============================================================================================================== diff --git a/include/mdspan/impl/extents.hpp b/include/mdspan/impl/extents.hpp index 3770aa7e..f51afe54 100644 --- a/include/mdspan/impl/extents.hpp +++ b/include/mdspan/impl/extents.hpp @@ -20,8 +20,8 @@ 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 -constexpr std::integral_constant impl_check_compatible_extents( +MDSPAN_INLINE_FUNCTION constexpr std::integral_constant +impl_check_compatible_extents( std::integral_constant, std::integer_sequence, std::integer_sequence) noexcept { @@ -30,16 +30,14 @@ constexpr std::integral_constant impl_check_compatible_extents( // This helper prevents ICE's on MSVC. template -struct impl_compare_extent_compatible : std::integral_constant -{}; +struct impl_compare_extent_compatible + : std::integral_constant {}; template -MDSPAN_INLINE_FUNCTION -constexpr std::integral_constant< - bool, MDSPAN_IMPL_FOLD_AND(impl_compare_extent_compatible::value)> +MDSPAN_INLINE_FUNCTION constexpr std::integral_constant< + bool, MDSPAN_IMPL_FOLD_AND( + impl_compare_extent_compatible::value)> impl_check_compatible_extents( std::integral_constant, std::integer_sequence, @@ -47,12 +45,12 @@ impl_check_compatible_extents( return {}; } -template -MDSPAN_INLINE_FUNCTION -constexpr bool are_valid_indices() { - return - MDSPAN_IMPL_FOLD_AND(std::is_convertible::value) && - MDSPAN_IMPL_FOLD_AND(std::is_nothrow_constructible::value); +template +MDSPAN_INLINE_FUNCTION constexpr bool are_valid_indices() { + return MDSPAN_IMPL_FOLD_AND( + std::is_convertible::value) && + MDSPAN_IMPL_FOLD_AND( + std::is_nothrow_constructible::value); } // ------------------------------------------------------------------ @@ -63,7 +61,8 @@ constexpr bool are_valid_indices() { // function and operator []. // Implementation of Static Array with recursive implementation of get. -template struct static_array_impl; +template +struct static_array_impl; template struct static_array_impl { @@ -84,23 +83,22 @@ struct static_array_impl { }; // Don't start recursion if size 0 -template struct static_array_impl<0, T> { +template +struct static_array_impl<0, T> { MDSPAN_INLINE_FUNCTION constexpr static T get(size_t) { return T(); } }; // Static array, provides get(), get(r) and operator[r] -template struct static_array: - public static_array_impl<0, T, Values...> { - -public: +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 --------------------------------- // ------------------------------------------------------------------ @@ -109,7 +107,8 @@ template struct static_array: // 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; template struct index_sequence_scan_impl { @@ -124,7 +123,7 @@ struct index_sequence_scan_impl { template struct index_sequence_scan_impl { -#if defined(__NVCC__) || defined(__NVCOMPILER) || \ +#if defined(__NVCC__) || defined(__NVCOMPILER) || \ defined(MDSPAN_IMPL_COMPILER_INTEL) // NVCC warns about pointless comparison with 0 for R==0 and r being const // evaluatable and also 0. @@ -137,7 +136,8 @@ struct index_sequence_scan_impl { constexpr static size_t get(size_t r) { return R > r ? FirstVal : 0; } #endif }; -template <> struct index_sequence_scan_impl<0> { +template <> +struct index_sequence_scan_impl<0> { MDSPAN_INLINE_FUNCTION constexpr static size_t get(size_t) { return 0; } }; @@ -151,7 +151,8 @@ template <> struct index_sequence_scan_impl<0> { // This is needed to make the maybe_static_array be truly empty, for // all static values. -template struct possibly_empty_array { +template +struct possibly_empty_array { T vals[N]{}; MDSPAN_INLINE_FUNCTION constexpr T &operator[](size_t r) { return vals[r]; } @@ -159,7 +160,8 @@ template struct possibly_empty_array { constexpr const T &operator[](size_t r) const { return vals[r]; } }; -template struct possibly_empty_array { +template +struct possibly_empty_array { MDSPAN_INLINE_FUNCTION constexpr T operator[](size_t) { return T(); } MDSPAN_INLINE_FUNCTION @@ -176,13 +178,14 @@ template struct possibly_empty_array { // 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"); - 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: + private: // Static values member - using static_vals_t = static_array; + using static_vals_t = static_array; constexpr static size_t m_size = sizeof...(Values); constexpr static size_t m_size_dynamic = MDSPAN_IMPL_FOLD_PLUS_RIGHT((Values == dyn_tag), 0); @@ -192,11 +195,12 @@ struct maybe_static_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: + 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 value_type = TDynamic; using static_value_type = TStatic; // tag value indicating dynamic value constexpr static static_value_type tag_value = dyn_tag; @@ -220,7 +224,6 @@ struct maybe_static_array { 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 @@ -255,8 +258,7 @@ struct maybe_static_array { m_size_dynamic && m_size_dynamic > 0)) MDSPAN_INLINE_FUNCTION - constexpr maybe_static_array(DynVals... vals) - : m_dyn_vals{} { + 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++) { @@ -325,7 +327,9 @@ struct maybe_static_array { // access functions MDSPAN_INLINE_FUNCTION - constexpr static TStatic static_value(size_t r) { return static_vals_t::get(r); } + constexpr static TStatic static_value(size_t r) { + return static_vals_t::get(r); + } MDSPAN_INLINE_FUNCTION constexpr TDynamic value(size_t r) const { @@ -334,12 +338,11 @@ struct maybe_static_array { // FIXME: workaround for nvhpc OpenACC compiler bug TStatic dyn_tag_copy = dyn_tag; return static_val == dyn_tag_copy ? m_dyn_vals[dyn_map_t::get(r)] - : static_cast(static_val); + : 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; } @@ -347,8 +350,8 @@ struct maybe_static_array { constexpr static size_t size_dynamic() { return m_size_dynamic; } }; -} // namespace detail -} // namespace MDSPAN_IMPL_STANDARD_NAMESPACE +} // namespace detail +} // namespace MDSPAN_IMPL_STANDARD_NAMESPACE namespace MDSPAN_IMPL_STANDARD_NAMESPACE { @@ -360,16 +363,21 @@ namespace MDSPAN_IMPL_STANDARD_NAMESPACE { // Used by mdspan, mdarray and layout mappings. // See ISO C++ standard [mdspan.extents] -template class extents { -public: +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; + 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"); - 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: + private: constexpr static rank_type m_rank = sizeof...(Extents); constexpr static rank_type m_rank_dynamic = MDSPAN_IMPL_FOLD_PLUS_RIGHT((Extents == dynamic_extent), /* + ... + */ 0); @@ -379,7 +387,7 @@ template class extents { detail::maybe_static_array; MDSPAN_IMPL_NO_UNIQUE_ADDRESS vals_t m_vals; -public: + public: // [mdspan.extents.obs], observers of multidimensional index space MDSPAN_INLINE_FUNCTION constexpr static rank_type rank() noexcept { return m_rank; } @@ -387,7 +395,9 @@ template class extents { 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); } + 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); @@ -401,30 +411,32 @@ template class extents { // Precondition check is deferred to maybe_static_array constructor MDSPAN_TEMPLATE_REQUIRES( class... OtherIndexTypes, - /* requires */ ( - MDSPAN_IMPL_FOLD_AND(MDSPAN_IMPL_TRAIT(std::is_convertible, OtherIndexTypes, - index_type) /* && ... */) && - MDSPAN_IMPL_FOLD_AND(MDSPAN_IMPL_TRAIT(std::is_nothrow_constructible, index_type, - OtherIndexTypes) /* && ... */) && - (sizeof...(OtherIndexTypes) == m_rank || - sizeof...(OtherIndexTypes) == m_rank_dynamic))) + /* requires */ (MDSPAN_IMPL_FOLD_AND(MDSPAN_IMPL_TRAIT( + std::is_convertible, OtherIndexTypes, + index_type) /* && ... */) && + MDSPAN_IMPL_FOLD_AND(MDSPAN_IMPL_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)...) { #if MDSPAN_HAS_CXX_17 MDSPAN_IMPL_PRECONDITION( - detail::all_values_are_nonnegative_and_representable(dynvals...)); + detail::all_values_are_nonnegative_and_representable( + dynvals...)); #endif } MDSPAN_TEMPLATE_REQUIRES( class OtherIndexType, size_t N, /* requires */ - ( - MDSPAN_IMPL_TRAIT(std::is_convertible, const OtherIndexType&, index_type) && - MDSPAN_IMPL_TRAIT(std::is_nothrow_constructible, index_type, - const OtherIndexType&) && - (N == m_rank || N == m_rank_dynamic))) + (MDSPAN_IMPL_TRAIT(std::is_convertible, const OtherIndexType &, + index_type) && + MDSPAN_IMPL_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 @@ -440,8 +452,10 @@ template class extents { MDSPAN_TEMPLATE_REQUIRES( class OtherIndexType, size_t N, /* requires */ - (MDSPAN_IMPL_TRAIT(std::is_convertible, const OtherIndexType&, index_type) && - MDSPAN_IMPL_TRAIT(std::is_nothrow_constructible, index_type, const OtherIndexType&) && + (MDSPAN_IMPL_TRAIT(std::is_convertible, const OtherIndexType &, + index_type) && + MDSPAN_IMPL_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) @@ -453,7 +467,7 @@ template class extents { } #endif -private: + 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. @@ -462,11 +476,10 @@ template class extents { 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 impl_construct_vals_from_extents(std::integral_constant, - std::integral_constant, - const OtherExtents &exts, - DynamicValues... dynamic_values) noexcept { + constexpr vals_t impl_construct_vals_from_extents( + std::integral_constant, + std::integral_constant, const OtherExtents &exts, + DynamicValues... dynamic_values) noexcept { return impl_construct_vals_from_extents( std::integral_constant(), std::integral_constant(), exts, dynamic_values..., @@ -477,11 +490,10 @@ template class extents { 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 impl_construct_vals_from_extents(std::integral_constant, - std::integral_constant, - const OtherExtents &exts, - DynamicValues... dynamic_values) noexcept { + constexpr vals_t impl_construct_vals_from_extents( + std::integral_constant, + std::integral_constant, const OtherExtents &exts, + DynamicValues... dynamic_values) noexcept { return impl_construct_vals_from_extents( std::integral_constant(), std::integral_constant(), exts, dynamic_values...); @@ -491,31 +503,30 @@ template class extents { size_t DynCount, size_t R, class OtherExtents, class... DynamicValues, /* requires */ ((R == m_rank) && (DynCount == m_rank_dynamic))) MDSPAN_INLINE_FUNCTION - constexpr - vals_t impl_construct_vals_from_extents(std::integral_constant, - std::integral_constant, - const OtherExtents &, - DynamicValues... dynamic_values) noexcept { + constexpr vals_t impl_construct_vals_from_extents( + std::integral_constant, + std::integral_constant, const OtherExtents &, + DynamicValues... dynamic_values) noexcept { return vals_t{static_cast(dynamic_values)...}; } -public: - + 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::impl_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()>{}, + 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::impl_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< + bool, extents::rank() == + extents::rank()>{}, std::integer_sequence{}, - std::integer_sequence{}))::value - ) - ) + std::integer_sequence{}))::value)) MDSPAN_INLINE_FUNCTION MDSPAN_CONDITIONAL_EXPLICIT((((Extents != dynamic_extent) && (OtherExtents == dynamic_extent)) || @@ -535,19 +546,19 @@ template class extents { // 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); + 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 { + MDSPAN_INLINE_FUNCTION friend constexpr bool operator!=( + extents const &lhs, + extents const &rhs) noexcept { return !(lhs == rhs); } #endif @@ -562,23 +573,24 @@ struct impl_make_dextents; template struct impl_make_dextents< - IndexType, Rank, ::MDSPAN_IMPL_STANDARD_NAMESPACE::extents> -{ + IndexType, Rank, + ::MDSPAN_IMPL_STANDARD_NAMESPACE::extents> { using type = typename impl_make_dextents< IndexType, Rank - 1, - ::MDSPAN_IMPL_STANDARD_NAMESPACE::extents>::type; + ::MDSPAN_IMPL_STANDARD_NAMESPACE::extents< + IndexType, ::MDSPAN_IMPL_STANDARD_NAMESPACE::dynamic_extent, + ExtentsPack...>>::type; }; template struct impl_make_dextents< - IndexType, 0, ::MDSPAN_IMPL_STANDARD_NAMESPACE::extents> -{ - using type = ::MDSPAN_IMPL_STANDARD_NAMESPACE::extents; + IndexType, 0, + ::MDSPAN_IMPL_STANDARD_NAMESPACE::extents> { + using type = + ::MDSPAN_IMPL_STANDARD_NAMESPACE::extents; }; -} // end namespace detail +} // end namespace detail // [mdspan.extents.dextents], alias template template @@ -588,17 +600,19 @@ using dextents = typename detail::impl_make_dextents::type; #if defined(MDSPAN_IMPL_USE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION) template extents(IndexTypes...) - -> extents; + -> extents; #endif // Helper type traits for identifying a class as extents. namespace detail { -template struct impl_is_extents : ::std::false_type {}; +template +struct impl_is_extents : ::std::false_type {}; template -struct impl_is_extents<::MDSPAN_IMPL_STANDARD_NAMESPACE::extents> +struct impl_is_extents< + ::MDSPAN_IMPL_STANDARD_NAMESPACE::extents> : ::std::true_type {}; template @@ -607,37 +621,28 @@ inline #else static #endif -constexpr bool impl_is_extents_v = impl_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 + constexpr bool impl_is_extents_v = impl_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; +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 @@ -646,43 +651,32 @@ check_upper_bound(InputIndexType user_index, // Returning true to use AND fold instead of comma // CPP14 mode doesn't like the use of void expressions // with the way the MDSPAN_IMPL_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>{}); +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) -{ +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_IMPL_FOLD_AND( - (check_one_index(indices, exts.extent(RankIndices))) - ); + (void)MDSPAN_IMPL_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...); +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 +} // namespace detail +} // namespace MDSPAN_IMPL_STANDARD_NAMESPACE diff --git a/include/mdspan/impl/full_extent_t.hpp b/include/mdspan/impl/full_extent_t.hpp index ba270e83..35796fdf 100644 --- a/include/mdspan/impl/full_extent_t.hpp +++ b/include/mdspan/impl/full_extent_t.hpp @@ -7,8 +7,10 @@ namespace MDSPAN_IMPL_STANDARD_NAMESPACE { -struct full_extent_t { explicit full_extent_t() = default; }; +struct full_extent_t { + explicit full_extent_t() = default; +}; -MDSPAN_IMPL_INLINE_VARIABLE constexpr auto full_extent = full_extent_t{ }; +MDSPAN_IMPL_INLINE_VARIABLE constexpr auto full_extent = full_extent_t{}; -} // namespace MDSPAN_IMPL_STANDARD_NAMESPACE +} // namespace MDSPAN_IMPL_STANDARD_NAMESPACE diff --git a/include/mdspan/impl/integral_constant_like.hpp b/include/mdspan/impl/integral_constant_like.hpp index 5c0b84ce..70d52505 100644 --- a/include/mdspan/impl/integral_constant_like.hpp +++ b/include/mdspan/impl/integral_constant_like.hpp @@ -6,8 +6,8 @@ #include "utility.hpp" #include #if defined(__cpp_lib_concepts) -# include -#endif // __cpp_lib_concepts +#include +#endif // __cpp_lib_concepts // ============================================================ // equality_comparable back-port (used only by integral_constant_like) @@ -16,14 +16,16 @@ #if defined(__cpp_lib_concepts) namespace MDSPAN_IMPL_STANDARD_NAMESPACE { - namespace detail { - template - struct is_equality_comparable : std::bool_constant> {}; +namespace detail { +template +struct is_equality_comparable + : std::bool_constant> {}; - template - struct is_equality_comparable_with : std::bool_constant> {}; - } // namespace detail -} // namespace MDSPAN_IMPL_STANDARD_NAMESPACE +template +struct is_equality_comparable_with + : std::bool_constant> {}; +} // namespace detail +} // namespace MDSPAN_IMPL_STANDARD_NAMESPACE #else @@ -32,64 +34,52 @@ namespace MDSPAN_IMPL_STANDARD_NAMESPACE { namespace MDSPAN_IMPL_STANDARD_NAMESPACE { namespace detail { - template - struct is_equality_comparable : std::false_type {}; +template +struct is_equality_comparable : std::false_type {}; - template - struct is_equality_comparable< +template +struct is_equality_comparable< T, - std::void_t< - decltype(std::declval() == std::declval()), - decltype(std::declval() != std::declval()) - > - > : std::bool_constant< - std::is_convertible_v< - decltype(std::declval() == std::declval()), - bool - > && - std::is_convertible_v< - decltype(std::declval() != std::declval()), - bool - > - > {}; - - template - struct is_equality_comparable_with : std::false_type {}; - - template - struct is_equality_comparable_with< + std::void_t() == std::declval()), + decltype(std::declval() != std::declval())>> + : std::bool_constant< + std::is_convertible_v() == + std::declval()), + bool> && + std::is_convertible_v() != + std::declval()), + bool>> {}; + +template +struct is_equality_comparable_with : std::false_type {}; + +template +struct is_equality_comparable_with< T, U, - std::void_t< - decltype(std::declval() == std::declval()), - decltype(std::declval() != std::declval()), - decltype(std::declval() == std::declval()), - decltype(std::declval() != std::declval()) - > - > : std::bool_constant< - is_equality_comparable::value && - is_equality_comparable::value && - std::is_convertible_v< - decltype(std::declval() == std::declval()), - bool - > && - std::is_convertible_v< - decltype(std::declval() != std::declval()), - bool - > && - std::is_convertible_v< - decltype(std::declval() == std::declval()), - bool - > && - std::is_convertible_v< - decltype(std::declval() != std::declval()), - bool - > - > {}; - -} // namespace detail -} // namespace MDSPAN_IMPL_STANDARD_NAMESPACE - -#endif // defined(__cpp_lib_concepts) + std::void_t() == std::declval()), + decltype(std::declval() != std::declval()), + decltype(std::declval() == std::declval()), + decltype(std::declval() != std::declval())>> + : std::bool_constant< + is_equality_comparable::value && + is_equality_comparable::value && + std::is_convertible_v() == + std::declval()), + bool> && + std::is_convertible_v() != + std::declval()), + bool> && + std::is_convertible_v() == + std::declval()), + bool> && + std::is_convertible_v() != + std::declval()), + bool>> {}; + +} // namespace detail +} // namespace MDSPAN_IMPL_STANDARD_NAMESPACE + +#endif // defined(__cpp_lib_concepts) // ============================================================ // integral_constant_like concept / trait @@ -98,47 +88,48 @@ namespace detail { #if defined(__cpp_lib_concepts) namespace MDSPAN_IMPL_STANDARD_NAMESPACE { - namespace detail { +namespace detail { - template - concept integral_constant_like = - std::is_integral_v> && - !std::is_same_v> && - std::convertible_to && - std::equality_comparable_with && - std::bool_constant::value && - std::bool_constant(T()) == T::value>::value; +template +concept integral_constant_like = + std::is_integral_v> && + !std::is_same_v> && + std::convertible_to && + std::equality_comparable_with && + std::bool_constant::value && + std::bool_constant(T()) == T::value>::value; - template - constexpr bool is_integral_constant_like_v = integral_constant_like; +template +constexpr bool is_integral_constant_like_v = integral_constant_like; - } // namespace detail -} // namespace MDSPAN_IMPL_STANDARD_NAMESPACE +} // namespace detail +} // namespace MDSPAN_IMPL_STANDARD_NAMESPACE #else namespace MDSPAN_IMPL_STANDARD_NAMESPACE { - namespace detail { - - template - struct is_integral_constant_like_impl : std::false_type {}; - - template - struct is_integral_constant_like_impl> : - std::bool_constant< - std::is_integral_v> && - ! std::is_same_v> && - std::is_convertible_v && - is_equality_comparable_with::value && - std::bool_constant::value && - std::bool_constant(T()) == T::value>::value - > - {}; - - template - constexpr bool is_integral_constant_like_v = is_integral_constant_like_impl::value; - - } // namespace detail -} // namespace MDSPAN_IMPL_STANDARD_NAMESPACE - -#endif // __cpp_lib_concepts +namespace detail { + +template +struct is_integral_constant_like_impl : std::false_type {}; + +template +struct is_integral_constant_like_impl< + T, std::void_t> + : std::bool_constant< + std::is_integral_v> && + !std::is_same_v> && + std::is_convertible_v && + is_equality_comparable_with::value && + std::bool_constant::value && + std::bool_constant(T()) == + T::value>::value> {}; + +template +constexpr bool is_integral_constant_like_v = + is_integral_constant_like_impl::value; + +} // namespace detail +} // namespace MDSPAN_IMPL_STANDARD_NAMESPACE + +#endif // __cpp_lib_concepts diff --git a/include/mdspan/impl/layout_left.hpp b/include/mdspan/impl/layout_left.hpp index 87d0bdbd..1dca83c1 100644 --- a/include/mdspan/impl/layout_left.hpp +++ b/include/mdspan/impl/layout_left.hpp @@ -19,169 +19,166 @@ 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::impl_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_IMPL_HOST_DEVICE - constexpr index_type compute_offset( - rank_count, const I& i, Indices... idx) const { - return compute_offset(rank_count(), idx...) * - m_extents.extent(r) + i; - } - - template - MDSPAN_IMPL_HOST_DEVICE - constexpr index_type compute_offset( - rank_count, const I& i) const { - return i; - } - - MDSPAN_IMPL_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_IMPL_HOST_DEVICE - constexpr mapping(extents_type const& exts) noexcept - :m_extents(exts) - { } - - MDSPAN_TEMPLATE_REQUIRES( + 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::impl_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_IMPL_HOST_DEVICE constexpr index_type compute_offset( + rank_count, const I& i, Indices... idx) const { + return compute_offset(rank_count(), idx...) * + m_extents.extent(r) + + i; + } + + template + MDSPAN_IMPL_HOST_DEVICE constexpr index_type compute_offset( + rank_count, + const I& i) const { + return i; + } + + MDSPAN_IMPL_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_IMPL_HOST_DEVICE + constexpr mapping(extents_type const& exts) noexcept : m_extents(exts) {} + + MDSPAN_TEMPLATE_REQUIRES( class OtherExtents, - /* requires */ ( - MDSPAN_IMPL_TRAIT(std::is_constructible, extents_type, OtherExtents) - ) - ) - MDSPAN_CONDITIONAL_EXPLICIT((!std::is_convertible::value)) // needs two () due to comma - MDSPAN_INLINE_FUNCTION MDSPAN_IMPL_CONSTEXPR_14 - mapping(mapping const& other) noexcept // NOLINT(google-explicit-constructor) - :m_extents(other.extents()) - { - /* - * TODO: check precondition - * other.required_span_size() is a representable value of type index_type - */ - } - - MDSPAN_TEMPLATE_REQUIRES( + /* requires */ (MDSPAN_IMPL_TRAIT(std::is_constructible, extents_type, + OtherExtents))) + MDSPAN_CONDITIONAL_EXPLICIT( + (!std::is_convertible::value)) // needs two () due to comma + MDSPAN_INLINE_FUNCTION MDSPAN_IMPL_CONSTEXPR_14 + mapping(mapping const& + other) noexcept // NOLINT(google-explicit-constructor) + : m_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_IMPL_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_IMPL_CONSTEXPR_14 - mapping(layout_right::mapping const& other) noexcept // NOLINT(google-explicit-constructor) - :m_extents(other.extents()) - { - /* - * TODO: check precondition - * other.required_span_size() is a representable value of type index_type - */ - } + /* requires */ (MDSPAN_IMPL_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_IMPL_CONSTEXPR_14 + mapping(layout_right::mapping const& + other) noexcept // NOLINT(google-explicit-constructor) + : m_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 */ (detail::is_layout_left_padded_mapping::value - &&std::is_constructible_v< - extents_type, typename Mapping::extents_type>)) - MDSPAN_CONDITIONAL_EXPLICIT( - (!std::is_convertible_v)) - MDSPAN_INLINE_FUNCTION constexpr mapping(const Mapping &other) noexcept - : m_extents(other.extents()) { - detail::check_padded_layout_converting_constructor_mandates( - detail::with_rank{}); - detail::check_padded_layout_converting_constructor_preconditions< - extents_type>(detail::with_rank{}, other); - } + /** + * 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 */ (detail::is_layout_left_padded_mapping::value&& + std::is_constructible_v< + extents_type, typename Mapping::extents_type>)) + MDSPAN_CONDITIONAL_EXPLICIT( + (!std::is_convertible_v)) + MDSPAN_INLINE_FUNCTION constexpr mapping(const Mapping& other) noexcept + : m_extents(other.extents()) { + detail::check_padded_layout_converting_constructor_mandates( + detail::with_rank{}); + detail::check_padded_layout_converting_constructor_preconditions< + extents_type>(detail::with_rank{}, other); + } #endif - MDSPAN_TEMPLATE_REQUIRES( + MDSPAN_TEMPLATE_REQUIRES( class OtherExtents, - /* requires */ ( - MDSPAN_IMPL_TRAIT(std::is_constructible, extents_type, OtherExtents) - ) - ) - MDSPAN_CONDITIONAL_EXPLICIT((extents_type::rank() > 0)) - MDSPAN_INLINE_FUNCTION MDSPAN_IMPL_CONSTEXPR_14 - mapping(layout_stride::mapping const& other) noexcept // NOLINT(google-explicit-constructor) - :m_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{}, m_extents, other); - } - - MDSPAN_INLINE_FUNCTION_DEFAULTED MDSPAN_IMPL_CONSTEXPR_14_DEFAULTED mapping& operator=(mapping const&) noexcept = default; - - MDSPAN_INLINE_FUNCTION - constexpr const extents_type& extents() const noexcept { - return m_extents; - } - - MDSPAN_INLINE_FUNCTION - constexpr index_type required_span_size() const noexcept { - index_type value = 1; - for(rank_type r=0; r()) - ) - ) - MDSPAN_IMPL_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)...); - } + /* requires */ (MDSPAN_IMPL_TRAIT(std::is_constructible, extents_type, + OtherExtents))) + MDSPAN_CONDITIONAL_EXPLICIT((extents_type::rank() > 0)) + MDSPAN_INLINE_FUNCTION MDSPAN_IMPL_CONSTEXPR_14 + mapping(layout_stride::mapping const& + other) noexcept // NOLINT(google-explicit-constructor) + : m_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{}, m_extents, other); + } + + MDSPAN_INLINE_FUNCTION_DEFAULTED MDSPAN_IMPL_CONSTEXPR_14_DEFAULTED mapping& + operator=(mapping const&) noexcept = default; + MDSPAN_INLINE_FUNCTION + constexpr const extents_type& extents() const noexcept { return m_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 *= m_extents.extent(r); + return value; + } + //-------------------------------------------------------------------------------- + + MDSPAN_TEMPLATE_REQUIRES( + class... Indices, + /* requires */ ((sizeof...(Indices) == extents_type::rank()) && + (detail::are_valid_indices()))) + MDSPAN_IMPL_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)...); + } + + // clang-format off 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; } @@ -189,67 +186,68 @@ class layout_left::mapping { 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; } + // clang-format on - MDSPAN_INLINE_FUNCTION - constexpr index_type stride(rank_type i) const noexcept + MDSPAN_INLINE_FUNCTION + constexpr index_type stride(rank_type i) const noexcept #if MDSPAN_HAS_CXX_20 - requires ( Extents::rank() > 0 ) + 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 + { + index_type value = 1; + for (rank_type r = 0; r < i; r++) value *= m_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(); - } + 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 - MDSPAN_INLINE_FUNCTION - constexpr index_type impl_get_stride(MDSPAN_IMPL_STANDARD_NAMESPACE::extents,std::integer_sequence) const { - return MDSPAN_IMPL_FOLD_TIMES_RIGHT((Idx():1),1); - } - template - MDSPAN_INLINE_FUNCTION - constexpr index_type impl_stide() const noexcept { - return impl_get_stride(m_extents, std::make_index_sequence()); - } - -private: - MDSPAN_IMPL_NO_UNIQUE_ADDRESS extents_type m_extents{}; - - // [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...); - } + // Not really public, but currently needed to implement fully constexpr + // useable submdspan: + template + MDSPAN_INLINE_FUNCTION constexpr index_type impl_get_stride( + MDSPAN_IMPL_STANDARD_NAMESPACE::extents, + std::integer_sequence) const { + return MDSPAN_IMPL_FOLD_TIMES_RIGHT( + (Idx < N ? m_extents.template extent() : 1), 1); + } + template + MDSPAN_INLINE_FUNCTION constexpr index_type impl_stide() const noexcept { + return impl_get_stride(m_extents, + std::make_index_sequence()); + } + + private: + MDSPAN_IMPL_NO_UNIQUE_ADDRESS extents_type m_extents{}; + + // [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 namespace MDSPAN_IMPL_STANDARD_NAMESPACE +} // end namespace MDSPAN_IMPL_STANDARD_NAMESPACE diff --git a/include/mdspan/impl/layout_padded.hpp b/include/mdspan/impl/layout_padded.hpp index 77659ddd..67900d2f 100644 --- a/include/mdspan/impl/layout_padded.hpp +++ b/include/mdspan/impl/layout_padded.hpp @@ -15,15 +15,12 @@ namespace MDSPAN_IMPL_STANDARD_NAMESPACE { namespace detail { -template -MDSPAN_INLINE_FUNCTION -constexpr T -find_next_multiple(T alignment, U offset) -{ - if ( alignment == T(0) ) { +template +MDSPAN_INLINE_FUNCTION constexpr T find_next_multiple(T alignment, U offset) { + if (alignment == T(0)) { return T(0); } else { - return ( ( offset + alignment - 1 ) / alignment) * alignment; + return ((offset + alignment - 1) / alignment) * alignment; } } @@ -64,20 +61,19 @@ 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 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::detail:: - get_actual_static_padding_value()>; + ::MDSPAN_IMPL_STANDARD_NAMESPACE::detail::get_actual_static_padding_value< + extents_type, PaddingValue, ExtentToPadIdx>()>; }; template struct static_array_type_for_padded_extent< PaddingValue, Extents, ExtentToPadIdx, Rank, std::enable_if_t> { - using index_type = typename Extents::index_type; + 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>; @@ -86,8 +82,8 @@ struct static_array_type_for_padded_extent< template struct padded_extent { static constexpr size_t padding_value = PaddingValue; - using index_type = typename Extents::index_type; - using extents_type = Extents; + 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; @@ -109,9 +105,8 @@ struct padded_extent { #endif } - MDSPAN_INLINE_FUNCTION static constexpr static_array_type - init_padding([[maybe_unused]] const Extents &exts, - [[maybe_unused]] size_t pv) { + MDSPAN_INLINE_FUNCTION static constexpr static_array_type init_padding( + [[maybe_unused]] const Extents &exts, [[maybe_unused]] size_t pv) { using MDSPAN_IMPL_STANDARD_NAMESPACE::detail::in_range; if constexpr (Extents::rank() > 1) { auto strd = find_next_multiple(pv, exts.extent(ExtentToPadIdx)); @@ -127,9 +122,9 @@ struct padded_extent { } template - MDSPAN_INLINE_FUNCTION static constexpr static_array_type - init_padding([[maybe_unused]] const Mapping &other_mapping, - std::integral_constant) { + 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 { @@ -143,20 +138,21 @@ struct padded_extent { }; template -MDSPAN_INLINE_FUNCTION constexpr bool -check_static_extents_representability() { - using MDSPAN_IMPL_STANDARD_NAMESPACE::detail::check_mul_result_is_nonnegative_and_representable; +MDSPAN_INLINE_FUNCTION constexpr bool check_static_extents_representability() { + using MDSPAN_IMPL_STANDARD_NAMESPACE::detail:: + check_mul_result_is_nonnegative_and_representable; // We cannot check statically for sure if the extents are representable // if we have dynamic values -- this can only be checked by a precondition - // We can check if the product of only the static extents is representable though... + // We can check if the product of only the static extents is representable + // though... using index_type = typename Extents::index_type; - // get rid of NVCC warning "pointless comparison of unsigned integer with zero" - if constexpr ( Extents::rank() > 0 ) { + // get rid of NVCC warning "pointless comparison of unsigned integer with + // zero" + if constexpr (Extents::rank() > 0) { auto prod = index_type(1); for (size_t i = 0; i < Extents::rank(); ++i) { - if (Extents::static_extent(i) == dynamic_extent) - continue; + if (Extents::static_extent(i) == dynamic_extent) continue; if (!check_mul_result_is_nonnegative_and_representable( prod, static_cast(Extents::static_extent(i)))) return false; @@ -168,13 +164,15 @@ check_static_extents_representability() { } template -MDSPAN_INLINE_FUNCTION constexpr bool -check_extents_representability(const Extents &exts) { - using MDSPAN_IMPL_STANDARD_NAMESPACE::detail::check_mul_result_is_nonnegative_and_representable; +MDSPAN_INLINE_FUNCTION constexpr bool check_extents_representability( + const Extents &exts) { + using MDSPAN_IMPL_STANDARD_NAMESPACE::detail:: + check_mul_result_is_nonnegative_and_representable; using index_type = typename Extents::index_type; - // get rid of NVCC warning "pointless comparison of unsigned integer with zero" - if constexpr ( Extents::rank() > 0 ) { + // get rid of NVCC warning "pointless comparison of unsigned integer with + // zero" + if constexpr (Extents::rank() > 0) { auto prod = index_type(1); for (size_t i = 0; i < Extents::rank(); ++i) { if (!check_mul_result_is_nonnegative_and_representable( @@ -190,24 +188,29 @@ check_extents_representability(const Extents &exts) { template MDSPAN_INLINE_FUNCTION constexpr bool check_static_extents_and_left_padding_representability() { - using MDSPAN_IMPL_STANDARD_NAMESPACE::detail::check_mul_result_is_nonnegative_and_representable; + using MDSPAN_IMPL_STANDARD_NAMESPACE::detail:: + check_mul_result_is_nonnegative_and_representable; if constexpr (Extents::rank() < 2) { return true; } - // We cannot check statically for sure if the product of the extents and padding value - // are representable if we have dynamic values -- this can only be checked by a precondition - // We can check if the product of only the static extents and potentially the padding value (if it is static) - // is representable though... - // We already checked that StaticPaddingValue is representable by index_type - - // get rid of NVCC warning "pointless comparison of unsigned integer with zero" - if constexpr ( Extents::rank() > 0 ) { - auto prod = (StaticPaddingValue != dynamic_extent) ? static_cast< CheckType >(StaticPaddingValue) : CheckType(1); + // We cannot check statically for sure if the product of the extents and + // padding value are representable if we have dynamic values -- this can only + // be checked by a precondition We can check if the product of only the static + // extents and potentially the padding value (if it is static) is + // representable though... We already checked that StaticPaddingValue is + // representable by index_type + + // get rid of NVCC warning "pointless comparison of unsigned integer with + // zero" + if constexpr (Extents::rank() > 0) { + auto prod = (StaticPaddingValue != dynamic_extent) + ? static_cast(StaticPaddingValue) + : CheckType(1); for (size_t i = 1; i < Extents::rank(); ++i) { - if (Extents::static_extent(i) == dynamic_extent) - continue; - if (!check_mul_result_is_nonnegative_and_representable(prod, static_cast< CheckType >(Extents::static_extent(i)))) + if (Extents::static_extent(i) == dynamic_extent) continue; + if (!check_mul_result_is_nonnegative_and_representable( + prod, static_cast(Extents::static_extent(i)))) return false; prod *= Extents::static_extent(i); } @@ -218,13 +221,14 @@ check_static_extents_and_left_padding_representability() { template MDSPAN_INLINE_FUNCTION constexpr bool -check_extents_and_left_padding_representability(const Extents &exts, - [[maybe_unused]] size_t dynamic_padding_value) { - using MDSPAN_IMPL_STANDARD_NAMESPACE::detail::check_mul_result_is_nonnegative_and_representable; - - // get rid of NVCC warning "pointless comparison of unsigned integer with zero" - // And also a rank 1 layout cannot overflow - if constexpr ( Extents::rank() > 1 ) { +check_extents_and_left_padding_representability( + const Extents &exts, [[maybe_unused]] size_t dynamic_padding_value) { + using MDSPAN_IMPL_STANDARD_NAMESPACE::detail:: + check_mul_result_is_nonnegative_and_representable; + + // get rid of NVCC warning "pointless comparison of unsigned integer with + // zero" And also a rank 1 layout cannot overflow + if constexpr (Extents::rank() > 1) { auto prod = static_cast(dynamic_padding_value); for (size_t i = 1; i < Extents::rank(); ++i) { if (!check_mul_result_is_nonnegative_and_representable( @@ -240,22 +244,26 @@ check_extents_and_left_padding_representability(const Extents &exts, template MDSPAN_INLINE_FUNCTION constexpr bool check_static_extents_and_right_padding_representability() { - using MDSPAN_IMPL_STANDARD_NAMESPACE::detail::check_mul_result_is_nonnegative_and_representable; - - // We cannot check statically for sure if the product of the extents and padding value - // are representable if we have dynamic values -- this can only be checked by a precondition - // We can check if the product of only the static extents and potentially the padding value (if it is static) - // is representable though... - // We already checked that StaticPaddingValue is representable by index_type - - // get rid of NVCC warning "pointless comparison of unsigned integer with zero" - // And also a rank 1 layout cannot overflow - if constexpr ( Extents::rank() > 1 ) { - auto prod = (StaticPaddingValue != dynamic_extent) ? static_cast< CheckType >(StaticPaddingValue) : CheckType(1); + using MDSPAN_IMPL_STANDARD_NAMESPACE::detail:: + check_mul_result_is_nonnegative_and_representable; + + // We cannot check statically for sure if the product of the extents and + // padding value are representable if we have dynamic values -- this can only + // be checked by a precondition We can check if the product of only the static + // extents and potentially the padding value (if it is static) is + // representable though... We already checked that StaticPaddingValue is + // representable by index_type + + // get rid of NVCC warning "pointless comparison of unsigned integer with + // zero" And also a rank 1 layout cannot overflow + if constexpr (Extents::rank() > 1) { + auto prod = (StaticPaddingValue != dynamic_extent) + ? static_cast(StaticPaddingValue) + : CheckType(1); for (size_t i = 0; i < Extents::rank() - 1; ++i) { - if (Extents::static_extent(i) == dynamic_extent) - continue; - if (!check_mul_result_is_nonnegative_and_representable(prod, static_cast< CheckType >(Extents::static_extent(i)))) + if (Extents::static_extent(i) == dynamic_extent) continue; + if (!check_mul_result_is_nonnegative_and_representable( + prod, static_cast(Extents::static_extent(i)))) return false; prod *= Extents::static_extent(i); } @@ -266,16 +274,18 @@ check_static_extents_and_right_padding_representability() { template MDSPAN_INLINE_FUNCTION constexpr bool -check_extents_and_right_padding_representability(const Extents &exts, - [[maybe_unused]] size_t dynamic_padding_value) { - using MDSPAN_IMPL_STANDARD_NAMESPACE::detail::check_mul_result_is_nonnegative_and_representable; - - // get rid of NVCC warning "pointless comparison of unsigned integer with zero" - // And also a rank 1 layout cannot overflow - if constexpr ( Extents::rank() > 1 ) { +check_extents_and_right_padding_representability( + const Extents &exts, [[maybe_unused]] size_t dynamic_padding_value) { + using MDSPAN_IMPL_STANDARD_NAMESPACE::detail:: + check_mul_result_is_nonnegative_and_representable; + + // get rid of NVCC warning "pointless comparison of unsigned integer with + // zero" And also a rank 1 layout cannot overflow + if constexpr (Extents::rank() > 1) { auto prod = static_cast(dynamic_padding_value); for (size_t i = 0; i < Extents::rank() - 1; ++i) { - if (!check_mul_result_is_nonnegative_and_representable(prod, static_cast< CheckType >(exts.extent(i)))) + if (!check_mul_result_is_nonnegative_and_representable( + prod, static_cast(exts.extent(i)))) return false; prod *= exts.extent(i); } @@ -283,60 +293,76 @@ check_extents_and_right_padding_representability(const Extents &exts, return true; } -} // namespace detail +} // namespace detail template template class layout_left_padded::mapping { -public: + 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; + 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), + 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"); - static_assert(detail::check_static_extents_representability(), "The size of the muiltidimensional index space given by the extents must be representable as a value of index_type"); - static_assert((padding_value == dynamic_extent) || MDSPAN_IMPL_STANDARD_NAMESPACE::detail::in_range(padding_value), "padding_value must be representable as a value of type index_type"); - - 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(); - - static_assert(detail::check_static_extents_and_left_padding_representability() - && detail::check_static_extents_and_left_padding_representability(), - "the product of static_padding_stride and static extents 1 through rank must be representable as a value of type size_t and index_type"); + static_assert(detail::check_static_extents_representability(), + "The size of the muiltidimensional index space given by the " + "extents must be representable as a value of index_type"); + static_assert( + (padding_value == dynamic_extent) || + MDSPAN_IMPL_STANDARD_NAMESPACE::detail::in_range( + padding_value), + "padding_value must be representable as a value of type index_type"); + + using padded_stride_type = + detail::padded_extent; + + static constexpr size_t static_padding_stride = + padded_stride_type::static_value(); + + static_assert( + detail::check_static_extents_and_left_padding_representability< + index_type, static_padding_stride, extents_type>() && + detail::check_static_extents_and_left_padding_representability< + size_t, static_padding_stride, extents_type>(), + "the product of static_padding_stride and static extents 1 through rank " + "must be representable as a value of type size_t and index_type"); typename padded_stride_type::static_array_type padded_stride = {}; - extents_type exts = {}; + extents_type exts = {}; - MDSPAN_INLINE_FUNCTION constexpr index_type - compute_offset(std::index_sequence<>) const { + 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 { + 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 { + 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 @@ -350,26 +376,26 @@ class layout_left_padded::mapping { return res; } -public: + public: #if !MDSPAN_HAS_CXX_20 || defined(__NVCC__) MDSPAN_INLINE_FUNCTION - constexpr mapping() - : mapping(extents_type{}) - {} + constexpr mapping() : mapping(extents_type{}) {} #else MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr mapping() - requires(static_padding_stride != dynamic_extent) = default; + requires(static_padding_stride != dynamic_extent) + = default; MDSPAN_INLINE_FUNCTION constexpr mapping() requires(static_padding_stride == dynamic_extent) - : mapping(extents_type{}) - {} + : 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; + 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. @@ -377,9 +403,8 @@ class layout_left_padded::mapping { * \param ext the given extents */ MDSPAN_INLINE_FUNCTION - constexpr mapping(const extents_type& ext) - : padded_stride(padded_stride_type::init_padding(ext)), exts(ext) - { + constexpr mapping(const extents_type &ext) + : padded_stride(padded_stride_type::init_padding(ext)), exts(ext) { MDSPAN_IMPL_PRECONDITION(detail::check_extents_representability(ext)); MDSPAN_IMPL_PRECONDITION( detail::check_extents_and_left_padding_representability( @@ -387,26 +412,28 @@ class layout_left_padded::mapping { } /** - * Initializes the mapping with the given extents and the specified padding value. + * 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` + * 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 - && std::is_nothrow_constructible_v - ) - ) + class Size, + /* requires */ (std::is_convertible_v + &&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))); + : 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))); MDSPAN_IMPL_PRECONDITION(detail::check_extents_representability(ext)); MDSPAN_IMPL_PRECONDITION( detail::check_extents_and_left_padding_representability( @@ -526,13 +553,13 @@ class layout_left_padded::mapping { exts, padded_stride.value(0))); } - MDSPAN_INLINE_FUNCTION constexpr const extents_type & - extents() const noexcept { + MDSPAN_INLINE_FUNCTION constexpr const extents_type &extents() + const noexcept { return exts; } - constexpr std::array - strides() const noexcept { + constexpr std::array strides() + const noexcept { if constexpr (extents_type::rank() == 0) { return {}; } else if constexpr (extents_type::rank() == 1) { @@ -552,8 +579,8 @@ class layout_left_padded::mapping { } } - MDSPAN_INLINE_FUNCTION constexpr index_type - required_span_size() const noexcept { + 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) { @@ -580,12 +607,12 @@ class layout_left_padded::mapping { /* requires */ (sizeof...(Indices) == extents_type::rank() && (::MDSPAN_IMPL_STANDARD_NAMESPACE::detail:: are_valid_indices()))) - MDSPAN_INLINE_FUNCTION constexpr index_type - operator()(Indices... idxs) const noexcept { + MDSPAN_INLINE_FUNCTION constexpr index_type operator()( + Indices... idxs) const noexcept { #if !defined(NDEBUG) ::MDSPAN_IMPL_STANDARD_NAMESPACE::detail::check_all_indices(this->extents(), idxs...); -#endif // ! NDEBUG +#endif // ! NDEBUG return compute_offset(std::index_sequence_for{}, idxs...); } @@ -616,12 +643,10 @@ class layout_left_padded::mapping { MDSPAN_INLINE_FUNCTION constexpr index_type stride(rank_type r) const noexcept { assert(r < extents_type::rank()); - if (r == 0) - return index_type(1); + 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); + for (rank_type k = 1; k < r; k++) value *= exts.extent(k); return value; } @@ -640,8 +665,8 @@ class layout_left_padded::mapping { class Mapping, /* requires */ (detail::is_layout_left_padded_mapping::value && (Mapping::extents_type::rank() == extents_type::rank()))) - MDSPAN_INLINE_FUNCTION friend constexpr bool - operator==(const mapping &left, const Mapping &right) noexcept { + 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 @@ -664,78 +689,92 @@ class layout_left_padded::mapping { class Mapping, /* requires */ (detail::is_layout_left_padded_mapping::value && (Mapping::extents_type::rank() == extents_type::rank()))) - MDSPAN_INLINE_FUNCTION friend constexpr bool - operator!=(const mapping &left, const Mapping &right) noexcept { + 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...); - } + // [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: + 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; + 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"); - static_assert(detail::check_static_extents_representability(), "The size of the muiltidimensional index space given by the extents must be representable as a value of index_type"); - static_assert((padding_value == dynamic_extent) || MDSPAN_IMPL_STANDARD_NAMESPACE::detail::in_range(padding_value), "padding_value must be representable as a value of type index_type"); - - - 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(); - - static_assert(detail::check_static_extents_and_right_padding_representability() - && detail::check_static_extents_and_right_padding_representability(), - "the product of static_padding_stride and static extents 1 through rank must be representable as a value of type size_t and index_type"); + 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"); + static_assert(detail::check_static_extents_representability(), + "The size of the muiltidimensional index space given by the " + "extents must be representable as a value of index_type"); + static_assert( + (padding_value == dynamic_extent) || + MDSPAN_IMPL_STANDARD_NAMESPACE::detail::in_range( + padding_value), + "padding_value must be representable as a value of type index_type"); + + using padded_stride_type = + detail::padded_extent; + static constexpr size_t static_padding_stride = + padded_stride_type::static_value(); + + static_assert( + detail::check_static_extents_and_right_padding_representability< + index_type, static_padding_stride, extents_type>() && + detail::check_static_extents_and_right_padding_representability< + size_t, static_padding_stride, extents_type>(), + "the product of static_padding_stride and static extents 1 through rank " + "must be representable as a value of type size_t and index_type"); typename padded_stride_type::static_array_type padded_stride = {}; - extents_type exts = {}; + extents_type exts = {}; - MDSPAN_INLINE_FUNCTION constexpr index_type - compute_offset(std::index_sequence<>) const { + 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 { + 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 { + 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; @@ -747,26 +786,26 @@ class layout_right_padded::mapping { return res; } -public: + public: #if !MDSPAN_HAS_CXX_20 || defined(__NVCC__) MDSPAN_INLINE_FUNCTION - constexpr mapping() - : mapping(extents_type{}) - {} + constexpr mapping() : mapping(extents_type{}) {} #else MDSPAN_INLINE_FUNCTION_DEFAULTED - constexpr mapping() - requires(static_padding_stride != dynamic_extent) = default; + constexpr mapping() + requires(static_padding_stride != dynamic_extent) + = default; MDSPAN_INLINE_FUNCTION - constexpr mapping() + constexpr mapping() requires(static_padding_stride == dynamic_extent) - : mapping(extents_type{}) - {} + : 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; + 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. @@ -783,27 +822,28 @@ class layout_right_padded::mapping { } /** - * Initializes the mapping with the given extents and the specified padding value. + * 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` + * 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 - && std::is_nothrow_constructible_v - ) - ) + /* requires */ (std::is_convertible_v + &&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))), + : 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))); + (static_cast(padding_value) == + static_cast(dynamic_padding_value))); MDSPAN_IMPL_PRECONDITION(detail::check_extents_representability(ext)); MDSPAN_IMPL_PRECONDITION( detail::check_extents_and_right_padding_representability( @@ -813,9 +853,12 @@ class layout_right_padded::mapping { /** * 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)` + * 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, @@ -920,13 +963,13 @@ class layout_right_padded::mapping { exts, padded_stride.value(0))); } - MDSPAN_INLINE_FUNCTION constexpr const extents_type & - extents() const noexcept { + MDSPAN_INLINE_FUNCTION constexpr const extents_type &extents() + const noexcept { return exts; } - constexpr std::array - strides() const noexcept { + constexpr std::array strides() + const noexcept { if constexpr (extents_type::rank() == 0) { return {}; } else if constexpr (extents_type::rank() == 1) { @@ -945,8 +988,8 @@ class layout_right_padded::mapping { } } - MDSPAN_INLINE_FUNCTION constexpr index_type - required_span_size() const noexcept { + 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) { @@ -956,7 +999,9 @@ class layout_right_padded::mapping { for (rank_type r = 0; r < extent_to_pad_idx; ++r) { value *= exts.extent(r); } - return value == 0 ? 0 : value + exts.extent(extent_to_pad_idx) - padded_stride.value(0); + return value == 0 ? 0 + : value + exts.extent(extent_to_pad_idx) - + padded_stride.value(0); } } @@ -973,8 +1018,8 @@ class layout_right_padded::mapping { /* requires */ (sizeof...(Indices) == extents_type::rank() && (::MDSPAN_IMPL_STANDARD_NAMESPACE::detail:: are_valid_indices()))) - MDSPAN_INLINE_FUNCTION constexpr index_type - operator()(Indices... idxs) const noexcept { + MDSPAN_INLINE_FUNCTION constexpr index_type operator()( + Indices... idxs) const noexcept { return compute_offset(std::index_sequence_for{}, idxs...); } @@ -1002,11 +1047,10 @@ class layout_right_padded::mapping { return true; } - MDSPAN_INLINE_FUNCTION constexpr index_type - stride(rank_type r) const noexcept { + 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); + 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--) @@ -1029,8 +1073,8 @@ class layout_right_padded::mapping { class Mapping, /* requires */ (detail::is_layout_right_padded_mapping::value && (Mapping::extents_type::rank() == extents_type::rank()))) - MDSPAN_INLINE_FUNCTION friend constexpr bool - operator==(const mapping &left, const Mapping &right) noexcept { + 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 @@ -1053,23 +1097,21 @@ class layout_right_padded::mapping { class Mapping, /* requires */ (detail::is_layout_right_padded_mapping::value && (Mapping::extents_type::rank() == extents_type::rank()))) - MDSPAN_INLINE_FUNCTION friend constexpr bool - operator!=(const mapping &left, const Mapping &right) noexcept { + 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...); - } + // [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...); + } }; -} +} // namespace MDSPAN_IMPL_STANDARD_NAMESPACE diff --git a/include/mdspan/impl/layout_padded_fwd.hpp b/include/mdspan/impl/layout_padded_fwd.hpp index c633e63c..18aca55f 100644 --- a/include/mdspan/impl/layout_padded_fwd.hpp +++ b/include/mdspan/impl/layout_padded_fwd.hpp @@ -22,21 +22,21 @@ struct layout_right_padded { }; namespace detail { -// The layout_padded_constants structs are only useful if rank > 1, otherwise they may wrap +// 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> -{ +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> -{ +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; @@ -46,78 +46,95 @@ template struct is_layout_left_padded : std::false_type {}; template -struct is_layout_left_padded> : std::true_type {}; +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::template mapping>::value>> +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 {}; +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::template mapping>::value>> +struct is_layout_right_padded_mapping< + Mapping, + std::enable_if_t:: + template mapping>::value>> : std::true_type {}; - template -MDSPAN_INLINE_FUNCTION -constexpr void check_padded_layout_converting_constructor_mandates(MDSPAN_IMPL_STANDARD_NAMESPACE::detail::with_rank<0>) {} +MDSPAN_INLINE_FUNCTION constexpr void +check_padded_layout_converting_constructor_mandates( + MDSPAN_IMPL_STANDARD_NAMESPACE::detail::with_rank<0>) {} template -MDSPAN_INLINE_FUNCTION -constexpr void check_padded_layout_converting_constructor_mandates(MDSPAN_IMPL_STANDARD_NAMESPACE::detail::with_rank<1>) {} +MDSPAN_INLINE_FUNCTION constexpr void +check_padded_layout_converting_constructor_mandates( + MDSPAN_IMPL_STANDARD_NAMESPACE::detail::with_rank<1>) {} template -MDSPAN_INLINE_FUNCTION -constexpr void check_padded_layout_converting_constructor_mandates(MDSPAN_IMPL_STANDARD_NAMESPACE::detail::with_rank) -{ - using extents_type = typename PaddedLayoutMappingType::extents_type; +MDSPAN_INLINE_FUNCTION 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 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), - ""); + (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 -MDSPAN_INLINE_FUNCTION -constexpr void check_padded_layout_converting_constructor_preconditions(MDSPAN_IMPL_STANDARD_NAMESPACE::detail::with_rank<0>, - const OtherMapping&) {} +MDSPAN_INLINE_FUNCTION constexpr void +check_padded_layout_converting_constructor_preconditions( + MDSPAN_IMPL_STANDARD_NAMESPACE::detail::with_rank<0>, + const OtherMapping &) {} template -MDSPAN_INLINE_FUNCTION -constexpr void check_padded_layout_converting_constructor_preconditions(MDSPAN_IMPL_STANDARD_NAMESPACE::detail::with_rank<1>, - const OtherMapping&) {} +MDSPAN_INLINE_FUNCTION constexpr void +check_padded_layout_converting_constructor_preconditions( + MDSPAN_IMPL_STANDARD_NAMESPACE::detail::with_rank<1>, + const OtherMapping &) {} template -MDSPAN_INLINE_FUNCTION -constexpr void check_padded_layout_converting_constructor_preconditions(MDSPAN_IMPL_STANDARD_NAMESPACE::detail::with_rank, - const OtherMapping &other_mapping) { +MDSPAN_INLINE_FUNCTION 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)); + 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)); } - -} -} +} // namespace detail +} // namespace MDSPAN_IMPL_STANDARD_NAMESPACE diff --git a/include/mdspan/impl/layout_right.hpp b/include/mdspan/impl/layout_right.hpp index 73c92f3e..897affb9 100644 --- a/include/mdspan/impl/layout_right.hpp +++ b/include/mdspan/impl/layout_right.hpp @@ -17,235 +17,241 @@ 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::impl_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_IMPL_HOST_DEVICE - constexpr index_type compute_offset( - index_type offset, rank_count, const I& i, Indices... idx) const { - return compute_offset(offset * m_extents.extent(r) + i,rank_count(), idx...); - } - - template - MDSPAN_IMPL_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_IMPL_HOST_DEVICE - constexpr index_type compute_offset(size_t offset, rank_count) const { - return static_cast(offset); - } - - MDSPAN_IMPL_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_IMPL_HOST_DEVICE - constexpr mapping(extents_type const& exts) noexcept - :m_extents(exts) - { } - - MDSPAN_TEMPLATE_REQUIRES( + 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::impl_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_IMPL_HOST_DEVICE constexpr index_type compute_offset( + index_type offset, rank_count, const I& i, + Indices... idx) const { + return compute_offset(offset * m_extents.extent(r) + i, + rank_count(), idx...); + } + + template + MDSPAN_IMPL_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_IMPL_HOST_DEVICE + constexpr index_type compute_offset( + size_t offset, + rank_count) const { + return static_cast(offset); + } + + MDSPAN_IMPL_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_IMPL_HOST_DEVICE + constexpr mapping(extents_type const& exts) noexcept : m_extents(exts) {} + + MDSPAN_TEMPLATE_REQUIRES( class OtherExtents, - /* requires */ ( - MDSPAN_IMPL_TRAIT(std::is_constructible, extents_type, OtherExtents) - ) - ) - MDSPAN_CONDITIONAL_EXPLICIT((!std::is_convertible::value)) // needs two () due to comma - MDSPAN_INLINE_FUNCTION MDSPAN_IMPL_CONSTEXPR_14 - mapping(mapping const& other) noexcept // NOLINT(google-explicit-constructor) - :m_extents(other.extents()) - { - /* - * TODO: check precondition - * other.required_span_size() is a representable value of type index_type - */ - } - - MDSPAN_TEMPLATE_REQUIRES( + /* requires */ (MDSPAN_IMPL_TRAIT(std::is_constructible, extents_type, + OtherExtents))) + MDSPAN_CONDITIONAL_EXPLICIT( + (!std::is_convertible::value)) // needs two () due to comma + MDSPAN_INLINE_FUNCTION MDSPAN_IMPL_CONSTEXPR_14 + mapping(mapping const& + other) noexcept // NOLINT(google-explicit-constructor) + : m_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_IMPL_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_IMPL_CONSTEXPR_14 - mapping(layout_left::mapping const& other) noexcept // NOLINT(google-explicit-constructor) - :m_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. + /* requires */ (MDSPAN_IMPL_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_IMPL_CONSTEXPR_14 + mapping(layout_left::mapping const& + other) noexcept // NOLINT(google-explicit-constructor) + : m_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 */ (detail::is_layout_right_padded_mapping::value - &&std::is_constructible_v< - extents_type, typename Mapping::extents_type>)) - MDSPAN_CONDITIONAL_EXPLICIT( - (!std::is_convertible_v)) - MDSPAN_INLINE_FUNCTION constexpr mapping(const Mapping &other) noexcept - : m_extents(other.extents()) { - detail::check_padded_layout_converting_constructor_mandates( - detail::with_rank{}); - detail::check_padded_layout_converting_constructor_preconditions< - extents_type>(detail::with_rank{}, other); - } + MDSPAN_TEMPLATE_REQUIRES( + class Mapping, + /* requires */ (detail::is_layout_right_padded_mapping::value&& + std::is_constructible_v< + extents_type, typename Mapping::extents_type>)) + MDSPAN_CONDITIONAL_EXPLICIT( + (!std::is_convertible_v)) + MDSPAN_INLINE_FUNCTION constexpr mapping(const Mapping& other) noexcept + : m_extents(other.extents()) { + detail::check_padded_layout_converting_constructor_mandates( + detail::with_rank{}); + detail::check_padded_layout_converting_constructor_preconditions< + extents_type>(detail::with_rank{}, other); + } #endif - MDSPAN_TEMPLATE_REQUIRES( + MDSPAN_TEMPLATE_REQUIRES( class OtherExtents, - /* requires */ ( - MDSPAN_IMPL_TRAIT(std::is_constructible, extents_type, OtherExtents) - ) - ) - MDSPAN_CONDITIONAL_EXPLICIT((extents_type::rank() > 0)) - MDSPAN_INLINE_FUNCTION MDSPAN_IMPL_CONSTEXPR_14 - mapping(layout_stride::mapping const& other) noexcept // NOLINT(google-explicit-constructor) - :m_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{}, m_extents, other); - } - - MDSPAN_INLINE_FUNCTION_DEFAULTED MDSPAN_IMPL_CONSTEXPR_14_DEFAULTED mapping& operator=(mapping const&) noexcept = default; - - MDSPAN_INLINE_FUNCTION - constexpr const extents_type& extents() const noexcept { - return m_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*=m_extents.extent(r); - return value; - } - - //-------------------------------------------------------------------------------- - - MDSPAN_TEMPLATE_REQUIRES( - class ... Indices, - /* requires */ ( - (sizeof...(Indices) == extents_type::rank()) && - (detail::are_valid_indices()) - ) - ) - MDSPAN_IMPL_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)...); - } - + /* requires */ (MDSPAN_IMPL_TRAIT(std::is_constructible, extents_type, + OtherExtents))) + MDSPAN_CONDITIONAL_EXPLICIT((extents_type::rank() > 0)) + MDSPAN_INLINE_FUNCTION MDSPAN_IMPL_CONSTEXPR_14 + mapping(layout_stride::mapping const& + other) noexcept // NOLINT(google-explicit-constructor) + : m_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{}, m_extents, other); + } + + MDSPAN_INLINE_FUNCTION_DEFAULTED MDSPAN_IMPL_CONSTEXPR_14_DEFAULTED mapping& + operator=(mapping const&) noexcept = default; + + MDSPAN_INLINE_FUNCTION + constexpr const extents_type& extents() const noexcept { return m_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 *= m_extents.extent(r); + return value; + } + + //-------------------------------------------------------------------------------- + + MDSPAN_TEMPLATE_REQUIRES( + class... Indices, + /* requires */ ((sizeof...(Indices) == extents_type::rank()) && + (detail::are_valid_indices()))) + MDSPAN_IMPL_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)...); + } + + // clang-format off 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; } + // clang-format on - MDSPAN_INLINE_FUNCTION - constexpr index_type stride(rank_type i) const noexcept + MDSPAN_INLINE_FUNCTION + constexpr index_type stride(rank_type i) const noexcept #if MDSPAN_HAS_CXX_20 - requires ( Extents::rank() > 0 ) + requires(Extents::rank() > 0) #endif - { - index_type value = 1; - for(rank_type r=extents_type::rank()-1; r>i; r--) value*=m_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 + { + index_type value = 1; + for (rank_type r = extents_type::rank() - 1; r > i; r--) + value *= m_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(); - } + 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 - MDSPAN_INLINE_FUNCTION - constexpr index_type impl_get_stride(MDSPAN_IMPL_STANDARD_NAMESPACE::extents,std::integer_sequence) const { - return MDSPAN_IMPL_FOLD_TIMES_RIGHT((Idx>N? m_extents.template extent():1),1); - } - template - MDSPAN_INLINE_FUNCTION - constexpr index_type impl_stide() const noexcept { - return impl_get_stride(m_extents, std::make_index_sequence()); - } - -private: - MDSPAN_IMPL_NO_UNIQUE_ADDRESS extents_type m_extents{}; - - // [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...); - } + // Not really public, but currently needed to implement fully constexpr + // useable submdspan: + template + MDSPAN_INLINE_FUNCTION constexpr index_type impl_get_stride( + MDSPAN_IMPL_STANDARD_NAMESPACE::extents, + std::integer_sequence) const { + return MDSPAN_IMPL_FOLD_TIMES_RIGHT( + (Idx > N ? m_extents.template extent() : 1), 1); + } + template + MDSPAN_INLINE_FUNCTION constexpr index_type impl_stide() const noexcept { + return impl_get_stride(m_extents, + std::make_index_sequence()); + } + + private: + MDSPAN_IMPL_NO_UNIQUE_ADDRESS extents_type m_extents{}; + + // [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 namespace MDSPAN_IMPL_STANDARD_NAMESPACE +} // end namespace MDSPAN_IMPL_STANDARD_NAMESPACE diff --git a/include/mdspan/impl/layout_stride.hpp b/include/mdspan/impl/layout_stride.hpp index 3b50e3a5..846d9ded 100644 --- a/include/mdspan/impl/layout_stride.hpp +++ b/include/mdspan/impl/layout_stride.hpp @@ -14,7 +14,7 @@ #endif #if !defined(MDSPAN_IMPL_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) -# include "no_unique_address.hpp" +#include "no_unique_address.hpp" #endif #include @@ -24,106 +24,115 @@ #ifdef __cpp_lib_span #include #endif -#if defined(MDSPAN_IMPL_USE_CONCEPTS) && MDSPAN_HAS_CXX_20 && defined(__cpp_lib_concepts) -# include +#if defined(MDSPAN_IMPL_USE_CONCEPTS) && MDSPAN_HAS_CXX_20 && \ + defined(__cpp_lib_concepts) +#include #endif namespace MDSPAN_IMPL_STANDARD_NAMESPACE { struct layout_left { - template + template class mapping; }; struct layout_right { - template + template class mapping; }; namespace detail { #if MDSPAN_HAS_CXX_17 - using std::void_t; +using std::void_t; #else - template using void_t = void; +template +using void_t = void; #endif - // FIXME GCC <= 12: workaround gcc-12 bug that shows up in Kokkos; compilation fails when Mapping doesn't have - // extents_type. Normally this should just be a substitution failure, but causes an error with GCC <= 12 - // FIXME MSVC: I guess MSVC has a similar issue when it hits Layout::template mapping - template - struct is_mapping_of_impl : std::false_type {}; - - // FIXME GCC <= 12: We can't just do a conjunction of the two conditions, because the affected GCC versions seem to not - // short-circuit when resolving the substitution of Mapping - template - struct is_mapping_of_impl, void_t< typename Layout::template mapping >> - : std::is_same, Mapping> - {}; - - template - constexpr bool is_mapping_of = - is_mapping_of_impl::value; +// FIXME GCC <= 12: workaround gcc-12 bug that shows up in Kokkos; compilation +// fails when Mapping doesn't have extents_type. Normally this should just be a +// substitution failure, but causes an error with GCC <= 12 +// FIXME MSVC: I guess MSVC has a similar issue when it hits Layout::template +// mapping +template +struct is_mapping_of_impl : std::false_type {}; + +// FIXME GCC <= 12: We can't just do a conjunction of the two conditions, +// because the affected GCC versions seem to not short-circuit when resolving +// the substitution of Mapping +template +struct is_mapping_of_impl< + Mapping, Layout, void_t, + void_t>> + : std::is_same< + typename Layout::template mapping, + Mapping> {}; + +template +constexpr bool is_mapping_of = is_mapping_of_impl::value; #if defined(MDSPAN_IMPL_USE_CONCEPTS) && MDSPAN_HAS_CXX_20 -# if !defined(__cpp_lib_concepts) - namespace internal { - namespace detail { - template - concept same_as = std::is_same_v; - } // namespace detail - template - concept same_as = detail::same_as && detail::same_as; - } // namespace internal -# endif - - template - concept layout_mapping_alike = requires { - requires impl_is_extents::value; +#if !defined(__cpp_lib_concepts) +namespace internal { +namespace detail { +template +concept same_as = std::is_same_v; +} // namespace detail +template +concept same_as = detail::same_as && detail::same_as; +} // namespace internal +#endif + +template +concept layout_mapping_alike = requires { + requires impl_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; + { 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; + { 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; - }; + std::bool_constant::value; + std::bool_constant::value; + std::bool_constant::value; +}; #endif -} // namespace detail +} // namespace detail struct layout_stride { template class mapping #if !defined(MDSPAN_IMPL_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) - : private detail::no_unique_address_emulation< - detail::impl_compressed_pair< - Extents, - detail::possibly_empty_array - > - > + : private detail::no_unique_address_emulation< + detail::impl_compressed_pair< + Extents, detail::possibly_empty_array< + typename Extents::index_type, Extents::rank()>>> #endif { - public: + 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; + 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`. + // This could be a `requires`, but I think it's better and clearer as a + // `static_assert`. static_assert(detail::impl_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: + 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::impl_compressed_pair; + using strides_storage_t = + detail::possibly_empty_array; + using member_pair_t = + detail::impl_compressed_pair; #if defined(MDSPAN_IMPL_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) MDSPAN_IMPL_NO_UNIQUE_ADDRESS member_pair_t m_members; @@ -148,10 +157,12 @@ struct layout_stride { #endif } - template - MDSPAN_IMPL_HOST_DEVICE - constexpr index_type get_size(::MDSPAN_IMPL_STANDARD_NAMESPACE::extents,std::integer_sequence) const { - return MDSPAN_IMPL_FOLD_TIMES_RIGHT( static_cast(extents().extent(Idx)), 1 ); + template + MDSPAN_IMPL_HOST_DEVICE constexpr index_type get_size( + ::MDSPAN_IMPL_STANDARD_NAMESPACE::extents, + std::integer_sequence) const { + return MDSPAN_IMPL_FOLD_TIMES_RIGHT( + static_cast(extents().extent(Idx)), 1); } //---------------------------------------------------------------------------- @@ -161,90 +172,112 @@ struct layout_stride { //---------------------------------------------------------------------------- - // Workaround for non-deducibility of the index sequence template parameter if it's given at the top level + // 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> - { + 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; + MDSPAN_INLINE_FUNCTION static constexpr bool _eq_impl( + mapping const& self, mapping const& other) noexcept { + using common_t = + std::common_type_t; + // clang-format off return MDSPAN_IMPL_FOLD_AND((static_cast(self.stride(Idxs)) == static_cast(other.stride(Idxs))) /* && ... */) && MDSPAN_IMPL_FOLD_AND((static_cast(self.extents().extent(Idxs)) == static_cast(other.extents().extent(Idxs))) /* || ... */); + // clang-format on } template - MDSPAN_INLINE_FUNCTION - static constexpr bool _not_eq_impl(mapping const& self, mapping const& other) noexcept { - using common_t = std::common_type_t; + MDSPAN_INLINE_FUNCTION static constexpr bool _not_eq_impl( + mapping const& self, mapping const& other) noexcept { + using common_t = + std::common_type_t; + // clang-format off return MDSPAN_IMPL_FOLD_OR((static_cast(self.stride(Idxs)) != static_cast(other.stride(Idxs))) /* || ... */) || MDSPAN_IMPL_FOLD_OR((static_cast(self.extents().extent(Idxs)) != static_cast(other.extents().extent(Idxs))) /* || ... */); + // clang-format on } template - MDSPAN_FORCE_INLINE_FUNCTION - static constexpr size_t _call_op_impl(mapping const& self, Integral... idxs) noexcept { - return MDSPAN_IMPL_FOLD_PLUS_RIGHT((idxs * self.stride(Idxs)), /* + ... + */ 0); + MDSPAN_FORCE_INLINE_FUNCTION static constexpr size_t _call_op_impl( + mapping const& self, Integral... idxs) noexcept { + return MDSPAN_IMPL_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 deduction_workaround_impl::_call_op_impl(self, (self.extents().template extent() - 1)...) + 1; + 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 deduction_workaround_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) { + 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) { + static constexpr const strides_storage_t& fill_strides( + const strides_storage_t& s) { return s; } - template - static constexpr const strides_storage_t fill_strides(const std::array& s) { + template + 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, - (MDSPAN_IMPL_TRAIT(std::is_convertible, IntegralType, typename extents_type::index_type)) - ) + class IntegralType, + (MDSPAN_IMPL_TRAIT(std::is_convertible, IntegralType, + typename extents_type::index_type))) MDSPAN_INLINE_FUNCTION // Need to avoid zero length c-array - static constexpr const strides_storage_t fill_strides(mdspan_non_standard_tag, const IntegralType (&s)[extents_type::rank()>0?extents_type::rank():1]) { + 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 - static constexpr const strides_storage_t fill_strides(const std::span& s) { + template + 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) { + 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 size_t return_zero() { + return 0; + } - template - MDSPAN_INLINE_FUNCTION - static constexpr typename Mapping::index_type - offset(const Mapping& m) { return m(return_zero()...); } + 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 deduction_workaround_impl = deduction_workaround>; + // Can't use defaulted parameter in the deduction_workaround template + // because of a bug in MSVC warning C4348. + using deduction_workaround_impl = + deduction_workaround>; MDSPAN_FUNCTION static constexpr strides_storage_t strides_storage(detail::with_rank<0>) { @@ -252,13 +285,13 @@ struct layout_stride { } template - MDSPAN_FUNCTION - static constexpr strides_storage_t strides_storage(detail::with_rank) { + MDSPAN_FUNCTION 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--) { + for (int r = static_cast(extents_type::rank() - 1); r >= 0; r--) { s[r] = stride; stride *= e.extent(r); } @@ -269,43 +302,50 @@ struct layout_stride { //---------------------------------------------------------------------------- #if defined(MDSPAN_IMPL_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) - MDSPAN_INLINE_FUNCTION constexpr explicit - mapping(member_pair_t&& m) : m_members(::std::move(m)) {} + MDSPAN_INLINE_FUNCTION constexpr explicit mapping(member_pair_t&& m) + : m_members(::std::move(m)) {} #else - MDSPAN_INLINE_FUNCTION constexpr explicit - mapping(base_t&& __b) : base_t(::std::move(__b)) {} + MDSPAN_INLINE_FUNCTION constexpr explicit mapping(base_t&& __b) + : base_t(::std::move(__b)) {} #endif - public: - + public: //-------------------------------------------------------------------------------- MDSPAN_INLINE_FUNCTION constexpr mapping() noexcept #if defined(MDSPAN_IMPL_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) : m_members{ #else - : base_t(base_t{member_pair_t( + : base_t(base_t { + member_pair_t( #endif extents_type(), strides_storage_t(strides_storage(detail::with_rank{})) #if defined(MDSPAN_IMPL_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) } #else - )}) + ) + }) #endif - {} + { + } - MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr mapping(mapping const&) noexcept = default; + 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_IMPL_TRAIT(std::is_convertible, const std::remove_const_t&, typename Extents::index_type) && - MDSPAN_IMPL_TRAIT(std::is_nothrow_constructible, typename Extents::index_type, const std::remove_const_t&) - ) - ) + 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_IMPL_TRAIT(std::is_convertible, + const std::remove_const_t&, + typename Extents::index_type) && + MDSPAN_IMPL_TRAIT(std::is_nothrow_constructible, + typename Extents::index_type, + const std::remove_const_t&))) constexpr mapping( extents_type const& e, @@ -314,34 +354,42 @@ struct layout_stride { #if defined(MDSPAN_IMPL_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) : m_members{ #else - : base_t(base_t{member_pair_t( + : base_t(base_t { + member_pair_t( #endif e, strides_storage_t(deduction_workaround_impl::fill_strides(s)) #if defined(MDSPAN_IMPL_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. + * - 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_IMPL_TRAIT(std::is_convertible, const std::remove_const_t&, typename Extents::index_type) && - MDSPAN_IMPL_TRAIT(std::is_nothrow_constructible, typename Extents::index_type, const std::remove_const_t&) - ) - ) + 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_IMPL_TRAIT(std::is_convertible, + const std::remove_const_t&, + typename Extents::index_type) && + MDSPAN_IMPL_TRAIT(std::is_nothrow_constructible, + typename Extents::index_type, + const std::remove_const_t&))) MDSPAN_INLINE_FUNCTION constexpr mapping( @@ -353,35 +401,43 @@ struct layout_stride { #if defined(MDSPAN_IMPL_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) : m_members{ #else - : base_t(base_t{member_pair_t( + : base_t(base_t { + member_pair_t( #endif e, strides_storage_t(deduction_workaround_impl::fill_strides(mdspan_non_standard_tag(), s)) #if defined(MDSPAN_IMPL_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. + * - 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_IMPL_TRAIT(std::is_convertible, const std::remove_const_t&, typename Extents::index_type) && - MDSPAN_IMPL_TRAIT(std::is_nothrow_constructible, typename Extents::index_type, const std::remove_const_t&) - ) - ) + 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_IMPL_TRAIT(std::is_convertible, + const std::remove_const_t&, + typename Extents::index_type) && + MDSPAN_IMPL_TRAIT(std::is_nothrow_constructible, + typename Extents::index_type, + const std::remove_const_t&))) constexpr mapping( extents_type const& e, @@ -390,26 +446,31 @@ struct layout_stride { #if defined(MDSPAN_IMPL_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) : m_members{ #else - : base_t(base_t{member_pair_t( + : base_t(base_t { + member_pair_t( #endif e, strides_storage_t(deduction_workaround_impl::fill_strides(s)) #if defined(MDSPAN_IMPL_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. + * - 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 +#endif // __cpp_lib_span +// clang-format off #if !(defined(MDSPAN_IMPL_USE_CONCEPTS) && MDSPAN_HAS_CXX_20) MDSPAN_TEMPLATE_REQUIRES( class StridedLayoutMapping, @@ -458,13 +519,15 @@ struct layout_stride { * - OFFSET(other) == 0 */ } + // clang-format on //-------------------------------------------------------------------------------- - MDSPAN_INLINE_FUNCTION_DEFAULTED MDSPAN_IMPL_CONSTEXPR_14_DEFAULTED - mapping& operator=(mapping const&) noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED MDSPAN_IMPL_CONSTEXPR_14_DEFAULTED mapping& + operator=(mapping const&) noexcept = default; - MDSPAN_INLINE_FUNCTION constexpr const extents_type& extents() const noexcept { + MDSPAN_INLINE_FUNCTION constexpr const extents_type& extents() + const noexcept { #if defined(MDSPAN_IMPL_USE_ATTRIBUTE_NO_UNIQUE_ADDRESS) return m_members.first(); #else @@ -473,7 +536,8 @@ struct layout_stride { } MDSPAN_INLINE_FUNCTION - constexpr std::array< index_type, extents_type::rank() > strides() const noexcept { + constexpr std::array strides() + const noexcept { return deduction_workaround_impl::return_strides(strides_storage()); } @@ -481,62 +545,65 @@ struct layout_stride { constexpr index_type required_span_size() const noexcept { index_type span_size = 1; // using int here to avoid warning about pointless comparison to 0 - for(int r = 0; r < static_cast(extents_type::rank()); r++) { + for (int r = 0; r < static_cast(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]); + 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()) - ) - ) + 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) +#if !defined(NDEBUG) detail::check_all_indices(this->extents(), idxs...); -#endif // ! NDEBUG - return static_cast(deduction_workaround_impl::_call_op_impl(*this, static_cast(idxs)...)); +#endif // ! NDEBUG + return static_cast(deduction_workaround_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 { + 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_always_strided() noexcept { + return true; + } - MDSPAN_INLINE_FUNCTION static constexpr bool is_unique() noexcept { return true; } + MDSPAN_INLINE_FUNCTION static constexpr bool is_unique() noexcept { + return true; + } - private: + private: MDSPAN_INLINE_FUNCTION - constexpr bool exhaustive_for_nonzero_span_size() const - { - return required_span_size() == get_size(extents(), std::make_index_sequence()); + constexpr bool exhaustive_for_nonzero_span_size() const { + return required_span_size() == + get_size(extents(), + std::make_index_sequence()); } MDSPAN_INLINE_FUNCTION - constexpr bool is_exhaustive_impl(detail::with_rank<0>) const - { + constexpr bool is_exhaustive_impl(detail::with_rank<0>) const { return true; } MDSPAN_INLINE_FUNCTION - constexpr bool is_exhaustive_impl(detail::with_rank<1>) const - { + 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 - MDSPAN_INLINE_FUNCTION - constexpr bool is_exhaustive_impl(detail::with_rank) const - { + MDSPAN_INLINE_FUNCTION constexpr bool is_exhaustive_impl( + detail::with_rank) const { if (required_span_size() != static_cast(0)) { return exhaustive_for_nonzero_span_size(); } @@ -555,12 +622,14 @@ struct layout_stride { return true; } - public: - MDSPAN_INLINE_FUNCTION MDSPAN_IMPL_CONSTEXPR_14 bool is_exhaustive() const noexcept { + public: + MDSPAN_INLINE_FUNCTION MDSPAN_IMPL_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 static constexpr bool is_strided() noexcept { + return true; + } MDSPAN_INLINE_FUNCTION constexpr index_type stride(rank_type r) const noexcept { @@ -569,13 +638,13 @@ struct layout_stride { #if !(defined(MDSPAN_IMPL_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() - ) - ) + class StridedLayoutMapping, + /* requires */ ( + detail::is_mapping_of && + (extents_type::rank() == + StridedLayoutMapping::extents_type::rank()) && + StridedLayoutMapping::is_always_strided())) #else template requires( @@ -585,60 +654,59 @@ struct layout_stride { ) #endif MDSPAN_INLINE_FUNCTION - friend constexpr bool operator==(const mapping& x, const StridedLayoutMapping& y) noexcept { + friend constexpr bool operator==(const mapping& x, + const StridedLayoutMapping& y) noexcept { return (x.extents() == y.extents()) && - (deduction_workaround_impl::offset(y) == static_cast(0)) && - detail::rankwise_equal(detail::with_rank{}, x, y, detail::stride); + (deduction_workaround_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()) - ) - ) + // 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 { + friend constexpr bool operator==( + mapping const& lhs, mapping const& rhs) noexcept { return deduction_workaround_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() - ) - ) + 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 { + 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_TEMPLATE_REQUIRES(class OtherExtents, + /* requires */ ((extents_type::rank() == + OtherExtents::rank()))) MDSPAN_INLINE_FUNCTION - friend constexpr bool operator!=(mapping const& lhs, mapping const& rhs) noexcept { + friend constexpr bool operator!=( + mapping const& lhs, mapping const& rhs) noexcept { return deduction_workaround_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; + // [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) { + template + MDSPAN_INLINE_FUNCTION friend constexpr auto submdspan_mapping( + const mapping& src, SliceSpecifiers... slices) { return src.submdspan_mapping_impl(slices...); } }; @@ -647,19 +715,20 @@ struct layout_stride { namespace detail { template -MDSPAN_INLINE_FUNCTION -constexpr void validate_strides(with_rank<0>, Layout, const Extents&, const Mapping&) -{} +MDSPAN_INLINE_FUNCTION constexpr void validate_strides(with_rank<0>, Layout, + const Extents&, + const Mapping&) {} template -MDSPAN_INLINE_FUNCTION -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."); +MDSPAN_INLINE_FUNCTION 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; @@ -668,12 +737,13 @@ constexpr void validate_strides(with_rank, Layout, const Extents& ext, const 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}"); + 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 +} // namespace detail +} // end namespace MDSPAN_IMPL_STANDARD_NAMESPACE diff --git a/include/mdspan/impl/macros.hpp b/include/mdspan/impl/macros.hpp index 9955e41c..70a1af31 100644 --- a/include/mdspan/impl/macros.hpp +++ b/include/mdspan/impl/macros.hpp @@ -7,52 +7,55 @@ #include #include -#include // std::is_void +#include // std::is_void #if defined(MDSPAN_IMPL_HAS_SYCL) -#include // sycl::ext::oneapi::experimental::printf +#include // sycl::ext::oneapi::experimental::printf #endif -#if defined(MDSPAN_IMPL_HAS_CUDA) || defined(MDSPAN_IMPL_HAS_HIP) || defined(MDSPAN_IMPL_HAS_SYCL) || defined(MDSPAN_IMPL_HAS_OPENACC) +#if defined(MDSPAN_IMPL_HAS_CUDA) || defined(MDSPAN_IMPL_HAS_HIP) || \ + defined(MDSPAN_IMPL_HAS_SYCL) || defined(MDSPAN_IMPL_HAS_OPENACC) #include "assert.h" #endif #ifndef MDSPAN_IMPL_HOST_DEVICE -# if defined(MDSPAN_IMPL_HAS_CUDA) || defined(MDSPAN_IMPL_HAS_HIP) -# define MDSPAN_IMPL_HOST_DEVICE __host__ __device__ -# else -# define MDSPAN_IMPL_HOST_DEVICE -# endif +#if defined(MDSPAN_IMPL_HAS_CUDA) || defined(MDSPAN_IMPL_HAS_HIP) +#define MDSPAN_IMPL_HOST_DEVICE __host__ __device__ +#else +#define MDSPAN_IMPL_HOST_DEVICE +#endif #endif #ifndef MDSPAN_FORCE_INLINE_FUNCTION -# ifdef MDSPAN_IMPL_COMPILER_MSVC // Microsoft compilers -# define MDSPAN_FORCE_INLINE_FUNCTION __forceinline MDSPAN_IMPL_HOST_DEVICE -# else -# define MDSPAN_FORCE_INLINE_FUNCTION __attribute__((always_inline)) MDSPAN_IMPL_HOST_DEVICE -# endif +#ifdef MDSPAN_IMPL_COMPILER_MSVC // Microsoft compilers +#define MDSPAN_FORCE_INLINE_FUNCTION __forceinline MDSPAN_IMPL_HOST_DEVICE +#else +#define MDSPAN_FORCE_INLINE_FUNCTION \ + __attribute__((always_inline)) MDSPAN_IMPL_HOST_DEVICE +#endif #endif #ifndef MDSPAN_INLINE_FUNCTION -# define MDSPAN_INLINE_FUNCTION inline MDSPAN_IMPL_HOST_DEVICE +#define MDSPAN_INLINE_FUNCTION inline MDSPAN_IMPL_HOST_DEVICE #endif #ifndef MDSPAN_FUNCTION -# define MDSPAN_FUNCTION MDSPAN_IMPL_HOST_DEVICE +#define MDSPAN_FUNCTION MDSPAN_IMPL_HOST_DEVICE #endif #ifdef MDSPAN_IMPL_HAS_HIP -# define MDSPAN_DEDUCTION_GUIDE MDSPAN_IMPL_HOST_DEVICE +#define MDSPAN_DEDUCTION_GUIDE MDSPAN_IMPL_HOST_DEVICE #else -# define MDSPAN_DEDUCTION_GUIDE +#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 +#define MDSPAN_INLINE_FUNCTION_DEFAULTED #endif //============================================================================== // {{{1 +// clang-format off #define MDSPAN_PP_COUNT(...) \ MDSPAN_IMPL_PP_INTERNAL_EXPAND_ARGS( \ MDSPAN_IMPL_PP_INTERNAL_ARGS_AUGMENTER(__VA_ARGS__) \ @@ -95,79 +98,85 @@ #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) +// clang-format on namespace MDSPAN_IMPL_STANDARD_NAMESPACE { namespace detail { #if defined(MDSPAN_IMPL_HAS_CUDA) || defined(MDSPAN_IMPL_HAS_HIP) -MDSPAN_FUNCTION inline void default_precondition_violation_handler(const char* cond, const char* file, unsigned line) -{ +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_IMPL_HAS_SYCL) -MDSPAN_FUNCTION inline void default_precondition_violation_handler(const char* cond, const char* file, unsigned line) -{ +MDSPAN_FUNCTION inline void default_precondition_violation_handler( + const char* cond, const char* file, unsigned line) { #ifdef __INTEL_LLVM_COMPILER - sycl::ext::oneapi::experimental::printf("%s:%u: precondition failure: `%s`\n", file, line, cond); + sycl::ext::oneapi::experimental::printf("%s:%u: precondition failure: `%s`\n", + file, line, cond); #else - (void) cond; - (void) file; - (void) line; + (void)cond; + (void)file; + (void)line; #endif assert(0); } #elif defined(MDSPAN_IMPL_HAS_OPENACC) -MDSPAN_FUNCTION inline void default_precondition_violation_handler(const char* /* cond */, const char* /* file */, unsigned /* line */) -{ +MDSPAN_FUNCTION inline void default_precondition_violation_handler( + const char* /* cond */, const char* /* file */, unsigned /* line */) { assert(false); } #else -MDSPAN_FUNCTION inline void default_precondition_violation_handler(const char* cond, const char* file, unsigned line) -{ +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 +} // 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) + MDSPAN_IMPL_STANDARD_NAMESPACE::detail:: \ + default_precondition_violation_handler(cond, file, line) #endif #ifndef MDSPAN_IMPL_CHECK_PRECONDITION - #ifdef NDEBUG - #define MDSPAN_IMPL_CHECK_PRECONDITION 0 - #else - #define MDSPAN_IMPL_CHECK_PRECONDITION 1 - #endif +#ifdef 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; } +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; + (void)cond; + (void)file; + (void)line; MDSPAN_IMPL_PRECONDITION_VIOLATION_HANDLER(cond, file, line); } -} // namespace detail -} // namespace MDSPAN_IMPL_STANDARD_NAMESPACE +} // 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__); \ - } \ +#define MDSPAN_IMPL_PRECONDITION(...) \ + do { \ + if (!(__VA_ARGS__)) { \ + MDSPAN_IMPL_STANDARD_NAMESPACE::detail::precondition( \ + #__VA_ARGS__, __FILE__, __LINE__); \ + } \ } while (0) // end Preprocessor helpers }}}1 @@ -176,6 +185,7 @@ MDSPAN_FUNCTION constexpr void precondition(const char* cond, const char* file, //============================================================================== // {{{1 +// clang-format off // 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_IMPL_USE_CONCEPTS @@ -347,83 +357,85 @@ struct enable_fold_comma { }; # define MDSPAN_IMPL_FOLD_COMMA(...) ((__VA_ARGS__), ...) #else +// clang-format on + 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 +// 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_IMPL_USE_RETURN_TYPE_DEDUCTION MDSPAN_FORCE_INLINE_FUNCTION -constexpr decltype(auto) fold_right_and_impl() { - return true; -} +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_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; -} +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...); +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) { +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...); +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) { +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...); +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) { +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...); +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) { +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...); +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 @@ -437,26 +449,23 @@ template <> struct fold_right_and_impl_<> { using rv = bool; MDSPAN_FORCE_INLINE_FUNCTION - static constexpr rv - impl() noexcept { - return true; - } + 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()); + using rv = + decltype(std::declval() && std::declval()); MDSPAN_FORCE_INLINE_FUNCTION - static constexpr rv - impl(Arg&& arg, Args&&... args) noexcept { + 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) { +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...); } @@ -472,25 +481,21 @@ template <> struct fold_right_or_impl_<> { using rv = bool; MDSPAN_FORCE_INLINE_FUNCTION - static constexpr rv - impl() noexcept { - return false; - } + 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()); + using rv = + decltype(std::declval() || std::declval()); MDSPAN_FORCE_INLINE_FUNCTION - static constexpr rv - impl(Arg&& arg, Args&&... args) noexcept { + 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 +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...); } @@ -507,26 +512,23 @@ template struct fold_right_plus_impl_ { using rv = Arg&&; MDSPAN_FORCE_INLINE_FUNCTION - static constexpr rv - impl(Arg&& arg) noexcept { - return (Arg&&)arg; - } + 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()); + using rv = + decltype(std::declval() + std::declval()); MDSPAN_FORCE_INLINE_FUNCTION - static constexpr rv - impl(Arg1&& arg, Arg2&& arg2, Args&&... args) noexcept { + 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) { +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...); } @@ -542,26 +544,23 @@ template struct fold_right_times_impl_ { using rv = Arg&&; MDSPAN_FORCE_INLINE_FUNCTION - static constexpr rv - impl(Arg&& arg) noexcept { - return (Arg&&)arg; - } + 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()); + using rv = + decltype(std::declval() * std::declval()); MDSPAN_FORCE_INLINE_FUNCTION - static constexpr rv - impl(Arg1&& arg, Arg2&& arg2, Args&&... args) noexcept { + 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) { +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...); } @@ -577,26 +576,23 @@ template struct fold_right_assign_impl_ { using rv = Arg&&; MDSPAN_FORCE_INLINE_FUNCTION - static constexpr rv - impl(Arg&& arg) noexcept { - return (Arg&&)arg; - } + 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()); + using rv = + decltype(std::declval() = std::declval()); MDSPAN_FORCE_INLINE_FUNCTION - static constexpr rv - impl(Arg1&& arg, Arg2&& arg2, Args&&... args) noexcept { + 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) { +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...); } @@ -612,27 +608,23 @@ template struct fold_left_assign_impl_ { using rv = Arg&&; MDSPAN_FORCE_INLINE_FUNCTION - static constexpr rv - impl(Arg&& arg) noexcept { - return (Arg&&)arg; - } + 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_; - using rv = typename next_t::rv; + using next_t = fold_left_assign_impl_; + using rv = typename next_t::rv; MDSPAN_FORCE_INLINE_FUNCTION - static constexpr rv - impl(Arg1&& arg, Arg2&& arg2, Args&&... args) noexcept { + 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) { +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...); } @@ -641,27 +633,45 @@ fold_left_assign_impl(Args&&... args) { #endif - template -constexpr enable_fold_comma fold_comma_impl(Args&&...) noexcept { return { }; } +constexpr enable_fold_comma fold_comma_impl(Args&&...) noexcept { + return {}; +} template struct fold_bools; -} // fold_compatibility_impl - -} // end namespace MDSPAN_IMPL_STANDARD_NAMESPACE - -# define MDSPAN_IMPL_FOLD_AND(...) MDSPAN_IMPL_STANDARD_NAMESPACE::fold_compatibility_impl::fold_right_and_impl((__VA_ARGS__)...) -# define MDSPAN_IMPL_FOLD_OR(...) MDSPAN_IMPL_STANDARD_NAMESPACE::fold_compatibility_impl::fold_right_or_impl((__VA_ARGS__)...) -# define MDSPAN_IMPL_FOLD_ASSIGN_LEFT(INIT, ...) MDSPAN_IMPL_STANDARD_NAMESPACE::fold_compatibility_impl::fold_left_assign_impl(INIT, (__VA_ARGS__)...) -# define MDSPAN_IMPL_FOLD_ASSIGN_RIGHT(PACK, ...) MDSPAN_IMPL_STANDARD_NAMESPACE::fold_compatibility_impl::fold_right_assign_impl((PACK)..., __VA_ARGS__) -# define MDSPAN_IMPL_FOLD_TIMES_RIGHT(PACK, ...) MDSPAN_IMPL_STANDARD_NAMESPACE::fold_compatibility_impl::fold_right_times_impl((PACK)..., __VA_ARGS__) -# define MDSPAN_IMPL_FOLD_PLUS_RIGHT(PACK, ...) MDSPAN_IMPL_STANDARD_NAMESPACE::fold_compatibility_impl::fold_right_plus_impl((PACK)..., __VA_ARGS__) -# define MDSPAN_IMPL_FOLD_COMMA(...) MDSPAN_IMPL_STANDARD_NAMESPACE::fold_compatibility_impl::fold_comma_impl((__VA_ARGS__)...) - -# define MDSPAN_IMPL_FOLD_AND_TEMPLATE(...) \ - MDSPAN_IMPL_TRAIT(std::is_same, fold_compatibility_impl::fold_bools<(__VA_ARGS__)..., true>, fold_compatibility_impl::fold_bools) +} // namespace fold_compatibility_impl + +} // end namespace MDSPAN_IMPL_STANDARD_NAMESPACE + +#define MDSPAN_IMPL_FOLD_AND(...) \ + MDSPAN_IMPL_STANDARD_NAMESPACE::fold_compatibility_impl:: \ + fold_right_and_impl((__VA_ARGS__)...) +#define MDSPAN_IMPL_FOLD_OR(...) \ + MDSPAN_IMPL_STANDARD_NAMESPACE::fold_compatibility_impl::fold_right_or_impl( \ + (__VA_ARGS__)...) +#define MDSPAN_IMPL_FOLD_ASSIGN_LEFT(INIT, ...) \ + MDSPAN_IMPL_STANDARD_NAMESPACE::fold_compatibility_impl:: \ + fold_left_assign_impl(INIT, (__VA_ARGS__)...) +#define MDSPAN_IMPL_FOLD_ASSIGN_RIGHT(PACK, ...) \ + MDSPAN_IMPL_STANDARD_NAMESPACE::fold_compatibility_impl:: \ + fold_right_assign_impl((PACK)..., __VA_ARGS__) +#define MDSPAN_IMPL_FOLD_TIMES_RIGHT(PACK, ...) \ + MDSPAN_IMPL_STANDARD_NAMESPACE::fold_compatibility_impl:: \ + fold_right_times_impl((PACK)..., __VA_ARGS__) +#define MDSPAN_IMPL_FOLD_PLUS_RIGHT(PACK, ...) \ + MDSPAN_IMPL_STANDARD_NAMESPACE::fold_compatibility_impl:: \ + fold_right_plus_impl((PACK)..., __VA_ARGS__) +#define MDSPAN_IMPL_FOLD_COMMA(...) \ + MDSPAN_IMPL_STANDARD_NAMESPACE::fold_compatibility_impl::fold_comma_impl( \ + (__VA_ARGS__)...) + +#define MDSPAN_IMPL_FOLD_AND_TEMPLATE(...) \ + MDSPAN_IMPL_TRAIT( \ + std::is_same, \ + fold_compatibility_impl::fold_bools<(__VA_ARGS__)..., true>, \ + fold_compatibility_impl::fold_bools) #endif @@ -672,9 +682,9 @@ struct fold_bools; // {{{1 #if MDSPAN_IMPL_USE_VARIABLE_TEMPLATES -# define MDSPAN_IMPL_TRAIT(TRAIT, ...) TRAIT##_v<__VA_ARGS__> +#define MDSPAN_IMPL_TRAIT(TRAIT, ...) TRAIT##_v<__VA_ARGS__> #else -# define MDSPAN_IMPL_TRAIT(TRAIT, ...) TRAIT<__VA_ARGS__>::value +#define MDSPAN_IMPL_TRAIT(TRAIT, ...) TRAIT<__VA_ARGS__>::value #endif // end Variable template compatibility }}}1 @@ -684,23 +694,23 @@ struct fold_bools; // {{{1 #if MDSPAN_IMPL_USE_CONSTEXPR_14 -# define MDSPAN_IMPL_CONSTEXPR_14 constexpr +#define MDSPAN_IMPL_CONSTEXPR_14 constexpr // Workaround for a bug (I think?) in EDG frontends -# ifdef __EDG__ -# define MDSPAN_IMPL_CONSTEXPR_14_DEFAULTED -# else -# define MDSPAN_IMPL_CONSTEXPR_14_DEFAULTED constexpr -# endif +#ifdef __EDG__ +#define MDSPAN_IMPL_CONSTEXPR_14_DEFAULTED +#else +#define MDSPAN_IMPL_CONSTEXPR_14_DEFAULTED constexpr +#endif #else -# define MDSPAN_IMPL_CONSTEXPR_14 -# define MDSPAN_IMPL_CONSTEXPR_14_DEFAULTED +#define MDSPAN_IMPL_CONSTEXPR_14 +#define MDSPAN_IMPL_CONSTEXPR_14_DEFAULTED #endif // end Pre-C++14 constexpr }}}1 //============================================================================== #if MDSPAN_IMPL_USE_IF_CONSTEXPR_17 -# define MDSPAN_IMPL_IF_CONSTEXPR_17 constexpr +#define MDSPAN_IMPL_IF_CONSTEXPR_17 constexpr #else -# define MDSPAN_IMPL_IF_CONSTEXPR_17 +#define MDSPAN_IMPL_IF_CONSTEXPR_17 #endif diff --git a/include/mdspan/impl/mdarray.hpp b/include/mdspan/impl/mdarray.hpp index 34b7c62a..f80203ed 100644 --- a/include/mdspan/impl/mdarray.hpp +++ b/include/mdspan/impl/mdarray.hpp @@ -11,260 +11,283 @@ 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; - } - }; -} +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 < extents::rank(); r++) + size *= extents::static_extent(r); + return size; + } +}; +} // namespace 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::impl_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: +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(); + } +}; +} // namespace +template > +class mdarray { + private: + static_assert( + ::MDSPAN_IMPL_STANDARD_NAMESPACE::detail::impl_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 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 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: - + 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)) {} + 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; + 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; + 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_IMPL_TRAIT( std::is_constructible, extents_type, SizeTypes...) && - MDSPAN_IMPL_TRAIT( std::is_constructible, mapping_type, extents_type) && - (MDSPAN_IMPL_TRAIT( std::is_constructible, container_type, size_t) || - container_is_array::value) && - (extents_type::rank()>0 || extents_type::rank_dynamic()==0) - ) - ) + class... SizeTypes, + /* requires */ ( + (::MDSPAN_IMPL_STANDARD_NAMESPACE::detail::are_valid_indices< + index_type, SizeTypes...>()) && + MDSPAN_IMPL_TRAIT(std::is_constructible, extents_type, + SizeTypes...) && + MDSPAN_IMPL_TRAIT(std::is_constructible, mapping_type, + extents_type) && + (MDSPAN_IMPL_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_)) - { } + : 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_IMPL_TRAIT( std::is_constructible, container_type, size_t) || - container_is_array::value) && - MDSPAN_IMPL_TRAIT( std::is_constructible, mapping_type, extents_type)) - ) : map_(exts), ctr_(container_is_array::construct(map_)) - { } + (MDSPAN_INLINE_FUNCTION constexpr), mdarray, (const extents_type& exts), , + /* requires */ + ((MDSPAN_IMPL_TRAIT(std::is_constructible, container_type, size_t) || + container_is_array::value) && + MDSPAN_IMPL_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_IMPL_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 mapping_type& m), , - /* requires */ (MDSPAN_IMPL_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_IMPL_TRAIT( std::is_constructible, mapping_type, extents_type)) - ) : map_(exts), ctr_(ctr) - { assert(ctr.size() >= static_cast(map_.required_span_size())); } + (MDSPAN_INLINE_FUNCTION constexpr), mdarray, + (const extents_type& exts, const container_type& ctr), , + /* requires */ + (MDSPAN_IMPL_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())); } + : 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_IMPL_TRAIT( std::is_constructible, mapping_type, extents_type)) - ) : map_(exts), ctr_(std::move(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_IMPL_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())); } - + : 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_IMPL_TRAIT( std::is_constructible, mapping_type, typename OtherLayoutPolicy::template mapping) && - MDSPAN_IMPL_TRAIT( std::is_constructible, container_type, OtherContainer) - ) - ) + class OtherElementType, class OtherExtents, class OtherLayoutPolicy, + class OtherContainer, + /* requires */ + (MDSPAN_IMPL_TRAIT( + std::is_constructible, mapping_type, + typename OtherLayoutPolicy::template mapping) && + MDSPAN_IMPL_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, ""); + 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_IMPL_TRAIT( std::is_constructible, container_type, size_t, Alloc) && - MDSPAN_IMPL_TRAIT( std::is_constructible, mapping_type, extents_type)) - ) + class Alloc, + /* requires */ (MDSPAN_IMPL_TRAIT(std::is_constructible, container_type, + size_t, Alloc) && + MDSPAN_IMPL_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) - { } + : map_(exts), ctr_(map_.required_span_size(), a) {} MDSPAN_TEMPLATE_REQUIRES( - class Alloc, - /* requires */ (MDSPAN_IMPL_TRAIT( std::is_constructible, container_type, size_t, Alloc)) - ) + class Alloc, + /* requires */ (MDSPAN_IMPL_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) - { } + : map_(map), ctr_(map_.required_span_size(), a) {} - // Constructors for container types constructible from a container and allocator + // Constructors for container types constructible from a container and + // allocator MDSPAN_TEMPLATE_REQUIRES( - class Alloc, - /* requires */ (MDSPAN_IMPL_TRAIT( std::is_constructible, container_type, container_type, Alloc) && - MDSPAN_IMPL_TRAIT( std::is_constructible, mapping_type, extents_type)) - ) + class Alloc, + /* requires */ (MDSPAN_IMPL_TRAIT(std::is_constructible, container_type, + container_type, Alloc) && + MDSPAN_IMPL_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())); } + 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_IMPL_TRAIT( std::is_constructible, container_type, size_t, Alloc)) - ) + class Alloc, + /* requires */ (MDSPAN_IMPL_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())); } + 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_IMPL_TRAIT( std::is_constructible, container_type, container_type, Alloc) && - MDSPAN_IMPL_TRAIT( std::is_constructible, mapping_type, extents_type)) - ) + class Alloc, + /* requires */ (MDSPAN_IMPL_TRAIT(std::is_constructible, container_type, + container_type, Alloc) && + MDSPAN_IMPL_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())); } + 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_IMPL_TRAIT( std::is_constructible, container_type, size_t, Alloc)) - ) + class Alloc, + /* requires */ (MDSPAN_IMPL_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()); } + 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_IMPL_TRAIT( std::is_constructible, mapping_type, typename OtherLayoutPolicy::template mapping) && - MDSPAN_IMPL_TRAIT( std::is_constructible, container_type, OtherContainer, Alloc) - ) - ) + class OtherElementType, class OtherExtents, class OtherLayoutPolicy, + class OtherContainer, class Alloc, + /* requires */ + (MDSPAN_IMPL_TRAIT( + std::is_constructible, mapping_type, + typename OtherLayoutPolicy::template mapping) && + MDSPAN_IMPL_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, ""); + 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 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 + // [mdspan.basic.mapping], mdspan mapping domain multidimensional index to + // access codomain element - #if MDSPAN_USE_BRACKET_OPERATOR +#if MDSPAN_USE_BRACKET_OPERATOR MDSPAN_TEMPLATE_REQUIRES( - class... SizeTypes, - /* requires */ ( - MDSPAN_IMPL_FOLD_AND(MDSPAN_IMPL_TRAIT( std::is_convertible, SizeTypes, index_type) /* && ... */) && - extents_type::rank() == sizeof...(SizeTypes) - ) - ) + class... SizeTypes, + /* requires */ ( + MDSPAN_IMPL_FOLD_AND(MDSPAN_IMPL_TRAIT(std::is_convertible, SizeTypes, + index_type) /* && ... */) && + extents_type::rank() == sizeof...(SizeTypes))) MDSPAN_FORCE_INLINE_FUNCTION - constexpr const_reference operator[](SizeTypes... indices) const noexcept - { + constexpr const_reference operator[](SizeTypes... indices) const noexcept { return ctr_[map_(static_cast(std::move(indices))...)]; } MDSPAN_TEMPLATE_REQUIRES( - class... SizeTypes, - /* requires */ ( - MDSPAN_IMPL_FOLD_AND(MDSPAN_IMPL_TRAIT( std::is_convertible, SizeTypes, index_type) /* && ... */) && - extents_type::rank() == sizeof...(SizeTypes) - ) - ) + class... SizeTypes, + /* requires */ ( + MDSPAN_IMPL_FOLD_AND(MDSPAN_IMPL_TRAIT(std::is_convertible, SizeTypes, + index_type) /* && ... */) && + extents_type::rank() == sizeof...(SizeTypes))) MDSPAN_FORCE_INLINE_FUNCTION - constexpr reference operator[](SizeTypes... indices) noexcept - { + constexpr reference operator[](SizeTypes... indices) noexcept { return ctr_[map_(static_cast(std::move(indices))...)]; } - #endif +#endif #if 0 MDSPAN_TEMPLATE_REQUIRES( @@ -294,30 +317,23 @@ class mdarray { } #endif - - #if MDSPAN_USE_PAREN_OPERATOR +#if MDSPAN_USE_PAREN_OPERATOR MDSPAN_TEMPLATE_REQUIRES( - class... SizeTypes, - /* requires */ ( - (::MDSPAN_IMPL_STANDARD_NAMESPACE::detail::are_valid_indices()) && - extents_type::rank() == sizeof...(SizeTypes) - ) - ) + 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 - { + 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) - ) - ) + 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 - { + constexpr reference operator()(SizeTypes... indices) noexcept { return ctr_[map_(static_cast(std::move(indices))...)]; } @@ -348,93 +364,132 @@ class mdarray { return impl::template callop(*this, indices); } #endif - #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_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.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 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 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 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 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); } + 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_IMPL_TRAIT(std::is_assignable, - mdspan, - mdspan_type) - ) - ) - constexpr operator mdspan () { + class OtherElementType, class OtherExtents, class OtherLayoutType, + class OtherAccessorType, + /* requires */ + (MDSPAN_IMPL_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_IMPL_TRAIT(std::is_assignable, - mdspan, - const_mdspan_type) - ) - ) - constexpr operator mdspan () const { + class OtherElementType, class OtherExtents, class OtherLayoutType, + class OtherAccessorType, + /* requires */ + (MDSPAN_IMPL_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_IMPL_TRAIT(std::is_assignable, mdspan_type, - mdspan) - ) - ) + class OtherAccessorType = default_accessor, + /* requires */ (MDSPAN_IMPL_TRAIT( + std::is_assignable, mdspan_type, + mdspan))) constexpr mdspan - to_mdspan(const OtherAccessorType& a = default_accessor()) { - return mdspan(data(), map_, a); + to_mdspan(const OtherAccessorType& a = default_accessor()) { + return mdspan( + data(), map_, a); } MDSPAN_TEMPLATE_REQUIRES( - class OtherAccessorType = default_accessor, - /* requires */ ( - MDSPAN_IMPL_TRAIT(std::is_assignable, const_mdspan_type, - mdspan) - ) - ) - constexpr mdspan - to_mdspan(const OtherAccessorType& a = default_accessor()) const { - return mdspan(data(), map_, a); + class OtherAccessorType = default_accessor, + /* requires */ ( + MDSPAN_IMPL_TRAIT(std::is_assignable, const_mdspan_type, + mdspan))) + constexpr mdspan + to_mdspan(const OtherAccessorType& a = + default_accessor()) const { + return mdspan(data(), map_, a); } -private: + private: mapping_type map_; container_type ctr_; @@ -442,6 +497,5 @@ class mdarray { friend class mdarray; }; - -} // end namespace MDSPAN_IMPL_PROPOSED_NAMESPACE -} // end namespace MDSPAN_IMPL_STANDARD_NAMESPACE +} // end namespace MDSPAN_IMPL_PROPOSED_NAMESPACE +} // end namespace MDSPAN_IMPL_STANDARD_NAMESPACE diff --git a/include/mdspan/impl/mdspan.hpp b/include/mdspan/impl/mdspan.hpp index d8b92dfc..5eb9d38b 100644 --- a/include/mdspan/impl/mdspan.hpp +++ b/include/mdspan/impl/mdspan.hpp @@ -15,80 +15,95 @@ #include namespace MDSPAN_IMPL_STANDARD_NAMESPACE { -template < - class ElementType, - class Extents, - class LayoutPolicy = layout_right, - class AccessorPolicy = default_accessor -> -class mdspan -{ -private: +template > +class mdspan { + private: static_assert(detail::impl_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 + 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_IMPL_FOLD_TIMES_RIGHT((self.mapping_ref().extents().extent(Idxs)), /* * ... * */ size_t(1)); + struct deduction_workaround> { + MDSPAN_FORCE_INLINE_FUNCTION static constexpr size_t size( + mdspan const& self) noexcept { + return MDSPAN_IMPL_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_IMPL_FOLD_OR((self.mapping_ref().extents().extent(Idxs)==index_type(0))); + MDSPAN_FORCE_INLINE_FUNCTION static constexpr bool empty( + mdspan const& self) noexcept { + return (self.rank() > 0) && + MDSPAN_IMPL_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]...)); + 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]...)); + 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: - + 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 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 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 index_type extent(size_t r) const noexcept { return mapping_ref().extents().extent(r); } + using reference = typename accessor_type::reference; -private: - - // Can't use defaulted parameter in the deduction_workaround template because of a bug in MSVC warning C4348. - using deduction_workaround_impl = deduction_workaround>; + 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 index_type extent(size_t r) const noexcept { + return mapping_ref().extents().extent(r); + } - using map_acc_pair_t = detail::impl_compressed_pair; + private: + // Can't use defaulted parameter in the deduction_workaround template because + // of a bug in MSVC warning C4348. + using deduction_workaround_impl = + deduction_workaround>; -public: + using map_acc_pair_t = + detail::impl_compressed_pair; + public: //-------------------------------------------------------------------------------- // [mdspan.basic.cons], mdspan constructors, assignment, and destructor @@ -97,106 +112,127 @@ class mdspan #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_IMPL_TRAIT(std::is_default_constructible, data_handle_type) && - MDSPAN_IMPL_TRAIT(std::is_default_constructible, mapping_type) && - MDSPAN_IMPL_TRAIT(std::is_default_constructible, accessor_type) - ) = default; + // nvhpc has a bug where using just rank_dynamic() here doesn't + // work ... + (extents_type::rank_dynamic() > 0) && + MDSPAN_IMPL_TRAIT(std::is_default_constructible, + data_handle_type) && + MDSPAN_IMPL_TRAIT(std::is_default_constructible, + mapping_type) && + MDSPAN_IMPL_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_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_IMPL_TRAIT(std::is_constructible, mapping_type, extents_type) && - MDSPAN_IMPL_TRAIT(std::is_default_constructible, accessor_type) - ) - ) + class... SizeTypes, + /* requires */ (((sizeof...(SizeTypes) == rank()) || + (sizeof...(SizeTypes) == rank_dynamic())) && + (detail::are_valid_indices()) && + MDSPAN_IMPL_TRAIT(std::is_constructible, mapping_type, + extents_type) && + MDSPAN_IMPL_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? - : m_members(std::move(p), map_acc_pair_t(mapping_type(extents_type(static_cast(std::move(dynamic_extents))...)), accessor_type())) - { } + // TODO @proposal-bug shouldn't I be allowed to do `move(p)` here? + : m_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_IMPL_TRAIT(std::is_convertible, const SizeType&, index_type) && - MDSPAN_IMPL_TRAIT(std::is_nothrow_constructible, index_type, const SizeType&) && - ((N == rank()) || (N == rank_dynamic())) && - MDSPAN_IMPL_TRAIT(std::is_constructible, mapping_type, extents_type) && - MDSPAN_IMPL_TRAIT(std::is_default_constructible, accessor_type) - ) - ) + class SizeType, size_t N, + /* requires */ + (MDSPAN_IMPL_TRAIT(std::is_convertible, const SizeType&, index_type) && + MDSPAN_IMPL_TRAIT(std::is_nothrow_constructible, index_type, + const SizeType&) && + ((N == rank()) || (N == rank_dynamic())) && + MDSPAN_IMPL_TRAIT(std::is_constructible, mapping_type, extents_type) && + MDSPAN_IMPL_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) - : m_members(std::move(p), map_acc_pair_t(mapping_type(extents_type(dynamic_extents)), accessor_type())) - { } + constexpr mdspan(data_handle_type p, + const std::array& dynamic_extents) + : m_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_IMPL_TRAIT(std::is_convertible, const SizeType&, index_type) && - MDSPAN_IMPL_TRAIT(std::is_nothrow_constructible, index_type, const SizeType&) && - ((N == rank()) || (N == rank_dynamic())) && - MDSPAN_IMPL_TRAIT(std::is_constructible, mapping_type, extents_type) && - MDSPAN_IMPL_TRAIT(std::is_default_constructible, accessor_type) - ) - ) + class SizeType, size_t N, + /* requires */ + (MDSPAN_IMPL_TRAIT(std::is_convertible, const SizeType&, index_type) && + MDSPAN_IMPL_TRAIT(std::is_nothrow_constructible, index_type, + const SizeType&) && + ((N == rank()) || (N == rank_dynamic())) && + MDSPAN_IMPL_TRAIT(std::is_constructible, mapping_type, extents_type) && + MDSPAN_IMPL_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) - : m_members(std::move(p), map_acc_pair_t(mapping_type(extents_type(as_const(dynamic_extents))), accessor_type())) - { } + : m_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_IMPL_TRAIT(std::is_default_constructible, accessor_type) && - MDSPAN_IMPL_TRAIT(std::is_constructible, mapping_type, const extents_type&)) - ) : m_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_IMPL_TRAIT(std::is_default_constructible, accessor_type)) - ) : m_members(std::move(p), map_acc_pair_t(m, accessor_type())) - { } + (MDSPAN_INLINE_FUNCTION constexpr), mdspan, + (data_handle_type p, const extents_type& exts), , + /* requires */ + (MDSPAN_IMPL_TRAIT(std::is_default_constructible, accessor_type) && + MDSPAN_IMPL_TRAIT(std::is_constructible, mapping_type, + const extents_type&))) + : m_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_IMPL_TRAIT(std::is_default_constructible, + accessor_type))) + : m_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) - : m_members(std::move(p), map_acc_pair_t(m, a)) - { } + constexpr mdspan(data_handle_type p, const mapping_type& m, + const accessor_type& a) + : m_members(std::move(p), map_acc_pair_t(m, a)) {} MDSPAN_TEMPLATE_REQUIRES( - class OtherElementType, class OtherExtents, class OtherLayoutPolicy, class OtherAccessor, - /* requires */ ( - MDSPAN_IMPL_TRAIT(std::is_constructible, mapping_type, const typename OtherLayoutPolicy::template mapping&) && - MDSPAN_IMPL_TRAIT(std::is_constructible, accessor_type, const OtherAccessor&) - ) - ) + class OtherElementType, class OtherExtents, class OtherLayoutPolicy, + class OtherAccessor, + /* requires */ + (MDSPAN_IMPL_TRAIT( + std::is_constructible, mapping_type, + const typename OtherLayoutPolicy::template mapping&) && + MDSPAN_IMPL_TRAIT(std::is_constructible, accessor_type, + const OtherAccessor&))) MDSPAN_CONDITIONAL_EXPLICIT( - !MDSPAN_IMPL_TRAIT(std::is_convertible, const typename OtherLayoutPolicy::template mapping&, mapping_type) || - !MDSPAN_IMPL_TRAIT(std::is_convertible, const OtherAccessor&, accessor_type) - ) + !MDSPAN_IMPL_TRAIT( + std::is_convertible, + const typename OtherLayoutPolicy::template mapping&, + mapping_type) || + !MDSPAN_IMPL_TRAIT(std::is_convertible, const OtherAccessor&, + accessor_type)) MDSPAN_INLINE_FUNCTION - constexpr mdspan(const mdspan& other) - : m_members(other.ptr_ref(), map_acc_pair_t(other.mapping_ref(), other.accessor_ref())) - { - static_assert(MDSPAN_IMPL_TRAIT(std::is_constructible, data_handle_type, typename OtherAccessor::data_handle_type),"Incompatible data_handle_type for mdspan construction"); - static_assert(MDSPAN_IMPL_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. - */ + constexpr mdspan(const mdspan& other) + : m_members(other.ptr_ref(), + map_acc_pair_t(other.mapping_ref(), other.accessor_ref())) { + static_assert(MDSPAN_IMPL_TRAIT(std::is_constructible, data_handle_type, + typename OtherAccessor::data_handle_type), + "Incompatible data_handle_type for mdspan construction"); + static_assert( + MDSPAN_IMPL_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? @@ -204,175 +240,171 @@ class mdspan ~mdspan() = default; */ - MDSPAN_INLINE_FUNCTION_DEFAULTED MDSPAN_IMPL_CONSTEXPR_14_DEFAULTED mdspan& operator=(const mdspan&) = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED MDSPAN_IMPL_CONSTEXPR_14_DEFAULTED mdspan& operator=(mdspan&&) = default; - + MDSPAN_INLINE_FUNCTION_DEFAULTED MDSPAN_IMPL_CONSTEXPR_14_DEFAULTED mdspan& + operator=(const mdspan&) = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED MDSPAN_IMPL_CONSTEXPR_14_DEFAULTED mdspan& + operator=(mdspan&&) = default; //-------------------------------------------------------------------------------- - // [mdspan.basic.mapping], mdspan mapping domain multidimensional index to access codomain element + // [mdspan.basic.mapping], mdspan mapping domain multidimensional index to + // access codomain element MDSPAN_TEMPLATE_REQUIRES( - class... SizeTypes, - /* requires */ ( - extents_type::rank() == sizeof...(SizeTypes) && - (detail::are_valid_indices()) - ) - ) - constexpr reference at(SizeTypes... indices) const - { + class... SizeTypes, + /* requires */ (extents_type::rank() == sizeof...(SizeTypes) && + (detail::are_valid_indices()))) + constexpr reference at(SizeTypes... indices) const { size_t r = 0; for (const auto& index : {indices...}) { if (is_index_oor(index, mapping_ref().extents().extent(r))) { throw std::out_of_range( - "mdspan::at(...," + std::to_string(index) + ",...) out-of-range at rank index " + std::to_string(r) + - " for mdspan with extent {...," + std::to_string(mapping_ref().extents().extent(r)) + ",...}"); + "mdspan::at(...," + std::to_string(index) + + ",...) out-of-range at rank index " + std::to_string(r) + + " for mdspan with extent {...," + + std::to_string(mapping_ref().extents().extent(r)) + ",...}"); } ++r; } - return accessor_ref().access(ptr_ref(), mapping_ref()(static_cast(std::move(indices))...)); + return accessor_ref().access( + ptr_ref(), + mapping_ref()(static_cast(std::move(indices))...)); } MDSPAN_TEMPLATE_REQUIRES( - class SizeType, - /* requires */ ( - MDSPAN_IMPL_TRAIT(std::is_convertible, const SizeType&, index_type) && - MDSPAN_IMPL_TRAIT(std::is_nothrow_constructible, index_type, const SizeType&) - ) - ) - constexpr reference at(const std::array& indices) const - { + class SizeType, + /* requires */ (MDSPAN_IMPL_TRAIT(std::is_convertible, const SizeType&, + index_type) && + MDSPAN_IMPL_TRAIT(std::is_nothrow_constructible, + index_type, const SizeType&))) + constexpr reference at(const std::array& indices) const { for (size_t r = 0; r < indices.size(); ++r) { if (is_index_oor(indices[r], mapping_ref().extents().extent(r))) { throw std::out_of_range( - "mdspan::at({...," + std::to_string(indices[r]) + ",...}) out-of-range at rank index " + std::to_string(r) + - " for mdspan with extent {...," + std::to_string(mapping_ref().extents().extent(r)) + ",...}"); + "mdspan::at({...," + std::to_string(indices[r]) + + ",...}) out-of-range at rank index " + std::to_string(r) + + " for mdspan with extent {...," + + std::to_string(mapping_ref().extents().extent(r)) + ",...}"); } } - return deduction_workaround_impl::template callop(*this, indices); + return deduction_workaround_impl::template callop(*this, + indices); } - #ifdef __cpp_lib_span +#ifdef __cpp_lib_span MDSPAN_TEMPLATE_REQUIRES( - class SizeType, - /* requires */ ( - MDSPAN_IMPL_TRAIT(std::is_convertible, const SizeType&, index_type) && - MDSPAN_IMPL_TRAIT(std::is_nothrow_constructible, index_type, const SizeType&) - ) - ) - constexpr reference at(std::span indices) const - { + class SizeType, + /* requires */ (MDSPAN_IMPL_TRAIT(std::is_convertible, const SizeType&, + index_type) && + MDSPAN_IMPL_TRAIT(std::is_nothrow_constructible, + index_type, const SizeType&))) + constexpr reference at(std::span indices) const { for (size_t r = 0; r < indices.size(); ++r) { if (is_index_oor(indices[r], mapping_ref().extents().extent(r))) { throw std::out_of_range( - "mdspan::at({...," + std::to_string(indices[r]) + ",...}) out-of-range at rank index " + std::to_string(r) + - " for mdspan with extent {...," + std::to_string(mapping_ref().extents().extent(r)) + ",...}"); + "mdspan::at({...," + std::to_string(indices[r]) + + ",...}) out-of-range at rank index " + std::to_string(r) + + " for mdspan with extent {...," + + std::to_string(mapping_ref().extents().extent(r)) + ",...}"); } } - return deduction_workaround_impl::template callop(*this, indices); + return deduction_workaround_impl::template callop(*this, + indices); } - #endif // __cpp_lib_span +#endif // __cpp_lib_span - #if MDSPAN_USE_BRACKET_OPERATOR +#if MDSPAN_USE_BRACKET_OPERATOR MDSPAN_TEMPLATE_REQUIRES( - class... SizeTypes, - /* requires */ ( - extents_type::rank() == sizeof...(SizeTypes) && - (detail::are_valid_indices()) - ) - ) + 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))...)); + constexpr reference operator[](SizeTypes... indices) const { + return accessor_ref().access( + ptr_ref(), + mapping_ref()(static_cast(std::move(indices))...)); } - #endif +#endif MDSPAN_TEMPLATE_REQUIRES( - class SizeType, - /* requires */ ( - MDSPAN_IMPL_TRAIT(std::is_convertible, const SizeType&, index_type) && - MDSPAN_IMPL_TRAIT(std::is_nothrow_constructible, index_type, const SizeType&) - ) - ) + class SizeType, + /* requires */ (MDSPAN_IMPL_TRAIT(std::is_convertible, const SizeType&, + index_type) && + MDSPAN_IMPL_TRAIT(std::is_nothrow_constructible, + index_type, const SizeType&))) MDSPAN_FORCE_INLINE_FUNCTION - constexpr reference operator[](const std::array& indices) const - { - return deduction_workaround_impl::template callop(*this, indices); + constexpr reference operator[]( + const std::array& indices) const { + return deduction_workaround_impl::template callop(*this, + indices); } - #ifdef __cpp_lib_span +#ifdef __cpp_lib_span MDSPAN_TEMPLATE_REQUIRES( - class SizeType, - /* requires */ ( - MDSPAN_IMPL_TRAIT(std::is_convertible, const SizeType&, index_type) && - MDSPAN_IMPL_TRAIT(std::is_nothrow_constructible, index_type, const SizeType&) - ) - ) + class SizeType, + /* requires */ (MDSPAN_IMPL_TRAIT(std::is_convertible, const SizeType&, + index_type) && + MDSPAN_IMPL_TRAIT(std::is_nothrow_constructible, + index_type, const SizeType&))) MDSPAN_FORCE_INLINE_FUNCTION - constexpr reference operator[](std::span indices) const - { - return deduction_workaround_impl::template callop(*this, indices); + constexpr reference operator[](std::span indices) const { + return deduction_workaround_impl::template callop(*this, + indices); } - #endif // __cpp_lib_span +#endif // __cpp_lib_span - #if !MDSPAN_USE_BRACKET_OPERATOR +#if !MDSPAN_USE_BRACKET_OPERATOR MDSPAN_TEMPLATE_REQUIRES( - class Index, - /* requires */ ( - MDSPAN_IMPL_TRAIT(std::is_convertible, Index, index_type) && - MDSPAN_IMPL_TRAIT(std::is_nothrow_constructible, index_type, Index) && - extents_type::rank() == 1 - ) - ) + class Index, + /* requires */ ( + MDSPAN_IMPL_TRAIT(std::is_convertible, Index, index_type) && + MDSPAN_IMPL_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)))); + constexpr reference operator[](Index idx) const { + return accessor_ref().access( + ptr_ref(), mapping_ref()(static_cast(std::move(idx)))); } - #endif +#endif - #if MDSPAN_USE_PAREN_OPERATOR +#if MDSPAN_USE_PAREN_OPERATOR MDSPAN_TEMPLATE_REQUIRES( - class... SizeTypes, - /* requires */ ( - extents_type::rank() == sizeof...(SizeTypes) && - (detail::are_valid_indices()) - ) - ) + 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))...)); + 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_IMPL_TRAIT(std::is_convertible, const SizeType&, index_type) && - MDSPAN_IMPL_TRAIT(std::is_nothrow_constructible, index_type, const SizeType&) - ) - ) + class SizeType, + /* requires */ (MDSPAN_IMPL_TRAIT(std::is_convertible, const SizeType&, + index_type) && + MDSPAN_IMPL_TRAIT(std::is_nothrow_constructible, + index_type, const SizeType&))) MDSPAN_FORCE_INLINE_FUNCTION - constexpr reference operator()(const std::array& indices) const - { - return deduction_workaround_impl::template callop(*this, indices); + constexpr reference operator()( + const std::array& indices) const { + return deduction_workaround_impl::template callop(*this, + indices); } - #ifdef __cpp_lib_span +#ifdef __cpp_lib_span MDSPAN_TEMPLATE_REQUIRES( - class SizeType, - /* requires */ ( - MDSPAN_IMPL_TRAIT(std::is_convertible, const SizeType&, index_type) && - MDSPAN_IMPL_TRAIT(std::is_nothrow_constructible, index_type, const SizeType&) - ) - ) + class SizeType, + /* requires */ (MDSPAN_IMPL_TRAIT(std::is_convertible, const SizeType&, + index_type) && + MDSPAN_IMPL_TRAIT(std::is_nothrow_constructible, + index_type, const SizeType&))) MDSPAN_FORCE_INLINE_FUNCTION - constexpr reference operator()(std::span indices) const - { - return deduction_workaround_impl::template callop(*this, indices); + constexpr reference operator()(std::span indices) const { + return deduction_workaround_impl::template callop(*this, + indices); } - #endif // __cpp_lib_span - #endif // MDSPAN_USE_PAREN_OPERATOR +#endif // __cpp_lib_span +#endif // MDSPAN_USE_PAREN_OPERATOR MDSPAN_INLINE_FUNCTION constexpr size_type size() const noexcept { return static_cast(deduction_workaround_impl::size(*this)); @@ -384,23 +416,24 @@ class mdspan MDSPAN_INLINE_FUNCTION friend constexpr void swap(mdspan& x, mdspan& y) noexcept { - // can't call the std::swap inside on HIP - #if !defined(MDSPAN_IMPL_HAS_HIP) && !defined(MDSPAN_IMPL_HAS_CUDA) +// can't call the std::swap inside on HIP +#if !defined(MDSPAN_IMPL_HAS_HIP) && !defined(MDSPAN_IMPL_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 +#else mdspan tmp = y; - y = x; - x = tmp; - #endif + y = x; + x = tmp; +#endif } //-------------------------------------------------------------------------------- - // [mdspan.basic.domobs], mdspan observers of the domain multidimensional index space - + // [mdspan.basic.domobs], mdspan observers of the domain multidimensional + // index space + // clang-format off 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(); } @@ -428,18 +461,20 @@ class mdspan MDSPAN_FORCE_INLINE_FUNCTION constexpr mapping_type const& mapping_ref() const noexcept { return m_members.second().first(); } MDSPAN_FORCE_INLINE_FUNCTION MDSPAN_IMPL_CONSTEXPR_14 accessor_type& accessor_ref() noexcept { return m_members.second().second(); } MDSPAN_FORCE_INLINE_FUNCTION constexpr accessor_type const& accessor_ref() const noexcept { return m_members.second().second(); } - + // clang-format on + MDSPAN_TEMPLATE_REQUIRES( - class SizeType, - /* requires */ ( - MDSPAN_IMPL_TRAIT(std::is_convertible, const SizeType&, index_type) && - MDSPAN_IMPL_TRAIT(std::is_nothrow_constructible, index_type, const SizeType&) - ) - ) - MDSPAN_FORCE_INLINE_FUNCTION constexpr bool is_index_oor(SizeType index, index_type extent) const noexcept { + class SizeType, + /* requires */ (MDSPAN_IMPL_TRAIT(std::is_convertible, const SizeType&, + index_type) && + MDSPAN_IMPL_TRAIT(std::is_nothrow_constructible, + index_type, const SizeType&))) + MDSPAN_FORCE_INLINE_FUNCTION constexpr bool is_index_oor( + SizeType index, index_type extent) const noexcept { // Check for negative indices - if MDSPAN_IMPL_IF_CONSTEXPR_17 (MDSPAN_IMPL_TRAIT(std::is_signed, SizeType)) { - if(index < 0) { + if MDSPAN_IMPL_IF_CONSTEXPR_17 (MDSPAN_IMPL_TRAIT(std::is_signed, + SizeType)) { + if (index < 0) { return true; } } @@ -448,54 +483,66 @@ class mdspan template friend class mdspan; - }; #if defined(MDSPAN_IMPL_USE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION) MDSPAN_TEMPLATE_REQUIRES( - class ElementType, class... SizeTypes, - /* requires */ MDSPAN_IMPL_FOLD_AND(MDSPAN_IMPL_TRAIT(std::is_convertible, SizeTypes, size_t) /* && ... */) && - (sizeof...(SizeTypes) > 0) -) -MDSPAN_DEDUCTION_GUIDE explicit mdspan(ElementType*, SizeTypes...) - -> mdspan>; - -MDSPAN_TEMPLATE_REQUIRES( - class Pointer, - (MDSPAN_IMPL_TRAIT(std::is_pointer, std::remove_reference_t)) -) -MDSPAN_DEDUCTION_GUIDE mdspan(Pointer&&) -> mdspan>, extents>; - -MDSPAN_TEMPLATE_REQUIRES( - class CArray, - (MDSPAN_IMPL_TRAIT(std::is_array, CArray) && (std::rank_v == 1)) -) -MDSPAN_DEDUCTION_GUIDE mdspan(CArray&) -> mdspan, extents>>; + class ElementType, class... SizeTypes, + /* requires */ + MDSPAN_IMPL_FOLD_AND(MDSPAN_IMPL_TRAIT(std::is_convertible, SizeTypes, + size_t) /* && ... */) && + (sizeof...(SizeTypes) > 0)) +MDSPAN_DEDUCTION_GUIDE explicit mdspan(ElementType*, SizeTypes...) -> mdspan< + ElementType, + ::MDSPAN_IMPL_STANDARD_NAMESPACE::dextents>; + +MDSPAN_TEMPLATE_REQUIRES(class Pointer, + (MDSPAN_IMPL_TRAIT(std::is_pointer, + std::remove_reference_t))) +MDSPAN_DEDUCTION_GUIDE mdspan(Pointer&&) + -> mdspan>, + extents>; + +MDSPAN_TEMPLATE_REQUIRES(class CArray, + (MDSPAN_IMPL_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>; + -> mdspan>; #ifdef __cpp_lib_span template MDSPAN_DEDUCTION_GUIDE mdspan(ElementType*, ::std::span) - -> mdspan>; + -> 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. +// 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>; +MDSPAN_DEDUCTION_GUIDE mdspan(ElementType*, + const extents&) + -> mdspan>; template MDSPAN_DEDUCTION_GUIDE mdspan(ElementType*, const MappingType&) - -> mdspan; + -> mdspan; template -MDSPAN_DEDUCTION_GUIDE mdspan(const typename AccessorType::data_handle_type, const MappingType&, const AccessorType&) - -> mdspan; +MDSPAN_DEDUCTION_GUIDE mdspan(const typename AccessorType::data_handle_type, + const MappingType&, const AccessorType&) + -> mdspan; #endif -} // end namespace MDSPAN_IMPL_STANDARD_NAMESPACE +} // end namespace MDSPAN_IMPL_STANDARD_NAMESPACE diff --git a/include/mdspan/impl/no_unique_address.hpp b/include/mdspan/impl/no_unique_address.hpp index 1a4af56f..ae9f5235 100644 --- a/include/mdspan/impl/no_unique_address.hpp +++ b/include/mdspan/impl/no_unique_address.hpp @@ -30,19 +30,19 @@ template struct no_unique_address_emulation< T, Disambiguator, std::enable_if_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_IMPL_TRAIT(std::is_trivially_destructible, T)>> : #ifdef MDSPAN_IMPL_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. + // 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 { @@ -63,23 +63,24 @@ struct no_unique_address_emulation< constexpr no_unique_address_emulation( no_unique_address_emulation &&) noexcept = default; MDSPAN_INLINE_FUNCTION_DEFAULTED - MDSPAN_IMPL_CONSTEXPR_14_DEFAULTED no_unique_address_emulation & - operator=(no_unique_address_emulation const &) noexcept = default; + MDSPAN_IMPL_CONSTEXPR_14_DEFAULTED no_unique_address_emulation &operator=( + no_unique_address_emulation const &) noexcept = default; MDSPAN_INLINE_FUNCTION_DEFAULTED - MDSPAN_IMPL_CONSTEXPR_14_DEFAULTED no_unique_address_emulation & - operator=(no_unique_address_emulation &&) noexcept = default; + MDSPAN_IMPL_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) {} + 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)) {} + explicit constexpr no_unique_address_emulation(T &&v) noexcept + : T(::std::move(v)) {} }; //============================================================================== -} // end namespace detail -} // end namespace MDSPAN_IMPL_STANDARD_NAMESPACE +} // end namespace detail +} // end namespace MDSPAN_IMPL_STANDARD_NAMESPACE diff --git a/include/mdspan/impl/strided_slice.hpp b/include/mdspan/impl/strided_slice.hpp index c1dcd8a5..15ec2d81 100644 --- a/include/mdspan/impl/strided_slice.hpp +++ b/include/mdspan/impl/strided_slice.hpp @@ -13,27 +13,25 @@ namespace MDSPAN_IMPL_STANDARD_NAMESPACE { namespace detail { - template - struct is_signed_or_unsigned_integral_constant_like : std::false_type {}; +template +struct is_signed_or_unsigned_integral_constant_like : std::false_type {}; - template - struct is_signed_or_unsigned_integral_constant_like< - T, std::enable_if_t> - > : std::bool_constant< - std::is_integral_v> && - ! std::is_same_v> - > - {}; +template +struct is_signed_or_unsigned_integral_constant_like< + T, std::enable_if_t>> + : std::bool_constant< + std::is_integral_v> && + !std::is_same_v>> {}; - template - constexpr bool is_signed_or_unsigned_integral_constant_like_v = +template +constexpr bool is_signed_or_unsigned_integral_constant_like_v = is_signed_or_unsigned_integral_constant_like::value; - template - constexpr bool mdspan_is_index_like_v = - (std::is_integral_v && ! std::is_same_v) || +template +constexpr bool mdspan_is_index_like_v = + (std::is_integral_v && !std::is_same_v) || is_signed_or_unsigned_integral_constant_like_v; -} // namespace detail +} // namespace detail // Slice Specifier allowing for strides and compile time extent template @@ -51,7 +49,8 @@ struct extent_slice { static_assert(detail::mdspan_is_index_like_v); }; -template> +template > struct range_slice { MDSPAN_IMPL_NO_UNIQUE_ADDRESS FirstType first{}; MDSPAN_IMPL_NO_UNIQUE_ADDRESS LastType last{}; @@ -62,4 +61,4 @@ struct range_slice { static_assert(detail::mdspan_is_index_like_v); }; -} // MDSPAN_IMPL_STANDARD_NAMESPACE +} // namespace MDSPAN_IMPL_STANDARD_NAMESPACE diff --git a/include/mdspan/impl/submdspan.hpp b/include/mdspan/impl/submdspan.hpp index 4e050cc6..2740eb87 100644 --- a/include/mdspan/impl/submdspan.hpp +++ b/include/mdspan/impl/submdspan.hpp @@ -10,22 +10,24 @@ namespace MDSPAN_IMPL_STANDARD_NAMESPACE { template -MDSPAN_INLINE_FUNCTION -constexpr auto -submdspan(const mdspan &src, - SliceSpecifiers... slices) { - detail::check_submdspan_slice_mandates(std::make_index_sequence(), slices...); +MDSPAN_INLINE_FUNCTION constexpr auto submdspan( + const mdspan &src, + SliceSpecifiers... slices) { + detail::check_submdspan_slice_mandates( + std::make_index_sequence(), slices...); - const auto sub_submdspan_mapping_result = submdspan_mapping(src.mapping(), - detail::canonical_slice(slices)...); + const auto sub_submdspan_mapping_result = submdspan_mapping( + src.mapping(), + detail::canonical_slice(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_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())); + 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 +} // namespace MDSPAN_IMPL_STANDARD_NAMESPACE diff --git a/include/mdspan/impl/submdspan_canonicalize_slices.hpp b/include/mdspan/impl/submdspan_canonicalize_slices.hpp index c0d9f0b5..85ecaa70 100644 --- a/include/mdspan/impl/submdspan_canonicalize_slices.hpp +++ b/include/mdspan/impl/submdspan_canonicalize_slices.hpp @@ -13,65 +13,50 @@ namespace MDSPAN_IMPL_STANDARD_NAMESPACE { namespace detail { // Helper for identifying extent_slice and range_slice -template struct is_extent_slice : std::false_type {}; +template +struct is_extent_slice : std::false_type {}; template -struct is_extent_slice< - extent_slice> : std::true_type {}; +struct is_extent_slice> + : std::true_type {}; -template struct is_range_slice : std::false_type {}; +template +struct is_range_slice : std::false_type {}; -template -struct is_range_slice< - range_slice> : std::true_type {}; +template +struct is_range_slice> + : std::true_type {}; // ============================================================ // de_ice: extract the value of an integral-constant-like type // ============================================================ -MDSPAN_TEMPLATE_REQUIRES( - class T, - /* requires */ (std::is_integral_v>) -) +MDSPAN_TEMPLATE_REQUIRES(class T, + /* requires */ (std::is_integral_v>)) MDSPAN_INLINE_FUNCTION -constexpr T de_ice(T val) { - return val; -} +constexpr T de_ice(T val) { return val; } MDSPAN_TEMPLATE_REQUIRES( - class T, - /* requires */ (is_integral_constant_like_v>) -) + class T, + /* requires */ (is_integral_constant_like_v>)) MDSPAN_INLINE_FUNCTION -constexpr decltype(T::value) de_ice([[maybe_unused]] T) { - return T::value; -} +constexpr decltype(T::value) de_ice([[maybe_unused]] T) { return T::value; } // ============================================================ // index_cast: cast to IndexType, preserving integral-constant nature // ============================================================ -MDSPAN_TEMPLATE_REQUIRES( - class IndexType, - class OtherIndexType, - /* requires */ ( - std::is_signed_v> || - std::is_unsigned_v> - ) -) +MDSPAN_TEMPLATE_REQUIRES(class IndexType, class OtherIndexType, + /* requires */ + (std::is_signed_v> || + std::is_unsigned_v>)) MDSPAN_INLINE_FUNCTION -constexpr auto index_cast(OtherIndexType&& i) noexcept { - return i; -} +constexpr auto index_cast(OtherIndexType&& i) noexcept { return i; } -MDSPAN_TEMPLATE_REQUIRES( - class IndexType, - class OtherIndexType, - /* requires */ ( - ! std::is_signed_v> && - ! std::is_unsigned_v> - ) -) +MDSPAN_TEMPLATE_REQUIRES(class IndexType, class OtherIndexType, + /* requires */ + (!std::is_signed_v> && + !std::is_unsigned_v>)) MDSPAN_INLINE_FUNCTION constexpr auto index_cast(OtherIndexType&& i) noexcept { return static_cast(std::forward(i)); @@ -82,11 +67,8 @@ constexpr auto index_cast(OtherIndexType&& i) noexcept { // preserving integral-constant nature when possible // ============================================================ -MDSPAN_TEMPLATE_REQUIRES( - class IndexType, - class S, - /* requires */ (std::is_convertible_v) -) +MDSPAN_TEMPLATE_REQUIRES(class IndexType, class S, + /* requires */ (std::is_convertible_v)) MDSPAN_INLINE_FUNCTION constexpr auto canonical_index([[maybe_unused]] S s) { // TODO: might move to public semi/public only to get error earlier, and @@ -96,8 +78,7 @@ constexpr auto canonical_index([[maybe_unused]] S s) { static_assert(std::is_signed_v || std::is_unsigned_v); if constexpr (is_integral_constant_like_v) { return cw(index_cast(S::value))>; - } - else { + } else { return static_cast(index_cast(std::move(s))); } } @@ -107,16 +88,14 @@ constexpr auto canonical_index([[maybe_unused]] S s) { // nature when both inputs are integral-constant-like // ============================================================ -template -MDSPAN_INLINE_FUNCTION -constexpr auto subtract_ice([[maybe_unused]] X x, [[maybe_unused]] Y y) { - if constexpr ( - is_integral_constant_like_v> && - is_integral_constant_like_v>) - { - return cw(Y::value) - canonical_index(X::value))>; - } - else { +template +MDSPAN_INLINE_FUNCTION constexpr auto subtract_ice([[maybe_unused]] X x, + [[maybe_unused]] Y y) { + if constexpr (is_integral_constant_like_v> && + is_integral_constant_like_v>) { + return cw(Y::value) - + canonical_index(X::value))>; + } else { return canonical_index(y) - canonical_index(x); } } @@ -129,100 +108,82 @@ constexpr auto subtract_ice([[maybe_unused]] X x, [[maybe_unused]] Y y) { // This function is called only in static_assert contexts. // ============================================================ -template -constexpr bool check_static_bounds() -{ +template +constexpr bool check_static_bounds() { if constexpr (std::is_convertible_v) { return true; - } - else if constexpr (std::is_convertible_v) { + } else if constexpr (std::is_convertible_v) { if constexpr (is_integral_constant_like_v) { if constexpr (de_ice(S_k{}) < 0) { return false; - } - else if constexpr ( - Exts_k != dynamic_extent && - Exts_k <= static_cast(de_ice(S_k{}))) - { + } else if constexpr (Exts_k != dynamic_extent && + Exts_k <= static_cast(de_ice(S_k{}))) { return false; + } else { + return true; } - else { return true; } } else { return true; } - } - else if constexpr (is_extent_slice::value) { + } else if constexpr (is_extent_slice::value) { using offset_type = typename S_k::offset_type; if constexpr (is_integral_constant_like_v) { if constexpr (de_ice(offset_type{}) < 0) { return false; - } - else if constexpr ( - Exts_k != dynamic_extent && - Exts_k < static_cast(de_ice(offset_type{}))) - { + } else if constexpr (Exts_k != dynamic_extent && + Exts_k < + static_cast(de_ice(offset_type{}))) { return false; - } - else if constexpr (is_integral_constant_like_v) { + } else if constexpr (is_integral_constant_like_v< + typename S_k::extent_type>) { using extent_type = typename S_k::extent_type; if constexpr (de_ice(offset_type{}) + de_ice(extent_type{}) < 0) { return false; - } - else if constexpr ( - Exts_k != dynamic_extent && - Exts_k < - static_cast(de_ice(offset_type{}) + de_ice(extent_type{}))) - { + } else if constexpr (Exts_k != dynamic_extent && + Exts_k < + static_cast(de_ice(offset_type{}) + + de_ice(extent_type{}))) { return false; - } - else if constexpr ( - Exts_k != dynamic_extent && - 0 <= de_ice(offset_type{}) && - de_ice(offset_type{}) <= - de_ice(offset_type{}) + de_ice(extent_type{}) && - static_cast( - de_ice(offset_type{}) + de_ice(extent_type{})) <= Exts_k) - { + } else if constexpr (Exts_k != dynamic_extent && + 0 <= de_ice(offset_type{}) && + de_ice(offset_type{}) <= + de_ice(offset_type{}) + + de_ice(extent_type{}) && + static_cast(de_ice(offset_type{}) + + de_ice(extent_type{})) <= + Exts_k) { return true; - } - else { + } else { return true; } - } - else { + } else { return true; } - } - else { + } else { return true; } } else if constexpr (is_range_slice::value) { using first_type = decltype(std::declval().first); - using last_type = decltype(std::declval().last); + using last_type = decltype(std::declval().last); if constexpr (is_integral_constant_like_v) { if constexpr (de_ice(first_type{}) < 0) { return false; - } - else if constexpr ( - Exts_k != dynamic_extent && - Exts_k < static_cast(de_ice(first_type{}))) - { + } else if constexpr (Exts_k != dynamic_extent && + Exts_k < static_cast(de_ice(first_type{}))) { return false; } } if constexpr (is_integral_constant_like_v) { - if constexpr ((is_integral_constant_like_v && (de_ice(first_type()) > de_ice(last_type{}))) - || de_ice(last_type{}) < 0) { + if constexpr ((is_integral_constant_like_v && + (de_ice(first_type()) > de_ice(last_type{}))) || + de_ice(last_type{}) < 0) { return false; - } - else if constexpr ( - Exts_k != dynamic_extent && - Exts_k < static_cast(de_ice(last_type{}))) - { + } else if constexpr (Exts_k != dynamic_extent && + Exts_k < static_cast(de_ice(last_type{}))) { return false; } } @@ -234,11 +195,11 @@ constexpr bool check_static_bounds() // which implements the Mandates clause. // Doing this via these lambdas since we can do the declval only in a // non-evaluated context - auto get_first = [] (S_k s_k) { + auto get_first = [](S_k s_k) { auto [s_k0, _x] = s_k; return s_k0; }; - auto get_second = [] (S_k s_k) { + auto get_second = [](S_k s_k) { auto [_x, s_k1] = s_k; return s_k1; }; @@ -248,40 +209,26 @@ constexpr bool check_static_bounds() if constexpr (is_integral_constant_like_v) { if constexpr (de_ice(S_k0{}) < 0) { return false; - } - else if constexpr ( - Exts_k != dynamic_extent && - Exts_k < static_cast(de_ice(S_k0{}))) - { + } else if constexpr (Exts_k != dynamic_extent && + Exts_k < static_cast(de_ice(S_k0{}))) { return false; - } - else if constexpr (is_integral_constant_like_v) { + } else if constexpr (is_integral_constant_like_v) { if constexpr (de_ice(S_k1{}) < de_ice(S_k0{})) { return false; - } - else if constexpr ( - Exts_k != dynamic_extent && - Exts_k < static_cast(de_ice(S_k1{}))) - { + } else if constexpr (Exts_k != dynamic_extent && + Exts_k < static_cast(de_ice(S_k1{}))) { return false; - } - else if constexpr ( - Exts_k != dynamic_extent && - 0 <= de_ice(S_k0{}) && - de_ice(S_k0{}) <= de_ice(S_k1{}) && - static_cast(de_ice(S_k1{})) <= Exts_k) - { + } else if constexpr (Exts_k != dynamic_extent && 0 <= de_ice(S_k0{}) && + de_ice(S_k0{}) <= de_ice(S_k1{}) && + static_cast(de_ice(S_k1{})) <= Exts_k) { return true; - } - else { + } else { return true; } - } - else { + } else { return true; } - } - else { + } else { return true; } } @@ -295,86 +242,76 @@ constexpr bool check_static_bounds() // mandate checking and canonicalization are distinct concerns. // ============================================================ -template -MDSPAN_INLINE_FUNCTION -constexpr bool check_submdspan_slice_mandate( - [[maybe_unused]] const Slice&) -{ +template +MDSPAN_INLINE_FUNCTION constexpr bool check_submdspan_slice_mandate( + [[maybe_unused]] const Slice&) { static_assert(check_static_bounds()); return true; } -template -MDSPAN_INLINE_FUNCTION -constexpr bool check_submdspan_slice_mandates( - const std::index_sequence& , - [[maybe_unused]] const Slices& ... slices) -{ - return (check_submdspan_slice_mandate(slices) && ... && true); +template +MDSPAN_INLINE_FUNCTION constexpr bool check_submdspan_slice_mandates( + const std::index_sequence&, + [[maybe_unused]] const Slices&... slices) { + return (check_submdspan_slice_mandate( + slices) && + ... && true); } - -template -struct calculate_extents -{ - static constexpr IndexType value(SpanType span, StrideType stride) - { - return static_cast(span != 0 ? 1 + divide(span - 1, stride) : 0); +template +struct calculate_extents { + static constexpr IndexType value(SpanType span, StrideType stride) { + return static_cast( + span != 0 ? 1 + divide(span - 1, stride) : 0); } }; -template -struct calculate_extents, constant_wrapper> -{ - static constexpr auto value(constant_wrapper, constant_wrapper) - { - return cw(Span != 0 ? 1 + divide(Span - 1, Stride) : 0)>; +template +struct calculate_extents, + constant_wrapper> { + static constexpr auto value(constant_wrapper, + constant_wrapper) { + return cw( + Span != 0 ? 1 + divide(Span - 1, Stride) : 0)>; } }; - -template -struct calculate_stride -{ - template< class SpanType > - static constexpr auto value(SpanType span, StrideType stride) - { +template +struct calculate_stride { + template + static constexpr auto value(SpanType span, StrideType stride) { return span != 0 ? stride : IndexType(1); } }; -template -struct calculate_stride> -{ - template< class SpanType > - static constexpr auto value(SpanType, constant_wrapper) - { +template +struct calculate_stride> { + template + static constexpr auto value(SpanType, constant_wrapper) { return cw; } }; - // Some compilers do not do ctad properly with canonical_range_slice -template -constexpr extent_slice -make_extent_slice(OffsetType offset, ExtentType extent, StrideType stride) -{ - return extent_slice{offset, extent, stride}; +template +constexpr extent_slice make_extent_slice( + OffsetType offset, ExtentType extent, StrideType stride) { + return extent_slice{offset, extent, + stride}; } -template -constexpr auto canonical_range_slice(OffsetType offset, SpanType span, StrideType stride) -{ +template +constexpr auto canonical_range_slice(OffsetType offset, SpanType span, + StrideType stride) { return make_extent_slice( - offset, - calculate_extents::value(span, stride), - calculate_stride::value(span, stride) - ); + offset, + calculate_extents::value(span, stride), + calculate_stride::value(span, stride)); } -template -constexpr auto canonical_range_slice(OffsetType offset, SpanType span) -{ +template +constexpr auto canonical_range_slice(OffsetType offset, SpanType span) { return canonical_range_slice(offset, span, cw); } @@ -389,40 +326,33 @@ constexpr auto canonical_range_slice(OffsetType offset, SpanType span) // Neither k nor the extents are needed for the actual conversion. // ============================================================ -template -MDSPAN_INLINE_FUNCTION -constexpr auto canonical_slice([[maybe_unused]] Slice s) -{ +template +MDSPAN_INLINE_FUNCTION constexpr auto canonical_slice( + [[maybe_unused]] Slice s) { if constexpr (std::is_convertible_v) { - return full_extent; // canonical full-extent slice - } - else if constexpr (std::is_convertible_v) { - return canonical_index(std::move(s)); // canonical integer index - } - else if constexpr (is_extent_slice::value) { + return full_extent; // canonical full-extent slice + } else if constexpr (std::is_convertible_v) { + return canonical_index(std::move(s)); // canonical integer index + } else if constexpr (is_extent_slice::value) { // Canonicalize each component of the strided_slice auto offset = canonical_index(s.offset); auto extent = canonical_index(s.extent); auto stride = canonical_index(s.stride); return extent_slice{ - /* .offset = */ offset, - /* .extent = */ extent, - /* .stride = */ stride - }; - } - else if constexpr (is_range_slice::value) { + /* .offset = */ offset, + /* .extent = */ extent, + /* .stride = */ stride}; + } else if constexpr (is_range_slice::value) { auto c_first = canonical_index(std::move(s.first)); - auto c_last = canonical_index(std::move(s.last)); + auto c_last = canonical_index(std::move(s.last)); return canonical_range_slice( - c_first, - subtract_ice(c_first, c_last), - canonical_index(std::move(s.stride)) - ); + c_first, subtract_ice(c_first, c_last), + canonical_index(std::move(s.stride))); } else { // General pair-like case: structured binding into [first, last) auto [s_k0, s_k1] = std::move(s); - using S_k0 = decltype(s_k0); - using S_k1 = decltype(s_k1); + using S_k0 = decltype(s_k0); + using S_k1 = decltype(s_k1); static_assert(std::is_convertible_v); static_assert(std::is_convertible_v); @@ -430,10 +360,9 @@ constexpr auto canonical_slice([[maybe_unused]] Slice s) auto extent = subtract_ice(s_k0, s_k1); auto stride = cw; return extent_slice{ - /* .offset = */ offset, - /* .extent = */ extent, - /* .stride = */ stride - }; + /* .offset = */ offset, + /* .extent = */ extent, + /* .stride = */ stride}; } } @@ -446,29 +375,23 @@ constexpr auto canonical_slice([[maybe_unused]] Slice s) // code compatibility (e.g., CUDA). // ============================================================ -MDSPAN_TEMPLATE_REQUIRES( - size_t... Inds, - class Extents, - class... Slices, - /* requires */ (sizeof...(Slices) == Extents::rank()) -) +MDSPAN_TEMPLATE_REQUIRES(size_t... Inds, class Extents, class... Slices, + /* requires */ (sizeof...(Slices) == Extents::rank())) MDSPAN_INLINE_FUNCTION -constexpr auto canonical_slices_impl( - std::index_sequence, - const Extents&, - Slices... slices) -{ +constexpr auto canonical_slices_impl(std::index_sequence, + const Extents&, Slices... slices) { // Mandate checks (static_asserts only, no computation). // Separated from canonicalization for clarity. - (void)(check_submdspan_slice_mandate(slices) && ... && true); + (void)(check_submdspan_slice_mandate(slices) && + ... && true); // Actual canonicalization: returns detail::tuple for device compatibility. return detail::tuple{ - canonical_slice(slices)... - }; + canonical_slice(slices)...}; } -} // namespace detail +} // namespace detail // ============================================================ // canonicalize_slices: public API @@ -482,20 +405,15 @@ constexpr auto canonical_slices_impl( // ============================================================ MDSPAN_TEMPLATE_REQUIRES( - class IndexType, - size_t... Extents, - class... Slices, - /* requires */ (sizeof...(Slices) == sizeof...(Extents)) -) + class IndexType, size_t... Extents, class... Slices, + /* requires */ (sizeof...(Slices) == sizeof...(Extents))) MDSPAN_INLINE_FUNCTION -constexpr auto canonical_slices( - const extents& exts, - Slices... slices) -{ +constexpr auto canonical_slices(const extents& exts, + Slices... slices) { return detail::canonical_slices_impl( - std::make_index_sequence(), exts, slices...); + std::make_index_sequence(), exts, slices...); } -#endif // MDSPAN_HAS_CXX_17 +#endif // MDSPAN_HAS_CXX_17 -} // namespace MDSPAN_IMPL_STANDARD_NAMESPACE +} // namespace MDSPAN_IMPL_STANDARD_NAMESPACE diff --git a/include/mdspan/impl/submdspan_extents.hpp b/include/mdspan/impl/submdspan_extents.hpp index 44b883d3..7fcbc5cc 100644 --- a/include/mdspan/impl/submdspan_extents.hpp +++ b/include/mdspan/impl/submdspan_extents.hpp @@ -16,50 +16,48 @@ namespace detail { // 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) { +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>; +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...); + return inv_map_rank(std::integral_constant(), + next_idx_seq_t(), slices...); } // first_of(slice): getting begin of slice specifier range MDSPAN_TEMPLATE_REQUIRES( - class Integral, - /* requires */(std::is_convertible_v) -) + class Integral, + /* requires */ (std::is_convertible_v)) MDSPAN_INLINE_FUNCTION -constexpr Integral first_of(const Integral &i) { - return i; -} +constexpr Integral first_of(const Integral &i) { return i; } -template -MDSPAN_INLINE_FUNCTION -constexpr auto first_of(const constant_wrapper&) { +template +MDSPAN_INLINE_FUNCTION constexpr auto first_of( + const constant_wrapper &) { return constant_wrapper(); } MDSPAN_INLINE_FUNCTION -constexpr integral_constant -first_of(const ::MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent_t &) { +constexpr integral_constant first_of( + const ::MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent_t &) { return integral_constant(); } template -MDSPAN_INLINE_FUNCTION -constexpr OffsetType -first_of(const extent_slice &r) { +MDSPAN_INLINE_FUNCTION constexpr OffsetType first_of( + const extent_slice &r) { return r.offset; } @@ -68,12 +66,11 @@ first_of(const extent_slice &r) { // 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) -) + 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) { +constexpr Integral last_of(std::integral_constant, const Extents &, + const Integral &i) { return i; } @@ -83,23 +80,23 @@ constexpr Integral // 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 +#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 +#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) { +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 { @@ -111,42 +108,40 @@ constexpr auto last_of(std::integral_constant, const Extents &ext, #endif } #if defined __NVCC__ - #ifdef __NVCC_DIAG_PRAGMA_SUPPORT__ - #pragma nv_diagnostic pop - #else - #ifdef __CUDA_ARCH__ - #pragma diagnostic pop - #endif - #endif +#ifdef __NVCC_DIAG_PRAGMA_SUPPORT__ +#pragma nv_diagnostic pop +#else +#ifdef __CUDA_ARCH__ +#pragma diagnostic pop +#endif +#endif #elif defined __NVCOMPILER - #pragma diagnostic pop +#pragma diagnostic pop #endif template -MDSPAN_INLINE_FUNCTION -constexpr OffsetType -last_of(std::integral_constant, const Extents &, - const extent_slice &r) { +MDSPAN_INLINE_FUNCTION constexpr OffsetType last_of( + std::integral_constant, const Extents &, + const extent_slice &r) { return r.extent; } // get stride of slices template -MDSPAN_INLINE_FUNCTION -constexpr auto stride_of(const T &) { +MDSPAN_INLINE_FUNCTION constexpr auto stride_of(const T &) { return integral_constant(); } template -MDSPAN_INLINE_FUNCTION -constexpr auto -stride_of(const extent_slice &r) { +MDSPAN_INLINE_FUNCTION constexpr auto stride_of( + const extent_slice &r) { return r.stride; } // compute new static extent from range, preserving static knowledge -template struct StaticExtentFromRange { +template +struct StaticExtentFromRange { constexpr static size_t value = dynamic_extent; }; @@ -164,17 +159,21 @@ struct StaticExtentFromRange, // compute new static extent from strided_slice, preserving static // knowledge -template struct StaticExtentFromStridedRange { +template +struct StaticExtentFromStridedRange { constexpr static size_t value = dynamic_extent; }; -template -struct StaticExtentFromStridedRange, - std::integral_constant> { +template +struct StaticExtentFromStridedRange< + std::integral_constant, + std::integral_constant> { constexpr static size_t value = Extent; }; -template +template struct StaticExtentFromStridedRange, integral_constant> { constexpr static size_t value = Extent; @@ -184,11 +183,10 @@ struct StaticExtentFromStridedRange, // 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_extent_slice::value) - ) + MDSPAN_TEMPLATE_REQUIRES(class Slice, class... SlicesAndExtents, + /* requires */ + (!std::is_convertible_v && + !is_extent_slice::value)) MDSPAN_INLINE_FUNCTION constexpr static auto next_extent(const Extents &ext, const Slice &sl, SlicesAndExtents... slices_and_extents) { @@ -203,15 +201,14 @@ struct 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(last_of(std::integral_constant(), + ext, sl)) - index_t(first_of(sl))); } MDSPAN_TEMPLATE_REQUIRES( - class Slice, class... SlicesAndExtents, - /* requires */ (std::is_convertible_v) - ) + 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) { @@ -221,52 +218,47 @@ struct extents_constructor { template - MDSPAN_INLINE_FUNCTION - constexpr static auto - next_extent(const Extents &ext, - const extent_slice &r, - SlicesAndExtents... slices_and_extents) { + MDSPAN_INLINE_FUNCTION constexpr static auto next_extent( + const Extents &ext, + const extent_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); + return next_t::next_extent(ext, slices_and_extents..., r.extent); } 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()))); + 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) { + MDSPAN_INLINE_FUNCTION constexpr static auto next_extent( + const Extents &, NewExtents... new_exts) { return extents( new_exts...); } }; -} // namespace detail +} // namespace detail // subextents creates new extents given src extents and submdspan slice // specifiers template -MDSPAN_INLINE_FUNCTION -constexpr auto subextents(const extents &src_exts, - SliceSpecifiers... slices) { - +MDSPAN_INLINE_FUNCTION constexpr auto subextents( + const extents &src_exts, SliceSpecifiers... slices) { using ext_t = extents; return detail::extents_constructor::next_extent( src_exts, detail::canonical_slice(slices)...); } -} // namespace MDSPAN_IMPL_STANDARD_NAMESPACE +} // namespace MDSPAN_IMPL_STANDARD_NAMESPACE diff --git a/include/mdspan/impl/submdspan_mapping.hpp b/include/mdspan/impl/submdspan_mapping.hpp index 00041b4f..dd26b9cf 100644 --- a/include/mdspan/impl/submdspan_mapping.hpp +++ b/include/mdspan/impl/submdspan_mapping.hpp @@ -5,7 +5,7 @@ #include #include -#include // index_sequence +#include // index_sequence #include "utility.hpp" // Suppress spurious warning with NVCC about no return statement. @@ -32,7 +32,8 @@ namespace MDSPAN_IMPL_STANDARD_NAMESPACE { //****************************************** // Return type of submdspan_mapping overloads //****************************************** -template struct submdspan_mapping_result { +template +struct submdspan_mapping_result { MDSPAN_IMPL_NO_UNIQUE_ADDRESS LayoutMapping mapping{}; size_t offset; }; @@ -45,8 +46,8 @@ namespace detail { // 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) { +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)) == @@ -55,72 +56,64 @@ one_slice_out_of_bounds(const IndexType &ext, const Slice &slice) { template -MDSPAN_INLINE_FUNCTION constexpr bool -any_slice_out_of_bounds_helper(std::index_sequence, - const extents &exts, - const Slices &... slices) { +MDSPAN_INLINE_FUNCTION constexpr bool any_slice_out_of_bounds_helper( + std::index_sequence, + const extents &exts, const Slices &...slices) { return MDSPAN_IMPL_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) { +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 -struct sub_strides -{ +template +struct sub_strides { T values[N > 0 ? N : 1]; }; template MDSPAN_INLINE_FUNCTION constexpr auto construct_sub_strides( const SrcMapping &src_mapping, std::index_sequence, - const MDSPAN_IMPL_STANDARD_NAMESPACE::detail::tuple &slices_stride_factor) { + const MDSPAN_IMPL_STANDARD_NAMESPACE::detail::tuple + &slices_stride_factor) { using index_type = typename SrcMapping::index_type; - return sub_strides{{ - (static_cast(src_mapping.stride(InvMapIdxs)) * - static_cast(get(slices_stride_factor)))...}}; + return sub_strides{ + {(static_cast(src_mapping.stride(InvMapIdxs)) * + static_cast(get(slices_stride_factor)))...}}; } -template +template constexpr bool is_range_like_slice_v = false; -template +template constexpr bool is_range_like_slice_v = true; -template +template constexpr bool is_range_like_slice_v< - extent_slice< - OffsetType, - ExtentType, - constant_wrapper>, - IndexType - > = (constant_wrapper::value == IndexType(1)); - -template + extent_slice>, IndexType> = + (constant_wrapper::value == IndexType(1)); + +template constexpr bool is_range_like_slice_v< - range_slice< - FirstType, - LastType, - constant_wrapper>, - IndexType - > = (constant_wrapper::value == IndexType(1)); - -template + range_slice>, IndexType> = + (constant_wrapper::value == IndexType(1)); + +template struct is_index_slice { - constexpr static bool value = std::is_convertible_v; + constexpr static bool value = + std::is_convertible_v; }; -template -constexpr bool is_index_slice_v = is_index_slice::value; +template +constexpr bool is_index_slice_v = + is_index_slice::value; -} // namespace detail +} // namespace detail //********************************** // layout_left submdspan_mapping @@ -136,7 +129,6 @@ 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)...>; @@ -152,16 +144,22 @@ struct deduce_layout_left_submapping< // 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 + // Use layout_left for rank 1 result if leftmost slice specifier is range + // like } else if constexpr (SubRank == 1) { - return ((Idx > 0 || is_range_like_slice_v)&&...); + return ( + (Idx > 0 || is_range_like_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_like_slice_v) || - ((Idx > SubRank - 1) && is_index_slice_v)) && ...); + return ((((Idx < SubRank - 1) && + std::is_same_v) || + ((Idx == SubRank - 1) && + is_range_like_slice_v) || + ((Idx > SubRank - 1) && + is_index_slice_v)) && + ...); } #if defined(__NVCC__) && !defined(__CUDA_ARCH__) && defined(__GNUC__) __builtin_unreachable(); @@ -181,27 +179,39 @@ struct deduce_layout_left_submapping< // 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_like_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_like_slice_v) || - ((Idx > gap_len + SubRank - 1) && is_index_slice_v)) && ... ); + return ( + (((Idx == 0) && is_range_like_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_like_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 -MDSPAN_INLINE_FUNCTION constexpr size_t -compute_s_static_layout_left(std::index_sequence) { +template +MDSPAN_INLINE_FUNCTION constexpr size_t compute_s_static_layout_left( + std::index_sequence) { // 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 - 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; - } + // 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 + 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 +} // namespace detail // Actual submdspan mapping call template @@ -209,20 +219,19 @@ template MDSPAN_INLINE_FUNCTION constexpr auto layout_left::mapping::submdspan_mapping_impl( SliceSpecifiers... slices) const { - // Implements mandate check - detail::check_submdspan_slice_mandates(std::make_index_sequence(), slices...); + detail::check_submdspan_slice_mandates( + std::make_index_sequence(), slices...); // compute sub extents using src_ext_t = Extents; - auto dst_ext = subextents(extents(), slices...); + auto dst_ext = subextents(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...>; + 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. @@ -238,8 +247,12 @@ layout_left::mapping::submdspan_mapping_impl( 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(std::make_index_sequence()); - using dst_mapping_t = typename layout_left_padded::template mapping; + constexpr size_t S_static = + MDSPAN_IMPL_STANDARD_NAMESPACE::detail::compute_s_static_layout_left< + Extents, deduce_layout::gap_len, Extents::static_extent(0)>( + std::make_index_sequence()); + using dst_mapping_t = + typename layout_left_padded::template mapping; return submdspan_mapping_result{ dst_mapping_t(dst_ext, stride(1 + deduce_layout::gap_len)), offset}; } else { @@ -257,9 +270,11 @@ layout_left::mapping::submdspan_mapping_impl( // disable it for CUDA altogether #if defined(MDSPAN_IMPL_HAS_HIP) || defined(MDSPAN_IMPL_HAS_CUDA) detail::tuple{ - detail::stride_of(slices)...}).values), + detail::stride_of(slices)...}) + .values), #else - detail::tuple{detail::stride_of(slices)...}).values), + detail::tuple{detail::stride_of(slices)...}) + .values), #endif offset }; @@ -275,80 +290,109 @@ template MDSPAN_INLINE_FUNCTION constexpr auto layout_left_padded::mapping::submdspan_mapping_impl( SliceSpecifiers... slices) const { - // Implements mandate check - detail::check_submdspan_slice_mandates(std::make_index_sequence(), slices...); + detail::check_submdspan_slice_mandates( + std::make_index_sequence(), slices...); // compute sub extents using src_ext_t = Extents; - auto dst_ext = subextents(extents(), slices...); + auto dst_ext = subextents(extents(), slices...); using dst_ext_t = decltype(dst_ext); - if constexpr (Extents::rank() == 0) { // rank-0 case - using dst_mapping_t = typename layout_left_padded::template mapping; + if constexpr (Extents::rank() == 0) { // rank-0 case + using dst_mapping_t = + typename 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...); + 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 + 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}; + // 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 + // 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>{ + 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 + // 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(std::make_index_sequence()); - using dst_mapping_t = typename layout_left_padded::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( + std::make_index_sequence()); + using dst_mapping_t = + typename 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(mdspan_non_standard_tag(), dst_ext, - MDSPAN_IMPL_STANDARD_NAMESPACE::detail::construct_sub_strides( - *this, inv_map, + 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( + mdspan_non_standard_tag(), 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_IMPL_HAS_HIP) || defined(MDSPAN_IMPL_HAS_CUDA) - MDSPAN_IMPL_STANDARD_NAMESPACE::detail::tuple{ - MDSPAN_IMPL_STANDARD_NAMESPACE::detail::stride_of(slices)...}).values), + MDSPAN_IMPL_STANDARD_NAMESPACE::detail::tuple< + decltype(MDSPAN_IMPL_STANDARD_NAMESPACE::detail:: + stride_of(slices))...>{ + MDSPAN_IMPL_STANDARD_NAMESPACE::detail::stride_of( + slices)...}) + .values), #else - MDSPAN_IMPL_STANDARD_NAMESPACE::detail::tuple{MDSPAN_IMPL_STANDARD_NAMESPACE::detail::stride_of(slices)...}).values), + MDSPAN_IMPL_STANDARD_NAMESPACE::detail::tuple{ + MDSPAN_IMPL_STANDARD_NAMESPACE::detail::stride_of( + slices)...}) + .values), #endif - offset - }; + offset + }; } } } - #if defined(__NVCC__) && !defined(__CUDA_ARCH__) && defined(__GNUC__) __builtin_unreachable(); #endif @@ -368,9 +412,8 @@ 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< + using count_range = index_sequence_scan_impl< 0u, (std::is_convertible_v ? 0u : 1u)...>; //__static_partial_sums...>; @@ -386,16 +429,22 @@ struct deduce_layout_right_submapping< // 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 + // 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_like_slice_v)&&...); + return ((Idx < Rank - 1 || + is_range_like_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_like_slice_v) || - ((Idx < Rank - SubRank) && is_index_slice_v)) && ...); + return ((((Idx >= Rank - SubRank) && + std::is_same_v) || + ((Idx == Rank - SubRank) && + is_range_like_slice_v) || + ((Idx < Rank - SubRank) && + is_index_slice_v)) && + ...); } #if defined(__NVCC__) && !defined(__CUDA_ARCH__) && defined(__GNUC__) __builtin_unreachable(); @@ -415,30 +464,42 @@ struct deduce_layout_right_submapping< // 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_like_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_like_slice_v) || - ((Idx < Rank - gap_len - SubRank) && is_index_slice_v)) && ... ); + return ((((Idx == Rank - 1) && + is_range_like_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_like_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 -MDSPAN_INLINE_FUNCTION constexpr size_t -compute_s_static_layout_right (std::index_sequence) { +template +MDSPAN_INLINE_FUNCTION constexpr size_t compute_s_static_layout_right( + std::index_sequence) { // 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 - // Note the condition was originally written as Idx >= Extents::rank() - 1 - NumGaps && Idx < Extents::rank() - 1 - // But that triggered CodeQL warnings. - size_t val = ((Idx + 1 + NumGaps >= Extents::rank() && Idx + 1 < Extents::rank() ? - (Extents::static_extent(Idx) == dynamic_extent?0:Extents::static_extent(Idx)) : 1) * ... * (StaticStride == dynamic_extent?0:StaticStride)); - return val == 0?dynamic_extent:val; - } + // 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 Note the condition was originally written as Idx >= + // Extents::rank() - 1 - NumGaps && Idx < Extents::rank() - 1 But that + // triggered CodeQL warnings. + size_t val = + ((Idx + 1 + NumGaps >= Extents::rank() && Idx + 1 < Extents::rank() + ? (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 +} // namespace detail // Actual submdspan mapping call template @@ -446,20 +507,19 @@ template MDSPAN_INLINE_FUNCTION constexpr auto layout_right::mapping::submdspan_mapping_impl( SliceSpecifiers... slices) const { - // Implements mandate check - detail::check_submdspan_slice_mandates(std::make_index_sequence(), slices...); + detail::check_submdspan_slice_mandates( + std::make_index_sequence(), slices...); // compute sub extents using src_ext_t = Extents; - auto dst_ext = subextents(extents(), slices...); + auto dst_ext = subextents(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...>; + 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. @@ -475,8 +535,13 @@ layout_right::mapping::submdspan_mapping_impl( 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(std::make_index_sequence()); - using dst_mapping_t = typename layout_right_padded::template mapping; + constexpr size_t S_static = + MDSPAN_IMPL_STANDARD_NAMESPACE::detail::compute_s_static_layout_left< + Extents, deduce_layout::gap_len, + Extents::static_extent(Extents::rank() - 1)>( + std::make_index_sequence()); + using dst_mapping_t = + typename layout_right_padded::template mapping; return submdspan_mapping_result{ dst_mapping_t(dst_ext, stride(src_ext_t::rank() - 2 - deduce_layout::gap_len)), @@ -495,10 +560,14 @@ layout_right::mapping::submdspan_mapping_impl( // the issue but Clang-CUDA also doesn't accept the use of deduction guide so // disable it for CUDA altogether #if defined(MDSPAN_IMPL_HAS_HIP) || defined(MDSPAN_IMPL_HAS_CUDA) - MDSPAN_IMPL_STANDARD_NAMESPACE::detail::tuple{ - detail::stride_of(slices)...}).values), + MDSPAN_IMPL_STANDARD_NAMESPACE::detail::tuple< + decltype(detail::stride_of(slices))...>{ + detail::stride_of(slices)...}) + .values), #else - MDSPAN_IMPL_STANDARD_NAMESPACE::detail::tuple{detail::stride_of(slices)...}).values), + MDSPAN_IMPL_STANDARD_NAMESPACE::detail::tuple{ + detail::stride_of(slices)...}) + .values), #endif offset }; @@ -514,72 +583,100 @@ template MDSPAN_INLINE_FUNCTION constexpr auto layout_right_padded::mapping::submdspan_mapping_impl( SliceSpecifiers... slices) const { - // Implements mandate check - detail::check_submdspan_slice_mandates(std::make_index_sequence(), slices...); + detail::check_submdspan_slice_mandates( + std::make_index_sequence(), slices...); // compute sub extents using src_ext_t = Extents; - auto dst_ext = subextents(extents(), slices...); + auto dst_ext = subextents(extents(), slices...); using dst_ext_t = decltype(dst_ext); - if constexpr (Extents::rank() == 0) { // rank-0 case - using dst_mapping_t = typename layout_right_padded::template mapping; + if constexpr (Extents::rank() == 0) { // rank-0 case + using dst_mapping_t = + typename 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...); + 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 + 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(std::make_index_sequence()); - using dst_mapping_t = typename layout_right_padded::template mapping; + // 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>{ + 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( + std::make_index_sequence()); + using dst_mapping_t = + typename 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(mdspan_non_standard_tag(), dst_ext, - MDSPAN_IMPL_STANDARD_NAMESPACE::detail::construct_sub_strides( - *this, inv_map, + 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( + mdspan_non_standard_tag(), 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_IMPL_HAS_HIP) || defined(MDSPAN_IMPL_HAS_CUDA) - MDSPAN_IMPL_STANDARD_NAMESPACE::detail::tuple{ - MDSPAN_IMPL_STANDARD_NAMESPACE::detail::stride_of(slices)...}).values), + MDSPAN_IMPL_STANDARD_NAMESPACE::detail::tuple< + decltype(MDSPAN_IMPL_STANDARD_NAMESPACE::detail:: + stride_of(slices))...>{ + MDSPAN_IMPL_STANDARD_NAMESPACE::detail::stride_of( + slices)...}) + .values), #else - MDSPAN_IMPL_STANDARD_NAMESPACE::detail::tuple{MDSPAN_IMPL_STANDARD_NAMESPACE::detail::stride_of(slices)...}).values), + MDSPAN_IMPL_STANDARD_NAMESPACE::detail::tuple{ + MDSPAN_IMPL_STANDARD_NAMESPACE::detail::stride_of( + slices)...}) + .values), #endif - offset - }; + offset + }; } } } - #if defined(__NVCC__) && !defined(__CUDA_ARCH__) && defined(__GNUC__) __builtin_unreachable(); #endif @@ -593,14 +690,14 @@ template MDSPAN_INLINE_FUNCTION constexpr auto layout_stride::mapping::submdspan_mapping_impl( SliceSpecifiers... slices) const { - // Implements mandate check - detail::check_submdspan_slice_mandates(std::make_index_sequence(), slices...); + detail::check_submdspan_slice_mandates( + std::make_index_sequence(), slices...); - auto dst_ext = subextents(extents(), slices...); + auto dst_ext = subextents(extents(), slices...); using dst_ext_t = decltype(dst_ext); - auto inv_map = detail::inv_map_rank(std::integral_constant(), - std::index_sequence<>(), slices...); + 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. @@ -620,16 +717,20 @@ layout_stride::mapping::submdspan_mapping_impl( // the issue but Clang-CUDA also doesn't accept the use of deduction guide so // disable it for CUDA alltogether #if defined(MDSPAN_IMPL_HAS_HIP) || defined(MDSPAN_IMPL_HAS_CUDA) - MDSPAN_IMPL_STANDARD_NAMESPACE::detail::tuple( - detail::stride_of(slices)...)).values), + MDSPAN_IMPL_STANDARD_NAMESPACE::detail::tuple< + decltype(detail::stride_of(slices))...>( + detail::stride_of(slices)...)) + .values), #else - MDSPAN_IMPL_STANDARD_NAMESPACE::detail::tuple(detail::stride_of(slices)...)).values), + MDSPAN_IMPL_STANDARD_NAMESPACE::detail::tuple( + detail::stride_of(slices)...)) + .values), #endif offset }; } -} // namespace MDSPAN_IMPL_STANDARD_NAMESPACE +} // namespace MDSPAN_IMPL_STANDARD_NAMESPACE #if defined __NVCC__ #ifdef __NVCC_DIAG_PRAGMA_SUPPORT__ diff --git a/include/mdspan/impl/trait_backports.hpp b/include/mdspan/impl/trait_backports.hpp index 96b24c3e..b281374f 100644 --- a/include/mdspan/impl/trait_backports.hpp +++ b/include/mdspan/impl/trait_backports.hpp @@ -8,7 +8,7 @@ #include "config.hpp" #include -#include // integer_sequence +#include // integer_sequence //============================================================================== // {{{1 @@ -18,8 +18,10 @@ #if MDSPAN_IMPL_USE_VARIABLE_TEMPLATES namespace MDSPAN_IMPL_STANDARD_NAMESPACE { -#define MDSPAN_IMPL_BACKPORT_TRAIT(TRAIT) \ - template MDSPAN_IMPL_INLINE_VARIABLE constexpr auto TRAIT##_v = TRAIT::value; +#define MDSPAN_IMPL_BACKPORT_TRAIT(TRAIT) \ + template \ + MDSPAN_IMPL_INLINE_VARIABLE constexpr auto TRAIT##_v = \ + TRAIT::value; MDSPAN_IMPL_BACKPORT_TRAIT(is_assignable) MDSPAN_IMPL_BACKPORT_TRAIT(is_constructible) @@ -32,11 +34,11 @@ MDSPAN_IMPL_BACKPORT_TRAIT(is_void) #undef MDSPAN_IMPL_BACKPORT_TRAIT -} // end namespace MDSPAN_IMPL_STANDARD_NAMESPACE +} // end namespace MDSPAN_IMPL_STANDARD_NAMESPACE -#endif // MDSPAN_IMPL_USE_VARIABLE_TEMPLATES +#endif // MDSPAN_IMPL_USE_VARIABLE_TEMPLATES -#endif // MDSPAN_IMPL_NEEDS_TRAIT_VARIABLE_TEMPLATE_BACKPORTS +#endif // MDSPAN_IMPL_NEEDS_TRAIT_VARIABLE_TEMPLATE_BACKPORTS // end Variable template trait backports (e.g., is_void_v) }}}1 //============================================================================== @@ -44,7 +46,8 @@ MDSPAN_IMPL_BACKPORT_TRAIT(is_void) //============================================================================== // {{{1 -#if !defined(MDSPAN_IMPL_USE_INTEGER_SEQUENCE_14) || !MDSPAN_IMPL_USE_INTEGER_SEQUENCE_14 +#if !defined(MDSPAN_IMPL_USE_INTEGER_SEQUENCE_14) || \ + !MDSPAN_IMPL_USE_INTEGER_SEQUENCE_14 namespace MDSPAN_IMPL_STANDARD_NAMESPACE { @@ -63,29 +66,29 @@ template struct __make_int_seq_impl; template -struct __make_int_seq_impl> -{ +struct __make_int_seq_impl> { using type = integer_sequence; }; template -struct __make_int_seq_impl< - T, N, I, integer_sequence -> : __make_int_seq_impl> -{ }; +struct __make_int_seq_impl> + : __make_int_seq_impl> {}; -} // end namespace __detail +} // end namespace __detail template -using make_integer_sequence = typename __detail::__make_int_seq_impl>::type; +using make_integer_sequence = + typename __detail::__make_int_seq_impl>::type; template -using make_index_sequence = typename __detail::__make_int_seq_impl>::type; +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 +} // end namespace MDSPAN_IMPL_STANDARD_NAMESPACE #endif @@ -95,26 +98,28 @@ using index_sequence_for = make_index_sequence; //============================================================================== // {{{1 -#if !defined(MDSPAN_IMPL_USE_STANDARD_TRAIT_ALIASES) || !MDSPAN_IMPL_USE_STANDARD_TRAIT_ALIASES +#if !defined(MDSPAN_IMPL_USE_STANDARD_TRAIT_ALIASES) || \ + !MDSPAN_IMPL_USE_STANDARD_TRAIT_ALIASES namespace MDSPAN_IMPL_STANDARD_NAMESPACE { #define MDSPAN_IMPL_BACKPORT_TRAIT_ALIAS(TRAIT) \ - template using TRAIT##_t = typename TRAIT::type; + template \ + using TRAIT##_t = typename TRAIT::type; MDSPAN_IMPL_BACKPORT_TRAIT_ALIAS(remove_cv) MDSPAN_IMPL_BACKPORT_TRAIT_ALIAS(remove_reference) -template +template using enable_if_t = typename enable_if<_B, T>::type; #undef MDSPAN_IMPL_BACKPORT_TRAIT_ALIAS -} // end namespace MDSPAN_IMPL_STANDARD_NAMESPACE +} // end namespace MDSPAN_IMPL_STANDARD_NAMESPACE #endif // end standard trait aliases }}}1 //============================================================================== -#endif //MDSPAN_INCLUDE_EXPERIMENTAL_BITS_TRAIT_BACKPORTS_HPP_ +#endif // MDSPAN_INCLUDE_EXPERIMENTAL_BITS_TRAIT_BACKPORTS_HPP_ diff --git a/include/mdspan/impl/type_list.hpp b/include/mdspan/impl/type_list.hpp index 3314e0e2..871f697f 100644 --- a/include/mdspan/impl/type_list.hpp +++ b/include/mdspan/impl/type_list.hpp @@ -3,7 +3,7 @@ #include "macros.hpp" -#include "trait_backports.hpp" // make_index_sequence +#include "trait_backports.hpp" // make_index_sequence namespace MDSPAN_IMPL_STANDARD_NAMESPACE { @@ -11,14 +11,19 @@ namespace MDSPAN_IMPL_STANDARD_NAMESPACE { namespace detail { -template struct type_list { static constexpr auto size = sizeof...(Ts); }; +template +struct type_list { + static constexpr auto size = sizeof...(Ts); +}; // Implementation of type_list at() that's heavily optimized for small typelists -template struct type_at; -template > struct type_at_large_impl; +template +struct type_at; +template > +struct type_at_large_impl; template -struct type_at_entry { }; +struct type_at_entry {}; template struct type_at_assign_op_ignore_rest { @@ -35,16 +40,15 @@ struct type_at_assign_op_impl { }; template -struct type_at_large_impl, std::integer_sequence> - : decltype( - MDSPAN_IMPL_FOLD_ASSIGN_LEFT(type_at_assign_op_impl{}, /* = ... = */ type_at_entry{}) - ) -{ }; +struct type_at_large_impl, + std::integer_sequence> + : decltype(MDSPAN_IMPL_FOLD_ASSIGN_LEFT( + type_at_assign_op_impl{}, + /* = ... = */ type_at_entry{})) {}; template -struct type_at> - : type_at_large_impl> -{ }; +struct type_at> : type_at_large_impl> { +}; template struct type_at<0, type_list> { @@ -66,9 +70,8 @@ struct type_at<3, type_list> { using type = T3; }; - -} // namespace detail +} // namespace detail //============================================================================== -} // end namespace MDSPAN_IMPL_STANDARD_NAMESPACE +} // end namespace MDSPAN_IMPL_STANDARD_NAMESPACE diff --git a/include/mdspan/impl/utility.hpp b/include/mdspan/impl/utility.hpp index 2cc6aefd..5c98caad 100644 --- a/include/mdspan/impl/utility.hpp +++ b/include/mdspan/impl/utility.hpp @@ -7,7 +7,8 @@ #include #include #include -#if defined(MDSPAN_IMPL_HAS_CUDA) && defined(__NVCC__) && (__CUDACC_VER_MAJOR__ * 100 + __CUDACC_VER_MINOR__ * 10 >= 1260) +#if defined(MDSPAN_IMPL_HAS_CUDA) && defined(__NVCC__) && \ + (__CUDACC_VER_MAJOR__ * 100 + __CUDACC_VER_MINOR__ * 10 >= 1260) #include #else #include @@ -19,11 +20,11 @@ namespace detail { // Backport of std::remove_cvref / std::remove_cvref_t (C++20) #if (__cplusplus >= 202002L) - using std::remove_cvref_t; +using std::remove_cvref_t; #else - template - using remove_cvref_t = std::remove_cv_t>; -#endif // __cplusplus >= 202002L +template +using remove_cvref_t = std::remove_cv_t >; +#endif // __cplusplus >= 202002L // type alias used for rank-based tag dispatch // @@ -33,27 +34,22 @@ 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, ""); +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) -{ +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) -{ +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++) { @@ -66,12 +62,9 @@ constexpr bool rankwise_equal(with_rank, const T1& x, const T2& y, F func) #if MDSPAN_HAS_CXX_17 inline #endif -constexpr struct extent_functor -{ + constexpr struct extent_functor { template - MDSPAN_INLINE_FUNCTION - constexpr auto operator()(const T& x, I i) const - { + MDSPAN_INLINE_FUNCTION constexpr auto operator()(const T& x, I i) const { return x.extent(i); } } extent; @@ -79,12 +72,9 @@ constexpr struct extent_functor #if MDSPAN_HAS_CXX_17 inline #endif -constexpr struct stride_functor -{ + constexpr struct stride_functor { template - MDSPAN_INLINE_FUNCTION - constexpr auto operator()(const T& x, I i) const - { + MDSPAN_INLINE_FUNCTION constexpr auto operator()(const T& x, I i) const { return x.stride(i); } } stride; @@ -93,8 +83,8 @@ constexpr struct stride_functor // the implicit conversion function and the call operator template struct integral_constant { - using value_type = T; - using type = integral_constant; + using value_type = T; + using type = integral_constant; static constexpr T value = v; @@ -104,10 +94,11 @@ struct integral_constant { // These interop functions work, because other than the value_type operator // everything of std::integral_constant works on device (defaulted functions) MDSPAN_FUNCTION - constexpr integral_constant(std::integral_constant) {} + constexpr integral_constant(std::integral_constant) {} - MDSPAN_FUNCTION constexpr operator std::integral_constant() const noexcept { - return std::integral_constant{}; + MDSPAN_FUNCTION constexpr operator std::integral_constant() + const noexcept { + return std::integral_constant{}; } MDSPAN_FUNCTION constexpr operator value_type() const noexcept { @@ -122,9 +113,9 @@ struct integral_constant { // The tuple implementation only comes in play when using capabilities // such as submdspan which require C++17 anyway #if MDSPAN_HAS_CXX_17 -template +template struct tuple_member { - using type = T; + using type = T; static constexpr size_t idx = Idx; T val; MDSPAN_FUNCTION constexpr T& get() { return val; } @@ -133,59 +124,66 @@ struct tuple_member { // A helper class which will be used via a fold expression to // select the type with the correct Idx in a pack of tuple_member -template +template struct tuple_idx_matcher { using type = tuple_member; - template - MDSPAN_FUNCTION - constexpr auto operator | ([[maybe_unused]] Other v) const { - if constexpr (Idx == SearchIdx) { return *this; } - else { return v; } + template + MDSPAN_FUNCTION constexpr auto operator|([[maybe_unused]] Other v) const { + if constexpr (Idx == SearchIdx) { + return *this; + } else { + return v; + } } }; -template +template struct tuple_impl; -template -struct tuple_impl, Elements...>: public tuple_member ... { - +template +struct tuple_impl, Elements...> + : public tuple_member... { MDSPAN_FUNCTION - constexpr tuple_impl(Elements ... vals):tuple_member{vals}... {} + constexpr tuple_impl(Elements... vals) + : tuple_member{vals}... {} - template - MDSPAN_FUNCTION - constexpr auto& get() { - using base_t = decltype((tuple_idx_matcher() | ...) ); + template + MDSPAN_FUNCTION constexpr auto& get() { + using base_t = decltype((tuple_idx_matcher() | ...)); return base_t::type::get(); } - template - MDSPAN_FUNCTION - constexpr const auto& get() const { - using base_t = decltype((tuple_idx_matcher() | ...) ); + template + MDSPAN_FUNCTION constexpr const auto& get() const { + using base_t = decltype((tuple_idx_matcher() | ...)); return base_t::type::get(); } }; -// A simple tuple-like class for representing slices internally and is compatible with device code -// This doesn't support type access since we don't need it -// This is not meant as an external API -template -struct tuple: public tuple_impl()), Elements...> { +// A simple tuple-like class for representing slices internally and is +// compatible with device code This doesn't support type access since we don't +// need it This is not meant as an external API +template +struct tuple : public tuple_impl< + decltype(std::make_index_sequence()), + Elements...> { MDSPAN_FUNCTION - constexpr tuple(Elements ... vals):tuple_impl()), Elements ...>(vals ...) {} + constexpr tuple(Elements... vals) + : tuple_impl()), + Elements...>(vals...) {} }; -template -MDSPAN_FUNCTION -constexpr auto& get(tuple& vals) { return vals.template get(); } +template +MDSPAN_FUNCTION constexpr auto& get(tuple& vals) { + return vals.template get(); +} -template -MDSPAN_FUNCTION -constexpr const auto& get(const tuple& vals) { return vals.template get(); } +template +MDSPAN_FUNCTION constexpr const auto& get(const tuple& vals) { + return vals.template get(); +} -template -tuple(Elements ...) -> tuple; +template +tuple(Elements...) -> tuple; #endif #if MDSPAN_HAS_CXX_17 @@ -216,91 +214,85 @@ template MDSPAN_INLINE_FUNCTION constexpr bool in_range(T t) noexcept { static_assert(std::is_integral_v && std::is_integral_v); -#if defined(MDSPAN_IMPL_HAS_CUDA) && defined(__NVCC__) && (__CUDACC_VER_MAJOR__ * 100 + __CUDACC_VER_MINOR__ * 10 >= 1260) +#if defined(MDSPAN_IMPL_HAS_CUDA) && defined(__NVCC__) && \ + (__CUDACC_VER_MAJOR__ * 100 + __CUDACC_VER_MINOR__ * 10 >= 1260) using cuda::std::numeric_limits; #else using std::numeric_limits; #endif return cmp_greater_equal(t, numeric_limits::min()) && - cmp_less_equal(t, numeric_limits::max()); + cmp_less_equal(t, numeric_limits::max()); } template -MDSPAN_INLINE_FUNCTION constexpr bool is_nonnegative_and_representable(T t) noexcept { +MDSPAN_INLINE_FUNCTION constexpr bool is_nonnegative_and_representable( + T t) noexcept { // T might not be integral and thus invalid to pass to in_range // Only check this if we can actually call in_range - if constexpr (std::is_integral_v) - { + if constexpr (std::is_integral_v) { if constexpr (std::is_signed_v) { - if (t < 0) - return false; + if (t < 0) return false; } return in_range(t); - } else - { + } else { if constexpr (std::is_signed_v) { - if (static_cast(t) < 0) - return false; + if (static_cast(t) < 0) return false; } return true; } } -template -MDSPAN_INLINE_FUNCTION constexpr bool -all_values_are_representable(Values... values) noexcept { - return ( in_range( values ) && ... ); +template +MDSPAN_INLINE_FUNCTION constexpr bool all_values_are_representable( + Values... values) noexcept { + return (in_range(values) && ...); } -template +template MDSPAN_INLINE_FUNCTION constexpr bool all_values_are_nonnegative_and_representable(Values... values) noexcept { - return ( is_nonnegative_and_representable( values ) && ... ); + return (is_nonnegative_and_representable(values) && ...); } -template -MDSPAN_INLINE_FUNCTION constexpr bool - range_is_nonnegative_and_representable(ContiguousIterator begin, ContiguousIterator end) noexcept { - for ( auto it = begin; it < end; ++it ) - { - if ( !is_nonnegative_and_representable( *it ) ) - return false; +template +MDSPAN_INLINE_FUNCTION constexpr bool range_is_nonnegative_and_representable( + ContiguousIterator begin, ContiguousIterator end) noexcept { + for (auto it = begin; it < end; ++it) { + if (!is_nonnegative_and_representable(*it)) return false; } return true; } -template -MDSPAN_INLINE_FUNCTION constexpr bool -extent_is_representable(const Extents &exts) noexcept { - for ( std::size_t r = 0; r < Extents::rank(); ++r ) - { - if ( !is_nonnegative_and_representable( exts.extent(r) ) ) - return false; +template +MDSPAN_INLINE_FUNCTION constexpr bool extent_is_representable( + const Extents& exts) noexcept { + for (std::size_t r = 0; r < Extents::rank(); ++r) { + if (!is_nonnegative_and_representable(exts.extent(r))) return false; } return true; } -template +template MDSPAN_INLINE_FUNCTION constexpr bool check_mul_result_is_nonnegative_and_representable(T a, T b) { // FIXME_SYCL The code below compiles to old_llvm.umul.with.overflow.i64 // which isn't defined in device code #ifdef __SYCL_DEVICE_ONLY__ - (void) a; - (void) b; + (void)a; + (void)b; return true; #else - if (b == 0 || a == 0) - return true; + if (b == 0 || a == 0) return true; if constexpr (std::is_signed_v) { - if ( a < 0 || b < 0 ) return false; + if (a < 0 || b < 0) return false; } -#if defined(MDSPAN_IMPL_HAS_CUDA) && defined(__NVCC__) && (__CUDACC_VER_MAJOR__ * 100 + __CUDACC_VER_MINOR__ * 10 >= 1260) +#if defined(MDSPAN_IMPL_HAS_CUDA) && defined(__NVCC__) && \ + (__CUDACC_VER_MAJOR__ * 100 + __CUDACC_VER_MINOR__ * 10 >= 1260) using cuda::std::numeric_limits; #else using std::numeric_limits; @@ -309,12 +301,12 @@ check_mul_result_is_nonnegative_and_representable(T a, T b) { #endif } #endif -} // namespace detail +} // namespace detail #if MDSPAN_HAS_CXX_17 inline #endif -constexpr struct mdspan_non_standard_tag { + constexpr struct mdspan_non_standard_tag { } mdspan_non_standard; -} // namespace MDSPAN_IMPL_STANDARD_NAMESPACE +} // namespace MDSPAN_IMPL_STANDARD_NAMESPACE diff --git a/include/mdspan/mdarray.hpp b/include/mdspan/mdarray.hpp index 95e8ec65..4f00f281 100644 --- a/include/mdspan/mdarray.hpp +++ b/include/mdspan/mdarray.hpp @@ -5,14 +5,14 @@ #define MDARRAY_HPP_ #ifndef MDSPAN_IMPL_STANDARD_NAMESPACE - #define MDSPAN_IMPL_STANDARD_NAMESPACE Kokkos +#define MDSPAN_IMPL_STANDARD_NAMESPACE Kokkos #endif #ifndef MDSPAN_IMPL_PROPOSED_NAMESPACE - #define MDSPAN_IMPL_PROPOSED_NAMESPACE Experimental +#define MDSPAN_IMPL_PROPOSED_NAMESPACE Experimental #endif #include "mdspan.hpp" #include "impl/mdarray.hpp" -#endif // MDARRAY_HPP_ +#endif // MDARRAY_HPP_ diff --git a/include/mdspan/mdspan.hpp b/include/mdspan/mdspan.hpp index 1aeb949a..ea5a3f05 100644 --- a/include/mdspan/mdspan.hpp +++ b/include/mdspan/mdspan.hpp @@ -5,11 +5,11 @@ #define MDSPAN_HPP_ #ifndef MDSPAN_IMPL_STANDARD_NAMESPACE - #define MDSPAN_IMPL_STANDARD_NAMESPACE Kokkos +#define MDSPAN_IMPL_STANDARD_NAMESPACE Kokkos #endif #ifndef MDSPAN_IMPL_PROPOSED_NAMESPACE - #define MDSPAN_IMPL_PROPOSED_NAMESPACE Experimental +#define MDSPAN_IMPL_PROPOSED_NAMESPACE Experimental #endif #include "impl/default_accessor.hpp" @@ -27,4 +27,4 @@ #endif #include "impl/dims.hpp" -#endif // MDSPAN_HPP_ +#endif // MDSPAN_HPP_ diff --git a/tests/foo_customizations.hpp b/tests/foo_customizations.hpp index 5de05400..33be4e7e 100644 --- a/tests/foo_customizations.hpp +++ b/tests/foo_customizations.hpp @@ -7,234 +7,255 @@ #include namespace Foo { - template - struct foo_ptr { - T* data; - MDSPAN_INLINE_FUNCTION - constexpr foo_ptr(T* ptr):data(ptr) {} - }; - - template - struct foo_accessor { - using offset_policy = foo_accessor; - using element_type = T; - using reference = T&; - using data_handle_type = foo_ptr; - - MDSPAN_INLINE_FUNCTION - constexpr foo_accessor(int* ptr = nullptr) noexcept { flag = ptr; } - - template - MDSPAN_INLINE_FUNCTION - constexpr foo_accessor(Kokkos::default_accessor) noexcept { flag = nullptr; } - - template - MDSPAN_INLINE_FUNCTION - constexpr foo_accessor(foo_accessor other) noexcept { flag = other.flag; } - - - MDSPAN_INLINE_FUNCTION - constexpr reference access(data_handle_type p, size_t i) const noexcept { - return p.data[i]; - } - - MDSPAN_INLINE_FUNCTION - constexpr data_handle_type offset(data_handle_type p, size_t i) const noexcept { - return data_handle_type(p.data+i); - } - int* flag; +template +struct foo_ptr { + T* data; + MDSPAN_INLINE_FUNCTION + constexpr foo_ptr(T* ptr) : data(ptr) {} +}; - MDSPAN_INLINE_FUNCTION - friend constexpr void swap(foo_accessor& x, foo_accessor& y) { - x.flag[0] = 99; - y.flag[0] = 77; - std::swap(x.flag, y.flag); - } - }; +template +struct foo_accessor { + using offset_policy = foo_accessor; + using element_type = T; + using reference = T&; + using data_handle_type = foo_ptr; + + MDSPAN_INLINE_FUNCTION + constexpr foo_accessor(int* ptr = nullptr) noexcept { flag = ptr; } + + template + MDSPAN_INLINE_FUNCTION constexpr foo_accessor( + Kokkos::default_accessor) noexcept { + flag = nullptr; + } + + template + MDSPAN_INLINE_FUNCTION constexpr foo_accessor( + foo_accessor other) noexcept { + flag = other.flag; + } + + MDSPAN_INLINE_FUNCTION + constexpr reference access(data_handle_type p, size_t i) const noexcept { + return p.data[i]; + } + + MDSPAN_INLINE_FUNCTION + constexpr data_handle_type offset(data_handle_type p, + size_t i) const noexcept { + return data_handle_type(p.data + i); + } + int* flag; + + MDSPAN_INLINE_FUNCTION + friend constexpr void swap(foo_accessor& x, foo_accessor& y) { + x.flag[0] = 99; + y.flag[0] = 77; + std::swap(x.flag, y.flag); + } +}; struct layout_foo { - template - class mapping; + template + class mapping; }; template class layout_foo::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_foo; - private: + 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_foo; - static_assert(Kokkos::detail::impl_is_extents_v, - "layout_foo::mapping must be instantiated with a specialization of Kokkos::extents."); - static_assert(extents_type::rank() < 3, "layout_foo only supports 0D, 1D and 2D"); + private: + static_assert(Kokkos::detail::impl_is_extents_v, + "layout_foo::mapping must be instantiated with a " + "specialization of Kokkos::extents."); + static_assert(extents_type::rank() < 3, + "layout_foo only supports 0D, 1D and 2D"); - template - friend class mapping; + template + friend class mapping; - public: + public: + //-------------------------------------------------------------------------------- - //-------------------------------------------------------------------------------- + MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr mapping() noexcept = default; + MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr mapping(mapping const&) noexcept = + default; - MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr mapping() noexcept = default; - MDSPAN_INLINE_FUNCTION_DEFAULTED constexpr mapping(mapping const&) noexcept = default; + constexpr mapping(extents_type const& exts) noexcept : m_extents(exts) {} - constexpr mapping(extents_type const& exts) noexcept - :m_extents(exts) - { } - - MDSPAN_TEMPLATE_REQUIRES( + MDSPAN_TEMPLATE_REQUIRES( class OtherExtents, - /* requires */ ( - MDSPAN_IMPL_TRAIT(std::is_constructible, extents_type, OtherExtents) - ) - ) - MDSPAN_CONDITIONAL_EXPLICIT((!std::is_convertible::value)) // needs two () due to comma - MDSPAN_INLINE_FUNCTION MDSPAN_IMPL_CONSTEXPR_14 - mapping(mapping const& other) noexcept // NOLINT(google-explicit-constructor) - :m_extents(other.extents()) - { - /* - * TODO: check precondition - * other.required_span_size() is a representable value of type index_type - */ - } - - MDSPAN_TEMPLATE_REQUIRES( + /* requires */ (MDSPAN_IMPL_TRAIT(std::is_constructible, extents_type, + OtherExtents))) + MDSPAN_CONDITIONAL_EXPLICIT( + (!std::is_convertible::value)) // needs two () due to comma + MDSPAN_INLINE_FUNCTION MDSPAN_IMPL_CONSTEXPR_14 + mapping(mapping const& + other) noexcept // NOLINT(google-explicit-constructor) + : m_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_IMPL_TRAIT(std::is_constructible, extents_type, OtherExtents) - ) - ) - MDSPAN_CONDITIONAL_EXPLICIT((!std::is_convertible::value)) // needs two () due to comma - MDSPAN_INLINE_FUNCTION MDSPAN_IMPL_CONSTEXPR_14 - mapping(Kokkos::layout_right::mapping const& other) noexcept // NOLINT(google-explicit-constructor) - :m_extents(other.extents()) - {} - - MDSPAN_TEMPLATE_REQUIRES( + /* requires */ (MDSPAN_IMPL_TRAIT(std::is_constructible, extents_type, + OtherExtents))) + MDSPAN_CONDITIONAL_EXPLICIT( + (!std::is_convertible::value)) // needs two () due to comma + MDSPAN_INLINE_FUNCTION MDSPAN_IMPL_CONSTEXPR_14 + mapping(Kokkos::layout_right::mapping const& + other) noexcept // NOLINT(google-explicit-constructor) + : m_extents(other.extents()) {} + + MDSPAN_TEMPLATE_REQUIRES( class OtherExtents, - /* requires */ ( - MDSPAN_IMPL_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_IMPL_CONSTEXPR_14 - mapping(Kokkos::layout_left::mapping const& other) noexcept // NOLINT(google-explicit-constructor) - :m_extents(other.extents()) - {} - - MDSPAN_TEMPLATE_REQUIRES( + /* requires */ (MDSPAN_IMPL_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_IMPL_CONSTEXPR_14 + mapping(Kokkos::layout_left::mapping const& + other) noexcept // NOLINT(google-explicit-constructor) + : m_extents(other.extents()) {} + + MDSPAN_TEMPLATE_REQUIRES( class OtherExtents, - /* requires */ ( - MDSPAN_IMPL_TRAIT(std::is_constructible, extents_type, OtherExtents) - ) - ) - MDSPAN_CONDITIONAL_EXPLICIT((extents_type::rank() > 0)) - MDSPAN_INLINE_FUNCTION MDSPAN_IMPL_CONSTEXPR_14 - mapping(Kokkos::layout_stride::mapping const& other) // NOLINT(google-explicit-constructor) - :m_extents(other.extents()) - { - /* - * TODO: check precondition - * other.required_span_size() is a representable value of type index_type - */ - #ifndef __CUDA_ARCH__ - size_t stride = 1; - for(rank_type r=m_extents.rank(); r>0; r--) { - if(stride != other.stride(r-1)) - throw std::runtime_error("Assigning layout_stride to layout_foo with invalid strides."); - stride *= m_extents.extent(r-1); - } - #endif - } - - MDSPAN_INLINE_FUNCTION_DEFAULTED MDSPAN_IMPL_CONSTEXPR_14_DEFAULTED mapping& operator=(mapping const&) noexcept = default; - - MDSPAN_INLINE_FUNCTION - constexpr const extents_type& extents() const noexcept { - return m_extents; + /* requires */ (MDSPAN_IMPL_TRAIT(std::is_constructible, extents_type, + OtherExtents))) + MDSPAN_CONDITIONAL_EXPLICIT((extents_type::rank() > 0)) + MDSPAN_INLINE_FUNCTION MDSPAN_IMPL_CONSTEXPR_14 + mapping(Kokkos::layout_stride::mapping const& + other) // NOLINT(google-explicit-constructor) + : m_extents(other.extents()) { +/* + * TODO: check precondition + * other.required_span_size() is a representable value of type index_type + */ +#ifndef __CUDA_ARCH__ + size_t stride = 1; + for (rank_type r = m_extents.rank(); r > 0; r--) { + if (stride != other.stride(r - 1)) + throw std::runtime_error( + "Assigning layout_stride to layout_foo with invalid strides."); + stride *= m_extents.extent(r - 1); } - - 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*=m_extents.extent(r); - return value; - } - - //-------------------------------------------------------------------------------- - - MDSPAN_INLINE_FUNCTION - constexpr index_type operator() () const noexcept { return index_type(0); } - - template - MDSPAN_INLINE_FUNCTION - constexpr index_type operator()(Indx0 idx0) const noexcept { - return static_cast(idx0); - } - - template - MDSPAN_INLINE_FUNCTION - constexpr index_type operator()(Indx0 idx0, Indx1 idx1) const noexcept { - return static_cast(idx0 * m_extents.extent(1) + idx1); - } - - 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 constexpr bool is_unique() const noexcept { return true; } - MDSPAN_INLINE_FUNCTION constexpr bool is_exhaustive() const noexcept { return true; } - MDSPAN_INLINE_FUNCTION constexpr bool is_strided() const noexcept { return true; } - - MDSPAN_INLINE_FUNCTION - constexpr index_type stride(rank_type i) const noexcept { - index_type value = 1; - for(rank_type r=extents_type::rank()-1; r>i; r--) value*=m_extents.extent(r); - return value; - } - - template - 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 +#endif + } + + MDSPAN_INLINE_FUNCTION_DEFAULTED MDSPAN_IMPL_CONSTEXPR_14_DEFAULTED mapping& + operator=(mapping const&) noexcept = default; + + MDSPAN_INLINE_FUNCTION + constexpr const extents_type& extents() const noexcept { return m_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 *= m_extents.extent(r); + return value; + } + + //-------------------------------------------------------------------------------- + + MDSPAN_INLINE_FUNCTION + constexpr index_type operator()() const noexcept { return index_type(0); } + + template + MDSPAN_INLINE_FUNCTION constexpr index_type operator()( + Indx0 idx0) const noexcept { + return static_cast(idx0); + } + + template + MDSPAN_INLINE_FUNCTION constexpr index_type operator()( + Indx0 idx0, Indx1 idx1) const noexcept { + return static_cast(idx0 * m_extents.extent(1) + idx1); + } + + 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 constexpr bool is_unique() const noexcept { + return true; + } + MDSPAN_INLINE_FUNCTION constexpr bool is_exhaustive() const noexcept { + return true; + } + MDSPAN_INLINE_FUNCTION constexpr bool is_strided() const noexcept { + return true; + } + + MDSPAN_INLINE_FUNCTION + constexpr index_type stride(rank_type i) const noexcept { + index_type value = 1; + for (rank_type r = extents_type::rank() - 1; r > i; r--) + value *= m_extents.extent(r); + return value; + } + + template + 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 - template - MDSPAN_INLINE_FUNCTION - friend constexpr bool operator!=(mapping const& lhs, mapping const& rhs) noexcept { - return lhs.extents() != rhs.extents(); - } + template + MDSPAN_INLINE_FUNCTION friend constexpr bool operator!=( + mapping const& lhs, mapping const& rhs) noexcept { + return lhs.extents() != rhs.extents(); + } #endif #if MDSPAN_HAS_CXX_17 - template - friend constexpr auto submdspan_mapping( - const mapping& src, SliceSpecifiers... slices) { - // use the fact that layout_foo is layout_right with rank 1 or rank 2 - // i.e. we don't need to implement everything here, we just reuse submdspan_mapping for layout_right - Kokkos::layout_right::mapping compatible_mapping(src.extents()); - auto sub_right = submdspan_mapping(compatible_mapping, slices...); - if constexpr (std::is_same_v) { - // NVCC does not like deduction here, so get the extents type explicitly - using sub_ext_t = std::remove_const_t>; - auto sub_mapping = layout_foo::mapping(sub_right.mapping.extents()); - return Kokkos::submdspan_mapping_result{sub_mapping, sub_right.offset}; - } else { - return sub_right; - } - } + template + friend constexpr auto submdspan_mapping(const mapping& src, + SliceSpecifiers... slices) { + // use the fact that layout_foo is layout_right with rank 1 or rank 2 + // i.e. we don't need to implement everything here, we just reuse + // submdspan_mapping for layout_right + Kokkos::layout_right::mapping compatible_mapping(src.extents()); + auto sub_right = submdspan_mapping(compatible_mapping, slices...); + if constexpr (std::is_same_v< + typename decltype(sub_right.mapping)::layout_type, + Kokkos::layout_right>) { + // NVCC does not like deduction here, so get the extents type explicitly + using sub_ext_t = std::remove_const_t< + std::remove_reference_t>; + auto sub_mapping = + layout_foo::mapping(sub_right.mapping.extents()); + return Kokkos::submdspan_mapping_result{ + sub_mapping, sub_right.offset}; + } else { + return sub_right; + } + } #endif -private: - MDSPAN_IMPL_NO_UNIQUE_ADDRESS extents_type m_extents{}; - + private: + MDSPAN_IMPL_NO_UNIQUE_ADDRESS extents_type m_extents{}; }; -} +} // namespace Foo #endif diff --git a/tests/libcxx-backports/ConvertibleToIntegral.h b/tests/libcxx-backports/ConvertibleToIntegral.h index 2f31941a..c2fc5d08 100644 --- a/tests/libcxx-backports/ConvertibleToIntegral.h +++ b/tests/libcxx-backports/ConvertibleToIntegral.h @@ -12,7 +12,7 @@ struct IntType { int val; constexpr IntType() = default; - constexpr IntType(int v) noexcept : val(v){} + constexpr IntType(int v) noexcept : val(v) {} constexpr bool operator==(const IntType& rhs) const { return val == rhs.val; } constexpr operator int() const noexcept { return val; } @@ -24,7 +24,7 @@ struct IntType { struct IntTypeNC { int val; constexpr IntTypeNC() = default; - constexpr IntTypeNC(int v) noexcept : val(v){} + constexpr IntTypeNC(int v) noexcept : val(v) {} constexpr bool operator==(const IntType& rhs) const { return val == rhs.val; } constexpr operator int() noexcept { return val; } @@ -33,12 +33,20 @@ struct IntTypeNC { }; // weird configurability of convertibility to int -template +template struct IntConfig { int val; - constexpr explicit IntConfig(int val_):val(val_){} - constexpr operator int() noexcept(ctor_nt_nc) requires(conv_nc) { return val; } - constexpr operator int() const noexcept(ctor_nt_c) requires(conv_c) { return val; } + constexpr explicit IntConfig(int val_) : val(val_) {} + constexpr operator int() noexcept(ctor_nt_nc) + requires(conv_nc) + { + return val; + } + constexpr operator int() const noexcept(ctor_nt_c) + requires(conv_c) + { + return val; + } }; -#endif // TEST_STD_CONTAINERS_VIEWS_MDSPAN_CONVERTIBLE_TO_INTEGRAL_H +#endif // TEST_STD_CONTAINERS_VIEWS_MDSPAN_CONVERTIBLE_TO_INTEGRAL_H diff --git a/tests/libcxx-backports/CustomTestLayouts.h b/tests/libcxx-backports/CustomTestLayouts.h index 36eb05f6..83c6dbe9 100644 --- a/tests/libcxx-backports/CustomTestLayouts.h +++ b/tests/libcxx-backports/CustomTestLayouts.h @@ -44,7 +44,7 @@ struct not_extents_constructible_tag {}; template class layout_wrapping_integral { -public: + public: template class mapping; }; @@ -52,36 +52,40 @@ class layout_wrapping_integral { template template class layout_wrapping_integral::mapping { - static constexpr typename Extents::index_type Wrap = static_cast(WrapArg); + static constexpr typename Extents::index_type Wrap = + static_cast(WrapArg); -public: + 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_wrapping_integral; -private: - static constexpr bool required_span_size_is_representable(const extents_type& ext) { - if constexpr (extents_type::rank() == 0) - return true; + private: + static constexpr bool required_span_size_is_representable( + const extents_type& ext) { + if constexpr (extents_type::rank() == 0) return true; index_type prod = ext.extent(0); for (rank_type r = 1; r < extents_type::rank(); r++) { - bool overflowed = __builtin_mul_overflow(prod, std::min(ext.extent(r), Wrap), &prod); - if (overflowed) - return false; + bool overflowed = + __builtin_mul_overflow(prod, std::min(ext.extent(r), Wrap), &prod); + if (overflowed) return false; } return true; } -public: + public: constexpr mapping() noexcept = delete; - constexpr mapping(const mapping& other) noexcept : extents_(other.extents()){} + constexpr mapping(const mapping& other) noexcept + : extents_(other.extents()) {} constexpr mapping(extents_type&& ext) noexcept requires(Wrap == 8) : extents_(ext) {} - constexpr mapping(const extents_type& ext, not_extents_constructible_tag) noexcept : extents_(ext) {} + constexpr mapping(const extents_type& ext, + not_extents_constructible_tag) noexcept + : extents_(ext) {} template requires(std::is_constructible_v && (Wrap != 8)) @@ -125,15 +129,18 @@ class layout_wrapping_integral::mapping { } template - requires((sizeof...(Indices) == extents_type::rank()) && (std::is_convertible_v && ...) && + requires((sizeof...(Indices) == extents_type::rank()) && + (std::is_convertible_v && ...) && (std::is_nothrow_constructible_v && ...)) constexpr index_type operator()(Indices... idx) const noexcept { - std::array idx_a{static_cast(static_cast(idx) % Wrap)...}; + std::array idx_a{ + static_cast(static_cast(idx) % Wrap)...}; return [&](std::index_sequence) { index_type res = 0; ((res = idx_a[extents_type::rank() - 1 - Pos] + - (extents_.extent(extents_type::rank() - 1 - Pos) < Wrap ? extents_.extent(extents_type::rank() - 1 - Pos) - : Wrap) * + (extents_.extent(extents_type::rank() - 1 - Pos) < Wrap + ? extents_.extent(extents_type::rank() - 1 - Pos) + : Wrap) * res), ...); return res; @@ -146,16 +153,14 @@ class layout_wrapping_integral::mapping { constexpr bool is_unique() const noexcept { for (rank_type r = 0; r < extents_type::rank(); r++) { - if (extents_.extent(r) > Wrap) - return false; + if (extents_.extent(r) > Wrap) return false; } return true; } static constexpr bool is_exhaustive() noexcept { return true; } constexpr bool is_strided() const noexcept { for (rank_type r = 0; r < extents_type::rank(); r++) { - if (extents_.extent(r) > Wrap) - return false; + if (extents_.extent(r) > Wrap) return false; } return true; } @@ -171,7 +176,8 @@ class layout_wrapping_integral::mapping { template requires(OtherExtents::rank() == extents_type::rank()) - friend constexpr bool operator==(const mapping& lhs, const mapping& rhs) noexcept { + friend constexpr bool operator==(const mapping& lhs, + const mapping& rhs) noexcept { return lhs.extents() == rhs.extents(); } @@ -190,7 +196,7 @@ class layout_wrapping_integral::mapping { } #endif -private: + private: extents_type extents_{}; }; @@ -205,48 +211,52 @@ constexpr auto construct_mapping(std::layout_right, Extents exts) { } template -constexpr auto construct_mapping(layout_wrapping_integral, Extents exts) { - return typename layout_wrapping_integral::template mapping(exts, not_extents_constructible_tag{}); +constexpr auto construct_mapping(layout_wrapping_integral, + Extents exts) { + return typename layout_wrapping_integral::template mapping( + exts, not_extents_constructible_tag{}); } // This layout does not check convertibility of extents for its conversion ctor // Allows triggering mdspan's ctor static assertion on convertibility of extents // It also allows for negative strides and offsets via runtime arguments class always_convertible_layout { -public: + public: template class mapping; }; template class always_convertible_layout::mapping { -public: + 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 = always_convertible_layout; -private: - static constexpr bool required_span_size_is_representable(const extents_type& ext) { - if constexpr (extents_type::rank() == 0) - return true; + private: + static constexpr bool required_span_size_is_representable( + const extents_type& ext) { + if constexpr (extents_type::rank() == 0) return true; index_type prod = ext.extent(0); for (rank_type r = 1; r < extents_type::rank(); r++) { bool overflowed = __builtin_mul_overflow(prod, ext.extent(r), &prod); - if (overflowed) - return false; + if (overflowed) return false; } return true; } -public: + public: constexpr mapping() noexcept = delete; constexpr mapping(const mapping& other) noexcept - : extents_(other.extents_), offset_(other.offset_), scaling_(other.scaling_){} - constexpr mapping(const extents_type& ext, index_type offset = 0, index_type scaling = 1) noexcept - : extents_(ext), offset_(offset), scaling_(scaling){} + : extents_(other.extents_), + offset_(other.offset_), + scaling_(other.scaling_) {} + constexpr mapping(const extents_type& ext, index_type offset = 0, + index_type scaling = 1) noexcept + : extents_(ext), offset_(offset), scaling_(scaling) {} template constexpr mapping(const mapping& other) noexcept { @@ -283,14 +293,17 @@ class always_convertible_layout::mapping { } template - requires((sizeof...(Indices) == extents_type::rank()) && (std::is_convertible_v && ...) && + requires((sizeof...(Indices) == extents_type::rank()) && + (std::is_convertible_v && ...) && (std::is_nothrow_constructible_v && ...)) constexpr index_type operator()(Indices... idx) const noexcept { - std::array idx_a{static_cast(static_cast(idx))...}; + std::array idx_a{ + static_cast(static_cast(idx))...}; return offset_ + scaling_ * ([&](std::index_sequence) { index_type res = 0; - ((res = idx_a[extents_type::rank() - 1 - Pos] + extents_.extent(extents_type::rank() - 1 - Pos) * res), + ((res = idx_a[extents_type::rank() - 1 - Pos] + + extents_.extent(extents_type::rank() - 1 - Pos) * res), ...); return res; }(std::make_index_sequence())); @@ -308,15 +321,16 @@ class always_convertible_layout::mapping { requires(extents_type::rank() > 0) { index_type s = 1; - for (rank_type i = 0; i < r; i++) - s *= extents_.extent(i); + for (rank_type i = 0; i < r; i++) s *= extents_.extent(i); return s * scaling_; } template requires(OtherExtents::rank() == extents_type::rank()) - friend constexpr bool operator==(const mapping& lhs, const mapping& rhs) noexcept { - return lhs.extents() == rhs.extents() && lhs.offset_ == rhs.offset && lhs.scaling_ == rhs.scaling_; + friend constexpr bool operator==(const mapping& lhs, + const mapping& rhs) noexcept { + return lhs.extents() == rhs.extents() && lhs.offset_ == rhs.offset && + lhs.scaling_ == rhs.scaling_; } #if MDSPAN_HAS_CXX_23 @@ -333,7 +347,7 @@ class always_convertible_layout::mapping { } #endif -private: + private: template friend class mapping; @@ -341,4 +355,4 @@ class always_convertible_layout::mapping { index_type offset_{}; index_type scaling_{}; }; -#endif // TEST_STD_CONTAINERS_VIEWS_MDSPAN_CUSTOM_TEST_LAYOUTS_H +#endif // TEST_STD_CONTAINERS_VIEWS_MDSPAN_CUSTOM_TEST_LAYOUTS_H diff --git a/tests/libcxx-backports/MinimalElementType.h b/tests/libcxx-backports/MinimalElementType.h index 38679089..e8374ae8 100644 --- a/tests/libcxx-backports/MinimalElementType.h +++ b/tests/libcxx-backports/MinimalElementType.h @@ -9,39 +9,37 @@ #ifndef TEST_STD_CONTAINERS_VIEWS_MDSPAN_MINIMAL_ELEMENT_TYPE_H #define TEST_STD_CONTAINERS_VIEWS_MDSPAN_MINIMAL_ELEMENT_TYPE_H -#include +#include // Idiosyncratic element type for mdspan // Make sure we don't assume copyable, default constructible, movable etc. struct MinimalElementType { int val; - constexpr MinimalElementType() = delete; + constexpr MinimalElementType() = delete; constexpr MinimalElementType(const MinimalElementType&) = delete; - constexpr explicit MinimalElementType(int v) noexcept : val(v){} + constexpr explicit MinimalElementType(int v) noexcept : val(v) {} constexpr MinimalElementType& operator=(const MinimalElementType&) = delete; }; // Helper class to create pointer to MinimalElementType -template +template struct ElementPool { constexpr ElementPool() { nc_ptr_ = std::allocator>().allocate(N); - ptr_ = nc_ptr_; - for (int i = 0; i != N; ++i) - std::construct_at(nc_ptr_ + i, 42); + ptr_ = nc_ptr_; + for (int i = 0; i != N; ++i) std::construct_at(nc_ptr_ + i, 42); } constexpr T* get_ptr() { return ptr_; } constexpr ~ElementPool() { - for (int i = 0; i != N; ++i) - std::destroy_at(nc_ptr_ + i); + for (int i = 0; i != N; ++i) std::destroy_at(nc_ptr_ + i); std::allocator>().deallocate(nc_ptr_, N); } -private: + private: std::remove_const_t* nc_ptr_; T* ptr_; }; -#endif // TEST_STD_CONTAINERS_VIEWS_MDSPAN_MINIMAL_ELEMENT_TYPE_H +#endif // TEST_STD_CONTAINERS_VIEWS_MDSPAN_MINIMAL_ELEMENT_TYPE_H diff --git a/tests/libcxx-backports/default_accessor/default_accessor.access.pass.cpp b/tests/libcxx-backports/default_accessor/default_accessor.access.pass.cpp index b173bbbd..61943279 100644 --- a/tests/libcxx-backports/default_accessor/default_accessor.access.pass.cpp +++ b/tests/libcxx-backports/default_accessor/default_accessor.access.pass.cpp @@ -27,8 +27,9 @@ constexpr void test_access() { ElementPool, 10> data; T* ptr = data.get_ptr(); std::default_accessor acc; - for(int i = 0; i < 10; i++) { - static_assert(std::is_same_v::reference>); + for (int i = 0; i < 10; i++) { + static_assert(std::is_same_v::reference>); ASSERT_NOEXCEPT(acc.access(ptr, i)); assert(&acc.access(ptr, i) == ptr + i); } diff --git a/tests/libcxx-backports/default_accessor/default_accessor.ctor.conversion.pass.cpp b/tests/libcxx-backports/default_accessor/default_accessor.ctor.conversion.pass.cpp index 807505dc..dc8eeed6 100644 --- a/tests/libcxx-backports/default_accessor/default_accessor.ctor.conversion.pass.cpp +++ b/tests/libcxx-backports/default_accessor/default_accessor.ctor.conversion.pass.cpp @@ -15,7 +15,8 @@ // template // constexpr default_accessor(default_accessor) noexcept {} // -// Constraints: is_convertible_v is true. +// Constraints: is_convertible_v is +// true. #include #include @@ -27,7 +28,7 @@ #include "../MinimalElementType.h" struct Base {}; -struct Derived: public Base {}; +struct Derived : public Base {}; template constexpr void test_conversion() { @@ -45,6 +46,7 @@ constexpr bool test() { test_conversion(); test_conversion(); + // clang-format off // char is convertible to int, but accessors are not static_assert(!std::is_constructible_v, std::default_accessor>); // don't allow conversion from const elements to non-const @@ -57,6 +59,7 @@ constexpr bool test() { static_assert(!std::is_constructible_v, std::default_accessor>); // don't allow conversion from Derived to Base static_assert(!std::is_constructible_v, std::default_accessor>); + // clang-format on return true; } diff --git a/tests/libcxx-backports/default_accessor/default_accessor.ctor.default.pass.cpp b/tests/libcxx-backports/default_accessor/default_accessor.ctor.default.pass.cpp index e3226af1..6ae95ccd 100644 --- a/tests/libcxx-backports/default_accessor/default_accessor.ctor.default.pass.cpp +++ b/tests/libcxx-backports/default_accessor/default_accessor.ctor.default.pass.cpp @@ -27,7 +27,8 @@ template constexpr void test_construction() { ASSERT_NOEXCEPT(std::default_accessor{}); [[maybe_unused]] std::default_accessor acc; - static_assert(std::is_trivially_default_constructible_v>); + static_assert( + std::is_trivially_default_constructible_v>); } constexpr bool test() { diff --git a/tests/libcxx-backports/default_accessor/default_accessor.element_type.verify.cpp b/tests/libcxx-backports/default_accessor/default_accessor.element_type.verify.cpp index e7260c8e..8e31caa2 100644 --- a/tests/libcxx-backports/default_accessor/default_accessor.element_type.verify.cpp +++ b/tests/libcxx-backports/default_accessor/default_accessor.element_type.verify.cpp @@ -12,23 +12,25 @@ // template // class default_accessor; -// ElementType is required to be a complete object type that is neither an abstract class type nor an array type. +// ElementType is required to be a complete object type that is neither an +// abstract class type nor an array type. #include #include "../llvm_test_macros.h" class AbstractClass { -public: + public: virtual void method() = 0; }; void not_abstract_class() { - // expected-error-re@*:* {{static assertion failed {{.*}}default_accessor: template argument may not be an abstract class}} + // expected-error-re@*:* {{static assertion failed {{.*}}default_accessor: + // template argument may not be an abstract class}} [[maybe_unused]] std::default_accessor acc; } void not_array_type() { - // expected-error-re@*:* {{static assertion failed {{.*}}default_accessor: template argument may not be an array type}} + // expected-error-re@*:* {{static assertion failed {{.*}}default_accessor: + // template argument may not be an array type}} [[maybe_unused]] std::default_accessor acc; } - diff --git a/tests/libcxx-backports/default_accessor/default_accessor.offset.pass.cpp b/tests/libcxx-backports/default_accessor/default_accessor.offset.pass.cpp index 00142cff..902b51c3 100644 --- a/tests/libcxx-backports/default_accessor/default_accessor.offset.pass.cpp +++ b/tests/libcxx-backports/default_accessor/default_accessor.offset.pass.cpp @@ -10,7 +10,8 @@ // -// constexpr data_handle_type offset(data_handle_type p, size_t i) const noexcept; +// constexpr data_handle_type offset(data_handle_type p, size_t i) const +// noexcept; // // Effects: Equivalent to: return p+i; @@ -27,8 +28,10 @@ constexpr void test_offset() { ElementPool, 10> data; T* ptr = data.get_ptr(); std::default_accessor acc; - for(int i = 0; i < 10; i++) { - static_assert(std::is_same_v::data_handle_type>); + for (int i = 0; i < 10; i++) { + static_assert( + std::is_same_v::data_handle_type>); ASSERT_NOEXCEPT(acc.offset(ptr, i)); assert(acc.offset(ptr, i) == ptr + i); } diff --git a/tests/libcxx-backports/default_accessor/default_accessor.types.pass.cpp b/tests/libcxx-backports/default_accessor/default_accessor.types.pass.cpp index 4da59bc2..0750d4fd 100644 --- a/tests/libcxx-backports/default_accessor/default_accessor.types.pass.cpp +++ b/tests/libcxx-backports/default_accessor/default_accessor.types.pass.cpp @@ -19,8 +19,8 @@ // ... // }; // -// Each specialization of default_accessor is a trivially copyable type that models semiregular. - +// Each specialization of default_accessor is a trivially copyable type that +// models semiregular. #include #include diff --git a/tests/libcxx-backports/extents/CtorTestCombinations.h b/tests/libcxx-backports/extents/CtorTestCombinations.h index 4b8f4957..3f3c9dbf 100644 --- a/tests/libcxx-backports/extents/CtorTestCombinations.h +++ b/tests/libcxx-backports/extents/CtorTestCombinations.h @@ -19,10 +19,11 @@ // Helper file to implement combinatorical testing of extents constructor // -// std::extents can be constructed from just indices, a std::array, or a std::span -// In each of those cases one can either provide all extents, or just the dynamic ones -// If constructed from std::span, the span needs to have a static extent -// Furthermore, the indices/array/span can have integer types other than index_type +// std::extents can be constructed from just indices, a std::array, or a +// std::span In each of those cases one can either provide all extents, or just +// the dynamic ones If constructed from std::span, the span needs to have a +// static extent Furthermore, the indices/array/span can have integer types +// other than index_type template constexpr void test_runtime_observers(E ext, AllExtents expected) { @@ -41,7 +42,8 @@ constexpr void test_implicit_construction_call(E e, AllExtents all_ext) { template constexpr void test_construction(AllExtents all_ext) { // test construction from all extents - Test::template test_construction(all_ext, all_ext, std::make_index_sequence()); + Test::template test_construction(all_ext, all_ext, + std::make_index_sequence()); // test construction from just dynamic extents // create an array of just the extents corresponding to dynamic values @@ -54,10 +56,12 @@ constexpr void test_construction(AllExtents all_ext) { dynamic_idx++; } } - Test::template test_construction(all_ext, dyn_ext, std::make_index_sequence()); + Test::template test_construction( + all_ext, dyn_ext, std::make_index_sequence()); } else { std::array dyn_ext{}; - Test::template test_construction(all_ext, dyn_ext, std::make_index_sequence()); + Test::template test_construction( + all_ext, dyn_ext, std::make_index_sequence()); } } @@ -65,6 +69,7 @@ template constexpr void test() { constexpr size_t D = std::dynamic_extent; + // clang-format off test_construction, Test>(std::array{}); test_construction, Test>(std::array{3}); @@ -87,6 +92,7 @@ constexpr void test() { test_construction, Test>(std::array{1, 2, 3, 4, 5, 6, 7, 8, 9}); test_construction, Test>(std::array{1, 2, 3, 4, 5, 6, 7, 8, 9}); test_construction, Test>(std::array{1, 2, 3, 4, 5, 6, 7, 8, 9}); + // clang-format on } template diff --git a/tests/libcxx-backports/extents/comparison.pass.cpp b/tests/libcxx-backports/extents/comparison.pass.cpp index 44fb58f1..79fc034d 100644 --- a/tests/libcxx-backports/extents/comparison.pass.cpp +++ b/tests/libcxx-backports/extents/comparison.pass.cpp @@ -11,10 +11,12 @@ // // template // friend constexpr bool operator==(const extents& lhs, -// const extents& rhs) noexcept; +// const extents& rhs) noexcept; // // Returns: true if lhs.rank() equals rhs.rank() and -// if lhs.extent(r) equals rhs.extent(r) for every rank index r of rhs, otherwise false. +// if lhs.extent(r) equals rhs.extent(r) for every rank index r of rhs, +// otherwise false. // #include @@ -54,6 +56,7 @@ template constexpr void test_comparison_same_rank() { constexpr size_t D = std::dynamic_extent; + // clang-format off test_comparison(true, std::extents(), std::extents()); test_comparison(true, std::extents(5), std::extents(5)); @@ -72,6 +75,7 @@ constexpr void test_comparison_same_rank() { false, std::extents(5, 6, 7, 8, 9), std::extents(5, 6, 3, 8, 9)); test_comparison(false, std::extents(5, 7, 9), std::extents(6, 7)); test_comparison(false, std::extents(5, 6, 7, 8, 9), std::extents()); + // clang-format on } template diff --git a/tests/libcxx-backports/extents/conversion.pass.cpp b/tests/libcxx-backports/extents/conversion.pass.cpp index edae21fd..64f32c6d 100644 --- a/tests/libcxx-backports/extents/conversion.pass.cpp +++ b/tests/libcxx-backports/extents/conversion.pass.cpp @@ -10,7 +10,8 @@ // // template -// constexpr explicit(see below) extents(const extents&) noexcept; +// constexpr explicit(see below) extents(const extents&) noexcept; // // Constraints: // * sizeof...(OtherExtents) == rank() is true. @@ -25,8 +26,9 @@ // every rank index r of other. // // Remarks: The expression inside explicit is equivalent to: -// (((Extents != dynamic_extent) && (OtherExtents == dynamic_extent)) || ... ) || -// (numeric_limits::max() < numeric_limits::max()) +// (((Extents != dynamic_extent) && (OtherExtents == dynamic_extent)) +// || ... ) || (numeric_limits::max() < +// numeric_limits::max()) #include #include @@ -52,13 +54,13 @@ constexpr void test_conversion(From src) { } } +// clang-format off template constexpr void test_conversion() { constexpr size_t D = std::dynamic_extent; constexpr bool idx_convertible = static_cast(std::numeric_limits::max()) >= static_cast(std::numeric_limits::max()); - // clang-format off test_conversion>(std::extents()); test_conversion>(std::extents(5)); test_conversion>(std::extents(5)); @@ -72,7 +74,6 @@ constexpr void test_conversion() { std::extents(5, 7, 8, 9, 1)); test_conversion>(std::extents(5)); test_conversion>(std::extents()); - // clang-format on } constexpr void test_no_implicit_conversion() { @@ -118,6 +119,7 @@ constexpr void test_static_extent_mismatch() { static_assert(!std::is_constructible_v, std::extents>, ""); static_assert(!std::is_constructible_v, std::extents>, ""); } +// clang-format on constexpr bool test() { test_conversion(); diff --git a/tests/libcxx-backports/extents/ctad.pass.cpp b/tests/libcxx-backports/extents/ctad.pass.cpp index 482a99c8..e00df31e 100644 --- a/tests/libcxx-backports/extents/ctad.pass.cpp +++ b/tests/libcxx-backports/extents/ctad.pass.cpp @@ -24,7 +24,7 @@ struct NoDefaultCtorIndex { size_t value; constexpr NoDefaultCtorIndex() = delete; - constexpr NoDefaultCtorIndex(size_t val) : value(val){} + constexpr NoDefaultCtorIndex(size_t val) : value(val) {} constexpr operator size_t() const noexcept { return value; } }; @@ -41,8 +41,10 @@ constexpr bool test() { test(std::extents(1), std::extents(1)); test(std::extents(1, 2u), std::extents(1, 2u)); test(std::extents(1, 2u, 3, 4, 5, 6, 7, 8, 9), - std::extents(1, 2u, 3, 4, 5, 6, 7, 8, 9)); - test(std::extents(NoDefaultCtorIndex{1}, NoDefaultCtorIndex{2}), std::extents(1, 2)); + std::extents(1, 2u, 3, 4, 5, 6, + 7, 8, 9)); + test(std::extents(NoDefaultCtorIndex{1}, NoDefaultCtorIndex{2}), + std::extents(1, 2)); return true; } diff --git a/tests/libcxx-backports/extents/ctor_default.pass.cpp b/tests/libcxx-backports/extents/ctor_default.pass.cpp index 0e7997ad..7eab0a88 100644 --- a/tests/libcxx-backports/extents/ctor_default.pass.cpp +++ b/tests/libcxx-backports/extents/ctor_default.pass.cpp @@ -13,8 +13,8 @@ // // constexpr extents() noexcept = default; // -// Remarks: since the standard uses an exposition only array member, dynamic extents -// need to be zero intialized! +// Remarks: since the standard uses an exposition only array member, dynamic +// extents need to be zero intialized! #include #include @@ -26,10 +26,12 @@ struct DefaultCtorTest { template - static constexpr void test_construction(AllExtents all_ext, Extents, std::index_sequence) { - // This function gets called twice: once with Extents being just the dynamic ones, and once with all the extents specified. - // We only test during the all extent case, since then Indices is the correct number. This allows us to reuse the same - // testing machinery used in other constructor tests. + static constexpr void test_construction(AllExtents all_ext, Extents, + std::index_sequence) { + // This function gets called twice: once with Extents being just the dynamic + // ones, and once with all the extents specified. We only test during the + // all extent case, since then Indices is the correct number. This allows us + // to reuse the same testing machinery used in other constructor tests. if constexpr (sizeof...(Indices) == E::rank()) { ASSERT_NOEXCEPT(E{}); // Need to construct new expected values, replacing dynamic values with 0 diff --git a/tests/libcxx-backports/extents/ctor_from_array.pass.cpp b/tests/libcxx-backports/extents/ctor_from_array.pass.cpp index d2ad901f..36c42564 100644 --- a/tests/libcxx-backports/extents/ctor_from_array.pass.cpp +++ b/tests/libcxx-backports/extents/ctor_from_array.pass.cpp @@ -12,11 +12,13 @@ // Test construction from array: // // template -// constexpr explicit(N != rank_dynamic()) extents(const array& exts) noexcept; +// constexpr explicit(N != rank_dynamic()) extents(const +// array& exts) noexcept; // // Constraints: // * is_convertible_v is true, -// * is_nothrow_constructible_v is true, and +// * is_nothrow_constructible_v is true, +// and // * N == rank_dynamic() || N == rank() is true. // // Preconditions: @@ -24,7 +26,8 @@ // Er is a static extent, and // * either // - N is zero, or -// - exts[r] is nonnegative and is representable as a value of type index_type +// - exts[r] is nonnegative and is representable as a value of type +// index_type // for every rank index r. // @@ -39,7 +42,8 @@ struct ArrayCtorTest { template - static constexpr void test_construction(std::array all_ext, Extents ext, std::index_sequence) { + static constexpr void test_construction(std::array all_ext, Extents ext, + std::index_sequence) { ASSERT_NOEXCEPT(E(ext)); if constexpr (N == E::rank_dynamic()) { test_implicit_construction_call(ext, all_ext); @@ -64,35 +68,47 @@ int main(int, char**) { using E = std::extents; // check can't construct from too few arguments - static_assert(!std::is_constructible_v>, "extents constructible from illegal arguments"); + static_assert(!std::is_constructible_v>, + "extents constructible from illegal arguments"); // check can't construct from rank_dynamic < #args < rank - static_assert(!std::is_constructible_v>, "extents constructible from illegal arguments"); + static_assert(!std::is_constructible_v>, + "extents constructible from illegal arguments"); // check can't construct from too many arguments - static_assert(!std::is_constructible_v>, "extents constructible from illegal arguments"); + static_assert(!std::is_constructible_v>, + "extents constructible from illegal arguments"); - // test implicit construction fails from span and array if all extents are given + // test implicit construction fails from span and array if all extents are + // given std::array a5{3, 4, 5, 6, 7}; // check that explicit construction works, i.e. no error - static_assert(std::is_constructible_v< std::extents, decltype(a5)>, - "extents unexpectectly not constructible"); + static_assert( + std::is_constructible_v, decltype(a5)>, + "extents unexpectectly not constructible"); // check that implicit construction doesn't work - assert((implicit_construction>(a5).value == false)); + assert((implicit_construction>(a5).value == + false)); - // test construction fails from types not convertible to index_type but convertible to other integer types - static_assert(std::is_convertible_v, "Test helper IntType unexpectedly not convertible to int"); - static_assert(!std::is_constructible_v< std::extents, std::array>, + // test construction fails from types not convertible to index_type but + // convertible to other integer types + static_assert(std::is_convertible_v, + "Test helper IntType unexpectedly not convertible to int"); + static_assert(!std::is_constructible_v, + std::array>, "extents constructible from illegal arguments"); // index_type is not nothrow constructible static_assert(std::is_convertible_v); static_assert(std::is_convertible_v); - static_assert(!std::is_nothrow_constructible_v); - static_assert(!std::is_constructible_v, std::array>); + static_assert( + !std::is_nothrow_constructible_v); + static_assert(!std::is_constructible_v, + std::array>); // convertible from non-const to index_type but not from const static_assert(std::is_convertible_v); static_assert(!std::is_convertible_v); static_assert(std::is_nothrow_constructible_v); - static_assert(!std::is_constructible_v, std::array>); + static_assert(!std::is_constructible_v, + std::array>); return 0; } diff --git a/tests/libcxx-backports/extents/ctor_from_integral.pass.cpp b/tests/libcxx-backports/extents/ctor_from_integral.pass.cpp index aea4340d..5256ce17 100644 --- a/tests/libcxx-backports/extents/ctor_from_integral.pass.cpp +++ b/tests/libcxx-backports/extents/ctor_from_integral.pass.cpp @@ -15,19 +15,23 @@ // constexpr explicit extents(OtherIndexTypes ... exts) noexcept; // // Let N be sizeof...(OtherIndexTypes), and let -// exts_arr be array{static_cast(std::move(exts))...}. +// exts_arr be array{static_cast(std::move(exts))...}. // // Constraints: // * (is_convertible_v && ...) is true, -// * (is_nothrow_constructible_v && ...) is true, and +// * (is_nothrow_constructible_v && ...) is true, +// and // * N == rank_dynamic() || N == rank() is true. // // Preconditions: -// * If N != rank_dynamic() is true, exts_arr[r] equals Er for each r for which +// * If N != rank_dynamic() is true, exts_arr[r] equals Er for each r for +// which // Er is a static extent, and // * either // - sizeof...(exts) == 0 is true, or -// - each element of exts is nonnegative and is representable as a value of type index_type. +// - each element of exts is nonnegative and is representable as a value of +// type index_type. // #include @@ -40,7 +44,8 @@ struct IntegralCtorTest { template - static constexpr void test_construction(AllExtents all_ext, Extents ext, std::index_sequence) { + static constexpr void test_construction(AllExtents all_ext, Extents ext, + std::index_sequence) { // construction from indices ASSERT_NOEXCEPT(E(ext[Indices]...)); test_runtime_observers(E(ext[Indices]...), all_ext); @@ -55,15 +60,21 @@ int main(int, char**) { using E = std::extents; // check can't construct from too few arguments - static_assert(!std::is_constructible_v, "extents constructible from illegal arguments"); + static_assert(!std::is_constructible_v, + "extents constructible from illegal arguments"); // check can't construct from rank_dynamic < #args < rank - static_assert(!std::is_constructible_v, "extents constructible from illegal arguments"); + static_assert(!std::is_constructible_v, + "extents constructible from illegal arguments"); // check can't construct from too many arguments - static_assert(!std::is_constructible_v, "extents constructible from illegal arguments"); - - // test construction fails from types not convertible to index_type but convertible to other integer types - static_assert(std::is_convertible_v, "Test helper IntType unexpectedly not convertible to int"); - static_assert(!std::is_constructible_v< std::extents, IntType>, + static_assert(!std::is_constructible_v, "extents constructible from illegal arguments"); + + // test construction fails from types not convertible to index_type but + // convertible to other integer types + static_assert(std::is_convertible_v, + "Test helper IntType unexpectedly not convertible to int"); + static_assert( + !std::is_constructible_v, IntType>, + "extents constructible from illegal arguments"); return 0; } diff --git a/tests/libcxx-backports/extents/ctor_from_span.pass.cpp b/tests/libcxx-backports/extents/ctor_from_span.pass.cpp index 7f412ff1..c90017fc 100644 --- a/tests/libcxx-backports/extents/ctor_from_span.pass.cpp +++ b/tests/libcxx-backports/extents/ctor_from_span.pass.cpp @@ -12,11 +12,13 @@ // Test construction from span: // // template -// constexpr explicit(N != rank_dynamic()) extents(span exts) noexcept; +// constexpr explicit(N != rank_dynamic()) extents(span +// exts) noexcept; // // Constraints: // * is_convertible_v is true, -// * is_nothrow_constructible_v is true, and +// * is_nothrow_constructible_v is true, +// and // * N == rank_dynamic() || N == rank() is true. // // Preconditions: @@ -24,7 +26,8 @@ // Er is a static extent, and // * either // - N is zero, or -// - exts[r] is nonnegative and is representable as a value of type index_type +// - exts[r] is nonnegative and is representable as a value of type +// index_type // for every rank index r. // @@ -40,7 +43,8 @@ struct SpanCtorTest { template - static constexpr void test_construction(std::array all_ext, Extents ext, std::index_sequence) { + static constexpr void test_construction(std::array all_ext, Extents ext, + std::index_sequence) { ASSERT_NOEXCEPT(E(ext)); if constexpr (N == E::rank_dynamic()) { test_implicit_construction_call(std::span(ext), all_ext); @@ -64,6 +68,7 @@ int main(int, char**) { constexpr size_t D = std::dynamic_extent; using E = std::extents; + // clang-format off // check can't construct from too few arguments static_assert(!std::is_constructible_v>, "extents constructible from illegal arguments"); // check can't construct from rank_dynamic < #args < rank @@ -96,5 +101,6 @@ int main(int, char**) { static_assert(!std::is_convertible_v); static_assert(std::is_nothrow_constructible_v); static_assert(!std::is_constructible_v, std::span>); + // clang-format on return 0; } diff --git a/tests/libcxx-backports/extents/dextents.pass.cpp b/tests/libcxx-backports/extents/dextents.pass.cpp index 7a855281..14224548 100644 --- a/tests/libcxx-backports/extents/dextents.pass.cpp +++ b/tests/libcxx-backports/extents/dextents.pass.cpp @@ -27,8 +27,10 @@ void test_alias_template_dextents() { ASSERT_SAME_TYPE(std::dextents, std::extents); ASSERT_SAME_TYPE(std::dextents, std::extents); ASSERT_SAME_TYPE(std::dextents, std::extents); - ASSERT_SAME_TYPE(std::dextents, std::extents); - ASSERT_SAME_TYPE(std::dextents, std::extents); + ASSERT_SAME_TYPE(std::dextents, + std::extents); + ASSERT_SAME_TYPE(std::dextents, + std::extents); } int main(int, char**) { diff --git a/tests/libcxx-backports/extents/obs_static.pass.cpp b/tests/libcxx-backports/extents/obs_static.pass.cpp index e284f337..1f324181 100644 --- a/tests/libcxx-backports/extents/obs_static.pass.cpp +++ b/tests/libcxx-backports/extents/obs_static.pass.cpp @@ -32,8 +32,10 @@ #include "../llvm_test_macros.h" -template -void test_static_observers(std::index_sequence, std::index_sequence) { +template +void test_static_observers(std::index_sequence, + std::index_sequence) { ASSERT_NOEXCEPT(E::rank()); static_assert(E::rank() == rank); ASSERT_NOEXCEPT(E::rank_dynamic()); @@ -50,7 +52,8 @@ void test_static_observers(std::index_sequence, std::index_sequen template void test_static_observers() { test_static_observers( - std::index_sequence(), std::make_index_sequence()); + std::index_sequence(), + std::make_index_sequence()); } template @@ -58,6 +61,7 @@ void test() { constexpr size_t D = std::dynamic_extent; constexpr size_t S = 5; + // clang-format off test_static_observers, 0, 0>(); test_static_observers, 1, 0, S>(); @@ -76,6 +80,7 @@ void test() { test_static_observers, 3, 2, D, S, D>(); test_static_observers, 3, 2, D, D, S>(); test_static_observers, 3, 3, D, D, D>(); + // clang-format on } int main(int, char**) { diff --git a/tests/libcxx-backports/extents/types.pass.cpp b/tests/libcxx-backports/extents/types.pass.cpp index 47501d5b..8ea30cb4 100644 --- a/tests/libcxx-backports/extents/types.pass.cpp +++ b/tests/libcxx-backports/extents/types.pass.cpp @@ -18,7 +18,8 @@ // using rank_type = size_t; // // static constexpr rank_type rank() noexcept { return sizeof...(Extents); } -// static constexpr rank_type rank_dynamic() noexcept { return dynamic-index(rank()); } +// static constexpr rank_type rank_dynamic() noexcept { return +// dynamic-index(rank()); } // ... // } @@ -36,7 +37,8 @@ void testExtents() { ASSERT_SAME_TYPE(typename E::rank_type, size_t); static_assert(sizeof...(Extents) == E::rank()); - static_assert((static_cast(Extents == std::dynamic_extent) + ...) == E::rank_dynamic()); + static_assert((static_cast(Extents == std::dynamic_extent) + ...) == + E::rank_dynamic()); static_assert(std::regular); static_assert(std::is_trivially_copyable_v); @@ -55,6 +57,7 @@ void testExtents() { template void test() { constexpr size_t D = std::dynamic_extent; + // clang-format off testExtents(); testExtents(); testExtents(); @@ -73,6 +76,7 @@ void test() { testExtents(); testExtents(); testExtents(); + // clang-format on } int main(int, char**) { diff --git a/tests/libcxx-backports/layout_left/layout_left.comparison.pass.cpp b/tests/libcxx-backports/layout_left/layout_left.comparison.pass.cpp index 1f797c78..7de191cd 100644 --- a/tests/libcxx-backports/layout_left/layout_left.comparison.pass.cpp +++ b/tests/libcxx-backports/layout_left/layout_left.comparison.pass.cpp @@ -11,7 +11,8 @@ // // template -// friend constexpr bool operator==(const mapping& x, const mapping& y) noexcept; +// friend constexpr bool operator==(const mapping& x, const +// mapping& y) noexcept; // ` // Constraints: extents_type::rank() == OtherExtents::rank() is true. @@ -39,7 +40,8 @@ constexpr X compare_layout_mappings(...) { return {}; } template constexpr auto compare_layout_mappings(E1 e1, E2 e2) - -> decltype(std::layout_left::mapping(e1) == std::layout_left::mapping(e2)) { + -> decltype(std::layout_left::mapping(e1) == + std::layout_left::mapping(e2)) { return true; } @@ -48,49 +50,74 @@ constexpr void test_comparison_different_rank() { constexpr size_t D = std::dynamic_extent; // sanity check same rank - static_assert(compare_layout_mappings(std::extents(5), std::extents(5))); - static_assert(compare_layout_mappings(std::extents(), std::extents(5))); - static_assert(compare_layout_mappings(std::extents(5), std::extents())); - static_assert(compare_layout_mappings(std::extents(), std::extents())); + static_assert( + compare_layout_mappings(std::extents(5), std::extents(5))); + static_assert( + compare_layout_mappings(std::extents(), std::extents(5))); + static_assert( + compare_layout_mappings(std::extents(5), std::extents())); + static_assert( + compare_layout_mappings(std::extents(), std::extents())); // not equality comparable when rank is not the same - static_assert(compare_layout_mappings(std::extents(), std::extents(1)).does_not_match()); - static_assert(compare_layout_mappings(std::extents(), std::extents()).does_not_match()); - - static_assert(compare_layout_mappings(std::extents(1), std::extents()).does_not_match()); - static_assert(compare_layout_mappings(std::extents(), std::extents()).does_not_match()); - - static_assert(compare_layout_mappings(std::extents(5), std::extents(5, 5)).does_not_match()); - static_assert(compare_layout_mappings(std::extents(), std::extents(5)).does_not_match()); - static_assert(compare_layout_mappings(std::extents(), std::extents()).does_not_match()); - - static_assert(compare_layout_mappings(std::extents(5, 5), std::extents(5)).does_not_match()); - static_assert(compare_layout_mappings(std::extents(5), std::extents(5)).does_not_match()); - static_assert(compare_layout_mappings(std::extents(), std::extents()).does_not_match()); + static_assert( + compare_layout_mappings(std::extents(), std::extents(1)) + .does_not_match()); + static_assert( + compare_layout_mappings(std::extents(), std::extents()) + .does_not_match()); + + static_assert( + compare_layout_mappings(std::extents(1), std::extents()) + .does_not_match()); + static_assert( + compare_layout_mappings(std::extents(), std::extents()) + .does_not_match()); + + static_assert(compare_layout_mappings(std::extents(5), + std::extents(5, 5)) + .does_not_match()); + static_assert( + compare_layout_mappings(std::extents(), std::extents(5)) + .does_not_match()); + static_assert( + compare_layout_mappings(std::extents(), std::extents()) + .does_not_match()); + + static_assert(compare_layout_mappings(std::extents(5, 5), + std::extents(5)) + .does_not_match()); + static_assert( + compare_layout_mappings(std::extents(5), std::extents(5)) + .does_not_match()); + static_assert( + compare_layout_mappings(std::extents(), std::extents()) + .does_not_match()); } template constexpr void test_comparison_same_rank() { constexpr size_t D = std::dynamic_extent; - test_comparison(true, std::extents(), std::extents()); + // clang-format off + test_comparison(true, std::extents(), std::extents()); - test_comparison(true, std::extents(5), std::extents(5)); - test_comparison(true, std::extents(), std::extents(5)); - test_comparison(true, std::extents(5), std::extents()); - test_comparison(true, std::extents(), std::extents< T2, 5>()); + test_comparison(true, std::extents(5), std::extents(5)); + test_comparison(true, std::extents(), std::extents(5)); + test_comparison(true, std::extents(5), std::extents()); + test_comparison(true, std::extents(), std::extents< T2, 5>()); test_comparison(false, std::extents(5), std::extents(7)); test_comparison(false, std::extents(), std::extents(7)); test_comparison(false, std::extents(5), std::extents()); test_comparison(false, std::extents(), std::extents()); - test_comparison(true, std::extents(5, 6, 7, 8, 9), std::extents(5, 6, 7, 8, 9)); - test_comparison(true, std::extents(5, 7, 9), std::extents(6, 7)); - test_comparison(true, std::extents(5, 6, 7, 8, 9), std::extents()); - test_comparison( - false, std::extents(5, 6, 7, 8, 9), std::extents(5, 6, 3, 8, 9)); + test_comparison(true, std::extents(5, 6, 7, 8, 9), std::extents(5, 6, 7, 8, 9)); + test_comparison(true, std::extents(5, 7, 9), std::extents(6, 7)); + test_comparison(true, std::extents(5, 6, 7, 8, 9), std::extents()); + test_comparison(false, std::extents(5, 6, 7, 8, 9), std::extents(5, 6, 3, 8, 9)); test_comparison(false, std::extents(5, 7, 9), std::extents(6, 7)); test_comparison(false, std::extents(5, 6, 7, 8, 9), std::extents()); + // clang-format on } template diff --git a/tests/libcxx-backports/layout_left/layout_left.ctor.extents.pass.cpp b/tests/libcxx-backports/layout_left/layout_left.ctor.extents.pass.cpp index 41185c8f..ab180f99 100644 --- a/tests/libcxx-backports/layout_left/layout_left.ctor.extents.pass.cpp +++ b/tests/libcxx-backports/layout_left/layout_left.ctor.extents.pass.cpp @@ -12,7 +12,8 @@ // constexpr mapping(const extents_type&) noexcept; // -// Preconditions: The size of the multidimensional index space e is representable +// Preconditions: The size of the multidimensional index space e is +// representable // as a value of type index_type ([basic.fundamental]). // // Effects: Direct-non-list-initializes extents_ with e. diff --git a/tests/libcxx-backports/layout_left/layout_left.ctor.layout_right.pass.cpp b/tests/libcxx-backports/layout_left/layout_left.ctor.layout_right.pass.cpp index 78d54c79..d1613b11 100644 --- a/tests/libcxx-backports/layout_left/layout_left.ctor.layout_right.pass.cpp +++ b/tests/libcxx-backports/layout_left/layout_left.ctor.layout_right.pass.cpp @@ -18,7 +18,8 @@ // - extents_type::rank() <= 1 is true, and // - is_constructible_v is true. // -// Preconditions: other.required_span_size() is representable as a value of type index_type +// Preconditions: other.required_span_size() is representable as a value of type +// index_type #include #include @@ -53,7 +54,8 @@ template constexpr void test_conversion() { constexpr size_t D = std::dynamic_extent; constexpr bool idx_convertible = - static_cast(std::numeric_limits::max()) >= static_cast(std::numeric_limits::max()); + static_cast(std::numeric_limits::max()) >= + static_cast(std::numeric_limits::max()); // clang-format off test_conversion>(std::extents()); @@ -64,49 +66,68 @@ constexpr void test_conversion() { } template -using lr_mapping_t = typename std::layout_right::template mapping>; +using lr_mapping_t = typename std::layout_right::template mapping< + std::extents>; template -using ll_mapping_t = typename std::layout_left::template mapping>; +using ll_mapping_t = + typename std::layout_left::template mapping>; constexpr void test_no_implicit_conversion() { constexpr size_t D = std::dynamic_extent; // Sanity check that one static to dynamic conversion works - static_assert(std::is_constructible_v, lr_mapping_t>); - static_assert(std::is_convertible_v, ll_mapping_t>); + static_assert( + std::is_constructible_v, lr_mapping_t>); + static_assert( + std::is_convertible_v, ll_mapping_t>); // Check that dynamic to static conversion only works explicitly - static_assert(std::is_constructible_v, lr_mapping_t>); - static_assert(!std::is_convertible_v, ll_mapping_t>); + static_assert( + std::is_constructible_v, lr_mapping_t>); + static_assert( + !std::is_convertible_v, ll_mapping_t>); // Sanity check that smaller index_type to larger index_type conversion works - static_assert(std::is_constructible_v, lr_mapping_t>); - static_assert(std::is_convertible_v, ll_mapping_t>); - - // Check that larger index_type to smaller index_type conversion works explicitly only - static_assert(std::is_constructible_v, lr_mapping_t>); - static_assert(!std::is_convertible_v, ll_mapping_t>); + static_assert( + std::is_constructible_v, lr_mapping_t>); + static_assert( + std::is_convertible_v, ll_mapping_t>); + + // Check that larger index_type to smaller index_type conversion works + // explicitly only + static_assert( + std::is_constructible_v, lr_mapping_t>); + static_assert( + !std::is_convertible_v, ll_mapping_t>); } constexpr void test_rank_mismatch() { constexpr size_t D = std::dynamic_extent; - static_assert(!std::is_constructible_v, lr_mapping_t>); - static_assert(!std::is_constructible_v, lr_mapping_t>); - static_assert(!std::is_constructible_v, lr_mapping_t>); - static_assert(!std::is_constructible_v, lr_mapping_t>); + static_assert( + !std::is_constructible_v, lr_mapping_t>); + static_assert( + !std::is_constructible_v, lr_mapping_t>); + static_assert( + !std::is_constructible_v, lr_mapping_t>); + static_assert(!std::is_constructible_v, + lr_mapping_t>); } constexpr void test_static_extent_mismatch() { - static_assert(!std::is_constructible_v, lr_mapping_t>); + static_assert( + !std::is_constructible_v, lr_mapping_t>); } constexpr void test_rank_greater_one() { constexpr size_t D = std::dynamic_extent; - static_assert(!std::is_constructible_v, lr_mapping_t>); - static_assert(!std::is_constructible_v, lr_mapping_t>); - static_assert(!std::is_constructible_v, lr_mapping_t>); + static_assert(!std::is_constructible_v, + lr_mapping_t>); + static_assert(!std::is_constructible_v, + lr_mapping_t>); + static_assert(!std::is_constructible_v, + lr_mapping_t>); } constexpr bool test() { diff --git a/tests/libcxx-backports/layout_left/layout_left.ctor.layout_stride.pass.cpp b/tests/libcxx-backports/layout_left/layout_left.ctor.layout_stride.pass.cpp index 05417d1b..57320834 100644 --- a/tests/libcxx-backports/layout_left/layout_left.ctor.layout_stride.pass.cpp +++ b/tests/libcxx-backports/layout_left/layout_left.ctor.layout_stride.pass.cpp @@ -17,9 +17,11 @@ // Constraints: is_constructible_v is true. // // Preconditions: -// - If extents_type::rank() > 0 is true, then for all r in the range [0, extents_type::rank()), +// - If extents_type::rank() > 0 is true, then for all r in the range [0, +// extents_type::rank()), // other.stride(r) equals other.extents().fwd-prod-of-extents(r), and -// - other.required_span_size() is representable as a value of type index_type ([basic.fundamental]). +// - other.required_span_size() is representable as a value of type index_type +// ([basic.fundamental]). // // Effects: Direct-non-list-initializes extents_ with other.extents(). @@ -80,25 +82,34 @@ constexpr void test_conversion() { } template -using ll_mapping_t = typename std::layout_left::template mapping>; +using ll_mapping_t = + typename std::layout_left::template mapping>; template -using ls_mapping_t = typename std::layout_stride::template mapping>; +using ls_mapping_t = typename std::layout_stride::template mapping< + std::extents>; constexpr void test_rank_mismatch() { constexpr size_t D = std::dynamic_extent; - static_assert(!std::is_constructible_v, ls_mapping_t>); - static_assert(!std::is_constructible_v, ls_mapping_t>); - static_assert(!std::is_constructible_v, ls_mapping_t>); - static_assert(!std::is_constructible_v, ls_mapping_t>); + static_assert( + !std::is_constructible_v, ls_mapping_t>); + static_assert( + !std::is_constructible_v, ls_mapping_t>); + static_assert( + !std::is_constructible_v, ls_mapping_t>); + static_assert(!std::is_constructible_v, + ls_mapping_t>); } constexpr void test_static_extent_mismatch() { constexpr size_t D = std::dynamic_extent; - static_assert(!std::is_constructible_v, ls_mapping_t>); - static_assert(!std::is_constructible_v, ls_mapping_t>); - static_assert(!std::is_constructible_v, ls_mapping_t>); + static_assert(!std::is_constructible_v, + ls_mapping_t>); + static_assert( + !std::is_constructible_v, ls_mapping_t>); + static_assert(!std::is_constructible_v, + ls_mapping_t>); } constexpr bool test() { diff --git a/tests/libcxx-backports/layout_left/layout_left.ctor.mapping.pass.cpp b/tests/libcxx-backports/layout_left/layout_left.ctor.mapping.pass.cpp index a1cdcabc..8ce45349 100644 --- a/tests/libcxx-backports/layout_left/layout_left.ctor.mapping.pass.cpp +++ b/tests/libcxx-backports/layout_left/layout_left.ctor.mapping.pass.cpp @@ -16,7 +16,8 @@ // Constraints: is_constructible_v is true. // -// Preconditions: other.required_span_size() is representable as a value of type index_type +// Preconditions: other.required_span_size() is representable as a value of type +// index_type #include #include @@ -51,7 +52,8 @@ template constexpr void test_conversion() { constexpr size_t D = std::dynamic_extent; constexpr bool idx_convertible = - static_cast(std::numeric_limits::max()) >= static_cast(std::numeric_limits::max()); + static_cast(std::numeric_limits::max()) >= + static_cast(std::numeric_limits::max()); // clang-format off test_conversion>(std::extents()); @@ -71,7 +73,8 @@ constexpr void test_conversion() { } template -using mapping_t = typename std::layout_left::template mapping>; +using mapping_t = + typename std::layout_left::template mapping>; constexpr void test_no_implicit_conversion() { constexpr size_t D = std::dynamic_extent; @@ -85,20 +88,28 @@ constexpr void test_no_implicit_conversion() { static_assert(!std::is_convertible_v, mapping_t>); // Sanity check that one static to dynamic conversion works - static_assert(std::is_constructible_v, mapping_t>); - static_assert(std::is_convertible_v, mapping_t>); + static_assert( + std::is_constructible_v, mapping_t>); + static_assert( + std::is_convertible_v, mapping_t>); // Check that dynamic to static conversion only works explicitly - static_assert(std::is_constructible_v, mapping_t>); - static_assert(!std::is_convertible_v, mapping_t>); + static_assert( + std::is_constructible_v, mapping_t>); + static_assert( + !std::is_convertible_v, mapping_t>); // Sanity check that smaller index_type to larger index_type conversion works - static_assert(std::is_constructible_v, mapping_t>); + static_assert( + std::is_constructible_v, mapping_t>); static_assert(std::is_convertible_v, mapping_t>); - // Check that larger index_type to smaller index_type conversion works explicitly only - static_assert(std::is_constructible_v, mapping_t>); - static_assert(!std::is_convertible_v, mapping_t>); + // Check that larger index_type to smaller index_type conversion works + // explicitly only + static_assert( + std::is_constructible_v, mapping_t>); + static_assert( + !std::is_convertible_v, mapping_t>); } constexpr void test_rank_mismatch() { @@ -106,16 +117,20 @@ constexpr void test_rank_mismatch() { static_assert(!std::is_constructible_v, mapping_t>); static_assert(!std::is_constructible_v, mapping_t>); - static_assert(!std::is_constructible_v, mapping_t>); - static_assert(!std::is_constructible_v, mapping_t>); + static_assert( + !std::is_constructible_v, mapping_t>); + static_assert( + !std::is_constructible_v, mapping_t>); } constexpr void test_static_extent_mismatch() { constexpr size_t D = std::dynamic_extent; - static_assert(!std::is_constructible_v, mapping_t>); + static_assert( + !std::is_constructible_v, mapping_t>); static_assert(!std::is_constructible_v, mapping_t>); - static_assert(!std::is_constructible_v, mapping_t>); + static_assert( + !std::is_constructible_v, mapping_t>); } constexpr bool test() { diff --git a/tests/libcxx-backports/layout_left/layout_left.extents.verify.cpp b/tests/libcxx-backports/layout_left/layout_left.extents.verify.cpp index 85995d36..33954107 100644 --- a/tests/libcxx-backports/layout_left/layout_left.extents.verify.cpp +++ b/tests/libcxx-backports/layout_left/layout_left.extents.verify.cpp @@ -23,11 +23,14 @@ #include void not_extents() { - // expected-error-re@*:* {{static assertion failed {{.*}}layout_left::mapping template argument must be a specialization of extents}} + // expected-error-re@*:* {{static assertion failed {{.*}}layout_left::mapping + // template argument must be a specialization of extents}} [[maybe_unused]] std::layout_left::mapping mapping; } void representable() { - // expected-error-re@*:* {{static assertion failed {{.*}}layout_left::mapping product of static extents must be representable as index_type.}} - [[maybe_unused]] std::layout_left::mapping> mapping; + // expected-error-re@*:* {{static assertion failed {{.*}}layout_left::mapping + // product of static extents must be representable as index_type.}} + [[maybe_unused]] std::layout_left::mapping> + mapping; } diff --git a/tests/libcxx-backports/layout_left/layout_left.index_operator.pass.cpp b/tests/libcxx-backports/layout_left/layout_left.index_operator.pass.cpp index 1a3394e7..946f981d 100644 --- a/tests/libcxx-backports/layout_left/layout_left.index_operator.pass.cpp +++ b/tests/libcxx-backports/layout_left/layout_left.index_operator.pass.cpp @@ -31,28 +31,27 @@ #include "../ConvertibleToIntegral.h" -template -concept operator_constraints = requires(Mapping m, Indices ... idxs) { - {std::is_same_v}; +template +concept operator_constraints = requires(Mapping m, Indices... idxs) { + { std::is_same_v }; }; -template - requires( - operator_constraints - ) -constexpr bool check_operator_constraints(Mapping m, Indices ... idxs) { - (void) m(idxs...); +template + requires(operator_constraints) +constexpr bool check_operator_constraints(Mapping m, Indices... idxs) { + (void)m(idxs...); return true; } -template -constexpr bool check_operator_constraints(Mapping, Indices ...) { +template +constexpr bool check_operator_constraints(Mapping, Indices...) { return false; } template constexpr void iterate_left(M m, T& count, Args... args) { - constexpr int r = static_cast(M::extents_type::rank()) - 1 - static_cast(sizeof...(Args)); + constexpr int r = static_cast(M::extents_type::rank()) - 1 - + static_cast(sizeof...(Args)); if constexpr (-1 == r) { ASSERT_NOEXCEPT(m(args...)); assert(count == m(args...)); @@ -83,15 +82,28 @@ constexpr bool test() { test_iteration>(1, 1, 1, 1); // Check operator constraint for number of arguments - static_assert(check_operator_constraints(std::layout_left::mapping>(std::extents(1)), 0)); - static_assert(!check_operator_constraints(std::layout_left::mapping>(std::extents(1)), 0, 0)); + static_assert(check_operator_constraints( + std::layout_left::mapping>(std::extents(1)), + 0)); + static_assert(!check_operator_constraints( + std::layout_left::mapping>(std::extents(1)), + 0, 0)); // Check operator constraint for convertibility of arguments to index_type - static_assert(check_operator_constraints(std::layout_left::mapping>(std::extents(1)), IntType(0))); - static_assert(!check_operator_constraints(std::layout_left::mapping>(std::extents(1)), IntType(0))); - - // Check operator constraint for no-throw-constructibility of index_type from arguments - static_assert(!check_operator_constraints(std::layout_left::mapping>(std::extents(1)), IntType(0))); + static_assert(check_operator_constraints( + std::layout_left::mapping>(std::extents(1)), + IntType(0))); + static_assert(!check_operator_constraints( + std::layout_left::mapping>( + std::extents(1)), + IntType(0))); + + // Check operator constraint for no-throw-constructibility of index_type from + // arguments + static_assert(!check_operator_constraints( + std::layout_left::mapping>( + std::extents(1)), + IntType(0))); return true; } diff --git a/tests/libcxx-backports/layout_left/layout_left.required_span_size.pass.cpp b/tests/libcxx-backports/layout_left/layout_left.required_span_size.pass.cpp index 39eb154a..863e8fca 100644 --- a/tests/libcxx-backports/layout_left/layout_left.required_span_size.pass.cpp +++ b/tests/libcxx-backports/layout_left/layout_left.required_span_size.pass.cpp @@ -14,7 +14,6 @@ // // Returns: extents().fwd-prod-of-extents(extents_type::rank()). - #include #include #include @@ -22,7 +21,8 @@ #include "../llvm_test_macros.h" template -constexpr void test_required_span_size(E e, typename E::index_type expected_size) { +constexpr void test_required_span_size(E e, + typename E::index_type expected_size) { using M = std::layout_left::mapping; const M m(e); @@ -32,6 +32,7 @@ constexpr void test_required_span_size(E e, typename E::index_type expected_size constexpr bool test() { constexpr size_t D = std::dynamic_extent; + // clang-format off test_required_span_size(std::extents(), 1); test_required_span_size(std::extents(0), 0); test_required_span_size(std::extents(1), 1); @@ -41,6 +42,7 @@ constexpr bool test() { test_required_span_size(std::extents(7, 9, 10), 5040); test_required_span_size(std::extents(9, 10), 720); test_required_span_size(std::extents(9, 10), 0); + // clang-format on return true; } diff --git a/tests/libcxx-backports/layout_left/layout_left.static_requirements.pass.cpp b/tests/libcxx-backports/layout_left/layout_left.static_requirements.pass.cpp index 329a852e..d058c6f8 100644 --- a/tests/libcxx-backports/layout_left/layout_left.static_requirements.pass.cpp +++ b/tests/libcxx-backports/layout_left/layout_left.static_requirements.pass.cpp @@ -16,7 +16,8 @@ // - is_nothrow_move_assignable_v is true, // - is_nothrow_swappable_v is true, and // -// the following types and expressions are well-formed and have the specified semantics. +// the following types and expressions are well-formed and have the specified +// semantics. // // typename M::extents_type // Result: A type that is a specialization of extents. @@ -28,14 +29,18 @@ // Result: typename M::extents_type::rank_type. // // typename M::layout_type -// Result: A type MP that meets the layout mapping policy requirements ([mdspan.layout.policy.reqmts]) and for which is-mapping-of is true. +// Result: A type MP that meets the layout mapping policy requirements +// ([mdspan.layout.policy.reqmts]) and for which is-mapping-of is +// true. // // m.extents() // Result: const typename M::extents_type& // // m(i...) // Result: typename M::index_type -// Returns: A nonnegative integer less than numeric_limits::max() and less than or equal to numeric_limits::max(). +// Returns: A nonnegative integer less than numeric_limits::max() and less than or equal to +// numeric_limits::max(). // // m(i...) == m(static_cast(i)...) // Result: bool @@ -43,21 +48,26 @@ // // m.required_span_size() // Result: typename M::index_type -// Returns: If the size of the multidimensional index space m.extents() is 0, then 0, else 1 plus the maximum value of m(i...) for all i. +// Returns: If the size of the multidimensional index space m.extents() is 0, +// then 0, else 1 plus the maximum value of m(i...) for all i. // // m.is_unique() // Result: bool -// Returns: true only if for every i and j where (i != j || ...) is true, m(i...) != m(j...) is true. +// Returns: true only if for every i and j where (i != j || ...) is true, +// m(i...) != m(j...) is true. // // m.is_exhaustive() // Result: bool -// Returns: true only if for all k in the range [0, m.required_span_size()) there exists an i such that m(i...) equals k. +// Returns: true only if for all k in the range [0, m.required_span_size()) +// there exists an i such that m(i...) equals k. // // m.is_strided() // Result: bool -// Returns: true only if for every rank index r of m.extents() there exists an integer -// sr such that, for all i where (i+dr) is a multidimensional index in m.extents() ([mdspan.overview]), -// m((i + dr)...) - m(i...) equals sr +// Returns: true only if for every rank index r of m.extents() there exists +// an integer +// sr such that, for all i where (i+dr) is a multidimensional index +// in m.extents() ([mdspan.overview]), m((i + dr)...) - m(i...) +// equals sr // // m.stride(r) // Preconditions: m.is_strided() is true. @@ -66,15 +76,18 @@ // // M::is_always_unique() // Result: A constant expression ([expr.const]) of type bool. -// Returns: true only if m.is_unique() is true for all possible objects m of type M. +// Returns: true only if m.is_unique() is true for all possible objects m of +// type M. // // M::is_always_exhaustive() // Result: A constant expression ([expr.const]) of type bool. -// Returns: true only if m.is_exhaustive() is true for all possible objects m of type M. +// Returns: true only if m.is_exhaustive() is true for all possible objects m +// of type M. // // M::is_always_strided() // Result: A constant expression ([expr.const]) of type bool. -// Returns: true only if m.is_strided() is true for all possible objects m of type M. +// Returns: true only if m.is_strided() is true for all possible objects m of +// type M. #include #include @@ -97,14 +110,19 @@ void test_mapping_requirements(std::index_sequence) { ASSERT_SAME_TYPE(typename M::rank_type, typename E::rank_type); ASSERT_SAME_TYPE(typename M::layout_type, std::layout_left); ASSERT_SAME_TYPE(typename M::layout_type::template mapping, M); - static_assert(std::is_same_v().extents()), const E&>); - static_assert(std::is_same_v()(Idxs...)), typename M::index_type>); - static_assert(std::is_same_v().required_span_size()), typename M::index_type>); + static_assert( + std::is_same_v().extents()), const E&>); + static_assert(std::is_same_v()(Idxs...)), + typename M::index_type>); + static_assert(std::is_same_v().required_span_size()), + typename M::index_type>); static_assert(std::is_same_v().is_unique()), bool>); - static_assert(std::is_same_v().is_exhaustive()), bool>); + static_assert( + std::is_same_v().is_exhaustive()), bool>); static_assert(std::is_same_v().is_strided()), bool>); if constexpr (E::rank() > 0) - static_assert(std::is_same_v().stride(0)), typename M::index_type>); + static_assert(std::is_same_v().stride(0)), + typename M::index_type>); static_assert(std::is_same_v); static_assert(std::is_same_v); static_assert(std::is_same_v); diff --git a/tests/libcxx-backports/layout_left/layout_left.stride.pass.cpp b/tests/libcxx-backports/layout_left/layout_left.stride.pass.cpp index 0e1a73d0..fc2a22a2 100644 --- a/tests/libcxx-backports/layout_left/layout_left.stride.pass.cpp +++ b/tests/libcxx-backports/layout_left/layout_left.stride.pass.cpp @@ -26,21 +26,23 @@ #include "../llvm_test_macros.h" template -constexpr void test_stride(std::array strides, Args... args) { +constexpr void test_stride( + std::array strides, Args... args) { using M = std::layout_left::mapping; M m(E(args...)); ASSERT_NOEXCEPT(m.stride(0)); - for (size_t r = 0; r < E::rank(); r++) - assert(strides[r] == m.stride(r)); + for (size_t r = 0; r < E::rank(); r++) assert(strides[r] == m.stride(r)); } constexpr bool test() { constexpr size_t D = std::dynamic_extent; + // clang-format off test_stride>(std::array{1}, 7); test_stride>(std::array{1}); test_stride>(std::array{1, 7}); test_stride>(std::array{1, 7, 56, 504}, 7, 9, 10); + // clang-format on return true; } diff --git a/tests/libcxx-backports/layout_right/layout_right.comparison.pass.cpp b/tests/libcxx-backports/layout_right/layout_right.comparison.pass.cpp index d8c284e0..c79a5382 100644 --- a/tests/libcxx-backports/layout_right/layout_right.comparison.pass.cpp +++ b/tests/libcxx-backports/layout_right/layout_right.comparison.pass.cpp @@ -11,7 +11,8 @@ // // template -// friend constexpr bool operator==(const mapping& x, const mapping& y) noexcept; +// friend constexpr bool operator==(const mapping& x, const +// mapping& y) noexcept; // ` // Constraints: extents_type::rank() == OtherExtents::rank() is true. @@ -39,7 +40,8 @@ constexpr X compare_layout_mappings(...) { return {}; } template constexpr auto compare_layout_mappings(E1 e1, E2 e2) - -> decltype(std::layout_right::mapping(e1) == std::layout_right::mapping(e2)) { + -> decltype(std::layout_right::mapping(e1) == + std::layout_right::mapping(e2)) { return true; } @@ -48,49 +50,74 @@ constexpr void test_comparison_different_rank() { constexpr size_t D = std::dynamic_extent; // sanity check same rank - static_assert(compare_layout_mappings(std::extents(5), std::extents(5))); - static_assert(compare_layout_mappings(std::extents(), std::extents(5))); - static_assert(compare_layout_mappings(std::extents(5), std::extents())); - static_assert(compare_layout_mappings(std::extents(), std::extents())); + static_assert( + compare_layout_mappings(std::extents(5), std::extents(5))); + static_assert( + compare_layout_mappings(std::extents(), std::extents(5))); + static_assert( + compare_layout_mappings(std::extents(5), std::extents())); + static_assert( + compare_layout_mappings(std::extents(), std::extents())); // not equality comparable when rank is not the same - static_assert(compare_layout_mappings(std::extents(), std::extents(1)).does_not_match()); - static_assert(compare_layout_mappings(std::extents(), std::extents()).does_not_match()); - - static_assert(compare_layout_mappings(std::extents(1), std::extents()).does_not_match()); - static_assert(compare_layout_mappings(std::extents(), std::extents()).does_not_match()); - - static_assert(compare_layout_mappings(std::extents(5), std::extents(5, 5)).does_not_match()); - static_assert(compare_layout_mappings(std::extents(), std::extents(5)).does_not_match()); - static_assert(compare_layout_mappings(std::extents(), std::extents()).does_not_match()); - - static_assert(compare_layout_mappings(std::extents(5, 5), std::extents(5)).does_not_match()); - static_assert(compare_layout_mappings(std::extents(5), std::extents(5)).does_not_match()); - static_assert(compare_layout_mappings(std::extents(), std::extents()).does_not_match()); + static_assert( + compare_layout_mappings(std::extents(), std::extents(1)) + .does_not_match()); + static_assert( + compare_layout_mappings(std::extents(), std::extents()) + .does_not_match()); + + static_assert( + compare_layout_mappings(std::extents(1), std::extents()) + .does_not_match()); + static_assert( + compare_layout_mappings(std::extents(), std::extents()) + .does_not_match()); + + static_assert(compare_layout_mappings(std::extents(5), + std::extents(5, 5)) + .does_not_match()); + static_assert( + compare_layout_mappings(std::extents(), std::extents(5)) + .does_not_match()); + static_assert( + compare_layout_mappings(std::extents(), std::extents()) + .does_not_match()); + + static_assert(compare_layout_mappings(std::extents(5, 5), + std::extents(5)) + .does_not_match()); + static_assert( + compare_layout_mappings(std::extents(5), std::extents(5)) + .does_not_match()); + static_assert( + compare_layout_mappings(std::extents(), std::extents()) + .does_not_match()); } template constexpr void test_comparison_same_rank() { constexpr size_t D = std::dynamic_extent; - test_comparison(true, std::extents(), std::extents()); + // clang-format off + test_comparison(true, std::extents(), std::extents()); - test_comparison(true, std::extents(5), std::extents(5)); - test_comparison(true, std::extents(), std::extents(5)); - test_comparison(true, std::extents(5), std::extents()); - test_comparison(true, std::extents(), std::extents< T2, 5>()); + test_comparison(true, std::extents(5), std::extents(5)); + test_comparison(true, std::extents(), std::extents(5)); + test_comparison(true, std::extents(5), std::extents()); + test_comparison(true, std::extents(), std::extents< T2, 5>()); test_comparison(false, std::extents(5), std::extents(7)); test_comparison(false, std::extents(), std::extents(7)); test_comparison(false, std::extents(5), std::extents()); test_comparison(false, std::extents(), std::extents()); - test_comparison(true, std::extents(5, 6, 7, 8, 9), std::extents(5, 6, 7, 8, 9)); - test_comparison(true, std::extents(5, 7, 9), std::extents(6, 7)); - test_comparison(true, std::extents(5, 6, 7, 8, 9), std::extents()); - test_comparison( - false, std::extents(5, 6, 7, 8, 9), std::extents(5, 6, 3, 8, 9)); + test_comparison(true, std::extents(5, 6, 7, 8, 9), std::extents(5, 6, 7, 8, 9)); + test_comparison(true, std::extents(5, 7, 9), std::extents(6, 7)); + test_comparison(true, std::extents(5, 6, 7, 8, 9), std::extents()); + test_comparison(false, std::extents(5, 6, 7, 8, 9), std::extents(5, 6, 3, 8, 9)); test_comparison(false, std::extents(5, 7, 9), std::extents(6, 7)); test_comparison(false, std::extents(5, 6, 7, 8, 9), std::extents()); + // clang-format on } template diff --git a/tests/libcxx-backports/layout_right/layout_right.ctor.extents.pass.cpp b/tests/libcxx-backports/layout_right/layout_right.ctor.extents.pass.cpp index e5c7f8ef..3b9d7e1f 100644 --- a/tests/libcxx-backports/layout_right/layout_right.ctor.extents.pass.cpp +++ b/tests/libcxx-backports/layout_right/layout_right.ctor.extents.pass.cpp @@ -12,7 +12,8 @@ // constexpr mapping(const extents_type&) noexcept; // -// Preconditions: The size of the multidimensional index space e is representable +// Preconditions: The size of the multidimensional index space e is +// representable // as a value of type index_type ([basic.fundamental]). // // Effects: Direct-non-list-initializes extents_ with e. diff --git a/tests/libcxx-backports/layout_right/layout_right.ctor.layout_left.pass.cpp b/tests/libcxx-backports/layout_right/layout_right.ctor.layout_left.pass.cpp index 6bccfdee..902ed261 100644 --- a/tests/libcxx-backports/layout_right/layout_right.ctor.layout_left.pass.cpp +++ b/tests/libcxx-backports/layout_right/layout_right.ctor.layout_left.pass.cpp @@ -18,7 +18,8 @@ // - extents_type::rank() <= 1 is true, and // - is_constructible_v is true. // -// Preconditions: other.required_span_size() is representable as a value of type index_type +// Preconditions: other.required_span_size() is representable as a value of type +// index_type #include #include @@ -53,7 +54,8 @@ template constexpr void test_conversion() { constexpr size_t D = std::dynamic_extent; constexpr bool idx_convertible = - static_cast(std::numeric_limits::max()) >= static_cast(std::numeric_limits::max()); + static_cast(std::numeric_limits::max()) >= + static_cast(std::numeric_limits::max()); // clang-format off test_conversion>(std::extents()); @@ -64,49 +66,68 @@ constexpr void test_conversion() { } template -using lr_mapping_t = typename std::layout_right::template mapping>; +using lr_mapping_t = typename std::layout_right::template mapping< + std::extents>; template -using ll_mapping_t = typename std::layout_left::template mapping>; +using ll_mapping_t = + typename std::layout_left::template mapping>; constexpr void test_no_implicit_conversion() { constexpr size_t D = std::dynamic_extent; // Sanity check that one static to dynamic conversion works - static_assert(std::is_constructible_v, ll_mapping_t>); - static_assert(std::is_convertible_v, lr_mapping_t>); + static_assert( + std::is_constructible_v, ll_mapping_t>); + static_assert( + std::is_convertible_v, lr_mapping_t>); // Check that dynamic to static conversion only works explicitly - static_assert(std::is_constructible_v, ll_mapping_t>); - static_assert(!std::is_convertible_v, lr_mapping_t>); + static_assert( + std::is_constructible_v, ll_mapping_t>); + static_assert( + !std::is_convertible_v, lr_mapping_t>); // Sanity check that smaller index_type to larger index_type conversion works - static_assert(std::is_constructible_v, ll_mapping_t>); - static_assert(std::is_convertible_v, lr_mapping_t>); - - // Check that larger index_type to smaller index_type conversion works explicitly only - static_assert(std::is_constructible_v, ll_mapping_t>); - static_assert(!std::is_convertible_v, lr_mapping_t>); + static_assert( + std::is_constructible_v, ll_mapping_t>); + static_assert( + std::is_convertible_v, lr_mapping_t>); + + // Check that larger index_type to smaller index_type conversion works + // explicitly only + static_assert( + std::is_constructible_v, ll_mapping_t>); + static_assert( + !std::is_convertible_v, lr_mapping_t>); } constexpr void test_rank_mismatch() { constexpr size_t D = std::dynamic_extent; - static_assert(!std::is_constructible_v, ll_mapping_t>); - static_assert(!std::is_constructible_v, ll_mapping_t>); - static_assert(!std::is_constructible_v, ll_mapping_t>); - static_assert(!std::is_constructible_v, ll_mapping_t>); + static_assert( + !std::is_constructible_v, ll_mapping_t>); + static_assert( + !std::is_constructible_v, ll_mapping_t>); + static_assert( + !std::is_constructible_v, ll_mapping_t>); + static_assert(!std::is_constructible_v, + ll_mapping_t>); } constexpr void test_static_extent_mismatch() { - static_assert(!std::is_constructible_v, ll_mapping_t>); + static_assert( + !std::is_constructible_v, ll_mapping_t>); } constexpr void test_rank_greater_one() { constexpr size_t D = std::dynamic_extent; - static_assert(!std::is_constructible_v, ll_mapping_t>); - static_assert(!std::is_constructible_v, ll_mapping_t>); - static_assert(!std::is_constructible_v, ll_mapping_t>); + static_assert(!std::is_constructible_v, + ll_mapping_t>); + static_assert(!std::is_constructible_v, + ll_mapping_t>); + static_assert(!std::is_constructible_v, + ll_mapping_t>); } constexpr bool test() { diff --git a/tests/libcxx-backports/layout_right/layout_right.ctor.layout_stride.pass.cpp b/tests/libcxx-backports/layout_right/layout_right.ctor.layout_stride.pass.cpp index 469f5406..6c156bfe 100644 --- a/tests/libcxx-backports/layout_right/layout_right.ctor.layout_stride.pass.cpp +++ b/tests/libcxx-backports/layout_right/layout_right.ctor.layout_stride.pass.cpp @@ -17,9 +17,11 @@ // Constraints: is_constructible_v is true. // // Preconditions: -// - If extents_type::rank() > 0 is true, then for all r in the range [0, extents_type::rank()), +// - If extents_type::rank() > 0 is true, then for all r in the range [0, +// extents_type::rank()), // other.stride(r) equals other.extents().fwd-prod-of-extents(r), and -// - other.required_span_size() is representable as a value of type index_type ([basic.fundamental]). +// - other.required_span_size() is representable as a value of type index_type +// ([basic.fundamental]). // // Effects: Direct-non-list-initializes extents_ with other.extents(). @@ -80,25 +82,34 @@ constexpr void test_conversion() { } template -using lr_mapping_t = typename std::layout_right::template mapping>; +using lr_mapping_t = typename std::layout_right::template mapping< + std::extents>; template -using ls_mapping_t = typename std::layout_stride::template mapping>; +using ls_mapping_t = typename std::layout_stride::template mapping< + std::extents>; constexpr void test_rank_mismatch() { constexpr size_t D = std::dynamic_extent; - static_assert(!std::is_constructible_v, ls_mapping_t>); - static_assert(!std::is_constructible_v, ls_mapping_t>); - static_assert(!std::is_constructible_v, ls_mapping_t>); - static_assert(!std::is_constructible_v, ls_mapping_t>); + static_assert( + !std::is_constructible_v, ls_mapping_t>); + static_assert( + !std::is_constructible_v, ls_mapping_t>); + static_assert( + !std::is_constructible_v, ls_mapping_t>); + static_assert(!std::is_constructible_v, + ls_mapping_t>); } constexpr void test_static_extent_mismatch() { constexpr size_t D = std::dynamic_extent; - static_assert(!std::is_constructible_v, ls_mapping_t>); - static_assert(!std::is_constructible_v, ls_mapping_t>); - static_assert(!std::is_constructible_v, ls_mapping_t>); + static_assert(!std::is_constructible_v, + ls_mapping_t>); + static_assert( + !std::is_constructible_v, ls_mapping_t>); + static_assert(!std::is_constructible_v, + ls_mapping_t>); } constexpr bool test() { diff --git a/tests/libcxx-backports/layout_right/layout_right.ctor.mapping.pass.cpp b/tests/libcxx-backports/layout_right/layout_right.ctor.mapping.pass.cpp index ab10e681..246340e0 100644 --- a/tests/libcxx-backports/layout_right/layout_right.ctor.mapping.pass.cpp +++ b/tests/libcxx-backports/layout_right/layout_right.ctor.mapping.pass.cpp @@ -16,7 +16,8 @@ // Constraints: is_constructible_v is true. // -// Preconditions: other.required_span_size() is representable as a value of type index_type +// Preconditions: other.required_span_size() is representable as a value of type +// index_type #include #include @@ -51,7 +52,8 @@ template constexpr void test_conversion() { constexpr size_t D = std::dynamic_extent; constexpr bool idx_convertible = - static_cast(std::numeric_limits::max()) >= static_cast(std::numeric_limits::max()); + static_cast(std::numeric_limits::max()) >= + static_cast(std::numeric_limits::max()); // clang-format off test_conversion>(std::extents()); @@ -71,7 +73,8 @@ constexpr void test_conversion() { } template -using mapping_t = typename std::layout_right::template mapping>; +using mapping_t = typename std::layout_right::template mapping< + std::extents>; constexpr void test_no_implicit_conversion() { constexpr size_t D = std::dynamic_extent; @@ -85,20 +88,28 @@ constexpr void test_no_implicit_conversion() { static_assert(!std::is_convertible_v, mapping_t>); // Sanity check that one static to dynamic conversion works - static_assert(std::is_constructible_v, mapping_t>); - static_assert(std::is_convertible_v, mapping_t>); + static_assert( + std::is_constructible_v, mapping_t>); + static_assert( + std::is_convertible_v, mapping_t>); // Check that dynamic to static conversion only works explicitly - static_assert(std::is_constructible_v, mapping_t>); - static_assert(!std::is_convertible_v, mapping_t>); + static_assert( + std::is_constructible_v, mapping_t>); + static_assert( + !std::is_convertible_v, mapping_t>); // Sanity check that smaller index_type to larger index_type conversion works - static_assert(std::is_constructible_v, mapping_t>); + static_assert( + std::is_constructible_v, mapping_t>); static_assert(std::is_convertible_v, mapping_t>); - // Check that larger index_type to smaller index_type conversion works explicitly only - static_assert(std::is_constructible_v, mapping_t>); - static_assert(!std::is_convertible_v, mapping_t>); + // Check that larger index_type to smaller index_type conversion works + // explicitly only + static_assert( + std::is_constructible_v, mapping_t>); + static_assert( + !std::is_convertible_v, mapping_t>); } constexpr void test_rank_mismatch() { @@ -106,16 +117,20 @@ constexpr void test_rank_mismatch() { static_assert(!std::is_constructible_v, mapping_t>); static_assert(!std::is_constructible_v, mapping_t>); - static_assert(!std::is_constructible_v, mapping_t>); - static_assert(!std::is_constructible_v, mapping_t>); + static_assert( + !std::is_constructible_v, mapping_t>); + static_assert( + !std::is_constructible_v, mapping_t>); } constexpr void test_static_extent_mismatch() { constexpr size_t D = std::dynamic_extent; - static_assert(!std::is_constructible_v, mapping_t>); + static_assert( + !std::is_constructible_v, mapping_t>); static_assert(!std::is_constructible_v, mapping_t>); - static_assert(!std::is_constructible_v, mapping_t>); + static_assert( + !std::is_constructible_v, mapping_t>); } constexpr bool test() { diff --git a/tests/libcxx-backports/layout_right/layout_right.extents.verify.cpp b/tests/libcxx-backports/layout_right/layout_right.extents.verify.cpp index 69c1cf79..f0ebcfaf 100644 --- a/tests/libcxx-backports/layout_right/layout_right.extents.verify.cpp +++ b/tests/libcxx-backports/layout_right/layout_right.extents.verify.cpp @@ -23,11 +23,14 @@ #include void not_extents() { - // expected-error-re@*:* {{static assertion failed {{.*}}layout_right::mapping template argument must be a specialization of extents}} + // expected-error-re@*:* {{static assertion failed {{.*}}layout_right::mapping + // template argument must be a specialization of extents}} [[maybe_unused]] std::layout_right::mapping mapping; } void representable() { - // expected-error-re@*:* {{static assertion failed {{.*}}layout_right::mapping product of static extents must be representable as index_type.}} - [[maybe_unused]] std::layout_right::mapping> mapping; + // expected-error-re@*:* {{static assertion failed {{.*}}layout_right::mapping + // product of static extents must be representable as index_type.}} + [[maybe_unused]] std::layout_right::mapping> + mapping; } diff --git a/tests/libcxx-backports/layout_right/layout_right.index_operator.pass.cpp b/tests/libcxx-backports/layout_right/layout_right.index_operator.pass.cpp index 61dca46d..f60044e4 100644 --- a/tests/libcxx-backports/layout_right/layout_right.index_operator.pass.cpp +++ b/tests/libcxx-backports/layout_right/layout_right.index_operator.pass.cpp @@ -31,22 +31,20 @@ #include "../ConvertibleToIntegral.h" -template -concept operator_constraints = requires(Mapping m, Indices ... idxs) { - {std::is_same_v}; +template +concept operator_constraints = requires(Mapping m, Indices... idxs) { + { std::is_same_v }; }; -template - requires( - operator_constraints - ) -constexpr bool check_operator_constraints(Mapping m, Indices ... idxs) { - (void) m(idxs...); +template + requires(operator_constraints) +constexpr bool check_operator_constraints(Mapping m, Indices... idxs) { + (void)m(idxs...); return true; } -template -constexpr bool check_operator_constraints(Mapping, Indices ...) { +template +constexpr bool check_operator_constraints(Mapping, Indices...) { return false; } @@ -83,15 +81,28 @@ constexpr bool test() { test_iteration>(1, 1, 1, 1); // Check operator constraint for number of arguments - static_assert(check_operator_constraints(std::layout_right::mapping>(std::extents(1)), 0)); - static_assert(!check_operator_constraints(std::layout_right::mapping>(std::extents(1)), 0, 0)); + static_assert(check_operator_constraints( + std::layout_right::mapping>(std::extents(1)), + 0)); + static_assert(!check_operator_constraints( + std::layout_right::mapping>(std::extents(1)), + 0, 0)); // Check operator constraint for convertibility of arguments to index_type - static_assert(check_operator_constraints(std::layout_right::mapping>(std::extents(1)), IntType(0))); - static_assert(!check_operator_constraints(std::layout_right::mapping>(std::extents(1)), IntType(0))); - - // Check operator constraint for no-throw-constructibility of index_type from arguments - static_assert(!check_operator_constraints(std::layout_right::mapping>(std::extents(1)), IntType(0))); + static_assert(check_operator_constraints( + std::layout_right::mapping>(std::extents(1)), + IntType(0))); + static_assert(!check_operator_constraints( + std::layout_right::mapping>( + std::extents(1)), + IntType(0))); + + // Check operator constraint for no-throw-constructibility of index_type from + // arguments + static_assert(!check_operator_constraints( + std::layout_right::mapping>( + std::extents(1)), + IntType(0))); return true; } diff --git a/tests/libcxx-backports/layout_right/layout_right.required_span_size.pass.cpp b/tests/libcxx-backports/layout_right/layout_right.required_span_size.pass.cpp index 18c05129..957a8a2f 100644 --- a/tests/libcxx-backports/layout_right/layout_right.required_span_size.pass.cpp +++ b/tests/libcxx-backports/layout_right/layout_right.required_span_size.pass.cpp @@ -14,7 +14,6 @@ // // Returns: extents().fwd-prod-of-extents(extents_type::rank()). - #include #include #include @@ -22,7 +21,8 @@ #include "../llvm_test_macros.h" template -constexpr void test_required_span_size(E e, typename E::index_type expected_size) { +constexpr void test_required_span_size(E e, + typename E::index_type expected_size) { using M = std::layout_right::mapping; const M m(e); diff --git a/tests/libcxx-backports/layout_right/layout_right.static_requirements.pass.cpp b/tests/libcxx-backports/layout_right/layout_right.static_requirements.pass.cpp index 51e76adb..1723bae4 100644 --- a/tests/libcxx-backports/layout_right/layout_right.static_requirements.pass.cpp +++ b/tests/libcxx-backports/layout_right/layout_right.static_requirements.pass.cpp @@ -16,7 +16,8 @@ // - is_nothrow_move_assignable_v is true, // - is_nothrow_swappable_v is true, and // -// the following types and expressions are well-formed and have the specified semantics. +// the following types and expressions are well-formed and have the specified +// semantics. // // typename M::extents_type // Result: A type that is a specialization of extents. @@ -28,14 +29,18 @@ // Result: typename M::extents_type::rank_type. // // typename M::layout_type -// Result: A type MP that meets the layout mapping policy requirements ([mdspan.layout.policy.reqmts]) and for which is-mapping-of is true. +// Result: A type MP that meets the layout mapping policy requirements +// ([mdspan.layout.policy.reqmts]) and for which is-mapping-of is +// true. // // m.extents() // Result: const typename M::extents_type& // // m(i...) // Result: typename M::index_type -// Returns: A nonnegative integer less than numeric_limits::max() and less than or equal to numeric_limits::max(). +// Returns: A nonnegative integer less than numeric_limits::max() and less than or equal to +// numeric_limits::max(). // // m(i...) == m(static_cast(i)...) // Result: bool @@ -43,21 +48,26 @@ // // m.required_span_size() // Result: typename M::index_type -// Returns: If the size of the multidimensional index space m.extents() is 0, then 0, else 1 plus the maximum value of m(i...) for all i. +// Returns: If the size of the multidimensional index space m.extents() is 0, +// then 0, else 1 plus the maximum value of m(i...) for all i. // // m.is_unique() // Result: bool -// Returns: true only if for every i and j where (i != j || ...) is true, m(i...) != m(j...) is true. +// Returns: true only if for every i and j where (i != j || ...) is true, +// m(i...) != m(j...) is true. // // m.is_exhaustive() // Result: bool -// Returns: true only if for all k in the range [0, m.required_span_size()) there exists an i such that m(i...) equals k. +// Returns: true only if for all k in the range [0, m.required_span_size()) +// there exists an i such that m(i...) equals k. // // m.is_strided() // Result: bool -// Returns: true only if for every rank index r of m.extents() there exists an integer -// sr such that, for all i where (i+dr) is a multidimensional index in m.extents() ([mdspan.overview]), -// m((i + dr)...) - m(i...) equals sr +// Returns: true only if for every rank index r of m.extents() there exists +// an integer +// sr such that, for all i where (i+dr) is a multidimensional index +// in m.extents() ([mdspan.overview]), m((i + dr)...) - m(i...) +// equals sr // // m.stride(r) // Preconditions: m.is_strided() is true. @@ -66,15 +76,18 @@ // // M::is_always_unique() // Result: A constant expression ([expr.const]) of type bool. -// Returns: true only if m.is_unique() is true for all possible objects m of type M. +// Returns: true only if m.is_unique() is true for all possible objects m of +// type M. // // M::is_always_exhaustive() // Result: A constant expression ([expr.const]) of type bool. -// Returns: true only if m.is_exhaustive() is true for all possible objects m of type M. +// Returns: true only if m.is_exhaustive() is true for all possible objects m +// of type M. // // M::is_always_strided() // Result: A constant expression ([expr.const]) of type bool. -// Returns: true only if m.is_strided() is true for all possible objects m of type M. +// Returns: true only if m.is_strided() is true for all possible objects m of +// type M. #include #include @@ -87,7 +100,7 @@ template void test_mapping_requirements(std::index_sequence) { using E = typename M::extents_type; - //static_assert(std::__mdspan_detail::impl_is_extents_v); //FIXME + // static_assert(std::__mdspan_detail::impl_is_extents_v); //FIXME static_assert(std::is_copy_constructible_v); static_assert(std::is_nothrow_move_constructible_v); static_assert(std::is_nothrow_move_assignable_v); @@ -97,14 +110,19 @@ void test_mapping_requirements(std::index_sequence) { ASSERT_SAME_TYPE(typename M::rank_type, typename E::rank_type); ASSERT_SAME_TYPE(typename M::layout_type, std::layout_right); ASSERT_SAME_TYPE(typename M::layout_type::template mapping, M); - static_assert(std::is_same_v().extents()), const E&>); - static_assert(std::is_same_v()(Idxs...)), typename M::index_type>); - static_assert(std::is_same_v().required_span_size()), typename M::index_type>); + static_assert( + std::is_same_v().extents()), const E&>); + static_assert(std::is_same_v()(Idxs...)), + typename M::index_type>); + static_assert(std::is_same_v().required_span_size()), + typename M::index_type>); static_assert(std::is_same_v().is_unique()), bool>); - static_assert(std::is_same_v().is_exhaustive()), bool>); + static_assert( + std::is_same_v().is_exhaustive()), bool>); static_assert(std::is_same_v().is_strided()), bool>); if constexpr (E::rank() > 0) - static_assert(std::is_same_v().stride(0)), typename M::index_type>); + static_assert(std::is_same_v().stride(0)), + typename M::index_type>); static_assert(std::is_same_v); static_assert(std::is_same_v); static_assert(std::is_same_v); diff --git a/tests/libcxx-backports/layout_right/layout_right.stride.pass.cpp b/tests/libcxx-backports/layout_right/layout_right.stride.pass.cpp index 8b0a4d0d..41ded2fe 100644 --- a/tests/libcxx-backports/layout_right/layout_right.stride.pass.cpp +++ b/tests/libcxx-backports/layout_right/layout_right.stride.pass.cpp @@ -26,13 +26,13 @@ #include "../llvm_test_macros.h" template -constexpr void test_stride(std::array strides, Args... args) { +constexpr void test_stride( + std::array strides, Args... args) { using M = std::layout_right::mapping; M m(E(args...)); ASSERT_NOEXCEPT(m.stride(0)); - for (size_t r = 0; r < E::rank(); r++) - assert(strides[r] == m.stride(r)); + for (size_t r = 0; r < E::rank(); r++) assert(strides[r] == m.stride(r)); } constexpr bool test() { @@ -40,7 +40,8 @@ constexpr bool test() { test_stride>(std::array{1}, 7); test_stride>(std::array{1}); test_stride>(std::array{8, 1}); - test_stride>(std::array{720, 90, 10, 1}, 7, 9, 10); + test_stride>( + std::array{720, 90, 10, 1}, 7, 9, 10); return true; } diff --git a/tests/libcxx-backports/layout_stride/layout_stride.comparison.pass.cpp b/tests/libcxx-backports/layout_stride/layout_stride.comparison.pass.cpp index f0d0ace3..96913ea3 100644 --- a/tests/libcxx-backports/layout_stride/layout_stride.comparison.pass.cpp +++ b/tests/libcxx-backports/layout_stride/layout_stride.comparison.pass.cpp @@ -11,16 +11,20 @@ // // template -// friend constexpr bool operator==(const mapping& x, const OtherMapping& y) noexcept; +// friend constexpr bool operator==(const mapping& x, const OtherMapping& y) +// noexcept; // // Constraints: // - layout-mapping-alike is satisfied. // - rank_ == OtherMapping::extents_type::rank() is true. // - OtherMapping::is_always_strided() is true. // -// Preconditions: OtherMapping meets the layout mapping requirements ([mdspan.layout.policy.reqmts]). +// Preconditions: OtherMapping meets the layout mapping requirements +// ([mdspan.layout.policy.reqmts]). // -// Returns: true if x.extents() == y.extents() is true, OFFSET(y) == 0 is true, and each of x.stride(r) == y.stride(r) is true for r in the range [0, x.extents().rank()). Otherwise, false. +// Returns: true if x.extents() == y.extents() is true, OFFSET(y) == 0 is true, +// and each of x.stride(r) == y.stride(r) is true for r in the range [0, +// x.extents().rank()). Otherwise, false. #include #include @@ -32,44 +36,54 @@ #include "../CustomTestLayouts.h" template -concept layout_mapping_comparable = requires( - E1 e1, - E2 e2, - std::array s1, - std::array s2) { - std::layout_stride::mapping(e1, s1) == std::layout_stride::mapping(e2, s2); -}; +concept layout_mapping_comparable = + requires(E1 e1, E2 e2, std::array s1, + std::array s2) { + std::layout_stride::mapping(e1, s1) == + std::layout_stride::mapping(e2, s2); + }; template constexpr void test_comparison_different_rank() { constexpr size_t D = std::dynamic_extent; // sanity check same rank - static_assert(layout_mapping_comparable, std::extents>); - static_assert(layout_mapping_comparable, std::extents>); - static_assert(layout_mapping_comparable, std::extents>); - static_assert(layout_mapping_comparable, std::extents>); + static_assert( + layout_mapping_comparable, std::extents>); + static_assert( + layout_mapping_comparable, std::extents>); + static_assert( + layout_mapping_comparable, std::extents>); + static_assert( + layout_mapping_comparable, std::extents>); // not equality comparable when rank is not the same - static_assert(!layout_mapping_comparable, std::extents>); - static_assert(!layout_mapping_comparable, std::extents>); - static_assert(!layout_mapping_comparable, std::extents>); - static_assert(!layout_mapping_comparable, std::extents>); - static_assert(!layout_mapping_comparable, std::extents>); - static_assert(!layout_mapping_comparable, std::extents>); - static_assert(!layout_mapping_comparable, std::extents>); - static_assert(!layout_mapping_comparable, std::extents>); - static_assert(!layout_mapping_comparable, std::extents>); - static_assert(!layout_mapping_comparable, std::extents>); + static_assert( + !layout_mapping_comparable, std::extents>); + static_assert( + !layout_mapping_comparable, std::extents>); + static_assert( + !layout_mapping_comparable, std::extents>); + static_assert( + !layout_mapping_comparable, std::extents>); + static_assert( + !layout_mapping_comparable, std::extents>); + static_assert( + !layout_mapping_comparable, std::extents>); + static_assert( + !layout_mapping_comparable, std::extents>); + static_assert( + !layout_mapping_comparable, std::extents>); + static_assert( + !layout_mapping_comparable, std::extents>); + static_assert( + !layout_mapping_comparable, std::extents>); } template -constexpr void test_comparison( - bool equal, - To dest_exts, - From src_exts, - std::array dest_strides, - std::array src_strides) { +constexpr void test_comparison(bool equal, To dest_exts, From src_exts, + std::array dest_strides, + std::array src_strides) { std::layout_stride::mapping dest(dest_exts, dest_strides); std::layout_stride::mapping src(src_exts, src_strides); ASSERT_NOEXCEPT(dest == src); @@ -81,67 +95,67 @@ template constexpr void test_comparison_same_rank() { constexpr size_t D = std::dynamic_extent; - test_comparison(true, std::extents(), std::extents(), std::array{}, std::array{}); - - test_comparison(true, std::extents(5), std::extents(5), std::array{1}, std::array{1}); - test_comparison(true, std::extents(0), std::extents(0), std::array{1}, std::array{1}); - test_comparison(true, std::extents(), std::extents(5), std::array{3}, std::array{3}); - test_comparison(true, std::extents(5), std::extents(), std::array{1}, std::array{1}); - test_comparison(true, std::extents(), std::extents< T2, 5>(), std::array{1}, std::array{1}); - test_comparison(false, std::extents(), std::extents(5), std::array{2}, std::array{1}); - test_comparison(false, std::extents(5), std::extents(5), std::array{2}, std::array{1}); - test_comparison(false, std::extents(5), std::extents(7), std::array{1}, std::array{1}); - test_comparison(false, std::extents(), std::extents(7), std::array{1}, std::array{1}); - test_comparison(false, std::extents(5), std::extents(), std::array{1}, std::array{1}); - test_comparison(false, std::extents(), std::extents(), std::array{1}, std::array{1}); - - test_comparison( - true, - std::extents(5, 6, 7, 8, 9), - std::extents(5, 6, 7, 8, 9), - std::array{2, 20, 200, 2000, 20000}, - std::array{2, 20, 200, 2000, 20000}); - test_comparison( - true, - std::extents(5, 7, 9), - std::extents(6, 7), - std::array{2, 20, 200, 2000, 20000}, - std::array{2, 20, 200, 2000, 20000}); - test_comparison( - true, - std::extents(5, 6, 7, 8, 9), - std::extents(), - std::array{2, 20, 200, 2000, 20000}, - std::array{2, 20, 200, 2000, 20000}); - test_comparison( - false, - std::extents(5, 6, 7, 8, 9), - std::extents(), - std::array{2, 20, 200, 20000, 2000}, - std::array{2, 20, 200, 2000, 20000}); - test_comparison( - false, - std::extents(5, 6, 7, 8, 9), - std::extents(5, 6, 3, 8, 9), - std::array{2, 20, 200, 2000, 20000}, - std::array{2, 20, 200, 2000, 20000}); - test_comparison( - false, - std::extents(5, 7, 9), - std::extents(6, 7), - std::array{2, 20, 200, 2000, 20000}, - std::array{2, 20, 200, 2000, 20000}); - test_comparison( - false, - std::extents(5, 6, 7, 8, 9), - std::extents(), - std::array{2, 20, 200, 2000, 20000}, - std::array{2, 20, 200, 2000, 20000}); + test_comparison(true, std::extents(), std::extents(), + std::array{}, std::array{}); + + test_comparison(true, std::extents(5), std::extents(5), + std::array{1}, std::array{1}); + test_comparison(true, std::extents(0), std::extents(0), + std::array{1}, std::array{1}); + test_comparison(true, std::extents(), std::extents(5), + std::array{3}, std::array{3}); + test_comparison(true, std::extents(5), std::extents(), + std::array{1}, std::array{1}); + test_comparison(true, std::extents(), std::extents(), + std::array{1}, std::array{1}); + test_comparison(false, std::extents(), std::extents(5), + std::array{2}, std::array{1}); + test_comparison(false, std::extents(5), std::extents(5), + std::array{2}, std::array{1}); + test_comparison(false, std::extents(5), std::extents(7), + std::array{1}, std::array{1}); + test_comparison(false, std::extents(), std::extents(7), + std::array{1}, std::array{1}); + test_comparison(false, std::extents(5), std::extents(), + std::array{1}, std::array{1}); + test_comparison(false, std::extents(), std::extents(), + std::array{1}, std::array{1}); + + test_comparison(true, std::extents(5, 6, 7, 8, 9), + std::extents(5, 6, 7, 8, 9), + std::array{2, 20, 200, 2000, 20000}, + std::array{2, 20, 200, 2000, 20000}); + test_comparison(true, std::extents(5, 7, 9), + std::extents(6, 7), + std::array{2, 20, 200, 2000, 20000}, + std::array{2, 20, 200, 2000, 20000}); + test_comparison(true, std::extents(5, 6, 7, 8, 9), + std::extents(), + std::array{2, 20, 200, 2000, 20000}, + std::array{2, 20, 200, 2000, 20000}); + test_comparison(false, std::extents(5, 6, 7, 8, 9), + std::extents(), + std::array{2, 20, 200, 20000, 2000}, + std::array{2, 20, 200, 2000, 20000}); + test_comparison(false, std::extents(5, 6, 7, 8, 9), + std::extents(5, 6, 3, 8, 9), + std::array{2, 20, 200, 2000, 20000}, + std::array{2, 20, 200, 2000, 20000}); + test_comparison(false, std::extents(5, 7, 9), + std::extents(6, 7), + std::array{2, 20, 200, 2000, 20000}, + std::array{2, 20, 200, 2000, 20000}); + test_comparison(false, std::extents(5, 6, 7, 8, 9), + std::extents(), + std::array{2, 20, 200, 2000, 20000}, + std::array{2, 20, 200, 2000, 20000}); } template constexpr void test_comparison_with( - bool expect_equal, E1 e1, std::array strides, E2 e2, OtherArgs... other_args) { + bool expect_equal, E1 e1, + std::array strides, E2 e2, + OtherArgs... other_args) { typename std::layout_stride::template mapping map(e1, strides); typename OtherLayout::template mapping other_map(e2, other_args...); @@ -151,26 +165,39 @@ constexpr void test_comparison_with( template constexpr void test_comparison_with() { constexpr size_t D = std::dynamic_extent; - bool is_left_based = - std::is_same_v || std::is_same_v; - test_comparison_with(true, std::extents(), std::array{}, std::extents()); - test_comparison_with(true, std::extents(), std::array{1}, std::extents()); - test_comparison_with(true, std::extents(5), std::array{1}, std::extents()); - test_comparison_with(false, std::extents(5), std::array{2}, std::extents()); + bool is_left_based = std::is_same_v || + std::is_same_v; + test_comparison_with(true, std::extents(), + std::array{}, + std::extents()); + test_comparison_with(true, std::extents(), + std::array{1}, + std::extents()); + test_comparison_with(true, std::extents(5), + std::array{1}, + std::extents()); + test_comparison_with(false, std::extents(5), + std::array{2}, + std::extents()); test_comparison_with( - is_left_based, std::extents(5, 7), std::array{1, 5}, std::extents(5, 7)); + is_left_based, std::extents(5, 7), std::array{1, 5}, + std::extents(5, 7)); test_comparison_with( - !is_left_based, std::extents(5, 7), std::array{7, 1}, std::extents(5, 7)); - test_comparison_with( - false, std::extents(5, 7), std::array{8, 1}, std::extents(5, 7)); + !is_left_based, std::extents(5, 7), std::array{7, 1}, + std::extents(5, 7)); + test_comparison_with(false, std::extents(5, 7), + std::array{8, 1}, + std::extents(5, 7)); if constexpr (std::is_same_v) { // test layout with strides not equal to product of extents - test_comparison_with( - true, std::extents(5, 7), std::array{2, 10}, std::extents(5, 7), 0, 2); + test_comparison_with(true, std::extents(5, 7), + std::array{2, 10}, + std::extents(5, 7), 0, 2); // make sure that offset != 0 results in false - test_comparison_with( - false, std::extents(5, 7), std::array{2, 10}, std::extents(5, 7), 1, 2); + test_comparison_with(false, std::extents(5, 7), + std::array{2, 10}, + std::extents(5, 7), 1, 2); } } diff --git a/tests/libcxx-backports/layout_stride/layout_stride.ctor.default.pass.cpp b/tests/libcxx-backports/layout_stride/layout_stride.ctor.default.pass.cpp index 0310d164..c67ab416 100644 --- a/tests/libcxx-backports/layout_stride/layout_stride.ctor.default.pass.cpp +++ b/tests/libcxx-backports/layout_stride/layout_stride.ctor.default.pass.cpp @@ -15,10 +15,13 @@ // constexpr mapping() noexcept; // // -// Preconditions: layout_right::mapping().required_span_size() is representable as a value of type index_type ([basic.fundamental]). +// Preconditions: layout_right::mapping().required_span_size() is +// representable as a value of type index_type ([basic.fundamental]). // -// Effects: Direct-non-list-initializes extents_ with extents_type(), and for all d in the range [0, rank_), -// direct-non-list-initializes strides_[d] with layout_right::mapping().stride(d). +// Effects: Direct-non-list-initializes extents_ with extents_type(), and for +// all d in the range [0, rank_), +// direct-non-list-initializes strides_[d] with +// layout_right::mapping().stride(d). #include #include @@ -43,7 +46,8 @@ constexpr void test_construction() { expected_size *= e.extent(r); assert(m.required_span_size() == expected_size); - // check strides: node stride function is constrained on rank>0, e.extent(r) is not + // check strides: node stride function is constrained on rank>0, e.extent(r) + // is not auto strides = m.strides(); ASSERT_NOEXCEPT(m.strides()); if constexpr (E::rank() > 0) { diff --git a/tests/libcxx-backports/layout_stride/layout_stride.ctor.extents_array.pass.cpp b/tests/libcxx-backports/layout_stride/layout_stride.ctor.extents_array.pass.cpp index ce1a532b..3428d7a3 100644 --- a/tests/libcxx-backports/layout_stride/layout_stride.ctor.extents_array.pass.cpp +++ b/tests/libcxx-backports/layout_stride/layout_stride.ctor.extents_array.pass.cpp @@ -11,7 +11,8 @@ // // template -// constexpr mapping(const extents_type& e, array s) noexcept; +// constexpr mapping(const extents_type& e, array s) +// noexcept; // // Constraints: // - is_convertible_v is true, and @@ -19,12 +20,17 @@ // // Preconditions: // - s[i] > 0 is true for all i in the range [0, rank_). -// - REQUIRED-SPAN-SIZE(e, s) is representable as a 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. -// Note 1: For layout_stride, this condition is necessary and sufficient for is_unique() to be true. +// - REQUIRED-SPAN-SIZE(e, s) is representable as a 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. +// Note 1: For layout_stride, this condition is necessary and sufficient for +// is_unique() to be true. // -// Effects: Direct-non-list-initializes extents_ with e, and for all d in the range [0, rank_), +// Effects: Direct-non-list-initializes extents_ with e, and for all d in the +// range [0, rank_), // direct-non-list-initializes strides_[d] with as_const(s[d]). #include @@ -51,11 +57,13 @@ constexpr void test_construction(E e, S s) { expected_size = 0; break; } - expected_size += (e.extent(r) - 1) * static_cast(s[r]); + expected_size += + (e.extent(r) - 1) * static_cast(s[r]); } assert(m.required_span_size() == expected_size); - // check strides: node stride function is constrained on rank>0, e.extent(r) is not + // check strides: node stride function is constrained on rank>0, e.extent(r) + // is not auto strides = m.strides(); ASSERT_NOEXCEPT(m.strides()); if constexpr (E::rank() > 0) { @@ -114,18 +122,24 @@ constexpr bool test() { { using mapping_t = std::layout_stride::mapping>; // wrong strides size - static_assert(!std::is_constructible_v, std::array>); - static_assert(!std::is_constructible_v, std::array>); + static_assert(!std::is_constructible_v, + std::array>); + static_assert(!std::is_constructible_v, + std::array>); // wrong extents rank - static_assert(!std::is_constructible_v, std::array>); + static_assert(!std::is_constructible_v, + std::array>); // none-convertible strides - static_assert(!std::is_constructible_v, std::array>); + static_assert(!std::is_constructible_v, + std::array>); } { // not no-throw constructible index_type from stride - using mapping_t = std::layout_stride::mapping>; + using mapping_t = + std::layout_stride::mapping>; static_assert(std::is_convertible_v); - static_assert(!std::is_constructible_v, std::array>); + static_assert(!std::is_constructible_v, + std::array>); } return true; diff --git a/tests/libcxx-backports/layout_stride/layout_stride.ctor.extents_span.pass.cpp b/tests/libcxx-backports/layout_stride/layout_stride.ctor.extents_span.pass.cpp index 7c71a1f9..9d933878 100644 --- a/tests/libcxx-backports/layout_stride/layout_stride.ctor.extents_span.pass.cpp +++ b/tests/libcxx-backports/layout_stride/layout_stride.ctor.extents_span.pass.cpp @@ -11,7 +11,8 @@ // // template -// constexpr mapping(const extents_type& e, span s) noexcept; +// constexpr mapping(const extents_type& e, span s) +// noexcept; // // Constraints: // - is_convertible_v is true, and @@ -19,12 +20,17 @@ // // Preconditions: // - s[i] > 0 is true for all i in the range [0, rank_). -// - REQUIRED-SPAN-SIZE(e, s) is representable as a 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. -// Note 1: For layout_stride, this condition is necessary and sufficient for is_unique() to be true. +// - REQUIRED-SPAN-SIZE(e, s) is representable as a 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. +// Note 1: For layout_stride, this condition is necessary and sufficient for +// is_unique() to be true. // -// Effects: Direct-non-list-initializes extents_ with e, and for all d in the range [0, rank_), +// Effects: Direct-non-list-initializes extents_ with e, and for all d in the +// range [0, rank_), // direct-non-list-initializes strides_[d] with as_const(s[d]). #include @@ -51,11 +57,13 @@ constexpr void test_construction(E e, S s) { expected_size = 0; break; } - expected_size += (e.extent(r) - 1) * static_cast(s[r]); + expected_size += + (e.extent(r) - 1) * static_cast(s[r]); } assert(m.required_span_size() == expected_size); - // check strides: node stride function is constrained on rank>0, e.extent(r) is not + // check strides: node stride function is constrained on rank>0, e.extent(r) + // is not auto strides = m.strides(); ASSERT_NOEXCEPT(m.strides()); if constexpr (E::rank() > 0) { @@ -94,42 +102,60 @@ constexpr bool test() { } { std::array s{20, 2, 200, 2000}; - test_construction(std::extents(7, 9, 10), std::span(s)); + test_construction(std::extents(7, 9, 10), + std::span(s)); } { std::array s{20, 2, 200, 2000}; - test_construction(std::extents(7, 0, 10), std::span(s)); - test_construction(std::extents(0, 9, 10), std::span(s)); + test_construction(std::extents(7, 0, 10), + std::span(s)); + test_construction(std::extents(0, 9, 10), + std::span(s)); test_construction(std::extents(0, 8, 0), std::span(s)); } { std::array s{200, 20, 20, 2000}; - test_construction(std::extents(7, 0, 8, 9), std::span(s)); - test_construction(std::extents(7, 8, 0, 9), std::span(s)); - test_construction(std::extents(7, 1, 8, 9), std::span(s)); - test_construction(std::extents(7, 8, 1, 9), std::span(s)); - test_construction(std::extents(7, 1, 1, 9), std::span(s)); - test_construction(std::extents(7, 0, 0, 9), std::span(s)); - test_construction(std::extents(7, 1, 1, 9), std::span(s)); - test_construction(std::extents(7, 1, 0, 9), std::span(s)); - test_construction(std::extents(7, 0, 1, 9), std::span(s)); + test_construction(std::extents(7, 0, 8, 9), + std::span(s)); + test_construction(std::extents(7, 8, 0, 9), + std::span(s)); + test_construction(std::extents(7, 1, 8, 9), + std::span(s)); + test_construction(std::extents(7, 8, 1, 9), + std::span(s)); + test_construction(std::extents(7, 1, 1, 9), + std::span(s)); + test_construction(std::extents(7, 0, 0, 9), + std::span(s)); + test_construction(std::extents(7, 1, 1, 9), + std::span(s)); + test_construction(std::extents(7, 1, 0, 9), + std::span(s)); + test_construction(std::extents(7, 0, 1, 9), + std::span(s)); } { using mapping_t = std::layout_stride::mapping>; // wrong strides size - static_assert(!std::is_constructible_v, std::span>); - static_assert(!std::is_constructible_v, std::span>); + static_assert(!std::is_constructible_v, + std::span>); + static_assert(!std::is_constructible_v, + std::span>); // wrong extents rank - static_assert(!std::is_constructible_v, std::span>); + static_assert(!std::is_constructible_v, + std::span>); // none-convertible strides - static_assert(!std::is_constructible_v, std::span>); + static_assert(!std::is_constructible_v, + std::span>); } { // not no-throw constructible index_type from stride - using mapping_t = std::layout_stride::mapping>; + using mapping_t = + std::layout_stride::mapping>; static_assert(std::is_convertible_v); - static_assert(!std::is_constructible_v, std::span>); + static_assert(!std::is_constructible_v, + std::span>); } return true; } diff --git a/tests/libcxx-backports/layout_stride/layout_stride.ctor.strided_mapping.pass.cpp b/tests/libcxx-backports/layout_stride/layout_stride.ctor.strided_mapping.pass.cpp index 7772cbe2..3f301fbe 100644 --- a/tests/libcxx-backports/layout_stride/layout_stride.ctor.strided_mapping.pass.cpp +++ b/tests/libcxx-backports/layout_stride/layout_stride.ctor.strided_mapping.pass.cpp @@ -16,21 +16,26 @@ // // Constraints: // - layout-mapping-alike is satisfied. -// - is_constructible_v is true. +// - is_constructible_v is true. // - StridedLayoutMapping::is_always_unique() is true. // - StridedLayoutMapping::is_always_strided() is true. // // Preconditions: -// - StridedLayoutMapping meets the layout mapping requirements ([mdspan.layout.policy.reqmts]), +// - StridedLayoutMapping meets the layout mapping requirements +// ([mdspan.layout.policy.reqmts]), // - other.stride(r) > 0 is true for every rank index r of extents(), -// - other.required_span_size() is representable as a value of type index_type ([basic.fundamental]), and +// - other.required_span_size() is representable as a value of type index_type +// ([basic.fundamental]), and // - OFFSET(other) == 0 is true. // -// Effects: Direct-non-list-initializes extents_ with other.extents(), and for all d in the range [0, rank_), +// Effects: Direct-non-list-initializes extents_ with other.extents(), and for +// all d in the range [0, rank_), // direct-non-list-initializes strides_[d] with other.stride(d). // // Remarks: The expression inside explicit is equivalent to: -// - !(is_convertible_v && +// - !(is_convertible_v && // (is-mapping-of || // is-mapping-of || // is-mapping-of)) @@ -86,10 +91,11 @@ template constexpr void test_conversion() { constexpr size_t D = std::dynamic_extent; constexpr bool idx_convertible = - static_cast(std::numeric_limits::max()) >= static_cast(std::numeric_limits::max()); - constexpr bool l_convertible = - std::is_same_v || std::is_same_v || - std::is_same_v; + static_cast(std::numeric_limits::max()) >= + static_cast(std::numeric_limits::max()); + constexpr bool l_convertible = std::is_same_v || + std::is_same_v || + std::is_same_v; constexpr bool idx_l_convertible = idx_convertible && l_convertible; // clang-format off @@ -112,7 +118,8 @@ constexpr void test_conversion() { } template -using ToM = typename std::layout_stride::template mapping>; +using ToM = typename std::layout_stride::template mapping< + std::extents>; template using FromM = typename FromL::template mapping>; @@ -130,18 +137,22 @@ constexpr void test_no_implicit_conversion() { static_assert(!std::is_convertible_v, ToM>); // Sanity check that one static to dynamic conversion works - static_assert(std::is_constructible_v, FromM>); + static_assert( + std::is_constructible_v, FromM>); static_assert(std::is_convertible_v, ToM>); // Check that dynamic to static conversion only works explicitly - static_assert(std::is_constructible_v, FromM>); - static_assert(!std::is_convertible_v, ToM>); + static_assert( + std::is_constructible_v, FromM>); + static_assert( + !std::is_convertible_v, ToM>); // Sanity check that smaller index_type to larger index_type conversion works static_assert(std::is_constructible_v, FromM>); static_assert(std::is_convertible_v, ToM>); - // Check that larger index_type to smaller index_type conversion works explicitly only + // Check that larger index_type to smaller index_type conversion works + // explicitly only static_assert(std::is_constructible_v, FromM>); static_assert(!std::is_convertible_v, ToM>); } @@ -153,16 +164,19 @@ constexpr void test_rank_mismatch() { static_assert(!std::is_constructible_v, FromM>); static_assert(!std::is_constructible_v, FromM>); static_assert(!std::is_constructible_v, FromM>); - static_assert(!std::is_constructible_v, FromM>); + static_assert( + !std::is_constructible_v, FromM>); } template constexpr void test_static_extent_mismatch() { constexpr size_t D = std::dynamic_extent; - static_assert(!std::is_constructible_v, FromM>); + static_assert( + !std::is_constructible_v, FromM>); static_assert(!std::is_constructible_v, FromM>); - static_assert(!std::is_constructible_v, FromM>); + static_assert( + !std::is_constructible_v, FromM>); } template diff --git a/tests/libcxx-backports/layout_stride/layout_stride.deduction.pass.cpp b/tests/libcxx-backports/layout_stride/layout_stride.deduction.pass.cpp index b69363a7..686a1c4d 100644 --- a/tests/libcxx-backports/layout_stride/layout_stride.deduction.pass.cpp +++ b/tests/libcxx-backports/layout_stride/layout_stride.deduction.pass.cpp @@ -26,6 +26,7 @@ constexpr bool test() { constexpr size_t D = std::dynamic_extent; + // clang-format off ASSERT_SAME_TYPE(decltype(std::layout_stride::mapping(std::extents(), std::array())), std::layout_stride::template mapping>); ASSERT_SAME_TYPE(decltype(std::layout_stride::mapping(std::extents(), std::array{1})), @@ -45,6 +46,7 @@ constexpr bool test() { ASSERT_SAME_TYPE( decltype(std::layout_stride::mapping(std::extents(), std::declval>())), std::layout_stride::template mapping>); + // clang-format on return true; } diff --git a/tests/libcxx-backports/layout_stride/layout_stride.extents.verify.cpp b/tests/libcxx-backports/layout_stride/layout_stride.extents.verify.cpp index 5ee5314e..b3f8cc1d 100644 --- a/tests/libcxx-backports/layout_stride/layout_stride.extents.verify.cpp +++ b/tests/libcxx-backports/layout_stride/layout_stride.extents.verify.cpp @@ -24,11 +24,16 @@ #include "../llvm_test_macros.h" void not_extents() { - // expected-error-re@*:* {{{{(static_assert|static assertion)}} failed {{.*}}layout_stride::mapping template argument must be a specialization of extents}} + // expected-error-re@*:* {{{{(static_assert|static assertion)}} failed + // {{.*}}layout_stride::mapping template argument must be a specialization of + // extents}} [[maybe_unused]] std::layout_stride::mapping mapping; } void representable() { - // expected-error-re@*:* {{{{(static_assert|static assertion)}} failed {{.*}}layout_stride::mapping product of static extents must be representable as index_type.}} - [[maybe_unused]] std::layout_stride::mapping> mapping; + // expected-error-re@*:* {{{{(static_assert|static assertion)}} failed + // {{.*}}layout_stride::mapping product of static extents must be + // representable as index_type.}} + [[maybe_unused]] std::layout_stride::mapping> + mapping; } diff --git a/tests/libcxx-backports/layout_stride/layout_stride.index_operator.pass.cpp b/tests/libcxx-backports/layout_stride/layout_stride.index_operator.pass.cpp index 781f1df7..acf09757 100644 --- a/tests/libcxx-backports/layout_stride/layout_stride.index_operator.pass.cpp +++ b/tests/libcxx-backports/layout_stride/layout_stride.index_operator.pass.cpp @@ -49,8 +49,11 @@ constexpr bool check_operator_constraints(Mapping, Indices...) { } template -constexpr void iterate_stride(M m, const std::array& strides, Args... args) { - constexpr int r = static_cast(M::extents_type::rank()) - 1 - static_cast(sizeof...(Args)); +constexpr void iterate_stride( + M m, const std::array& strides, + Args... args) { + constexpr int r = static_cast(M::extents_type::rank()) - 1 - + static_cast(sizeof...(Args)); if constexpr (-1 == r) { ASSERT_NOEXCEPT(m(args...)); size_t expected_val = [&](std::index_sequence) { @@ -65,7 +68,8 @@ constexpr void iterate_stride(M m, const std::array -constexpr void test_iteration(std::array strides, Args... args) { +constexpr void test_iteration(std::array strides, + Args... args) { using M = std::layout_stride::mapping; M m(E(args...), strides); @@ -79,23 +83,34 @@ constexpr bool test() { test_iteration>(std::array{3}, 7); test_iteration>(std::array{4}); test_iteration>(std::array{25, 3}); - test_iteration>(std::array{1, 1, 1, 1}, 1, 1, 1, 1); + test_iteration>(std::array{1, 1, 1, 1}, + 1, 1, 1, 1); // Check operator constraint for number of arguments static_assert(check_operator_constraints( - std::layout_stride::mapping>(std::extents(1), std::array{1}), 0)); + std::layout_stride::mapping>(std::extents(1), + std::array{1}), + 0)); static_assert(!check_operator_constraints( - std::layout_stride::mapping>(std::extents(1), std::array{1}), 0, 0)); + std::layout_stride::mapping>(std::extents(1), + std::array{1}), + 0, 0)); // Check operator constraint for convertibility of arguments to index_type static_assert(check_operator_constraints( - std::layout_stride::mapping>(std::extents(1), std::array{1}), IntType(0))); + std::layout_stride::mapping>(std::extents(1), + std::array{1}), + IntType(0))); static_assert(!check_operator_constraints( - std::layout_stride::mapping>(std::extents(1), std::array{1}), IntType(0))); + std::layout_stride::mapping>( + std::extents(1), std::array{1}), + IntType(0))); - // Check operator constraint for no-throw-constructibility of index_type from arguments + // Check operator constraint for no-throw-constructibility of index_type from + // arguments static_assert(!check_operator_constraints( - std::layout_stride::mapping>(std::extents(1), std::array{1}), + std::layout_stride::mapping>( + std::extents(1), std::array{1}), IntType(0))); return true; @@ -103,8 +118,10 @@ constexpr bool test() { constexpr bool test_large() { constexpr size_t D = std::dynamic_extent; - test_iteration>(std::array{2000, 2, 20, 200}, 7, 9, 10); - test_iteration>(std::array{2000, 20, 20, 200}, 7, 10); + test_iteration>( + std::array{2000, 2, 20, 200}, 7, 9, 10); + test_iteration>( + std::array{2000, 20, 20, 200}, 7, 10); return true; } diff --git a/tests/libcxx-backports/layout_stride/layout_stride.is_exhaustive_corner_case.pass.cpp b/tests/libcxx-backports/layout_stride/layout_stride.is_exhaustive_corner_case.pass.cpp index e5f768bd..c33dc83a 100644 --- a/tests/libcxx-backports/layout_stride/layout_stride.is_exhaustive_corner_case.pass.cpp +++ b/tests/libcxx-backports/layout_stride/layout_stride.is_exhaustive_corner_case.pass.cpp @@ -14,9 +14,11 @@ // // Returns: // - true if rank_ is 0. -// - Otherwise, true if there is a permutation P of the integers in the range [0, rank_) such that -// stride(p0) equals 1, and stride(pi) equals stride(pi_1) * extents().extent(pi_1) for i in the -// range [1, rank_), where pi is the ith element of P. +// - Otherwise, true if there is a permutation P of the integers in the range +// [0, rank_) such that +// stride(p0) equals 1, and stride(pi) equals stride(pi_1) * +// extents().extent(pi_1) for i in the range [1, rank_), where pi is the ith +// element of P. // - Otherwise, false. #include @@ -27,8 +29,9 @@ #include "../llvm_test_macros.h" template -constexpr void -test_layout_mapping_stride(E ext, std::array strides, bool exhaustive) { +constexpr void test_layout_mapping_stride( + E ext, std::array strides, + bool exhaustive) { using M = std::layout_stride::template mapping; M m(ext, strides); assert(m.is_exhaustive() == exhaustive); @@ -36,14 +39,15 @@ test_layout_mapping_stride(E ext, std::array constexpr bool test() { constexpr size_t D = std::dynamic_extent; + // clang-format off test_layout_mapping_stride(std::extents(), std::array{1}, true); test_layout_mapping_stride(std::extents(0), std::array{3}, false); test_layout_mapping_stride(std::extents(), std::array{6, 2}, true); test_layout_mapping_stride(std::extents(3, 0), std::array{6, 2}, false); test_layout_mapping_stride(std::extents(0, 0), std::array{6, 2}, false); - test_layout_mapping_stride( - std::extents(3, 3, 0, 3), std::array{3, 1, 27, 9}, true); + test_layout_mapping_stride(std::extents(3, 3, 0, 3), std::array{3, 1, 27, 9}, true); test_layout_mapping_stride(std::extents(0, 3, 3, 3), std::array{3, 1, 27, 9}, false); + // clang-format on return true; } diff --git a/tests/libcxx-backports/layout_stride/layout_stride.properties.pass.cpp b/tests/libcxx-backports/layout_stride/layout_stride.properties.pass.cpp index 36b7e007..e652905a 100644 --- a/tests/libcxx-backports/layout_stride/layout_stride.properties.pass.cpp +++ b/tests/libcxx-backports/layout_stride/layout_stride.properties.pass.cpp @@ -27,15 +27,18 @@ // } // // -// layout_stride::mapping is a trivially copyable type that models regular for each E. +// layout_stride::mapping is a trivially copyable type that models regular +// for each E. // // constexpr bool is_exhaustive() const noexcept; // // Returns: // - true if rank_ is 0. -// - Otherwise, true if there is a permutation P of the integers in the range [0, rank_) such that -// stride(p0) equals 1, and stride(pi) equals stride(pi_1) * extents().extent(pi_1) for i in the -// range [1, rank_), where pi is the ith element of P. +// - Otherwise, true if there is a permutation P of the integers in the range +// [0, rank_) such that +// stride(p0) equals 1, and stride(pi) equals stride(pi_1) * +// extents().extent(pi_1) for i in the range [1, rank_), where pi is the ith +// element of P. // - Otherwise, false. #include @@ -46,8 +49,9 @@ #include "../llvm_test_macros.h" template -constexpr void -test_layout_mapping_stride(E ext, std::array strides, bool exhaustive) { +constexpr void test_layout_mapping_stride( + E ext, std::array strides, + bool exhaustive) { using M = std::layout_stride::template mapping; M m(ext, strides); const M c_m = m; @@ -88,7 +92,8 @@ test_layout_mapping_stride(E ext, std::array expected_size = 0; break; } - expected_size += (ext.extent(r) - 1) * static_cast(strides[r]); + expected_size += + (ext.extent(r) - 1) * static_cast(strides[r]); } assert(m.required_span_size() == expected_size); assert(c_m.required_span_size() == expected_size); @@ -101,11 +106,13 @@ test_layout_mapping_stride(E ext, std::array constexpr bool test() { constexpr size_t D = std::dynamic_extent; + // clang-format off test_layout_mapping_stride(std::extents(), std::array{}, true); test_layout_mapping_stride(std::extents(), std::array{1, 4}, true); test_layout_mapping_stride(std::extents(), std::array{1, 5}, false); test_layout_mapping_stride(std::extents(7), std::array{20, 2}, false); test_layout_mapping_stride(std::extents(3, 3, 3, 3), std::array{3, 1, 9, 27}, true); + // clang-format on return true; } diff --git a/tests/libcxx-backports/layout_stride/layout_stride.required_span_size.pass.cpp b/tests/libcxx-backports/layout_stride/layout_stride.required_span_size.pass.cpp index 62c59430..f3019312 100644 --- a/tests/libcxx-backports/layout_stride/layout_stride.required_span_size.pass.cpp +++ b/tests/libcxx-backports/layout_stride/layout_stride.required_span_size.pass.cpp @@ -13,7 +13,8 @@ // Let REQUIRED-SPAN-SIZE(e, strides) be: // - 1, if e.rank() == 0 is true, // - otherwise 0, if the size of the multidimensional index space e is 0, -// - otherwise 1 plus the sum of products of (e.extent(r) - 1) and strides[r] for all r in the range [0, e.rank()). +// - otherwise 1 plus the sum of products of (e.extent(r) - 1) and strides[r] +// for all r in the range [0, e.rank()). // constexpr index_type required_span_size() const noexcept; // @@ -26,7 +27,8 @@ #include "../llvm_test_macros.h" template -constexpr void test_required_span_size(E e, std::array strides, typename E::index_type expected_size) { +constexpr void test_required_span_size(E e, std::array strides, + typename E::index_type expected_size) { using M = std::layout_stride::mapping; const M m(e, strides); @@ -36,16 +38,17 @@ constexpr void test_required_span_size(E e, std::array strides, constexpr bool test() { constexpr size_t D = std::dynamic_extent; + // clang-format off test_required_span_size(std::extents(), std::array{}, 1); test_required_span_size(std::extents(0), std::array{5}, 0); test_required_span_size(std::extents(1), std::array{5}, 1); test_required_span_size(std::extents(7), std::array{5}, 31); test_required_span_size(std::extents(), std::array{5}, 31); test_required_span_size(std::extents(), std::array{20, 2}, 135); - test_required_span_size( - std::extents(7, 9, 10), std::array{1, 7, 7 * 8, 7 * 8 * 9}, 5040); + test_required_span_size(std::extents(7, 9, 10), std::array{1, 7, 7 * 8, 7 * 8 * 9}, 5040); test_required_span_size(std::extents(9, 10), std::array{1, 7, 7 * 8, 7 * 8 * 9}, 5034); test_required_span_size(std::extents(9, 10), std::array{1, 7, 7 * 8, 7 * 8 * 9}, 0); + // clang-format on return true; } diff --git a/tests/libcxx-backports/layout_stride/layout_stride.static_requirements.pass.cpp b/tests/libcxx-backports/layout_stride/layout_stride.static_requirements.pass.cpp index eeec3a92..e6263088 100644 --- a/tests/libcxx-backports/layout_stride/layout_stride.static_requirements.pass.cpp +++ b/tests/libcxx-backports/layout_stride/layout_stride.static_requirements.pass.cpp @@ -16,7 +16,8 @@ // - is_nothrow_move_assignable_v is true, // - is_nothrow_swappable_v is true, and // -// the following types and expressions are well-formed and have the specified semantics. +// the following types and expressions are well-formed and have the specified +// semantics. // // typename M::extents_type // Result: A type that is a specialization of extents. @@ -28,14 +29,18 @@ // Result: typename M::extents_type::rank_type. // // typename M::layout_type -// Result: A type MP that meets the layout mapping policy requirements ([mdspan.layout.policy.reqmts]) and for which is-mapping-of is true. +// Result: A type MP that meets the layout mapping policy requirements +// ([mdspan.layout.policy.reqmts]) and for which is-mapping-of is +// true. // // m.extents() // Result: const typename M::extents_type& // // m(i...) // Result: typename M::index_type -// Returns: A nonnegative integer less than numeric_limits::max() and less than or equal to numeric_limits::max(). +// Returns: A nonnegative integer less than numeric_limits::max() and less than or equal to +// numeric_limits::max(). // // m(i...) == m(static_cast(i)...) // Result: bool @@ -43,21 +48,26 @@ // // m.required_span_size() // Result: typename M::index_type -// Returns: If the size of the multidimensional index space m.extents() is 0, then 0, else 1 plus the maximum value of m(i...) for all i. +// Returns: If the size of the multidimensional index space m.extents() is 0, +// then 0, else 1 plus the maximum value of m(i...) for all i. // // m.is_unique() // Result: bool -// Returns: true only if for every i and j where (i != j || ...) is true, m(i...) != m(j...) is true. +// Returns: true only if for every i and j where (i != j || ...) is true, +// m(i...) != m(j...) is true. // // m.is_exhaustive() // Result: bool -// Returns: true only if for all k in the range [0, m.required_span_size()) there exists an i such that m(i...) equals k. +// Returns: true only if for all k in the range [0, m.required_span_size()) +// there exists an i such that m(i...) equals k. // // m.is_strided() // Result: bool -// Returns: true only if for every rank index r of m.extents() there exists an integer -// sr such that, for all i where (i+dr) is a multidimensional index in m.extents() ([mdspan.overview]), -// m((i + dr)...) - m(i...) equals sr +// Returns: true only if for every rank index r of m.extents() there exists +// an integer +// sr such that, for all i where (i+dr) is a multidimensional index +// in m.extents() ([mdspan.overview]), m((i + dr)...) - m(i...) +// equals sr // // m.stride(r) // Preconditions: m.is_strided() is true. @@ -66,15 +76,18 @@ // // M::is_always_unique() // Result: A constant expression ([expr.const]) of type bool. -// Returns: true only if m.is_unique() is true for all possible objects m of type M. +// Returns: true only if m.is_unique() is true for all possible objects m of +// type M. // // M::is_always_exhaustive() // Result: A constant expression ([expr.const]) of type bool. -// Returns: true only if m.is_exhaustive() is true for all possible objects m of type M. +// Returns: true only if m.is_exhaustive() is true for all possible objects m +// of type M. // // M::is_always_strided() // Result: A constant expression ([expr.const]) of type bool. -// Returns: true only if m.is_strided() is true for all possible objects m of type M. +// Returns: true only if m.is_strided() is true for all possible objects m of +// type M. #include #include @@ -87,7 +100,7 @@ template void test_mapping_requirements(std::index_sequence) { using E = typename M::extents_type; - //static_assert(std::__mdspan_detail::impl_is_extents_v); //FIXME + // static_assert(std::__mdspan_detail::impl_is_extents_v); //FIXME static_assert(std::is_copy_constructible_v); static_assert(std::is_nothrow_move_constructible_v); static_assert(std::is_nothrow_move_assignable_v); @@ -97,14 +110,20 @@ void test_mapping_requirements(std::index_sequence) { ASSERT_SAME_TYPE(typename M::rank_type, typename E::rank_type); ASSERT_SAME_TYPE(typename M::layout_type, std::layout_stride); ASSERT_SAME_TYPE(typename M::layout_type::template mapping, M); - static_assert(std::is_same_v().extents()), const E&>); - static_assert(std::is_same_v().strides()), std::array>); - static_assert(std::is_same_v()(Idxs...)), typename M::index_type>); - static_assert(std::is_same_v().required_span_size()), typename M::index_type>); + static_assert( + std::is_same_v().extents()), const E&>); + static_assert(std::is_same_v().strides()), + std::array>); + static_assert(std::is_same_v()(Idxs...)), + typename M::index_type>); + static_assert(std::is_same_v().required_span_size()), + typename M::index_type>); static_assert(std::is_same_v().is_unique()), bool>); - static_assert(std::is_same_v().is_exhaustive()), bool>); + static_assert( + std::is_same_v().is_exhaustive()), bool>); static_assert(std::is_same_v().is_strided()), bool>); - static_assert(std::is_same_v().stride(0)), typename M::index_type>); + static_assert(std::is_same_v().stride(0)), + typename M::index_type>); static_assert(std::is_same_v); static_assert(std::is_same_v); static_assert(std::is_same_v); diff --git a/tests/libcxx-backports/layout_stride/layout_stride.stride.pass.cpp b/tests/libcxx-backports/layout_stride/layout_stride.stride.pass.cpp index 83dc2827..74649966 100644 --- a/tests/libcxx-backports/layout_stride/layout_stride.stride.pass.cpp +++ b/tests/libcxx-backports/layout_stride/layout_stride.stride.pass.cpp @@ -26,19 +26,19 @@ #include "../llvm_test_macros.h" template -constexpr void test_stride(std::array strides, Args... args) { +constexpr void test_stride( + std::array strides, Args... args) { using M = std::layout_stride::mapping; M m(E(args...), strides); ASSERT_NOEXCEPT(m.stride(0)); - for (size_t r = 0; r < E::rank(); r++) - assert(strides[r] == m.stride(r)); + for (size_t r = 0; r < E::rank(); r++) assert(strides[r] == m.stride(r)); ASSERT_NOEXCEPT(m.strides()); auto strides_out = m.strides(); - static_assert(std::is_same_v>); - for (size_t r = 0; r < E::rank(); r++) - assert(strides[r] == strides_out[r]); + static_assert(std::is_same_v>); + for (size_t r = 0; r < E::rank(); r++) assert(strides[r] == strides_out[r]); } constexpr bool test() { @@ -46,7 +46,8 @@ constexpr bool test() { test_stride>(std::array{1}, 7); test_stride>(std::array{1}); test_stride>(std::array{8, 1}); - test_stride>(std::array{720, 90, 10, 1}, 7, 9, 10); + test_stride>( + std::array{720, 90, 10, 1}, 7, 9, 10); return true; } diff --git a/tests/libcxx-backports/llvm_test_macros.h b/tests/libcxx-backports/llvm_test_macros.h index 0c706556..6337a707 100644 --- a/tests/libcxx-backports/llvm_test_macros.h +++ b/tests/libcxx-backports/llvm_test_macros.h @@ -1,15 +1,18 @@ -#define ASSERT_SAME_TYPE(...) static_assert((std::is_same_v<__VA_ARGS__>), "Types must be the same") +#define ASSERT_SAME_TYPE(...) \ + static_assert((std::is_same_v<__VA_ARGS__>), "Types must be the same") #define LIBCPP_STATIC_ASSERT(A) static_assert(A); -//#define ASSERT_NOEXCEPT(A) if consteval { static_assert(noexcept(A)); } else { assert(noexcept(A)); } -#define ASSERT_NOEXCEPT(...) static_assert(noexcept(__VA_ARGS__), "Operation must be noexcept"); +// #define ASSERT_NOEXCEPT(A) if consteval { static_assert(noexcept(A)); } else +// { assert(noexcept(A)); } +#define ASSERT_NOEXCEPT(...) \ + static_assert(noexcept(__VA_ARGS__), "Operation must be noexcept"); namespace std { - using Kokkos::mdspan; - using Kokkos::extents; - using Kokkos::dextents; - using Kokkos::default_accessor; - using Kokkos::layout_left; - using Kokkos::layout_right; - using Kokkos::layout_stride; -} +using Kokkos::default_accessor; +using Kokkos::dextents; +using Kokkos::extents; +using Kokkos::layout_left; +using Kokkos::layout_right; +using Kokkos::layout_stride; +using Kokkos::mdspan; +} // namespace std diff --git a/tests/libcxx-backports/mdspan/CustomTestAccessors.h b/tests/libcxx-backports/mdspan/CustomTestAccessors.h index 6856c0a5..c56652a1 100644 --- a/tests/libcxx-backports/mdspan/CustomTestAccessors.h +++ b/tests/libcxx-backports/mdspan/CustomTestAccessors.h @@ -22,8 +22,9 @@ #include #include "../llvm_test_macros.h" -// This contains a bunch of accessors and handles which have different properties -// regarding constructibility and convertibility in order to test mdspan constraints +// This contains a bunch of accessors and handles which have different +// properties regarding constructibility and convertibility in order to test +// mdspan constraints // non default constructible data handle template @@ -51,7 +52,8 @@ struct move_counted_handle { constexpr move_counted_handle(const move_counted_handle&) = default; template requires(std::is_constructible_v) - constexpr move_counted_handle(const move_counted_handle& other) : ptr(other.ptr){} + constexpr move_counted_handle(const move_counted_handle& other) + : ptr(other.ptr) {} constexpr move_counted_handle(move_counted_handle&& other) { ptr = other.ptr; #if MDSPAN_HAS_CXX_23 @@ -62,7 +64,8 @@ struct move_counted_handle { } constexpr move_counted_handle(T* ptr_) : ptr(ptr_) {} - constexpr move_counted_handle& operator=(const move_counted_handle&) = default; + constexpr move_counted_handle& operator=(const move_counted_handle&) = + default; constexpr T& operator[](size_t i) const { return ptr[i]; } @@ -84,7 +87,8 @@ struct checked_accessor { constexpr checked_accessor(size_t N_) : N(N_) {} template requires(std::is_convertible_v) - explicit constexpr checked_accessor(const checked_accessor& other) noexcept { + explicit constexpr checked_accessor( + const checked_accessor& other) noexcept { N = other.N; } @@ -92,14 +96,17 @@ struct checked_accessor { assert(i < N); return p[i]; } - constexpr data_handle_type offset(data_handle_type p, size_t i) const noexcept { + constexpr data_handle_type offset(data_handle_type p, + size_t i) const noexcept { assert(i < N); return data_handle_type(p.ptr + i); } }; -static_assert(std::is_constructible_v, const checked_accessor&>); -static_assert(!std::is_convertible_v&, checked_accessor>); +static_assert(std::is_constructible_v, + const checked_accessor&>); +static_assert(!std::is_convertible_v&, + checked_accessor>); template <> struct checked_accessor { @@ -113,7 +120,8 @@ struct checked_accessor { template requires(std::is_convertible_v) - constexpr checked_accessor(checked_accessor&& other) noexcept { + constexpr checked_accessor( + checked_accessor&& other) noexcept { N = other.N; } @@ -121,7 +129,8 @@ struct checked_accessor { assert(i < N); return p.ptr[i]; } - constexpr data_handle_type offset(data_handle_type p, size_t i) const noexcept { + constexpr data_handle_type offset(data_handle_type p, + size_t i) const noexcept { assert(i < N); return p.ptr + i; } @@ -161,7 +170,8 @@ struct checked_accessor { constexpr checked_accessor(const checked_accessor& acc) : N(acc.N) {} template - constexpr explicit(std::is_const_v) checked_accessor(OtherACC&& acc) : N(acc.N) {} + constexpr explicit(std::is_const_v) checked_accessor(OtherACC&& acc) + : N(acc.N) {} constexpr reference access(data_handle_type p, size_t i) const noexcept { assert(i < N); @@ -191,7 +201,8 @@ struct checked_accessor { assert(i < N); return p[i]; } - constexpr data_handle_type offset(data_handle_type p, size_t i) const noexcept { + constexpr data_handle_type offset(data_handle_type p, + size_t i) const noexcept { assert(i < N); return data_handle_type(p.ptr + i); } @@ -213,7 +224,8 @@ struct checked_accessor { assert(i < N); return p[i]; } - constexpr data_handle_type offset(data_handle_type p, size_t i) const noexcept { + constexpr data_handle_type offset(data_handle_type p, + size_t i) const noexcept { assert(i < N); return data_handle_type(p.ptr + i); } @@ -249,8 +261,13 @@ struct conv_test_accessor_nc { return conv_test_accessor_c{}; } - constexpr reference access(data_handle_type p, size_t i) const noexcept { return p[i]; } - constexpr data_handle_type offset(data_handle_type p, size_t i) const noexcept { return p + i; } + constexpr reference access(data_handle_type p, size_t i) const noexcept { + return p[i]; + } + constexpr data_handle_type offset(data_handle_type p, + size_t i) const noexcept { + return p + i; + } }; template @@ -272,7 +289,8 @@ struct conv_test_accessor_c { requires(ctor_mv) {} template - constexpr conv_test_accessor_c& operator=(const conv_test_accessor_nc&) + constexpr conv_test_accessor_c& operator=( + const conv_test_accessor_nc&) requires(assign_c) { return {}; @@ -284,8 +302,13 @@ struct conv_test_accessor_c { return {}; } - constexpr reference access(data_handle_type p, size_t i) const noexcept { return p[i]; } - constexpr data_handle_type offset(data_handle_type p, size_t i) const noexcept { return p + i; } + constexpr reference access(data_handle_type p, size_t i) const noexcept { + return p[i]; + } + constexpr data_handle_type offset(data_handle_type p, + size_t i) const noexcept { + return p + i; + } }; template @@ -300,7 +323,8 @@ struct convertible_accessor_but_not_handle { template requires(std::is_convertible_v) explicit constexpr convertible_accessor_but_not_handle( - const convertible_accessor_but_not_handle& other) noexcept { + const convertible_accessor_but_not_handle& + other) noexcept { N = other.N; } @@ -308,10 +332,11 @@ struct convertible_accessor_but_not_handle { assert(i < N); return p[i]; } - constexpr data_handle_type offset(data_handle_type p, size_t i) const noexcept { + constexpr data_handle_type offset(data_handle_type p, + size_t i) const noexcept { assert(i < N); return data_handle_type(p.ptr + i); } }; -#endif // TEST_STD_CONTAINERS_VIEWS_MDSPAN_MDSPAN_CUSTOM_TEST_ACCESSORS_H +#endif // TEST_STD_CONTAINERS_VIEWS_MDSPAN_MDSPAN_CUSTOM_TEST_ACCESSORS_H diff --git a/tests/libcxx-backports/mdspan/mdspan.assign.pass.cpp b/tests/libcxx-backports/mdspan/mdspan.assign.pass.cpp index 7dee1f99..7fbc7e59 100644 --- a/tests/libcxx-backports/mdspan/mdspan.assign.pass.cpp +++ b/tests/libcxx-backports/mdspan/mdspan.assign.pass.cpp @@ -24,57 +24,74 @@ template constexpr void test_mdspan_types(const H& handle, const M& map, const A& acc) { - using MDS = std::mdspan; + using MDS = std::mdspan; MDS m_org(handle, map, acc); MDS m(handle, map, acc); // The defaulted assignment operator seems to be deprecated because: - // error: definition of implicit copy assignment operator for 'checked_accessor' is deprecated - // because it has a user-provided copy constructor [-Werror,-Wdeprecated-copy-with-user-provided-copy] - if constexpr (!std::is_same_v>) - m = m_org; + // error: definition of implicit copy assignment operator for + // 'checked_accessor' is deprecated because it has a + // user-provided copy constructor + // [-Werror,-Wdeprecated-copy-with-user-provided-copy] + if constexpr (!std::is_same_v>) m = m_org; // even though the following checks out: static_assert(std::copyable>); - static_assert(std::is_assignable_v, checked_accessor>); + static_assert(std::is_assignable_v, + checked_accessor>); static_assert(noexcept(m = m_org)); assert(m.extents() == map.extents()); - if constexpr (std::equality_comparable) - assert(m.data_handle() == handle); - if constexpr (std::equality_comparable) - assert(m.mapping() == map); - if constexpr (std::equality_comparable) - assert(m.accessor() == acc); + if constexpr (std::equality_comparable) assert(m.data_handle() == handle); + if constexpr (std::equality_comparable) assert(m.mapping() == map); + if constexpr (std::equality_comparable) assert(m.accessor() == acc); - static_assert(std::is_trivially_assignable_v == - ((!std::is_class_v || - std::is_trivially_assignable_v)&&std::is_trivially_assignable_v && - std::is_trivially_assignable_v)); + static_assert( + std::is_trivially_assignable_v == + ((!std::is_class_v || + std::is_trivially_assignable_v< + H, const H&>)&&std::is_trivially_assignable_v && + std::is_trivially_assignable_v)); } template constexpr void mixin_extents(const H& handle, const L& layout, const A& acc) { constexpr size_t D = std::dynamic_extent; - test_mdspan_types(handle, construct_mapping(layout, std::extents()), acc); - test_mdspan_types(handle, construct_mapping(layout, std::extents(7)), acc); - test_mdspan_types(handle, construct_mapping(layout, std::extents()), acc); - test_mdspan_types(handle, construct_mapping(layout, std::extents(2, 3)), acc); - test_mdspan_types(handle, construct_mapping(layout, std::extents(0, 3)), acc); - test_mdspan_types(handle, construct_mapping(layout, std::extents(1, 2, 3, 2)), acc); + test_mdspan_types(handle, construct_mapping(layout, std::extents()), + acc); + test_mdspan_types(handle, construct_mapping(layout, std::extents(7)), + acc); + test_mdspan_types( + handle, construct_mapping(layout, std::extents()), acc); + test_mdspan_types( + handle, construct_mapping(layout, std::extents(2, 3)), + acc); + test_mdspan_types( + handle, construct_mapping(layout, std::extents(0, 3)), + acc); + test_mdspan_types( + handle, + construct_mapping(layout, + std::extents(1, 2, 3, 2)), + acc); } template constexpr void mixin_layout(const H& handle, const A& acc) { // make sure we test a trivially assignable mapping - static_assert(std::is_trivially_assignable_v>, - const typename std::layout_left::template mapping>&>); + static_assert(std::is_trivially_assignable_v< + typename std::layout_left::template mapping>, + const typename std::layout_left::template mapping< + std::extents>&>); mixin_extents(handle, std::layout_left(), acc); mixin_extents(handle, std::layout_right(), acc); // make sure we test a not trivially assignable mapping static_assert(!std::is_trivially_assignable_v< - typename layout_wrapping_integral<4>::template mapping>, - const typename layout_wrapping_integral<4>::template mapping>&>); + typename layout_wrapping_integral<4>::template mapping< + std::extents>, + const typename layout_wrapping_integral<4>::template mapping< + std::extents>&>); mixin_extents(handle, layout_wrapping_integral<4>(), acc); } @@ -83,15 +100,18 @@ constexpr void mixin_accessor() { ElementPool elements; // make sure we test trivially constructible accessor and data_handle static_assert(std::is_trivially_copyable_v>); - static_assert(std::is_trivially_copyable_v::data_handle_type>); + static_assert(std::is_trivially_copyable_v< + typename std::default_accessor::data_handle_type>); mixin_layout(elements.get_ptr(), std::default_accessor()); // Using weird accessor/data_handle // Make sure they actually got the properties we want to test // checked_accessor is noexcept copy constructible except for const double checked_accessor acc(1024); - static_assert(noexcept(checked_accessor(acc)) != std::is_same_v); - mixin_layout(typename checked_accessor::data_handle_type(elements.get_ptr()), acc); + static_assert(noexcept(checked_accessor(acc)) != + std::is_same_v); + mixin_layout( + typename checked_accessor::data_handle_type(elements.get_ptr()), acc); } constexpr bool test() { diff --git a/tests/libcxx-backports/mdspan/mdspan.conversion.pass.cpp b/tests/libcxx-backports/mdspan/mdspan.conversion.pass.cpp index d2f2df5c..7d3ec1c2 100644 --- a/tests/libcxx-backports/mdspan/mdspan.conversion.pass.cpp +++ b/tests/libcxx-backports/mdspan/mdspan.conversion.pass.cpp @@ -16,15 +16,20 @@ // OtherLayoutPolicy, OtherAccessor>& other); // // Constraints: -// - is_constructible_v&> is true, and +// - is_constructible_v&> is true, and // - is_constructible_v is true. // Mandates: -// - is_constructible_v is +// - is_constructible_v is // - is_constructible_v is true. // // Preconditions: -// - For each rank index r of extents_type, static_extent(r) == dynamic_extent || static_extent(r) == other.extent(r) is true. -// - [0, map_.required_span_size()) is an accessible range of ptr_ and acc_ for values of ptr_, map_, and acc_ after the invocation of this constructor. +// - For each rank index r of extents_type, static_extent(r) == dynamic_extent +// || static_extent(r) == other.extent(r) is true. +// - [0, map_.required_span_size()) is an accessible range of ptr_ and acc_ +// for values of ptr_, map_, and acc_ after the invocation of this +// constructor. // // Effects: // - Direct-non-list-initializes ptr_ with other.ptr_, @@ -32,7 +37,8 @@ // - direct-non-list-initializes acc_ with other.acc_. // // Remarks: The expression inside explicit is equivalent to: -// !is_convertible_v&, mapping_type> +// !is_convertible_v&, +// mapping_type> // || !is_convertible_v #include @@ -49,45 +55,64 @@ template constexpr void test_implicit_conversion(ToMDS to_mds, FromMDS from_mds) { assert(to_mds.extents() == from_mds.extents()); - if constexpr (std::equality_comparable_with) + if constexpr (std::equality_comparable_with< + typename ToMDS::data_handle_type, + typename FromMDS::data_handle_type>) assert(to_mds.data_handle() == from_mds.data_handle()); - if constexpr (std::equality_comparable_with) + if constexpr (std::equality_comparable_with) assert(to_mds.mapping() == from_mds.mapping()); - if constexpr (std::equality_comparable_with) + if constexpr (std::equality_comparable_with) assert(to_mds.accessor() == from_mds.accessor()); } template concept mapping_requirements = requires() { - requires(std::copyable && std::equality_comparable) && std::is_nothrow_move_constructible_v && - std::is_nothrow_move_assignable_v && std::is_nothrow_swappable_v; + requires(std::copyable && std::equality_comparable) && + std::is_nothrow_move_constructible_v && + std::is_nothrow_move_assignable_v && + std::is_nothrow_swappable_v; }; template constexpr void test_conversion(FromMDS from_mds) { - // check some requirements, to see we didn't screw up our test layouts/accessors + // check some requirements, to see we didn't screw up our test + // layouts/accessors static_assert(mapping_requirements); static_assert(mapping_requirements); constexpr bool constructible = - std::is_constructible_v && - std::is_constructible_v; + std::is_constructible_v && + std::is_constructible_v; constexpr bool convertible = - std::is_convertible_v && - std::is_convertible_v; + std::is_convertible_v && + std::is_convertible_v; constexpr bool passes_mandates = - std::is_constructible_v && - std::is_constructible_v; + std::is_constructible_v && + std::is_constructible_v; if constexpr (constructible) { if constexpr (passes_mandates) { ToMDS to_mds(from_mds); assert(to_mds.extents() == from_mds.extents()); - if constexpr (std::equality_comparable_with) + if constexpr (std::equality_comparable_with< + typename ToMDS::data_handle_type, + typename FromMDS::data_handle_type>) assert(to_mds.data_handle() == from_mds.data_handle()); - if constexpr (std::equality_comparable_with) + if constexpr (std::equality_comparable_with< + typename ToMDS::mapping_type, + typename FromMDS::mapping_type>) assert(to_mds.mapping() == from_mds.mapping()); - if constexpr (std::equality_comparable_with) + if constexpr (std::equality_comparable_with< + typename ToMDS::accessor_type, + typename FromMDS::accessor_type>) assert(to_mds.accessor() == from_mds.accessor()); if constexpr (convertible) { test_implicit_conversion(from_mds, from_mds); @@ -100,35 +125,51 @@ constexpr void test_conversion(FromMDS from_mds) { } } -template -constexpr void construct_from_mds(const FromH& handle, const FromL& layout, const FromE& exts, const FromA& acc) { - using ToMDS = std::mdspan; - using FromMDS = std::mdspan; +template +constexpr void construct_from_mds(const FromH& handle, const FromL& layout, + const FromE& exts, const FromA& acc) { + using ToMDS = std::mdspan; + using FromMDS = + std::mdspan; test_conversion(FromMDS(handle, construct_mapping(layout, exts), acc)); } template -constexpr void mixin_extents(const FromH& handle, const FromL& layout, const FromA& acc) { +constexpr void mixin_extents(const FromH& handle, const FromL& layout, + const FromA& acc) { constexpr size_t D = std::dynamic_extent; // constructible and convertible - construct_from_mds, ToA>(handle, layout, std::dextents(), acc); - construct_from_mds, ToA>(handle, layout, std::dextents(4), acc); - construct_from_mds, ToA>(handle, layout, std::extents(), acc); - construct_from_mds, ToA>(handle, layout, std::dextents(4, 5), acc); - construct_from_mds, ToA>(handle, layout, std::dextents(4, 5), acc); - construct_from_mds, ToA>(handle, layout, std::extents(4), acc); - construct_from_mds, ToA>(handle, layout, std::extents(4), acc); - construct_from_mds, ToA>(handle, layout, std::extents(4), acc); - construct_from_mds, ToA>(handle, layout, std::extents(4, 6), acc); + construct_from_mds, ToA>( + handle, layout, std::dextents(), acc); + construct_from_mds, ToA>( + handle, layout, std::dextents(4), acc); + construct_from_mds, ToA>( + handle, layout, std::extents(), acc); + construct_from_mds, ToA>( + handle, layout, std::dextents(4, 5), acc); + construct_from_mds, ToA>( + handle, layout, std::dextents(4, 5), acc); + construct_from_mds, ToA>( + handle, layout, std::extents(4), acc); + construct_from_mds, ToA>( + handle, layout, std::extents(4), acc); + construct_from_mds, ToA>( + handle, layout, std::extents(4), acc); + construct_from_mds, ToA>( + handle, layout, std::extents(4, 6), acc); // not convertible - construct_from_mds, ToA>(handle, layout, std::dextents(4), acc); + construct_from_mds, ToA>( + handle, layout, std::dextents(4), acc); construct_from_mds, ToA>( handle, layout, std::extents(4, 6, 7), acc); // not constructible - construct_from_mds, ToA>(handle, layout, std::dextents(4, 5), acc); - construct_from_mds, ToA>(handle, layout, std::extents(4, 6), acc); + construct_from_mds, ToA>( + handle, layout, std::dextents(4, 5), acc); + construct_from_mds, ToA>( + handle, layout, std::extents(4, 6), acc); } template @@ -137,58 +178,74 @@ constexpr void mixin_layout(const FromH& handle, const FromA& acc) { mixin_extents(handle, std::layout_right(), acc); // Check layout policy conversion // different layout policies, but constructible and convertible - static_assert(std::is_constructible_v>, - const std::layout_right::mapping>&>); - static_assert(std::is_convertible_v>&, - std::layout_left::mapping>>); + static_assert(std::is_constructible_v< + std::layout_left::mapping>, + const std::layout_right::mapping>&>); + static_assert(std::is_convertible_v< + const std::layout_right::mapping>&, + std::layout_left::mapping>>); // different layout policies, not constructible - static_assert(!std::is_constructible_v>, - const std::layout_right::mapping>&>); + static_assert(!std::is_constructible_v< + std::layout_left::mapping>, + const std::layout_right::mapping>&>); // different layout policies, constructible and not convertible - static_assert(std::is_constructible_v>, - const std::layout_right::mapping>&>); - static_assert(!std::is_convertible_v>&, - std::layout_left::mapping>>); + static_assert(std::is_constructible_v< + std::layout_left::mapping>, + const std::layout_right::mapping>&>); + static_assert(!std::is_convertible_v< + const std::layout_right::mapping>&, + std::layout_left::mapping>>); mixin_extents(handle, std::layout_right(), acc); - mixin_extents, ToA>(handle, layout_wrapping_integral<4>(), acc); + mixin_extents, ToA>( + handle, layout_wrapping_integral<4>(), acc); // different layout policies, constructible and not convertible - static_assert(!std::is_constructible_v::mapping>, - const layout_wrapping_integral<8>::mapping>&>); - static_assert(std::is_constructible_v::mapping>, - layout_wrapping_integral<8>::mapping>>); - mixin_extents, ToA>(handle, layout_wrapping_integral<8>(), acc); + static_assert( + !std::is_constructible_v< + layout_wrapping_integral<8>::mapping>, + const layout_wrapping_integral<8>::mapping>&>); + static_assert( + std::is_constructible_v< + layout_wrapping_integral<8>::mapping>, + layout_wrapping_integral<8>::mapping>>); + mixin_extents, ToA>( + handle, layout_wrapping_integral<8>(), acc); } -// check that we cover all corners with respect to constructibility and convertibility -template +// check that we cover all corners with respect to constructibility and +// convertibility +template constexpr bool test(FromA from_acc) { static_assert(std::copyable); static_assert(std::copyable); - static_assert(std::is_constructible_v == constructible_constref_acc); - static_assert(std::is_constructible_v == constructible_nonconst_acc); - static_assert(std::is_constructible_v == - constructible_constref_handle); - static_assert(std::is_constructible_v == + static_assert(std::is_constructible_v == + constructible_constref_acc); + static_assert(std::is_constructible_v == + constructible_nonconst_acc); + static_assert( + std::is_constructible_v == + constructible_constref_handle); + static_assert(std::is_constructible_v == constructible_nonconst_handle); - static_assert(std::is_convertible_v == convertible_constref_acc); + static_assert(std::is_convertible_v == + convertible_constref_acc); static_assert(std::is_convertible_v == convertible_nonconst_acc); - static_assert(std::is_convertible_v == + static_assert(std::is_convertible_v == convertible_constref_handle); - static_assert(std::is_convertible_v == + static_assert(std::is_convertible_v == convertible_nonconst_handle); ElementPool elements; - mixin_layout(typename FromA::data_handle_type(elements.get_ptr()), from_acc); + mixin_layout(typename FromA::data_handle_type(elements.get_ptr()), + from_acc); return true; } @@ -197,27 +254,21 @@ int main(int, char**) { constexpr bool t = true; constexpr bool o = false; - // possibility matrix for constructibility and convertibility https://godbolt.org/z/98KGo8Wbc - // you can't have convertibility without constructibility - // and if you take const T& then you also can take T - // this leaves 7 combinations - // const_ref_ctor, const_ref_conv, nonconst_ctor, nonconst_conv, tested - // o o o o X - // o o t o X - // o o t t X - // t o t o X - // t o t t X - // t t t o X - // t t t t X + // possibility matrix for constructibility and convertibility + // https://godbolt.org/z/98KGo8Wbc you can't have convertibility without + // constructibility and if you take const T& then you also can take T this + // leaves 7 combinations const_ref_ctor, const_ref_conv, nonconst_ctor, + // nonconst_conv, tested o o o o X o o t o X o o t t X t o t o X t o t t X t t + // t o X t t t t X + // clang-format off // checked_accessor has various weird data handles and some weird conversion properties // conv_test_accessor_c/nc is an accessor pair which has configurable conversion properties, but plain ptr as data handle // accessor constructible test>(std::default_accessor()); test>(std::default_accessor()); test>(std::default_accessor()); - test>( - std::default_accessor()); + test>(std::default_accessor()); test>(checked_accessor(1024)); test>(checked_accessor(1024)); test>(checked_accessor(1024)); @@ -246,36 +297,26 @@ int main(int, char**) { // Ran into trouble with doing it all in one static_assert: exceeding step limit for consteval static_assert(test>(std::default_accessor())); static_assert(test>(std::default_accessor())); - static_assert(test>( - std::default_accessor())); - static_assert(test>( - std::default_accessor())); + static_assert(test>(std::default_accessor())); + static_assert(test>(std::default_accessor())); static_assert(test>(checked_accessor(1024))); static_assert(test>(checked_accessor(1024))); static_assert(test>(checked_accessor(1024))); static_assert(test>(checked_accessor(1024))); static_assert(test>(checked_accessor(1024))); - static_assert( - test>(checked_accessor(1024))); - static_assert(test>( - checked_accessor(1024))); - static_assert( - test>(conv_test_accessor_nc())); - static_assert( - test>(conv_test_accessor_nc())); - static_assert( - test>(conv_test_accessor_nc())); - static_assert( - test>(conv_test_accessor_nc())); + static_assert(test>(checked_accessor(1024))); + static_assert(test>(checked_accessor(1024))); + static_assert(test>(conv_test_accessor_nc())); + static_assert(test>(conv_test_accessor_nc())); + static_assert(test>(conv_test_accessor_nc())); + static_assert(test>(conv_test_accessor_nc())); static_assert(test>(std::default_accessor())); static_assert(test>(checked_accessor(1024))); static_assert(test>(checked_accessor(1024))); - static_assert( - test>(conv_test_accessor_nc())); - static_assert( - test>(conv_test_accessor_nc())); - static_assert( - test>(conv_test_accessor_nc())); + static_assert(test>(conv_test_accessor_nc())); + static_assert(test>(conv_test_accessor_nc())); + static_assert(test>(conv_test_accessor_nc())); + // clang-format on return 0; } diff --git a/tests/libcxx-backports/mdspan/mdspan.conversion.verify.cpp b/tests/libcxx-backports/mdspan/mdspan.conversion.verify.cpp index 4daeb06f..505755c5 100644 --- a/tests/libcxx-backports/mdspan/mdspan.conversion.verify.cpp +++ b/tests/libcxx-backports/mdspan/mdspan.conversion.verify.cpp @@ -16,15 +16,20 @@ // OtherLayoutPolicy, OtherAccessor>& other); // // Constraints: -// - is_constructible_v&> is true, and +// - is_constructible_v&> is true, and // - is_constructible_v is true. // Mandates: -// - is_constructible_v is +// - is_constructible_v is // - is_constructible_v is true. // // Preconditions: -// - For each rank index r of extents_type, static_extent(r) == dynamic_extent || static_extent(r) == other.extent(r) is true. -// - [0, map_.required_span_size()) is an accessible range of ptr_ and acc_ for values of ptr_, map_, and acc_ after the invocation of this constructor. +// - For each rank index r of extents_type, static_extent(r) == dynamic_extent +// || static_extent(r) == other.extent(r) is true. +// - [0, map_.required_span_size()) is an accessible range of ptr_ and acc_ +// for values of ptr_, map_, and acc_ after the invocation of this +// constructor. // // Effects: // - Direct-non-list-initializes ptr_ with other.ptr_, @@ -32,7 +37,8 @@ // - direct-non-list-initializes acc_ with other.acc_. // // Remarks: The expression inside explicit is equivalent to: -// !is_convertible_v&, mapping_type> +// !is_convertible_v&, +// mapping_type> // || !is_convertible_v #include @@ -41,17 +47,24 @@ void cant_construct_data_handle_type() { int data; - std::mdspan, std::layout_right, convertible_accessor_but_not_handle> m_nc(&data); - // expected-error-re@*:* {{{{.*}}no matching constructor for initialization of {{.*}} (aka 'not_const_convertible_handle')}} - // expected-error-re@*:* {{static assertion failed {{.*}}mdspan: incompatible data_handle_type for mdspan construction}} - [[maybe_unused]] std:: - mdspan, std::layout_right, convertible_accessor_but_not_handle> - m_c(m_nc); + std::mdspan, std::layout_right, + convertible_accessor_but_not_handle> + m_nc(&data); + // expected-error-re@*:* {{{{.*}}no matching constructor for initialization of + // {{.*}} (aka 'not_const_convertible_handle')}} + // expected-error-re@*:* {{static assertion failed {{.*}}mdspan: incompatible + // data_handle_type for mdspan construction}} + [[maybe_unused]] std::mdspan, std::layout_right, + convertible_accessor_but_not_handle> + m_c(m_nc); } void mapping_constructible_despite_extents_compatibility() { int data; std::mdspan, always_convertible_layout> m(&data); - // expected-error-re@*:* {{static assertion failed {{.*}}mdspan: incompatible extents for mdspan construction}} - [[maybe_unused]] std::mdspan, always_convertible_layout> m2(m); + // expected-error-re@*:* {{static assertion failed {{.*}}mdspan: incompatible + // extents for mdspan construction}} + [[maybe_unused]] std::mdspan, + always_convertible_layout> + m2(m); } diff --git a/tests/libcxx-backports/mdspan/mdspan.ctor.copy.pass.cpp b/tests/libcxx-backports/mdspan/mdspan.ctor.copy.pass.cpp index 7b8e498f..6bbddadf 100644 --- a/tests/libcxx-backports/mdspan/mdspan.ctor.copy.pass.cpp +++ b/tests/libcxx-backports/mdspan/mdspan.ctor.copy.pass.cpp @@ -11,7 +11,8 @@ // constexpr mdspan(const mdspan&) = default; // -// A specialization of mdspan is a trivially copyable type if its accessor_type, mapping_type, and data_handle_type are trivially copyable types. +// A specialization of mdspan is a trivially copyable type if its accessor_type, +// mapping_type, and data_handle_type are trivially copyable types. #include #include @@ -26,43 +27,56 @@ template constexpr void test_mdspan_types(const H& handle, const M& map, const A& acc) { - using MDS = std::mdspan; + using MDS = std::mdspan; MDS m_org(handle, map, acc); MDS m(m_org); - static_assert(noexcept(MDS(m_org)) == (noexcept(H(handle))&& noexcept(M(map))&& noexcept(A(acc)))); - static_assert( - std::is_trivially_copyable_v == - (std::is_trivially_copyable_v && std::is_trivially_copyable_v && std::is_trivially_copyable_v)); + static_assert(noexcept(MDS(m_org)) == + (noexcept(H(handle))&& noexcept(M(map))&& noexcept(A(acc)))); + static_assert(std::is_trivially_copyable_v == + (std::is_trivially_copyable_v && + std::is_trivially_copyable_v && + std::is_trivially_copyable_v)); assert(m.extents() == map.extents()); - if constexpr (std::equality_comparable) - assert(m.data_handle() == handle); - if constexpr (std::equality_comparable) - assert(m.mapping() == map); - if constexpr (std::equality_comparable) - assert(m.accessor() == acc); + if constexpr (std::equality_comparable) assert(m.data_handle() == handle); + if constexpr (std::equality_comparable) assert(m.mapping() == map); + if constexpr (std::equality_comparable) assert(m.accessor() == acc); } template constexpr void mixin_extents(const H& handle, const L& layout, const A& acc) { constexpr size_t D = std::dynamic_extent; - test_mdspan_types(handle, construct_mapping(layout, std::extents()), acc); - test_mdspan_types(handle, construct_mapping(layout, std::extents(7)), acc); - test_mdspan_types(handle, construct_mapping(layout, std::extents()), acc); - test_mdspan_types(handle, construct_mapping(layout, std::extents(2, 3)), acc); - test_mdspan_types(handle, construct_mapping(layout, std::extents(0, 3)), acc); - test_mdspan_types(handle, construct_mapping(layout, std::extents(1, 2, 3, 2)), acc); + test_mdspan_types(handle, construct_mapping(layout, std::extents()), + acc); + test_mdspan_types(handle, construct_mapping(layout, std::extents(7)), + acc); + test_mdspan_types( + handle, construct_mapping(layout, std::extents()), acc); + test_mdspan_types( + handle, construct_mapping(layout, std::extents(2, 3)), + acc); + test_mdspan_types( + handle, construct_mapping(layout, std::extents(0, 3)), + acc); + test_mdspan_types( + handle, + construct_mapping(layout, + std::extents(1, 2, 3, 2)), + acc); } template constexpr void mixin_layout(const H& handle, const A& acc) { // make sure we test a trivially copyable mapping - static_assert(std::is_trivially_copyable_v>>); + static_assert( + std::is_trivially_copyable_v< + typename std::layout_left::template mapping>>); mixin_extents(handle, std::layout_left(), acc); mixin_extents(handle, std::layout_right(), acc); // make sure we test a not trivially copyable mapping - static_assert( - !std::is_trivially_copyable_v::template mapping>>); + static_assert(!std::is_trivially_copyable_v::template mapping>>); mixin_extents(handle, layout_wrapping_integral<4>(), acc); } @@ -71,15 +85,18 @@ constexpr void mixin_accessor() { ElementPool elements; // make sure we test trivially constructible accessor and data_handle static_assert(std::is_trivially_copyable_v>); - static_assert(std::is_trivially_copyable_v::data_handle_type>); + static_assert(std::is_trivially_copyable_v< + typename std::default_accessor::data_handle_type>); mixin_layout(elements.get_ptr(), std::default_accessor()); // Using weird accessor/data_handle // Make sure they actually got the properties we want to test // checked_accessor is noexcept copy constructible except for const double checked_accessor acc(1024); - static_assert(noexcept(checked_accessor(acc)) != std::is_same_v); - mixin_layout(typename checked_accessor::data_handle_type(elements.get_ptr()), acc); + static_assert(noexcept(checked_accessor(acc)) != + std::is_same_v); + mixin_layout( + typename checked_accessor::data_handle_type(elements.get_ptr()), acc); } constexpr bool test() { diff --git a/tests/libcxx-backports/mdspan/mdspan.ctor.default.pass.cpp b/tests/libcxx-backports/mdspan/mdspan.ctor.default.pass.cpp index 41ebfdab..5a06cc9c 100644 --- a/tests/libcxx-backports/mdspan/mdspan.ctor.default.pass.cpp +++ b/tests/libcxx-backports/mdspan/mdspan.ctor.default.pass.cpp @@ -17,7 +17,8 @@ // - is_default_constructible_v is true. // // Preconditions: [0, map_.required_span_size()) is an accessible range of ptr_ -// and acc_ for the values of map_ and acc_ after the invocation of this constructor. +// and acc_ for the values of map_ and acc_ after the invocation +// of this constructor. // // Effects: Value-initializes ptr_, map_, and acc_. @@ -34,7 +35,8 @@ template constexpr void test_mdspan_types(const H&, const M&, const A&) { - using MDS = std::mdspan; + using MDS = std::mdspan; static_assert(hc == std::is_default_constructible_v); static_assert(mc == std::is_default_constructible_v); @@ -42,14 +44,12 @@ constexpr void test_mdspan_types(const H&, const M&, const A&) { if constexpr (MDS::rank_dynamic() > 0 && hc && mc && ac) { MDS m; - static_assert(noexcept(MDS()) == (noexcept(H())&& noexcept(M())&& noexcept(A()))); + static_assert(noexcept(MDS()) == + (noexcept(H())&& noexcept(M())&& noexcept(A()))); assert(m.extents() == typename MDS::extents_type()); - if constexpr (std::equality_comparable) - assert(m.data_handle() == H()); - if constexpr (std::equality_comparable) - assert(m.mapping() == M()); - if constexpr (std::equality_comparable) - assert(m.accessor() == A()); + if constexpr (std::equality_comparable) assert(m.data_handle() == H()); + if constexpr (std::equality_comparable) assert(m.mapping() == M()); + if constexpr (std::equality_comparable) assert(m.accessor() == A()); } else { static_assert(!std::is_default_constructible_v); } @@ -58,13 +58,23 @@ constexpr void test_mdspan_types(const H&, const M&, const A&) { template constexpr void mixin_extents(const H& handle, const L& layout, const A& acc) { constexpr size_t D = std::dynamic_extent; - test_mdspan_types(handle, construct_mapping(layout, std::extents()), acc); - test_mdspan_types(handle, construct_mapping(layout, std::extents(7)), acc); - test_mdspan_types(handle, construct_mapping(layout, std::extents()), acc); - test_mdspan_types(handle, construct_mapping(layout, std::extents(2, 3)), acc); - test_mdspan_types(handle, construct_mapping(layout, std::extents(0, 3)), acc); test_mdspan_types( - handle, construct_mapping(layout, std::extents(1, 2, 3, 2)), acc); + handle, construct_mapping(layout, std::extents()), acc); + test_mdspan_types( + handle, construct_mapping(layout, std::extents(7)), acc); + test_mdspan_types( + handle, construct_mapping(layout, std::extents()), acc); + test_mdspan_types( + handle, construct_mapping(layout, std::extents(2, 3)), + acc); + test_mdspan_types( + handle, construct_mapping(layout, std::extents(0, 3)), + acc); + test_mdspan_types( + handle, + construct_mapping(layout, + std::extents(1, 2, 3, 2)), + acc); } template @@ -75,7 +85,8 @@ constexpr void mixin_layout(const H& handle, const A& acc) { // Use weird layout, make sure it has the properties we want to test constexpr size_t D = std::dynamic_extent; static_assert( - !std::is_default_constructible_v< typename layout_wrapping_integral<4>::template mapping>>); + !std::is_default_constructible_v::template mapping>>); mixin_extents(handle, layout_wrapping_integral<4>(), acc); } @@ -86,13 +97,17 @@ constexpr void mixin_accessor() { // Using weird accessor/data_handle // Make sure they actually got the properties we want to test - // checked_accessor is not default constructible except for const double, where it is not noexcept - static_assert(std::is_default_constructible_v> == std::is_same_v); + // checked_accessor is not default constructible except for const double, + // where it is not noexcept + static_assert(std::is_default_constructible_v> == + std::is_same_v); // checked_accessor's data handle type is not default constructible for double - static_assert( - std::is_default_constructible_v::data_handle_type> != std::is_same_v); + static_assert(std::is_default_constructible_v< + typename checked_accessor::data_handle_type> != + std::is_same_v); mixin_layout, std::is_same_v>( - typename checked_accessor::data_handle_type(elements.get_ptr()), checked_accessor(1024)); + typename checked_accessor::data_handle_type(elements.get_ptr()), + checked_accessor(1024)); } constexpr bool test() { diff --git a/tests/libcxx-backports/mdspan/mdspan.ctor.dh_array.pass.cpp b/tests/libcxx-backports/mdspan/mdspan.ctor.dh_array.pass.cpp index 3e8eb112..129e4ff4 100644 --- a/tests/libcxx-backports/mdspan/mdspan.ctor.dh_array.pass.cpp +++ b/tests/libcxx-backports/mdspan/mdspan.ctor.dh_array.pass.cpp @@ -15,13 +15,16 @@ // // Constraints: // - is_convertible_v is true, -// - (is_nothrow_constructible && ...) is true, +// - (is_nothrow_constructible && ...) is +// true, // - N == rank() || N == rank_dynamic() is true, // - is_constructible_v is true, and // - is_default_constructible_v is true. // -// Preconditions: [0, map_.required_span_size()) is an accessible range of p and acc_ -// for the values of map_ and acc_ after the invocation of this constructor. +// Preconditions: [0, map_.required_span_size()) is an accessible range of p and +// acc_ +// for the values of map_ and acc_ after the invocation of this +// constructor. // // Effects: // - Direct-non-list-initializes ptr_ with std::move(p), @@ -42,19 +45,24 @@ #include "CustomTestAccessors.h" template -constexpr auto array_from_extents(const Extents& exts, std::index_sequence) { - return std::array{exts.extent(Idxs)...}; +constexpr auto array_from_extents(const Extents& exts, + std::index_sequence) { + return std::array{ + exts.extent(Idxs)...}; } template -concept check_mdspan_ctor_implicit = requires(MDS m, typename MDS::data_handle_type h, const Exts& exts) { - m = {h, exts}; -}; +concept check_mdspan_ctor_implicit = + requires(MDS m, typename MDS::data_handle_type h, const Exts& exts) { + m = {h, exts}; + }; template -constexpr void -test_mdspan_ctor_array(const H& handle, const M& map, const A&, std::array exts) { - using MDS = std::mdspan; +constexpr void test_mdspan_ctor_array( + const H& handle, const M& map, const A&, + std::array exts) { + using MDS = std::mdspan; #if MDSPAN_HAS_CXX_23 if !consteval { move_counted_handle::move_counter() = 0; @@ -63,7 +71,8 @@ test_mdspan_ctor_array(const H& handle, const M& map, const A&, std::array>) { + if constexpr (std::is_same_v< + H, move_counted_handle>) { assert((H::move_counter() == 1)); } } @@ -71,25 +80,25 @@ test_mdspan_ctor_array(const H& handle, const M& map, const A&, std::array == (N == MDS::rank_dynamic())); + static_assert(check_mdspan_ctor_implicit == + (N == MDS::rank_dynamic())); assert(m.extents() == map.extents()); - if constexpr (std::equality_comparable) - assert(m.data_handle() == handle); - if constexpr (std::equality_comparable) - assert(m.mapping() == map); - if constexpr (std::equality_comparable) - assert(m.accessor() == A()); + if constexpr (std::equality_comparable) assert(m.data_handle() == handle); + if constexpr (std::equality_comparable) assert(m.mapping() == map); + if constexpr (std::equality_comparable) assert(m.accessor() == A()); } template constexpr void test_mdspan_ctor(const H& handle, const M& map, const A& acc) { - using MDS = std::mdspan; + using MDS = std::mdspan; static_assert(mec == std::is_constructible_v); static_assert(ac == std::is_default_constructible_v); if constexpr (mec && ac) { // test from all extents - auto exts = array_from_extents(map.extents(), std::make_index_sequence()); + auto exts = array_from_extents(map.extents(), + std::make_index_sequence()); test_mdspan_ctor_array(handle, map, acc, exts); // test from dynamic extents @@ -101,20 +110,32 @@ constexpr void test_mdspan_ctor(const H& handle, const M& map, const A& acc) { } test_mdspan_ctor_array(handle, map, acc, exts_dynamic); } else { - static_assert(!std::is_constructible_v&>); + static_assert(!std::is_constructible_v< + MDS, const H&, + const std::array&>); } } template constexpr void mixin_extents(const H& handle, const L& layout, const A& acc) { constexpr size_t D = std::dynamic_extent; - test_mdspan_ctor(handle, construct_mapping(layout, std::extents()), acc); - test_mdspan_ctor(handle, construct_mapping(layout, std::extents(7)), acc); - test_mdspan_ctor(handle, construct_mapping(layout, std::extents()), acc); - test_mdspan_ctor(handle, construct_mapping(layout, std::extents(2, 3)), acc); - test_mdspan_ctor(handle, construct_mapping(layout, std::extents(0, 3)), acc); test_mdspan_ctor( - handle, construct_mapping(layout, std::extents(1, 2, 3, 2)), acc); + handle, construct_mapping(layout, std::extents()), acc); + test_mdspan_ctor( + handle, construct_mapping(layout, std::extents(7)), acc); + test_mdspan_ctor( + handle, construct_mapping(layout, std::extents()), acc); + test_mdspan_ctor( + handle, construct_mapping(layout, std::extents(2, 3)), + acc); + test_mdspan_ctor( + handle, construct_mapping(layout, std::extents(0, 3)), + acc); + test_mdspan_ctor( + handle, + construct_mapping(layout, + std::extents(1, 2, 3, 2)), + acc); } template @@ -122,17 +143,26 @@ constexpr void mixin_layout(const H& handle, const A& acc) { mixin_extents(handle, std::layout_left(), acc); mixin_extents(handle, std::layout_right(), acc); - // Sanity check that this layouts mapping is constructible from extents (via its move constructor) - static_assert(std::is_constructible_v::template mapping>, - std::extents>); - static_assert(!std::is_constructible_v::template mapping>, - const std::extents&>); + // Sanity check that this layouts mapping is constructible from extents (via + // its move constructor) + static_assert( + std::is_constructible_v::template mapping>, + std::extents>); + static_assert( + !std::is_constructible_v::template mapping>, + const std::extents&>); mixin_extents(handle, layout_wrapping_integral<8>(), acc); // Sanity check that this layouts mapping is not constructible from extents - static_assert(!std::is_constructible_v::template mapping>, - std::extents>); - static_assert(!std::is_constructible_v::template mapping>, - const std::extents&>); + static_assert( + !std::is_constructible_v::template mapping>, + std::extents>); + static_assert( + !std::is_constructible_v::template mapping>, + const std::extents&>); mixin_extents(handle, layout_wrapping_integral<4>(), acc); } @@ -143,10 +173,13 @@ constexpr void mixin_accessor() { // Using weird accessor/data_handle // Make sure they actually got the properties we want to test - // checked_accessor is not default constructible except for const double, where it is not noexcept - static_assert(std::is_default_constructible_v> == std::is_same_v); + // checked_accessor is not default constructible except for const double, + // where it is not noexcept + static_assert(std::is_default_constructible_v> == + std::is_same_v); mixin_layout>( - typename checked_accessor::data_handle_type(elements.get_ptr()), checked_accessor(1024)); + typename checked_accessor::data_handle_type(elements.get_ptr()), + checked_accessor(1024)); } constexpr bool test() { @@ -169,27 +202,33 @@ constexpr bool test() { // not convertible to index_type static_assert(std::is_convertible_v); static_assert(!std::is_convertible_v); - static_assert(!std::is_constructible_v>); + static_assert( + !std::is_constructible_v>); // index_type is not nothrow constructible using mds_uchar_t = std::mdspan>; static_assert(std::is_convertible_v); static_assert(std::is_convertible_v); - static_assert(!std::is_nothrow_constructible_v); - static_assert(!std::is_constructible_v>); + static_assert( + !std::is_nothrow_constructible_v); + static_assert( + !std::is_constructible_v>); // convertible from non-const to index_type but not from const using mds_int_t = std::mdspan>; static_assert(std::is_convertible_v); static_assert(!std::is_convertible_v); static_assert(std::is_nothrow_constructible_v); - static_assert(!std::is_constructible_v>); + static_assert( + !std::is_constructible_v>); - // can't test a combo where std::is_nothrow_constructible_v is true, - // but std::is_convertible_v is false + // can't test a combo where std::is_nothrow_constructible_v is true, but std::is_convertible_v is + // false // test non-constructibility from wrong handle_type - static_assert(!std::is_constructible_v>); + static_assert( + !std::is_constructible_v>); return true; } diff --git a/tests/libcxx-backports/mdspan/mdspan.ctor.dh_extents.pass.cpp b/tests/libcxx-backports/mdspan/mdspan.ctor.dh_extents.pass.cpp index 2a7aac22..d3cbeb44 100644 --- a/tests/libcxx-backports/mdspan/mdspan.ctor.dh_extents.pass.cpp +++ b/tests/libcxx-backports/mdspan/mdspan.ctor.dh_extents.pass.cpp @@ -15,8 +15,10 @@ // - is_constructible_v is true, and // - is_default_constructible_v is true. // -// Preconditions: [0, map_.required_span_size()) is an accessible range of p and acc_ -// for the values of map_ and acc_ after the invocation of this constructor. +// Preconditions: [0, map_.required_span_size()) is an accessible range of p and +// acc_ +// for the values of map_ and acc_ after the invocation of this +// constructor. // // Effects: // - Direct-non-list-initializes ptr_ with std::move(p), @@ -36,9 +38,11 @@ template constexpr void test_mdspan_types(const H& handle, const M& map, const A&) { - using MDS = std::mdspan; + using MDS = std::mdspan; - static_assert(mec == std::is_constructible_v); + static_assert(mec == + std::is_constructible_v); static_assert(ac == std::is_default_constructible_v); if constexpr (mec && ac) { #if MDSPAN_HAS_CXX_23 @@ -50,7 +54,8 @@ constexpr void test_mdspan_types(const H& handle, const M& map, const A&) { MDS m = {handle, map.extents()}; #if MDSPAN_HAS_CXX_23 if !consteval { - if constexpr (std::is_same_v>) { + if constexpr (std::is_same_v< + H, move_counted_handle>) { assert((H::move_counter() == 1)); } } @@ -59,25 +64,34 @@ constexpr void test_mdspan_types(const H& handle, const M& map, const A&) { assert(m.extents() == map.extents()); if constexpr (std::equality_comparable) assert(m.data_handle() == handle); - if constexpr (std::equality_comparable) - assert(m.mapping() == map); - if constexpr (std::equality_comparable) - assert(m.accessor() == A()); + if constexpr (std::equality_comparable) assert(m.mapping() == map); + if constexpr (std::equality_comparable) assert(m.accessor() == A()); } else { - static_assert(!std::is_constructible_v); + static_assert(!std::is_constructible_v); } } template constexpr void mixin_extents(const H& handle, const L& layout, const A& acc) { constexpr size_t D = std::dynamic_extent; - test_mdspan_types(handle, construct_mapping(layout, std::extents()), acc); - test_mdspan_types(handle, construct_mapping(layout, std::extents(7)), acc); - test_mdspan_types(handle, construct_mapping(layout, std::extents()), acc); - test_mdspan_types(handle, construct_mapping(layout, std::extents(2, 3)), acc); - test_mdspan_types(handle, construct_mapping(layout, std::extents(0, 3)), acc); test_mdspan_types( - handle, construct_mapping(layout, std::extents(1, 2, 3, 2)), acc); + handle, construct_mapping(layout, std::extents()), acc); + test_mdspan_types( + handle, construct_mapping(layout, std::extents(7)), acc); + test_mdspan_types( + handle, construct_mapping(layout, std::extents()), acc); + test_mdspan_types( + handle, construct_mapping(layout, std::extents(2, 3)), + acc); + test_mdspan_types( + handle, construct_mapping(layout, std::extents(0, 3)), + acc); + test_mdspan_types( + handle, + construct_mapping(layout, + std::extents(1, 2, 3, 2)), + acc); } template @@ -86,17 +100,26 @@ constexpr void mixin_layout(const H& handle, const A& acc) { mixin_extents(handle, std::layout_right(), acc); // Use weird layout, make sure it has the properties we want to test - // Sanity check that this layouts mapping is constructible from extents (via its move constructor) - static_assert(std::is_constructible_v::template mapping>, - std::extents>); - static_assert(!std::is_constructible_v::template mapping>, - const std::extents&>); + // Sanity check that this layouts mapping is constructible from extents (via + // its move constructor) + static_assert( + std::is_constructible_v::template mapping>, + std::extents>); + static_assert( + !std::is_constructible_v::template mapping>, + const std::extents&>); mixin_extents(handle, layout_wrapping_integral<8>(), acc); // Sanity check that this layouts mapping is not constructible from extents - static_assert(!std::is_constructible_v::template mapping>, - std::extents>); - static_assert(!std::is_constructible_v::template mapping>, - const std::extents&>); + static_assert( + !std::is_constructible_v::template mapping>, + std::extents>); + static_assert( + !std::is_constructible_v::template mapping>, + const std::extents&>); mixin_extents(handle, layout_wrapping_integral<4>(), acc); } @@ -107,10 +130,13 @@ constexpr void mixin_accessor() { // Using weird accessor/data_handle // Make sure they actually got the properties we want to test - // checked_accessor is not default constructible except for const double, where it is not noexcept - static_assert(std::is_default_constructible_v> == std::is_same_v); + // checked_accessor is not default constructible except for const double, + // where it is not noexcept + static_assert(std::is_default_constructible_v> == + std::is_same_v); mixin_layout>( - typename checked_accessor::data_handle_type(elements.get_ptr()), checked_accessor(1024)); + typename checked_accessor::data_handle_type(elements.get_ptr()), + checked_accessor(1024)); } constexpr bool test() { @@ -125,16 +151,23 @@ constexpr bool test() { constexpr size_t D = std::dynamic_extent; using mds_t = std::mdspan>; // sanity check - static_assert(std::is_constructible_v>); + static_assert( + std::is_constructible_v>); // wrong size - static_assert(!std::is_constructible_v>); - static_assert(!std::is_constructible_v>); - // wrong type in general: note the extents constructor does NOT convert, since it takes by const& - static_assert(!std::is_constructible_v>); - static_assert(!std::is_constructible_v>); + static_assert( + !std::is_constructible_v>); + static_assert( + !std::is_constructible_v>); + // wrong type in general: note the extents constructor does NOT convert, since + // it takes by const& + static_assert( + !std::is_constructible_v>); + static_assert( + !std::is_constructible_v>); // test non-constructibility from wrong handle_type - static_assert(!std::is_constructible_v>); + static_assert(!std::is_constructible_v>); return true; } diff --git a/tests/libcxx-backports/mdspan/mdspan.ctor.dh_integers.pass.cpp b/tests/libcxx-backports/mdspan/mdspan.ctor.dh_integers.pass.cpp index a37b7765..7de8b0f5 100644 --- a/tests/libcxx-backports/mdspan/mdspan.ctor.dh_integers.pass.cpp +++ b/tests/libcxx-backports/mdspan/mdspan.ctor.dh_integers.pass.cpp @@ -21,12 +21,15 @@ // - is_constructible_v is true, and // - is_default_constructible_v is true. // -// Preconditions: [0, map_.required_span_size()) is an accessible range of p and acc_ -// for the values of map_ and acc_ after the invocation of this constructor. +// Preconditions: [0, map_.required_span_size()) is an accessible range of p and +// acc_ +// for the values of map_ and acc_ after the invocation of this +// constructor. // // Effects: // - Direct-non-list-initializes ptr_ with std::move(p), -// - direct-non-list-initializes map_ with extents_type(static_cast(std::move(exts))...), and +// - direct-non-list-initializes map_ with +// extents_type(static_cast(std::move(exts))...), and // - value-initializes acc_. #include @@ -42,11 +45,14 @@ #include "CustomTestAccessors.h" template -concept check_mdspan_ctor_implicit = requires(MDS m, Args... args) { m = {args...}; }; +concept check_mdspan_ctor_implicit = + requires(MDS m, Args... args) { m = {args...}; }; template -constexpr void test_mdspan_types(const H& handle, const M& map, const A&, Idxs... idxs) { - using MDS = std::mdspan; +constexpr void test_mdspan_types(const H& handle, const M& map, const A&, + Idxs... idxs) { + using MDS = std::mdspan; static_assert(mec == std::is_constructible_v); static_assert(ac == std::is_default_constructible_v); @@ -60,26 +66,27 @@ constexpr void test_mdspan_types(const H& handle, const M& map, const A&, Idxs.. MDS m(handle, idxs...); #if MDSPAN_HAS_CXX_23 if !consteval { - if constexpr (std::is_same_v>) { + if constexpr (std::is_same_v< + H, move_counted_handle>) { assert((H::move_counter() == 1)); } } #endif // sanity check that concept works - static_assert(check_mdspan_ctor_implicit>); + static_assert( + check_mdspan_ctor_implicit< + MDS, H, std::array>); // check that the constructor from integral is explicit static_assert(!check_mdspan_ctor_implicit); assert(m.extents() == map.extents()); if constexpr (std::equality_comparable) assert(m.data_handle() == handle); - if constexpr (std::equality_comparable) - assert(m.mapping() == map); - if constexpr (std::equality_comparable) - assert(m.accessor() == A()); + if constexpr (std::equality_comparable) assert(m.mapping() == map); + if constexpr (std::equality_comparable) assert(m.accessor() == A()); } else { - static_assert(!std::is_constructible_v); + static_assert(!std::is_constructible_v); } } @@ -87,20 +94,38 @@ template constexpr void mixin_extents(const H& handle, const L& layout, const A& acc) { constexpr size_t D = std::dynamic_extent; // construct from just dynamic extents - test_mdspan_types(handle, construct_mapping(layout, std::extents()), acc); - test_mdspan_types(handle, construct_mapping(layout, std::extents(7)), acc, 7); - test_mdspan_types(handle, construct_mapping(layout, std::extents()), acc); - test_mdspan_types(handle, construct_mapping(layout, std::extents(2, 3)), acc, 2, 3); - test_mdspan_types(handle, construct_mapping(layout, std::extents(0, 3)), acc, 0, 3); test_mdspan_types( - handle, construct_mapping(layout, std::extents(1, 2, 3, 2)), acc, 1, 2, 3, 2); + handle, construct_mapping(layout, std::extents()), acc); + test_mdspan_types( + handle, construct_mapping(layout, std::extents(7)), acc, 7); + test_mdspan_types( + handle, construct_mapping(layout, std::extents()), acc); + test_mdspan_types( + handle, construct_mapping(layout, std::extents(2, 3)), + acc, 2, 3); + test_mdspan_types( + handle, construct_mapping(layout, std::extents(0, 3)), acc, + 0, 3); + test_mdspan_types( + handle, + construct_mapping(layout, + std::extents(1, 2, 3, 2)), + acc, 1, 2, 3, 2); // construct from all extents - test_mdspan_types(handle, construct_mapping(layout, std::extents()), acc, 7); - test_mdspan_types(handle, construct_mapping(layout, std::extents(2, 3)), acc, 2, 4, 3); - test_mdspan_types(handle, construct_mapping(layout, std::extents(0, 3)), acc, 0, 7, 3); test_mdspan_types( - handle, construct_mapping(layout, std::extents(1, 2, 3, 2)), acc, 1, 7, 2, 4, 3, 2); + handle, construct_mapping(layout, std::extents()), acc, 7); + test_mdspan_types( + handle, construct_mapping(layout, std::extents(2, 3)), + acc, 2, 4, 3); + test_mdspan_types( + handle, construct_mapping(layout, std::extents(0, 3)), acc, + 0, 7, 3); + test_mdspan_types( + handle, + construct_mapping(layout, + std::extents(1, 2, 3, 2)), + acc, 1, 7, 2, 4, 3, 2); } template @@ -109,17 +134,26 @@ constexpr void mixin_layout(const H& handle, const A& acc) { mixin_extents(handle, std::layout_right(), acc); // Use weird layout, make sure it has the properties we want to test - // Sanity check that this layouts mapping is constructible from extents (via its move constructor) - static_assert(std::is_constructible_v::template mapping>, - std::extents>); - static_assert(!std::is_constructible_v::template mapping>, - const std::extents&>); + // Sanity check that this layouts mapping is constructible from extents (via + // its move constructor) + static_assert( + std::is_constructible_v::template mapping>, + std::extents>); + static_assert( + !std::is_constructible_v::template mapping>, + const std::extents&>); mixin_extents(handle, layout_wrapping_integral<8>(), acc); // Sanity check that this layouts mapping is not constructible from extents - static_assert(!std::is_constructible_v::template mapping>, - std::extents>); - static_assert(!std::is_constructible_v::template mapping>, - const std::extents&>); + static_assert( + !std::is_constructible_v::template mapping>, + std::extents>); + static_assert( + !std::is_constructible_v::template mapping>, + const std::extents&>); mixin_extents(handle, layout_wrapping_integral<4>(), acc); } @@ -130,10 +164,13 @@ constexpr void mixin_accessor() { // Using weird accessor/data_handle // Make sure they actually got the properties we want to test - // checked_accessor is not default constructible except for const double, where it is not noexcept - static_assert(std::is_default_constructible_v> == std::is_same_v); + // checked_accessor is not default constructible except for const double, + // where it is not noexcept + static_assert(std::is_default_constructible_v> == + std::is_same_v); mixin_layout>( - typename checked_accessor::data_handle_type(elements.get_ptr()), checked_accessor(1024)); + typename checked_accessor::data_handle_type(elements.get_ptr()), + checked_accessor(1024)); } constexpr bool test() { @@ -154,7 +191,8 @@ constexpr bool test() { static_assert(!std::is_constructible_v); static_assert(!std::is_constructible_v); // not convertible to int - static_assert(!std::is_constructible_v>); + static_assert( + !std::is_constructible_v>); // test non-constructibility from wrong handle_type static_assert(!std::is_constructible_v); diff --git a/tests/libcxx-backports/mdspan/mdspan.ctor.dh_map.pass.cpp b/tests/libcxx-backports/mdspan/mdspan.ctor.dh_map.pass.cpp index 99b95a63..5c7b08b2 100644 --- a/tests/libcxx-backports/mdspan/mdspan.ctor.dh_map.pass.cpp +++ b/tests/libcxx-backports/mdspan/mdspan.ctor.dh_map.pass.cpp @@ -13,8 +13,10 @@ // // Constraints: is_default_constructible_v is true. // -// Preconditions: [0, m.required_span_size()) is an accessible range of p and acc_ -// for the value of acc_ after the invocation of this constructor. +// Preconditions: [0, m.required_span_size()) is an accessible range of p and +// acc_ +// for the value of acc_ after the invocation of this +// constructor. // // Effects: // - Direct-non-list-initializes ptr_ with std::move(p), @@ -34,7 +36,8 @@ template constexpr void test_mdspan_types(const H& handle, const M& map, const A&) { - using MDS = std::mdspan; + using MDS = std::mdspan; static_assert(ac == std::is_default_constructible_v); if constexpr (ac) { @@ -47,7 +50,8 @@ constexpr void test_mdspan_types(const H& handle, const M& map, const A&) { MDS m = {handle, map}; #if MDSPAN_HAS_CXX_23 if !consteval { - if constexpr (std::is_same_v>) { + if constexpr (std::is_same_v< + H, move_counted_handle>) { assert((H::move_counter() == 1)); } } @@ -56,10 +60,8 @@ constexpr void test_mdspan_types(const H& handle, const M& map, const A&) { assert(m.extents() == map.extents()); if constexpr (std::equality_comparable) assert(m.data_handle() == handle); - if constexpr (std::equality_comparable) - assert(m.mapping() == map); - if constexpr (std::equality_comparable) - assert(m.accessor() == A()); + if constexpr (std::equality_comparable) assert(m.mapping() == map); + if constexpr (std::equality_comparable) assert(m.accessor() == A()); } else { static_assert(!std::is_constructible_v); } @@ -68,12 +70,23 @@ constexpr void test_mdspan_types(const H& handle, const M& map, const A&) { template constexpr void mixin_extents(const H& handle, const L& layout, const A& acc) { constexpr size_t D = std::dynamic_extent; - test_mdspan_types(handle, construct_mapping(layout, std::extents()), acc); - test_mdspan_types(handle, construct_mapping(layout, std::extents(7)), acc); - test_mdspan_types(handle, construct_mapping(layout, std::extents()), acc); - test_mdspan_types(handle, construct_mapping(layout, std::extents(2, 3)), acc); - test_mdspan_types(handle, construct_mapping(layout, std::extents(0, 3)), acc); - test_mdspan_types(handle, construct_mapping(layout, std::extents(1, 2, 3, 2)), acc); + test_mdspan_types(handle, construct_mapping(layout, std::extents()), + acc); + test_mdspan_types( + handle, construct_mapping(layout, std::extents(7)), acc); + test_mdspan_types( + handle, construct_mapping(layout, std::extents()), acc); + test_mdspan_types( + handle, construct_mapping(layout, std::extents(2, 3)), + acc); + test_mdspan_types( + handle, construct_mapping(layout, std::extents(0, 3)), + acc); + test_mdspan_types( + handle, + construct_mapping(layout, + std::extents(1, 2, 3, 2)), + acc); } template @@ -90,10 +103,13 @@ constexpr void mixin_accessor() { // Using weird accessor/data_handle // Make sure they actually got the properties we want to test - // checked_accessor is not default constructible except for const double, where it is not noexcept - static_assert(std::is_default_constructible_v> == std::is_same_v); + // checked_accessor is not default constructible except for const double, + // where it is not noexcept + static_assert(std::is_default_constructible_v> == + std::is_same_v); mixin_layout>( - typename checked_accessor::data_handle_type(elements.get_ptr()), checked_accessor(1024)); + typename checked_accessor::data_handle_type(elements.get_ptr()), + checked_accessor(1024)); } template @@ -111,18 +127,29 @@ constexpr bool test() { using mds_t = std::mdspan>; // sanity check - static_assert(std::is_constructible_v>>); + static_assert(std::is_constructible_v>>); // test non-constructibility from wrong mapping type // wrong rank - static_assert(!std::is_constructible_v>>); - static_assert(!std::is_constructible_v>>); - // wrong type in general: note the map constructor does NOT convert, since it takes by const& - static_assert(!std::is_constructible_v>>); - static_assert(!std::is_constructible_v>>); + static_assert(!std::is_constructible_v>>); + static_assert( + !std::is_constructible_v>>); + // wrong type in general: note the map constructor does NOT convert, since it + // takes by const& + static_assert( + !std::is_constructible_v>>); + static_assert( + !std::is_constructible_v>>); // test non-constructibility from wrong handle_type - static_assert(!std::is_constructible_v>>); + static_assert( + !std::is_constructible_v>>); return true; } diff --git a/tests/libcxx-backports/mdspan/mdspan.ctor.dh_map_acc.pass.cpp b/tests/libcxx-backports/mdspan/mdspan.ctor.dh_map_acc.pass.cpp index bd0006cc..e4579471 100644 --- a/tests/libcxx-backports/mdspan/mdspan.ctor.dh_map_acc.pass.cpp +++ b/tests/libcxx-backports/mdspan/mdspan.ctor.dh_map_acc.pass.cpp @@ -9,7 +9,8 @@ // -// constexpr mdspan(data_handle_type p, const mapping_type& m, const accessor_type& a); +// constexpr mdspan(data_handle_type p, const mapping_type& m, const +// accessor_type& a); // // Preconditions: [0, m.required_span_size()) is an accessible range of p and a. // @@ -31,7 +32,8 @@ template constexpr void test_mdspan_types(const H& handle, const M& map, const A& acc) { - using MDS = std::mdspan; + using MDS = std::mdspan; #if MDSPAN_HAS_CXX_23 if !consteval { @@ -42,30 +44,39 @@ constexpr void test_mdspan_types(const H& handle, const M& map, const A& acc) { MDS m = {handle, map, acc}; #if MDSPAN_HAS_CXX_23 if !consteval { - if constexpr (std::is_same_v>) { + if constexpr (std::is_same_v< + H, move_counted_handle>) { assert((H::move_counter() == 1)); } } #endif static_assert(!noexcept(MDS(handle, map, acc))); assert(m.extents() == map.extents()); - if constexpr (std::equality_comparable) - assert(m.data_handle() == handle); - if constexpr (std::equality_comparable) - assert(m.mapping() == map); - if constexpr (std::equality_comparable) - assert(m.accessor() == acc); + if constexpr (std::equality_comparable) assert(m.data_handle() == handle); + if constexpr (std::equality_comparable) assert(m.mapping() == map); + if constexpr (std::equality_comparable) assert(m.accessor() == acc); } template constexpr void mixin_extents(const H& handle, const L& layout, const A& acc) { constexpr size_t D = std::dynamic_extent; - test_mdspan_types(handle, construct_mapping(layout, std::extents()), acc); - test_mdspan_types(handle, construct_mapping(layout, std::extents(7)), acc); - test_mdspan_types(handle, construct_mapping(layout, std::extents()), acc); - test_mdspan_types(handle, construct_mapping(layout, std::extents(2, 3)), acc); - test_mdspan_types(handle, construct_mapping(layout, std::extents(0, 3)), acc); - test_mdspan_types(handle, construct_mapping(layout, std::extents(1, 2, 3, 2)), acc); + test_mdspan_types(handle, construct_mapping(layout, std::extents()), + acc); + test_mdspan_types(handle, construct_mapping(layout, std::extents(7)), + acc); + test_mdspan_types( + handle, construct_mapping(layout, std::extents()), acc); + test_mdspan_types( + handle, construct_mapping(layout, std::extents(2, 3)), + acc); + test_mdspan_types( + handle, construct_mapping(layout, std::extents(0, 3)), + acc); + test_mdspan_types( + handle, + construct_mapping(layout, + std::extents(1, 2, 3, 2)), + acc); } template @@ -82,12 +93,17 @@ constexpr void mixin_accessor() { // Using weird accessor/data_handle // Make sure they actually got the properties we want to test - // checked_accessor is not default constructible except for const double, where it is not noexcept - static_assert(std::is_default_constructible_v> == std::is_same_v); + // checked_accessor is not default constructible except for const double, + // where it is not noexcept + static_assert(std::is_default_constructible_v> == + std::is_same_v); // checked_accessor's data handle type is not default constructible for double - static_assert( - std::is_default_constructible_v::data_handle_type> != std::is_same_v); - mixin_layout(typename checked_accessor::data_handle_type(elements.get_ptr()), checked_accessor(1024)); + static_assert(std::is_default_constructible_v< + typename checked_accessor::data_handle_type> != + std::is_same_v); + mixin_layout( + typename checked_accessor::data_handle_type(elements.get_ptr()), + checked_accessor(1024)); } template @@ -107,23 +123,36 @@ constexpr bool test() { using acc_t = std::default_accessor; // sanity check - static_assert(std::is_constructible_v>, acc_t>); + static_assert( + std::is_constructible_v>, acc_t>); // test non-constructibility from wrong accessor - static_assert( - !std:: - is_constructible_v>, std::default_accessor>); + static_assert(!std::is_constructible_v>, + std::default_accessor>); // test non-constructibility from wrong mapping type // wrong rank - static_assert(!std::is_constructible_v>, acc_t>); - static_assert(!std::is_constructible_v>, acc_t>); - // wrong type in general: note the map constructor does NOT convert, since it takes by const& - static_assert(!std::is_constructible_v>, acc_t>); - static_assert(!std::is_constructible_v>, acc_t>); + static_assert( + !std::is_constructible_v>, acc_t>); + static_assert( + !std::is_constructible_v< + mds_t, float*, mapping_t>, acc_t>); + // wrong type in general: note the map constructor does NOT convert, since it + // takes by const& + static_assert( + !std::is_constructible_v>, acc_t>); + static_assert( + !std::is_constructible_v< + mds_t, float*, mapping_t>, acc_t>); // test non-constructibility from wrong handle_type - static_assert(!std::is_constructible_v>, acc_t>); + static_assert( + !std::is_constructible_v>, acc_t>); return true; } diff --git a/tests/libcxx-backports/mdspan/mdspan.ctor.dh_span.pass.cpp b/tests/libcxx-backports/mdspan/mdspan.ctor.dh_span.pass.cpp index 1de91a11..2bc5a80e 100644 --- a/tests/libcxx-backports/mdspan/mdspan.ctor.dh_span.pass.cpp +++ b/tests/libcxx-backports/mdspan/mdspan.ctor.dh_span.pass.cpp @@ -15,13 +15,16 @@ // // Constraints: // - is_convertible_v is true, -// - (is_nothrow_constructible && ...) is true, +// - (is_nothrow_constructible && ...) is +// true, // - N == rank() || N == rank_dynamic() is true, // - is_constructible_v is true, and // - is_default_constructible_v is true. // -// Preconditions: [0, map_.required_span_size()) is an accessible range of p and acc_ -// for the values of map_ and acc_ after the invocation of this constructor. +// Preconditions: [0, map_.required_span_size()) is an accessible range of p and +// acc_ +// for the values of map_ and acc_ after the invocation of this +// constructor. // // Effects: // - Direct-non-list-initializes ptr_ with std::move(p), @@ -42,19 +45,24 @@ #include "CustomTestAccessors.h" template -constexpr auto array_from_extents(const Extents& exts, std::index_sequence) { - return std::array{exts.extent(Idxs)...}; +constexpr auto array_from_extents(const Extents& exts, + std::index_sequence) { + return std::array{ + exts.extent(Idxs)...}; } template -concept check_mdspan_ctor_implicit = requires(MDS m, typename MDS::data_handle_type h, const Exts& exts) { - m = {h, exts}; -}; +concept check_mdspan_ctor_implicit = + requires(MDS m, typename MDS::data_handle_type h, const Exts& exts) { + m = {h, exts}; + }; template -constexpr void -test_mdspan_ctor_span(const H& handle, const M& map, const A&, std::span exts) { - using MDS = std::mdspan; +constexpr void test_mdspan_ctor_span( + const H& handle, const M& map, const A&, + std::span exts) { + using MDS = std::mdspan; #if MDSPAN_HAS_CXX_23 if !consteval { move_counted_handle::move_counter() = 0; @@ -63,7 +71,8 @@ test_mdspan_ctor_span(const H& handle, const M& map, const A&, std::span>) { + if constexpr (std::is_same_v< + H, move_counted_handle>) { assert((H::move_counter() == 1)); } } @@ -71,25 +80,25 @@ test_mdspan_ctor_span(const H& handle, const M& map, const A&, std::span == (N == MDS::rank_dynamic())); + static_assert(check_mdspan_ctor_implicit == + (N == MDS::rank_dynamic())); assert(m.extents() == map.extents()); - if constexpr (std::equality_comparable) - assert(m.data_handle() == handle); - if constexpr (std::equality_comparable) - assert(m.mapping() == map); - if constexpr (std::equality_comparable) - assert(m.accessor() == A()); + if constexpr (std::equality_comparable) assert(m.data_handle() == handle); + if constexpr (std::equality_comparable) assert(m.mapping() == map); + if constexpr (std::equality_comparable) assert(m.accessor() == A()); } template constexpr void test_mdspan_ctor(const H& handle, const M& map, const A& acc) { - using MDS = std::mdspan; + using MDS = std::mdspan; static_assert(mec == std::is_constructible_v); static_assert(ac == std::is_default_constructible_v); if constexpr (mec && ac) { // test from all extents - auto exts = array_from_extents(map.extents(), std::make_index_sequence()); + auto exts = array_from_extents(map.extents(), + std::make_index_sequence()); test_mdspan_ctor_span(handle, map, acc, std::span(exts)); // test from dynamic extents @@ -101,20 +110,32 @@ constexpr void test_mdspan_ctor(const H& handle, const M& map, const A& acc) { } test_mdspan_ctor_span(handle, map, acc, std::span(exts_dynamic)); } else { - static_assert(!std::is_constructible_v>); + static_assert( + !std::is_constructible_v< + MDS, const H&, std::span>); } } template constexpr void mixin_extents(const H& handle, const L& layout, const A& acc) { constexpr size_t D = std::dynamic_extent; - test_mdspan_ctor(handle, construct_mapping(layout, std::extents()), acc); - test_mdspan_ctor(handle, construct_mapping(layout, std::extents(7)), acc); - test_mdspan_ctor(handle, construct_mapping(layout, std::extents()), acc); - test_mdspan_ctor(handle, construct_mapping(layout, std::extents(2, 3)), acc); - test_mdspan_ctor(handle, construct_mapping(layout, std::extents(0, 3)), acc); test_mdspan_ctor( - handle, construct_mapping(layout, std::extents(1, 2, 3, 2)), acc); + handle, construct_mapping(layout, std::extents()), acc); + test_mdspan_ctor( + handle, construct_mapping(layout, std::extents(7)), acc); + test_mdspan_ctor( + handle, construct_mapping(layout, std::extents()), acc); + test_mdspan_ctor( + handle, construct_mapping(layout, std::extents(2, 3)), + acc); + test_mdspan_ctor( + handle, construct_mapping(layout, std::extents(0, 3)), + acc); + test_mdspan_ctor( + handle, + construct_mapping(layout, + std::extents(1, 2, 3, 2)), + acc); } template @@ -122,17 +143,26 @@ constexpr void mixin_layout(const H& handle, const A& acc) { mixin_extents(handle, std::layout_left(), acc); mixin_extents(handle, std::layout_right(), acc); - // Sanity check that this layouts mapping is constructible from extents (via its move constructor) - static_assert(std::is_constructible_v::template mapping>, - std::extents>); - static_assert(!std::is_constructible_v::template mapping>, - const std::extents&>); + // Sanity check that this layouts mapping is constructible from extents (via + // its move constructor) + static_assert( + std::is_constructible_v::template mapping>, + std::extents>); + static_assert( + !std::is_constructible_v::template mapping>, + const std::extents&>); mixin_extents(handle, layout_wrapping_integral<8>(), acc); // Sanity check that this layouts mapping is not constructible from extents - static_assert(!std::is_constructible_v::template mapping>, - std::extents>); - static_assert(!std::is_constructible_v::template mapping>, - const std::extents&>); + static_assert( + !std::is_constructible_v::template mapping>, + std::extents>); + static_assert( + !std::is_constructible_v::template mapping>, + const std::extents&>); mixin_extents(handle, layout_wrapping_integral<4>(), acc); } @@ -143,10 +173,13 @@ constexpr void mixin_accessor() { // Using weird accessor/data_handle // Make sure they actually got the properties we want to test - // checked_accessor is not default constructible except for const double, where it is not noexcept - static_assert(std::is_default_constructible_v> == std::is_same_v); + // checked_accessor is not default constructible except for const double, + // where it is not noexcept + static_assert(std::is_default_constructible_v> == + std::is_same_v); mixin_layout>( - typename checked_accessor::data_handle_type(elements.get_ptr()), checked_accessor(1024)); + typename checked_accessor::data_handle_type(elements.get_ptr()), + checked_accessor(1024)); } constexpr bool test() { @@ -175,21 +208,26 @@ constexpr bool test() { using mds_uchar_t = std::mdspan>; static_assert(std::is_convertible_v); static_assert(std::is_convertible_v); - static_assert(!std::is_nothrow_constructible_v); - static_assert(!std::is_constructible_v>); + static_assert( + !std::is_nothrow_constructible_v); + static_assert( + !std::is_constructible_v>); // convertible from non-const to index_type but not from const using mds_int_t = std::mdspan>; static_assert(std::is_convertible_v); static_assert(!std::is_convertible_v); static_assert(std::is_nothrow_constructible_v); - static_assert(!std::is_constructible_v>); + static_assert( + !std::is_constructible_v>); - // can't test a combo where std::is_nothrow_constructible_v is true, - // but std::is_convertible_v is false + // can't test a combo where std::is_nothrow_constructible_v is true, but std::is_convertible_v is + // false // test non-constructibility from wrong handle_type - static_assert(!std::is_constructible_v>); + static_assert( + !std::is_constructible_v>); return true; } diff --git a/tests/libcxx-backports/mdspan/mdspan.ctor.move.pass.cpp b/tests/libcxx-backports/mdspan/mdspan.ctor.move.pass.cpp index 4db5bdaf..c7b52f97 100644 --- a/tests/libcxx-backports/mdspan/mdspan.ctor.move.pass.cpp +++ b/tests/libcxx-backports/mdspan/mdspan.ctor.move.pass.cpp @@ -11,7 +11,8 @@ // constexpr mdspan(mdspan&&) = default; // -// A specialization of mdspan is a trivially copyable type if its accessor_type, mapping_type, and data_handle_type are trivially copyable types. +// A specialization of mdspan is a trivially copyable type if its accessor_type, +// mapping_type, and data_handle_type are trivially copyable types. #include #include @@ -26,42 +27,55 @@ template constexpr void test_mdspan_types(const H& handle, const M& map, const A& acc) { - using MDS = std::mdspan; + using MDS = std::mdspan; MDS m_org(handle, map, acc); MDS m(std::move(m_org)); static_assert(std::is_trivially_move_constructible_v == - (std::is_trivially_move_constructible_v && std::is_trivially_move_constructible_v && + (std::is_trivially_move_constructible_v && + std::is_trivially_move_constructible_v && std::is_trivially_move_constructible_v)); assert(m.extents() == map.extents()); - if constexpr (std::equality_comparable) - assert(m.data_handle() == handle); - if constexpr (std::equality_comparable) - assert(m.mapping() == map); - if constexpr (std::equality_comparable) - assert(m.accessor() == acc); + if constexpr (std::equality_comparable) assert(m.data_handle() == handle); + if constexpr (std::equality_comparable) assert(m.mapping() == map); + if constexpr (std::equality_comparable) assert(m.accessor() == acc); } template constexpr void mixin_extents(const H& handle, const L& layout, const A& acc) { constexpr size_t D = std::dynamic_extent; - test_mdspan_types(handle, construct_mapping(layout, std::extents()), acc); - test_mdspan_types(handle, construct_mapping(layout, std::extents(7)), acc); - test_mdspan_types(handle, construct_mapping(layout, std::extents()), acc); - test_mdspan_types(handle, construct_mapping(layout, std::extents(2, 3)), acc); - test_mdspan_types(handle, construct_mapping(layout, std::extents(0, 3)), acc); - test_mdspan_types(handle, construct_mapping(layout, std::extents(1, 2, 3, 2)), acc); + test_mdspan_types(handle, construct_mapping(layout, std::extents()), + acc); + test_mdspan_types(handle, construct_mapping(layout, std::extents(7)), + acc); + test_mdspan_types( + handle, construct_mapping(layout, std::extents()), acc); + test_mdspan_types( + handle, construct_mapping(layout, std::extents(2, 3)), + acc); + test_mdspan_types( + handle, construct_mapping(layout, std::extents(0, 3)), + acc); + test_mdspan_types( + handle, + construct_mapping(layout, + std::extents(1, 2, 3, 2)), + acc); } template constexpr void mixin_layout(const H& handle, const A& acc) { // make sure we test a trivially copyable mapping - static_assert(std::is_trivially_move_constructible_v>>); + static_assert( + std::is_trivially_move_constructible_v< + typename std::layout_left::template mapping>>); mixin_extents(handle, std::layout_left(), acc); mixin_extents(handle, std::layout_right(), acc); // make sure we test a not trivially copyable mapping - static_assert(!std::is_trivially_move_constructible_v< - typename layout_wrapping_integral<4>::template mapping>>); + static_assert( + !std::is_trivially_move_constructible_v::template mapping>>); mixin_extents(handle, layout_wrapping_integral<4>(), acc); } @@ -69,17 +83,21 @@ template constexpr void mixin_accessor() { ElementPool elements; // make sure we test trivially constructible accessor and data_handle - static_assert(std::is_trivially_move_constructible_v>); - static_assert(std::is_trivially_move_constructible_v::data_handle_type>); + static_assert( + std::is_trivially_move_constructible_v>); + static_assert(std::is_trivially_move_constructible_v< + typename std::default_accessor::data_handle_type>); mixin_layout(elements.get_ptr(), std::default_accessor()); // Using weird accessor/data_handle // Make sure they actually got the properties we want to test // checked_accessor is noexcept copy constructible except for const double checked_accessor acc(1024); - static_assert(std::is_trivially_move_constructible_v::data_handle_type> == + static_assert(std::is_trivially_move_constructible_v< + typename checked_accessor::data_handle_type> == std::is_same_v); - mixin_layout(typename checked_accessor::data_handle_type(elements.get_ptr()), acc); + mixin_layout( + typename checked_accessor::data_handle_type(elements.get_ptr()), acc); } constexpr bool test() { diff --git a/tests/libcxx-backports/mdspan/mdspan.deduction.pass.cpp b/tests/libcxx-backports/mdspan/mdspan.deduction.pass.cpp index 1f2362e2..6a6cc43f 100644 --- a/tests/libcxx-backports/mdspan/mdspan.deduction.pass.cpp +++ b/tests/libcxx-backports/mdspan/mdspan.deduction.pass.cpp @@ -12,16 +12,18 @@ // template // requires(is_array_v && rank_v == 1) // mdspan(CArray&) -// -> mdspan, extents>>; +// -> mdspan, extents>>; // // template // requires(is_pointer_v>) // mdspan(Pointer&&) -// -> mdspan>, extents>; +// -> mdspan>, +// extents>; // // template -// requires((is_convertible_v && ...) && sizeof...(Integrals) > 0) -// explicit mdspan(ElementType*, Integrals...) +// requires((is_convertible_v && ...) && +// sizeof...(Integrals) > 0) explicit mdspan(ElementType*, Integrals...) // -> mdspan>; // // template @@ -44,7 +46,8 @@ // template // mdspan(const typename AccessorType::data_handle_type&, const MappingType&, // const AccessorType&) -// -> mdspan mdspan; #include @@ -60,12 +63,15 @@ template constexpr void test_mdspan_types(const H& handle, const M& map, const A& acc) { - using MDS = std::mdspan; + using MDS = std::mdspan; - // deduction from data_handle_type (including non-pointer), mapping and accessor + // deduction from data_handle_type (including non-pointer), mapping and + // accessor ASSERT_SAME_TYPE(decltype(std::mdspan(handle, map, acc)), MDS); - if constexpr (std::is_same_v>) { + if constexpr (std::is_same_v< + A, std::default_accessor>) { // deduction from pointer and mapping // non-pointer data-handle-types have other accessor ASSERT_SAME_TYPE(decltype(std::mdspan(handle, map)), MDS); @@ -79,12 +85,23 @@ constexpr void test_mdspan_types(const H& handle, const M& map, const A& acc) { template constexpr void mixin_extents(const H& handle, const L& layout, const A& acc) { constexpr size_t D = std::dynamic_extent; - test_mdspan_types(handle, construct_mapping(layout, std::extents()), acc); - test_mdspan_types(handle, construct_mapping(layout, std::extents(7)), acc); - test_mdspan_types(handle, construct_mapping(layout, std::extents()), acc); - test_mdspan_types(handle, construct_mapping(layout, std::extents(2, 3)), acc); - test_mdspan_types(handle, construct_mapping(layout, std::extents(0, 3)), acc); - test_mdspan_types(handle, construct_mapping(layout, std::extents(1, 2, 3, 2)), acc); + test_mdspan_types(handle, construct_mapping(layout, std::extents()), + acc); + test_mdspan_types(handle, construct_mapping(layout, std::extents(7)), + acc); + test_mdspan_types( + handle, construct_mapping(layout, std::extents()), acc); + test_mdspan_types( + handle, construct_mapping(layout, std::extents(2, 3)), + acc); + test_mdspan_types( + handle, construct_mapping(layout, std::extents(0, 3)), + acc); + test_mdspan_types( + handle, + construct_mapping(layout, + std::extents(1, 2, 3, 2)), + acc); } struct SizeTIntType { @@ -98,15 +115,19 @@ template constexpr bool test_no_layout_deduction_guides(const H& handle, const A&) { using T = typename A::element_type; // deduction from pointer alone - ASSERT_SAME_TYPE(decltype(std::mdspan(handle)), std::mdspan>); + ASSERT_SAME_TYPE(decltype(std::mdspan(handle)), + std::mdspan>); // deduction from pointer and integral like - ASSERT_SAME_TYPE(decltype(std::mdspan(handle, 5, SizeTIntType(6))), std::mdspan>); + ASSERT_SAME_TYPE(decltype(std::mdspan(handle, 5, SizeTIntType(6))), + std::mdspan>); std::array exts; // deduction from pointer and array - ASSERT_SAME_TYPE(decltype(std::mdspan(handle, exts)), std::mdspan>); + ASSERT_SAME_TYPE(decltype(std::mdspan(handle, exts)), + std::mdspan>); // deduction from pointer and span - ASSERT_SAME_TYPE(decltype(std::mdspan(handle, std::span(exts))), std::mdspan>); + ASSERT_SAME_TYPE(decltype(std::mdspan(handle, std::span(exts))), + std::mdspan>); return true; } @@ -122,7 +143,8 @@ constexpr void mixin_layout(const H& handle, const A& acc) { mixin_extents(handle, layout_wrapping_integral<4>(), acc); // checking that there is no deduction happen for non-pointer handle type - assert((test_no_layout_deduction_guides(handle, acc) == std::is_same_v)); + assert((test_no_layout_deduction_guides(handle, acc) == + std::is_same_v)); } template @@ -134,8 +156,10 @@ constexpr void mixin_accessor() { // Make sure they actually got the properties we want to test // checked_accessor is noexcept copy constructible except for const double checked_accessor acc(1024); - static_assert(noexcept(checked_accessor(acc)) != std::is_same_v); - mixin_layout(typename checked_accessor::data_handle_type(elements.get_ptr()), acc); + static_assert(noexcept(checked_accessor(acc)) != + std::is_same_v); + mixin_layout( + typename checked_accessor::data_handle_type(elements.get_ptr()), acc); } constexpr bool test() { @@ -148,7 +172,8 @@ constexpr bool test() { // deduction from array alone float a[12]; - ASSERT_SAME_TYPE(decltype(std::mdspan(a)), std::mdspan>); + ASSERT_SAME_TYPE(decltype(std::mdspan(a)), + std::mdspan>); return true; } diff --git a/tests/libcxx-backports/mdspan/mdspan.element_type.verify.cpp b/tests/libcxx-backports/mdspan/mdspan.element_type.verify.cpp index a3e7ecb2..a59a6469 100644 --- a/tests/libcxx-backports/mdspan/mdspan.element_type.verify.cpp +++ b/tests/libcxx-backports/mdspan/mdspan.element_type.verify.cpp @@ -9,31 +9,37 @@ // -// template -// class mdspan; +// template class mdspan; // // Mandates: -// - ElementType is a complete object type that is neither an abstract class type nor an array type. +// - ElementType is a complete object type that is neither an abstract class +// type nor an array type. // - is_same_v is true. #include class AbstractClass { -public: + public: virtual void method() = 0; }; void not_abstract_class() { - // expected-error-re@*:* {{static assertion failed {{.*}}mdspan: ElementType template parameter may not be an abstract class}} + // expected-error-re@*:* {{static assertion failed {{.*}}mdspan: ElementType + // template parameter may not be an abstract class}} [[maybe_unused]] std::mdspan> m; } void not_array_type() { - // expected-error-re@*:* {{static assertion failed {{.*}}mdspan: ElementType template parameter may not be an array type}} + // expected-error-re@*:* {{static assertion failed {{.*}}mdspan: ElementType + // template parameter may not be an array type}} [[maybe_unused]] std::mdspan> m; } void element_type_mismatch() { - // expected-error-re@*:* {{static assertion failed {{.*}}mdspan: ElementType template parameter must match AccessorPolicy::element_type}} - [[maybe_unused]] std::mdspan, std::layout_right, std::default_accessor> m; + // expected-error-re@*:* {{static assertion failed {{.*}}mdspan: ElementType + // template parameter must match AccessorPolicy::element_type}} + [[maybe_unused]] std::mdspan, std::layout_right, + std::default_accessor> + m; } diff --git a/tests/libcxx-backports/mdspan/mdspan.extents.verify.cpp b/tests/libcxx-backports/mdspan/mdspan.extents.verify.cpp index 1ee6f733..3c385158 100644 --- a/tests/libcxx-backports/mdspan/mdspan.extents.verify.cpp +++ b/tests/libcxx-backports/mdspan/mdspan.extents.verify.cpp @@ -9,8 +9,8 @@ // -// template -// class mdspan; +// template class mdspan; // // Mandates: // - Extents is a specialization of extents @@ -18,6 +18,7 @@ #include void not_extents() { - // expected-error-re@*:* {{static assertion failed {{.*}}mdspan: Extents template parameter must be a specialization of extents.}} + // expected-error-re@*:* {{static assertion failed {{.*}}mdspan: Extents + // template parameter must be a specialization of extents.}} [[maybe_unused]] std::mdspan m; } diff --git a/tests/libcxx-backports/mdspan/mdspan.index_operator.pass.cpp b/tests/libcxx-backports/mdspan/mdspan.index_operator.pass.cpp index 5cca1d80..c1dbc731 100644 --- a/tests/libcxx-backports/mdspan/mdspan.index_operator.pass.cpp +++ b/tests/libcxx-backports/mdspan/mdspan.index_operator.pass.cpp @@ -25,8 +25,8 @@ // GCC warns about comma operator changing its meaning inside [] in C++23 #if defined(__GNUC__) && !defined(__clang_major__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wcomma-subscript" +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcomma-subscript" #endif #include @@ -38,7 +38,8 @@ #include "../ConvertibleToIntegral.h" #include "../CustomTestLayouts.h" -// This test uses the bracket operator, but its not something we have at configure time +// This test uses the bracket operator, but its not something we have at +// configure time #if MDSPAN_USE_BRACKET_OPERATOR // Clang 16 does not support argument packs as input to operator [] @@ -60,7 +61,8 @@ constexpr auto& access(MDS mds, int64_t i0, int64_t i1, int64_t i2) { return mds[i0, i1, i2]; } template -constexpr auto& access(MDS mds, int64_t i0, int64_t i1, int64_t i2, int64_t i3) { +constexpr auto& access(MDS mds, int64_t i0, int64_t i1, int64_t i2, + int64_t i3) { return mds[i0, i1, i2, i3]; } #endif @@ -84,17 +86,20 @@ constexpr bool check_operator_constraints(MDS, Indices...) { template constexpr void iterate(MDS mds, Args... args) { - constexpr int r = static_cast(MDS::extents_type::rank()) - 1 - static_cast(sizeof...(Args)); + constexpr int r = static_cast(MDS::extents_type::rank()) - 1 - + static_cast(sizeof...(Args)); if constexpr (-1 == r) { #if defined(__clang_major__) && __clang_major__ < 17 int* ptr1 = &access(mds, args...); #else int* ptr1 = &mds[args...]; #endif - int* ptr2 = &(mds.accessor().access(mds.data_handle(), mds.mapping()(args...))); + int* ptr2 = + &(mds.accessor().access(mds.data_handle(), mds.mapping()(args...))); assert(ptr1 == ptr2); - std::array args_arr{static_cast(args)...}; + std::array args_arr{ + static_cast(args)...}; int* ptr3 = &mds[args_arr]; assert(ptr3 == ptr2); int* ptr4 = &mds[std::span(args_arr)]; @@ -109,7 +114,8 @@ constexpr void iterate(MDS mds, Args... args) { template constexpr void test_iteration(Mapping m) { std::array data; - using MDS = std::mdspan; + using MDS = std::mdspan; MDS mds(data.data(), m); iterate(mds); @@ -123,100 +129,142 @@ constexpr void test_layout() { test_iteration(construct_mapping(Layout(), std::extents(7))); test_iteration(construct_mapping(Layout(), std::extents())); test_iteration(construct_mapping(Layout(), std::extents())); - test_iteration(construct_mapping(Layout(), std::extents(1, 1, 1, 1))); + test_iteration( + construct_mapping(Layout(), std::extents(1, 1, 1, 1))); -// TODO enable for GCC 13, when the CI pipeline is switched, doesn't work with GCC 12 +// TODO enable for GCC 13, when the CI pipeline is switched, doesn't work with +// GCC 12 #if defined(__clang_major__) && __clang_major__ >= 17 int data[1]; // Check operator constraint for number of arguments - static_assert(check_operator_constraints(std::mdspan(data, construct_mapping(Layout(), std::extents(1))), 0)); - static_assert( - !check_operator_constraints(std::mdspan(data, construct_mapping(Layout(), std::extents(1))), 0, 0)); + static_assert(check_operator_constraints( + std::mdspan(data, construct_mapping(Layout(), std::extents(1))), + 0)); + static_assert(!check_operator_constraints( + std::mdspan(data, construct_mapping(Layout(), std::extents(1))), + 0, 0)); // Check operator constraint for convertibility of arguments to index_type - static_assert( - check_operator_constraints(std::mdspan(data, construct_mapping(Layout(), std::extents(1))), IntType(0))); + static_assert(check_operator_constraints( + std::mdspan(data, construct_mapping(Layout(), std::extents(1))), + IntType(0))); static_assert(!check_operator_constraints( - std::mdspan(data, construct_mapping(Layout(), std::extents(1))), IntType(0))); + std::mdspan(data, + construct_mapping(Layout(), std::extents(1))), + IntType(0))); - // Check operator constraint for no-throw-constructibility of index_type from arguments + // Check operator constraint for no-throw-constructibility of index_type from + // arguments static_assert(!check_operator_constraints( - std::mdspan(data, construct_mapping(Layout(), std::extents(1))), IntType(0))); + std::mdspan( + data, construct_mapping(Layout(), std::extents(1))), + IntType(0))); - // Check that mixed integrals work: note the second one tests that mdspan casts: layout_wrapping_integral does not accept IntType + // Check that mixed integrals work: note the second one tests that mdspan + // casts: layout_wrapping_integral does not accept IntType static_assert(check_operator_constraints( - std::mdspan(data, construct_mapping(Layout(), std::extents(1, 1))), int(0), size_t(0))); + std::mdspan(data, construct_mapping( + Layout(), std::extents(1, 1))), + int(0), size_t(0))); static_assert(check_operator_constraints( - std::mdspan(data, construct_mapping(Layout(), std::extents(1, 1))), unsigned(0), IntType(0))); + std::mdspan(data, + construct_mapping(Layout(), std::extents(1, 1))), + unsigned(0), IntType(0))); constexpr bool t = true; constexpr bool o = false; static_assert(!check_operator_constraints( - std::mdspan(data, construct_mapping(Layout(), std::extents(1, 1))), - unsigned(0), - IntConfig(0))); + std::mdspan(data, + construct_mapping(Layout(), std::extents(1, 1))), + unsigned(0), IntConfig(0))); static_assert(check_operator_constraints( - std::mdspan(data, construct_mapping(Layout(), std::extents(1, 1))), - unsigned(0), - IntConfig(0))); + std::mdspan(data, + construct_mapping(Layout(), std::extents(1, 1))), + unsigned(0), IntConfig(0))); static_assert(check_operator_constraints( - std::mdspan(data, construct_mapping(Layout(), std::extents(1, 1))), - unsigned(0), - IntConfig(0))); + std::mdspan(data, + construct_mapping(Layout(), std::extents(1, 1))), + unsigned(0), IntConfig(0))); static_assert(!check_operator_constraints( - std::mdspan(data, construct_mapping(Layout(), std::extents(1, 1))), - unsigned(0), - IntConfig(0))); + std::mdspan(data, + construct_mapping(Layout(), std::extents(1, 1))), + unsigned(0), IntConfig(0))); static_assert(check_operator_constraints( - std::mdspan(data, construct_mapping(Layout(), std::extents(1, 1))), - unsigned(0), - IntConfig(0))); + std::mdspan(data, + construct_mapping(Layout(), std::extents(1, 1))), + unsigned(0), IntConfig(0))); // layout_wrapped wouldn't quite work here the way we wrote the check - // IntConfig has configurable conversion properties: convert from const&, convert from non-const, no-throw-ctor from const&, no-throw-ctor from non-const + // IntConfig has configurable conversion properties: convert from const&, + // convert from non-const, no-throw-ctor from const&, no-throw-ctor from + // non-const if constexpr (std::is_same_v) { static_assert(!check_operator_constraints( - std::mdspan(data, construct_mapping(Layout(), std::extents(1))), std::array{IntConfig(0)})); + std::mdspan(data, construct_mapping(Layout(), std::extents(1))), + std::array{IntConfig(0)})); static_assert(!check_operator_constraints( - std::mdspan(data, construct_mapping(Layout(), std::extents(1))), std::array{IntConfig(0)})); + std::mdspan(data, construct_mapping(Layout(), std::extents(1))), + std::array{IntConfig(0)})); static_assert(!check_operator_constraints( - std::mdspan(data, construct_mapping(Layout(), std::extents(1))), std::array{IntConfig(0)})); + std::mdspan(data, construct_mapping(Layout(), std::extents(1))), + std::array{IntConfig(0)})); static_assert(!check_operator_constraints( - std::mdspan(data, construct_mapping(Layout(), std::extents(1))), std::array{IntConfig(0)})); + std::mdspan(data, construct_mapping(Layout(), std::extents(1))), + std::array{IntConfig(0)})); static_assert(check_operator_constraints( - std::mdspan(data, construct_mapping(Layout(), std::extents(1))), std::array{IntConfig(0)})); + std::mdspan(data, construct_mapping(Layout(), std::extents(1))), + std::array{IntConfig(0)})); static_assert(check_operator_constraints( - std::mdspan(data, construct_mapping(Layout(), std::extents(1))), std::array{IntConfig(0)})); + std::mdspan(data, construct_mapping(Layout(), std::extents(1))), + std::array{IntConfig(0)})); { std::array idx{IntConfig(0)}; std::span s(idx); - assert(!check_operator_constraints(std::mdspan(data, construct_mapping(Layout(), std::extents(1))), s)); + assert(!check_operator_constraints( + std::mdspan(data, + construct_mapping(Layout(), std::extents(1))), + s)); } { std::array idx{IntConfig(0)}; std::span s(idx); - assert(!check_operator_constraints(std::mdspan(data, construct_mapping(Layout(), std::extents(1))), s)); + assert(!check_operator_constraints( + std::mdspan(data, + construct_mapping(Layout(), std::extents(1))), + s)); } { std::array idx{IntConfig(0)}; std::span s(idx); - assert(!check_operator_constraints(std::mdspan(data, construct_mapping(Layout(), std::extents(1))), s)); + assert(!check_operator_constraints( + std::mdspan(data, + construct_mapping(Layout(), std::extents(1))), + s)); } { std::array idx{IntConfig(0)}; std::span s(idx); - assert(!check_operator_constraints(std::mdspan(data, construct_mapping(Layout(), std::extents(1))), s)); + assert(!check_operator_constraints( + std::mdspan(data, + construct_mapping(Layout(), std::extents(1))), + s)); } { std::array idx{IntConfig(0)}; std::span s(idx); - assert(!check_operator_constraints(std::mdspan(data, construct_mapping(Layout(), std::extents(1))), s)); + assert(!check_operator_constraints( + std::mdspan(data, + construct_mapping(Layout(), std::extents(1))), + s)); } { std::array idx{IntConfig(0)}; std::span s(idx); - assert(!check_operator_constraints(std::mdspan(data, construct_mapping(Layout(), std::extents(1))), s)); + assert(!check_operator_constraints( + std::mdspan(data, + construct_mapping(Layout(), std::extents(1))), + s)); } } #endif @@ -225,12 +273,15 @@ constexpr void test_layout() { template constexpr void test_layout_large() { constexpr size_t D = std::dynamic_extent; - test_iteration(construct_mapping(Layout(), std::extents(3, 5, 6))); - test_iteration(construct_mapping(Layout(), std::extents(3, 6))); + test_iteration( + construct_mapping(Layout(), std::extents(3, 5, 6))); + test_iteration( + construct_mapping(Layout(), std::extents(3, 6))); } // mdspan::operator[] casts to index_type before calling mapping -// mapping requirements only require the index operator to mixed integer types not anything convertible to index_type +// mapping requirements only require the index operator to mixed integer types +// not anything convertible to index_type constexpr void test_index_cast_happens() {} constexpr bool test() { @@ -258,8 +309,8 @@ int main(int, char**) { return 0; } -#endif // MDSPAN_USE_BRACKET_OPERATOR +#endif // MDSPAN_USE_BRACKET_OPERATOR #if defined(__GNUC__) && !defined(__clang_major__) -# pragma GCC diagnostic pop +#pragma GCC diagnostic pop #endif diff --git a/tests/libcxx-backports/mdspan/mdspan.mapping.verify.cpp b/tests/libcxx-backports/mdspan/mdspan.mapping.verify.cpp index 581add96..6c7a42d5 100644 --- a/tests/libcxx-backports/mdspan/mdspan.mapping.verify.cpp +++ b/tests/libcxx-backports/mdspan/mdspan.mapping.verify.cpp @@ -9,15 +9,21 @@ // -// template -// class mdspan; +// template class mdspan; // // Mandates: -// - LayoutPolicy shall meet the layout mapping policy requirements ([mdspan.layout.policy.reqmts]) +// - LayoutPolicy shall meet the layout mapping policy requirements +// ([mdspan.layout.policy.reqmts]) #include void not_layout_policy() { - // expected-error-re@*:* {{static assertion failed {{.*}}mdspan: LayoutPolicy template parameter is invalid. A common mistake is to pass a layout mapping instead of a layout policy}} - [[maybe_unused]] std::mdspan, std::layout_left::template mapping>> m; + // expected-error-re@*:* {{static assertion failed {{.*}}mdspan: LayoutPolicy + // template parameter is invalid. A common mistake is to pass a layout mapping + // instead of a layout policy}} + [[maybe_unused]] std::mdspan< + int, std::extents, + std::layout_left::template mapping>> + m; } diff --git a/tests/libcxx-backports/mdspan/mdspan.move.pass.cpp b/tests/libcxx-backports/mdspan/mdspan.move.pass.cpp index 0bc4be36..d0578443 100644 --- a/tests/libcxx-backports/mdspan/mdspan.move.pass.cpp +++ b/tests/libcxx-backports/mdspan/mdspan.move.pass.cpp @@ -11,7 +11,8 @@ // constexpr mdspan& operator=(mdspan&&) = default; // -// A specialization of mdspan is a trivially copyable type if its accessor_type, mapping_type, and data_handle_type are trivially copyable types. +// A specialization of mdspan is a trivially copyable type if its accessor_type, +// mapping_type, and data_handle_type are trivially copyable types. #include #include @@ -26,45 +27,58 @@ template constexpr void test_mdspan_types(const H& handle, const M& map, const A& acc) { - using MDS = std::mdspan; + using MDS = std::mdspan; MDS m_org(handle, map, acc); MDS m_copy(m_org); MDS m(std::move(m_copy)); assert(m.extents() == map.extents()); - if constexpr (std::equality_comparable) - assert(m.data_handle() == handle); - if constexpr (std::equality_comparable) - assert(m.mapping() == map); - if constexpr (std::equality_comparable) - assert(m.accessor() == acc); + if constexpr (std::equality_comparable) assert(m.data_handle() == handle); + if constexpr (std::equality_comparable) assert(m.mapping() == map); + if constexpr (std::equality_comparable) assert(m.accessor() == acc); static_assert(std::is_trivially_move_assignable_v == - (std::is_trivially_move_assignable_v && std::is_trivially_move_assignable_v && + (std::is_trivially_move_assignable_v && + std::is_trivially_move_assignable_v && std::is_trivially_move_assignable_v)); } template constexpr void mixin_extents(const H& handle, const L& layout, const A& acc) { constexpr size_t D = std::dynamic_extent; - test_mdspan_types(handle, construct_mapping(layout, std::extents()), acc); - test_mdspan_types(handle, construct_mapping(layout, std::extents(7)), acc); - test_mdspan_types(handle, construct_mapping(layout, std::extents()), acc); - test_mdspan_types(handle, construct_mapping(layout, std::extents(2, 3)), acc); - test_mdspan_types(handle, construct_mapping(layout, std::extents(0, 3)), acc); - test_mdspan_types(handle, construct_mapping(layout, std::extents(1, 2, 3, 2)), acc); + test_mdspan_types(handle, construct_mapping(layout, std::extents()), + acc); + test_mdspan_types(handle, construct_mapping(layout, std::extents(7)), + acc); + test_mdspan_types( + handle, construct_mapping(layout, std::extents()), acc); + test_mdspan_types( + handle, construct_mapping(layout, std::extents(2, 3)), + acc); + test_mdspan_types( + handle, construct_mapping(layout, std::extents(0, 3)), + acc); + test_mdspan_types( + handle, + construct_mapping(layout, + std::extents(1, 2, 3, 2)), + acc); } template constexpr void mixin_layout(const H& handle, const A& acc) { // make sure we test a trivially copyable mapping - static_assert(std::is_trivially_move_assignable_v>>); + static_assert( + std::is_trivially_move_assignable_v< + typename std::layout_left::template mapping>>); mixin_extents(handle, std::layout_left(), acc); mixin_extents(handle, std::layout_right(), acc); // make sure we test a not trivially copyable mapping static_assert( - !std::is_trivially_move_assignable_v::template mapping>>); + !std::is_trivially_move_assignable_v::template mapping>>); mixin_extents(handle, layout_wrapping_integral<4>(), acc); } @@ -73,15 +87,18 @@ constexpr void mixin_accessor() { ElementPool elements; // make sure we test trivially constructible accessor and data_handle static_assert(std::is_trivially_copyable_v>); - static_assert(std::is_trivially_copyable_v::data_handle_type>); + static_assert(std::is_trivially_copyable_v< + typename std::default_accessor::data_handle_type>); mixin_layout(elements.get_ptr(), std::default_accessor()); // Using weird accessor/data_handle // Make sure they actually got the properties we want to test // checked_accessor is noexcept copy constructible except for const double checked_accessor acc(1024); - static_assert(noexcept(checked_accessor(acc)) != std::is_same_v); - mixin_layout(typename checked_accessor::data_handle_type(elements.get_ptr()), acc); + static_assert(noexcept(checked_accessor(acc)) != + std::is_same_v); + mixin_layout( + typename checked_accessor::data_handle_type(elements.get_ptr()), acc); } constexpr bool test() { diff --git a/tests/libcxx-backports/mdspan/mdspan.properties.pass.cpp b/tests/libcxx-backports/mdspan/mdspan.properties.pass.cpp index dab43a13..2a69abce 100644 --- a/tests/libcxx-backports/mdspan/mdspan.properties.pass.cpp +++ b/tests/libcxx-backports/mdspan/mdspan.properties.pass.cpp @@ -13,21 +13,23 @@ // class AccessorPolicy = default_accessor> // class mdspan { // public: -// static constexpr rank_type rank() noexcept { return extents_type::rank(); } -// static constexpr rank_type rank_dynamic() noexcept { return extents_type::rank_dynamic(); } -// static constexpr size_t static_extent(rank_type r) noexcept +// static constexpr rank_type rank() noexcept { return extents_type::rank(); +// } static constexpr rank_type rank_dynamic() noexcept { return +// extents_type::rank_dynamic(); } static constexpr size_t +// static_extent(rank_type r) noexcept // { return extents_type::static_extent(r); } -// constexpr index_type extent(rank_type r) const noexcept { return extents().extent(r); } +// constexpr index_type extent(rank_type r) const noexcept { return +// extents().extent(r); } // // constexpr size_type size() const noexcept; // [[nodiscard]] constexpr bool empty() const noexcept; // // -// constexpr const extents_type& extents() const noexcept { return map_.extents(); } -// constexpr const data_handle_type& data_handle() const noexcept { return ptr_; } -// constexpr const mapping_type& mapping() const noexcept { return map_; } -// constexpr const accessor_type& accessor() const noexcept { return acc_; } -// static constexpr bool is_always_unique() +// constexpr const extents_type& extents() const noexcept { return +// map_.extents(); } constexpr const data_handle_type& data_handle() const +// noexcept { return ptr_; } constexpr const mapping_type& mapping() const +// noexcept { return map_; } constexpr const accessor_type& accessor() const +// noexcept { return acc_; } static constexpr bool is_always_unique() // { return mapping_type::is_always_unique(); } // static constexpr bool is_always_exhaustive() // { return mapping_type::is_always_exhaustive(); } @@ -48,7 +50,8 @@ // - is_nothrow_move_constructible_v is true, // - is_nothrow_move_assignable_v is true, and // - is_nothrow_swappable_v is true. -// A specialization of mdspan is a trivially copyable type if its accessor_type, mapping_type, and data_handle_type are trivially copyable types. +// A specialization of mdspan is a trivially copyable type if its accessor_type, +// mapping_type, and data_handle_type are trivially copyable types. #include #include @@ -62,7 +65,8 @@ template constexpr void test_mdspan_types(const H& handle, const M& map, const A& acc) { - using MDS = std::mdspan; + using MDS = std::mdspan; MDS m(handle, map, acc); // ===================================== @@ -177,12 +181,14 @@ constexpr void test_mdspan_types(const H& handle, const M& map, const A& acc) { template constexpr void mixin_extents(const H& handle, const L& layout, const A& acc) { constexpr size_t D = std::dynamic_extent; + // clang-format off test_mdspan_types(handle, construct_mapping(layout, std::extents()), acc); test_mdspan_types(handle, construct_mapping(layout, std::extents(7)), acc); test_mdspan_types(handle, construct_mapping(layout, std::extents()), acc); test_mdspan_types(handle, construct_mapping(layout, std::extents(2, 3)), acc); test_mdspan_types(handle, construct_mapping(layout, std::extents(0, 3)), acc); test_mdspan_types(handle, construct_mapping(layout, std::extents(1, 2, 3, 2)), acc); + // clang-format on } template diff --git a/tests/libcxx-backports/mdspan/mdspan.swap.pass.cpp b/tests/libcxx-backports/mdspan/mdspan.swap.pass.cpp index 079fb9ef..43fe5018 100644 --- a/tests/libcxx-backports/mdspan/mdspan.swap.pass.cpp +++ b/tests/libcxx-backports/mdspan/mdspan.swap.pass.cpp @@ -41,15 +41,16 @@ constexpr void test_swap(MDS a, MDS b) { assert(a.data_handle() == org_b.data_handle()); assert(b.data_handle() == org_a.data_handle()); } - // This check uses a side effect of layout_wrapping_integral::swap to make sure - // mdspan calls the underlying components' swap via ADL - #if MDSPAN_HAS_CXX23 +// This check uses a side effect of layout_wrapping_integral::swap to make sure +// mdspan calls the underlying components' swap via ADL +#if MDSPAN_HAS_CXX23 if !consteval { - if constexpr (std::is_same_v>) { + if constexpr (std::is_same_v>) { assert(MDS::mapping_type::swap_counter() > 0); } } - #endif +#endif } constexpr bool test() { @@ -62,7 +63,8 @@ constexpr bool test() { test_swap(a, b); } { - layout_wrapping_integral<4>::template mapping map_a(extents_t(12), not_extents_constructible_tag()), + layout_wrapping_integral<4>::template mapping map_a( + extents_t(12), not_extents_constructible_tag()), map_b(extents_t(5), not_extents_constructible_tag()); std::mdspan a(data_a, map_a); std::mdspan b(data_b, map_b); diff --git a/tests/libcxx-backports/mdspan/mdspan.types.pass.cpp b/tests/libcxx-backports/mdspan/mdspan.types.pass.cpp index f4cea447..1c3d130d 100644 --- a/tests/libcxx-backports/mdspan/mdspan.types.pass.cpp +++ b/tests/libcxx-backports/mdspan/mdspan.types.pass.cpp @@ -9,7 +9,8 @@ // // -// template> // class mdspan { // public: @@ -40,29 +41,33 @@ // Calculated expected size of an mdspan // Note this expectes that only default_accessor is empty -template +template constexpr size_t expected_size() { size_t sizeof_dht = sizeof(typename MDS::data_handle_type); - size_t result = sizeof_dht; - if(MDS::rank_dynamic() > 0) { + size_t result = sizeof_dht; + if (MDS::rank_dynamic() > 0) { size_t alignof_idx = alignof(typename MDS::index_type); - size_t sizeof_idx = sizeof(typename MDS::index_type); + size_t sizeof_idx = sizeof(typename MDS::index_type); // add alignment if necessary - result += sizeof_dht%alignof_idx == 0?0:alignof_idx - (sizeof_dht%alignof_idx); + result += sizeof_dht % alignof_idx == 0 + ? 0 + : alignof_idx - (sizeof_dht % alignof_idx); // add sizeof stored extents result += MDS::rank_dynamic() * sizeof_idx; } using A = typename MDS::accessor_type; - if(!std::is_same_v>) { + if (!std::is_same_v>) { size_t alignof_acc = alignof(A); - size_t sizeof_acc = sizeof(A); + size_t sizeof_acc = sizeof(A); // add alignment if necessary - result += result%alignof_acc == 0?0:alignof_acc - (result%alignof_acc); + result += + result % alignof_acc == 0 ? 0 : alignof_acc - (result % alignof_acc); // add sizeof stored accessor result += sizeof_acc; } // add alignment of the mdspan itself - result += result%alignof(MDS) == 0?0:alignof(MDS) - (result%alignof(MDS)); + result += + result % alignof(MDS) == 0 ? 0 : alignof(MDS) - (result % alignof(MDS)); return result; } @@ -80,7 +85,8 @@ constexpr bool trv_cp_asgn = std::is_trivially_copy_assignable_v; template constexpr bool trv_mv_asgn = std::is_trivially_move_assignable_v; -template +template void check_triviality() { static_assert(trv_df_ctor == default_ctor); static_assert(trv_cp_ctor == copy_ctor); @@ -103,28 +109,33 @@ void test_mdspan_types() { ASSERT_SAME_TYPE(typename MDS::index_type, typename E::index_type); ASSERT_SAME_TYPE(typename MDS::size_type, typename E::size_type); ASSERT_SAME_TYPE(typename MDS::rank_type, typename E::rank_type); - ASSERT_SAME_TYPE(typename MDS::data_handle_type, typename A::data_handle_type); + ASSERT_SAME_TYPE(typename MDS::data_handle_type, + typename A::data_handle_type); ASSERT_SAME_TYPE(typename MDS::reference, typename A::reference); // This miserably failed with clang-cl - likely because it doesn't honor/enable // no-unique-address fully by default #ifndef _WIN32 // check the size of mdspan - if constexpr (std::is_same_v || std::is_same_v) { + if constexpr (std::is_same_v || + std::is_same_v) { LIBCPP_STATIC_ASSERT(sizeof(MDS) == expected_size()); } #endif // check default template parameters: - ASSERT_SAME_TYPE(std::mdspan, std::mdspan>); - ASSERT_SAME_TYPE(std::mdspan, std::mdspan>); + ASSERT_SAME_TYPE( + std::mdspan, + std::mdspan>); + ASSERT_SAME_TYPE(std::mdspan, + std::mdspan>); // check triviality using DH = typename MDS::data_handle_type; using MP = typename MDS::mapping_type; check_triviality && trv_cp_ctor && trv_cp_ctor, trv_mv_ctor && trv_mv_ctor && trv_mv_ctor, trv_dstruct && trv_dstruct && trv_dstruct, @@ -167,14 +178,10 @@ int main(int, char**) { mixin_accessor(); // sanity checks for triviality + // clang-format off check_triviality>, false, true, true, true, true, true>(); check_triviality>, false, true, true, true, true, true>(); - check_triviality, std::layout_right, checked_accessor>, - false, - true, - false, - true, - true, - true>(); + check_triviality, std::layout_right, checked_accessor>, false, true, false, true, true, true>(); + // clang-format on return 0; } diff --git a/tests/offload_utils.hpp b/tests/offload_utils.hpp index c1aa988b..7829b6e0 100644 --- a/tests/offload_utils.hpp +++ b/tests/offload_utils.hpp @@ -10,158 +10,160 @@ #include #endif -#include +#include namespace { bool dispatch_host = true; #ifdef MDSPAN_IMPL_HAS_SYCL -#define MDSPAN_IMPL_DEVICE_ASSERT_EQ(LHS, RHS) \ -if (!(LHS == RHS)) { \ - sycl::ext::oneapi::experimental::printf("expected equality of %s and %s\n", #LHS, #RHS); \ - errors[0]++; \ -} +#define MDSPAN_IMPL_DEVICE_ASSERT_EQ(LHS, RHS) \ + if (!(LHS == RHS)) { \ + sycl::ext::oneapi::experimental::printf( \ + "expected equality of %s and %s\n", #LHS, #RHS); \ + errors[0]++; \ + } #else - #define MDSPAN_IMPL_DEVICE_ASSERT_EQ(LHS, RHS) \ - if (!(LHS == RHS)) { \ - printf("expected equality of %s and %s\n", #LHS, #RHS); \ - errors[0]++; \ -} +#define MDSPAN_IMPL_DEVICE_ASSERT_EQ(LHS, RHS) \ + if (!(LHS == RHS)) { \ + printf("expected equality of %s and %s\n", #LHS, #RHS); \ + errors[0]++; \ + } #endif #if defined(MDSPAN_IMPL_HAS_CUDA) || defined(MDSPAN_IMPL_HAS_HIP) #if defined(MDSPAN_IMPL_HAS_CUDA) -void deviceSynchronize() { (void) cudaDeviceSynchronize(); } -template -void mallocManaged(T** ptr, size_t size) { (void) cudaMallocManaged(ptr, size); } -template -void freeManaged(T* ptr) { (void) cudaFree(ptr); } +void deviceSynchronize() { (void)cudaDeviceSynchronize(); } +template +void mallocManaged(T** ptr, size_t size) { + (void)cudaMallocManaged(ptr, size); +} +template +void freeManaged(T* ptr) { + (void)cudaFree(ptr); +} #endif #if defined(MDSPAN_IMPL_HAS_HIP) -void deviceSynchronize() { (void) hipDeviceSynchronize(); } -template -void mallocManaged(T** ptr, size_t size) { (void) hipMallocManaged(ptr, size); } -template -void freeManaged(T* ptr) { (void) hipFree(ptr); } +void deviceSynchronize() { (void)hipDeviceSynchronize(); } +template +void mallocManaged(T** ptr, size_t size) { + (void)hipMallocManaged(ptr, size); +} +template +void freeManaged(T* ptr) { + (void)hipFree(ptr); +} #endif -template +template __global__ void dispatch_kernel(const LAMBDA f) { f(); } -template +template void dispatch(LAMBDA&& f) { - if(dispatch_host) { + if (dispatch_host) { static_cast(f)(); } else { - dispatch_kernel<<<1,1>>>(static_cast(f)); + dispatch_kernel<<<1, 1>>>(static_cast(f)); deviceSynchronize(); } } -template +template T* allocate_array(size_t size) { T* ptr = nullptr; - if(dispatch_host == true) + if (dispatch_host == true) ptr = new T[size]; else - mallocManaged(&ptr, sizeof(T)*size); + mallocManaged(&ptr, sizeof(T) * size); return ptr; } -template +template void free_array(T* ptr) { - if(dispatch_host == true) - delete [] ptr; + if (dispatch_host == true) + delete[] ptr; else freeManaged(ptr); } #define MDSPAN_IMPL_TESTS_RUN_TEST(A) \ - dispatch_host = true; \ - A; \ - dispatch_host = false; \ - A; + dispatch_host = true; \ + A; \ + dispatch_host = false; \ + A; #define MDSPAN_IMPL_TESTS_DISPATCH_DEFINED -#endif // MDSPAN_IMPL_HAS_CUDA +#endif // MDSPAN_IMPL_HAS_CUDA #ifdef MDSPAN_IMPL_HAS_SYCL -sycl::queue get_test_queue() -{ +sycl::queue get_test_queue() { static sycl::queue q; return q; } -template +template void dispatch(LAMBDA&& f) { - if(dispatch_host) { + if (dispatch_host) { static_cast(f)(); } else { sycl::queue q = get_test_queue(); - q.submit([&](sycl::handler &cgh) { - cgh.single_task([=]() { - f(); - }); - }); + q.submit([&](sycl::handler& cgh) { cgh.single_task([=]() { f(); }); }); q.wait_and_throw(); } } -template +template T* allocate_array(size_t size) { - if(dispatch_host == true) + if (dispatch_host == true) return new T[size]; - else - { + else { sycl::queue q = get_test_queue(); return sycl::malloc_shared(size, q); } } -template +template void free_array(T* ptr) { - if(dispatch_host == true) - delete [] ptr; - else - { + if (dispatch_host == true) + delete[] ptr; + else { sycl::queue q = get_test_queue(); sycl::free(ptr, q); } } #define MDSPAN_IMPL_TESTS_RUN_TEST(A) \ - dispatch_host = true; \ - A; \ - dispatch_host = false; \ - A; + dispatch_host = true; \ + A; \ + dispatch_host = false; \ + A; #define MDSPAN_IMPL_TESTS_DISPATCH_DEFINED -#endif // MDSPAN_IMPL_HAS_SYCL +#endif // MDSPAN_IMPL_HAS_SYCL #ifndef MDSPAN_IMPL_TESTS_DISPATCH_DEFINED -template +template void dispatch(LAMBDA&& f) { static_cast(f)(); } -template +template T* allocate_array(size_t size) { T* ptr = nullptr; - ptr = new T[size]; + ptr = new T[size]; return ptr; } -template +template void free_array(T* ptr) { - delete [] ptr; + delete[] ptr; } #define MDSPAN_IMPL_TESTS_RUN_TEST(A) \ - dispatch_host = true; \ - A; + dispatch_host = true; \ + A; #endif -} // namespace +} // namespace diff --git a/tests/test_alternate_precondition_violation_handler.cpp b/tests/test_alternate_precondition_violation_handler.cpp index d7b9d7ed..7d0ea078 100644 --- a/tests/test_alternate_precondition_violation_handler.cpp +++ b/tests/test_alternate_precondition_violation_handler.cpp @@ -4,24 +4,20 @@ #include #define MDSPAN_IMPL_PRECONDITION_VIOLATION_HANDLER(cond, file, line) \ - do { \ - throw std::logic_error{"precondition failure"}; \ + do { \ + throw std::logic_error{"precondition failure"}; \ } while (0); #include #include -TEST(mdspan_macros, alternate_precondition_violation_handler) -{ +TEST(mdspan_macros, alternate_precondition_violation_handler) { ASSERT_THROW(MDSPAN_IMPL_PRECONDITION(false), std::logic_error); } -TEST(mdspan_macros, alternate_precondition_check_constexpr_invocable) -{ - struct fn - { - constexpr auto operator()() const - { +TEST(mdspan_macros, alternate_precondition_check_constexpr_invocable) { + struct fn { + constexpr auto operator()() const { MDSPAN_IMPL_PRECONDITION(1 + 1 == 2); return 42; } diff --git a/tests/test_canonicalize_slices.cpp b/tests/test_canonicalize_slices.cpp index fc20e7ae..0ca80378 100644 --- a/tests/test_canonicalize_slices.cpp +++ b/tests/test_canonicalize_slices.cpp @@ -10,79 +10,74 @@ namespace my_test { // Aggregate pair type (supports structured binding natively as aggregate) -template +template struct my_aggregate_pair { First first; Second second; }; // Non-aggregate pair type (uses the tuple protocol) -template +template class my_nonaggregate_pair { -public: + public: constexpr my_nonaggregate_pair(First first, Second second) - : first_(first), second_(second) - {} + : first_(first), second_(second) {} - template + template constexpr auto get() -> std::conditional_t { if constexpr (Index == 0) { return first_; - } - else { + } else { static_assert(Index == 1); return second_; } } - template + template constexpr auto get() const -> std::conditional_t { if constexpr (Index == 0) { return first_; - } - else { + } else { static_assert(Index == 1); return second_; } } -private: + private: First first_; Second second_; }; -} // namespace my_test +} // namespace my_test -template +template struct std::tuple_size> - : std::integral_constant {}; + : std::integral_constant {}; -template +template struct std::tuple_element> { static_assert(Index == 0 || Index == 1, "Index out of range"); }; -template +template struct std::tuple_element<0, my_test::my_nonaggregate_pair> { using type = First; }; -template +template struct std::tuple_element<1, my_test::my_nonaggregate_pair> { using type = Second; }; -template +template constexpr auto get(my_test::my_nonaggregate_pair& p) - -> std::conditional_t -{ + -> std::conditional_t { return p.template get(); } -template +template constexpr auto get(const my_test::my_nonaggregate_pair& p) - -> std::conditional_t -{ + -> std::conditional_t { return p.template get(); } @@ -93,36 +88,32 @@ namespace { // ============================================================ // full_extent_t lacks operator==; two full_extent_t values are always equal -constexpr bool slice_equal( - MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent_t, - MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent_t) -{ +constexpr bool slice_equal(MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent_t, + MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent_t) { return true; } -template +template constexpr bool slice_equal( - const MDSPAN_IMPL_STANDARD_NAMESPACE::extent_slice& left, - const MDSPAN_IMPL_STANDARD_NAMESPACE::extent_slice& right) -{ - return left.offset == right.offset && - left.extent == right.extent && + const MDSPAN_IMPL_STANDARD_NAMESPACE::extent_slice& left, + const MDSPAN_IMPL_STANDARD_NAMESPACE::extent_slice& right) { + return left.offset == right.offset && left.extent == right.extent && left.stride == right.stride; } // Integer (index) slices: compare by value -template, int> = 0> +template , int> = 0> constexpr bool slice_equal(T left, T right) { return left == right; } // Integral-constant-like slices: compare their values -template && - MDSPAN_IMPL_STANDARD_NAMESPACE::detail::is_integral_constant_like_v, - int> = 0> +template && + MDSPAN_IMPL_STANDARD_NAMESPACE::detail:: + is_integral_constant_like_v, + int> = 0> constexpr bool slice_equal(T, U) { return T::value == U::value; } @@ -131,41 +122,36 @@ constexpr bool slice_equal(T, U) { // Test helpers: compare the k-th element of result vs expected // ============================================================ -template -void test_canonicalize_slices_impl_one( - std::integral_constant, - const Result& result, - const ExpectedResult& expected_result) -{ +template +void test_canonicalize_slices_impl_one(std::integral_constant, + const Result& result, + const ExpectedResult& expected_result) { // Use ADL to find the right get<>() for each tuple type using MDSPAN_IMPL_STANDARD_NAMESPACE::detail::get; using std::get; - auto left = get(result); - auto right = get(expected_result); + auto left = get(result); + auto right = get(expected_result); const bool outcome = slice_equal(left, right); ASSERT_TRUE(outcome) << " failed for k=" << Index; } -template -void test_canonicalize_slices_impl( - std::index_sequence, - const Result& result, - const ExpectedResult& expected_result) -{ - (test_canonicalize_slices_impl_one( - std::integral_constant{}, result, expected_result), ...); +template +void test_canonicalize_slices_impl(std::index_sequence, + const Result& result, + const ExpectedResult& expected_result) { + (test_canonicalize_slices_impl_one(std::integral_constant{}, + result, expected_result), + ...); } -template -void test_canonicalize_slices( - const ExpectedResult& expected_result, - const InputExtents& input_extents, - Slices... slices) -{ - auto result = MDSPAN_IMPL_STANDARD_NAMESPACE::canonical_slices( - input_extents, slices...); - test_canonicalize_slices_impl( - std::make_index_sequence(), result, expected_result); +template +void test_canonicalize_slices(const ExpectedResult& expected_result, + const InputExtents& input_extents, + Slices... slices) { + auto result = MDSPAN_IMPL_STANDARD_NAMESPACE::canonical_slices(input_extents, + slices...); + test_canonicalize_slices_impl(std::make_index_sequence(), + result, expected_result); } // ============================================================ @@ -174,27 +160,31 @@ void test_canonicalize_slices( TEST(CanonicalizeSlices, Rank0) { using MDSPAN_IMPL_STANDARD_NAMESPACE::detail::tuple; - test_canonicalize_slices(tuple{}, MDSPAN_IMPL_STANDARD_NAMESPACE::extents{}); - test_canonicalize_slices(tuple{}, MDSPAN_IMPL_STANDARD_NAMESPACE::extents{}); + test_canonicalize_slices(tuple{}, + MDSPAN_IMPL_STANDARD_NAMESPACE::extents{}); + test_canonicalize_slices(tuple{}, + MDSPAN_IMPL_STANDARD_NAMESPACE::extents{}); } TEST(CanonicalizeSlices, Rank1_full) { using MDSPAN_IMPL_STANDARD_NAMESPACE::detail::tuple; - constexpr auto full = MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent; + constexpr auto full = MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent; const auto expected_result = tuple{full}; test_canonicalize_slices(expected_result, - MDSPAN_IMPL_STANDARD_NAMESPACE::extents{}, full); - test_canonicalize_slices(expected_result, - MDSPAN_IMPL_STANDARD_NAMESPACE::extents{}, - full); + MDSPAN_IMPL_STANDARD_NAMESPACE::extents{}, + full); + test_canonicalize_slices( + expected_result, + MDSPAN_IMPL_STANDARD_NAMESPACE::extents< + size_t, MDSPAN_IMPL_STANDARD_NAMESPACE::dynamic_extent>{}, + full); } TEST(CanonicalizeSlices, Rank1_integer_dynamic) { using MDSPAN_IMPL_STANDARD_NAMESPACE::detail::cw; using MDSPAN_IMPL_STANDARD_NAMESPACE::detail::tuple; - constexpr auto slice0 = int(7); + constexpr auto slice0 = int(7); constexpr auto expected_slices = tuple{size_t(7u)}; constexpr auto exts = MDSPAN_IMPL_STANDARD_NAMESPACE::extents{}; test_canonicalize_slices(expected_slices, exts, slice0); @@ -204,7 +194,7 @@ TEST(CanonicalizeSlices, Rank1_integer_static) { using MDSPAN_IMPL_STANDARD_NAMESPACE::detail::cw; using MDSPAN_IMPL_STANDARD_NAMESPACE::detail::tuple; - constexpr auto slice0 = std::integral_constant{}; + constexpr auto slice0 = std::integral_constant{}; constexpr auto expected_slices = tuple{cw}; constexpr auto exts = MDSPAN_IMPL_STANDARD_NAMESPACE::extents{}; test_canonicalize_slices(expected_slices, exts, slice0); @@ -218,14 +208,13 @@ TEST(CanonicalizeSlices, Rank1_pair) { constexpr auto slice0 = std::pair{std::integral_constant{}, 11}; constexpr auto offset = cw; - constexpr auto extent = size_t(4u); // 11 - 7 + constexpr auto extent = size_t(4u); // 11 - 7 constexpr auto stride = cw; - const auto expected_slices = tuple{ - MDSPAN_IMPL_STANDARD_NAMESPACE::extent_slice< - decltype(offset), decltype(extent), decltype(stride) - >{offset, extent, stride} - }; + const auto expected_slices = + tuple{MDSPAN_IMPL_STANDARD_NAMESPACE::extent_slice< + decltype(offset), decltype(extent), decltype(stride)>{offset, extent, + stride}}; constexpr auto exts = MDSPAN_IMPL_STANDARD_NAMESPACE::extents{}; test_canonicalize_slices(expected_slices, exts, slice0); } @@ -237,14 +226,13 @@ TEST(CanonicalizeSlices, Rank1_aggregate_pair) { constexpr auto slice0 = my_test::my_aggregate_pair{7, 11}; constexpr auto offset = size_t(7u); - constexpr auto extent = size_t(4u); // 11 - 7 + constexpr auto extent = size_t(4u); // 11 - 7 constexpr auto stride = cw; - const auto expected_slices = tuple{ - MDSPAN_IMPL_STANDARD_NAMESPACE::extent_slice< - decltype(offset), decltype(extent), decltype(stride) - >{offset, extent, stride} - }; + const auto expected_slices = + tuple{MDSPAN_IMPL_STANDARD_NAMESPACE::extent_slice< + decltype(offset), decltype(extent), decltype(stride)>{offset, extent, + stride}}; constexpr auto exts = MDSPAN_IMPL_STANDARD_NAMESPACE::extents{}; test_canonicalize_slices(expected_slices, exts, slice0); } @@ -256,24 +244,24 @@ TEST(CanonicalizeSlices, Rank1_nonaggregate_pair) { auto slice0 = my_test::my_nonaggregate_pair(7, 11); constexpr auto offset = size_t(7u); - constexpr auto extent = size_t(4u); // 11 - 7 + constexpr auto extent = size_t(4u); // 11 - 7 constexpr auto stride = cw; - const auto expected_slices = tuple{ - MDSPAN_IMPL_STANDARD_NAMESPACE::extent_slice< - decltype(offset), decltype(extent), decltype(stride) - >{offset, extent, stride} - }; + const auto expected_slices = + tuple{MDSPAN_IMPL_STANDARD_NAMESPACE::extent_slice< + decltype(offset), decltype(extent), decltype(stride)>{offset, extent, + stride}}; constexpr auto exts = MDSPAN_IMPL_STANDARD_NAMESPACE::extents{}; test_canonicalize_slices(expected_slices, exts, slice0); } TEST(CanonicalizeSlices, Rank2_full) { using MDSPAN_IMPL_STANDARD_NAMESPACE::detail::tuple; - constexpr auto full = MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent; + constexpr auto full = MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent; const auto expected_result = tuple{full, full}; - test_canonicalize_slices(expected_result, - MDSPAN_IMPL_STANDARD_NAMESPACE::extents{}, full, full); + test_canonicalize_slices( + expected_result, MDSPAN_IMPL_STANDARD_NAMESPACE::extents{}, + full, full); } TEST(CanonicalizeSlices, Rank1_extent_slice_dynamic) { @@ -281,17 +269,15 @@ TEST(CanonicalizeSlices, Rank1_extent_slice_dynamic) { using MDSPAN_IMPL_STANDARD_NAMESPACE::detail::tuple; // extent_slice with all dynamic values - const auto slice0 = MDSPAN_IMPL_STANDARD_NAMESPACE::extent_slice{ - /* .offset = */ 1, - /* .extent = */ 4, - /* .stride = */ 2 - }; + const auto slice0 = + MDSPAN_IMPL_STANDARD_NAMESPACE::extent_slice{ + /* .offset = */ 1, + /* .extent = */ 4, + /* .stride = */ 2}; const auto expected_slices = tuple{ - MDSPAN_IMPL_STANDARD_NAMESPACE::extent_slice{ - size_t(1), size_t(4), size_t(2) - } - }; + MDSPAN_IMPL_STANDARD_NAMESPACE::extent_slice{ + size_t(1), size_t(4), size_t(2)}}; const auto exts = MDSPAN_IMPL_STANDARD_NAMESPACE::extents{}; test_canonicalize_slices(expected_slices, exts, slice0); } @@ -301,17 +287,15 @@ TEST(CanonicalizeSlices, Rank1_range_slice_dynamic) { using MDSPAN_IMPL_STANDARD_NAMESPACE::detail::tuple; // range_slice with all dynamic values - const auto slice0 = MDSPAN_IMPL_STANDARD_NAMESPACE::range_slice{ - /* .first = */ 1, - /* .last = */ 11, - /* .stride = */ 3 - }; + const auto slice0 = + MDSPAN_IMPL_STANDARD_NAMESPACE::range_slice{ + /* .first = */ 1, + /* .last = */ 11, + /* .stride = */ 3}; const auto expected_slices = tuple{ - MDSPAN_IMPL_STANDARD_NAMESPACE::extent_slice{ - size_t(1), size_t(4), size_t(3) - } - }; + MDSPAN_IMPL_STANDARD_NAMESPACE::extent_slice{ + size_t(1), size_t(4), size_t(3)}}; const auto exts = MDSPAN_IMPL_STANDARD_NAMESPACE::extents{}; test_canonicalize_slices(expected_slices, exts, slice0); } @@ -324,15 +308,14 @@ TEST(CanonicalizeSlices, Rank1_extent_slice_static) { using extent_t = std::integral_constant; using stride_t = std::integral_constant; const auto slice0 = - MDSPAN_IMPL_STANDARD_NAMESPACE::extent_slice{}; + MDSPAN_IMPL_STANDARD_NAMESPACE::extent_slice{}; const auto expected_slices = tuple{ - MDSPAN_IMPL_STANDARD_NAMESPACE::extent_slice< - decltype(cw), - decltype(cw), - decltype(cw) - >{cw, cw, cw} - }; + MDSPAN_IMPL_STANDARD_NAMESPACE::extent_slice), + decltype(cw), + decltype(cw)>{ + cw, cw, cw}}; const auto exts = MDSPAN_IMPL_STANDARD_NAMESPACE::extents{}; test_canonicalize_slices(expected_slices, exts, slice0); } @@ -345,17 +328,16 @@ TEST(CanonicalizeSlices, Rank1_range_slice_static) { using extent_t = std::integral_constant; using stride_t = std::integral_constant; const auto slice0 = - MDSPAN_IMPL_STANDARD_NAMESPACE::range_slice{}; + MDSPAN_IMPL_STANDARD_NAMESPACE::range_slice{}; const auto expected_slices = tuple{ - MDSPAN_IMPL_STANDARD_NAMESPACE::extent_slice< - decltype(cw), - decltype(cw), - decltype(cw) - >{cw, cw, cw} - }; + MDSPAN_IMPL_STANDARD_NAMESPACE::extent_slice), + decltype(cw), + decltype(cw)>{ + cw, cw, cw}}; const auto exts = MDSPAN_IMPL_STANDARD_NAMESPACE::extents{}; test_canonicalize_slices(expected_slices, exts, slice0); } -} // namespace (anonymous) +} // namespace diff --git a/tests/test_constant_wrapper.cpp b/tests/test_constant_wrapper.cpp index 3f145f09..6c9f7c4e 100644 --- a/tests/test_constant_wrapper.cpp +++ b/tests/test_constant_wrapper.cpp @@ -6,30 +6,26 @@ #include "mdspan/impl/constant_wrapper.hpp" -namespace { // (anonymous) +namespace { // (anonymous) #if defined(__cpp_lib_constant_wrapper) -template +template using IC = std::integral_constant; -template +template constexpr void test_integral_constant_wrapper(IC ic) { - using MDSPAN_IMPL_STANDARD_NAMESPACE::detail::cw; using MDSPAN_IMPL_STANDARD_NAMESPACE::detail::constant_wrapper; + using MDSPAN_IMPL_STANDARD_NAMESPACE::detail::cw; constexpr auto c = cw; - static_assert(std::is_same_v< - std::remove_const_t)>, - constant_wrapper>); + static_assert(std::is_same_v)>, + constant_wrapper>); static_assert(decltype(c)::value == Value); - static_assert(std::is_same_v< - typename decltype(c)::type, - constant_wrapper>); - static_assert(std::is_same_v< - typename decltype(c)::value_type, - Integral>); + static_assert( + std::is_same_v>); + static_assert(std::is_same_v); constexpr auto c2 = cw; // Casting the arithmetic result back to Integral undoes @@ -59,49 +55,44 @@ TEST(TestConstantWrapper, Construction) { #endif TEST(TestConstantWrapper, IntegerPlus) { - using MDSPAN_IMPL_STANDARD_NAMESPACE::detail::cw; using MDSPAN_IMPL_STANDARD_NAMESPACE::detail::constant_wrapper; + using MDSPAN_IMPL_STANDARD_NAMESPACE::detail::cw; constant_wrapper cw_11; - constexpr size_t value = cw_11; + constexpr size_t value = cw_11; constexpr size_t value2 = constant_wrapper::value; static_assert(value == value2); constexpr size_t value3 = decltype(cw_11)(); static_assert(value == value3); #if defined(__cpp_lib_constant_wrapper) - static_assert(std::is_same_v< - decltype(cw_11), - std::remove_const_t)>>); + static_assert(std::is_same_v)>>); #endif [[maybe_unused]] auto expected_result = cw; - using expected_type = constant_wrapper; + using expected_type = constant_wrapper; static_assert(std::is_same_v); #if defined(__cpp_lib_constant_wrapper) [[maybe_unused]] auto cw_11_plus_one = cw_11 + cw; [[maybe_unused]] auto one_plus_cw_11 = cw + cw_11; - static_assert(! std::is_same_v< - decltype(cw_11 + cw), - size_t>); - static_assert(std::is_same_v< - decltype(cw_11 + cw), - constant_wrapper>); - static_assert(std::is_same_v< - decltype(cw + cw_11), - constant_wrapper>); + static_assert(!std::is_same_v), size_t>); + static_assert(std::is_same_v), + constant_wrapper>); + static_assert(std::is_same_v + cw_11), + constant_wrapper>); #endif } TEST(TestConstantWrapper, Arithmetic) { - using MDSPAN_IMPL_STANDARD_NAMESPACE::detail::cw; using MDSPAN_IMPL_STANDARD_NAMESPACE::detail::constant_wrapper; - using MDSPAN_IMPL_STANDARD_NAMESPACE::detail::increment; + using MDSPAN_IMPL_STANDARD_NAMESPACE::detail::cw; using MDSPAN_IMPL_STANDARD_NAMESPACE::detail::divide; - using MDSPAN_IMPL_STANDARD_NAMESPACE::detail::multiply; + using MDSPAN_IMPL_STANDARD_NAMESPACE::detail::increment; using MDSPAN_IMPL_STANDARD_NAMESPACE::detail::is_constant_wrapper; + using MDSPAN_IMPL_STANDARD_NAMESPACE::detail::multiply; constexpr auto c6 = cw; constexpr auto c3 = cw; @@ -128,4 +119,4 @@ TEST(TestConstantWrapper, Arithmetic) { static_assert(is_constant_wrapper); } -} // namespace (anonymous) +} // namespace diff --git a/tests/test_dims.cpp b/tests/test_dims.cpp index 21b220a8..11b8ac76 100644 --- a/tests/test_dims.cpp +++ b/tests/test_dims.cpp @@ -7,36 +7,36 @@ namespace test { -template +template static constexpr bool is_extents_v = false; -template +template static constexpr bool is_extents_v< - MDSPAN_IMPL_STANDARD_NAMESPACE :: extents -> = true; - -template -void test_dims_with_one_template_argument() -{ - using d = MDSPAN_IMPL_STANDARD_NAMESPACE :: dims; - static_assert(test::is_extents_v, "dims is not an extents specialization"); - static_assert(std::is_same::value, "dims::index_type is wrong"); + MDSPAN_IMPL_STANDARD_NAMESPACE ::extents > = true; + +template +void test_dims_with_one_template_argument() { + using d = MDSPAN_IMPL_STANDARD_NAMESPACE ::dims; + static_assert(test::is_extents_v, + "dims is not an extents specialization"); + static_assert(std::is_same::value, + "dims::index_type is wrong"); static_assert(d::rank() == Rank, "dims::rank() is wrong"); } -template -void test_dims_with_two_template_arguments() -{ - using d = MDSPAN_IMPL_STANDARD_NAMESPACE :: dims; - static_assert(test::is_extents_v, "dims is not an extents specialization"); - static_assert(std::is_same::value, "dims::index_type is wrong"); +template +void test_dims_with_two_template_arguments() { + using d = MDSPAN_IMPL_STANDARD_NAMESPACE ::dims; + static_assert(test::is_extents_v, + "dims is not an extents specialization"); + static_assert(std::is_same::value, + "dims::index_type is wrong"); static_assert(d::rank() == Rank, "dims::rank() is wrong"); } -} // namespace test +} // namespace test -TEST(TestDims, Test0) -{ +TEST(TestDims, Test0) { using test::test_dims_with_one_template_argument; using test::test_dims_with_two_template_arguments; diff --git a/tests/test_element_access.cpp b/tests/test_element_access.cpp index 7070950c..dc082a45 100644 --- a/tests/test_element_access.cpp +++ b/tests/test_element_access.cpp @@ -5,11 +5,10 @@ #include - TEST(TestElementAccess, element_access_with_std_array) { - std::array a{}; - Kokkos::mdspan> s(a.data()); - ASSERT_EQ(MDSPAN_IMPL_OP(s, (std::array{1, 2})), 0); - MDSPAN_IMPL_OP(s, (std::array{0, 1})) = 3.14; - ASSERT_EQ(MDSPAN_IMPL_OP(s, (std::array{0, 1})), 3.14); + std::array a{}; + Kokkos::mdspan> s(a.data()); + ASSERT_EQ(MDSPAN_IMPL_OP(s, (std::array{1, 2})), 0); + MDSPAN_IMPL_OP(s, (std::array{0, 1})) = 3.14; + ASSERT_EQ(MDSPAN_IMPL_OP(s, (std::array{0, 1})), 3.14); } diff --git a/tests/test_exhaustive_layouts.cpp b/tests/test_exhaustive_layouts.cpp index b44b0359..5b4cf4a3 100644 --- a/tests/test_exhaustive_layouts.cpp +++ b/tests/test_exhaustive_layouts.cpp @@ -12,42 +12,36 @@ MDSPAN_IMPL_INLINE_VARIABLE constexpr auto dyn = Kokkos::dynamic_extent; template size_t get_expected_mapping( - typename Kokkos::layout_left::template mapping const& map, - size_t i, size_t j, size_t k -) -{ + typename Kokkos::layout_left::template mapping const& map, + size_t i, size_t j, size_t k) { auto const& extents = map.extents(); - return i + j*extents.extent(0) + k*extents.extent(0)*extents.extent(1); + return i + j * extents.extent(0) + k * extents.extent(0) * extents.extent(1); } template size_t get_expected_mapping( - typename Kokkos::layout_right::template mapping const& map, - size_t i, size_t j, size_t k -) -{ + typename Kokkos::layout_right::template mapping const& map, + size_t i, size_t j, size_t k) { auto const& extents = map.extents(); - return k + j*extents.extent(2) + i*extents.extent(1)*extents.extent(2); + return k + j * extents.extent(2) + i * extents.extent(1) * extents.extent(2); } -template struct TestLayout; +template +struct TestLayout; template -struct TestLayout ->> : public ::testing::Test -{ +struct TestLayout< + std::tuple>> + : public ::testing::Test { Mapping map; void initialize_mapping() { - using extents_type = std::remove_cv_t>; + using extents_type = + std::remove_cv_t>; map = Mapping(extents_type(DynamicSizes...)); } - void SetUp() override { - initialize_mapping(); - } + void SetUp() override { initialize_mapping(); } template size_t expected_mapping(Index... idxs) const { @@ -56,263 +50,468 @@ struct TestLayout -using test_3d_left_types = std::tuple< - typename Kokkos::layout_left::template mapping, - std::integer_sequence ->; +using test_3d_left_types = + std::tuple, + std::integer_sequence>; template -using test_3d_right_types = std::tuple< - typename Kokkos::layout_right::template mapping, - std::integer_sequence ->; - -using layout_test_types_3d = - ::testing::Types< - test_3d_left_types>, - test_3d_left_types>, - test_3d_left_types, 5>, - test_3d_left_types, 3>, - test_3d_left_types, 4>, - test_3d_left_types, 4>, - test_3d_left_types, 3>, - test_3d_left_types, 5>, - test_3d_left_types, 3, 4>, - test_3d_left_types, 5, 4>, - test_3d_left_types, 3, 5>, - test_3d_left_types, 5, 3>, - test_3d_left_types, 4, 5>, - test_3d_left_types, 4, 3>, - test_3d_left_types, 3, 4, 5>, - test_3d_left_types, 5, 4, 3>, - test_3d_right_types>, - test_3d_right_types>, - test_3d_right_types, 5>, - test_3d_right_types, 3>, - test_3d_right_types, 4>, - test_3d_right_types, 4>, - test_3d_right_types, 3>, - test_3d_right_types, 5>, - test_3d_right_types, 3, 4>, - test_3d_right_types, 5, 4>, - test_3d_right_types, 3, 5>, - test_3d_right_types, 5, 3>, - test_3d_right_types, 4, 5>, - test_3d_right_types, 4, 3>, - test_3d_right_types, 3, 4, 5>, - test_3d_right_types, 5, 4, 3> - >; - -template struct TestLayout3D : TestLayout { }; +using test_3d_right_types = + std::tuple, + std::integer_sequence>; + +using layout_test_types_3d = ::testing::Types< + test_3d_left_types>, + test_3d_left_types>, + test_3d_left_types, 5>, + test_3d_left_types, 3>, + test_3d_left_types, 4>, + test_3d_left_types, 4>, + test_3d_left_types, 3>, + test_3d_left_types, 5>, + test_3d_left_types, 3, 4>, + test_3d_left_types, 5, 4>, + test_3d_left_types, 3, 5>, + test_3d_left_types, 5, 3>, + test_3d_left_types, 4, 5>, + test_3d_left_types, 4, 3>, + test_3d_left_types, 3, 4, 5>, + test_3d_left_types, 5, 4, 3>, + test_3d_right_types>, + test_3d_right_types>, + test_3d_right_types, 5>, + test_3d_right_types, 3>, + test_3d_right_types, 4>, + test_3d_right_types, 4>, + test_3d_right_types, 3>, + test_3d_right_types, 5>, + test_3d_right_types, 3, 4>, + test_3d_right_types, 5, 4>, + test_3d_right_types, 3, 5>, + test_3d_right_types, 5, 3>, + test_3d_right_types, 4, 5>, + test_3d_right_types, 4, 3>, + test_3d_right_types, 3, 4, 5>, + test_3d_right_types, 5, 4, 3>>; + +template +struct TestLayout3D : TestLayout {}; TYPED_TEST_SUITE(TestLayout3D, layout_test_types_3d); TYPED_TEST(TestLayout3D, mapping_works) { - for(size_t i = 0; i < this->map.extents().extent(0); ++i) { - for(size_t j = 0; j < this->map.extents().extent(1); ++j) { - for(size_t k = 0; k < this->map.extents().extent(2); ++k) { + for (size_t i = 0; i < this->map.extents().extent(0); ++i) { + for (size_t j = 0; j < this->map.extents().extent(1); ++j) { + for (size_t k = 0; k < this->map.extents().extent(2); ++k) { EXPECT_EQ(this->map(i, j, k), this->expected_mapping(i, j, k)) - << "Incorrect mapping for index " << i << ", " << j << ", " << k - << " with extents " - << this->map.extents().extent(0) << ", " - << this->map.extents().extent(1) << ", " - << this->map.extents().extent(2) << "."; + << "Incorrect mapping for index " << i << ", " << j << ", " << k + << " with extents " << this->map.extents().extent(0) << ", " + << this->map.extents().extent(1) << ", " + << this->map.extents().extent(2) << "."; } } } } TYPED_TEST(TestLayout3D, required_span_size_works) { - ASSERT_EQ(this->map.required_span_size(), 3*4*5); + ASSERT_EQ(this->map.required_span_size(), 3 * 4 * 5); } -template +template using test_layout_conversion = - std::tuple, - std::integral_constant>; + std::tuple, + std::integral_constant>; // We separate layout_conversion_test_types into multiple type lists // in order to avoid an nvc++ compiler error (recursion too deep). // Left <=> Left conversion -using layout_conversion_test_types_left_to_left = - ::testing::Types< - test_layout_conversion, Kokkos::extents, true, 5> - ,test_layout_conversion, Kokkos::extents, true> - ,test_layout_conversion, Kokkos::extents, false, 5> - ,test_layout_conversion, Kokkos::extents, true, 5,10> - ,test_layout_conversion, Kokkos::extents, true, 5,0> // intentional 0 here to test degenerated - ,test_layout_conversion, Kokkos::extents, true, 5,10> - ,test_layout_conversion, Kokkos::extents, true, 5,10> - ,test_layout_conversion, Kokkos::extents, true, 5,10> - ,test_layout_conversion, Kokkos::extents, false, 5, 10, 15, 20, 25> - ,test_layout_conversion, Kokkos::extents, false, 5, 10, 15, 20, 25> - ,test_layout_conversion, Kokkos::extents, true, 5, 10, 15, 20, 25> - ,test_layout_conversion, Kokkos::extents, true, 5, 10, 15, 20, 25> - >; +using layout_conversion_test_types_left_to_left = ::testing::Types< + test_layout_conversion, + Kokkos::extents, true, 5>, + test_layout_conversion, Kokkos::extents, + true>, + test_layout_conversion, + Kokkos::extents, false, 5>, + test_layout_conversion, + Kokkos::extents, true, 5, 10>, + test_layout_conversion, + Kokkos::extents, true, 5, + 0> // intentional 0 here to test degenerated + , + test_layout_conversion, + Kokkos::extents, true, 5, 10>, + test_layout_conversion, + Kokkos::extents, true, 5, 10>, + test_layout_conversion, + Kokkos::extents, true, 5, 10>, + test_layout_conversion, + Kokkos::extents, false, + 5, 10, 15, 20, 25>, + test_layout_conversion, + Kokkos::extents, false, + 5, 10, 15, 20, 25>, + test_layout_conversion, + Kokkos::extents, true, + 5, 10, 15, 20, 25>, + test_layout_conversion, + Kokkos::extents, true, 5, + 10, 15, 20, 25>>; // Right <=> Right conversion -using layout_conversion_test_types_right_to_right = - ::testing::Types< - test_layout_conversion, Kokkos::extents, true, 5> - ,test_layout_conversion, Kokkos::extents, true> - ,test_layout_conversion, Kokkos::extents, false, 5> - ,test_layout_conversion, Kokkos::extents, true, 5,10> - ,test_layout_conversion, Kokkos::extents, true, 5,0> //intentional 0 to test degenerate - ,test_layout_conversion, Kokkos::extents, true, 5,10> - ,test_layout_conversion, Kokkos::extents, true, 5,10> - ,test_layout_conversion, Kokkos::extents, true, 5,10> - ,test_layout_conversion, Kokkos::extents, false, 5, 10, 15, 20, 25> - ,test_layout_conversion, Kokkos::extents, false, 5, 10, 15, 20, 25> - ,test_layout_conversion, Kokkos::extents, true, 5, 10, 15, 20, 25> - ,test_layout_conversion, Kokkos::extents, true, 5, 10, 15, 20, 25> - >; +using layout_conversion_test_types_right_to_right = ::testing::Types< + test_layout_conversion, + Kokkos::extents, true, 5>, + test_layout_conversion, Kokkos::extents, + true>, + test_layout_conversion, + Kokkos::extents, false, 5>, + test_layout_conversion, + Kokkos::extents, true, 5, 10>, + test_layout_conversion, + Kokkos::extents, true, 5, + 0> // intentional 0 to test degenerate + , + test_layout_conversion, + Kokkos::extents, true, 5, 10>, + test_layout_conversion, + Kokkos::extents, true, 5, 10>, + test_layout_conversion, + Kokkos::extents, true, 5, 10>, + test_layout_conversion, + Kokkos::extents, false, + 5, 10, 15, 20, 25>, + test_layout_conversion, + Kokkos::extents, false, + 5, 10, 15, 20, 25>, + test_layout_conversion, + Kokkos::extents, true, + 5, 10, 15, 20, 25>, + test_layout_conversion, + Kokkos::extents, true, 5, + 10, 15, 20, 25>>; // Stride <=> Stride conversion -using layout_conversion_test_types_stride_to_stride = - ::testing::Types< - test_layout_conversion, Kokkos::extents, true, 5> - ,test_layout_conversion, Kokkos::extents, true> - ,test_layout_conversion, Kokkos::extents, false, 5> - ,test_layout_conversion, Kokkos::extents, true, 5,10> - ,test_layout_conversion, Kokkos::extents, true, 5,0> //intentional 0 to test degenerate - ,test_layout_conversion, Kokkos::extents, true, 5,10> - ,test_layout_conversion, Kokkos::extents, true, 5,10> - ,test_layout_conversion, Kokkos::extents, true, 5,10> - ,test_layout_conversion, Kokkos::extents, false, 5, 10, 15, 20, 25> - ,test_layout_conversion, Kokkos::extents, false, 5, 10, 15, 20, 25> - ,test_layout_conversion, Kokkos::extents, true, 5, 10, 15, 20, 25> - ,test_layout_conversion, Kokkos::extents, true, 5, 10, 15, 20, 25> - >; +using layout_conversion_test_types_stride_to_stride = ::testing::Types< + test_layout_conversion, + Kokkos::extents, true, 5>, + test_layout_conversion, Kokkos::extents, + true>, + test_layout_conversion, + Kokkos::extents, false, 5>, + test_layout_conversion, + Kokkos::extents, true, 5, 10>, + test_layout_conversion, + Kokkos::extents, true, 5, + 0> // intentional 0 to test degenerate + , + test_layout_conversion, + Kokkos::extents, true, 5, 10>, + test_layout_conversion, + Kokkos::extents, true, 5, 10>, + test_layout_conversion, + Kokkos::extents, true, 5, 10>, + test_layout_conversion, + Kokkos::extents, false, + 5, 10, 15, 20, 25>, + test_layout_conversion, + Kokkos::extents, false, + 5, 10, 15, 20, 25>, + test_layout_conversion, + Kokkos::extents, true, + 5, 10, 15, 20, 25>, + test_layout_conversion, + Kokkos::extents, true, 5, + 10, 15, 20, 25>>; // Right => Stride conversion -using layout_conversion_test_types_right_to_stride = - ::testing::Types< - test_layout_conversion, Kokkos::extents, true, 5> - ,test_layout_conversion, Kokkos::extents, true> - ,test_layout_conversion, Kokkos::extents, false, 5> - ,test_layout_conversion, Kokkos::extents, true, 5,10> - ,test_layout_conversion, Kokkos::extents, true, 5,0> //intentional 0 to test degenerate - ,test_layout_conversion, Kokkos::extents, true, 5,10> - ,test_layout_conversion, Kokkos::extents, true, 5,10> - ,test_layout_conversion, Kokkos::extents, true, 5,10> - ,test_layout_conversion, Kokkos::extents, false, 5, 10, 15, 20, 25> - ,test_layout_conversion, Kokkos::extents, false, 5, 10, 15, 20, 25> - ,test_layout_conversion, Kokkos::extents, true, 5, 10, 15, 20, 25> - ,test_layout_conversion, Kokkos::extents, true, 5, 10, 15, 20, 25> - >; +using layout_conversion_test_types_right_to_stride = ::testing::Types< + test_layout_conversion, + Kokkos::extents, true, 5>, + test_layout_conversion, Kokkos::extents, + true>, + test_layout_conversion, + Kokkos::extents, false, 5>, + test_layout_conversion, + Kokkos::extents, true, 5, 10>, + test_layout_conversion, + Kokkos::extents, true, 5, + 0> // intentional 0 to test degenerate + , + test_layout_conversion, + Kokkos::extents, true, 5, 10>, + test_layout_conversion, + Kokkos::extents, true, 5, 10>, + test_layout_conversion, + Kokkos::extents, true, 5, 10>, + test_layout_conversion, + Kokkos::extents, false, + 5, 10, 15, 20, 25>, + test_layout_conversion, + Kokkos::extents, false, + 5, 10, 15, 20, 25>, + test_layout_conversion, + Kokkos::extents, true, + 5, 10, 15, 20, 25>, + test_layout_conversion, + Kokkos::extents, true, 5, + 10, 15, 20, 25>>; // Left => Stride conversion -using layout_conversion_test_types_left_to_stride = - ::testing::Types< - test_layout_conversion, Kokkos::extents, true, 5> - ,test_layout_conversion, Kokkos::extents, true> - ,test_layout_conversion, Kokkos::extents, false, 5> - ,test_layout_conversion, Kokkos::extents, true, 5,10> - ,test_layout_conversion, Kokkos::extents, true, 5,0> //intentional 0 to test degenerate - ,test_layout_conversion, Kokkos::extents, true, 5,10> - ,test_layout_conversion, Kokkos::extents, true, 5,10> - ,test_layout_conversion, Kokkos::extents, true, 5,10> - ,test_layout_conversion, Kokkos::extents, false, 5, 10, 15, 20, 25> - ,test_layout_conversion, Kokkos::extents, false, 5, 10, 15, 20, 25> - ,test_layout_conversion, Kokkos::extents, true, 5, 10, 15, 20, 25> - ,test_layout_conversion, Kokkos::extents, true, 5, 10, 15, 20, 25> - >; +using layout_conversion_test_types_left_to_stride = ::testing::Types< + test_layout_conversion, + Kokkos::extents, true, 5>, + test_layout_conversion, Kokkos::extents, + true>, + test_layout_conversion, + Kokkos::extents, false, 5>, + test_layout_conversion, + Kokkos::extents, true, 5, 10>, + test_layout_conversion, + Kokkos::extents, true, 5, + 0> // intentional 0 to test degenerate + , + test_layout_conversion, + Kokkos::extents, true, 5, 10>, + test_layout_conversion, + Kokkos::extents, true, 5, 10>, + test_layout_conversion, + Kokkos::extents, true, 5, 10>, + test_layout_conversion, + Kokkos::extents, false, + 5, 10, 15, 20, 25>, + test_layout_conversion, + Kokkos::extents, false, + 5, 10, 15, 20, 25>, + test_layout_conversion, + Kokkos::extents, true, + 5, 10, 15, 20, 25>, + test_layout_conversion, + Kokkos::extents, true, 5, + 10, 15, 20, 25>>; // Stride => Left conversion -using layout_conversion_test_types_stride_to_left = - ::testing::Types< - test_layout_conversion, Kokkos::extents, false, 5> - ,test_layout_conversion, Kokkos::extents, true> - ,test_layout_conversion, Kokkos::extents, false, 5> - ,test_layout_conversion, Kokkos::extents, false, 5,10> - ,test_layout_conversion, Kokkos::extents, false, 5,0> //intentional 0 to test degenerate - ,test_layout_conversion, Kokkos::extents, false, 5,10> - ,test_layout_conversion, Kokkos::extents, false, 5,10> - ,test_layout_conversion, Kokkos::extents, false, 5,10> - ,test_layout_conversion, Kokkos::extents, false, 5, 10, 15, 20, 25> - ,test_layout_conversion, Kokkos::extents, false, 5, 10, 15, 20, 25> - ,test_layout_conversion, Kokkos::extents, false, 5, 10, 15, 20, 25> - ,test_layout_conversion, Kokkos::extents, false, 5, 10, 15, 20, 25> - >; +using layout_conversion_test_types_stride_to_left = ::testing::Types< + test_layout_conversion, + Kokkos::extents, false, 5>, + test_layout_conversion, Kokkos::extents, + true>, + test_layout_conversion, + Kokkos::extents, false, 5>, + test_layout_conversion, + Kokkos::extents, false, 5, 10>, + test_layout_conversion, + Kokkos::extents, false, 5, + 0> // intentional 0 to test degenerate + , + test_layout_conversion, + Kokkos::extents, false, 5, 10>, + test_layout_conversion, + Kokkos::extents, false, 5, 10>, + test_layout_conversion, + Kokkos::extents, false, 5, 10>, + test_layout_conversion, + Kokkos::extents, false, + 5, 10, 15, 20, 25>, + test_layout_conversion, + Kokkos::extents, false, + 5, 10, 15, 20, 25>, + test_layout_conversion, + Kokkos::extents, false, + 5, 10, 15, 20, 25>, + test_layout_conversion, + Kokkos::extents, false, 5, + 10, 15, 20, 25>>; // Stride => Right conversion -using layout_conversion_test_types_stride_to_right = - ::testing::Types< - test_layout_conversion, Kokkos::extents, false, 5> - ,test_layout_conversion, Kokkos::extents, true> - ,test_layout_conversion, Kokkos::extents, false, 5> - ,test_layout_conversion, Kokkos::extents, false, 5,10> - ,test_layout_conversion, Kokkos::extents, false, 5,0> //intentional 0 to test degenerate - ,test_layout_conversion, Kokkos::extents, false, 5,10> - ,test_layout_conversion, Kokkos::extents, false, 5,10> - ,test_layout_conversion, Kokkos::extents, false, 5,10> - ,test_layout_conversion, Kokkos::extents, false, 5, 10, 15, 20, 25> - ,test_layout_conversion, Kokkos::extents, false, 5, 10, 15, 20, 25> - ,test_layout_conversion, Kokkos::extents, false, 5, 10, 15, 20, 25> - ,test_layout_conversion, Kokkos::extents, false, 5, 10, 15, 20, 25> - >; +using layout_conversion_test_types_stride_to_right = ::testing::Types< + test_layout_conversion, + Kokkos::extents, false, 5>, + test_layout_conversion, Kokkos::extents, + true>, + test_layout_conversion, + Kokkos::extents, false, 5>, + test_layout_conversion, + Kokkos::extents, false, 5, 10>, + test_layout_conversion, + Kokkos::extents, false, 5, + 0> // intentional 0 to test degenerate + , + test_layout_conversion, + Kokkos::extents, false, 5, 10>, + test_layout_conversion, + Kokkos::extents, false, 5, 10>, + test_layout_conversion, + Kokkos::extents, false, 5, 10>, + test_layout_conversion, + Kokkos::extents, false, + 5, 10, 15, 20, 25>, + test_layout_conversion, + Kokkos::extents, false, + 5, 10, 15, 20, 25>, + test_layout_conversion, + Kokkos::extents, false, + 5, 10, 15, 20, 25>, + test_layout_conversion, + Kokkos::extents, false, 5, + 10, 15, 20, 25>>; // Left <=> Right conversion -using layout_conversion_test_types_left_to_right = - ::testing::Types< - test_layout_conversion, Kokkos::extents, true, 5> - ,test_layout_conversion, Kokkos::extents, false, 5> - ,test_layout_conversion, Kokkos::extents, true, 5> - ,test_layout_conversion, Kokkos::extents, false, 5> - ,test_layout_conversion, Kokkos::extents, true> - ,test_layout_conversion, Kokkos::extents, true> - >; - -template struct TestLayoutConversion; - -template +using layout_conversion_test_types_left_to_right = ::testing::Types< + test_layout_conversion, + Kokkos::extents, true, 5>, + test_layout_conversion, + Kokkos::extents, false, 5>, + test_layout_conversion, + Kokkos::extents, true, 5>, + test_layout_conversion, + Kokkos::extents, false, 5>, + test_layout_conversion, Kokkos::extents, + true>, + test_layout_conversion, Kokkos::extents, + true>>; + +template +struct TestLayoutConversion; + +template struct TestLayoutConversion< - std::tuple, - std::integral_constant>> : public ::testing::Test { + std::tuple, + std::integral_constant>> + : public ::testing::Test { static constexpr bool implicit = Implicit; - using layout_1_t = Layout1; - using exts_1_t = Extents1; - using map_1_t = typename Layout1::template mapping; - using layout_2_t = Layout2; - using exts_2_t = Extents2; - using map_2_t = typename Layout2::template mapping; - exts_1_t exts1 { AllSizes... }; - exts_2_t exts2 { AllSizes... }; - - map_1_t implicit_conv(map_1_t map) const { - return map; - } - - template + using layout_1_t = Layout1; + using exts_1_t = Extents1; + using map_1_t = typename Layout1::template mapping; + using layout_2_t = Layout2; + using exts_2_t = Extents2; + using map_2_t = typename Layout2::template mapping; + exts_1_t exts1{AllSizes...}; + exts_2_t exts2{AllSizes...}; + + map_1_t implicit_conv(map_1_t map) const { return map; } + + template static constexpr std::enable_if_t< - std::is_same::value && - !std::is_same::value && - std::is_same::value, - map_2_t> create_map2(Extents exts) { - return map_2_t(map_1_t(Extents1(exts))); + std::is_same::value && + !std::is_same::value && + std::is_same::value, + map_2_t> + create_map2(Extents exts) { + return map_2_t(map_1_t(Extents1(exts))); } - template + template static constexpr std::enable_if_t< - std::is_same::value && - std::is_same::value && - std::is_same::value, - map_2_t> create_map2(Extents exts) { - return map_2_t(typename Kokkos::layout_left::template mapping(exts)); + std::is_same::value && + std::is_same::value && + std::is_same::value, + map_2_t> + create_map2(Extents exts) { + return map_2_t( + typename Kokkos::layout_left::template mapping(exts)); } - template + template static constexpr std::enable_if_t< - std::is_same::value && - !std::is_same::value, - map_2_t> create_map2(Extents exts) { - return map_2_t(exts); + std::is_same::value && + !std::is_same::value, + map_2_t> + create_map2(Extents exts) { + return map_2_t(exts); } }; @@ -320,68 +519,77 @@ struct TestLayoutConversion< // because this results in duplicate test names. // However, creating an alias for each suite works around this. -TYPED_TEST_SUITE(TestLayoutConversion, layout_conversion_test_types_left_to_left); +TYPED_TEST_SUITE(TestLayoutConversion, + layout_conversion_test_types_left_to_left); -template +template using TestLayoutConversion_R2R = TestLayoutConversion; -TYPED_TEST_SUITE(TestLayoutConversion_R2R, layout_conversion_test_types_right_to_right); +TYPED_TEST_SUITE(TestLayoutConversion_R2R, + layout_conversion_test_types_right_to_right); -template +template using TestLayoutConversion_S2S = TestLayoutConversion; -TYPED_TEST_SUITE(TestLayoutConversion_S2S, layout_conversion_test_types_stride_to_stride); +TYPED_TEST_SUITE(TestLayoutConversion_S2S, + layout_conversion_test_types_stride_to_stride); -template +template using TestLayoutConversion_R2S = TestLayoutConversion; -TYPED_TEST_SUITE(TestLayoutConversion_R2S, layout_conversion_test_types_right_to_stride); +TYPED_TEST_SUITE(TestLayoutConversion_R2S, + layout_conversion_test_types_right_to_stride); -template +template using TestLayoutConversion_L2S = TestLayoutConversion; -TYPED_TEST_SUITE(TestLayoutConversion_L2S, layout_conversion_test_types_left_to_stride); +TYPED_TEST_SUITE(TestLayoutConversion_L2S, + layout_conversion_test_types_left_to_stride); -template +template using TestLayoutConversion_S2L = TestLayoutConversion; -TYPED_TEST_SUITE(TestLayoutConversion_S2L, layout_conversion_test_types_stride_to_left); +TYPED_TEST_SUITE(TestLayoutConversion_S2L, + layout_conversion_test_types_stride_to_left); -template +template using TestLayoutConversion_S2R = TestLayoutConversion; -TYPED_TEST_SUITE(TestLayoutConversion_S2R, layout_conversion_test_types_stride_to_right); +TYPED_TEST_SUITE(TestLayoutConversion_S2R, + layout_conversion_test_types_stride_to_right); -template +template using TestLayoutConversion_L2R = TestLayoutConversion; -TYPED_TEST_SUITE(TestLayoutConversion_L2R, layout_conversion_test_types_left_to_right); +TYPED_TEST_SUITE(TestLayoutConversion_L2R, + layout_conversion_test_types_left_to_right); TYPED_TEST(TestLayoutConversion, implicit_conversion) { typename TestFixture::map_2_t map2 = this->create_map2(this->exts2); typename TestFixture::map_1_t map1; - #if MDSPAN_HAS_CXX_20 && !defined(MDSPAN_IMPL_COMPILER_MSVC) +#if MDSPAN_HAS_CXX_20 && !defined(MDSPAN_IMPL_COMPILER_MSVC) static_assert(TestFixture::implicit == - ( - ( - !std::is_same::value && - std::is_convertible::value - ) || ( - std::is_same::value && - std::is_same::value && - std::is_convertible::value - )|| ( - std::is_same::value && - !std::is_same::value && - TestFixture::exts_2_t::rank()==0 - ) - ) - ); - static_assert(std::is_convertible::value == + ((!std::is_same::value && + std::is_convertible::value) || + (std::is_same::value && + std::is_same::value && + std::is_convertible::value) || + (std::is_same::value && + !std::is_same::value && + TestFixture::exts_2_t::rank() == 0))); + static_assert(std::is_convertible::value == TestFixture::implicit); - if constexpr(TestFixture::implicit) + if constexpr (TestFixture::implicit) map1 = this->implicit_conv(map2); else - #endif +#endif map1 = typename TestFixture::map_1_t(map2); #if MDSPAN_HAS_CXX_20 if constexpr (TestFixture::exts_1_t::rank() > 0) { #endif - for(size_t r=0; r != this->exts1.rank(); ++r) { + for (size_t r = 0; r != this->exts1.rank(); ++r) { ASSERT_EQ(map1.extents().extent(r), map2.extents().extent(r)); ASSERT_EQ(map1.stride(r), map2.stride(r)); } diff --git a/tests/test_extents.cpp b/tests/test_extents.cpp index b8665553..ba2d1f87 100644 --- a/tests/test_extents.cpp +++ b/tests/test_extents.cpp @@ -5,41 +5,42 @@ #include "offload_utils.hpp" #include - // Making actual test implementations part of the class, -// can't create CUDA lambdas in the primary test functions, since they are private -// making a non-member function would require replicating all the type info +// can't create CUDA lambdas in the primary test functions, since they are +// private making a non-member function would require replicating all the type +// info -template struct TestExtents; +template +struct TestExtents; template -struct TestExtents< - std::tuple< - Kokkos::extents, - std::integer_sequence - > -> : public ::testing::Test { - using extents_type = Kokkos::extents; +struct TestExtents, + std::integer_sequence>> + : public ::testing::Test { + using extents_type = Kokkos::extents; // Double Braces here to make it work with GCC 5 - // Otherwise: "error: array must be initialized with a brace-enclosed initializer" - const std::array static_sizes {{ Extents... }}; - const std::array dyn_sizes {{ DynamicSizes... }}; - extents_type exts { DynamicSizes... }; - using Fixture = TestExtents< std::tuple< - Kokkos::extents, - std::integer_sequence - >>; + // Otherwise: "error: array must be initialized with a brace-enclosed + // initializer" + const std::array static_sizes{{Extents...}}; + const std::array dyn_sizes{ + {DynamicSizes...}}; + extents_type exts{DynamicSizes...}; + using Fixture = + TestExtents, + std::integer_sequence>>; void test_rank() { size_t* result = allocate_array(2); - dispatch([=] MDSPAN_IMPL_HOST_DEVICE () { + dispatch([=] MDSPAN_IMPL_HOST_DEVICE() { extents_type exts(DynamicSizes...); // Silencing an unused warning in nvc++ the condition will never be true - size_t dyn_val = exts.rank()>0?static_cast(exts.extent(0)):1; + size_t dyn_val = + exts.rank() > 0 ? static_cast(exts.extent(0)) : 1; result[0] = dyn_val > 1e9 ? dyn_val : exts.rank(); result[1] = exts.rank_dynamic(); - // Some compilers warn about unused exts since the functions are all static constexpr - (void) exts; + // Some compilers warn about unused exts since the functions are all + // static constexpr + (void)exts; }); EXPECT_EQ(result[0], static_sizes.size()); EXPECT_EQ(result[1], dyn_sizes.size()); @@ -50,17 +51,18 @@ struct TestExtents< void test_static_extent() { size_t* result = allocate_array(extents_type::rank()); - dispatch([=] MDSPAN_IMPL_HOST_DEVICE () { + dispatch([=] MDSPAN_IMPL_HOST_DEVICE() { extents_type exts(DynamicSizes...); - for(size_t r=0; r(exts.extent(r)); - result[r] = dyn_val > 1e9 ? dyn_val : exts.static_extent(r); + result[r] = dyn_val > 1e9 ? dyn_val : exts.static_extent(r); } - // Some compilers warn about unused exts since the functions are all static constexpr - (void) exts; + // Some compilers warn about unused exts since the functions are all + // static constexpr + (void)exts; }); - for(size_t r=0; r(extents_type::rank()); - dispatch([=] MDSPAN_IMPL_HOST_DEVICE () { + dispatch([=] MDSPAN_IMPL_HOST_DEVICE() { extents_type exts(DynamicSizes...); - for(size_t r=0; r using sizes = std::integer_sequence; template -using exts = Kokkos::extents; +using exts = Kokkos::extents; -using extents_test_types = - ::testing::Types< +using extents_test_types = ::testing::Types< std::tuple, sizes<>>, std::tuple, sizes<10>>, std::tuple, sizes<>>, std::tuple, sizes<10>>, std::tuple, sizes<3>>, - std::tuple, sizes<10, 3>> - >; + std::tuple, + sizes<10, 3>>>; TYPED_TEST_SUITE(TestExtents, extents_test_types); -TYPED_TEST(TestExtents, rank) { - MDSPAN_IMPL_TESTS_RUN_TEST(this->test_rank()) -} +TYPED_TEST(TestExtents, rank){MDSPAN_IMPL_TESTS_RUN_TEST(this->test_rank())} -TYPED_TEST(TestExtents, static_extent) { - MDSPAN_IMPL_TESTS_RUN_TEST(this->test_static_extent()) -} +TYPED_TEST(TestExtents, static_extent){ + MDSPAN_IMPL_TESTS_RUN_TEST(this->test_static_extent())} -TYPED_TEST(TestExtents, extent) { - MDSPAN_IMPL_TESTS_RUN_TEST(this->test_extent()) -} +TYPED_TEST(TestExtents, extent){MDSPAN_IMPL_TESTS_RUN_TEST(this->test_extent())} TYPED_TEST(TestExtents, default_ctor) { - auto e = typename TestFixture::extents_type(); + auto e = typename TestFixture::extents_type(); auto e2 = typename TestFixture::extents_type{}; EXPECT_EQ(e, e2); for (size_t r = 0; r < e.rank(); ++r) { @@ -133,7 +129,7 @@ TYPED_TEST(TestExtents, array_ctor) { } TYPED_TEST(TestExtents, copy_ctor) { - typename TestFixture::extents_type e { this->exts }; + typename TestFixture::extents_type e{this->exts}; EXPECT_EQ(e, this->exts); } @@ -145,94 +141,117 @@ TYPED_TEST(TestExtents, copy_assign) { // Only types can be part of the gtest type iteration // so i need this wrapper to wrap around true/false values -template +template struct BoolPairDeducer { static constexpr bool val1 = Val1; static constexpr bool val2 = Val2; }; - -template struct TestExtentsCompatCtors; -template -struct TestExtentsCompatCtors, - std::integer_sequence, - Kokkos::extents, - std::integer_sequence, - BoolPairDeducer ->> : public ::testing::Test { - using extents_type1 = Kokkos::extents; - using extents_type2 = Kokkos::extents; - extents_type1 exts1 { DynamicSizes... }; - extents_type2 exts2 { DynamicSizes2... }; +template +struct TestExtentsCompatCtors; +template +struct TestExtentsCompatCtors< + std::tuple, + std::integer_sequence, + Kokkos::extents, + std::integer_sequence, + BoolPairDeducer>> + : public ::testing::Test { + using extents_type1 = Kokkos::extents; + using extents_type2 = Kokkos::extents; + extents_type1 exts1{DynamicSizes...}; + extents_type2 exts2{DynamicSizes2...}; static constexpr bool implicit_exts1_to_exts2 = ImplicitExts1ToExts2; static constexpr bool implicit_exts2_to_exts1 = ImplicitExts2ToExts1; // Idx starts at rank() - template + template struct make_extents; // Construct all extents - doesn't matter if idx is static or not - template - struct make_extents - { - template - static Exts construct(SizeTypes...sizes) { - return make_extents::construct(Idx*5, sizes...); + template + struct make_extents { + template + static Exts construct(SizeTypes... sizes) { + return make_extents::construct(Idx * 5, + sizes...); } }; - // Construct dynamic extents - opnly add a parameter if the current index is not static - template - struct make_extents - { - template - static Exts construct(SizeTypes...sizes) { - return make_extents1?Exts::static_extent(Idx-2)!=Kokkos::dynamic_extent:true)>::construct(Idx*5, sizes...); + // Construct dynamic extents - opnly add a parameter if the current index is + // not static + template + struct make_extents { + template + static Exts construct(SizeTypes... sizes) { + return make_extents 1 ? Exts::static_extent(Idx - 2) != + Kokkos::dynamic_extent + : true)>::construct(Idx * 5, sizes...); } }; - template - struct make_extents - { - template - static Exts construct(SizeTypes...sizes) { - return make_extents1?Exts::static_extent(Idx-2)!=Kokkos::dynamic_extent:true)>::construct(sizes...); + template + struct make_extents { + template + static Exts construct(SizeTypes... sizes) { + return make_extents 1 ? Exts::static_extent(Idx - 2) != + Kokkos::dynamic_extent + : true)>::construct(sizes...); } }; // End case - template - struct make_extents { - template - static Exts construct(SizeTypes...sizes) { - return Exts{sizes...}; + template + struct make_extents { + template + static Exts construct(SizeTypes... sizes) { + return Exts{sizes...}; } }; - template - struct make_extents { - template - static Exts construct(SizeTypes...sizes) { - return Exts{sizes...}; + template + struct make_extents { + template + static Exts construct(SizeTypes... sizes) { + return Exts{sizes...}; } }; }; -using compatible_extents_test_types = - ::testing::Types< - std::tuple, sizes<5>, exts<5>, sizes<>, BoolPairDeducer>, - std::tuple, sizes<>, exts, sizes<5>, BoolPairDeducer>, +using compatible_extents_test_types = ::testing::Types< + std::tuple, sizes<5>, exts<5>, sizes<>, + BoolPairDeducer>, + std::tuple, sizes<>, exts, sizes<5>, + BoolPairDeducer>, //-------------------- - std::tuple, sizes<5>, exts<5, Kokkos::dynamic_extent>, sizes<10>, BoolPairDeducer>, - std::tuple, sizes<5, 10>, exts<5, Kokkos::dynamic_extent>, sizes<10>, BoolPairDeducer>, - std::tuple, sizes<5, 10>, exts, sizes<5>, BoolPairDeducer>, - std::tuple, sizes<5, 10>, exts<5, 10>, sizes<>, BoolPairDeducer>, - std::tuple, sizes<>, exts<5, Kokkos::dynamic_extent>, sizes<10>, BoolPairDeducer>, - std::tuple, sizes<>, exts, sizes<5>, BoolPairDeducer>, + std::tuple, sizes<5>, + exts<5, Kokkos::dynamic_extent>, sizes<10>, + BoolPairDeducer>, + std::tuple, + sizes<5, 10>, exts<5, Kokkos::dynamic_extent>, sizes<10>, + BoolPairDeducer>, + std::tuple, + sizes<5, 10>, exts, sizes<5>, + BoolPairDeducer>, + std::tuple, + sizes<5, 10>, exts<5, 10>, sizes<>, + BoolPairDeducer>, + std::tuple, sizes<>, exts<5, Kokkos::dynamic_extent>, sizes<10>, + BoolPairDeducer>, + std::tuple, sizes<>, exts, sizes<5>, + BoolPairDeducer>, //-------------------- - std::tuple, sizes<5, 10>, exts<5, Kokkos::dynamic_extent, 15>, sizes<10>, BoolPairDeducer>, - std::tuple, sizes<>, exts<5, Kokkos::dynamic_extent, 15>, sizes<10>, BoolPairDeducer>, - std::tuple, sizes<>, exts, sizes<5, 10, 15>, BoolPairDeducer> - >; + std::tuple, + sizes<5, 10>, exts<5, Kokkos::dynamic_extent, 15>, sizes<10>, + BoolPairDeducer>, + std::tuple, sizes<>, exts<5, Kokkos::dynamic_extent, 15>, + sizes<10>, BoolPairDeducer>, + std::tuple, sizes<>, + exts, + sizes<5, 10, 15>, BoolPairDeducer>>; TYPED_TEST_SUITE(TestExtentsCompatCtors, compatible_extents_test_types); @@ -248,8 +267,8 @@ TYPED_TEST(TestExtentsCompatCtors, compatible_construct_2) { TYPED_TEST(TestExtentsCompatCtors, compatible_assign_1) { #if MDSPAN_HAS_CXX_17 - if constexpr(std::is_convertible_v) { + if constexpr (std::is_convertible_v) { this->exts1 = this->exts2; } else { this->exts1 = typename TestFixture::extents_type1(this->exts2); @@ -258,13 +277,12 @@ TYPED_TEST(TestExtentsCompatCtors, compatible_assign_1) { this->exts1 = typename TestFixture::extents_type1(this->exts2); #endif EXPECT_EQ(this->exts1, this->exts2); - } TYPED_TEST(TestExtentsCompatCtors, compatible_assign_2) { #if MDSPAN_HAS_CXX_17 - if constexpr(std::is_convertible_v) { + if constexpr (std::is_convertible_v) { this->exts2 = this->exts1; } else { this->exts2 = typename TestFixture::extents_type2(this->exts1); @@ -275,51 +293,48 @@ TYPED_TEST(TestExtentsCompatCtors, compatible_assign_2) { EXPECT_EQ(this->exts1, this->exts2); } - -template +template struct ImplicitConversionToExts; -template -struct ImplicitConversionToExts { - static bool convert(Extents) { - return true; - } +template +struct ImplicitConversionToExts { + static bool convert(Extents) { return true; } }; -template -struct ImplicitConversionToExts { - template - static bool convert(E) { +template +struct ImplicitConversionToExts { + template + static bool convert(E) { return false; } }; - #if MDSPAN_HAS_CXX_20 TYPED_TEST(TestExtentsCompatCtors, implicit_construct_1) { bool exts1_convertible_exts2 = - std::is_convertible::value; + std::is_convertible::value; bool exts2_convertible_exts1 = - std::is_convertible::value; + std::is_convertible::value; bool exts1_implicit_exts2 = ImplicitConversionToExts< - typename TestFixture::extents_type2, - TestFixture::implicit_exts1_to_exts2>::convert(this->exts1); + typename TestFixture::extents_type2, + TestFixture::implicit_exts1_to_exts2>::convert(this->exts1); bool exts2_implicit_exts1 = ImplicitConversionToExts< - typename TestFixture::extents_type1, - TestFixture::implicit_exts2_to_exts1>::convert(this->exts2); + typename TestFixture::extents_type1, + TestFixture::implicit_exts2_to_exts1>::convert(this->exts2); - EXPECT_EQ(exts1_convertible_exts2,exts1_implicit_exts2); - EXPECT_EQ(exts2_convertible_exts1,exts2_implicit_exts1); - EXPECT_EQ(exts1_convertible_exts2,TestFixture::implicit_exts1_to_exts2); - EXPECT_EQ(exts2_convertible_exts1,TestFixture::implicit_exts2_to_exts1); + EXPECT_EQ(exts1_convertible_exts2, exts1_implicit_exts2); + EXPECT_EQ(exts2_convertible_exts1, exts2_implicit_exts1); + EXPECT_EQ(exts1_convertible_exts2, TestFixture::implicit_exts1_to_exts2); + EXPECT_EQ(exts2_convertible_exts1, TestFixture::implicit_exts2_to_exts1); } #endif -TEST(TestExtentsCtorStdArrayConvertibleToSizeT, test_extents_ctor_std_array_convertible_to_size_t) { +TEST(TestExtentsCtorStdArrayConvertibleToSizeT, + test_extents_ctor_std_array_convertible_to_size_t) { std::array i{2, 2}; - Kokkos::dextents e{i}; + Kokkos::dextents e{i}; ASSERT_EQ(e.rank(), 2); ASSERT_EQ(e.rank_dynamic(), 2); ASSERT_EQ(e.extent(0), 2); @@ -327,10 +342,11 @@ TEST(TestExtentsCtorStdArrayConvertibleToSizeT, test_extents_ctor_std_array_conv } #ifdef __cpp_lib_span -TEST(TestExtentsCtorStdArrayConvertibleToSizeT, test_extents_ctor_std_span_convertible_to_size_t) { +TEST(TestExtentsCtorStdArrayConvertibleToSizeT, + test_extents_ctor_std_span_convertible_to_size_t) { std::array i{2, 2}; - std::span s(i.data(),2); - Kokkos::dextents e{s}; + std::span s(i.data(), 2); + Kokkos::dextents e{s}; ASSERT_EQ(e.rank(), 2); ASSERT_EQ(e.rank_dynamic(), 2); ASSERT_EQ(e.extent(0), 2); @@ -340,28 +356,34 @@ TEST(TestExtentsCtorStdArrayConvertibleToSizeT, test_extents_ctor_std_span_conve TYPED_TEST(TestExtentsCompatCtors, construct_from_dynamic_sizes) { using e1_t = typename TestFixture::extents_type1; - constexpr bool e1_last_ext_static = e1_t::rank()>0?e1_t::static_extent(e1_t::rank()-1)!=Kokkos::dynamic_extent:true; - e1_t e1 = TestFixture::template make_extents::construct(); - for(size_t r=0; r 0 + ? e1_t::static_extent(e1_t::rank() - 1) != Kokkos::dynamic_extent + : true; + e1_t e1 = TestFixture::template make_extents::construct(); + for (size_t r = 0; r < e1.rank(); r++) ASSERT_EQ(e1.extent(r), (r + 1) * 5); using e2_t = typename TestFixture::extents_type2; - constexpr bool e2_last_ext_static = e2_t::rank()>0?e2_t::static_extent(e2_t::rank()-1)!=Kokkos::dynamic_extent:true; - e2_t e2 = TestFixture::template make_extents::construct(); - for(size_t r=0; r 0 + ? e2_t::static_extent(e2_t::rank() - 1) != Kokkos::dynamic_extent + : true; + e2_t e2 = TestFixture::template make_extents::construct(); + for (size_t r = 0; r < e2.rank(); r++) ASSERT_EQ(e2.extent(r), (r + 1) * 5); } TYPED_TEST(TestExtentsCompatCtors, construct_from_all_sizes) { using e1_t = typename TestFixture::extents_type1; - e1_t e1 = TestFixture::template make_extents::construct(); - for(size_t r=0; r::construct(); + for (size_t r = 0; r < e1.rank(); r++) ASSERT_EQ(e1.extent(r), (r + 1) * 5); using e2_t = typename TestFixture::extents_type2; - e2_t e2 = TestFixture::template make_extents::construct(); - for(size_t r=0; r::construct(); + for (size_t r = 0; r < e2.rank(); r++) ASSERT_EQ(e2.extent(r), (r + 1) * 5); } TYPED_TEST(TestExtentsCompatCtors, construct_from_dynamic_array) { @@ -369,47 +391,45 @@ TYPED_TEST(TestExtentsCompatCtors, construct_from_dynamic_array) { std::array ext1_array_dynamic; int dyn_idx = 0; - for(size_t r=0; r((r+1)*5); + for (size_t r = 0; r < e1_t::rank(); r++) { + if (e1_t::static_extent(r) == Kokkos::dynamic_extent) { + ext1_array_dynamic[dyn_idx] = static_cast((r + 1) * 5); dyn_idx++; } } e1_t e1(ext1_array_dynamic); - for(size_t r=0; r ext2_array_dynamic; dyn_idx = 0; - for(size_t r=0; r((r+1)*5); + for (size_t r = 0; r < e2_t::rank(); r++) { + if (e2_t::static_extent(r) == Kokkos::dynamic_extent) { + ext2_array_dynamic[dyn_idx] = static_cast((r + 1) * 5); dyn_idx++; } } e2_t e2(ext2_array_dynamic); - for(size_t r=0; r ext1_array_all; - for(size_t r=0; r((r+1)*5); + for (size_t r = 0; r < e1_t::rank(); r++) + ext1_array_all[r] = static_cast((r + 1) * 5); e1_t e1(ext1_array_all); - for(size_t r=0; r ext2_array_all; - for(size_t r=0; r((r+1)*5); + for (size_t r = 0; r < e2_t::rank(); r++) + ext2_array_all[r] = static_cast((r + 1) * 5); e2_t e2(ext2_array_all); - for(size_t r=0; r{ 500, 500 }; + [[maybe_unused]] auto exts = Kokkos::dextents{500, 500}; }; -#if defined(MDSPAN_IMPL_HAS_CUDA) || defined(MDSPAN_IMPL_HAS_HIP) || defined(MDSPAN_IMPL_HAS_SYCL) +#if defined(MDSPAN_IMPL_HAS_CUDA) || defined(MDSPAN_IMPL_HAS_HIP) || \ + defined(MDSPAN_IMPL_HAS_SYCL) EXPECT_DEATH(test_precondition_indices_not_representable(), ""); #else - EXPECT_DEATH(test_precondition_indices_not_representable(), "all_values_are_nonnegative_and_representable"); + EXPECT_DEATH(test_precondition_indices_not_representable(), + "all_values_are_nonnegative_and_representable"); #endif auto test_precondition_indices_are_negative = [] { - [[maybe_unused]] auto exts = Kokkos::dextents< int, 2 >{ 500, -500 }; + [[maybe_unused]] auto exts = Kokkos::dextents{500, -500}; }; -#if defined(MDSPAN_IMPL_HAS_CUDA) || defined(MDSPAN_IMPL_HAS_HIP) || defined(MDSPAN_IMPL_HAS_SYCL) +#if defined(MDSPAN_IMPL_HAS_CUDA) || defined(MDSPAN_IMPL_HAS_HIP) || \ + defined(MDSPAN_IMPL_HAS_SYCL) EXPECT_DEATH(test_precondition_indices_are_negative(), ""); #else - EXPECT_DEATH(test_precondition_indices_are_negative(), "all_values_are_nonnegative_and_representable"); + EXPECT_DEATH(test_precondition_indices_are_negative(), + "all_values_are_nonnegative_and_representable"); #endif } TEST(TestExtentsConstructorPreconditions, test_extents_construct_array) { auto test_precondition_array_elements_not_representable = [] { - [[maybe_unused]] auto exts = Kokkos::dextents< std::int8_t, 2 >{ std::array{ 500, 500 } }; + [[maybe_unused]] auto exts = + Kokkos::dextents{std::array{500, 500}}; }; -#if defined(MDSPAN_IMPL_HAS_CUDA) || defined(MDSPAN_IMPL_HAS_HIP) || defined(MDSPAN_IMPL_HAS_SYCL) +#if defined(MDSPAN_IMPL_HAS_CUDA) || defined(MDSPAN_IMPL_HAS_HIP) || \ + defined(MDSPAN_IMPL_HAS_SYCL) EXPECT_DEATH(test_precondition_array_elements_not_representable(), ""); #else - EXPECT_DEATH(test_precondition_array_elements_not_representable(), "range_is_nonnegative_and_representable"); + EXPECT_DEATH(test_precondition_array_elements_not_representable(), + "range_is_nonnegative_and_representable"); #endif auto test_precondition_array_elements_are_negative = [] { - [[maybe_unused]] auto exts = Kokkos::dextents< int, 2 >{ std::array{ 500, -500 } }; + [[maybe_unused]] auto exts = + Kokkos::dextents{std::array{500, -500}}; }; -#if defined(MDSPAN_IMPL_HAS_CUDA) || defined(MDSPAN_IMPL_HAS_HIP) || defined(MDSPAN_IMPL_HAS_SYCL) +#if defined(MDSPAN_IMPL_HAS_CUDA) || defined(MDSPAN_IMPL_HAS_HIP) || \ + defined(MDSPAN_IMPL_HAS_SYCL) EXPECT_DEATH(test_precondition_array_elements_are_negative(), ""); #else - EXPECT_DEATH(test_precondition_array_elements_are_negative(), "range_is_nonnegative_and_representable"); + EXPECT_DEATH(test_precondition_array_elements_are_negative(), + "range_is_nonnegative_and_representable"); #endif } #ifdef __cpp_lib_span TEST(TestExtentsConstructorPreconditions, test_extents_construct_span) { auto test_precondition_span_elements_not_representable = [] { - auto indices = std::array{ 500, 500 }; - [[maybe_unused]] auto exts = Kokkos::dextents< std::int8_t, 2 >{ std::span{ indices } }; + auto indices = std::array{500, 500}; + [[maybe_unused]] auto exts = + Kokkos::dextents{std::span{indices}}; }; -#if defined(MDSPAN_IMPL_HAS_CUDA) || defined(MDSPAN_IMPL_HAS_HIP) || defined(MDSPAN_IMPL_HAS_SYCL) +#if defined(MDSPAN_IMPL_HAS_CUDA) || defined(MDSPAN_IMPL_HAS_HIP) || \ + defined(MDSPAN_IMPL_HAS_SYCL) EXPECT_DEATH(test_precondition_span_elements_not_representable(), ""); #else - EXPECT_DEATH(test_precondition_span_elements_not_representable(), "range_is_nonnegative_and_representable"); + EXPECT_DEATH(test_precondition_span_elements_not_representable(), + "range_is_nonnegative_and_representable"); #endif auto test_precondition_span_elements_are_negative = [] { - auto indices = std::array{ 500, -500 }; - [[maybe_unused]] auto exts = Kokkos::dextents< int, 2 >{ std::span{ indices } }; + auto indices = std::array{500, -500}; + [[maybe_unused]] auto exts = Kokkos::dextents{std::span{indices}}; }; -#if defined(MDSPAN_IMPL_HAS_CUDA) || defined(MDSPAN_IMPL_HAS_HIP) || defined(MDSPAN_IMPL_HAS_SYCL) +#if defined(MDSPAN_IMPL_HAS_CUDA) || defined(MDSPAN_IMPL_HAS_HIP) || \ + defined(MDSPAN_IMPL_HAS_SYCL) EXPECT_DEATH(test_precondition_span_elements_are_negative(), ""); #else - EXPECT_DEATH(test_precondition_span_elements_are_negative(), "range_is_nonnegative_and_representable"); + EXPECT_DEATH(test_precondition_span_elements_are_negative(), + "range_is_nonnegative_and_representable"); #endif } #endif -TEST(TestExtentsConstructorPreconditions, test_extents_construct_other_extents) { +TEST(TestExtentsConstructorPreconditions, + test_extents_construct_other_extents) { auto test_precondition_extent_ranks_not_representable = [] { - auto first = Kokkos::dextents< int, 2 >{ 500, 500 }; - [[maybe_unused]] auto exts = Kokkos::dextents< std::int8_t, 2 >{ first }; + auto first = Kokkos::dextents{500, 500}; + [[maybe_unused]] auto exts = Kokkos::dextents{first}; }; -#if defined(MDSPAN_IMPL_HAS_CUDA) || defined(MDSPAN_IMPL_HAS_HIP) || defined(MDSPAN_IMPL_HAS_SYCL) +#if defined(MDSPAN_IMPL_HAS_CUDA) || defined(MDSPAN_IMPL_HAS_HIP) || \ + defined(MDSPAN_IMPL_HAS_SYCL) EXPECT_DEATH(test_precondition_extent_ranks_not_representable(), ""); #else - EXPECT_DEATH(test_precondition_extent_ranks_not_representable(), "extent_is_representable"); + EXPECT_DEATH(test_precondition_extent_ranks_not_representable(), + "extent_is_representable"); #endif } #endif diff --git a/tests/test_layout_ctors.cpp b/tests/test_layout_ctors.cpp index c300c33d..cf6b3c96 100644 --- a/tests/test_layout_ctors.cpp +++ b/tests/test_layout_ctors.cpp @@ -7,44 +7,40 @@ MDSPAN_IMPL_INLINE_VARIABLE constexpr auto dyn = Kokkos::dynamic_extent; -template struct TestLayoutCtors; +template +struct TestLayoutCtors; template -struct TestLayoutCtors ->> : public ::testing::Test { +struct TestLayoutCtors< + std::tuple>> + : public ::testing::Test { using mapping_type = Mapping; using extents_type = typename mapping_type::extents_type; - Mapping map = { extents_type{ DynamicSizes... } }; + Mapping map = {extents_type{DynamicSizes...}}; }; template -using test_left_type = std::tuple< - typename Kokkos::layout_left::template mapping, - std::integer_sequence ->; +using test_left_type = + std::tuple, + std::integer_sequence>; template -using test_right_type = std::tuple< - typename Kokkos::layout_right::template mapping, - std::integer_sequence ->; +using test_right_type = + std::tuple, + std::integer_sequence>; using layout_test_types = - ::testing::Types< - test_left_type>, - test_right_type>, - //---------- - test_left_type, 10>, - test_right_type, 10>, - //---------- - test_left_type, 5>, - test_left_type, 10>, - test_left_type>, - test_right_type, 5>, - test_right_type, 10>, - test_right_type> - >; + ::testing::Types>, + test_right_type>, + //---------- + test_left_type, 10>, + test_right_type, 10>, + //---------- + test_left_type, 5>, + test_left_type, 10>, + test_left_type>, + test_right_type, 5>, + test_right_type, 10>, + test_right_type>>; TYPED_TEST_SUITE(TestLayoutCtors, layout_test_types); @@ -58,40 +54,39 @@ TYPED_TEST(TestLayoutCtors, default_ctor) { ASSERT_FALSE(m != m2); } -template struct TestLayoutCompatCtors; -template -struct TestLayoutCompatCtors, - Mapping2, - std::integer_sequence ->> : public ::testing::Test { +template +struct TestLayoutCompatCtors; +template +struct TestLayoutCompatCtors< + std::tuple, + Mapping2, std::integer_sequence>> + : public ::testing::Test { using mapping_type1 = Mapping; using mapping_type2 = Mapping2; - using extents_type1 = std::remove_reference_t().extents())>; - using extents_type2 = std::remove_reference_t().extents())>; - Mapping map1 = { extents_type1{ DynamicSizes... } }; - Mapping2 map2 = { extents_type2{ DynamicSizes2... } }; + using extents_type1 = std::remove_reference_t< + decltype(std::declval().extents())>; + using extents_type2 = std::remove_reference_t< + decltype(std::declval().extents())>; + Mapping map1 = {extents_type1{DynamicSizes...}}; + Mapping2 map2 = {extents_type2{DynamicSizes2...}}; }; template -using test_left_type_compatible = std::tuple< - typename Kokkos::layout_left::template mapping, S1, - typename Kokkos::layout_left::template mapping, S2 ->; +using test_left_type_compatible = + std::tuple, S1, + typename Kokkos::layout_left::template mapping, S2>; template -using test_right_type_compatible = std::tuple< - typename Kokkos::layout_right::template mapping, S1, - typename Kokkos::layout_right::template mapping, S2 ->; +using test_right_type_compatible = + std::tuple, S1, + typename Kokkos::layout_right::template mapping, S2>; template using sizes = std::integer_sequence; template -using exts = Kokkos::extents; +using exts = Kokkos::extents; template