[libcxx-commits] [libcxx] [libc++][c++17] P0452: Implementing PSTL overloads for `std::transform_{ex, in}clusive_scan` (PR #195548)

via libcxx-commits libcxx-commits at lists.llvm.org
Sun May 3 13:25:21 PDT 2026


https://github.com/PaulXiCao created https://github.com/llvm/llvm-project/pull/195548

Closes 99948.

>From 8301a5ae47251c0c760aa9dc39b114f23cc5532b Mon Sep 17 00:00:00 2001
From: Paul <paulxicao7 at gmail.com>
Date: Sun, 3 May 2026 12:44:33 +0200
Subject: [PATCH 1/9] mark paper status as complete

---
 libcxx/docs/Status/Cxx17Papers.csv | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libcxx/docs/Status/Cxx17Papers.csv b/libcxx/docs/Status/Cxx17Papers.csv
index ba2ceeedc2ce8..c3e6c4d16c6b4 100644
--- a/libcxx/docs/Status/Cxx17Papers.csv
+++ b/libcxx/docs/Status/Cxx17Papers.csv
@@ -95,7 +95,7 @@
 "`P0317R1 <https://wg21.link/P0317R1>`__","Directory Entry Caching for Filesystem","2017-02 (Kona)","|Complete|","7","`#103684 <https://github.com/llvm/llvm-project/issues/103684>`__",""
 "`P0430R2 <https://wg21.link/P0430R2>`__","File system library on non-POSIX-like operating systems","2017-02 (Kona)","|Complete|","7","`#103685 <https://github.com/llvm/llvm-project/issues/103685>`__",""
 "`P0433R2 <https://wg21.link/P0433R2>`__","Toward a resolution of US7 and US14: Integrating template deduction for class templates into the standard library","2017-02 (Kona)","|Complete|","14","`#103686 <https://github.com/llvm/llvm-project/issues/103686>`__",""
-"`P0452R1 <https://wg21.link/P0452R1>`__","Unifying <numeric> Parallel Algorithms","2017-02 (Kona)","|Partial|","","`#99948 <https://github.com/llvm/llvm-project/issues/99948>`__","The changes to ``std::transform_inclusive_scan`` and ``std::transform_exclusive_scan`` have not yet been implemented."
+"`P0452R1 <https://wg21.link/P0452R1>`__","Unifying <numeric> Parallel Algorithms","2017-02 (Kona)","|Complete|","","`#99948 <https://github.com/llvm/llvm-project/issues/99948>`__",""
 "`P0467R2 <https://wg21.link/P0467R2>`__","Iterator Concerns for Parallel Algorithms","2017-02 (Kona)","|Partial|","","`#99949 <https://github.com/llvm/llvm-project/issues/99949>`__",""
 "`P0492R2 <https://wg21.link/P0492R2>`__","Proposed Resolution of C++17 National Body Comments for Filesystems","2017-02 (Kona)","|Complete|","7","`#103687 <https://github.com/llvm/llvm-project/issues/103687>`__",""
 "`P0518R1 <https://wg21.link/P0518R1>`__","Allowing copies as arguments to function objects given to parallel algorithms in response to CH11","2017-02 (Kona)","|Nothing To Do|","","`#103689 <https://github.com/llvm/llvm-project/issues/103689>`__",""

>From 60d06f0b569478b21882830fcd886bffdc5d3cfe Mon Sep 17 00:00:00 2001
From: Paul <paulxicao7 at gmail.com>
Date: Sun, 3 May 2026 12:44:47 +0200
Subject: [PATCH 2/9] backend_fwd: __transform_exclusive_scan

---
 libcxx/include/__pstl/backend_fwd.h | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/libcxx/include/__pstl/backend_fwd.h b/libcxx/include/__pstl/backend_fwd.h
index a52e6db954d0c..3cad5b8c461f0 100644
--- a/libcxx/include/__pstl/backend_fwd.h
+++ b/libcxx/include/__pstl/backend_fwd.h
@@ -303,6 +303,17 @@ struct __is_sorted;
 // optional<bool>
 // operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Comp&& __comp) const noexcept;
 
+template <class _Backend, class _ExecutionPolicy>
+struct __transform_exclusive_scan;
+// template <class _Policy, class _ForwardIterator1, class _ForwardIterator2,
+//           class _Tp, class _BinaryOperation, class _UnaryOperation>
+// optional<_ForwardIterator2>
+// operator()(_Policy&&,
+//            _ForwardIterator1 __first, _ForwardIterator1 __last,
+//            _ForwardIterator2 __result,
+//            _Tp __init,
+//            _BinaryOperation __binary_op,
+//            _UnaryOperation __unary_op) const noexcept;
 } // namespace __pstl
 _LIBCPP_END_NAMESPACE_STD
 

