素数計算 | JavaScript |
#ifndef PRIME_H_ #define PRIME_H_ /* * prime.h * https://mind.kittttttan.info/c/prime */ int sieve(int *p, int l); int sieve_below(int *p, int limit); int mod_math_pow(int base, int power, int mod); int mrpt(int n, int i); #endif /* PRIME_H_ */
/*
* prime.c
* https://mind.kittttttan.info/c/prime
*/
#include "prime.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <assert.h>
/*
* get prime number list with sieve algorhythm
* @param[out] p Array for the list
* @param[in] l Length of the list
* @return
*/
int sieve(int *p, int l) {
int i, j, sq, limit, *s;
double times;
if (l < 1) {
return 0;
}
if (l < 50) {
times = 5.0;
} else {
times = log(l) + 2.0;
}
limit = (int)floor(l * times);
s = (int*)malloc(sizeof(int) * limit);
if (!s) {
fprintf(stderr, "failed malloc: %s@%d\n", __FILE__, __LINE__);
return 0;
}
sq = (int)floor(sqrt(limit));
s[0] = 0;
s[1] = 0;
for (i = 2; i < limit + 1; ++i) {
s[i] = 1;
}
for (i = 2; i < sq + 1; ++i) {
for (j = i * i; j < limit + 1; j += i) {
s[j] = 0;
}
}
j = 0;
for (i = 0; j < l; ++i) {
if (s[i]) {
p[j++] = i;
}
}
free(s);
return j;
}
/*
* get prime number list below limit
* @param[out] p
* @param[in] limit
* @return length
*/
int sieve_below(int *p, int limit) {
int i, j, sq, *s;
s = (int*)malloc(sizeof(int) * limit);
if (!s) {
fprintf(stderr, "failed malloc: %s@%d\n", __FILE__, __LINE__);
return 0;
}
sq = (int)floor(sqrt(limit));
s[0] = 0;
s[1] = 0;
for (i = 2; i < limit + 1; ++i) {
s[i] = 1;
}
for (i = 2; i < sq + 1; ++i) {
for (j = i * i; j < limit + 1; j += i) {
s[j] = 0;
}
}
j = 0;
for (i = 0; i < limit + 1; ++i) {
if (s[i]) {
p[j++] = i;
}
}
free(s);
return j;
}
/*
* mod_math_pow
* @param[in] base
* @param[in] power
* @param[in] mod
* @return [base]^[power] (mod [mod])
*/
int mod_math_pow(int base, int power, int mod) {
int result = 1;
while (power > 0) {
if (power & 1) {
result = result * base % mod;
}
base = base * base % mod;
power >>= 1;
}
return result;
}
/*
* Miller-Rabin primality test
* @param[in] n Target number
* @param[in] i Repeat times of the test
* @return 1 means prime
*/
int mrpt(int n, int i) {
int a, d, t, y;
if (n == 2) {
return 1;
}
assert(n <= 0xfffffff);
if (n < 2 || (n & 1) == 0) {
return 0;
}
d = n - 1;
srand((unsigned int)time(NULL));
while ((d & 1) == 0) {
d >>= 1;
}
while (i--) {
a = rand() % (n - 1) + 1;
t = d;
y = mod_math_pow(a, t, n);
while (t != n - 1 && y != 1 && y != n - 1) {
y = y * y % n;
t <<= 1;
}
if (y != n - 1 && (t & 1) == 0) {
return 0;
}
}
return 1;
}