summaryrefslogtreecommitdiff
path: root/src/runtime/c/gu/prime.c
diff options
context:
space:
mode:
authorkr.angelov <kr.angelov@gmail.com>2012-01-20 13:41:10 +0000
committerkr.angelov <kr.angelov@gmail.com>2012-01-20 13:41:10 +0000
commit2eee382a62a909d5a3f2f5eda94f30fe68fd5335 (patch)
treeb0b0d513535895f244214aebf6358e172b8dce6d /src/runtime/c/gu/prime.c
parentb9728357126f8b9a6311cca17d9f0dcc2a7bfb9b (diff)
initial import of the C runtime
Diffstat (limited to 'src/runtime/c/gu/prime.c')
-rw-r--r--src/runtime/c/gu/prime.c154
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;
+}
+