Skip to content

Commit

Permalink
Bring more uniformity in indirect algorithms
Browse files Browse the repository at this point in the history
Algorithms that needed to perform indirect operations (operations on a
collection of iterators instead of on a collection of values) mostly
used indirect_compare so far, which embedded both the comparison and the
projection. This commit introduces indirect() to only adapt the
projection, making it it simpler and more powerful. This new function
object also allows to replace the lambdas used for that exact purpose in
indirect_adapter, bringing more uniformity into the library.
  • Loading branch information
Morwenn committed Mar 13, 2021
1 parent a3a8408 commit 2ab06c1
Show file tree
Hide file tree
Showing 8 changed files with 74 additions and 89 deletions.
15 changes: 5 additions & 10 deletions include/cpp-sort/adapters/indirect_adapter.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@
#include <cpp-sort/sorter_facade.h>
#include <cpp-sort/sorter_traits.h>
#include <cpp-sort/utility/adapter_storage.h>
#include <cpp-sort/utility/as_function.h>
#include <cpp-sort/utility/functional.h>
#include <cpp-sort/utility/iter_move.h>
#include <cpp-sort/utility/size.h>
#include "../detail/checkers.h"
#include "../detail/functional.h"
#include "../detail/indiesort.h"
#include "../detail/iterator_traits.h"
#include "../detail/memory.h"
Expand Down Expand Up @@ -55,7 +55,6 @@ namespace cppsort
-> decltype(auto)
{
using utility::iter_move;
auto&& proj = utility::as_function(projection);

////////////////////////////////////////////////////////////
// Indirectly sort the iterators
Expand All @@ -75,10 +74,8 @@ namespace cppsort
#ifndef __cpp_lib_uncaught_exceptions
// Sort the iterators on pointed values
std::forward<Sorter>(sorter)(
iterators.get(), iterators.get() + size, std::move(compare),
[&proj](RandomAccessIterator it) -> decltype(auto) {
return proj(*it);
}
iterators.get(), iterators.get() + size,
std::move(compare), indirect(projection)
);
#else
// Work around the sorters that return void
Expand Down Expand Up @@ -126,10 +123,8 @@ namespace cppsort
}

return std::forward<Sorter>(sorter)(
iterators.get(), iterators.get() + size, std::move(compare),
[&proj](RandomAccessIterator it) -> decltype(auto) {
return proj(*it);
}
iterators.get(), iterators.get() + size,
std::move(compare), indirect(projection)
);
#endif
}
Expand Down
26 changes: 14 additions & 12 deletions include/cpp-sort/detail/count_inversions.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2020 Morwenn
* Copyright (c) 2016-2021 Morwenn
* SPDX-License-Identifier: MIT
*/
#ifndef CPPSORT_DETAIL_COUNT_INVERSIONS_H_
Expand All @@ -22,32 +22,33 @@ namespace detail
typename ResultType,
typename RandomAccessIterator1,
typename RandomAccessIterator2,
typename Compare
typename Compare,
typename Projection
>
auto count_inversions_merge(RandomAccessIterator1 first, RandomAccessIterator1 middle,
RandomAccessIterator1 last, RandomAccessIterator2 cache,
Compare compare)
Compare compare, Projection projection)
-> ResultType
{
using utility::iter_move;
auto&& comp = utility::as_function(compare);
auto&& proj = utility::as_function(projection);

ResultType inversions = 0;

// Shrink the problem size on the left side
while (comp(*first, *middle)) {
while (comp(proj(*first), proj(*middle))) {
++first;
}

auto first2 = middle;
auto result = cache;
for (auto first1 = first ; first1 != middle ; ++result)
{
for (auto first1 = first ; first1 != middle ; ++result) {
if (first2 == last) {
detail::move(first1, middle, result);
break;
}
if (comp(*first2, *first1)) {
if (comp(proj(*first2), proj(*first1))) {
*result = iter_move(first2);
++first2;
inversions += middle - first1;
Expand All @@ -69,10 +70,11 @@ namespace detail
typename ResultType,
typename RandomAccessIterator1,
typename RandomAccessIterator2,
typename Compare
typename Compare,
typename Projection
>
auto count_inversions(RandomAccessIterator1 first, RandomAccessIterator1 last,
RandomAccessIterator2 cache, Compare compare)
RandomAccessIterator2 cache, Compare compare, Projection projection)
-> ResultType
{
auto size = last - first;
Expand All @@ -83,11 +85,11 @@ namespace detail
ResultType inversions = 0;
auto middle = first + size / 2;

inversions += count_inversions<ResultType>(first, middle, cache, compare);
inversions += count_inversions<ResultType>(middle, last, cache, compare);
inversions += count_inversions<ResultType>(first, middle, cache, compare, projection);
inversions += count_inversions<ResultType>(middle, last, cache, compare, projection);
inversions += count_inversions_merge<ResultType>(std::move(first), std::move(middle),
std::move(last), std::move(cache),
std::move(compare));
std::move(compare), std::move(projection));
return inversions;
}
}}
Expand Down
42 changes: 42 additions & 0 deletions include/cpp-sort/detail/functional.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,48 @@ namespace detail
{
return invert_t<std::decay_t<Predicate>>(std::forward<Predicate>(pred));
}

////////////////////////////////////////////////////////////
// indirect

template<typename Projection>
class indirect_t
{
private:

Projection projection;

public:

indirect_t() = delete;

explicit indirect_t(Projection projection):
projection(std::move(projection))
{}

template<typename T>
auto operator()(T&& indirect_value)
-> decltype(utility::as_function(projection)(*indirect_value))
{
auto&& proj = utility::as_function(projection);
return proj(*indirect_value);
}

template<typename T>
auto operator()(T&& indirect_value) const
-> decltype(utility::as_function(projection)(*indirect_value))
{
auto&& proj = utility::as_function(projection);
return proj(*indirect_value);
}
};

template<typename Projection>
auto indirect(Projection&& proj)
-> indirect_t<std::decay_t<Projection>>
{
return indirect_t<std::decay_t<Projection>>(std::forward<Projection>(proj));
}
}}

