Compare commits
24 Commits
Author | SHA1 | Date | |
---|---|---|---|
7fa4d9d2bf | |||
6ed153b9e2 | |||
c8d1c095ba | |||
ae8cbed179 | |||
69028a15c8 | |||
b20733f3ac | |||
2b5541d2c3 | |||
94248612ba | |||
8ee18c8c4b | |||
bdea1979e8 | |||
a3ec19d47c | |||
22239ec644 | |||
22278999e7 | |||
a5b68282b3 | |||
b9cafadf8e | |||
32076a67cd | |||
9673a4da57 | |||
76936644cd | |||
a6ecea514f | |||
22c7702cf0 | |||
f8726497a4 | |||
3e902efd18 | |||
3246870b75 | |||
09166efe89 |
@ -30,3 +30,9 @@ Change Log
|
|||||||
- v0.7: Data Saving
|
- v0.7: Data Saving
|
||||||
- Allow user to save found primes to be loaded later.
|
- Allow user to save found primes to be loaded later.
|
||||||
- User can save and read primes in raw output.
|
- User can save and read primes in raw output.
|
||||||
|
- v1.0: Parallelization
|
||||||
|
- Now completely parallelized.
|
||||||
|
- Cleaned up/organized the code-base
|
||||||
|
- Exporting files uses less memory
|
||||||
|
- Allow searching for the nth prime number
|
||||||
|
- Clearing some memory leaks
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
Contributing
|
Contributing
|
||||||
============
|
============
|
||||||
We gladly accept contributions to Indivisible, however there are a few guidelines that must be followed.
|
We gladly accept contributions to Indivisible (send Git patches to <deathsbreed@themusicinnoise.net>), however there are a few guidelines that must be followed.
|
||||||
|
|
||||||
1) Copyright & Licensing
|
1) Copyright & Licensing
|
||||||
------------------------
|
------------------------
|
||||||
@ -8,7 +8,7 @@ The copyright of this project and all of its code, unless stated otherwise, belo
|
|||||||
|
|
||||||
2) Documentation
|
2) Documentation
|
||||||
----------------
|
----------------
|
||||||
All new features added must be well documented using DOxygen style comments. If your merge request adds a new feature and it is not well documented we will ask you to finish documenting the code before accepting a merge. This is simply so that both the maintainers of this repo and other users can understand the new API that bas been added.
|
All new features added must be well documented using DOxygen style comments. If your patch adds a new feature and it is not well documented we will ask you to finish documenting the code before accepting a patch. This is simply so that both the maintainers of this repo and other users can understand the new API that bas been added.
|
||||||
|
|
||||||
3) Code-Style
|
3) Code-Style
|
||||||
-------------
|
-------------
|
||||||
@ -16,8 +16,8 @@ The only aspects that will be religiously upheld for all contributions to this r
|
|||||||
|
|
||||||
Things that would be nice is if you could avoid having the lines being too long, and please avoid having more than one empty line in a row.
|
Things that would be nice is if you could avoid having the lines being too long, and please avoid having more than one empty line in a row.
|
||||||
|
|
||||||
4) Fractured Merge Requests
|
4) Fractured Patches
|
||||||
---------------------------
|
--------------------
|
||||||
Please make sure your merge requests are fractured into separate parts so that it may be easy for us to deal with them individually. The reason for this is to avoid having merge requests that both fix bugs and add features when in reality they should be separate requests. The only exception to this will be if the changes made to the code depend on one another to function properly.
|
Please make sure your patches are fractured into separate parts so that it may be easy for us to deal with them individually. The reason for this is to avoid having patches that both fix bugs and add features when in reality they should be separate requests. The only exception to this will be if the changes made to the code depend on one another to function properly.
|
||||||
|
|
||||||
If your merge request meets all these requirements and is passed by one of the moderators it will be merged into the main repo.
|
If your patch meets all these requirements and is passed by one of the moderators it will be merged into the main repo.
|
||||||
|
@ -22,7 +22,7 @@ To build a release build run `cmake -DCMAKE_BUILD_TYPE=Release ..` instead.
|
|||||||
|
|
||||||
Contributing
|
Contributing
|
||||||
------------
|
------------
|
||||||
If you would like to contribute to Uhn then please read the [contributing file](/CONTRIBUTING.md) before creating a merge request.
|
If you would like to contribute to Indivisible then please read the [contributing file](/CONTRIBUTING.md) before sending a patch. You may send the patches to <deathsbreed@themusicinnoise.net>.
|
||||||
|
|
||||||
License
|
License
|
||||||
-------
|
-------
|
||||||
|
67
src/files.c
67
src/files.c
@ -5,57 +5,62 @@
|
|||||||
|
|
||||||
int inputPrimes(char *file, List *list) {
|
int inputPrimes(char *file, List *list) {
|
||||||
// Assert safeguards
|
// Assert safeguards
|
||||||
assert(file != NULL);
|
assert(file);
|
||||||
assert(list != NULL);
|
assert(list);
|
||||||
|
|
||||||
FILE *pFile = fopen(file, "r");
|
FILE *in = fopen(file, "r");
|
||||||
if(pFile == NULL) return 1;
|
if(!in) return 1;
|
||||||
mpz_t n;
|
mpz_t n;
|
||||||
mpz_init(n);
|
mpz_init(n);
|
||||||
while(mpz_inp_raw(n, pFile) != 0) addToList(list, n);
|
while(mpz_inp_raw(n, in))
|
||||||
if(fclose(pFile) != 0) return 2;
|
if(addToList(list, n) == 1) return 3;
|
||||||
|
|
||||||
|
mpz_clear(n);
|
||||||
|
|
||||||
|
if(fclose(in)) return 2;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int outputPrimes(char *file, List *list) {
|
int outputPrimes(char *file, List *list, size_t startPos) {
|
||||||
// Assert safeguards
|
// Assert safeguards
|
||||||
assert(file != NULL);
|
assert(file);
|
||||||
assert(list != NULL);
|
assert(list);
|
||||||
|
|
||||||
|
FILE *out = fopen(file, "a");
|
||||||
|
if(!out) return 1;
|
||||||
|
|
||||||
FILE *oFile = fopen(file, "w");
|
|
||||||
if(oFile == NULL) return 1;
|
|
||||||
printf("Saving primes to `%s'...\n", file);
|
printf("Saving primes to `%s'...\n", file);
|
||||||
puts("0%");
|
puts("0%");
|
||||||
for(size_t i = 0; i < list->end; ++i) {
|
for(size_t i = startPos; i < list->end; ++i) {
|
||||||
if(mpz_out_raw(oFile, list->list[i]) == 0) return 3;
|
if(!mpz_out_raw(out, list->list[i])) return 3;
|
||||||
if(i == list->end / 4) puts("25%");
|
if(i == list->end / 4) puts("25%");
|
||||||
else if(i == list->end / 2) puts("50%");
|
else if(i == list->end / 2) puts("50%");
|
||||||
else if(i == list->end * 3 / 4) puts("75%");
|
else if(i == list->end * 3 / 4) puts("75%");
|
||||||
}
|
}
|
||||||
puts("100%");
|
puts("100%");
|
||||||
if(fclose(oFile) != 0) return 2;
|
|
||||||
|
if(fclose(out)) return 2;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int exportPrimes(char *file, List *list, int base) {
|
int exportPrimes(char *efile, char *dfile, int base) {
|
||||||
// Assert safeguards
|
// Assert safeguards
|
||||||
assert(file != NULL);
|
assert(efile);
|
||||||
assert(list != NULL);
|
assert(dfile);
|
||||||
assert(list->list != NULL);
|
|
||||||
|
|
||||||
FILE *eFile = fopen(file, "w");
|
FILE *in = fopen(dfile, "r");
|
||||||
if(eFile == NULL) return 1;
|
FILE *out = fopen(efile, "w");
|
||||||
printf("Exporting primes to `%s'...\n", file);
|
if(!in || !out) return 1;
|
||||||
puts("0%");
|
|
||||||
for(size_t i = 0; i < list->end; ++i) {
|
printf("Exporting primes to `%s'...\n", efile);
|
||||||
if(mpz_out_str(eFile, base, list->list[i]) == 0) return 3;
|
mpz_t n;
|
||||||
fprintf(eFile, "\n");
|
mpz_init(n);
|
||||||
if(i == list->end / 4) puts("25%");
|
while(mpz_inp_raw(n, in)) {
|
||||||
else if(i == list->end / 2) puts("50%");
|
if(!mpz_out_str(out, base, n)) return 3;
|
||||||
else if(i == list->end * 3 / 4) puts("75%");
|
fprintf(out, "\n");
|
||||||
}
|
}
|
||||||
puts("100%");
|
|
||||||
if(fclose(eFile) != 0) return 2;
|
if(fclose(in) || fclose(out)) return 2;
|
||||||
puts("Finished exporting primes.");
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
13
src/files.h
13
src/files.h
@ -12,7 +12,8 @@
|
|||||||
* @param file File to input primes from.
|
* @param file File to input primes from.
|
||||||
* @param list List to load primes into.
|
* @param list List to load primes into.
|
||||||
* @returns If 0 then load was successful, if 1 then failed to open,
|
* @returns If 0 then load was successful, if 1 then failed to open,
|
||||||
* if 2 failed to close.
|
* if 2 failed to close, if 3 failed to allocate new memory to List
|
||||||
|
* (see `addToList()')
|
||||||
*/
|
*/
|
||||||
int inputPrimes(char *file, List *list);
|
int inputPrimes(char *file, List *list);
|
||||||
|
|
||||||
@ -20,17 +21,19 @@ int inputPrimes(char *file, List *list);
|
|||||||
* @brief Output primes from a List into an Indivisible file.
|
* @brief Output primes from a List into an Indivisible file.
|
||||||
* @param file File to output primes to.
|
* @param file File to output primes to.
|
||||||
* @param list List to read primes from.
|
* @param list List to read primes from.
|
||||||
|
* @param startPos The position in the List of primes at which to append
|
||||||
|
* to the file.
|
||||||
* @returns If 0 then load was successful, if 1 then failed to open,
|
* @returns If 0 then load was successful, if 1 then failed to open,
|
||||||
* if 2 failed to close, if 3 failed when writing.
|
* if 2 failed to close, if 3 failed when writing.
|
||||||
*/
|
*/
|
||||||
int outputPrimes(char *file, List *list);
|
int outputPrimes(char *file, List *list, size_t startPos);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Export primes from a List to a plain text file.
|
* @brief Export primes from a List to a plain text file.
|
||||||
* @param file File to output primes as plain text to.
|
* @param efile File to export primes as plain text to.
|
||||||
* @param list List to read primes from.
|
* @param dfile File to read primes from.
|
||||||
* @param base The base in which the primes will be written.
|
* @param base The base in which the primes will be written.
|
||||||
* @returns If 0 then load was successful, if 1 then failed to open,
|
* @returns If 0 then load was successful, if 1 then failed to open,
|
||||||
* if 2 failed to close, if 3 failed when writing.
|
* if 2 failed to close, if 3 failed when writing.
|
||||||
*/
|
*/
|
||||||
int exportPrimes(char *file, List *list, int base);
|
int exportPrimes(char *efile, char *dfile, int base);
|
||||||
|
19
src/list.c
19
src/list.c
@ -1,39 +1,34 @@
|
|||||||
#include "list.h"
|
#include "list.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the number of elements by which the list expands.
|
* This is the number of elements by which the list expands.
|
||||||
*/
|
*/
|
||||||
#define BLOCK_SIZE 1024
|
#define BLOCK_SIZE 1024
|
||||||
|
|
||||||
void initList(List *restrict l) {
|
int initList(List *restrict l) {
|
||||||
l->list = malloc(sizeof(mpz_t) * BLOCK_SIZE);
|
l->list = malloc(sizeof(mpz_t) * BLOCK_SIZE);
|
||||||
if(!l->list) {
|
if(!l->list) return 1;
|
||||||
fprintf(stderr, "Failed to allocate memory to list!\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
l->size = BLOCK_SIZE;
|
l->size = BLOCK_SIZE;
|
||||||
l->end = 0;
|
l->end = 0;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void deInitList(List *restrict l) {
|
void deInitList(List *restrict l) {
|
||||||
for(size_t i = 0; i < l->size; ++i) {
|
for(size_t i = 0; i < l->end; ++i) {
|
||||||
mpz_clear(l->list[i]);
|
mpz_clear(l->list[i]);
|
||||||
}
|
}
|
||||||
free(l->list);
|
free(l->list);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addToList(List *l, mpz_t n) {
|
int addToList(List *restrict l, mpz_t n) {
|
||||||
if(l->end == l->size) {
|
if(l->end == l->size) {
|
||||||
l->size += BLOCK_SIZE;
|
l->size += BLOCK_SIZE;
|
||||||
void *tmp = realloc(l->list, sizeof(mpz_t) * l->size);
|
void *tmp = realloc(l->list, sizeof(mpz_t) * l->size);
|
||||||
if(!tmp) {
|
if(!tmp) return 1;
|
||||||
fprintf(stderr, "Failed to allocate more memory to list!\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
l->list = tmp;
|
l->list = tmp;
|
||||||
}
|
}
|
||||||
mpz_init(l->list[l->end]);
|
mpz_init(l->list[l->end]);
|
||||||
mpz_set(l->list[l->end++], n);
|
mpz_set(l->list[l->end++], n);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <gmp.h>
|
#include <gmp.h>
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief An infinitely expanding list type.
|
* @brief An infinitely expanding list type.
|
||||||
@ -23,8 +22,9 @@ typedef struct {
|
|||||||
* @details Initialize the list and its variables, allocating memory
|
* @details Initialize the list and its variables, allocating memory
|
||||||
* to the pointer array inside.
|
* to the pointer array inside.
|
||||||
* @param[in] l A pointer to a List type to be initialized.
|
* @param[in] l A pointer to a List type to be initialized.
|
||||||
|
* @returns Returns 0 if successful and 1 if failed.
|
||||||
*/
|
*/
|
||||||
void initList(List *restrict l);
|
int initList(List *restrict l);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Deinitialize a List.
|
* @brief Deinitialize a List.
|
||||||
@ -38,5 +38,6 @@ void deInitList(List *restrict l);
|
|||||||
* @details Add item `n' at the end of a List type.
|
* @details Add item `n' at the end of a List type.
|
||||||
* @param[out] l List to which the variable should be appended.
|
* @param[out] l List to which the variable should be appended.
|
||||||
* @param[in] n variable to be appended to the list.
|
* @param[in] n variable to be appended to the list.
|
||||||
|
* @returns Returns 0 if successful and 1 if failed.
|
||||||
*/
|
*/
|
||||||
void addToList(List *l, mpz_t n);
|
int addToList(List *restrict l, mpz_t n);
|
||||||
|
216
src/main.c
216
src/main.c
@ -4,13 +4,14 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <gmp.h>
|
#include <gmp.h>
|
||||||
|
#include <omp.h>
|
||||||
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
#include "files.h"
|
#include "files.h"
|
||||||
|
|
||||||
#define VERSION "v0.7"
|
#define VERSION "v1.0"
|
||||||
|
|
||||||
static bool run;
|
static bool run;
|
||||||
|
|
||||||
@ -23,12 +24,13 @@ int main(int argc, char *argv[]) {
|
|||||||
f_version = false,
|
f_version = false,
|
||||||
f_quiet = false;
|
f_quiet = false;
|
||||||
int base = 10;
|
int base = 10;
|
||||||
char *file = NULL;
|
size_t n_prime = 0;
|
||||||
|
char *dfile = NULL;
|
||||||
char *efile = NULL;
|
char *efile = NULL;
|
||||||
|
|
||||||
// Parse commandline arguments
|
// Parse commandline arguments
|
||||||
int c;
|
int c;
|
||||||
while((c = getopt(argc, argv, "hvqb:f:e:")) != -1) {
|
while((c = getopt(argc, argv, "hvqb:f:e:n:")) != -1) {
|
||||||
switch(c) {
|
switch(c) {
|
||||||
case 'h':
|
case 'h':
|
||||||
f_help = true;
|
f_help = true;
|
||||||
@ -45,15 +47,23 @@ int main(int argc, char *argv[]) {
|
|||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Invalid base `%d'. Base must be between 2 and 62.\n",
|
"Invalid base `%d'. Base must be between 2 and 62.\n",
|
||||||
base);
|
base);
|
||||||
exit(1);
|
return 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'f':
|
case 'f':
|
||||||
file = optarg;
|
dfile = optarg;
|
||||||
break;
|
break;
|
||||||
case 'e':
|
case 'e':
|
||||||
efile = optarg;
|
efile = optarg;
|
||||||
break;
|
break;
|
||||||
|
case 'n':
|
||||||
|
n_prime = atoi(optarg);
|
||||||
|
if(n_prime <= 2) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"`n' must be larger than 2 (first two primes are 2 and 3).\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
printUsage(argv[0]);
|
printUsage(argv[0]);
|
||||||
return 1;
|
return 1;
|
||||||
@ -63,153 +73,201 @@ int main(int argc, char *argv[]) {
|
|||||||
// Act based on which flags were used
|
// Act based on which flags were used
|
||||||
if(f_help) {
|
if(f_help) {
|
||||||
printUsage(argv[0]);
|
printUsage(argv[0]);
|
||||||
|
puts("\nArguments:");
|
||||||
puts(" -h print this help information");
|
puts(" -h print this help information");
|
||||||
puts(" -v print version number of program");
|
puts(" -v print version number of program");
|
||||||
puts(" -q quiet mode");
|
puts(" -q quiet mode");
|
||||||
puts(" -b <base> base in which to print primes between 2 and 62 (default 10)");
|
puts(" -b <base> base in which to print primes between 2 and 62 (default 10)");
|
||||||
puts(" -f <file> file in/from which primes are stored and read from in raw format");
|
puts(" -f <file> file in/from which primes are stored and read from in raw format");
|
||||||
puts(" -e <file> export input file to plain text format");
|
puts(" -e <file> export input file to plain text format");
|
||||||
|
puts(" -n <n> run until the 'n'th prime\n");
|
||||||
return 0;
|
return 0;
|
||||||
} else if(f_version) {
|
} else if(f_version) {
|
||||||
printf("Indivisible %s\n", VERSION);
|
printf("Indivisible %s\n", VERSION);
|
||||||
return 0;
|
return 0;
|
||||||
|
} else if(f_quiet && !dfile) {
|
||||||
|
puts("Error: you cannot run in quiet mode without specifying a data file.");
|
||||||
|
printUsage(argv[0]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(efile && !dfile) {
|
||||||
|
puts("Error: you must have a file to export to.");
|
||||||
|
printUsage(argv[0]);
|
||||||
|
return 0;
|
||||||
|
} else if(efile && dfile) {
|
||||||
|
exportPrimes(efile, dfile, base);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!omp_get_cancellation()) {
|
||||||
|
puts("Warning: the OpenMP cancellation environment variable (`OMP_CANCELLATION') is not enabled.");
|
||||||
|
char in;
|
||||||
|
while(true) {
|
||||||
|
printf("[e]nable/[c]ontinue/[q]uit? ");
|
||||||
|
scanf("%c", &in);
|
||||||
|
if(in == 'e' || in == 'E') {
|
||||||
|
putenv("OMP_CANCELLATION=true");
|
||||||
|
execv(argv[0], argv);
|
||||||
|
} else if(in == 'c' || in == 'C') {
|
||||||
|
break;
|
||||||
|
} else if(in == 'q' || in == 'Q') {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Quit on ^C by setting `run = false'
|
// Quit on ^C by setting `run = false'
|
||||||
run = true;
|
run = true;
|
||||||
signal(SIGINT, leave);
|
signal(SIGINT, leave);
|
||||||
|
|
||||||
if(efile != NULL && file == NULL) {
|
puts("Use Ctrl+C to exit.");
|
||||||
fprintf(stderr, "There must be an input file to export! Use `-h' for help.\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
bool newFile = true;
|
bool newFile = true;
|
||||||
if(file != NULL) {
|
if(dfile) {
|
||||||
struct stat s;
|
struct stat s;
|
||||||
if(stat(file, &s) == 0) newFile = false;
|
if(stat(dfile, &s) == 0) newFile = false;
|
||||||
}
|
}
|
||||||
|
// Last position added from file
|
||||||
|
size_t startPos = 0;
|
||||||
|
|
||||||
int exitCode = 0;
|
int exitCode = 0;
|
||||||
|
|
||||||
// Primes we've found
|
// Primes we've found
|
||||||
List primes;
|
List primes;
|
||||||
initList(&primes);
|
if(initList(&primes) == 1) {
|
||||||
|
fprintf(stderr, "Failed to initialize primes list.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
// The number we're going to be testing for
|
// The number we're going to be testing for
|
||||||
mpz_t num;
|
mpz_t num;
|
||||||
mpz_init(num);
|
mpz_init(num);
|
||||||
|
|
||||||
// Variable for half `num'
|
// Variable for sqrt of `num'
|
||||||
mpz_t halfNum;
|
mpz_t numRoot;
|
||||||
mpz_init(halfNum);
|
mpz_init(numRoot);
|
||||||
|
// Index of the prime number above and closest to `numRoot'
|
||||||
if(efile == NULL) puts("Use Ctrl+C to exit.");
|
size_t rootInd = 0;
|
||||||
|
|
||||||
if(newFile) {
|
if(newFile) {
|
||||||
// Add 2, a known prime to this list
|
// Add 2, a known prime to this list
|
||||||
mpz_set_ui(num, 2);
|
mpz_set_ui(num, 2);
|
||||||
addToList(&primes, num);
|
if(addToList(&primes, num) == 1) {
|
||||||
if(!f_quiet) {
|
fprintf(stderr, "Failed to allocate more memory for list.\n");
|
||||||
if(mpz_out_str(stdout, base, num) == 0) {
|
exitCode = 1;
|
||||||
fprintf(stderr, "Could not print to `stdout'!\n");
|
goto releaseMemory;
|
||||||
exitCode = 1;
|
}
|
||||||
goto releaseMemory;
|
// Add 3 as well to optimize the algorithm
|
||||||
}
|
mpz_set_ui(num, 3);
|
||||||
printf("\n");
|
if(addToList(&primes, num) == 1) {
|
||||||
|
fprintf(stderr, "Failed to allocate more memory for list.\n");
|
||||||
|
exitCode = 1;
|
||||||
|
goto releaseMemory;
|
||||||
|
}
|
||||||
|
if(!f_quiet) {
|
||||||
|
puts("2\n3");
|
||||||
}
|
}
|
||||||
mpz_add_ui(num, num, 1);
|
|
||||||
} else {
|
} else {
|
||||||
// Load primes from file
|
// Load primes from file
|
||||||
int err = inputPrimes(file, &primes);
|
int err = inputPrimes(dfile, &primes);
|
||||||
|
startPos = primes.end;
|
||||||
|
|
||||||
if(err == 0) {
|
if(err == 0) {
|
||||||
printf("Loaded %zu primes.\n", primes.end);
|
printf("Loaded %zu primes.\n", primes.end);
|
||||||
} else {
|
} else {
|
||||||
if(err == 1)
|
if(err == 1)
|
||||||
fprintf(stderr, "Failed to open Indivisible file `%s'.\n", file);
|
fprintf(stderr, "Failed to open Indivisible file `%s'.\n", dfile);
|
||||||
else if(err == 2)
|
else if(err == 2)
|
||||||
fprintf(stderr, "Failed to close Indivisible file `%s'.\n", file);
|
fprintf(stderr, "Failed to close Indivisible file `%s'.\n", dfile);
|
||||||
|
else if(err == 3)
|
||||||
|
fprintf(stderr, "Failed to allocate more memory for list.\n");
|
||||||
exitCode = 1;
|
exitCode = 1;
|
||||||
goto releaseMemory;
|
goto releaseMemory;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Yes, I realize there's a -1 here, I don't know why but it won't
|
* I set to `primes.end-1' because primes.end indicates the next new
|
||||||
* work if it's not there, so don't change it unless necessary.
|
* element in the list that can be used, which is also equal to the total
|
||||||
|
* number of elements in the list.
|
||||||
*/
|
*/
|
||||||
mpz_set(num, primes.list[primes.end-1]);
|
mpz_set(num, primes.list[primes.end-1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(efile != NULL) {
|
while(run) {
|
||||||
int err = exportPrimes(efile, &primes, base);
|
mpz_add_ui(num, num, 2);
|
||||||
|
|
||||||
if(err == 0) {
|
// Calculate the sqrt(num)
|
||||||
puts("Successfully exported primes.");
|
mpz_sqrt(numRoot, num);
|
||||||
} else {
|
|
||||||
if(err == 1)
|
|
||||||
fprintf(stderr, "Failed to open/create plain text file `%s'.\n", efile);
|
|
||||||
else if(err == 2)
|
|
||||||
fprintf(stderr, "Failed to close plain text file `%s'.\n", efile);
|
|
||||||
else if(err == 3)
|
|
||||||
fprintf(stderr, "Failed to write prime to plain text file `%s'.\n", efile);
|
|
||||||
exitCode = 1;
|
|
||||||
}
|
|
||||||
goto releaseMemory;
|
|
||||||
}
|
|
||||||
|
|
||||||
do {
|
while(mpz_cmp(primes.list[rootInd], numRoot) <= 0) {
|
||||||
// Calculate half of `num'
|
if(++rootInd > primes.end) {
|
||||||
mpz_fdiv_q_ui(halfNum, num, 2);
|
fprintf(stderr, "Error: `rootInd' surpassed `primes.end'.\n");
|
||||||
/**
|
|
||||||
* Loop through primes we've found until we get to half of the number
|
|
||||||
* we're analyzing
|
|
||||||
*/
|
|
||||||
for(size_t i = 0; mpz_cmp(primes.list[i], halfNum) < 0; ++i) {
|
|
||||||
// If `num' is divisible by a prime then go to the next number
|
|
||||||
if(mpz_divisible_p(num, primes.list[i]) != 0)
|
|
||||||
goto nextPrime;
|
|
||||||
}
|
|
||||||
|
|
||||||
// `num' is a prime so we add it to the list and print it
|
|
||||||
addToList(&primes, num);
|
|
||||||
if(!f_quiet) {
|
|
||||||
if(mpz_out_str(stdout, base, num) == 0) {
|
|
||||||
fprintf(stderr, "Could not print to `stdout'!\n");
|
|
||||||
exitCode = 1;
|
exitCode = 1;
|
||||||
goto releaseMemory;
|
goto releaseMemory;
|
||||||
}
|
}
|
||||||
printf("\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nextPrime:
|
bool isPrime = true;
|
||||||
// Add 2 (skip even numbers since they're all divisible by 2)
|
/**
|
||||||
mpz_add_ui(num, num, 2);
|
* Loop through primes we've found until we get to the sqrt of the
|
||||||
} while(run);
|
* number we're analyzing. Also, skip `2' since we're not testing even
|
||||||
|
* numbers.
|
||||||
|
*/
|
||||||
|
#pragma omp parallel
|
||||||
|
{
|
||||||
|
#pragma omp for
|
||||||
|
for(size_t i = 1; i < rootInd; ++i) {
|
||||||
|
if(mpz_divisible_p(num, primes.list[i])) {
|
||||||
|
#pragma omp atomic write
|
||||||
|
isPrime = false;
|
||||||
|
#pragma omp cancel for
|
||||||
|
}
|
||||||
|
#pragma omp cancellation point for
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(isPrime) {
|
||||||
|
// `num' is a prime so we add it to the list and print it
|
||||||
|
if(addToList(&primes, num) == 1) {
|
||||||
|
fprintf(stderr, "Failed to allocate more memory for list.\n");
|
||||||
|
exitCode = 1;
|
||||||
|
goto releaseMemory;
|
||||||
|
}
|
||||||
|
if(!f_quiet) {
|
||||||
|
if(!mpz_out_str(stdout, base, num))
|
||||||
|
fprintf(stderr, "Could not print to `stdout'!\n");
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(primes.end == n_prime) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
printf("Found %zu primes.\n", primes.end);
|
printf("Found %zu primes.\n", primes.end);
|
||||||
|
|
||||||
if(file != NULL) {
|
if(dfile) {
|
||||||
int err = outputPrimes(file, &primes);
|
int err = outputPrimes(dfile, &primes, startPos);
|
||||||
if(err == 0) {
|
if(err == 0) {
|
||||||
puts("Successfully saved primes.");
|
puts("Successfully saved primes.");
|
||||||
} else {
|
} else {
|
||||||
if(err == 1)
|
if(err == 1)
|
||||||
fprintf(stderr, "Failed to open/create file `%s'.\n", file);
|
fprintf(stderr, "Failed to open/create file `%s'.\n", dfile);
|
||||||
else if(err == 2)
|
else if(err == 2)
|
||||||
fprintf(stderr, "Failed to close file `%s'.\n", file);
|
fprintf(stderr, "Failed to close file `%s'.\n", dfile);
|
||||||
else if(err == 3)
|
else if(err == 3)
|
||||||
fprintf(stderr, "Failed while writing a prime to `%s'.\n", file);
|
fprintf(stderr, "Failed while writing a prime to `%s'.\n", dfile);
|
||||||
exitCode = 1;
|
exitCode = 1;
|
||||||
goto releaseMemory;
|
goto releaseMemory;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear GMP variables
|
|
||||||
mpz_clear(halfNum);
|
|
||||||
mpz_clear(num);
|
|
||||||
|
|
||||||
releaseMemory:
|
releaseMemory:
|
||||||
puts("Clearing memory...");
|
puts("Clearing memory...");
|
||||||
|
// Clear GMP variables
|
||||||
|
mpz_clear(numRoot);
|
||||||
|
mpz_clear(num);
|
||||||
// Deinitialize the list
|
// Deinitialize the list
|
||||||
deInitList(&primes);
|
deInitList(&primes);
|
||||||
|
|
||||||
@ -218,7 +276,7 @@ releaseMemory:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void printUsage(char *progName) {
|
void printUsage(char *progName) {
|
||||||
printf("%s [OPTIONS]\n", progName);
|
printf("%s [[-f <file> [-e <file> | -q]] [-b <base>] [-n <n>] | [-h] | [-v]]\n", progName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void leave() { run = false; }
|
void leave() { run = false; }
|
||||||
|
Reference in New Issue
Block a user