79 Commits
v0.2 ... v1.0

Author SHA1 Message Date
7fa4d9d2bf Added stuff to CHANGELOG for v1.0 2017-02-13 17:08:30 +01:00
6ed153b9e2 Will be disabling merge requests. 2017-02-13 10:09:25 +01:00
c8d1c095ba Clarify. 2017-02-13 09:56:23 +01:00
ae8cbed179 Details... 2017-02-13 09:55:31 +01:00
69028a15c8 Promote patches. 2017-02-13 09:54:13 +01:00
b20733f3ac Append new primes to the end of a file. 2017-02-13 09:47:47 +01:00
2b5541d2c3 Fixed some memory leaks. 2017-02-12 19:33:57 +01:00
94248612ba Find the nth prime. 2017-02-06 18:00:34 +01:00
8ee18c8c4b Forget it, it's unnecessary. 2017-02-06 17:51:07 +01:00
bdea1979e8 Use inline functions. 2017-02-06 17:50:26 +01:00
a3ec19d47c Cleaned the code. 2017-02-02 19:53:29 +01:00
22239ec644 Preparing for v1.0 release. 2017-02-02 10:46:34 +01:00
22278999e7 Fixed algorithm problem. 2017-02-02 10:35:43 +01:00
a5b68282b3 Cancel if `primes.list[i] >= numRoot'.
It has been solved!!!
2017-02-01 23:12:23 +01:00
b9cafadf8e Parallelized, but needs algorithm optimization. 2017-02-01 19:36:05 +01:00
32076a67cd Remove parallelization code to start anew. 2017-02-01 17:18:03 +01:00
9673a4da57 Use shared as default. 2017-01-31 22:24:06 +01:00
76936644cd Almost completely parallelized. 2017-01-31 19:39:35 +01:00
a6ecea514f Restrict will no longer apply to `addToList' 2017-01-17 00:11:51 +01:00
22c7702cf0 We only need to test up to the sqrt(num). 2017-01-01 17:05:25 +01:00
f8726497a4 Don't test for divisibility by 2.
We skip all even numbers, so we can skip 2, this also means giving 3 as
a given.
2016-12-30 17:57:28 +01:00
3e902efd18 Small cleanup. 2016-12-30 17:51:48 +01:00
3246870b75 Better help information. 2016-12-28 14:43:17 +01:00
09166efe89 Small improvements and optimizations.
All error catching is now in `main.c' so we can neatly release memory as
well as adding the `restrict' optimizer to the `addToList()' function.
2016-12-28 00:30:31 +01:00
8b35c5aea3 Fixed title for v0.7 2016-12-27 22:53:22 +01:00
1264edc8c8 We're going to release v0.7 first. 2016-12-27 22:52:06 +01:00
63aa8e14cb Fixed the damn exporting for once.
Now I'm checking to see if it was actually worth a damn to have raw
files in the first place (-_-;).
2016-12-27 22:34:34 +01:00
f2eb3e869e Fixed the file issue...
but the export issue still remains -_- I hate seg faults.
2016-12-27 21:47:16 +01:00
a695cce709 Moving shit to files.c 2016-12-27 21:31:24 +01:00
096cb2eb16 Moving file I/O to own file. Everything works except export. 2016-12-26 18:50:51 +01:00
1783b16024 Use raw I/O for file saving. 2016-12-26 16:51:51 +01:00
c602b5fe1b Added OpenMP to CI. 2016-12-26 16:35:52 +01:00
6b2411e860 Now using OpenMP for parallel programming and next version is v1.0 2016-12-26 15:57:28 +01:00
6c2f96416b Read and write primes to and from file. 2016-12-26 15:56:56 +01:00
fa3f2dd2b1 New goal before paralellization 2016-12-22 16:31:24 +01:00
591ee92971 Cast is unnecessary in C. 2016-12-15 15:16:04 +01:00
803c6f9e06 `size_t' makes this safeguard unnecessary. 2016-12-14 23:42:20 +01:00
4390fca3ef Added comments. 2016-12-14 23:38:22 +01:00
2629c12f1a Set goal for v1.0 2016-12-14 22:26:43 +01:00
af79d206d3 Added entry for v0.6 2016-12-14 20:12:46 +01:00
4b034ce5e3 Print more info about the file writing. 2016-12-14 19:34:50 +01:00
f146dbf11c Able to save found primes to a file afterwards. 2016-12-14 19:28:28 +01:00
656fee720e Allow user to choose base. 2016-12-14 19:06:33 +01:00
5e45656e1a Forgot that from the switch to C. 2016-12-14 17:58:12 +01:00
c522196d66 Argument parsing! 2016-12-14 17:52:52 +01:00
b5dcadce19 Added new goal for v0.5 2016-12-14 17:31:36 +01:00
003b94dcdb Added some more useful docs and stuff. 2016-12-14 16:14:58 +01:00
fcee95da17 Fixed something from the description 2016-12-14 16:14:37 +01:00
43620ba2d3 Enable documentation. 2016-12-14 16:08:11 +01:00
9f1160242a Removed warning (no longer necessary). 2016-12-14 15:56:28 +01:00
b414bff9dc Minor optimization. 2016-12-14 15:55:39 +01:00
d8c81b172b Print some fun information at the end. 2016-12-14 15:29:06 +01:00
c2f0fb0ffd Defining changes for v0.5 2016-12-14 15:05:24 +01:00
5bbac132bc Use size_t, which is better for arrays of very large sizes. 2016-12-14 14:13:32 +01:00
2a3e97f4bc Prepare version number so I don't forget later. 2016-12-13 18:09:05 +01:00
06d5ddb0cc Fixed problem with the algorithm.
If it's equal to half then we want to check if it's divisible, since if
it's half then it is NOT prime.
2016-12-13 18:05:02 +01:00
a9019291c2 New goal for v0.4 2016-12-13 17:51:48 +01:00
5aa0b333c0 Made a fix, because previously it was not measuring primes. 2016-12-13 16:32:10 +01:00
3110c74174 Added entry about `restrict' keyword. 2016-12-13 16:12:31 +01:00
a5ce845c68 `restrict' keyword must be in declaration. 2016-12-13 16:12:03 +01:00
449fef2994 Add restrict
Add restrict for better pointer optimizations. This is not being applied
to `addToList()' because that function we want to thread later on.
2016-12-13 11:26:12 +01:00
2e9326b5fb Preparing for v0.4
I'm going to be learning OpenCL, after which I will decide whether to
use OpenCL or OpenMP for the development of Indivisible. This mostly
depends on the compatibility of each library with GMP, especially since
I believe GMP already does some of its own threading.
2016-12-12 23:21:22 +01:00
06cb271dba Forgot to set that shit to v0.3 2016-12-12 16:20:21 +01:00
4cbc3fae7d Cache the right .o files. 2016-12-10 17:43:31 +01:00
9b4fa96474 Remove TODO list. 2016-12-10 17:41:40 +01:00
e2aedab3b0 Added new entry. 2016-12-10 17:12:58 +01:00
bc8b48dd29 Updated info for v0.3 2016-12-10 17:12:00 +01:00
dab78093ab Deleted macros 2016-12-10 17:11:21 +01:00
a782bdb57d Organized TODO.md 2016-12-10 15:31:04 +01:00
9157d15383 Added goals for v0.3 2016-12-10 15:30:51 +01:00
f1fd758bfc Added entry for v0.2.1 (which I had previously forgotten). 2016-12-10 14:54:12 +01:00
66c0a5d027 Added a TODO list. 2016-12-10 14:54:00 +01:00
f4ee9872bc Optimize the algorithm to avoid numbers larger than half. 2016-12-10 14:46:51 +01:00
8a42e85d04 Better explanation of error. 2016-12-10 11:51:32 +01:00
dd38b53e31 Fixed leaks. 2016-12-10 11:20:01 +01:00
3c8b9922fb Shorten the long ass `unsigned long long int' to ulli. 2016-12-10 02:20:57 +01:00
cb9e1648e9 No need to use that macro outside a loop. 2016-12-10 02:09:34 +01:00
30703314dd Forgot it for the main loop as well. 2016-12-10 01:15:52 +01:00
4905391c82 Add more optimizations. 2016-12-10 00:50:23 +01:00
13 changed files with 2917 additions and 79 deletions

3
.gitignore vendored
View File

@ -2,5 +2,8 @@
build/*
!build/.keep
# Ignore documentation
doc/
# Ignore vim temporary files
*.sw[a-z]

View File

@ -4,7 +4,7 @@ build:
stage: build
# Install dependencies
before_script:
- apt update && apt -y install cmake libgmp-dev
- apt update && apt -y install cmake libgmp-dev libgomp1
# Build the project
script:
- cd build/
@ -17,4 +17,4 @@ build:
# Cache .o files for faster compiling
cache:
paths:
- "*.o"
- "build/CMakeFiles/indivisible.dir/src/*.o"

View File

@ -9,3 +9,30 @@ Change Log
- Switch to C.
- Uses GNU Multiple Precision library (GMP) to hold prime numbers, allowing for 'infinite' size.
- Add `likely()' and `unlikely()' macros to optimize.
- v0.2.1: Memory Leak Fixes
- Fixed a major memory leak at the end of the program.
- Added more optimizers.
- v0.3: Optimizations
- Algorithm skips half the known primes.
- Removed `likely()' and `unlikely()' macros due to lack of information.
- Improved performance.
- v0.4: Fixed Algorithm
- Fixed algorithm to actually calculate primes.
- Added extra C99 optimizations.
- v0.5: Minor Changes
- Use `size_t' instead of `unsigned long long int'.
- Minor optimizations to the algorithm.
- Added commandline argument parsing.
- v0.6: User Control
- Allow user to choose base in which the prime numbers are printed.
- Give option for primes to be saved to a file upon exit.
- Free memory and leave instead of emergency exit.
- v0.7: Data Saving
- Allow user to save found primes to be loaded later.
- 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

View File

@ -14,20 +14,22 @@ set(CMAKE_MODULE_PATH
${CMAKE_SOURCE_DIR}/cmake/)
find_package(GMP REQUIRED)
find_package(OpenMP REQUIRED)
include_directories(
${GMP_INCLUDE_DIR})
set(SRCS
src/main.c
src/files.c
src/list.c)
# Define the C flags.
set(CMAKE_C_FLAGS "-std=gnu99 -Wall -Wextra -Werror -Wfatal-errors -Wmissing-declarations -pedantic-errors")
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS} -g -O0")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -O3")
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS} -g -O3")
set(CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS} -Os")
set(CMAKE_C_FLAGS "-std=gnu99 ${OpenMP_C_FLAGS} -Wall -Wextra -Werror -Wfatal-errors -Wmissing-declarations -pedantic-errors")
set(CMAKE_C_FLAGS_DEBUG "-g -O0")
set(CMAKE_C_FLAGS_RELEASE "-O3")
set(CMAKE_C_FLAGS_RELWITHDEBINFO "-g -O3")
set(CMAKE_C_FLAGS_MINSIZEREL "-Os")
if(NOT CMAKE_BUILD_TYPE MATCHES Debug AND NOT CMAKE_BUILD_TYPE MATCHES RelWithDebInfo)
add_definitions(-DNDEBUG)

