Skip to content

Commit a9a58e7

Browse files
chore: update minified library versions
1 parent 548e409 commit a9a58e7

File tree

2 files changed

+3
-3
lines changed

2 files changed

+3
-3
lines changed

cp-algo/min/math/sieve.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
#include <span>
1111
#include <algorithm>
1212
#include <cassert>
13-
CP_ALGO_BIT_PRAGMA_PUSHnamespace cp_algo::math{using cp_algo::structures::dynamic_bit_array;using cp_algo::structures::bit_array;constexpr uint32_t period=210;constexpr uint32_t coprime=48;constexpr auto coprime210=[](auto x){return x%2&&x%3&&x%5&&x%7;};constexpr auto res210=[](){std::array<uint8_t,coprime>res;int idx=0;for(uint8_t i=1;i<period;i+=2){if(coprime210(i)){res[idx++]=i;}}return res;}();constexpr auto state210=[](){std::array<uint8_t,period>state;uint8_t idx=0;for(uint8_t i=0;i<period;i++){state[i]=idx;idx+=coprime210(i);}return state;}();constexpr auto add210=[](){std::array<uint8_t,period>add;for(uint8_t i=0;i<period;i++){add[i]=1;while(!coprime210(i+add[i])){add[i]++;}}return add;}();constexpr auto gap210=[](){std::array<uint8_t,coprime>gap;for(uint8_t i=0;i<coprime;i++){gap[i]=add210[res210[i]];}return gap;}();constexpr uint32_t to_ord(uint32_t x){return(x/period)*coprime+state210[x%period];}constexpr uint32_t to_val(uint32_t x){return(x/coprime)*period+res210[x%coprime];}constexpr size_t sqrt_threshold=1<<15;constexpr auto sqrt_prime_bits=[](){const int size=sqrt_threshold/4;bit_array<size>prime;prime.set_all();prime.reset(to_ord(1));for(uint32_t i=11;to_ord(i*i)<size;i+=add210[i%period]){if(prime[to_ord(i)]){for(uint32_t k=i;to_ord(i*k)<size;k+=add210[k%period]){prime.reset(to_ord(i*k));}}}return prime;}();constexpr size_t num_primes=[](){size_t cnt=0;for(uint32_t i=11;i<sqrt_threshold;i+=add210[i%period]){cnt+=sqrt_prime_bits[to_ord(i)];}return cnt;}();constexpr auto sqrt_primes=[](){std::array<uint32_t,num_primes>primes;size_t j=0;for(uint32_t i=11;i<sqrt_threshold;i+=add210[i%period]){if(sqrt_prime_bits[to_ord(i)]){primes[j++]=i;}}return primes;}();constexpr size_t max_wheel_size=1<<21;struct wheel_t{dynamic_bit_array mask;uint32_t product;};auto make_wheel(big_vector<uint32_t>primes,uint32_t product){assert(product%(period*dynamic_bit_array::width)==0);wheel_t wheel;wheel.product=product;wheel.mask.resize(product/period*coprime);wheel.mask.set_all();for(auto p:primes){for(uint32_t k=1;p*k<product;k+=add210[k%period]){wheel.mask.reset(to_ord(p*k));}}return wheel;}constexpr uint32_t wheel_threshold=500;size_t medium_primes_begin;const auto wheels=[](){uint32_t product=period*dynamic_bit_array::width;big_vector<uint32_t>current;big_vector<wheel_t>wheels;for(size_t i=0;i<size(sqrt_primes);i++){uint32_t p=sqrt_primes[i];if(product*p>max_wheel_size){wheels.push_back(make_wheel(current,product));current={p};product=period*dynamic_bit_array::width*p;if(product>max_wheel_size||p>wheel_threshold){medium_primes_begin=i;checkpoint("make wheels");return wheels;}}else{current.push_back(p);product*=p;}}assert(false);}();const auto[ord_step,step_sum]=[](){big_vector<std::array<uint32_t,2*coprime>>ord_steps(num_primes);big_vector<uint32_t>sums(num_primes);for(uint32_t i=0;i<size(sqrt_primes);i++){auto p=sqrt_primes[i];for(uint32_t j=0;j<coprime;j++){ord_steps[i][j]=to_ord(p*(res210[j]+gap210[j]))-to_ord(p*res210[j]);}sums[i]=std::ranges::fold_left(ord_steps[i],0u,std::plus{});for(uint32_t j=0;j<coprime;j++){ord_steps[i][j+coprime]=ord_steps[i][j];}}return std::pair{ord_steps,sums};}();void sieve_dense(auto&prime,uint32_t l,uint32_t r,wheel_t const&wheel){if(l>=r)return;const auto width=(uint32_t)dynamic_bit_array::width;uint32_t wl=l/width;uint32_t wr=(r+width-1)/width;uint32_t N=(uint32_t)wheel.mask.words;for(uint32_t i=wl;i<wr;i+=N){auto block=std::min(N,wr-i);for(uint32_t j=0;j<block;j++){prime.word(i+j)&=wheel.mask.word(j);}}}template<class BitArray>void sieve210(BitArray&prime,uint32_t l,uint32_t r,size_t i,int state){while(l+step_sum[i]<=r){
13+
CP_ALGO_BIT_PRAGMA_PUSHnamespace cp_algo::math{using cp_algo::structures::dynamic_bit_array;using cp_algo::structures::bit_array;constexpr uint32_t period=210;constexpr uint32_t coprime=48;constexpr auto coprime210=[](auto x){return x%2&&x%3&&x%5&&x%7;};constexpr auto res210=[](){std::array<uint8_t,coprime>res;int idx=0;for(uint8_t i=1;i<period;i+=2){if(coprime210(i)){res[idx++]=i;}}return res;}();constexpr auto state210=[](){std::array<uint8_t,period>state;uint8_t idx=0;for(uint8_t i=0;i<period;i++){state[i]=idx;idx+=coprime210(i);}return state;}();constexpr auto add210=[](){std::array<uint8_t,period>add;for(uint8_t i=0;i<period;i++){add[i]=1;while(!coprime210(i+add[i])){add[i]++;}}return add;}();constexpr auto gap210=[](){std::array<uint8_t,coprime>gap;for(uint8_t i=0;i<coprime;i++){gap[i]=add210[res210[i]];}return gap;}();constexpr uint32_t to_ord(uint32_t x){return(x/period)*coprime+state210[x%period];}constexpr uint32_t to_val(uint32_t x){return(x/coprime)*period+res210[x%coprime];}constexpr size_t sqrt_threshold=1<<15;constexpr auto sqrt_prime_bits=[](){const int size=sqrt_threshold/4;bit_array<size>prime;prime.set_all();prime.reset(to_ord(1));for(uint32_t i=11;to_ord(i*i)<size;i+=add210[i%period]){if(prime[to_ord(i)]){for(uint32_t k=i;to_ord(i*k)<size;k+=add210[k%period]){prime.reset(to_ord(i*k));}}}return prime;}();constexpr size_t num_primes=[](){size_t cnt=0;for(uint32_t i=11;i<sqrt_threshold;i+=add210[i%period]){cnt+=sqrt_prime_bits[to_ord(i)];}return cnt;}();constexpr auto sqrt_primes=[](){std::array<uint32_t,num_primes>primes;size_t j=0;for(uint32_t i=11;i<sqrt_threshold;i+=add210[i%period]){if(sqrt_prime_bits[to_ord(i)]){primes[j++]=i;}}return primes;}();constexpr size_t max_wheel_size=1<<21;struct wheel_t{dynamic_bit_array mask;uint32_t product;};constexpr auto make_wheel(big_vector<uint32_t>primes,uint32_t product){assert(product%(period*dynamic_bit_array::width)==0);wheel_t wheel;wheel.product=product;wheel.mask.resize(product/period*coprime);wheel.mask.set_all();for(auto p:primes){for(uint32_t k=1;p*k<product;k+=add210[k%period]){wheel.mask.reset(to_ord(p*k));}}return wheel;}constexpr void sieve_dense(auto&prime,uint32_t l,uint32_t r,wheel_t const&wheel){if(l>=r)return;const uint32_t width=(uint32_t)dynamic_bit_array::width;uint32_t wl=l/width;uint32_t wr=(r+width-1)/width;uint32_t N=(uint32_t)wheel.mask.words;for(uint32_t i=wl;i<wr;i+=N){uint32_t block=std::min(N,wr-i);uint32_t j=0;for(;j+4<=block;j+=4){auto&p_vec=vector_cast<u64x4>(prime.word(i+j));auto m_vec=vector_cast<const u64x4>(wheel.mask.word(j));p_vec&=m_vec;}for(;j<block;j++){prime.word(i+j)&=wheel.mask.word(j);}}}template<class BitArray>constexpr void sieve210(BitArray&prime,uint32_t l,uint32_t r,size_t i,int state){static const auto[ord_step,step_sum]=[](){big_vector<std::array<uint32_t,2*coprime>>ord_steps(num_primes);big_vector<uint32_t>sums(num_primes);for(uint32_t i=0;i<size(sqrt_primes);i++){auto p=sqrt_primes[i];for(uint32_t j=0;j<coprime;j++){ord_steps[i][j]=to_ord(p*(res210[j]+gap210[j]))-to_ord(p*res210[j]);}sums[i]=std::ranges::fold_left(ord_steps[i],0u,std::plus{});for(uint32_t j=0;j<coprime;j++){ord_steps[i][j+coprime]=ord_steps[i][j];}}return std::pair{ord_steps,sums};}();while(l+step_sum[i]<=r){
1414
#pragma GCC unroll coprime
15-
for(size_t j=0;j<coprime;j++){prime.reset(l);l+=ord_step[i][state++];}state-=coprime;}while(l<r){prime.reset(l);l+=ord_step[i][state++];state=state==coprime?0:state;}}dynamic_bit_array sieve210(uint32_t N){N++;dynamic_bit_array prime(to_ord(N));prime.set_all();static constexpr uint32_t dense_block=1<<25;for(uint32_t start=0;start<N;start+=dense_block){uint32_t r=std::min(start+dense_block,N);for(auto const&wheel:wheels){auto l=start/wheel.product*wheel.product;sieve_dense(prime,to_ord(l),to_ord(r),wheel);}}checkpoint("dense sieve");static constexpr uint32_t sparse_block=1<<24;for(uint32_t start=0;start<N;start+=sparse_block){uint32_t r=std::min(start+sparse_block,N);for(size_t i=medium_primes_begin;i<size(sqrt_primes);i++){auto p=sqrt_primes[i];if(p*p>=r)break;auto k=std::max(start/p,p);if(!coprime210(k)){k+=add210[k%210];}sieve210(prime,to_ord(p*k),to_ord(r),i,state210[k%210]);}}checkpoint("sparse sieve");for(size_t i=0;i<std::min(prime.words,sqrt_prime_bits.words);i++){prime.word(i)=sqrt_prime_bits.word(i);}return prime;}}
15+
for(size_t j=0;j<coprime;j++){prime.reset(l);l+=ord_step[i][state++];}state-=coprime;}while(l<r){prime.reset(l);l+=ord_step[i][state++];state=state==coprime?0:state;}}constexpr dynamic_bit_array sieve210(uint32_t N){N++;dynamic_bit_array prime(to_ord(N));prime.set_all();constexpr uint32_t wheel_threshold=500;static const auto[wheels,medium_primes_begin]=[](){uint32_t product=period*dynamic_bit_array::width;big_vector<uint32_t>current;big_vector<wheel_t>wheels;for(size_t i=0;i<size(sqrt_primes);i++){uint32_t p=sqrt_primes[i];if(product*p>max_wheel_size){wheels.push_back(make_wheel(current,product));current={p};product=period*dynamic_bit_array::width*p;if(product>max_wheel_size||p>wheel_threshold){checkpoint("make wheels");return std::pair{wheels,i};}}else{current.push_back(p);product*=p;}}assert(false);}();static constexpr uint32_t dense_block=1<<25;for(uint32_t start=0;start<N;start+=dense_block){uint32_t r=std::min(start+dense_block,N);for(auto const&wheel:wheels){auto l=start/wheel.product*wheel.product;sieve_dense(prime,to_ord(l),to_ord(r),wheel);}}checkpoint("dense sieve");static constexpr uint32_t sparse_block=1<<24;for(uint32_t start=0;start<N;start+=sparse_block){uint32_t r=std::min(start+sparse_block,N);for(size_t i=medium_primes_begin;i<size(sqrt_primes);i++){auto p=sqrt_primes[i];if(p*p>=r)break;auto k=std::max(start/p,p);if(!coprime210(k)){k+=add210[k%210];}sieve210(prime,to_ord(p*k),to_ord(r),i,state210[k%210]);}}checkpoint("sparse sieve");for(size_t i=0;i<std::min(prime.words,sqrt_prime_bits.words);i++){prime.word(i)=sqrt_prime_bits.word(i);}return prime;}}
1616
#pragma GCC pop_options
1717
#endif

