Skip to content

Commit 0ca8d5a

Browse files
chore: update minified library versions
1 parent 6cfb439 commit 0ca8d5a

File tree

3 files changed

+3
-3
lines changed

3 files changed

+3
-3
lines changed

cp-algo/min/math/bigint.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@
33
#include "../util/big_alloc.hpp"
44
#include "../math/fft_simple.hpp"
55
#include <bits/stdc++.h>
6-
namespace cp_algo::math{enum base_v{x10=uint64_t(1e16),x16=uint64_t(1ull<<60)};template<base_v base=x10>struct bigint{static constexpr uint16_t digit_length=base==x10?16:15;static constexpr uint16_t sub_base=base==x10?10:16;static constexpr uint32_t meta_base=base==x10?uint32_t(1e4):uint32_t(1<<15);big_vector<uint64_t>digits;bool negative;bigint(){}bigint&normalize(){while(!empty(digits)&&digits.back()==0){digits.pop_back();}if(digits.empty()){negative=false;}return*this;}bigint&negate(){negative^=1;return*this;}bigint operator-(){return bigint(*this).negate();}bigint&operator-=(const bigint&other){if(negative!=other.negative){return(negate()+=other).negate().normalize();}digits.resize(std::max(size(digits),size(other.digits)));bool carry=false;auto d_ptr=std::assume_aligned<32>(digits.data());auto o_ptr=std::assume_aligned<32>(other.digits.data());size_t N=size(other.digits);size_t i=0;for(;i<N;i++){d_ptr[i]-=o_ptr[i]+carry;carry=d_ptr[i]>=base;d_ptr[i]+=carry?uint64_t(base):0;}if(carry){N=size(digits);for(;i<N&&d_ptr[i]==0;i++){d_ptr[i]=base-1;}if(i<N){d_ptr[i]--;}else{d_ptr[0]--;for(i=0;i<N;i++){d_ptr[i]=base-d_ptr[i]-1;}negate();}}return normalize();}bigint&operator+=(const bigint&other){if(negative!=other.negative){return(negate()-=other).negate().normalize();}digits.resize(std::max(size(digits),size(other.digits)));bool carry=false;auto d_ptr=std::assume_aligned<32>(digits.data());auto o_ptr=std::assume_aligned<32>(other.digits.data());size_t N=size(other.digits);size_t i=0;for(;i<N;i++){d_ptr[i]+=o_ptr[i]+carry;carry=d_ptr[i]>=base;d_ptr[i]-=carry?uint64_t(base):0;}if(carry){N=size(digits);for(;i<N&&d_ptr[i]==uint64_t(base)-1;i++){d_ptr[i]=0;}if(i<N){d_ptr[i]++;}else{digits.push_back(1);}}return*this;}bigint(std::span<char>s):negative(false){if(!empty(s)&&s[0]=='-'){negative=true;s=s.subspan(1);}size_t len=size(s);assert(len>0);size_t num_digits=(len+digit_length-1)/digit_length;digits.resize(num_digits);size_t i=len;for(size_t j=0;j<num_digits-1;j++){std::from_chars(s.data()+i-digit_length,s.data()+i,digits[j],sub_base);i-=digit_length;}std::from_chars(s.data(),s.data()+i,digits.back(),sub_base);normalize();}bigint operator+(const bigint&other)const{return bigint(*this)+=other;}bigint operator-(const bigint&other)const{return bigint(*this)-=other;}void to_metabase(){auto N=ssize(digits);digits.resize(4*N);for(auto i=N-1;i>=0;i--){uint64_t val=digits[i];digits[4*i]=val%meta_base;val/=meta_base;digits[4*i+1]=val%meta_base;val/=meta_base;digits[4*i+2]=val%meta_base;val/=meta_base;digits[4*i+3]=val;}}void from_metabase(){auto N=(ssize(digits)+3)/4;digits.resize(4*N);uint64_t carry=0;for(int i=0;i<N;i++){__uint128_t val=digits[4*i+3];val=val*meta_base+digits[4*i+2];val=val*meta_base+digits[4*i+1];val=val*meta_base+digits[4*i];val+=carry;digits[i]=uint64_t(val%base);carry=uint64_t(val/base);}digits.resize(N);while(carry){digits.push_back(carry%base);carry/=base;}}bigint&mul_inplace(auto&&other){size_t n=size(digits);size_t m=size(other.digits);negative^=other.negative;if(std::min(n,m)<128){big_vector<uint64_t>result(n+m);for(size_t i=0;i<n;i++){uint64_t carry=0;for(size_t j=0;j<m||carry;j++){__uint128_t cur=result[i+j]+carry;if(j<m){cur+=__uint128_t(digits[i])*other.digits[j];}result[i+j]=uint64_t(cur%base);carry=uint64_t(cur/base);}}digits=std::move(result);return normalize();}to_metabase();other.to_metabase();fft::conv_simple(digits,other.digits);from_metabase();return normalize();}bigint&operator*=(bigint const&other){return mul_inplace(bigint(other));}bigint operator*(const bigint&other)const{return bigint(*this).mul_inplace(bigint(other));}};template<base_v base>decltype(std::cin)&operator>>(decltype(std::cin)&in,cp_algo::math::bigint<base>&x){std::string s;in>>s;x={s};return in;}template<base_v base>decltype(std::cout)&operator<<(decltype(std::cout)&out,cp_algo::math::bigint<base>const&x){if(x.negative){out<<'-';}if(empty(x.digits)){return out<<'0';}char buf[20];auto[ptr,ec]=std::to_chars(buf,buf+sizeof(buf),x.digits.back(),bigint<base>::sub_base);if constexpr(base==x16){std::ranges::transform(buf,buf,toupper);}out<<std::string_view(buf,ptr-buf);for(auto d:x.digits|std::views::reverse|std::views::drop(1)){auto[ptr,ec]=std::to_chars(buf,buf+sizeof(buf),d,bigint<base>::sub_base);if constexpr(base==x16){std::ranges::transform(buf,buf,toupper);}auto len=ptr-buf;out<<std::string(bigint<base>::digit_length-len,'0');out<<std::string_view(buf,len);}return out;}}
6+
namespace cp_algo::math{enum base_v{x10=uint64_t(1e16),x16=uint64_t(1ull<<60)};template<base_v base=x10>struct bigint{static constexpr uint16_t digit_length=base==x10?16:15;static constexpr uint16_t sub_base=base==x10?10:16;static constexpr uint32_t meta_base=base==x10?uint32_t(1e4):uint32_t(1<<15);big_basic_string<uint64_t>digits;bool negative;bigint(){}bigint&normalize(){while(!empty(digits)&&digits.back()==0){digits.pop_back();}if(digits.empty()){negative=false;}return*this;}bigint&negate(){negative^=1;return*this;}bigint operator-(){return bigint(*this).negate();}bigint&operator-=(const bigint&other){if(negative!=other.negative){return(negate()+=other).negate().normalize();}digits.resize(std::max(size(digits),size(other.digits)));bool carry=false;auto d_ptr=std::assume_aligned<32>(digits.data());auto o_ptr=std::assume_aligned<32>(other.digits.data());size_t N=size(other.digits);size_t i=0;for(;i<N;i++){d_ptr[i]-=o_ptr[i]+carry;carry=d_ptr[i]>=base;d_ptr[i]+=carry?uint64_t(base):0;}if(carry){N=size(digits);for(;i<N&&d_ptr[i]==0;i++){d_ptr[i]=base-1;}if(i<N){d_ptr[i]--;}else{d_ptr[0]--;for(i=0;i<N;i++){d_ptr[i]=base-d_ptr[i]-1;}negate();}}return normalize();}bigint&operator+=(const bigint&other){if(negative!=other.negative){return(negate()-=other).negate().normalize();}digits.resize(std::max(size(digits),size(other.digits)));bool carry=false;auto d_ptr=std::assume_aligned<32>(digits.data());auto o_ptr=std::assume_aligned<32>(other.digits.data());size_t N=size(other.digits);size_t i=0;for(;i<N;i++){d_ptr[i]+=o_ptr[i]+carry;carry=d_ptr[i]>=base;d_ptr[i]-=carry?uint64_t(base):0;}if(carry){N=size(digits);for(;i<N&&d_ptr[i]==uint64_t(base)-1;i++){d_ptr[i]=0;}if(i<N){d_ptr[i]++;}else{digits.push_back(1);}}return*this;}bigint(int64_t x){negative=x<0;x=negative?-x:x;digits=x?big_basic_string<uint64_t>{uint64_t(x)}:big_basic_string<uint64_t>{};}bigint(std::span<char>s):negative(false){if(size(s)<digit_length){int64_t val=0;std::from_chars(s.data(),s.data()+size(s),val,sub_base);*this=bigint(val);return;}if(!empty(s)&&s[0]=='-'){negative=true;s=s.subspan(1);}size_t len=size(s);assert(len>0);size_t num_digits=(len+digit_length-1)/digit_length;digits.resize(num_digits);size_t i=len;for(size_t j=0;j<num_digits-1;j++){std::from_chars(s.data()+i-digit_length,s.data()+i,digits[j],sub_base);i-=digit_length;}std::from_chars(s.data(),s.data()+i,digits.back(),sub_base);normalize();}bigint operator+(const bigint&other)const{return bigint(*this)+=other;}bigint operator-(const bigint&other)const{return bigint(*this)-=other;}void to_metabase(){auto N=ssize(digits);digits.resize(4*N);for(auto i=N-1;i>=0;i--){uint64_t val=digits[i];digits[4*i]=val%meta_base;val/=meta_base;digits[4*i+1]=val%meta_base;val/=meta_base;digits[4*i+2]=val%meta_base;val/=meta_base;digits[4*i+3]=val;}}void from_metabase(){auto N=(ssize(digits)+3)/4;digits.resize(4*N);uint64_t carry=0;for(int i=0;i<N;i++){__uint128_t val=digits[4*i+3];val=val*meta_base+digits[4*i+2];val=val*meta_base+digits[4*i+1];val=val*meta_base+digits[4*i];val+=carry;digits[i]=uint64_t(val%base);carry=uint64_t(val/base);}digits.resize(N);while(carry){digits.push_back(carry%base);carry/=base;}}bigint&operator*=(int64_t other){if(other<0){negative^=1;other=-other;}if(other==0){return*this=bigint(0);}else if(other==1){return*this;}uint64_t carry=0;for(auto&d:digits){__uint128_t val=__uint128_t(d)*other+carry;d=uint64_t(val%base);carry=uint64_t(val/base);}if(carry){digits.push_back(carry%base);carry/=base;}return*this;}bigint operator*(int64_t other)const{return bigint(*this)*=other;}friend bigint operator*(int64_t lhs,const bigint&rhs){return bigint(rhs)*=lhs;}bigint&mul_inplace(auto&&other){negative^=other.negative;auto n=size(digits),m=size(other.digits);if(n<m){std::swap(n,m);std::swap(digits,other.digits);}if(m<=1){return*this*=int64_t(m==0?0:other.digits[0]);}to_metabase();other.to_metabase();fft::conv_simple(digits,other.digits);from_metabase();return normalize();}bigint&operator*=(bigint const&other){return mul_inplace(bigint(other));}bigint operator*(const bigint&other)const{return bigint(*this).mul_inplace(bigint(other));}};template<base_v base>decltype(std::cin)&operator>>(decltype(std::cin)&in,cp_algo::math::bigint<base>&x){std::string s;in>>s;x={s};return in;}template<base_v base>decltype(std::cout)&operator<<(decltype(std::cout)&out,cp_algo::math::bigint<base>const&x){char buf[16];if(size(x.digits)<=1){if(x.negative){out<<'-';}if constexpr(base==x16){auto[ptr,ec]=std::to_chars(buf,buf+sizeof(buf),empty(x.digits)?0:x.digits[0],bigint<base>::sub_base);std::ranges::transform(buf,buf,toupper);return out<<std::string_view(buf,ptr-buf);}else{return out<<(empty(x.digits)?0:x.digits[0]);}}if(x.negative){out<<'-';}if(empty(x.digits)){return out<<'0';}auto[ptr,ec]=std::to_chars(buf,buf+sizeof(buf),x.digits.back(),bigint<base>::sub_base);if constexpr(base==x16){std::ranges::transform(buf,buf,toupper);}out<<std::string_view(buf,ptr-buf);for(auto d:x.digits|std::views::reverse|std::views::drop(1)){auto[ptr,ec]=std::to_chars(buf,buf+sizeof(buf),d,bigint<base>::sub_base);if constexpr(base==x16){std::ranges::transform(buf,buf,toupper);}auto len=ptr-buf;out<<std::string(bigint<base>::digit_length-len,'0');out<<std::string_view(buf,len);}return out;}}
77
#endif