View File

@ -1,6 +1,6 @@
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
------------------------
@ -8,7 +8,7 @@ The copyright of this project and all of its code, unless stated otherwise, belo
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
-------------
@ -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.
4) Fractured Merge Requests
---------------------------
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.
4) Fractured Patches
--------------------
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.

2489
Doxyfile Normal file

File diff suppressed because it is too large Load Diff

View File

@ -9,6 +9,7 @@ Building
There are multiple dependencies to install before compiling the project:
- CMake
- GMP
- OpenMP
Once the dependencies are installed you can compile by running the following from the root directory of the project:
```bash
@ -21,7 +22,7 @@ To build a release build run `cmake -DCMAKE_BUILD_TYPE=Release ..` instead.
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
-------

66
src/files.c Normal file
View File

@ -0,0 +1,66 @@
#include "files.h"
#include <stdio.h>
#include <gmp.h>
#include <assert.h>
int inputPrimes(char *file, List *list) {
// Assert safeguards
assert(file);
assert(list);
FILE *in = fopen(file, "r");
if(!in) return 1;
mpz_t n;
mpz_init(n);
while(mpz_inp_raw(n, in))
if(addToList(list, n) == 1) return 3;
mpz_clear(n);
if(fclose(in)) return 2;
return 0;
}
int outputPrimes(char *file, List *list, size_t startPos) {
// Assert safeguards
assert(file);
assert(list);
FILE *out = fopen(file, "a");
if(!out) return 1;
printf("Saving primes to `%s'...\n", file);
puts("0%");
for(size_t i = startPos; i < list->end; ++i) {
if(!mpz_out_raw(out, list->list[i])) return 3;
if(i == list->end / 4) puts("25%");
else if(i == list->end / 2) puts("50%");
else if(i == list->end * 3 / 4) puts("75%");
}
puts("100%");
if(fclose(out)) return 2;
return 0;
}
int exportPrimes(char *efile, char *dfile, int base) {
// Assert safeguards
assert(efile);
assert(dfile);
FILE *in = fopen(dfile, "r");
FILE *out = fopen(efile, "w");
if(!in || !out) return 1;
printf("Exporting primes to `%s'...\n", efile);
mpz_t n;
mpz_init(n);
while(mpz_inp_raw(n, in)) {
if(!mpz_out_str(out, base, n)) return 3;
fprintf(out, "\n");
}
if(fclose(in) || fclose(out)) return 2;
return 0;
}

