diff --git a/Makefile b/Makefile index 78270267f8c292d95de00faae50c3fbf0ec8bfd6..1c08db7e0a073b6572a77bba1010af6a403dbe15 100644 --- a/Makefile +++ b/Makefile @@ -2,8 +2,11 @@ fact : main.o run.o gcc -g -std=c99 -o fact run.o main.o -lpthread -test : test.o run.o - gcc -g -std=c99 -o test test.o run.o -lpthread -lcunit && ./test +test_ex : test.o run.o + gcc -g -std=c99 -o test test.o run.o -lpthread -lcunit + +test : test_ex + ./test run.o : run.c run.h gcc -g -std=c99 -o run.o -c run.c -W -Wall -lpthread @@ -17,7 +20,7 @@ test.o : test.c run.h clean : - rm -rf test fact *.o *.xml "actual_output.txt" "output.txt" + rm -rf test_ex fact *.o *.xml "actual_output.txt" "output.txt" cpp : run.c test.c cppcheck --enable=all run.c && cppcheck --enable=all test.c diff --git a/README.md b/README.md index c81bac848a29b44260616a57eaf31a6ec492bc28..804b4a5403930d033026558894de0d4f1ca9e714 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,7 @@ Le travail est décomposé en 3 sections coordonnées via un double problème du * N threads s'occupent de : * récupérer les chaines de caractères dans le premier tableau - * les convertir en 'unsigned long long' et calculer leur liste de diviseurs premiers + * les convertir en 'unsigned long long' et calculer leur liste de diviseurs premiers grâce au test de primalité de Fermat * Stocker ces listes dans un 2e tableau @@ -74,15 +74,19 @@ Note : * Les diviseurs premiers d'un même nombre sont stockés dans une circular linked list +* Le nombre de threads de calcul par défaut est 4 + ## Architecture des tests : -6 tests sont réalisés afin de tester: +10 tests sont réalisés afin de vérifier: -* La fonction is_div -* La fonction is_prime (2 tests) +* "is_div" (2 tests) +* "is_prime" (2 tests) +* "mod_pow" +* "randomiser" * Le fonctionnement complet pour un fichier vide (N = 4) -* Le fonctionnement complet pour un fichier d'une ligne : check du format et des diviseurs (N = 4) -* Le fonctionnement complet pour un fichier de 100 lignes : check du nombre de lignes (réalisé avec N = 4 puis N = 1) +* Le fonctionnement complet pour un fichier d'une ligne : check du format et des diviseurs (N = 4) +* Le fonctionnement complet pour un fichier de 100 lignes : check du nombre de lignes (réalisé avec N = 4 puis N = 1) # lepl1503-2020-groupe-M2 diff --git a/Test_files/big_numb_input.txt b/Test_files/big_numb_input.txt index 44ea552b43d405f983049ae739f006c1cd9c3a0a..54228a4c68a5d60eaef18a4125096880b9ad3133 100644 --- a/Test_files/big_numb_input.txt +++ b/Test_files/big_numb_input.txt @@ -1,4 +1 @@ 4856742312 -213486416658 -16975134987934 -2378974143134643 diff --git a/run.c b/run.c index a377d56709987c642f8859c05b0954a9d6322b60..5957b7cdc8fcbebf10e9fe9126a6f218e7098da4 100755 --- a/run.c +++ b/run.c @@ -1,4 +1,5 @@ #include "run.h" +#define uint_64 unsigned long long void put_in_buffer_1(char *c, struct buffer_rc *ptr){ //ajouter un element dans le buffer 1 @@ -40,26 +41,65 @@ queue_t *get_from_buffer_2(struct buffer_cw *buf){ // trouver un element } -int is_div(unsigned long long number, unsigned long long i) { // Vérifie si i est un diviseur de number. +int is_div(uint_64 number, uint_64 i) { // Vérifie si i est un diviseur de number. + if (i == 0){return 0;} + return (number % i == 0) ; // renvoie 0 si le nombre n'est pas divisible par i et 1 si il est divisible } +uint_64 modpow (uint_64 base, uint_64 exp, uint_64 mod){ -int is_prime(unsigned long long number) { // Vérifie si number est un nombre premier. Return 1 si il est premier, 0 sinon - if (number != 2) { - if (number % 2 == 0) { - return 0 ; + uint_64 result = 1; + + while (exp > 0) + { + if ((exp & 1) > 0) { + result = (result * base) % mod; } + exp >>= 1; + base = (base * base) % mod; } - for (unsigned long long i = 3 ; i*i <= number; i = i + 2) { //regarde les differents nombres pouvant etre diviser number - if (is_div(number,i) != 0) { // si i peut diviser number - return 0 ; //renvoi 0 => FAUX + return result; +} + +uint_64* randomiser (int k, uint_64 N){ + + uint_64 *result; + result = malloc(sizeof(uint_64)*k); + srand(time(NULL)); + for (int i = 0; i < k; i++) + { + result[i] = rand() % (N-1) +1; + } + return result; + +} + +int is_prime (uint_64 number){ + + uint_64 *random; + int k; + if (number <= 20){k = number-1;} + else{k = 20;} + random = randomiser(k,number); + for (int i = 0; i < k; i++) + { + if (modpow(random[i],number-1,number) == 1) + { + continue; } + else{ + free(random); + return 0; + } + } - return 1 ; //sinon => VRAI + free(random); + return 1; + } -void enqueue(queue_t* q, unsigned long long val){ +void enqueue(queue_t* q, uint_64 val){ struct node *ptr; ptr = malloc(sizeof(node_t)); @@ -82,7 +122,7 @@ void enqueue(queue_t* q, unsigned long long val){ } -queue_t* prime_divs(unsigned long long number){ +queue_t* prime_divs(uint_64 number){ queue_t *ptr; ptr = malloc(sizeof(queue_t)); @@ -92,7 +132,7 @@ queue_t* prime_divs(unsigned long long number){ ptr->size = 0; ptr->final = 0; - for (unsigned long long i = 2; i <= number/2; i++){ + for (uint_64 i = 2; i <= number/2; i++){ if (is_div(number, i) && is_prime(i) == 1){ enqueue(ptr,i); } @@ -108,7 +148,7 @@ void *writing(void *param){ struct buffer_cw *param1 = (struct buffer_cw *) param; int stop = 0; - while(param1->stop == 0){ + while(1){ sem_wait(&full2); pthread_mutex_lock(&mutex2); @@ -151,10 +191,7 @@ void *writing(void *param){ free(pr_divs->tail); free(pr_divs); } - - } - return NULL; } @@ -164,9 +201,8 @@ void *calculating(void *param){ struct buffer_rc *buffer_1 = param1->struct1; struct buffer_cw *buffer_2 = param1->struct2; - unsigned long long number; - while(buffer_1->stop == 0){ + while(1){ sem_wait(&full1); pthread_mutex_lock(&mutex1); @@ -191,7 +227,7 @@ void *calculating(void *param){ free(chaine); return NULL; } - + uint_64 number; number = strtoll(chaine,NULL,0); if (number != 0 || strcmp("0\n",chaine) == 0) { @@ -273,7 +309,6 @@ struct buffer_rc * buff_init_1(FILE *file1){ ptr1->len = 0; ptr1->head = 0; ptr1->tail = 0; - ptr1->stop = 0; ptr1->file1 = file1; return ptr1; @@ -292,7 +327,6 @@ struct buffer_cw * buff_init_2(FILE *file2){ ptr2->len = 0; ptr2->head = 0; ptr2->tail = 0; - ptr2->stop = 0; ptr2->file2 = file2; return ptr2; diff --git a/run.h b/run.h index 03363e435979bb3d100f0e475fbe3c3806ecf36d..e09a28b7d2f3912e75b8bb2f3eadc64722b710ad 100644 --- a/run.h +++ b/run.h @@ -7,10 +7,12 @@ #include <pthread.h> #include <semaphore.h> +#define uint_64 unsigned long long + int N; //travailler avec des linkendList typedef struct node{ - unsigned long long value; + uint_64 value; struct node *next; }node_t; @@ -26,7 +28,6 @@ struct buffer_rc{ int len; int head; int tail; - int stop; FILE *file1; }; @@ -38,7 +39,6 @@ struct buffer_cw int len; int head; int tail; - int stop; FILE *file2; }; @@ -65,11 +65,13 @@ char *get_from_buffer_1(struct buffer_rc *ptr); void put_in_buffer_2(struct queue *ptr, struct buffer_cw *buf); queue_t *get_from_buffer_2(struct buffer_cw *buf); -int is_div(unsigned long long number, unsigned long long i); -int is_prime(unsigned long long number); +int is_div(uint_64 number, uint_64 i); +uint_64 modpow (uint_64 base, uint_64 exp, uint_64 mod); +uint_64* randomiser (int k, uint_64 N); +int is_prime(uint_64 number); -void enqueue(queue_t* q, unsigned long long val); -queue_t* prime_divs(unsigned long long number); +void enqueue(queue_t* q, uint_64 val); +queue_t* prime_divs(uint_64 number); void *reading (void *param); void *calculating(void *param); diff --git a/test.c b/test.c index cb03a2c35a06614dc746d839c09da0e0427fce44..95ae303bbb25c2db35f4e71902354f0263fbdffa 100644 --- a/test.c +++ b/test.c @@ -9,13 +9,44 @@ void test_is_div(void){ CU_ASSERT_TRUE(is_div(14,7)); + CU_ASSERT_TRUE(is_div(25,5)); + CU_ASSERT_TRUE(is_div(1,1)); + CU_ASSERT_TRUE(is_div(0,2)); +} +void test_is_not_div(void){ + CU_ASSERT_FALSE(is_div(15,2)); + CU_ASSERT_FALSE(is_div(33,4)); + CU_ASSERT_FALSE(is_div(2,0)); } void test_is_prime(void){ CU_ASSERT_TRUE(is_prime(13)); + CU_ASSERT_TRUE(is_prime(2591)); + CU_ASSERT_TRUE(is_prime(4649)); + CU_ASSERT_TRUE(is_prime(2)); } void test_is_not_prime(void){ CU_ASSERT_FALSE(is_prime(14)); + CU_ASSERT_FALSE(is_prime(15648)); + CU_ASSERT_FALSE(is_prime(13544)); + CU_ASSERT_FALSE(is_prime(3214765)); +} + +void test_modpow(void){ + CU_ASSERT_EQUAL(modpow(5,3,13),8); + CU_ASSERT_NOT_EQUAL(modpow(5,3,13),7); +} + +void test_randomiser(void){ + unsigned long long *result; + result = randomiser(8,100); + for (int i = 0; i < 8; i++) + { + CU_ASSERT(result[i] < 100); + CU_ASSERT(result[i] > 0); + } + free(result); + } void empty_file_test(void){ @@ -187,8 +218,11 @@ int main(){ } if (NULL == CU_add_test(pSuite,"test_is_div",test_is_div) || + NULL == CU_add_test(pSuite,"test_is_not_div",test_is_not_div) || NULL == CU_add_test(pSuite, "test_is_prime",test_is_prime) || NULL == CU_add_test(pSuite, "test_is_not_prime",test_is_not_prime) || + NULL == CU_add_test(pSuite,"test_modpow",test_modpow) || + NULL == CU_add_test(pSuite,"test_randomiser",test_randomiser) || NULL == CU_add_test(pSuite,"empty_file_test",empty_file_test) || NULL == CU_add_test(pSuite,"short_file_test",short_file_test) || NULL == CU_add_test(pSuite,"file_test : N = 4",file_test_N_4) ||