diff --git a/projet k3/implem.c b/projet k3/implem.c
new file mode 100644
index 0000000000000000000000000000000000000000..f95970b9686b4ca978ccb79d4addf8a571f1f361
--- /dev/null
+++ b/projet k3/implem.c	
@@ -0,0 +1,307 @@
+#define NT 4
+#include <math.h>
+#include <time.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdint.h>
+#include <pthread.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <semaphore.h>
+
+typedef struct{
+    int file_descriptor;
+    pthread_mutex_t mutex;
+} threadf_t;
+
+typedef struct{
+    pthread_mutex_t mutex;
+    sem_t empty, full;
+    long w, x, y, *z;
+    threadf_t *out;
+} buffer_t;
+
+typedef struct{
+    size_t len;
+    char *str;
+} word_t;
+
+typedef struct _link{
+    void *data;
+    struct _link *nx;
+} link_t;
+
+threadf_t *threadf_init(const char *fn){
+    threadf_t *new = malloc(sizeof(threadf_t));
+    if(new == NULL) exit(EXIT_FAILURE);
+
+    new->file_descriptor = open(fn, O_RDWR | O_CREAT | O_TRUNC, S_IRWXU);
+    if(new->file_descriptor == -1) exit(EXIT_FAILURE);
+    pthread_mutex_init(&new->mutex, NULL);
+    return new;
+}
+
+void threadf_destroy(threadf_t *threadf){
+    pthread_mutex_destroy(&threadf->mutex);
+    if(close(threadf->file_descriptor) == -1)
+        strerror(errno);
+    free(threadf);
+}
+
+buffer_t *buffer_init(const char *fn){
+    buffer_t *new = malloc(sizeof(buffer_t));
+    if(new == NULL) exit(EXIT_FAILURE);
+
+    new->w = 2 * NT; new->x = 0; new->y = 0;
+    new->z = malloc(sizeof(long) * new->w);
+    if(new->z == NULL) exit(EXIT_FAILURE);
+    new->out = threadf_init(fn);
+
+    pthread_mutex_init(&new->mutex, NULL);
+    sem_init(&new->empty, 0, new->w);
+    sem_init(&new->full, 0, 0);
+    return new;
+}
+
+void buffer_put(buffer_t *bf, long v){
+    sem_wait(&bf->empty); // WAITING FOR AT LEAST ONE FREE CASE IN THE BUFFER
+    pthread_mutex_lock(&bf->mutex);
+    bf->z[bf->x % bf->w] = v;
+    bf->x = (bf->x + 1) % bf->w;
+    pthread_mutex_unlock(&bf->mutex);
+    sem_post(&bf->full); // SIGNALING THAT THERE'S ONE MORE ELEMENT IN THE BUFFER
+}
+
+long buffer_get(buffer_t *bf){
+    long output;
+    sem_wait(&bf->full); // WAITING FOR AT LEAST ONE ELEMENT IN THE BUFFER TO CONSUME
+    pthread_mutex_lock(&bf->mutex);
+    output = bf->z[bf->y % bf->w];
+    bf->y = (bf->y + 1) % bf->w;
+    pthread_mutex_unlock(&bf->mutex);
+    sem_post(&bf->empty);
+    return output;
+}
+
+void buffer_destroy(buffer_t *bf){
+    free(bf->z);
+    sem_destroy(&bf->full);
+    sem_destroy(&bf->empty);
+    threadf_destroy(bf->out);
+    pthread_mutex_destroy(&bf->mutex);
+    free(bf);
+}
+
+word_t *word_init(char *str, size_t len){
+    word_t *new = malloc(sizeof(word_t));
+    if(new == NULL) exit(EXIT_FAILURE);
+    new->str = str; new->len = len;
+    return new;
+}
+
+word_t *long_to_str(long value){
+    size_t len = 1;
+    long tmp = value;
+    while(tmp /= 10) len++;
+    int len_copy = len;
+    char *str = malloc(sizeof(char) * len);
+    if(str == NULL) exit(EXIT_FAILURE);
+    while(len_copy--){ str[len_copy] = (char) ((value % 10) + '0'); value /= 10; }
+    return word_init(str, len);
+}
+
+void *word_destroy(word_t *word){
+    free(word->str);
+    free(word);
+}
+
+link_t *link_init(void *data){
+    link_t *new = malloc(sizeof(link_t));
+    if(new == NULL) exit(EXIT_FAILURE);
+    new->data = data;
+    new->nx = new;
+    return new;
+}
+
+void link_enqueue(link_t **link, void *data){
+    if((*link)->data){
+        link_t *new = link_init(data);
+        new->nx = (*link)->nx;
+        (*link)->nx = new;
+        *link = new;
+    }
+    else{
+        (*link)->data = data;
+    }
+}
+
+void *link_dequeue(link_t **link){
+    void *output;
+    if(*link == (*link)->nx){
+        output = (*link)->data;
+        (*link)->data = NULL;
+    }
+    else{
+        link_t *tmp = (*link)->nx;
+        (*link)->nx = tmp->nx;
+        output = tmp->data;
+        free(tmp);
+    }
+    return output;
+}
+
+void fermat_slave(link_t **link, long x){
+    if(x == 1) return;
+
+    long a = ceil(sqrt(x));
+    long sq = a * a;
+
+    if(sq == x){
+        fermat_slave(link, a);
+    }
+    else{
+        long b, c;
+        do {
+            b = (a * a) - x;
+            c = floor(sqrt(b));
+        } while ((c * c) != b && ++a);
+
+        if(a - c == 1){
+            long *a_plus_c = malloc(sizeof(long));
+            if(a_plus_c == NULL) exit(EXIT_FAILURE);
+            *a_plus_c = a + c;
+
+            int is_in = 0;
+            if((*link)->data){
+                link_t *tmp = (*link);
+                is_in = (*a_plus_c == *(long *)  tmp->data);
+                tmp = tmp->nx;
+                while (!is_in && tmp != *link){
+                    is_in = (*a_plus_c == *(long *)  tmp->data);
+                    tmp = tmp->nx;
+                }
+            }
+            
+            if(!is_in)
+                link_enqueue(link, a_plus_c);
+        }
+        else{
+            fermat_slave(link, a - c);
+            fermat_slave(link, a + c);
+        }
+    }
+}
+
+void fermat(link_t **link, long x){
+    long tmp = x;
+    if(x != 2){
+        if(x % 2 == 0){
+            long *two = malloc(sizeof(long));
+            if(two == NULL) exit(EXIT_FAILURE);
+            *two = 2; link_enqueue(link, two);
+            x /= 2;
+            while(x % 2 == 0){
+                x /= 2;
+            }
+        }
+        fermat_slave(link, x);
+
+        if(*(long *) (*link)->data == tmp){
+            link_dequeue(link);
+        }
+    }
+}
+
+void *consumer(void *arg){
+    char *space = malloc(sizeof(char)), *new_line = malloc(sizeof(char));
+    if(space == NULL) exit(EXIT_FAILURE); if(new_line == NULL) exit(EXIT_FAILURE);
+    *space = ' '; *new_line = '\n';
+    buffer_t *bf = (buffer_t *) arg;
+    while(1){
+        long value = buffer_get(bf);
+        if(value < 0){ break; } // IF BUFFER SIGNALS END THEN QUIT
+
+        link_t *line = link_init(NULL);
+        fermat(&line, value);
+
+        // modif here
+        pthread_mutex_lock(&bf->out->mutex);
+        word_t *first = long_to_str(value);
+        write(bf->out->file_descriptor, first->str, first->len);
+
+        while(line->data){
+            word_t *out = long_to_str(*(long *) link_dequeue(&line));
+            write(bf->out->file_descriptor, space, 1);
+            write(bf->out->file_descriptor, out->str, out->len);
+            word_destroy(out);
+        }
+        write(bf->out->file_descriptor, new_line, 1);
+        pthread_mutex_unlock(&bf->out->mutex);
+    }
+    free(space); free(new_line);
+    return NULL;
+}
+
+// gcc implem.c -o files/implem -lpthread -lm
+// ./files/implem test_input.txt files/implem.txt
+// valgrind --leak-check=yes ./files/implem files/example_input.txt files/ouput.txt
+
+int main(int argc, char const *argv[]){
+     pthread_t threads[NT];
+    buffer_t *bf = buffer_init(argv[2]);
+
+    int input_fd = open(argv[1], O_RDONLY);
+    if(input_fd == -1) strerror(errno);
+
+    struct stat fs;
+    if(fstat(input_fd, &fs) == -1){ strerror(errno); close(input_fd); }
+
+    char *proj = mmap(NULL, fs.st_size, PROT_READ, MAP_PRIVATE, input_fd, 0);
+    if(proj == MAP_FAILED){ strerror(errno); close(input_fd); }
+
+    // BOOTING CONSUMERS
+    for(uint8_t t = 0; t < NT; t++){
+        if(pthread_create(&threads[t], NULL, consumer, bf)){
+            printf("Error while creating a thread \n"); exit(EXIT_FAILURE);
+        }
+    }
+
+    long current = 0;
+    size_t len = fs.st_size / sizeof(char);
+    for(size_t i = 0; i < len; i++){
+        if(proj[i] != '\r'){
+            long tmp = proj[i] - '0';
+            if(0 <= tmp && tmp <= 9){
+                current = (current * 10) + tmp;
+            }
+            else{
+                printf("Wrong file format \n"); exit(EXIT_FAILURE);
+            }
+        }
+        else{
+            buffer_put(bf, current);
+            current = 0;
+            i++;
+        }
+    }
+
+    // ENDING CONSUMERS ACTIVITY
+    for(uint8_t t = 0; t < NT; t++){ buffer_put(bf, -1); }
+    for(uint8_t t = 0; t < NT; t++){
+        if(pthread_join(threads[t], NULL)){
+            printf("Error on joining !"); exit(EXIT_FAILURE);
+        }
+    }
+
+    // TERMINATE TODO: HANDLE MEMORY PROPERLY
+    buffer_destroy(bf);
+    if(munmap(proj, fs.st_size) == -1)
+        strerror(errno); close(input_fd);
+    if(close(input_fd) == -1)
+        strerror(errno);
+    return 0;
+}