diff --git a/.gitignore b/.gitignore index e5a1754..f5e9da1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ -# Ignore build files -build/* -!build/.keep +# Ignore binary files +*.o +indivisible # Ignore vim temporary files *.sw[a-z] diff --git a/CHANGELOG b/CHANGELOG index 4d29873..e9fc744 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -37,6 +37,5 @@ Change Log - Allow searching for the nth prime number - Clearing some memory leaks - v2.0: Linked List - - Implement linked list for faster addition to list. - - Multi-Processor support (MPI). - Code cleanup. + - Replace OpenMP code with OpenMPI diff --git a/CMakeLists.txt b/CMakeLists.txt deleted file mode 100644 index b83f93e..0000000 --- a/CMakeLists.txt +++ /dev/null @@ -1,68 +0,0 @@ -# Copyright (C) 2017 Ortega Froysa, Nicolás -# Author: Ortega Froysa, Nicolás -# -# 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 . - -cmake_minimum_required(VERSION 3.0) -project(Indivisible C) - -set(TARGET_NAME indivisible) -set(TARGET_VERSION "v2.0") - -if(NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE "release") -endif() -string(TOLOWER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE) -message(STATUS "Build type: ${CMAKE_BUILD_TYPE}") - -set(CMAKE_MODULE_PATH - ${CMAKE_MODULE_PATH} - ${CMAKE_SOURCE_DIR}/cmake/) - -find_package(GMP REQUIRED) -find_package(MPI REQUIRED) - -include_directories( - ${MPI_C_INCLUDE_PATH} - ${GMP_INCLUDE_DIR}) - -set(SRCS - "src/linked_list.c" - "src/main.c") - -set(CMAKE_C_COMPILER ${MPI_C_COMPILER}) - -# Define the C flags. -set(CMAKE_C_FLAGS "-std=gnu99 ${MPI_C_COMPILE_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") -else() - add_definitions("-DDEBUG") -endif() - -add_definitions("-DVERSION=\"${TARGET_VERSION}\"") - -add_executable(${TARGET_NAME} ${SRCS}) - -target_link_libraries(${TARGET_NAME} - ${MPI_C_LIBRARIES} - ${GMP_LIBRARY}) - -install(TARGETS ${TARGET_NAME} - RUNTIME DESTINATION "bin") diff --git a/LICENSE b/LICENSE index 9cecc1d..94a9ed0 100644 --- a/LICENSE +++ b/LICENSE @@ -631,8 +631,8 @@ to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. - {one line to give the program's name and a brief idea of what it does.} - Copyright (C) {year} {name of author} + + Copyright (C) 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 @@ -652,7 +652,7 @@ Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: - {project} Copyright (C) {year} {fullname} + Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..6286554 --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +# Copyright (C) 2019 Ortega Froysa, Nicolás +# Author: Ortega Froysa, Nicolás +# +# 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 . + +CC=gcc +DEBUG=0 +PREFIX=/usr/local +INCFLAGS= +LDFLAGS=-lgmp +DEFS=-DVERSION=\"2.0\" -DAPP_NAME=\"Indivisible\" +CFLAGS=$(INCFLAGS) $(DEFS) -std=c99 -Wall -Wextra -Wfatal-errors -Werror +HDRS=src/globals.h +OBJS=src/main.o + +ifeq ($(DEBUG),1) + CFLAGS+=-g -O0 -DDEBUG +else + CFLAGS+=-O2 -DNDEBUG +endif + +%.o:%.c $(HDRS) + $(CC) -c -o $@ $< $(CFLAGS) + +indivisible: $(OBJS) + $(CC) -o $@ $^ $(LDFLAGS) + +.PHONY: clean distclean install + +clean: + $(RM) $(OBJS) + +distclean: clean + $(RM) indivisible + +install: indivisible + install -m 755 indivisible $(PREFIX)/bin/ diff --git a/README b/README index 16c6ac5..f3d22ed 100644 --- a/README +++ b/README @@ -1,32 +1,35 @@ =================== *** Indivisible *** =================== -Indivisible is a parallelized prime number generator written in C. +A parallelized prime number generator written in C. It uses a bignum +library as well as OpenMPI for parallelization. # Building ---------- -There are multiple dependencies to install before compiling the project: +## Dependencies +The dependencies for compiling are minimal, and should be available +on most UNIX-like systems: + - GNU Make + - C99 Compiler (GCC is recommended) + - GNU Multi-Precision Arithmetics Library (GMP) + - OpenMPI - - CMake build system - - GNU Multi-Precision Arithmetics Library - -Once the dependencies are installed you can compile by running the following -from the root directory of the project: - - cd build/ - cmake .. - make - -This will create a release build, to build with debug options append the -`-DCMAKE_BUILD_TYPE=debug' flag to the `cmake' command. +## Compiling +To compile you simply need to run the `make` command, which will +create the `indivisible` binary file. Additionally you can set the +following flags by appending them to the `make` command: + - `DEBUG=<1|0>`: whether to create a debug or release build. (0 by + default) + - `PREFIX=`: what base prefix to install the binaries at. + (`/usr/local` by default) # Contributing -------------- -To contribute to indivisible you can send patch files to my e-mail[0]. - -[0] nortega@themusicinnoise.net +To contribute to the project, please follow the same coding style you +see in the current code base. Then, either submit a pull request or send +a patch file to . # License --------- -This project is licensed under the GNU General Public License version 3 or -greater (see `LICENSE' for more information). +This project is licensed under the terms & conditions of the GNU General +Public License version 3 or greater (see `LICENSE` file). diff --git a/build/.keep b/build/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/cmake/FindGMP.cmake b/cmake/FindGMP.cmake deleted file mode 100644 index c85990d..0000000 --- a/cmake/FindGMP.cmake +++ /dev/null @@ -1,24 +0,0 @@ -# SOURCE: http://stackoverflow.com/questions/29307862/error-linking-gmp-library -set(GMP_PREFIX "" CACHE PATH "path ") - -find_path(GMP_INCLUDE_DIR gmp.h gmpxx.h - PATHS ${GMP_PREFIX}/include /usr/include /usr/local/include ) - -find_library(GMP_LIBRARY NAMES gmp libgmp - PATHS ${GMP_PREFIX}/lib /usr/lib /usr/local/lib) - - -if(GMP_INCLUDE_DIR AND GMP_LIBRARY) - get_filename_component(GMP_LIBRARY_DIR ${GMP_LIBRARY} PATH) - set(GMP_FOUND TRUE) -endif() - -if(GMP_FOUND) - if(NOT GMP_FIND_QUIETLY) - MESSAGE(STATUS "Found GMP: ${GMP_LIBRARY}") - endif() -else() - if(GMP_FIND_REQUIRED) - message(FATAL_ERROR "Could not find GMP") - endif() -endif() diff --git a/src/global.h b/src/global.h deleted file mode 100644 index 95922b7..0000000 --- a/src/global.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2018 Ortega Froysa, Nicolás - * Author: Ortega Froysa, Nicolás - * - * 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 . - */ - -#pragma once - -#ifndef VERSION -# define VERSION "version" -#endif - -/* argp variables */ -const char *argp_program_version = VERSION; -const char *argp_program_bug_address = ""; - -/* argp options */ -static char desc[] = "A parallelized prime number generator."; -/*static char args_doc[] = "--count= [--verbose]";*/ -static struct argp_option opts[] = { - { "count", 'c', "number", 0, "The number of primes to generate (default is 1000)", 0}, - { "verbose", 'v', 0, 0, "Print out discovered primes", 0 }, - { 0 } -}; - -struct args { - size_t count; - int verbose; -}; - -static error_t parse_opt(int key, char *arg, struct argp_state *state) { - struct args *args = state->input; - switch(key) - { - case 'c': - args->count = (size_t)atol(arg); - break; - case 'v': - args->verbose = 1; - break; - case ARGP_KEY_ARG: - return 0; - default: - return ARGP_ERR_UNKNOWN; - } - return 0; -} - -static struct argp argp = { opts, parse_opt, 0, desc, 0, 0, 0 }; diff --git a/src/linked_list.h b/src/globals.h similarity index 58% rename from src/linked_list.h rename to src/globals.h index f3e3ccc..154c2d7 100644 --- a/src/linked_list.h +++ b/src/globals.h @@ -1,6 +1,6 @@ /* - * Copyright (C) 2018 Ortega Froysa, Nicolás - * Author: Ortega Froysa, Nicolás + * Copyright (C) 2019 Ortega Froysa, Nicolás + * Author: Ortega Froysa, Nicolás * * 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 @@ -18,20 +18,10 @@ #pragma once -#include +#ifndef APP_NAME +#define APP_NAME "app name" +#endif -struct llist_item { - mpz_t num; - struct llist_item *prev; - struct llist_item *next; -}; - -struct llist { - struct llist_item *first; - struct llist_item *last; - size_t size; // size of the list -}; - -void llist_init(struct llist *list); -int llist_add(struct llist *list, mpz_t num); -void llist_deinit(struct llist *list); +#ifndef VERSION +#define VERSION "version" +#endif diff --git a/src/linked_list.c b/src/linked_list.c deleted file mode 100644 index 73c5727..0000000 --- a/src/linked_list.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2018 Ortega Froysa, Nicolás - * Author: Ortega Froysa, Nicolás - * - * 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 . - */ - -#include "linked_list.h" - -#include - -void llist_init(struct llist *list) { - list->size = 0; - list->first = NULL; - list->last = NULL; -} - -int llist_add(struct llist *list, mpz_t num) { - struct llist_item *item = - malloc(sizeof(struct llist_item)); - if(!item) - return 0; - - mpz_init(item->num); - mpz_set(item->num, num); - - if(!(list->first)) - { - list->first = item; - list->last = item; - } - else - { - list->last->next = item; - list->last = item; - } - list->size++; - - return 1; -} - -void llist_deinit(struct llist *list) { - struct llist_item *i = list->first; - - while(i) - { - mpz_clear(i->num); - struct llist_item *next = i->next; - free(i); - i = next; - } - - list->size = 0; -} diff --git a/src/main.c b/src/main.c index 089609d..25af0a5 100644 --- a/src/main.c +++ b/src/main.c @@ -1,6 +1,6 @@ /* - * Copyright (C) 2018 Ortega Froysa, Nicolás - * Author: Ortega Froysa, Nicolás + * Copyright (C) 2019 Ortega Froysa, Nicolás + * Author: Ortega Froysa, Nicolás * * 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 @@ -16,75 +16,56 @@ * along with this program. If not, see . */ +#include "globals.h" + +#include #include -#include -#include #include -#include "global.h" -#include "linked_list.h" +int run = 1; -int main(int argc, char *argv[]) { - struct args args = { 1000, 0 }; +void quit_signal(int signum) { + printf("Received signal %d. Ending process...\n", signum); + run = 0; +} - argp_parse(&argp, argc, argv, 0, 0, &args); +int main() { + printf("%s v%s\n", APP_NAME, VERSION); - if(args.count == 0) + signal(SIGINT, quit_signal); + + mpz_t tnum; // number to be tested for prime-ness + mpz_t tsqrt; // square root of tnum + mpz_t aux; // auxilary number to test against tnum + mpz_t r; // remainder from modulus operation + + mpz_inits(tnum, tsqrt, aux, r, NULL); + mpz_set_ui(tnum, 3); + mpz_sqrt(tsqrt, tnum); + + while(run) { - fprintf(stderr, "ERROR: count must be larger than 0.\n"); - return 1; - } - - struct llist prime_list; - llist_init(&prime_list); - - { - // initialize the list with 2 - mpz_t tmp; - mpz_init(tmp); - mpz_set_ui(tmp, 2); - llist_add(&prime_list, tmp); - mpz_clear(tmp); - if(args.verbose) - puts("2"); - } - - mpz_t aux; - mpz_init(aux); - mpz_set_ui(aux, 3); - while(prime_list.size < args.count) - { - struct llist_item *item = prime_list.first; + mpz_set_ui(aux, 3); int is_prime = 1; - - mpz_t root; - mpz_init(root); - mpz_sqrt(root, aux); - while(item && mpz_cmp(item->num, root) < 0) + while(mpz_cmp(aux, tsqrt) <= 0) { - if(mpz_divisible_p(aux, item->num)) - { + mpz_mod(r, tnum, aux); + if(mpz_cmp_ui(r, 0) == 0) is_prime = 0; - break; - } - item = item->next; + mpz_add_ui(aux, aux, 2); } + if(is_prime) { - llist_add(&prime_list, aux); - if(args.verbose) - { - mpz_out_str(stdout, 10, aux); - printf("\n"); - } + mpz_out_str(stdout, 10, tnum); + printf("\n"); } - mpz_add_ui(aux, aux, 2); + + mpz_add_ui(tnum, tnum, 2); + mpz_sqrt(tsqrt, tnum); } - printf("The %zu prime is ", prime_list.size); - mpz_out_str(stdout, 10, prime_list.last->num); - printf("\n"); + mpz_clears(tnum, tsqrt, aux, r, NULL); - llist_deinit(&prime_list); return 0; }