Skip to content

Instantly share code, notes, and snippets.

@rileylev
Created March 18, 2021 17:37
Show Gist options
  • Save rileylev/8dc6ba23a4aab549c52dc0ba13b088f8 to your computer and use it in GitHub Desktop.
Save rileylev/8dc6ba23a4aab549c52dc0ba13b088f8 to your computer and use it in GitHub Desktop.
a place for goto
template<class T, class Less = std::less<>>
constexpr auto minmax(T&& x, T&& y, Less less = {})
BODX(less(y, x) ? std::forward_as_tuple(y, x) : std::forward_as_tuple(x, y))
// s is for stable
template<class T, class Less = std::less<>>
constexpr auto smin(T&& x, T&& y, Less less = {})
BODX(std::get<0>(minmax(x, y, less)))
template<class T, class Less = std::less<>>
constexpr auto smax(T&& x, T&& y, Less less = {})
BODX(std::get<1>(minmax(x, y, less)))
template<class Key, class Less = std::less<>>
constexpr auto cmpby(Key key, Less less = {}) {
return [ key, less ](auto x, auto y){
return less(key(x), key(y));
}
}
template<std::forward_iterator I, class S, class Less>
std::pair<I, I> minmax_elt(I begin, S const end, Less less) {
auto const n = std::next(begin);
if(begin == end || n == end) return {begin, begin};
else {
auto const iter_less = cmpby([](auto x){return *x;}, less);
auto [the_min, the_max] = minmax(begin, n, iter_less);
begin = std::next(n);
read2:
I const i = begin;
I const j = std::next(i);
if(i == end) goto done;
if(j == end) goto one_more;
else {
auto const [smaller, bigger] = minmax(i, j, iter_less);
the_min = smin(the_min, smaller, iter_less);
the_max = smax(the_max, bigger, iter_less);
}
begin = std::next(j);
goto read2;
one_more:
the_min = smin(the_min, begin, iter_less);
the_max = smax(the_max, begin, iter_less);
done:
return {the_min, the_max};
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment