From a1433fa640fb0925f7c9fd5329f79dfa67fc18c1 Mon Sep 17 00:00:00 2001
From: gazandic <gazandic@gmail.com>
Date: Fri, 19 Feb 2016 14:10:42 +0700
Subject: [PATCH] openmp work

---
 bucket_sort.c | 177 ++++++++++++++++++++++++++++++++------------------
 bucketsort.c  | 130 ------------------------------------
 main          | Bin 16792 -> 0 bytes
 3 files changed, 114 insertions(+), 193 deletions(-)
 delete mode 100644 bucketsort.c
 delete mode 100755 main

diff --git a/bucket_sort.c b/bucket_sort.c
index 1c0b4ff..151d166 100644
--- a/bucket_sort.c
+++ b/bucket_sort.c
@@ -3,7 +3,7 @@
 #include <time.h> 
 #include <omp.h> 
 #include <assert.h> 
-
+#include <time.h>
 int *create_rand_nums(int num_elements) { 
 	int *rand_nums = (int *)malloc(sizeof(int) * num_elements); 
 	assert(rand_nums != NULL); 
@@ -16,79 +16,130 @@ int *create_rand_nums(int num_elements) {
 
 int main(int argc, char** argv) {
 	if (argc != 3) {
-		fprintf(stderr, "Usage: avg num_elements nuim_thread\n");
+		fprintf(stderr, "Usage: avg num_elements num_threads\n");
+		exit(1);
 	}
+	//MPI_Status Stat;
 
 	srand(time(NULL)); 
 	 
-	int world_rank; 
-	int thread_count; 
-	int position=0, order=0;
-	int i, j, k, l, t, rc, max = -RAND_MAX, min = RAND_MAX;
+	//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); 
+
+	int i, j, k, l, max = -RAND_MAX, min = RAND_MAX;
 	int total_elements =  atoi(argv[1]);
 	int range;
-	
-	int my_rank; 
-	thread_count = atoi(argv[2]); 
-
-	
-	int inmsg[total_elements];
-	int bucket[total_elements];
+	int world_size =  atoi(argv[2]);
+	//int inmsg[total_elements];
+	int bucket[world_size][total_elements];
 	int *rand_nums = NULL;
-
-	double time_start, time_stop;
-
-	rand_nums = create_rand_nums(total_elements); 
-	for (i = 0; i < total_elements; i++) {
-		if (rand_nums[i] > max)
-			max = rand_nums[i];
-		if (rand_nums[i] < min)
-			min = rand_nums[i];
-	}
-	range = (max - min) / thread_count + ((max - min) % thread_count > 0);
-	//time_start = MPI_Wtime();
-	//bucketing
-	#pragma omp parallel num_threads(thread_count,position,order) shared(rand_nums) private(bucket,i,j,k,my_rank)
-	my_rank = omp_get_thread_num();
-	for (j = 0; j < total_elements; j++) {
-		if ((rand_nums[j] < my_rank * range + range) && (rand_nums[j] >= my_rank * range)) {
-			bucket[i] = rand_nums[j];
-			i++;
-		} 
-	}
-	for (l = i; l < total_elements; l++) {
-		bucket[l] = RAND_MAX;
-	}
-
-	//Sort
-	for (k = 0; k < i-1; k++)
-		for (j = k+1; j < i; j++)
-			if (bucket[k] > bucket[j]) {
-				int temp = bucket[k];
-				bucket[k] = bucket[j];
-				bucket[j] = temp;
+	clock_t time_start, time_stop;
+	time_start = clock();
+	// if (world_rank == 0) { 
+		rand_nums = create_rand_nums(total_elements); 
+		for (i = 0; i < total_elements; i++) {
+			if (rand_nums[i] > max)
+				max = rand_nums[i];
+			if (rand_nums[i] < min)
+				min = rand_nums[i];
+			printf("%d ",rand_nums[i]);
+		}
+		printf("\n");
+		range = (max - min) / world_size + ((max - min) % world_size > 0);
+		//time_start = MPI_Wtime();
+		for (i = 0; i < world_size; i++) {
+			k = 0;
+			for (j = 0; j < total_elements; j++) {
+				if ((rand_nums[j] < i*range+range) && (rand_nums[j] >= i*range)) {
+					bucket[i][k] = rand_nums[j];
+					k++;
+				} 
+			}
+			for (l = k; l < total_elements; l++) {
+				bucket[i][l] = -1;
+			}
+			//rc = MPI_Send(bucket[i], total_elements+1, MPI_INT, i, 1, MPI_COMM_WORLD); 
 		}
-	while (order != my_rank);
-	
-	#pragma omp critical
-	
-	for (j = 0; j < total_elements; j++) {
-		if (bucket[j] >= 0) {
-			if (bucket[j] < RAND_MAX) {
-				rand_nums[position] = bucket[j];
-				position++;
+		for (i = 1 ; i < total_elements-1; i++)// {
+			for (j = i; j < total_elements; j++)
+				if (bucket[0][i] > bucket[0][j]) {
+					int temp = bucket[0][i];
+					bucket[0][i] = bucket[0][j];
+					bucket[0][j] = temp;
+			}
+			/*j = i;
+		 
+			while ( j > 0 && bucket[0][j] < bucket[0][j-1]) {
+			  t          = bucket[0][j];
+			  bucket[0][j]   = bucket[0][j-1];
+			  bucket[0][j-1] = t;
+		 
+			  j--;
+			}
+		}*/
+	// } else {
+		//rc = MPI_Recv(inmsg, total_elements+1, MPI_INT, 0, 1, MPI_COMM_WORLD, &Stat); 
+		//Sort
+		int thread_count = strtol(argv[2], NULL, 10);
+			#pragma omp parallel for num_threads(thread_count) 
+			for(k=0;k<world_size;k++)
+				for (i = 0; i < total_elements-1; i++)
+					for (j = i+1; j < total_elements; j++)
+						if (bucket[k][i] > bucket[k][j]) {
+							int temp = bucket[k][i];
+							bucket[k][i] = bucket[k][j];
+							bucket[k][j] = temp;
+						}
+		/* for (i = 1 ; i < total_elements; i++) {
+			j = i;
+		 
+			while ( j > 0 && inmsg[j] < inmsg[j-1]) {
+			  t          = inmsg[j];
+			  inmsg[j]   = inmsg[j-1];
+			  inmsg[j-1] = t;
+		 
+			  j--;
+			}
+		} */
+		//rc = MPI_Send(inmsg, total_elements+1, MPI_INT, 0, 1, MPI_COMM_WORLD);
+	// }
+	// if (world_rank == 0) { 
+		k = 0;
+		for (j = 0; j < total_elements; j++) {
+			if (bucket[0][j] >= 0) {
+				rand_nums[k] = bucket[0][j];
+				k++;
 			}
 		}
-	}
-	//time_stop = MPI_Wtime() - time_start;
-
-	if (my_rank == 3) { 		
-		for(j=0;j<total_elements;j++){
-			printf("%d",rand_nums[j]);
+		for (i = 1; i < world_size; i++) {
+			// rc = MPI_Recv(bucket[i], total_elements+1, MPI_INT, i, 1, MPI_COMM_WORLD, &Stat);
+			for (j = 0; j < total_elements; j++) {
+				if (bucket[i][j] >= 0) {
+					rand_nums[k] = bucket[i][j];
+					k++;
+				}
+			}	
 		}
-		free(rand_nums);
-		
-		//printf("%d processes, %d elements, %.2lf seconds", thread_count, total_elements, time_stop);
+		// time_stop = MPI_Wtime() - time_start;
+
+	for(i=0;i<total_elements;i++){
+		printf("%d ",rand_nums[i]);
 	}
+	printf("\n");
+	time_stop = clock();
+	double waktu = (double) (time_stop - time_start) / CLOCKS_PER_SEC;
+	//if (world_rank == 0) { 
+	free(rand_nums);
+	printf("%d processes, %d elements, %.2lf seconds", world_size, total_elements, waktu);
+	//} 
+	 
+	// MPI_Barrier(MPI_COMM_WORLD); 
+	// MPI_Finalize(); 
 }  
 
+
+
diff --git a/bucketsort.c b/bucketsort.c
deleted file mode 100644
index 8f7c19e..0000000
--- a/bucketsort.c
+++ /dev/null
@@ -1,130 +0,0 @@
-#include <stdio.h> 
-#include <stdlib.h> 
-#include <time.h> 
-#include <mpi.h> 
-#include <assert.h> 
-
-int *create_rand_nums(int num_elements) { 
-	int *rand_nums = (int *)malloc(sizeof(int) * num_elements); 
-	assert(rand_nums != NULL); 
-	int i; 
-	for (i = 0; i < num_elements; i++) { 
-		rand_nums[i] = rand() % num_elements;
-	} 
-	return rand_nums; 
-} 
-
-int main(int argc, char** argv) {
-	if (argc != 3) {
-		fprintf(stderr, "Usage: avg num_elements num_thread\n");
-	}
-	 
-	int world_rank; 
-	
-	int i, j, k, l, t, rc, max = -RAND_MAX, min = RAND_MAX;
-	int total_element =  atoi(argv[1]);
-	int total_thread =  atoi(argv[2]);
-	int range;
-	
-	int inmsg[total_elements];
-	int bucket[total_elements];
-	int *rand_nums = NULL;
-
-	//double time_start, time_stop;
-	//if (world_rank == 0) { 
-		rand_nums = create_rand_nums(total_elements); 
-		for (i = 0; i < total_elements; i++) {
-			if (rand_nums[i] > max)
-				max = rand_nums[i];
-			if (rand_nums[i] < min)
-				min = rand_nums[i];
-		}
-		range = (max - min) / total_thread + ((max - min) % total_thread > 0);
-		//time_start = MPI_Wtime();
-		
-#  pragma omp parallel for schedule(static) default(none) \
-      shared(rand_nums) private(i, bucket, j,k) \ num_threads(thread_count)
-      
-		
-		
-		for (i = 0; i < total_thread; i++) {
-			k = 0;
-			for (j = 0; j < total_elements; j++) {
-				if ((rand_nums[j] < i*range+range) && (rand_nums[j] >= i*range)) {
-					bucket[k] = rand_nums[j];
-					k++;
-				} 
-			}
-			for (l = k; l < total_elements; l++) {
-				bucket[l] = -1;
-			}
-			//rc = MPI_Send(bucket[i], total_elements+1, MPI_INT, i, 1, MPI_COMM_WORLD); 
-		}
-		for (i = 1 ; i < total_elements-1; i++)// {
-			for (j = i; j < total_elements; j++)
-				if (bucket[i] > bucket[j]) {
-					int temp = bucket[i];
-					bucket[i] = bucket[j];
-					bucket[j] = temp;
-			}
-			/*j = i;
-		 
-			while ( j > 0 && bucket[0][j] < bucket[0][j-1]) {
-			  t          = bucket[0][j];
-			  bucket[0][j]   = bucket[0][j-1];
-			  bucket[0][j-1] = t;
-		 
-			  j--;
-			}
-		}*/
-	//} else {
-		//rc = MPI_Recv(inmsg, total_elements+1, MPI_INT, 0, 1, MPI_COMM_WORLD, &Stat); 
-		//Sort
-		for (i = 0; i < total_elements-1; i++)
-			for (j = i+1; j < total_elements; j++)
-				if (bucket[i] > bucket[j]) {
-					int temp = bucket[i];
-					bucket[i] = bucket[j];
-					bucket[j] = temp;
-			}
-		/* for (i = 1 ; i < total_elements; i++) {
-			j = i;
-		 
-			while ( j > 0 && inmsg[j] < inmsg[j-1]) {
-			  t          = inmsg[j];
-			  inmsg[j]   = inmsg[j-1];
-			  inmsg[j-1] = t;
-		 
-			  j--;
-			}
-		} */
-		//rc = MPI_Send(inmsg, total_elements+1, MPI_INT, 0, 1, MPI_COMM_WORLD);
-	//}
-	//if (world_rank == 0) { 
-		k = 0;
-		for (j = 0; j < total_elements; j++) {
-			if (bucket[j] >= 0) {
-				rand_nums[k] = bucket[j];
-				k++;
-			}
-		}
-		for (i = 1; i < total_thread; i++) {
-			//rc = MPI_Recv(bucket[i], total_elements+1, MPI_INT, i, 1, MPI_COMM_WORLD, &Stat);
-			for (j = 0; j < total_elements; j++) {
-				if (bucket[j] >= 0) {
-					rand_nums[k] = bucket[j];
-					k++;
-				}
-			}	
-		}
-		//time_stop = MPI_Wtime() - time_start;
-
-	//}
-	//if (world_rank == 0) { 
-		free(rand_nums);
-		printf("%d processes, %d elements, %.2lf seconds", total_thread, total_elements/*, time_stop*/);
-	//} 
-	
-}  
-
-
diff --git a/main b/main
deleted file mode 100755
index 91b7da3fb8bdd7a99ad1da4ae86fdf1906010917..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 16792
zcmeHOe{@{Mb)L6xwc54h-IZk<2|Hnf?I569OGY*_j>F3Knia@DFfx#U^R(JsNgJ<r
z)%_uCiY>$1jyFO?N(eQS7AJ?KZcdu|v}uk5)X1@moR%hny5N&K2SY+CVUjvAF-kC~
z-<>zJdi%6$+Md(@JbT`|bHBNF=FXjYvor6_^!Z!XTNH)KU}2wT#CaS(4(WHs&NOmX
zV2#Ydd~6Z(FdL8(Tt1#cRF6qIA+na#F62~DE3QV14m4VPJR<2r9cGeB3yD&BQ^6;q
zI{kKq&Ps}!aDep4)(aowENB~#Ncya>V^~nBM=a^tKhDKL+jvCM3&Jo-W&NmbbhV27
zS}i_s#QTV_b^Ja>NtVLqx6@&YFLrYl)W;)|&ZKuI^vKTtX%N}7Euy@c{Nfh&ODd|%
zmd2v(D;k!@!nLtzJhP*AN8^gx6%F20!n=&uoAM{w+cs|HCP_bfz)}6?;-Wr4>6fhG
zw|<<~T=(7c#-E*k_|7lBdb;x+lCQ)i+l@yU<JJ(q@;CjmYk->`=0b7KbeK7Td5Yi}
zV8!GQ%z(c+1OBfw;FcNeIW>d)4ZuCP%;84>irG0f1HKZt2bVc~2%uO#muA2>0QcZB
zhfV;+@_A|o{D(8({|UT;RkK5$HpK9}@jGtlXPt@e9_m^3Olxl4poJsJNM|&ajwD+*
ztc@k&k=9^)EW$LcvpW&jQt4nat!YfVy;s{J<krT5sZ=DTs~1(iZPSL$T2C+;jKv}`
zhVrz|NLovGB_qMG7SD7uE)Ysa)6q~crbXgm6T*unV|#QZvbT=-5XDxoR5A#ibhMic
zC2L@0M=%;=J;`W1-NCw1aw5c1Y1A&sIvzkt5f)4*q7bKCM7_F$(Kzc!Mk0Fg4Jd<K
zR!@<Z<~3`zW!`1p<>WkiR8%}`7V#s5F#TR4QWVIbYchIXeYi#!eG-pn39AN3*k}#$
zR(7r6eT#`#*&<RxQ1CkjD#w$|)lmnPaid6|xTcN7_!x?We30!-V>vy~GE|B7F9jg7
z;7J|>PUD6QH3po<6&dObxbgp@(SRGrOP>L!vSkPu@O+;{;${PGtk=B;e3r}vw9SB*
z8SpLxKHGrz7;qZ1WY}TArOzpCj{z5dfn4Q)0XIIUf$Y2XK!3?^ukx_KzTtGq*jFGP
z$ey&H;A;8X<np&5GP&gExVx_LAx3-`rH`MRL|F0@;;E^|M>+p0@zl}AhdKXG#H+*~
z;rtJXr=}V|#QEolrzRR7<ow?fPfatvhx6Yeo|<I5hx1=2o|<C3jq^_tPfaksne$&J
zo?Jif<NOziCzp@casCnF%Zc}J{z2l&_2X{NCy6JQk2CP~ziiIE^0`3ntw8qY7dE#x
zj|?Aj`B-4&cpWDrPtNkOv6~_IUWe<Nb&MT-1`gjEs67Z0$WAx|xwm^497S&2%@x~T
zq=d<H5Z+55+jgRZf>-j#D1B?-;a~9#j(?;ggFx;=;P}|B0p+E@D<7rj<#Q{Oxw)>P
ze0ceLR=+ae!&s(bD-_4#Fl^gPCC30M7f(?8y~r?u31n|&nUeEgfnGkdUz5V*=(h0(
zp+oVz&_!x;yUzCe&jt<#j-RsxawB5{A5BgMa{hCH?5=YxQ~iCn+sB?G=N}t}KVJM1
zZe!Ju8S%eMwLAaGe*e4B9+<n2*g!ut2Nqh!o`A@c@9#RB8_lU%|GNsLR{769^ePv~
zo~*fV+X*tE>F%bjO|5qY9)9--v~&LugK2@>-&4B>a_5?JC$k(<(;r7yes!LQ1#-uq
zTMW@-)E{3QBWphRaB}iRaBS>2VyMDXAS3>>1daHIb#e;wdq(^xk#S$3e;+R(JB$Ye
zIgX4SCPn`XQweU7@Fkvbv>$1q(LnYcC6L>Cgrd2xQeO;=?7J6)iqJuy4hAHsyLDi*
zdXygJKz2+CD5K9){5h`l{>8xdVRzvAlc;SVJFKD?SoD_gA1)~Lke)wva1`1o^M@q^
z3%|;<3XL}B{;i2dY9?CKRO~TBv6p5n_F!PdKS-INczEVC9DwdHIO0D;;Q3g;|4c!1
z528Z-Y?c4i?&{)6Isd8R39I}kcg?7CGV4EsPIG3J|AmJh?f0L$(SH)%>1gh_AwIfq
z*!9e?>wCk>sht1OK<>|b;FkWa!-0W)6#G6I9LT-&qKkUT+aFM;IL#~3)9*h$y%O$z
z|AFkV;`$r^qbq-~3mtU^8C~F^>xv4XNBIx-Z#@$Ty_zc@q)KG{r%{p9RFMOyP|pAI
z`FXm~%Mco|4#L#Ftp8;Qy-Y$s8}W~FD^vacQP`97pFV%Tt}qIP{_;VcIZcdpaOLsc
zw-{2bgE{|RgMgGKRTyMQ*|3)zD2zMv(9>D}D0v)xbd`U!?~#80@GAd-%*5F9zn}8l
zorVmogZqYee5wFgO?64v=mW~skT4h+D7O>{=HQmIM%Vo1*t5TzoXqYzpk~kk^=7)U
zsD~L^bT$ShKCX@JCaozC{|ibPq$hd>@Rr=q^}%l-a_+vS`<u2keNG>BFz$H*xm{yp
z9!TZ<mw$L-YIq)Ox(9<&Zj#2OmVqVTae6RV57ZL9t2uWG&sfX#Z}b1w;~%PHe>#E3
zW8W{+p89{6<9kc)otE6Cb;x0I?%6>0gc4YJKJyO!@!q#hH=;?yUqb%>;Nl4y81P>$
z{+bm&hoc^#hxSZpJ7%h>L^ACSF`8u3bT#Gq#A;7XO>ZI^_S|rN-Sv!ZO$9q6w|IiR
zogSoXkyxZV5>KbVM7za2cNSX`W+BXY(-AG75tX7WP*?dt=}-9b`;(K85=GVS2mK9v
z^j**lx&e);=P|NdF`Aa6trvqn1R4XKi!=(#gIk!g!>ueRFSQRUrEbC(;yQ@@Xw4%-
zae1tZAwcq7u!Bz!o$mF{s@q*<57_sxTd!Vq!%d5?r94P(9WH9=ECEeU_kPRT**1Sx
zwd_RUgdvbz4A&6kdaZ~^xs8vh1J*}NvNknjg*cV@IIcG^;>`!m%iXExMP+>#*Eys|
zD1D97{Uys9XVqh>-{~2!u5s2pS`u*9?Y9M-joH!-PG8d5*yOBha@MSIdLRe+HBLMC
z(`BgJ;YXT8T?tn_aK!^xJaEMWS3GdV16Mq7#RFG7aK!^xJn(<@zy<MLcT`ZB50+>=
znCW*+IDdl#tX$v|r9K{;E%;~gHibepzti{DHXd6bc)9MnTJRGhoz_<rWcqJEnoJOX
z(BdPK|K@whs`K*Q{jf#n<-7KqMFr$L_9~`_d4fu!%7~|p$K+azzsUw7*PrrRz*Rzi
z(B|VYiMI(}+Fd8)<Tn9XK9+O5K1|4CS<HD^?ghc0Dbe#6+5Eo~`5oI_&<eY5$9h5U
z7PLdqUP1Q@`h=k06!d$7z9i^tg8o9#OM==&Kb&vqkGHK|dyA(AUxu&uEce!X>pjcr
z>X+B8sBiStY>9+DfnZw4Ya6a-e+0vIAL=bIf0k~yi@qon3GZ3;@6YII%0Bd!@_EqS
z55Z!J7V4E2zV$)1m);6SRqUluP%Wh^p{!a<*KyG1;9$uj5UaHWU-X!2FNu;iE~aLA
zbOQ<Pr6_WXL%+msv(xKYRk6|c_0qS1ow5FQA>#JG0&cz3jytnc)vO<UiAU)rg!MAT
z-S&GRX#J4lRra?i{t?AJ_9e*2I!W;w#{(2+3Ndw#THLJ)XBr(xh_P_S=V&1@D`x_Z
zZ&6+)oZ0M%5M$%ay^fDa%&yR`hBgO1Q`T9^XTfwizD7*B(hkz&Xd^K<XVQ+>C}ob)
z1G2;M0x|QI^&op3wUqT$N-LO09E&KWN@)X@b$pgGSg7=XIpFvSr7ThY1Z2>WBpt6Z
z0Op`$CoxMobI7rWm^#iJc6@=Ddd?hiJVwkig=&A)K~K1~f!j9h_$sBWP<la5vRSWF
z(o>}qkgKvDqDtCtBZ05+T^#nCDEaGDUAz5v6#r&BB;Cwrr*^m5p9WV(?MY^rQ>P-7
zT9c#uC0Yrz9ckzyVNObK0h#?4Zb~Uh$-c;6ToL;8`#_!dZ~@Y^47Iq%iL;ZqWoWZI
z39b}_nnR^eG88JJOqrz%->(}$>D(+gn?o7S{wZ!s1<BB7EDHP;7^w2}4m>E%k-UI9
zbauD%8=R#Sb!c>V<;%oYk-F<SidIup9Xj0SQsEutYGTRKJ1IlXsY6Hl$gTx?QlR4V
z`S`ku?fJN`A|~SM&<lNY(}J0s42f7pcW_5u;%Hw*H@=GNnW{tI?Q{K_tXZgA^X)#@
zMY85&I(vDy>pZd7=<LL9*Xty_Xg4Zl9Xi-&bDbh<7k`=a2f%YbFCjmxLwouvKSko#
zeG|!*<&+VR&imPHAJiD5hNR%Sh?}xjFXX-5)DP$hEF*xjo=?5QI&`Sdrel<!zy^V-
zcI%HJaMgU2K;I`Q@VAbj%F}N^xavP}vkcv9sEuVP#;WaC+bMa$o476f3)ounE$Xmn
zW@U-9vP^X@a8@XDO5ONBv&?6z^OmwzWzF~iuP$a~WuHbm%o0(IIwdZkFrElWl~yXM
zv#gAi6tMQ$`5YP{<`8U2b0x8}Wd5kPqBK{MM)@aLbLCPb&h{#|R_n!ISKVAmHu<Wa
zSW`_x&XRn#7W{v@8VXo9vCWkY)s$8N#;(_a*g2m>_Gp<Y4g8Z&i7+;=433zCKkxb6
z5U5<`MU}3rZm2FWp{fKK=|xmmqVf%x&s^;mURZE5FJ<9WDYsUCiY7dRXf6wThTN@u
z;GB&+-&sf9WN9Xqq&-thJ42zR*es>3XsAs_!d=0%zJY2f|EF6TjfY~HaD;Jj!7Oc$
zrc(t7V}-B%Q6M&sgd-i^E_x@P-q{mLA&PcKiO~e2c=913qi8CN9Am1Ux8K1mR>hXK
z+4mx%4$;j%$+6pQ`|jwqzt%Zq|7ZLB*I&2qx9_uLDlHFG?tgvA{)|0qe+FU}`)(n8
zz_MhXWzk&9L9tmD&#~DrS{7B3$Zb*rRL#;&7Vw3kzqbGIqMdXsztW{BYI`^zS8RW`
z_p?LxO8aWdVxHN0J;}C5Ex)%DaouFgbrk~NXZNXhpL+gbiv=y9X^D;wEsecDn>4<g
zrzf3cTBwUQ(xjpfMkp!Oh0iDLnGP-ls<j7G5r(ZrogRM6#8c7EIHn%-$DT-Hiw-k>
zL@`K`fTnHU;%{yJjJAI3#<i`@n>J!M($daMB$ZyesV5TOuzAWB+DD{yL}QV70yGxv
zq&-TTG%|rFg)&Jkl!#@z<D$h`IFaF-of5GyRV)=rPyb|-j&%3%e7b|l?Xa~ck;1;E
zM4WFw!bYM*54Iac<6e#SId#Obb%+Y(TaGmDofP?kJH=B_brMSjdn3AkG;CPfF3euW
zwC)7@EqRo>pCL!SS8C%{&)WL>KRBK9)OM#c@yP1VNIa5^hQJ1sp{~{X=0Z<xr>C|f
z0T+tuQTd`}*EhHLS@%x*Znd4hf_1_IR2x=t7o=Fe9%%Wb>G9EP%A2k?O?%0tXKA~Z
zzVV7_@yHHpTKIfLgRwjDu99~QZ#8Tr3uCVu5%`73O*(1N$#SM;;+a$gsbarZFxlCw
zw|p?PJ=3H6SL{9uB{Jw#kO;8{5=k^WuVXaco$BPxXmB;RC7npq4mI(Ck1=m*XE$mE
znojDpOU6*;NV11{<B4>{+q9;+HXZB~TxUGvZO=rpzcU(UUgElfsV?RX?~Efqo#H{_
zDZP<oin^DP(U6vm#Db(CVm+}m^G4%Q+|%StZwDBpCBngUka;6rT1PSnhj)dcD>+?5
z3nr7now|mMe?9~;<R0vfhEQ|@8RF*UrRX`fr&7!tN_5kgPKZX@Go4VT&H-F!qw$V}
zj0fA>laXG@VOwiN#^Emvv41eoPP#^mZ<?Hnk+`)euCjDd+?rqa8Z%R|3LY*hZ)0*@
zTqs}4imfMAT4mdOMo}JDv8%hSC_anHb+1uLWo1mR{|oVQEJA!nh{shnJHM~on5be`
zu6%D$h`ZPkG5aaR-T8gdg?I()60_ezd`|v7L?K?u<okz0d@iGHQs$ttdHMa{#xxak
zGr7;P5XUUb(`JNtTxC^kuqZyY|JA6ZGWoW|h+@vh<XaUpF5jk@@sAY(f>YVYXTYzS
zhGTkx<>asVrY2(|y$@38t%=ERG%d2A-8VaYMsem9_@D`I61e&O6kq$`t<quPH?o65
z2QCFWNX_j?>q9E{f+_zex%~A0a1?m4dcDNuT`a$<0#D%$T$KN`**WlH`TPpFf*sC>
zD}0Deh0BN*^BYMN%g4?uK4)5eX}_*gq<_-BUD}~7-@_3{VL6wd-aqdEJ_q$WB%V83
zJ5acf<9gh9?*{HM0wSK{`1F4MIL~MHv?cC0fV=TrJZ^d}zRl&Q7eG7q<`fw>el&yp
zJ2T+)LSxSK>{&G`UJR%6D#h?SfRp{^=lWjYo+9~o0<W;R*iqB?mL{A{jeA(e@sI^x
ztXz75LG4A`Q7Q1fC!n-cFDCze;BGueM@)V`Ci0Qzes18oG4_u_-rO#)2zm31gV%t2
zgszd$fsSJKT%G}UtK^?5M%!SGVIgpj5fJeez>DR-aRxlb@#+6x$r<GL0xx<#A(Tv~
z(i!a73Sn}0``Rs9OY>c=nDI}YQqa=fT8Pdmq?kN=V1P6&oX|RBiFQod!s$dZr3EuP
z7-lU!u}C@+_O4jDjHZo6gs^akNA=kdRtxFmP8<xN`BOO4-Mtek22P`CSAl5Z0<y@G
z#d}lTO)I9Y6SVbPnl|_~|HgH6#DdpX#tVwTvS!_9Ha2Z&UJEHhihfK&yRBu@nx+<Q
z)B5#y`CGNtrZp{o%8nm&2&FQ-X8f3g&u2W<@ZTN(pedi2t54g*rbYOKaQd+hpO4Oc
z(BTQa$Z4lMP`;GV4{DeUG9KkHC-K_o$5CjxRhZ1rgA_t&<f%HCPqS#@R6^^*_C7l4
zLd!6$=HnVIBKWG#oKxPD<a=?r#3aL)Dxy6!OqGT6_z9C@hiB+8N?{iIDV0J@({Lz9
z_76I(BfEUTSsm_FdE5pWkdO0cS@NfBxN#ztw-K)lCh+0HGWA7NAy#CF_+LRZv%+5k
z{^Ru^=k+xHQ!vl4NY)q@fuV0iQeV#h`I}_m9$dyC$9aj>BVyE->je6Lps-jc`MX(v
z9a1jgo02U5pvA{!51RDlXA-Ok3c^NkcukkLf7s#!$FTn3gq;%=wt=On)UVQ$+1;QR
zGV}U!eR4<`db7!4CYF5;y7Y}q+Ar5JXN18uq8w?zl#_Hj(&?L<<eAN<YmmVRZTya9
z5Gct=`vuG%M1)M0`fWnLP3X(-e6oD0FYCWo=&unO%JtKr(3jsCNuTD<X8p&2kxztp
zew{TzodUtUA|P9hAqU2&FV|xpS&+%$ZlNsc<7Ry^kM=lp!AGQFCOyHjr%d{CefO+O
zmk`-VaqjCpgUBIVWTN!HTn8Qz`hScxV~}=B>@XrmeR+OXo~vCa1qC(x?|UYFxvuOI
z1+6prPr6lRJB)}E7d-<M<osKnvo*_``In(XRh9a3eKR4JaAtWke+If_qSVi?%fwR8
zEN|w23SDYqsV~11%X853ytC{EQeU>iFHGgj_3?yQQc8J<@gR9g&jT&6-_xcGdUP_V
zll)!kN%|gAjQVn3KIqX^%<XMzPWF3<QC_nCheY|03w>EnJvYV#ELlbiWXiKHkLVGp
zPv5PLL6$Emt@C8uC^ziUIdi^d*{f#IzaaD{Ob#&X)A>#_MkS9e(aVpR5=|_tpFw}a
zb-F&S1C7DNveiQ0T+cUagqCa=!AgBeD}b9sxa6BR>IwlVXwnxfue%(3Bu2EZR_ENJ
dqg@NO0hjD|a{Q<9tyuZK<+}bsQ=-Wn_FoEkLqz}p

-- 
GitLab