>From 74bfc8ad3df48b1b158aa55e4a8bf3553cb66e5f Mon Sep 17 00:00:00 2001
From: Paul <paulxicao7 at gmail.com>
Date: Sun, 3 May 2026 19:05:10 +0200
Subject: [PATCH 3/9] backend_fwd: __transform_inclusive_scan

---
 libcxx/include/__pstl/backend_fwd.h | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/libcxx/include/__pstl/backend_fwd.h b/libcxx/include/__pstl/backend_fwd.h
index 3cad5b8c461f0..bf0e3cd47488f 100644
--- a/libcxx/include/__pstl/backend_fwd.h
+++ b/libcxx/include/__pstl/backend_fwd.h
@@ -314,6 +314,27 @@ struct __transform_exclusive_scan;
 //            _Tp __init,
 //            _BinaryOperation __binary_op,
 //            _UnaryOperation __unary_op) const noexcept;
+
+template <class _Backend, class _ExecutionPolicy>
+struct __transform_inclusive_scan;
+// template <class _Policy, class _ForwardIterator1, class _ForwardIterator2,
+//           class _BinaryOperation, class _UnaryOperation>
+// optional<_ForwardIterator2>
+// operator()(_Policy&&,
+//            _ForwardIterator1 __first, _ForwardIterator1 __last,
+//            _ForwardIterator2 __result,
+//            _BinaryOperation __binary_op,
+//            _UnaryOperation __unary_op) const noexcept;
+//
+// template <class _Policy, class _ForwardIterator1, class _ForwardIterator2,
+//           class _BinaryOperation, class _UnaryOperation, class _Tp>
+// optional<_ForwardIterator2>
+// operator()(_Policy&&,
+//            _ForwardIterator1 __first, _ForwardIterator1 __last,
+//            _ForwardIterator2 __result,
+//            _BinaryOperation __binary_op,
+//            _UnaryOperation __unary_op,
+//            _Tp __init) const noexcept;
 } // namespace __pstl
 _LIBCPP_END_NAMESPACE_STD
 

>From 6077b955a9d72c7da60438adafa5a6a6cd6b850b Mon Sep 17 00:00:00 2001
From: Paul <paulxicao7 at gmail.com>
Date: Sun, 3 May 2026 19:17:45 +0200
Subject: [PATCH 4/9] transform_exclusive_scan for __serial_backend_tag

---
 libcxx/include/__pstl/backends/serial.h | 27 +++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/libcxx/include/__pstl/backends/serial.h b/libcxx/include/__pstl/backends/serial.h
index f4142016ccc79..a96b79eded118 100644
--- a/libcxx/include/__pstl/backends/serial.h
+++ b/libcxx/include/__pstl/backends/serial.h
@@ -16,6 +16,7 @@
 #include <__algorithm/stable_sort.h>
 #include <__algorithm/transform.h>
 #include <__config>
+#include <__numeric/transform_exclusive_scan.h>
 #include <__numeric/transform_reduce.h>
 #include <__pstl/backend_fwd.h>
 #include <__utility/empty.h>
@@ -175,6 +176,32 @@ struct __transform_reduce_binary<__serial_backend_tag, _ExecutionPolicy> {
   }
 };
 
+template <class _ExecutionPolicy>
+struct __transform_exclusive_scan<__serial_backend_tag, _ExecutionPolicy> {
+  template <class _Policy,
+            class _ForwardIterator1,
+            class _ForwardIterator2,
+            class _Tp,
+            class _BinaryOperation,
+            class _UnaryOperation>
+  _LIBCPP_HIDE_FROM_ABI optional<_ForwardIterator2> operator()(
+      _Policy&&,
+      _ForwardIterator1 __first,
+      _ForwardIterator1 __last,
+      _ForwardIterator2 __result,
+      _Tp __init,
+      _BinaryOperation&& __binary_op,
+      _UnaryOperation&& __unary_op) const noexcept {
+    return std::transform_exclusive_scan(
+        std::move(__first),
+        std::move(__last),
+        std::move(__result),
+        std::move(__init),
+        std::forward<_BinaryOperation>(__binary_op),
+        std::forward<_UnaryOperation>(__unary_op));
+  }
+};
+
 } // namespace __pstl
 _LIBCPP_END_NAMESPACE_STD
 

