Skip to content

Commit c6e6371

Browse files
chore: update minified library versions
1 parent 18b711b commit c6e6371

File tree

1 file changed

+3
-1
lines changed

1 file changed

+3
-1
lines changed

cp-algo/min/math/laurent.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@
66
#include <vector>
77
#include <cassert>
88
#include <algorithm>
9+
#include <iterator>
910
#include <type_traits>
1011
#include <bit>
12+
#include <ranges>
1113
#include "cvector.hpp"
1214
#include "convolution.hpp"
13-
namespace cp_algo::math{template<typename T>struct provider{mutable big_vector<T>cache;mutable int cache_offset=0;mutable bool initialized=false;mutable bool all_cached=false;virtual~provider()=default;virtual int offset()const{return 0;}virtual bool needs_lazy_eval()const{return false;}virtual T coeff_lazy(int k)const=0;virtual void double_up()const{int old_size=cache.size();int new_size=old_size==0?1:2*old_size;cache.resize(new_size);for(int i=old_size;i<new_size;i++){cache[i]=coeff_lazy(cache_offset+i);}}virtual T coeff(int k)const{if(!initialized){cache_offset=offset();initialized=true;}int idx=k-cache_offset;if(idx<0){return T(0);}if(all_cached&&idx>=(int)cache.size()){return T(0);}if(needs_lazy_eval()){while(idx>=(int)cache.size()&&!all_cached){int next_k=cache_offset+(int)cache.size();cache.push_back(coeff_lazy(next_k));}}else{while(idx>=(int)cache.size()&&!all_cached){double_up();}}if(idx<(int)cache.size()){return cache[idx];}return T(0);}T get(int k)const{return coeff(k);}};template<typename T>struct constant_provider:provider<T>{T value;int offset;constant_provider(T value,int offset=0):value(value),offset(offset){}int offset()const override{return offset;}T coeff_lazy(int k)const override{return k==offset?value:T(0);}T coeff(int k)const override{return coeff_lazy(k);}};template<typename T>struct polynomial_provider:provider<T>{polynomial_provider(big_vector<T>coeffs,int offset=0){auto non_zero=[](const T&x){return x!=T(0);};auto first=std::ranges::find_if(coeffs,non_zero);auto last=std::ranges::find_if(coeffs|std::views::reverse,non_zero);if(first!=coeffs.end()){int leading_zeros=first-coeffs.begin();int trailing_zeros=last-coeffs.rbegin();coeffs=big_vector<T>(first,coeffs.end()-trailing_zeros);offset+=leading_zeros;}else{coeffs.clear();}this->cache=std::move(coeffs);this->cache_offset=offset;this->initialized=true;this->all_cached=true;}int offset()const override{return this->cache_offset;}T coeff_lazy(int k)const override{int idx=k-this->cache_offset;if(idx<0||idx>=(int)this->cache.size()){return T(0);}return this->cache[idx];}T coeff(int k)const override{return coeff_lazy(k);}};template<typename T>struct unary_provider:provider<T>{std::shared_ptr<provider<T>>operand;unary_provider(std::shared_ptr<provider<T>>operand):operand(std::move(operand)){}virtual T transform(T const&a)const=0;int offset()const override{return operand->offset();}T coeff_lazy(int k)const override{return transform(operand->coeff_lazy(k));}T coeff(int k)const{return transform(operand->coeff(k));}};template<typename T>struct binary_provider:provider<T>{std::shared_ptr<provider<T>>lhs,rhs;binary_provider(std::shared_ptr<provider<T>>lhs,std::shared_ptr<provider<T>>rhs):lhs(std::move(lhs)),rhs(std::move(rhs)){}virtual T combine(T const&a,T const&b)const=0;int offset()const override{return std::min(lhs->offset(),rhs->offset());}T coeff_lazy(int k)const override{return combine(lhs->coeff_lazy(k),rhs->coeff_lazy(k));}T coeff(int k)const{return combine(lhs->coeff(k),rhs->coeff(k));}};template<typename T>struct add_provider:binary_provider<T>{using binary_provider<T>::binary_provider;T combine(T const&a,T const&b)const override{return a+b;}};template<typename T>struct subtract_provider:binary_provider<T>{using binary_provider<T>::binary_provider;T combine(T const&a,T const&b)const override{return a-b;}};template<typename T>struct negate_provider:unary_provider<T>{using unary_provider<T>::unary_provider;T transform(T const&a)const override{return-a;}};template<typename T>struct scale_provider:unary_provider<T>{T scalar;scale_provider(std::shared_ptr<provider<T>>operand,T scalar):unary_provider<T>(std::move(operand)),scalar(scalar){}T transform(T const&a)const override{return a*scalar;}};template<typename T>struct multiply_provider:provider<T>{std::shared_ptr<provider<T>>lhs,rhs;multiply_provider(std::shared_ptr<provider<T>>lhs,std::shared_ptr<provider<T>>rhs):lhs(std::move(lhs)),rhs(std::move(rhs)){}int offset()const override{return lhs->offset()+rhs->offset();}bool needs_lazy_eval()const override{return lhs->needs_lazy_eval()||rhs->needs_lazy_eval();}T coeff_lazy(int k)const override{int n=k-offset();if(n<0)return T(0);T result=T(0);bool lazy_lhs=lhs->needs_lazy_eval();bool lazy_rhs=rhs->needs_lazy_eval();for(int j=0;j<=n;j++){int i_l=lhs->offset()+j;int i_r=rhs->offset()+(n-j);auto a=lazy_lhs?lhs->coeff(i_l):lhs->coeff_lazy(i_l);auto b=lazy_rhs?rhs->coeff(i_r):rhs->coeff_lazy(i_r);result+=a*b;}return result;}void double_up()const override{int old_size=this->cache.size();int new_size=old_size==0?1:2*old_size;if(needs_lazy_eval()){int k=this->cache_offset+old_size;this->cache.push_back(coeff_lazy(k));return;}int lhs_need=lhs->offset()+new_size-1;int rhs_need=rhs->offset()+new_size-1;lhs->coeff(lhs_need);rhs->coeff(rhs_need);big_vector<T>la(new_size),rb(new_size);for(int i=0;i<new_size;i++){la[i]=lhs->coeff(lhs->offset()+i);rb[i]=rhs->coeff(rhs->offset()+i);}this->cache.resize(new_size);convolution_prefix(la,rb,new_size);for(int i=old_size;i<new_size&&i<(int)la.size();i++){this->cache[i]=la[i];}if(lhs->all_cached&&rhs->all_cached){size_t total_len=lhs->cache.size()+rhs->cache.size()-1;if((size_t)new_size>=total_len){this->cache.resize(total_len);this->all_cached=true;}}}};template<typename T>struct laurent{std::shared_ptr<provider<T>>impl;laurent():impl(std::make_shared<constant_provider<T>>(T(0),0)){}laurent(T value,int offset=0):impl(std::make_shared<constant_provider<T>>(value,offset)){}laurent(big_vector<T>coeffs,int offset=0):impl(std::make_shared<polynomial_provider<T>>(std::move(coeffs),offset)){}laurent(std::shared_ptr<provider<T>>impl):impl(std::move(impl)){}T operator[](int k)const{return impl->get(k);}laurent operator-()const{return std::make_shared<negate_provider<T>>(impl);}laurent operator+(const laurent&other)const{return std::make_shared<add_provider<T>>(impl,other.impl);}laurent operator-(const laurent&other)const{return std::make_shared<subtract_provider<T>>(impl,other.impl);}laurent operator*(const laurent&other)const{return std::make_shared<multiply_provider<T>>(impl,other.impl);}laurent&operator+=(const laurent&other){return*this=*this+other;}laurent&operator-=(const laurent&other){return*this=*this-other;}laurent&operator*=(const laurent&other){return*this=*this*other;}laurent operator*(T const&scalar)const{return std::make_shared<scale_provider<T>>(impl,scalar);}laurent&operator*=(T const&scalar){return*this=*this*scalar;}};template<typename T>laurent<T>operator*(T const&scalar,laurent<T>const&series){return series*scalar;}}
15+
namespace cp_algo::math{struct eval_options{bool direct=false;bool lazy=false;bool precache_arguments=false;};template<typename T>struct provider{mutable big_vector<T>cache;mutable int cache_valid=0;mutable int cache_offset=0;mutable bool initialized=false;mutable bool all_cached=false;void initialize_if_needed()const{if(!initialized){cache_offset=offset();initialized=true;}}virtual~provider()=default;virtual int offset()const{return 0;}virtual bool needs_lazy_eval()const{return false;}virtual T coeff_lazy(int k)const=0;T coeff_direct(int k)const{initialize_if_needed();int idx=k-cache_offset;if(idx<0)return T(0);if(idx<cache_valid)return cache[idx];return coeff_direct_impl(k);}protected:virtual T coeff_direct_impl(int k)const=0;virtual void double_up()const{int old_size=cache.size();int new_size=old_size==0?1:2*old_size;cache.resize(new_size);for(int i=old_size;i<new_size;i++){cache[i]=coeff(cache_offset+i);}cache_valid=new_size;}void upcache(int n)const{if(all_cached)return;initialize_if_needed();int idx=n-cache_offset;if(idx<0)return;if(needs_lazy_eval()){while(idx>=cache_valid&&!all_cached){int next_k=cache_offset+cache_valid;if((int)cache.size()<=cache_valid)cache.resize(cache_valid+1);cache[cache_valid]=coeff_lazy(next_k);cache_valid++;}}else{while(idx>=cache_valid&&!all_cached){double_up();}}}virtual T coeff(int k)const{static constexpr eval_options defaults{};return coeff(k,defaults);}virtual T coeff(int k,eval_options const&opt)const{initialize_if_needed();int idx=k-cache_offset;if(idx<0){return T(0);}if(all_cached&&idx>=(int)cache.size()){return T(0);}if(opt.direct){if(idx<cache_valid)return cache[idx];return coeff_direct(k);}else{if(opt.lazy||needs_lazy_eval()){upcache(k);}else{upcache(k);}}if(idx<cache_valid){return cache[idx];}return T(0);}};template<typename T>struct constant_provider:provider<T>{T value;int offset;constant_provider(T value,int offset=0):value(value),offset(offset){}int offset()const override{return offset;}T coeff_lazy(int k)const override{return k==offset?value:T(0);}T coeff_direct_impl(int k)const override{return k==offset?value:T(0);}T coeff(int k)const override{return coeff_lazy(k);}};template<typename T>struct polynomial_provider:provider<T>{polynomial_provider(auto&&coeffs,int offset=0){auto non_zero=[](const T&x){return x!=T(0);};auto first=std::ranges::find_if(coeffs,non_zero);auto last=std::ranges::find_last_if(coeffs,non_zero);if(first!=coeffs.end()){int leading_zeros=first-coeffs.begin();int trailing_zeros=static_cast<int>(std::ranges::ssize(last))-1;this->cache=big_vector<T>(first,coeffs.end()-trailing_zeros);offset+=leading_zeros;}this->cache_offset=offset;this->initialized=true;this->cache_valid=(int)this->cache.size();this->all_cached=true;}int offset()const override{return this->cache_offset;}T coeff_lazy(int k)const override{int idx=k-this->cache_offset;if(idx<0||idx>=this->cache_valid){return T(0);}return this->cache[idx];}T coeff_direct_impl(int k)const override{return coeff_lazy(k);}T coeff(int k)const override{return coeff_lazy(k);}T coeff(int k,eval_options const&)const override{return coeff_lazy(k);}};template<typename T>struct unary_provider:provider<T>{std::shared_ptr<provider<T>>operand;unary_provider(std::shared_ptr<provider<T>>operand):operand(std::move(operand)){}bool needs_lazy_eval()const override{return operand->needs_lazy_eval();}virtual T transform(T const&a)const=0;int offset()const override{return operand->offset();}T coeff_lazy(int k)const override{return transform(operand->coeff_lazy(k));}T coeff_direct_impl(int k)const override{return transform(operand->coeff_direct(k));}T coeff(int k)const{return transform(operand->coeff(k));}T coeff(int k,eval_options const&opt)const override{return transform(operand->coeff(k,opt));}};template<typename T>struct binary_provider:provider<T>{std::shared_ptr<provider<T>>lhs,rhs;binary_provider(std::shared_ptr<provider<T>>lhs,std::shared_ptr<provider<T>>rhs):lhs(std::move(lhs)),rhs(std::move(rhs)){}bool needs_lazy_eval()const override{return lhs->needs_lazy_eval()||rhs->needs_lazy_eval();}virtual T combine(T const&a,T const&b)const=0;int offset()const override{return std::min(lhs->offset(),rhs->offset());}T coeff_lazy(int k)const override{return combine(lhs->coeff_lazy(k),rhs->coeff_lazy(k));}T coeff_direct_impl(int k)const override{return combine(lhs->coeff_direct(k),rhs->coeff_direct(k));}T coeff(int k)const{return combine(lhs->coeff(k),rhs->coeff(k));}T coeff(int k,eval_options const&opt)const override{return combine(lhs->coeff(k,opt),rhs->coeff(k,opt));}};template<typename T>struct add_provider:binary_provider<T>{using binary_provider<T>::binary_provider;T combine(T const&a,T const&b)const override{return a+b;}};template<typename T>struct subtract_provider:binary_provider<T>{using binary_provider<T>::binary_provider;T combine(T const&a,T const&b)const override{return a-b;}};template<typename T>struct negate_provider:unary_provider<T>{using unary_provider<T>::unary_provider;T transform(T const&a)const override{return-a;}};template<typename T>struct scale_provider:unary_provider<T>{T scalar;scale_provider(std::shared_ptr<provider<T>>operand,T scalar):unary_provider<T>(std::move(operand)),scalar(scalar){}T transform(T const&a)const override{return a*scalar;}};template<typename T>struct multiply_provider:provider<T>{std::shared_ptr<provider<T>>lhs,rhs;multiply_provider(std::shared_ptr<provider<T>>lhs,std::shared_ptr<provider<T>>rhs):lhs(std::move(lhs)),rhs(std::move(rhs)){}int offset()const override{return lhs->offset()+rhs->offset();}bool needs_lazy_eval()const override{return lhs->needs_lazy_eval()||rhs->needs_lazy_eval();}T coeff_lazy(int k)const override{int n=k-offset();if(n<0)return T(0);T result=T(0);bool lazy_lhs=lhs->needs_lazy_eval();bool lazy_rhs=rhs->needs_lazy_eval();for(int j=0;j<=n;j++){int i_l=lhs->offset()+j;int i_r=rhs->offset()+(n-j);auto a=lazy_lhs?lhs->coeff(i_l):lhs->coeff_lazy(i_l);auto b=lazy_rhs?rhs->coeff(i_r):rhs->coeff_lazy(i_r);result+=a*b;}return result;}T coeff_direct_impl(int k)const override{int n=k-offset();if(n<0)return T(0);T result=T(0);for(int j=0;j<=n;j++){int i_l=lhs->offset()+j;int i_r=rhs->offset()+(n-j);auto a=lhs->coeff(i_l);auto b=rhs->coeff(i_r);result+=a*b;}return result;}T coeff(int k,eval_options const&opt)const override{int n=k-offset();if(n<0)return T(0);if(opt.direct){T result=T(0);for(int j=0;j<=n;j++){int i_l=lhs->offset()+j;int i_r=rhs->offset()+(n-j);if(opt.precache_arguments&&!opt.lazy){lhs->coeff(i_l);rhs->coeff(i_r);}auto a=(opt.lazy||lhs->needs_lazy_eval())?lhs->coeff_lazy(i_l):lhs->coeff(i_l);auto b=(opt.lazy||rhs->needs_lazy_eval())?rhs->coeff_lazy(i_r):rhs->coeff(i_r);result+=a*b;}return result;}int idx=k-this->cache_offset;if(idx<0)return T(0);while(idx>=(int)this->cache.size()&&!this->all_cached){if(opt.lazy||needs_lazy_eval()){int next_k=this->cache_offset+(int)this->cache.size();if(opt.precache_arguments&&!opt.lazy){int n2=next_k-offset();int lhs_need=lhs->offset()+n2;int rhs_need=rhs->offset()+n2;lhs->upcache(lhs_need);rhs->upcache(rhs_need);}if((int)this->cache.size()<=this->cache_valid)this->cache.resize(this->cache_valid+1);this->cache[this->cache_valid]=coeff_lazy(next_k);this->cache_valid++;}else{double_up();}}return idx<this->cache_valid?this->cache[idx]:T(0);}void double_up()const override{int old_size=this->cache.size();int new_size=old_size==0?1:2*old_size;if(needs_lazy_eval()){int k=this->cache_offset+old_size;if((int)this->cache.size()<=this->cache_valid)this->cache.resize(this->cache_valid+1);this->cache[this->cache_valid]=coeff_lazy(k);this->cache_valid++;return;}int lhs_need=lhs->offset()+new_size-1;int rhs_need=rhs->offset()+new_size-1;lhs->coeff(lhs_need);rhs->coeff(rhs_need);big_vector<T>la(new_size),rb(new_size);for(int i=0;i<new_size;i++){la[i]=lhs->coeff(lhs->offset()+i);rb[i]=rhs->coeff(rhs->offset()+i);}this->cache.resize(new_size);convolution_prefix(la,rb,new_size);for(int i=old_size;i<new_size&&i<(int)la.size();i++){this->cache[i]=la[i];}this->cache_valid=new_size;if(lhs->all_cached&&rhs->all_cached){size_t total_len=lhs->cache.size()+rhs->cache.size()-1;if((size_t)new_size>=total_len){this->cache.resize(total_len);this->all_cached=true;}}}};template<typename T>struct laurent{std::shared_ptr<provider<T>>impl;laurent():impl(std::make_shared<constant_provider<T>>(T(0),0)){}laurent(T value,int offset=0):impl(std::make_shared<constant_provider<T>>(value,offset)){}laurent(big_vector<T>coeffs,int offset=0):impl(std::make_shared<polynomial_provider<T>>(std::move(coeffs),offset)){}laurent(std::shared_ptr<provider<T>>impl):impl(std::move(impl)){}T operator[](int k)const{return impl->get(k);}laurent operator-()const{return std::make_shared<negate_provider<T>>(impl);}laurent operator+(const laurent&other)const{return std::make_shared<add_provider<T>>(impl,other.impl);}laurent operator-(const laurent&other)const{return std::make_shared<subtract_provider<T>>(impl,other.impl);}laurent operator*(const laurent&other)const{return std::make_shared<multiply_provider<T>>(impl,other.impl);}laurent&operator+=(const laurent&other){return*this=*this+other;}laurent&operator-=(const laurent&other){return*this=*this-other;}laurent&operator*=(const laurent&other){return*this=*this*other;}laurent operator*(T const&scalar)const{return std::make_shared<scale_provider<T>>(impl,scalar);}laurent&operator*=(T const&scalar){return*this=*this*scalar;}T coeff(int k,eval_options const&opt)const{return impl->coeff(k,opt);}};template<typename T>laurent<T>operator*(T const&scalar,laurent<T>const&series){return series*scalar;}}
1416
#endif

0 commit comments

Comments
 (0)