#ifndef M1UNE_MINMAX_MONOID_HPP
#define M1UNE_MINMAX_MONOID_HPP 1
#include<algorithm>
#include<limits>
#include<utility>#include"../monoid.hpp"namespacem1une{// Monoid for storing both a minimum and maximum value.// The operation combines two pairs by taking the component-wise min and max.template<typenameT>usingminmax_monoid=monoid<std::pair<T,T>,[](std::pair<T,T>a,std::pair<T,T>b){returnstd::pair<T,T>(std::min(a.first,b.first),std::max(a.second,b.second));},[](){returnstd::pair<T,T>(std::numeric_limits<T>::max(),std::numeric_limits<T>::lowest());},true>;}// namespace m1une#endif // M1UNE_MINMAX_MONOID_HPP
#line 1 "monoid/monoids/minmax_monoid.hpp"
#include<algorithm>
#include<limits>
#include<utility>#line 1 "monoid/monoid.hpp"
#include<concepts>
#include<functional>
#include<type_traits>namespacem1une{template<typenameT,autooperation,autoidentity,boolcommutative>structmonoid{static_assert(std::is_invocable_r_v<T,decltype(operation),T,T>,"operation must work as T(T, T)");static_assert(std::is_invocable_r_v<T,decltype(identity)>,"identity must work as T()");usingvalue_type=T;staticconstexprautoop=operation;staticconstexprautoid=identity;staticconstexprboolis_commutative=commutative;};template<typenameT>conceptMonoid=requires(typenameT::value_typev){typenameT::value_type;{T::op(v,v)}->std::same_as<typenameT::value_type>;{T::id()}->std::same_as<typenameT::value_type>;{T::is_commutative}->std::convertible_to<bool>;};}// namespace m1une#line 9 "monoid/monoids/minmax_monoid.hpp"
namespacem1une{// Monoid for storing both a minimum and maximum value.// The operation combines two pairs by taking the component-wise min and max.template<typenameT>usingminmax_monoid=monoid<std::pair<T,T>,[](std::pair<T,T>a,std::pair<T,T>b){returnstd::pair<T,T>(std::min(a.first,b.first),std::max(a.second,b.second));},[](){returnstd::pair<T,T>(std::numeric_limits<T>::max(),std::numeric_limits<T>::lowest());},true>;}// namespace m1une