-
Notifications
You must be signed in to change notification settings - Fork 29
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #113 from tcbrindle/pr/find_min_max
Add find_min/max/minmax algorithms
- Loading branch information
Showing
12 changed files
with
478 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
|
||
#include <flux.hpp> | ||
|
||
#include <cassert> | ||
#include <string> | ||
#include <vector> | ||
|
||
int main() | ||
{ | ||
struct Person { | ||
std::string name; | ||
int age; | ||
}; | ||
|
||
std::vector<Person> people{ | ||
{"Alice", 44}, | ||
{"Bob", 63}, | ||
{"Chris", 29}, | ||
{"Dani", 29}, | ||
{"Eddy", 63} | ||
}; | ||
|
||
// Get a cursor to the maximum of the people vector, according to age | ||
auto max_cur = flux::find_max(people, flux::proj(std::less{}, &Person::age)); | ||
|
||
// The oldest person is 63 | ||
assert(flux::read_at(people, max_cur).age == 63); | ||
|
||
// Note that (unlike std::max_element) find_max() return a cursor to the | ||
// *last* of several equally-maximum elements | ||
assert(flux::read_at(people, max_cur).name == "Eddy"); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
|
||
#include <flux.hpp> | ||
|
||
#include <cassert> | ||
#include <string> | ||
#include <vector> | ||
|
||
int main() | ||
{ | ||
struct Person { | ||
std::string name; | ||
int age; | ||
}; | ||
|
||
std::vector<Person> people{ | ||
{"Alice", 44}, | ||
{"Bob", 63}, | ||
{"Chris", 29}, | ||
{"Dani", 29}, | ||
{"Eddy", 63} | ||
}; | ||
|
||
// Get a cursor to the maximum of the people vector, according to age | ||
auto min_cur = flux::find_min(people, flux::proj(std::less{}, &Person::age)); | ||
|
||
// The youngest person is 29 | ||
assert(flux::read_at(people, min_cur).age == 29); | ||
|
||
// Note that find_min() return a cursor to the first of several | ||
// equally-minimum elements | ||
assert(flux::read_at(people, min_cur).name == "Chris"); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
|
||
#include <flux.hpp> | ||
|
||
#include <cassert> | ||
#include <string> | ||
#include <vector> | ||
|
||
int main() | ||
{ | ||
struct Person { | ||
std::string name; | ||
int age; | ||
}; | ||
|
||
std::vector<Person> people{ | ||
{"Alice", 44}, | ||
{"Bob", 63}, | ||
{"Chris", 29}, | ||
{"Dani", 29}, | ||
{"Eddy", 63} | ||
}; | ||
|
||
// find_minmax() returns a pair of cursors which we can destructure | ||
// Here we'll get the min and max of the people vector, according to age | ||
auto [min, max] = flux::find_minmax(people, flux::proj(std::less{}, &Person::age)); | ||
|
||
// The "minimum" is Chris. Dani is the same age, but Chris appears earlier | ||
// in the sequence | ||
assert(flux::read_at(people, min).name == "Chris"); | ||
|
||
// The "maximum" is Eddy. Bob is the same age, but Eddy appears later in the | ||
// sequence | ||
assert(flux::read_at(people, max).name == "Eddy"); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
|
||
// Copyright (c) 2023 Tristan Brindle (tcbrindle at gmail dot com) | ||
// Distributed under the Boost Software License, Version 1.0. (See accompanying | ||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||
|
||
#ifndef FLUX_OP_FIND_MIN_MAX_HPP_INCLUDED | ||
#define FLUX_OP_FIND_MIN_MAX_HPP_INCLUDED | ||
|
||
#include <flux/core.hpp> | ||
#include <flux/op/minmax.hpp> | ||
|
||
namespace flux { | ||
|
||
namespace detail { | ||
|
||
struct find_min_fn { | ||
template <multipass_sequence Seq, | ||
strict_weak_order_for<Seq> Cmp = std::ranges::less> | ||
[[nodiscard]] | ||
constexpr auto operator()(Seq&& seq, Cmp cmp = {}) const -> cursor_t<Seq> | ||
{ | ||
auto min = first(seq); | ||
if (!is_last(seq, min)) { | ||
for (auto cur = next(seq, min); !is_last(seq, cur); inc(seq, cur)) { | ||
if (std::invoke(cmp, read_at(seq, cur), read_at(seq, min))) { | ||
min = cur; | ||
} | ||
} | ||
} | ||
|
||
return min; | ||
} | ||
}; | ||
|
||
struct find_max_fn { | ||
template <multipass_sequence Seq, | ||
strict_weak_order_for<Seq> Cmp = std::ranges::less> | ||
[[nodiscard]] | ||
constexpr auto operator()(Seq&& seq, Cmp cmp = {}) const -> cursor_t<Seq> | ||
{ | ||
auto max = first(seq); | ||
if (!is_last(seq, max)) { | ||
for (auto cur = next(seq, max); !is_last(seq, cur); inc(seq, cur)) { | ||
if (!std::invoke(cmp, read_at(seq, cur), read_at(seq, max))) { | ||
max = cur; | ||
} | ||
} | ||
} | ||
|
||
return max; | ||
} | ||
}; | ||
|
||
struct find_minmax_fn { | ||
template <multipass_sequence Seq, | ||
strict_weak_order_for<Seq> Cmp = std::ranges::less> | ||
[[nodiscard]] | ||
constexpr auto operator()(Seq&& seq, Cmp cmp = {}) const | ||
-> minmax_result<cursor_t<Seq>> | ||
{ | ||
auto min = first(seq); | ||
auto max = min; | ||
if (!is_last(seq, min)) { | ||
for (auto cur = next(seq, min); !is_last(seq, cur); inc(seq, cur)) { | ||
auto&& elem = read_at(seq, cur); | ||
|
||
if (std::invoke(cmp, elem, read_at(seq, min))) { | ||
min = cur; | ||
} | ||
if (!std::invoke(cmp, elem, read_at(seq, max))) { | ||
max = cur; | ||
} | ||
} | ||
} | ||
|
||
return {std::move(min), std::move(max)}; | ||
} | ||
}; | ||
|
||
} // namespace detail | ||
|
||
FLUX_EXPORT inline constexpr auto find_min = detail::find_min_fn{}; | ||
FLUX_EXPORT inline constexpr auto find_max = detail::find_max_fn{}; | ||
FLUX_EXPORT inline constexpr auto find_minmax = detail::find_minmax_fn{}; | ||
|
||
template <typename D> | ||
template <typename Cmp> | ||
requires strict_weak_order_for<Cmp, D> | ||
constexpr auto inline_sequence_base<D>::find_min(Cmp cmp) | ||
{ | ||
return flux::find_min(derived(), std::move(cmp)); | ||
} | ||
|
||
template <typename D> | ||
template <typename Cmp> | ||
requires strict_weak_order_for<Cmp, D> | ||
constexpr auto inline_sequence_base<D>::find_max(Cmp cmp) | ||
{ | ||
return flux::find_max(derived(), std::move(cmp)); | ||
} | ||
|
||
template <typename D> | ||
template <typename Cmp> | ||
requires strict_weak_order_for<Cmp, D> | ||
constexpr auto inline_sequence_base<D>::find_minmax(Cmp cmp) | ||
{ | ||
return flux::find_minmax(derived(), std::move(cmp)); | ||
} | ||
|
||
} // namespace flux | ||
|
||
#endif // FLUX_OP_FIND_MIN_MAX_HPP_INCLUDED |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,6 +8,7 @@ | |
|
||
#include <flux/core.hpp> | ||
|
||
#include <flux/op/fold.hpp> | ||
#include <flux/op/slice.hpp> | ||
|
||
namespace flux { | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.