>From f869e770057cda22d20014a175210a2cb47b4649 Mon Sep 17 00:00:00 2001
From: Paul <paulxicao7 at gmail.com>
Date: Sun, 3 May 2026 21:31:32 +0200
Subject: [PATCH 5/9] transform_inclusive_scan for __serial_backend_tag

---
 libcxx/include/__pstl/backends/serial.h | 46 +++++++++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/libcxx/include/__pstl/backends/serial.h b/libcxx/include/__pstl/backends/serial.h
index a96b79eded118..5bae6397bcc53 100644
--- a/libcxx/include/__pstl/backends/serial.h
+++ b/libcxx/include/__pstl/backends/serial.h
@@ -17,6 +17,7 @@
 #include <__algorithm/transform.h>
 #include <__config>
 #include <__numeric/transform_exclusive_scan.h>
+#include <__numeric/transform_inclusive_scan.h>
 #include <__numeric/transform_reduce.h>
 #include <__pstl/backend_fwd.h>
 #include <__utility/empty.h>
@@ -202,6 +203,51 @@ struct __transform_exclusive_scan<__serial_backend_tag, _ExecutionPolicy> {
   }
 };
 
+template <class _ExecutionPolicy>
+struct __transform_inclusive_scan<__serial_backend_tag, _ExecutionPolicy> {
+  template <class _Policy,
+            class _ForwardIterator1,
+            class _ForwardIterator2,
+            class _BinaryOperation,
+            class _UnaryOperation>
+  _LIBCPP_HIDE_FROM_ABI optional<_ForwardIterator2>
+  operator()(_Policy&&,
+             _ForwardIterator1 __first,
+             _ForwardIterator1 __last,
+             _ForwardIterator2 __result,
+             _BinaryOperation&& __binary_op,
+             _UnaryOperation&& __unary_op) const noexcept {
+    return std::transform_inclusive_scan(
+        std::move(__first),
+        std::move(__last),
+        std::move(__result),
+        std::forward<_BinaryOperation>(__binary_op),
+        std::forward<_UnaryOperation>(__unary_op));
+  }
+
+  template <class _Policy,
+            class _ForwardIterator1,
+            class _ForwardIterator2,
+            class _BinaryOperation,
+            class _UnaryOperation,
+            class _Tp>
+  _LIBCPP_HIDE_FROM_ABI optional<_ForwardIterator2> operator()(
+      _Policy&&,
+      _ForwardIterator1 __first,
+      _ForwardIterator1 __last,
+      _ForwardIterator2 __result,
+      _BinaryOperation&& __binary_op,
+      _UnaryOperation&& __unary_op,
+      _Tp __init) const noexcept {
+    return std::transform_inclusive_scan(
+        std::move(__first),
+        std::move(__last),
+        std::move(__result),
+        std::forward<_BinaryOperation>(__binary_op),
+        std::forward<_UnaryOperation>(__unary_op),
+        std::move(__init));
+  }
+};
 } // namespace __pstl
 _LIBCPP_END_NAMESPACE_STD
 

>From 5dd255fe68ac956e2735e94cc67c265f8c822c4b Mon Sep 17 00:00:00 2001
From: Paul <paulxicao7 at gmail.com>
Date: Sun, 3 May 2026 21:42:37 +0200
Subject: [PATCH 6/9] transform_*_scan for default_backend

---
 libcxx/include/__pstl/backends/default.h | 77 ++++++++++++++++++++++++
 1 file changed, 77 insertions(+)

diff --git a/libcxx/include/__pstl/backends/default.h b/libcxx/include/__pstl/backends/default.h
index be90715af13b5..9762124f3d9ce 100644
--- a/libcxx/include/__pstl/backends/default.h
+++ b/libcxx/include/__pstl/backends/default.h
@@ -21,6 +21,8 @@
 #include <__iterator/concepts.h>
 #include <__iterator/iterator_traits.h>
 #include <__iterator/next.h>
