Skip to content

Commit 207e8b3

Browse files
chore: update minified library versions
1 parent 09e6c57 commit 207e8b3

File tree

2 files changed

+2
-2
lines changed

2 files changed

+2
-2
lines changed

cp-algo/min/linalg/matrix.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,6 @@
88
#include <cassert>
99
#include <vector>
1010
#include <array>
11-
CP_ALGO_SIMD_PRAGMA_PUSHnamespace cp_algo::linalg{enum gauss_mode{normal,reverse};template<typename base_t,class _vec_t=std::conditional_t<math::modint_type<base_t>,modint_vec<base_t>,vec<base_t>>>struct matrix:big_vector<_vec_t>{using vec_t=_vec_t;using base=base_t;using Base=big_vector<vec_t>;using Base::Base;matrix(size_t n):Base(n,vec_t(n)){}matrix(size_t n,size_t m):Base(n,vec_t(m)){}matrix(Base const&t):Base(t){}matrix(Base&&t):Base(std::move(t)){}template<std::ranges::input_range R>matrix(R&&r):Base(std::from_range,std::forward<R>(r)){}size_t n()const{return size(*this);}size_t m()const{return n()?size(row(0)):0;}void resize(size_t n,size_t m){Base::resize(n);for(auto&it:*this){it.resize(m);}}auto&row(size_t i){return(*this)[i];}auto const&row(size_t i)const{return(*this)[i];}auto elements(){return*this|std::views::join;}auto elements()const{return*this|std::views::join;}matrix operator-()const{return*this|std::views::transform([](auto x){return vec_t(-x);});}matrix&operator+=(matrix const&t){for(auto[a,b]:std::views::zip(elements(),t.elements())){a+=b;}return*this;}matrix&operator-=(matrix const&t){for(auto[a,b]:std::views::zip(elements(),t.elements())){a-=b;}return*this;}matrix operator+(matrix const&t)const{return matrix(*this)+=t;}matrix operator-(matrix const&t)const{return matrix(*this)-=t;}matrix&operator*=(base t){for(auto&it:*this)it*=t;return*this;}matrix operator*(base t)const{return matrix(*this)*=t;}matrix&operator/=(base t){return*this*=base(1)/t;}matrix operator/(base t)const{return matrix(*this)/=t;}matrix&operator*=(matrix const&t){return*this=*this*t;}void read_transposed(){for(size_t j=0;j<m();j++){for(size_t i=0;i<n();i++){std::cin>>(*this)[i][j];}}}void read(){for(auto&it:*this){it.read();}}void print()const{for(auto const&it:*this){it.print();}}static matrix block_diagonal(big_vector<matrix>const&blocks){size_t n=0;for(auto&it:blocks){assert(it.n()==it.m());n+=it.n();}matrix res(n);n=0;for(auto&it:blocks){for(size_t i=0;i<it.n();i++){std::ranges::copy(it[i],begin(res[n+i])+n);}n+=it.n();}return res;}static matrix random(size_t n,size_t m){matrix res(n,m);std::ranges::generate(res,std::bind(vec_t::random,m));return res;}static matrix random(size_t n){return random(n,n);}static matrix eye(size_t n){matrix res(n);for(size_t i=0;i<n;i++){res[i][i]=1;}return res;}matrix operator|(matrix const&b)const{assert(n()==b.n());matrix res(n(),m()+b.m());for(size_t i=0;i<n();i++){res[i]=row(i)|b[i];}return res;}void assign_submatrix(auto viewx,auto viewy,matrix const&t){for(auto[a,b]:std::views::zip(*this|viewx,t)){std::ranges::copy(b,begin(a|viewy));}}auto submatrix(auto viewx,auto viewy)const{return*this|viewx|std::views::transform([viewy](auto const&y){return y|viewy;});}matrix T()const{matrix res(m(),n());for(size_t i=0;i<n();i++){for(size_t j=0;j<m();j++){res[j][i]=row(i)[j];}}return res;}matrix operator*(matrix const&b)const{assert(m()==b.n());matrix res(n(),b.m());for(size_t i=0;i<n();i++){for(size_t j=0;j<m();j++){res[i].add_scaled(b[j],row(i)[j]);}}return res.normalize();}vec_t apply(vec_t const&x)const{return(matrix(1,x)**this)[0];}matrix pow(uint64_t k)const{assert(n()==m());return bpow(*this,k,eye(n()));}matrix&normalize(){for(auto&it:*this){it.normalize();}return*this;}template<gauss_mode mode=normal>void eliminate(size_t i,size_t k){auto kinv=base(1)/row(i).normalize()[k];for(size_t j=(mode==normal)*i;j<n();j++){if(j!=i){row(j).add_scaled(row(i),-row(j).normalize(k)*kinv);}}}template<gauss_mode mode=normal>void eliminate(size_t i){row(i).normalize();for(size_t j=(mode==normal)*i;j<n();j++){if(j!=i){row(j).reduce_by(row(i));}}}template<gauss_mode mode=normal>matrix&gauss(){for(size_t i=0;i<n();i++){eliminate<mode>(i);}return normalize();}template<gauss_mode mode=normal>auto echelonize(size_t lim){return gauss<mode>().sort_classify(lim);}template<gauss_mode mode=normal>auto echelonize(){return echelonize<mode>(m());}size_t rank()const{if(n()>m()){return T().rank();}return size(matrix(*this).echelonize()[0]);}base det()const{assert(n()==m());matrix b=*this;b.echelonize();base res=1;for(size_t i=0;i<n();i++){res*=b[i][i];}return res;}std::pair<base,matrix>inv()const{assert(n()==m());matrix b=*this|eye(n());if(size(b.echelonize<reverse>(n())[0])<n()){return{0,{}};}base det=1;for(size_t i=0;i<n();i++){det*=b[i][i];b[i]*=base(1)/b[i][i];}return{det,b.submatrix(std::views::all,std::views::drop(n()))};}auto kernel()const{auto A=*this;auto[pivots,free]=A.template echelonize<reverse>();matrix sols(size(free),m());for(size_t j=0;j<size(pivots);j++){base scale=base(1)/A[j][pivots[j]];for(size_t i=0;i<size(free);i++){sols[i][pivots[j]]=A[j][free[i]]*scale;}}for(size_t i=0;i<size(free);i++){sols[i][free[i]]=-1;}return sols;}std::optional<std::array<matrix,2>>solve(matrix t)const{matrix sols=(*this|t).kernel();if(sols.n()<t.m()||matrix(sols.submatrix(std::views::drop(sols.n()-t.m()),std::views::drop(m())))!=-eye(t.m())){return std::nullopt;}else{return std::array{matrix(sols.submatrix(std::views::drop(sols.n()-t.m()),std::views::take(m()))),matrix(sols.submatrix(std::views::take(sols.n()-t.m()),std::views::take(m())))};}}auto sort_classify(size_t lim){size_t rk=0;big_vector<size_t>free,pivots;for(size_t j=0;j<lim;j++){for(size_t i=rk+1;i<n()&&row(rk)[j]==base(0);i++){if(row(i)[j]!=base(0)){std::swap(row(i),row(rk));row(rk)=-row(rk);}}if(rk<n()&&row(rk)[j]!=base(0)){pivots.push_back(j);rk++;}else{free.push_back(j);}}return std::array{pivots,free};}};template<typename base_t>auto operator*(base_t t,matrix<base_t>const&A){return A*t;}}
11+
CP_ALGO_SIMD_PRAGMA_PUSHnamespace cp_algo::linalg{enum gauss_mode{normal,reverse};template<typename base_t,class _vec_t=std::conditional_t<math::modint_type<base_t>,modint_vec<base_t>,vec<base_t>>>struct matrix:big_vector<_vec_t>{using vec_t=_vec_t;using base=base_t;using Base=big_vector<vec_t>;using Base::Base;matrix(size_t n):Base(n,vec_t(n)){}matrix(size_t n,size_t m):Base(n,vec_t(m)){}matrix(Base const&t):Base(t){}matrix(Base&&t):Base(std::move(t)){}template<std::ranges::input_range R>matrix(R&&r):Base(r.begin(),r.end()){}size_t n()const{return size(*this);}size_t m()const{return n()?size(row(0)):0;}void resize(size_t n,size_t m){Base::resize(n);for(auto&it:*this){it.resize(m);}}auto&row(size_t i){return(*this)[i];}auto const&row(size_t i)const{return(*this)[i];}auto elements(){return*this|std::views::join;}auto elements()const{return*this|std::views::join;}matrix operator-()const{return*this|std::views::transform([](auto x){return vec_t(-x);});}matrix&operator+=(matrix const&t){for(auto[a,b]:std::views::zip(elements(),t.elements())){a+=b;}return*this;}matrix&operator-=(matrix const&t){for(auto[a,b]:std::views::zip(elements(),t.elements())){a-=b;}return*this;}matrix operator+(matrix const&t)const{return matrix(*this)+=t;}matrix operator-(matrix const&t)const{return matrix(*this)-=t;}matrix&operator*=(base t){for(auto&it:*this)it*=t;return*this;}matrix operator*(base t)const{return matrix(*this)*=t;}matrix&operator/=(base t){return*this*=base(1)/t;}matrix operator/(base t)const{return matrix(*this)/=t;}matrix&operator*=(matrix const&t){return*this=*this*t;}void read_transposed(){for(size_t j=0;j<m();j++){for(size_t i=0;i<n();i++){std::cin>>(*this)[i][j];}}}void read(){for(auto&it:*this){it.read();}}void print()const{for(auto const&it:*this){it.print();}}static matrix block_diagonal(big_vector<matrix>const&blocks){size_t n=0;for(auto&it:blocks){assert(it.n()==it.m());n+=it.n();}matrix res(n);n=0;for(auto&it:blocks){for(size_t i=0;i<it.n();i++){std::ranges::copy(it[i],begin(res[n+i])+n);}n+=it.n();}return res;}static matrix random(size_t n,size_t m){matrix res(n,m);std::ranges::generate(res,std::bind(vec_t::random,m));return res;}static matrix random(size_t n){return random(n,n);}static matrix eye(size_t n){matrix res(n);for(size_t i=0;i<n;i++){res[i][i]=1;}return res;}matrix operator|(matrix const&b)const{assert(n()==b.n());matrix res(n(),m()+b.m());for(size_t i=0;i<n();i++){res[i]=row(i)|b[i];}return res;}void assign_submatrix(auto viewx,auto viewy,matrix const&t){for(auto[a,b]:std::views::zip(*this|viewx,t)){std::ranges::copy(b,begin(a|viewy));}}auto submatrix(auto viewx,auto viewy)const{return*this|viewx|std::views::transform([viewy](auto const&y){return y|viewy;});}matrix T()const{matrix res(m(),n());for(size_t i=0;i<n();i++){for(size_t j=0;j<m();j++){res[j][i]=row(i)[j];}}return res;}matrix operator*(matrix const&b)const{assert(m()==b.n());matrix res(n(),b.m());for(size_t i=0;i<n();i++){for(size_t j=0;j<m();j++){res[i].add_scaled(b[j],row(i)[j]);}}return res.normalize();}vec_t apply(vec_t const&x)const{return(matrix(1,x)**this)[0];}matrix pow(uint64_t k)const{assert(n()==m());return bpow(*this,k,eye(n()));}matrix&normalize(){for(auto&it:*this){it.normalize();}return*this;}template<gauss_mode mode=normal>void eliminate(size_t i,size_t k){auto kinv=base(1)/row(i).normalize()[k];for(size_t j=(mode==normal)*i;j<n();j++){if(j!=i){row(j).add_scaled(row(i),-row(j).normalize(k)*kinv);}}}template<gauss_mode mode=normal>void eliminate(size_t i){row(i).normalize();for(size_t j=(mode==normal)*i;j<n();j++){if(j!=i){row(j).reduce_by(row(i));}}}template<gauss_mode mode=normal>matrix&gauss(){for(size_t i=0;i<n();i++){eliminate<mode>(i);}return normalize();}template<gauss_mode mode=normal>auto echelonize(size_t lim){return gauss<mode>().sort_classify(lim);}template<gauss_mode mode=normal>auto echelonize(){return echelonize<mode>(m());}size_t rank()const{if(n()>m()){return T().rank();}return size(matrix(*this).echelonize()[0]);}base det()const{assert(n()==m());matrix b=*this;b.echelonize();base res=1;for(size_t i=0;i<n();i++){res*=b[i][i];}return res;}std::pair<base,matrix>inv()const{assert(n()==m());matrix b=*this|eye(n());if(size(b.echelonize<reverse>(n())[0])<n()){return{0,{}};}base det=1;for(size_t i=0;i<n();i++){det*=b[i][i];b[i]*=base(1)/b[i][i];}return{det,b.submatrix(std::views::all,std::views::drop(n()))};}auto kernel()const{auto A=*this;auto[pivots,free]=A.template echelonize<reverse>();matrix sols(size(free),m());for(size_t j=0;j<size(pivots);j++){base scale=base(1)/A[j][pivots[j]];for(size_t i=0;i<size(free);i++){sols[i][pivots[j]]=A[j][free[i]]*scale;}}for(size_t i=0;i<size(free);i++){sols[i][free[i]]=-1;}return sols;}std::optional<std::array<matrix,2>>solve(matrix t)const{matrix sols=(*this|t).kernel();if(sols.n()<t.m()||matrix(sols.submatrix(std::views::drop(sols.n()-t.m()),std::views::drop(m())))!=-eye(t.m())){return std::nullopt;}else{return std::array{matrix(sols.submatrix(std::views::drop(sols.n()-t.m()),std::views::take(m()))),matrix(sols.submatrix(std::views::take(sols.n()-t.m()),std::views::take(m())))};}}auto sort_classify(size_t lim){size_t rk=0;big_vector<size_t>free,pivots;for(size_t j=0;j<lim;j++){for(size_t i=rk+1;i<n()&&row(rk)[j]==base(0);i++){if(row(i)[j]!=base(0)){std::swap(row(i),row(rk));row(rk)=-row(rk);}}if(rk<n()&&row(rk)[j]!=base(0)){pivots.push_back(j);rk++;}else{free.push_back(j);}}return std::array{pivots,free};}};template<typename base_t>auto operator*(base_t t,matrix<base_t>const&A){return A*t;}}
1212
#pragma GCC pop_options
1313
#endif

