diff options
| author | kr.angelov <kr.angelov@gmail.com> | 2012-01-20 13:41:10 +0000 |
|---|---|---|
| committer | kr.angelov <kr.angelov@gmail.com> | 2012-01-20 13:41:10 +0000 |
| commit | 2eee382a62a909d5a3f2f5eda94f30fe68fd5335 (patch) | |
| tree | b0b0d513535895f244214aebf6358e172b8dce6d /src/runtime/c/gu/prime.c | |
| parent | b9728357126f8b9a6311cca17d9f0dcc2a7bfb9b (diff) | |
initial import of the C runtime
Diffstat (limited to 'src/runtime/c/gu/prime.c')
| -rw-r--r-- | src/runtime/c/gu/prime.c | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/src/runtime/c/gu/prime.c b/src/runtime/c/gu/prime.c new file mode 100644 index 000000000..6452f8777 --- /dev/null +++ b/src/runtime/c/gu/prime.c @@ -0,0 +1,154 @@ +#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; +} + |
