diff --git a/projet E2/prime_divs.c b/projet E2/prime_divs.c new file mode 100644 index 0000000000000000000000000000000000000000..4c18e481164ea9b2bdc0aecdb418b8f4ac856ad7 --- /dev/null +++ b/projet E2/prime_divs.c @@ -0,0 +1,118 @@ +#include <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <string.h> +#include <semaphore.h> +#include <pthread.h> +#include <limits.h> + +#define NTYPE unsigned long long +#define NTYPE_POURCENT "%llu" + +NTYPE *prime_divs (NTYPE *diviseur, NTYPE number){ + /* + @pre : + - diviseur est un pointeur vers un unsigned long long (plus petit que 10**19) + qui contiendra le nombre de diviseurs de number après appel de cette fonction même + - number est un unsigned long long (number > 1) qui est le nombre dont la fonction cherche + tous les diviseurs premiers + @post : + return : un pointeur vers le tableau de longueur "nombre de diviseurs" qui contient + tous les diviseurs premiers de number (sauf le nombre lui-même s'il est premier) + */ + *diviseur = 0; + if(number == 1 || number == 2){return NULL;} + + NTYPE fix_number = number; + NTYPE i, j; + NTYPE a = ceil(sqrt(number));//ceil pour arrondi supérieur + + //NTYPE clk_tck = CLOCKS_PER_SEC; + //clock_t t1, t2, t3; + //t1 = clock(); + + /*INFO: pour trouver les nombres premiers, on utilise un bitset tel que : + 1 => pas un bon nombre (pas premier et/ou pas diviseur) + 0 => ok on le prend (ou pas encore calculé) + exemple pour 35 => bitarray : [0,1,1,1,0,1] + */ + + //création du bitset de longueur "racine carrée du nombre" + char *bitarray = (char*) malloc(sizeof(char) * a); + if (bitarray == NULL){ fprintf(stdout, "erreur malloc de prime_divs\n"); } + + //on met tous les bits à 0 + //0: index de début, a: size + memset(bitarray, 0, a); + //t2 = clock(); + i = 2; + + //remplit le bitarray avec les 0/1, en divisant number par ses diviseurs premiers + //(au maximum, donc autant de fois possible par tel ou tel diviseur premier) + //de telle manière à arriver à 1 ou bien au seul diviseur premier qui serait + //plus grand que la racine carrée du nombre + while (number > 1 && i<a+1) { //changer le i<a+1 si possible + + //CASE: pour les nombres qui sont à 0 (sont premiers mais pas forcément diviseurs) + if (!bitarray[i]){ + + //tous les mult de i (sauf i lui-même) à 1 pcq se sont PAS des nombres premiers + for(j = 2*i; j < a; j += i){ if (!bitarray[j]){ bitarray[j] = 1; } } + + //SWITCH on sait que i est nombre premier => est-il un diviseur ? + + /*CASE oui => les nombres premiers qu'il reste à identifier sont les diviseurs premiers de number/i + (divisés par i autant de fois que nécessaire pour + - éviter les redondances de calcul + - trouver plus aisément le dernier nombre premier) + */ + if ((number % i) == 0){ + (*diviseur)++; + //fprintf(stdout," diviseur ++ du while global| diviseur = %llu \n",*diviseur); + number /= i; + while(number % i == 0){ number /= i; } + + //CASE non => on met à 1 pour dire de ne pas le prendre en compte après + }else{ bitarray[i]=1; } + } + i++; + } + + //t3 = clock(); + //printf("tout le code prend : %lf ", (t3-t1)/clk_tck); + //printf("bitarray prend : %lf ", (t2-t1)/clk_tck); + + //création du tableau qui contiendra les diviseurs premiers + NTYPE* prime_dividers; + if(( prime_dividers= (NTYPE*) malloc(sizeof(NTYPE)*((*diviseur)+1) ) )==NULL){ fprintf(stderr,"erreur dans le malloc de prime_divs\n"); } + + NTYPE index = 0; + + //remplit prime_dividers avec les nombres premiers, diviseurs de number + for(NTYPE m = 2; m < i; m++) { + // on add à prime_dividers les nombres dont l'indice vaut 0 dans le bitset + if(!bitarray[m] && (fix_number != 2) ) { + prime_dividers[index] = m; + index++; + } + } + /* + //gère le cas number = 2 + if (fix_number == 2){ + (*diviseur)--; + fprintf(stdout," diviseur ++ de la condi spéciale| diviseur = %llu \n",*diviseur); + }*/ + + //ajoute le dernier nombre dans la liste de diviseurs au cas où le dernier diviseur + //premier est plus grand que la racine carrée du nombre + if (number != 1 && (number != fix_number)) { + prime_dividers[index] = number; + (*diviseur)++; + //fprintf(stdout," diviseur ++ dans lequel il n'est pas sencé rentrer| diviseur = %llu \n",*diviseur); + + } + + free(bitarray); + + return prime_dividers; +}