From 109d834f255c7613a01791b0f2ddfe2248ebee1e Mon Sep 17 00:00:00 2001 From: WaikeiChan Date: Wed, 25 Sep 2019 21:12:40 -0400 Subject: [PATCH 1/4] Implemented required methods and updated READ.md --- Project2-Stream-Compaction/README.md | 93 +++++++++++++++-- Project2-Stream-Compaction/src/main.cpp | 2 +- .../stream_compaction/CMakeLists.txt | 2 +- .../stream_compaction/common.cu | 14 +++ .../stream_compaction/common.h | 1 + .../stream_compaction/cpu.cu | 37 ++++++- .../stream_compaction/efficient.cu | 99 ++++++++++++++++++- .../stream_compaction/naive.cu | 51 ++++++++++ .../stream_compaction/thrust.cu | 12 ++- 9 files changed, 296 insertions(+), 15 deletions(-) diff --git a/Project2-Stream-Compaction/README.md b/Project2-Stream-Compaction/README.md index 0e38ddb..f14e7c6 100644 --- a/Project2-Stream-Compaction/README.md +++ b/Project2-Stream-Compaction/README.md @@ -1,14 +1,93 @@ -CUDA Stream Compaction +# Project 2-1 GPU Stream Compaction ====================== **University of Pennsylvania, CIS 565: GPU Programming and Architecture, Project 2** -* (TODO) YOUR NAME HERE - * (TODO) [LinkedIn](), [personal website](), [twitter](), etc. -* Tested on: (TODO) Windows 22, i7-2222 @ 2.22GHz 22GB, GTX 222 222MB (Moore 2222 Lab) +* Weiqi Chen + * [LinkedIn](https://www.linkedin.com/in/weiqi-ricky-chen-2b04b2ab/) +* Tested on: Windows 10, i7-8750H @ 2.20GHz 2.21GHz, 16GB, GTX 1050 2GB -### (TODO: Your README) +## Project Goal +In this project, we will implement CUDA stream compaction and use it to remove 0s (or any other elements you don't want) from arrays. 3 versions of exclusive scan are implemented for computing scatter indices: -Include analysis, etc. (Remember, this is public, so don't put -anything here that you don't want to share with the world.) +* CPU Scan +* Naive GPU Scan +* Work-Efficient GPU Scan +We will compare the performances of the three methods along with the implementation provided by Thrust library. + +## Performance Analysis +### Block Size Optimization +The bar plot below shows the performance vs block size. The best is 128 and we will use this for all subsequent tasks. + +![](img/bar.png) + +### GPU Scan Implementations vs CPU Scan Implementations +Below is a plot of performance vs array size for all four methods. For each method, an array size of power of two and one of non power of two are used. + +![](img/plot.png) + +* When the array size is below 213, CPU scan has the best performance. This could be due to the overheads of invoking kernels when computation time is not the bottleneck. +* As array size gets larger, GPU implementations start to perform much better than CPU method. +* Thrust's scan is the fastest of all when array size is large. This could be due to the use of shared memory instead of reading from global memory. + +### Extra Credit + +I didn't encounter the problem of GPU approach running slower than expected. I think this is because during the implementation of UpSweep and DownSweep for work-efficient scan, I change the grid size and allocate necessary threads in different stages of the sweeping process. It makes sense that if we use as many threads as the array size throughout the computation, inactive threads will be present and slow down the performance. + + +Console Output with a block size of 128 and an array size of 216. +``` +**************** +** SCAN TESTS ** +**************** + [ 17 25 12 21 22 4 37 44 40 8 40 46 43 ... 5 0 ] +==== cpu scan, power-of-two ==== + elapsed time: 0.2863ms (std::chrono Measured) + [ 0 17 42 54 75 97 101 138 182 222 230 270 316 ... 3209400 3209405 ] +==== cpu scan, non-power-of-two ==== + elapsed time: 0.2797ms (std::chrono Measured) + [ 0 17 42 54 75 97 101 138 182 222 230 270 316 ... 3209316 3209325 ] + passed +==== naive scan, power-of-two ==== + elapsed time: 0.726016ms (CUDA Measured) + passed +==== naive scan, non-power-of-two ==== + elapsed time: 0.727008ms (CUDA Measured) + passed +==== work-efficient scan, power-of-two ==== + elapsed time: 0.393216ms (CUDA Measured) + passed +==== work-efficient scan, non-power-of-two ==== + elapsed time: 0.39216ms (CUDA Measured) + passed +==== thrust scan, power-of-two ==== + elapsed time: 17.0906ms (CUDA Measured) + passed +==== thrust scan, non-power-of-two ==== + elapsed time: 11.7248ms (CUDA Measured) + passed + +***************************** +** STREAM COMPACTION TESTS ** +***************************** + [ 2 0 3 2 2 0 0 1 1 2 0 0 2 ... 2 0 ] +==== cpu compact without scan, power-of-two ==== + elapsed time: 0.5571ms (std::chrono Measured) + [ 2 3 2 2 1 1 2 2 1 1 1 3 1 ... 2 2 ] + passed +==== cpu compact without scan, non-power-of-two ==== + elapsed time: 0.5431ms (std::chrono Measured) + [ 2 3 2 2 1 1 2 2 1 1 1 3 1 ... 2 1 ] + passed +==== cpu compact with scan ==== + elapsed time: 0.2748ms (std::chrono Measured) + [ 2 3 2 2 1 1 2 2 1 1 1 3 1 ... 2 2 ] + passed +==== work-efficient compact, power-of-two ==== + elapsed time: 0.490592ms (CUDA Measured) + passed +==== work-efficient compact, non-power-of-two ==== + elapsed time: 0.49152ms (CUDA Measured) + passed +``` diff --git a/Project2-Stream-Compaction/src/main.cpp b/Project2-Stream-Compaction/src/main.cpp index d016553..49243a0 100644 --- a/Project2-Stream-Compaction/src/main.cpp +++ b/Project2-Stream-Compaction/src/main.cpp @@ -13,7 +13,7 @@ #include #include "testing_helpers.hpp" -const int SIZE = 1 << 8; // feel free to change the size of array +const int SIZE = 2 << 20; // feel free to change the size of array const int NPOT = SIZE - 3; // Non-Power-Of-Two int *a = new int[SIZE]; int *b = new int[SIZE]; diff --git a/Project2-Stream-Compaction/stream_compaction/CMakeLists.txt b/Project2-Stream-Compaction/stream_compaction/CMakeLists.txt index cdbef77..4bb0dc2 100644 --- a/Project2-Stream-Compaction/stream_compaction/CMakeLists.txt +++ b/Project2-Stream-Compaction/stream_compaction/CMakeLists.txt @@ -13,5 +13,5 @@ set(SOURCE_FILES cuda_add_library(stream_compaction ${SOURCE_FILES} - OPTIONS -arch=sm_20 + OPTIONS -arch=sm_61 ) diff --git a/Project2-Stream-Compaction/stream_compaction/common.cu b/Project2-Stream-Compaction/stream_compaction/common.cu index 2ed6d63..b596264 100644 --- a/Project2-Stream-Compaction/stream_compaction/common.cu +++ b/Project2-Stream-Compaction/stream_compaction/common.cu @@ -24,6 +24,12 @@ namespace StreamCompaction { */ __global__ void kernMapToBoolean(int n, int *bools, const int *idata) { // TODO + int index = threadIdx.x + (blockIdx.x * blockDim.x); + + if (index >= n) { + return; + } + bools[index] = idata[index] == 0 ? 0 : 1; } /** @@ -33,6 +39,14 @@ namespace StreamCompaction { __global__ void kernScatter(int n, int *odata, const int *idata, const int *bools, const int *indices) { // TODO + int index = threadIdx.x + (blockIdx.x * blockDim.x); + + if (index >= n) { + return; + } + if (bools[index]) { + odata[indices[index]] = idata[index]; + } } } diff --git a/Project2-Stream-Compaction/stream_compaction/common.h b/Project2-Stream-Compaction/stream_compaction/common.h index 996997e..2938bc0 100644 --- a/Project2-Stream-Compaction/stream_compaction/common.h +++ b/Project2-Stream-Compaction/stream_compaction/common.h @@ -12,6 +12,7 @@ #define FILENAME (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) #define checkCUDAError(msg) checkCUDAErrorFn(msg, FILENAME, __LINE__) +#define blockSize 128 /** * Check for CUDA errors; print and exit if there was a problem. diff --git a/Project2-Stream-Compaction/stream_compaction/cpu.cu b/Project2-Stream-Compaction/stream_compaction/cpu.cu index a2d3e6c..501803d 100644 --- a/Project2-Stream-Compaction/stream_compaction/cpu.cu +++ b/Project2-Stream-Compaction/stream_compaction/cpu.cu @@ -20,6 +20,10 @@ namespace StreamCompaction { void scan(int n, int *odata, const int *idata) { timer().startCpuTimer(); // TODO + odata[0] = 0; + for (int i = 1; i < n; i++) { + odata[i] = odata[i - 1] + idata[i-1]; + } timer().endCpuTimer(); } @@ -31,8 +35,14 @@ namespace StreamCompaction { int compactWithoutScan(int n, int *odata, const int *idata) { timer().startCpuTimer(); // TODO + int remain = 0; + for (int i = 0; i < n; i++) { + if (idata[i] != 0) { + odata[remain++] = idata[i]; + } + } timer().endCpuTimer(); - return -1; + return remain; } /** @@ -41,10 +51,33 @@ namespace StreamCompaction { * @returns the number of elements remaining after compaction. */ int compactWithScan(int n, int *odata, const int *idata) { + + int *temp = (int*)malloc(n * sizeof(int)); + int *scanResult = (int*)malloc(n * sizeof(int)); + timer().startCpuTimer(); // TODO + int remain = 0; + for (int i = 0; i < n; i++) { + temp[i] = idata[i] == 0 ? 0 : 1; + } + + scanResult[0] = 0; + for (int i = 1; i < n; i++) { + scanResult[i] = scanResult[i - 1] + temp[i - 1]; + } + + for (int i = 0; i < n; i++) { + if (temp[i] == 1) { + odata[remain++] = idata[i]; + } + } + timer().endCpuTimer(); - return -1; + + free(temp); + free(scanResult); + return remain; } } } diff --git a/Project2-Stream-Compaction/stream_compaction/efficient.cu b/Project2-Stream-Compaction/stream_compaction/efficient.cu index 2db346e..298317e 100644 --- a/Project2-Stream-Compaction/stream_compaction/efficient.cu +++ b/Project2-Stream-Compaction/stream_compaction/efficient.cu @@ -3,6 +3,7 @@ #include "common.h" #include "efficient.h" + namespace StreamCompaction { namespace Efficient { using StreamCompaction::Common::PerformanceTimer; @@ -12,13 +13,58 @@ namespace StreamCompaction { return timer; } + __global__ void kernUpSweep(int n, int offset, int *idata) { + int index = threadIdx.x + (blockIdx.x * blockDim.x); + if (index >= n) { + return; + } + idata[(index+1)*offset*2 - 1] += idata[offset*(2*index + 1) - 1]; + } + + __global__ void kernDownSweep(int n, int offset, int *idata) { + int index = threadIdx.x + (blockIdx.x * blockDim.x); + if (index >= n) { + return; + } + int t = idata[offset*(2 * index + 1) - 1]; + idata[offset*(2 * index + 1) - 1] = idata[(index + 1)*offset * 2 - 1]; + idata[(index + 1)*offset * 2 - 1] += t; + } + /** * Performs prefix-sum (aka scan) on idata, storing the result into odata. */ void scan(int n, int *odata, const int *idata) { + + int tempSize = pow(2, ilog2ceil(n)); + int* dev_idata; + cudaMalloc((void**)&dev_idata, tempSize * sizeof(int)); + cudaMemcpy(dev_idata, idata, n * sizeof(int),cudaMemcpyHostToDevice); + checkCUDAErrorFn("cudaMemcpyHostToDevice failed!"); + timer().startGpuTimer(); // TODO - timer().endGpuTimer(); + int level = ilog2ceil(n); + dim3 fullBlocksPerGrid; + + for (int d = 0; d < level; d++) { + int threads = 1 << (level - 1 - d); + fullBlocksPerGrid = dim3((threads + blockSize - 1) / blockSize); + kernUpSweep << > > (threads, 1 << d, dev_idata); + } + + cudaMemset(dev_idata + tempSize - 1, 0, sizeof(int)); + + for (int d = level - 1; d >= 0; d--) { + int threads = 1 << (level - 1 - d); + fullBlocksPerGrid = dim3((threads + blockSize - 1) / blockSize); + kernDownSweep << > > (threads, 1 << d, dev_idata); + } + + timer().endGpuTimer(); + cudaMemcpy(odata, dev_idata, n * sizeof(int), cudaMemcpyDeviceToHost); + checkCUDAErrorFn("cudaMemcpyDeviceToHost failed!"); + cudaFree(dev_idata); } /** @@ -31,10 +77,59 @@ namespace StreamCompaction { * @returns The number of elements remaining after compaction. */ int compact(int n, int *odata, const int *idata) { + + int tempSize = pow(2, ilog2ceil(n)); + int *dev_indices, *dev_bools, *dev_odata, *dev_idata; + + cudaMalloc((void**)&dev_indices, tempSize * sizeof(int)); + cudaMalloc((void**)&dev_bools, n * sizeof(int)); + cudaMalloc((void**)&dev_odata, n * sizeof(int)); + cudaMalloc((void**)&dev_idata, n * sizeof(int)); + + cudaMemcpy(dev_idata, idata, n * sizeof(int), cudaMemcpyHostToDevice); + timer().startGpuTimer(); // TODO + dim3 fullBlocksPerGrid = (n + blockSize - 1) / blockSize; + Common::kernMapToBoolean << > > (n, dev_bools, dev_idata); + + dim3 fullBlocksPerGrid2; + int level = ilog2ceil(tempSize); + cudaMemcpy(dev_indices, dev_bools, n * sizeof(int), cudaMemcpyDeviceToDevice); + int threads; + + for (int d = 0; d < level; d++) { + threads = 1 << (level - 1 - d); + fullBlocksPerGrid2 = dim3((threads + blockSize - 1) / blockSize); + kernUpSweep << > > (threads, 1 << d, dev_indices); + } + + cudaMemset(dev_indices + tempSize - 1, 0, sizeof(int)); + + for (int d = level - 1; d >= 0; d--) { + threads = 1 << (level - 1 - d); + fullBlocksPerGrid2 = dim3((threads + blockSize - 1) / blockSize); + kernDownSweep << > > (threads, 1 << d, dev_indices); + } + Common::kernScatter << > > (n, dev_odata, dev_idata, dev_bools, dev_indices); + timer().endGpuTimer(); - return -1; + int *bools = (int*)malloc(n * sizeof(int)); + int *indices = (int*)malloc(n * sizeof(int)); + cudaMemcpy(odata, dev_odata, n * sizeof(int), cudaMemcpyDeviceToHost); + cudaMemcpy(bools, dev_bools, n * sizeof(int), cudaMemcpyDeviceToHost); + cudaMemcpy(indices, dev_indices, n * sizeof(int), cudaMemcpyDeviceToHost); + + int remain = bools[n - 1] ? indices[n - 1] + 1 : indices[n - 1]; + + cudaFree(dev_bools); + cudaFree(dev_indices); + cudaFree(dev_odata); + cudaFree(dev_idata); + free(bools); + free(indices); + + return remain; } } } diff --git a/Project2-Stream-Compaction/stream_compaction/naive.cu b/Project2-Stream-Compaction/stream_compaction/naive.cu index 4308876..742ca0c 100644 --- a/Project2-Stream-Compaction/stream_compaction/naive.cu +++ b/Project2-Stream-Compaction/stream_compaction/naive.cu @@ -3,6 +3,8 @@ #include "common.h" #include "naive.h" + + namespace StreamCompaction { namespace Naive { using StreamCompaction::Common::PerformanceTimer; @@ -12,14 +14,63 @@ namespace StreamCompaction { return timer; } // TODO: __global__ + __global__ void kernNaiveScan(int n, int offset, int *odata, const int *idata) { + int index = threadIdx.x + (blockIdx.x * blockDim.x); + + if (index >= n) { + return; + } + + if (index >= offset) { + odata[index] = idata[index] + idata[index-offset]; + } + else { + odata[index] = idata[index]; + } + } /** * Performs prefix-sum (aka scan) on idata, storing the result into odata. */ void scan(int n, int *odata, const int *idata) { + + int* dev_data1; + int* dev_data2; + cudaMalloc((void**)&dev_data1, n * sizeof(int)); + checkCUDAErrorFn("cudaMalloc dev_data1 failed!"); + + cudaMalloc((void**)&dev_data2, n * sizeof(int)); + checkCUDAErrorFn("cudaMalloc dev_data2 failed!"); + + cudaMemcpy(dev_data1, idata, n * sizeof(int), cudaMemcpyHostToDevice); + checkCUDAErrorFn("cudaMemcpyHostToDevice failed!"); + timer().startGpuTimer(); // TODO + dim3 fullBlocksPerGrid((n + blockSize - 1) / blockSize); + for (int d = 0; d < ilog2ceil(n); d++) { + if (d % 2 == 0) { + kernNaiveScan << > > (n, 1 << d, dev_data2, dev_data1); + } + else { + kernNaiveScan << > > (n, 1 << d, dev_data1, dev_data2); + } + } + timer().endGpuTimer(); + + if ((ilog2ceil(n) % 2) == 1) { + cudaMemcpy(odata + 1, dev_data2, (n - 1) * sizeof(int), cudaMemcpyDeviceToHost); + checkCUDAErrorFn("cudaMemcpyDeviceToHost) failed!"); + } + else { + cudaMemcpy(odata + 1, dev_data1, (n - 1) * sizeof(int), cudaMemcpyDeviceToHost); + checkCUDAErrorFn("cudaMemcpyDeviceToHost) failed!"); + } + + odata[0] = 0; + cudaFree(dev_data1); + cudaFree(dev_data2); } } } diff --git a/Project2-Stream-Compaction/stream_compaction/thrust.cu b/Project2-Stream-Compaction/stream_compaction/thrust.cu index 1def45e..02a4922 100644 --- a/Project2-Stream-Compaction/stream_compaction/thrust.cu +++ b/Project2-Stream-Compaction/stream_compaction/thrust.cu @@ -18,11 +18,19 @@ namespace StreamCompaction { * Performs prefix-sum (aka scan) on idata, storing the result into odata. */ void scan(int n, int *odata, const int *idata) { - timer().startGpuTimer(); // TODO use `thrust::exclusive_scan` // example: for device_vectors dv_in and dv_out: // thrust::exclusive_scan(dv_in.begin(), dv_in.end(), dv_out.begin()); - timer().endGpuTimer(); + + thrust::host_vector host_in(idata, idata + n); + thrust::device_vector dv_in = host_in; + thrust::device_vector dv_out(n); + + timer().startGpuTimer(); + thrust::exclusive_scan(dv_in.begin(), dv_in.end(), dv_out.begin()); + timer().endGpuTimer(); + + thrust::copy(dv_out.begin(), dv_out.end(), odata); } } } From 488e2bc1bd863c1f8437b307b2d95c2e4a8c1809 Mon Sep 17 00:00:00 2001 From: WaikeiChan Date: Wed, 25 Sep 2019 21:14:28 -0400 Subject: [PATCH 2/4] Img for README --- Project2-Stream-Compaction/img/1.png | Bin 0 -> 76229 bytes Project2-Stream-Compaction/img/bar.png | Bin 0 -> 18280 bytes Project2-Stream-Compaction/img/plot.png | Bin 0 -> 37692 bytes 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 Project2-Stream-Compaction/img/1.png create mode 100644 Project2-Stream-Compaction/img/bar.png create mode 100644 Project2-Stream-Compaction/img/plot.png diff --git a/Project2-Stream-Compaction/img/1.png b/Project2-Stream-Compaction/img/1.png new file mode 100644 index 0000000000000000000000000000000000000000..92ee62b60b2afa66704d5701c41f32bb57b88c96 GIT binary patch literal 76229 zcmb@u2Ut_hxBrX1Qw3By3aAJX8=Z)Nh%^NiBtWDIh=BB-_zEgLA{vwyrHH)r7J4E| zkuJRxAhZAhLJFkcMBj6N=bZn!_c_1&TpoCm?7cIy_S!RRX1KcM5l%%sJR|%1__(jneE2yw za(+Y){PzQ{vb2p}D4LzQ-KTP-f9y?9YZ@>2O5}k)bB*N2{#~5+-zbc2KPZbu-=;w9p8pZ0RDeC~-$*=9_7p|=hBAD4W)yjhc$75}>=ZaF*RmVJQlU8m=68P**e z_-(+_qYyq^psDLVIqn5dJLe7T$6O5bQyFwhFbj1a@c3<_KPV>|&AoW0A|AQMpw=>V z>^nh!dy0H@4#Xz~2X2bpQPW zV|FCWdM{=K&GDs%J?EC0KI}#|!(>2btFq(`g-So_-s$fLe%=VIUj@T3pa-qyrKiX4 zWTs^U3aSe}b$Yx*HxYG|z1soPzKzu1Hy!XX8Y0~C%37K5B~34CQ*l12Isf1oohYo2 zTix~%i@U3|L1r`twK>_SUlU&Dx_(J<^7y@GI$p-bsVlnX^Aon zkv1yOlS|9rlwu{01d)G+;|Rtcwf4Yji*frO|2%b9RgUY40#UVc8U}9`+p=#-#kt5V zI*9YhZik58eYyk<(|S>ZSggHG!bqZf*HUf6k8G{#0|t-vm9$la1~ccBs#|(Jb_#;I zckrCd5Pi8^Ao@nOG&wllQS-2#w+3}WFWkZteEJ2YPx~b-t4jF zEq9c37Q1)>_HyfdpOlxfuK+mKJ7i^=t#Ma?sWN4XXs&0@T^LD2q%_WP`x4JE5pj4b zCA#$NDHnY8!G*J3-^*O9<)=ROoX>fs!|aBySw~-dU$qPmuKtx4wZ32XWu8w3zX7y7 zf`8USA8K?C<#(aa8&i3Kp6gsZd6haedfA>^>>~;0mSjkOICQUrNb_t(nC`Hk%e22_ z*7XhjPqF>^Zl>n(jpi?jE&#$ShYRH|&(I7$ESl4|`I&Q_O%2)O&`%Ozsvw$p6N5Tz;w?6bMHac`_kzsMk z$}3BbQ$YOh0^FQN7PRHcd9}Ut)DO-+=qoXPs6Y7louis4lh7*tg}SQ1v_LMo*mMHq zB>NDX^H$hfgx%blb>snCi*qXLaZ)cot7b6px_dV~Z+`nywWH)gGjP+1yUI9!Nuh0j zAK<8}2vm`VEhD5tO2CDF4{AM#1!YzZ+%mp}-UJ1H$(uI5@hi=X*Z9-+lK#anFdL(~ zb@#H2K>luOC~KB+&&^yP3Pvm;;#e%(n%SDyVqzuW4!?jtv@(zndJ@1bs5Dc;06p&j z#490sR)yS&r)_0mPe0y5WkPQWd7s(>AHLmJg1h%-WM6$sRTda|a!6tR7^FQvjuk)+ z*=+qwRf1bc_^bA|T9%+NvAheb6FoG+B+$?6KM`D)J(c_ow%QMF{7@1zaYk(+t`hg* z9L=&0D8jT@w`&dxw8WB)du(exwzysW`D$sw@`wU)TY9=4f9CxN$-VJYR>NE6LzG~z z3x8+N;DdF_{Rg)9>c1-yX5ywIQHAYqv$_J~`b>=?!6F^PHvg1TR}hUEzeB&yKkbzhvAur$iJa=z(|UDw z0}pk%qZ`k}rH~}6z=r}!@@$lLCc2~}?qkmBDG}VfH}~w$g={5FD8vg58`&C;&8d*d zNciX3?biq5WwDniI}uF!wj$Uc?;v)ITY~j< zo#Pt)Z`hgWZNvuk&N5XWC@aN1F)adhphLm6_?GB zKjdKc99pLnhbCNxumjD!6k5b&A{LF9(5~E=Nr5`>oW;lCT79H(>o@C)9(rKFRVCGv zjdQ)87&CmDC0;62t3nAI!Y)i`g8>l{hfJlOR`lRo&Mm?+Xl>&xx)mWv1U|=FX3+;3 z0&NfU*$zqH-nAloB6ceQ#3twV3cV;UouwRXIp9||lR1UTxboCjZ z0sF`U==`r^ozSv~NbPM91GHb{N2}U7K3o(?gVGe!>xszeT#MT?zcev20gTd~>-E6c z<3SdyQb3^3cS&+WqSn-K`e~Lp#i(Il)8<>GXy2woz0H^hgIK7so;azP>5rQK5TWOSZH0Dzqjj!y~R+I5NAo~l*Y-v@zD>*n+ z=ZnXl76A2;1u=PeH92d@0W&$nu;R213hZ<AI-MoK{-afD^g)?V6!6j`WPyc^%=RB z-9CVUbk0307+ORu{v;?2hJSDq28KP$q3VrRK<7VjDxcfHMP>8&We!)Msh;-zP>!oZo#eAh*Mf{d1nW2c1$C@gr>kdXH0$QqcD4C+{y!^ z^O*gpKW&v$KVk-l4y!83gGMuZe<{4hJ9>mWkT>Y<0$4!aFjPos&Xq6m8uScBoIM;5 z2y4OIB{Vm>rZYTrw4vfv=m7?Nln*gD!70; z&-y`RutDMX#dXgpY3Sf61+TZ!5#>GyX7x~!e*E?gNGaV>V!>&QUKZ_y&9LV6=vslbs_XK(>f}QHzmbb{K&u&tG zu`K!|8Gl#fwppmG+gJg4=hsw&PTB3qXD|EB!>Hb77xmNDbZ1NUMp^xu?>YuY$Ztq- zJSXl%r?_K=Sq{|bow&-;Z7Utn4|^;|-0%eZ_7kFaPbL;4@NnRPBoLZv-YXT&iX@I? zff15XTOFVN4tP}~-^0#XFDcb9Trq*FpKblCW*wo;P;jxKJLGwivP>zTK7Ggk$O>pj zor2C9d$UIsIlUJ@g;K9#eWskc28Xcr8YTii525tpSir4^N5UwuVXEp7NJ*1_~vr#9jLz_NQnlPM1&!|V_b~Eu7R-p(8((v|{cwO5(l_n~b~Pqpm!29|l3>3Bt0dmz z?y8g{B6`9|`@H$1>X~K2h$Ch>b&v%eEw*R*GCUkgSbdXF)mZc(uknkZReyxzx%EcK zbh3H3lu8M9kO;U=0`MQG=6@tn^06_dvuWv8bE5bGgf$G;8-kFH{n+$6$=#4{%+6If z>6Es=BW61=#Z%}tk>-qx3`CAvAw4~xvG-21%B&b6c={@(n?QoaM0}RSh(n7g`L{mg zh|z<+xe;v$sKpFg-KmdV_Ku;8WKGiC1~UQ;D2Db@4qA^?Mk9P85L3b^o*0 z`S$YPS_OSe{CTaC${I1GNpn}iwg>cq-^`jf%#KQ7jikgwAA?a(b%9rWOJRR=&VEzj zl)V-O$@lpI>%^JY)&CM|4J=7leu+hHW13tLG)r$E=1O}C-XIOzJy4+;5b4Rjk?|@t z#|2OZkwKgMig_lcQ=nb=8o=B>Jn|5dgbWTCX+h$)Y|dpat$bc0*1apd;75B%NK{7O zXMw(QXMgE&#xW4PfeTsqkc}40<7!SS*^U>ZPY6UbmL6{!iTR`htVQxW-o0KV#Oy;o z^Mv?)rX&!FgL*JrLc4W5uB>Yj0pdr8UKrjMU=3q+-z}}SSAS{m%{UvO?HF;tG_Ni< z^f;s!@wNb6UbWT^JqI)e#zfv})gIls)uzYtB?@oB%wwF!;R>ypq4QnZI5071Ja&X- zo6H_x;ZFA2mMpT+#~W@?%X1_Z_darz{cud+er%oy$wu$p)Qin7B5_!+zp-2_Qf8{g z>p?{JMSCkgfIVnx|P2R&Q>3Fy!X7!NIFZcYr6_ zMl1?~zOSN(L%ENdP&=3k5s=IMTJdvV?{curha&%tXozkmq|@S1$T(1;M~i%GIeD}) z{bowui7coEZ0AbDP@7UPBR%sxD6sj&$(6Tp&cdJUG=G{}LL$1M@SkQ`?5Q*aJoF69 zh7`uA{vzqu?D0y+Q^p1VzNh>oXT2Y5yJ!RzEHe~kz9?}xhedDH#+CAX><707TGy*_h3g2RKG$18gw%7ASIG1w@}cZ zN4|famQ7tSn7pADhP^)efJ9$O+VSh#*uOKy{g&Znn!^F1MFAO~R3Gv}i#X=` zalB3g%`Moky_+Y1J+wJi&+OPf-Ok*3cL`d1KPr&={qNXp=?_HzMP-ebrNa%*rl`ZY z&pc(MQ=+pj9PGM#(h*}F9=76;n^dHNy%s0y_yesuyC}?jYgT>cY836%BxHT%()gwO z1EwuChkMt98@$p}-mF|BAlB{gDj}h}OTK5BnPFDl@ z4ZNz?@`U{E2IpO=9Th89e98Wjg~7Szd$X7?e8Ef^JAP!wod-UEiN8)ETm1sq3Cv56 zv}e7VEMZz-_J5fRJNBdc&=a2p5~AX_GsJDpNMWNEqxQ!H5~!x%G-q5n#yxj>zO32< zRowb~e$}Jaqp6p3jHhj8Ri7Q~-g3?O{G-DV?n+9H7fj9hy?~fW<3z4+%FUuN4_W(4 z_eSjFLGo~d7c?>Y13gxvlm{g|Rpj|Y39@U3uJ&?S^si_2ov&X>)*ZvvPn?(BC#>_? z-XgE0sJIcW<&8 z8Y->2N0qv@@j+{Gw<9Lq)z{nS`&Nkh=B6=(yPN2gWqfTGvoHRezI zFvz(yWThztuqs9uc!73SHVbgQ(t47|dRG?I70EAi{u=sGzlr&TVb*6NCiTPS;*zNX zezWGzQ^<;NHH2*ogLnc;qp8wQbtsDfP9A#aG%LhL6pBX;W?5b;-0l$Xb(f<;)WW5>xn zP;Vcw6pRL4I(R~kB6<5C$RepcFjD8tI zl9Mg!+`z1=cbKPC|E%9te&M?OhE7p~wOY58Lh#3T<&61-`mJ+u)soauQzfDR%U=C? z!Lm`{!f_$D)HD4dolupMk&V+uSBG;IA7;dBHR6#8%dik@@|xKyu^Gz?!QoBV!+VtgC;oc|@ZRVv9&o^-d4%f6vU0-(xxu$NB{{yvAGhMMZAo z@;*ck_*NFo0yPkPa_cQbU6O49(O`AI)67Bi_QoaZ!d}yK$hm6D`_Q*c-jUBTti-_Z zR=PfE><##&RT-d@(3H4S@GeIRPPkhAx^;e^#P_#5$~kKx9$UDZis`GpBvmT7Y`l9!BHs3cd-CI@nBOc{>R93RAy8oer*@>TzRKt|h++M21h(s2uY#v^S`W#v2 zfY55UOT7?PE=fLwJDUalFgZBvW%1D@TyY$4_bSFG6+Ql>a!GueVbd|xt|26XvrgZ^ z66ArMm_*L%k(h-pLK*v%pp<$z?HhivQ>nQ@@^b5EH;h__feA#oNr5etE0T$Lt zUR=^8@?~8EfLKapcW4E}#V%_<1BwaLC#@dTx**nIn&a8Ik^{a=*n1`JPxtUVw=;mM z@5n9gzap`$m?a~#=keqoO(qFsvip70XzImzt6fwhP^RF}{vdDdLVx4P`qwrQ7oM;b z6{;sGTa&4QVJU7uOll44m1euW<9u7dSHV40b^Cg8sH^PuO9SJGlsT3q(=*0~eYVWt zizgyr;GzbmCI3D^Ng>YCyjF=C@{3_Wa#d0GRAP_lycrwNK;4@5!#2*uC{6$dbn@Fo z$MrUcolMh1osRNIy9V`1ja)o+Pu}n3MUTh~-d`Ha=sEM^ZF))JtSW*eMg?Voqr;xW zeLJ$p^Ml$JB6**=cE9wrMork)p|-3=w6AZc!k0f*&ntNJTZNtC_-n+b*yTq$V5vtA zKDS}wR(J~4MHmiJUI&h07QeptaELRRK#h+MB1)PQGZl-;?%;cTJQOnSyr;q7^UEVH^dYdzte~H zj%G!@b8o?XbQ6d-CTGOaZESO}h~p;x)0x4Q9M59jVjS1*>1Vx5wp%?{EeGUFh4Rz3 zHbxQO)dpJ{sPG=h{}i>Hv^o?vb2 z!#KfM9WIZ{rFar5R9QW*qGc?*t_%mATQ5>mn!pOV)wb@)x+u&RK+|LgM8Z_2hhw_> z`M5ZO(*Wx0Jg5)F-m(5(K)?VG5aNlV*v8AnPtoyoXXs>~WM=5W2X(b-MGHrGN}ExD ztw14D)+PASUwl*dze}2Q{-u$$zg-J3_V%(@qTD4bXDc(e1?RtT{Z9h;wpK0KIYy*JK%QKQUg2Pv9fGxK7DXP@J3NIe^Pi(aeJcg z?t2q*BJrW{;4R{pJ9<3?4XL$Lnm?9K=E1MP=* zEMmJ(fLtQ9Wh)9x_}i)o0sq`#^72UC@d)V(g|SPjC~KWei4ARRu!Gfw%ke1|W~JJq zD=3O}v7w17rNZ7SX5hn;S|Sfm!`gY;OSNwXNg^W}W-pyi9j9N>ZgCdbKLoBfv0r4093Z5a>>ZmQk8Sw+paNj3)94xV zG%I259)FtijW}rBGsz6&VuU+_tqOu$1K+Gj1Zzy-2|AK44eLzfFCNRCaRNr z4=O>tV$c;bp3a9RhG{)5jlcRa4L&QJX~rV$b)qiL_Q{50x)3{l;Mky}=CEqqz$5If zD;nH5rtrPJRr`%3?=#bQiLvYr(NIfQ#%y?P)SU4zCOCp-2|XRDQy+to;2$z{cI@f zRr4s;^Ztm{$&YTc)7w?59f`qEG#nulO`Fc!ros)umraq;#;I|e#Cw!Mq zPW|00Fkp=9C=&Jn?Lp2}nQ!joa{8MewJ4^bXpM+`9W=Q~$`;Y0v{1x5y3SRDy2rAh zHO!?o^aQ;(1yLR0ha`YOoUs{g#~vL<6-{jatR!_RVZBQT{w1`PTG`?!SPo8r6g4;S zGZ$+c`w-4IW{j_sbZHKtA*qM_tuekf#i)itWP6JArcDfy}H-gvkv!9uc&J~OU zwsU4xv#Qnb#D{sTrpB9lbIloMOszq^;(D}0cJ<`jRPgYk)sHlUYVoz|lF!;&*jI}R zBa77b07X1$JdeKp`qE9*>Mi#R)9X_9^mL}`Vzm};h*Q`))Suq+yXV{Y>&4zytmlgHRoM-eMc=BMK zsd6lJFloyP*h>uG1t2; z?9qOdISH1H#ixMUF!orS7x@@6tTiRQmNCqa72`f_p<^$8>%jNK;*t9MZ&RPlf3-dR zGnbeP-EO;aU|ROBQ|h~@-~_FqH-}u(%Z*$}`l?UW%ZO>pX1v%{!rT6$vLO$|JEq$SG;&2sl5WA&W{zm`h7cB)+%f4zoW&+; zx(1U4ed>-;ptbc8D4j*Wn*faVWtB2~K*d}i9pVMBcxJ8pXy0sJ(yjoUr?#cqRkK6UEY+A}PvaDi?Hp5p%X#&yf6rL7D2=fjmRQSEPmRdO zZ>9M8KUdj*DWTDeXSCeXBVNsMJWaXmeS+}us^7lpwZ( zi8Zf2e)YkGJNO`_eV}0{Ibcl@u7p^TIy8Xld7a5h!%Dnvu%?Dgs7lat*ji+AE0g0m zO$zfqTTL(%LKP(_P#G=3byg9UnPHsSKU$5lM`%m4a{q+F9kiS48#A@4(@R3SmCZ@` zRRsSnu~+PoIpe^+w=#k|&F~V(K?lssMq=9^z&kw2#va;m&VZIsP=q&rho6;DeS)Lu zR3&{an=|ML-jB%DQPhbC44N@_@>xk=TPmvAhn28zUe_`j@M(z=-=Rue+u%&6BXri^ zQ1L_g6BcNOKZCgtT<03mi0#a41(qN{*GXt2kJ1Riv3-5n(bQ~;3dbK zA00&g@~QGm5xP}+4v2K&K3}ECywQ4+-`A8{-;o{8B3-h98iM7xZ*PINO>4qV(56Q! z$-g?;FnYvO-&D!o-&d*GI(4rh9wp0b^P!@50BWp-y>sLNL=1LforwYL!u9{Ly; zH|bPWN7pK8Rt4Q5eM#Qsrq~1+?66xE_110(CK6kRhABhir^$OZYVNWsl_nPR?}QEv zUnOL9%Gdbs#{49?7UK0+4+kzl7QMghPR(6IPCs2zA?XA8#?TYb5#+KV@myoa+s z{N0>agXVvFCwq;*s>zaBO%TdaPkj2@qVXhGeJgQ(WZ8h`S>@bh+B*A~yRy zVPHD8f+Mph*oVFB1Z&O&CsDp}s zghQzLJM>QOP}W0zly7Ft@{k#p;>OyvD?cm4Sya0#J7=WpX5RW{O9Z}g3w3p!dXYUL zdZ6T&dPPcUjkOW!f!A7SU2Sd&BJ>gaamS?~qS5yd=o98I8&_5(z_+LIX!SDQK(zId zEa+)R>DHc45?Z5FQS+0I{H>RqYRP$G3o|>S;uxJV-U}7pkDte8gxnHy-+04(RQV=F z!7g-8#Z>6w<;`IH>HuIT_bOU06%UFoP{Mn7@|_EFpFBIza5)A!u8NcT%!ZUh8$7`+ zs+>5&net~+@B>~~PzNRH4cu|;)>BW+1E!u@-Lhx{b4!S@oq~0DETOG`=JU-0U^=ts z!?V!-Pu%V)D*c}PJd8#=&WD%%vwa}&e^0=ATcM(T-GF(7@$}p7GMvYUsE+@=(JrIb)@uQ_&*xGYS^ac}1%d zt_V5V&o~l5d#c^w^X5YZKq;)xPZ03&lhEw7@CRYmd|>2;qOI$YmE*#Yov2e@r$=tE zJ;~2LfyY->VFd0`c8zH}t%;laXY{flC< zxyKchmaASZ*Y0yjSz0Q3ofGDwx?iu(XR45PbGEiv(!OC~CD~Tb7T#7}{92W_fzpm? z{MO@Wh!}T8-<)6SSJ5qo3Zrdu0%7Q9l_M%`AXpTwNeuMI<;ly??Zv`>Dd%nCgj9#FvNz?F z+pc3rIs1KHb!y?v=QftJz`w}zCDPBnH|yA0PTk=vlgk+jSS}}FAtMdl3QVzB7eJ=( z5(DP}L-RAu==0v)=HmwNV=aN3&D3=ZEQGdx<}sz;U6`<1->1Ocw^O) zDc)<4e(ut0R<^J}VL7}${OxMKp>UBA+@EFr zy*_*maaeOTt9@-@VHpY3!EQOU>zHNgR{jMf1hDADl@sDVql@|;9Z=!t?N3{P1 zkIqs!So2%7uMGVy+ACnMy^y71%$pNK}Y8?<733z6vANteb^-H`thW@cjRYJ zz4W}D9G5>^XR+fgLrd#CM(##~FOF5CRDgU+KBdl>H_8Vm%+40nq~Na~1GoB-DH0<= z-$K7ny~vXc>EbhK**^8kTWD}@8V7U@ z4aUd+8hemXXNn8Ogb+cN#kQ7^)3QqM5Exx!H0=l2jI$k%S zglqf8Z}?Y}V4RtauOiCbV{CrA92Eh*u?hPSXBn})*}6x7r$&+^&yU@({Tj`9(SA|e zQ!3`K9;k=o_cX9aEg}7a@yFOOT?MD+&I@N zN=i9>+sck-R8pVa)1at4A8Pz=_zkIgWdQeVeUDHS<0wbx|GwVxt*bu`-q1)bI%nl{ zB}Wyp+&gczl}}OI13F|!*w!RC#GZ52@)p?sJ`w|=-g>kNS`TyoVO5jF5&;H(Oc?m+ z$FrHiQ75oD;v;g0%U`J$`5~4bz8U?j?}NwwX^kjCv4$cp`-lRdrOme_f7L9C3Z{0i|cr>vT#}IQ2Wn; z39pH0)`!@$I+$L($ao*lD5VW!W;6kYexLk9bo)ORUFdU^7%8dzVmUMcJ2iGW2G@Gk1vNWA%R zJ(VxBPe;IBFQgA;@sqluauD^w>;TP6Fl5Qyq%-;3Z=wI!TdvU0bFO8Tt1a7JNLiu< zdY_%(HUvRXB%&1}mKcN3RO!pGyepWPr*@)0Wa2cVkw4GX(X6m?I4B=_)U&}8Z7WMY zU0eHc)v%A{+aUP)W6SeN{tjMOn194qOHpuW1l+X|_3%`CNu2sQD=)QdB`jBnyoWAujW?_1(-i_a*=__EzUPU zeO?=vOo9g(Ll3gGmo^tiEQ)vJ%&lmiYS$wA6}qV5NbPy=%V?kU%$Sfq%mYj=>+^5z zACU4#`xl~js$4iUn1#a8cA}<{cHtg}nzm}HZM`9qSJ=`|h~<{(^UV7mBbNf_HAWg{ z;uQ-f%grfm68Js~n0qbJ=kJj#$Xz_PDO~OUD@Xf3FY!&$QCen?!{mepGY52Z{k`sR z>cRQ;qV>OhOG-*8!#{3UUvc{n5xu{|6VO}aUL6#3t?M1Aazb#Lk=idD0AOAduOJQt zioaj=;A;}fbG_mCR2gowQa=dP83LqyC1(qEvQi_4O@Azhi$WhXZtbkH?a%&}s?pJ` z3#|hsuHy$Th1s;pw1;`w^K1FI&|StA$U8T}4o-7@?j67DTTp5JGR#Bh*!kqjqfu45 zCI{>#y1<0IK|0fFcr(qMmcUTz12i|58_c}ib;aZ$wYQlQ{@tH>NmObNt~lK#g4Nv@ zgv>&`OgRW?EBWfj0_}u_P@-R+q~N zb5N)HlLZ@V%E($lf&-I!du_RP&gLI}ai65X{+UYt@S5^hm*j?8&b3z!@Wq$S7Pe!M zGUg27uRO`B;QW@ResxY?;icw46YJa(_M{(t+4tz_(YmVwpW0mayPeY;wt<^_X_2ij zyM^TswK*#GVaB~cpOUf8yRt6UKB4k9d$AS~OEkkG zi2;K7VR>(0`C7?X^?daSP2r@o3(g~<9iHvIk&9AMD267b{-S+=k9Q19jx86aO}r6f z>%oN;_2!`l=xRwNpHrSsh(I3OG)|jPcJ}ozEsB2sx7$$Dkm|BcB=XL9Hh_65@ZGiG zRfpWPv@4D8$VploW1Vj5_u0b954=_j(FOHz zM3pYC#D+yxySJJLM>KHSL(BSVCS`L_k3%C`+?BvQJNA@_r0TTmTPcOkGZD*P0u@0+|!_$4jE}!&wkxdwBX+JZcoQF?bSZHn1woQ{t)`~Og1;HGiudlsXtt039 z7G0eUURHpw(`rT4mY7S&KPKSimvW}z-`ove`usFpNnJauaIMPDvFWR8i~<_&uWt0r zB>xtB6 zxSlhdEIhZPis}Ist8y8QAk&V0lKfX!rgP_{nlm*x(0((1`=wo3*Tv%7>P-~euk>-J zT1l0u(cVxyIWwnBtlDm#(fgz$J~OehO2rQ8huf}g6{@FH}H-4ATRCGVFp^L7>+f)A133cCAacj3tH|k102`N{8=$=85 zq-dIRR_s4u;O&2af!&UOz<@pnJpBd(?&Dq1JqCrRSe*)ZIK?eyfP)6yf1?31-{)L# zD0VE_tiOwVTB4x8c5u2S_$=#Wp4eCNU)Gq6Qf<;>BQiNlM^xOD0b7!kg}x-P z=bK9OjW-H#9(&TF+~lbB63# zlJI`c3Y0U`Gflru>a=NTKk~NF?swi$^5v(4Nzr2GtldYR>GZ*Va_583j|i!jUniw4 zQEr}UtIx&4n>`m_)!!(X9H;nnyav1Jq(%6MHBh&ZlXq`c&-gWyEb4qao5$hMqF}s` z7R0^1_lGUSWA2F}y@4wuYB9g=gGH2SzrN(x;d##wxh&(Zz(f%U?ITaR^{7k3krS09Yys?4_+_*~+{N0R!j8>WB_ z6m`0Hmv@NxR{vW}YKVgvTWKPX65J~4ssTuwP@uZ_d?IY!WUFcXHs23smDXcOA5wK) z^_O&%xB=EBO)PC^N%@!GL?(JB?6(@5jW^n0eb{fha*JA4q+SAJO4>BqE-j`gpI z-blQ;s$2Jax#0eXmEP?lERXyW)%EH%DbV~y8-C39Ua`RZCATjeF7QHn{Quwra`6Ag1@h#V-~RuG z1$sGLgN-b;iU7VZe)(Z(FlFQUGBo-4y$2UTx;yU9*Q+#a6M5fhMtobi#nD|2$9} z0R_KAWbkP-RoggJrEH6c^yVZGutT`gHi!BItA@;O5< zET4lzBO{)83;2NopClw5Qd4vop>O5dxjq~H;hIT?0Y1(zb$icm#wO%4<9 z_Oz|mJJePEcQhar=~Ex$rDRwNfV%{J34f8KYy2Ax1i4=_4(^X|d|vdvewf<}e5koH z#mGwUV(n=ORf~*5qneQW53QE_&|>bm?n?o<}>8h}=+MT3xaNm-Hgnq~t)O zDWh2&t-A$M>%%BIS;7ILDZrAAR^08hhUQQiTDM=A%>>bMr@b#?4^ zM27u5gEVi)I98c6xDZ{!MkeYR z2NOXPs12I8=^tjdlM@lc(czQs0@Y~?!-SEy2-k2zxfKV9nk~tUd&B&GlYy(>!b5)< zHEA95J*1}jbHEPwz&vqL4HZF7ti96obS%I6!_%w7hk>g;WyEe)|D~}|M!!Y~VD>kx zDD9n)oc1}rs4BTrbf_n;4TWNhprSpsHjK^1yJjm&>~BuL@@W06&Y>Gf?{-ZV2*er9 z&=Wu%2h1=N%ca~!*xoeoQ&|4SRZQ#XSOrRs6LR@iVcd{wddk^Ghs{vd;JrAJd!{^0)t4}5G$2F%-3Rc}RU6U^9dRU9w| zYWpn5v6wSL)MJf3B8H0nb%>xC)hR*HM70Z>e~#R#8pScQzn>fNav5_fU^cnjl|%74 zZXIq~7v;KD|7i1QZB^s}P4?V5z4UpH-wSh#`6d|6lAzWaGyx_q6-}Xk7yalEM}29A0XSrUTalkMEoeW7DsX-f z`}@$B|J1Z|<+UiYnvUJ3hO zSY5RxM=FJ1MO%a#dg0(ENWLFC5HP0VTI2pEZJ)p_Y;7Frue*F;7osBu_d+S#H@o{> z#`M{*-T#;-6*gxZ!j|l33QbASu)~^HZLSZrz}3>P?7taN~<$G)A7f7~KDUPUo{Ma55?fUF82C z?%-esLVI}i1N-4A%m&Tud4QAjGJW?{XoLV|_*A&Lh5*qg0j2A@UAp(+A7^qB?nMmiJ05k6 zaOj?2O7wPb{woNttd%-bn=9D^f_#{Esvq@UUuis?Euy1-_!S; z|8ekaABUWY>Q+}rOn3Wv{7T!8f^oj~>=0{!4@{=dOlWNY340#4)~1{1RK!p330Voj zitT##h?8d`xUucJ{Q7_pGv110+-gl%GQ_Tv!D;LM>Mt%B-;yGSe(d!1au9^R_dp!E z3oKlKHN=OvIzF-n7QHZnB>>Ngv19RQftxc@IVAcOn zN&~cIT!5&)kz$qWTh-IvdZ)N7+<_;B$K`^CRfO~T?InFHAPO%w4#1*hU97dL%5dLecV{hpf z%UOF-nNU+xQc%{jGg=Gn-bpC=toe2~r499aCMT(!M3f7wAh^fWSI++sAQOkJ7Y@5H zNk$bikWTDY5TLXId2XUOcj_$|3y|5Me*Yg(7jntMgXTBeCv|ym2xL7Ip71ky^L-Zh zY^UKZ*;!T$NOXIh2}Ad|LRf1(qkaF{1jxzjtMPh}@TV!$ zHcdd11C7$lpxoS^7|BtCDkHS!!M$quB59reKpzE#p zy#|Fb{K$Q=a<;w}(^qAZpSE`(zUn`_EXbX!~CHKkW5suM6ky zq6qm|>!=*3NNHh}%WK5UX4~U|wa-l)0lBLm1pDPJ?0gfiWsTzC; zX@Yp58D}k)I>|e^ExoCEIT#C)v3+fZFxx1CxFI@-dj07;QmCWM^QlbTpqCT+=!L1X z%Cq@~$ERJ!ED4RTW+(Pm)%enS$GH7s^Q1C4M=G(c-}KHA(DZfA5e}q^hU}d9CmrQa zCSKv5KEAw14N)#>xr*FNFuVU#xST1728dUf9Niy%h-YU%C-!Y#jjpLLnUobRPFS}` z&cdsCcnq<}v%vBz6LvaBNxwXWFjM;pXTS0sBEQwpzBWF)xT4<&_hf#Zh%MgEPyiY^ zc}<-<8zg_eT3ZR7eaBeU3I>X%%XmhtnwZyO5*x(IhrBGFnJu>3#lQ->06aW$c>>IG z_V(pR5d>o4eAp8ECI89hg2oiu$zOnPfng2X;4C{VRGaE&Q*buCp2ILx3BO zYF-d66AH3dKVI8 z?)~+ZR@MgA=VVHkw|v9=%_4~9wwE{`Gc>hrSzHr*&JXKF5@qh^DQ?HXw{7u8CaLc* z0?gFce%k*Rd+#09BylxEHgC?+e*sffpdI5wt zq)Wr+nfqRlRqGj^D&P-mFQ9!t!5J(!H=vf_?`b&>D}p}PZwif^hwU*75u%-hi0*ex zH*#iDAoTo7XyD!Yjn$P4R|crY zcv7k{j8E6EtLe$z>RZ6aN(3rHY%cbF(>YL7gA;FHXkEmmWrSIpM>xf1mj%}2_Hwsm zPsGt+rZ2$v-)#ri?BgTmnK!-fsdt1nJFAbbr#OA*;`kyEm#>mqq|b->IG3cl;t;w| z1PU{vrM2_OWA2;Wmhs8`TFXpo#~%!dpe^Xu@B*;sgE%nW;iX`Zs(h`jk=JL(L`P#s z*2+PoW{`>p&$~T}o9+*|c}2t_+R87e6*)v@8z?7_<#=^9<>rjfZn?FP z4ddyTanf|+v-qFE`<~|d6)y8hCaK;H&Kt!6vm0mK11dCx+4lT`b&Gv04@|CU(W|Y~ z?ZvQiEUPs1`q53_HfF&;KzB9O={77a_DQWSc1H={2AZ4+09a3sv3S8|>KqE;y!0wh zkvDSm$#`hF-B*lx24a>SbS@>v`5i-`uG~4rJw-lhTms~o6wrpL2HG(B4kEsDxjGsa z27@Hb7?Wbq3_Y1C&|U_q(M4&HIMW)ZE{)ZvEys}_1*_D#I^8N8E9;s`;`<|Aeq%$j zdOr7@mtVr8Cfzw7#-~3#uR?$nX62gmI0}&%TpHj>O-SfVb?C#EZ$A%vH@vtUGKV2> z*^4ejjusZ%b!#cUaL?CTnn(M|xA{iTp(4DdoAI4Dwr1`>a<{o4G2EB>q9OEPSnqZC zr1wQX+3e`0xRwbc=n3FQ_ESO&pF8WKWoU6LRThItbnQx1>1@BQt@&Ka@XA&@JvOUd zoo`7Sbt{sa7}TzBzrtJJ-c*-9F=-iJm9v{yaNnn=FA5bBfZ)@5Wqzly^_2>6>nS&op}Y0>%j5Gsc^3B2<~{hjT0)cLIK*jFA2D9N}!=ikSKGyMrynrr}tBwUlqG zG8M^W{X&=UoF32O4zPKVd?8L{cffZ~jG7Q1$Fc_j-U%BJz-wgBoyzjUja#I!{oOH> ztxb%j40m>i>R%#;2K0%fo9}D0PWI_1`BEAYU=2BT8$$7i-6AE1!hdXsL1#d40~_ql zj8nB=v@HKbvft=rf?uk0=j~)$*k}4}t8}|O#ZBBJSEIqHJ+{6g_ds(=y(CCq=zcyp ziyC)eZWYS#AK$A|L0X(ebD@8 zkpFm!^ckub&nVkpml8hN^<6t-lW^Z`fDrzJb2E@w)4Qulfx z=P_ktO!GJ7X{jqG-!#LyB6B>v(L| z&33bxd{Ui_7PYh0TJ8HFx63P!QGMzgdAz9)(oPV&Ii*loe42Pib%!@{L{+j>8AcRe z=Cl6^Y>FZkTjSDUctOm2&|mukyx8%fY8OeDm5Nh(ESS-W*C6zbOL3zGo7z3YNE3MW z&ec%*`kpoyUzhLT%E>o4Nyl*%^?K5`-gK4Jh%=*lBZftYN6<@r zPU^Z+(}G1jA1F#uKKB`AFKj*Qeu7LRx^`(Q^9sIwz`YgkJbi<)usc#UwV9sVQT7cY zyYyb+(olOx`B2kB8j7=aY0k7Nc^jq6aJwQYIoccgDmV7V*TZJaE4|;%nCLrgmB(XT zy;Iyo`QaT7Rr#P)8yJ(mAAG_&ET*s$Bp@wRbZg2rZ9ID`mc;7hf4dBIML3?AwPViE z3mJLLzy0S9d>;L(LV3ht5v^`vo7C*Syn(4;tDJrzvsFOaq4PGOBimT@4MmsC?K$FA zQ=hrZ5W=Dl_s7_+Vbr*=LS&gaI?i*EcA&Y&vt=TFuFQmrs_;`G&;vX1g2CDeJp1U* zRy01qtc04r`6J3J@#0j|Tc9_i({t3D5fP^JX8b<1>jL{@yjhg}F-?&YadV+jqdt2T zfvv3e;!5zlbAR%gohr_y=RZc^7u7@E}FJ`{ATf=6G7+^f~!HZldh&Ij4GO zeSHmyv+Ej(m4!zi`V21m4iHC3|6^8FNWCwKc`lrZ>eJPu?Xa2|t;T|lpMEs-R6nVG zQ|39y<0)iCYRdKBi^mOkRe8#-PZB_EiE`tgmMJW)mzTPnJp|f=gKbjw$f$6nEEMA7_vIIbkp!+-j{Hg(m>ab2(^Xu^Jzj}Smw_2wnhgS!xabn5G$OmK%t zERv@ol;zluEl(!1$pp=1(f$b(_s>$6H;dF~kFJ~LTD=s}Tz`S@7PaEec^ffhs`+JG z&tP6-1cJBs?4ukbKqmaF^f&QeG*pOV4}yL@mJ5F$2dc}%7H2s@CKs-qG>|y`ssZw~ z0K@#$vEcJ|CcQ8RW}d~>{j%E2qwMa_%4F!KRVO^kGY+)mRWn+2Owzfafyy}l8zeU? zPj;dA=<5EHX|mDgT&Gof6)MEtMFU;OY8UL|2jZm1O}gSlQUfM$SYV(F{hjr{uoDBw z`<(|V%Aq<`6D_KlnvG@GRrKHS01ZxSGOD9yMiN&jrvufRb0LTp-0FhFP2L%> zHe&o~DD_27gW2IUUTWOY3^o3>2^rYA`Rm&(;wa5}V10k__lktobaSb*Xr%v|Z95S7 z1pW+4Hb=t`Zy8+v{h$7(JpX}x*fJv>no;I%jsD&g5eHHK3gIroy3q@6C zW{uw1>Ex{28LaP0X<6uFDG2r;cs&2L-e8rKc1 z@!1ZEP*XENglHS4=z=Ij$l{0y-35q{YItKtW0eIPhbNJijl)r&!ivvc@0(-mWhY3 z-3vSYdBaoD$A~nwUP=Swomjo!3U$ypiQM0woofbO%ud26NX2M9ZJ2({jN&tS()>*) zx$>({Wc9QyKN-C43vqvd-}(JQUO;WOf_!!_LBN@dW<3BsAspKp(= zTdsQi-Ia_EGQd7@aW9zF57x`;5uV`0LrGJVOtfMgPXOk-P-UK4!{h97=sO8{NFuDt z>Dul`>A1=wjGU}cW2rQIk*Gr#rF_(f)wwKNSw64jwy^lTUU_;02Bo~+^|Vpgk@0%& zq-T^?>uD~K+0$WVSwt3Jvh$yDO^+U6M6a9Snnxu+fAIS2t)^E2JxL)yDF1N}{=$~e zRzYRQe}JPuHYJcOi%I_ICnb)4=5Tgm%`7~>Y%K~9UUAwJMM0 zOZ8U#VG<|Hh_$`apz$!&C+8q}g+jLVej}u>vBQg}DOUqeY-z|pg=g+P9Kt*=I)C`4 z8v*?F^YyFzc zuIe?HrJ+BnMc>u0EDScR41`xE`&tPM3tV3__3d=fc_J#Y`oP!N5`K(|Pm&UWE=L_( z3Qe?93NRXlk|6z-h-Mb{kjXwWUVrO--j( z+y!-n<=XD2@ zF}Zqq+w^A5K+d+dw?GS!I_d>T6FNN zNef^|>2he=3;UtJ8Io}H9MoarCahv8sU~E8=r*;2%jz2o#NedmRpC@x5>Go!PiAoR zDzGpBw&9*R;MeJtz7RkJoq%&|!B9u|6t-1iKkiCotF&+&;w)`o)+YhS+eY{S?zgllI{CN%c3=uv>Cv zZ%LNnwg2l-$wPIMIbF8Z9L8Yv`s?#{$f$&g9QVR~2?&P`R`kg^Cs{fAGv20?*B3{> zv-Lp+9fW3@%_MnO2t9XxzK#6BC=qh)1ir9Uf#k=MJ7M1klc%gR0U3+PrwG%`i_yA7 z#DtmZCbltPFG{tp6LQclmwNfQ>Lm4B+^q#G4-Emx&Q+}+V%<+rGusz2arBiG6N?U5 zG`PH+J}d-np|2_YIY(76rIN(Fah_Y3lwqy(;(y4Nf?pfIMPDa6M)?;aO-K}(qz1N3nM{hT~E^l*bHm{cWrI0;ZZ6F`&xAU@q^#T-%mtPVKj%K($rpv~5M?tNbVYCPL_?>OKd%jU58agbpw(LN ze&Nb}bM-rMaHW5xNDva#T)eb(%zqF5c9$2(RByC|;*hG#?cpDm2bml`X2|}i8# zC@#Ru&E>UzMVd)fJ6Mkwl#5eXhyEr@^vhe@F-oVWM_f`qsJ7-K%93U1Z~@uTfq+|O z-6XN=(5bPZxBAe+$z9Nq7omBzj5cy^m@%*QWGfVF3o9lS9zpd z;6<-kYrQ$<(H!H5!NCT6=NU@e zw7Nyts?GoxSB&AnIA@Zq8~hUAc&m4&aCq3-Q&Y}BMshjA)8W%ML|YXvD5Pvh)QMzW z6Q6lAI#4`qfnL{(`&xj$J%0T#TD|Le(J+*X7>)Yla}vTeR3Wi zx>7rXw9vYGreIf9&|rzBeF57Y zpg;9Z)k`XE!H25o*1MCnc=9*;RPRjHY&ZP+!@NkPZhvt4i=!kp&x66#7H8;2DZUVq znLICzdim8E+om=3eyh<*ZI2fa)v7<|5C&rE>(|P++(Y4#sk??`)0sI0|AlZXMzVGC zJ6PnDLAKYkEziB8QIOw_VHt^3;BL)$HSm^=xl=?A`)hg9^y)YT9J{oE$S!Rsp8-ad zhn)eEiI2kC&EYzQT4FkH@~?tXe|RkxKf|x<07p3C52rk%6@P$s5zjwTV$`T?(J6&U z$l0S{WnK<0FLP7{ul6cxD7MsKrmZ$6d`hNApD9(VnLnfs zALHD_VTB9t$*(7W$V`zo_9kE*fEZ>sy;2NO@ImS&Q|oK zbSBtVff)a7uqNsq$ynn`>4dm7(HAoSFzw{cE^}rqt52lFg^Iy5x1iLL%w>pKHJ;fnclRd|123 zPiq^P)i^4ABwbCB8|V8Nwb5djnhYU$!OTQv+M&y3REUa7 z|A{`(9yn&eOGm4%y%Tf7L7rcWk9X{r_U4}CnJEhz&>LexLbP-0hLdr7r~joJUSd^0I?v0W?4L%<$9}*Q9eeP$vzL|5GP)) zah|tGooQsK_i~zievB%aRuS#QPF1M3e`8$gGWLw{F)HjQ3}U~pcVa|q5V-yWo;92R z>L^J>*>R+NfCVQz707uY2S>8_70`YPKOEyqJ4A~gf;YSj}&-yekY);Dq4ZX}~1@YVJ2LeD@yHN%X3l-D9y>jh>H;Gl&VU%c03@2{P4~%XK5fyH zaT4b@S*YH~rn)Yen?t`@FOjIWTE?)z860su-T#ClRh>ISSutq=gBU>iLkG@D>=GJx z&W;#W^z_~%J-G(0Z>%WWyneZfpNfifDtMoI7`nMsk=Ag!Ig`wNm zrx>WH_Fo-re$ih5EuQb)(<1#5=Oi>ozaW?q*}|xVmhr2z-_Zyt*nlc@)XLvu<;s3y z4t$CzhwILs0tOH`AwcAXIkyxB3w#&vr36k_op0zfPxoDF59D0IaGC8W@#+LVMy>;2 zIe%1p(41=%Kc zUe2kH#%4B{_|&;x4G;`cv4%xk-n-|+oNsr5tAbqB0N8Q8GUnDpIfaQgF#$#SYjN`; z`Hvjf*K~l8l4T)B!6Fj4bl>b`VrqT;20mlSuPHAKD4#xUJ15{|onEmHjm&CIKk|KM z`)t61=sjNBE`FApadCI%YQ)6ak1F*tXBp$`+>jX#)P03FfU1C(ftat!2ddXR^Rxi@BqA+)jDfs!LzKPf*yGKt`nm@2_Y-VJ`7s5^`qwSU) zI|*&=OAq^XR_7BRBs<6+9e%Dj89$SUYAZ!NLS1_HN*DF^YIKF0%y}ZGL1}yW4Q8@b z-(M^(OnW6)di%7g*5Paqrkaom2ovCJz4$dCOGHZEZ_1&}|jp zjoq@@W0>L#`JS+qOsflS8*ntd$)&Y7*JKz9+dM4{&UptrE7*s9h%NZAYahJv)t`l^ zJsB}|Jr9=cl6r?mhTMN|$&=GytL}?VviC2o?$jOQdmW;s}nW*3yF?snAqvZGw7-Qm^~99gJWv$SD8LrSqA}r=g82Fylu5K zo>keSW25{UsyQtl75+bYIDz|6ybVEh!B+xe)O+xau-kWA#YDM_<5^|tpC$0dK~YV} z53=j|KNz{dW=j1%h)t%w05IN`@w1wl4Ok~TUmSuG^I3ei9P4gCS6o1t2uZ}^_xt)I zWym_u0WDa79q@cm9#h7dTz~C6VXQsz= zb?6yy-VO(OnbP)i>)o*Lh64-5z`LF@?C$%ayON8xhzv z8hJ%v092xv?6t%Kb2s5|uo@a+&49aKPsn6VKiHsi{NN`&~rLt&~Q z?yq!AHmnwLTYx zuQm_Y`DyHe2QgbN43Y~~xVfjj+l0L_HTCB5!D@~bk}KGgOGuO7I9z#iK!5Xc&vezHr&=h2wYM3C-CM^ zQU9K~Bl*v$mGNa@<7+bv`O&V_mGVKd_0Mr5KOZ+SKQ(MPd7|kgmG24Q>S5=a;`l^3 z_>W_*`UTXLW~Zp`T%*_mv;kYd=fog~x$V_0U%(ciLa_xD_w@+qg8)dTrZBOJ_rose z1&Pwbs~OGwE~wc`_ek^?d?+#&-R=%>ygz9;Y=gXh2jntc*wp%XmYM2h)IczN1jti; zY*6&lQ&h>8Z9h;5Rutx&>YJS2yEu;@; ziH%DJ2Cc52D<_IQGj4V3544wi!F3=RBymDGWSX0(X0|toe9@*{ym{R!#5Y+mOmYGl zGr;T=D;PVLW_4eU0jq_>ortp&E^sPKRy0 zC{(VW;K-BLDVL}>5DMI4Ileu|6kzn8x8{_jev7e9C8_FsgN|!1AM0{yVQA|YY6UKZ zp+SjM=698oAbq9L;-TKD?#J$5m`3^8S%|UU8WL~s_zpTW$K~LgE$eslf*tJlIK}21 zRN_>e9>?{yeqr%~y_0ZEO;lo+SAjnMt3?o#=MIuz}q6LE0w1bvE-iE`D#ud)1EvzGXuO|!&X?h{20IkB68mvtUl3AdHc5X9`Z8M z&cB4Q2!~-TYXJv7@%vxGzt@tdZ8F^}mHf%9M`@ByDrs+RVRg*~kb5XkpZ^7V2lRbt z;IsILr6gCc&^i{*&ZqsotBHE4Z?FBAz^whh0A>o>6ksOy@4yT^c+w<1@ncVQd$&Td z+%SYVwwSjYQOJhu8*k{TlD|;C6~6Lg$=}7xQ_;WfnBdf1;xlAUs$=kH*6uml<+Jul zX1rT_R(IH!g~l)={>a0;NmG36^lP^E?P{%=_^{rZ@!Zh$c#jSb6Ir8HlX}C%1S<+} z2Q;Ue4@9aiX=z(VCD6YR@ftimZFHU)%i@Z%x?%DpgDenW`#aYEQWbS zl-EI7_B0psz(T+`jW=sDkN-kk3_Vm8%)bRx1yh&Avw|sUn*N)wpnWpeP9mEgf-kuU z>rSc+E%w0%%FS*4np4yKT2{naZLP6Cw-tV;uELGNs+9aOEg8c16&>OWxFX_k7z6{3zh2m=O) zPQ_^;&bJo=H>abSO)Y7ABI8p?FTM~j{w^+BIX(HSYsszUXcM_OUeUCCWxqz5ka-SX zSb2HUCNKR)2w+=yI+Z$GRB>%(M8OoxlewRYOd~9qJs<1W@0+}PqZyQN_s;2qtTHfx z(FgBp>0{XXY)pUu_Go3;o~YBKKGa?rbFYAJKIXJG%M!i$_2$6Qlo8$1-fKn1)48Ii z`OXCf-=>WsV&uCkwFVwiGz8NQ1qBoY1wfM9w7t|-QnXhwGxO2OWns#S`jV=Tc`w*1 z41j9ziehKWMrWoAf?`+0()}sGsqAU?c>09V`lwKY!w8vg#H3>FxlbDnY#SQ(y0{m) zl(%rcwsWf_qPzSMlW_^#mKSZMq_2wG2m=8{{aPJXR|ES7MF_F9LLI&TVIo1cfWllE zWq>ESIYd@=60u+HeuU;$hwzjqwKjC$xp65s*x>3{+t2705A(ACw0-imz-5wQI%kY5PnHR`Pl}H}%?9NI%|- z!|QQeUjI>0RN*&r`V<`$ypm)PvL~7b7xA^Gu(B&op>X@W&%KM=-11tiM$hX$%xg`D zkvbS!MY=^PH1(St;`5V@anD49kV6KQ7v3zH>V0wlXJoC*9B{^WaiKPQx#;7;M$>1Uto2=hkns#eSOsa!32R_1#gm)n}y-l_&1rrW`;(vL)-!=Ew(O8>lNE1+hkHq}Nn zD_UO19zatk0lngf2~n>L!kRfw<=G8!Z*8oxQAUR+bC_Gvp35OEyQce#mW3YDG6#i2 zT1ME!GFa(gwMmcvA7N#4vOc*&Ig4mBe7AjyG*T4f0DV&KR4@U}{iga=B+OGAy(zb- z7{zbXk`8p$B2;z17v(#Sm<|C|L_bYW zR-q$jCgOOY&Mo$%7WlIVtA(M_W^Ev?F}BXm@aRWXx8-@gn6!fH2v>L$doEQMLO}u; zBl?^m_^ai@$|gm#NqG$_N*DyD@$Q}rD8;&uCvjs5)<{1A`Gx>fAj*u{&!|X^k;VE)YvIL8 zr*p5HJ^-*;+U5Ug-0GwHji)+;2&bE@d#YXv!Xs}G>DXRL8qn)I!ZYcAp<*^R^{Ty1 zE4I3pFYFpD)yNXQx<1wE=nR9r=%7|nfq6---97mn5E4jkRq%*#y`R#F4An?cIT!qa z4GNQ$cdO*vH6u&rEFrnNb)pX}0c`DZtb=$V` zPXpwCMrIzrkQqzs1dVO<(miO-v`ZNN0;Z`(u~rB6@WBuCL)f|H^OVpu>BNbruW~(?7xZGVRY{Q*Co6E4Py3$ea#bC5n)dN#LVKA z-wNMz^WA|W`W(nXMK-+yekpLBwxrxH1r@aOS**f4a4kIx<@25c&=mm#Jx(u!iEhw= zxd|EMw1x-cqvfA|XLdv?R_8XaQ@ynP31qcyl201{_?N6!Usd`%GRLQq8jbkq23J$@ z+O`V5-gMsgDl}w2W9#}XnChjw(0Zmk*|*?zp}OYCC&3dRHI0bdoL&A7+t{GO=EynI zl38*3EbbXp@7&r3VewSG@jy{@H}7Yi&85sST&;UaShT$Z*4z$eIu|v5+p6Z#Gh-hP zuWrFs{*`F)FSwwA$#zE_Y@w`aP1hfBESY6R?Imex^%wLi0%^wJ##pP5S#^CIJ4$b_ z_{G{5>JNFS8Fdo2G71*cI-7LhUj8wpFr0wPR>3uikgbB|T&wZtPy2eQ$>W_m^2DYp zpsI+P7U}evIw_WK-i>n4-Fej4ry(<8L7>1h0ri=igB$JqthLxLP6=%@o>javT=b88 zN27DtLiY_Oca}bbwSqT^oODrs&VrgB?p>8cdG_SZ9?6E#eEs^>8X_2zD(YX0r^5Wlz=sYx>~bqgm| zq4W!hT2Enk-GWJ%T>yfd>NMa~?@(&3C#xI6Rt8sHrr!WcW4gsN(>q2s1Wive#_0F)^@5~R zRF0@xOihl)AyrGh@-I|v)M7Pd2HNy8v*4S#1{-EZe>87JH#m}y-D=e3ety|MRGDBP zk3wL%{DW6mh`?`FRNMgM#VWHn>`fw#YA=y*g+Zvda8A7T&%;@O`jh6V-l`vIZgq5m zK9gy)YXN|QcTrfmj<<(iJTt$(-|+Scs^#vi)XgQuylCC{C!2EzcU0vY(LTr0qa$Un z&ZR$HHBe3b4l5b|0|_qEc*5f}mH$M&VN$h0>7t5}+V>m9L);F5M(|ga4N^at2q^kU zJ)#FivibeX6O5}yITmv5HCI95J!BTgcI~VzqP~Ub5STL_M|l=)RuYk87AR7|?zdKI zKn4^CjK2a7)QDIelm(yp1=}i&)i!ewI4%hB6cbYEX`pyEa zD7C>Qw_`@P z`lZ_|gO8~~OJN(uiu&=x9G9gJnn|pL@}|~gPr-puzimbizJ8>#0K9i;W?d~Tc7a|? zpr;OiAkl@9m2{LdYH-v+&0zN&kmn?ii#ix!&RHfe3b$7M0L0zEbgiicWniQgMWR}P zb54hW-a3?oYauWGnbm6f>KZSnEs{}VDZWnQb9QUCrH{%h6;xstLa(yskiaE^qw_M$ zd7pFbI+|g-LK8N2cNc+qPLJ)`ld(5dC7Zym5%ib%-s-N zw4w$6u^n=VXyg5*s6Y%kHW&#^6;Os@#v|XL#8+PV-IJQD>SM?`QO;rtN%i*J+r1V? z?9-bD_HKP6IuY=fj*5ySiAkNJCEut4b?0HI9pG|YAAH-Jz8&r&mQhk_1Gh{YOS=03 ziNQ-p%E&F?&*2n%3YXI`WdBcG?)DLvllmu@yBiLiaoPW&( zZm(gW;G`8V$vN*ck?Gx#d-8oLE7>~SEHK;#tG@GWCgr8$2=1)izjYtiHh}Kq!g_x2 zdo>?8(0)XiJ#5OT5849ykN)mHKHCJtU00!&$MG}KDn&CHK5s*VSKZsR``$xhA_B{^ zqs_gfiZN{%-OGT_38>QUieXhYt^Cdf`MN%kcg}8WMK{I|_^C?zIo+Q0r1qNG!*^C$ ztj2PTKE&t7LT&vaWP*;~)qA^=?lL;FEfez);w38M=mGFr^=Ndw7(b9O5x+d=Jvc@# zCSHH+GZ1Q{_Pi)L)8FClhf_9F#&2CLyRzKXT07A}uG^~unH#sEtunZ{CSS!FF5?GH zC?LMJa&TVaOGi$4>HmFA`yZrBzvf+MJu| zU)fE(Be2+aK=bmIs9r5mYW zBNI3v_S!EBD{2hY9G~=_SyCbd{PB93eMrIZ8tRAV z$67m>)$cN-IW*$3`wi@z+&gm-xh3bELdZYLko{f%8e2=G#MXYkJB+QR^Z#FntpU!^ z|GEz85yG!DLy?Al_Rt;MbNA1%>(03QLiHl9VsLpWPy-{kHk2VKAum_fTUGzY9K6D^ zZyLNOs!i`iskVjER?e@PJr!#SZd;-BADfFS5;m3XF+xK(&_5m7%td_a$d!?;T@qgV z3-J=Bf@pO!EeA!*oC@UV?|bbo3xeuR|iaGihdTG zvMAc;YlWpTFavc$t!_EnI_IP6W4YPmNLxvreKD+@#y#0=TuhzW}>C|wLoHim%lUeMm<5Q+u;(mf$?8A2BiKiUbov$$79o*gc~}k6|v)` z`4g&$rCw+F9GHr0N4>|Uw7{0w!`@>e;ZB@& zYJ%+Ke%_X9{^@_~J?;)xNqbzP`rgHgS3O`A`Ew*){L-Mv(+FNhb9_81W{EyLhRgQ8 z>|QQ1Kf$+-(#zaN!6-da@K;qh_cc3oMahkd8xi@Ctq%4BTygRh{{hc+U=mvOzmd1r z-r3r1i`H`c&Mng`uWg=_PNqQ)BGws+URJh-4xOI3t6FOR=r{^5=ubF7H$yd6?14`` zS0JYNP4y9Pcu3V-+x$P}H0c`J&E0i+mj5yMi>I$RYaR*MKGoa~ZJ&<+V*8wYP@wrL z?rBpfk*Ah7o2508|7QvT(3R^Pz3}xw=`RzU4}Vtv?tSAez-uj6+8?-&oP#n~ny*{e zUw_wM9&yIT7DOy32}bs>8s*QCF(Iu#JcU!Grn6R=VUj$D)4wF;F?it9S9-6ZO@KaD zCh*(|yTr2=$Gv3!Z&Npv&kyJSHR^^;&!*(m5Lw=3G0>=!V|VVejADSm=smJo)00Ky zRHU}dnS;MkTL??N&Ug!taB=+}X>W_IkR_tEA(jKCP^6ZQwmr~>YIUTpq1!=Ti6iTS zqMA(Z%_8>%ZU0xRjY?>g3#aC3C$qL@eR=-5g#u>+X=6KKj2T}H`(RuM%mjoWIA+uz;BV~lCu#&(N}5B_Mv%^N2grx3oC=~!uq##A!#dwf{(Y}E2p z^8W_O@E$UQ=uDDu70p`(I~Hl|VB8kQV&yi?Qh$E~7omt(`;0gX9i)ROclZ;XLV zNZ>GkuJcqkBxPLp-i1 z7{{{{>Ucw32wyk6OdjaPRWsz|kt!cj z)_4Z3;>hjI^hu@*>vh4CcOR+`Nn&4l)?)qFF4NxRe(>rg?K{?<)*P>dhr%79udD=# zN;Gn>hJ7riM9-%!bpQGB(PhY_vw00?Me24#SG>cAJix4yQha5=JfUDwUY3bWI_tl* z&e`Dt951Ez7`+vKT+F{CQE_33b}8?b>^JbYjOVQ+{%WF{qm9n!JURxI4Iu$D#&*_j zgxKqt$Q+J#!5&4*es>=v6Bi%KP=(1!M75q=^g5`5K$Ke)~%gv+56rtiJ&j z)&Xg;czQCBYtbz_Fj}IdaN$Cg*|4_2z-?cKi~$jFAJlA4f|2}6CNPfY0)DXm8O$sf zm@L=9==3;bKyp*n&PX$(Q}<%u+U7>wASn(TpPADU$L8&)hcv#CN3}Bg*dYIg zSOF@ODI2`Lj!DN(1LIHPubYa7@i6HOnJx$>0go%!&J0;wNAwx<&9=HMlk9*9w&SUj zTnr~ajVI!O4_Og?hriIuo3;~=en-1*qc)|}VD{o73X2 z(&DFH9wqdxyy?&`taJ4>&7tZ|};cHo1!|wKl4nIPW z>)l~@1;gfgyE8V!*LuH^G1v4>f!`2w*C#g{FdrFm0B`mfMKU&8l|LWk!j;}fEH|hA zCB8B~rYOH0;rpS3XtZi{)Sx$~A-~}NyR=C0Dgk$ed_OyMYgWrLn}ZpTJF@KU&Tc3)D~f z?DaW8=LZ@EHG0M)?ycACZl8AzeGtUCp1r3xV-iu|?*Ga~L?V?^TAT#lk~*yw(aTF< zpGhbTFC)M`)1SKP&t-6W-Fq^Ut=Vt&H96&N9GZuBXh&;10*UmiO?mxDtPN>?!Knbt z{5I*&Bws@h_0+-}4Uc3P$-=3x&#Fq$F$%9~Y_B|*?pYqX!Es?A63vhAtGE^C3X9i- zo!6sO7Wvye&EeCW<6l+f%ANQ2D@rEb>`Qf=03 z*g;|>5!|HgAAMz17KmYmp7;JzNfda}m*W_9*L+)m4!}}aC z#~DAR*_Ht#=@V4G7Y@Z#nRSXzPULnNXeE5n8nNeDM{k&L=WSW!oA^+#HfMT%^ZkW% z{a{W5yY!uM|7so7)j6}hi>mMK$FrE_Sf0VB!*GqL)4tW zxIx1}PN9m82XqrHF?5_NIb}i#eX(iVfi0U;J}?J01%C9f`|L+(eEgpH*PCKrnv!ri zozR&HD#J_B@Kj70-eSnp2x!jl-9TGaRV06}C$wQwT96OFUp0y5!u(n^<-v;uZT3xQCNyr!wh*~^eG?G|F&>AC76<#(ku{|Ib@@ZL|j z;VRPCZmW_<{}7nc-OfD8C77)p-jwO`8oyq)%XNu&QgXqaE$g*b&K86HzSGh8>Hkq|q4jU={}6i6K5I%~Ty zItB)&!}MCE^G*qJnPx0PivY~?Ow3)S%hkPkV~O|%z&xV%7=wyg=KTWU_}1J~n2o8k z;D$!3ztn6v5UGhCj%Lvw`4c>TN7<)ww~(W?;+oy&koo)<;S}RavDBf_Ye3U^n9@%S zytOTM|MUvbPuv0eiRUVlE$DDfIng0U{lra5KM_Ho^b<3Iexh@-`ge-CtN)~9Y|_~1 zD^n2Rfte{v=5!kK;yYx988^M$f&l~X7pL{k`L#wzCetz7g~U;f{o7=#0~@E)5jTl0 zs1}3u5uNm-yj5#HgO!a3dk*7XzEhjHrqp!v%}S=dVpe|tL`PJ18fD;n>i|W{<$Hp{ zc>-i5ZY>2^8b{MB8IdF<_XF&M;pRHUymDU7d9`0ChO5jY!^6 za~T(vvInjR%3+@hdKVdDYtsm7T`D!IiF2oyS@-3|-)=()3$N`deyem0hL;O8KMrE7 zRohILx9!}tjRJCE1EUaRi|S{3NF2vedDK-$V|nUc2Jv3*^k zDJJCwq^(;2PFt-lG%?GcX5>uu zq!|;`+sv@4H@-3nlrmxz{#O}s{jlEYh;6TaLxj*yTaGqt={_7wRn*v-@oatqHc_jM z9h}-#A5^r+_mS0M_5HJ6#SlJPhvmBl1X#%yb{ z(V=WBH77aFJ7%H(Z@R+>&>c4}dR}D6*>|@2=eRU^8&sdUYx>6yKWnU=Ct$NmQtC$XxS{sOx>-2AV)snEtW@olj|5b<^dZ&Yb{cwuQZgm`l>Qm*% zwa~hh_Z_gC(TLggWX(i`bEE2Jv|}97uKjAIOSCF4skT-~GnES^1NeO)5}MC|VTP*MVfSxp{57WNsx-zL5&K|E2qGLih&@c<_nlON=oWrg+ZfCw>iGfe@~?8nheNWV^exY>YgVXDN;) zCIPytoFb>BCiiQ^toKfj$7${#SaL(nAuZ-8bjt_YdnU^dQ0@HUc=#;YYOW)feA7nu&ta6UoT zubYq+A_QhFUY5zCu4M&918bTF=Sl46r?DVEw1x#!4!8XG=lJ06#@^rb2$ zqF1;BVobk8xAH)^Fs9Kztzp%vgv->~XY;gS>oO%bB{jR{b#ajR0X^Y6ojY79#tw|C z1U~u>*kiPoslJaZ{@E3691o0j?_mKl7y_^7C3;SL+HFGxK<9q!9bSwzXl_QrnR?+J zrzsa}RX1U~nH-c`-;)5h1my-mat<>%6tuGzTxY?H`h+Z4z(f2Gr@h#nOZQjqSGJqU zni2)(FjMXjL7nbzHMKwWtFp%mTw?rg7XshmmwZUB`-jrOiV*6d|9-#Cu6LX@X zqT*IiK;U=K-k;C=^Bs@h{dnB>Kezvs2%N(?2RP??UDxxXEy?bmTz{NTpg+w#YEP4U z(Z9Cgbn{aCFKgEC9{;^b4ai-ugA1Bb7Z_U-u-tHi6O z<2d``-uL5I_ozu7?8#E^m0Kl#1(=yMx_qlbb9BM+4Gtd4xY#+mW7hRQ%c_i-K^jh1 zm#vm8GW-E}c;1=a8aUn=EHSJIjUDst2}wXg*AFXKzY)Fq=cSr;NKwDofOS>dqe-e3 z3;h9nmBtV@Y3yA5ub#fNb;1s`=@H04in=x>Ycy=ARb814u{*%UII}QH-1C zjsn+KiJ^M+u3da_tI21mw+>PPNN>Hvf01;?LW9Q;ryxTHkP@dLe}KyN{9!i;Qd|3S z235#j&(rPbv#sdNXah^qSkGl!-1v(29z~?zmjA=9;#!oIl@`4%yQ$68uS9Y%#qnVU%zG&P96mL91!+rS|aI*Hv>ewcV$} z_yHf&XGX7ecjq=3D_vn@4O<$MtclxJa}@jXiv?uF-szNfi|1>|eV$2cfRu_N+U80M zgTDY8PkGL0US?@A{H}jeogGku;Y&QzZc(7!F&xc^bJ6aR^`$vHhgS7)-$%k6$# z^R7&i)4qx5(ZntDbTFUneAV6;_v0=~{%;D;|3B(b2t0Gac@}G zkaT{8Fs}RqWTidf0;LA|O_0-&!cL~yqCR@_TiNN5w>dQ>=dPwz_0Q``_ObS$u;tAa zg*Tg${%b-~BpFRiZ>QM=i)2+c-$ndV^^E0DnpQB7B2NiF+-t|{>2fz70)ayGp7>6T zUjH{`oP{?3{=oKMX!DMr+lo(xdGORf6rT@VV!tb|eAOe_*%S=lLm+4RtAa|aj#$L` z4=*L5DVexgg49ZkN zx#hkPGWSpEXW(z?C(Xs0_S<8I^w6TbKs(=J%_VtWubBLn_to|4V7nso-P z4KQHhb?GnNH~_EEl(f{!#MeLks?3~CE5m1Dvt?NKm%pZ_?K=O~g6J)H43_or!xsV# zWt@AUeD-c#(V*~z>V$aqsaMYjv7iHQd_fQ)rpv;2?zOw-%zUZjM>X>1$qx7hS3W1<1yEu9kNbqZiu$%o$kSG%w6 zaDw~a?Y_zrqpYmnFg6|6{kJ)&KB^*fhWB-COEc}0_E#R%T!c6UP=qSC6(JO-*7bO? z{hA|lw*f^cHW*p))a$=1La)9vR&_ORXe7SM-BE;gcjL^RKEfFEm#uZA2#WU%F^Sf_ z{3Y9>2&TjP%27P#{&2g;`_~|Rr4KEVr~*K&06Wkm+-_SP`USKGyOskJociuR>d>>F zch~-Sg4hChx7DGYg5T}${(1;t3fjE>Z+WO_&p-HrW5*hJpFfn}%L?n&vjKlFKn7P= z7n9BhEXtRUpC|&Z0j5|`^mPDl`EjjlVIOWpefj*y+uKm|x+jFB{H}a%g`^hP*@D+n zIt26$Qk+VBLAg}+otiN-C#0!AY?ttAK?8c8u}9t&|A`gUJIoePmU3ggy>6g{P)o}C z@kRLCrG-QW?@KNE$G>_;1Gi=x6!%Aa9{YMGm~pKRA8l>=IvV=S(U z4u@Z>xG|(ze`v)C-as7cRwLVbTz`jjo^8g(bg5t7k%K1g19H$A*;BA4(4(Anmq10o znY_#;*hReCOkuC;4Z?4Zn~7%(GcYp>Y|A76gB-NLOagV`E(9V2fgyTfS0M@O={o2t&g!pz)zkE8DNpIt z;p6&|L1$ic|74$N)M7b(OyCe5BzXLpA7}=#z|H?W)7o|6unEQKz)w3A&uRaoo6i%F9I)Jm(zcM{8 zg>J0dj6uvLn^woc$L=n8?2|lO(9Aoyp*?zZj;fKLuL>lQiHBt*KquOZDp$0i zcCPTUK`=?}-$khSyBjOLehaPu?tJvrLD4^CD$>wz6wBk|YlAUAEe_z$)9ZTwMD47G zUqfvw?|KFvUo)T-Yp_j<8gb?jPo-`qk>U=& zKBP}gEQd;(t#Nau@DqELsaexymkbV!dKGV74pFP*isk<;&?BL@?`|v}9UkJ)8(UA|ios?S7wS^dp^L(#sr9y4h=D3MQn#@bOx%nfL zii!0mr9;?Ba{gJ4eYpaz-oEXm?7I--9{Xpnl8>$UGBjm3obOh*;-12r0qJC0*&$DO z2O&v=LJrpOi3Cw*oN_J@QM>XFX(zmvQ4uFHWw^G`EBDLVbaBhe6bc1q-~hk|l3YaC z_cXOA9P099EMAT7e#$U`P0TR(LUibrmDa+)s*>Al>zoG7j$Rz;IXCseSP%#^nl|8p zA+sr_PheYb~K8oU9TxEO&$v&$evX%+2R{|enDBv!I8wu(S0jU zF;(gOPu>*k82O)gQ#mZ&RNadapmJD-d`~m)&{mm-nfU3{8q1X&JWVb59G(L^KdF|w zInkW_?G^X@JB~}thvv(_L~h;4kB)g`3YT=wI;p1XeqYzM_V;BhVl;_ z1v{mNx_X=dZBm_k(D*e<3XuA+#!lUZE0;I7Ia3kI?=;qPR<2|7nk%|gWdSqSodwr$ zmY7+*btkNL@MQAZrxmxb;uHV!>vXgHIy0AxBgF)*-zB1Ih}`dD&KjDwi{DT4$xF=q z+pxou#qu9sOh4vbqu=p!v)8OZ+#>wvr%R_h28t7g`g@#2%Yb#d0&WC=Qf}K3ITs6x zRCrc#*6SvFPUK@%hzo#4q1!bsQfI$wz zXO*hJXel)i`H1NMAr4m;1cyw*PvM<7{T)dGQoYFl7fpKBb-bWE(*~ zdFpQj`I8en2=eH20D_$3(>8*<7eJ8jA$~yVun^=wSO{{}KM3+~4u`v8?{F24#~i8~ zUK(|#+&fyFy8*H3u%u&O7vxAtc%N_iT#E6xcM#l&@QL*+ zqrz9ns1J|>r`acRB|8CI&V!JZUP7VFl?c>vXpikGUT?--cRe>%Yul9*zwOF#?%@Ju zu?l%RbhZn5H>~fQln3Pq$XMis*{Vi(8w~9Q^oZ?F-uICc+8ojPN|!dGH(puYIl|pm zg!4&~o7nRXAdav8A&&R3h~sw|ZiV*ztOVR@TYC*|;>kHP?dgdEo{`t3R*)o37C7or zS57+1m(!qs_0<~S%X#&0U(Ra>wNQYF;s5osw#2X6DW6`_tmu(16{W$%Pj714uJlPQ zV2`n+x#243m8My@`IF6aW9^4(y-)fnI5C}*kp)NbcmBbNYOJ_(fEh%sYHoe))wMetnddsmw*{T8x%;g77rfcAwmNkaMh^)R#^!p1^ zp52bw+LmgHL;-k|u3&Lgd}!yE^EuZ26y*WECWICy@_%oatM|FX!@wroiVNjV@b*iw`D=#X|LKokh(##1iX{=eMi>0-$v-m8#PN1t|3kZ^VqRJ@{MFdUfr>8y3`oz9 zSK+U33oDWhHL|I{Z8NLET4S~fhx*QN{t-YT*Mj}8-!pq@iEQUyFO}4Zr|S2%6tWkZ za4u~Oox|}NR^1sEzc=|N8JJ?l9{IDZ={xCQ^~5D?TYD9aW`W}Lc^ z8n~n@Zlzw(tuQk$5XW|QXQRTD&@-KJ^m8kchS)W?GRSV1NmKZ)iU+xnJ9;L*Jt*K@ z8Q2p6wTfkcnYvTc8O*aVo#gMW^qX^oYH(Got#-D}MwO#hx1|8xlNIm#2MaG@ur9o` zDLUf9o9b_yqIwIXmL1GkUNZRDoE*GznSbQw7q5v$gZQ)wTN`Lq&Wcshfh|@()_3V@ zL7CIG>xFG}%G{6&D=Amcj}<)V0C4b@U~E-3V9Mc_+0jy0@yhhz`9z3ht#fv7>4mW` zZm;1<(!+-)-79bn>XjctKnLSzStbYIX@0f)vi`&N=ntH}z7YV6^~XcLWL?3&JGK3% zkFKHOI}_p}fqyHE|4nlI|Jw~IAu|{-6OcwmwVNe%Y_BVy=^1zn1SQxQe`$he^;x$h z=l24eslI$`!xh0`&^D-Wbtj)OvKPIs1SlPBULeG~Ws306s>d2I0HG_Oa|PGgN#9s` z*Sdi+XaXST;3e?LE51lIK@1vo$vZj{xcA7Lo`-?lz*3%RV`>O2!WQ`3tE~g7yOGsO zr+|C>HLD~3ES0qy>fi6Jx4)WCtkKn0?ul~3y8*W?pL#HQo%P#>8+MFULNFxb9cALt z|F-oZ1MaJefW-2y>TKUV*KJh+_`6?ZcU&qMjK(!Xz4g?97ufOIO+FLYRRNg4x(%y1 zGQXTn{fV6g?)k`9Opvhs;S>P~B-JT2$S9UaQ)w~%J+4y;J zbDBasRM*;Tr_^Z@FSZGaamSphGb>tRoLoK0y|r<2%XYeWIjFDFCw#uB#c#vaH{8l* zj6|E6OG#J@dyeqvKjA1Fikukc8}%t|!Wq-QC$nU8^XQNn6Pd|P{W^saKH&h%vq;Nd zdw02-e2@>WK%r<$Yq&4G&+aVda(@7$pD*%sWD)NlKY}x%PatraY zv%{*v&n2}UfvRq;a$1$NYm6#>m`TO)GC1-n`CN$`mZQS3z1SaWc~VVWPK# zdem>(PNLAa!r=EYKllnMTFbvOvf!@M6P@_@ghj3f`md(@=@?N1DB}k`ojF>707`V* z&3z}m{v7qZds~WLUEg!}*kPkmEse2T;t1bh!}AMJ%@)l#UWl}sXZ0y7ne5n-9K)c%gahB^9;(V1s|2<<@X(D?`hvPU)i!SoX6VJ!taN05 z6*ks=K6xKwFyzn;C>C<1u*l3Wt7NJc<3u;2Us1BnT!d;i@rw&#ws92ZZ)wHP@CSUb zYys|DIe%$4K*ar?D24B@P(1s_y7T;j+S$Bo4j-RKizgqB_Lp#QaY)A;500C;DJ(}H z5#;3>u*mJ_xh5Mr_uNrTE@Rp6HU6tYemaDBiKkoCb#~QNirm-makfwtqewKm++U|; zlPp%_ABD-7F_cmL1&aVG!Xob4ZrSrI%nL$SbBhT;>Ya^kVZGgVk^^s%wx8W-dETBVg(%3SHy)N|8K)$bNu)i;!A-y$W1&W#1?UxijJ z!=$S3uje|p8-fWvQxoNl>g^!3&<#|PS zlWx4_I0`nNL^lZFSrU7xED!ziSzocGAUCPu^`P(PZ^Wf(N{2DtYTr1nfZs}=Ih~Ws z(b#SJjO*6d4poa|eU)#c5n&OPT?Vu93EcTguCp#&Lsk%dS(4td4W%%DXKcn~MmmOb zLwCIyp||DEpm2ACNv=Ol%t%O}{7i3N$%(ZmP!{nUF)dVU3wCvpfH*Ct&~TgkJY1Q_ zLMD~LuL)hSxxo{E7L`)7WqA+kErX2dcS;BQrjJ-bX5*Dk&?oY=L$pf|m@;k{Qb{SJ z6%8dA5rWX|LSp$HQo!U)4?qP6g~r|NR{mp0bo77}V&lEe0SCnZ~st!GDL)PlPz zf9~hi>&kMyViX7rNG2!mJGv?TjABRI82gtAKyU1u{*&js`D!PV-4D6x8GZO}em z4V`w(ebrh^ObKt*R_)DoPx=16*2mv`I;{U9e&DwiE(PM^=fBdIp{foXai+W?{;Wez zJRO6CdbfHHyjFUOcWdgDV3aQkLf6(VZT{>4kKbZ_><)d&0H)OQIet@j@hJ~w?gL4x z#>Z#vrZwZAT~B=0)}Jrlc7`KgTl}+i9VL3wqZ{-<{-CLGIbV7l#u7&X-gQctNv|zo z!1O2!EZCc0Pt`wU7MKO-sIUIM)NHP%x`K9RK1fErN${*yJ2uMt;we&#M!M2PFMOLM z&}l+<+|UW3id;_{W6o0X#l$juG$C_-zsGxJBG`B3fxwNhu`?z`!UR9D7zTF79Y0KFY zULesH@=YQO9=?htR*C=4a53gUw6>4)a)muq_LjN4&~yh2@2EQ;T8-HqcV2Kxff#ST zsX{F7s`E%{xK~<5KX#sYp}5p|9k35_Bd!lFP~UXD+g^z<3oS6PA%L&c|2HQ=iNXH# zmOJDZ?@zP7c@NJ%(_!sU#IAIdo7g|Ti_I9cN-%;+_ob@~DyTj8t?`EpV5U<1vQht^ zpKt)DBso2-vmD!mQ2)fYYS9X_tTPD5lby12;VD zoWz?0{{k~Rsec*}SvNTUuQw3xr88OG({$R#Mab&>W7_sUd2m&oQ>o`IGYzu=qF&gd zXo7`V`;2W=$X{h&H{wBu5S4{5AnbCC8LIg4$R&*Rkf&RnyI+(a7oC0jV>)EF_@2p&hX>h9jSxLP zYW_=)g~DI>^Qn|sWZ~Td-T3N{KEZt*;-!rSGHB|}f)Gm#k|xFApRWdMUVUZF&iVR{ zAk$zRgCF$V2Rv(t_gU)EFptIEd#yS;7s$Q`?Vbz#xIr?LVKZ$ePl)Yy8~=i$t=$eJ zM-7?mtRi8CteadXV8ki*?)iD-(%0^0Oa^UfhRmM|6M%5i*|pD5174nOK3%_YBS^nO zuLE&JrRV*5?%~|hrK^Dk9YEOwJ8RvBIwa<0EwR0Lb~|DQ5~00;>t0Y%p34F8L#)(; z8Q)*dz{K5;w2S4+@&|2Z61`Hnx~T%c`wFYQlnn$W@Hy6K)x zWVHi0^}2>FF8Z6j-M9|csW7EeVCxrFbV;&@*5fn3T6Zb&cFyWsmj_z3coKvAEHL|9%|$57R+A4mw;v$ygptp za(<81K#jQVN#K#|kPcwQ4+Q&bGCydnqg|VHA9@saq1KO7tk3-WK{5Dt;0jo7UhM#o zHh=YOWm-GP7APuADxF1X6PF;WRA<84APYpfSuryI{ddBi^y_{%#dwTkg&G)>49x0^Po=cJXb@}DY``NOAU;-U^B0ub!b-IHcb;=2 zBAsd09Ir?gv`t|i>=36`-&o>^fMsoShIM8N_lfX_Y+qZm1swc;bTyJNPVivX;-;X; z=7DR+f%pD<9!;=$Tm}1*ubIn;=CYmu2>AWzz`log6-UU1jju7_tpgCJ~+=0gPf6mHT_Mk&N@0_>>-b0YpVEfEC55 zSzU+0PC6+-lS?x5Ue`KA>`Rp4!=>1c%cq6G=%I1(2j0{iNd1uRAsq^OQ8zoNxlT=s zIm!qm0!A~iL&{~$F1ADFi@Jyuzi&_C_VxFFVNy)HrUU@Aik|=Ly4L7Va{DpggjBck z^10J3!TMG!gyjVJ&M!ftG^*Rza_zW9QK;h=x0Sm+Un5JW%^llT7w5@X1?Pj&eYxg% z=m6oPc4_x}qm!97?DVpMR~NVmw++mZlI4wMTTv!9-pKwsjrI1`pnHTdum~>80}9Yt zx8g;}Y7o3fbbL&^`|zluMJTU@Y}!QUI40jNf>!APjlg*Q{EaAlo;t;AA7&CdG~5yE zSaTeav28|>FfiFE)avTU(nNsBX&e5lq1->b0E?@lzVPK)GIzCp#mKo|g#NJF`2>SU zfcc}jErIgAwd2jkH!-;u zBX@6>X=_c%A#_c+=^>)D2}%zFPwMjd(d~5IpHVUR4RP%m`t}Wf*NfhUbK_8mVNFY+ z(Oh5$!o~V?bKrRp9W8o`KHTjjwGzJ-zuLPV#QX)?c!U?>KT2u;Y0?52s@6NhO=FWp-Uf0ye z!y|cLHs0KboZ0xzyM`tTz)vh(TxbzrUQI#Q(Ve|Z;^MShxN*V}{hcAEl>ABed%L>& zj5MKA#`hAWDSltoRgO&b4&N(4k5DmZfO0A($LhLS+|8C=hN=J0g=$Wa02BTa!1-3d z>=j^JeOtC6^XI7f9x$MeoTEL>69~{CfyQ&|NUw;P``Uj9$MrcCKcX4ugjKDy*eCbO z0NvN(9n;H$3Ktn-RyI2Eh99StJmFKyJdTAGzsCHTv1Q$OIe)OY!xTE5?4WLyBRLf8 z0n~LuuU*|LnOWOQn^!y;W(=#I#YH%m#WIgojn9c$c+MX+zpQH@a zDhBK)Or4SbKL0lL!+C3||46{pH)q9dc%g0^HwN%^ihJM9`z4+ws!DF$a+HY~G8rts zxsF^76V_jSa7@&4dtG|^iDyA}`&6uf*m%sEa%H% zc&%(MaRU(`wD#R|Y4K()|`#wv1=TUEF!~Y*LA42wH%?lJ2MLso-&YMW`-HJX`ocy5rhkde0nr z=vi;e1yI^vD==+ebr-;&O(yvf#3P$8Ctj!&#Fb|Mt1=X?_p7vW8z>_B$iI}$revddv zSG*=HdzFT6AypAC29bg{G;l&m$Lu-eji zQ`vZbe~^b>X;a?`M%cnd=%+U&P)a2=O2jgW9&c6FV<1(!?h32+o`5NuY~X%_cIzp8 z)B^~Z&7<}A{0bjS7>w-LF*YkxW;TkliWGO_j3J63;nQo$0iHsOz==4Jx@n^1zSw*r zDpfixzyR__{j@arY%Y*F&6JfcafUCoRJ`_%A`yC#xBSMVZIs#c zx=h#}9Rajjz7t$B8?h=jyZl6|a*ff~kFj0tkkG{FZ=tLGW~M$2jn!7?j~Lz7;GPq8 z_jy)o-P#u-d}*l75FKK^qyqC_beoos!@IqUugtQ0l$#1Ic$xQ;2}SXJg0x{{FE6Tj z`yAZs>U@DdePQh!+p}g?eup6Gn_vccu6mJTIfFR+Y+tecQUrY8`k6h26}FxbltP*V z;H=5)Rco2b>ULs3t((&yJNpFXQ+cYQmDjX+a<-12L^x8twB?RT!Hd0wSS=j%ID5KD zJh$@+p{|}+V0uE18piv3*P|cXJ@gzml75VG@g}`l(|sQr98E3c?Hka1$|@1-bd@Z# zK9&5vU+W80r5lwKDB<$GG-$?YRxm`0I%VwFi_K_VvVmJ8t}n;`X#BMJs8Mk@+bLk8 zGH}iOWAN6?)=O%Rf*~(D5Kyac$tdwu(Zw}4%H&0RLEg}DLr$$xd5li}tf1L?d;aFl zZb)e@m8~26SlR%e;5G_z-}T5BXntKQsCY}1GBUm1gS%kZh=^Q&wuUh7SS(*C`Rl#>1th z<3tkmG}tRKqBqf%Z8>#bnu^cl>lZyx^4bJ@%gjD#n^Zihr)e6G!}Pnxprm0@p1UUr z{)sWP($#Nca*)&to08Vm==iy|9B~#MgQ`aCPKf!MqH;r7dh1Sw`?%}cvm z(BS*^|A8tl09z}lcdt$p4A9rsaW5;nMGwv;uN=AZb74HZ_sjdb)Q3r9p9;~4%&i)F z&za6NHyiK;{MB9{=&+8Diny-tpx^3i_*HzC_uWiJ%#xht>zYhvWOHi_Dl%Gj>c}hs zFkD&p;Xl+F!lff2UqQ#XZPX4h`Nv>kw+;+OYN6x6{kuacq9rf~S`DN(o{O9+JnDX|_;d%6Wc=*bTyj>_R#if@%hYSx!OOLkq)CDnT$o}v zQ2evBU>w(-mM7@WFgyK*>Yp@_LO?|}ZpGo-LUVLc&m4|I)UXYou&&e7r`YPkShezA z2VA-94q1I6lyKY&j<%NZI=%bzZG%0^EvJEA`N1sRtE^smyGWo{URMw3l@DuuRleOT zzns0(D?k3TFl%^oL+JEGwA#Q^;N0Z$L)&k{{9)V(Pe(o97TgWr7-t``X)S~qJf8Z7 zTCRxE!kB-PM02kB{5V;d4#&Is)Ksghe?U9(;!Lj9;Z*JcX= zpHQ(#f93RETl0rgaqtrGq8&1hRS|}~Tbo^cm~E_T{sOgKLrO;B_AHwv*KUqe`|+dL zS@998=Y@w#u$n@c11*Mq!jlex<=egQ8bdoY;n-+nCtq);e{+!ImZ$qoohqLYfSNGk zO4w%E^jal3xL>+?Hn9c%xcd&UmsURcS8C=9#{L%WE$^(dKbg8TG4MG)F1qmxKyKSo zwPOfVznqLOk7GgwTjuTg-<(^j^wwBzh+T-cNBzPdTsZ4REEY4UmD$IJ`?{D8F1RK4 zQNQOhCw89A%>9v~rW4DFDR zBgFHSqAItG!hiCk{la5|YYbS5+F)ffeqC23wIfu(`DQ&b2Z+92|vL1*whxrT0F$)$= z{jvM9Fb)&~{%xP(8+>EUSop;u5MF&i(6bbXfB`^cX#*(bulkJ=AjdPZ=N;yW=f0FLK-0NE?X#9ppK(xD({j_W|0&cDrr2hk=0hFplQy z;9|G_&f0nm?7!Q?2)E)V945aDXWyyv(^GFXTw2enzI3^$FEI2&!GFiII*~nbj_I{?R~<6P9gy^bmqe8V$p!k{L;VFXbA{oo-mTZkY#*}JOefZ#>6n>*D=({arC+z3jUV+QXGY7p z(si0YyGfUM$_Ruanr49pc_FOldGs*vs9Avm_^5Jrru=@o9&^#7Ru^vCx^=4e7d^*b z&a!Il#avAnr%9!nsR`*83(^971^v3-`w8_%u1t}KrivG2^W$Y%LT0oOHp2S?tT}^( z3?+Bf%>2}=C@yBb>2^Xr&Ml}-Q^GExYmi+5O533xu@3*iZQ9j`1p1!J`v_;1s`170@+(uL ze0>Oxd0!-+jC^ELKJ~=0y`fgohpAS_jC6!dRL}!At1sgQ5rCvg0J;5jpb4Y>Q1X+|#m zXg9*VbmgeLkeI*IYU?^@c!}lwBl)>Vt)N>gc$wx?$C2~kU9?er3pwQ0)SK{$C%2gi zJrI|5hOZlwe?o{Ytru7odUV?YX$JvG6hBu+Gx-lN=B+|*%Fsh6;s__Fr7IjL`93Je^Rn664_SD zqMWBF2?a)Rx>Fww4F}*GM5Xd$(38KmTs<93WtJ&`=XU3Jk^a4&)N`9nh%B0JGUFJvtV_nM`zH)WN zf7XK^-F%n+w3hC#%DQs^ocOl5k$UX&d@4{D1?}iU0K0B{hAav^&N+^(c46n3(LOEE zjk|GZ?vi3WP0|zGDFBeyG>N{CAS%iQCyCKz$oXf)Q`Ds>x;U_weA7sej$d`!lRF#Q z4lh{24P|TXJ<5^3+tEFXTlZ=7?@xyIM^4OZlOTTqhe`;FgefU>lc2^;GLd{($cB#y8~q4}u$!*-%~o3oQ9 zoNWpsaGjwXjv8R%F?8>CJFDfdAjgp9-dc72vFNsX#|f7L?$b%}on;+sN6!HUIj9&+b1j zxYJpn8y4)K*F|*pewh}xclHj-{xpR&MmjJ-_fMWo#_O7d(q4sbJ?DPMDDU~>#p*S` z3AB{2jhK2r^h98YD!Z@|FWxU5bR&|qew#s;)n+w+G+&|aOC9-sOlZfZv?WD2K_4hV zolBc)^+_urL$5}f=YrUHp(H(rSqDR^>&`wc;>|fhr>rKPU(87#G4BO|*w0K@;y79~ zD-|p%!^J-+a14-)tJYmWz!f&|quv-|ImwU7G+RvXT?&uRnMF4r?-pc?0MssS8O!Vp zGy4;U!y~gjcenDM-P(||JY@U=H*mJ!eTl!N410Jx5LaKFLeyp6!eVpER;@LFjOH5s z@KyA@I7S1gCE06do+B8gwicG9(BYP3yw@+TqsXu~DEURrk&Wcv;tFyrHshCBaW6LD zX?(o5iLGpsJ5Ds9WDF(BZ0-gtJ3&!4?7!}`6HeT&rcBTPcX=ST z)KN7$tcf3CZ}-u7QMjCxe~M%3BTUFxyy|bY17n>MnA&ul{0G6m*zy3wqM*2c#WTU~ zy!4UH1k;Xpa9`M|>KrB;`Pv?4`{tYvHQoCn03qK5$Rf+mZYAo=(W{~~GB3TEELbnz zwUG38C~tXTE9Yf4jvY4*K+3;0E5@&dxW#pIQYuG|fM2xsmeFKO2?o*mF^FVJdEg)E zeE07#DJ`ZEjcX0Wwj~MfMJtC`ZKQsDV?0QuvDGpXqKT-eZdk(3MQ=Q0&Dgc@nl zi|yuf+B<}%01+37Zd_O`p%%qA!KN;d=U#F!uvFiH-XOtks?f4QAz6V`vbh_SyO)YV z*(h3)fe$DDi$U z!|GWQCNmfKR(%Iw@tei0_*kn=+o8{b5$2BL;Irjs=Yg8Q*cx%ta#^9c zDbt77SdU{2y^C{ETbTZ7ICNq1%A57dZ08nh$aSX9LNcJHYtbCwOJAF`l?7IhdIzT# zN6O@*>xze`d?qK|&)Z9Qy4}hWETa_W1EEpv@jHM^hwr6CM<|E143}inIU|E3QeF$a z;(AR_;ssHt%qBt&DHhXvOYq)@Z9D375c0b~Dbvxq|YDmn)-N$8Q$C;-uJI&5qn z)b`~EF0OPw3WnpMpZZkBN!y&E$ZuKL_4fDG=aygjT@~a9?Foxr$FZ6qPWXe&02{cxu2P6bLE#kFnU}yxvf}p7AurS|3g%F zdl)DDpQ1X(9!(;BEQ5}M%;wj~NK=}ruu6#kMQJm;Pukx~2>cEV1Ft{rfth*Ae}GYA zHRjX0h$KHXKw7T}YAug*GD!J3UIvq9emZ%wXNud{yTbxfDgFB+F?1?ti$*uW3Ltwo z=_wy$aiN2`l;G47N#Vhj{mg<}r4#X5D9~@)=C2Rty@zfwox)k8AQtMJ6ZF^$Rq)Aa zMmy50+wBOT|NmK4qB*!Qi^#-oWm?S9MGg!CHH@K`u|TU{10>9!H3rztHg?|J!5g{3 zVdGvBi>I7(FjysNAUKe48HAbUBstb2?-)H}E8QzfHBJn^v+-t$q_@06fvI;0LY7lF zW1n%D7SpAggivVcGiF?jQf@JIf_e|Qq)_pVc#Pq)!a{kSK$*wScE^&=0kA1`2|%4^ z350-o={uD3dZUW1B!7*4bIl@WDlP^hlv*FmQbQgG&1?*sB*(bYZmLXoc+Z^?->|RE z)5Vz~8D2(pnbl`hV!SwUE!?_^ZW(~ue&b(idt=(a)b`bn|Dm?u!3bGQzy=+CyCHGJ zGQ;KdqeNwmxjRlUXc@uObWX<8Pbv+dzW+J48aLG7xMZr%+2EAc_foq{^+z8cJ4sG054xAK$LjP*dsXuOiE{YD?waPh z7-^hg?Xb3rT2xQS4e>A17M!LTu9v-)h!>-+5SFWVj5zmxTYueRf@~-f->icF*XYQY~z!kb?1NF5vV+=)7@%4Q2rJ0QMd&!H7nb_DK-ajh%mRHQm|Ctb9nt2D;H_~AGt^%u*nkQ zV~Z3I?g;U1Sk)_Fk##+w-B52wiLVF%l=zoz@%rZcR8gR;Rum9qo5B3Bwdj>7N;&nf zlwI35U-=IpLp|WKzE^T+-y;s{0k$8&2s_}ru<&%9OO7PKW%ulx^AP%rtwkwlCO(Ae z5r6cPs#|iUCptpqzy-T&wV4J;&_MB|Mf(09ZFa6#Ockr zRA^1h;0A`=8b!@|c31*G8l8i_eTg@x2Uc*|@UMCRvA*8!-&*pfk`&bNMVQ-X@FETL z>Zg$WLTyfGfPdf^&ql){ajogD6wE)(t*RMa6Em=IRb+O(>T>G*lC;8Z1i#=A6&5sZXYFN36pb%C3N25JobO$Y0n(f(9fO9d*!|PHjdK0Qc zHJkdhiIkL~)bII#%0sw*TWkzinf#o^;9w0rnhJLrD^tvReEc0L_k2@c)6l`bc4lhEL=lRQc90DB1;OY&>c?LnPbzCUMizt>IbYV1^l|Le&!uxa{bM z>`Jv1XP*u>y3OPqssBP6_+BsR~{uN{NO ztfn@#zl~qVttck0_By*{51*y``CGc>`KbQd_|)0Ba&c43Dm_no95bj`3J8knov*jr zDnj9w0NK2u4mA6Qfg2X+@Cm2as3LR(i<+d_HVpvSj`O8>4g25Yn)?V!yTk*X9651bNFI+x{j@9w(diZ!e?=UbW7BkLpQfP_#&ocN1v z;?)OH7V&D=u}&NAL7O1wO6ZptqJ8{6sO^EVrXdPVY-1|FE!LaMLiWY#n(q5HD3ras@W^!G=G{3u<05qP zr#SrvBW{Lw!g4@(`5W8kYfgTncad_6=p%!Fs9q_hs~kD1=bzxW}rq?jrHx+ZQqsNs(JfPXQ4Y~@9cK$+L4#;-j}z`NxLB@+=@ zWf!qKWq(ljqi2Vzu5i6?w%unZaUE+KXXvC#dLV1(`w7^@i^?ONUO(0Abo^ zju@Zi=?#NQ8AkSs71$JU9ONj1|Io;<{cU{?HFs!LHvE*jkp=eJR-F=&HIC9K^bdsFe0utRr)JK)F9)Q zBZEBv`XzU!Ge|%3NI6gO9iIHx6{jPS?CQ|26E}U=vmoCid-lQ9^4wgbv*SzD-`Q3^ zRW%|(WbCKPJ5t*dp=c=pIEGymsG(fpC#K!Zwl=Dmbd(K#8zUwl*sP)F>jfy)!Atrw zy$=AT`f;P{fB@=h`<14%5-J=J`q1&j^50?3l?G4Z{Fi|_2{7=$^;xuc4!&PEkz)Gs zl~8A&*CgSFRjbin3IY@rli^Y5Gmg-DJ@GOExsqqMVvl!B{J~=?#`2@lafRtSE3C(NRbgyxVG~` zQJNTR)(mj`x5iaEx2&$r*NmN7I>r;;B30c?X;N)=-osXu z3mokAJX)sa-xYZx?Td)L>&K(-oqR-tzuoQ38L`_zx{lf^xr5SbuVSIJDhB-(mkJ{V*`6mYvl;Zw`%e*PmHT7$BT*D!ms52de|Gj zx8Zc=@P`6?$mMQfsv5<+H`d;YHb{yfzOHsl!ae5}DlOI4175hjp5E_rtY-mYztql% z_#H4NoqZ77kwunny1vq>IC3@rXan`gR2=OakPM$DXf((C+V=r5iyJ9W_+)r75p11Q z#gvO^((_cmoyvQ9;sRQm__>Y)2xyKD3q<{z0Z#pO7Mv4mLGS{F?xw{F>}!VWmy>OZ$iFT7z=4nc(e;bUy7O0?i`SMJ-|Ntd+DtDJEhVhh6F$y738D(tG1I;w z*vprWvlRUcxM4)u(pf4pOrG&|UqeIZE%ii!mqyqy{vS6+ia!=f_^VDU22KF7EK5Hg zP%r+p_0}lm(4631svcm;1!VDzA@NIyJi?&`-zRmI%qBn9Y@sC`{P^%&UyVOp9rXXW~QN{*t+lM@L2~p~rO;!^IEXCprEEB3G)1yKB zO7lUF9f|mI!T+i4&Euhb`~Pq4N{AL^4apXhWX%$hq)3XalY}((eVviAheXyvMo5;) zF58qf#!kk*kHJ`n!3<-5=g{Z6uJ7;q-v8Y9eCSQG-w#!2r8g z+!|Nw#0qY_=GmK8+!)*Q#u<=72o!+-km*=Kjz(2$ulLC>ypME~*$1|`j}JZ@9K1Gp ziR^%ACZOm4DD5`;%+*kc9moyfw+Jxo8h;C~y`21f&mgaN@sJuG@_ZcsyC+binF)#8 z6LkecxrT$Oo+)F);FaCSz{z+pA*g;0Y0Z0ETNlsJ$US7ke%$cr9VBHd{%F16Pgr%6 zA=v@BYxMWnn%{R5#%$GT=fH)t4M;EF+kpg3o}EyR1i<|;2WkK)JEQ%EcRH&%mmmihI!zs+9E{N-;jItIF@>ZnH$kV^j?xm%`RPF86pXWKa4< z2Gd&?uMWcYx~)U9+nIdi8^5KwiWhl0{YnH&N67$tW19*p%Z}p{m>q}r)Sabm)X{G0@fY zexr=f?K;~&VaBQNSKFjiHeiVx<`@1pA)ivC#{b(e5B3kjPg+)|+Eq{$xua0H={=7s zMp)G457XH(X(~eF?^k&j&s|;h-DNB<{TxT!h_W`(Nvl&-Wyj(YMkinDEmr{8Ug=K4 z{Yn7a&rWjx3)|2CtLOT{-=1s2lK2a6VFJj|9<5DRzBXcvap3Vm(=$LTNo+1PsLnJ!h~IqV9~;=))RYM8QO17Lgg+ZCfc z0JaYTu)Smboukmrx<`J8{+=XGHfl~rtyEx+SlRYD+ft>n&zkElRMAuEttXFtuBVH_ z?UUa!Iw5@y-_TuVG!UQG zoYPX>tUfPpx2*n;OCjl8C)fDkpxcP^Kgvt{@1nVMe}4o0yuZS1uK?{s{_6pA!RU`l zNf(qm+#h@&2OiWp;oP)>vLIl|M?>|Cw-AQvRcjKZaK#_$qG0fn(f#bs%^S zTu*C*bQBkt>E%&3*;GN|EY?&&rps%dyNZ@_%@3_SW1e{)FT4&qlBjelF0=+#zBBG} z+Gm5`+-LLQWPsh)wGqj897T>IPZ|%@>r>oIo3ns=9kC!680{H1e^r4LBF%pD)T@-x z&b0P-Y4p`{DHZNu+i(bpzq6IVjr1#?i?_Tj+?l@X9>-|MOWg4kN9#y4#QQK;FIghT zzAR}kO+=7@^YwRe6z*0It!cgRRF?%} z+yZ=>&CYAgLiRkA%=!__A9!iHCq7p9%&c_Tj7;rZn|T%__r@yL;*>+Ig{b9^TvJ|( zr;b`47wR1ir>FX@L4jxb!`t_7(Ra>*5{;nf?P}~|jtuGPz2U9|W-paK{AA|pDemJiJ5inIrsye!I?C zR9eSQvs|Ih3kXE%^%S)0LsG|h$>BE=-tD|`|4g*_;!y>%UaP?_=9hcmXzQ(`9^lyF zLL+BA1G4Nw3LXm?PMWb$xOZOcx{p~Ts_!JJqxez1#LGvg2RCe5e&2Xs4nJGEVcfF* z6?EHz8|ZKxY8_Uie&cE|-0qi7`Tz#MY>8{z#PryS<5IkRtd(v8f%S3s;Nz#P2Z5!# ziZ-#zQVxwbQ%7NH^S51glz7QRx%1(jmpNBdZZpA(1fO4O0(XQOk@LUSutyCDqn{wS zwpOVoBeNSKTj zNaK#*g&?Wucm|wN#p6fi6Q#(jo6Z0SE?f2@aHvnogX26mW-ThszJMl=PtROtek^Ts zQlrGq_+of|J_1$JX@8=*vBj9o!*umsI{>&u;mVT__WW@ONpT@eN&z7zm?1UGsS=y z`W>mHP)Azp0>Y71S!MAduAgJ_ozM-7i-tPleD~j3DQtc>74lltnk2Z4NG)A6Nm|o4 z&qlbNW;;4Il^SAU4OQRmz-s0 z8f?m(XwMnUwv=g2(uaZxc3bU?oS$S(it)SR%+VI5-NrQ zCXw#@(Qbzk6#M?2#(#Vkrv|Gv$u=o+R{!Vkvx3$K8AVW9Mv?2ok?-welFvG{Yq)fp{n3N4IxuT~{H7AP8AASF$tvD`t z$bWqLCIZ}H5nsHvRr}NXDnW99%3v-T-cB6cv{pf>tiB(=mOxmq%Zrn#<)3eQ*cUg) z<9c=3odHyQ%&P*dfofR|)XUz(Lw__rJc=qQ<&pJ+aHsYAL7Y}jwAR(@--^JNa{JIt zlMSak-tHazVdMST=<=`z{Cwp7nnK*$~L3azIo_9kQ-jVHB__ef}jGMRW#acVfB*P7g#1|wQX5%gb&?nvajie zM)too%;tfL-7p3wf-s-m`xRJcGoO;_7@rSK!|c?m_bf3{%F0fv%{Hw;FnOVM@T`Lp z!7U+aR&m$Q@wvW4%wnrBrv>|NuV3!&3lo*kSyBxm`o#*DoV@W%iU{Q<^Ff+~x#N}B zG~}Uy_19+K@UX_o9*2I!bAs|s)aiUB)N@2z?5WR@%X)P16SwLQUZ z#Y#!%0olTbzmy3NZk=nTp;NR_W0gI~#iR!oKm9UHr@1A<6}LLP=G9%e0L2vT3z^eR zzC4U23AG}nnU+X_YS)V8YKu%8l|UHlTP2;4?H@=POt2&m+Ieh?hg|fskBx5kD)=uu zRXVAD94B_bPLtJW?6kCzPO;(F(-Z4*c}%~}FSnoQe3eFzl&g6){`j}ox&*`Ti`pm1 z-J#VtIC^iKeI|-(DZ5;9CH0xTu7B(l@m@{M{oL)bdJZt8vZrj;*(lCf_1K#dRH146 z((_2jeT*s3$laK4qny2LWEKt>56&IwRt(>9)mcMadDr^ah-_Z-m&5p*g>vN%<>f zmOsq(l5yu{kb5TpPn8xTv)H(5dmnJ6_)ytt%PrXAcO8Ra`9ltGEvddA{}iE7qRej~No1H9l%~@%Gz0zhPG|D3I>Gb;19~&^=_aHT=X)ksSCnYe2x9g^%du(mtlW z?en%eQp~u#)faE}0-2I}QcNeK&83<&xS~T)&`i6duDbj5}tc1^xBgBoS=>%2H zB`$KjwSRbYju>&ssOLjz9JVb&kVoUV9jJ8oSs&VAzNAcTHrm_g!~&;5N58lM^VoJ| zmhsuc>}lN{8)ODx!%$|pwDF*XzNu!{o)~4Mn1xR}_u%n(syih7!EkMjbGThLAFDvh zqT%0b4CD_`o1tt?xrL*~2pDqrV+}Xz5nrd#{y=rS)lo7$VoNuN`tgbLo6 zjJI~`c~8`HnF?xEFzh9PJ=~)kkOAGHiT2?0_GlY#;dOqeI7rjkKLk;@zCFIb2A&TL zSf2~CF#1-eHe)^xdjZ+b_mZpZoZfn|F>%rk&@MN85Vm4p2Uc|6rb&OZV3%uz)4d+; zIs>Y-dY0JcizM!PtuN;_{K-@tUt0hy<;j-d z=Yhkovr9b>O?Z%&?~Zl9nMnp}rFB^tiw3Bc0E=q4OO^5oi#Ip8Z)>Ey`V zIg7c{Q8y3VgqXWBxCkQ^wNFw@IU|Ex3g34+*iDRx)0E43GCu@KWknc`a$i^pt!VdDkH#<2st3)twBn*wKp7)+!|GXyHt-P6bAYHbNxTAl`fqWoc?ggaF zUk;?pN}KB}^(zj{jW{PBT#&Y9bs zYSaEn4CIzX>}0+xv6j;?evoZSqBF;R=1zU!F9jW!ipF0g;Um7YH;tni0qOEby+m8B zmrOUqv{h_bHE6K3x*{I_Q4+`|0@d*qo4jeO50ylhv11rJ zx3I2JBR1uI8d|p$IUdKyeYb00(WjmR_i%ydu=HIx$% z9ho<6t#tXw?RT|@>5O;bbKu0idds=U{pD2o zTn%*-4D}n1pDTxT?G>~kH)$*mcxIRmJ*h*v7bg9?!?w>kCP>l!qoVet-tkK$>t zR2v7t(zo{8D;62BEkL=9#T3$%%O$8>0-9p5!;L_J0kFk!<}8(_T<*GPS@X=V&eT?aI@uh{Ob@4j@9)@zGLD>d7t2`^|Tbr0$D4N!pHacc!a)50B z2~aH;pV$Y7NPaCgZmwI^sXNFnKa!g*fLPtU9bh%ZgG2~oOU6r z{H$3{*KCf10nsuYb&cJ69$=G@e~#tjF!wG#Pdf(>c=5@gG4cxXWRQ+ORkmZ0?BKBb z;x8h-SiW-y-9AJaOUn=G2W&Aceh<9xJNdLj8-%1_;OW#&6R7ISrobvsv#b_nv-M!H z+-u|~4~Im^pYFiQp{F~GYwY?}XppruV>+x*$#Ca)yq)45>e7$hcVkQFUo?hIUWx`L z7Pwm7tt)_J`N+pXW*apwF1O6cE5(|NeTGRL>^?|r{7(Q>b}N-?M)AA{tF_N#kA|oI zWt9&%29)1{A+RKHGedh-z295#3QA&crF@#osz&7qVH7+akZu8*&z2YsYW5s4njt+y z$-%J@3BK=_dp!yeU^abGJa`+jp_u~>05CK-5Xy<6|N9_JNIbT3Ft5! z?iTGUIG_T{G@8420N&_K=nww!pGmL#OzA&gpt40zBZADgtCUk=TTGFWG-Tip37Dhu zQSEhC(S^E-a5hHTXJY_ZYuOWQcp#Zw6+S}&|IK?yI}ZHi@5?roY?SiJy)93Lz0|0k z@g?b9#emz9Y1+`^>AsS6!Qb@~ey*>{jPwT>0dXOzPKth~w&-nQ(=6PBV;=sPCi_m3 zPMeF&XSwYr1^WnbjNPWA6VB08Q+cw@almtVzW8*5_zW9M!j=qw=3Zp3lVd}dSB1=H z{>DI5{Ks!Zb6aDu4RBJXiW#6@9xt{YuG@E?ye}BUPh7MaeowW*|C*;STZGe?^DjZ@fKFFS}g?)XSvPQ+^fs zQ|)W-L>v87)uEmzHDSh+|6Cby0rGU)ZiT*C|0wg@<&)pdP9GfwT`$0}nLFhF+In|Z zf(J9l@!q{t%m42?#+~iE)5LZ(rwpz7*B$r0Ck;pGO!EGKasqSP|49y+Foqj#;Lz5H z3UIi)%R`hcEjeU)U%YHW6EA~K4zBB0l>A`(>w!6?#^Dv8?26WN&5Cg%T<={=;3L;l zHPX2OlWw%@hEV&9rco~O_9<%{NJVg=#Is|2uYwh1mT!Hq&S%?all}&Bmyufem=3-&UrqJ|*W=)LCq^DSxmWL6g*E(Q{)Jh`D&f zpFr&!PI?W2$u^Euu+i&&Cad`%rCkCPb7(3Xr~OBiKbwpFa6hX#ufp(Pd`(EVf(& z0xfSPb$L$M!cx~h2aY;@O{aPf=8o&U&jvuCpLlV#p!_$l8i^4_5)0kiI4GLlq(jM%nU`?$!0@|`0N2KKX+S2E*nO>E3%W8E@?I#M&y?x#eH_;R) z|C!7YQe0kq-SKR(_}zNk#ouc|XRp{k`~p$P{LG2YiCf9vt|mp)SqTH#wL5upTeFzn zg0jXwLh7gS`NTGEvEeh#L$%oAG2aJUV^5%fT#gv)LLQdn?js0y#@k7M!t{GiG$u!> zjp>j5GNX8-ky5}uYn4m9G)vh7a5TIt;Zmh+g_G*IZ|J0vd`kBRZy2k@dj-LO@e8wJ zeN$iM{E!!4u`sfh#YORZDX@ZVko`Kmj}dd@UppCfryBv*QT6%)C5YnUBU+%fqlJF? z@-B+L*T`W-L>ZL2TedM?Z7Z@jjkhofa@4Ig> zBy?}af4PYFIz5lm$D%cHmsp9mpnKQgvCU4O%wJTxSyyV<%@zh3oGuADe$u!&{g2Wl z*P0<8wif|j9l+TcWZrAVf2lSo2GWMwPz{AbY#F0v{litQo#7zV-rlWGxF*lbC9&wL zceYwetYQ>QJup$NEB64*KXD77{0vh+ErYb-k6gPT!DcRmI6Xx^a#Y*5**INtlO|qUW_|V+_^ip>pk@6$``XUlyK{krS{G% zdG7f3W>>%L-6<=~^ip+03^*M)=cXfgxnBzoscS#Aw3NyUcp7_^6|k5j;GVn96n~bo z@ak^1N!VAlYVk;0_a~)#4-~Y=PMt;O_ikRVxp_2LPVS{5Yvc@9jEFF4O2P!p^z^p_4L*PQjW0QfYIvC}K*&QlzVxFg#07381 z6*?5^_Ak+GRy+q7e(->vG+pC2O&B~vx<#}(rB0=SFnYL)gUdlV5%#eV%> z3*Ee(^J@LtgB%4VK6Pi@bkErhW6q6hLzkQ*U+|ljw|Xi0`1z&67*cn$9F3Pm+TpLc zpSVTcxcP zWKJ3yf3T$9A1=r3Ok|UJ`x#Qif`I&-vDjGkA?>;!#Vnj+}`V zcQ=`;@g=;ng2vMYB~iKCY;^t~dqbddJY<&dwe(*4YF(Mdzo-nn2<+FoE+xp$={dtq zl~>`PQwT1O?&4*+6EiW-3K}w!A4okUsX~HyFHbYnU8}%4*c5xoI#hb!^**z^wf2tF z%f5>diH<0cXqSUO_v>50gklZBb-X;;_s1W8DDr7dkc8%V?ggn{4(EsQ#yZ*j;FSxE zXG4+E^TtC?nPOtgb~BXt0d@}yuWkpRNWUM%V)f#q9#nk;!r4LmD$n58L(uEiKV>#; z#6Z1!2#F}*tDJe&N)XUgK3&H8Y%<9*P2$$deVGx_Vei))m@=)--CQ zc!Unl1xNt~ot4ZGuPSQwK=%;S{v}6by zkM8ae%F#yd($&OilRI_eB6X_PY049GuBPPhItx~*pt;vAu!sw9@(`c5EiKWt zVr4ylF1@rc44IKxIa0bC?}ybR`q1)PFdhp_X^Z^qJ7`fLtp(Q}U*Y+1VeOOCggB3u zXk6Ya<7h=*&}LL_^up)`3K6ggx1Pl#z{dv~o7yJeWzv`9RI}9jZ|FcWpT0UCoYV-U z^uBcP4=LLyt_u1@9BjG<4@z8$*;ZTq6giw6<*S&JbxCbh_e91E5MVVTyFJs;v(M=} zFPrrQJxX+IBfM;w&oAE!*}E8Q>GSYG>7%o*7g)>kkRwXx@wb*lx<3}2=@pJU6JZ02 z%MM{24A*p_$PZHtzkVu?)%$@%H0g74ck@^S%?AvAF7NeLWJ&@#BXHb{^lr)Idy899 zj*0_*->J(H*`YO?2+M4Mzds(tS+Wk>dFsdAitv+fN|{oOi|ThW0LMx1o~HYGiS%tQ zN?Y?d#!Fh#{&pUNtP^+XFIoAxOuZfmgNCGMC1j^8rIdjKxlp-Cad?>r-nOn<1O)&kP`JW52zl=~w~ zJH9Btu4yWfQeycvSSp;CL49rFEGC+)u;w(Ui~pI3W1oRgYQ!rs%uMGJ8y$urc~IxCjT@VEsJ zhR>y?Acy4TYd%>hJ#s+axV7xI`#M)QO>BlVs=97}64kAgYf?6~nI(E}sQ;?1-JMCx zI}3to-EHV^IZ&(vP~dQfUG+Xs@k-R5BHg}(FIMSm+HI)4OpRCgo943CDwQff9RA6E za5D>^6!`@e>2a#}0}ZcF+vgV?qU&fgP=~d%I51W$guJ(QetA1yl9uLjalk-Q`MkBc z+|3ljPnWvWYq^JLa6NT>?GZXkJ%86oZ4#iqpI+79t)xcJA+dgFrTnxozcE*V$e|pq zxQ9+nF7|*CkErJmCGo?JqE@;7b|Y7#zJ-PJ-AMO9h@3vhkOeEn(DXi6E9$j}l@5eD z%As>i$EUEh@wJb)-#Lmgaf*g-9Y*pS_b;b7Su0pZm!09Wmt#r345|pvJ<|)5mg#2(=|IiP5Bq zmQd_-%+pHixcpP-X#_YGd2%md89E|HOdf!2S*zlI3R!D~V7~tOWV`{nm4G%x*MxNT za$hTfeVx;pexGL;wWK=Twz#$lF71>^y}CIR{#3lQ%zz`@MM-Mee)I^PtfXnjh668C z8xYw0`9kmyN0FfQ0ryrn4St*7r(eq*!L~HB;HEQyGKDvZq)xk%Cl+Q55WmDR`U)>Z z%Q8!Ecl#Lb7>^ErO{;Mgc!&?LnZMXA<`kPf{1_!r3QYNH?74L_2W1E48o{apH{-|? zgvH2#(ymRmceT69n=xIT8pdc><0jD-ht#P2&A6|nY`G?{?K)#RvYSR<>G=RYu^S!0 zy#EOe>-`$S;MK%Fml3ln7xge3KA4dVWxREtqnh-+PM~{DyBp-hG?-Nhe@!~yAye*# zH|x-^sX3Ax2_cT%7t@i`{qP5WfBL$uE{lGskEm&Ta<_J=l89T(bbdV{wR|*?kF!J1A^E2i^!!|Y^W?OPzR6BN^l%-5F z@mkmW3Zyf6j>cG%aNr4W(bt0?DJzl~c=Cv?^HC@Msi8|(?`wQafWN*F&)ITGMk;Kb zp30LJt}W3J6U>Fg&fgV0pW2Spgg2g!mfE*W^}2$O9zu510UZXh=QQog}Aj zZc)>s*itT#V5E8YAt7l|h^u5s-0s)!Z1ubop&o`90pYQv%gKwEmSP}Iat%g(4<<$D zn<{4HSgvcep7nj~Bd(*<(rfn(Y+a?ykqpx9Q9^HWw!*qQOVipZ23_P&MXgiU8trV4 z6q-I*(;?ncmH|ikiK1$QmEzS%o6|7gu9neA~-)1w35Gbvb&KpBajFO&$y-&Z=8YhtUCmL2~aUEV*- zpSc~0&%y0rlNRF0b~al;7EBOvYRaw?FJU#9g)3_7iVyy=7)MmbkQPW?WxYhP3u}Sa zFU%08IUu3T)$tajkAmGR&<{m#_}8-aGw$aW3ZpV*0rWlycBpkSSRCd6f)+YjG3rzq zA?qois1|ZKG125%1_;!_21NNv2F%GUANlFlVqKTNv+C1zm2QG z{B}zsbe~^<{};I;RsH39g71)7Bpi*J+Yf_T)dsczSN!02rO&64GBjxK?2-xD1D)+; z)HqPP;cjpIOO6OQ3j9l@2&f3hkCSear&ol*TGji)L?8@?yS|;Cr%v1aaA))Q^Mfeg zR9cj8g~mM#q1xYbOoGYI%|ue&`lY%jJrD8QQp{VcGJl)l?*Yt4ttiaq{BW_qfduzE z7xB1hjC(vE7xZ z{(pTET;LiT9Ec&-4R2GcuHK@{rVGVP{3vdPG?i-R@~72usg9WyI$wV?gLvm1L^=PC zyB)A6g(vc0Xjw4kU5bbL!{2<~Io3oZ^DX8}ZKpc&%}%rXz3pE1I(g>c9ee*y@@@0x z-Zv9a$mQ@4FC`0=qKO=uNhW*~$$Nr#7SCv^^l()~P6cYSf~ zofZ#=k3s4f7Z2S=s0Zg^I)9+siOO+CV`~@jIbt4((uUXW4zp`lv>@4`oq{6Vm4Sofq zqg%mJH|h=Mvj^_)Lc(z*d9y4!c+Ds-}nU^l)&ebGZqzzvQ{M zqMC&xyjAkbo?9uUOo9$gw3)ofQl`Amdz&U3YU>~S=21%Uo+86KtbB5%0J1h+lbxs7 zu9ibjYMx%(@>CL30d+pWKb5q85(agHT2yPK=(~FV@Y~At^Geln9)?doPI6lEoB2`5 znO&mOzZ}P-?ITe86xvMoT38D}#_90*n$4}yHE!SrRMAFAoui*6ej(+>gz32LWgNMf(nP~^S7e_6crJ$i z0MGFq;JI^7{R01i=d##svhJoacgWN5oJI2gGoFK&hH&iTxk6tqCmNocjQ$Ti$E))K zHWsA*M7$gJ9Z=WZmEx_Xn7^>e@GbW`gfv_G3T$2m^rW-J7u^arF^WR^z}B02mas0=i6`w#JDK z-8SIfHYoSLSV@1RJ4^M7Z3sf`G=FF4M0ubWL#ga*?LT;1V|dZKeC+f+?x+TXp-0O*-&FLQn2=d0u zOuy%+WiN8@#3iIc$qc{w;QFajg0?3ORF#Evs!^ZZ=^^XOqOIus8#1kETr-CLNX_19 zo)oO&E{yf?!cp7oSE2hDFLF~@c?VB;Bdzh6mFwBD`jg%%cHw$)-{ZROA#&6ePL*yS zb%6d^J5QpP(17P~L93%zO6=C_&3L=VX$;Z}WM{)3iPNy6<9?U2YR1NNp<6D$BswuPcZ=WZvGs%tT#QQH1+PK zh4F02iv-5#XR?Q)EQIPCT=5;RqlVhd7?H(xPOYqER(Ep!>TXRz&O7-aeuXzHIaGhO_{Lj+*JULyo4HpYV^H~Xf9z1D1)-&G% zRMSz`D6BP*L}8B-fCjv+8DHA=n0A@LupTnzD>x0>WIUmCZl)cXZTe6Zd#oGfd3Shh z_d(t3a)1eAJX%5aR~5%Pw5o~tB~<>BC9{qnz1VcPb#+nd*}S!%l4f2uEzSMJjKxyr zUwY8|gF&68$bX2^MxN6R^)%&dT%>=Uo!|-odj6`JarP4L$+Ian_nCB};KefZJ}Cy_ zF)`ocGR{3Fin8214cY*?)_dU^2w}o>=F%H!?z=WIk2)ZJKc50#xCR;$^4xB5MIB=o2O4c!6Z8KtOJ$LpQK zSXRvVB4V^L%qLHm`jvsW@Cm`8Ob*(DMeg2Xj+vupgT96%EQV{dw%rMkco)~%`O2pq z>w~k+9o9OYgycHA(%hSpIbM%+C4oAi*s|u{mCncdyd%D2mAV}yzfi44bCDg@5Ay5L z1Hc1&6GF+@CV#wa5AOgn_Qc<*UmlPNc8N52NU_M;L@YJNFt2PozZ>1ei78wA0e723 zfLHqGu8ONrG}U6cymA!zt-k`4&mWMw`fJadzHANtOb|G0urK7d28yO#yl8>5D~2M6 zn$v0IaPgn=7a+-}gN9Ym9DJ|eNv87$(*dwh`E5wmFWCjw+d99zr=v6I=xUr!b%P?w z(!YZZm%VLAbDO(}0jEBE0JZc|G_-GfeG(cf%GlcQY{j6pqc(D7cZZxp?ps>m^nC^7 z(c2}M(0C2TWv)VD+r};Y@1b3=oE^PwS(B*^kHH#c5a*ZzBGar|a45EMf5NcA=wRWNJTFXu68^5KlX^ ztW2MjW2HVinXDJS@(<;M(I_9`zbKz@oZkg~dN-l9z8*iVTLmRQ8fzk|sjSA+_SZmU zCLpV;S8RnP+dDHcVI~&LLSYYfQCzUAKy5^Sb3h>S&lLBUUf7E`Y^H9i?%L8Fi`DuF zook_A2?Yrbfe^MSCqgr9@i{epO1jbR8@R z*4Uj&2z*INFi>}e7@tyg!3VyK>Jx9hnYFp9I%4n=GLrvClJ4gqtqDjBH!Tnrgug|6 z{O+U=-vBx;gN+4MdBN;xnOdoatlBV8mv{s_-|avV$-s!M{Wv=gI@^e(FvRzNastKS zd~5WxSv_hWG{|=<`!No@&Su^FBdmWE}<3e?Yo$1f2HyN$YpDrrA zrbd7e-%z%d^ibA6S*N`HGEC?F1~qQRS>$Ug{+sy`511bV**W`hHP`IohwQ#zM0dTv;1J4Z#KtuJ^Frq9e4=DGczg46}kc?$cqMN!X7KJ>#JGB z3G!<@)YJem@UpL8Z2j>&C8c7`YreGr0V$<;aicS?_K204ohh4w6wsbt8A{1r&J3jW z4OG6Y0z$c?5`UWVSsUv8=G=LCxdCK|l@j!(}$I~5I5=<06lo(Xb%Rj4w1Jt+e3Jn-J0IzPPK;(hN{(f^R-728cL*olLxspDcdS0Wva*EBi3lv)Y-yq$*0-xb%S z{vdakUTs+;0Oe-<{FPMZ*g_=^HM=&QMTQ*HuLnuZ|FFG+Kl;SVEdF`qbV}XL8H<$V z%?jgOAgNh${b@JYrNQ_}fjr-IB4>BfZHrXLW zrZH4C4(T3Blp0KIMWA&1CQlPQ*Ew-7z;tS$RVpLZ_ljWe zg0Dg!!2$rk7j!*on%++_0{8n;*?RL&rox{w)mDCMWK*}&H#=^*OL(x9@YKQgADV}5 z`Nn()pn3f{1{)C5c5EKjtN~{ed|^oW$ws!*T|g9D_~8FF%}eTbKHeG=#oy7a1+YdU zVLiMKSeHzFEl9PurUm()4f?iPkT)+TLqWP{mApY;Z2Xvi%HO?d-iY~!%k zLA`a{P4Q)%%uvq9kVL~t)vDjq`QgKv+a;U#zBuMjzZsGb+bc?mbH@x>jlq(e^sIey;=@5HtU5|Z zMMw1IFjKTR`ti}TriimzcblP9SH-HX{^+3EQ~BL@1{((GOg`z7(U(iF+)z@rd2sZ1qBKuo!RwUYFjnaw#T#8Ahb z0if4YDQ+quhiD0_AvKv6Iyj5~DaxW?Hp=*Cc<2%T@yn-PS~;6X)K<%aO8}%tj~K6D zro#xNoh)CjUs0j$$R==V)G6F@L?$~8z0es<{*RU=;FbSNTi0$uuPjd4{q;KBi#>G<(15Hzo^_w5l+yW>tKWS= zBRdN;`{3USpDMyx+W(1QtA1pGrD-mpTSs3aMmP#g znqs=*-z|EHnhcGE|MhHjLPS)fA68<8<$GIXy%Odw)aaI`r+-;K{3-EesDwu9*Y@VhO->;*%a|Wgp@B z`yD6;>DaP;x{=A?{~6(YK$ro;ivyfFG4-F19l+=Oe|n*vy0b&Id;5K?{~V!_HY!bZ LZM6c`=K=o*t9ODR literal 0 HcmV?d00001 diff --git a/Project2-Stream-Compaction/img/bar.png b/Project2-Stream-Compaction/img/bar.png new file mode 100644 index 0000000000000000000000000000000000000000..f3f63f45a39372ed748f67659d91a0d9e4d1f65c GIT binary patch literal 18280 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 literal 0 HcmV?d00001 diff --git a/Project2-Stream-Compaction/img/plot.png b/Project2-Stream-Compaction/img/plot.png new file mode 100644 index 0000000000000000000000000000000000000000..795936354c931a2ed75b029ffd7955043dba8acc GIT binary patch literal 37692 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 G@BTkHi=4Lr literal 0 HcmV?d00001 From 00e41d03dcb5c3cacbf5296cfc8cb42dc1bd8dd3 Mon Sep 17 00:00:00 2001 From: WaikeiChan Date: Thu, 26 Sep 2019 00:00:06 -0400 Subject: [PATCH 3/4] projetc 2 --- Project2-Character-Recognition/CMakeLists.txt | 2 + Project2-Character-Recognition/README.md | 144 ++++++++- .../character_recognition/CMakeLists.txt | 2 +- .../character_recognition/mlp.cu | 291 +++++++++++++++-- .../character_recognition/mlp.h | 43 ++- Project2-Character-Recognition/img/acc.png | Bin 0 -> 18890 bytes Project2-Character-Recognition/img/error.png | Bin 0 -> 15456 bytes Project2-Character-Recognition/img/xor.png | Bin 0 -> 16055 bytes Project2-Character-Recognition/src/main.cpp | 293 +++++++++--------- 9 files changed, 604 insertions(+), 171 deletions(-) create mode 100644 Project2-Character-Recognition/img/acc.png create mode 100644 Project2-Character-Recognition/img/error.png create mode 100644 Project2-Character-Recognition/img/xor.png diff --git a/Project2-Character-Recognition/CMakeLists.txt b/Project2-Character-Recognition/CMakeLists.txt index 09e9198..1caf239 100644 --- a/Project2-Character-Recognition/CMakeLists.txt +++ b/Project2-Character-Recognition/CMakeLists.txt @@ -22,6 +22,7 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") endif() include_directories(.) +link_directories(${CUDA_TOOLKIT_ROOT_DIR}/lib/x64) add_subdirectory(character_recognition) cuda_add_executable(${CMAKE_PROJECT_NAME} @@ -32,4 +33,5 @@ cuda_add_executable(${CMAKE_PROJECT_NAME} target_link_libraries(${CMAKE_PROJECT_NAME} character_recognition ${CORELIBS} + cublas ) diff --git a/Project2-Character-Recognition/README.md b/Project2-Character-Recognition/README.md index 4503fac..924de17 100644 --- a/Project2-Character-Recognition/README.md +++ b/Project2-Character-Recognition/README.md @@ -1,14 +1,144 @@ -CUDA Character Recognition +# Project 2-2 CUDA Character Recognition ====================== **University of Pennsylvania, CIS 565: GPU Programming and Architecture, Project 2** -* (TODO) YOUR NAME HERE - * (TODO) [LinkedIn](), [personal website](), [twitter](), etc. -* Tested on: (TODO) Windows 22, i7-2222 @ 2.22GHz 22GB, GTX 222 222MB (Moore 2222 Lab) +* Weiqi Chen + * [LinkedIn](https://www.linkedin.com/in/weiqi-ricky-chen-2b04b2ab/) +* Tested on: Windows 10, i7-8750H @ 2.20GHz 2.21GHz, 16GB, GTX 1050 2GB -### (TODO: Your README) +## Project goal +This project aims to build a Multiple Layer Perceptron (MLP) using CUDA. In my case, a 3-layer MLP is implemented and tested on two different datasets. -Include analysis, etc. (Remember, this is public, so don't put -anything here that you don't want to share with the world.) +The MLP consists of one input layer, one hidden layer and one output layer. The number of hidden neurons in the hidden layer can be specified by user when constructing. +### XOR Example Test +To make sure the implementation is correct, a simple test to train the MLP for XOR operation is performed first. Parameters include: + +* Input neurons: 2 +* Hidden neurons: 2 +* Output neurons: 1 +* Learning Rate (lambda): 0.01 +* Initial weights from input layer to hidden layer : w11 = 10.1, w12 = 0.9, w21 = 20, w22 = 0.87 +* Initial weights from hidden layer to output layer: w1 = 41, w2 = -54 + +The plot below shows the total squared error vs number of epochs. + +![](img/xor.png) + +Console Output + +``` +--- XOR Example --- +epoch: 0 | error: 0.00286369 +epoch: 10 | error: 0.00229358 +epoch: 20 | error: 0.00190236 +epoch: 30 | error: 0.00162444 +epoch: 40 | error: 0.00142166 +epoch: 50 | error: 0.00127057 +epoch: 60 | error: 0.0011561 +epoch: 70 | error: 0.00106817 +epoch: 80 | error: 0.000999872 +epoch: 90 | error: 0.000946314 +epoch: 100 | error: 0.000903958 +epoch: 110 | error: 0.000870197 +epoch: 120 | error: 0.000843124 +epoch: 130 | error: 0.000821268 +epoch: 140 | error: 0.000803517 +``` + + +### Character Recognition +Parameters: +* Input neurons: 10201 +* Hidden neurons: 256 +* Output neurons: 52 +* Learning Rate (lambda): 0.01 +* Initial weights: sampled from a uniform distribution from -1 to 1 randomly + +The dataset has 52 images of size 101x101. Each image is a letter from the alphabet, either capitalized or not. Therefore our input is a 1x10201 array expanding the image matrix. The corresponding label is a 1x52 one-hot array. + +The plot below shows the total squared error vs number of epochs. + +![](img/error.png) + +The plot below shows the accuracy vs number of epochs. + +![](img/acc.png) + +Console Output + +``` +--- Character Recognition --- +epoch: 0 | error: 0.179246 | accuracy: 90.3846% +epoch: 10 | error: 0.0394659 | accuracy: 100% +epoch: 20 | error: 0.018194 | accuracy: 100% +epoch: 30 | error: 0.00813415 | accuracy: 100% +epoch: 40 | error: 0.00660377 | accuracy: 100% +epoch: 50 | error: 0.00379195 | accuracy: 100% +epoch: 60 | error: 0.00267373 | accuracy: 100% +epoch: 70 | error: 0.00241532 | accuracy: 100% +epoch: 80 | error: 0.00199531 | accuracy: 100% +epoch: 90 | error: 0.00165342 | accuracy: 100% +epoch: 100 | error: 0.00178789 | accuracy: 100% +epoch: 110 | error: 0.000856958 | accuracy: 100% +epoch: 120 | error: 0.00144631 | accuracy: 100% +epoch: 130 | error: 0.000920435 | accuracy: 100% +epoch: 140 | error: 0.000663891 | accuracy: 100% +--- +Target:1, Predicted:1 +Target:2, Predicted:2 +Target:3, Predicted:3 +Target:4, Predicted:4 +Target:5, Predicted:5 +Target:6, Predicted:6 +Target:7, Predicted:7 +Target:8, Predicted:8 +Target:9, Predicted:9 +Target:10, Predicted:10 +Target:11, Predicted:11 +Target:12, Predicted:12 +Target:13, Predicted:13 +Target:14, Predicted:14 +Target:15, Predicted:15 +Target:16, Predicted:16 +Target:17, Predicted:17 +Target:18, Predicted:18 +Target:19, Predicted:19 +Target:20, Predicted:20 +Target:21, Predicted:21 +Target:22, Predicted:22 +Target:23, Predicted:23 +Target:24, Predicted:24 +Target:25, Predicted:25 +Target:26, Predicted:26 +Target:27, Predicted:27 +Target:28, Predicted:28 +Target:29, Predicted:29 +Target:30, Predicted:30 +Target:31, Predicted:31 +Target:32, Predicted:32 +Target:33, Predicted:33 +Target:34, Predicted:34 +Target:35, Predicted:35 +Target:36, Predicted:36 +Target:37, Predicted:37 +Target:38, Predicted:38 +Target:39, Predicted:39 +Target:40, Predicted:40 +Target:41, Predicted:41 +Target:42, Predicted:42 +Target:43, Predicted:43 +Target:44, Predicted:44 +Target:45, Predicted:45 +Target:46, Predicted:46 +Target:47, Predicted:47 +Target:48, Predicted:48 +Target:49, Predicted:49 +Target:50, Predicted:50 +Target:51, Predicted:51 +Target:52, Predicted:52 +``` + +### Extra credit: +Matrix multiplication is implemented in place of doing 1d vector for input to output. diff --git a/Project2-Character-Recognition/character_recognition/CMakeLists.txt b/Project2-Character-Recognition/character_recognition/CMakeLists.txt index 7446175..9e834c1 100644 --- a/Project2-Character-Recognition/character_recognition/CMakeLists.txt +++ b/Project2-Character-Recognition/character_recognition/CMakeLists.txt @@ -7,5 +7,5 @@ set(SOURCE_FILES cuda_add_library(character_recognition ${SOURCE_FILES} - OPTIONS -arch=sm_20 + OPTIONS -arch=sm_61 ) diff --git a/Project2-Character-Recognition/character_recognition/mlp.cu b/Project2-Character-Recognition/character_recognition/mlp.cu index 5a3ed7f..c21f96a 100644 --- a/Project2-Character-Recognition/character_recognition/mlp.cu +++ b/Project2-Character-Recognition/character_recognition/mlp.cu @@ -2,26 +2,275 @@ #include #include "common.h" #include "mlp.h" +#include +#include +#include -namespace CharacterRecognition { - using Common::PerformanceTimer; - PerformanceTimer& timer() - { - static PerformanceTimer timer; - return timer; - } - - // TODO: __global__ - - /** - * Example of use case (follow how you did it in stream compaction) - */ - /*void scan(int n, int *odata, const int *idata) { - timer().startGpuTimer(); - // TODO - timer().endGpuTimer(); - } - */ - - // TODO: implement required elements for MLP sections 1 and 2 here + +#define blockSize 128 + +void gpu_blas_mmul(cublasHandle_t &handle, const float *A, const float *B, float *C, const int aRow, const int bRow, const int cRow) { + + const float alf = 1; + const float bet = 0; + + cublasSgemm(handle, CUBLAS_OP_N, CUBLAS_OP_N, aRow, cRow, bRow, &alf, A, aRow, B, bRow, &bet, C, aRow); } + +void gpu_blas_mtrans(cublasHandle_t &handle, const float *A, float *B, const int row, const int col) { + float alf = 1; + float bet = 0; + + cublasSgeam(handle, CUBLAS_OP_T, CUBLAS_OP_T, row, col, &alf, A, col, &bet, A, col, B, row); +} + +namespace CharacterRecognition { + using Common::PerformanceTimer; + PerformanceTimer& timer() + { + static PerformanceTimer timer; + return timer; + } + + __host__ __device__ unsigned int hash(unsigned int a) { + a = (a + 0x7ed55d16) + (a << 12); + a = (a ^ 0xc761c23c) ^ (a >> 19); + a = (a + 0x165667b1) + (a << 5); + a = (a + 0xd3a2646c) ^ (a << 9); + a = (a + 0xfd7046c5) + (a << 3); + a = (a ^ 0xb55a4f09) ^ (a >> 16); + return a; + } + + __global__ void kernRandomNumber(int n, int time, float* array) { + int index = threadIdx.x + (blockIdx.x * blockDim.x); + if (index >= n) { + return; + } + thrust::default_random_engine rng(hash((int)(index * time))); + thrust::uniform_real_distribution unitDistrib(-1, 1); + array[index] = (float)unitDistrib(rng); + } + + __global__ void kernSigmoid(int n, float *out, float *in) { + int index = threadIdx.x + (blockIdx.x * blockDim.x); + if (index >= n) { + return; + } + out[index] = 1 / (1 + exp(-in[index])); + } + + __global__ void kernSmDerivative(int n, float *out, float *in) { + int index = threadIdx.x + (blockIdx.x * blockDim.x); + if (index >= n) { + return; + } + float sigma = 1 / (1 + exp(-in[index])); + out[index] = (1 - sigma) * sigma; + } + + __global__ void kernLoss(int n, float *out, float *a, float *b) { + int index = threadIdx.x + (blockIdx.x * blockDim.x); + if (index >= n) { + return; + } + float diff = a[index] - b[index]; + out[index] = powf(diff, 2); + } + + __global__ void kernUpdate(int n, float *weights, float *gradients, float lambda) { + int index = threadIdx.x + (blockIdx.x * blockDim.x); + if (index >= n) { + return; + } + weights[index] -= gradients[index] * lambda; + } + + __global__ void kernSubtract(int n, float *out, float *a, float *b) { + int index = threadIdx.x + (blockIdx.x * blockDim.x); + if (index >= n) { + return; + } + out[index] = a[index] - b[index]; + } + + __global__ void kernDotProd(int n, float *out, float *a, float *b) { + int index = threadIdx.x + (blockIdx.x * blockDim.x); + if (index >= n) { + return; + } + out[index] = a[index] * b[index]; + } + + + mlp::mlp(int input, int hidden, int output) { + input_size = input; + hidden_size = hidden; + output_size = output; + + cudaMalloc((void**)&wkj, input_size * hidden_size * sizeof(float)); + cudaMalloc((void**)&wji, hidden_size * output_size * sizeof(float)); + cudaMalloc((void**)&gwkj, input_size * hidden_size * sizeof(float)); + cudaMalloc((void**)&gwji, hidden_size * output_size * sizeof(float)); + + cublasCreate(&handle); + } + + mlp::~mlp() { + cudaFree(wkj); + cudaFree(wji); + cudaFree(gwkj); + cudaFree(gwji); + + cublasDestroy(handle); + } + + void mlp::initRandom() { + // TODO: initialize random weights + int n1 = input_size * hidden_size; + int fullBlockPerGrid1 = (n1 + blockSize - 1) / blockSize; + kernRandomNumber << > > (n1, 1, wji); + + int n2 = hidden_size * output_size; + int fullBlockPerGrid2 = (n2 + blockSize - 1) / blockSize; + kernRandomNumber << > > (n2, 1, wkj); + } + + void mlp::initWeights(float *xwkj, float *xwji) { + cudaMemcpy(wkj, xwkj, input_size * hidden_size * sizeof(float), cudaMemcpyHostToDevice); + cudaMemcpy(wji, xwji, hidden_size * output_size * sizeof(float), cudaMemcpyHostToDevice); + } + + + void mlp::train(float *x_train, float *y_train, int n, int epoch) { + num = n; + int n1 = n * input_size; + int n2 = n * hidden_size; + int n3 = n * output_size; + + cudaMalloc((void**)&dev_x, n1 * sizeof(float)); + cudaMalloc((void**)&dev_target, n3 * sizeof(float)); + cudaMemcpy(dev_x, x_train, n1 * sizeof(float), cudaMemcpyHostToDevice); + cudaMemcpy(dev_target, y_train, n3 * sizeof(float), cudaMemcpyHostToDevice); + + cudaMalloc((void**)&dev_hidden, n2 * sizeof(float)); + cudaMalloc((void**)&dev_hidden_sm, n2 * sizeof(float)); + cudaMalloc((void**)&dev_y, n3 * sizeof(float)); + cudaMalloc((void**)&dev_y_sm, n3 * sizeof(float)); + + for (int i = 0; i < epoch; i++) { + forward(); + backProp(); + loss(); + update(); + } + + cudaFree(dev_x); + cudaFree(dev_target); + cudaFree(dev_hidden); + cudaFree(dev_hidden_sm); + cudaFree(dev_y); + cudaFree(dev_y_sm); + } + + void mlp::predict(float *x, float *y, int n) { + num = n; + cudaMalloc((void**)&dev_x, n * input_size * sizeof(float)); + cudaMalloc((void**)&dev_hidden, n * hidden_size * sizeof(float)); + cudaMalloc((void**)&dev_hidden_sm, n * hidden_size * sizeof(float)); + cudaMalloc((void**)&dev_y, n * output_size * sizeof(float)); + cudaMalloc((void**)&dev_y_sm, n * output_size * sizeof(float)); + cudaMemcpy(dev_x, x, n * input_size * sizeof(float), cudaMemcpyHostToDevice); + + forward(); + cudaMemcpy(y, dev_y_sm, n * output_size * sizeof(float), cudaMemcpyDeviceToHost); + + cudaFree(dev_x); + cudaFree(dev_hidden); + cudaFree(dev_hidden_sm); + cudaFree(dev_y); + cudaFree(dev_y_sm); + } + + void mlp::forward() { + gpu_blas_mmul(handle, dev_x, wkj, dev_hidden, num, input_size, hidden_size); + dim3 fullBlockPerGrid1((hidden_size * num + blockSize - 1) / blockSize); + kernSigmoid << > > (hidden_size * num, dev_hidden_sm, dev_hidden); + + gpu_blas_mmul(handle, dev_hidden_sm, wji, dev_y, num, hidden_size, output_size); + dim3 fullBlockPerGrid2((output_size * num + blockSize - 1) / blockSize); + kernSigmoid << > > (output_size * num, dev_y_sm, dev_y); + } + + void mlp::backProp() { + float *wji_T, *y_smDer, *temp1, *psi_right, *hidden_sm_T, *hidden_smDer, *psi_left, *temp2, *dev_x_T; + + cudaMalloc((void**)&dev_x_T, num * input_size * sizeof(float)); + cudaMalloc((void**)&y_smDer, num * output_size * sizeof(float)); + cudaMalloc((void**)&temp1, num * output_size * sizeof(float)); + cudaMalloc((void**)&psi_right, num * output_size * sizeof(float)); + cudaMalloc((void**)&hidden_sm_T, num * hidden_size * sizeof(float)); + cudaMalloc((void**)&hidden_smDer, num * hidden_size * sizeof(float)); + cudaMalloc((void**)&psi_left, num * hidden_size * sizeof(float)); + cudaMalloc((void**)&wji_T, output_size * hidden_size * sizeof(float)); + cudaMalloc((void**)&temp2, num * hidden_size * sizeof(float)); + + int n1 = output_size * num; + dim3 fullBlockPerGrid1((n1 + blockSize - 1) / blockSize); + kernSmDerivative << > > (n1, y_smDer, dev_y_sm); + kernSubtract << > > (num * output_size, temp1, dev_y_sm, dev_target); + kernDotProd << > > (n1, psi_right, y_smDer, temp1); + gpu_blas_mtrans(handle, dev_hidden_sm, hidden_sm_T, hidden_size, num); + gpu_blas_mmul(handle, hidden_sm_T, psi_right, gwji, hidden_size, num, output_size); + + int n2 = hidden_size * num; + dim3 fullBlockPerGrid2((n2 + blockSize - 1) / blockSize); + kernSmDerivative << > > (n2, hidden_smDer, dev_hidden_sm); + gpu_blas_mtrans(handle, wji, wji_T, output_size, hidden_size); + gpu_blas_mmul(handle, psi_right, wji_T, psi_left, num, output_size, hidden_size); + kernDotProd << > > (n2, temp2, psi_left, hidden_smDer); + + gpu_blas_mtrans(handle, dev_x, dev_x_T, input_size, num); + gpu_blas_mmul(handle, dev_x_T, temp2, gwkj, input_size, num, hidden_size); + + cudaFree(y_smDer); + cudaFree(temp1); + cudaFree(psi_right); + cudaFree(hidden_sm_T); + cudaFree(hidden_smDer); + cudaFree(psi_left); + cudaFree(temp2); + cudaFree(dev_x_T); + cudaFree(wji_T); + } + + void mlp::loss() { + + int n1 = num * output_size; + float *dev_loss; + float *h_loss = new float[n1](); + + cudaMalloc((void**)&dev_loss, sizeof(float) * n1); + dim3 fullBlockPerGrid = dim3((n1 + blockSize - 1) / blockSize); + kernLoss << > > (n1, dev_loss, dev_target, dev_y_sm); + cudaMemcpy(h_loss, dev_loss, n1 * sizeof(float), cudaMemcpyDeviceToHost); + + error = 0.0; + for (int i = 0; i < n1; i++) { + error += h_loss[i]; + } + error /= (2.0 * output_size); + cudaFree(dev_loss); + delete[] h_loss; + } + + void mlp::update() { + float lambda = 0.01; + + dim3 fullBlockPerGrid1 = dim3((hidden_size * output_size + blockSize) / blockSize); + kernUpdate << > > (hidden_size * output_size, wji, gwji, lambda); + + dim3 fullBlockPerGrid2 = dim3((input_size * hidden_size + blockSize) / blockSize); + kernUpdate << > > (input_size * hidden_size, wkj, gwkj, lambda); + } +} \ No newline at end of file diff --git a/Project2-Character-Recognition/character_recognition/mlp.h b/Project2-Character-Recognition/character_recognition/mlp.h index 2096228..0630411 100644 --- a/Project2-Character-Recognition/character_recognition/mlp.h +++ b/Project2-Character-Recognition/character_recognition/mlp.h @@ -1,9 +1,46 @@ #pragma once - #include "common.h" +#include + namespace CharacterRecognition { - Common::PerformanceTimer& timer(); + Common::PerformanceTimer& timer(); + + class mlp { + public: + + mlp(int n_input, int n_hidden, int n_output); + ~mlp(); + + void initWeights(float *wkj, float *wji); + void initRandom(); + void train(float *x, float *y, int n, int epoch); + void predict(float *x, float *y, int n); + float getError() const { + return error; + } + + private: + void forward(); + void backProp(); + void loss(); + void update(); + + int input_size; + int hidden_size; + int output_size; + + float *wkj, *wji; + float *gwkj, *gwji; + int num; + float* dev_x; + float* dev_hidden; + float* dev_hidden_sm; + float* dev_y; + float* dev_y_sm; + float* dev_target; + float error; - // TODO: implement required elements for MLP sections 1 and 2 here + cublasHandle_t handle; + }; } diff --git a/Project2-Character-Recognition/img/acc.png b/Project2-Character-Recognition/img/acc.png new file mode 100644 index 0000000000000000000000000000000000000000..e4b5ab18f57f361175d6dc17d6629d2640159cd5 GIT binary patch literal 18890 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 B%Qyf4 literal 0 HcmV?d00001 diff --git a/Project2-Character-Recognition/img/error.png b/Project2-Character-Recognition/img/error.png new file mode 100644 index 0000000000000000000000000000000000000000..c5f7e6c5e3c5b95efdbfdff5dc099076d0757277 GIT binary patch literal 15456 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 literal 0 HcmV?d00001 diff --git a/Project2-Character-Recognition/src/main.cpp b/Project2-Character-Recognition/src/main.cpp index 11dd534..3eaa42b 100644 --- a/Project2-Character-Recognition/src/main.cpp +++ b/Project2-Character-Recognition/src/main.cpp @@ -1,8 +1,8 @@ /** * @file main.cpp * @brief Stream compaction test program - * @authors Kai Ninomiya - * @date 2015 + * @authors Weiqi Chen + * @date 2019 * @copyright University of Pennsylvania */ @@ -10,143 +10,158 @@ #include #include #include "testing_helpers.hpp" +#include +#include + +using namespace std; +bool test(CharacterRecognition::mlp &mlp, int label); +int decode(int n, float* array); + + +void xor_test() { + const int input_size = 2; + const int hidden_size = 2; + const int output_size = 1; + + CharacterRecognition::mlp xor(input_size, hidden_size, output_size); + float *wkj = new float[input_size * hidden_size]; + float *wji = new float[hidden_size * output_size]; + + wkj[0] = 10.1; + wkj[1] = 20; + wkj[2] = 0.9; + wkj[3] = 0.87; + + wji[0] = 41; + wji[1] = -54; + xor.initWeights(wkj, wji); + + const int combo = 4; + float *x = new float[combo * input_size]; + float *y = new float[combo * output_size]; + + x[0] = 0; + x[4] = 0; + y[0] = 0; + + x[1] = 0; + x[5] = 1; + y[1] = 1; + + x[2] = 1; + x[6] = 0; + y[2] = 1; + + x[3] = 1; + x[7] = 1; + y[3] = 0; + + cout << "--- XOR ---" << endl; + for (int e = 0; e < 14; e++) { + // Train + xor.train(x, y, combo, 10); + float err = xor.getError(); + + std::cout << "epoch: " << e * 10 << " | error: " << err << std::endl; + } +} + +void char_reg() { + + const int num_data = 52; + const int input_size = 10201; + const int hidden_size = 256; + const int output_size = 52; + CharacterRecognition::mlp characterRec(input_size, hidden_size, output_size); + characterRec.initRandom(); + + float *x = new float[num_data * input_size]; + float *y = new float[num_data * output_size]; + memset(y, 0, num_data * output_size * sizeof(float)); + + for (int i = 0; i < 52; i++) { + string id = to_string(i + 1); + if (id.length() == 1) { + id = "0" + id; + } + string name = "../data-set/" + id + "info.txt"; + ifstream input_stream(name); + + int a, b; + input_stream >> a; + input_stream >> b; + for (int j = 0; j < input_size; j++) { + input_stream >> x[i+ j * num_data]; + } + y[i * num_data + i] = 1.0; + } + + cout << "--- Character Recognition ---" << endl; + for (int t = 0; t < 14; t++) { + + float err = characterRec.getError(); + int correct_cnt = 0; + for (int i = 1; i <= 52; i++) { + if (test(characterRec, i)) { + correct_cnt++; + } + } + std::cout << "epoch: " << t * 10 << " | error: " << err << " | accuracy: " << correct_cnt / 52.0 * 100 << "%" << std::endl; + } + cout << "---" << endl; + for (int i = 1; i <= 52; i++) { + if (test(characterRec, i)) { + } + } +} -const int SIZE = 1 << 8; // feel free to change the size of array -const int NPOT = SIZE - 3; // Non-Power-Of-Two -int *a = new int[SIZE]; -int *b = new int[SIZE]; -int *c = new int[SIZE]; +bool test(CharacterRecognition::mlp &mlp, int label) { + + float *x = new float[10201]; + float *y = new float[52]; + + string id = to_string(label); + if (id.length() == 1) { + id = "0" + id; + } + string name = "../data-set/" + id + "info.txt"; + ifstream input_stream(name); + int a, b; + input_stream >> a; + input_stream >> b; + + for (int i = 0; i < 10201; i++) { + input_stream >> x[i]; + } + mlp.predict(x, y, 1); + int pred = decode(52, y) + 1; + cout << "Target:" << label << ", Predicted:" << pred << endl; + + + delete[] x; + delete[] y; + if (pred == label) { + return true; + } + else { + return false; + } -int main(int argc, char* argv[]) { - // Scan tests - - printf("\n"); - printf("****************\n"); - printf("** SCAN TESTS **\n"); - printf("****************\n"); - - genArray(SIZE - 1, a, 50); // Leave a 0 at the end to test that edge case - a[SIZE - 1] = 0; - printArray(SIZE, a, true); - - // initialize b using StreamCompaction::CPU::scan you implement - // We use b for further comparison. Make sure your StreamCompaction::CPU::scan is correct. - // At first all cases passed because b && c are all zeroes. - zeroArray(SIZE, b); - printDesc("cpu scan, power-of-two"); - StreamCompaction::CPU::scan(SIZE, b, a); - printElapsedTime(StreamCompaction::CPU::timer().getCpuElapsedTimeForPreviousOperation(), "(std::chrono Measured)"); - printArray(SIZE, b, true); - - zeroArray(SIZE, c); - printDesc("cpu scan, non-power-of-two"); - StreamCompaction::CPU::scan(NPOT, c, a); - printElapsedTime(StreamCompaction::CPU::timer().getCpuElapsedTimeForPreviousOperation(), "(std::chrono Measured)"); - printArray(NPOT, b, true); - printCmpResult(NPOT, b, c); - - zeroArray(SIZE, c); - printDesc("naive scan, power-of-two"); - StreamCompaction::Naive::scan(SIZE, c, a); - printElapsedTime(StreamCompaction::Naive::timer().getGpuElapsedTimeForPreviousOperation(), "(CUDA Measured)"); - //printArray(SIZE, c, true); - printCmpResult(SIZE, b, c); - - /* For bug-finding only: Array of 1s to help find bugs in stream compaction or scan - onesArray(SIZE, c); - printDesc("1s array for finding bugs"); - StreamCompaction::Naive::scan(SIZE, c, a); - printArray(SIZE, c, true); */ - - zeroArray(SIZE, c); - printDesc("naive scan, non-power-of-two"); - StreamCompaction::Naive::scan(NPOT, c, a); - printElapsedTime(StreamCompaction::Naive::timer().getGpuElapsedTimeForPreviousOperation(), "(CUDA Measured)"); - //printArray(SIZE, c, true); - printCmpResult(NPOT, b, c); - - zeroArray(SIZE, c); - printDesc("work-efficient scan, power-of-two"); - StreamCompaction::Efficient::scan(SIZE, c, a); - printElapsedTime(StreamCompaction::Efficient::timer().getGpuElapsedTimeForPreviousOperation(), "(CUDA Measured)"); - //printArray(SIZE, c, true); - printCmpResult(SIZE, b, c); - - zeroArray(SIZE, c); - printDesc("work-efficient scan, non-power-of-two"); - StreamCompaction::Efficient::scan(NPOT, c, a); - printElapsedTime(StreamCompaction::Efficient::timer().getGpuElapsedTimeForPreviousOperation(), "(CUDA Measured)"); - //printArray(NPOT, c, true); - printCmpResult(NPOT, b, c); - - zeroArray(SIZE, c); - printDesc("thrust scan, power-of-two"); - StreamCompaction::Thrust::scan(SIZE, c, a); - printElapsedTime(StreamCompaction::Thrust::timer().getGpuElapsedTimeForPreviousOperation(), "(CUDA Measured)"); - //printArray(SIZE, c, true); - printCmpResult(SIZE, b, c); - - zeroArray(SIZE, c); - printDesc("thrust scan, non-power-of-two"); - StreamCompaction::Thrust::scan(NPOT, c, a); - printElapsedTime(StreamCompaction::Thrust::timer().getGpuElapsedTimeForPreviousOperation(), "(CUDA Measured)"); - //printArray(NPOT, c, true); - printCmpResult(NPOT, b, c); - - printf("\n"); - printf("*****************************\n"); - printf("** STREAM COMPACTION TESTS **\n"); - printf("*****************************\n"); - - // Compaction tests - - genArray(SIZE - 1, a, 4); // Leave a 0 at the end to test that edge case - a[SIZE - 1] = 0; - printArray(SIZE, a, true); - - int count, expectedCount, expectedNPOT; - - // initialize b using StreamCompaction::CPU::compactWithoutScan you implement - // We use b for further comparison. Make sure your StreamCompaction::CPU::compactWithoutScan is correct. - zeroArray(SIZE, b); - printDesc("cpu compact without scan, power-of-two"); - count = StreamCompaction::CPU::compactWithoutScan(SIZE, b, a); - printElapsedTime(StreamCompaction::CPU::timer().getCpuElapsedTimeForPreviousOperation(), "(std::chrono Measured)"); - expectedCount = count; - printArray(count, b, true); - printCmpLenResult(count, expectedCount, b, b); - - zeroArray(SIZE, c); - printDesc("cpu compact without scan, non-power-of-two"); - count = StreamCompaction::CPU::compactWithoutScan(NPOT, c, a); - printElapsedTime(StreamCompaction::CPU::timer().getCpuElapsedTimeForPreviousOperation(), "(std::chrono Measured)"); - expectedNPOT = count; - printArray(count, c, true); - printCmpLenResult(count, expectedNPOT, b, c); - - zeroArray(SIZE, c); - printDesc("cpu compact with scan"); - count = StreamCompaction::CPU::compactWithScan(SIZE, c, a); - printElapsedTime(StreamCompaction::CPU::timer().getCpuElapsedTimeForPreviousOperation(), "(std::chrono Measured)"); - printArray(count, c, true); - printCmpLenResult(count, expectedCount, b, c); - - zeroArray(SIZE, c); - printDesc("work-efficient compact, power-of-two"); - count = StreamCompaction::Efficient::compact(SIZE, c, a); - printElapsedTime(StreamCompaction::Efficient::timer().getGpuElapsedTimeForPreviousOperation(), "(CUDA Measured)"); - //printArray(count, c, true); - printCmpLenResult(count, expectedCount, b, c); - - zeroArray(SIZE, c); - printDesc("work-efficient compact, non-power-of-two"); - count = StreamCompaction::Efficient::compact(NPOT, c, a); - printElapsedTime(StreamCompaction::Efficient::timer().getGpuElapsedTimeForPreviousOperation(), "(CUDA Measured)"); - //printArray(count, c, true); - printCmpLenResult(count, expectedNPOT, b, c); - - system("pause"); // stop Win32 console from closing on exit - delete[] a; - delete[] b; - delete[] c; } + +int decode(int n, float* array) { + float temp = 10000; + int index = 0; + for (int i = 0; i < n; i++) { + if (array[i] > temp) { + index = i; + temp = array[i]; + } + } + return index; +} + +int main(int argc, char* argv[]) { + xor_test(); + char_reg(); +} \ No newline at end of file From 2e41fc93df39111be135d0e1adaddc74f9c87d37 Mon Sep 17 00:00:00 2001 From: WaikeiChan Date: Thu, 26 Sep 2019 00:09:34 -0400 Subject: [PATCH 4/4] Replaced by the correct version --- Project2-Character-Recognition/src/main.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/Project2-Character-Recognition/src/main.cpp b/Project2-Character-Recognition/src/main.cpp index 3eaa42b..9263ad6 100644 --- a/Project2-Character-Recognition/src/main.cpp +++ b/Project2-Character-Recognition/src/main.cpp @@ -14,7 +14,7 @@ #include using namespace std; -bool test(CharacterRecognition::mlp &mlp, int label); +bool test(bool flag, CharacterRecognition::mlp &mlp, int label); int decode(int n, float* array); @@ -99,10 +99,11 @@ void char_reg() { cout << "--- Character Recognition ---" << endl; for (int t = 0; t < 14; t++) { + characterRec.train(x, y, num_data, 10); float err = characterRec.getError(); int correct_cnt = 0; for (int i = 1; i <= 52; i++) { - if (test(characterRec, i)) { + if (test(false, characterRec, i)) { correct_cnt++; } } @@ -110,12 +111,12 @@ void char_reg() { } cout << "---" << endl; for (int i = 1; i <= 52; i++) { - if (test(characterRec, i)) { + if (test(true, characterRec, i)) { } } } -bool test(CharacterRecognition::mlp &mlp, int label) { +bool test(bool flag, CharacterRecognition::mlp &mlp, int label) { float *x = new float[10201]; float *y = new float[52]; @@ -135,8 +136,9 @@ bool test(CharacterRecognition::mlp &mlp, int label) { } mlp.predict(x, y, 1); int pred = decode(52, y) + 1; - cout << "Target:" << label << ", Predicted:" << pred << endl; - + if (flag) { + cout << "Target:" << label << ", Predicted:" << pred << endl; + } delete[] x; delete[] y; @@ -150,7 +152,7 @@ bool test(CharacterRecognition::mlp &mlp, int label) { } int decode(int n, float* array) { - float temp = 10000; + float temp = FLT_MIN; int index = 0; for (int i = 0; i < n; i++) { if (array[i] > temp) {