[libcxx-commits] [libcxx] [libcxx] Added segmented iterator for count_if (PR #105888)

via libcxx-commits libcxx-commits at lists.llvm.org
Mon Sep 2 01:34:43 PDT 2024


https://github.com/adeel10x updated https://github.com/llvm/llvm-project/pull/105888

>From 7e47590501af2ddef9b889b0d0a83051d9c63937 Mon Sep 17 00:00:00 2001
From: adeel10x <adeel.ahmad at 10xengineers.ai>
Date: Sat, 24 Aug 2024 02:04:23 +0500
Subject: [PATCH 1/4] [libcxx] Added segmented iterator for count_if

---
 libcxx/include/__algorithm/count_if.h | 33 +++++++++++++++++++++++----
 1 file changed, 29 insertions(+), 4 deletions(-)

diff --git a/libcxx/include/__algorithm/count_if.h b/libcxx/include/__algorithm/count_if.h
index 25782069d03275..ba1cdb16b56b41 100644
--- a/libcxx/include/__algorithm/count_if.h
+++ b/libcxx/include/__algorithm/count_if.h
@@ -10,8 +10,10 @@
 #ifndef _LIBCPP___ALGORITHM_COUNT_IF_H
 #define _LIBCPP___ALGORITHM_COUNT_IF_H
 
+#include <__algorithm/for_each.h>
 #include <__config>
 #include <__iterator/iterator_traits.h>
+#include <__iterator/segmented_iterator.h>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 #  pragma GCC system_header
@@ -19,10 +21,12 @@
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
-template <class _InputIterator, class _Predicate>
+template <class _InputIterator,
+          class _Predicate,
+          __enable_if_t<!__is_segmented_iterator<_InputIterator>::value, int> = 0>
 _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
-typename iterator_traits<_InputIterator>::difference_type
-count_if(_InputIterator __first, _InputIterator __last, _Predicate __pred) {
+    typename iterator_traits<_InputIterator>::difference_type
+    __count_if(_InputIterator __first, _InputIterator __last, _Predicate __pred) {
   typename iterator_traits<_InputIterator>::difference_type __r(0);
   for (; __first != __last; ++__first)
     if (__pred(*__first))
@@ -30,6 +34,27 @@ count_if(_InputIterator __first, _InputIterator __last, _Predicate __pred) {
   return __r;
 }
 
+template <class _SegmentedIterator,
+          class _Predicate,
+          __enable_if_t<__is_segmented_iterator<_SegmentedIterator>::value, int> = 0>
+_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
+    typename iterator_traits<_SegmentedIterator>::difference_type
+    __count_if(_SegmentedIterator __first, _SegmentedIterator __last, _Predicate __pred) {
+  typename iterator_traits<_SegmentedIterator>::difference_type __r(0);
+  std::for_each(__first, __last, [&__r, __pred](auto& __val) mutable {
+    if (__pred(__val))
+      ++__r;
+  });
+  return __r;
+}
+
+template <class _InputIterator, class _Predicate>
+_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
+    typename iterator_traits<_InputIterator>::difference_type
+    count_if(_InputIterator __first, _InputIterator __last, _Predicate __pred) {
+  return __count_if(__first, __last, __pred);
+}
+
 _LIBCPP_END_NAMESPACE_STD
 
-#endif // _LIBCPP___ALGORITHM_COUNT_IF_H
+#endif // _LIBCPP___ALGORITHM_COUNT_IF_H
\ No newline at end of file

>From f6e14b363683aac98df71df2e0b2b5ca3a3e2769 Mon Sep 17 00:00:00 2001
From: adeel10x <adeel.ahmad at 10xengineers.ai>
Date: Sat, 24 Aug 2024 02:16:10 +0500
Subject: [PATCH 2/4] Added newline at the end of the file

---
 libcxx/include/__algorithm/count_if.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/libcxx/include/__algorithm/count_if.h b/libcxx/include/__algorithm/count_if.h
index ba1cdb16b56b41..4cf0fc81481b13 100644
--- a/libcxx/include/__algorithm/count_if.h
+++ b/libcxx/include/__algorithm/count_if.h
@@ -57,4 +57,5 @@ _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
 
 _LIBCPP_END_NAMESPACE_STD
 
-#endif // _LIBCPP___ALGORITHM_COUNT_IF_H
\ No newline at end of file
+#endif // _LIBCPP___ALGORITHM_COUNT_IF_H
+

>From 2aee2511c4035846cd25a230dac5675f17964158 Mon Sep 17 00:00:00 2001
From: adeel10x <adeel.ahmad at 10xengineers.ai>
Date: Sat, 31 Aug 2024 03:47:03 +0500
Subject: [PATCH 3/4] [libcxx] Removed separate function templates for input
 and segmented iterators. Used a single function template that calls
 std::for_each.

---
 libcxx/include/__algorithm/count_if.h | 29 +++------------------------
 1 file changed, 3 insertions(+), 26 deletions(-)

diff --git a/libcxx/include/__algorithm/count_if.h b/libcxx/include/__algorithm/count_if.h
index 4cf0fc81481b13..6c2d3013ebd577 100644
--- a/libcxx/include/__algorithm/count_if.h
+++ b/libcxx/include/__algorithm/count_if.h
@@ -21,41 +21,18 @@
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
-template <class _InputIterator,
-          class _Predicate,
-          __enable_if_t<!__is_segmented_iterator<_InputIterator>::value, int> = 0>
+template <class _InputIterator, class _Predicate>
 _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
     typename iterator_traits<_InputIterator>::difference_type
-    __count_if(_InputIterator __first, _InputIterator __last, _Predicate __pred) {
+    count_if(_InputIterator __first, _InputIterator __last, _Predicate __pred) {
   typename iterator_traits<_InputIterator>::difference_type __r(0);
-  for (; __first != __last; ++__first)
-    if (__pred(*__first))
-      ++__r;
-  return __r;
-}
-
-template <class _SegmentedIterator,
-          class _Predicate,
-          __enable_if_t<__is_segmented_iterator<_SegmentedIterator>::value, int> = 0>
-_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
-    typename iterator_traits<_SegmentedIterator>::difference_type
-    __count_if(_SegmentedIterator __first, _SegmentedIterator __last, _Predicate __pred) {
-  typename iterator_traits<_SegmentedIterator>::difference_type __r(0);
-  std::for_each(__first, __last, [&__r, __pred](auto& __val) mutable {
+  std::for_each(__first, __last, [&__r, &__pred](auto& __val) mutable {
     if (__pred(__val))
       ++__r;
   });
   return __r;
 }
 
-template <class _InputIterator, class _Predicate>
-_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
-    typename iterator_traits<_InputIterator>::difference_type
-    count_if(_InputIterator __first, _InputIterator __last, _Predicate __pred) {
-  return __count_if(__first, __last, __pred);
-}
-
 _LIBCPP_END_NAMESPACE_STD
 
 #endif // _LIBCPP___ALGORITHM_COUNT_IF_H
-

>From b6268b021ade7f3b58001f92e957fca922239315 Mon Sep 17 00:00:00 2001
From: adeel10x <adeel.ahmad at 10xengineers.ai>
Date: Mon, 2 Sep 2024 13:26:36 +0500
Subject: [PATCH 4/4] [libcxx] Added benchmark for count_if algorithm's
 implemetation for segemnted iterators

---
 libcxx/test/benchmarks/CMakeLists.txt         |  1 +
 .../benchmarks/algorithms/count_if.bench.cpp  | 22 +++++++++++++++++++
 2 files changed, 23 insertions(+)
 create mode 100644 libcxx/test/benchmarks/algorithms/count_if.bench.cpp

diff --git a/libcxx/test/benchmarks/CMakeLists.txt b/libcxx/test/benchmarks/CMakeLists.txt
index 616cf0ff8d2374..5d946d9114b804 100644
--- a/libcxx/test/benchmarks/CMakeLists.txt
+++ b/libcxx/test/benchmarks/CMakeLists.txt
@@ -110,6 +110,7 @@ endfunction()
 set(BENCHMARK_TESTS
     algorithms.partition_point.bench.cpp
     algorithms/count.bench.cpp
+    algorithms/count_if.bench.cpp
     algorithms/equal.bench.cpp
     algorithms/find.bench.cpp
     algorithms/fill.bench.cpp
diff --git a/libcxx/test/benchmarks/algorithms/count_if.bench.cpp b/libcxx/test/benchmarks/algorithms/count_if.bench.cpp
new file mode 100644
index 00000000000000..785d6eec619843
--- /dev/null
+++ b/libcxx/test/benchmarks/algorithms/count_if.bench.cpp
@@ -0,0 +1,22 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include <algorithm>
+#include <benchmark/benchmark.h>
+#include <deque>
+
+static void bm_deque_count_if(benchmark::State& state) {
+  std::deque<char> deque1(state.range(), '1');
+  for (auto _ : state) {
+    benchmark::DoNotOptimize(deque1);
+    benchmark::DoNotOptimize(std::count_if(deque1.begin(), deque1.end(), [](char& v) { return v == '0'; }));
+  }
+}
+BENCHMARK(bm_deque_count_if)->DenseRange(1, 8)->Range(16, 1 << 20);
+
+BENCHMARK_MAIN();



More information about the libcxx-commits mailing list