| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980 |
- //
- // minmax.h
- // stream
- //
- // Created by Sam Jaffe on 3/30/23.
- //
- #pragma once
- #include <optional>
- #include <stream/detail/identity.h>
- #include <stream/detail/named_pair.h>
- #include <stream/detail/traits.h>
- #define FWD(x) std::forward<decltype(x)>(x)
- namespace stream::detail {
- template <typename T, typename Comp, typename Proj>
- bool compare(T const & l, T const & r, Comp && comp, Proj && proj) {
- return std::invoke(FWD(comp), std::invoke(proj, l), std::invoke(proj, r));
- }
- }
- namespace stream::ranges {
- template <typename It, typename S, typename Comp = std::less<>,
- typename Proj = detail::identity,
- typename = std::enable_if_t<detail::is_comparable_v<It, S>>>
- auto minmax(It it, S end, Comp comp = {}, Proj proj = {}) {
- detail::min_max_result v(*it, *it);
- for (++it; it != end; ++it) {
- if (detail::compare(v.max, *it, comp, proj)) { v.max = *it; }
- if (detail::compare(*it, v.min, comp, proj)) { v.min = *it; }
- }
- return v;
- }
- template <typename Stream, typename Comp = std::less<>,
- typename Proj = detail::identity>
- auto minmax(Stream const & stream, Comp comp = {}, Proj proj = {}) {
- return minmax(stream.begin(), stream.end(), std::move(comp), std::move(proj));
- }
- template <typename It, typename S, typename Comp = std::less<>,
- typename Proj = detail::identity,
- typename = std::enable_if_t<detail::is_comparable_v<It, S>>>
- auto min(It it, S end, Comp comp = {}, Proj proj = {}) {
- auto v = *it;
- for (++it; it != end; ++it) {
- if (detail::compare(*it, v, comp, proj)) { v = *it; }
- }
- return v;
- }
- template <typename Stream, typename Comp = std::less<>,
- typename Proj = detail::identity>
- auto min(Stream const & stream, Comp comp = {}, Proj proj = {}) {
- return min(stream.begin(), stream.end(), std::move(comp), std::move(proj));
- }
- template <typename It, typename S, typename Comp = std::less<>,
- typename Proj = detail::identity,
- typename = std::enable_if_t<detail::is_comparable_v<It, S>>>
- auto max(It it, S end, Comp comp = {}, Proj proj = {}) {
- auto v = *it;
- for (++it; it != end; ++it) {
- if (detail::compare(v, *it, comp, proj)) { v = *it; }
- }
- return v;
- }
- template <typename Stream, typename Comp = std::less<>,
- typename Proj = detail::identity>
- auto max(Stream const & stream, Comp comp = {}, Proj proj = {}) {
- return max(stream.begin(), stream.end(), std::move(comp), std::move(proj));
- }
- }
- #undef FWD
|