+#include <__numeric/transform_exclusive_scan.h>
+#include <__numeric/transform_inclusive_scan.h>
 #include <__pstl/backend_fwd.h>
 #include <__pstl/dispatch.h>
 #include <__utility/empty.h>
@@ -420,6 +422,81 @@ struct __is_sorted<__default_backend_tag, _ExecutionPolicy> {
   }
 };
 
+//////////////////////////////////////////////////////////////
+// transform_*clusive_scan family
+//////////////////////////////////////////////////////////////
+template <class _ExecutionPolicy>
+struct __transform_exclusive_scan<__default_backend_tag, _ExecutionPolicy> {
+  template <class _Policy,
+            class _ForwardIterator1,
+            class _ForwardIterator2,
+            class _Tp,
+            class _BinaryOperation,
+            class _UnaryOperation>
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<_ForwardIterator2> operator()(
+      _Policy&&,
+      _ForwardIterator1 __first,
+      _ForwardIterator1 __last,
+      _ForwardIterator2 __result,
+      _Tp __init,
+      _BinaryOperation&& __binary_op,
+      _UnaryOperation&& __unary_op) const noexcept {
+    return std::transform_exclusive_scan(
+        std::move(__first),
+        std::move(__last),
+        std::move(__result),
+        std::move(__init),
+        std::forward<_BinaryOperation>(__binary_op),
+        std::forward<_UnaryOperation>(__unary_op));
+  }
+};
+
+template <class _ExecutionPolicy>
+struct __transform_inclusive_scan<__default_backend_tag, _ExecutionPolicy> {
+  template <class _Policy,
+            class _ForwardIterator1,
+            class _ForwardIterator2,
+            class _BinaryOperation,
+            class _UnaryOperation>
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<_ForwardIterator2>
+  operator()(_Policy&&,
+             _ForwardIterator1 __first,
+             _ForwardIterator1 __last,
+             _ForwardIterator2 __result,
+             _BinaryOperation&& __binary_op,
+             _UnaryOperation&& __unary_op) const noexcept {
+    return std::transform_inclusive_scan(
+        std::move(__first),
+        std::move(__last),
+        std::move(__result),
+        std::forward<_BinaryOperation>(__binary_op),
+        std::forward<_UnaryOperation>(__unary_op));
+  }
+
+  template <class _Policy,
+            class _ForwardIterator1,
+            class _ForwardIterator2,
+            class _BinaryOperation,
+            class _UnaryOperation,
+            class _Tp>
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<_ForwardIterator2> operator()(
+      _Policy&&,
+      _ForwardIterator1 __first,
+      _ForwardIterator1 __last,
+      _ForwardIterator2 __result,
+      _BinaryOperation&& __binary_op,
+      _UnaryOperation&& __unary_op,
+      _Tp __init) const noexcept {
+    return std::transform_inclusive_scan(
+        std::move(__first),
+        std::move(__last),
+        std::move(__result),
+        std::forward<_BinaryOperation>(__binary_op),
+        std::forward<_UnaryOperation>(__unary_op),
+        std::move(__init));
+  }
+};
+
 //////////////////////////////////////////////////////////////
 // transform family
 //////////////////////////////////////////////////////////////

>From ba42c590fcdf6d8072217f7d4fc4a138f0e81c88 Mon Sep 17 00:00:00 2001
From: Paul <paulxicao7 at gmail.com>
Date: Sun, 3 May 2026 21:56:43 +0200
Subject: [PATCH 7/9] pstl: transform_exclusive_scan

---
 libcxx/include/__numeric/pstl.h | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/libcxx/include/__numeric/pstl.h b/libcxx/include/__numeric/pstl.h
index fe7b2cc7a82cc..442b32e8ab12a 100644
--- a/libcxx/include/__numeric/pstl.h
+++ b/libcxx/include/__numeric/pstl.h
@@ -9,6 +9,7 @@
 #ifndef _LIBCPP___NUMERIC_PSTL_H
 #define _LIBCPP___NUMERIC_PSTL_H
 
+#include "__pstl/backend_fwd.h"
 #include <__config>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -165,6 +166,36 @@ _LIBCPP_HIDE_FROM_ABI _Tp transform_reduce(
       std::move(__transform));
 }
 