cp-algo/min/math/fft64.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@
33
#include "../random/rng.hpp"
44
#include "../math/common.hpp"
55
#include "../math/cvector.hpp"
6-
CP_ALGO_SIMD_PRAGMA_PUSHnamespace cp_algo::math::fft{struct dft64{big_vector<cp_algo::math::fft::cvector>cv;static uint64_t factor,ifactor;static bool _init;static void init(){if(_init)return;_init=true;factor=random::rng();if(factor%2==0){factor++;}ifactor=inv2(factor);}dft64(auto const&a,size_t n):cv(4,n){init();uint64_t cur=1,step=bpow(factor,n);for(size_t i=0;i<std::min(std::size(a),n);i++){auto split=[&](size_t i,uint64_t mul)->std::array<int16_t,4>{uint64_t x=i<std::size(a)?a[i]*mul:0;std::array<int16_t,4>res;for(int z=0;z<4;z++){res[z]=int16_t(x);x=(x>>16)+(res[z]<0);}return res;};auto re=split(i,cur);auto im=split(n+i,cur*step);for(int z=0;z<4;z++){real(cv[z].at(i))[i%4]=re[z];imag(cv[z].at(i))[i%4]=im[z];}cur*=factor;}checkpoint("dft64 init");for(auto&x:cv){x.fft();}}static void do_dot_iter(point rt,std::array<vpoint,4>&B,std::array<vpoint,4>const&A,std::array<vpoint,4>&C){for(size_t k=0;k<4;k++){for(size_t i=0;i<=k;i++){C[k]+=A[i]*B[k-i];}}for(size_t k=0;k<4;k++){real(B[k])=rotate_right(real(B[k]));imag(B[k])=rotate_right(imag(B[k]));auto bx=real(B[k])[0],by=imag(B[k])[0];real(B[k])[0]=bx*real(rt)-by*imag(rt);imag(B[k])[0]=bx*imag(rt)+by*real(rt);}}void dot(dft64 const&t){size_t N=cv[0].size();cvector::exec_on_evals<1>(N/flen,[&](size_t k,point rt)__attribute__((always_inline)){k*=flen;auto[A0x,A0y]=cv[0].at(k);auto[A1x,A1y]=cv[1].at(k);auto[A2x,A2y]=cv[2].at(k);auto[A3x,A3y]=cv[3].at(k);std::array B={t.cv[0].at(k),t.cv[1].at(k),t.cv[2].at(k),t.cv[3].at(k)};std::array<vpoint,4>C={vz,vz,vz,vz};for(size_t i=0;i<flen;i++){std::array A={vpoint{vz+A0x[i],vz+A0y[i]},vpoint{vz+A1x[i],vz+A1y[i]},vpoint{vz+A2x[i],vz+A2y[i]},vpoint{vz+A3x[i],vz+A3y[i]}};do_dot_iter(rt,B,A,C);}cv[0].at(k)=C[0];cv[1].at(k)=C[1];cv[2].at(k)=C[2];cv[3].at(k)=C[3];});checkpoint("dot");for(auto&x:cv){x.ifft();}}void recover_mod(auto&res,size_t k){size_t n=cv[0].size();uint64_t cur=1,step=bpow(ifactor,n);for(size_t i=0;i<std::min(k,n);i++){std::array re={real(cv[0].get(i)),real(cv[1].get(i)),real(cv[2].get(i)),real(cv[3].get(i))};std::array im={imag(cv[0].get(i)),imag(cv[1].get(i)),imag(cv[2].get(i)),imag(cv[3].get(i))};auto set_i=[&](size_t i,auto&x,auto mul){if(i>=k)return;res[i]=llround(x[0])+(llround(x[1])<<16)+(llround(x[2])<<32)+(llround(x[3])<<48);res[i]*=mul;};set_i(i,re,cur);set_i(n+i,im,cur*step);cur*=ifactor;}cp_algo::checkpoint("recover mod");}};uint64_t dft64::factor=1,dft64::ifactor=1;bool dft64::_init=false;void conv64(auto&a,auto const&b){size_t n=a.size(),m=b.size();size_t N=std::max(flen,std::bit_ceil(n+m-1)/2);dft64 A(a,N),B(b,N);A.dot(B);a.resize(n+m-1);A.recover_mod(a,n+m-1);}}
6+
CP_ALGO_SIMD_PRAGMA_PUSHnamespace cp_algo::math::fft{struct dft64{big_vector<cp_algo::math::fft::cvector>cv;static uint64_t factor,ifactor;static bool _init;static void init(){if(_init)return;_init=true;factor=random::rng();if(factor%2==0){factor++;}ifactor=inv2(factor);}dft64(auto const&a,size_t n):cv(4,n){init();uint64_t cur=1,step=bpow(factor,n);for(size_t i=0;i<std::min(std::size(a),n);i++){auto split=[&](size_t i,uint64_t mul)->std::array<int16_t,4>{uint64_t x=i<std::size(a)?a[i]*mul:0;std::array<int16_t,4>res;for(int z=0;z<4;z++){res[z]=int16_t(x);x=(x>>16)+(res[z]<0);}return res;};auto re=split(i,cur);auto im=split(n+i,cur*step);for(int z=0;z<4;z++){real(cv[z].at(i))[i%4]=re[z];imag(cv[z].at(i))[i%4]=im[z];}cur*=factor;}checkpoint("dft64 init");for(auto&x:cv){x.fft();}}static void do_dot_iter(point rt,std::array<vpoint,4>&B,std::array<vpoint,4>const&A,std::array<vpoint,4>&C){for(size_t k=0;k<4;k++){for(size_t i=0;i<=k;i++){C[k]+=A[i]*B[k-i];}}for(size_t k=0;k<4;k++){real(B[k])=rotate_right(real(B[k]));imag(B[k])=rotate_right(imag(B[k]));auto bx=real(B[k])[0],by=imag(B[k])[0];real(B[k])[0]=bx*real(rt)-by*imag(rt);imag(B[k])[0]=bx*imag(rt)+by*real(rt);}}void dot(dft64 const&t){size_t N=cv[0].size();cvector::exec_on_evals<1>(N/flen,[&](size_t k,point rt)__attribute__((always_inline)){k*=flen;auto[A0x,A0y]=cv[0].at(k);auto[A1x,A1y]=cv[1].at(k);auto[A2x,A2y]=cv[2].at(k);auto[A3x,A3y]=cv[3].at(k);std::array B={t.cv[0].at(k),t.cv[1].at(k),t.cv[2].at(k),t.cv[3].at(k)};std::array<vpoint,4>C={vz,vz,vz,vz};for(size_t i=0;i<flen;i++){std::array A={vpoint{vz+A0x[i],vz+A0y[i]},vpoint{vz+A1x[i],vz+A1y[i]},vpoint{vz+A2x[i],vz+A2y[i]},vpoint{vz+A3x[i],vz+A3y[i]}};do_dot_iter(rt,B,A,C);}cv[0].at(k)=C[0];cv[1].at(k)=C[1];cv[2].at(k)=C[2];cv[3].at(k)=C[3];});checkpoint("dot");for(auto&x:cv){x.ifft();}}void recover_mod(auto&res,size_t k){size_t n=cv[0].size();uint64_t cur=1,step=bpow(ifactor,n);for(size_t i=0;i<std::min(k,n);i++){std::array re={real(cv[0].get(i)),real(cv[1].get(i)),real(cv[2].get(i)),real(cv[3].get(i))};std::array im={imag(cv[0].get(i)),imag(cv[1].get(i)),imag(cv[2].get(i)),imag(cv[3].get(i))};auto set_i=[&](size_t i,auto&x,auto mul){if(i>=k)return;res[i]=llround(x[0])+(llround(x[1])<<16)+(llround(x[2])<<32)+(llround(x[3])<<48);res[i]*=mul;};set_i(i,re,cur);set_i(n+i,im,cur*step);cur*=ifactor;}cp_algo::checkpoint("recover mod");}};uint64_t dft64::factor=1,dft64::ifactor=1;bool dft64::_init=false;void conv64(auto&a,auto const&b){size_t n=a.size(),m=b.size();if(n==0||m==0){a.clear();return;}size_t N=std::max(flen,std::bit_ceil(n+m-1)/2);dft64 A(a,N),B(b,N);A.dot(B);a.resize(n+m-1);A.recover_mod(a,n+m-1);}}
77
#pragma GCC pop_options
88
#endif

