From 8795ba4f274a9f6ca44ddb9de44638054395364e Mon Sep 17 00:00:00 2001
From: mfikrin <muhammad.fikrin1729@gmail.com>
Date: Sun, 6 Mar 2022 18:58:43 +0700
Subject: [PATCH] feat : tc spek passed

---
 src/par         | Bin 21944 -> 22016 bytes
 src/parallel.c  | 234 ++++++++++++++++++------
 src/parallel2.c | 476 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 658 insertions(+), 52 deletions(-)
 create mode 100644 src/parallel2.c

diff --git a/src/par b/src/par
index 8bf4ea24047dd88c1e67dfcc6830ff4f8b2f82c4..ffafc83fe9e030b3ca6386844af9bd6f87ef3bf2 100644
GIT binary patch
delta 5872
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
NQ`7^W1bw?K`G1DK#^V40

delta 4436
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

diff --git a/src/parallel.c b/src/parallel.c
index ebf4562..2f3cec5 100644
--- a/src/parallel.c
+++ b/src/parallel.c
@@ -289,6 +289,8 @@ int main() {
 	
     // 10 / 4 = 2 2 2 (10-6)
     int kernel_row, kernel_col, target_row, target_col, num_targets;
+	int counter_distribute = 0;
+	int counter_receiver = 0;
 	
 	// reads kernel's row and column and initalize kernel matrix from input
 	scanf("%d %d", &kernel_row, &kernel_col);
@@ -299,7 +301,7 @@ int main() {
 	// initialize array of matrices and array of data ranges (int)
 	scanf("%d %d %d", &num_targets, &target_row, &target_col);
 	Matrix* arr_mat = (Matrix*)malloc(num_targets * sizeof(Matrix));
-	Matrix* arr_mat2 = (Matrix*)malloc(num_targets * sizeof(Matrix));
+
 	int arr_range[num_targets];
     
 	
@@ -310,8 +312,7 @@ int main() {
 
     print_matrix(&kernel);
 
-	int counter_distribute = 0;
-	int counter_receiver = 0;
+	
 
     printf("HELLO OPEN MPI\n");
 
@@ -354,77 +355,206 @@ int main() {
 
     6 7 8
 
-    9
+    9 10 11
 
     */ 
 
-    int root = 0;
+	int root = 0;
+	int divide = num_targets/(world_size-1);
+
+	if (world_rank == root){
+		// Divide input
+		int i;
+		int j = 0;
+		// int k = 0;
+		int sisa = num_targets % (world_size-1);
+		for (int rank = 0; rank < world_size; rank++) {
+            printf("I = %d\n", rank);
+			if (rank != world_rank) {
+				int jumlah_diambil = divide;
+				printf("jumlah diambil pre-sisa: %d\n", jumlah_diambil);
+				if (sisa != 0){
+					jumlah_diambil += 1;
+					sisa -= 1;
+				}
+				printf("jumlah diambil post-sisa: %d\n", jumlah_diambil);
+
+				MPI_Send(&kernel, 1, mat_MPI, rank, 0, MPI_COMM_WORLD);
+				MPI_Send(&jumlah_diambil, 1, MPI_INT, rank, 1, MPI_COMM_WORLD);
+				
+				for (int k=0; k < jumlah_diambil; k++){
+					MPI_Send(&arr_mat[j], 1, mat_MPI, rank, 2+k, MPI_COMM_WORLD);
+					j++;
+				}
+				
+				printf("Checkpoint A\n");
+			}
+		}
+
+
+		printf("BACK TO PROCESS 0");
+		// Now receive the message with the allocated buffer
+		int idxArrRange = 0;
+        for (int i = 0; i < world_size; i++ ){
+			if (i != root){
+                MPI_Status status;
+                // Probe for an incoming message from process zero
+                MPI_Probe(i, 0, MPI_COMM_WORLD, &status);
 
+                // When probe returns, the status object has the size and other
+                // attributes of the incoming message. Get the message size
+                int number_amount;
+                MPI_Get_count(&status, MPI_INT, &number_amount);
 
+                // Allocate a buffer to hold the incoming numbers
+                int* number_buf = (int*)malloc(sizeof(int) * number_amount);
 
-    while (counter_distribute < PING_PONG_LIMIT){
-        // distribute(arr_mat[counter_distribute],1,mat_MPI,0, MPI_COMM_WORLD)
-		printf("Counter dis %d \n", counter_distribute);
-		if (world_rank == root) {
-			// If we are the root process, send our data to every process
-            int i;
-            for (i = 0; i < world_size; i++) {
-                if (i != world_rank) {
-                    MPI_Send(&arr_mat[counter_distribute], 1, mat_MPI, i, 1, MPI_COMM_WORLD);
-                    MPI_Send(&kernel, 1, mat_MPI, i, 0, MPI_COMM_WORLD);
-                    counter_distribute++;
-                }
+
+                MPI_Recv(number_buf, number_amount, MPI_INT, i, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
+                printf("\nPROCESS 0 IN RECEIVING\n");
+                print_array(number_buf,number_amount);
+                //[3]
+                //[46]
+                //[22]
+
+				for (int j=0; j<number_amount; j++){
+					arr_range[idxArrRange] = number_buf[j];
+					idxArrRange++;
+				}
             }
+		}
+	} else {	
+		Matrix kernel_recv;
+		MPI_Recv(&kernel_recv, 1, mat_MPI, root, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
+
+        int totalData;
+		MPI_Recv(&totalData, 1, MPI_INT, root, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
+		printf("Total datanya %d \n", totalData);
+
+		print_matrix(&kernel_recv);
+
+		Matrix* arr_mat2 = (Matrix*)malloc(totalData * sizeof(Matrix));
+
+		for (int i=0; i<totalData; i++){
+            Matrix mat_recv;
+            MPI_Recv(&mat_recv, 1, mat_MPI, root, i+2, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
+			printf("Hasil passing\n");
+			print_matrix(&mat_recv);
+            
+            arr_mat2[i] = convolution(&kernel_recv, &mat_recv);
+            
+            print_matrix(&arr_mat2[i]);
+			arr_range[i] = get_matrix_datarange(&arr_mat2[i]);
+		}
+
+		printf("HASILLL RANGE\n");
+		merge_sort(arr_range, 0, totalData-1);
+		print_array(arr_range,totalData);
+
+		MPI_Send(&arr_range, totalData, MPI_INT, 0, 0, MPI_COMM_WORLD);
+	}
+
+
+    // if (world_rank == 0){
+	// 	printf("BACK TO PROCESS 0");
+	// 	// Now receive the message with the allocated buffer
+    //     for (int i = 0; i < world_size; i++ ){
+	// 		if (i != root){
+    //             MPI_Status status;
+    //             // Probe for an incoming message from process zero
+    //             MPI_Probe(i, 0, MPI_COMM_WORLD, &status);
+
+    //             // When probe returns, the status object has the size and other
+    //             // attributes of the incoming message. Get the message size
+    //             int number_amount;
+    //             MPI_Get_count(&status, MPI_INT, &number_amount);
+
+    //             // Allocate a buffer to hold the incoming numbers
+    //             int* number_buf = (int*)malloc(sizeof(int) * number_amount);
+
+
+    //             MPI_Recv(number_buf, number_amount, MPI_INT, i, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
+    //             printf("PROCESS 0 IN RECEIVING");
+    //             print_array(number_buf,number_amount);
+    //         }
+	// 	}
+    // }
+
+
+    // while (counter_distribute < PING_PONG_LIMIT){
+    //     // distribute(arr_mat[counter_distribute],1,mat_MPI,0, MPI_COMM_WORLD)
+	// 	printf("Counter dis %d \n", counter_distribute);
+	// 	if (world_rank == root) {
+	// 		// If we are the root process, send our data to every process
+    //         int i;
+    //         for (i = 0; i < world_size; i++) {
+    //             if (i != world_rank) {
+    //                 MPI_Send(&arr_mat[counter_distribute], 1, mat_MPI, i, 1, MPI_COMM_WORLD);
+    //                 MPI_Send(&kernel, 1, mat_MPI, i, 0, MPI_COMM_WORLD);
+                    
+    //                 counter_distribute++;
+
+    //                 MPI_Send(&counter_distribute, 1, MPI_INT, i, 2, MPI_COMM_WORLD);
+    //             }
+    //         }
 			
-		} else {
-			// If we are a receiver process, receive the data from the root
-            Matrix recv_data;
-            MPI_Recv(&recv_data, 1, mat_MPI, root, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
-            Matrix kernel_recv;
-            MPI_Recv(&kernel_recv, 1, mat_MPI, root, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
-            print_matrix(&recv_data);
-            print_matrix(&kernel_recv);
-
-			printf("HASILLL\n");
-			arr_mat2[counter_receiver] = convolution(&kernel_recv, &recv_data);
+	// 	} else {
+	// 		// If we are a receiver process, receive the data from the root
+    //         Matrix recv_data;
+    //         MPI_Recv(&recv_data, 1, mat_MPI, root, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
+    //         Matrix kernel_recv;
+    //         MPI_Recv(&kernel_recv, 1, mat_MPI, root, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
+    //         print_matrix(&recv_data);
+    //         print_matrix(&kernel_recv);
+    //         MPI_Recv(&counter_distribute, 1, mat_MPI, root, 2, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
+	// 		printf("HASILLL\n");
+	// 		arr_mat2[counter_receiver] = convolution(&kernel_recv, &recv_data);
             
-            print_matrix(&arr_mat2[counter_receiver]);
-			arr_range[counter_receiver] = get_matrix_datarange(&arr_mat2[counter_receiver]);
+    //         print_matrix(&arr_mat2[counter_receiver]);
+	// 		arr_range[counter_receiver] = get_matrix_datarange(&arr_mat2[counter_receiver]);
+    //         counter_distribute = counter_distribute;
+	// 		printf("Counter reciver now %d \n", counter_distribute);
+    //         printf("Counter disribute now %d \n", counter_distribute);
+            
+	// 		counter_receiver++;
+	// 	}
+    // }
 
-			counter_receiver++;
-		}
-    }
+    printf("HOOOOOOOOOOOOOOO\n");
+	
 
-	MPI_Finalize();
-    
+    MPI_Finalize();
 
-    // // Print hasil
+	// print_array(arr_range,num_targets);
+    // Print hasil
 	// for (int i = 0; i < num_targets; i++) {
 	// 	printf("\nMATRIX CONV %d",i);
 	// 	print_matrix(arr_mat2); 
 	// }
 
-	// // sort the data range array
-	// printf("\n");
-	// print_array(arr_range,num_targets);
-	// merge_sort(arr_range, 0, num_targets - 1);
+	// sort the data range array
+	printf("BAWAHNYA PRINT ARRAY\n");
+	print_array(arr_range,num_targets);
+	merge_sort(arr_range, 0, num_targets - 1);
+
+
+    printf("AFTER SORT\n");
+	print_array(arr_range,num_targets);
 	
-	// int median = get_median(arr_range, num_targets);	
-	// int floored_mean = get_floored_mean(arr_range, num_targets); 
+	int median = get_median(arr_range, num_targets);	
+	int floored_mean = get_floored_mean(arr_range, num_targets); 
 
-	// // print the min, max, median, and floored mean of data range array
-	// printf("%d\n%d\n%d\n%d\n", 
-	// 		arr_range[0], 
-	// 		arr_range[num_targets - 1], 
-	// 		median, 
-	// 		floored_mean);
+	// print the min, max, median, and floored mean of data range array
+	printf("HASIL FINALLLL\n");
+	printf("MIN : %d\nMAX : %d\nMedian : %d\nRata-Rata : %d\n", 
+			arr_range[0], 
+			arr_range[num_targets - 1], 
+			median, 
+			floored_mean);
 
     
 	
-    // START OPEN MP	
-	
-	
-    
+    // START OPEN MP
 	
 	return 0;
 }
diff --git a/src/parallel2.c b/src/parallel2.c
new file mode 100644
index 0000000..f4ecd9b
--- /dev/null
+++ b/src/parallel2.c
@@ -0,0 +1,476 @@
+// serial.c
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <mpi.h>
+
+#define NMAX 100
+#define DATAMAX 1000
+#define DATAMIN -1000
+
+/* 
+ * Struct Matrix
+ *
+ * Matrix representation consists of matrix data 
+ * and effective dimensions 
+ * */
+typedef struct Matrix {
+	int mat[NMAX][NMAX];	// Matrix cells
+	int row_eff;			// Matrix effective row
+	int col_eff;			// Matrix effective column
+} Matrix;
+
+
+/* 
+ * Procedure init_matrix
+ * 
+ * Initializing newly allocated matrix
+ * Setting all data to 0 and effective dimensions according
+ * to nrow and ncol 
+ * */
+void init_matrix(Matrix *m, int nrow, int ncol) {
+	m->row_eff = nrow;
+	m->col_eff = ncol;
+
+	for (int i = 0; i < m->row_eff; i++) {
+		for (int j = 0; j < m->col_eff; j++) {
+			m->mat[i][j] = 0;
+		}
+	}
+}
+
+
+/* 
+ * Function input_matrix
+ *
+ * Returns a matrix with values from stdin input
+ * */
+Matrix input_matrix(int nrow, int ncol) {
+	Matrix input;
+	init_matrix(&input, nrow, ncol);
+
+	for (int i = 0; i < nrow; i++) {
+		for (int j = 0; j < ncol; j++) {
+			scanf("%d", &input.mat[i][j]);
+		}
+	}
+
+	return input;
+}
+
+
+/* 
+ * Procedure print_matrix
+ * 
+ * Print matrix data
+ * */
+void print_matrix(Matrix *m) {
+	for (int i = 0; i < m->row_eff; i++) {
+		for (int j = 0; j < m->col_eff; j++) {
+			printf("%d ", m->mat[i][j]);
+		}
+		printf("\n");
+	}
+}
+
+
+/* 
+ * Function get_matrix_datarange
+ *
+ * Returns the range between maximum and minimum
+ * element of a matrix
+ * */
+int get_matrix_datarange(Matrix *m) {
+	int max = DATAMIN;
+	int min = DATAMAX;
+	for (int i = 0; i < m->row_eff; i++) {
+		for (int j = 0; j < m->col_eff; j++) {
+			int el = m->mat[i][j];
+			if (el > max) max = el;
+			if (el < min) min = el;
+		}
+	}
+
+	return max - min;
+}
+
+
+/*
+ * Function supression_op
+ *
+ * Returns the sum of intermediate value of special multiplication
+ * operation where kernel[0][0] corresponds to target[row][col]
+ * */
+int supression_op(Matrix *kernel, Matrix *target, int row, int col) {
+	int intermediate_sum = 0;
+	for (int i = 0; i < kernel->row_eff; i++) {
+		for (int j = 0; j < kernel->col_eff; j++) {
+			intermediate_sum += kernel->mat[i][j] * target->mat[row + i][col + j];
+		}
+	}
+
+	return intermediate_sum;
+}
+
+
+/* 
+ * Function convolution
+ *
+ * Return the output matrix of convolution operation
+ * between kernel and target
+ * */
+Matrix convolution(Matrix *kernel, Matrix *target) {
+	Matrix out;
+	int out_row_eff = target->row_eff - kernel->row_eff + 1;
+	int out_col_eff = target->col_eff - kernel->col_eff + 1;
+
+    // printf("kernel row %d",kernel->row_eff);
+    // printf("kernel col %d",kernel->col_eff);
+
+    // printf("out_row_eff %d %d",out_row_eff,out_col_eff);
+	
+	init_matrix(&out, out_row_eff, out_col_eff);
+
+	for (int i = 0; i < out.row_eff; i++) {
+		for (int j = 0; j < out.col_eff; j++) {
+			out.mat[i][j] = supression_op(kernel, target, i, j);
+		}
+	}
+
+	return out;
+}
+
+
+/*
+ * Procedure merge_array
+ *
+ * Merges two subarrays of n with n[left..mid] and n[mid+1..right]
+ * to n itself, with n now ordered ascendingly
+ * */
+void merge_array(int *n, int left, int mid, int right) {
+	int n_left = mid - left + 1;
+	int n_right = right - mid;
+	int iter_left = 0, iter_right = 0, iter_merged = left;
+	int arr_left[n_left], arr_right[n_right];
+
+	for (int i = 0; i < n_left; i++) {
+		arr_left[i] = n[i + left];
+	}
+
+	for (int i = 0; i < n_right; i++) {
+		arr_right[i] = n[i + mid + 1];
+	}
+
+	while (iter_left < n_left && iter_right < n_right) {
+		if (arr_left[iter_left] <= arr_right[iter_right]) {
+			n[iter_merged] = arr_left[iter_left++];
+		} else {
+			n[iter_merged] = arr_right[iter_right++];
+		}
+		iter_merged++;
+	}
+
+	while (iter_left < n_left)  {
+		n[iter_merged++] = arr_left[iter_left++];
+	}
+	while (iter_right < n_right) {
+		n[iter_merged++] = arr_right[iter_right++];
+	} 
+}
+
+
+/* 
+ * Procedure merge_sort
+ *
+ * Sorts array n with merge sort algorithm
+ * */
+void merge_sort(int *n, int left, int right) {
+	if (left < right) {
+		int mid = left + (right - left) / 2;
+
+		merge_sort(n, left, mid);
+		merge_sort(n, mid + 1, right);
+
+		merge_array(n, left, mid, right);
+	}	
+}
+ 
+
+/* 
+ * Procedure print_array
+ *
+ * Prints all elements of array n of size to stdout
+ * */
+void print_array(int *n, int size) {
+	for (int i = 0; i < size; i++ ) printf("%d ", n[i]);
+	printf("\n");
+}
+
+
+/* 
+ * Function get_median
+ *
+ * Returns median of array n of length
+ * */
+int get_median(int *n, int length) {
+	int mid = length / 2;
+	if (length & 1) return n[mid];
+
+	return (n[mid - 1] + n[mid]) / 2;
+}
+
+
+/* 
+ * Function get_floored_mean
+ *
+ * Returns floored mean from an array of integers
+ * */
+long get_floored_mean(int *n, int length) {
+	long sum = 0;
+	for (int i = 0; i < length; i++) {
+		sum += n[i];
+	}
+
+	return sum / length;
+}
+
+
+void distribute(void* data, int count, MPI_Datatype datatype, int root,
+              MPI_Comm communicator) {
+	int world_rank;
+	MPI_Comm_rank(communicator, &world_rank);
+	int world_size;
+	MPI_Comm_size(communicator, &world_size);
+
+	// Procecss 0 --> Kirim matriks inputan 1,2,3 ke prcess 1,2,3
+	// process 1,2,3 -> receive
+	// prcess 0 --> kirim matriks input 4,5,6, ke process 1,2,3
+	
+	if (world_rank == root) {
+	// If we are the root process, send our data to every process
+	int i;
+	for (i = 0; i < world_size; i++) {
+		if (i != world_rank) {
+		MPI_Send(data, count, datatype, i, 0, communicator);
+		}
+	}
+	} else {
+	// If we are a receiver process, receive the data from the root
+	MPI_Recv(data, count, datatype, root, 0, communicator,
+				MPI_STATUS_IGNORE);
+    
+
+	// Ngitung con sama data range		 
+	}
+}
+
+// void init_matrix_kernel() {
+// 	m->row_eff = 2;
+// 	m->col_eff = 2;
+
+// 	m->mat[0][0] = 1;
+//     m->mat[0][1] = 0;
+//     m->mat[1][0] = 0;
+//     m->mat[1][1] = -1;
+// }
+
+// main() driver
+int main() {
+	// OPEN MPI
+	MPI_Init(NULL, NULL);
+
+	int world_rank;
+    MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
+    int world_size;
+    MPI_Comm_size(MPI_COMM_WORLD, &world_size);
+
+	const int PING_PONG_LIMIT = 3;
+    printf("HELLO WORLD\n");
+	
+    // 10 / 4 = 2 2 2 (10-6)
+    int kernel_row, kernel_col, target_row, target_col, num_targets;
+	int counter_distribute = 0;
+	int counter_receiver = 0;
+	
+	// reads kernel's row and column and initalize kernel matrix from input
+	scanf("%d %d", &kernel_row, &kernel_col);
+    // Matrix* kernel = (Matrix*)malloc(num_targets * sizeof(Matrix));
+	Matrix kernel = input_matrix(kernel_row, kernel_col);
+	
+	// reads number of target matrices and their dimensions.
+	// initialize array of matrices and array of data ranges (int)
+	scanf("%d %d %d", &num_targets, &target_row, &target_col);
+	Matrix* arr_mat = (Matrix*)malloc(num_targets * sizeof(Matrix));
+	Matrix* arr_mat2 = (Matrix*)malloc(num_targets * sizeof(Matrix));
+	int arr_range[num_targets];
+    
+	
+	// read each target matrix, compute their convolution matrices, and compute their data ranges
+	for (int i = 0; i < num_targets; i++) {
+		arr_mat[i] = input_matrix(target_row, target_col);	 
+	}
+
+    print_matrix(&kernel);
+
+	
+
+    printf("HELLO OPEN MPI\n");
+
+	
+
+    // --------------------------- Create the datatype ----------------------------- //
+    MPI_Datatype mat_MPI;
+    int lengths[3] = { NMAX * NMAX, 1, 1 };
+ 
+    // Calculate displacements
+    // In C, by default padding can be inserted between fields. MPI_Get_address will allow
+    // to get the address of each struct field and calculate the corresponding displacement
+    // relative to that struct base address. The displacements thus calculated will therefore
+    // include padding if any.
+    MPI_Aint displacements[3];
+    Matrix dummy_matrix;
+    MPI_Aint base_address;
+    MPI_Get_address(&dummy_matrix, &base_address);
+    MPI_Get_address(&dummy_matrix.mat, &displacements[0]);
+    MPI_Get_address(&dummy_matrix.row_eff, &displacements[1]);
+    MPI_Get_address(&dummy_matrix.col_eff, &displacements[2]);
+    displacements[0] = MPI_Aint_diff(displacements[0], base_address);
+    displacements[1] = MPI_Aint_diff(displacements[1], base_address);
+    displacements[2] = MPI_Aint_diff(displacements[2], base_address);
+ 
+    MPI_Datatype types[3] = { MPI_INT, MPI_INT, MPI_INT };
+    MPI_Type_create_struct(3, lengths, displacements, types, &mat_MPI);
+    MPI_Type_commit(&mat_MPI);
+     
+    // --------------------------- End Create the datatype ----------------------------- //
+
+	// Distribusi matriks input ke process-process
+	
+    /*
+    0 1 2 3 4 5 6 7 8 9
+
+    0 1 2
+
+    3 4 5
+
+    6 7 8
+
+    9 10 11
+
+    */ 
+
+    int root = 0;
+	int divide = num_targets/(world_size-1);
+ 	int divideInput[world_size-1]] = { NMAX * NMAX, 1, 1 };
+
+	//  [[1,2,3], [4,5,6], [7,8,9],[10]]
+
+	if (world_rank == root){
+		// Divide input
+		int i;
+		int sisa = num_targets % (world_size-1)
+		for (i = 1; i < world_size; i++) {
+			int jumlah_diambil = divide
+			if (sisa != 0){
+				jumlah_diambil += 1;
+				sisa -= 1;
+			}
+
+
+			if (i != world_rank) {
+				MPI_Send(&kernel, 1, mat_MPI, i, 0, MPI_COMM_WORLD);
+				for (int j=0; j<divide; j++){
+					MPI_Send(&arr_mat[j], 1, mat_MPI, i, 1, MPI_COMM_WORLD);
+				}
+			}
+		}
+	} else {
+		Matrix recv_data;
+		MPI_Recv(&recv_data, 1, mat_MPI, root, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
+		Matrix kernel_recv;
+		MPI_Recv(&kernel_recv, 1, mat_MPI, root, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
+
+
+		
+	}
+
+
+	
+    
+
+
+    while (counter_distribute < PING_PONG_LIMIT){
+        // distribute(arr_mat[counter_distribute],1,mat_MPI,0, MPI_COMM_WORLD)
+		printf("Counter dis %d \n", counter_distribute);
+		if (world_rank == root) {
+			// If we are the root process, send our data to every process
+            int i;
+            for (i = 0; i < world_size; i++) {
+                if (i != world_rank) {
+                    MPI_Send(&arr_mat[counter_distribute], 1, mat_MPI, i, 1, MPI_COMM_WORLD);
+                    MPI_Send(&kernel, 1, mat_MPI, i, 0, MPI_COMM_WORLD);
+                    
+                    counter_distribute++;
+
+                    MPI_Send(&counter_distribute, 1, MPI_INT, i, 2, MPI_COMM_WORLD);
+                }
+            }
+			
+		} else {
+			// If we are a receiver process, receive the data from the root
+            Matrix recv_data;
+            MPI_Recv(&recv_data, 1, mat_MPI, root, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
+            Matrix kernel_recv;
+            MPI_Recv(&kernel_recv, 1, mat_MPI, root, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
+            print_matrix(&recv_data);
+            print_matrix(&kernel_recv);
+            MPI_Recv(&counter_distribute, 1, mat_MPI, root, 2, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
+			printf("HASILLL\n");
+			arr_mat2[counter_receiver] = convolution(&kernel_recv, &recv_data);
+            
+            print_matrix(&arr_mat2[counter_receiver]);
+			arr_range[counter_receiver] = get_matrix_datarange(&arr_mat2[counter_receiver]);
+            counter_distribute = counter_distribute;
+			printf("Counter reciver now %d \n", counter_distribute);
+            printf("Counter disribute now %d \n", counter_distribute);
+            
+			counter_receiver++;
+		}
+    }
+
+    printf("HOOOOOOOOOOOOOOO");
+	
+
+    MPI_Finalize();
+
+	print_array(arr_range,num_targets);
+    // Print hasil
+	for (int i = 0; i < num_targets; i++) {
+		printf("\nMATRIX CONV %d",i);
+		print_matrix(arr_mat2); 
+	}
+
+	// sort the data range array
+	printf("\n");
+	print_array(arr_range,num_targets);
+	merge_sort(arr_range, 0, num_targets - 1);
+	
+	int median = get_median(arr_range, num_targets);	
+	int floored_mean = get_floored_mean(arr_range, num_targets); 
+
+	// print the min, max, median, and floored mean of data range array
+	printf("%d\n%d\n%d\n%d\n", 
+			arr_range[0], 
+			arr_range[num_targets - 1], 
+			median, 
+			floored_mean);
+
+    
+	
+    // START OPEN MP	
+	
+	
+    
+	
+	return 0;
+}
-- 
GitLab