cp-algo/min/structures/bit_array.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@
33
#include "../util/bit.hpp"
44
#include "../util/big_alloc.hpp"
55
#include <cassert>
6-
CP_ALGO_SIMD_PRAGMA_PUSHnamespace cp_algo::structures{template<typename C>concept Resizable=requires(C&c,std::size_t n){c.resize(n);};template<class Cont>struct _bit_array{using word_t=typename Cont::value_type;static constexpr size_t width=bit_width<word_t>;size_t words,n;alignas(32)Cont data;constexpr void resize(size_t N){n=N;words=(n+width-1)/width;if constexpr(Resizable<Cont>){data.resize(words);}else{assert(std::size(data)>=words);}}constexpr _bit_array():data(){if constexpr(!Resizable<Cont>){resize(std::size(data)*width);}else{resize(0);}}constexpr _bit_array(size_t N):data(){resize(N);}constexpr word_t&word(size_t x){return data[x];}constexpr word_t word(size_t x)const{return data[x];}constexpr void set_all(word_t val=-1){for(size_t i=0;i<words;i++){data[i]=val;}}constexpr void reset(){set_all(0);}constexpr void set(size_t x){word(x/width)|=1ULL<<(x%width);}constexpr void reset(size_t x){word(x/width)&=~(1ULL<<(x%width));}constexpr void flip(size_t x){word(x/width)^=1ULL<<(x%width);}constexpr bool test(size_t x)const{return(word(x/width)>>(x%width))&1;}constexpr bool operator[](size_t x)const{return test(x);}constexpr size_t size()const{return n;}auto operator<=>(_bit_array const&t)const=default;constexpr _bit_array&xor_hint(_bit_array const&t,size_t hint){for(size_t i=hint/width;i<words;i++){data[i]^=t.data[i];}return*this;}constexpr _bit_array&operator^=(_bit_array const&t){return xor_hint(t,0);}constexpr _bit_array operator^(_bit_array const&t)const{return _bit_array(*this)^=t;}};template<size_t N>using bit_array=_bit_array<std::array<uint64_t,(N+63)/64>>;using dynamic_bit_array=_bit_array<big_vector<uint64_t>>;}
6+
CP_ALGO_SIMD_PRAGMA_PUSHnamespace cp_algo::structures{template<typename C>concept Resizable=requires(C&c,std::size_t n){c.resize(n);};template<class Cont>struct _bit_array{using word_t=typename Cont::value_type;static constexpr size_t width=bit_width<word_t>;size_t words,n;alignas(32)Cont data;constexpr void resize(size_t N){n=N;words=(n+width-1)/width;if constexpr(Resizable<Cont>){data.resize(words);}else{assert(std::size(data)>=words);}}constexpr _bit_array():data(){if constexpr(!Resizable<Cont>){resize(std::size(data)*width);}else{resize(0);}}constexpr _bit_array(size_t N):data(){resize(N);}constexpr auto&&word(this auto&&self,size_t x){return self.data[x];}constexpr void set_all(word_t val=-1){for(size_t i=0;i<words;i++){data[i]=val;}}constexpr void reset(){set_all(0);}constexpr void set(size_t x){word(x/width)|=1ULL<<(x%width);}constexpr void reset(size_t x){word(x/width)&=~(1ULL<<(x%width));}constexpr void flip(size_t x){word(x/width)^=1ULL<<(x%width);}constexpr bool test(size_t x)const{return(word(x/width)>>(x%width))&1;}constexpr bool operator[](size_t x)const{return test(x);}constexpr size_t size()const{return n;}auto operator<=>(_bit_array const&t)const=default;constexpr _bit_array&xor_hint(_bit_array const&t,size_t hint){for(size_t i=hint/width;i<words;i++){data[i]^=t.data[i];}return*this;}constexpr _bit_array&operator^=(_bit_array const&t){return xor_hint(t,0);}constexpr _bit_array operator^(_bit_array const&t)const{return _bit_array(*this)^=t;}};template<size_t N>using bit_array=_bit_array<std::array<uint64_t,(N+63)/64>>;using dynamic_bit_array=_bit_array<big_vector<uint64_t>>;}
77
#pragma GCC pop_options
88
#endif

0 commit comments

Comments
 (0)