+template <class _ExecutionPolicy,
+          class _ForwardIterator1,
+          class _ForwardIterator2,
+          class _Tp,
+          class _BinaryOperation,
+          class _UnaryOperation,
+          class _RawPolicy                                    = __remove_cvref_t<_ExecutionPolicy>,
+          enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
+_LIBCPP_HIDE_FROM_ABI _ForwardIterator2 transform_exclusive_scan(
+    _ExecutionPolicy&& __policy,
+    _ForwardIterator1 __first,
+    _ForwardIterator1 __last,
+    _ForwardIterator2 __result,
+    _Tp __init,
+    _BinaryOperation __binary_op,
+    _UnaryOperation __unary_op) {
+  _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator1, "transform_exclusive_scan requires ForwardIterators");
+  _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator2, "transform_exclusive_scan requires ForwardIterators");
+  using _Implementation =
+      __pstl::__dispatch<__pstl::__transform_exclusive_scan, __pstl::__current_configuration, _RawPolicy>;
+  return __pstl::__handle_exception<_Implementation>(
+      std::forward<_ExecutionPolicy>(__policy),
+      std::move(__first),
+      std::move(__last),
+      std::move(__result),
+      std::move(__init),
+      std::move(__binary_op),
+      std::move(__unary_op));
+}
+
 _LIBCPP_END_NAMESPACE_STD
 
 #endif // _LIBCPP_HAS_EXPERIMENTAL_PSTL && _LIBCPP_STD_VER >= 17

>From 966477d08be10e8c7886db1ef2f5cb2e67b64aea Mon Sep 17 00:00:00 2001
From: Paul <paulxicao7 at gmail.com>
Date: Sun, 3 May 2026 21:59:45 +0200
Subject: [PATCH 8/9] pstl: transform_inclusive_scan

---
 libcxx/include/__numeric/pstl.h | 57 +++++++++++++++++++++++++++++++++
 1 file changed, 57 insertions(+)

diff --git a/libcxx/include/__numeric/pstl.h b/libcxx/include/__numeric/pstl.h
index 442b32e8ab12a..41ba3c85c2366 100644
--- a/libcxx/include/__numeric/pstl.h
+++ b/libcxx/include/__numeric/pstl.h
@@ -196,6 +196,63 @@ _LIBCPP_HIDE_FROM_ABI _ForwardIterator2 transform_exclusive_scan(
       std::move(__unary_op));
 }
 
+template <class _ExecutionPolicy,
+          class _ForwardIterator1,
+          class _ForwardIterator2,
+          class _BinaryOperation,
+          class _UnaryOperation,
+          class _RawPolicy                                    = __remove_cvref_t<_ExecutionPolicy>,
+          enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
+_LIBCPP_HIDE_FROM_ABI _ForwardIterator2 transform_inclusive_scan(
+    _ExecutionPolicy&& __policy,
+    _ForwardIterator1 __first,
+    _ForwardIterator1 __last,
+    _ForwardIterator2 __result,
+    _BinaryOperation __binary_op,
+    _UnaryOperation __unary_op) {
+  _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator1, "transform_inclusive_scan requires ForwardIterators");
+  _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator2, "transform_inclusive_scan requires ForwardIterators");
+  using _Implementation =
+      __pstl::__dispatch<__pstl::__transform_inclusive_scan, __pstl::__current_configuration, _RawPolicy>;
+  return __pstl::__handle_exception<_Implementation>(
+      std::forward<_ExecutionPolicy>(__policy),
+      std::move(__first),
+      std::move(__last),
+      std::move(__result),
+      std::move(__binary_op),
+      std::move(__unary_op));
+}
+
+template <class _ExecutionPolicy,
+          class _ForwardIterator1,
+          class _ForwardIterator2,
+          class _Tp,
+          class _BinaryOperation,
+          class _UnaryOperation,
+          class _RawPolicy                                    = __remove_cvref_t<_ExecutionPolicy>,
+          enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
+_LIBCPP_HIDE_FROM_ABI _ForwardIterator2 transform_inclusive_scan(
+    _ExecutionPolicy&& __policy,
+    _ForwardIterator1 __first,
+    _ForwardIterator1 __last,
+    _ForwardIterator2 __result,
+    _BinaryOperation __binary_op,
+    _UnaryOperation __unary_op,
+    _Tp __init) {
+  _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator1, "transform_inclusive_scan requires ForwardIterators");
+  _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator2, "transform_inclusive_scan requires ForwardIterators");
+  using _Implementation =
+      __pstl::__dispatch<__pstl::__transform_inclusive_scan, __pstl::__current_configuration, _RawPolicy>;
+  return __pstl::__handle_exception<_Implementation>(
+      std::forward<_ExecutionPolicy>(__policy),
+      std::move(__first),
+      std::move(__last),
+      std::move(__result),
+      std::move(__binary_op),
+      std::move(__unary_op),
+      std::move(__init));
+}
+
 _LIBCPP_END_NAMESPACE_STD
 
 #endif // _LIBCPP_HAS_EXPERIMENTAL_PSTL && _LIBCPP_STD_VER >= 17

