diff --git a/Final Code/fonctions.c b/Final Code/fonctions.c
new file mode 100644
index 0000000000000000000000000000000000000000..6e3ce8cc89799fb427a841206a533b807dcb18a1
--- /dev/null
+++ b/Final Code/fonctions.c	
@@ -0,0 +1,246 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <stdint.h>
+
+#include <pthread.h>
+#include <semaphore.h>
+
+#include "fonctions.h"
+
+/*
+Initialise une liste de node_t
+@my_list : la list_t qui est initialisée
+*/
+void init_list_t(list_t *my_list) {
+    my_list->first = NULL;
+    my_list->last = NULL;
+    my_list->length = 0;
+}
+
+/*
+Initialise une liste de node_lst
+@my_list : la list_lst qui est initialisée
+*/
+void init_list_lst(list_lst *my_list) {
+    my_list->first = NULL;
+    my_list->last = NULL;
+    my_list->length = 0;
+}
+
+/*
+Ajoute un node_t à la fin d'une list_t
+@my_list : la list_t a laquelle on va ajouter un node_t
+@value : la valeur (uint64_t) que contiendra le node_t
+*/
+void put_node_t(list_t *my_list, uint64_t value) {
+    node_t *new = malloc(sizeof(node_t));
+    if (!new) return;
+    new->next = NULL;
+    new->value = value;
+    if (my_list->length == 0) {
+        my_list->first = new;
+        my_list->last = new;
+    } else {
+        my_list->last->next = new;
+        my_list->last = new;
+    }
+    my_list->length += 1;
+}
+
+/*
+Ajoute un node_lst à la fin d'une list_lst
+@my_list : la list_lst a laquelle on va ajouter un node_lst
+@put_list : la list_t que contiendra le node_lst
+*/
+void put_node_lst(list_lst *my_list, list_t *put_list) {
+    node_lst *new = malloc(sizeof(node_lst));
+    if (!new) return;
+    new->next = NULL;
+    new->diviseurs = put_list;
+    if (my_list->length == 0) {
+        my_list->first = new;
+        my_list->last = new;
+    } else {
+        my_list->last->next = new;
+        my_list->last = new;
+    }
+    my_list->length += 1;
+}
+
+/*
+Retire le premier node_t d'une list_t et renvoit son entier
+@my_list : la list_t de laquelle on va retier le node_t pointé par first
+@return : la valeur (uint64_t) que contenait le node_t retiré
+*/
+uint64_t get_node_t(list_t *my_list) {
+    if (my_list->length == 0) return -1;
+    int value = my_list->first->value;
+    node_t *temp = my_list->first;
+    my_list->first = my_list->first->next;
+    my_list->length -= 1;
+    free(temp);
+    return value;
+}
+
+/*
+Retire le premier node_lst d'une list_lst et renvoit sa liste
+@my_list ; la list_lst de laquelle on va retirer le node_lst pointé par first
+@return : la liste (list_t) que contenait le node_lst retiré
+*/
+list_t *get_node_lst(list_lst *my_list) {
+    if (my_list->length == 0) return NULL;
+    list_t *get_list = my_list->first->diviseurs;
+    node_lst *temp = my_list->first;
+    my_list->first = my_list->first->next;
+    my_list->length -= 1;
+    free(temp);
+    return get_list;
+}
+
+/*
+Vide une list_t de node_t
+@my_list : la list_t qui va être vidée
+*/
+void clear_list_t(list_t *my_list) {
+    if (my_list == NULL || my_list->length == 0) return;
+    node_t *temp = my_list->first->next;
+    while(my_list->first != NULL) {
+        free(my_list->first);
+        my_list->first = temp;
+        if (temp != NULL) {
+            temp = temp->next;
+        }
+    }
+    my_list->first = NULL;
+}
+
+/*
+Renvoie une list_t contenant un nombre suivi de ses diviseurs premiers
+@value : le nombre (uint64_t) dont on veut trouver les diviseurs premiers
+@return : une list_t contenant value dans le node_t pointé par first ainsi que ses diviseurs premiers
+*/
+list_t *prime_list(uint64_t value) {
+    list_t *prime = malloc(sizeof(list_t));
+    if (!prime) return NULL;
+    init_list_t(prime);
+    put_node_t(prime, value);
+
+    uint64_t in_node = 0;
+    uint64_t chiffre = value;
+    uint64_t div = 2;
+
+    while (value % div == 0) {
+        if (div != in_node && value != div) {
+            put_node_t(prime, div);
+            in_node = div;
+        }
+        value = value/div;
+    }
+    for (uint64_t i = 3; i*i <= value; i += 2) {
+        while (value % i == 0) {
+            if (i != in_node) {
+                put_node_t(prime, i);
+                in_node = i;
+            }
+            value = value / i;
+        }
+    }
+    if (value != chiffre && value != 1){
+        put_node_t(prime, value);
+    }
+    
+    return prime;
+}
+
+/*
+Compte les lignes d'un fichier
+@filename : un pointeur vers le nom du fichier à ouvrir
+@return : le nombre (int) de lignes dans le fichier donné
+*/
+int count_lines(char *filename){
+    uint64_t number;
+    int lines = 0;
+    FILE *file = fopen(filename, "r");
+    while (fscanf(file, "%lu", &number) != EOF) {
+        lines++;
+    }
+    fclose(file);
+    return lines;
+}
+
+/*
+Initialise un buffer1
+@nthreads : le nombre (int) de threads passé en argument du programme
+@return : un pointeur vers un buffer1 initialisé
+*/
+buffer1 *init_buffer_1(int nthreads) {
+    buffer1 *buffer_1 = malloc(sizeof(buffer1));
+    if (!buffer_1) {
+        free(buffer_1);
+        return NULL;
+    }
+
+    if (pthread_mutex_init(&(buffer_1->mutex), NULL) == -1) {
+        free(buffer_1);
+        return NULL;
+    }
+    if (sem_init(&(buffer_1->free), 0, nthreads + 2) == -1) {
+        free(buffer_1);
+        return NULL;
+    }
+    if (sem_init(&(buffer_1->full), 0, 0) == -1) {
+        free(buffer_1);
+        return NULL;
+    }
+
+    buffer_1->can_stop = false;
+    buffer_1->numbers = malloc(sizeof(list_t));
+    if (!buffer_1->numbers) {
+        free(buffer_1->numbers);
+        free(buffer_1);
+        return NULL;
+    }
+
+    init_list_t(buffer_1->numbers);
+
+    return buffer_1;
+}
+
+/*
+Initialise un buffer2
+@nthreads : le nombre (int) de threads passé en argument du programme
+@return : un pointeur vers un buffer2 initialisé
+*/
+buffer2 *init_buffer_2(int nthreads) {
+    buffer2 *buffer_2 = malloc(sizeof(buffer2));
+    if (!buffer_2) {
+        free(buffer_2);
+        return NULL;
+    }
+
+    if (pthread_mutex_init(&(buffer_2->mutex), NULL) == -1) {
+        free(buffer_2);
+        return NULL;
+    }
+    if (sem_init(&(buffer_2->free), 0, nthreads + 2) == -1) {
+        free(buffer_2);
+        return NULL;
+    }
+    if (sem_init(&(buffer_2->full), 0, 0) == -1) {
+        free(buffer_2);
+        return NULL;
+    }
+
+    buffer_2->prime_numbers = malloc(sizeof(list_lst));
+    if (!buffer_2->prime_numbers) {
+        free(buffer_2->prime_numbers);
+        free(buffer_2);
+        return NULL;
+    }
+
+    init_list_lst(buffer_2->prime_numbers);
+
+    return buffer_2;
+}
\ No newline at end of file