#include #include #include #include #include #include #include /* ========================= Basic factor structures ========================= */ typedef struct { uint64_t prime; uint64_t power; } Factor; typedef struct { uint64_t num_primes; Factor factors[]; } Factors; typedef struct { uint64_t len; uint64_t elems[]; } U64Array; /* ========================= Utilities ========================= */ static inline void *get(void *buf, size_t pitch, uint64_t i) { return (uint8_t*)buf + pitch*i; } static inline uint64_t get_factors(uint64_t w){ return offsetof(U64Array, elems) + w*sizeof(uint64_t); } static inline uint64_t get_factorizations(uint64_t w){ return offsetof(Factors, factors) + w*sizeof(Factor); } static inline void factor_append(Factors *f, uint64_t p, uint64_t k){ f->factors[f->num_primes].prime = p; f->factors[f->num_primes].power = k; f->num_primes++; } /* ========================= Math helpers ========================= */ static uint64_t u64_pow(uint64_t a, uint64_t e){ uint64_t r=1; while(e){ if(e&1) r*=a; a*=a; e>>=1; } return r; } static uint64_t u64_nth_root(uint64_t x, uint64_t n){ return pow((double)x,1.0/n); } static uint64_t u64_binom(uint64_t n,uint64_t k){ if(k>n) return 0; uint64_t r=1; for(uint64_t i=1;i<=k;i++) r=r*(n-k+i)/i; return r; } static int64_t i64_gcd(int64_t a,int64_t b){ while(b){ int64_t t=a%b; a=b; b=t; } return a; } static int64_t i64_lcm(int64_t a,int64_t b){ return a/i64_gcd(a,b)*b; } static int64_t i64_egcd(int64_t a,int64_t b,int64_t *x,int64_t *y){ if(!b){ *x=1; *y=0; return a; } int64_t x1,y1; int64_t g=i64_egcd(b,a%b,&x1,&y1); *x=y1; *y=x1-y1*(a/b); return g; } uint64_t max_prime_divs(uint64_t max){ static const uint64_t primorials[]={ 6ULL,30ULL,210ULL,2310ULL,30030ULL, 510510ULL,9699690ULL,223092870ULL }; for(uint64_t i=0;inum_primes=0; while(n>1){ uint64_t p=spf[n]; uint64_t k=0; while(spf[n]==p){ n/=p; k++; } factor_append(out,p,k); } } /* ========================= Totient sieve https://cp-algorithms.com/algebra/phi-function.html ========================= */ uint64_t *sieve_phi(uint64_t max){ uint64_t *phi=malloc((max+1)*sizeof(uint64_t)); if(!phi) return NULL; for(uint64_t i=1;i<=max;i++) phi[i]=i; for(uint64_t p=2;p<=max;p++){ if(phi[p]!=p) continue; for(uint64_t m=p;m<=max;m+=p) phi[m]-=phi[m]/p; } return phi; } /* ========================= Sigma_0 (divisor count) ========================= */ uint64_t *sigma0(uint64_t max){ uint64_t *d=calloc(max+1,sizeof(uint64_t)); if(!d) return NULL; for(uint64_t i=1;i<=max;i++) for(uint64_t j=i;j<=max;j+=i) d[j]++; return d; } /* ========================= Mobius sieve https://mathoverflow.net/questions/99473/calculating-m%C3%B6bius-function ========================= */ int8_t *mobius(uint64_t max){ int8_t *mu=malloc(max+1); if(!mu) return NULL; for(uint64_t i=1;i<=max;i++) mu[i]=1; for(uint64_t p=2;p<=max;p++){ if(mu[p]==1){ for(uint64_t m=p;m<=max;m+=p) mu[m]*=-1; uint64_t p2=p*p; for(uint64_t m=p2;m<=max;m+=p2) mu[m]=0; } } return mu; } uint64_t *sieve_primes(uint64_t max,uint64_t *count){ uint8_t *is_comp=calloc(max+1,1); if(!is_comp) return NULL; uint64_t cap=max_primes_le(max); uint64_t *primes=malloc(cap*sizeof(uint64_t)); uint64_t pc=0; for(uint64_t p=2;p<=max;p++){ if(is_comp[p]) continue; primes[pc++]=p; if(p*p<=max) for(uint64_t m=p*p;m<=max;m+=p) is_comp[m]=1; } free(is_comp); *count=pc; return realloc(primes,pc*sizeof(uint64_t)); } int main(){ uint64_t max = 10000000; uint64_t pc; uint64_t *primes=sieve_primes(max,&pc); printf("Primes up to %llu:\n",(unsigned long long)max); for(uint64_t i=0;i