>From db659b7bd9c74b172ec29b7425336485b65420f3 Mon Sep 17 00:00:00 2001
From: Paul <paulxicao7 at gmail.com>
Date: Sun, 3 May 2026 22:21:30 +0200
Subject: [PATCH 9/9] tests

---
 .../pstl.transform_exclusive_scan.pass.cpp    |  73 +++++++++++
 .../pstl.transform_inclusive_scan.pass.cpp    | 118 ++++++++++++++++++
 2 files changed, 191 insertions(+)
 create mode 100644 libcxx/test/std/numerics/numeric.ops/transform.exclusive.scan/pstl.transform_exclusive_scan.pass.cpp
 create mode 100644 libcxx/test/std/numerics/numeric.ops/transform.inclusive.scan/pstl.transform_inclusive_scan.pass.cpp

diff --git a/libcxx/test/std/numerics/numeric.ops/transform.exclusive.scan/pstl.transform_exclusive_scan.pass.cpp b/libcxx/test/std/numerics/numeric.ops/transform.exclusive.scan/pstl.transform_exclusive_scan.pass.cpp
new file mode 100644
index 0000000000000..506c83ea6ccbd
--- /dev/null
+++ b/libcxx/test/std/numerics/numeric.ops/transform.exclusive.scan/pstl.transform_exclusive_scan.pass.cpp
@@ -0,0 +1,73 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++17
+
+// UNSUPPORTED: libcpp-has-no-incomplete-pstl
+
+// <numeric>
+
+// template<class ExecutionPolicy,
+//          class ForwardIterator1, class ForwardIterator2, class T,
+//          class BinaryOperation, class UnaryOperation>
+//   ForwardIterator2
+//   transform_exclusive_scan(ExecutionPolicy&& exec,
+//                            ForwardIterator1 first, ForwardIterator1 last,
+//                            ForwardIterator2 result,
+//                            T init,
+//                            BinaryOperation binary_op,
+//                            UnaryOperation unary_op);
+
+#include <cassert>
+#include <numeric>
+#include <string>
+#include <vector>
+
+#include "test_execution_policies.h"
+#include "test_iterators.h"
+#include "type_algorithms.h"
+
+template <class Iter>
+struct Test {
+  template <class Policy>
+  void operator()(Policy&& policy) {
+    for (int size : {0, 1, 2, 100, 350}) {
+      std::vector<int> a(size);
+      for (int i = 0; i != size; ++i)
+        a[i] = i;
+
+      std::vector<int> expected(size);
+      std::transform_exclusive_scan(
+          a.begin(), a.end(), expected.begin(), 0, std::plus{}, [](int x) { return x + 1; });
+
+      std::vector<int> result(size);
+      auto ret = std::transform_exclusive_scan(
+          policy,
+          Iter(std::data(a)),
+          Iter(std::data(a) + std::size(a)),
+          std::data(result),
+          0,
+          [check = std::string("Banane")](int i, int j) {
+            assert(check == "Banane");
+            return i + j;
+          },
+          [check = std::string("Banane")](int i) {
+            assert(check == "Banane");
+            return i + 1;
+          });
+      static_assert(std::is_same_v<decltype(ret), int*>);
+      assert(ret == std::data(result) + size);
+      assert(result == expected);
+    }
+  }
+};
+
+int main(int, char**) {
+  types::for_each(types::forward_iterator_list<int*>{}, TestIteratorWithPolicies<Test>{});
+  return 0;
+}
diff --git a/libcxx/test/std/numerics/numeric.ops/transform.inclusive.scan/pstl.transform_inclusive_scan.pass.cpp b/libcxx/test/std/numerics/numeric.ops/transform.inclusive.scan/pstl.transform_inclusive_scan.pass.cpp
new file mode 100644
index 0000000000000..54c800a29f243
--- /dev/null
+++ b/libcxx/test/std/numerics/numeric.ops/transform.inclusive.scan/pstl.transform_inclusive_scan.pass.cpp
@@ -0,0 +1,118 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++17
+
+// UNSUPPORTED: libcpp-has-no-incomplete-pstl
+
+// <numeric>
+
+// template<class ExecutionPolicy,
+//          class ForwardIterator1, class ForwardIterator2,
+//          class BinaryOperation, class UnaryOperation>
+//   ForwardIterator2
+//   transform_inclusive_scan(ExecutionPolicy&& exec,
+//                            ForwardIterator1 first, ForwardIterator1 last,
+//                            ForwardIterator2 result,
+//                            BinaryOperation binary_op,
+//                            UnaryOperation unary_op);
+//
+// template<class ExecutionPolicy,
+//          class ForwardIterator1, class ForwardIterator2,
+//          class BinaryOperation, class UnaryOperation, class T>
+//   ForwardIterator2
+//   transform_inclusive_scan(ExecutionPolicy&& exec,
+//                            ForwardIterator1 first, ForwardIterator1 last,
+//                            ForwardIterator2 result,
+//                            BinaryOperation binary_op,
+//                            UnaryOperation unary_op,
+//                            T init);
+
+#include <cassert>
+#include <numeric>
+#include <string>
+#include <vector>
+
+#include "test_execution_policies.h"
+#include "test_iterators.h"
+#include "type_algorithms.h"
+
+template <class Iter>
+struct TestNoInit {
+  template <class Policy>
+  void operator()(Policy&& policy) {
+    for (int size : {0, 1, 2, 100, 350}) {
+      std::vector<int> a(size);
+      for (int i = 0; i != size; ++i)
+        a[i] = i + 1;
+
+      std::vector<int> expected(size);
+      std::transform_inclusive_scan(
+          a.begin(), a.end(), expected.begin(), std::plus{}, [](int x) { return x + 1; });
+
+      std::vector<int> result(size);
+      auto ret = std::transform_inclusive_scan(
+          policy,
+          Iter(std::data(a)),
+          Iter(std::data(a) + std::size(a)),
+          std::data(result),
+          [check = std::string("Banane")](int i, int j) {
+            assert(check == "Banane");
+            return i + j;
+          },
+          [check = std::string("Banane")](int i) {
+            assert(check == "Banane");
+            return i + 1;
+          });
+      static_assert(std::is_same_v<decltype(ret), int*>);
+      assert(ret == std::data(result) + size);
+      assert(result == expected);
+    }
+  }
+};
+
+template <class Iter>
+struct TestWithInit {
+  template <class Policy>
+  void operator()(Policy&& policy) {
+    for (int size : {0, 1, 2, 100, 350}) {
+      std::vector<int> a(size);
+      for (int i = 0; i != size; ++i)
+        a[i] = i;
+
+      std::vector<int> expected(size);
+      std::transform_inclusive_scan(
+          a.begin(), a.end(), expected.begin(), std::plus{}, [](int x) { return x + 1; }, 100);
+
+      std::vector<int> result(size);
+      auto ret = std::transform_inclusive_scan(
+          policy,
+          Iter(std::data(a)),
+          Iter(std::data(a) + std::size(a)),
+          std::data(result),
+          [check = std::string("Banane")](int i, int j) {
+            assert(check == "Banane");
+            return i + j;
+          },
+          [check = std::string("Banane")](int i) {
+            assert(check == "Banane");
+            return i + 1;
+          },
+          100);
+      static_assert(std::is_same_v<decltype(ret), int*>);
+      assert(ret == std::data(result) + size);
+      assert(result == expected);
+    }
+  }
+};
+
+int main(int, char**) {
+  types::for_each(types::forward_iterator_list<int*>{}, TestIteratorWithPolicies<TestNoInit>{});
+  types::for_each(types::forward_iterator_list<int*>{}, TestIteratorWithPolicies<TestWithInit>{});
+  return 0;
+}



More information about the libcxx-commits mailing list