#ifndef M1UNE_ACTED_MONOIDS_RANGE_AFFINE_RANGE_SUM_HPP
#define M1UNE_ACTED_MONOIDS_RANGE_AFFINE_RANGE_SUM_HPP 1
#include"../acted_monoid.hpp"
#include"../monoid_addsz.hpp"
#include"../monoids/add_monoid.hpp"
#include"../monoids/affine_monoid.hpp"namespacem1une{template<typenameT>usingrange_affine_range_sum_monoid=acted_monoid<monoid_addsz<add_monoid<T>>,affine_monoid<T>,[](typenameaffine_monoid<T>::value_typef,typenamemonoid_addsz<add_monoid<T>>::value_typex){// f = (a, b) is the affine transformation// x = {value, size} is the data (sum and size of the range)// Applying f to each element xi and summing up:// sum(a*xi + b) = a * sum(xi) + b * sizereturntypenamemonoid_addsz<add_monoid<T>>::value_type{f.first*x.value+f.second*x.size,x.size};}>;}// namespace m1une#endif // M1UNE_ACTED_MONOIDS_RANGE_AFFINE_RANGE_SUM_HPP
#line 1 "monoid/acted_monoids/range_affine_range_sum.hpp"
#line 1 "monoid/acted_monoid.hpp"
#include<concepts>
#include<functional>
#include<type_traits>#line 1 "monoid/monoid.hpp"
#line 7 "monoid/monoid.hpp"
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/acted_monoid.hpp"
namespacem1une{template<MonoidData,MonoidAct,automapping>structacted_monoid{usingdata_monoid=Data;usingact_monoid=Act;usingdata_type=typenameData::value_type;usingact_type=typenameAct::value_type;static_assert(std::is_invocable_r_v<data_type,decltype(mapping),act_type,data_type>,"mapping must work as data_type(act_type, data_type)");staticconstexprautodata_op=Data::op;staticconstexprautodata_id=Data::id;staticconstexprbooldata_is_commutative=Data::is_commutative;staticconstexprautoact_op=Act::op;staticconstexprautoact_id=Act::id;staticconstexprboolact_is_commutative=Act::is_commutative;staticconstexprautoapply=mapping;};template<typenameT>conceptActedMonoid=requires(typenameT::data_typed,typenameT::act_typea){typenameT::data_monoid;typenameT::act_monoid;typenameT::data_type;typenameT::act_type;requiresMonoid<typenameT::data_monoid>;requiresMonoid<typenameT::act_monoid>;{T::apply(a,d)}->std::same_as<typenameT::data_type>;};}// namespace m1une#line 1 "monoid/monoid_addsz.hpp"
#line 5 "monoid/monoid_addsz.hpp"
#line 7 "monoid/monoid_addsz.hpp"
namespacem1une{template<typenameT>structvalue_and_size{Tvalue;intsize;};template<MonoidM>usingmonoid_addsz=monoid<value_and_size<typenameM::value_type>,[](value_and_size<typenameM::value_type>a,value_and_size<typenameM::value_type>b){returnvalue_and_size<typenameM::value_type>{M::op(a.value,b.value),a.size+b.size};},[](){returnvalue_and_size<typenameM::value_type>{M::id(),0};},M::is_commutative>;}// namespace m1une#line 1 "monoid/monoids/add_monoid.hpp"
#line 5 "monoid/monoids/add_monoid.hpp"
namespacem1une{template<typenameT>usingadd_monoid=monoid<T,[](Ta,Tb){returna+b;},[](){returnT(0);},true>;}// namespace m1une#line 1 "monoid/monoids/affine_monoid.hpp"
#include<utility>#line 7 "monoid/monoids/affine_monoid.hpp"
namespacem1une{// Affine transformation f(x) = ax + b is represented as (a, b)// perform f first, then g// op(f, g)(x) = g(f(x))template<typenameT>usingaffine_monoid=monoid<std::pair<T,T>,[](std::pair<T,T>f,std::pair<T,T>g){returnstd::pair<T,T>(f.first*g.first,f.second*g.first+g.second);},[](){returnstd::pair<T,T>(1,0);},false>;}// namespace m1une#line 8 "monoid/acted_monoids/range_affine_range_sum.hpp"
namespacem1une{template<typenameT>usingrange_affine_range_sum_monoid=acted_monoid<monoid_addsz<add_monoid<T>>,affine_monoid<T>,[](typenameaffine_monoid<T>::value_typef,typenamemonoid_addsz<add_monoid<T>>::value_typex){// f = (a, b) is the affine transformation// x = {value, size} is the data (sum and size of the range)// Applying f to each element xi and summing up:// sum(a*xi + b) = a * sum(xi) + b * sizereturntypenamemonoid_addsz<add_monoid<T>>::value_type{f.first*x.value+f.second*x.size,x.size};}>;}// namespace m1une