forked from GitHub/gf-core
155 lines
2.0 KiB
C
155 lines
2.0 KiB
C
#include <gu/defs.h>
|
|
#include <gu/assert.h>
|
|
|
|
static const uint32_t gu_prime_wheel_mask = 0UL
|
|
| 1 << 1
|
|
| 1 << 7
|
|
| 1 << 11
|
|
| 1 << 13
|
|
| 1 << 17
|
|
| 1 << 19
|
|
| 1 << 23
|
|
| 1 << 29;
|
|
|
|
static bool
|
|
gu_prime_wheel(int i)
|
|
{
|
|
gu_assert(i >= 0 && i < 30);
|
|
return !!(gu_prime_wheel_mask & (1 << i));
|
|
}
|
|
|
|
static const uint32_t gu_small_prime_mask = 0UL
|
|
| 1 << 2
|
|
| 1 << 3
|
|
| 1 << 5
|
|
| 1 << 7
|
|
| 1 << 11
|
|
| 1 << 13
|
|
| 1 << 17
|
|
| 1 << 19
|
|
| 1 << 23
|
|
| 1 << 29
|
|
| 1U << 31;
|
|
|
|
static bool
|
|
gu_is_wheel_prime(int u)
|
|
{
|
|
gu_assert(u > 30 && u % 2 != 0 && u % 3 != 0 && u % 5 != 0);
|
|
int d = 0;
|
|
int i = 7;
|
|
goto start;
|
|
while (d * d <= u) {
|
|
for (i = 1; i <= 29; i+=2) {
|
|
start:
|
|
if (gu_prime_wheel(i) && u % (d + i) == 0) {
|
|
return false;
|
|
}
|
|
}
|
|
d += 30;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
int
|
|
gu_prime_inf(int i)
|
|
{
|
|
if (i < 2) {
|
|
return 0;
|
|
} else if (i < 32) {
|
|
while (!(gu_small_prime_mask & (1 << i))) {
|
|
i--;
|
|
}
|
|
return i;
|
|
}
|
|
|
|
int d = (i - 1) | 1;
|
|
int r = d % 30;
|
|
|
|
while (!gu_prime_wheel(r) || !gu_is_wheel_prime(d)) {
|
|
d -= 2;
|
|
r -= 2;
|
|
if (r < 0) {
|
|
r += 30;
|
|
}
|
|
}
|
|
return d;
|
|
}
|
|
|
|
int
|
|
gu_prime_sup(int i)
|
|
{
|
|
if (i <= 2) {
|
|
return 2;
|
|
} else if (i < 32) {
|
|
while (!(gu_small_prime_mask & (1 << i))) {
|
|
i++;
|
|
}
|
|
return i;
|
|
}
|
|
|
|
int d = i | 1;
|
|
int r = d % 30;
|
|
|
|
while (!gu_prime_wheel(r) || !gu_is_wheel_prime(d)) {
|
|
d += 2;
|
|
r += 2;
|
|
if (r > 30) {
|
|
r -= 30;
|
|
}
|
|
}
|
|
return d;
|
|
}
|
|
|
|
bool
|
|
gu_is_prime(int i)
|
|
{
|
|
if (i < 2) {
|
|
return false;
|
|
} else if (i < 30) {
|
|
return !!(gu_small_prime_mask & (1 << i));
|
|
} else if (!gu_prime_wheel(i % 30)) {
|
|
return false;
|
|
} else {
|
|
return gu_is_wheel_prime(i);
|
|
}
|
|
}
|
|
|
|
bool
|
|
gu_is_twin_prime(int i)
|
|
{
|
|
return gu_is_prime(i) && gu_is_prime(i - 2);
|
|
}
|
|
|
|
int
|
|
gu_twin_prime_inf(int i)
|
|
{
|
|
while (true) {
|
|
i = gu_prime_inf(i);
|
|
if (i == 0) {
|
|
return 0;
|
|
} else if (gu_is_prime(i - 2)) {
|
|
return i;
|
|
}
|
|
i = i - 4;
|
|
}
|
|
return i;
|
|
}
|
|
|
|
int
|
|
gu_twin_prime_sup(int i)
|
|
{
|
|
if (i <= 5) {
|
|
return 5;
|
|
}
|
|
i = i - 2;
|
|
while (true) {
|
|
i = gu_prime_sup(i);
|
|
if (gu_is_prime(i + 2)) {
|
|
return i + 2;
|
|
}
|
|
i = i + 4;
|
|
}
|
|
return i;
|
|
}
|
|
|