Skip to content

Commit

Permalink
Implement ranges::elements_view
Browse files Browse the repository at this point in the history
  • Loading branch information
miscco committed Jul 11, 2023
1 parent f9bb126 commit 269b29f
Show file tree
Hide file tree
Showing 58 changed files with 6,058 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
// SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES
//
//===----------------------------------------------------------------------===//

// UNSUPPORTED: c++03, c++11, c++14

// cuda::std::views::elements<N>
// cuda::std::views::keys
// cuda::std::views::values

#include <cuda/std/cassert>
#include <cuda/std/ranges>
#include <cuda/std/tuple>
#include <cuda/std/type_traits>
#include <cuda/std/utility>

#include "test_macros.h"

template <class T>
struct View : cuda::std::ranges::view_base {
__host__ __device__ T* begin() const;
__host__ __device__ T* end() const;
};

static_assert(!cuda::std::is_invocable_v<decltype((cuda::std::views::elements<0>))>);
static_assert(!cuda::std::is_invocable_v<decltype((cuda::std::views::elements<0>)), View<int>>);
static_assert(cuda::std::is_invocable_v<decltype((cuda::std::views::elements<0>)), View<cuda::std::pair<int, int>>>);
static_assert(cuda::std::is_invocable_v<decltype((cuda::std::views::elements<0>)), View<cuda::std::tuple<int>>>);
static_assert(!cuda::std::is_invocable_v<decltype((cuda::std::views::elements<5>)), View<cuda::std::tuple<int>>>);

static_assert(!cuda::std::is_invocable_v<decltype((cuda::std::views::keys))>);
static_assert(!cuda::std::is_invocable_v<decltype((cuda::std::views::keys)), View<int>>);
static_assert(cuda::std::is_invocable_v<decltype((cuda::std::views::keys)), View<cuda::std::pair<int, int>>>);
static_assert(cuda::std::is_invocable_v<decltype((cuda::std::views::keys)), View<cuda::std::tuple<int>>>);

static_assert(!cuda::std::is_invocable_v<decltype((cuda::std::views::values))>);
static_assert(!cuda::std::is_invocable_v<decltype((cuda::std::views::values)), View<int>>);
static_assert(cuda::std::is_invocable_v<decltype((cuda::std::views::values)), View<cuda::std::pair<int, int>>>);
static_assert(!cuda::std::is_invocable_v<decltype((cuda::std::views::values)), View<cuda::std::tuple<int>>>);

#if TEST_STD_VER > 17
template <class View, class T>
concept CanBePiped = requires (View&& view, T&& t) {
{ cuda::std::forward<View>(view) | cuda::std::forward<T>(t) };
};
#else
template<class View, class T, class = void>
inline constexpr bool CanBePiped = false;

template<class View, class T>
inline constexpr bool CanBePiped<View, T, cuda::std::void_t<decltype(cuda::std::declval<View>() | cuda::std::declval<T>())>> = true;
#endif

static_assert(!CanBePiped<View<int>, decltype((cuda::std::views::elements<0>))>);
static_assert(CanBePiped<View<cuda::std::pair<int, int>>, decltype((cuda::std::views::elements<0>))>);
static_assert(CanBePiped<View<cuda::std::tuple<int>>, decltype((cuda::std::views::elements<0>))>);
static_assert(!CanBePiped<View<cuda::std::tuple<int>>, decltype((cuda::std::views::elements<5>))>);

static_assert(!CanBePiped<View<int>, decltype((cuda::std::views::keys))>);
static_assert(CanBePiped<View<cuda::std::pair<int, int>>, decltype((cuda::std::views::keys))>);
static_assert(CanBePiped<View<cuda::std::tuple<int>>, decltype((cuda::std::views::keys))>);

static_assert(!CanBePiped<View<int>, decltype((cuda::std::views::values))>);
static_assert(CanBePiped<View<cuda::std::pair<int, int>>, decltype((cuda::std::views::values))>);
static_assert(!CanBePiped<View<cuda::std::tuple<int>>, decltype((cuda::std::views::values))>);

template <class Range, class Expected>
__host__ __device__ constexpr bool equal(Range&& range, Expected&& expected) {
auto irange = range.begin();
auto iexpected = cuda::std::begin(expected);
for (; irange != range.end(); ++irange, ++iexpected) {
if (*irange != *iexpected) {
return false;
}
}
return true;
}

