minmax.h 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. //
  2. // minmax.h
  3. // stream
  4. //
  5. // Created by Sam Jaffe on 3/30/23.
  6. //
  7. #pragma once
  8. #include <optional>
  9. #include <stream/detail/identity.h>
  10. #include <stream/detail/named_pair.h>
  11. #include <stream/detail/traits.h>
  12. #define FWD(x) std::forward<decltype(x)>(x)
  13. namespace stream::detail {
  14. template <typename T, typename Comp, typename Proj>
  15. bool compare(T const & l, T const & r, Comp comp, Proj proj) {
  16. return std::invoke(comp, std::invoke(proj, l), std::invoke(proj, r));
  17. }
  18. }
  19. namespace stream::ranges {
  20. template <typename It, typename S, typename Comp = std::less<>,
  21. typename Proj = detail::identity>
  22. auto minmax(It it, S end, Comp comp = {}, Proj proj = {}) {
  23. detail::min_max_result v(*it, *it);
  24. for (++it; it != end; ++it) {
  25. if (detail::compare(v.max, *it, std::ref(comp), std::ref(proj))) {
  26. v.max = *it;
  27. }
  28. if (detail::compare(*it, v.min, std::ref(comp), std::ref(proj))) {
  29. v.min = *it;
  30. }
  31. }
  32. return v;
  33. }
  34. template <typename Stream, typename Comp = std::less<>,
  35. typename Proj = detail::identity>
  36. auto minmax(Stream const & stream, Comp comp = {}, Proj proj = {}) {
  37. return minmax(stream.begin(), stream.end(), std::move(comp), std::move(proj));
  38. }
  39. template <typename It, typename S, typename Comp = std::less<>,
  40. typename Proj = detail::identity>
  41. auto min(It it, S end, Comp comp = {}, Proj proj = {}) {
  42. auto v = *it;
  43. for (++it; it != end; ++it) {
  44. if (detail::compare(*it, v, std::ref(comp), std::ref(proj))) { v = *it; }
  45. }
  46. return v;
  47. }
  48. template <typename Stream, typename Comp = std::less<>,
  49. typename Proj = detail::identity>
  50. auto min(Stream const & stream, Comp comp = {}, Proj proj = {}) {
  51. return min(stream.begin(), stream.end(), std::move(comp), std::move(proj));
  52. }
  53. template <typename It, typename S, typename Comp = std::less<>,
  54. typename Proj = detail::identity>
  55. auto max(It it, S end, Comp comp = {}, Proj proj = {}) {
  56. auto v = *it;
  57. for (++it; it != end; ++it) {
  58. if (detail::compare(v, *it, std::ref(comp), std::ref(proj))) { v = *it; }
  59. }
  60. return v;
  61. }
  62. template <typename Stream, typename Comp = std::less<>,
  63. typename Proj = detail::identity>
  64. auto max(Stream const & stream, Comp comp = {}, Proj proj = {}) {
  65. return max(stream.begin(), stream.end(), std::move(comp), std::move(proj));
  66. }
  67. }
  68. #undef FWD