#endif // CPPSORT_DETAIL_FUNCTIONAL_H_
51 changes: 0 additions & 51 deletions include/cpp-sort/detail/indirect_compare.h

This file was deleted.

9 changes: 4 additions & 5 deletions include/cpp-sort/probes/exc.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
#include <cpp-sort/utility/functional.h>
#include <cpp-sort/utility/size.h>
#include <cpp-sort/utility/static_const.h>
#include "../detail/indirect_compare.h"
#include "../detail/functional.h"
#include "../detail/iterator_traits.h"
#include "../detail/pdqsort.h"

Expand Down Expand Up @@ -54,10 +54,9 @@ namespace probe
}

// Sort the iterators on pointed values
pdqsort(
iterators.begin(), iterators.end(),
cppsort::detail::make_indirect_compare(compare, projection),
utility::identity{}
cppsort::detail::pdqsort(
iterators.begin(), iterators.end(), compare,
cppsort::detail::indirect(projection)
);

////////////////////////////////////////////////////////////
Expand Down
7 changes: 3 additions & 4 deletions include/cpp-sort/probes/ham.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
#include <cpp-sort/utility/functional.h>
#include <cpp-sort/utility/size.h>
#include <cpp-sort/utility/static_const.h>
#include "../detail/indirect_compare.h"
#include "../detail/functional.h"
#include "../detail/iterator_traits.h"
#include "../detail/pdqsort.h"

Expand Down Expand Up @@ -55,9 +55,8 @@ namespace probe

// Sort the iterators on pointed values
cppsort::detail::pdqsort(
iterators.begin(), iterators.end(),
cppsort::detail::make_indirect_compare(compare, projection),
utility::identity{}
iterators.begin(), iterators.end(), compare,
cppsort::detail::indirect(projection)
);

////////////////////////////////////////////////////////////
Expand Down
6 changes: 3 additions & 3 deletions include/cpp-sort/probes/inv.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
#include <cpp-sort/utility/size.h>
#include <cpp-sort/utility/static_const.h>
#include "../detail/count_inversions.h"
#include "../detail/indirect_compare.h"
#include "../detail/functional.h"
#include "../detail/iterator_traits.h"

namespace cppsort
Expand Down Expand Up @@ -50,8 +50,8 @@ namespace probe

return cppsort::detail::count_inversions<difference_type>(
iterators.get(), iterators.get() + size, buffer.get(),
cppsort::detail::indirect_compare<Compare, Projection>(std::move(compare),
std::move(projection))
std::move(compare),
cppsort::detail::indirect(std::move(projection))
);
}

Expand Down
7 changes: 3 additions & 4 deletions include/cpp-sort/probes/max.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
#include <cpp-sort/utility/size.h>
#include <cpp-sort/utility/static_const.h>
#include "../detail/equal_range.h"
#include "../detail/indirect_compare.h"
#include "../detail/functional.h"
#include "../detail/iterator_traits.h"
#include "../detail/pdqsort.h"

Expand Down Expand Up @@ -56,9 +56,8 @@ namespace probe

// Sort the iterators on pointed values
cppsort::detail::pdqsort(
iterators.begin(), iterators.end(),
cppsort::detail::make_indirect_compare(compare, projection),
utility::identity{}
iterators.begin(), iterators.end(), compare,
cppsort::detail::indirect(projection)
);

////////////////////////////////////////////////////////////
Expand Down

0 comments on commit 2ab06c1

Please sign in to comment.