__host__ __device__ constexpr bool test() {
cuda::std::pair<int, int> buff[] = {{1, 2}, {3, 4}, {5, 6}};

// Test `views::elements<N>(v)`
{
using Result = cuda::std::ranges::elements_view<cuda::std::ranges::ref_view<cuda::std::pair<int, int>[3]>, 0>;
decltype(auto) result = cuda::std::views::elements<0>(buff);
static_assert(cuda::std::same_as<decltype(result), Result>);
auto expected = {1, 3, 5};
assert(equal(result, expected));
}

// Test `views::keys(v)`
{
using Result = cuda::std::ranges::elements_view<cuda::std::ranges::ref_view<cuda::std::pair<int, int>[3]>, 0>;
decltype(auto) result = cuda::std::views::keys(buff);
static_assert(cuda::std::same_as<decltype(result), Result>);
auto expected = {1, 3, 5};
assert(equal(result, expected));
}

// Test `views::values(v)`
{
using Result = cuda::std::ranges::elements_view<cuda::std::ranges::ref_view<cuda::std::pair<int, int>[3]>, 1>;
decltype(auto) result = cuda::std::views::values(buff);
static_assert(cuda::std::same_as<decltype(result), Result>);
auto expected = {2, 4, 6};
assert(equal(result, expected));
}

// Test `v | views::elements<N>`
{
using Result = cuda::std::ranges::elements_view<cuda::std::ranges::ref_view<cuda::std::pair<int, int>[3]>, 1>;
decltype(auto) result = buff | cuda::std::views::elements<1>;
static_assert(cuda::std::same_as<decltype(result), Result>);
auto expected = {2, 4, 6};
assert(equal(result, expected));
}

// Test `v | views::keys`
{
using Result = cuda::std::ranges::elements_view<cuda::std::ranges::ref_view<cuda::std::pair<int, int>[3]>, 0>;
decltype(auto) result = buff | cuda::std::views::keys;
static_assert(cuda::std::same_as<decltype(result), Result>);
auto expected = {1, 3, 5};
assert(equal(result, expected));
}

// Test `v | views::values`
{
using Result = cuda::std::ranges::elements_view<cuda::std::ranges::ref_view<cuda::std::pair<int, int>[3]>, 1>;
decltype(auto) result = buff | cuda::std::views::values;
static_assert(cuda::std::same_as<decltype(result), Result>);
auto expected = {2, 4, 6};
assert(equal(result, expected));
}

// Test views::elements<0> | views::elements<0>
{
cuda::std::pair<cuda::std::tuple<int>, cuda::std::tuple<int>> nested[] = {{{1}, {2}}, {{3}, {4}}, {{5}, {6}}};
using Result = cuda::std::ranges::elements_view<
cuda::std::ranges::elements_view<cuda::std::ranges::ref_view<cuda::std::pair<cuda::std::tuple<int>, cuda::std::tuple<int>>[3]>, 0>,
0>;
auto const partial = cuda::std::views::elements<0> | cuda::std::views::elements<0>;
decltype(auto) result = nested | partial;
static_assert(cuda::std::same_as<decltype(result), Result>);
auto expected = {1, 3, 5};
assert(equal(result, expected));
}

// Test views::keys | views::keys
{
cuda::std::pair<cuda::std::tuple<int>, cuda::std::tuple<int>> nested[] = {{{1}, {2}}, {{3}, {4}}, {{5}, {6}}};
using Result = cuda::std::ranges::elements_view<
cuda::std::ranges::elements_view<cuda::std::ranges::ref_view<cuda::std::pair<cuda::std::tuple<int>, cuda::std::tuple<int>>[3]>, 0>,
0>;
auto const partial = cuda::std::views::keys | cuda::std::views::keys;
decltype(auto) result = nested | partial;
static_assert(cuda::std::same_as<decltype(result), Result>);
auto expected = {1, 3, 5};
assert(equal(result, expected));
}

// Test views::values | views::values
{
cuda::std::pair<cuda::std::tuple<int>, cuda::std::tuple<int, int>> nested[] = {{{1}, {2, 3}}, {{4}, {5, 6}}, {{7}, {8, 9}}};
using Result = cuda::std::ranges::elements_view<
cuda::std::ranges::elements_view<cuda::std::ranges::ref_view<cuda::std::pair<cuda::std::tuple<int>, cuda::std::tuple<int, int>>[3]>, 1>,
1>;
auto const partial = cuda::std::views::values | cuda::std::views::values;
decltype(auto) result = nested | partial;
static_assert(cuda::std::same_as<decltype(result), Result>);
auto expected = {3, 6, 9};
assert(equal(result, expected));
}

// Test views::keys | views::values
{
cuda::std::pair<cuda::std::tuple<int, int>, cuda::std::tuple<int>> nested[] = {{{1, 2}, {3}}, {{4, 5}, {6}}, {{7, 8}, {9}}};
using Result = cuda::std::ranges::elements_view<
cuda::std::ranges::elements_view<cuda::std::ranges::ref_view<cuda::std::pair<cuda::std::tuple<int, int>, cuda::std::tuple<int>>[3]>, 0>,
1>;
auto const partial = cuda::std::views::keys | cuda::std::views::values;
decltype(auto) result = nested | partial;
static_assert(cuda::std::same_as<decltype(result), Result>);
auto expected = {2, 5, 8};
assert(equal(result, expected));
}

// Test views::values | views::keys
{
cuda::std::pair<cuda::std::tuple<int>, cuda::std::tuple<int, int>> nested[] = {{{1}, {2, 3}}, {{4}, {5, 6}}, {{7}, {8, 9}}};
using Result = cuda::std::ranges::elements_view<
cuda::std::ranges::elements_view<cuda::std::ranges::ref_view<cuda::std::pair<cuda::std::tuple<int>, cuda::std::tuple<int, int>>[3]>, 1>,
0>;
auto const partial = cuda::std::views::values | cuda::std::views::keys;
decltype(auto) result = nested | partial;
static_assert(cuda::std::same_as<decltype(result), Result>);
auto expected = {2, 5, 8};
assert(equal(result, expected));
}

return true;
}

