aboutsummaryrefslogtreecommitdiff
path: root/absl/algorithm
diff options
context:
space:
mode:
Diffstat (limited to 'absl/algorithm')
-rw-r--r--absl/algorithm/BUILD.bazel26
-rw-r--r--absl/algorithm/CMakeLists.txt1
-rw-r--r--absl/algorithm/algorithm.h111
-rw-r--r--absl/algorithm/algorithm_test.cc141
-rw-r--r--absl/algorithm/container.h128
-rw-r--r--absl/algorithm/container_test.cc22
-rw-r--r--absl/algorithm/equal_benchmark.cc126
7 files changed, 98 insertions, 457 deletions
diff --git a/absl/algorithm/BUILD.bazel b/absl/algorithm/BUILD.bazel
index 3a9ab013..ddf9e11f 100644
--- a/absl/algorithm/BUILD.bazel
+++ b/absl/algorithm/BUILD.bazel
@@ -21,7 +21,14 @@ load(
"ABSL_TEST_COPTS",
)
-package(default_visibility = ["//visibility:public"])
+package(
+ default_visibility = ["//visibility:public"],
+ features = [
+ "header_modules",
+ "layering_check",
+ "parse_headers",
+ ],
+)
licenses(["notice"])
@@ -44,24 +51,11 @@ cc_test(
deps = [
":algorithm",
"//absl/base:config",
+ "@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
],
)
-cc_binary(
- name = "algorithm_benchmark",
- testonly = 1,
- srcs = ["equal_benchmark.cc"],
- copts = ABSL_TEST_COPTS,
- linkopts = ABSL_DEFAULT_LINKOPTS,
- tags = ["benchmark"],
- deps = [
- ":algorithm",
- "//absl/base:core_headers",
- "@com_github_google_benchmark//:benchmark_main",
- ],
-)
-
cc_library(
name = "container",
hdrs = [
@@ -72,6 +66,7 @@ cc_library(
deps = [
":algorithm",
"//absl/base:core_headers",
+ "//absl/base:nullability",
"//absl/meta:type_traits",
],
)
@@ -87,6 +82,7 @@ cc_test(
"//absl/base:core_headers",
"//absl/memory",
"//absl/types:span",
+ "@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
],
)
diff --git a/absl/algorithm/CMakeLists.txt b/absl/algorithm/CMakeLists.txt
index 181b49ca..5577164d 100644
--- a/absl/algorithm/CMakeLists.txt
+++ b/absl/algorithm/CMakeLists.txt
@@ -50,6 +50,7 @@ absl_cc_library(
absl::algorithm
absl::core_headers
absl::meta
+ absl::nullability
PUBLIC
)
diff --git a/absl/algorithm/algorithm.h b/absl/algorithm/algorithm.h
index e9b47338..59aeed7d 100644
--- a/absl/algorithm/algorithm.h
+++ b/absl/algorithm/algorithm.h
@@ -31,92 +31,17 @@
namespace absl {
ABSL_NAMESPACE_BEGIN
-namespace algorithm_internal {
-
-// Performs comparisons with operator==, similar to C++14's `std::equal_to<>`.
-struct EqualTo {
- template <typename T, typename U>
- bool operator()(const T& a, const U& b) const {
- return a == b;
- }
-};
-
-template <typename InputIter1, typename InputIter2, typename Pred>
-bool EqualImpl(InputIter1 first1, InputIter1 last1, InputIter2 first2,
- InputIter2 last2, Pred pred, std::input_iterator_tag,
- std::input_iterator_tag) {
- while (true) {
- if (first1 == last1) return first2 == last2;
- if (first2 == last2) return false;
- if (!pred(*first1, *first2)) return false;
- ++first1;
- ++first2;
- }
-}
-
-template <typename InputIter1, typename InputIter2, typename Pred>
-bool EqualImpl(InputIter1 first1, InputIter1 last1, InputIter2 first2,
- InputIter2 last2, Pred&& pred, std::random_access_iterator_tag,
- std::random_access_iterator_tag) {
- return (last1 - first1 == last2 - first2) &&
- std::equal(first1, last1, first2, std::forward<Pred>(pred));
-}
-
-// When we are using our own internal predicate that just applies operator==, we
-// forward to the non-predicate form of std::equal. This enables an optimization
-// in libstdc++ that can result in std::memcmp being used for integer types.
-template <typename InputIter1, typename InputIter2>
-bool EqualImpl(InputIter1 first1, InputIter1 last1, InputIter2 first2,
- InputIter2 last2, algorithm_internal::EqualTo /* unused */,
- std::random_access_iterator_tag,
- std::random_access_iterator_tag) {
- return (last1 - first1 == last2 - first2) &&
- std::equal(first1, last1, first2);
-}
-
-template <typename It>
-It RotateImpl(It first, It middle, It last, std::true_type) {
- return std::rotate(first, middle, last);
-}
-
-template <typename It>
-It RotateImpl(It first, It middle, It last, std::false_type) {
- std::rotate(first, middle, last);
- return std::next(first, std::distance(middle, last));
-}
-
-} // namespace algorithm_internal
-
// equal()
+// rotate()
//
-// Compares the equality of two ranges specified by pairs of iterators, using
-// the given predicate, returning true iff for each corresponding iterator i1
-// and i2 in the first and second range respectively, pred(*i1, *i2) == true
-//
-// This comparison takes at most min(`last1` - `first1`, `last2` - `first2`)
-// invocations of the predicate. Additionally, if InputIter1 and InputIter2 are
-// both random-access iterators, and `last1` - `first1` != `last2` - `first2`,
-// then the predicate is never invoked and the function returns false.
+// Historical note: Abseil once provided implementations of these algorithms
+// prior to their adoption in C++14. New code should prefer to use the std
+// variants.
//
-// This is a C++11-compatible implementation of C++14 `std::equal`. See
-// https://en.cppreference.com/w/cpp/algorithm/equal for more information.
-template <typename InputIter1, typename InputIter2, typename Pred>
-bool equal(InputIter1 first1, InputIter1 last1, InputIter2 first2,
- InputIter2 last2, Pred&& pred) {
- return algorithm_internal::EqualImpl(
- first1, last1, first2, last2, std::forward<Pred>(pred),
- typename std::iterator_traits<InputIter1>::iterator_category{},
- typename std::iterator_traits<InputIter2>::iterator_category{});
-}
-
-// Overload of equal() that performs comparison of two ranges specified by pairs
-// of iterators using operator==.
-template <typename InputIter1, typename InputIter2>
-bool equal(InputIter1 first1, InputIter1 last1, InputIter2 first2,
- InputIter2 last2) {
- return absl::equal(first1, last1, first2, last2,
- algorithm_internal::EqualTo{});
-}
+// See the documentation for the STL <algorithm> header for more information:
+// https://en.cppreference.com/w/cpp/header/algorithm
+using std::equal;
+using std::rotate;
// linear_search()
//
@@ -133,26 +58,6 @@ bool linear_search(InputIterator first, InputIterator last,
return std::find(first, last, value) != last;
}
-// rotate()
-//
-// Performs a left rotation on a range of elements (`first`, `last`) such that
-// `middle` is now the first element. `rotate()` returns an iterator pointing to
-// the first element before rotation. This function is exactly the same as
-// `std::rotate`, but fixes a bug in gcc
-// <= 4.9 where `std::rotate` returns `void` instead of an iterator.
-//
-// The complexity of this algorithm is the same as that of `std::rotate`, but if
-// `ForwardIterator` is not a random-access iterator, then `absl::rotate`
-// performs an additional pass over the range to construct the return value.
-template <typename ForwardIterator>
-ForwardIterator rotate(ForwardIterator first, ForwardIterator middle,
- ForwardIterator last) {
- return algorithm_internal::RotateImpl(
- first, middle, last,
- std::is_same<decltype(std::rotate(first, middle, last)),
- ForwardIterator>());
-}
-
ABSL_NAMESPACE_END
} // namespace absl
diff --git a/absl/algorithm/algorithm_test.cc b/absl/algorithm/algorithm_test.cc
index d18df024..e6ee4695 100644
--- a/absl/algorithm/algorithm_test.cc
+++ b/absl/algorithm/algorithm_test.cc
@@ -24,137 +24,6 @@
namespace {
-TEST(EqualTest, DefaultComparisonRandomAccess) {
- std::vector<int> v1{1, 2, 3};
- std::vector<int> v2 = v1;
- std::vector<int> v3 = {1, 2};
- std::vector<int> v4 = {1, 2, 4};
-
- EXPECT_TRUE(absl::equal(v1.begin(), v1.end(), v2.begin(), v2.end()));
- EXPECT_FALSE(absl::equal(v1.begin(), v1.end(), v3.begin(), v3.end()));
- EXPECT_FALSE(absl::equal(v1.begin(), v1.end(), v4.begin(), v4.end()));
-}
-
-TEST(EqualTest, DefaultComparison) {
- std::list<int> lst1{1, 2, 3};
- std::list<int> lst2 = lst1;
- std::list<int> lst3{1, 2};
- std::list<int> lst4{1, 2, 4};
-
- EXPECT_TRUE(absl::equal(lst1.begin(), lst1.end(), lst2.begin(), lst2.end()));
- EXPECT_FALSE(absl::equal(lst1.begin(), lst1.end(), lst3.begin(), lst3.end()));
- EXPECT_FALSE(absl::equal(lst1.begin(), lst1.end(), lst4.begin(), lst4.end()));
-}
-
-TEST(EqualTest, EmptyRange) {
- std::vector<int> v1{1, 2, 3};
- std::vector<int> empty1;
- std::vector<int> empty2;
-
- // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105705
-#if ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(12, 0)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wnonnull"
-#endif
- EXPECT_FALSE(absl::equal(v1.begin(), v1.end(), empty1.begin(), empty1.end()));
-#if ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(12, 0)
-#pragma GCC diagnostic pop
-#endif
- EXPECT_FALSE(absl::equal(empty1.begin(), empty1.end(), v1.begin(), v1.end()));
- EXPECT_TRUE(
- absl::equal(empty1.begin(), empty1.end(), empty2.begin(), empty2.end()));
-}
-
-TEST(EqualTest, MixedIterTypes) {
- std::vector<int> v1{1, 2, 3};
- std::list<int> lst1{v1.begin(), v1.end()};
- std::list<int> lst2{1, 2, 4};
- std::list<int> lst3{1, 2};
-
- EXPECT_TRUE(absl::equal(v1.begin(), v1.end(), lst1.begin(), lst1.end()));
- EXPECT_FALSE(absl::equal(v1.begin(), v1.end(), lst2.begin(), lst2.end()));
- EXPECT_FALSE(absl::equal(v1.begin(), v1.end(), lst3.begin(), lst3.end()));
-}
-
-TEST(EqualTest, MixedValueTypes) {
- std::vector<int> v1{1, 2, 3};
- std::vector<char> v2{1, 2, 3};
- std::vector<char> v3{1, 2};
- std::vector<char> v4{1, 2, 4};
-
- EXPECT_TRUE(absl::equal(v1.begin(), v1.end(), v2.begin(), v2.end()));
- EXPECT_FALSE(absl::equal(v1.begin(), v1.end(), v3.begin(), v3.end()));
- EXPECT_FALSE(absl::equal(v1.begin(), v1.end(), v4.begin(), v4.end()));
-}
-
-TEST(EqualTest, WeirdIterators) {
- std::vector<bool> v1{true, false};
- std::vector<bool> v2 = v1;
- std::vector<bool> v3{true};
- std::vector<bool> v4{true, true, true};
-
- EXPECT_TRUE(absl::equal(v1.begin(), v1.end(), v2.begin(), v2.end()));
- EXPECT_FALSE(absl::equal(v1.begin(), v1.end(), v3.begin(), v3.end()));
- EXPECT_FALSE(absl::equal(v1.begin(), v1.end(), v4.begin(), v4.end()));
-}
-
-TEST(EqualTest, CustomComparison) {
- int n[] = {1, 2, 3, 4};
- std::vector<int*> v1{&n[0], &n[1], &n[2]};
- std::vector<int*> v2 = v1;
- std::vector<int*> v3{&n[0], &n[1], &n[3]};
- std::vector<int*> v4{&n[0], &n[1]};
-
- auto eq = [](int* a, int* b) { return *a == *b; };
-
- EXPECT_TRUE(absl::equal(v1.begin(), v1.end(), v2.begin(), v2.end(), eq));
- EXPECT_FALSE(absl::equal(v1.begin(), v1.end(), v3.begin(), v3.end(), eq));
- EXPECT_FALSE(absl::equal(v1.begin(), v1.end(), v4.begin(), v4.end(), eq));
-}
-
-TEST(EqualTest, MoveOnlyPredicate) {
- std::vector<int> v1{1, 2, 3};
- std::vector<int> v2{4, 5, 6};
-
- // move-only equality predicate
- struct Eq {
- Eq() = default;
- Eq(Eq &&) = default;
- Eq(const Eq &) = delete;
- Eq &operator=(const Eq &) = delete;
- bool operator()(const int a, const int b) const { return a == b; }
- };
-
- EXPECT_TRUE(absl::equal(v1.begin(), v1.end(), v1.begin(), v1.end(), Eq()));
- EXPECT_FALSE(absl::equal(v1.begin(), v1.end(), v2.begin(), v2.end(), Eq()));
-}
-
-struct CountingTrivialPred {
- int* count;
- bool operator()(int, int) const {
- ++*count;
- return true;
- }
-};
-
-TEST(EqualTest, RandomAccessComplexity) {
- std::vector<int> v1{1, 1, 3};
- std::vector<int> v2 = v1;
- std::vector<int> v3{1, 2};
-
- do {
- int count = 0;
- absl::equal(v1.begin(), v1.end(), v2.begin(), v2.end(),
- CountingTrivialPred{&count});
- EXPECT_LE(count, 3);
- } while (std::next_permutation(v2.begin(), v2.end()));
-
- int count = 0;
- absl::equal(v1.begin(), v1.end(), v3.begin(), v3.end(),
- CountingTrivialPred{&count});
- EXPECT_EQ(count, 0);
-}
-
class LinearSearchTest : public testing::Test {
protected:
LinearSearchTest() : container_{1, 2, 3} {}
@@ -178,14 +47,4 @@ TEST_F(LinearSearchTest, linear_searchConst) {
absl::linear_search(const_container->begin(), const_container->end(), 4));
}
-TEST(RotateTest, Rotate) {
- std::vector<int> v{0, 1, 2, 3, 4};
- EXPECT_EQ(*absl::rotate(v.begin(), v.begin() + 2, v.end()), 0);
- EXPECT_THAT(v, testing::ElementsAreArray({2, 3, 4, 0, 1}));
-
- std::list<int> l{0, 1, 2, 3, 4};
- EXPECT_EQ(*absl::rotate(l.begin(), std::next(l.begin(), 3), l.end()), 0);
- EXPECT_THAT(l, testing::ElementsAreArray({3, 4, 0, 1, 2}));
-}
-
} // namespace
diff --git a/absl/algorithm/container.h b/absl/algorithm/container.h
index 679e0267..c7bafae1 100644
--- a/absl/algorithm/container.h
+++ b/absl/algorithm/container.h
@@ -52,6 +52,7 @@
#include "absl/algorithm/algorithm.h"
#include "absl/base/macros.h"
+#include "absl/base/nullability.h"
#include "absl/meta/type_traits.h"
namespace absl {
@@ -116,18 +117,6 @@ template <class Key, class Hash, class KeyEqual, class Allocator>
struct IsUnorderedContainer<std::unordered_set<Key, Hash, KeyEqual, Allocator>>
: std::true_type {};
-// container_algorithm_internal::c_size. It is meant for internal use only.
-
-template <class C>
-auto c_size(C& c) -> decltype(c.size()) {
- return c.size();
-}
-
-template <class T, std::size_t N>
-constexpr std::size_t c_size(T (&)[N]) {
- return N;
-}
-
} // namespace container_algorithm_internal
// PUBLIC API
@@ -348,20 +337,10 @@ container_algorithm_internal::ContainerDifferenceType<const C> c_count_if(
template <typename C1, typename C2>
container_algorithm_internal::ContainerIterPairType<C1, C2> c_mismatch(C1& c1,
C2& c2) {
- auto first1 = container_algorithm_internal::c_begin(c1);
- auto last1 = container_algorithm_internal::c_end(c1);
- auto first2 = container_algorithm_internal::c_begin(c2);
- auto last2 = container_algorithm_internal::c_end(c2);
-
- for (; first1 != last1 && first2 != last2; ++first1, (void)++first2) {
- // Negates equality because Cpp17EqualityComparable doesn't require clients
- // to overload both `operator==` and `operator!=`.
- if (!(*first1 == *first2)) {
- break;
- }
- }
-
- return std::make_pair(first1, first2);
+ return std::mismatch(container_algorithm_internal::c_begin(c1),
+ container_algorithm_internal::c_end(c1),
+ container_algorithm_internal::c_begin(c2),
+ container_algorithm_internal::c_end(c2));
}
// Overload of c_mismatch() for using a predicate evaluation other than `==` as
@@ -370,56 +349,33 @@ container_algorithm_internal::ContainerIterPairType<C1, C2> c_mismatch(C1& c1,
template <typename C1, typename C2, typename BinaryPredicate>
container_algorithm_internal::ContainerIterPairType<C1, C2> c_mismatch(
C1& c1, C2& c2, BinaryPredicate pred) {
- auto first1 = container_algorithm_internal::c_begin(c1);
- auto last1 = container_algorithm_internal::c_end(c1);
- auto first2 = container_algorithm_internal::c_begin(c2);
- auto last2 = container_algorithm_internal::c_end(c2);
-
- for (; first1 != last1 && first2 != last2; ++first1, (void)++first2) {
- if (!pred(*first1, *first2)) {
- break;
- }
- }
-
- return std::make_pair(first1, first2);
+ return std::mismatch(container_algorithm_internal::c_begin(c1),
+ container_algorithm_internal::c_end(c1),
+ container_algorithm_internal::c_begin(c2),
+ container_algorithm_internal::c_end(c2), pred);
}
// c_equal()
//
// Container-based version of the <algorithm> `std::equal()` function to
// test whether two containers are equal.
-//
-// NOTE: the semantics of c_equal() are slightly different than those of
-// equal(): while the latter iterates over the second container only up to the
-// size of the first container, c_equal() also checks whether the container
-// sizes are equal. This better matches expectations about c_equal() based on
-// its signature.
-//
-// Example:
-// vector v1 = <1, 2, 3>;
-// vector v2 = <1, 2, 3, 4>;
-// equal(std::begin(v1), std::end(v1), std::begin(v2)) returns true
-// c_equal(v1, v2) returns false
-
template <typename C1, typename C2>
bool c_equal(const C1& c1, const C2& c2) {
- return ((container_algorithm_internal::c_size(c1) ==
- container_algorithm_internal::c_size(c2)) &&
- std::equal(container_algorithm_internal::c_begin(c1),
- container_algorithm_internal::c_end(c1),
- container_algorithm_internal::c_begin(c2)));
+ return std::equal(container_algorithm_internal::c_begin(c1),
+ container_algorithm_internal::c_end(c1),
+ container_algorithm_internal::c_begin(c2),
+ container_algorithm_internal::c_end(c2));
}
// Overload of c_equal() for using a predicate evaluation other than `==` as
// the function's test condition.
template <typename C1, typename C2, typename BinaryPredicate>
bool c_equal(const C1& c1, const C2& c2, BinaryPredicate&& pred) {
- return ((container_algorithm_internal::c_size(c1) ==
- container_algorithm_internal::c_size(c2)) &&
- std::equal(container_algorithm_internal::c_begin(c1),
- container_algorithm_internal::c_end(c1),
- container_algorithm_internal::c_begin(c2),
- std::forward<BinaryPredicate>(pred)));
+ return std::equal(container_algorithm_internal::c_begin(c1),
+ container_algorithm_internal::c_end(c1),
+ container_algorithm_internal::c_begin(c2),
+ container_algorithm_internal::c_end(c2),
+ std::forward<BinaryPredicate>(pred));
}
// c_is_permutation()
@@ -428,20 +384,20 @@ bool c_equal(const C1& c1, const C2& c2, BinaryPredicate&& pred) {
// to test whether a container is a permutation of another.
template <typename C1, typename C2>
bool c_is_permutation(const C1& c1, const C2& c2) {
- using std::begin;
- using std::end;
- return c1.size() == c2.size() &&
- std::is_permutation(begin(c1), end(c1), begin(c2));
+ return std::is_permutation(container_algorithm_internal::c_begin(c1),
+ container_algorithm_internal::c_end(c1),
+ container_algorithm_internal::c_begin(c2),
+ container_algorithm_internal::c_end(c2));
}
// Overload of c_is_permutation() for using a predicate evaluation other than
// `==` as the function's test condition.
template <typename C1, typename C2, typename BinaryPredicate>
bool c_is_permutation(const C1& c1, const C2& c2, BinaryPredicate&& pred) {
- using std::begin;
- using std::end;
- return c1.size() == c2.size() &&
- std::is_permutation(begin(c1), end(c1), begin(c2),
+ return std::is_permutation(container_algorithm_internal::c_begin(c1),
+ container_algorithm_internal::c_end(c1),
+ container_algorithm_internal::c_begin(c2),
+ container_algorithm_internal::c_end(c2),
std::forward<BinaryPredicate>(pred));
}
@@ -818,6 +774,36 @@ void c_shuffle(RandomAccessContainer& c, UniformRandomBitGenerator&& gen) {
std::forward<UniformRandomBitGenerator>(gen));
}
+// c_sample()
+//
+// Container-based version of the <algorithm> `std::sample()` function to
+// randomly sample elements from the container without replacement using a
+// `gen()` uniform random number generator and write them to an iterator range.
+template <typename C, typename OutputIterator, typename Distance,
+ typename UniformRandomBitGenerator>
+OutputIterator c_sample(const C& c, OutputIterator result, Distance n,
+ UniformRandomBitGenerator&& gen) {
+#if defined(__cpp_lib_sample) && __cpp_lib_sample >= 201603L
+ return std::sample(container_algorithm_internal::c_begin(c),
+ container_algorithm_internal::c_end(c), result, n,
+ std::forward<UniformRandomBitGenerator>(gen));
+#else
+ // Fall back to a stable selection-sampling implementation.
+ auto first = container_algorithm_internal::c_begin(c);
+ Distance unsampled_elements = c_distance(c);
+ n = (std::min)(n, unsampled_elements);
+ for (; n != 0; ++first) {
+ Distance r =
+ std::uniform_int_distribution<Distance>(0, --unsampled_elements)(gen);
+ if (r < n) {
+ *result++ = *first;
+ --n;
+ }
+ }
+ return result;
+#endif
+}
+
//------------------------------------------------------------------------------
// <algorithm> Partition functions
//------------------------------------------------------------------------------
@@ -1657,7 +1643,7 @@ bool c_prev_permutation(C& c, LessThan&& comp) {
//
// Container-based version of the <numeric> `std::iota()` function
// to compute successive values of `value`, as if incremented with `++value`
-// after each element is written. and write them to the container.
+// after each element is written, and write them to the container.
template <typename Sequence, typename T>
void c_iota(Sequence& sequence, const T& value) {
std::iota(container_algorithm_internal::c_begin(sequence),
diff --git a/absl/algorithm/container_test.cc b/absl/algorithm/container_test.cc
index 0fbc7773..c01f5fc0 100644
--- a/absl/algorithm/container_test.cc
+++ b/absl/algorithm/container_test.cc
@@ -14,6 +14,7 @@
#include "absl/algorithm/container.h"
+#include <algorithm>
#include <functional>
#include <initializer_list>
#include <iterator>
@@ -40,8 +41,10 @@ using ::testing::Each;
using ::testing::ElementsAre;
using ::testing::Gt;
using ::testing::IsNull;
+using ::testing::IsSubsetOf;
using ::testing::Lt;
using ::testing::Pointee;
+using ::testing::SizeIs;
using ::testing::Truly;
using ::testing::UnorderedElementsAre;
@@ -963,12 +966,29 @@ TEST(MutatingTest, RotateCopy) {
EXPECT_THAT(actual, ElementsAre(3, 4, 1, 2, 5));
}
+template <typename T>
+T RandomlySeededPrng() {
+ std::random_device rdev;
+ std::seed_seq::result_type data[T::state_size];
+ std::generate_n(data, T::state_size, std::ref(rdev));
+ std::seed_seq prng_seed(data, data + T::state_size);
+ return T(prng_seed);
+}
+
TEST(MutatingTest, Shuffle) {
std::vector<int> actual = {1, 2, 3, 4, 5};
- absl::c_shuffle(actual, std::random_device());
+ absl::c_shuffle(actual, RandomlySeededPrng<std::mt19937_64>());
EXPECT_THAT(actual, UnorderedElementsAre(1, 2, 3, 4, 5));
}
+TEST(MutatingTest, Sample) {
+ std::vector<int> actual;
+ absl::c_sample(std::vector<int>{1, 2, 3, 4, 5}, std::back_inserter(actual), 3,
+ RandomlySeededPrng<std::mt19937_64>());
+ EXPECT_THAT(actual, IsSubsetOf({1, 2, 3, 4, 5}));
+ EXPECT_THAT(actual, SizeIs(3));
+}
+
TEST(MutatingTest, PartialSort) {
std::vector<int> sequence{5, 3, 42, 0};
absl::c_partial_sort(sequence, sequence.begin() + 2);
diff --git a/absl/algorithm/equal_benchmark.cc b/absl/algorithm/equal_benchmark.cc
deleted file mode 100644
index 948cd65c..00000000
--- a/absl/algorithm/equal_benchmark.cc
+++ /dev/null
@@ -1,126 +0,0 @@
-// Copyright 2017 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include <cstdint>
-#include <cstring>
-
-#include "absl/algorithm/algorithm.h"
-#include "benchmark/benchmark.h"
-
-namespace {
-
-// The range of sequence sizes to benchmark.
-constexpr int kMinBenchmarkSize = 1024;
-constexpr int kMaxBenchmarkSize = 8 * 1024 * 1024;
-
-// A user-defined type for use in equality benchmarks. Note that we expect
-// std::memcmp to win for this type: libstdc++'s std::equal only defers to
-// memcmp for integral types. This is because it is not straightforward to
-// guarantee that std::memcmp would produce a result "as-if" compared by
-// operator== for other types (example gotchas: NaN floats, structs with
-// padding).
-struct EightBits {
- explicit EightBits(int /* unused */) : data(0) {}
- bool operator==(const EightBits& rhs) const { return data == rhs.data; }
- uint8_t data;
-};
-
-template <typename T>
-void BM_absl_equal_benchmark(benchmark::State& state) {
- std::vector<T> xs(state.range(0), T(0));
- std::vector<T> ys = xs;
- while (state.KeepRunning()) {
- const bool same = absl::equal(xs.begin(), xs.end(), ys.begin(), ys.end());
- benchmark::DoNotOptimize(same);
- }
-}
-
-template <typename T>
-void BM_std_equal_benchmark(benchmark::State& state) {
- std::vector<T> xs(state.range(0), T(0));
- std::vector<T> ys = xs;
- while (state.KeepRunning()) {
- const bool same = std::equal(xs.begin(), xs.end(), ys.begin());
- benchmark::DoNotOptimize(same);
- }
-}
-
-template <typename T>
-void BM_memcmp_benchmark(benchmark::State& state) {
- std::vector<T> xs(state.range(0), T(0));
- std::vector<T> ys = xs;
- while (state.KeepRunning()) {
- const bool same =
- std::memcmp(xs.data(), ys.data(), xs.size() * sizeof(T)) == 0;
- benchmark::DoNotOptimize(same);
- }
-}
-
-// The expectation is that the compiler should be able to elide the equality
-// comparison altogether for sufficiently simple types.
-template <typename T>
-void BM_absl_equal_self_benchmark(benchmark::State& state) {
- std::vector<T> xs(state.range(0), T(0));
- while (state.KeepRunning()) {
- const bool same = absl::equal(xs.begin(), xs.end(), xs.begin(), xs.end());
- benchmark::DoNotOptimize(same);
- }
-}
-
-BENCHMARK_TEMPLATE(BM_absl_equal_benchmark, uint8_t)
- ->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
-BENCHMARK_TEMPLATE(BM_std_equal_benchmark, uint8_t)
- ->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
-BENCHMARK_TEMPLATE(BM_memcmp_benchmark, uint8_t)
- ->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
-BENCHMARK_TEMPLATE(BM_absl_equal_self_benchmark, uint8_t)
- ->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
-
-BENCHMARK_TEMPLATE(BM_absl_equal_benchmark, uint16_t)
- ->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
-BENCHMARK_TEMPLATE(BM_std_equal_benchmark, uint16_t)
- ->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
-BENCHMARK_TEMPLATE(BM_memcmp_benchmark, uint16_t)
- ->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
-BENCHMARK_TEMPLATE(BM_absl_equal_self_benchmark, uint16_t)
- ->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
-
-BENCHMARK_TEMPLATE(BM_absl_equal_benchmark, uint32_t)
- ->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
-BENCHMARK_TEMPLATE(BM_std_equal_benchmark, uint32_t)
- ->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
-BENCHMARK_TEMPLATE(BM_memcmp_benchmark, uint32_t)
- ->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
-BENCHMARK_TEMPLATE(BM_absl_equal_self_benchmark, uint32_t)
- ->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
-
-BENCHMARK_TEMPLATE(BM_absl_equal_benchmark, uint64_t)
- ->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
-BENCHMARK_TEMPLATE(BM_std_equal_benchmark, uint64_t)
- ->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
-BENCHMARK_TEMPLATE(BM_memcmp_benchmark, uint64_t)
- ->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
-BENCHMARK_TEMPLATE(BM_absl_equal_self_benchmark, uint64_t)
- ->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
-
-BENCHMARK_TEMPLATE(BM_absl_equal_benchmark, EightBits)
- ->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
-BENCHMARK_TEMPLATE(BM_std_equal_benchmark, EightBits)
- ->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
-BENCHMARK_TEMPLATE(BM_memcmp_benchmark, EightBits)
- ->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
-BENCHMARK_TEMPLATE(BM_absl_equal_self_benchmark, EightBits)
- ->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
-
-} // namespace