39
src/files.h Normal file
View File

@ -0,0 +1,39 @@
/**
* @file files.h
* @author Deathsbreed <deathsbreed@themusicinnoise.net>
* @brief Functions to deal with file I/O of primes.
* @details Functions that input, output, and export primes from/to files.
*/
#pragma once
#include "list.h"
/**
* @brief Load primes from an Indivisible file into a List.
* @param file File to input primes from.
* @param list List to load primes into.
* @returns If 0 then load was successful, if 1 then failed to open,
* if 2 failed to close, if 3 failed to allocate new memory to List
* (see `addToList()')
*/
int inputPrimes(char *file, List *list);
/**
* @brief Output primes from a List into an Indivisible file.
* @param file File to output primes to.
* @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,
* if 2 failed to close, if 3 failed when writing.
*/
int outputPrimes(char *file, List *list, size_t startPos);
/**
* @brief Export primes from a List to a plain text file.
* @param efile File to export primes as plain text to.
* @param dfile File to read primes from.
* @param base The base in which the primes will be written.
* @returns If 0 then load was successful, if 1 then failed to open,
* if 2 failed to close, if 3 failed when writing.
*/
int exportPrimes(char *efile, char *dfile, int base);

View File

@ -1,44 +1,34 @@
#include "list.h"
#include <stdlib.h>
#include <stdio.h>
#include "optimizers.h"
/**
* This is the number of elements by which the list expands.
* WARNING: Always use doubles for this number (2^X)
*/
#define BLOCK_SIZE 1024
void initList(List *l) {
int initList(List *restrict l) {
l->list = malloc(sizeof(mpz_t) * BLOCK_SIZE);
if(!l->list) {
fprintf(stderr, "Failed to allocate memory to list!\n");
exit(1);
}
if(!l->list) return 1;
l->size = BLOCK_SIZE;
l->end = 0;
return 0;
}
void deInitList(List *l) {
void deInitList(List *restrict l) {
for(size_t i = 0; i < l->end; ++i) {
mpz_clear(l->list[i]);
}
free(l->list);
}
void addToList(List *l, mpz_t n) {
int addToList(List *restrict l, mpz_t n) {
if(l->end == l->size) {
l->size += BLOCK_SIZE;
if(unlikely(l->size == 0)) {
fprintf(stderr,
"size has reached limit of `long long int' type!\n");
exit(1);
}
void *tmp = realloc(l->list, sizeof(mpz_t) * l->size);
if(!tmp) {
fprintf(stderr, "Failed to allocate more memory to list!\n");
exit(1);
}
l->list = (mpz_t*)tmp;
if(!tmp) return 1;
l->list = tmp;
}
mpz_init(l->list[l->end]);
mpz_set(l->list[l->end++], n);
return 0;
}

View File

@ -1,36 +1,43 @@
/**
* @file list.h
* @author Deathsbreed <deathsbreed@themusicinnoise.net>
* @brief Code responsible for List management.
* @details Code responsible for the definition and management of the
* List object.
*/
#pragma once
#include <gmp.h>
#include <stdbool.h>
/**
* @brief An infinitely expanding list type.
*/
typedef struct {
mpz_t *list; //!< The list of elements
unsigned long long int size; //!< How many elements are in the list
unsigned long long int end; //!< The last element of the list (in use)
size_t size; //!< How many elements are in the list
size_t end; //!< The last element of the list (in use)
} List;
/**
* @brief Initialize a List.
* @details Initialize the list and its variables, allocating memory
* to the pointer array inside. Returns true on success and false on
* failure.
* to the pointer array inside.
* @param[in] l A pointer to a List type to be initialized.
* @returns Returns 0 if successful and 1 if failed.
*/
void initList(List *l);
int initList(List *restrict l);
/**
* @brief Deinitialize a List.
* @details Release all memory that has been allocated to the list.
* @param[in] l A pointer to a List type to be deinitialized.
*/
void deInitList(List *l);
void deInitList(List *restrict l);
/**
* @brief Adds a new item to 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[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);

View File

@ -2,64 +2,281 @@
#include <stdlib.h>
#include <signal.h>
#include <stdbool.h>
#include <unistd.h>
#include <gmp.h>
#include <omp.h>
#include <sys/stat.h>
#include "list.h"
#include "files.h"
#define VERSION "v1.0"
static bool run;
void printUsage(char *progName);
void leave();
int main(void) {
printf("Indivisible v0.2\n");
int main(int argc, char *argv[]) {
// Variables for argument parsing
bool f_help = false,
f_version = false,
f_quiet = false;
int base = 10;
size_t n_prime = 0;
char *dfile = NULL;
char *efile = NULL;
// Parse commandline arguments
int c;
while((c = getopt(argc, argv, "hvqb:f:e:n:")) != -1) {
switch(c) {
case 'h':
f_help = true;
break;
case 'v':
f_version = true;
break;
case 'q':
f_quiet = true;
break;
case 'b':
base = atoi(optarg);
if(base < 2 || base > 62) {
fprintf(stderr,
"Invalid base `%d'. Base must be between 2 and 62.\n",
base);
return 1;
}
break;
case 'f':
dfile = optarg;
break;
case 'e':
efile = optarg;
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:
printUsage(argv[0]);
return 1;
}
}
// Act based on which flags were used
if(f_help) {
printUsage(argv[0]);
puts("\nArguments:");
puts(" -h print this help information");
puts(" -v print version number of program");
puts(" -q quiet mode");
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(" -e <file> export input file to plain text format");
puts(" -n <n> run until the 'n'th prime\n");
return 0;
} else if(f_version) {
printf("Indivisible %s\n", VERSION);
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'
run = true;
signal(SIGINT, leave);
puts("Use Ctrl+C to exit.");
bool newFile = true;
if(dfile) {
struct stat s;
if(stat(dfile, &s) == 0) newFile = false;
}
// Last position added from file
size_t startPos = 0;
int exitCode = 0;
// Primes we've found
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
mpz_t num;
mpz_init(num);
// Add 2, a known prime to this list
mpz_set_ui(num, 2);
addToList(&primes, num);
if(mpz_out_str(stdout, 10, num) == 0) {
fprintf(stderr, "Could not print to `stdout'!\n");
exit(1);
// Variable for sqrt of `num'
mpz_t numRoot;
mpz_init(numRoot);
// Index of the prime number above and closest to `numRoot'
size_t rootInd = 0;
if(newFile) {
// Add 2, a known prime to this list
mpz_set_ui(num, 2);
if(addToList(&primes, num) == 1) {
fprintf(stderr, "Failed to allocate more memory for list.\n");
exitCode = 1;
goto releaseMemory;
}
// Add 3 as well to optimize the algorithm
mpz_set_ui(num, 3);
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");
}
} else {
// Load primes from file
int err = inputPrimes(dfile, &primes);
startPos = primes.end;
if(err == 0) {
printf("Loaded %zu primes.\n", primes.end);
} else {
if(err == 1)
fprintf(stderr, "Failed to open Indivisible file `%s'.\n", dfile);
else if(err == 2)
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;
goto releaseMemory;
}
/**
* I set to `primes.end-1' because primes.end indicates the next new
* 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]);
}
printf("\n");
mpz_add_ui(num, num, 1);
do {
// Loop through found primes
for(unsigned long long int i = 0; i < primes.size; ++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(mpz_out_str(stdout, 10, num) == 0) {
fprintf(stderr, "Could not print to `stdout'!\n");
exit(1);
}
printf("\n");
nextPrime:
// Add 2 (skip even numbers since they're all divisible by 2)
while(run) {
mpz_add_ui(num, num, 2);
} while(run);
// Calculate the sqrt(num)
mpz_sqrt(numRoot, num);
while(mpz_cmp(primes.list[rootInd], numRoot) <= 0) {
if(++rootInd > primes.end) {
fprintf(stderr, "Error: `rootInd' surpassed `primes.end'.\n");
exitCode = 1;
goto releaseMemory;
}
}
bool isPrime = true;
/**
* Loop through primes we've found until we get to the sqrt of the
* 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);
if(dfile) {
int err = outputPrimes(dfile, &primes, startPos);
if(err == 0) {
puts("Successfully saved primes.");
} else {
if(err == 1)
fprintf(stderr, "Failed to open/create file `%s'.\n", dfile);
else if(err == 2)
fprintf(stderr, "Failed to close file `%s'.\n", dfile);
else if(err == 3)
fprintf(stderr, "Failed while writing a prime to `%s'.\n", dfile);
exitCode = 1;
goto releaseMemory;
}
}
releaseMemory:
puts("Clearing memory...");
// Clear GMP variables
mpz_clear(numRoot);
mpz_clear(num);
// Deinitialize the list
deInitList(&primes);
return 0;
puts("Exit successful.");
return exitCode;
}
void leave() {
printf("Exiting...\n");
run = false;
void printUsage(char *progName) {
printf("%s [[-f <file> [-e <file> | -q]] [-b <base>] [-n <n>] | [-h] | [-v]]\n", progName);
}
void leave() { run = false; }

View File

@ -1,3 +0,0 @@
#pragma once
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)