Bifurcation depuis
Charles-Henry Bertrand Van Ouytsel / Projet3_first_pull_request
234 validations de retard, 60 validations d'avance sur le dépôt en amont.
-
Giovanna Stefanelli a rédigéGiovanna Stefanelli a rédigé
fact.c 8,49 Kio
//
// Modified on 09/05/2020.
//
#include <errno.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <stdbool.h>
//#include <time.h>
#include <pthread.h>
/* STRUCTURES AND VARIABLES */
/* "struct factorization"
* "prime_dividers" is an array containing max N dividers
* "cnt" is the number of calculated dividers
* "number" is number to calculate the prime dividers
*/
#define N 10 // Max number of dividers in the buffer
typedef struct factorization {
unsigned long prime_dividers[N];
unsigned int cnt;
unsigned long number;
} factor;
/* struct file_descriptors
* "in" is the inputfile file descriptor
* "out" is the outputfile file descriptor
* "options" "v" (verbose) with debugging information, "q" without debugging information
*/
typedef struct file_descriptors {
FILE *in;
FILE *out;
// char options; // For internal command test
} fd;
// Declare f (type fd). Structure containing the file descriptors
fd f;
/* MUTEX */
pthread_mutex_t mutex_readwrite; // define mutex variable
/*
* FUNCTIONS used in the programme:
* bool is_div(unsigned long, unsigned long);
* bool is_prime(unsigned long);
* factor *prime_divs(unsigned long);
* void *read_write(fd);
*/
bool is_div(unsigned long numbr, unsigned long i){
if((numbr % i) == 0) { // verify if i is the divider of numbr
return(true); // i is a divider of numbr
} else {
return(false); // i is not a divider of numbr
}
}
bool is_prime(unsigned long nbr) {
/*
* Optimised solution with less loop, see: https://fr.wikipedia.org/wiki/Nombre_premier
* "Crible d'Ératosthène:
* Les premiers algorithmes pour décider si un nombre est premier
* (appelés tests de primalité) consistent à essayer de le diviser par tous les nombres
* qui n'excèdent pas sa racine carrée"
*/
unsigned long j;
for (j = 2; j <= sqrt(nbr); j++) {
if ((nbr % j) == 0) { // verify if i is the divider of nbr
return (false); // i is a divider of nbr
}
}
return (true); // i is a prime number
}
factor* prime_divs (unsigned long numbr) {
factor *dividers; // Structure storing dividers and their number
/* Allocation of memory for "struct factor" and
* initialization the "dividers" struture to zero
* */
dividers = (factor *) calloc(1, sizeof(factor));
unsigned int n = 0;
dividers->number = numbr;
unsigned long tmp_number = dividers->number;
unsigned long i;
for(i = 2; i <= tmp_number ; i++) {
if(is_div(dividers->number,i) == true){
if(is_prime(i) == true){
dividers->prime_dividers[n] = i;
/* The max numbers of loops is reduced
* from "number" to "tmp_number/i"
* */
tmp_number = tmp_number/i;
if(i != dividers->number) {
n++;
}
}
}
}
dividers->cnt = n;
return(dividers);
}
void *read_write() {
factor *dividers;
long in_number;
unsigned long number;
long neg_number = 0;
// Read input file line by line till the end of file (eof)
while (!feof(f.in)) {
fscanf(f.in, "%ld\n", &in_number); // Read number to be factored
/* Check if the number is > 2
* in this case skip the number and
* leave a message in the file
*/
if((in_number > 2) || (in_number < -2)) {
/* Verify if the number is prime or not, in this case the dividers are calculated */
/* Handle negative number to calculate prime dividers *********NEW***********/
if(in_number < -2) {
neg_number = in_number;
}
number = abs(in_number);
dividers = prime_divs(number); // Core function of the app //
/* MUTEX LOCK - CONTROL OF CRITICAL ACCESS - START */
if (pthread_mutex_lock(&mutex_readwrite) != 0) {
printf("\nmutex_lock-mutex_readwrite %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
/* Handle negative number to calculate prime dividers *********NEW********** */
if (neg_number != 0) {
in_number = neg_number;
neg_number = 0;
}
if (dividers->cnt != 0) {
/* fprintf(f.out, "%lu ", dividers->number); ********** OLD *********** */
fprintf(f.out, "%ld", in_number); /* ********NEW********** */
int i;
for (i = 0; i < dividers->cnt; i++) {
fprintf(f.out, " %lu", dividers->prime_dividers[i]);
}
} else { // For internal command test
fprintf(f.out, "%ld", in_number); /* ********NEW********** */
/* fprintf(f.out, "%lu ", dividers->number); *********** OLD ********** */
}
/* MUTEX UNLOCK - CONTROL OF CRITICAL ACCESS - END */
if (pthread_mutex_unlock(&mutex_readwrite) != 0) {
printf("\nmutex_lock-mutex_readwrite %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
fprintf(f.out, "\n");
free(dividers);
} else {
fprintf(f.out, "%ld\n", in_number);
}
}
pthread_exit((void *) 0); // thread exit: normal termination => 0
}
#define DEFAULT_NO_THREADS 2
#define MAX_NO_THREADS 20
// MAIN PROGRAMME
int main (int argc, char *argv[]) {
// Input arguments
char *inputfile; // Input filemane (string)
char *outputfile; // Output filemane (string)
char *thread_arg; //
int NO_THREADS = DEFAULT_NO_THREADS; // Define default number of threads
/* WARNING: ONLY NUMBER POSITIVE AND >2 ARE ACCEPTED
*printf("!!! WARNING: ONLY POSITIVE NUMBER AND >2 ARE ACCEPTED !!!\n");
*printf(" OTHERWISE THE PROGRAMME CANNOT RUN CORRECTLY\n\n");
*/
if (argc == 3) { // Check if the number of argument is correct
inputfile = argv[1];
outputfile = argv[2];
printf("Thread number not mentioned\n");
printf("The default threads number is %d\n", DEFAULT_NO_THREADS);
} else if(argc == 5) {
thread_arg = argv[1];
if(strcmp(thread_arg, "-N") != 0) {
printf("%s\n", "Wrong input of the option\n Use option \"-N\"\n");
exit(EXIT_FAILURE);
}
NO_THREADS = atoi(argv[2]);
/* If the number of threads is <= 0 ************* VERSION UPDATE ***************
* NO_THREADS is set to DEFAULT_NO_THREADS
*/
if(NO_THREADS <= 0) {
NO_THREADS = 1;
printf("The threads number cannot be <= 0 - Threads number set to 1\n");
}
if(NO_THREADS > MAX_NO_THREADS) {
printf("Threads requested > %d\n", MAX_NO_THREADS);
exit(EXIT_FAILURE);
}
inputfile = argv[3];
outputfile = argv[4];
} else {
printf("%s\n", "Many or few arguments\n");
printf("Correct command syntax:\n");
printf("./fact [-N number_of_threads] input_file.txt output_file.txt\n\n");
exit(EXIT_FAILURE);
}
/*
* START CLOCK to measure CPU time
* calculate programme performance
*/
/*
clock_t start, end;
double cpu_time_used;
start = clock();
*/
// Open input and output files
f.in = fopen(inputfile, "r");
f.out = fopen(outputfile, "a+");
if ((f.in == NULL) || (f.out == NULL)) {
printf("Incorrect input_file or output_file name\n");
exit(EXIT_FAILURE);
}
pthread_t thread[NO_THREADS]; // thread IDs
// INITIALIZE MUTEX "mutex_readwrite"
if (pthread_mutex_init(&mutex_readwrite , NULL) != 0){
printf("\n mutex init failed-mutex_readwrite\n");
exit(EXIT_FAILURE);
}
int i;
for (i = 0; i < NO_THREADS; i++) {
pthread_create(&thread[i], NULL, (void*)read_write, NULL);
}
for (i = 0; i < NO_THREADS; i++) {
pthread_join(thread[i], NULL);
}
/* END CLOCK to measure CPU time */
/*
end = clock();
cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;
fprintf(f.out, "\nThe programme execution needed %.3f seconds\n\n", cpu_time_used);
printf("\nThe programme execution needed %.3f seconds", cpu_time_used);
printf("\n -- Programme end --\n");
*/
// Eliminate mutex "mutex_readwrite"
if (pthread_mutex_destroy(&mutex_readwrite) != 0){
printf("\nmutex_destroy-mutex_readwrite %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
fclose(f.in);
fclose(f.out);
return (EXIT_SUCCESS);
}