#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <string.h>
#include <errno.h>
#include <primesieve.h>
#include "wren.h"
#define psi primesieve_iterator
/* Primes functions */
void Primes_iterator(WrenVM* vm) {
psi *pit = (psi *)wrenSetSlotNewForeign(vm, 0, 0, sizeof(psi));
primesieve_init(pit);
}
void Primes_free(void* data) {
psi *pit = (psi *)data;
primesieve_free_iterator(pit);
}
void Primes_next(WrenVM* vm) {
psi *pit = (psi *)wrenGetSlotForeign(vm, 0);
uint64_t prime = primesieve_next_prime(pit);
wrenSetSlotDouble(vm, 0, (double)prime);
}
void Primes_prev(WrenVM* vm) {
psi *pit = (psi *)wrenGetSlotForeign(vm, 0);
uint64_t prime = primesieve_prev_prime(pit);
wrenSetSlotDouble(vm, 0, (double)prime);
}
void Primes_skipTo(WrenVM* vm) {
psi *pit = (psi *)wrenGetSlotForeign(vm, 0);
uint64_t start = (uint64_t)wrenGetSlotDouble(vm, 1);
uint64_t stop = (uint64_t)wrenGetSlotDouble(vm, 2);
primesieve_skipto(pit, start, stop);
}
void Primes_between(WrenVM* vm) {
uint64_t start = (uint64_t)wrenGetSlotDouble(vm, 1);
uint64_t stop = (uint64_t)wrenGetSlotDouble(vm, 2);
size_t size;
uint64_t *primes = (uint64_t *)primesieve_generate_primes(start, stop, &size, UINT64_PRIMES);
int i;
wrenEnsureSlots(vm, 2);
wrenSetSlotNewList(vm, 0);
for (i = 0; i < size; ++i) {
wrenSetSlotDouble(vm, 1, (double)primes[i]);
wrenInsertInList(vm, 0, i, 1);
}
primesieve_free(primes);
}
void Primes_firstNfrom(WrenVM* vm) {
uint64_t n = (uint64_t)wrenGetSlotDouble(vm, 1);
uint64_t start = (uint64_t)wrenGetSlotDouble(vm, 2);
uint64_t *primes = (uint64_t *)primesieve_generate_n_primes(n, start, UINT64_PRIMES);
int i;
wrenEnsureSlots(vm, 2);
wrenSetSlotNewList(vm, 0);
for (i = 0; i < n; ++i) {
wrenSetSlotDouble(vm, 1, (double)primes[i]);
wrenInsertInList(vm, 0, i, 1);
}
primesieve_free(primes);
}
void Primes_firstFrom(WrenVM* vm) {
uint64_t start = (uint64_t)wrenGetSlotDouble(vm, 1);
uint64_t prime = primesieve_nth_prime(0, start);
wrenSetSlotDouble(vm, 0, (double)prime);
}
void Primes_nthAfter(WrenVM* vm) {
int64_t n = (int64_t)wrenGetSlotDouble(vm, 1);
uint64_t after = (uint64_t)wrenGetSlotDouble(vm, 2);
uint64_t prime = primesieve_nth_prime(n, after);
wrenSetSlotDouble(vm, 0, (double)prime);
}
void Primes_nthBefore(WrenVM* vm) {
int64_t n = (int64_t)wrenGetSlotDouble(vm, 1);
uint64_t before = (uint64_t)wrenGetSlotDouble(vm, 2);
uint64_t prime = primesieve_nth_prime(-n, before);
wrenSetSlotDouble(vm, 0, (double)prime);
}
void Primes_count(WrenVM* vm) {
uint64_t start = (uint64_t)wrenGetSlotDouble(vm, 1);
uint64_t stop = (uint64_t)wrenGetSlotDouble(vm, 2);
uint64_t count = primesieve_count_primes(start, stop);
wrenSetSlotDouble(vm, 0, (double)count);
}
void Primes_count2(WrenVM* vm) {
uint64_t start = (uint64_t)wrenGetSlotDouble(vm, 1);
uint64_t stop = (uint64_t)wrenGetSlotDouble(vm, 2);
uint64_t count = primesieve_count_twins(start, stop);
wrenSetSlotDouble(vm, 0, (double)count);
}
void Primes_count3(WrenVM* vm) {
uint64_t start = (uint64_t)wrenGetSlotDouble(vm, 1);
uint64_t stop = (uint64_t)wrenGetSlotDouble(vm, 2);
uint64_t count = primesieve_count_triplets(start, stop);
wrenSetSlotDouble(vm, 0, (double)count);
}
void Primes_count4(WrenVM* vm) {
uint64_t start = (uint64_t)wrenGetSlotDouble(vm, 1);
uint64_t stop = (uint64_t)wrenGetSlotDouble(vm, 2);
uint64_t count = primesieve_count_quadruplets(start, stop);
wrenSetSlotDouble(vm, 0, (double)count);
}
void Primes_count5(WrenVM* vm) {
uint64_t start = (uint64_t)wrenGetSlotDouble(vm, 1);
uint64_t stop = (uint64_t)wrenGetSlotDouble(vm, 2);
uint64_t count = primesieve_count_quintuplets(start, stop);
wrenSetSlotDouble(vm, 0, (double)count);
}
void Primes_count6(WrenVM* vm) {
uint64_t start = (uint64_t)wrenGetSlotDouble(vm, 1);
uint64_t stop = (uint64_t)wrenGetSlotDouble(vm, 2);
uint64_t count = primesieve_count_sextuplets(start, stop);
wrenSetSlotDouble(vm, 0, (double)count);
}
void Primes_print(WrenVM* vm) {
uint64_t start = (uint64_t)wrenGetSlotDouble(vm, 1);
uint64_t stop = (uint64_t)wrenGetSlotDouble(vm, 2);
primesieve_print_primes(start, stop);
}
void Primes_print2(WrenVM* vm) {
uint64_t start = (uint64_t)wrenGetSlotDouble(vm, 1);
uint64_t stop = (uint64_t)wrenGetSlotDouble(vm, 2);
primesieve_print_twins(start, stop);
}
void Primes_print3(WrenVM* vm) {
uint64_t start = (uint64_t)wrenGetSlotDouble(vm, 1);
uint64_t stop = (uint64_t)wrenGetSlotDouble(vm, 2);
primesieve_print_triplets(start, stop);
}
void Primes_print4(WrenVM* vm) {
uint64_t start = (uint64_t)wrenGetSlotDouble(vm, 1);
uint64_t stop = (uint64_t)wrenGetSlotDouble(vm, 2);
primesieve_print_quadruplets(start, stop);
}
void Primes_print5(WrenVM* vm) {
uint64_t start = (uint64_t)wrenGetSlotDouble(vm, 1);
uint64_t stop = (uint64_t)wrenGetSlotDouble(vm, 2);
primesieve_print_quintuplets(start, stop);
}
void Primes_print6(WrenVM* vm) {
uint64_t start = (uint64_t)wrenGetSlotDouble(vm, 1);
uint64_t stop = (uint64_t)wrenGetSlotDouble(vm, 2);
primesieve_print_sextuplets(start, stop);
}
void Primes_factorize(WrenVM* vm) {
uint64_t n = (uint64_t)wrenGetSlotDouble(vm, 1);
wrenEnsureSlots(vm, 2);
wrenSetSlotNewList(vm, 0);
if (n < 2) return;
primesieve_iterator it;
primesieve_init(&it);
uint64_t prime;
int i = 0;
while (1) {
prime = primesieve_next_prime(&it);
if (prime * prime <= n) {
while (!(n%prime)) {
wrenSetSlotDouble(vm, 1, (double)prime);
wrenInsertInList(vm, 0, i++, 1);
n /= prime;
}
} else {
break;
}
}
if (n > 1) {
wrenSetSlotDouble(vm, 1, (double)n);
wrenInsertInList(vm, 0, i, 1);
}
primesieve_free_iterator(&it);
}
void Primes_sieveSize(WrenVM* vm) {
int size = primesieve_get_sieve_size();
wrenSetSlotDouble(vm, 0, (double)size);
}
void Primes_set_sieveSize(WrenVM* vm) {
int size = (int)wrenGetSlotDouble(vm, 1);
primesieve_set_sieve_size(size);
}
void Primes_numThreads(WrenVM* vm) {
int num = primesieve_get_num_threads();
wrenSetSlotDouble(vm, 0, (double)num);
}
void Primes_set_numThreads(WrenVM* vm) {
int num = (int)wrenGetSlotDouble(vm, 1);
primesieve_set_num_threads(num);
}
void Primes_version(WrenVM* vm) {
wrenSetSlotString(vm, 0, primesieve_version());
}
void Primes_lastError(WrenVM* vm) {
wrenSetSlotString(vm, 0, strerror(errno));
}
/* LPrimes functions */
void LPrimes_next(WrenVM* vm) {
psi *pit = (psi *)wrenGetSlotForeign(vm, 0);
uint64_t prime = primesieve_next_prime(pit);
char s[21];
sprintf(s, "%"PRIu64, prime);
wrenSetSlotString(vm, 0, s);
}
void LPrimes_prev(WrenVM* vm) {
psi *pit = (psi *)wrenGetSlotForeign(vm, 0);
uint64_t prime = primesieve_prev_prime(pit);
char s[21];
sprintf(s, "%"PRIu64, prime);
wrenSetSlotString(vm, 0, s);
}
void LPrimes_skipTo(WrenVM* vm) {
psi *pit = (psi *)wrenGetSlotForeign(vm, 0);
uint64_t start = strtoull(wrenGetSlotString(vm, 1), NULL, 10);
uint64_t stop = strtoull(wrenGetSlotString(vm, 2), NULL, 10);
primesieve_skipto(pit, start, stop);
}
void LPrimes_between(WrenVM* vm) {
uint64_t start = strtoull(wrenGetSlotString(vm, 1), NULL, 10);
uint64_t stop = strtoull(wrenGetSlotString(vm, 2), NULL, 10);
size_t size;
uint64_t *primes = (uint64_t *)primesieve_generate_primes(start, stop, &size, UINT64_PRIMES);
int i;
char s[21];
wrenEnsureSlots(vm, 2);
wrenSetSlotNewList(vm, 0);
for (i = 0; i < size; ++i) {
sprintf(s, "%"PRIu64, primes[i]);
wrenSetSlotString(vm, 1, s);
wrenInsertInList(vm, 0, i, 1);
}
primesieve_free(primes);
}
void LPrimes_firstNfrom(WrenVM* vm) {
uint64_t n = (uint64_t)wrenGetSlotDouble(vm, 1);
uint64_t start = strtoull(wrenGetSlotString(vm, 2), NULL, 10);
uint64_t *primes = (uint64_t *)primesieve_generate_n_primes(n, start, UINT64_PRIMES);
int i;
char s[21];
wrenEnsureSlots(vm, 2);
wrenSetSlotNewList(vm, 0);
for (i = 0; i < n; ++i) {
sprintf(s, "%"PRIu64, primes[i]);
wrenSetSlotString(vm, 1, s);
wrenInsertInList(vm, 0, i, 1);
}
primesieve_free(primes);
}
void LPrimes_firstFrom(WrenVM* vm) {
uint64_t start = strtoull(wrenGetSlotString(vm, 1), NULL, 10);
uint64_t prime = primesieve_nth_prime(0, start);
char s[21];
sprintf(s, "%"PRIu64, prime);
wrenSetSlotString(vm, 0, s);
}
void LPrimes_nthAfter(WrenVM* vm) {
int64_t n = (int64_t)wrenGetSlotDouble(vm, 1);
uint64_t after = strtoull(wrenGetSlotString(vm, 2), NULL, 10);
uint64_t prime = primesieve_nth_prime(n, after);
char s[21];
sprintf(s, "%"PRIu64, prime);
wrenSetSlotString(vm, 0, s);
}
void LPrimes_nthBefore(WrenVM* vm) {
int64_t n = (int64_t)wrenGetSlotDouble(vm, 1);
uint64_t before = strtoull(wrenGetSlotString(vm, 2), NULL, 10);
uint64_t prime = primesieve_nth_prime(-n, before);
char s[21];
sprintf(s, "%"PRIu64, prime);
wrenSetSlotString(vm, 0, s);
}
void LPrimes_count(WrenVM* vm) {
uint64_t start = strtoull(wrenGetSlotString(vm, 1), NULL, 10);
uint64_t stop = strtoull(wrenGetSlotString(vm, 2), NULL, 10);
uint64_t count = primesieve_count_primes(start, stop);
char s[21];
sprintf(s, "%"PRIu64, count);
wrenSetSlotString(vm, 0, s);
}
void LPrimes_count2(WrenVM* vm) {
uint64_t start = strtoull(wrenGetSlotString(vm, 1), NULL, 10);
uint64_t stop = strtoull(wrenGetSlotString(vm, 2), NULL, 10);
uint64_t count = primesieve_count_twins(start, stop);
char s[21];
sprintf(s, "%"PRIu64, count);
wrenSetSlotString(vm, 0, s);
}
void LPrimes_count3(WrenVM* vm) {
uint64_t start = strtoull(wrenGetSlotString(vm, 1), NULL, 10);
uint64_t stop = strtoull(wrenGetSlotString(vm, 2), NULL, 10);
uint64_t count = primesieve_count_triplets(start, stop);
char s[21];
sprintf(s, "%"PRIu64, count);
wrenSetSlotString(vm, 0, s);
}
void LPrimes_count4(WrenVM* vm) {
uint64_t start = strtoull(wrenGetSlotString(vm, 1), NULL, 10);
uint64_t stop = strtoull(wrenGetSlotString(vm, 2), NULL, 10);
uint64_t count = primesieve_count_quadruplets(start, stop);
char s[21];
sprintf(s, "%"PRIu64, count);
wrenSetSlotString(vm, 0, s);
}
void LPrimes_count5(WrenVM* vm) {
uint64_t start = strtoull(wrenGetSlotString(vm, 1), NULL, 10);
uint64_t stop = strtoull(wrenGetSlotString(vm, 2), NULL, 10);
uint64_t count = primesieve_count_quintuplets(start, stop);
char s[21];
sprintf(s, "%"PRIu64, count);
wrenSetSlotString(vm, 0, s);
}
void LPrimes_count6(WrenVM* vm) {
uint64_t start = strtoull(wrenGetSlotString(vm, 1), NULL, 10);
uint64_t stop = strtoull(wrenGetSlotString(vm, 2), NULL, 10);
uint64_t count = primesieve_count_sextuplets(start, stop);
char s[21];
sprintf(s, "%"PRIu64, count);
wrenSetSlotString(vm, 0, s);
}
void LPrimes_print(WrenVM* vm) {
uint64_t start = strtoull(wrenGetSlotString(vm, 1), NULL, 10);
uint64_t stop = strtoull(wrenGetSlotString(vm, 2), NULL, 10);
primesieve_print_primes(start, stop);
}
void LPrimes_print2(WrenVM* vm) {
uint64_t start = strtoull(wrenGetSlotString(vm, 1), NULL, 10);
uint64_t stop = strtoull(wrenGetSlotString(vm, 2), NULL, 10);
primesieve_print_twins(start, stop);
}
void LPrimes_print3(WrenVM* vm) {
uint64_t start = strtoull(wrenGetSlotString(vm, 1), NULL, 10);
uint64_t stop = strtoull(wrenGetSlotString(vm, 2), NULL, 10);
primesieve_print_triplets(start, stop);
}
void LPrimes_print4(WrenVM* vm) {
uint64_t start = strtoull(wrenGetSlotString(vm, 1), NULL, 10);
uint64_t stop = strtoull(wrenGetSlotString(vm, 2), NULL, 10);
primesieve_print_quadruplets(start, stop);
}
void LPrimes_print5(WrenVM* vm) {
uint64_t start = strtoull(wrenGetSlotString(vm, 1), NULL, 10);
uint64_t stop = strtoull(wrenGetSlotString(vm, 2), NULL, 10);
primesieve_print_quintuplets(start, stop);
}
void LPrimes_print6(WrenVM* vm) {
uint64_t start = strtoull(wrenGetSlotString(vm, 1), NULL, 10);
uint64_t stop = strtoull(wrenGetSlotString(vm, 2), NULL, 10);
primesieve_print_sextuplets(start, stop);
}
void LPrimes_factorize(WrenVM* vm) {
uint64_t n = strtoull(wrenGetSlotString(vm, 1), NULL, 10);
wrenEnsureSlots(vm, 2);
wrenSetSlotNewList(vm, 0);
if (n < 2) return;
primesieve_iterator it;
primesieve_init(&it);
uint64_t prime;
char s[21];
int i = 0;
while (1) {
prime = primesieve_next_prime(&it);
if (prime * prime <= n) {
while (!(n%prime)) {
sprintf(s, "%"PRIu64, prime);
wrenSetSlotString(vm, 1, s);
wrenInsertInList(vm, 0, i++, 1);
n /= prime;
}
} else {
break;
}
}
if (n > 1) {
sprintf(s, "%"PRIu64, n);
wrenSetSlotString(vm, 1, s);
wrenInsertInList(vm, 0, i, 1);
}
primesieve_free_iterator(&it);
}
WrenForeignClassMethods bindForeignClass(WrenVM* vm, const char* module, const char* className) {
WrenForeignClassMethods methods;
methods.allocate = NULL;
methods.finalize = NULL;
if (strcmp(module, "./psieve") == 0) {
if (strcmp(className, "Primes") == 0) {
methods.allocate = Primes_iterator;
methods.finalize = Primes_free;
} else if (strcmp(className, "LPrimes") == 0) {
methods.allocate = Primes_iterator;
methods.finalize = Primes_free;
}
}
return methods;
}
WrenForeignMethodFn bindForeignMethod(
WrenVM* vm,
const char* module,
const char* className,
bool isStatic,
const char* signature) {
if (strcmp(module, "./psieve") == 0) {
if (strcmp(className, "Primes") == 0) {
if( isStatic && strcmp(signature, "between(_,_)") == 0) return Primes_between;
if( isStatic && strcmp(signature, "firstNfrom(_,_)") == 0) return Primes_firstNfrom;
if( isStatic && strcmp(signature, "firstFrom(_)") == 0) return Primes_firstFrom;
if( isStatic && strcmp(signature, "nthAfter(_,_)") == 0) return Primes_nthAfter;
if( isStatic && strcmp(signature, "nthBefore(_,_)") == 0) return Primes_nthBefore;
if( isStatic && strcmp(signature, "count(_,_)") == 0) return Primes_count;
if( isStatic && strcmp(signature, "count2(_,_)") == 0) return Primes_count2;
if( isStatic && strcmp(signature, "count3(_,_)") == 0) return Primes_count3;
if( isStatic && strcmp(signature, "count4(_,_)") == 0) return Primes_count4;
if( isStatic && strcmp(signature, "count5(_,_)") == 0) return Primes_count5;
if( isStatic && strcmp(signature, "count6(_,_)") == 0) return Primes_count6;
if( isStatic && strcmp(signature, "print(_,_)") == 0) return Primes_print;
if( isStatic && strcmp(signature, "print2(_,_)") == 0) return Primes_print2;
if( isStatic && strcmp(signature, "print3(_,_)") == 0) return Primes_print3;
if( isStatic && strcmp(signature, "print4(_,_)") == 0) return Primes_print4;
if( isStatic && strcmp(signature, "print5(_,_)") == 0) return Primes_print5;
if( isStatic && strcmp(signature, "print6(_,_)") == 0) return Primes_print6;
if( isStatic && strcmp(signature, "factorize(_)") == 0) return Primes_factorize;
if( isStatic && strcmp(signature, "sieveSize") == 0) return Primes_sieveSize;
if( isStatic && strcmp(signature, "sieveSize=(_)") == 0) return Primes_set_sieveSize;
if( isStatic && strcmp(signature, "numThreads") == 0) return Primes_numThreads;
if( isStatic && strcmp(signature, "numThreads=(_)") == 0) return Primes_set_numThreads;
if( isStatic && strcmp(signature, "version") == 0) return Primes_version;
if( isStatic && strcmp(signature, "lastError") == 0) return Primes_lastError;
if(!isStatic && strcmp(signature, "next") == 0) return Primes_next;
if(!isStatic && strcmp(signature, "prev") == 0) return Primes_prev;
if(!isStatic && strcmp(signature, "skipTo(_,_)") == 0) return Primes_skipTo;
} else if (strcmp(className, "LPrimes") == 0) {
if( isStatic && strcmp(signature, "between(_,_)") == 0) return LPrimes_between;
if( isStatic && strcmp(signature, "firstNfrom(_,_)") == 0) return LPrimes_firstNfrom;
if( isStatic && strcmp(signature, "firstFrom(_)") == 0) return LPrimes_firstFrom;
if( isStatic && strcmp(signature, "nthAfter(_,_)") == 0) return LPrimes_nthAfter;
if( isStatic && strcmp(signature, "nthBefore(_,_)") == 0) return LPrimes_nthBefore;
if( isStatic && strcmp(signature, "count(_,_)") == 0) return LPrimes_count;
if( isStatic && strcmp(signature, "count2(_,_)") == 0) return LPrimes_count2;
if( isStatic && strcmp(signature, "count3(_,_)") == 0) return LPrimes_count3;
if( isStatic && strcmp(signature, "count4(_,_)") == 0) return LPrimes_count4;
if( isStatic && strcmp(signature, "count5(_,_)") == 0) return LPrimes_count5;
if( isStatic && strcmp(signature, "count6(_,_)") == 0) return LPrimes_count6;
if( isStatic && strcmp(signature, "print(_,_)") == 0) return LPrimes_print;
if( isStatic && strcmp(signature, "print2(_,_)") == 0) return LPrimes_print2;
if( isStatic && strcmp(signature, "print3(_,_)") == 0) return LPrimes_print3;
if( isStatic && strcmp(signature, "print4(_,_)") == 0) return LPrimes_print4;
if( isStatic && strcmp(signature, "print5(_,_)") == 0) return LPrimes_print5;
if( isStatic && strcmp(signature, "print6(_,_)") == 0) return LPrimes_print6;
if( isStatic && strcmp(signature, "factorize(_)") == 0) return LPrimes_factorize;
if(!isStatic && strcmp(signature, "next") == 0) return LPrimes_next;
if(!isStatic && strcmp(signature, "prev") == 0) return LPrimes_prev;
if(!isStatic && strcmp(signature, "skipTo(_,_)") == 0) return LPrimes_skipTo;
}
}
return NULL;
}
static void writeFn(WrenVM* vm, const char* text) {
printf("%s", text);
}
void errorFn(WrenVM* vm, WrenErrorType errorType, const char* module, const int line, const char* msg) {
switch (errorType) {
case WREN_ERROR_COMPILE:
printf("[%s line %d] [Error] %s\n", module, line, msg);
break;
case WREN_ERROR_STACK_TRACE:
printf("[%s line %d] in %s\n", module, line, msg);
break;
case WREN_ERROR_RUNTIME:
printf("[Runtime Error] %s\n", msg);
break;
}
}
char *readFile(const char *fileName) {
FILE *f = fopen(fileName, "r");
fseek(f, 0, SEEK_END);
long fsize = ftell(f);
rewind(f);
char *script = malloc(fsize + 1);
size_t ret = fread(script, 1, fsize, f);
if (ret != fsize) printf("Error reading %s\n", fileName);
fclose(f);
script[fsize] = 0;
return script;
}
static void loadModuleComplete(WrenVM* vm, const char* module, WrenLoadModuleResult result) {
if( result.source) free((void*)result.source);
}
WrenLoadModuleResult loadModule(WrenVM* vm, const char* name) {
WrenLoadModuleResult result = {0};
if (strcmp(name, "random") != 0 && strcmp(name, "meta") != 0) {
result.onComplete = loadModuleComplete;
char fullName[strlen(name) + 6];
strcpy(fullName, name);
strcat(fullName, ".wren");
result.source = readFile(fullName);
}
return result;
}
int main(int argc, char **argv) {
if (argc != 2) {
printf("Please pass the name of the Wren file to be executed.\n");
return 1;
}
WrenConfiguration config;
wrenInitConfiguration(&config);
config.writeFn = &writeFn;
config.errorFn = &errorFn;
config.bindForeignClassFn = &bindForeignClass;
config.bindForeignMethodFn = &bindForeignMethod;
config.loadModuleFn = &loadModule;
WrenVM* vm = wrenNewVM(&config);
const char* module = "main";
const char* fileName = argv[1];
char *script = readFile(fileName);
WrenInterpretResult result = wrenInterpret(vm, module, script);
switch (result) {
case WREN_RESULT_COMPILE_ERROR:
printf("Compile Error!\n");
break;
case WREN_RESULT_RUNTIME_ERROR:
printf("Runtime Error!\n");
break;
case WREN_RESULT_SUCCESS:
break;
}
wrenFreeVM(vm);
free(script);
return 0;
}