int main(int, char**) {
test();
#if defined(_LIBCUDACXX_ADDRESSOF) \
&& !defined(TEST_COMPILER_NVCC_BELOW_11_3)
static_assert(test());
#endif // defined(_LIBCUDACXX_ADDRESSOF) && !defined(TEST_COMPILER_NVCC_BELOW_11_3)

return 0;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
// SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES
//
//===----------------------------------------------------------------------===//

// UNSUPPORTED: c++03, c++11, c++14

// constexpr V base() const & requires copy_constructible<V> { return base_; }
// constexpr V base() && { return cuda::std::move(base_); }

#include <cuda/std/cassert>
#include <cuda/std/ranges>
#include <cuda/std/tuple>
#include <cuda/std/type_traits>
#include <cuda/std/utility>

#include "test_macros.h"
#include "MoveOnly.h"

struct View : cuda::std::ranges::view_base {
int i;
__host__ __device__ cuda::std::tuple<int>* begin() const;
__host__ __device__ cuda::std::tuple<int>* end() const;
};

struct MoveOnlyView : View {
MoveOnly mo;
};

#if TEST_STD_VER > 17
template <class T>
concept HasBase = requires(T&& t) { cuda::std::forward<T>(t).base(); };
#else
template <class T, class = void>
inline constexpr bool HasBase = false;

template <class T>
inline constexpr bool HasBase<T, cuda::std::void_t<decltype(cuda::std::declval<T>().base())>> = true;
#endif

static_assert(HasBase<cuda::std::ranges::elements_view<View, 0> const&>);
static_assert(HasBase<cuda::std::ranges::elements_view<View, 0>&&>);

static_assert(!HasBase<cuda::std::ranges::elements_view<MoveOnlyView, 0> const&>);
static_assert(HasBase<cuda::std::ranges::elements_view<MoveOnlyView, 0>&&>);

__host__ __device__ constexpr bool test() {
// const &
{
const cuda::std::ranges::elements_view<View, 0> ev{View{{}, 5}};
decltype(auto) v = ev.base();
static_assert(cuda::std::same_as<decltype(v), View>);
assert(v.i == 5);
}

// &
{
cuda::std::ranges::elements_view<View, 0> ev{View{{}, 5}};
decltype(auto) v = ev.base();
static_assert(cuda::std::same_as<decltype(v), View>);
assert(v.i == 5);
}

// &&
{
cuda::std::ranges::elements_view<View, 0> ev{View{{}, 5}};
decltype(auto) v = cuda::std::move(ev).base();
static_assert(cuda::std::same_as<decltype(v), View>);
assert(v.i == 5);
}

// const &&
{
const cuda::std::ranges::elements_view<View, 0> ev{View{{}, 5}};
decltype(auto) v = cuda::std::move(ev).base();
static_assert(cuda::std::same_as<decltype(v), View>);
assert(v.i == 5);
}

// move only
{
cuda::std::ranges::elements_view<MoveOnlyView, 0> ev{MoveOnlyView{{}, 5}};
decltype(auto) v = cuda::std::move(ev).base();
static_assert(cuda::std::same_as<decltype(v), MoveOnlyView>);
assert(v.mo.get() == 5);
}

return true;
}

int main(int, char**) {
test();
static_assert(test());
return 0;
}
Loading

0 comments on commit 269b29f

Please sign in to comment.