cp-algo/min/linalg/vector.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
#include <iterator>
1313
#include <cassert>
1414
#include <ranges>
15-
CP_ALGO_SIMD_PRAGMA_PUSHnamespace cp_algo::linalg{template<typename base,class Alloc=big_alloc<base>>struct vec:std::basic_string<base,std::char_traits<base>,Alloc>{using Base=std::basic_string<base,std::char_traits<base>,Alloc>;using Base::Base;vec(Base const&t):Base(t){}vec(Base&&t):Base(std::move(t)){}vec(size_t n):Base(n,base()){}vec(auto&&r):Base(std::from_range,r){}static vec ei(size_t n,size_t i){vec res(n);res[i]=1;return res;}auto operator-()const{return*this|std::views::transform([](auto x){return-x;});}auto operator*(base t)const{return*this|std::views::transform([t](auto x){return x*t;});}auto operator*=(base t){for(auto&it:*this){it*=t;}return*this;}virtual void add_scaled(vec const&b,base scale,size_t i=0){if(scale!=base(0)){for(;i<size(*this);i++){(*this)[i]+=scale*b[i];}}}virtual vec const&normalize(){return static_cast<vec&>(*this);}virtual base normalize(size_t i){return(*this)[i];}void read(){for(auto&it:*this){std::cin>>it;}}void print()const{for(auto&it:*this){std::cout<<it<<" ";}std::cout<<"\n";}static vec random(size_t n){vec res(n);std::ranges::generate(res,random::rng);return res;}vec operator|(vec const&t)const{return std::views::join(std::array{std::views::all(*this),std::views::all(t)});}std::pair<size_t,base>find_pivot(){if(pivot==size_t(-1)){pivot=0;while(pivot<size(*this)&&normalize(pivot)==base(0)){pivot++;}if(pivot<size(*this)){pivot_inv=base(1)/(*this)[pivot];}}return{pivot,pivot_inv};}void reduce_by(vec&t){auto[pivot,pinv]=t.find_pivot();if(pivot<size(*this)){add_scaled(t,-normalize(pivot)*pinv,pivot);}}private:size_t pivot=-1;base pivot_inv;};template<math::modint_type base,class Alloc=big_alloc<base>>struct modint_vec:vec<base,Alloc>{using Base=vec<base,Alloc>;using Base::Base;modint_vec(Base const&t):Base(t){}modint_vec(Base&&t):Base(std::move(t)){}void add_scaled(Base const&b,base scale,size_t i=0)override{static_assert(base::bits>=64,"Only wide modint types for linalg");if(scale!=base(0)){assert(Base::size()==b.size());size_t n=size(*this);u64x4 scaler=u64x4()+scale.getr();if(is_aligned(&(*this)[0])&&is_aligned(&b[0]))for(i-=i%4;i+3<n;i+=4){auto&ai=vector_cast<u64x4>((*this)[i]);auto bi=vector_cast<u64x4 const>(b[i]);
15+
CP_ALGO_SIMD_PRAGMA_PUSHnamespace cp_algo::linalg{template<typename base,class Alloc=big_alloc<base>>struct vec:std::basic_string<base,std::char_traits<base>,Alloc>{using Base=std::basic_string<base,std::char_traits<base>,Alloc>;using Base::Base;vec(Base const&t):Base(t){}vec(Base&&t):Base(std::move(t)){}vec(size_t n):Base(n,base()){}vec(auto&&r):Base(r.begin(),r.end()){}static vec ei(size_t n,size_t i){vec res(n);res[i]=1;return res;}auto operator-()const{return*this|std::views::transform([](auto x){return-x;});}auto operator*(base t)const{return*this|std::views::transform([t](auto x){return x*t;});}auto operator*=(base t){for(auto&it:*this){it*=t;}return*this;}virtual void add_scaled(vec const&b,base scale,size_t i=0){if(scale!=base(0)){for(;i<size(*this);i++){(*this)[i]+=scale*b[i];}}}virtual vec const&normalize(){return static_cast<vec&>(*this);}virtual base normalize(size_t i){return(*this)[i];}void read(){for(auto&it:*this){std::cin>>it;}}void print()const{for(auto&it:*this){std::cout<<it<<" ";}std::cout<<"\n";}static vec random(size_t n){vec res(n);std::ranges::generate(res,random::rng);return res;}vec operator|(vec const&t)const{return std::views::join(std::array{std::views::all(*this),std::views::all(t)});}std::pair<size_t,base>find_pivot(){if(pivot==size_t(-1)){pivot=0;while(pivot<size(*this)&&normalize(pivot)==base(0)){pivot++;}if(pivot<size(*this)){pivot_inv=base(1)/(*this)[pivot];}}return{pivot,pivot_inv};}void reduce_by(vec&t){auto[pivot,pinv]=t.find_pivot();if(pivot<size(*this)){add_scaled(t,-normalize(pivot)*pinv,pivot);}}private:size_t pivot=-1;base pivot_inv;};template<math::modint_type base,class Alloc=big_alloc<base>>struct modint_vec:vec<base,Alloc>{using Base=vec<base,Alloc>;using Base::Base;modint_vec(Base const&t):Base(t){}modint_vec(Base&&t):Base(std::move(t)){}void add_scaled(Base const&b,base scale,size_t i=0)override{static_assert(base::bits>=64,"Only wide modint types for linalg");if(scale!=base(0)){assert(Base::size()==b.size());size_t n=size(*this);u64x4 scaler=u64x4()+scale.getr();if(is_aligned(&(*this)[0])&&is_aligned(&b[0]))for(i-=i%4;i+3<n;i+=4){auto&ai=vector_cast<u64x4>((*this)[i]);auto bi=vector_cast<u64x4 const>(b[i]);
1616
#ifdef __AVX2__
1717
ai+=u64x4(_mm256_mul_epu32(__m256i(scaler),__m256i(bi)));
1818
#else

0 commit comments

Comments
 (0)