Compare commits
29 Commits
Author | SHA1 | Date | |
---|---|---|---|
2afe144e7f | |||
a988711918 | |||
74a82e2038 | |||
659bdeee27 | |||
d39a51baa2 | |||
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
|
||||
- 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
|
||||
|
@ -1,3 +1,19 @@
|
||||
# Copyright (C) 2017 Ortega Froysa, Nicolás <deathsbreed@themusicinnoise.net>
|
||||
# Author: Ortega Froysa, Nicolás <deathsbreed@themusicinnoise.net>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
project(Indivisible)
|
||||
|
||||
@ -6,8 +22,10 @@ cmake_policy(SET CMP0012 OLD)
|
||||
set(TARGET_NAME indivisible)
|
||||
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE Debug)
|
||||
set(CMAKE_BUILD_TYPE "debug")
|
||||
endif()
|
||||
string(TOLOWER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE)
|
||||
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
|
||||
|
||||
set(CMAKE_MODULE_PATH
|
||||
${CMAKE_MODULE_PATH}
|
||||
@ -31,11 +49,14 @@ 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)
|
||||
if(NOT CMAKE_BUILD_TYPE MATCHES "debug" AND NOT CMAKE_BUILD_TYPE MATCHES "relwithdebinfo")
|
||||
add_definitions("-DNDEBUG")
|
||||
endif()
|
||||
|
||||
add_executable(${TARGET_NAME} ${SRCS})
|
||||
|
||||
target_link_libraries(${TARGET_NAME}
|
||||
${GMP_LIBRARY})
|
||||
|
||||
install(TARGETS ${TARGET_NAME}
|
||||
RUNTIME DESTINATION "bin")
|
||||
|
@ -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.
|
||||
|
@ -22,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
|
||||
-------
|
||||
|
91
src/files.c
91
src/files.c
@ -1,3 +1,21 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Ortega Froysa, Nicolás <deathsbreed@themusicinnoise.net>
|
||||
* Author: Ortega Froysa, Nicolás <deathsbreed@themusicinnoise.net>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "files.h"
|
||||
#include <stdio.h>
|
||||
#include <gmp.h>
|
||||
@ -5,57 +23,62 @@
|
||||
|
||||
int inputPrimes(char *file, List *list) {
|
||||
// Assert safeguards
|
||||
assert(file != NULL);
|
||||
assert(list != NULL);
|
||||
assert(file);
|
||||
assert(list);
|
||||
|
||||
FILE *pFile = fopen(file, "r");
|
||||
if(pFile == NULL) return 1;
|
||||
FILE *in = fopen(file, "r");
|
||||
if(!in) return 1;
|
||||
mpz_t n;
|
||||
mpz_init(n);
|
||||
while(mpz_inp_raw(n, pFile) != 0) addToList(list, n);
|
||||
if(fclose(pFile) != 0) return 2;
|
||||
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) {
|
||||
int outputPrimes(char *file, List *list, size_t startPos) {
|
||||
// Assert safeguards
|
||||
assert(file != NULL);
|
||||
assert(list != NULL);
|
||||
assert(file);
|
||||
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);
|
||||
puts("0%");
|
||||
for(size_t i = 0; i < list->end; ++i) {
|
||||
if(mpz_out_raw(oFile, list->list[i]) == 0) 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%");
|
||||
for(size_t i = startPos; i < list->end; ++i) {
|
||||
if(!mpz_out_raw(out, list->list[i])) return 3;
|
||||
if(i - startPos == (list->end - startPos) / 4) puts("25%");
|
||||
else if(i - startPos == (list->end - startPos) / 2) puts("50%");
|
||||
else if(i - startPos == (list->end - startPos) * 3 / 4) puts("75%");
|
||||
}
|
||||
puts("100%");
|
||||
if(fclose(oFile) != 0) return 2;
|
||||
|
||||
if(fclose(out)) return 2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int exportPrimes(char *file, List *list, int base) {
|
||||
int exportPrimes(char *efile, char *dfile, int base) {
|
||||
// Assert safeguards
|
||||
assert(file != NULL);
|
||||
assert(list != NULL);
|
||||
assert(list->list != NULL);
|
||||
assert(efile);
|
||||
assert(dfile);
|
||||
|
||||
FILE *eFile = fopen(file, "w");
|
||||
if(eFile == NULL) return 1;
|
||||
printf("Exporting primes to `%s'...\n", file);
|
||||
puts("0%");
|
||||
for(size_t i = 0; i < list->end; ++i) {
|
||||
if(mpz_out_str(eFile, base, list->list[i]) == 0) return 3;
|
||||
fprintf(eFile, "\n");
|
||||
if(i == list->end / 4) puts("25%");
|
||||
else if(i == list->end / 2) puts("50%");
|
||||
else if(i == list->end * 3 / 4) puts("75%");
|
||||
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");
|
||||
}
|
||||
puts("100%");
|
||||
if(fclose(eFile) != 0) return 2;
|
||||
puts("Finished exporting primes.");
|
||||
|
||||
if(fclose(in) || fclose(out)) return 2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
31
src/files.h
31
src/files.h
@ -1,3 +1,21 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Ortega Froysa, Nicolás <deathsbreed@themusicinnoise.net>
|
||||
* Author: Ortega Froysa, Nicolás <deathsbreed@themusicinnoise.net>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file files.h
|
||||
* @author Deathsbreed <deathsbreed@themusicinnoise.net>
|
||||
@ -12,7 +30,8 @@
|
||||
* @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 2 failed to close, if 3 failed to allocate new memory to List
|
||||
* (see `addToList()')
|
||||
*/
|
||||
int inputPrimes(char *file, List *list);
|
||||
|
||||
@ -20,17 +39,19 @@ 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);
|
||||
int outputPrimes(char *file, List *list, size_t startPos);
|
||||
|
||||
/**
|
||||
* @brief Export primes from a List to a plain text file.
|
||||
* @param file File to output primes as plain text to.
|
||||
* @param list List to read primes from.
|
||||
* @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 *file, List *list, int base);
|
||||
int exportPrimes(char *efile, char *dfile, int base);
|
||||
|
37
src/list.c
37
src/list.c
@ -1,39 +1,52 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Ortega Froysa, Nicolás <deathsbreed@themusicinnoise.net>
|
||||
* Author: Ortega Froysa, Nicolás <deathsbreed@themusicinnoise.net>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "list.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/**
|
||||
* This is the number of elements by which the list expands.
|
||||
*/
|
||||
#define BLOCK_SIZE 1024
|
||||
|
||||
void initList(List *restrict 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 *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]);
|
||||
}
|
||||
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;
|
||||
void *tmp = realloc(l->list, sizeof(mpz_t) * l->size);
|
||||
if(!tmp) {
|
||||
fprintf(stderr, "Failed to allocate more memory to list!\n");
|
||||
exit(1);
|
||||
}
|
||||
if(!tmp) return 1;
|
||||
l->list = tmp;
|
||||
}
|
||||
mpz_init(l->list[l->end]);
|
||||
mpz_set(l->list[l->end++], n);
|
||||
return 0;
|
||||
}
|
||||
|
25
src/list.h
25
src/list.h
@ -1,3 +1,21 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Ortega Froysa, Nicolás <deathsbreed@themusicinnoise.net>
|
||||
* Author: Ortega Froysa, Nicolás <deathsbreed@themusicinnoise.net>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file list.h
|
||||
* @author Deathsbreed <deathsbreed@themusicinnoise.net>
|
||||
@ -7,7 +25,6 @@
|
||||
*/
|
||||
#pragma once
|
||||
#include <gmp.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/**
|
||||
* @brief An infinitely expanding list type.
|
||||
@ -23,8 +40,9 @@ typedef struct {
|
||||
* @details Initialize the list and its variables, allocating memory
|
||||
* 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 *restrict l);
|
||||
int initList(List *restrict l);
|
||||
|
||||
/**
|
||||
* @brief Deinitialize a List.
|
||||
@ -38,5 +56,6 @@ void deInitList(List *restrict l);
|
||||
* @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);
|
||||
|
216
src/main.c
216
src/main.c
@ -1,16 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Ortega Froysa, Nicolás <deathsbreed@themusicinnoise.net>
|
||||
* Author: Ortega Froysa, Nicolás <deathsbreed@themusicinnoise.net>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#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 "v0.7"
|
||||
#define VERSION "v1.0"
|
||||
|
||||
static bool run;
|
||||
|
||||
@ -23,12 +42,13 @@ int main(int argc, char *argv[]) {
|
||||
f_version = false,
|
||||
f_quiet = false;
|
||||
int base = 10;
|
||||
char *file = NULL;
|
||||
size_t n_prime = 0;
|
||||
char *dfile = NULL;
|
||||
char *efile = NULL;
|
||||
|
||||
// Parse commandline arguments
|
||||
int c;
|
||||
while((c = getopt(argc, argv, "hvqb:f:e:")) != -1) {
|
||||
while((c = getopt(argc, argv, "hvqb:f:e:n:")) != -1) {
|
||||
switch(c) {
|
||||
case 'h':
|
||||
f_help = true;
|
||||
@ -45,15 +65,23 @@ int main(int argc, char *argv[]) {
|
||||
fprintf(stderr,
|
||||
"Invalid base `%d'. Base must be between 2 and 62.\n",
|
||||
base);
|
||||
exit(1);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 'f':
|
||||
file = optarg;
|
||||
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;
|
||||
@ -63,153 +91,207 @@ int main(int argc, char *argv[]) {
|
||||
// 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) {
|
||||
int err = exportPrimes(efile, dfile, base);
|
||||
if(err) {
|
||||
if(err == 1) fprintf(stderr, "Error: failed to open files.\n");
|
||||
else if(err == 2) fprintf(stderr, "Error: failed to close files.\n");
|
||||
else if(err == 3) fprintf(stderr, "Error: failed to write to export file.\n");
|
||||
return 1;
|
||||
}
|
||||
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);
|
||||
|
||||
if(efile != NULL && file == NULL) {
|
||||
fprintf(stderr, "There must be an input file to export! Use `-h' for help.\n");
|
||||
return 1;
|
||||
}
|
||||
puts("Use Ctrl+C to exit.");
|
||||
|
||||
bool newFile = true;
|
||||
if(file != NULL) {
|
||||
if(dfile) {
|
||||
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;
|
||||
|
||||
// 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);
|
||||
|
||||
// Variable for half `num'
|
||||
mpz_t halfNum;
|
||||
mpz_init(halfNum);
|
||||
|
||||
if(efile == NULL) puts("Use Ctrl+C to exit.");
|
||||
// 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);
|
||||
addToList(&primes, num);
|
||||
if(!f_quiet) {
|
||||
if(mpz_out_str(stdout, base, num) == 0) {
|
||||
fprintf(stderr, "Could not print to `stdout'!\n");
|
||||
if(addToList(&primes, num) == 1) {
|
||||
fprintf(stderr, "Failed to allocate more memory for list.\n");
|
||||
exitCode = 1;
|
||||
goto releaseMemory;
|
||||
}
|
||||
printf("\n");
|
||||
// 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");
|
||||
}
|
||||
mpz_add_ui(num, num, 1);
|
||||
} else {
|
||||
// Load primes from file
|
||||
int err = inputPrimes(file, &primes);
|
||||
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", file);
|
||||
fprintf(stderr, "Failed to open Indivisible file `%s'.\n", dfile);
|
||||
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;
|
||||
goto releaseMemory;
|
||||
}
|
||||
/**
|
||||
* Yes, I realize there's a -1 here, I don't know why but it won't
|
||||
* work if it's not there, so don't change it unless necessary.
|
||||
* 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]);
|
||||
}
|
||||
|
||||
if(efile != NULL) {
|
||||
int err = exportPrimes(efile, &primes, base);
|
||||
while(run) {
|
||||
mpz_add_ui(num, num, 2);
|
||||
|
||||
if(err == 0) {
|
||||
puts("Successfully exported primes.");
|
||||
} 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);
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
do {
|
||||
// Calculate half of `num'
|
||||
mpz_fdiv_q_ui(halfNum, num, 2);
|
||||
bool isPrime = true;
|
||||
/**
|
||||
* Loop through primes we've found until we get to half of the number
|
||||
* we're analyzing
|
||||
* 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.
|
||||
*/
|
||||
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;
|
||||
#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
|
||||
addToList(&primes, num);
|
||||
if(!f_quiet) {
|
||||
if(mpz_out_str(stdout, base, num) == 0) {
|
||||
fprintf(stderr, "Could not print to `stdout'!\n");
|
||||
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;
|
||||
}
|
||||
|
||||
nextPrime:
|
||||
// Add 2 (skip even numbers since they're all divisible by 2)
|
||||
mpz_add_ui(num, num, 2);
|
||||
} while(run);
|
||||
|
||||
printf("Found %zu primes.\n", primes.end);
|
||||
|
||||
if(file != NULL) {
|
||||
int err = outputPrimes(file, &primes);
|
||||
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", file);
|
||||
fprintf(stderr, "Failed to open/create file `%s'.\n", dfile);
|
||||
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)
|
||||
fprintf(stderr, "Failed while writing a prime to `%s'.\n", file);
|
||||
fprintf(stderr, "Failed while writing a prime to `%s'.\n", dfile);
|
||||
exitCode = 1;
|
||||
goto releaseMemory;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Clear GMP variables
|
||||
mpz_clear(halfNum);
|
||||
mpz_clear(num);
|
||||
|
||||
releaseMemory:
|
||||
puts("Clearing memory...");
|
||||
// Clear GMP variables
|
||||
mpz_clear(numRoot);
|
||||
mpz_clear(num);
|
||||
// Deinitialize the list
|
||||
deInitList(&primes);
|
||||
|
||||
@ -218,7 +300,7 @@ releaseMemory:
|
||||
}
|
||||
|
||||
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; }
|
||||
|
Reference in New Issue
Block a user