From 65cd631932f8aa9b002e1e7d987752944b51d997 Mon Sep 17 00:00:00 2001 From: Mikhail Dvorskiy Date: Wed, 8 May 2024 12:14:54 +0200 Subject: [PATCH 01/19] [oneDPL][hetero][ranges][test] + xpu_test for std transform_view --- .../ranges/xpu_api/xpu_std_ranges_test.h | 32 +++++++++++++++ .../xpu_api/xpu_std_transform_view.pass.cpp | 40 +++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 test/parallel_api/ranges/xpu_api/xpu_std_ranges_test.h create mode 100644 test/parallel_api/ranges/xpu_api/xpu_std_transform_view.pass.cpp diff --git a/test/parallel_api/ranges/xpu_api/xpu_std_ranges_test.h b/test/parallel_api/ranges/xpu_api/xpu_std_ranges_test.h new file mode 100644 index 0000000000..a45dd46de5 --- /dev/null +++ b/test/parallel_api/ranges/xpu_api/xpu_std_ranges_test.h @@ -0,0 +1,32 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Copyright (C) Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// This file incorporates work covered by the following copyright and permission +// notice: +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// +//===----------------------------------------------------------------------===// + +template +bool +kernel_test(Test test) +{ + sycl::queue deviceQueue = TestUtils::get_test_queue(); + bool ret = false; + sycl::range<1> numOfItems{1}; + sycl::buffer buffer1(&ret, numOfItems); + deviceQueue.submit([&](sycl::handler& cgh) { + auto ret_access = buffer1.get_access(cgh); + cgh.single_task([=]() { + ret_access[0] = test(); //run test + }); + }); + + return buffer1.get_host_access(sycl::read_only)[0]; +} diff --git a/test/parallel_api/ranges/xpu_api/xpu_std_transform_view.pass.cpp b/test/parallel_api/ranges/xpu_api/xpu_std_transform_view.pass.cpp new file mode 100644 index 0000000000..621c419d1f --- /dev/null +++ b/test/parallel_api/ranges/xpu_api/xpu_std_transform_view.pass.cpp @@ -0,0 +1,40 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Copyright (C) Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// This file incorporates work covered by the following copyright and permission +// notice: +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// +//===----------------------------------------------------------------------===// + +#include "support/test_config.h" +#include "support/test_macros.h" +#include "support/utils.h" + +#include "xpu_std_ranges_test.h" + +#if _ENABLE_STD_RANGES_TESTING +#include +#endif //_ENABLE_STD_RANGES_TESTING + +int +main() +{ +#if _ENABLE_STD_RANGES_TESTING + auto test = [](){ + int a[4] = {0, 0, 0, 0}; + auto res = std::ranges::subrange(a, a+4) | std::ranges::views::transform([](auto v) { return v + 1;}); + return res[0] == 1 && res[1] == 1 && res[2] == 1 && res[3] == 1; + }; + const bool res = kernel_test(test); + EXPECT_TRUE(res, "Wrong result of transform_view check within a kernel"); +#endif //_ENABLE_STD_RANGES_TESTING + + return TestUtils::done(_ENABLE_STD_RANGES_TESTING); +} \ No newline at end of file From fc5ca24c0485540a9ae2bd1ac44304498e482ab6 Mon Sep 17 00:00:00 2001 From: Mikhail Dvorskiy Date: Wed, 8 May 2024 12:26:06 +0200 Subject: [PATCH 02/19] [oneDPL][hetero][ranges][test] + xpu_test for std iota_view --- .../ranges/xpu_api/xpu_std_iota_view.pass.cpp | 38 +++++++++++++++++++ .../xpu_api/xpu_std_transform_view.pass.cpp | 3 +- 2 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 test/parallel_api/ranges/xpu_api/xpu_std_iota_view.pass.cpp diff --git a/test/parallel_api/ranges/xpu_api/xpu_std_iota_view.pass.cpp b/test/parallel_api/ranges/xpu_api/xpu_std_iota_view.pass.cpp new file mode 100644 index 0000000000..5e36f67715 --- /dev/null +++ b/test/parallel_api/ranges/xpu_api/xpu_std_iota_view.pass.cpp @@ -0,0 +1,38 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Copyright (C) Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// This file incorporates work covered by the following copyright and permission +// notice: +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// +//===----------------------------------------------------------------------===// + +#include "support/test_config.h" +#include "support/test_macros.h" +#include "support/utils.h" + +#if _ENABLE_STD_RANGES_TESTING +#include +#include "xpu_std_ranges_test.h" +#endif //_ENABLE_STD_RANGES_TESTING + +int +main() +{ +#if _ENABLE_STD_RANGES_TESTING + auto test = [](){ + auto res = std::ranges::views::iota(0, 4); + return res.size() == 4 && res[0] == 0 && res[1] == 1 && res[2] == 2 && res[3] == 3; + }; + const bool res = kernel_test(test); + EXPECT_TRUE(res, "Wrong result of iota_view check within a kernel"); +#endif //_ENABLE_STD_RANGES_TESTING + + return TestUtils::done(_ENABLE_STD_RANGES_TESTING); +} \ No newline at end of file diff --git a/test/parallel_api/ranges/xpu_api/xpu_std_transform_view.pass.cpp b/test/parallel_api/ranges/xpu_api/xpu_std_transform_view.pass.cpp index 621c419d1f..9266fce4f9 100644 --- a/test/parallel_api/ranges/xpu_api/xpu_std_transform_view.pass.cpp +++ b/test/parallel_api/ranges/xpu_api/xpu_std_transform_view.pass.cpp @@ -17,10 +17,9 @@ #include "support/test_macros.h" #include "support/utils.h" -#include "xpu_std_ranges_test.h" - #if _ENABLE_STD_RANGES_TESTING #include +#include "xpu_std_ranges_test.h" #endif //_ENABLE_STD_RANGES_TESTING int From b85d78531300ded7a85a1ca1e08d438d1125fb58 Mon Sep 17 00:00:00 2001 From: Mikhail Dvorskiy Date: Wed, 8 May 2024 15:17:14 +0200 Subject: [PATCH 03/19] [oneDPL][hetero][ranges][test] + xpu_test for std::ranges::views:: single, all, reverse, drop. take --- .../ranges/xpu_api/xpu_std_all_view.pass.cpp | 38 +++++++++++++++++++ .../ranges/xpu_api/xpu_std_drop_view.pass.cpp | 38 +++++++++++++++++++ .../xpu_api/xpu_std_reverse_view.pass.cpp | 38 +++++++++++++++++++ .../xpu_api/xpu_std_single_view.pass.cpp | 38 +++++++++++++++++++ .../ranges/xpu_api/xpu_std_take_view.pass.cpp | 38 +++++++++++++++++++ 5 files changed, 190 insertions(+) create mode 100644 test/parallel_api/ranges/xpu_api/xpu_std_all_view.pass.cpp create mode 100644 test/parallel_api/ranges/xpu_api/xpu_std_drop_view.pass.cpp create mode 100644 test/parallel_api/ranges/xpu_api/xpu_std_reverse_view.pass.cpp create mode 100644 test/parallel_api/ranges/xpu_api/xpu_std_single_view.pass.cpp create mode 100644 test/parallel_api/ranges/xpu_api/xpu_std_take_view.pass.cpp diff --git a/test/parallel_api/ranges/xpu_api/xpu_std_all_view.pass.cpp b/test/parallel_api/ranges/xpu_api/xpu_std_all_view.pass.cpp new file mode 100644 index 0000000000..5f88560d28 --- /dev/null +++ b/test/parallel_api/ranges/xpu_api/xpu_std_all_view.pass.cpp @@ -0,0 +1,38 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Copyright (C) Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// This file incorporates work covered by the following copyright and permission +// notice: +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// +//===----------------------------------------------------------------------===// + +#include "support/test_config.h" +#include "support/test_macros.h" +#include "support/utils.h" + +#if _ENABLE_STD_RANGES_TESTING +#include +#include "xpu_std_ranges_test.h" +#endif //_ENABLE_STD_RANGES_TESTING + +int +main() +{ +#if _ENABLE_STD_RANGES_TESTING + auto test = [](){ + auto res = std::ranges::views::iota(0, 4) | std::ranges::views::all; + return res.size() == 4 && res[0] == 0 && res[1] == 1 && res[2] == 2 && res[3] == 3; + }; + const bool res = kernel_test(test); + EXPECT_TRUE(res, "Wrong result of all_view check within a kernel"); +#endif //_ENABLE_STD_RANGES_TESTING + + return TestUtils::done(_ENABLE_STD_RANGES_TESTING); +} \ No newline at end of file diff --git a/test/parallel_api/ranges/xpu_api/xpu_std_drop_view.pass.cpp b/test/parallel_api/ranges/xpu_api/xpu_std_drop_view.pass.cpp new file mode 100644 index 0000000000..066dfb62f8 --- /dev/null +++ b/test/parallel_api/ranges/xpu_api/xpu_std_drop_view.pass.cpp @@ -0,0 +1,38 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Copyright (C) Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// This file incorporates work covered by the following copyright and permission +// notice: +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// +//===----------------------------------------------------------------------===// + +#include "support/test_config.h" +#include "support/test_macros.h" +#include "support/utils.h" + +#if _ENABLE_STD_RANGES_TESTING +#include +#include "xpu_std_ranges_test.h" +#endif //_ENABLE_STD_RANGES_TESTING + +int +main() +{ +#if _ENABLE_STD_RANGES_TESTING + auto test = [](){ + auto res = std::ranges::views::iota(0, 4) | std::ranges::views::drop(2); + return res.size() == 2 && res[0] == 2 && res[1] == 3; + }; + const bool res = kernel_test(test); + EXPECT_TRUE(res, "Wrong result of drop_view check within a kernel"); +#endif //_ENABLE_STD_RANGES_TESTING + + return TestUtils::done(_ENABLE_STD_RANGES_TESTING); +} \ No newline at end of file diff --git a/test/parallel_api/ranges/xpu_api/xpu_std_reverse_view.pass.cpp b/test/parallel_api/ranges/xpu_api/xpu_std_reverse_view.pass.cpp new file mode 100644 index 0000000000..c1ef06b639 --- /dev/null +++ b/test/parallel_api/ranges/xpu_api/xpu_std_reverse_view.pass.cpp @@ -0,0 +1,38 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Copyright (C) Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// This file incorporates work covered by the following copyright and permission +// notice: +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// +//===----------------------------------------------------------------------===// + +#include "support/test_config.h" +#include "support/test_macros.h" +#include "support/utils.h" + +#if _ENABLE_STD_RANGES_TESTING +#include +#include "xpu_std_ranges_test.h" +#endif //_ENABLE_STD_RANGES_TESTING + +int +main() +{ +#if _ENABLE_STD_RANGES_TESTING + auto test = [](){ + auto res = std::ranges::views::iota(0, 4) | std::ranges::views::reverse; + return res.size() == 4 && res[0] == 3 && res[1] == 2 && res[2] == 1 && res[3] == 0; + }; + const bool res = kernel_test(test); + EXPECT_TRUE(res, "Wrong result of reverse_view check within a kernel"); +#endif //_ENABLE_STD_RANGES_TESTING + + return TestUtils::done(_ENABLE_STD_RANGES_TESTING); +} \ No newline at end of file diff --git a/test/parallel_api/ranges/xpu_api/xpu_std_single_view.pass.cpp b/test/parallel_api/ranges/xpu_api/xpu_std_single_view.pass.cpp new file mode 100644 index 0000000000..175311846e --- /dev/null +++ b/test/parallel_api/ranges/xpu_api/xpu_std_single_view.pass.cpp @@ -0,0 +1,38 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Copyright (C) Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// This file incorporates work covered by the following copyright and permission +// notice: +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// +//===----------------------------------------------------------------------===// + +#include "support/test_config.h" +#include "support/test_macros.h" +#include "support/utils.h" + +#if _ENABLE_STD_RANGES_TESTING +#include +#include "xpu_std_ranges_test.h" +#endif //_ENABLE_STD_RANGES_TESTING + +int +main() +{ +#if _ENABLE_STD_RANGES_TESTING + auto test = [](){ + auto res = std::ranges::views::single(1); + return res.size() == 1 && res[0] == 1; + }; + const bool res = kernel_test(test); + EXPECT_TRUE(res, "Wrong result of single_view check within a kernel"); +#endif //_ENABLE_STD_RANGES_TESTING + + return TestUtils::done(_ENABLE_STD_RANGES_TESTING); +} \ No newline at end of file diff --git a/test/parallel_api/ranges/xpu_api/xpu_std_take_view.pass.cpp b/test/parallel_api/ranges/xpu_api/xpu_std_take_view.pass.cpp new file mode 100644 index 0000000000..01072e74b4 --- /dev/null +++ b/test/parallel_api/ranges/xpu_api/xpu_std_take_view.pass.cpp @@ -0,0 +1,38 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Copyright (C) Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// This file incorporates work covered by the following copyright and permission +// notice: +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// +//===----------------------------------------------------------------------===// + +#include "support/test_config.h" +#include "support/test_macros.h" +#include "support/utils.h" + +#if _ENABLE_STD_RANGES_TESTING +#include +#include "xpu_std_ranges_test.h" +#endif //_ENABLE_STD_RANGES_TESTING + +int +main() +{ +#if _ENABLE_STD_RANGES_TESTING + auto test = [](){ + auto res = std::ranges::views::iota(0, 4) | std::ranges::views::take(2); + return res.size() == 2 && res[0] == 0 && res[1] == 1; + }; + const bool res = kernel_test(test); + EXPECT_TRUE(res, "Wrong result of take_view check within a kernel"); +#endif //_ENABLE_STD_RANGES_TESTING + + return TestUtils::done(_ENABLE_STD_RANGES_TESTING); +} \ No newline at end of file From 5557d263a21d4c70cab20102b2e2ed287b35a359 Mon Sep 17 00:00:00 2001 From: Mikhail Dvorskiy Date: Wed, 8 May 2024 16:00:44 +0200 Subject: [PATCH 04/19] [oneDPL][hetero][ranges][test] + empty line in the end of each file --- test/parallel_api/ranges/xpu_api/xpu_std_all_view.pass.cpp | 2 +- test/parallel_api/ranges/xpu_api/xpu_std_drop_view.pass.cpp | 2 +- test/parallel_api/ranges/xpu_api/xpu_std_iota_view.pass.cpp | 2 +- test/parallel_api/ranges/xpu_api/xpu_std_reverse_view.pass.cpp | 2 +- test/parallel_api/ranges/xpu_api/xpu_std_single_view.pass.cpp | 2 +- test/parallel_api/ranges/xpu_api/xpu_std_take_view.pass.cpp | 2 +- .../parallel_api/ranges/xpu_api/xpu_std_transform_view.pass.cpp | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/test/parallel_api/ranges/xpu_api/xpu_std_all_view.pass.cpp b/test/parallel_api/ranges/xpu_api/xpu_std_all_view.pass.cpp index 5f88560d28..726a390bad 100644 --- a/test/parallel_api/ranges/xpu_api/xpu_std_all_view.pass.cpp +++ b/test/parallel_api/ranges/xpu_api/xpu_std_all_view.pass.cpp @@ -35,4 +35,4 @@ main() #endif //_ENABLE_STD_RANGES_TESTING return TestUtils::done(_ENABLE_STD_RANGES_TESTING); -} \ No newline at end of file +} diff --git a/test/parallel_api/ranges/xpu_api/xpu_std_drop_view.pass.cpp b/test/parallel_api/ranges/xpu_api/xpu_std_drop_view.pass.cpp index 066dfb62f8..1c063ad6eb 100644 --- a/test/parallel_api/ranges/xpu_api/xpu_std_drop_view.pass.cpp +++ b/test/parallel_api/ranges/xpu_api/xpu_std_drop_view.pass.cpp @@ -35,4 +35,4 @@ main() #endif //_ENABLE_STD_RANGES_TESTING return TestUtils::done(_ENABLE_STD_RANGES_TESTING); -} \ No newline at end of file +} diff --git a/test/parallel_api/ranges/xpu_api/xpu_std_iota_view.pass.cpp b/test/parallel_api/ranges/xpu_api/xpu_std_iota_view.pass.cpp index 5e36f67715..5b39140a22 100644 --- a/test/parallel_api/ranges/xpu_api/xpu_std_iota_view.pass.cpp +++ b/test/parallel_api/ranges/xpu_api/xpu_std_iota_view.pass.cpp @@ -35,4 +35,4 @@ main() #endif //_ENABLE_STD_RANGES_TESTING return TestUtils::done(_ENABLE_STD_RANGES_TESTING); -} \ No newline at end of file +} diff --git a/test/parallel_api/ranges/xpu_api/xpu_std_reverse_view.pass.cpp b/test/parallel_api/ranges/xpu_api/xpu_std_reverse_view.pass.cpp index c1ef06b639..09ec9cbcfd 100644 --- a/test/parallel_api/ranges/xpu_api/xpu_std_reverse_view.pass.cpp +++ b/test/parallel_api/ranges/xpu_api/xpu_std_reverse_view.pass.cpp @@ -35,4 +35,4 @@ main() #endif //_ENABLE_STD_RANGES_TESTING return TestUtils::done(_ENABLE_STD_RANGES_TESTING); -} \ No newline at end of file +} diff --git a/test/parallel_api/ranges/xpu_api/xpu_std_single_view.pass.cpp b/test/parallel_api/ranges/xpu_api/xpu_std_single_view.pass.cpp index 175311846e..c809818175 100644 --- a/test/parallel_api/ranges/xpu_api/xpu_std_single_view.pass.cpp +++ b/test/parallel_api/ranges/xpu_api/xpu_std_single_view.pass.cpp @@ -35,4 +35,4 @@ main() #endif //_ENABLE_STD_RANGES_TESTING return TestUtils::done(_ENABLE_STD_RANGES_TESTING); -} \ No newline at end of file +} diff --git a/test/parallel_api/ranges/xpu_api/xpu_std_take_view.pass.cpp b/test/parallel_api/ranges/xpu_api/xpu_std_take_view.pass.cpp index 01072e74b4..04306f2b24 100644 --- a/test/parallel_api/ranges/xpu_api/xpu_std_take_view.pass.cpp +++ b/test/parallel_api/ranges/xpu_api/xpu_std_take_view.pass.cpp @@ -35,4 +35,4 @@ main() #endif //_ENABLE_STD_RANGES_TESTING return TestUtils::done(_ENABLE_STD_RANGES_TESTING); -} \ No newline at end of file +} diff --git a/test/parallel_api/ranges/xpu_api/xpu_std_transform_view.pass.cpp b/test/parallel_api/ranges/xpu_api/xpu_std_transform_view.pass.cpp index 9266fce4f9..b78f42ad10 100644 --- a/test/parallel_api/ranges/xpu_api/xpu_std_transform_view.pass.cpp +++ b/test/parallel_api/ranges/xpu_api/xpu_std_transform_view.pass.cpp @@ -36,4 +36,4 @@ main() #endif //_ENABLE_STD_RANGES_TESTING return TestUtils::done(_ENABLE_STD_RANGES_TESTING); -} \ No newline at end of file +} From 721482ce93b11cf764c3562c33027321c661f90b Mon Sep 17 00:00:00 2001 From: Mikhail Dvorskiy Date: Mon, 13 May 2024 14:30:51 +0200 Subject: [PATCH 05/19] [oneDPL][hetero][ranges][test] + move to the other place: oneDPL\test\xpu_api\ranges --- test/xpu_api/ranges/xpu_std_all_view.pass.cpp | 38 ++++++++++++++++++ .../xpu_api/ranges/xpu_std_drop_view.pass.cpp | 38 ++++++++++++++++++ .../xpu_api/ranges/xpu_std_iota_view.pass.cpp | 38 ++++++++++++++++++ test/xpu_api/ranges/xpu_std_ranges_test.h | 32 +++++++++++++++ .../ranges/xpu_std_reverse_view.pass.cpp | 38 ++++++++++++++++++ .../ranges/xpu_std_single_view.pass.cpp | 38 ++++++++++++++++++ .../xpu_api/ranges/xpu_std_take_view.pass.cpp | 38 ++++++++++++++++++ .../ranges/xpu_std_transform_view.pass.cpp | 39 +++++++++++++++++++ 8 files changed, 299 insertions(+) create mode 100644 test/xpu_api/ranges/xpu_std_all_view.pass.cpp create mode 100644 test/xpu_api/ranges/xpu_std_drop_view.pass.cpp create mode 100644 test/xpu_api/ranges/xpu_std_iota_view.pass.cpp create mode 100644 test/xpu_api/ranges/xpu_std_ranges_test.h create mode 100644 test/xpu_api/ranges/xpu_std_reverse_view.pass.cpp create mode 100644 test/xpu_api/ranges/xpu_std_single_view.pass.cpp create mode 100644 test/xpu_api/ranges/xpu_std_take_view.pass.cpp create mode 100644 test/xpu_api/ranges/xpu_std_transform_view.pass.cpp diff --git a/test/xpu_api/ranges/xpu_std_all_view.pass.cpp b/test/xpu_api/ranges/xpu_std_all_view.pass.cpp new file mode 100644 index 0000000000..726a390bad --- /dev/null +++ b/test/xpu_api/ranges/xpu_std_all_view.pass.cpp @@ -0,0 +1,38 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Copyright (C) Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// This file incorporates work covered by the following copyright and permission +// notice: +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// +//===----------------------------------------------------------------------===// + +#include "support/test_config.h" +#include "support/test_macros.h" +#include "support/utils.h" + +#if _ENABLE_STD_RANGES_TESTING +#include +#include "xpu_std_ranges_test.h" +#endif //_ENABLE_STD_RANGES_TESTING + +int +main() +{ +#if _ENABLE_STD_RANGES_TESTING + auto test = [](){ + auto res = std::ranges::views::iota(0, 4) | std::ranges::views::all; + return res.size() == 4 && res[0] == 0 && res[1] == 1 && res[2] == 2 && res[3] == 3; + }; + const bool res = kernel_test(test); + EXPECT_TRUE(res, "Wrong result of all_view check within a kernel"); +#endif //_ENABLE_STD_RANGES_TESTING + + return TestUtils::done(_ENABLE_STD_RANGES_TESTING); +} diff --git a/test/xpu_api/ranges/xpu_std_drop_view.pass.cpp b/test/xpu_api/ranges/xpu_std_drop_view.pass.cpp new file mode 100644 index 0000000000..1c063ad6eb --- /dev/null +++ b/test/xpu_api/ranges/xpu_std_drop_view.pass.cpp @@ -0,0 +1,38 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Copyright (C) Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// This file incorporates work covered by the following copyright and permission +// notice: +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// +//===----------------------------------------------------------------------===// + +#include "support/test_config.h" +#include "support/test_macros.h" +#include "support/utils.h" + +#if _ENABLE_STD_RANGES_TESTING +#include +#include "xpu_std_ranges_test.h" +#endif //_ENABLE_STD_RANGES_TESTING + +int +main() +{ +#if _ENABLE_STD_RANGES_TESTING + auto test = [](){ + auto res = std::ranges::views::iota(0, 4) | std::ranges::views::drop(2); + return res.size() == 2 && res[0] == 2 && res[1] == 3; + }; + const bool res = kernel_test(test); + EXPECT_TRUE(res, "Wrong result of drop_view check within a kernel"); +#endif //_ENABLE_STD_RANGES_TESTING + + return TestUtils::done(_ENABLE_STD_RANGES_TESTING); +} diff --git a/test/xpu_api/ranges/xpu_std_iota_view.pass.cpp b/test/xpu_api/ranges/xpu_std_iota_view.pass.cpp new file mode 100644 index 0000000000..5b39140a22 --- /dev/null +++ b/test/xpu_api/ranges/xpu_std_iota_view.pass.cpp @@ -0,0 +1,38 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Copyright (C) Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// This file incorporates work covered by the following copyright and permission +// notice: +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// +//===----------------------------------------------------------------------===// + +#include "support/test_config.h" +#include "support/test_macros.h" +#include "support/utils.h" + +#if _ENABLE_STD_RANGES_TESTING +#include +#include "xpu_std_ranges_test.h" +#endif //_ENABLE_STD_RANGES_TESTING + +int +main() +{ +#if _ENABLE_STD_RANGES_TESTING + auto test = [](){ + auto res = std::ranges::views::iota(0, 4); + return res.size() == 4 && res[0] == 0 && res[1] == 1 && res[2] == 2 && res[3] == 3; + }; + const bool res = kernel_test(test); + EXPECT_TRUE(res, "Wrong result of iota_view check within a kernel"); +#endif //_ENABLE_STD_RANGES_TESTING + + return TestUtils::done(_ENABLE_STD_RANGES_TESTING); +} diff --git a/test/xpu_api/ranges/xpu_std_ranges_test.h b/test/xpu_api/ranges/xpu_std_ranges_test.h new file mode 100644 index 0000000000..a45dd46de5 --- /dev/null +++ b/test/xpu_api/ranges/xpu_std_ranges_test.h @@ -0,0 +1,32 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Copyright (C) Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// This file incorporates work covered by the following copyright and permission +// notice: +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// +//===----------------------------------------------------------------------===// + +template +bool +kernel_test(Test test) +{ + sycl::queue deviceQueue = TestUtils::get_test_queue(); + bool ret = false; + sycl::range<1> numOfItems{1}; + sycl::buffer buffer1(&ret, numOfItems); + deviceQueue.submit([&](sycl::handler& cgh) { + auto ret_access = buffer1.get_access(cgh); + cgh.single_task([=]() { + ret_access[0] = test(); //run test + }); + }); + + return buffer1.get_host_access(sycl::read_only)[0]; +} diff --git a/test/xpu_api/ranges/xpu_std_reverse_view.pass.cpp b/test/xpu_api/ranges/xpu_std_reverse_view.pass.cpp new file mode 100644 index 0000000000..09ec9cbcfd --- /dev/null +++ b/test/xpu_api/ranges/xpu_std_reverse_view.pass.cpp @@ -0,0 +1,38 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Copyright (C) Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// This file incorporates work covered by the following copyright and permission +// notice: +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// +//===----------------------------------------------------------------------===// + +#include "support/test_config.h" +#include "support/test_macros.h" +#include "support/utils.h" + +#if _ENABLE_STD_RANGES_TESTING +#include +#include "xpu_std_ranges_test.h" +#endif //_ENABLE_STD_RANGES_TESTING + +int +main() +{ +#if _ENABLE_STD_RANGES_TESTING + auto test = [](){ + auto res = std::ranges::views::iota(0, 4) | std::ranges::views::reverse; + return res.size() == 4 && res[0] == 3 && res[1] == 2 && res[2] == 1 && res[3] == 0; + }; + const bool res = kernel_test(test); + EXPECT_TRUE(res, "Wrong result of reverse_view check within a kernel"); +#endif //_ENABLE_STD_RANGES_TESTING + + return TestUtils::done(_ENABLE_STD_RANGES_TESTING); +} diff --git a/test/xpu_api/ranges/xpu_std_single_view.pass.cpp b/test/xpu_api/ranges/xpu_std_single_view.pass.cpp new file mode 100644 index 0000000000..c809818175 --- /dev/null +++ b/test/xpu_api/ranges/xpu_std_single_view.pass.cpp @@ -0,0 +1,38 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Copyright (C) Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// This file incorporates work covered by the following copyright and permission +// notice: +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// +//===----------------------------------------------------------------------===// + +#include "support/test_config.h" +#include "support/test_macros.h" +#include "support/utils.h" + +#if _ENABLE_STD_RANGES_TESTING +#include +#include "xpu_std_ranges_test.h" +#endif //_ENABLE_STD_RANGES_TESTING + +int +main() +{ +#if _ENABLE_STD_RANGES_TESTING + auto test = [](){ + auto res = std::ranges::views::single(1); + return res.size() == 1 && res[0] == 1; + }; + const bool res = kernel_test(test); + EXPECT_TRUE(res, "Wrong result of single_view check within a kernel"); +#endif //_ENABLE_STD_RANGES_TESTING + + return TestUtils::done(_ENABLE_STD_RANGES_TESTING); +} diff --git a/test/xpu_api/ranges/xpu_std_take_view.pass.cpp b/test/xpu_api/ranges/xpu_std_take_view.pass.cpp new file mode 100644 index 0000000000..04306f2b24 --- /dev/null +++ b/test/xpu_api/ranges/xpu_std_take_view.pass.cpp @@ -0,0 +1,38 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Copyright (C) Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// This file incorporates work covered by the following copyright and permission +// notice: +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// +//===----------------------------------------------------------------------===// + +#include "support/test_config.h" +#include "support/test_macros.h" +#include "support/utils.h" + +#if _ENABLE_STD_RANGES_TESTING +#include +#include "xpu_std_ranges_test.h" +#endif //_ENABLE_STD_RANGES_TESTING + +int +main() +{ +#if _ENABLE_STD_RANGES_TESTING + auto test = [](){ + auto res = std::ranges::views::iota(0, 4) | std::ranges::views::take(2); + return res.size() == 2 && res[0] == 0 && res[1] == 1; + }; + const bool res = kernel_test(test); + EXPECT_TRUE(res, "Wrong result of take_view check within a kernel"); +#endif //_ENABLE_STD_RANGES_TESTING + + return TestUtils::done(_ENABLE_STD_RANGES_TESTING); +} diff --git a/test/xpu_api/ranges/xpu_std_transform_view.pass.cpp b/test/xpu_api/ranges/xpu_std_transform_view.pass.cpp new file mode 100644 index 0000000000..b78f42ad10 --- /dev/null +++ b/test/xpu_api/ranges/xpu_std_transform_view.pass.cpp @@ -0,0 +1,39 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Copyright (C) Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// This file incorporates work covered by the following copyright and permission +// notice: +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// +//===----------------------------------------------------------------------===// + +#include "support/test_config.h" +#include "support/test_macros.h" +#include "support/utils.h" + +#if _ENABLE_STD_RANGES_TESTING +#include +#include "xpu_std_ranges_test.h" +#endif //_ENABLE_STD_RANGES_TESTING + +int +main() +{ +#if _ENABLE_STD_RANGES_TESTING + auto test = [](){ + int a[4] = {0, 0, 0, 0}; + auto res = std::ranges::subrange(a, a+4) | std::ranges::views::transform([](auto v) { return v + 1;}); + return res[0] == 1 && res[1] == 1 && res[2] == 1 && res[3] == 1; + }; + const bool res = kernel_test(test); + EXPECT_TRUE(res, "Wrong result of transform_view check within a kernel"); +#endif //_ENABLE_STD_RANGES_TESTING + + return TestUtils::done(_ENABLE_STD_RANGES_TESTING); +} From 639d0596c003c317b8f03d3a1f868feb3a886f78 Mon Sep 17 00:00:00 2001 From: Mikhail Dvorskiy Date: Tue, 14 May 2024 14:19:37 +0200 Subject: [PATCH 06/19] [oneDPL][hetero][ranges][test] + modified LLVM std test for std::ranges::views::all --- test/xpu_api/ranges/all.pass.cpp | 216 ++++ test/xpu_api/ranges/test_iterators.h | 1597 +++++++++++++++++++++++++ test/xpu_api/ranges/test_macros.h | 490 ++++++++ test/xpu_api/ranges/test_range.h | 109 ++ test/xpu_api/ranges/type_algorithms.h | 149 +++ 5 files changed, 2561 insertions(+) create mode 100644 test/xpu_api/ranges/all.pass.cpp create mode 100644 test/xpu_api/ranges/test_iterators.h create mode 100644 test/xpu_api/ranges/test_macros.h create mode 100644 test/xpu_api/ranges/test_range.h create mode 100644 test/xpu_api/ranges/type_algorithms.h diff --git a/test/xpu_api/ranges/all.pass.cpp b/test/xpu_api/ranges/all.pass.cpp new file mode 100644 index 0000000000..a393662ef9 --- /dev/null +++ b/test/xpu_api/ranges/all.pass.cpp @@ -0,0 +1,216 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +// std::views::all; + +#include "support/test_config.h" +#include "support/utils.h" +#include "test_macros.h" +#include "test_iterators.h" +#include "test_range.h" + +#include + +#include +#include +#include +#include + +#include "xpu_std_ranges_test.h" + +template +struct View : std::ranges::view_base { + int* globalBuff; + int start_ = 0; + explicit View(int* p) noexcept(IsNoexcept): globalBuff(p) {} + constexpr explicit View(int start, int* p) : start_(start), globalBuff(p) {} + View(View&&) noexcept(IsNoexcept) = default; + View& operator=(View&&) noexcept(IsNoexcept) = default; + constexpr int* begin() const { return globalBuff + start_; } + constexpr int* end() const { return globalBuff + 8; } +}; +//static_assert(std::ranges::view>); +//static_assert(std::ranges::view>); + +template +struct CopyableView : std::ranges::view_base { + int* globalBuff; + int start_ = 0; + explicit CopyableView(int* p) noexcept(IsNoexcept): globalBuff(p) {} + CopyableView(CopyableView const&) noexcept(IsNoexcept) = default; + CopyableView& operator=(CopyableView const&) noexcept(IsNoexcept) = default; + constexpr explicit CopyableView(int start, int* p) noexcept : start_(start), globalBuff(p) {} + constexpr int* begin() const { return globalBuff + start_; } + constexpr int* end() const { return globalBuff + 8; } +}; +//static_assert(std::ranges::view>); +//static_assert(std::ranges::view>); + +struct MoveOnlyView : std::ranges::view_base{ + MoveOnlyView() = default; + MoveOnlyView(const MoveOnlyView&) = delete; + MoveOnlyView& operator=(const MoveOnlyView&) = delete; + MoveOnlyView(MoveOnlyView&&) = default; + MoveOnlyView& operator=(MoveOnlyView&&) = default; + + int* begin() const; + int* end() const; +}; + +struct Range { + int* globalBuff; + int start_; + constexpr explicit Range(int start, int* p) noexcept : start_(start), globalBuff(p) {} + constexpr int* begin() const { return globalBuff + start_; } + constexpr int* end() const { return globalBuff + 8; } +}; + +struct BorrowableRange { + int* globalBuff; + int start_; + constexpr explicit BorrowableRange(int start, int* p) noexcept : start_(start), globalBuff(p) {} + constexpr int* begin() const { return globalBuff + start_; } + constexpr int* end() const { return globalBuff + 8; } +}; +template<> +inline constexpr bool std::ranges::enable_borrowed_range = true; + +struct RandomAccessRange { + int* globalBuff; + constexpr explicit RandomAccessRange(int* p): globalBuff(p) {} + constexpr auto begin() { return random_access_iterator(globalBuff); } + constexpr auto end() { return sized_sentinel(random_access_iterator(globalBuff + 8)); } +}; +template<> +inline constexpr bool std::ranges::enable_borrowed_range = true; + +constexpr bool test() { + int globalBuff[8]; + { + ASSERT_SAME_TYPE(decltype(std::views::all(View(globalBuff))), View); + //static_assert(noexcept(std::views::all(View()))); + //static_assert(!noexcept(std::views::all(View()))); + + auto viewCopy = std::views::all(View(2, globalBuff)); + ASSERT_SAME_TYPE(decltype(viewCopy), View); + assert(std::ranges::begin(viewCopy) == globalBuff + 2); + assert(std::ranges::end(viewCopy) == globalBuff + 8); + } + + { + ASSERT_SAME_TYPE(decltype(std::views::all(std::declval&>())), CopyableView); + //static_assert(noexcept(std::views::all(CopyableView(globalBuff)))); + //static_assert(!noexcept(std::views::all(CopyableView()))); + + CopyableView view(2, globalBuff); + auto viewCopy = std::views::all(view); + ASSERT_SAME_TYPE(decltype(viewCopy), CopyableView); + assert(std::ranges::begin(viewCopy) == globalBuff + 2); + assert(std::ranges::end(viewCopy) == globalBuff + 8); + } + + { + Range range(2, globalBuff); + auto ref = std::views::all(range); + ASSERT_SAME_TYPE(decltype(ref), std::ranges::ref_view); + assert(std::ranges::begin(ref) == globalBuff + 2); + assert(std::ranges::end(ref) == globalBuff + 8); + + //auto own = std::views::all(std::move(range)); + //ASSERT_SAME_TYPE(decltype(own), std::ranges::owning_view); + //assert(std::ranges::begin(own) == globalBuff + 2); + //assert(std::ranges::end(own) == globalBuff + 8); + + auto cref = std::views::all(std::as_const(range)); + ASSERT_SAME_TYPE(decltype(cref), std::ranges::ref_view); + assert(std::ranges::begin(cref) == globalBuff + 2); + assert(std::ranges::end(cref) == globalBuff + 8); + + static_assert(!std::is_invocable_v); + } + + { + auto own = std::views::all(BorrowableRange(2, globalBuff)); + //ASSERT_SAME_TYPE(decltype(own), std::ranges::owning_view); + assert(std::ranges::begin(own) == globalBuff + 2); + assert(std::ranges::end(own) == globalBuff + 8); + } + + { + auto own = std::views::all(RandomAccessRange(globalBuff)); + //ASSERT_SAME_TYPE(decltype(own), std::ranges::owning_view); + assert(base(std::ranges::begin(own)) == globalBuff); + assert(base(base(std::ranges::end(own))) == globalBuff + 8); + } + + // Check SFINAE friendliness of the call operator + { + static_assert(!std::is_invocable_v); + static_assert(!std::is_invocable_v); + + // `views::all(v)` is expression equivalent to `decay-copy(v)` if the decayed type + // of `v` models `view`. If `v` is an lvalue-reference to a move-only view, the + // expression should be ill-formed because `v` is not copyable + static_assert(!std::is_invocable_v); + } + + // Test that std::views::all is a range adaptor + { + // Test `v | views::all` + { + Range range(0, globalBuff); + auto result = range | std::views::all; + ASSERT_SAME_TYPE(decltype(result), std::ranges::ref_view); + assert(&result.base() == &range); + } + + // Test `adaptor | views::all` + { + Range range(0, globalBuff); + auto f = [](int i) { return i; }; + auto const partial = std::views::transform(f) | std::views::all; + using Result = std::ranges::transform_view, decltype(f)>; + std::same_as auto result = partial(range); + assert(&result.base().base() == &range); + } + + // Test `views::all | adaptor` + { + Range range(0, globalBuff); + auto f = [](int i) { return i; }; + auto const partial = std::views::all | std::views::transform(f); + using Result = std::ranges::transform_view, decltype(f)>; + std::same_as auto result = partial(range); + assert(&result.base().base() == &range); + } + + { + struct NotAView { }; + static_assert( CanBePiped); + static_assert(!CanBePiped); + } + } + + { + static_assert(std::same_as); + } + + return true; +} + +int main(int, char**) { + + static_assert(test()); + + const bool res = kernel_test([](){ return test();}); + EXPECT_TRUE(res, "Wrong result of all_view check within a kernel"); + + return 0; +} diff --git a/test/xpu_api/ranges/test_iterators.h b/test/xpu_api/ranges/test_iterators.h new file mode 100644 index 0000000000..aa819ecd47 --- /dev/null +++ b/test/xpu_api/ranges/test_iterators.h @@ -0,0 +1,1597 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef SUPPORT_TEST_ITERATORS_H +#define SUPPORT_TEST_ITERATORS_H + +#include +#include +#include +#include +#include +#include +#include + +#include "test_macros.h" +#include "type_algorithms.h" + + +// This iterator meets C++20's Cpp17OutputIterator requirements, as described +// in Table 90 ([output.iterators]). +template +class cpp17_output_iterator +{ + It it_; + + template friend class cpp17_output_iterator; +public: + typedef std::output_iterator_tag iterator_category; + typedef void value_type; + typedef typename std::iterator_traits::difference_type difference_type; + typedef It pointer; + typedef typename std::iterator_traits::reference reference; + + TEST_CONSTEXPR explicit cpp17_output_iterator(It it) : it_(std::move(it)) {} + + template + TEST_CONSTEXPR cpp17_output_iterator(const cpp17_output_iterator& u) : it_(u.it_) {} + + template ::value>::type> + TEST_CONSTEXPR_CXX14 cpp17_output_iterator(cpp17_output_iterator&& u) : it_(u.it_) { u.it_ = U(); } + + TEST_CONSTEXPR reference operator*() const {return *it_;} + + TEST_CONSTEXPR_CXX14 cpp17_output_iterator& operator++() {++it_; return *this;} + TEST_CONSTEXPR_CXX14 cpp17_output_iterator operator++(int) {return cpp17_output_iterator(it_++);} + + friend TEST_CONSTEXPR It base(const cpp17_output_iterator& i) { return i.it_; } + + template + void operator,(T const &) = delete; +}; +#if TEST_STD_VER > 14 +template +cpp17_output_iterator(It) -> cpp17_output_iterator; +#endif + +#if TEST_STD_VER > 17 + static_assert(std::output_iterator, int>); +#endif + +// This iterator meets C++20's Cpp17InputIterator requirements, as described +// in Table 89 ([input.iterators]). +template +class cpp17_input_iterator +{ + typedef std::iterator_traits Traits; + It it_; + + template friend class cpp17_input_iterator; +public: + typedef std::input_iterator_tag iterator_category; + typedef typename Traits::value_type value_type; + typedef typename Traits::difference_type difference_type; + typedef It pointer; + typedef typename Traits::reference reference; + + TEST_CONSTEXPR explicit cpp17_input_iterator(It it) : it_(it) {} + + template + TEST_CONSTEXPR cpp17_input_iterator(const cpp17_input_iterator& u) : it_(u.it_) {} + + template ::value>::type> + TEST_CONSTEXPR_CXX14 cpp17_input_iterator(cpp17_input_iterator&& u) : it_(u.it_) { u.it_ = U(); } + + TEST_CONSTEXPR reference operator*() const {return *it_;} + + TEST_CONSTEXPR_CXX14 cpp17_input_iterator& operator++() {++it_; return *this;} + TEST_CONSTEXPR_CXX14 cpp17_input_iterator operator++(int) {return cpp17_input_iterator(it_++);} + + friend TEST_CONSTEXPR bool operator==(const cpp17_input_iterator& x, const cpp17_input_iterator& y) {return x.it_ == y.it_;} + friend TEST_CONSTEXPR bool operator!=(const cpp17_input_iterator& x, const cpp17_input_iterator& y) {return x.it_ != y.it_;} + + friend TEST_CONSTEXPR It base(const cpp17_input_iterator& i) { return i.it_; } + + template + void operator,(T const &) = delete; +}; +#if TEST_STD_VER > 14 +template +cpp17_input_iterator(It) -> cpp17_input_iterator; +#endif + +#if TEST_STD_VER > 17 + static_assert(std::input_iterator>); +#endif + +template +class forward_iterator +{ + It it_; + + template friend class forward_iterator; +public: + typedef std::forward_iterator_tag iterator_category; + typedef typename std::iterator_traits::value_type value_type; + typedef typename std::iterator_traits::difference_type difference_type; + typedef It pointer; + typedef typename std::iterator_traits::reference reference; + + TEST_CONSTEXPR forward_iterator() : it_() {} + TEST_CONSTEXPR explicit forward_iterator(It it) : it_(it) {} + + template + TEST_CONSTEXPR forward_iterator(const forward_iterator& u) : it_(u.it_) {} + + template ::value>::type> + TEST_CONSTEXPR_CXX14 forward_iterator(forward_iterator&& other) : it_(other.it_) { other.it_ = U(); } + + TEST_CONSTEXPR reference operator*() const {return *it_;} + + TEST_CONSTEXPR_CXX14 forward_iterator& operator++() {++it_; return *this;} + TEST_CONSTEXPR_CXX14 forward_iterator operator++(int) {return forward_iterator(it_++);} + + friend TEST_CONSTEXPR bool operator==(const forward_iterator& x, const forward_iterator& y) {return x.it_ == y.it_;} + friend TEST_CONSTEXPR bool operator!=(const forward_iterator& x, const forward_iterator& y) {return x.it_ != y.it_;} + + friend TEST_CONSTEXPR It base(const forward_iterator& i) { return i.it_; } + + template + void operator,(T const &) = delete; +}; +#if TEST_STD_VER > 14 +template +forward_iterator(It) -> forward_iterator; +#endif + +template +class bidirectional_iterator +{ + It it_; + + template friend class bidirectional_iterator; +public: + typedef std::bidirectional_iterator_tag iterator_category; + typedef typename std::iterator_traits::value_type value_type; + typedef typename std::iterator_traits::difference_type difference_type; + typedef It pointer; + typedef typename std::iterator_traits::reference reference; + + TEST_CONSTEXPR bidirectional_iterator() : it_() {} + TEST_CONSTEXPR explicit bidirectional_iterator(It it) : it_(it) {} + + template + TEST_CONSTEXPR bidirectional_iterator(const bidirectional_iterator& u) : it_(u.it_) {} + + template ::value>::type> + TEST_CONSTEXPR_CXX14 bidirectional_iterator(bidirectional_iterator&& u) : it_(u.it_) { u.it_ = U(); } + + TEST_CONSTEXPR reference operator*() const {return *it_;} + + TEST_CONSTEXPR_CXX14 bidirectional_iterator& operator++() {++it_; return *this;} + TEST_CONSTEXPR_CXX14 bidirectional_iterator& operator--() {--it_; return *this;} + TEST_CONSTEXPR_CXX14 bidirectional_iterator operator++(int) {return bidirectional_iterator(it_++);} + TEST_CONSTEXPR_CXX14 bidirectional_iterator operator--(int) {return bidirectional_iterator(it_--);} + + friend TEST_CONSTEXPR bool operator==(const bidirectional_iterator& x, const bidirectional_iterator& y) {return x.it_ == y.it_;} + friend TEST_CONSTEXPR bool operator!=(const bidirectional_iterator& x, const bidirectional_iterator& y) {return x.it_ != y.it_;} + + friend TEST_CONSTEXPR It base(const bidirectional_iterator& i) { return i.it_; } + + template + void operator,(T const &) = delete; +}; +#if TEST_STD_VER > 14 +template +bidirectional_iterator(It) -> bidirectional_iterator; +#endif + +template +class random_access_iterator +{ + It it_; + + template friend class random_access_iterator; +public: + typedef std::random_access_iterator_tag iterator_category; + typedef typename std::iterator_traits::value_type value_type; + typedef typename std::iterator_traits::difference_type difference_type; + typedef It pointer; + typedef typename std::iterator_traits::reference reference; + + TEST_CONSTEXPR random_access_iterator() : it_() {} + TEST_CONSTEXPR explicit random_access_iterator(It it) : it_(it) {} + + template + TEST_CONSTEXPR random_access_iterator(const random_access_iterator& u) : it_(u.it_) {} + + template ::value>::type> + TEST_CONSTEXPR_CXX14 random_access_iterator(random_access_iterator&& u) : it_(u.it_) { u.it_ = U(); } + + TEST_CONSTEXPR_CXX14 reference operator*() const {return *it_;} + TEST_CONSTEXPR_CXX14 reference operator[](difference_type n) const {return it_[n];} + + TEST_CONSTEXPR_CXX14 random_access_iterator& operator++() {++it_; return *this;} + TEST_CONSTEXPR_CXX14 random_access_iterator& operator--() {--it_; return *this;} + TEST_CONSTEXPR_CXX14 random_access_iterator operator++(int) {return random_access_iterator(it_++);} + TEST_CONSTEXPR_CXX14 random_access_iterator operator--(int) {return random_access_iterator(it_--);} + + TEST_CONSTEXPR_CXX14 random_access_iterator& operator+=(difference_type n) {it_ += n; return *this;} + TEST_CONSTEXPR_CXX14 random_access_iterator& operator-=(difference_type n) {it_ -= n; return *this;} + friend TEST_CONSTEXPR_CXX14 random_access_iterator operator+(random_access_iterator x, difference_type n) {x += n; return x;} + friend TEST_CONSTEXPR_CXX14 random_access_iterator operator+(difference_type n, random_access_iterator x) {x += n; return x;} + friend TEST_CONSTEXPR_CXX14 random_access_iterator operator-(random_access_iterator x, difference_type n) {x -= n; return x;} + friend TEST_CONSTEXPR difference_type operator-(random_access_iterator x, random_access_iterator y) {return x.it_ - y.it_;} + + friend TEST_CONSTEXPR bool operator==(const random_access_iterator& x, const random_access_iterator& y) {return x.it_ == y.it_;} + friend TEST_CONSTEXPR bool operator!=(const random_access_iterator& x, const random_access_iterator& y) {return x.it_ != y.it_;} + friend TEST_CONSTEXPR bool operator< (const random_access_iterator& x, const random_access_iterator& y) {return x.it_ < y.it_;} + friend TEST_CONSTEXPR bool operator<=(const random_access_iterator& x, const random_access_iterator& y) {return x.it_ <= y.it_;} + friend TEST_CONSTEXPR bool operator> (const random_access_iterator& x, const random_access_iterator& y) {return x.it_ > y.it_;} + friend TEST_CONSTEXPR bool operator>=(const random_access_iterator& x, const random_access_iterator& y) {return x.it_ >= y.it_;} + + friend TEST_CONSTEXPR It base(const random_access_iterator& i) { return i.it_; } + + template + void operator,(T const &) = delete; +}; +#if TEST_STD_VER > 14 +template +random_access_iterator(It) -> random_access_iterator; +#endif + +#if TEST_STD_VER > 17 + +template +class cpp20_random_access_iterator { + It it_; + + template + friend class cpp20_random_access_iterator; + +public: + using iterator_category = std::input_iterator_tag; + using iterator_concept = std::random_access_iterator_tag; + using value_type = typename std::iterator_traits::value_type; + using difference_type = typename std::iterator_traits::difference_type; + + constexpr cpp20_random_access_iterator() : it_() {} + constexpr explicit cpp20_random_access_iterator(It it) : it_(it) {} + + template + constexpr cpp20_random_access_iterator(const cpp20_random_access_iterator& u) : it_(u.it_) {} + + template + constexpr cpp20_random_access_iterator(cpp20_random_access_iterator&& u) : it_(u.it_) { + u.it_ = U(); + } + + constexpr decltype(auto) operator*() const { return *it_; } + constexpr decltype(auto) operator[](difference_type n) const { return it_[n]; } + + constexpr cpp20_random_access_iterator& operator++() { + ++it_; + return *this; + } + constexpr cpp20_random_access_iterator& operator--() { + --it_; + return *this; + } + constexpr cpp20_random_access_iterator operator++(int) { return cpp20_random_access_iterator(it_++); } + constexpr cpp20_random_access_iterator operator--(int) { return cpp20_random_access_iterator(it_--); } + + constexpr cpp20_random_access_iterator& operator+=(difference_type n) { + it_ += n; + return *this; + } + constexpr cpp20_random_access_iterator& operator-=(difference_type n) { + it_ -= n; + return *this; + } + friend constexpr cpp20_random_access_iterator operator+(cpp20_random_access_iterator x, difference_type n) { + x += n; + return x; + } + friend constexpr cpp20_random_access_iterator operator+(difference_type n, cpp20_random_access_iterator x) { + x += n; + return x; + } + friend constexpr cpp20_random_access_iterator operator-(cpp20_random_access_iterator x, difference_type n) { + x -= n; + return x; + } + friend constexpr difference_type operator-(cpp20_random_access_iterator x, cpp20_random_access_iterator y) { + return x.it_ - y.it_; + } + + friend constexpr bool operator==(const cpp20_random_access_iterator& x, const cpp20_random_access_iterator& y) { + return x.it_ == y.it_; + } + friend constexpr bool operator!=(const cpp20_random_access_iterator& x, const cpp20_random_access_iterator& y) { + return x.it_ != y.it_; + } + friend constexpr bool operator<(const cpp20_random_access_iterator& x, const cpp20_random_access_iterator& y) { + return x.it_ < y.it_; + } + friend constexpr bool operator<=(const cpp20_random_access_iterator& x, const cpp20_random_access_iterator& y) { + return x.it_ <= y.it_; + } + friend constexpr bool operator>(const cpp20_random_access_iterator& x, const cpp20_random_access_iterator& y) { + return x.it_ > y.it_; + } + friend constexpr bool operator>=(const cpp20_random_access_iterator& x, const cpp20_random_access_iterator& y) { + return x.it_ >= y.it_; + } + + friend constexpr It base(const cpp20_random_access_iterator& i) { return i.it_; } + + template + void operator,(T const&) = delete; +}; +template +cpp20_random_access_iterator(It) -> cpp20_random_access_iterator; + +static_assert(std::random_access_iterator>); + +template +class contiguous_iterator +{ + static_assert(std::is_pointer_v, "Things probably break in this case"); + + It it_; + + template friend class contiguous_iterator; +public: + typedef std::contiguous_iterator_tag iterator_category; + typedef typename std::iterator_traits::value_type value_type; + typedef typename std::iterator_traits::difference_type difference_type; + typedef It pointer; + typedef typename std::iterator_traits::reference reference; + typedef typename std::remove_pointer::type element_type; + + TEST_CONSTEXPR_CXX14 It base() const {return it_;} + + TEST_CONSTEXPR_CXX14 contiguous_iterator() : it_() {} + TEST_CONSTEXPR_CXX14 explicit contiguous_iterator(It it) : it_(it) {} + + template + TEST_CONSTEXPR_CXX14 contiguous_iterator(const contiguous_iterator& u) : it_(u.it_) {} + + template ::value>::type> + constexpr contiguous_iterator(contiguous_iterator&& u) : it_(u.it_) { u.it_ = U(); } + + TEST_CONSTEXPR reference operator*() const {return *it_;} + TEST_CONSTEXPR pointer operator->() const {return it_;} + TEST_CONSTEXPR reference operator[](difference_type n) const {return it_[n];} + + TEST_CONSTEXPR_CXX14 contiguous_iterator& operator++() {++it_; return *this;} + TEST_CONSTEXPR_CXX14 contiguous_iterator& operator--() {--it_; return *this;} + TEST_CONSTEXPR_CXX14 contiguous_iterator operator++(int) {return contiguous_iterator(it_++);} + TEST_CONSTEXPR_CXX14 contiguous_iterator operator--(int) {return contiguous_iterator(it_--);} + + TEST_CONSTEXPR_CXX14 contiguous_iterator& operator+=(difference_type n) {it_ += n; return *this;} + TEST_CONSTEXPR_CXX14 contiguous_iterator& operator-=(difference_type n) {it_ -= n; return *this;} + friend TEST_CONSTEXPR_CXX14 contiguous_iterator operator+(contiguous_iterator x, difference_type n) {x += n; return x;} + friend TEST_CONSTEXPR_CXX14 contiguous_iterator operator+(difference_type n, contiguous_iterator x) {x += n; return x;} + friend TEST_CONSTEXPR_CXX14 contiguous_iterator operator-(contiguous_iterator x, difference_type n) {x -= n; return x;} + friend TEST_CONSTEXPR difference_type operator-(contiguous_iterator x, contiguous_iterator y) {return x.it_ - y.it_;} + + friend TEST_CONSTEXPR bool operator==(const contiguous_iterator& x, const contiguous_iterator& y) {return x.it_ == y.it_;} + friend TEST_CONSTEXPR bool operator!=(const contiguous_iterator& x, const contiguous_iterator& y) {return x.it_ != y.it_;} + friend TEST_CONSTEXPR bool operator< (const contiguous_iterator& x, const contiguous_iterator& y) {return x.it_ < y.it_;} + friend TEST_CONSTEXPR bool operator<=(const contiguous_iterator& x, const contiguous_iterator& y) {return x.it_ <= y.it_;} + friend TEST_CONSTEXPR bool operator> (const contiguous_iterator& x, const contiguous_iterator& y) {return x.it_ > y.it_;} + friend TEST_CONSTEXPR bool operator>=(const contiguous_iterator& x, const contiguous_iterator& y) {return x.it_ >= y.it_;} + + friend TEST_CONSTEXPR It base(const contiguous_iterator& i) { return i.it_; } + + template + void operator,(T const &) = delete; +}; +template +contiguous_iterator(It) -> contiguous_iterator; + +template +class three_way_contiguous_iterator +{ + static_assert(std::is_pointer_v, "Things probably break in this case"); + + It it_; + + template friend class three_way_contiguous_iterator; +public: + typedef std::contiguous_iterator_tag iterator_category; + typedef typename std::iterator_traits::value_type value_type; + typedef typename std::iterator_traits::difference_type difference_type; + typedef It pointer; + typedef typename std::iterator_traits::reference reference; + typedef typename std::remove_pointer::type element_type; + + constexpr It base() const {return it_;} + + constexpr three_way_contiguous_iterator() : it_() {} + constexpr explicit three_way_contiguous_iterator(It it) : it_(it) {} + + template + constexpr three_way_contiguous_iterator(const three_way_contiguous_iterator& u) : it_(u.it_) {} + + template ::value>::type> + constexpr three_way_contiguous_iterator(three_way_contiguous_iterator&& u) : it_(u.it_) { u.it_ = U(); } + + constexpr reference operator*() const {return *it_;} + constexpr pointer operator->() const {return it_;} + constexpr reference operator[](difference_type n) const {return it_[n];} + + constexpr three_way_contiguous_iterator& operator++() {++it_; return *this;} + constexpr three_way_contiguous_iterator& operator--() {--it_; return *this;} + constexpr three_way_contiguous_iterator operator++(int) {return three_way_contiguous_iterator(it_++);} + constexpr three_way_contiguous_iterator operator--(int) {return three_way_contiguous_iterator(it_--);} + + constexpr three_way_contiguous_iterator& operator+=(difference_type n) {it_ += n; return *this;} + constexpr three_way_contiguous_iterator& operator-=(difference_type n) {it_ -= n; return *this;} + friend constexpr three_way_contiguous_iterator operator+(three_way_contiguous_iterator x, difference_type n) {x += n; return x;} + friend constexpr three_way_contiguous_iterator operator+(difference_type n, three_way_contiguous_iterator x) {x += n; return x;} + friend constexpr three_way_contiguous_iterator operator-(three_way_contiguous_iterator x, difference_type n) {x -= n; return x;} + friend constexpr difference_type operator-(three_way_contiguous_iterator x, three_way_contiguous_iterator y) {return x.it_ - y.it_;} + + friend constexpr auto operator<=>(const three_way_contiguous_iterator& x, const three_way_contiguous_iterator& y) {return x.it_ <=> y.it_;} + friend constexpr bool operator==(const three_way_contiguous_iterator& x, const three_way_contiguous_iterator& y) {return x.it_ == y.it_;} + + template + void operator,(T const &) = delete; +}; +template +three_way_contiguous_iterator(It) -> three_way_contiguous_iterator; +#endif // TEST_STD_VER > 17 + +template // ADL base() for everything else (including pointers) +TEST_CONSTEXPR Iter base(Iter i) { return i; } + +template +struct ThrowingIterator { + typedef std::bidirectional_iterator_tag iterator_category; + typedef std::ptrdiff_t difference_type; + typedef const T value_type; + typedef const T * pointer; + typedef const T & reference; + + enum ThrowingAction { TAIncrement, TADecrement, TADereference, TAAssignment, TAComparison }; + + TEST_CONSTEXPR ThrowingIterator() + : begin_(nullptr), end_(nullptr), current_(nullptr), action_(TADereference), index_(0) {} + TEST_CONSTEXPR explicit ThrowingIterator(const T* first, const T* last, int index = 0, + ThrowingAction action = TADereference) + : begin_(first), end_(last), current_(first), action_(action), index_(index) {} + TEST_CONSTEXPR ThrowingIterator(const ThrowingIterator &rhs) + : begin_(rhs.begin_), end_(rhs.end_), current_(rhs.current_), action_(rhs.action_), index_(rhs.index_) {} + + TEST_CONSTEXPR_CXX14 ThrowingIterator& operator=(const ThrowingIterator& rhs) { + if (action_ == TAAssignment && --index_ < 0) { +#ifndef TEST_HAS_NO_EXCEPTIONS + throw std::runtime_error("throw from iterator assignment"); +#else + assert(false); +#endif + } + begin_ = rhs.begin_; + end_ = rhs.end_; + current_ = rhs.current_; + action_ = rhs.action_; + index_ = rhs.index_; + return *this; + } + + TEST_CONSTEXPR_CXX14 reference operator*() const { + if (action_ == TADereference && --index_ < 0) { +#ifndef TEST_HAS_NO_EXCEPTIONS + throw std::runtime_error("throw from iterator dereference"); +#else + assert(false); +#endif + } + return *current_; + } + + TEST_CONSTEXPR_CXX14 ThrowingIterator& operator++() { + if (action_ == TAIncrement && --index_ < 0) { +#ifndef TEST_HAS_NO_EXCEPTIONS + throw std::runtime_error("throw from iterator increment"); +#else + assert(false); +#endif + } + ++current_; + return *this; + } + + TEST_CONSTEXPR_CXX14 ThrowingIterator operator++(int) { + ThrowingIterator temp = *this; + ++(*this); + return temp; + } + + TEST_CONSTEXPR_CXX14 ThrowingIterator& operator--() { + if (action_ == TADecrement && --index_ < 0) { +#ifndef TEST_HAS_NO_EXCEPTIONS + throw std::runtime_error("throw from iterator decrement"); +#else + assert(false); +#endif + } + --current_; + return *this; + } + + TEST_CONSTEXPR_CXX14 ThrowingIterator operator--(int) { + ThrowingIterator temp = *this; + --(*this); + return temp; + } + + TEST_CONSTEXPR_CXX14 friend bool operator==(const ThrowingIterator& a, const ThrowingIterator& b) { + if (a.action_ == TAComparison && --a.index_ < 0) { +#ifndef TEST_HAS_NO_EXCEPTIONS + throw std::runtime_error("throw from iterator comparison"); +#else + assert(false); +#endif + } + bool atEndL = a.current_ == a.end_; + bool atEndR = b.current_ == b.end_; + if (atEndL != atEndR) return false; // one is at the end (or empty), the other is not. + if (atEndL) return true; // both are at the end (or empty) + return a.current_ == b.current_; + } + + TEST_CONSTEXPR friend bool operator!=(const ThrowingIterator& a, const ThrowingIterator& b) { + return !(a == b); + } + + template + void operator,(T2 const &) = delete; + +private: + const T* begin_; + const T* end_; + const T* current_; + ThrowingAction action_; + mutable int index_; +}; + +template +struct NonThrowingIterator { + typedef std::bidirectional_iterator_tag iterator_category; + typedef std::ptrdiff_t difference_type; + typedef const T value_type; + typedef const T * pointer; + typedef const T & reference; + + NonThrowingIterator() + : begin_(nullptr), end_(nullptr), current_(nullptr) {} + explicit NonThrowingIterator(const T *first, const T *last) + : begin_(first), end_(last), current_(first) {} + NonThrowingIterator(const NonThrowingIterator& rhs) + : begin_(rhs.begin_), end_(rhs.end_), current_(rhs.current_) {} + + NonThrowingIterator& operator=(const NonThrowingIterator& rhs) TEST_NOEXCEPT { + begin_ = rhs.begin_; + end_ = rhs.end_; + current_ = rhs.current_; + return *this; + } + + reference operator*() const TEST_NOEXCEPT { + return *current_; + } + + NonThrowingIterator& operator++() TEST_NOEXCEPT { + ++current_; + return *this; + } + + NonThrowingIterator operator++(int) TEST_NOEXCEPT { + NonThrowingIterator temp = *this; + ++(*this); + return temp; + } + + NonThrowingIterator & operator--() TEST_NOEXCEPT { + --current_; + return *this; + } + + NonThrowingIterator operator--(int) TEST_NOEXCEPT { + NonThrowingIterator temp = *this; + --(*this); + return temp; + } + + friend bool operator==(const NonThrowingIterator& a, const NonThrowingIterator& b) TEST_NOEXCEPT { + bool atEndL = a.current_ == a.end_; + bool atEndR = b.current_ == b.end_; + if (atEndL != atEndR) return false; // one is at the end (or empty), the other is not. + if (atEndL) return true; // both are at the end (or empty) + return a.current_ == b.current_; + } + + friend bool operator!=(const NonThrowingIterator& a, const NonThrowingIterator& b) TEST_NOEXCEPT { + return !(a == b); + } + + template + void operator,(T2 const &) = delete; + +private: + const T *begin_; + const T *end_; + const T *current_; +}; + +#if TEST_STD_VER > 17 + +template +class cpp20_input_iterator +{ + It it_; + +public: + using value_type = std::iter_value_t; + using difference_type = std::iter_difference_t; + using iterator_concept = std::input_iterator_tag; + + constexpr explicit cpp20_input_iterator(It it) : it_(it) {} + cpp20_input_iterator(cpp20_input_iterator&&) = default; + cpp20_input_iterator& operator=(cpp20_input_iterator&&) = default; + constexpr decltype(auto) operator*() const { return *it_; } + constexpr cpp20_input_iterator& operator++() { ++it_; return *this; } + constexpr void operator++(int) { ++it_; } + + friend constexpr It base(const cpp20_input_iterator& i) { return i.it_; } + + template + void operator,(T const &) = delete; +}; +template +cpp20_input_iterator(It) -> cpp20_input_iterator; + +static_assert(std::input_iterator>); + +template +struct iter_value_or_void { using type = void; }; + +template +struct iter_value_or_void { + using type = std::iter_value_t; +}; + +template +class cpp20_output_iterator { + It it_; + +public: + using difference_type = std::iter_difference_t; + + constexpr explicit cpp20_output_iterator(It it) : it_(it) {} + cpp20_output_iterator(cpp20_output_iterator&&) = default; + cpp20_output_iterator& operator=(cpp20_output_iterator&&) = default; + + constexpr decltype(auto) operator*() const { return *it_; } + constexpr cpp20_output_iterator& operator++() { + ++it_; + return *this; + } + constexpr cpp20_output_iterator operator++(int) { return cpp20_output_iterator(it_++); } + + friend constexpr It base(const cpp20_output_iterator& i) { return i.it_; } + + template + void operator,(T const&) = delete; +}; +template +cpp20_output_iterator(It) -> cpp20_output_iterator; + +static_assert(std::output_iterator, int>); + +# if TEST_STD_VER >= 20 + +// An `input_iterator` that can be used in a `std::ranges::common_range` +template +struct common_input_iterator { + Base it_; + + using value_type = std::iter_value_t; + using difference_type = std::intptr_t; + using iterator_concept = std::input_iterator_tag; + + constexpr common_input_iterator() = default; + constexpr explicit common_input_iterator(Base it) : it_(it) {} + + constexpr common_input_iterator& operator++() { + ++it_; + return *this; + } + constexpr void operator++(int) { ++it_; } + + constexpr decltype(auto) operator*() const { return *it_; } + + friend constexpr bool operator==(common_input_iterator const&, common_input_iterator const&) = default; +}; + +# endif // TEST_STD_VER >= 20 + +// Iterator adaptor that counts the number of times the iterator has had a successor/predecessor +// operation or an equality comparison operation called. Has three recorders: +// * `stride_count`, which records the total number of calls to an op++, op--, op+=, or op-=. +// * `stride_displacement`, which records the displacement of the calls. This means that both +// op++/op+= will increase the displacement counter by 1, and op--/op-= will decrease the +// displacement counter by 1. +// * `equals_count`, which records the total number of calls to an op== or op!=. If compared +// against a sentinel object, that sentinel object must call the `record_equality_comparison` +// function so that the comparison is counted correctly. +template +class stride_counting_iterator { +public: + using value_type = typename iter_value_or_void::type; + using difference_type = std::iter_difference_t; + using iterator_concept = + std::conditional_t, std::contiguous_iterator_tag, + std::conditional_t, std::random_access_iterator_tag, + std::conditional_t, std::bidirectional_iterator_tag, + std::conditional_t, std::forward_iterator_tag, + std::conditional_t, std::input_iterator_tag, + /* else */ std::output_iterator_tag + >>>>>; + + stride_counting_iterator() requires std::default_initializable = default; + + constexpr explicit stride_counting_iterator(It const& it) : base_(base(it)) { } + + friend constexpr It base(stride_counting_iterator const& it) { return It(it.base_); } + + constexpr difference_type stride_count() const { return stride_count_; } + + constexpr difference_type stride_displacement() const { return stride_displacement_; } + + constexpr difference_type equals_count() const { return equals_count_; } + + constexpr decltype(auto) operator*() const { return *It(base_); } + + constexpr decltype(auto) operator[](difference_type n) const { return It(base_)[n]; } + + constexpr stride_counting_iterator& operator++() { + It tmp(base_); + base_ = base(++tmp); + ++stride_count_; + ++stride_displacement_; + return *this; + } + + constexpr void operator++(int) { ++*this; } + + constexpr stride_counting_iterator operator++(int) + requires std::forward_iterator + { + auto temp = *this; + ++*this; + return temp; + } + + constexpr stride_counting_iterator& operator--() + requires std::bidirectional_iterator + { + It tmp(base_); + base_ = base(--tmp); + ++stride_count_; + --stride_displacement_; + return *this; + } + + constexpr stride_counting_iterator operator--(int) + requires std::bidirectional_iterator + { + auto temp = *this; + --*this; + return temp; + } + + constexpr stride_counting_iterator& operator+=(difference_type const n) + requires std::random_access_iterator + { + It tmp(base_); + base_ = base(tmp += n); + ++stride_count_; + ++stride_displacement_; + return *this; + } + + constexpr stride_counting_iterator& operator-=(difference_type const n) + requires std::random_access_iterator + { + It tmp(base_); + base_ = base(tmp -= n); + ++stride_count_; + --stride_displacement_; + return *this; + } + + friend constexpr stride_counting_iterator operator+(stride_counting_iterator it, difference_type n) + requires std::random_access_iterator + { + return it += n; + } + + friend constexpr stride_counting_iterator operator+(difference_type n, stride_counting_iterator it) + requires std::random_access_iterator + { + return it += n; + } + + friend constexpr stride_counting_iterator operator-(stride_counting_iterator it, difference_type n) + requires std::random_access_iterator + { + return it -= n; + } + + friend constexpr difference_type operator-(stride_counting_iterator const& x, stride_counting_iterator const& y) + requires std::sized_sentinel_for + { + return base(x) - base(y); + } + + constexpr void record_equality_comparison() const { ++equals_count_; } + + constexpr bool operator==(stride_counting_iterator const& other) const + requires std::sentinel_for + { + record_equality_comparison(); + return It(base_) == It(other.base_); + } + + friend constexpr bool operator<(stride_counting_iterator const& x, stride_counting_iterator const& y) + requires std::random_access_iterator + { + return It(x.base_) < It(y.base_); + } + + friend constexpr bool operator>(stride_counting_iterator const& x, stride_counting_iterator const& y) + requires std::random_access_iterator + { + return It(x.base_) > It(y.base_); + } + + friend constexpr bool operator<=(stride_counting_iterator const& x, stride_counting_iterator const& y) + requires std::random_access_iterator + { + return It(x.base_) <= It(y.base_); + } + + friend constexpr bool operator>=(stride_counting_iterator const& x, stride_counting_iterator const& y) + requires std::random_access_iterator + { + return It(x.base_) >= It(y.base_); + } + + template + void operator,(T const &) = delete; + +private: + decltype(base(std::declval())) base_; + difference_type stride_count_ = 0; + difference_type stride_displacement_ = 0; + mutable difference_type equals_count_ = 0; +}; +template +stride_counting_iterator(It) -> stride_counting_iterator; + +#endif // TEST_STD_VER > 17 + +#if TEST_STD_VER > 17 +template +class sentinel_wrapper { +public: + explicit sentinel_wrapper() = default; + constexpr explicit sentinel_wrapper(const It& it) : base_(base(it)) {} + constexpr bool operator==(const It& other) const { + // If supported, record statistics about the equality operator call + // inside `other`. + if constexpr (requires { other.record_equality_comparison(); }) { + other.record_equality_comparison(); + } + return base_ == base(other); + } + friend constexpr It base(const sentinel_wrapper& s) { return It(s.base_); } +private: + decltype(base(std::declval())) base_; +}; +template +sentinel_wrapper(It) -> sentinel_wrapper; + +template +class sized_sentinel { +public: + explicit sized_sentinel() = default; + constexpr explicit sized_sentinel(const It& it) : base_(base(it)) {} + constexpr bool operator==(const It& other) const { return base_ == base(other); } + friend constexpr auto operator-(const sized_sentinel& s, const It& i) { return s.base_ - base(i); } + friend constexpr auto operator-(const It& i, const sized_sentinel& s) { return base(i) - s.base_; } + friend constexpr It base(const sized_sentinel& s) { return It(s.base_); } +private: + decltype(base(std::declval())) base_; +}; +template +sized_sentinel(It) -> sized_sentinel; + +namespace adl { + +class Iterator { + public: + using value_type = int; + using reference = int&; + using difference_type = std::ptrdiff_t; + + private: + value_type* ptr_ = nullptr; + int* iter_moves_ = nullptr; + int* iter_swaps_ = nullptr; + + constexpr Iterator(int* p, int* iter_moves, int* iter_swaps) + : ptr_(p) + , iter_moves_(iter_moves) + , iter_swaps_(iter_swaps) {} + + public: + constexpr Iterator() = default; + static constexpr Iterator TrackMoves(int* p, int& iter_moves) { + return Iterator(p, &iter_moves, /*iter_swaps=*/nullptr); + } + static constexpr Iterator TrackSwaps(int& iter_swaps) { + return Iterator(/*p=*/nullptr, /*iter_moves=*/nullptr, &iter_swaps); + } + static constexpr Iterator TrackSwaps(int* p, int& iter_swaps) { + return Iterator(p, /*iter_moves=*/nullptr, &iter_swaps); + } + + constexpr int iter_moves() const { assert(iter_moves_); return *iter_moves_; } + constexpr int iter_swaps() const { assert(iter_swaps_); return *iter_swaps_; } + + constexpr value_type& operator*() const { return *ptr_; } + constexpr reference operator[](difference_type n) const { return ptr_[n]; } + + friend constexpr Iterator operator+(Iterator i, difference_type n) { + return Iterator(i.ptr_ + n, i.iter_moves_, i.iter_swaps_); + } + friend constexpr Iterator operator+(difference_type n, Iterator i) { + return i + n; + } + constexpr Iterator operator-(difference_type n) const { + return Iterator(ptr_ - n, iter_moves_, iter_swaps_); + } + constexpr difference_type operator-(Iterator rhs) const { + return ptr_ - rhs.ptr_; + } + constexpr Iterator& operator+=(difference_type n) { + ptr_ += n; + return *this; + } + constexpr Iterator& operator-=(difference_type n) { + ptr_ -= n; + return *this; + } + + constexpr Iterator& operator++() { ++ptr_; return *this; } + constexpr Iterator operator++(int) { + Iterator prev = *this; + ++ptr_; + return prev; + } + + constexpr Iterator& operator--() { --ptr_; return *this; } + constexpr Iterator operator--(int) { + Iterator prev = *this; + --ptr_; + return prev; + } + + constexpr friend void iter_swap(Iterator a, Iterator b) { + std::swap(a.ptr_, b.ptr_); + if (a.iter_swaps_) { + ++(*a.iter_swaps_); + } + } + + constexpr friend value_type&& iter_move(Iterator iter) { + if (iter.iter_moves_) { + ++(*iter.iter_moves_); + } + return std::move(*iter); + } + + constexpr friend bool operator==(const Iterator& lhs, const Iterator& rhs) { + return lhs.ptr_ == rhs.ptr_; + } + constexpr friend auto operator<=>(const Iterator& lhs, const Iterator& rhs) { + return lhs.ptr_ <=> rhs.ptr_; + } +}; + +} // namespace adl + +template +class rvalue_iterator { +public: + using iterator_category = std::input_iterator_tag; + using iterator_concept = std::random_access_iterator_tag; + using difference_type = std::ptrdiff_t; + using reference = T&&; + using value_type = T; + + rvalue_iterator() = default; + constexpr rvalue_iterator(T* it) : it_(it) {} + + constexpr reference operator*() const { return std::move(*it_); } + + constexpr rvalue_iterator& operator++() { + ++it_; + return *this; + } + + constexpr rvalue_iterator operator++(int) { + auto tmp = *this; + ++it_; + return tmp; + } + + constexpr rvalue_iterator& operator--() { + --it_; + return *this; + } + + constexpr rvalue_iterator operator--(int) { + auto tmp = *this; + --it_; + return tmp; + } + + constexpr rvalue_iterator operator+(difference_type n) const { + auto tmp = *this; + tmp.it += n; + return tmp; + } + + constexpr friend rvalue_iterator operator+(difference_type n, rvalue_iterator iter) { + iter += n; + return iter; + } + + constexpr rvalue_iterator operator-(difference_type n) const { + auto tmp = *this; + tmp.it -= n; + return tmp; + } + + constexpr difference_type operator-(const rvalue_iterator& other) const { return it_ - other.it_; } + + constexpr rvalue_iterator& operator+=(difference_type n) { + it_ += n; + return *this; + } + + constexpr rvalue_iterator& operator-=(difference_type n) { + it_ -= n; + return *this; + } + + constexpr reference operator[](difference_type n) const { return std::move(it_[n]); } + + auto operator<=>(const rvalue_iterator&) const noexcept = default; + +private: + T* it_; +}; + +template +rvalue_iterator(T*) -> rvalue_iterator; + +static_assert(std::random_access_iterator>); + +// Proxy +// ====================================================================== +// Proxy that can wrap a value or a reference. It simulates C++23's tuple +// but simplified to just hold one argument. +// Note that unlike tuple, this class deliberately doesn't have special handling +// of swap to cause a compilation error if it's used in an algorithm that relies +// on plain swap instead of ranges::iter_swap. +// This class is useful for testing that if algorithms support proxy iterator +// properly, i.e. calling ranges::iter_swap and ranges::iter_move instead of +// plain swap and std::move. +template +struct Proxy; + +template +inline constexpr bool IsProxy = false; + +template +inline constexpr bool IsProxy> = true; + +template +struct Proxy { + T data; + + constexpr T& getData() & { return data; } + + constexpr const T& getData() const& { return data; } + + constexpr T&& getData() && { return static_cast(data); } + + constexpr const T&& getData() const&& { return static_cast(data); } + + template + requires std::constructible_from + constexpr Proxy(U&& u) : data{std::forward(u)} {} + + // This constructor covers conversion from cvref of Proxy, including non-const/const versions of copy/move constructor + template + requires(IsProxy> && std::constructible_from().getData())>) + constexpr Proxy(Other&& other) : data{std::forward(other).getData()} {} + + template + requires(IsProxy> && std::assignable_from().getData())>) + constexpr Proxy& operator=(Other&& other) { + data = std::forward(other).getData(); + return *this; + } + + // const assignment required to make ProxyIterator model std::indirectly_writable + template + requires(IsProxy> && std::assignable_from().getData())>) + constexpr const Proxy& operator=(Other&& other) const { + data = std::forward(other).getData(); + return *this; + } + + // If `T` is a reference type, the implicitly-generated assignment operator will be deleted (and would take precedence + // over the templated `operator=` above because it's a better match). + constexpr Proxy& operator=(const Proxy& rhs) { + data = rhs.data; + return *this; + } + + // no specialised swap function that takes const Proxy& and no specialised const member swap + // Calling swap(Proxy{}, Proxy{}) would fail (pass prvalues) + + // Compare operators are defined for the convenience of the tests + friend constexpr bool operator==(const Proxy&, const Proxy&) + requires (std::equality_comparable && !std::is_reference_v) + = default; + + // Helps compare e.g. `Proxy` and `Proxy`. Note that the default equality comparison operator is deleted + // when `T` is a reference type. + template + friend constexpr bool operator==(const Proxy& lhs, const Proxy& rhs) + requires std::equality_comparable_with, std::decay_t> { + return lhs.data == rhs.data; + } + + friend constexpr auto operator<=>(const Proxy&, const Proxy&) + requires (std::three_way_comparable && !std::is_reference_v) + = default; + + // Helps compare e.g. `Proxy` and `Proxy`. Note that the default 3-way comparison operator is deleted when + // `T` is a reference type. + template + friend constexpr auto operator<=>(const Proxy& lhs, const Proxy& rhs) + requires std::three_way_comparable_with, std::decay_t> { + return lhs.data <=> rhs.data; + } +}; + +// This is to make ProxyIterator model `std::indirectly_readable` +template class TQual, template class UQual> + requires requires { typename std::common_reference_t, UQual>; } +struct std::basic_common_reference, Proxy, TQual, UQual> { + using type = Proxy, UQual>>; +}; + +template + requires requires { typename std::common_type_t; } +struct std::common_type, Proxy> { + using type = Proxy>; +}; + +// ProxyIterator +// ====================================================================== +// It wraps `Base` iterator and when dereferenced it returns a Proxy +// It simulates C++23's zip_view::iterator but simplified to just wrap +// one base iterator. +// Note it forwards value_type, iter_move, iter_swap. e.g if the base +// iterator is int*, +// operator* -> Proxy +// iter_value_t -> Proxy +// iter_move -> Proxy +template +struct ProxyIteratorBase {}; + +template + requires std::derived_from< + typename std::iterator_traits::iterator_category, + std::input_iterator_tag> +struct ProxyIteratorBase { + using iterator_category = std::input_iterator_tag; +}; + +template +consteval auto get_iterator_concept() { + if constexpr (std::random_access_iterator) { + return std::random_access_iterator_tag{}; + } else if constexpr (std::bidirectional_iterator) { + return std::bidirectional_iterator_tag{}; + } else if constexpr (std::forward_iterator) { + return std::forward_iterator_tag{}; + } else { + return std::input_iterator_tag{}; + } +} + +template +struct ProxyIterator : ProxyIteratorBase { + Base base_; + + using iterator_concept = decltype(get_iterator_concept()); + using value_type = Proxy>; + using difference_type = std::iter_difference_t; + + ProxyIterator() + requires std::default_initializable + = default; + + constexpr ProxyIterator(Base base) : base_{std::move(base)} {} + + template + requires std::constructible_from + constexpr ProxyIterator(T&& t) : base_{std::forward(t)} {} + + friend constexpr decltype(auto) base(const ProxyIterator& p) { return base(p.base_); } + + // Specialization of iter_move + // If operator* returns Proxy, iter_move will return Proxy + // Note std::move(*it) returns Proxy&&, which is not what we want as + // it will likely result in a copy rather than a move + friend constexpr Proxy> iter_move(const ProxyIterator& p) noexcept { + return {std::ranges::iter_move(p.base_)}; + } + + // Specialization of iter_swap + // Note std::swap(*x, *y) would fail to compile as operator* returns prvalues + // and std::swap takes non-const lvalue references + friend constexpr void iter_swap(const ProxyIterator& x, const ProxyIterator& y) noexcept { + std::ranges::iter_swap(x.base_, y.base_); + } + + // to satisfy input_iterator + constexpr Proxy> operator*() const { return {*base_}; } + + constexpr ProxyIterator& operator++() { + ++base_; + return *this; + } + + constexpr void operator++(int) { ++*this; } + + friend constexpr bool operator==(const ProxyIterator& x, const ProxyIterator& y) + requires std::equality_comparable { + return x.base_ == y.base_; + } + + // to satisfy forward_iterator + constexpr ProxyIterator operator++(int) + requires std::forward_iterator { + auto tmp = *this; + ++*this; + return tmp; + } + + // to satisfy bidirectional_iterator + constexpr ProxyIterator& operator--() + requires std::bidirectional_iterator { + --base_; + return *this; + } + + constexpr ProxyIterator operator--(int) + requires std::bidirectional_iterator { + auto tmp = *this; + --*this; + return tmp; + } + + // to satisfy random_access_iterator + constexpr ProxyIterator& operator+=(difference_type n) + requires std::random_access_iterator { + base_ += n; + return *this; + } + + constexpr ProxyIterator& operator-=(difference_type n) + requires std::random_access_iterator { + base_ -= n; + return *this; + } + + constexpr Proxy> operator[](difference_type n) const + requires std::random_access_iterator { + return {base_[n]}; + } + + friend constexpr bool operator<(const ProxyIterator& x, const ProxyIterator& y) + requires std::random_access_iterator { + return x.base_ < y.base_; + } + + friend constexpr bool operator>(const ProxyIterator& x, const ProxyIterator& y) + requires std::random_access_iterator { + return x.base_ > y.base_; + } + + friend constexpr bool operator<=(const ProxyIterator& x, const ProxyIterator& y) + requires std::random_access_iterator { + return x.base_ <= y.base_; + } + + friend constexpr bool operator>=(const ProxyIterator& x, const ProxyIterator& y) + requires std::random_access_iterator { + return x.base_ >= y.base_; + } + + friend constexpr auto operator<=>(const ProxyIterator& x, const ProxyIterator& y) + requires(std::random_access_iterator && std::three_way_comparable) { + return x.base_ <=> y.base_; + } + + friend constexpr ProxyIterator operator+(const ProxyIterator& x, difference_type n) + requires std::random_access_iterator { + return ProxyIterator{x.base_ + n}; + } + + friend constexpr ProxyIterator operator+(difference_type n, const ProxyIterator& x) + requires std::random_access_iterator { + return ProxyIterator{n + x.base_}; + } + + friend constexpr ProxyIterator operator-(const ProxyIterator& x, difference_type n) + requires std::random_access_iterator { + return ProxyIterator{x.base_ - n}; + } + + friend constexpr difference_type operator-(const ProxyIterator& x, const ProxyIterator& y) + requires std::random_access_iterator { + return x.base_ - y.base_; + } +}; +template +ProxyIterator(Base) -> ProxyIterator; + +static_assert(std::indirectly_readable>); +static_assert(std::indirectly_writable, Proxy>); +static_assert(std::indirectly_writable, Proxy>); + +template +using Cpp20InputProxyIterator = ProxyIterator>; + +template +using ForwardProxyIterator = ProxyIterator>; + +template +using BidirectionalProxyIterator = ProxyIterator>; + +template +using RandomAccessProxyIterator = ProxyIterator>; + +template +using ContiguousProxyIterator = ProxyIterator>; + +template +struct ProxySentinel { + BaseSent base_; + + ProxySentinel() = default; + constexpr ProxySentinel(BaseSent base) : base_{std::move(base)} {} + + template + requires std::equality_comparable_with + friend constexpr bool operator==(const ProxyIterator& p, const ProxySentinel& sent) { + return p.base_ == sent.base_; + } +}; +template +ProxySentinel(BaseSent) -> ProxySentinel; + +template + requires std::ranges::view +struct ProxyRange { + Base base_; + + constexpr auto begin() { return ProxyIterator{std::ranges::begin(base_)}; } + + constexpr auto end() { return ProxySentinel{std::ranges::end(base_)}; } + + constexpr auto begin() const + requires std::ranges::input_range { + return ProxyIterator{std::ranges::begin(base_)}; + } + + constexpr auto end() const + requires std::ranges::input_range { + return ProxySentinel{std::ranges::end(base_)}; + } +}; + +template + requires std::ranges::viewable_range +ProxyRange(R&&) -> ProxyRange>; + +#endif // TEST_STD_VER > 17 + +#if TEST_STD_VER >= 17 + +namespace util { +template +class iterator_wrapper { + Iter iter_; + + using iter_traits = std::iterator_traits; + +public: + using iterator_category = typename iter_traits::iterator_category; + using value_type = typename iter_traits::value_type; + using difference_type = typename iter_traits::difference_type; + using pointer = typename iter_traits::pointer; + using reference = typename iter_traits::reference; + + constexpr iterator_wrapper() : iter_() {} + constexpr explicit iterator_wrapper(Iter iter) : iter_(iter) {} + + decltype(*iter_) operator*() { return *iter_; } + decltype(*iter_) operator*() const { return *iter_; } + + decltype(iter_[0]) operator[](difference_type v) const { + return iter_[v]; + } + + Derived& operator++() { + ++iter_; + return static_cast(*this); + } + + Derived operator++(int) { + auto tmp = static_cast(*this); + ++(*this); + return tmp; + } + + Derived& operator--() { + --iter_; + return static_cast(*this); + } + + Derived operator--(int) { + auto tmp = static_cast(*this); + --(*this); + return tmp; + } + + Derived& operator+=(difference_type i) { + iter_ += i; + return static_cast(*this); + } + + Derived& operator-=(difference_type i) { + iter_ -= i; + return static_cast(*this); + } + + friend decltype(iter_ - iter_) operator-(const iterator_wrapper& lhs, const iterator_wrapper& rhs) { + return lhs.iter_ - rhs.iter_; + } + + friend Derived operator-(Derived iter, difference_type i) { + iter.iter_ -= i; + return iter; + } + + friend Derived operator+(Derived iter, difference_type i) { + iter.iter_ += i; + return iter; + } + + friend Derived operator+(difference_type i, Derived iter) { return iter + i; } + + friend bool operator==(const iterator_wrapper& lhs, const iterator_wrapper& rhs) { return lhs.iter_ == rhs.iter_; } + friend bool operator!=(const iterator_wrapper& lhs, const iterator_wrapper& rhs) { return lhs.iter_ != rhs.iter_; } + + friend bool operator>(const iterator_wrapper& lhs, const iterator_wrapper& rhs) { return lhs.iter_ > rhs.iter_; } + friend bool operator<(const iterator_wrapper& lhs, const iterator_wrapper& rhs) { return lhs.iter_ < rhs.iter_; } + friend bool operator<=(const iterator_wrapper& lhs, const iterator_wrapper& rhs) { return lhs.iter_ <= rhs.iter_; } + friend bool operator>=(const iterator_wrapper& lhs, const iterator_wrapper& rhs) { return lhs.iter_ >= rhs.iter_; } +}; + +class iterator_error : std::runtime_error { +public: + iterator_error(const char* what) : std::runtime_error(what) {} +}; + +#ifndef TEST_HAS_NO_EXCEPTIONS +template +class throw_on_move_iterator : public iterator_wrapper, Iter> { + using base = iterator_wrapper, Iter>; + + int moves_until_throw_ = 0; + +public: + using difference_type = typename base::difference_type; + using value_type = typename base::value_type; + using iterator_category = typename base::iterator_category; + + throw_on_move_iterator() = default; + throw_on_move_iterator(Iter iter, int moves_until_throw) + : base(std::move(iter)), moves_until_throw_(moves_until_throw) {} + + throw_on_move_iterator(const throw_on_move_iterator& other) : base(other) {} + throw_on_move_iterator& operator=(const throw_on_move_iterator& other) { + static_cast(*this) = other; + return *this; + } + + throw_on_move_iterator(throw_on_move_iterator&& other) + : base(std::move(other)), moves_until_throw_(other.moves_until_throw_ - 1) { + if (moves_until_throw_ == -1) + throw iterator_error("throw_on_move_iterator"); + } + + throw_on_move_iterator& operator=(throw_on_move_iterator&& other) { + moves_until_throw_ = other.moves_until_throw_ - 1; + if (moves_until_throw_ == -1) + throw iterator_error("throw_on_move_iterator"); + return *this; + } +}; + +template +throw_on_move_iterator(Iter) -> throw_on_move_iterator; +#endif // TEST_HAS_NO_EXCEPTIONS +} // namespace util + +#endif // TEST_STD_VER >= 17 + +namespace types { +template +using random_access_iterator_list = + type_list= 20 + contiguous_iterator, +#endif + random_access_iterator >; + +template +using bidirectional_iterator_list = + concatenate_t, type_list > >; + +template +using forward_iterator_list = concatenate_t, type_list > >; + +template +using cpp17_input_iterator_list = concatenate_t, type_list > >; + +#if TEST_STD_VER >= 20 +template +using cpp20_input_iterator_list = + concatenate_t, type_list, cpp17_input_iterator>>; +#endif +} // namespace types + + +#endif // SUPPORT_TEST_ITERATORS_H diff --git a/test/xpu_api/ranges/test_macros.h b/test/xpu_api/ranges/test_macros.h new file mode 100644 index 0000000000..68dd591cb5 --- /dev/null +++ b/test/xpu_api/ranges/test_macros.h @@ -0,0 +1,490 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef SUPPORT_TEST_MACROS_HPP +#define SUPPORT_TEST_MACROS_HPP + +#ifdef __has_include +# if __has_include("") +# include +# else +# include +# endif +#else +# include +#endif + +#define TEST_STRINGIZE_IMPL(...) #__VA_ARGS__ +#define TEST_STRINGIZE(...) TEST_STRINGIZE_IMPL(__VA_ARGS__) + +#define TEST_CONCAT1(X, Y) X##Y +#define TEST_CONCAT(X, Y) TEST_CONCAT1(X, Y) + +#ifdef __has_feature +#define TEST_HAS_FEATURE(X) __has_feature(X) +#else +#define TEST_HAS_FEATURE(X) 0 +#endif + +#ifndef __has_include +#define __has_include(...) 0 +#endif + +#ifdef __has_extension +#define TEST_HAS_EXTENSION(X) __has_extension(X) +#else +#define TEST_HAS_EXTENSION(X) 0 +#endif + +#ifdef __has_warning +#define TEST_HAS_WARNING(X) __has_warning(X) +#else +#define TEST_HAS_WARNING(X) 0 +#endif + +#ifdef __has_builtin +#define TEST_HAS_BUILTIN(X) __has_builtin(X) +#else +#define TEST_HAS_BUILTIN(X) 0 +#endif +#ifdef __is_identifier +// '__is_identifier' returns '0' if '__x' is a reserved identifier provided by +// the compiler and '1' otherwise. +#define TEST_HAS_BUILTIN_IDENTIFIER(X) !__is_identifier(X) +#else +#define TEST_HAS_BUILTIN_IDENTIFIER(X) 0 +#endif + +#if defined(__EDG__) +# define TEST_COMPILER_EDG +#elif defined(__clang__) +# define TEST_COMPILER_CLANG +# if defined(__apple_build_version__) +# define TEST_COMPILER_APPLE_CLANG +# endif +#elif defined(_MSC_VER) +# define TEST_COMPILER_MSVC +#elif defined(__GNUC__) +# define TEST_COMPILER_GCC +#endif + +#if defined(__apple_build_version__) +// Given AppleClang XX.Y.Z, TEST_APPLE_CLANG_VER is XXYZ (e.g. AppleClang 14.0.3 => 1403) +#define TEST_APPLE_CLANG_VER (__apple_build_version__ / 10000) +#elif defined(__clang_major__) +#define TEST_CLANG_VER (__clang_major__ * 100) + __clang_minor__ +#elif defined(__GNUC__) +// Given GCC XX.YY.ZZ, TEST_GCC_VER is XXYYZZ +#define TEST_GCC_VER ((__GNUC__ * 10000) + (__GNUC_MINOR__ * 100) + __GNUC_PATCHLEVEL__) +#endif + +/* Make a nice name for the standard version */ +#ifndef TEST_STD_VER +#if __cplusplus <= 199711L +# define TEST_STD_VER 3 +#elif __cplusplus <= 201103L +# define TEST_STD_VER 11 +#elif __cplusplus <= 201402L +# define TEST_STD_VER 14 +#elif __cplusplus <= 201703L +# define TEST_STD_VER 17 +#elif __cplusplus <= 202002L +# define TEST_STD_VER 20 +#elif __cplusplus <= 202302L +# define TEST_STD_VER 23 +#else +# define TEST_STD_VER 99 // greater than current standard +// This is deliberately different than _LIBCPP_STD_VER to discourage matching them up. +#endif +#endif + +// Attempt to deduce the GLIBC version +#if (defined(__has_include) && __has_include()) || \ + defined(__linux__) +#include +#if defined(__GLIBC_PREREQ) +#define TEST_HAS_GLIBC +#define TEST_GLIBC_PREREQ(major, minor) __GLIBC_PREREQ(major, minor) +#endif +#endif + +#if TEST_STD_VER >= 11 +# define TEST_ALIGNOF(...) alignof(__VA_ARGS__) +# define TEST_ALIGNAS(...) alignas(__VA_ARGS__) +# define TEST_CONSTEXPR constexpr +# define TEST_NOEXCEPT noexcept +# define TEST_NOEXCEPT_FALSE noexcept(false) +# define TEST_NOEXCEPT_COND(...) noexcept(__VA_ARGS__) +#else +# if defined(TEST_COMPILER_CLANG) +# define TEST_ALIGNOF(...) _Alignof(__VA_ARGS__) +# else +# define TEST_ALIGNOF(...) __alignof(__VA_ARGS__) +# endif +# define TEST_ALIGNAS(...) __attribute__((__aligned__(__VA_ARGS__))) +# define TEST_CONSTEXPR +# define TEST_NOEXCEPT throw() +# define TEST_NOEXCEPT_FALSE +# define TEST_NOEXCEPT_COND(...) +#endif + +#if TEST_STD_VER >= 11 +# define TEST_THROW_SPEC(...) +#else +# define TEST_THROW_SPEC(...) throw(__VA_ARGS__) +#endif + +#if defined(__cpp_lib_is_constant_evaluated) && __cpp_lib_is_constant_evaluated >= 201811L +# define TEST_IS_CONSTANT_EVALUATED std::is_constant_evaluated() +#elif TEST_HAS_BUILTIN(__builtin_is_constant_evaluated) +# define TEST_IS_CONSTANT_EVALUATED __builtin_is_constant_evaluated() +#else +# define TEST_IS_CONSTANT_EVALUATED false +#endif + +#if TEST_STD_VER >= 23 +# define TEST_STD_AT_LEAST_23_OR_RUNTIME_EVALUATED true +#else +# define TEST_STD_AT_LEAST_23_OR_RUNTIME_EVALUATED (!TEST_IS_CONSTANT_EVALUATED) +#endif + +#if TEST_STD_VER >= 20 +# define TEST_STD_AT_LEAST_20_OR_RUNTIME_EVALUATED true +#else +# define TEST_STD_AT_LEAST_20_OR_RUNTIME_EVALUATED (!TEST_IS_CONSTANT_EVALUATED) +#endif + +#if TEST_STD_VER >= 14 +# define TEST_CONSTEXPR_CXX14 constexpr +#else +# define TEST_CONSTEXPR_CXX14 +#endif + +#if TEST_STD_VER >= 17 +# define TEST_CONSTEXPR_CXX17 constexpr +#else +# define TEST_CONSTEXPR_CXX17 +#endif + +#if TEST_STD_VER >= 20 +# define TEST_CONSTEXPR_CXX20 constexpr +#else +# define TEST_CONSTEXPR_CXX20 +#endif + +#if TEST_STD_VER >= 23 +# define TEST_CONSTEXPR_CXX23 constexpr +#else +# define TEST_CONSTEXPR_CXX23 +#endif + +#define TEST_ALIGNAS_TYPE(...) TEST_ALIGNAS(TEST_ALIGNOF(__VA_ARGS__)) + +#if !TEST_HAS_FEATURE(cxx_rtti) && !defined(__cpp_rtti) \ + && !defined(__GXX_RTTI) +#define TEST_HAS_NO_RTTI +#endif + +#if !defined(TEST_HAS_NO_RTTI) +# define RTTI_ASSERT(X) assert(X) +#else +# define RTTI_ASSERT(X) +#endif + +#if !TEST_HAS_FEATURE(cxx_exceptions) && !defined(__cpp_exceptions) \ + && !defined(__EXCEPTIONS) +#define TEST_HAS_NO_EXCEPTIONS +#endif + +#if TEST_HAS_FEATURE(address_sanitizer) || TEST_HAS_FEATURE(hwaddress_sanitizer) || \ + TEST_HAS_FEATURE(memory_sanitizer) || TEST_HAS_FEATURE(thread_sanitizer) +#define TEST_HAS_SANITIZERS +#define TEST_IS_EXECUTED_IN_A_SLOW_ENVIRONMENT +#endif + +#if defined(_LIBCPP_NORETURN) +#define TEST_NORETURN _LIBCPP_NORETURN +#else +#define TEST_NORETURN [[noreturn]] +#endif + +#if defined(_LIBCPP_HAS_NO_ALIGNED_ALLOCATION) || \ + (!(TEST_STD_VER > 14 || \ + (defined(__cpp_aligned_new) && __cpp_aligned_new >= 201606L))) +#define TEST_HAS_NO_ALIGNED_ALLOCATION +#endif + +#if TEST_STD_VER > 17 +#define TEST_CONSTINIT constinit +#else +#define TEST_CONSTINIT +#endif + +#if TEST_STD_VER < 11 +#define ASSERT_NOEXCEPT(...) +#define ASSERT_NOT_NOEXCEPT(...) +#else +#define ASSERT_NOEXCEPT(...) \ + static_assert(noexcept(__VA_ARGS__), "Operation must be noexcept") + +#define ASSERT_NOT_NOEXCEPT(...) \ + static_assert(!noexcept(__VA_ARGS__), "Operation must NOT be noexcept") +#endif + +/* Macros for testing libc++ specific behavior and extensions */ +#if defined(_LIBCPP_VERSION) +#define LIBCPP_ASSERT(...) assert(__VA_ARGS__) +#define LIBCPP_STATIC_ASSERT(...) static_assert(__VA_ARGS__) +#define LIBCPP_ASSERT_NOEXCEPT(...) ASSERT_NOEXCEPT(__VA_ARGS__) +#define LIBCPP_ASSERT_NOT_NOEXCEPT(...) ASSERT_NOT_NOEXCEPT(__VA_ARGS__) +#define LIBCPP_ONLY(...) __VA_ARGS__ +#else +#define LIBCPP_ASSERT(...) static_assert(true, "") +#define LIBCPP_STATIC_ASSERT(...) static_assert(true, "") +#define LIBCPP_ASSERT_NOEXCEPT(...) static_assert(true, "") +#define LIBCPP_ASSERT_NOT_NOEXCEPT(...) static_assert(true, "") +#define LIBCPP_ONLY(...) static_assert(true, "") +#endif + +#if __has_cpp_attribute(nodiscard) +# define TEST_NODISCARD [[nodiscard]] +#else +# define TEST_NODISCARD +#endif + +#define TEST_IGNORE_NODISCARD (void) + +namespace test_macros_detail { +template +struct is_same { enum { value = 0};} ; +template +struct is_same { enum {value = 1}; }; +} // namespace test_macros_detail + +#define ASSERT_SAME_TYPE(...) \ + static_assert((test_macros_detail::is_same<__VA_ARGS__>::value), \ + "Types differ unexpectedly") + +#ifndef TEST_HAS_NO_EXCEPTIONS +#define TEST_THROW(...) throw __VA_ARGS__ +#else +#if defined(__GNUC__) +#define TEST_THROW(...) __builtin_abort() +#else +#include +#define TEST_THROW(...) ::abort() +#endif +#endif + +#if defined(__GNUC__) || defined(__clang__) +// This function can be used to hide some objects from compiler optimizations. +// +// For example, this is useful to hide the result of a call to `new` and ensure +// that the compiler doesn't elide the call to new/delete. Otherwise, elliding +// calls to new/delete is allowed by the Standard and compilers actually do it +// when optimizations are enabled. +template +inline Tp const& DoNotOptimize(Tp const& value) { + asm volatile("" : : "r,m"(value) : "memory"); + return value; +} + +template +inline Tp& DoNotOptimize(Tp& value) { +#if defined(__clang__) + asm volatile("" : "+r,m"(value) : : "memory"); +#else + asm volatile("" : "+m,r"(value) : : "memory"); +#endif + return value; +} +#else +#include +template +inline Tp const& DoNotOptimize(Tp const& value) { + const volatile void* volatile unused = __builtin_addressof(value); + static_cast(unused); + _ReadWriteBarrier(); + return value; +} +#endif + +#if defined(__GNUC__) +#define TEST_ALWAYS_INLINE __attribute__((always_inline)) +#define TEST_NOINLINE __attribute__((noinline)) +#elif defined(_MSC_VER) +#define TEST_ALWAYS_INLINE __forceinline +#define TEST_NOINLINE __declspec(noinline) +#else +#define TEST_ALWAYS_INLINE +#define TEST_NOINLINE +#endif + +#ifdef _WIN32 +#define TEST_NOT_WIN32(...) ((void)0) +#else +#define TEST_NOT_WIN32(...) __VA_ARGS__ +#endif + +#if defined(TEST_WINDOWS_DLL) ||defined(__MVS__) || defined(_AIX) +// Macros for waiving cases when we can't count allocations done within +// the library implementation. +// +// On Windows, when libc++ is built as a DLL, references to operator new/delete +// within the DLL are bound at link time to the operator new/delete within +// the library; replacing them in the user executable doesn't override the +// calls within the library. +// +// The same goes on IBM zOS. +// The same goes on AIX. +#define ASSERT_WITH_LIBRARY_INTERNAL_ALLOCATIONS(...) ((void)(__VA_ARGS__)) +#define TEST_SUPPORTS_LIBRARY_INTERNAL_ALLOCATIONS 0 +#else +#define ASSERT_WITH_LIBRARY_INTERNAL_ALLOCATIONS(...) assert(__VA_ARGS__) +#define TEST_SUPPORTS_LIBRARY_INTERNAL_ALLOCATIONS 1 +#endif + +#if (defined(TEST_WINDOWS_DLL) && !defined(_MSC_VER)) || \ + defined(__MVS__) +// Normally, a replaced e.g. 'operator new' ends up used if the user code +// does a call to e.g. 'operator new[]'; it's enough to replace the base +// versions and have it override all of them. +// +// When the fallback operators are located within the libc++ library and we +// can't override the calls within it (see above), this fallback mechanism +// doesn't work either. +// +// On Windows, when using the MSVC vcruntime, the operator new/delete fallbacks +// are linked separately from the libc++ library, linked statically into +// the end user executable, and these fallbacks work even in DLL configurations. +// In MinGW configurations when built as a DLL, and on zOS, these fallbacks +// don't work though. +#define ASSERT_WITH_OPERATOR_NEW_FALLBACKS(...) ((void)(__VA_ARGS__)) +#else +#define ASSERT_WITH_OPERATOR_NEW_FALLBACKS(...) assert(__VA_ARGS__) +#endif + +#ifdef _WIN32 +#define TEST_WIN_NO_FILESYSTEM_PERMS_NONE +#endif + +// Support for carving out parts of the test suite, like removing wide characters, etc. +#if defined(_LIBCPP_HAS_NO_WIDE_CHARACTERS) +# define TEST_HAS_NO_WIDE_CHARACTERS +#endif + +#if defined(_LIBCPP_HAS_NO_UNICODE) +# define TEST_HAS_NO_UNICODE +#elif defined(_MSVC_EXECUTION_CHARACTER_SET) && _MSVC_EXECUTION_CHARACTER_SET != 65001 +# define TEST_HAS_NO_UNICODE +#endif + +#if defined(_LIBCPP_HAS_OPEN_WITH_WCHAR) +# define TEST_HAS_OPEN_WITH_WCHAR +#endif + +#if defined(_LIBCPP_HAS_NO_INT128) || defined(_MSVC_STL_VERSION) +# define TEST_HAS_NO_INT128 +#endif + +#if defined(_LIBCPP_HAS_NO_LOCALIZATION) +# define TEST_HAS_NO_LOCALIZATION +#endif + +#if TEST_STD_VER <= 17 || !defined(__cpp_char8_t) +# define TEST_HAS_NO_CHAR8_T +#endif + +#if defined(_LIBCPP_HAS_NO_THREADS) +# define TEST_HAS_NO_THREADS +#endif + +#if defined(_LIBCPP_HAS_NO_FILESYSTEM) +# define TEST_HAS_NO_FILESYSTEM +#endif + +#if defined(_LIBCPP_HAS_NO_C8RTOMB_MBRTOC8) +# define TEST_HAS_NO_C8RTOMB_MBRTOC8 +#endif + +#if defined(_LIBCPP_HAS_NO_RANDOM_DEVICE) +# define TEST_HAS_NO_RANDOM_DEVICE +#endif + +#if defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB) +# define TEST_HAS_NO_EXPERIMENTAL_TZDB +#endif + +#if defined(_LIBCPP_HAS_NO_TIME_ZONE_DATABASE) +# define TEST_HAS_NO_TIME_ZONE_DATABASE +#endif + +#if defined(TEST_COMPILER_CLANG) +# define TEST_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push") +# define TEST_DIAGNOSTIC_POP _Pragma("clang diagnostic pop") +# define TEST_CLANG_DIAGNOSTIC_IGNORED(str) _Pragma(TEST_STRINGIZE(clang diagnostic ignored str)) +# define TEST_GCC_DIAGNOSTIC_IGNORED(str) +# define TEST_MSVC_DIAGNOSTIC_IGNORED(num) +#elif defined(TEST_COMPILER_GCC) +# define TEST_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push") +# define TEST_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop") +# define TEST_CLANG_DIAGNOSTIC_IGNORED(str) +# define TEST_GCC_DIAGNOSTIC_IGNORED(str) _Pragma(TEST_STRINGIZE(GCC diagnostic ignored str)) +# define TEST_MSVC_DIAGNOSTIC_IGNORED(num) +#elif defined(TEST_COMPILER_MSVC) +# define TEST_DIAGNOSTIC_PUSH _Pragma("warning(push)") +# define TEST_DIAGNOSTIC_POP _Pragma("warning(pop)") +# define TEST_CLANG_DIAGNOSTIC_IGNORED(str) +# define TEST_GCC_DIAGNOSTIC_IGNORED(str) +# define TEST_MSVC_DIAGNOSTIC_IGNORED(num) _Pragma(TEST_STRINGIZE(warning(disable: num))) +#else +# define TEST_DIAGNOSTIC_PUSH +# define TEST_DIAGNOSTIC_POP +# define TEST_CLANG_DIAGNOSTIC_IGNORED(str) +# define TEST_GCC_DIAGNOSTIC_IGNORED(str) +# define TEST_MSVC_DIAGNOSTIC_IGNORED(num) +#endif + +#if __has_cpp_attribute(msvc::no_unique_address) +#define TEST_NO_UNIQUE_ADDRESS [[msvc::no_unique_address]] +#elif __has_cpp_attribute(no_unique_address) +#define TEST_NO_UNIQUE_ADDRESS [[no_unique_address]] +#else +#define TEST_NO_UNIQUE_ADDRESS +#endif + +#ifdef _LIBCPP_SHORT_WCHAR +# define TEST_SHORT_WCHAR +#endif + +#ifdef _LIBCPP_ABI_MICROSOFT +# define TEST_ABI_MICROSOFT +#endif + +// This is a temporary workaround for user-defined `operator new` definitions +// not being picked up on Apple platforms in some circumstances. This is under +// investigation and should be short-lived. +#ifdef __APPLE__ +# define TEST_WORKAROUND_BUG_109234844_WEAK __attribute__((weak)) +#else +# define TEST_WORKAROUND_BUG_109234844_WEAK /* nothing */ +#endif + +#ifdef _AIX +# define TEST_IF_AIX(arg_true, arg_false) arg_true +#else +# define TEST_IF_AIX(arg_true, arg_false) arg_false +#endif + +// Clang-18 has support for deducing this, but it does not set the FTM. +#ifdef _LIBCPP_HAS_EXPLICIT_THIS_PARAMETER +# define TEST_HAS_EXPLICIT_THIS_PARAMETER +#endif + +#endif // SUPPORT_TEST_MACROS_HPP diff --git a/test/xpu_api/ranges/test_range.h b/test/xpu_api/ranges/test_range.h new file mode 100644 index 0000000000..4efa26f266 --- /dev/null +++ b/test/xpu_api/ranges/test_range.h @@ -0,0 +1,109 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LIBCXX_TEST_SUPPORT_TEST_RANGE_H +#define LIBCXX_TEST_SUPPORT_TEST_RANGE_H + +#include +#include +#include +#include +#include + +#include "test_iterators.h" + +#if TEST_STD_VER < 17 +# error "test/support/test_range.h" can only be included in builds supporting ranges +#endif + +struct sentinel { + bool operator==(std::input_or_output_iterator auto const&) const; +}; + +template