cp-algo/min/math/fft_simple.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@
33
#include "../random/rng.hpp"
44
#include "../math/common.hpp"
55
#include "../math/cvector.hpp"
6-
CP_ALGO_SIMD_PRAGMA_PUSHnamespace cp_algo::math::fft{struct dft_simple{cp_algo::math::fft::cvector cv;dft_simple(auto const&a,size_t n):cv(n){for(size_t i=0;i<std::min(std::size(a),n);i++){real(cv.at(i))[i%4]=ftype(a[i]);imag(cv.at(i))[i%4]=ftype(i+n<std::size(a)?a[i+n]:0);}checkpoint("dft64 init");cv.fft();}void dot(dft_simple const&t){cv.dot(t.cv);}void recover_mod(auto&res,size_t k){cv.ifft();size_t n=cv.size();for(size_t i=0;i<std::min(k,n);i++){res[i]=llround(real(cv.get(i)));}for(size_t i=n;i<k;i++){res[i]=llround(imag(cv.get(i-n)));}cp_algo::checkpoint("recover mod");}};void conv_simple(auto&a,auto const&b){size_t n=a.size(),m=b.size();size_t N=std::max(flen,std::bit_ceil(n+m-1)/2);dft_simple A(a,N),B(b,N);A.dot(B);a.resize(n+m-1);A.recover_mod(a,n+m-1);}}
6+
CP_ALGO_SIMD_PRAGMA_PUSHnamespace cp_algo::math::fft{struct dft_simple{cp_algo::math::fft::cvector cv;dft_simple(auto const&a,size_t n):cv(n){for(size_t i=0;i<std::min(std::size(a),n);i++){real(cv.at(i))[i%4]=ftype(a[i]);imag(cv.at(i))[i%4]=ftype(i+n<std::size(a)?a[i+n]:0);}checkpoint("dft64 init");cv.fft();}void dot(dft_simple const&t){cv.dot(t.cv);}void recover_mod(auto&res,size_t k){cv.ifft();size_t n=cv.size();for(size_t i=0;i<std::min(k,n);i++){res[i]=llround(real(cv.get(i)));}for(size_t i=n;i<k;i++){res[i]=llround(imag(cv.get(i-n)));}cp_algo::checkpoint("recover mod");}};void conv_simple(auto&a,auto const&b){if(empty(a)||empty(b)){a.clear();return;}size_t n=a.size(),m=b.size();size_t N=std::max(flen,std::bit_ceil(n+m-1)/2);dft_simple A(a,N),B(b,N);A.dot(B);a.resize(n+m-1);A.recover_mod(a,n+m-1);}}
77
#pragma GCC pop_options
88
#endif

0 commit comments

Comments
 (0)