From a5a6c483d239359657e33c83f9290ab2ded722ac Mon Sep 17 00:00:00 2001 From: Josua Rieder Date: Mon, 20 Sep 2021 21:09:16 +0200 Subject: [PATCH 1/2] groupK submission --- .../2021/groupK_burgers_openmp/HPC4WC.pdf | Bin 0 -> 261824 bytes .../branch-master/CMakeLists.txt | 27 + .../branch-master/main.cpp | 495 ++++++++++++ .../branch-omp/CMakeLists.txt | 29 + .../groupK_burgers_openmp/branch-omp/bench.sh | 5 + .../groupK_burgers_openmp/branch-omp/main.cpp | 511 ++++++++++++ .../groupK_burgers_openmp/branch-omp/plot | 22 + .../groupK_burgers_openmp/branch-omp/plot.svg | 198 +++++ .../branch-omp/results-collapsed-dynamic.txt | 24 + .../branch-omp/results-collapsed-static.txt | 24 + .../branch-omp/results-shallow-dynamic.txt | 24 + .../branch-omp/results-shallow-static.txt | 24 + .../branch-omp/results-single.txt | 1 + .../branch-upcxx/main.cpp | 725 ++++++++++++++++++ .../branch-upcxx/upcxx_small_grid | 10 + .../branch-upcxx/upcxx_strong_scaling | 10 + 16 files changed, 2129 insertions(+) create mode 100644 projects/2021/groupK_burgers_openmp/HPC4WC.pdf create mode 100644 projects/2021/groupK_burgers_openmp/branch-master/CMakeLists.txt create mode 100644 projects/2021/groupK_burgers_openmp/branch-master/main.cpp create mode 100644 projects/2021/groupK_burgers_openmp/branch-omp/CMakeLists.txt create mode 100755 projects/2021/groupK_burgers_openmp/branch-omp/bench.sh create mode 100644 projects/2021/groupK_burgers_openmp/branch-omp/main.cpp create mode 100644 projects/2021/groupK_burgers_openmp/branch-omp/plot create mode 100644 projects/2021/groupK_burgers_openmp/branch-omp/plot.svg create mode 100644 projects/2021/groupK_burgers_openmp/branch-omp/results-collapsed-dynamic.txt create mode 100644 projects/2021/groupK_burgers_openmp/branch-omp/results-collapsed-static.txt create mode 100644 projects/2021/groupK_burgers_openmp/branch-omp/results-shallow-dynamic.txt create mode 100644 projects/2021/groupK_burgers_openmp/branch-omp/results-shallow-static.txt create mode 100644 projects/2021/groupK_burgers_openmp/branch-omp/results-single.txt create mode 100644 projects/2021/groupK_burgers_openmp/branch-upcxx/main.cpp create mode 100644 projects/2021/groupK_burgers_openmp/branch-upcxx/upcxx_small_grid create mode 100644 projects/2021/groupK_burgers_openmp/branch-upcxx/upcxx_strong_scaling diff --git a/projects/2021/groupK_burgers_openmp/HPC4WC.pdf b/projects/2021/groupK_burgers_openmp/HPC4WC.pdf new file mode 100644 index 0000000000000000000000000000000000000000..8170bad25cb8d563243d20e7ebef7229596cffca GIT binary patch literal 261824 zcmeFXRd6LulO-rFF*9B$!r zwY-@Y5gr~HC(Mp}x;v@7h!`y+9V;|x?^EF?G$R{;0bpln3C+U;pqI9=H8F6s@H8<7 zFn+fHOl*uCOe_F;34j)Wk(HAPz{JP^&;iiP0hky7^r8SpW@e6W1@y9j@0;>J;w)?o z06sow6I{J?u>Y^y-Qxrr+Bzu{Cox2QV^xZ$!+(+S$bM`)O_9 zY$9S}WM}*>_OGYBfuoHR;2#u(?W|pFY@GnC0D5^x6JrY_XFEp#Bh&Z30Q74AAOT?h z{(r+DX=`la{!a(nKS=zm$J7qM$nyOriU4{=J3D6pBgelQO5dn{k8u8*PS<}y#rQwN zLoX=;(Bk1_=44`LW;bPGGvqL3HZfvh;b1UiG%#jhG-799HelrAVP|7tG%;m1WimG5 zU}xlH=V0XEFfjR^!pg+P$z;OGr}NJtI5|6-7}!9&XB!zB>+hK98|v$GKoM!=`AZCA zGk8GJY(WyWrv^%Bcp*~effKn93lu*RAyOtmqN@QV%!djjDoh~^vB7~PP~8BS&}j-8 zeuyyj8t5Co&$xnE^MMk7NDRB(w>Tu@j*|eTnIgpebLjuRCNlp< zc`8mO|2azkPxrUbKZf9&wf;q&!UoO;)^=w9h07T^zsLV$?f)f@D*dzaw{2i#=J+41 z`)xk{8x`s6|HDI#`uYa?JFC-xQ6O-AHfB)j__5pgh+R9EC;A_`IGZS#n9;1olX#V- zcb4m*a!WC1<-cGd0YJZDVPjz5VPUCIa(%tooBu9BZG*JGltL}Y9J~DK$!&jM z6rJbwJ^T51ILv7Z` zwL=!WhYH#fk&(rV(^kp@8RXLQ5!;5_lW4qex7B6jQIzY=?(2H6hE%$}Lf zftzjw25^wd0H%YK0}F>zA_HZTG~_@ix*Z03bT_5bd3x6URon!4>uE1WM)5%L_VNWC zf?f}Ol*-(5PY7wI(Ml+Tjn{FMjaoGZz`fBQfihf(ImhueY&Mr(U5Zl}{KxLcZ4G(^ zv8+=}s^iaeCP^|*1;Mu!cEsP_fAB19$YYpIQFpQ550WL;vYxo?9Ds^ZD2LU#u=XP9 zKW|ny!_tUoSJo@lF>qjoRuIDNoI6*_g(LE=%ckw?Rd;mT>8@QtTWbjBvF+}tSbQkf zP5!Jiz?b+@4IA7AvX?*1iE|kxa^NzzL01IPe{}`iR7ycsp`UtHQj|^hr|jZn^cWE^ z9E5`3MP9qEquN}ly6=kP);_dQuN=&R0eNTb+jc|WK`=iQ1A2#Z5CQ`Q7)Lv#eA+Z3GAv-HyV>hpr1~Coqh~Ql;kv-4 z$k&Ayidpl83Y`;@KgWmBe=gbTupA;c?8H0?oL*x1Rt_Gkn9nWw2>ktPfXU+yEBN~g zWw8dxHVge6RtiZU^qOb7-k?w8P1GIR;c;XKTf|@wM=4v~6tw96?sA6VfNS%`;%Vw( zX@nYrFdynCN1Cp>x@5HJn4{0bC8&(*HIi6{L_tzs*9n(FwmIcai!v6~0ObyS8YYnqe{@~p=d;$yN|ZZ6eT?xn^*QHPGAOz3C~w`*-y3hJ zPI4&l=TAIO_+4I^>P2*pGf+e^zJy-_837M~y=|in{;B)L-ftC*h3VMuUUKc1B^%1) z$iVFWkOnUlV@9vIyY&Lbsq*7LP=YW)2C)8?0KLM?!$q0)mW#Ux&Vv0Q^FWRoQisHJ zHKL1Tgw0SWGdxcTh#FyJaRU7ThuSB^KYBYVA#e?3E|3tI2Z9}TN@iC6+U3Apf36ok zb>{$T@<_t=v_BjiF=P|VC6f-m$Z434t3YmuZze5l&Y%%kJm$#Dy0Z&bLlusM>FBAe zD6oR1xrCl9nVok;QzNwU-rmJLTM1nB=H*f{Yn44HSZr2D79PuwHrOGwv6 zS??fke@N#957dTSW2uVk{sOX0==Ooyz7oXrSvwm$q7KnKyN6~TDH?-;|8 zsyAFIq{ClnO4I?xY~K`9Kv)NrU7AQ%$+GT@f(3zcDYry<6sVn7sG<=_m{OWBKwci7 ziAa6>D~^<8f$%JEh6ohZz^u_jF7K{MI!pufrTaltg-4W3EFOga$MFzz*JCVG1UtdNp6o-w5Icn6`0b~>(tNsM2GT%r}s#+hCo^69zwq#^tg1Tvmc{%Jtk-Rtzo9V3!4k)x@t$sD#4=J7{0$ zE8yz9B~5%zjbG;}yG9G_JyP0a3(iNeGxrDlVteNs)rIMj(8qm$`v-&~V z*WS2O$iZSm-XILjc+ra$e&JB{xI#{1b==(yeNaM8_j1Ic2PD5t@>I~=0LiDnIW zm5~7o^a>>E8@PO#+V`51!E*q)MBDKRIp2$$)?dVp<+=jXs18UC5UTLiVKMON%qOta zPK-}hwUA@1SrP{Eg_8L3-L8#?h8nH-ZVm2&TvX-h8R6IArE0Tpuue2Um9*?5K%?OH zshqR;GWHxu^HWU(WO}N7^Q0)Xl#8B!4~WQjJm@*oi@aw^3oiF8A$^89!_YSM3}*%6 z^0USa-9T`TO6nPD2FME-A#=os&As@Y9gHD`%3wA)jYnr9V4D%5gP5X~!hvAXXoTVo zPWDfMQl-C+hp@lI_*L4p} z%N4wl&%PER31SZ$?nUr_La{#Ufqwc~>H-qb82MB!zOJqLhNTw&P>M&6@-RaW@y!Ch}8xd z%7tmvsWQ~53}InT2Uy%9?dYfq^9j;D zUnxz(%d98WK_Z#^0kh;NZ2P`f~*KVJB^+o!;qMW{E{j*OqZ2zvsop3T+%fN(X*++DO(I4oSC;74AY zi8}f@gYm;hz^=g0nD0<;_--V-hlA%0z?;vZy4(Jas)@Sv<*5iDB5?Cq{Q)O#CJ)g{ z=d-=rKzZq^vK8!RcMG9N%DdrjNq}5H>7d2gbaHUn#9}5X8rKjp5b>Mp5bjv=geQz!#Jyg+2uS2 zN*~|w#3}=JuJg%2iO!+6y*V_$aFflvC#*(c^9Qav)fZc&*!q5_(H|9}Cof7O^PL|C zj_EK*bZybcPHn`?(-cw_Y?OqX5^w+=W@k4kw-E+dh9Ov3VfanBc_|o) zGJm4Y$Uy(%L}aN*A__%<*XORQx2~_=<)<32nzx>rp4#r2Ei=70`+96l7z$28+=9Q5 z98y3ekjW6`CzTrh{y+eE5kyE-vV$FlfC8R;zjY|i$$SX{Oc1&c0$4N>)aZ_eia-T+ z5gjmG`#a`CS>w!R=9u^sB*tA1G#@KU_v6Wm_d9SA^43H7;s2}CMKfeZmW2;8BcOucw#Dh{~{svqs&mtWrJ7rc||B3jT@ z91{Hg@d4hS%NGb)9L0mc-$xMY2#zV}lP|$vjo;qqLx0R=g&BR zb%-D)1k4VBfC&cu)b4N-!Y!EKpS1}*tjPuBLr?Ke|7%(g%(pLZ5ZE6~@C*8B4 zg;W^mxpaX4;YA>xfj&7dA7OG|Ek>w!U<0=idqWa@_Y^9m$Q#n{unbyQh>-mlpW?o( z{n9>|ANS*F91FtD@lz!X=lbE`U?mjxX4ppq>ELU+7gxc=ikG-ANP@1UOqC z5w#ELFGvu|C--X%*5CJ)*U~Qub)Y_McVd1-py#ufmAs3Xfow$kxIVuHzgG3pQHd#K zovbUlu`iI66eM7vCjWX00ReR>Tu7jZ$OsS;l3-xMFIZ!s&=1K2{_N(RX-NM?y_YTA z#cj^F4ysekO1Li^Wu;&O!F6Ovkem0}5rPJT?Lscb!0eQEA^J0e zNIqAU3HZmaOtAtz`EwQF8qoFjZM()F@CSSed;;}qy&+&!dG??U$5c}(jxW0Xo^iLdF(1dG? z=2DsT;sUhRxAgH`MC#pP-{Vc)5s{q`t2)g%yU@k>VJ z5LUdxXqN_Woi-T=g^&KX0?_H?*r`_J9{UQ-)8!pf=y_SVa(>Nnu+ofaQ0kdSmQKlC~eDy*hjjhi-g*GBd*M4*%qoMcsej zu^WDjxK_YlM2P@jL1)zbkGVMnvaF4pVR35&~YAy|BOL=U!ZXOIu6WvZkRw zEDA2q=thbM$Ps6Td8p!gH;<2|{3^TFMts9{C%?|FVR4Ox;ljrY8ip{)d^U?sd3DYH6a5 zifRdOkCTQvMn1^x;nzk-fJWkH)|sXJw{uH5Ag`~p&ez0>2ZM~vq_RsoN0W>2_r+GU z3_;}V2y@8y7gD2fEY9fNwc_`W(o>!l`DQ*4n$ zpEg+GvDq7}NzlIZ@(@Hbn)f|QarX@PT-L9{Rc(*#ZlU^?g#C=eI?%p3u`>FlxU%YF z74l|aX0$@sZeT}xzjX%-lP~K&eqp)P)OL}|<&t{USS0{7fk&Yh^Q* z@C<2A*Y)KY?8xihf)Isj#@@4Z1u2Oy?<1)2l5xWAifT5nVW+BH+}lE@4+F~J*V#6; z&AQ$j8tbITo`w&9HHC*{^7g1B-HMIvk)`Cgg>y))85+D-@8Uy*l^g=)^!+c+DaMka z?hU@kOPz;Bh)>xCG#N%4y@#Be2i{t~-|n8XkPjUaIGG0$YF?bY8=vXc0_%1{ zWOs$93%v=H<~MV<;;An6A<7AgMP`veO<3=am&H^vhgYKg^oT z#9g&d4q!m>8&_%yO2*$`0Qo7jNn;-4)sYNn%3`uNHAB$vWoXEP4YIMrMqbD!dlART8$7K>Ge#ig&A$nZb=(nPv32nkJZXL|up#pJp6>WCpgd!# zdRy1&Ee8=d2tNp_Wi_i+N35HrO>4MH!-a2Goc0H@{UJhJ!iF=15D%BTZ6h?) z@g4hB&y9Q*D+;VPm^HRp`nqtMo*SI&Yhkvg3FEl=S>ls8FJT)wF27ha>wi!nw+&G7 zW`)m;f6MY!wg&f3TCHBE!>L%6#y56m!oAER;|l*noJ8`Ovr~( z6$T&W(SO6U&K4s3(Dhr;R7=;Y?rhBU&uHpTZY#lxNXGMp0e$=d568t2wz;5bHEcpf zKfFW!fN;wLerY{hXhUs{_yiK>^gA<{;6iIv{HS2*q6Wc`9YF9a=o zh93j2Bo-G=hqP$sT=X(+vTfq%bk?@D9u(I4ilY`Kf1#3M75$@a+fw3qe7sh8)3%)s zzmyDdIG#mbtati%#$UYjWs*i$(~igWK+p6RjQ-Y@WZon?>gS;*Dchge6gSu3;^6FD z3~}8G`Gt}~FFp!i_oIFWAe58LOk+cdeLUn%l=T5MS1UB3ywY2Bn3$?LsFdLKKGS?2 zF`WDld*_(U02cI^n~anl6^+@S8r0D!B9(w~2jxF6FFC}6kIl1%4FTdZxC<^~H~nlP z;|w;sys<^Iykv=*O&=^}`-Tb3im47L5ojK1z~|PHm<3Q zW_a82N%%)zyDU00QvvsFX-vB^$D(qmEK2w0d4(%t2rUgdSdrpQj%lmB`Zam{;Cy4n zIzzo)F~!;`HllOKV_(d;Bo5_;TY*o3WThwY%Bman{TV8M6PRXX`L!vnmei}aD%Iwz*TVn1>%|?i*I_@uXXgeaeupuV=qT#o za~o*R3I&2rjWT06Lu@t?mt!ty+$wwvcZBx@bk6hD8)jFP z_QvHIfWg<;E!l-Br+>zfJ=`{B>pb=2HCZ3VcP z8*EwbD)U#*Ipca9gWovkD*|#fAn0dr z;_ZVEVH_KlYIBOaZ}-#fsD%$fj)!U-zf7+|Y~d$%$(bmY7Kj%{zl_Ff&P-@t>gvR} z>aE4qPEo9erg7H6^Qu5d6#nXgEuysJy zN1;FMiV_CNS8 zYCh~61dJ@tjAm@xcf%>5gr6iHf-E5<#74G2Oy*ka>#do0(5Hjks5M}JO8-0;DC=_9 zEfHZ!^4sv0qE|a1;4F<>s|SU5j80!T&)fE>ZTa|`Hk&O(l}Jx%;}9QVYlK_Jk(Q`Y zQ%97#{wl(KtizHR(hP3qeE{Q0?B_-zD>PEV+#+pqskbYwXaSksmBeN+T058azMG-m ziO`Qu+>56oEaRPai)2Gb$SP=+P=Jh(Ia;Tf_ps1#xr))rCpxh{M}dOTk6TBxS#vx# zL|zlR((vl5qdREI7)j z&lE)Yyr&25^hqm}E0aa*Ankx^#5$VKo=tIdYL-uutC+9!=rSJohN@;afs^Tirc#t( ze#;23YY2oCH%jA5Re{Soe`FJkhP{sh*6_*`UUlIzOEhk}%r700N7gsd6`14p()=~C zA$ZoGNS7hra#m_5D{7;on}I9bB&mp2IhmditzDGJ^J7=-(p$(m@Z75!)WUfUq<%y5 zgI|HI-dA^>;QcxDBWJlW{L87`!#SeO*vkGooNM(M2m!W#rx7yz{ zg9yJ;zGItDoIk8Dkz{XPGQSU! zM~3=s%fHL+6_o~ql9j{jC80-GqC&4nLAqVV4WH_MyVU@6SBH+RvnQLk-}|JVV1oGM zTTnq7fQ(_SFs!pLZkpr$qM<*3vp+WxH1p`d2x{vp39_!Fy?pKH4ruOC$!PjKT8a*| zuvC>%H}Q;zw%?$Q+wRl-W7GnUJyuV<^!oD4BHFj?GYIgrA(TF&55nIx{%MKorG zOMl0ff@XD0Vou2_mw(u@UH0wD?AJJ;Zgz@gzRck-prY=EHn)-{(pzyjM@KzntGoN9Gj;1B^wR@2DWHXuF_qCj<&>6z=<_nJw zen>&Q9bkE3Tt43yR>(C_`zXWeaPN>6-Z#cu$1+fJ67d4eC8-id-36EN?T~Q+)(K-3 zFLZU*PoPj=^t*WniP5w);#eBMG-xz9nm3GJ7*Vk(QVud%s_S7KbZEv6KCq@h2#bFW zy`x;N(!?;$JZ+N^Qz4V*vbT+*n+@)n^mA|dSlBx__; z7B&yqb7V39EqiTVxt9L@hUF`HS6tJ*@wmYI5X=7eHhV}f)R(7AW9fp51urQseGj# z>2oLTLU&x2dQ)MEE=B9^Q2!g1h6nxLFQUX@sIb3RljijT{G`@U4Z!IRM611uNYzxo z0xMiJ4Dos^SwVXjpN@@W_A{th)_|7rXeYK^uYUWiL{dHBPVgcXW4b`*e~q^aU}aFA z+mOcWx6Hk}|1hcjxw2WTL(EL{hvQbg!hh5(Z{ckKVpr#ZXK4~{1+fp<3eh2Mw66_@ zpOdd(zYsh5r>fC09tjIOGx1-#IZbAU<5gW9 zv5LA5oEU!dyqwj&I=_>hp6P_-vcogT9{+W1tnR405~o7Fep382F+ILN zF6GgUfgmwI@|fcO76P5aRN2*)^Xx1|lB>(GnOox-f zK*}QyC~~!T4E1iO<`&Z{!J0PhJby(NE@$!aoZf+QEIO|XeR2!Pet2)pI@7%2}~OlU&{^_Le8%BPr4kdix(V%$9_I3fvn!NtvW?C=Bm3Z(zKnB+1 zcu`)N)Xp*PG26?rVzxncO#qW9nY6^`ZfzjWfhBbtz&xdRCvBdb(4P80bz?cC_A%u< zH4JpbXz??hb>f*}#-=8jecS>>T`D`a!rUZ}uODxt1nsV^AGpbMS1RA0LSyCJz~m$A zleE8`x$Zvq(Q0ymT_{5s)MG%J!3#Kk93$oPL(rv}q<1bpq6Nu*_2Xc$Y>$45g3MJ8 z%ABuRDmcB!vbB~aI|&QQzD z&>e+Iv0ddHR%E2 zbZYOjxO*eJH?TTz`Pp_0C#2itEIwK9goF{4S~~@&gHle`G*Zif)}bvOn;*`*QraI# z#pu5*6?@8sKh#WyHd5r=zs;+=Ib83r4TDQ{FMP5|DX|PUMBp4E$yKl2ixh%wXph?M z?yA~xTF>x@lgqjkU~b*^by%K58jDiV>G9_Go+br9E7VWG8hb+xRf zP{jv9w2cIxl2*KDLQQ0m4x+`nImDk^57dbI!=J8{eN=h~RgEJAI8)yng(&8}xp% zv8ep(-b8Em^OJ(Y&`S1f3@w3ao>=p30xi<@nf2BWHHgj^UyUxb%a&)uGR(^3y>&`x z7vOawtCJ^OIdYt(*s3*s(-j}m6;_1rO=C3mVe(zi>+9ruRYgpUa) zB~A1tzy7$1G8BEPw%Ci#3UgR}+5D)J#X#}1ZyHVE4=D>%MA^)~kK^v}Oft^01Zp;WtIkFzf3W zyKWy9;+_*Xdf~x(99nGZA|{;JrkADHdvtQ?DrHV9Nmrm>i6)ok%xD3%@r-lG^!S(_PU0# zNsHA)V>sur7rL6u3I=i2E=f{YL{?a@-c1}(n7#4*>7GTzZ6k9S712HQ+a zjvk%>hx@f7@&Rz#CZY>_>E9ZjJ={(@Wc1mrqJZ+&(WbtK?ob&fGRgTi*01+zH0Az| zSye*u4HQSl+1&QH1{~Q8tkiOH%%Dx66CjM>sJurK-*<-dsZ50G`l_uB5@z^sx1Q>J z&tLQbm=wIigmr>U)hGI}O^9(H<3w;6@0Jbz&QfMlI()%MGkaxVos`fSPOi1G5n!EU z!b3I@TOxJ4jU+sCo|Nc8)Eq0v#ZH8?FjvA^|A~ZM zd4r|p#FC0_T+&iv#-9xZclf7CYJgv_515)7#jyH@we8PDo{E!^ICnUs0^e%!ns#%z zw|U89v5hoK0XloI5?p@2-9r!ZNa4@&Duw3&Myv^#~jjTxV%zM0cxo@e{jLp+A zb0)uEv8O ze5RtDvixLmTzgqjq&GLRV?@zgeXD>3>8ZS2gQP93ud`O#oIT46ac2*n>fvVGKsT~L zn9D7CF4y}cm5A~N_%!!DSp{eXoV!cj2WwV>T_&1H!qMS!Zcki>H#sHoa(y~TeA2Ea zu+bMohRyX9)7ckLx~CxN{~~?*Pww-7H+}kDq5ZFf>38~+lleb$rvEK{%E`p}-%8

0S-E56w>OE#wowGjWS~=DK#et$&ExOpLG)GkhqJc~Vp*TG;mjDs~ zAPFK$qz4BLVg`r~d<9B!Nbllff?<^6#{X|SEFp8wGzWdf?*aIKyoZU5s+QxX!|+1Uw}Q;Q*9?7F9g z5$weDaRI~bVzz~0Y~WuUaKM(GE?~j>uKp$m#J^M52<#8u|3&wt_E;wbxp-wv0UPS-5>)7oL?P}E z3Ig@xq{0%$(5L<#h+_Ox4S*UUxPM!qD-VWj83yyb$%&d@sSo782l*+A0D33TX22MT z33iJiTA*iQUsfIXOHHV=V?aS2cC79*842GW^K#WERcGnrzPmUTP?&mFkIj7FIx;Z*)PjKXY}CqU#xgM{(k5SqWi`$ zKkUD19DgE$ferffeVNsK$-aC^zN@8t$sB%d##fRfzpPJvtbcvA71Tl&U+DpJEO{C_ zpyUS)PXYh!6~5~KlCFW@z~4Q6-PVPpL1l-6rV!801n(;h1kCYsfD}bu2dtkF*E5vy zXTAhwy=StLfPk-v8zJ`MV`!s8-s|yg`1fnuBS1osPx8}IK(O1aZm&E~gzg`m=J}N8 z>zlvn1(CxdfeP^QUSSrW8{0s~C_F{$xDDb( z{#ih@Iao|1rEbEd=6*&~H)+KjHNPzzBNZ|HU9YheA6qP5!SFD}mUD;|KRd}uK75Ka zMuzvNbD+A8RQ6;i+6YO)D_ulvi$g2fsJgd%va8a-{w}McyhmYe5GydG$K)Vpc~|Tb zcL%i0?66ZX-~(FBVLF3e9~~s{>2^0s89XPsYl~qvW{}--2No-Dqjqm|@(7X=g}kpI zxVpb0-F3LOjy8&2>E(fh30O=HE=>g*ysoPSYzD08`M02maX`8+CrUzv5-!R^TKNaG zRBHMd{k>u~m6CQ6^oEH7a^vBrN=E}_fDZczlpmj2JFUkLr=P04E4hC*w{0aqr!l1N zc6hpg^M82nCO|99&*8c1@-GJWHO3BGAOJg}*5B7&Di0+!V@k8EJR!=0Fh_KYnesq) zd^E;AFVQ22Y@r*QcA;BZG}I^*N}wZcvy1+E0H3KPC%|1tQkI_mJMfTk*o+M&W6&PD zi##rioQRfH#t(D1`QCG2W?^Sm#Rv5(Q+?Xn(y@ES+}BmU-jzqeY$?GLa+N#0`Hu@z zbIv@FodrHk9>TP8^6j{D$Ki|D7~WQsv8A%rSUs1f-b{NHETD7*ev5$;T-W+1?0o1= zZ#r*CFSWK33edH5U<#dRfK}p8l!wRwEVK%%aR+Qy5e)vi^$o;*x#X1GDB(MVv(LrZ zF$dWe&O0X2{Tlmwc@DJX2TVXM(3Y|Aq%oh18jmm^h=~PrXowr~6M=l!N7KjkBXR)j z{ce_$PsMqM68DR?w;BL{1?eKKn=`DSqwU!G`Y;bsHCG1=PlYR}RCyW!$D|w?`^QZtyUz*SN-((hUtVU2bL|$XGjRk&nCgBsVTZFD!2-v8Ac$lX~Of*mSWL2L5m!uE9& z9*KWEN}>E^@ST3~x+F~2Go`wZHSkwYSibFZ1q z9nVP|$3t$|wb1B_g^wC?N@b7Vfe!Ms9HPr$?SaNN%p)+qv~8ka`>+fNU}B)UMyRssjp(~L>OpT8Es$jo7_nWHi)D# z?Su+^s$Zc<`1*-=Pt_bK};4Vj|E`c^2%CY`MA>FM?q%z7!w8)v-pmH0^06D9!! zR9BO(A(!kq7#__gZ>*zM7c3*(K=@FALV1#5mn87j-mxcPk=DU|Iei|X%x|Cu z#)i>67_`s?kmin_&p%h{0$PR8t#Hy7>u$lUv0_4GY;9tgUvJS}tw4>}qCLaB(($iX zA>0U;(5Fh{ywddW&zBFOAex|FnAOq9<%mvo7f}{slNIXc>T%pFqGP{{`ZZ73W|FS9 zEl0kv`-VmcJ$PJgg@D&eu0G#S6@Q3rG%WtX{Dimm(RFc(G~DP(9Lv50R$DFFub0Yb z^l^&h!A5iJHpBu4ezc-bYWFWvWGvMZ1 zh1Z6qd;uN)825$xHIYwN5w*2k=;L(cepwsdFKV}FuL zOdI?mznzM6=B%~r!F9V)AV9-th*-~#&2Tq?qpF9LVZ+`_m&>b3p0e+`1ZC_rtIbww z6C1_;xNC-W8)fvKuMnmoEImn4688N_HvFjIA!PMY{;aIu600L*Wk2J}S+?2w+fJ1_ zbT_$Du^P*FRu{a`>e{ketRdJH?L)G1Q*YT^MlzMwG)e^}Lcckd^ z56kPlyL0TL6i%22peIE3%L7LsvWcXX?&YCxYWT9Q#@#=>fFSG&de82-mbKw;BO3xC zN*};)iR~OB?T?s)t<=66?Yk^mPL&dJQ55xRUed?hhMBtu1d*FI&A1(+nV8@B76qbD z277dULNS)%?mcbf@I4{g@Eenedr{i;p^x_S;SIra6Wt8dVc1M`^h1f<&56u7g-Fwa zQu;-fZ2GWXQe?P@CTD9D5u6T%+^DzEMv_w$?aItpg13@^XS58tV`arr&GW2R(Dstf zV6HW4SChz*EOOL#2=5`UN@!JbJrBT@qiVXh@W|z7^mrnG$MRVps;kfwGg zPjHrXwtYd|Jy9qqNO1;?z<1i!fXR4Q>&pw$fX}mAxRrA=%W;-#nzT$Z@^2&dX+?Ab zlKf_8-_LVi$uF;gG`lmP9g4zuoSStSC`)$Nox8sNSs7pd;T+ejfaEBLPO1hrkPf=k zJ1?c@;`S+5Bu%_U&I!5{@;8IGzVdLjWRfzq`jIHm^(vT_=7r-h8gk|Ip;x9K{psVb zLW}I=tBs!%w?d1#&?NmrEKsAe?&yGlCC#<#E~R5(B@6unTcn=-XW(a3FblZ2?#gVHwwWfcztGgS?*Y_fg-1f@Z0)9JoFkw}R>8M&HLDcp}|4Rtz{4eTvs56rB-N0Sn8te8Ko z__-7{a4}}rU=>o!FMKK!W0EtTTi%?6O?e~>3H$qRZ_ruHSAVoLH6hp@5OkV!ZKpth z$(oKw!~5);Yee2(BW2sB(i~>7!&h|Ce5rDs)y>9`OZlCo^(FoI8I%epY6+UnS-hot z822lUdPEpT+637=-}CBOsy?H$i0ltt1Rnwc9xDSCf?O#c>t9T1j%~}xj`LC{bZKe+ zG0ylI$)8XR&ki@aGpuqCu?NAoB7$EF1oWv9k|^7so`ujJQL4KwQagXB58^iy$QgT*-bH{i&f8zfIP zw_0;&?*fmzMQU&-Fsr+(hC%`^t73kFRV1ZqS}*{Daoc%cor@T$PcKB+%pcyuW5= z-=4-==+B{e!aJvU-8?xfXi9IFjTk|kl2Z@f>P}tluWqW3mINj!r$6)T6|9OyX zfWDL3O_2=AqG+FR`|VWgr-00JD6~lpZ?wwVZ6)ai9SCxR=_FaCWq8{AL;WQ?#1o5) z#G>T!3U^!CmIE6tD+4^$q2Qc@FE?PM8{d|_z>*Tm8x?)52XK=r3_}sv-m{YPv z)?4#R0q6@%wW-0qWdX{aqfy)Uw_gSqxMxnHRA80MY=m?IP$p z2rXMB8hS1CbZm{3Uo!7|ZifP`ga6H@b;a>oV?B}Db;ZS9OZtYrsj^o}RoNUKCBD`; zKahrC9X`*;hT;Mp^Isyp@qoGdre>8{NTNywGzq2cp)aA|#%6EU4k&0mjzqwP)^vY% zpUtny`qyZ^$~zaBQH@eGtw=Iyl_w;)lMenAinQr=l8h}OR$u&*b4*DLW0 z877R=qbrIN1c`vdb|0?_S|}bTFW_7(7Gd-e_7d1MygOU21+9sQYz3PYfoo_kCv^-) zq@lTTTkycpN?Ji=oHX%`PJGal3Cax#tMzIpK8fGKQY%L9OSVEd8QX;M zhgyuDC){Q7r5#?TQSgA=;@#9dN7hXg9E5TvqXjaOTF&sBNJSke((4M;YTj`@9hBSQ zXAK2H-N@7E2xS~BZ9O-)h&}v4z@t9EDwt_wD3boGE5kQLRfQ+hxXfc=w<%N?Ll$#! z_)c+bz&}=gVOXludQBy-;$7wQlU8`(XWK7u$dL2|Z#++WE}Yy>dJp5eb!z%V8%hs^ ztgK`eR*PyM38ecVVN0tFQdL>=FGlmMl%6^np@yAPaiNdQY^ZYy^P&jMzy_xgxXFRD z)P+JZHXu(QuAA29%$8}-mU>X3vwcN&w`*tR}fRaa5K&d>$&jC)4@&W0>g7| zH-|N-ESWksVrK-r#9No|)5MylXm8g`fP?DH2{U z{_%D2ix+>waNx2JS4-yksO7DbxJP<2V*^gvf%CAl?>X1#Fbp+g?M9_@$QL2S6llh2 zPc{voZ1^pey5e5%+}xKg8~?Eaw`P2P2-mbR^`bV%0fD(J#%xO`(`85<&o^GbC1tv_ zi|;dg7*+1^!8*8f*xWu zw*9;!C?(ymjlze$v!`0mjEUo_1-;ny60jUuk*ZDp4O4=#UyGslXr%iw4?{B^?@i zrd)0N6Y+VSeQ5NkUS=t$)ivl*neXAQFKbPrRsC2AA;}PNG8CJVdm2=}TdEVD#S$a) z&XQbDqsjqQJDqbgznGsGBb&0Ob*aT|40s|~nv)B+tK4j3HnC%^3VVV582W=xEDc1~ zJQahXe%F*D=i~5Rtx2z7@87B8AVovgi{y8KPQTcRXr1(^7T~LP{L*uAAAA=JBm{m> z(R+LDM@T3omga5Ly1tggc$>O99zY5T{p;8i=nv8wKF_0%lSk*lZ8JQ^^IrRDoA6_E zgf|8sUaw=y=*7xiP5~rkiIkozEn39NbnR^91BXwVEIIxEVeFimM2og1UAAr8wr$(C zZQHhO+uCK@ws+ap`#f|<-01UgAJ&K!GiJ;mFf#MY-wt{4t-{wG${vxE3v&^l-7Zp4 zUi#7^d6>S%<9p-%CBWMO#R405>|q6{i#c)J9kVo3-sC=LF#Joxt34{4*&Pm8!W%}h ztmM^z8u+OrSiDb5GurAr<)_Bb$b1QBJU>sR@nq?ZTqwWMdJVFlTp8LPF?*qR-b^Ti zlVIt`aKEWdz}|?wCSB(bk9T5n6|*dqJGl)j-I|_29W||WYF|{Y6N6&jsj80Ta_oTj zi?5TOq|1A%QmwA!-Uwb?a^PTb&tg6_b%yIkdBEcPqFo3i8z1lx7xS+ULqAlh{SVd- zVKjcval_YLq=w`$Dofn0o9T=2n0XC`{UWI(D5d@_f@22l>T)s73?RYmr zX0%h92lcXTZFR=;sA@#3gPSl?4@B--5oCwDu9wo}FQcDr8TUq!j%8RZ2&aQ5Baz?F z?w3IA9Lqz-F`;F8r*nNXTpwaZ&*Ne1JXuMP4&7P4-o;&3{mrfn1~rYW{?zVQ-U=co z>>Q}h>%ytV9%)@Jw|x~@9nkm+I1-K1O)4IDLLYmQvo9@QN?)z0x$`oo;1tw+uSiGq zkQX=a9AMX|Qp=}n z`=JK+;^gYVXU*c=MYOsnjbgccoAO%Wlr2XrMKFurF0;)MIYZs~%DmYW@)Hcj?6Z+5 z2WXywbvaQnpwDQ$UP9YiJ)db+A!KH0Lp@>AY{d+J8c!+c?WZow4Ids$YYkD~@$5`9 z78*NBN7z7K%DjosgPTM2v%coLxB?54Yz=EISIWxp4$9#U%vl1r4F}anmaIre`B}Kk zCl71a^1`sS%HI*4js~&nw`AMooY9n_tI?`nvjX*DDGsb&oz)~5@>YDxQmXH z7BP60n;RPHynE2MeyrImE;;Sy<~sC}UqW+3wL;d2_XS%mU0T*grRmUf`2LLx3N~~WVaV$RX0~y&|y*5Ziy-7w%@Lh4VGTVrUhQA{}0m4ox6_t+#N8upP6 z0I2?O%ou}|jin1bzp|X`(xdXz_sX`I-euPL(a<6nn=2x9_m)!qOGB_j>s!-ilynER zN@Pku)0CI>GpI^@cm$5<&^q|%Mp=ocP>vIS;OOF~LT;xe2Oz9^)MuA`nBIJt^J0X3 zikVMeeD#hQ@*)2E?MXkgPgyxBX03@%f_3XM17l-lx@l_wu?h1V%O%!mnL)bO%@U^- zwDuG;P9zgu&BDX?!|I;2==#(tBIkRgPGgoYG}n&2SShA337!)imGMI+#P6>|2`^C| zWmR{4R)zU2pAe$|^{r@#&f<(8Dk?k&neRZ)Xw`*LZHzOPYe5xCr55nneAz^ku|Eod zoaWqnYq%D=yt18Z%q)_I_dbM9j&Hl+IcvETLCW4iQuT}-ZySP-N%kI<1+3iKt>X;C zsZsRaHYOhWLH_B8HC659)gw}Q_2DC}ma5dGj97rlju6MCyIfxwk`nl9%Uxr?^Gh^m zDq4KnR{0Pxw?hA?6s}vnr$(z`)rQkV6path8h{c5;yQc?vE8n}?q}aOO#UBZ+Z6q4 zKN{$yy!7_|r6t%pwuP^tZ%$yq;tefrer56bn*`6!(`XIwl{dLg>KrT;epaw65Y5z% zW+b!tS*DytY#U&i`+dcjwZrajBqOjLJd9g?47Q$162T{{6)jvYMg2qG-Xr0u#)svv zZgbl1W8jlBZ=EIK(RPB3w|w`7(3p?o>$R8ss2dc7XDG|w$+WT^#P5>7Rk&!|SE~I^ z8W*&ll=vL(0Y1W0lW30ets3dv(fK~2n9fhbJZ~*atQU|(K(5;nRDj1iN@ur_Tm~cyIpd(Tbr1S ztCldNz3Whj+jFK&=hWUemKCGE!M8Rm~&7r^0|5#kDdxHKk%Ihih%z`Y5xxi=zpiQvorkz_55F@osof& z`5)@+|4%A2GBPo<|4*&G{a;i$5|3Smc!!Wv!o9qNWf4{?h8Y-!ae#qELdxA;3PLJ8 zg#}_UcM$?YDG7=G_I78-yZFAWpH4wMW27JC_yB?6Ft7|jglF86V+g>i?ghY4 z5THK-q`v|LA73CKUjBU~{0o}&TQ=D9$V|f$o@BS%&JOCR4 zcYwZ*PRbR$Yd{V#2plM&Apk7F5ZK}UJ|aj9_&H}#0Yb=`f2Kiliy%P`iHGOT&W>jQ z934-bgSDj_T>v+VA@F=?hrqra0>i%h5P)m}@bTQVM?)sy2b)4V|Akka8iYFm4v+`I zy09QZ##C?^H4IE3FkTMulgbL9mK?%*{?MgAlmp;T6>LC$_^-XQzvV9*Na%MV3`igj zZcYG$JjFDY0cdMDKugN9CjuS>9RLE@4=qHCyQ9xMco$&d%YZsOkiQ5V2*tz&Kma`C zPih`C1e~i-$9;#ujeq(0=hn1vDypG@r#Lt`1k6FuH#Z+B1rCrGMK}3fer{_pXV-Ag zFOZr7#`>i@l7Tw89x%r825M2&efl^sD+nOM>Cq7~Dmsur4j=-20_>gr<42xc z0)NI={{%edn-@1H7hnxuQox%~Edf0L`YxRSI|Klrd+3|jZ}#6ki0piPfUqEh0Cfaw z3Ybs)D|nNLmHfBDcZUk_ebBw(>%YKne*QmxOx_su4aC#CkNAK2Kc=b)?W^kRXWz|7 z{U7sqou2?aoS~rrJ3vF;0S}Fg02B@R0`B~^7r=ymqk``6RaG-mi3Psq4DhR-@&k5$ zF8R0gy9eRk?6tGv;Dw<98@`#3=-)%$1>p6+e&>>Z!Y6b{Imc5!b(i6?Eb*B zZQ+0Y!egHUw7z~x?;D!wBEmn`AG|eyHvFQp27PrlV<9jsuN?SyRzd6!kKBNAluho8uI4c?J9hYt~K#?j61se=y8%#FSB_k_;?ZSd;ArH4m;1%rBO zJtA5CSAVUIrto#TP0q8yVCuRTysK4TqK;c?A9vFaq3F`zLS& z{ELwzdEMVTpyB)^{^YXKzv(C74?w@8qk!ED{et52YLH{HqF83b{pWputf{)Yv0mY9Be8c8z2}VD-eWQO7)~Wjy2n3(Y`}Odnh(HJV zDSz{Cg+GQ0=f`Q_N4qX;{~h$#k%kxn1{%uCcLd>uZL5W}>#a#Dc01d}O3X6ZWs)*J zd&vuL@6q|9olqw~1`zbYgP$ z^(|PIQ+0N#1A-%WCGoUntG(*p=?(B8Uvud#1}cjB2F#$?ZCt@ma(bRQfkge&wi zs?~AFYGp8aCQNc&O@L+Pcp`xPTd`IQUaowd6y$Z3;$c5Q(w(FwPC za*bEBhTTX5M6{bGr^d_%a)5$f%pQ`lpwOayWvmtZu#irhm2oHkH~yl^6oy%foPvjp zDVC65U|DYdaPX`n_X4E5vPfE&iOZ7aI8%s%w~SZ$y3*aAvvLU6#Y;nSM0E93MU)XL zz(~6WN|WM9{yg>_DjuBQOvmvyHYj~2@1`t4Zhzv5Tq7NT7aQ&*%6fE$9eav~(P(aD zf;q&~t#BeoP%(dbo|npzlnc5&T?}5<$F)CJ>(xH8zYb?h^m-FpC)txRC9^SX$kcDb zL1Up_=VL@RKfW22;z#B7+B#j-evmY1!?f>ZGZ2SH^GT%k}IYZ$4um#&Hwsy{DD)1+2%rG0+;x7B@6c ziM{jJ2r?x-_KtY6kH#sMLbM5ftqEyHA5ki+KD+eH$6J}33vUFxHZyUgG0I(^7A9Ho zzgsJw`O_hlc3lj??XLv~QK><=Ux7-Wl>MzDiICYah)?JmK#$bV#+{BXPi571VEoLh zH`=Yf85^*l{D<5)taEAROGwDljV(Zp{k`PBm1s*hNoY2L+8ip$330cWN9^(^N43}* z2(*jJ>C71)G^}dNYR^GX%mGBpzs^|#R4cZ$2`pb_A(*dxvT7<2;xBlSHu4d)fn}-U zQ19Rd8M{p8Lt!fy-y>k<;!Rr(jrJ0;GRFvs4>1IZK(!)P1)jn-zCR{*IN;LB^NmY5 zK0Cx8X0jMTQt9Z{cESmkM@yX z=g0?jh=B4SiBa_y$&I$B5}T2&25Nk=bjUaA2eLFaC{ioB3WYX^KTn2>_{L^a1$j1U z(vhR)8OD?pR2Zqpz90#HQLT(BNh$mfvlP-BqpP z-41K)s$@-A4H05%h{V!nm{dTxjGOtllR>L3Kko9{jsv0?`03Z+xQ$_zSs-?f$grz& zb2{82t4qh`M46RdvQKjwuKr@r${TV7CtS1lOI9g^J}Y-doQZKrq%F6Xp5Zj~Cc%BO zr*fk$)at{d@P1*~oKKmR+aMger9xq(=y&Eb;&oNYPj4y@SIRNV`gVLt z;6xe9laJX=5f1*85(fMc1$&88^W zE4L2BSKrk7Ik>^qP?D4m_ft!f;4tRZp_I+ZxCnfY*Rz(lc#z0W>JI&}o6WY)lcn!q z45ViUeVQ=d=@J8`9fpcBZmDD44;2S>5Y`(Dzf&txK$^k0iXQs9q1_B4BP6BFk8oYm zg9Mfw<7`1`1UYt~ihaJN!>`xoZjEkV*k&N!m*vGXa!it+x$v5smf#$5Q!ECv>T(tI zLO(nXLRxXKLE}5CVWE25JQoXRpmPK9(T-5-=S)Zszx@gPx&u;RM1PWi!)wGq{_36^YMrRi!SXVAXL}tqbgm+7ymGgZ4Byd zC0{i)9*Mcic9mca-!*5~72m(awWwg97#l2sC>En%k(eyXpU$eP?jA%V<7>%EJGDPW z%xn^EVTOx`l&WU7 zzDcylcdA;ko&E%|R}Tp^$Ezz4+1%`|MK1m(fy;XSns0#9t;g$d(s zL=^s>{OttPbcextMn7Js=s7G6-#({pc^VIUXW4c)E2SfpwP7VNv2*+ZA)8BlKv&*p zD2^z9SJfCXJZMZrC!j1S&=}+N+1@TQx7~ zb5G@k7{N6_5ADwg=Yh_gN28XN-u5Xb%AIq3<#Cy_8$$k(0X}P6=2%RL0t;c%I z99ts?w3(VV{f|0z2gRUPaKGG@wFWV}fG&qlxW`q%t0;&RHtb3Ch=4z>uDS%|pV+4~ zr#T9_MD#`1(%P4FDLU<9dqBzKE@;%cBG*}uPulc0xR-T8M9iR07-{kNKL?P5dzD3n z8r>mjb-YF}tV1#?tpqKL)WE?{*tLV@^}guRkbFqGL8ZaOe9F97BluFCL&fcOKOvEE zHuerj=V~t4iBpm)pCaKK(pBM=%K(rYs!fS9vLfo7&pr)ymK4h~2UljappP4>?$UNQ zAe9^5l(wFG``M(>fu%o`-CN8`NNIPz6dc|1ge#Lp&5-A!Rg~$9wmw{Hxji#~&omJG z&++SV%uWR`o>qN9jF3`C^Tg&x2FJfZNoP}RkA&#g^|wgPVP>owCPmX|E~TcHSn4e@ zKJ~Ig16J}o{Y;$YKewlVGSt+L2sm;+O3-J{gu96E7XBqOK~`cO{OPJGv(cV&S#E}^ zn#`TwsU-HTSGMTRVR-aiaCk#9%K}D-jeImJBv>8V*xH}TXb3U&Pluo{<_d^Ze&!t`gD59&Il9I5qj?b}Zzm3}^|tD%nQvN3)t$}DIH zVhuvoQ-k2fJ}%^l^21P5Uv-A)Nd>iPM$QR%-BB}=>xEeN08gJ^^YhHJ1*+Qxe@Zo- zf|#Pt7nHZG`4Mb*bVe-!cB58A=mXO zNc<&;%#cS|nNPXH)vi@lEgsW!o4QNkbO}IIg|CDyP|p19-&e#YcO6CM)LQ$M{S$ZB zk#B|ooA{D*y>AT6Pt>UB+j!RHk#K^-$?NV+sIaZ&P*|43wUBbaQC+QQ&@Ck3mKEvi zQENS~mIK!$;L^TF>#SEj?TMT3hYn(sVUGI54XNTVMd9R6JU-Ci;@GA;W8p9iCUO3D{n3sudjbmGlO?yO=t?hEMxe#5F{PNW+ z^oDdu+-M^2ZE!AVmfc=e3x#_pmJ2fCH*B}8ZAhk2+q1Q`P-a3})l6p?w;}-gHOgvZ zr@W}uI=N+By^kycGk4mrUS9ZOn+(&4VOz7^F6`xEB{um`n~IzFU}ZknPex?D|H+ge zWI-TrfNhoVf2G-)g1wnf8kO;D--8+HJi=$dTfxx@pG9QxP}OfN6`WaH#&SyJ|8#nL z#0@jX|30*wt`u%2eBrJm`bMuU#|V979@rON)$^DhDt{kEq@3l+(+v^*20^d(cT8vd z9JSF#=-^CZT} z3CsI+wH0wlhjMM|&a||Re_b{g5`OJU++vFIYDIe8QBJgtwa(w&w!2y*|3N1MSZhLG zc_Funt9^XMPzGF8xp;{J`Miyc#pgB;;`}cD%JB@Uu8d;fJv>hDGI_`F%&Uw_wgv&r)UCMC6b-zebG9cbb zFnlNDL&x}*>yElVsxIClYctnuC)iIx-HBd>hiFw6Ld*TxI*fc0JVE!cqdWJh zh+&fZ#M=5HhqM7$@y{P#0s-5z&r>V#qyu$iC%V1J!_NZxcqYg4mh_1(- zvUZ$Phh>bzYEBaBD$i#t1wQve2}_vBPpqXrjb&7w?lk26Wf&lT|EAlp5|W@&kF@*4 zgm40XlSLI}W`)2kx8f`8URY91l|p#lzYCA{i$lnXJVQ2fYjqQ3rJRhyK^&o4Jmsd+ z6MaSIV==thKYxcpevGXbF;~5{?541bDvs|<-i{7D!itdW^4-n5!mu0=X&8_bZJ$It zy+K2$+TVqr0I`|lN$1`n@rsBMw~`*-n)NkiXFYXkV*IDT1OOhf^h3_g>OYu=>TuX3 z`>j+9w`al?y4*XhJDn_E^bfZPJp+iEmhNDo%ensSRl9ITt3tx`;F2Qo&|z?LWUj^0HEOX0Yq_1osT;94(3Aj^I9v zy+lVrETu9T5pDIwaN#4X;1Yh!Z9OEJlqD>5;-kc6Yp+55xX9#WLY88dIAOR--PAI# zmzuNY7h#xHZ>Tjoyb`nbc;Ah5M3H1`#`a8!WX(ZX3?JI@zu=j0f!sDRCbNGWrQEi^ zFZ@jt$Cg0z_Zi|4Gooz5K7h0^LDRwvPp=M6=jWIANs*Z%4((!#^y9%!9`;RkpxW&7 zuc4NBQ<0+#Ir47lVxDM7YF@{9`ddnwM}tROB5k%21w6I>wam}iCDpnk8W&Cs zY)!Ki4Z?{C3+){RH143&V9cLar%Dy+@gcaHGHR;N%;6l{`Wp!y-pa4CcLbfC=gTSS zjZsT3^+}P@vw_%rppBxYhK=M<_gT|qgFSA4Rz*1%zOT;rP66t>3H07An_-cpe?9wt*Ynrt) z6BxQy^jY#zDNi-y{i%nud}7h88+EEQsKp>+JKr(|qRcc6HgnmZ9_oQ5|LHGQ6~>va zjtgpEBPup+k;c&FVaUuVxB7<-Sh*^h5Cw+dnFiFjO99d224U`tNYay&4e@mPRlg~I zmaSo^y}8>d)owg?Gup4r4no9n2Fqos<))qG0Z02wA}(J8@hLNISE~6q25N;kspEL4 z0XCW-mLmrdB8+QNzGPwH5dxe-NJ^1MJ+ICN-E165ER zmzHXg8FP`>|D|Yru0(Wz`BLn zyPtvgBhu1EvPp%#hr2dRgdZ>Rda;hX7x3SLr-vV&+6E5-QknO@0r^{5?cl|bU~;!m@f@5ObU^Duzi+3Du?2D|=3ZglxRWbSc-w;$QG zFGVYx)+#vP?Lh@AB2fE7=nZ(i;`s_Va>uIzF7r$J6Qg@U^+}%?s`^N&+d}FVE~H;( zJZD_Wp?H~qEN3TeX2-R@=aFdMREhB3r*mc{3a68P6w4h3tD@D{u&927x<6t!ZYTG# ziI6%yin-`#&Mh?i^Q>en{7m{kd>!pQMJ-zMG(0bISC&1}rX@bu^-HmNrueR8NcCms zs1+OGnedI}h-us%Qrz>`a+952>6v!Ag*7T!jLq}L0wOubkx=*Z_;hWeHELS-$cq|m zSea9a@JB<1Nl6G>-9Q@b1#b5!-h})X)G7y%7P5crhyV4k#+dh`pC1WWeJjQi7uZKd zuj^&>+fmsWm7|dz8LhgoKCCo?oZVTGE-4Uio;i@bZhDl197`LrQV75;hHBhkPh3XZFwt)3>daD-XY)%I1Hz)!NAsG zdJ?N2Q%HTcQ!<+Hupc7RII>#m}cWA_6eCL9j%gU&kbwj|f$-2`Qt{gvy|oio<WJ-7&#z{W~8Kh%W_N%m-pAx-chWZf33G@!YSHhbc)PK!1~4zEGBG zV#WcpYR?)cxbwIizD{fEaR0o=o2X8X$4F?=4`V#jKhe1NCGXLZ@=^mm@-9*;q&_0( zEO=7y8Tr@NA#*TZkeef46c_F1g*V;@G8bV3n`_Yw-znd5?l}5g7#`1i7t)#Qd8M~D zaIBO;V!sYuo6rt$vE7beYSFnGho^K&jk8am)*uXr@Sv zjhyaFtGOfhvyK#C#5E_OC>q#)=ab!y{y)hqw?T80)M^JvGG^;?Fm_$n}KDQAAc^} znXU!V^p!yX$?%9C0YpDB+S^HwU0SL>CqY8jRer9LpQ)BUlIZehV%$Suh$H0`E45-_zW2$z!@dQ&I`|z0y@Qb* z{bdGVIvmaLqwj#~KI>5}7h^JOX@JC1T|LODwYnjK=KRw(>w9~FxfEeGzu_@KKF+sA zV>;k^^Tj_93$64Ezna%g^JLd{rbAj#VXTT!wrv$tpr;G&A31c@-Dx7JBq)aj2a*a; zTXef9FV5_DQ%Z^2T@#5waq6ikkM`6^ zf0YsN95%YkLwz9<@0^PFznJWC=lMBirrB^Sbq@}w*6b7iI`f{@#YZ3UI1g=!C!kU* zw>E7{?Qo^YTr8yIxTp)?QYp0a8go$(=W=D#gEm!=EpeR441<*F;`>=)J@+LD&GB0L z5q=7c<%e@SI;od1mr*#|tWL;$l^!bN>bvZ)~ zXbH4v=95htfwxu^#0Oy4^eod(d0rs@5KL2qlqhd^4`2x(Of5n}vD0}95H))rax=Zm zabUkWzUa*o_(02~;gi!?yK`E;XKP;`v1K|{MktQFSBMTJSzM04p|;#o210xXDPKpQ zam^tLn8I68MYmX-lb3`&4E=i#H>M?Wc0V-kHFG2*UAFq$bxMRs8NcKx?^Z`~k#|W^5edh6Sk_9u=|;N0 zm&lii#L5JsOg3P^B zr&9fiKOU9T+dBv=wc_}sh?2*%(96jd(1TT(9)5%bj;wanW0=s**p5<}ibPB@pGmaY zL3!F?lU3G2;aQ?lvU3b1G;#Tq4)bkzP-%=4y9AV{ZBylP!_G%n&5HYe^U%uitx6s~ zMHy<>xds^9C{R~0F#dzMz`H#2-FdW$A#00UW}*|B74wQVA*6gp&bZrcM7m<*_9_?!3OoX~=?cPU5Y)(JIulKHX-bpQyzHscM zaQS3=a>#lgdmV$}Q&pj#O);2tBirUv^kq8=n@ES*9b5peD>>WIct?0<-YU8{#V=(jkAf6N&(!Y%iIc3odQH%lz&L+a2-Mi zgI8=7^!D$Emu^o)Z}4bB*lyr{demdCo%Ar&aDkk^r3&!gj8tusB3$p*%}|u{Gh_LZ z-NtgkCa}*EAg=Vj;Llq^Sdg7ZW>K>waJA+!TC6s2;6Um$5Ta^IIf()PIrQsClUl{LaMx9pg+uW9SyNEQKUFXpLwW-{}et)rTZ6 zs8?i~3UNbAIOoqLs(T#KM;~7sCE>U1?2(=%sRY%ZF`PCsmPmk)x}u$$s|NJUI{_nI zi?l>B+69Xyj14b7&6`8-9zXCj(&49kGp_4nkjrbOI#&n^)|q?(rx7I6nHyvoE}LUS zNQcWtw0GW(urU-o)Z5Zn&SS)BH}g$1s!hNT+R;_8+!b0lC%hNx-J->R+i=_9Pfe@i zy?fCQ>aBb|<{ zKmtcg^`X}b;1jI9B!vh`l%?_(NK?Q-+43&`D(o> zSNzp_s0LEAG~_VDff&=|K(TXvsNF4#^NDfq2{&!sYai!VjOs7Ca4n&B9qUUWUqS(A zC5&QnmdvH$>%Gwwu0l@drJO0j6#N!x`DDXt)q=J&I+QL3{n~;kT$gG)A60l8LIz1; zHedHJqff35GLMZjGotKQ&BMV>bkMRQq&EH1iW8frUcf(Kpzz^bnIZIV^zt-4<@;)^t!-!Xv&~M>i#tvD;+RJf@_@3wZKy*F zoqq&>h9LBo#UsBqM9tU&X)9g-4sq+*hpXl@r}n;AQG4l4mkT&qZycQ(GStiU_Z`SgB z_2AN%JjR2LTB&{xMPhXVJcBa+|d>xG=h%&MvYys5?m5_am$jBHZ!TE0|?_f8+PK?BtjI7%#sS# zy_)i9u4@Ta>S`8f!6z3gXy;P%S zlMfirZ%c80mQZlS_I}4r(FR(l;VcA062wctFfsatd{3oZ&^VcV)l>u07)V!ek|^`P z<|fF2^1IhF(dJ`&Z85OqCu0`gi2S#8K5|zzP0T>t?nf`qQN=j8hIW>X)(TJ2Q zfpBpI+6=GwU_@{N#O3Ij6^TpHxjD2L1UELY24z8W|ZKKgJeU1F#6J zPJo#}#~1*MZ3YFzM5Ph6x!u73(4H5hGyZ-+6|xop(>gjhF8w=zLTm!y36Y2x1m?#k zfGwUA7Dgtp3XQCQfVtbh)F7<&p~=a(?8L>@)zra>vBbf(!JPcCxC5yFE-Qd>0paQd zlm+O+0w2fP1o*p-21r0Ev;uJckg7MbIyfd1!xZ1k%LDDm(3HA@Q0cioC|P0BO`;OV;w-i8(@BBB1i$11Kg(APnFcL4y(h;{J$0GyjA16YhX* z04^E&ZDTNo?~kuX>AO(9vNi+jSN|FRyL3fu2`y#qqaA(R-(qC6HdkPe#pWiUbItV( z0G+!H0Gzu{fZbnQ(FKSncT}0*E~&s78$ca@)K8|;UzF>I*PqJYK3J>)|FNWYUqV_0 zfp7XT*Ua?{8NDBdUw-EA_Nia|L4VQre#b9=Xe9Txwx8OvpW5HwidY+g)mwk;9*5P9 zi_l-EHhOh{AAM!meSLOna28O`t*?5u$%*q5xR8O<)!!JzV+uGY;4G@392uG)qA7i+ zR()|ZSRi0jTU^0@JyZZ*X5^*cb3MALk;{`42Oq;@d(`_Ahac`zjP;S#r?t?=hDP8R z9GsYK#7w=2k)ctrdlNrSQRRXydpKYW%z-vJdb)u0mmWZ~Hn@m>w#ivI1C$@q4`@d~ zj6XkuIW+)css0G)-~kKg`Xi7AEI;7iRXGb!@Z&HBAU}Yb05N9%1L+;7{sXT7V$u8r z*a3)7;69Qj-{3x#^QZdbUrFd+;64-9pZ^)J{~5pVCccp-cQ&6*mwVXXYnP=s;r#p3 zoN@o2@%*;@VnR9dC!CV@d;NFl7r%Gk?`C#*y?_5;_1#yM9{L0R>qitQz+M1(c$iZQ zDW6~}t8itTiV#TsJH?3a?LGrH*B#AB!AJn+PR1;X|yd>&J#V7{fEyT{HvH@<{CTB%WR)Nj04=B8Soh_A;{ zVo0duRBdgR=KEas?7FNeVQ<{dRs>lfEXjF0`q?jDt3TpfM#o7VJ}&F|-)h zm9+NC8>!#01aQdH8X8ZG1wKj^;LdhAr=x27bU4IIurY^Z8SMS#tE9V4M7w7~6Q$BB z^;B#zw!JfzS3QgbY?hG8?K;)`4{~vW`8w^dZG_YP08Q>TD7QJOM@>6HIm1AY#K_v2yk)kK}vCHS%3$Y=}NsEd9Zg7%i2bXL}$52#;C5b}2@LM7rSg*S$~Gtp~d;ht7gy zI{4;jPgfIb@2|&%tPCj`=}*%Vclyv*alr<<=RJ_rW|<-(-9B`#nmbptZ7M&AX|>-P zN9b~y`?EpYrny*+PQ~ih-D&rTZB)2QTO4wtEZ@%=q7NRa7YXV-b@M8EW7oHYJZQcV zFEI(2eHihr!n+RI#d~-{X9EKm9-|LP_CB%fywcO?Q_0^o2XVfZmA}1S@fp5t`%qlD z|Hxi+T~ellX?IYpT}aHV+>o&`T;iY`PFGaV`C@;un2AOj@Y*j;WH=m@YWd91u{oew zf8msskp5G4l9>w=d=jEwvu_Ocl5}*wea6vXw>A500gJ=&VId>uHK9CF@I|pT zmu5kFb4Y>>|CU4ab6pr}x>iD(nK@-NZeC1A;t?0fL?oW`XoD7{sV!N@Z{b8pFhL_l zP~Q_1>Q?lvRNL|78A;)2YE_*nXGb|@5Tx*pSmTvZL z;&+_5UyFF%vNGE-zQN_C**#bWLaQzf<<~Ri7^Ds-$qm|awfwc>)Lh}L zv8>cB6PKhM{JaS*OVI)piOGeRV{Fpj))7*lQ2teEww-F-c>oFA?(3KS0`73>^nXzx zW?61o!Rv-g^CPSBfiy>6+2FMxsNHryUTVO{b#zc^R6$*EG;Qxdox8#|CHhz1F!8{v zTOTjp#^8R>{%OJs?8n{G`5lOLA;UymL|8>>D$yz}h@>x0m!@hCET7a?Yj?nL>TP!J z4CU`8^jo9OAdOsB8K#zv!iaoiQX!hQXz-x3gOiX!$paU+=dBt~spE^xh(;4r8DlPP zx6lL>9@n(jNNL=F=CwlT?%8`@N`}>#rNo9U$?Ybx)$Xy$T6%7_l&5(j(DQ3Xoa7v& z=&XTy2P>ZKl)zBTylTCsEsOSxjUQ|HJZ>f6T<{YcN@4NaQ&$a~Ay+i1T+^IBwk^lg zO-iytryNi@;-mHq(2QlUUE~MK%LJ^n%Tamvdy&k})CG(C=UL__4M48FqLBpI6mr7O zr=LeHE4H=!`TDGsHx6Jp`ilH~h~tCOZyjRhsd6z(kGeXQ8i&`x}|iKD(>0WA=$dU(XQ%((mV|c1J~# zO0{CxRdP7)f{<02(RS)8K1ruvqDG=i{5wN0_REqKqg!PIJ5c2O2QS<9=#sxTX;AC%jQ zs%Hzr)b?9x8{``EuEm+p_h)Y!nCYl`^-^`lL?8agJ{@x|{{@^g<+k1oMw*~K-I=!< zKlW&S1Bt+i@w)|s>Bfxrr&T9)DEK(K9H18C?$;kfr|RxpLrbp|(tI(6Vxqg+9<2>E z2GTi)kv~d0_uOQBj9E%rSbs`Hb9tQkuDCWiQ&A(Ly8+i$U1~Y5Ijl)zG2J)G31A6e zgFv4Ka>$@>j6KMxzYDg^u855&jU8JKlNWRNo*j3<#_TkF)c!6i^!*+gr6S05@_%#- zoADR&q?E7m34PNABEdmIk2v{=>@bUM>9?y=T znYR+JFLr2pHkl4Fa976IY-_{65<`0FD1>PHl}~PoqP^B2*DQHfjqBYbO~ol!lh*8Y zDkV;CFDUL{p1ei6w2sTnO?IZV+nCFAM9F#o=?#^++}tfc{6CDHQ+Fm%n{8wJO;WLK z+qUggjEZgBwr$(CZQDu3ICXP+eBGlj`f~q+HTIg%TrW!v-6Es+A87HCX_|1N$Hp8u zGMX!rDHj04X=PS{a!9V$eL8o9-5lGCaT|UG^^604h}kzpuBx#@HSGzosK5CY9sp+n+6GkVTrdmM6rt`>Q!wM z2mqZr1wJs|#$AC-x%z%lnFD4GUgPMM#jecQi?XX{rnlG@Q=5kOBveAZrp5U{#Mc>y zsJSW7yLEf5A82t(J9|B**2%A}Z^;|8WNMZ8Z*sNDX=KJU;iSubv^46WZdHt_lE_#r zD&?S?aM>)?xvx&sXp4`NhuE`Q76_N~c6zLHJqUm~3-;T*&-Zg}63tgm zgYi@6puexJFo>E{NA@?6qeO`<0LHd#k{&)+5qhX=Gw?3g%UtnR3sJxJa)_h!&zYTZ z2AxSAbZk-`sd0>SdfQh-ury0=uWD!nEN-{u8`imk@n&Wv*G>9P{U<=wLu{btf=JAL&-s9bky7$C+AXM2KR2^GtFJ z+wvr?A=z{kO_Hh(yeP{I*0V;16h`H98sKbtn!I5c zW%!HyrH6B|Ks!2*n3JHYRwkc?SsIZ(t1@ewx4@ZJBE|nz&{FvIcRFXSDNoeJe&EVa zV0Uxh(UKq_&KI?X)srMnV@x9=ZWLVq41W7k*#?N^m&qkC3`mD1Ygj^Rs*`kF(_}Xp zbjq?~qQdP(S_VPLC62aE7^1&zX&6z#C?poG884~14X=35eQJ!gP6^x9jUs)Vp{-6x zip|fbSdG#nw%i+w{#?xnPk`;yvF6oBRcxU~Z}1O>pt}Ri?RdFYd&U#`_}@|8I)eK3 zGUHpk{|(*TaANhLdMzj9i>pSaV$|XtDf96ymz#7%k<(-TJBXP8=UflY^(YX6k7R;8 z#5MF*5l*35&>R{v2!DM@?CSgOo6`mW6M>#VWNZF9;s&Uz z<}e~oGEUb)#Bo-Gv5njBWsdOL88ho(l(qk5S+5YPmQ(1Q&jm9D0!58onOeYceac^` zDXyQd@oDEV8DXGJajQS@Lo`(~wJMavI3%h8fg2@V<^JOR+t&BAtV7@VozM7;U?<;L zv6g)q!-MPKFiVCLlUJf617WV9oJ6aHa5i30TNHBVP2JV?4!q4K%*{2Q?iDk5KQCEA zevA8Lu%OEy{fZ3FPIE8(yJYV-ScbN$0*J|jLT=?U#=H&uMP>qP)N8?<8z5~K4c;zw z4ob-Rv%66;Y{J$7RM{J%edD)~h>F$`S7m0cOM5_y!n1*4F=>559R#`iJt^waj&_Dx z(@KT|LO9CJ8I_G+2iBwpdwU`(b^^q)BS(Twp2pOq)CX0P)mlaMHQ+u|(xbLOE&$Bb z?8J;MkLOP*TNt}9k)5w*3v{tZa~#g+vilD+Q+c+(fN5%YWC{LuB_sZ%-JB(xWIvFt z;TjGZF2a1+PI`v=1Zl6GD8WX2ght+_7SJxc2F&ECYV%>M%nkoni>RTeLsj8E4ZP!1 zSe+uvwhA_qxVB9dey0IJZu6Vq>e}GagV&N#T+Mk7lH$~2s#vgAu>VX%o&$c%7ub3% zs-CWE6=G)ijh9tw;2%cL##p+I+#%Gw{fxoTDRzQlJKwwv(XY0-EaUahDf8K71JzbN zM<|j!Hs|URGzBJTO2D57W)IK$^}kx+oN%G%N_^dJC~_is-;*6(vsS*Aj0IyJ%JzCY zKJ9DK-PE;eBnYafhRjCM2T;n1)di<~KVb!hw#cDl5wdXigUsy7)F?#j-D@lE_c&7e zXI1G(OTzfbgJ|Mm_H*-PrNtaXubffLw zfdfjyP(jsZ&D9?SkoR2BM2CJ@b|=MjB5H__7XmO30WqHrY(i@8+4Xf4sPjxIhQ;3` zXFdqyHRQA-fBr01%aCr2pgC_nl(|Jtq}rfQ7xe6~^`!20*UQO&po7sy%C*L} zPf;mI)O@J^4e-UEDojB0xUCJh%&6*I8-lcymq@Pxm0QbO`(ttFBudNZ=@ROXuky_Bx1eArHmvn1Q{k$%%#=uXT+qFG*Fw;XTZ+v?|ys`x9PA zA5u6izV}AP9HI18Pn}aQh9`ExEb&uZp9Eydf8bnEAjeKJmd)oeROQQmQVy47kQJ%^ zPU))odK_I`grJ_v-rjdh3oiI8Z|(A%vJJ9B2FnPq@Vr&stxb_N>v|74Q=)3@L~JAf z6kq$}D2%PrZAg6*y}oWFmJ(Nu3KGs@6Hf_gHp(lU_FW7C5B@ELB78{xYTe|jK8V>M zK5?g6&N}es_1iV5*^7PRulyYwN44gqIqNU`Ddfk#2#3R2|HU26`#tpgI1I|s(%Vn* znd4<32~BgyyReb00;uPRu1PJip5{dEA_n#v9^41Rh#Fl+CFnD)G_16h`(MWEpSxBcidJE2cylwF;VO>X`Tq{~UsfQZv?T8Qis2t*E${y-W zacU!=2*uZpxKc8j>id;B)55jj*uF73lMjzP3Al1}m1$zcp`W!ZTA6%z)VFyv{1hC; z84P7oiL+NSC7jg6eHYS*h;NjE;$_NmfFR2HlOgDWN!uysVAP{D9jc64@reMx35%98v&l6ts_w&H#aYst*5EBwt$Y5`SD~lRY*^0d{D6jClmrw!4rK;hg1nsIKfvm1@B^YQnp;n|oofQ!+cKt%a&&$>@Mh?lCI-Je$;AuHP z8rhijq_-?*rOIM49b#IO#71;(ms|AlGGJ)-97uYbuwDHybqA4Z4jSXdM13upypzST z?g&BA;>49ps4H397JIEe0uOSggis2CAr*r!D8^g7D1^N41<5>i%LHQT*q0?0m&>`0 zX4pA$Gpj&()nXV=lkt)L$QO?vShH-(p>zo1IA3*aswVswos?h6tNy0-SM^4O_{A)$ z|0qbwpQeV(#@J)g$b+5m1eT5QqeBw!67Z1Ka@I{MRl)FIgRxY7_}N~|`+gm*453>x zK0MWmg3nK@R^huCgA7Ml)<_*B@n|Fz#AXE;yq+sKIEz-sy~MUC!oi*O^XcRaaXkAl`?_Nfhp za=RrMXm!0S7KQ>mr9Ni%^lF~5bs&37a*ek}C*NPTCLokDXf5?WuF3?KJqQJ9gEej7 zbq2Mq6*>u)`Z`X8AQrsyby_*bfB?c1%_3$@%Qr3VBQ)QDo~g>ozk10s>8NmeZUkO$ z3$g~1`z4<|imf{Iy<$ZP(Xd)p^GzeX?gj!iU~V+w+S1Mf)_;p?fo|&Ssrh zDuELj)?b#j)Arw`r1f(ZEA9bS;ZR5RtXh7rn|XPl{5~xkF^ExGVlq#{3b~O17EE|f z*@U;CJt025&aDr;?YJDJ6A6^roR6*wg5e&!AA;b91?QG_!ScOY@y=5{3;J0G#*`4k zIk(R<5o49It+7K>?0UjHB!)6;hB z7dhiafx z4`wxnZsNO|#G75f{{1=jsLv7IFCJf7g6d{<-ZPraHPTzVY5-8-LFsmuD@36X!^;fG zP|XnMCYcHt8>z)fFBfwSldwdzs-<3=pCZ4dG@Z$pCHZsN+Sc~T^2qhl-$Zl@K6a!R ze|App5P=`8&GJrYVYa`g4+WD`F$FuEg03y9w7rQcX@#KB(EO5g%AUW?e-(^eB)N$X z(dkL-?oFh>7?&(yzm*z0mT88>yvFonK@CPg;_?zVk*03Bptmw}8nj#zqt-qZ zLfx2xlso)Vw`f{DJus_7s%~^_eSHXLkkE>-2)N1PUvSqu*jnt%O+1r$#-_5m$dr#` zmhOSja2`GD-p7=;)Jgi}%;tKz=Uhy<$D=FUVC%HLIlTUsIjR>!Ah0@!k>g$oe-Cz5 zTRj|m&C9=~#!rnYkM3btO=MWj!wU$&dd@`2h~~&9wjC(JT_`MVHvv(hi23b?xOaG~ zg=Wg`Kc-3{ay3<%%bk!`PDg>j-xdA~$LXdWI_Ka6Lv!SO4gZ@tqfe+u)XfU&DR`6a zLu)605#a@-&2GCYT_nf`=J4Z&_Yd%d`e)9B<)ohaA4~mV-oiL{K+L!X$IrY9&0H%% zj%YzBw%NY61@eW2!uZYTRT!6;9oez&vwX+XI;(R9)sg!Z@j>fdz-p*UrnOFk*9=5w zs*}E0cc^$_M0pAGF9{qCIGD}GyU|*+G`K;H8LaDkxuF~cx>F8s00*f%FvD~^TGcD# zd9&~eLY-$b7ziu2@aAe7-a5R&N8&Y9QAH$emkEnLz0t-AtW8tGd zV)1}SJDH{qUq*`^@%8|{0h|Y8WpE&EzEP=z86CRvPX1yNsjXVZ=}GNsn_ zY&9~sp%Qay&Pfq9&*so@+#MXA-&uXm0#DsO%u1SvV@)xAO7pu#Pfcpv{F5AWPXNQ( z3GK|u1LJs9WtFa_-uvV=WN=*)V(V52p+1eofZt%we@#<>8Y5R(tS?s_`KBj1+GL&6 z`3(3w>J%U`y95g{$iAxnZPpbQe0450AJSxS{3k#Li1SbshtXX&EN^VRW)3;aNA#eT zC|7wm-7C%Ucl=J|fC^>&xTdOX7pi@{w35@N#RMm~e6hXtZu-ESRexD0W-o8?_+HG% z@iZx+{IIBc=7+5?J9d5JCxy&2pGzuiswa`xoTL4cfZa97s6We4o0(U3%tHl#?V=y& zJ%>*VMD_mnH6lVq5-#&7%qJ+Job=$t+J%P&j7!$+`0AEeG4#7OTfSW;xoPvx(rLJ# z7I0Oqpo%|NCWg5^PR5!4Xzag?40}LGH0Bu#672sfAV_;a9+{RY3OGXiG->e(GP?B4 zsYx9aNd$4;9MZ<~->3Bp7mAt6qC|6P(Qx#?P75>9E$mb+7`9zlFUBlMw^&=!IGDvI zK>+QPQCLl8y6tCIn&dWpxfhn^^FKz#zxZoQ*Qe}5c!{wW1WD;Vd+UekNU)&GPIOsL#MB~HE zIzbv6Lrnj&MW!Fv1qC^>WC$<^Yp9TWT{xdB%mbAQ0SDjDPfoGev74MIYdP%O(Q_yzc z2MhtN&xwRB+uY}(hVHi+S0U`%&>aFrbG_AmfurF3B-6}4MSIs!p%lueTz{{)B>!DC zj%AG;3h+*&z)U*}rDON3r#H#I*v*%PwpNQuaC93+X2f}aSE{o=%m=r{e%^@k+h z=8dk*8kECt`B=qK)%O0a8dqIOGP7r?QKw2(XyUHGL^LZDyq2u(EwzsM{7Kg;tkL(i z4|{Z*iZvR+MboNYVg@_n3| zTRW+SQT&nB49qxcG{*4;C*Ua`OKNxKn@sv>CpLzF6R_=P$hndqWI|$P@!^UV4fb}M zH+s{9l9iTOQ6YAb@UMPxvFPRR3yP>jyUpb$uuW0R*CrKeuXLZ@Xce0vT~mvCmp04r zQV6n~i5i7c1WWgjcSkhzmZ@zi7WBt|&3%FEWza+nt@1{Ni=|G$iMs@6v*Vp#i=XJ4 zhRQjX7l3rBmtUgJUd)<`i(nqg+hwU$)K67S(4po0F&mEdMx1%?)T%Jvct|64JJs!K zM}B>yV-aMw%a2Y%pc!pa2ShUKPq~m%#=_p@wXNE@{ppONT!4R+zF>PARV8S2m{0iU z#D_f!uw@(9Wx^~cGDIIo`523!t8rBVOfAA5odS+*Ia5quQKJ z!={OhbAYAsE>=29xUfq9T;Iu8WyS`PSMF> zABj731i_nTElVGVas&93-Ju|^I4HOg-% z>RnT}SogJx`BFlT=-2HXFBRVGO=#I5;zkdCH>c&Gu}PSkXC!SWYXj>#vs;M#D?o)L zB~Ci2jjXQvP-ijcO_1>%q@wC~(5S$0H!f!q*AYqKiG7ik7Y(0lf468YA{KUGtbrJW zl;F!dq_O3p6UsQ&1-NTY$1(BZoHER`mbwE#^6iUfH(F*p;o-RfWobu&f_L()+ZJlz z&ReX$K=*CjK1!W`8WypLv+lN+JcvPKVtJw--yWBH1_qTIN$C2HqyMdbhNP|pPQ{h% zt;a06GrkI^GESw>i5$LBxjcYsYBghISkwp)d1o0I6aW^Ut(yl{9%=53d89&t~b}@v;fIpzha5HwmiJIerdZHLKI9s(Q4s2L> zkO>sA7{On(Btcla%_cq+w3u-SDW+jgBsQo8P0kWMSF+c0E(sp|0!pOU;n!{sqHRh8 zx|G~;JXUxf>OZ>YX!YTb6PAAZxojsQf=7b+DQh93K)CudgCdunWh;6XhnP(iq91HS z8dm(OhHrrnPpHz5wFgQd$r({>v;RIip<(bC(5&nG~CS^r@Am9cOv1M|rBu;3gH+8U^ICS5!hq{j!fk ztSi6tE+|Px--;2y@u9in!BO;Nvzdmj?XIHG^+ga0kA1$P9l}Tt-hADmP9RJ-KT0a| z74W+|sK-AN!Rp>*)2hVEy_l$|RGd1c`k4rh^Pv*1GU1}D&Exr(Q#iw{ly-m6Nw1=; zIR@Y2hSOLrnOZa0=ARC5@Xe@S+us;!fvSo05l;~e6&fa#pCuZJLK1|nNT24_;5Crt z)`;%dL=-Egq7|3Je%(la`*4%mD2sxE{0d&>W%C~zw1Jni95->b$PV!N zb7(xXznKfFfRLw{xHkO+;2eD)KtL^ZI{X`bi&;B_1~ z_A~PM@~3KTS{(ZYgn+C@@Wgk$VbPzjuR_zyNApzR2kvr&rza2OYt5|E=?ZvqN!03P zGqs+oRb5N$sZAnL1<%_hTNM{B?_=Yqor{7`h|wImFl5t-m#h366e1(7@)-6GG@w|m zOXFUz*DbcsSkOQ3lcr-TAnH2bpcUZ%= zVnCqf>}AwPGCs-jw#DJRmlRxP475l<{c`H%X#d-7#}QwX&m8=t`f+L%IKhV%Rsc)| ztyoq3~Q7|lL$$S`K{!R{P9a?cN`2>;_T9FoVJswuf0{IvhoFk+G z=S*9qC36}0lT$%pj*T#on~F>g!_1cLXF@L#uans+Ik8wDYK1S*2;0-Nlj$`CL7o!c zKt(lJ{1v9(M%x85-)XTE!PTMr-Ka+wKA>(j$301L<^!6JF0eFX&WejWbh zEI?ohNZ|fMlzsw^92>aL;!?m(LHS+#5<#E7iR)$g5G+&!_;#-Ksf|f#O~7;MegNH4@JKCMHNQ5ibuR6b;Tk zh+RnMAdr~Wdx1He76y%hqJBRP( zfW+9+G;olcW6;I<*GUlaf>-Sm5Mj_F0fM-wDjc8_a6iMmn%}(vnMS;Zy~%s}zjeL@ zfpa9}{g`XOHITM2Lp&A1+=RUhfmkLW(NXVq(SEuV{rZ8(IZ)y4g4+9#QGLZn!wqMA zZ`!5{_b~k6p&)q}fSxYjUd9nZX~{_ja6ek#ZjU1{FSRl+Dq+8DUU#WjSxF#}2#63s z!osBefeh-hzyu&%q2A3y+B$z$9)6U55NU@%Z(_crV+Sh{ zu|mB;Nn(J*eps3VzVa)9r=V{R?{l?qS-?htRf8fwdPAXJRsxI+xk zAWz}O_+b)v@AvXi03kC#J>hfVROZ>V#fGpW#P+H(;8=X8D*=E-xxRj$}F~o$(F-+NlfewivOR&s<`&rRL?L~{x|a^H(T$-;g)(6tN)aw0KYupfE&xoI481W)Lc5 zV)yvH=V#3STwGiwkp1jW%j28^V^>EPy=>y8b#cJ+G|IE$>iP)Y+XvN~wHXWlUDsxN zz$Q9jR|lEx2B96?g3`X{cJ>d}<7-$N8Fmu)v29|U-BFwBip|ks(=1P3Ddefd07y1T z)WK7K0MR&1Wg46i2}ah%L+fo0&v|itGWt{-ye0^3zy!l6YIeJczOp_lmc}Xe&99B=dGQlg?au@I!RND)nvl+` zFfk|`VzyyATjYGS@?sHmJYvWy3R;&(y`Ig+quitC}>Y>Xsyi2qE9P+c_a*W2wy!P%*lr};r zB)!iaM;B6i;T>xxhK7QNo-2!pU*$LIV)$K>D!bVL*E1N|g_n4YtU^t%{xU`p88Qjx z{2gt&;co{P&-IVNGM^yuNbJVZ>IrHsJ?4{{+bVZ8M3>4@kVZ3gt)X3`E&gSU?U(cc zr=oWA+6eH2#4+0kEFvKncc%|lSv8kBv)vP768aZ@id4_vZ#@mtJW*|3khy?tPHeMl zZ--2C0XhyF3-dW-k@Loc)3Q8O!b#gI=THK>2)#kLv=G&fFc(3)j37<39enpReRV@H zUo60vQSrOQ1nvHrEfQwv;M5SBr`0eoS85mU<;-Jrf4@~U8loWyEI2qJApm?|50mkC zKgr9hHA}za(dx&SPSD3wh43O`Sv+3i1VlqLjB}ZTK-T*o51|&a=cJF6CL6dXI(*R~ zqDq7nS=$(U8OV-X&V%yM@Mgr1(A9qlc@vz{0duj5u23>Zq3_v5=``>^7qvT4%Tn-CI>aQj5Eys|{fCna#l!+j|}c3E*)9?i`b(ViTh&{HdU~tLtuBffQXc^EQ_CAuu*W+H8|O^A76m zy9B<>xv*J#&|eWQnkHb=XzeA7PjVA^p({~a%Tz*sKiyY-=i)ikd2Y~EclAn;f*Uir z9_PmFG{b$}#gSe?ZRBx1#l(1kJLA55@rJ)o@CO31E>_A7Y%$1~#OROcGuzRzb##t`7RCOJ*L(BY#UQewWzx@iC#u<%vx&`~X7< z_14FnIYMD>fslsMl1+8?yTp}9XwS>7_REgjYQ;C~Nz`%v4C;f1z}4t+%9*lX+g$Mu zI5JqmhISMr`a09`8+%&{i%kxMefGp(WGQpj1Qg->fciN&6mG7%Qj$(YjZ8vr7&C_7cY%vkl zL9)h8EWrR+3k5%fc9$A9g9kl%9k=Cvwi=ZU?_S`S34`-Ca%2Pjim%yNoXUt-PVu z%miv4&Qq=Lch4Yg`G=>Fjz&|Pw59MA-7N_oHo!iX+hI2V6F@m0hT&_*a68;eci5rC z+J1VGnl=Z<8FBdL{9sJ*c$z!l0ABRkG$>~5k$L!Ut`N~I+{<=u7ey{l9Zx!fOQMaC zW;;!;kF;ohu_4xBS-pu^6)iz;-n;li=VtRk#%zL3IP7)SGa~Ev%|UW(qn@|!ZPM@S z@v>Wo_NF2EOHwl}bdu8C+2rN%RqT)rydxVd`>f++(b!Tj@N~19ALBIc;>5|$e8!Pp zHXu@r)J;l{Gx*Hk;S-OWOx^U<%%kfJDxore<*ZCxL`wCc)u`EM7*9AZcDkK6i*4hQ zw68Jk!u)wvpE){6K);I#x>>y+_oj-SLZrBPc~!Y|PY$R!r00{YnBr$K6={ibtPlX^ zH@fasmdgMPvi#S_7&{-a#rlxLc70jvF}pH1)UyQ#PZt;sTirzA@}Ute=lsQA%i2dS z1wJj!#M-}nl-EhZwi%@=$3o1rZF;wSb7vdlRa9wvM%Xj^bsHW#~-EU7#r>&ADq_r7fEeRiC%^}0Vum+wSrm(0ol z&6l3Cr{_YlP1WnqY^ice@Z%Bm&JzEcP05T^+*zFjL!(aV@;>PSfu#9TjZXzH z3MX0kp}O2MGfWQEHe}j2N4z40_S3iH@etSED$Ci6$gV2eCF#J+S^CHuB#8*?7~3;; zI^WI*>$>M@I^Zk^GaK#620oy*K*FvXNo(I?F7-J>k=?WA;S)Yl+YUXm=I2fyw%fiq z7{u+-T0bQk$7YK`Zuu+~?{iem8`>48Aat8tDoDYvQ+w!`@d zI(7iBA|0&UaYmfn#q^ro>3Zaq>-*7-nXAqcbFxmb^{lpd`WMv2wZZW$LU|istiYm@Pxu< z^$g*=m+>4BxyXdd4W)WF8i2!6Lw~xZN8vNjy3XJ9h5Z&PAIma&7!!IuP=($p!-JKvJ9 za-VpeuM?fselUp$ev5Zr4d9EpppG+Ynum5X_bR~Y$08K{a{+pMyjx@N$%v3qeK%eB zXN{Uh;UD#$$T5lp-dzV7;ey18-d6?FYC#<_Y-pM$3;$`S`8=Au8lSmdnG0&F=TyyF zdjb(3@AOU>R2}6Cdv5iKk8DhKL?r{0K9W~R18I9pO9`*E5%b1lp*%_8-Pvs0UwgAD zd{*jU74eDp&V(Ufm=}Z@xWk1RYt9|M$RgKxJ~+3h8WTy%CW0Q$9tyh@1w+fmX10i` z5ZhCEJ1WwhDr51jDVI%D?KoMCP|i8-+WSge&~JbIj;;N2@$zm_qYx0yEY5fV(@oIo zJed{g4)2gFWNBfOpU!H^NkVDA{9Gyc$~S+W6Z2L0bxp+g+5jLLbT@^Sc}+ zL(qLT8-e$*T1Vtb8AlqH$2X_J;E&m-5caS%~$pQLts!fp@O2q9eAUKXhbo0c+%2zdcvq0okj`x>6|F(kGhGEsrAU9n@D=Hm0u@&;b~D! z1mC!hRH|~^Ukc;&^R=jR)AarbxK^6mqmr@2hC?B1jDw@-t-`m!Lr5c~Y3GgjzbB6X z{C8qnVF|<<#m}m#4U~p~O7=!WR;`yf0}0k=y9ixCNj0hzJ1nl@4Ilj`^Da$<3-mI8Sb6|FQXTOt=AHJV>VXzq!x)=o<5bC zJZ7i$UJrMECryC>GE%e6ye~+L^XdyPrK!K_sVQDX7R3dhhda*XFp;4Cu+Jo7C*Xj$ zqE_~iBb>G7aN^pmdkk&a)V`Z5k*nz_Do!g9{v?e01`>BJi=-KMoYxoRRQaCzkF5!$ z?K`iAq_y759=#4EWUyzP#wBIU^@2hrOzU7!yd>`TNwClq|Kt#sl3> za`AxfVddE46mz4nxzQ=5Es9uq{a2P!gC&Wa{H%k9sCGs|U(KMj1ek-JGv<>|#c#`n za(2+qfhbP-sDYs`idEF&$R?yYA%@ci%gP_;N#w;#ayVP32K_2uYa}MuOChH5WuC0~ zQq8m02Hu!^S>$dhKX}#T-xB)g?#BU@9Ccj zhRb}cRP2O$0qX1@Zz1CNVxGMbVK$L1>gL4LHI^l@k6cHs^!&EtiMy7+vQvJoA($Dr zVv?Gv5;}AV^rEqDc?+Se{q1+#C?r2qP1T5!zb0ypqDmD#w(>8LaNMM{ni`>{LS=%Y z(mt9>;LaMwIGZ{RxaxpdC2Nq%?o}iW78}P>a-J$Je zW_!6TX+B)Ts>d>1ilQsYL4A`0g-Z9VYPk)q6*+UP5L-SrJ8TOeROJs>F02ZOKiYC;iK5z3a~N#!FDS9WY1cQOt#7@94$ev zR4m^lpW;2kc%WM0Vj59Wfbh%Lbt`*OCFJL`Ai?F{!_FWiuO`kL6rCANe>WAnI=^>Z zj}bP;>a}NFaq8}jXB!x}st09_CK_erH3O2?$$3tUx6$ZSa2tZ@^>}5*U+z%X6QLo# zsXS4@&y<-cjPgvB8qeS)@dSX=9Ee{e^!a~{#8q%X*b|Z`jk|1O7%_II3AtJtPLwVk z68zou6|xNh(|Zsi-gUVl36OVwhqA!{Z{C;o-Z?3TIaLwCT;ng>bX3RB_IZjXOKQ$d zGn|ME`H-}gT40vEa5B+1Bn*7xy?bw^lb_Z2DBdWVww$Be;&}SaKx{-#*wt-$>mwB@ zZ4t`KL8i&aLgfZNlY5eb)LL|Oq6%7Gy@7TOvgkGa#W71>OTfTsOFmvt-9 zn5$MDDk8IcOv67{I${+jdr0+UICbjw6kNd1u2Jr!;VnY6Py$K-lfpZi+g<-vWQomxHV9mK=OLMr@&X-V#DkNe%nTlkAiN$J0(CzQsFH*yq6k|TT zI=eTefc`S06EE`F9!f?@dm{=59V6wit}7JZon*rt))v8l>>FKT?Lb{S$CXIN>C<1#}L7;32OA!l!bs?ZrJi zgVg|n-~7y?>7K$QjX#@@F@RAtvKWO^c9syK|e@#A=-(7BOXdb^rs;NFqu%v}@LelDyVre#d((ISRRoIWvMjTPXGM3hVO;)!uqcnwIWaN>5n zX^2uxC{g(Yc)K0Gk7isD!88X^oVU30x5T;X-MR;NwQJKR+gwANi$Tv;6fRmTLB2+9Z9%>wqVkh6blt^ z{60NPWIx~B#Z}WhV0|GN78A19SP+=*3hD`x zH+AVx%vTi1_(=Jsy7DzvX0i3Xq%4&~_*<|~N$rQ|(>gV(XZtR(+|v})tYvEFeNVmS*EVOxfQjw7`4Qyt;`&ZoWc!#Wr&;V(z>zp_%^Y2;6=-2 zspvw#GWKbpvS9R@;Id1nY$!6%=^3Wxp$@FnKGQS+kre3PIT%{0Wz%fZmz8v#KCxJ? z9Luilo2p}*QrcuZ2VCngT-FIt7v9L-7R%fzsq$y2uO6{FS92fRoxD(y#sr;wluwdE z{NWU{KH!TZO{k4%;;r$hK6vg_@9SpnpP)SX18Bi-LpQ=nu8*>HRGfv2+ZK)gLzPN z1njjG0%FI<03dpLes+3#d^$iPItDQCm!N&RlYkv010295hJycm_e74HW~0 zz&J7p&;zKSP=SDt`3^HX5pZ5b@E7XEO@ z!OiWMxyEHTxR)}!#sNHI5QMfzItC2p3X%@$lMJiCS`Yq37loY)oo52>@(OA-K!Y?x zW`_g>EzoC5PzK7>hir)u02*fo%7T^*Z0SO9hHrMvkC5fpTLS@f1o18VqW(lr#PH-= z7oLtewK4;C0TZGHLeqzYBp|Doj=dkS2bLx39Wn0TI+P&Qpck{T2jT@ddN#qaL#g`2_j)o&0ni`;p!5)%eB-`MLEv!X=E`Ra?WH}Gp5&=m4FJ3$}pUcE3Mq5{+y$UP#=C+yeacCR5xHtx{;K0a3w{s0WZ zyFMhr8`4bO?uT#k?-MBT2SOidc+FGa=U#nyq%m;g5N>90X24@>&66!xZCruNi55Nz zzL}P9^3cdJAE>QM7fGL#0kynmCm4US)Y*p&%a3f#UlE6tn-TBU9xUoILb<~GiNg(! zljAcF;+s|Eh@1T_-SP@LEgUR5+Hv?;Y)?d7ee5TXB{k9#8P8F2u#5Gg)0u1-I#u0a zM^Jy|ODybTA^N+T$k8^Ura^cwShBPRnMHC+Oa^3~rnM`QP`V%hdFdg^ZRqV;(r*qs z-WQ_R$F099Z$$KD+vrlwuQ(fJ80AkC7W48F5Mt@u#jQJ(ylF1Q4hd#qS zN%?wjRds|@WqQ)Tz0eSlJ!6Qu`YuokX9{;*(R@p@WWE~B7=#{m;)na4;yW14HYT~_ zu@;59(YERQg_dQayKaQjmkj#H$HmWKvTtm0;jFdP7~clPn1+Jr%x@_)^?e*=_pBWa z4&8cC$)2atkC{I}!>7$=7c(#eAktKbv4(T%((tB#QyV0RojH><4W~b+(H~;_zhF#W zAYjK7_9M!M36$O=q&H_rQu{nuBPq^`yB>d9b+j?Q+*zn*&CJ85qpBckmvrLU#T>Ig zx^-hha~er(3#)gCqgIcM{ur}iML|QIGO4JzS+%TK6LzufC-UDV+Irj>PFcs4qWkT+ zG-CIb2|qxEt_NpDrTi|BI0{Fr;eU(jES790m`-SrpDkjJ{1wus^;OSQoPON?eldz$ ziV+|C@KtV;dL$!a8#x>PC5Xq~ZyC;WSOV#DtRhIOU+d!HWGCgNzgIhgwY=&K!IutY z=`~TJw1SR=_j*mqmT`?DCX&C_chZTGp)tTD&-(uud#4^@v}oJ5%&%vhG*$?MGjLc+?HhOPP`31SB@EfN@S}uH10s)Z`V62d;9nHYTTVggO^Y3AmZ;{^`^>4K0 zfm)82YS0oc;h`M5v+`b4+v_Inlf3yJyw}HvwrBrEyQKpXe88M-H$S%<=|vywlej_3 zWPP6l5642 zw8A9Jkl9r~O@CTfV&I5e(d(fm&42_4p0KuHg=3O6g@*6)?O18nWE``4&U`ai(8iNu zwu;jn-czIf74{W1kdzwWw0%doL}8^IzHhfm6CzbRe0LHviokpZf1XKAjol3!XYIZy znMK1tjMP&)yuaXiOh>mGQ5BD%Sj*g&-6Ya%g-@%>ek9-oXgA>@?jb)uN7~yvW;}AO zMRiB=qKQ69=j~GK3O3V5O$JyDudt(Xs z_d^j(1zyamt}Wjn0n?XbJ5vY>lG-B^naLK8UY>1sLd@X;EAp{AaQS8Kpp)fHpO~md z-_R5Vr<3hyv>_h!d-jpTh&$0mU~)6d(ry?^ZT0k@A&~DxIVq0`8q?Ki3~43ww7^Ou zdreNAIJgn>q}}db=_Tu|2*P%q1}a;fIJQz|DYF!n>5uc!bd^PD1Qd-}FwV(QcRrwS zdLN^WmdJbMpvE7wqHSPM*1#IPIXSFS=9eijTMn~-ltQ`0XY=oWM65f&@im;yw{`TF z{x$sL#<`H?g2hXD>$wFp3gZ$G+fXc$LXEJKVrN^$_lkU?seYYG3iNuT%2b!Y(`VC* z9-A>A=g_3@@ZL3SG3gf-Nf|X_3EApvEprrR!KU<(wc21>iV)1OBFn}|(;@v-a1j-X z+{SLP;InspbQy%(yTfFy#yuv=i<#?YadP+kn#)ZezR-SVZ0I-5L2v#bypVc>vNo>) zVIeMzZH(Mt6-1)WNNGfeJBJz%_aXh{Nb@?aW`UW==mU5=z7Ydk_i|f5`*c=XCo1Y6 ziON|hp@@{f*FdE-8iyd?y5!3rT`qyUcDk81Sh0$ z>&yjG#gF-lcQrDYa5v<^yqPUT&E=+O0((VJOeU;w1qRe)SaEo>l;#ZR`l+`1H;}a0 z!g})fis9giBVgN|>MX~88I?k%8Oi>jF?nT*)1T4MS@!e5QR_ zBimcnzs)2{UXm8S^+w!gM1f;wJhH|9D%qvVdrDqQ4#c~s#Ja)qQ-}>2t_LR}`*Gmb zxEu2}nOr*-r&T&rfOpO^)}j5> zUh}=G?t|>rhvTwSraxN)c^QSQ1r21E$kn0r(KaboZ8;rKk>I4ZN-a{zP0kr7zc~&0;-zZEg4M3 zmbd(KP>~m?RENm9y$~$JiG%-Yvav_{yStnh?=07RGC_njg6h9udM!?RONSiYH#Ji< z+P-UrT67ID)J}Zvetf=dQX}a`S+prMr_oy(!DL;jn$Jc8SxzQKm6RjjhuyYg6)S(> zc*P*S(M7~{?M^sKjqSQUdYA{1Pu1QYVYaIDr`tL**XGq zI0+KWAdl8U2IqkBBuQiyS%XC5rndWHyvL*C=P~ZoW)7N__*Npdg8%i5HPuhUD|OrG zTFS+bn~LWq;pSncx!_cE*L9aY{!_CJXp-uu_N&}6!g?z(`zJs@(BtwjH3QX{DS+m< zga+=t25v4>peA|+E?PHB-(2Dx%-3%29x#rFH%k15+7NeUa&}fpwUa98+g3S5_hT^K&odgQ*Bm@><0G7H&yl zi1tBJTGXl3t=VuZlaP3-$R(^+>?UgA>2+BQ=`^g1ppE;%31h^k0j*iDkwNz18(e?1*z{Mst)H8G0HH zBSuMz0%$m3Ld~{V2xSRt<{|%}t*RgR-IGOL=QXdB+A137alQ<`^CUL&kp$-V<-G zO>BY0or(?PrTkzGa8)k|Xep2aN_|~`u4c6Zf~Xx&BLO8+MBSkBc%ZW{H8VvF0XEOI zL%VSiCvb~gDCgmFoK6}15?c+a_b`ulk&}HO7L`ue2A&b!IC@q_#?kUmHVGhjd8#J)|dTH{|rvLic1_P;qTH-PqT~b zv)6#+8Xc^uArHN}R$~FpEMu{fi@$CFuPL+DQL1T(;-Sdx<645rTIpxlizJpD6e2lX z$OcCGg@Siz=%SRwEKxd!UptjH_OX~mcK|a|&mFnx6EvF9t38x5LB4fAr`^>!J^Kv) z{PJ+>6oGsw&gOrh0;dZ}Ik63iuONHh+>ljl6;zApuYbuLb9(FFA*{nXUU z9st|f{;PmpK3EYO0UHZm{d^O?4jN%MA|n-(8T89`N>Mpqr}#n1=nZvl)1TW6X>-DO zol?3Idx->M9?Yz1WCu{VMo}gyZ<9U8(EEgWHIOBq7B)SMIgcA}d&y))9UeK@>(`@r zYTYNVqYOTlaM4F;Q>`KdpT@9iPg*#ig!r8Xb=rlB(a?S8o_waxsyQiI>n7yjstBX(2Eiy0|ef;SMJW0ZNRT;odD?+NE+YVsSIu*{}J8yrOhl$)M_-uQXO!5qjB{vCdj(wQB(Pit{-utIS4f2MfGsn-bd$_Oz z@YQ(I#&`D(xkI1PbBy&|0;ZRz>wbCP2$h6F-uC@<1CMPbnKe1E(oLVwb1(guRNEd_ z7lO8N&6(+jv#egN{rZwq?OmfZINSxzvK-~3xG>MNK{Mvw`D7_{VCK&H1Af^dy+dNeY#5LR~(sf#5{hyA-9jQjwrgt$>h7^^^!K5DD%^t zheot%_Akn6_B}oy>xJ_{=cxyC2@QFCrhymBt``z0*Wsh_VIrBZ&T)WPgleNJ!_w2+ z-IR)|iyGMWpHHunNawxP^T{@p;G1465WU&*)&C~uj>Pxghbc~?`Xa%8&`?m8uG){Y zWbAr~=H^*&SgwD^syIzMPbx>Fn3P+p!WK`@EtnWtW_Q z^}D;wJ3>__Mn~3v!rdEwNNtEEI2mhy3eZ~gh3osU-9-U4k;05cJuyZpQXB9eO@?*uy3Hvk9 zUALjU+>QIQJjXz64tHxvb%qFLX(hMCAhOG$A!R#dIejVjOshB0o!_TEg^bF<*E=aL z(Tg|Lav#*7pqB{!Dei`>O7G*r$DC*L;W8`U6@k3(YV(W#AjlcInf3AsIwc_f*@|Ve z>K=Li;bpMrU!KEW`VK4(B-OfV@6zH$wmWoP7}ruT_f0`nxEzkzFK**m zuQ@00bqc9`$BEa6o<04(=NIWXRt3JZ16FKxiYoS*lMYHmw_F2CdFDxs@$;OVu*?_G zs_X7sN9IE^Z0Q5mw@!T&gYvgs2&R6l+QdD!hNp~&8smpNv}$1A4%$>F`0r$U=F^E+ zZ^cfC*<>vsT3W;6gqy5I8!0LjLAwo=buunyJVPqR}q292(>#tN!Dk;|EiyLU=U$R9f0h+-xe zM8j*bdaX6q^%3!cg#zl)`tUcE5$O6-+MTzN?;82-j6RR6 z!tPze-d1B7EPy1)DwpSS<-B3%h~EzMYzQ+j3a*fZ1eWI;GgjHuj17ilPU(zQXn+_m zCfB+{+`D{0aM>84M{<-Q!>N7H(ffEXv`IfotL_D4zGR!U$K;C1gGfR&c)uSCUhgA| zW#1i~xUi3aiYHsc$;CekwYb^&owFAr4`r=75gi%USzxdhQuaG@*zPWk_U@oTjhMX8G6LVfGIVT>2 z9H75J!ltg&By*7+TPM#9Sh5Kcv&RhK<^l1nCiPgzBaJ~jgt#LYOD0}yhzt#ulGtl zc;9L|a?kZD4$&WzXcKTdSJ!Gej{1H1^xCJNdSGSE6>=T8Ctj1_@^kQ!T-oSM=x&V6z zqPa9dl2mGW?NDtPC!(-YSwubH zv1I%+TD#I@b-Pc;k9=m+VoOt~IR@{%vdETZgu8J)>OI}{*D-2cJp!j}8J<2{C7flQ zBTc3(<}kLEo1c82tOZ6?nZ@GBg?tMVJ74Ijzs2U?7v(Y6($~k1CsaRvw9s$-ahhVU zM>AR^*ETKZ>4$?kw7=$6?JeCycQo{H`Udnf2h&pV^hnw^zevXm5!n|rv z#;=hfesYmjY_}^qp5oYDBaeA=>rp=N0px z?|Lg9l~7zS>P+7S?kv)%Z`yzEsl^_VZ1^p=<;d<3DnXd^y(Cabqq5*|Ouk7H0%;daaL6_HsPykc9f+CZai7Tb*x3drQ^>l7r|c^sobmdAm3$&AJ&UYh#M`-_m~L}64=IK=Mgu-`)Tv=Az;@0!l1 zfSYs(C`gbq>XFLUt{+dcqcIBa3_jIEKC-I59`_0#`eZA>JAUfpH|Esb=wiDp7JcnU zGg0H+80OVv^R4emj_T9W-W?=MqU7klru?1RGv~`%8b_y-9sO)JdyW zj;O-ZN*~bHN6F-GT*i>{Wr_?K9+H(aDak1aBo>djZNLXva4U$3OE z0yy0%N@SzwR<}Q}xHF=z#J1fEX1UHVQ6p*6=BdUh(OYYH`{Cc2rrY8hYPLwa%D^5&YDJ#yX*{SDPWhVS8sV^Vysd%Z%tal{Y_TsZPi6{K zmsWl1IDm#Y%x$lIQ=v4fdp7l*V7I8ZCZa}Yn5G)LIh$hYE0Hz56&%=~pD&OKCRP<% zuDVr-=Ssiy|8!^ex~K?`ghS&ZU0r=FPAovOrV#y&Jx9>f&bA}~pq~+`Edzn5rMCZD z!93dWN;=B@hC?;hvj1QBIQ#!IA7}c%`8W#){r{?nVP$7#|DSx^1zb64rHfEGnR1UjcxvjRNs3 z`W+g$eFg!Y8ZjpEM-N2hA5i3wk)=F#Zdsftpv!hn0HGm2f`kSFg$6x3ITYB`cU1W3 zIM7Nyt~k3q9>}sl5xhD;8|CH-R#3BB|3TZw8c{slC>(M^LIUD<4y>}PfPOqZIaE2^ z2nYUurQC!0v;0WR|04Q5{)#~Ix`AQOD5LH@R zfndK`=TJ00R82{$b%3+-Z}a;{kOg?^d%EApl^<%LOzKR-T=OdpM}T|2*rgs3qb-A zRJhj@E@wiGnG5sePnewtcOSf)E#QYSA;L%I+uwVrr~kKz5(a9JFxw}J{Hp@yH+f0k zPPsV(8Zc-8*!QUivL~JUC~B$=q7)R7M<6>w}x^9)jR|ja4)t=aL)&z zN4*RTIBc+u@Z0;xbw7u~FAM@9HfY}u4&g-%b)R?Xj&AT~7SrebZxI>-@Ti3h2;}ec z`)dM>j*cDkO5a_>C1{%QR#6-Z) zzouvcoSr|#`$Cto1DO1{(Jg?NJ!R-& zyroN`eQ~$6zgWwoe0L)9qU#4kR73>ufRVp_@oKO|Xh1gMLw#63;wNynFB29sVkm>~ zQ9{2St$Pjqd%uzU-$0IoJv{YpTE8%O_pfg!Js0GEFn=dZ3Xl@`$Uy;~!2RwV5r=nM zY9Myv?1NWri2;N7$e3YrfQM$!;F|>u{(5UrU{GE73b*Tee_3ZCx zYAOyb=;NK;lx&&`oCej6zY8Rdu$LO%fQWgIey*+MT-D4n*JX2Uy+VvNKxmM1;$XdG z^%U8Veu}JfIH>{SB8LMmqmqSTOV4N#xSfROXJ0MCrGL6qu#+ji9*1Vcyf9rbuZJb6 z<4-FTa0uG}f@)^fn!wbu11*Fx*NPksB*>bwIIFx{iuaNMW)dHKdk#NAA7Z+m4qZ>H zi(|r7 zn0uq>W6H;iP7N&H0dl0Na%>%{FU<&hPHEcgKs%exRK5~9SGX1Bc2{OXT<}gY+7@H! z313g&F?W0ysajcwMC*~|toP{x4w)evZIKMZ_dE}(PuIt&5k2LVH#3)87Kfj%xA@f( zUT)ew<21&q&mLU1?8_#4V|uG9+PZ@Kq8-#%?$1iZwTl_Hzt_c&_h!wx=<^7X%inj* z+I=o9*N>xW_p93JjCBG6&3^p(A+`JpIE5ns%8xQwE|~G> zh0^P#o&BDFv}(+{Dt%P)yzUxQ@M;^C#k{FD0eaZ3dPKOxDKVkXrUw1yN z7P|f0?Fw?w3SFneaGW7bhMOq9=ZGMf!nKp!6PZ7J+lQ$oOyrXI1+~|0?8wF_ss}6$ z0k8?$IBI>r_cu|Ld0VPop02eKiXfU{#G_?8z$^4EEemELRGua*UjU3*GODv0HkO0) z%V$76E~X25I`-#n!iocB8L&FQ!Yt>0qCi;RC6|Vb(xfBI^9sqyh6E^2fgCpICZdeq2&m@2?2;J6fy=S{hDv3I43AOl z{AU%Y%9pF=THX{c*0N42&swt_S3EYm_j@tMW5qJ+$0rK7imS7qR@<~V>^HZ;ln6ce zYQwbloj~C-l5iYD&ZXI(HM^CU%S*sZq^S-s{{9(*eW6)e77OT%P8CYsN#eDi8QO+R zsyC9Z%{9%ubMnt7y_kZ>7KpC&nJI4zZTWo5`{=dDKyFJr+x8>*LP!`=`I<@rwMOJM ztM_(}%W_Uv8tSpzQU5Lz)&~KHjb*y~_H_wWT?9zKVuhzfUe{d~5#MB&jdwSrGV#zw z9F=iXs=AJpl4H=bQ@#IMCt}u}C<}>q92Y}url1udxya>Udt=7>h{SxnULKTQ)62-i z_8-^FmsSc0rPVF%FykthFDI<-cLO_Kf~hzBw5mey%cw~d*}+N`ZC1;;V6uq$_=~Oj z@1YZ9?xAT(T=XeD)9-lDyW%*$-@*>yPsxw|Y@9;h3*hKS(a z>AX+Ut-3kOFzVd+Bi@Juw^AB*{IU1ZhN|@*x_$D0KR6YV~u?rs}U}QPHB6gyw99b$+B2`W9xnM@(g~>T3nK|0S zVI{EI;noKAI^C6bq_${Hvym=5bzoHH+(q8>A1zT-?^g(<|C=kX$@mP{OL_)iPq*F; z@|Asxy_xl1=t=FmAoVg;Huk85Wrk@ZEcx$nhq&p|g*O?+jPFJGkUf|$lv0+Rt|7LC zk=lc+B!-WafFt_6Y74zgS7=4Y@are|Bf?kYoNgX_v;rz=Vz^h~k|FK1@ob)`>E>#i z365r>?MD}a6jp*43+v>ktGivGg+jGa-MDiQKSAMstTkelu(S8X$r@O>-t&p*9i>9k zMrS2=)bZmL0dFC8G7}QInf)YZSCI)BMc9z(Ix;VT5)x8Z!McBe?iO`V=S-TW7L6d)-rNSjcaj4Zi9nu9b6_<9(MYC)cis48{wsB7@cYwtr^cC5}rwdm1Kql?jn@fxSz_FOP8>$s!un8!|0PccGH#*!0A z;+OV&m?+~vsJ?sAPgj*vG#vm0K@t3H4;U}(%yKWK<^!mL!km$>WahG{UUVzG`Ln;u z__;kB2Ohg5@gf3J3Di_eUXd<-IWx?Y)M7r6&lwKy)_77IO=v{;$U+`%^)UVa_6oem zwiqF`rw%rcUVF{tu`1*BpT4S%HNXY?pBb!#e6eAnI3wdI-n~|}`bQlr-W#b!)&XTa zax-Lfrjs4UhuKuvut%5sBF;Xr|Db3?EIqX-_gteq9nz@9B-fZFAE5hgo~8JLgnC6B z6j~*gb;vN*Y+lsbVB((!TXqrKiqo1%TxhI|he0Pk zLa{h0Y|1CVyyr;_dcc#X7odft#p1~1F%^z0-=7^XM0)I>)|jItn)LWzvH^RSb84^s zRM~XW_O74Udukq$Sz5v<9?t;aMX50+lX`Nd-W}6#YSCG@x~A;J{q&dG6yNc$WIT{A zrIy)7vF47%-sl>;bBCLdSXh5)0fM|UR_{{>KB-&kr)=@97U1fE+zA`|o1n{DUbRA1|9rty@rzG%%*uKZA zq=4Oez}je9o~X`-tr3Szmzo zU!WX1?_6L0Ddd(a34#}EsG5;g@%FI1C~Y(T9KqMcx3|x2r@7i80QKO~B0N z_EOOO3p1ygZ{gkOC=ix|=l+t^3H(6DwgEp|I96sBN_PQZ`lb=ZD%!e_q3E#El74r- zS6~P>E0B=JOqLxk+D*~iK-YIcFh&G{@`e8{>b2B?%qQfyCBgCTNJBdJ~SJoBg~c!ZJPfe=5^2Vf`ZFt>+)JM|L`}l-hkt zO0RzcwyF+kw<+K7+L*9{6m-Uz45&{Jf1O-zq2rjG22Ac8mT(i7h7SU(qVFUlfCnsj zUYS??_4vbt)7qQ98utI5{V%9V=JHlRq&t-i1rcoWuIUOAVn@{$(D8X7D0~=s)r+4A zNP@9aHt%f{HJKOuPSSHztHsn(^>O9Iq{;~(^Oo{{i;MJf&?}YhW{kBbGk+p{jDVQI znd9}HrYPYOS8Rx6+#J$r37S2}+5RZ4H>|^76^8C0o4w_wyxoOJOZjQvIdGAj1d^dB zfo_-iQJFnI*Z6RoY(zjD)NQl%2uulFb2}LidOG~g7Jo~SRAN|Fr(iWLNnVEN{_7Nj zGZM>$>JWIEJb|t8Wz$$B9AbVMvz3CD!KZ!twEp<@mB>0d=mi`?tS8AZa8@bnap_#J zffFwaY#WgR5jGH>8sU5NqQ%*WABmAQ6s!)|?m6MDEG{RLh~8q~TKN+|=M-3obX)$s zV6AvfdcmfBwRqlfTFE@2PB=#9CQ^F|qdW8{9o_R^rfK~b1R9w*24l7lh%H-$LF>~QuhB7KFW!Bzq(>r_; zne9{ytJ@E#*ovoWhGbDB!xwsVAVUr$Y9n{e#cG<@c>>;~`-UlZe&!XBRIevJ}b!AR+8!PXVs9uCwb2;fA9QM=$Nt z4OK~CHQuho{5}RTdXo;jDe9iOd?mGZ-7a&XnbO&Sj@}S*$PtnpkrNQEKCH%&O&n&* z=O3W8GI8du2I3BB%c7=0Ve3`E{2cuZi54@Icv#I+<#nrCw`$@xkXSblQh&hQA0Xp5 ze$QLgJ4)IZ%Q(o>*h&|sfwQ&-*b-P3Ii<9V9n0h`vQH>ouuFl)Ies4ed$- zN!LV3`Qv-LW7CRcAni)_c!khNB>EU^gcG@tcdtF(mUbP^yV>WbEy#lQTVIPcX_PRxA|)E0A+a9x zlEh9Z33nyH+bKoCbE+txQCw36=)}Ows&=!KceA;yDm8)$Hfk30mY+4`mC%jhl#f0F zh<$-+P~XNIGTf3{?YpYlGYu^N0smCyrNNVk%>FxP9-}`wf()&tX3*~JtUxC!7 zLrfXm#JPl=J5c+-k-XK@wlPfCrX7qEeX#w}@L*3pNPC+|+cvbM^4id8J*wH|GkFUf_`-+`-jUpA$ke~&M{GR)wMpz(M2}7J*c5Q?Wsqu%#cO= zirS``QgccU2}beh!V)VAJ3N(dMzOLYZqu~J>^av1P&+H-=P}uIJL`6bOmI7pl{iqx zKgRFr-0$qtM#55Y1AonXni(03KPRe$8Qs|~@2T>u8E|~v)RSh-iPh3cp?gzTMzcli zOyXVmJ#NPAP{oJs$=g0}Bv$@6=73*} zCWB@gkzD&d&|*}TGzVBbY6G7aNvpN$yo4btl$_(=^#*+s9im491*F0p6Zs|b-fv}S zX(H6}ehNf~K9Wy%yt1#zLqRqnU_lyHtV(>=p*487h{cmr?X^s zgu?Q8XT5kf!k|wg-Wt$&4U_PfMOT-lFnB}}&}@ii9mvFpdg39&kMIMG(^JUaRO?M? zFGj@4gWu-Yxn8*z+PhueIvO$>69C(~2sQs*BHP>0{^57M9fZ6oVODY7o^Q8ut1>-r zO%v>Jg~bJ;cB%s%$MQO{EE>PQS?Z^;v@Ky)Xug_t+k+if!f`E8(3U=@4 z6!k3>%r64?$S+q9!ykl{59I*ZVMISEpzV{d&*ing#QR4LIK4^@fQx`Y@XB`pfMEuY zYz^ZKXbxcTihovyQxhNypcBr54)XL-hdh1wN}pauj+T~|hDJ8Ok%I)(l4NWE?jB(9 z3V;*O1#t=42>5M_kq_w%_OpXY21dj`hkN~-CWK}P{RAW^;7=BWw2pav_=|jaUOIY=|V>=?#90?ZSjPnN%ebRc)Z?_U_r3h=&su=mrUB{Wb=?k6O!&ukHWB<_mxTiX2ETuLii(H~=D!VqZ)fFIyN7lD(H{8A?%|u2=LvD| z6w(f4owo@9>Te?;=ZEfl%P$8H0QLd^`ubV-v9IUR+qAoG-!=aE6e*=`qyDdD6e7bAJR6 z4`P20We@D`4)OsgC>Q1bH(LY>@~1QAH(c4iF8E)jH08@#_AmMRqYW(m4;LP_-|uWO zn41C(ME|#KUZw-Iy(W*B`)|(i59#r*>~T-yw@&bHFA|w2JNx%Nmc!_D_lh&OU#-}vBXn+6U^cQb$$ytMomj~}wF7x{chzDlQ&#q$M5T@aS$D~`1 z?O(89057^++IKJrfG@Y)kvZ_=Z;>GYS{XFRD>9I~B`ttHbb#S^uYv#|K-#q35*{%j z$Ue|779?2(YfcEO2AUF3n0PVS7e;N0G#m%6A+Vy|_av9uz{eP6Zo4`;$m}i({V;Ypf~g^~C8GxZiPFSqnqkNUYlSKK8VTFQxCAjl44mF|w&SlP%EmMavH7 zlXhSH?4Q^m9E7by?i5X?-Jak_7buClUoX`jZPCf~aG|sI7Ite8l!vB~SrTA~_Q_N0*5}-F*ltZ{-C7jm)_StC z1GdwnF&_f;turU&Ty?dNBJd0K1}5xQZv#&XSe#K=B% zs(&ROj0?FN_DHkybR^+zT~9%vcK7n_RRGFTmJ^h04tf{qEPC-XFxF@wNU2|E=LiRX9*qT*uoSBxx&*_nJrXhKMD2H#S5#g>tOX z*IT%nu$kxb;nYlAWc#sO#2SN_(&CN_8>N4gE=u8$8;a$JtR9*672srZB*-n^>}&AM zJf1F3_sq(K-5OMyp2Ph30G$_Sb&|ZC0&b|&h)aD?BUGl7_?F~rs{5r;h<5PKRA9KP zqgvBzU4@p`PMR{roYHT#M*w|ks%>t-}g zC(567Cll+4+;(9rt}ASYr=edx%LXR_n4*;y61G+!ywc2J?U*&k0Yiv%SIdYcljn`m zP#6V^#2{`8`m$fB$>;mJ*C@KvnjESG@HcRn#>^Uj&ol;mcT(3qS<$3+#W0FL_EM8xFY~I;8D9F4iDs;Rpgv90nx{%I1 zWH8;WNZ{OG@GWq9`JC94*|~jy?C9Ue{j$`E*;mJACR($es2M05eq5#c`72SZMAiTI zuiDVN%2a#pw=G$?DoZhHGqj;4H4Qg4iKq!u&yGR%2}Hul+E)N|slyqx?cSRK<-M9& zOFD9Xw2&5b)w!|3-hI0XaZ8b&lhUaim!Y|uX)e+W`!DKkUEBH!#hK7$uN4u@k>!%@ zW5#!^NlC-%Gl4H|Fo;@M2QR|+P9R#eKZ3yYYRpsi{S)drW6F_n0eThs+(Nhal=vq7 zpZMZVFYlqWE??M%fv}08EZ2+^Olvi1qK?OL1&*kglMyMJcw~gDcf_e?AV5Pm^KR;O zCp5`sb|r%{3)us-*k;$t&2q<% zN{>D|-*eE15JT_C1?-b0iB&A`s>*JTD5H>(IsGyO^FixjNq^MJO}te865lUCIVKSf z$QhsJ7MqO>TV-$>Gj;D16zM||Vx^;fmD6+wb^(499`ot~M;knotaZ?)gllc4ywDG}N znN6bAmEfeu$4%<}k3%_*z}#1s#(e?0P1X#P1B{0x(Gv^ANJ#i-fQIAVB17Q|M?yVH z;mIc3`(r%t>5Txb#ScjqRB%K}GaG^98|kjm(e4UukE89g%(Le{t8BN^eaivRn%h0B zRe5se$)dQe0N?H*@JXG&4_8A(?Xc(er13>z97E#MB+EbwPna89naR{FEuj%NMjQ5l z8rO&0unDQV1jK#H81TA}`kp?lV7j?CFlH5RR_~qOU89{iMqZ2f-R>p4#Y7;9pRF7Y zY920)mnb^LO#AReok&+z$M_?tou~7a5W+@d9SR=f8|rBp zG%O=ekY-;j=Cc*_$x^WSlYNpbd_mIn{3)rcC-w`EU-ao4oBz%27DS?|!~`v*ye?#( z>m#z*sgrHqMavOmV>kOJv;mjpJ!ytQD)Jv=dHt6iMEJcA9V2X?Ls42Q6j1 z?{o2NTj?SI)7YVvK`?ZTwfizN#xg|2q_ufy|AAJId6KKxrZ-Tg^UB1_u;7b*bDEnO zBi}r0r`iMeF8KZ)YgeJy*fSY| zlo$V9#Rc|YPhlcyjNH%GU0+7$<-Alha=k)enFtKvRR3#XriH(Q;bj5X6}giG4wX$3 zOv+6UW3#h)85#e;D>AxrnrKnL*7PIY>9rM)7HqJBD{GL_3-Z<(C^acwEyKUOt&gLo zwbC>A%?94@S+~*|w>qzcrlB?fw`Q(2^Y#`nWkg9}HZY(>F@yLb=KT(ps%Am0im+7+ ztDN*`Y2&1eD*0@TCYK_ZMdq{~4_aa3$^ns}$R!MZ+Q^L4Hcr5a;$*r>)@_8|h|5q; zaRei8@1QB|=0!VY%ge*v8NSI(owF(h+KqxRutD)T&wZ@Iq?jNqr~l8RTYv0N%Rw{R zl-t@h&^JjqwNt8T{e`Fk@P8OPhhSlpsJmX?#eByOdK=N*9n2)4*eg^+A^cL{K$_gDF~77 zU&6lPoO?5)hSa+w!-^3G8-DVuH6~?XvfsVXb80(w4x#j_aKOzQ^Qk5{@gh1bC>yDMshE#vLsWDOgkXAvG>jjd_VUTZ zHzOnz`1LE5p{IUVR?x-xEBx*|izjJ)8A}LQ;ZzPPIjHR=44H;&y%HbCd`KfLoLVL4 zsG${fyr^khWpFCDcc&V}mu<=LCZ4i5IgO6XVJyL7H6$gTO&mKukv z$0K(BEZWHs@*Q$HW~OEw@KCKJDsW#KuoUo8R zC}X|(DQgKxx0-nbiVCR6zIrPokss;)aq)#RvYqy#);0Akgs6nRa4V}?@8hm9=vGrZ zqo~H&k11RMB~7CCj`Z$Q7{lrvFchT_LYtYP4x-adl6Kd-gH0efS&90k`xCi)JUnkQ zt*1J_>ii@W3bE29DJj=|uOA|xRji@-_)ODAglXYfX-24aSwD|7mRZZ#*e%L)n0dwc zf7*{lZy9^?XT|rIr_M&x2l4uvL3=_p=4g2>4BW5we>hPKTM?AOjUYz9-B5QV@~gf| zhB^%m_A#+*%`4G9+~%#aSWt#^BMyq+qg)6tis!zJt`|`zh^9GJwJ1m6^?zmO*y;S) zkejFxDetf)@u9;quh9qHF>4tU_Lx4oVg1Bb8kG6J6`~7lrqX#fplcJ%GAc8N=_|_P*yMNht$& z?VL4}i)}dOF>Qy%BSlfJ4SG6!pP$p*KBgZp0&4K;d|mR?1likAH@Yisq0`3M`LvH{ z0~*A|;PoJ9);>=%y6B|nV|86zJ?g$S?m|Ji@E5$;5F^x6JG)AXV=tI1T1cOSwe{Ye zAL}=078n$3>h4G1iQi?z?DJ@4ut&73bZy6VZ-!REIuEq8Fk5>w`=gczas;N##c*gRh%H1n9SZ!AAj=qV2ETrtC@ z^wXHK!rY3B6e;gf`~Vp?`qszY`!^La+w0x|>n8`yCBL(qZUZ7gz@yJhF%rh0Ca`79 z?gZ>1suJ44bhs~$&uVc4mU_jQ-{>c>RZN9ua~;hr*z(h5iXZA7D|D?wuV478U|Q-x zrifK4Z>-nnrWhc$A$?lTn=0cS|2+;M8>&u@4`xp!3uKz*q#KX#N=5%;N;^k14hq8V zLYh^ITUz6hs^&2?&dhauAfv4h0K2!ufPdXvY;<}0{{(o5#Cfv@4+VY>e~{ua=HZ9g z!rpm?Gtbnf86psBOT={ZeXuL_X|9pb-!^Gd?2{!k1hjpf<7<~6%N)B&AP@b@-rZ47 z@%k;F=ifwbdW0lK<*d}2^7~;79&9gaf^*xvXYOz`-Q1l9^%zSBqaZ9~vl-vP$kN|l zg$c#Es@^KBY$LQkgz?y(DRWp7 zt*J3uH`jfhv!`|Trd)^~<5AycTm1oO3r^!eH}`(k>J+om*lP}7dpHpTPwZAu4_+{h z`&>xGJX`W|Lu#HG<`?=Lvo0$HKC@{e*>2=-MW}dHQ=VMHqIa9Em{5wHR)5pRWw;AR z$4Y=DjdwV`UXZ4|YcqVJOcI6}=%G}K={px$M(UK6Ectt;(G9x^YWWofZOPpQ<8h*c zmU-$4%3WjXWnR4)CV=!T3nO&lL2k6oh3F&trEFo^(B3!Sc~S9Ufn`6&;(n zrzMQOor4f_E>6dg5clyEC!UOfSz?7jvjRSz9JMnaxk=ezYJku3&EWs(ptGG^ z@k8m}HdhwcCM8V=$>6!zl5ceX#>)2Nzw=I&_R(1LExr(*;^|6Ha;FC0RYU;d4UjEX4eD zr7`MbTKG49{{!fwIwXxWNn<%VXg)M9pH&@zJNNquI0%2@z9jY zuBd3xGXzyUyWm2)!%iCYyAyVLN#$x*A+dGmT&LicLOS4uS8abHD@kXOfg5w_bLNRm zll55MSWjonWf`BC9xWbjEq~97hB+Gl4$wD-RgO@QV~g^0yy-^4YxTRlosWvwm~8eu zG$GQw%4n(D)DS7F!JuY2$rf)LUjHPy*e@YjuE~;QP}s6sUn?g?)4O+GjHLSJn3&ev zyb;PDi^<~n8{?XXU&5T%0S{8OD7MzgEh2A^!F`mJx9BQcjhdr{{# zOST!SJK~>o5mYP7T&S%9g*YVzC>m{kj1k3?Pi-noXiA2WKI7n5u{~lesX&^ zn6uVwY?Bm)gJ>SJ)uO$}8#V4sQip19Zqfa#O7LYbts2BnlFRQaY^ zepuJTxlwPM_Dj{sZI08vXQ@dKquuoGsB*9$%VY9hYjmYcXX~sBVro_t?33E|iFIBy zK5ZJphl5m)qe_Q+aZ29gK`&Q-%2R=cWzE-Tm>V>uJ2ZGg(QeR&OT%!K}XHw=gc9;1Kt^$y~Lgg>LxfSIBstzfUMyTsPG4a?M{ zlUW@%{xE&Y%axAl1mNYixote`O2`qR!05-}1sCVvYh^%owY7N0XB+pO1D;z{qokv$ z((VH7(T%Lp>;@_fX+_nF%w#+;f{3hik(g7{Js%t0UZ>S&4?}M^w%4OR`O*tjEo2_p z>PINIB)@fTlzn6OSrA_8dRtO)m#H=<;~@&O#|IbutqRDpo4S+8<{KGO??7D9h$d*Y zrQ@fqMC^w>CFAq~v3z6aK@nNuGTB*MHkaT7cM+$%cp_q=EUPEQ_-vqoO)Z&w`yS%R zYQ!#hv@#~<#mjIo_xOK053Z(vRcJ$AyHUEk#x(6& z8kJS&$E`t%UH`Nc@}$FchmomhTDn7q84oY$Z}40EC>$q>-c1r+ZmyZ`h}MbL_nlt( zXroi~Gr?q*KR(k*s|I&x2573og$ zlEE}BYw~Vz`Xtx6of~_Sgx6(iC>deBKO|beA(*`u1&>|WWbQu@)9AU;O7BSFll-?DS6T$WFQzlk^Zy^)!l|cn|AH< z$whR>bN)2T^=6WxG1u4rK5MYPC$p;#V!MLyJ%$ZXgSA;0$n#Cwl&Y`BsTRO=x@1_e z4Y92tKH#UkSCvkig$!lD3X?M(?7>(^7wVwYYpO?eF{)tFNHDn*^aBxGg4)!sUmPVT zgoM5`*;40<@0vEaiMwP-Dd1;!X}m`DLK^SYmP%ZN$-S2Qde4en)(}VyF`+^Dv-<{U zgYZ0j8&n@&`O+&T0LmVw((4kyAZukBO!E}Rrls<#a)&!yJ4mf@{#x=o`vnPQJs4p5 zt~Z;Wm;a$_D?|L;CO%xtER9ugPFRM@GXz`#Y=sRY1_ndRHOi)TM zX9-HTfviscqe1r?n+#AJ>b59%9~h8Mthwe)lL{N@(V`$~jYUK1FsB9O656c{LP#Ub znQKm<-_-Hb&8GV}qn2rBC1cLL1vM8@QKGY)6}rX~;*O69L%IaCW=iaj-^_F8@ zZ)im3@TfXq+`}CpH`t}N-+r+ts%W=-2BO?hXtPVVe8^gQ1s^cAiUg%zm=40+sfW^_ zZZ@obG2nOrKrMFjfPaw$_m~Bxote) zkUnqmrp`(}-=`nz7Nr>NFMKL|T)G{}&4N_g|NJLbFUSk&ZftfsPuxUSIhAghP!REApnmbTw4BSn5R!|I!G1EP2r+>myPW_B@` zV|{!qCb*X`GuIwbtE(i!+ji1iT;M%;aJQgMA5~liZz1~Q#>0hTmS^P^<$*%ubqnRi zwrA2P@&WYdhD6hmqj$q1Qh8Cb{DVeU_ zqGtBSZ0+eGc1eYa-;3E`YrAMPuaFi365p+sJB4`EcJwoiJ%-eOPDn9ftKeQDNf$3Y zS0%EOUc2`wa@iQdivN#^BOA|!_w%X~Wq9W|+m>yMS9m`_e#LXcJ#~D#c0OilTR#Z8`4WUpZJge?9dliv(gCoj zBTS1Q@tdFVm7?fPxK0EXA%D-*epDtsj*LKz!1`Ew}ZTPy|$ zID=817I2%H#oRH`v!izK;@Y%Eg?&ay?(B!+YSMuWktE354y-JMEs=L~@}rJj#Yl&t z2f0HaeM}d1TFpKiJaX%LV;p<{NoGu$O6$MkM>HQyCO}ET`~->pckSJ?gL~?CVW?uq z0i`Gx2vEX+MSV1c3KGKfS)8{%y3k^-i6d_T&f>gR71h*hbulQZ4ZM^llZhDnYd-7$ zK-;0o9n5^j`mtQ@PQS~J4N;k{qDnuo2tfO;VmL|+#OOcFwx4XD;rfX1%)0Lbzs9IS z-JD03YWZwVf(DJ1V`wqY+%YM-*0Nk%_uXe=Ltyzo8r_D{UAu%jj$d=h3Qw$K)Oj5rTFp{e|BeU zLWtzkB07wJzQ<2hTbO5~{I=L%F|eA-BDH?w6}# z+(sC6@A2hKk`K}*A@DR$={QqO_a)_H9P_Hd70q%w(7eELB$=(o z>6}-Q?$vCG6Ng&;Ae=NgK+~BPrfGPuP?zPerwn!iHaL&%Qc8Ov!l*M2h7|$IsN_)CZD_;WLUm)8B>Vo@C6>I zOdgQQA>p_?K+atzfkEMYaSTgkZ+A8lb;GbsSiv~m*NT0`lzdrKcmP#OU~klQus7be zsyeti=Z&-7O-p^Cv!eY|kXM6-NP9#VmW4z55eoU|r3H>>@=Eutm*LNfX@9?wL%W(Vt9B68I{?iCAv|N0Q zkZVTTgj?H!ot1IAvufu&@X@NNv;ytYPby~6Q)_7P7Zlkvxab7xQ7C?mxpQ@=-w(60 zvUuBC0brSi@3{KvKz;kBtA@qQ($(dL-zar(sp3|IK_ONzz|&T$moFv+JQ;hdOdQkQ zNxKJ@9eR6{@NK^+VBGbuA}?R%@gbwhFP&hgnO02b*~X=3cw>E!W!*iCM$YgQsw--d97al_t@v=Ta`nKr?h}2s9jN9} z6l4ehjlyhkYbU2+sza5=kdMPi5?C4kTl5ru???w7kFqzFfr+!QhCLc=bb;#Wp>gw% z|Gkwoo&{hCZqZ`A!TV_}bqc-hkbP`{Z`2l)$`4%AnVVJ%YQIcan~W<8DMD}l1^Vz+ z=9irZ+J5il|_GBW(Xa56?_CU(yMlP7Bf zmCw3Dql-pybAwRb-ihiGvUmUh3`E|>jZ~u0jr=d3KzoZquZR=bHB|C-?bJE<@t5I6 z&Mc8@a@Vx_R?UvADak5>=D_TQ93S12!wd~h-9;dvsBwr3PVS$R6P1#agPf773Vm%2 z{Mm+^@k$GE2-4by{4Ewt0s`Xf+aLj$qX(37a{~ZH#|8jL2LN720G>y{&F!C*qqDyk z@QU!yA7viZ8cg04lwy4=AUocI^ahuQKp$G_EY0cn2UWms5?~(zVc+PN8kfKpI?!Jx zz!ktGzln7G^+Z@HA68X`-g^}P=1c`$W$7B0}*+Sb;#T0o0j)hj%N0+_iU_Szb9 z9)L4|pq7BS|1K4fN&Kxye~E1Uo~e0>gRKaMpp zQ28W916LO}GqAs_X&-O^o9rw7hkzQvI+*z*(mlEhfqa%cMsZIK?fC2lddbj0^M8n)eBAI|7gN|{e@)wek{^FcA9qxLY6XAv#F*&VS$*Hne^Bp#?*Xm) z*l~Tty2)3E-;JP?uk>B|Z+!(^`F=IE!96h>f1k%W0rXu2wq^!Td5nQM#{IVh%&hfI z6(@bikMv!ycOp%ITLH`0IsJWgXaLaQ++Tn1x~)^opC_O8o(so%bn{b>-){+vuBET0 zeQnW6VdwzC0{(d8*Yt{q#|MD!4&Bv7nBzb6sKD#$H`h6OiU9O89{|%ggyVgA6!iT5 zGM8-^^uuFt`bi%_?Euz~ehB#fG9Ucmf24{x@P{Dv7T^EqJu>|e=>2bQ@Shb$&iKXm zK>`2r(do$i;sN|;p83z;tkTUr4n+Yc@jkf+z z%nFBI`}beWQApGh{w2L^Sz6UW+*e896aL$j#cV3VJin(;!O^wpUtDmSsrD~pWg1Le z-@f0)Hx3?XVaGc+a<@oNP4=<~^n+x7H=8B|D|^f({*g7$}Q zCqJi=tr<_+R5M2oSA==EGvtImeS;X8o|nWm870EB2P*0?Rj?>pdJ^U=Tcqy@0GFeh zk}D0we^*fli+qa-DxRuuEgd?VSy{Iv33Iz)ZrX}$Xtwf*D$DDLaYDph(RRmk=p~ve z=NAeR@uId%l`~vkZyRb6C|JC!sF=vr@Q@wTq z>MX`>9d^*g`GSd`)*|#>=vMIZE3a$?6zLp~#W8FkkwFP!=lw2XmR|?-wV{cUSPg#6PXb~4p#5x-toaQ}LPt(>0c6sxI4H}GUi>X|>0&O-e!gsw|%DDn+) zIXjb6#WU~Ki5&v!jLEE*Dhluu4|lwEX5V_jD^yl$sgW^zUJ; z8%8vHLZ|SHE=4W;@G3=zfN3U*h<0_fv1t%lSn(KI<2L6C88IxhPXsnLg?<-TSz^0J zlo$_7=Gb3?GpenJp3V3vH)4p#ZAJ9p3`}A35`jD&Y?B|B2(!yw#lXC)|He>3={&S> z+G=W?0q(rfqIV;%8njRDq%+{u>osdv^H5p-@vp{Uh=C5t?SD%+=H8Iaht_-_ZOnji z_DxzETyrxQSYYNad7!-m7nh|;8=hH6>)>H3W1ui#lUG}zl>#B3nizXG)mzCl#%}!00V)EGr99{WOb%EZUE%q5aNT zRcTe0>E(HQo#-Qv{SdbZyQQdhV%uyk*wW%FoO=VT;=R;>tH_ zCGdsPx(_NH6x-jfP_l+XP=jbhZi3jDedG|L*a;E=_XxMC<5*D;D(cA^vu%U*&H$QP z&5P*JUL$D-DFFWxt;wKk6&RM@oiV(b&SbQ*ZLr+GTxo)Up%in}z3msME44gX8j0BO zm?!&cOQCJLu)*bQpc56l(xs_C`?mxiAC_ta0;aOzEeirF3w6^S=JiIi}0(LA@CllDI#?kD->+_9AZ^V8( zkCAg?YWYT;0}1+HR-xx}%kgZOyXdtP_UdCt!9^&A0fBE0#+zGpJR{jk5qh=v9T%MAw<597kwRs7Ee%+cG(3 z$=Rin;P^YV=<1v0?Dc!_M0;-n&Rhz?c41*R-oVv)FKBG(v*YdHa2J%hTJf zEL0yw$}*o6h0Cc0>`*XW^f!x#sB`o%VH+vDf0pA61=&)uQ@v`f(7Y6_F;h|0kTJhx zmUT|*Im|{3h*u$735qmSC;a}g?kPU=JazdzkG%a<7s4FMmWzNEAcK`DS{Sy z=?)gyS`lTZYit1kQn{ll`!_5rr|qsG_t%ovWuV8~;)rq8J6Y zCB17u26PzWFNtu1n+SL~8w8f_*y!Gc(z`V0A)*<<6H5EwRR&DZH8XSY*wv^Vg*o1-RxBtk*4}{Liil*15N_}260fiUFs19u zY%Z=aDa(bS3|!6IW6d2xe(Y+Q$NCnNu0oXLgy#cW0ON5Nzo1?-uz(t$$txFYn=uxc zrZACt!j?EhJtsCEK)=gZXSJ&$_LT7l(l} z1vKbZh*I-pi+G{yDs=TPI=qpO7F8>h_hRq9vi8MjnO~-SRkz_jElR(LR~U3eraBFs*5z#4P_;Ezr5WF+~o`x&q<0 z`)9|;`=qOoq8Dk@WOi8v8Qo6`yk+(C{$}{X(jq%S#lG#Zq zj^*Q&gVkC!o5tnRylN0rvucKjrOP;uSWPZjb`a_c*Dv*?bZcbHz>Lq&>9n$xwRUgE z9#zO~UE;gr`g`Z3Na&4*D~tILajV}ZX#$lvOMGv`R;ceOs@dLE>-F$TJYxCea;C^j zWYL^Qj-y}`7Sb6xhquATKkpxJ%&Kqem5w0!ra0xBZBVq zhSL2xpMRk7L85!&Lj`GnBpFIgpUS6o&aaRh$ajU^Q3tMizHC>H7q2;s$RX3zl?5qnF9H{4}TV@C`c zblUY!(+zVd5>Y%6Mu6r|%%Njyt+i5@xNF6?k^u)>%{zNDCPD95+i#>jo$sJS=GDdal1;4_*BWfKm;bfB_VYk&MS^c#%yHYPl@N+6~zb$Iq5D5Q%fybAYj)< zbE1C;+H=)yhR_%+YxpH@{ z%FLAQAu$;$tptg#q~L)CIV7z{bxZ-#?;Q;*Oc*36Xel7CC&nnDST z(xNfXwT}TqYx#0;0(e-LR&yro5qZ`1Pt8v2gnMTdUNim_So%{aO?dS!aBA`(9T<^y zcu_mS*rSp#TJZl{d2dZ&$dqPk>QxrYiS5d-W1eky%pS}z*q4(2ipT5~7w`!m_2fKz za*29V>}b@P&!;)`Ec4A13SHc{aSE2Yge^6dXN~f}G#tLnjHL=^jA|7|#<4fICRB62 z_M2-IlKK?tr{}j=&1WQhR8NA1R7Gc8D%`S%bN3v1)n2{7)Vn7D(c~c`2`I%=a#p9z zp5rMmTG{J0CJo#F1Dp*Gbv<2`k@JLRwbAcF#k+syULF%!`3eU3i=1KugQmDwVt&M= zg^mt%)l1FwNLl6XwO~^{L|9_@9tRMaK59ac`QDk+WRI@Zf(}jb%_>3Ay_2?3Zznhb`51o)TzH_u5-|dMx#CQ=H2OO^$~Pj z$7gu2%$uuDt;7AgaZ*F=gpB$#vTNS9@w+=^4F~ono7U;np;f2L#pCmH{c2lACr*N0 zkdSYz0Wzb);|6x}A+!efsWPQ8r@4ctl2$Sylt!cEwd%3+?L6gs$AX=T5JaS74l^1*|h^q}6;~+L6s%hV>FiaP4}NLXQ#5 zCcDH0djIfIOrEAfza7KE>a5fe?q~#$z(X-;}1Qlb) zsX=f6OFGt@Bd1GB=IfHIzZT1m{H>h_q0!MKIVy43| z6aE)e5gW`tDKF{Ue-dS3UumPFF zi|_zM!O(ZdE@S4q;Kd>sYBF1*g@wz)A?2g1816fhESV{1*DFM7MZu|P8$`kbFzTfy z7|Y`Nk#Q!J=|WTtwL~H590#dYK45R6E;X8@0V1E%bY^}5KNQb@aq(PgTNxL0(6bM0 z%6tF)`@{T9OVRDSW`pAdyL#wi5_(5pCRmIFsiCg>D`dCMPq^Z|{v!Dylipyo>$5wD z-alGsj0VfNNiMVM>ioTQ5`#Y*L5->LG8{7}&3xfYI?KFGG_I*{{i@W$*lO!)usoIJ zP-L48)5bIBIgL_k(FB{&Ay03OQn9g-`;IaBWXvElPkUB6?}>D9Y+ZV@gtE(~2l+Sp zkT-nQA!*0C@lbSJVuy?5oR?=|v@4N!jMhynh2I92^Cbm7G%X`1 zRmzDT5=I@n-y8q2l<|Z-SUDoUA?Y?Y&`N!tLoZv7Y4r^^X~9*p3#{e3^nJ^277S65 z+SL5UC0V@b`u8dtkgm#}pNC$W4YCqQsZ#t^itvsc9@aVKHerC&b4a6wlpTjlM(KYm}kA0 zf`dR;w4E(B-HPkwANs3>hfWBZp9t>myiK${Cq?5J^-qhlN3wow3j_eMcib^cjB;Ul zr@}5bKO*Onn<-<@qILs@^-V5(IPc?iV~rh9zV}(DR{2W{Z?ov?xXHwu)wX~0q{-MS=QCWLCQK!h~p0g#-bMN)3wl@32;9; z9(a!*jkS#7E^8Ld693(POPnlcb$0IEwhdY8?P*wI&caak;6L^{>Sy<(xi?vQXjEn- zEQ2{1t+3cOm4Dsmy03}>Hy9zKYKb(VjkY`F&^AMVDUF7-k?uvc`zmM(Ug(=+aj$&s z#HdV{8`OabnF{ZaF_x*B5bs7?QMEI17MmUWn&!WXgCj>=y1+wMa^#Q1yf!9~|L8CX zqb;xob*jv+V3o%LtLwjdjVjo~>!$96&@Wr!`TkKRltU~}env6?j`adHZQPy;YF%8# z=Ou9KhxPIcfk@J1je@sMtUBHF$}SXAd_vK~c9m6kxdW(_%dN;jzLQ_uS|mP4LjiS7 zY2|JU4z;{=CeOISy{&91<*80z4I+|V?trAFRfH|*VP8|VL6k7FJ^FTgtFtTL=03Kk zv0C*i6VV=*R2Pt{X*;}sByidc%@#oCX-}w$MNVv4j7y89wiS*B0S^?Tpda9}XBS%g z!oIW-_fFu}VxmFtk)4X!QgJskK9Gbwfm$QI53@q?5UT2(t5c3(o*$5Y3G4(y7HG30 zzdg13d=pHD?c3tAZ4KWR#PTH?U*y@~%#OXcCxX<1jcX@NGLuV(cCS4ht)=RDZc$#b z{2cpHS+Jrafb2SWf;6fV9TFr}c8((ZD)j6gVq%LeHkNgMbo6eZ zHQ5;EQ7tt_Q!@BxQ`Sje~Hv=yW-0fFdY22;-%leI7TW0#+hb0jTcm_KNra0Gc zlK??bVv{P6IZ}(TZkoHOLK=Z^$cD2z_EZLWKMPiM>hGOQ&Kz-wPjZ<@X6NRS z?NBEe73p}`&i+Z$zMhDa3}w#0SFV;vS;>z8)i>!Ifr}ml3;gWpPRgAbIRS_N=!Zwi zg+HRc-9uZRRCak_S1#T|Zr|42AB^Jf7yEIRWh2Ph_~#|^s=NI19xPehQ4LTaL-F2} z*uG~&O88Z=p$78Qf6@vd=+u=d?3{>gt;j~?u-T?0rg4YM zVh8(E!3nGdG)0H&E(0hF7b;ee{}+3J7WoS88|1bp9%FOT-(>Epzp?7e1a`N!0Fd+Z z4?^vjJy4-DSrrH3n{JO*n4=CKy5{sdJM&*zYD zNNm}`xk2m4M!1`5+2Tdua1#FV=Uk6f> zrNm$M!UflQnXtq-L&$B$gxo|#`0Bf}uSlqH2q}+S?{L?zJnzhy|Gct@1%Q0=tu(G0 zwP0F)!C`ErJ@1``IEng?=Dkpk6_52i+-{MQOnJdjslS zqBq5x;bbcWZgRcWvnZ%2R)i5y7;&5lm_cbDI_qu%<1DF4lPwYFYyRNuAL_@%kwAB` z(c=6k`Wm>2OC#e;r1I+3`W-krb~XrJG=*Kd`&G5=zTmD0=xM#})3l{lMPCmf+3eu) zVItf+zDmke2E=!L3c^NdoukX=tq>~Y5uJz)VY`d@VMSfsW67ZS^MxWf8Og(z+a`-g z6*D|%5IZ)WdgXYa$HI3)#y)}1YO;4?N*+x}OIh~5BVtK*1OBVHB@;&4HfAF`SvUp_ z2@B!9#jJthO6oB*v6MTRY2EvZi&E^aP!yibKp!W&GA-V1Zbzi-u`D#ql%``n#we8= zn(`M6R^__@^}tub=$Mv{T(r!^k|jQL#tTsNPNTT!jRMdoRYNUpMVyY7QIhcDChHD>N*XL6c&laExE` zKmx;haXN*k2#N9Xrq;r5=ODmcMJEN6)Ft<`p2lC0m01}3Wwv;4ncnp8_)+)vf-Xv= z?D2uy8fO_%{8!F}NdE@{!Ku!&9SAK(bM~+ z(-3SSNUA{%FY`(o#((qe$m3xl>|V^as@&6M4%jeVH)Y0`b-VP!tMD`-(zZ*5WGjcR zGQTL{E;Qjd?cg>wj1sO3d^M2AxF4xyc{~#8c2O^xU!!|BEg?)+OO~ZT36e{6^x%|a z3#)bH|3@mL?PNaKukFz48hAybh2fBZ%=)KJg%hHjZ zF@mC@6zs&UIyX1x$389X;p*L{pW3&Vf4oqzXK4%1r+l_$2HRR9j)PUv8C_c zzg0s@I>^O}+?wFj)CnYrmAJo?Rdd}jJv9N5X*%~9tqR} zxd<2Y31(PKb=yF<^6>s>hem6g2=EWT7WtYB4O; zfEd5wlQAJZ^+BX9KS}fsZ=$*qlbC`uSeUn(_}Sij4EfSZe0!75<$KXPPPS&#oyglm zvlBQle#!aBo5z7ND#!>;8e-eErFn170Zmpm^?=Re-sd0t9Ulq5%aq=3m zK_Qx5qYC>}l{Hxb)C;?!ctO3KFO`ie<4TL)e;!hGFN)LFh?_+Qx@NX1M(^uJ)5T+@}dp}Ft9C_GUh%JB30PlO#d6XJbQBzF=ryq4;;L(~b@j=?*+wjM?3)iI%(Fr) z^c&>adEW6L91U@=LhB3@d3w}-O2!##AkMw2ky0s}<8;vY(<&VX_blGFGf4YL*sGbj zupY0ZjEm~7k=`SerB)rx>d+rpkfF_3lh3Yue0n|*zndn^s z76}A9TRa#<%uG{#P!AMMk5G;{?B|i2LQ4tX)|C+5e@v5qvVOJ)Hl<;eY7pg2#q$_d zGip#?HD<@R=qF~|$>V}HsUPv)c8RI}8bMY9Yw8D1NC;GyP8eN*@jBbuI-S;Hjn$@v z%Wo7$PxSNFEO+l#`U-ND`@~h@@K7gj1{pBZ({Z|gR*TQH4{)hhm2c&BTdr8h#^uU! znAsE5@Wn13C4?_gY}%;GNg@JD8}m9Cj*jeq7<-2xUASo5GHu(ojgvlU+qP}nwr$%y zY1_7KfA4>ds)(w%joaVt9kJG$a}4Q9wi0zqwA&uH7c0IAX!cJ_TYK+C{iAy`;ZSzD zDZ<<69Q6QY`B=TwLyaglf;w!|20IXzsX_OvaAK#!Z+&mu)-%iY`RK4E{f|;c7T3Ii zd`!8p&D1DJl5-tL$*QG?t_{ysf;`!`Yx_?n>wn$42SYZ>!)b<<6gv<3%nx6# zZz5x$e|*8zgLIG4C$pWNrn^uU#cZWO{kod2gwo&omNM~R#%uDZDDST+rbJZ4FedzJ zW55S=Ge6~)s|Ot^a((*Eb|vAci6uRDTir&rt;ya^)zG)=SrKI@*;?SQX87C7YYefC z4{m9BRlw?DZ%p(RA<&X52&YaX-nt|kGqb~4g(+*WrpIgaPVb&?_-kHunZSEx#~!rw z^_t!TFS@&n+XfY?!eIkTBT*lQ%iR@UPneg_MJF)NE#co3XM*vyvSh-+!BJ&z#vnk$u>LB77gI zsgZ)5Ua@EHMF@!#O`M=8&eqG<9W%LQXOX1e@wWO`$cnKPs2-xu{-^r@E0_B;gST6} z3B^z}SIMRc0k@nt&qJZN{|z<3ZQ0Q=jqth!)9{5JTtkkXf{)Q&8dV zlTafmlQOMOmG2M8^4Gry`0&ZUw;~gT4?MZPUe4L7I32lag;%s68viyL9#;!y@-6TS{nr&6*QcJ!3 zS`p;@yAd>JiErMTxLyEq^_u*$+}-iX1_fX6DyWA#3e2(+?N_C_L5~=iXwNJ+n5(et zm#%2}%o)mc-!`%Aru@;fbJ9-!Pn6oDpphL|5D`54qv$$nzI!0X9b^=I-dpZXS5qE9 zpXoFG99a60XIxw-Vd}H*3wuxfh2jGM2Urf-#xVaeP6oFDH9sZ4ydc7)Iu=3S1Sg)p zRqQb)0isom1@Wg=@JETPk!d0Q#!8fX-H%uD)=?KX){bonN0{@o|Hq__P4IltYt2Q2 zgcW>0`2!ohla#TB?_PT%HECu!OcbIYQr;@G%NJSR#|&rhOkvaj@aW^IsogQX*DL!c zQ<}uFqMW$pb~b|sbXrGokKnhi?r)D;mf|5ljT0V4O-(y#c!DFBjvw)Ge=#71w<@ni zg8RyS;CykSgqzvgHSEd;ONiEWTiovHNoOT<^||(vh6Ed(gf_4U(K6a}OAi#xsX9b< z3YD3p6x}z|9N}gCZ(b0fNn(_`*31XX;_;dhhjbfdh6vN(3&0xBBxVV8VQh|6D&fF)33Dr${fdH-QjS9T(@|FSOkIW1NPQoNSEe6Gsa0=x+_AqigD+%*h0BX@ zs`s=BatgDG=N-IFrh$^#HZH3%G=Sq>Ae)2rvq1?oJvad^wg64-72kqAQqi}y_qJaU z8Jm^fT9wG$ewpPdE90!HKIqJ_s#bX?Y53(R!2^9-P5e>xr0g(xhKOnqG(A2RSmxL* zNg0Xj-EvqFwTq2L%;!F6DMEC8nyX0w}l~42uW$6 z<(4vo)dwB=UnjEK*_g~ruw1~~QxAr>9jh{aP+V7jvO`8J_gBS9|MW|-`%D|t;ac-% z4vbQd3yEuEOhR-MwQ-=rV7DDv;mCKUKqnj_w5o&2Jl_>3g=;l{k-_s7xp#Eix3^}Y zT1)V}oU~}#?g;XQr=FcG6ZA`Wlz+}vjv=2hIGHIl#T6B6g_g@>z{YRa#on%Sdh{In zHI6#S{wAgZJK$A*>QBk9T|t%bnXdcb)9?LU7(4v|9;hNdNlWp`%;XI zfgQ)~g%6r&v^PIdSH5ihVhc#jJXX^tI=A>(8f+SY_6wokS~NY2Kct7}9JF<)#Mrdx zo?wAms9*%jHB%+vU(??{^}bW%J)4%~v;60Iy#HvRuLYhTQW~wOHq;hBF`0WcdvRX%4^Xjo5wHf^y4LBAs(ur2ql=9>Io=}^!XrmC`zRDO06o$Tn8zlI9 zZhM{*g(Dl&Iir0#}&!7B#}cD%%uERih4X0j$pgVD0BlN z#@ZsS{*3j+HZeX#EQzg*q`qaRA@{p*s=}?ot>#{R*Q-NShvP$6a4xwg8}fV}?gwM7 ztwDI;$wL%xP|~tTBjKV$O7amU@*z207ke;5G$*Dbt*m34R8&mS5qWuEC`M(^KECEK z;rM4avefGE!;+ww{4xw(o+{ET0^~=8R`!x{`3W;_0K8q#A(6lxPu z4$iPKWT$B)G^H~v0XCHQ396F`i&{xT=Xo7*EBNas#SgaS9e&|6j4^zttn_lHDbmW%2b&#Q*u zDq2Xm$$+US~y9WG8sHc3aBT+dz*+<^C(q6=vNvmcCr6r?q9T&*Hs{Z z*!H^z}50b=r)FL=jboV`RHuSX&Eg zGE68MM+cdBp7_;Ad_32E(M9Wza5#TK_pW9}obh1L8^EjI?N^+j1sY)LW;+IxoGV|L*qr^8Or`Z2KFj1R#%1t#c5*9BNNp9Tn$be; z!p@p%l2zx6vp>#GqAm5!jrWEJ_lo7{07rVHE{~Pe~)Iwf*KdA;;_C{lTz)+ z4Q70?`9FjdT6Zn=rI#Oz_VyFHxjMd`IbFt#I4{lrLjlUmmnrhA%xKc{GJ#y@0Tc4! zytU0*6xf`EXGYL;E9;!iHW>H@A$l3^^A9SYW$=@l^dTzqpD{0bl5oSjnyXs3M-P66 zDtR}HhRusokN3yovIy|u08Ui!?aXt_=ZRx=Bx)7;jJ|tWlPl6R#KNv?7psCZXxG3a zX(~w`99(Dlpy0(L>q*!Be z#JEV2&Qt`j2}`-Rvn7GTF%3^Mu?{3G;xFQ(LJ^{uhmyuHAAoZJ|;8K7gKjnEE2rT|e{Sy#gX0Sgu&5h77ZjE|Z@ z33UbmR#BU>q_kb@CO0|f#J5h;Az z6TuM!D}Z?Zy$0U&0fNUuiy<>n4*A!Mj3iFEe8cT80K#?61q^a{81MP(06E?rh>XO8 zgjN9mmpgFBPQC@S69mq{4T)*;tN*Wq1b3l=1GJwXBO@b!0&Wswm_y3JF|db_f*g=9 z6H3fI*cPZ?I@~;PXCQzkHa-E~;2cco*ODoKyP!u9ifLc%0HzUCII*39K*5^{#KHT| zfS@jH0W7320L=OadLQ_E1up<7f53n6=j4Y63G6eRb$k}#6arGHmsmkO0CX4~ZeDfa zP`FT$7YJ$jmlNqYDrDy~m{$l%J>iCaKYm#V2>pW+Xx=u|e(U z&(Ln`Kl-0~NM~nYAr;xd-FFHRRKt$#UhfA0rw$hF6#V5!+bKZs2H!8;@DBKlGwAO& z-@v7mzoDIK2;dy=A5{R9!gXUp1{BaW0#NZy&bvRM!8tr6z!2@dwy*Zz9wtICD4yLE z(3ddYK)XOlpF{#BR={76fFECg?Yn)Xf*_CqVxusy&A&J#ssn)q`xS$5fs?HdQX-20 z?)x-95TO0LIsZI5du%hr;4Uu!D8P95n+77P3j$)>KlPiiI0ys|{{93V1?(Os3J4fP z(2#lHXbTbmh%1H+`c56|_gN`KU>dkH=zr?9UEbsN{uKp@>*okTz2E!iV$i+}4$Adw z*afZtX5s!teh-*_6VUkuSp4!#0#Yvk*@;o%)mMaWaRR^qLY{H>!^?4dIi!^yFs`QB#iV+&=SEF z0B{T45$s>_w-5mb{*LRnZ{HgIu0`#@C+Xkv7x||hkv%4`s(pGd41gwr+Yb*$qJkP< zAvoN>k53=3C3s|HR0I;Z)IT%^0`wb40l)JBkiqTa1p(4%K=+` zqb;=`dVnKy;6IB7{DW(_X*rhVPL7tJ7OlL0(eAz~Fy@>`%PI-(E$c9ZE9Ja~y-6ks z*{tQ7Wh`5?1x6>^rN#SxS?%u^1ManPrMuei8R?>?Ly04=AJa1rxs@h+sH2dqB{Nuz zGK**#k>Z%E3ZCsuSVrGs-88-t945oy1H4#qC-@6-$&K_ zRU>Zm4!Xw)uZq9w?I8&(8qpOlxiyekO1b7Cl6tBpQ=r1ZPshD7_QpYMyuoX48bgZ5 zlS#obQiC3MCE34v5ppBT0Pa>gL=YD+yLck)6R$oxNj}a)Tb9hKRBde;VB2i2u$l7OX$n=2zQJ(*+<9_v}KJ z%fxFfdK675x)e0TLn)i3ot>u3Sa;bKgf(RIIvh*sS2&i1MqACdCwC{5xyJs@@gavh zY~(M?Z7QP`zdW9k{s<+_Bg?p)Fc>#e`fJnu{b(rd2X|%yKeQ}=_^Nb4b8|j_6c!*OcL|)x5pFJ5W>khK3azoj&^&9R7gwCQH!pT{5I&Jw4;s4!5}%!lx>9 zN#PV$hSq$u347b_F>=|`o2in_t@J3cIRr?`UN=wkYX33!jSYBOnnW5~?C#J7Y0IVO z#xW%l$d)VbP;Z;#+Vjc`z23}h2F+D|wUT8f@Xr5(qGZOkfXx<)-gLzKR34!JBxl1t ztpO~E$+{Zi3s*PDKbj4RtMC(i!a#Aw)u5w_k69M4uVqvP9a1mp6T<38#HvlaP2>kn z&6bw1uQXtcZk?Uddd9jPgh+yefZC=upu1BvT$s^+PRNJ3enOB>n%^V*IaE@p<^Y8- zrPwu29Y1&}G6l!&qg2hqY2L`D!tZyLQ!0RkKk#30xus348GL+_NZSEj`-wSMK4^{L z)cmY!hm$`OvB|z?4~xo@QAfi>m<}o;PY;944;ltn# z_3snMN$UA<BrV2|Ht>!eJSp1S!N;h6S5@$Z= zV^@;slzmd$IZF(F@?a&b-?4wbHNy@v@&fM0h@`w|EQD0PUGgS#>T3OU!}S>Q^RL)6XT|2Pa0)I;^ ztKRrvD)CHu3!JO!RKKJoXtA|99fK6@tk;|Br&aL$g+y1ZMLE|O|2U-74g$cxr})0^ z`sCOKSr*V1Jk<207~hTuPPdUz8?m8 z?%zjXS%3e-mF=FfUkwQfXGyx~9ACmf`9)MSkn!xmx$wFY$- z&4c1cPb!$PHNr|^QO18m=jv@_RV%L^MLB5@vk>5l{TsRg2@yt@a$yq=tFgpRv%U+f7IQRWI5B9#S0e#SAU^&+@W{k6m9P zx*nRAv@Pdj$nx-JyaWe|ZJ+VX}3g>uF z(H+Gt4rh2^y1wz$oZeL2;s_OUo{xP~yBeNq=y8mS(DhCcO~|Y+{Upsd8vsig>B#Uc znR=~CB0hXaDK&>vCV&dIa?fCyi7i0i{6lP$WzG-sjOAFCsF>$e318D|zqwZX($oC# zJR(@6==I|GN+ZZK__D1K>xlHn@g{c%mgDlSzf&Y^!g%gXWN0u%L+po66G$~J(|Qlf zM=J=!g=RzfLRqCe7VH>j@Z)`inH+L-<<2Iy^1Y;??;4KnbGkk<^5k4he@u$b-U+6u% zoxtj?b}X@lThSW~ZgBX@*FPGC=4I9Yy9xdib$-}Rkox|>Ji(YoLDd!C?QF?xZ!B4{ z%D%U6aTl`cm`1#(_lc_CO?;4-VF{<A8gTnv$=?-NEhD|&mb430+unNu-wHSn;NKm>&7RhkY zuu5OennfHw*5P-NHg1M5bdy%kDgCuAt>>35Jt=i4nnU(fsyzd|Q}oK{Lwt|lRlqj) zx@_Rga0L>zLzX(zxHs}DE*KK-PW4t4`5(`)xfA(?UH6tKGYMz=u%h6 zK(=*px{c0R5gbN7A`W_AE!iBo6ufQi)kxD|W6mC!+nc@DOTl0VacOkIq)}{BWlz}@ zwP3iSzfR+K(O~2s4?r&_0p*|7j3`~CiXeHC116Z=6_PN z99)RA#oiGk;vAUeq~AYeTdC;dVQ!uNr5V)7RDB;iUMcM}d*p)FI=5eQQSM|zRg1l9 zCvy4iT)I_F+C*SRZOM`4P7>ALJ2jVe4+Jgu_)jjBj-MB-=8W(=^Lj-=NQk}JW zDLVqGfwAWe?~CsY?>{qZu)a*wqpX&t=!X7?3}41JRZTQwhFXp(IPIq|GSSep%)CCA z1K{mUCN2tn0iiL*t4iLnx2W9Iz}PDf-_F$qoJUJtmF#t}#)Q44*oe}#J|Zc`!RJ02 z^}*pceheVtx^P7Y(D;wu8FKYV5=9Mh61aG=h!blJ%s2F;Rg-ec*SJl~#D)PRlP6LT z*~{Ci+z%OF*i5k8wI&IMU8Vd{=a7~1>MNvPb?ua5Ne4ZXN6%M=6Ac`~TlKKIB-X03 zy6N~q)VVAt0&EMnfBDF#?rIh5Gj>hv`2pvgc8`(tC>m@eKeF74bye)4_UiLi*ox{T ziF5x-D3pPBGnQ~QE3%Vn{(SJ>Ux-%pXG_jf+|@(epnoV5mcTEr0zCDuuT>G7G~*`! zU~kOEXXdq6p=_W_Rb`ia*YWPSQkpGH{9PG+on?;Dtl_GTOf`1&pP!V7Xqx1!_Pexj ze-T7J6Z(iXSC@H8d}8Mo%drvr{rGO+T{2nXMD9~65h*_b3NFbqFx3#Rt+7`3t;I(l z*<=sXo0vH8W%64{r`Jmn{5JRV`VAD(uDoA9{-8~V{dL_V-=29u(|EN2HnkWG_p4bU zBsZ$EIaa)1czxUYk=^VkqfnkJRKL@>fdgsB7P(C)KWPO~F7BV52;GslhSN|c$?&0~ zko>+L@%xzpM#-k$v#QqGRCKIoYUH;NdbKhBN=D2x$!Rrp;vw08C9KkNQbiNEOsY6D z5LS73F;*RWPm5`OgF`7Xhgm$V5%=haXtUI8?#vQFjh}_gMJf@06Nb_lKu^LQatEc9 z`FxkU0hLp!51hoNEe69HiFN|9jwN@rkZ^5r%;a%AlyFw{oWyOyes>=;%H`49O_OHD z;C_-2a&OPI-r((r))@8%^w#it$SH(ju zjTq7sMb{|PBmxAN-1Q@=<-Q!u=w}AYFt5r_MjbgY+p~MgN?9RCnIqTq)bVJ?yol(e zIqK#2CAP?fHlpxLTtUmbT)(4YUp3HC9B;g2?&vc$v(`-7Ck{E1D)2}<6$d9w-E0=Z zA33gta>CL&o}JrGK0W+;sY)6rb+KVbf&XwZIH&c=qw(1FftPwP{)WJAgZG4auUN`x zg$TCc$l`IZAd=M$yrS4v9sc*NlrIG_&!(*8$k~QgQgW4B{lE9Qj5AgB`OqYl88Eo% z498daL#oLF=U8weTQ9J3x@~@c74AbBYxwijV%n8ds5BxsD$0`d1bGSDCAZ2a9bNs0 zh%GwjQ!7Eu#{Vl501ueV@mLRh?=0MH~ObXWo?Tw4(x}CYB?W>seN2$QwY0p zc;mkbsUQyqsU`%hd@IulctJ2MM>hVfOrMK}dPB*9VwTAQgWP|L^ z@g%1`#ENvBt}h=a)et^Iz6?Z^1eh_h($UDz`7rcEQU7e6&uzCAc7A9stuq}Pc4GZV z+33;eXcjG5Q*qkoh;76LQE~T|7l~{ASg>BEjt0!^exWJL`99woEuK2p=&=QkbM56Q zUkHDzk+XNzerxU%mFWr(Y+>NUq8zT=pY9Z(K)c&y{R&aq&xC$jqf1gZXMe{VrUUc& zeVxckgDD@Ugok}c)K#a`sdhj1wrSshioRf4*P+|g@rMu4DF8isHznm2#Wj?P9u59- zYMzAmKNq4>RwA~k=@2j+6H-iIqvd>AB028jRcRWq?kjyfmB@JDOwdR=LLijiXknP^ zqu-UZ-H@yL=x(e0a0&i$U_%yDPbIht>wbBR@Ia7C$B1R)OP#Zw4#9c=*@+iNJo@$Zk>ZN|Bu;p+f{>obPD?4_lX&A^RQxJYHFL+ zA=cC9EW43PR)1Jaw65UDy#B_cdiQ*EsXByB%=PBXuA`_~)Ce_Ln|bvN<536nac>2C zG?e@wpcs1;XQ-$Y(X|X6StMkoj={C^P2tt&w6MfX;CL3^>I?>xd=Jz=jN!i1w0e@B zuW3|6@$H*((QrJ^4ZBF$y#8a91_?QMtY=|DS2_IO4=NM5s<-7kLmx1W?9vOm+KV&q zI@hE^VewNVAbFy^{u#`T+j}QjpK>vwU5TY_^~D>KM@1JWTOgx<5zabrw_F);ECp2P zK;w5rSQ3g5&o^7NbpgQCrrVdHivMls6P+G|LZiw5Be9qW)Nab^O#v$>&?P-cNvBVS1FSpTXInMKT8wb_c^ZM_KAgZlodo zJE+(!8;P_^DU7U>>+AW-v6u*xAa7(CzAHkz*qh>M| zrqD_;X>}(GU=0@JjBNOR38+jThx~;cqV;3QEX6bUqvp3M8v7`xT6B71avJzwZXrhS zhICz+^1b7LLi_Ib6JPHK1R)cpZoxSya*;4Nh$K<&2DiJ`@6v~az}`0R96fg$%z5+M zEBE(!Lhy)UjC?oJp$W>?DtDziVPxKb=BAWJgABDVf+juo8qyd2Mk(neZ{X?zd2HpK z-lKhJ8-)Vx3a41PL_c7;uc(9kq1^0_BeWBv(7l;QsQ0fssdfA|Y1cUM!ps-N)>KIG z++1oU?$?U8o2a}e!!rC{li09syqEc$*frUnqI9sZR^JZR7WawfVpo&DrdQ!&Gtt6h zoJ_k%^2>n%+pjNqq*4r)Qw$S_oD44w(v4Lc$Da=?hyB1-wa-qvBOY&`V_G)uPI@wAx=UHYSXuu}VxlOeJ=rD@px2_~) z)cXD=K6l+Sb%o0x_)I=_L?i!=F@go(C)>-#+K17peI-ra?y8{joGFu$0chS=*z;zs$#__^+k3qF|UsiV{?JLJ0B^|tX0 zSX?kzr6(L<-r2!^K3){Yi;s#iYX>CtADUwrZbYL+-5YW(?jHnxS_a$W&h9%U?|FfV z@*ks$WPI|T$Bt*x7iev|Q9|ksYqenE?#hId{=OJlq793;uflBNyqCy$G8;}0RJ&R> z(l)fzFTgujY`-41SAXNVQC^@;0nN6*c_eO&`&c&W2vi=P8-QD}K*F|Tn(7e+rI_t*@%AvOtSXoTSL>n~!4S)0H(H)QrL=^HPW4Q`osvWRMe`7g9VRGiyCnykoLaqBV` zZTs{{vYGY~%XOBJu<@2^T7LuC+}+&w7zFdGo)AsfCf=EFTZuyRx0kZ%s>yZq#NBf^ zW|!Vux$kXTvtS}Aw?5q>Y=ziC2f8|=3@s^i@lEn3Cpkn4>Qqw*HnGB7V|^%5l{yvD`kaC1M7b86%@nND>j?Al>W-D)&?%LPO;!;kVH$t=Sqq->=-VUTK91C1aK_~;2 zhvtr3k;wG)$ct3?r3`PYZu#xShNW%(W&7HsfX+5ES<9s8;l3l|I!^D=*O69399t`h z;*rPPuvF9&8(^~VMIqcTKcGJ>5A{-`6+Vf__f;B6+p^5H>!J{%ZtB_BulyCJ-e&(V z?P>rdTp&P4K$`cRI@w|YV(7Y#gGW)J3h8t>e1wR>b!a5qK_C|FJK%O8{Hz*@byD1; zOp{!eW&2Ob(gjxj;zOshHv?fRRKylv9E&bo1Wf**4kZ8SmMYD;?G3|CZp|f@<3m)m z>k4W)^v!f1YOQwYhmrcV;V~3xNy?)Pp)qYyXD}I!^|q=m-)ipJLQ|=S$^t3sO2{O> zPKtckU(R${SYL0~DR^EZ7B*6i$Wvd*>Pew?MJ3?C)71z#!scK2U!BSi18L1=haz#K z%<0R#Clt6K+2fs`CrdZnmqGN8dmdp@uuY0&k{r4|`zT19{KrtFa%kzJ%;cBcu|3KP zQUN^}6Cb*YzqnO(+;MqXwwb1t8T6OTF1g$Cko*h$8h8F&ZCdv&C{0ofYr-wSh3=gN zr^uqfAO4VyY8%&bB zeo3rToRf_BVP6{xR~9=yfy?o@+!s=}n@mXQ?elU+h24V$Y9WZZ*y-H+y-hJV#+evP zsPh-ga(=~<4Kz%3%n+_@DOMl+4>wu{?xVM^Z8ztzm)TZMYhC*!M2l*F=Pto(lRv`A zuf}ZhjBHw$$~opR*Y>|eQNU|Wk74 zRAYtwx)|&m?>H{gTTpZPemj%P)4Jp+$9(cu3{(D)EuOd;RfFmai*yPjLX8T5mJZXN zlR68;kCvWDv{VO&-)82BdO)=9Ie?LfnK#vUHj5ORG{U8RMTP!|j3U-O1AqO3DVIFR z))xJ%N$rLdeVquZhasI9eiG^Fg<*^mDFI)5nN;%u>zt}Mf;63r{Kg`hxmo1DJ2G8s zb)g*pD=Uehop<@=sSJC0(t|~I0{O1qJGTSM2Xm*R!tmOd$(rB!s;!HZ2WA&FpcgKj z|0A1rbl8n?mgo?%*Pc?Xg_r!MKe-2Zgbv`0ff+6q2ssjQlX`rWgUAxs}C0nip&FM_Nm*(bPw&E$Mq6#I&4I0KG z2t;i+bGgJY_8(fqfA`I{m@=hwSJmc0LH@%7cZ&F%>-myW@sSohbSGQccsN~Vi_|T|Fc)R8s0n-0--&%3 zld^-8E4(Fgn=Eg!d6l~~=qX*`P$C+5exrc9NPWi(w<@3)rqCQ3iR3$X%-8#xR9aU5 zbvio55gY@irZNO?bgz0{BTWgQXtL;9;~Hy+j#unY;jhz!M6SN+mK`KN#XR0tJ~>(f z$d39NZ`YTvmGSJt9ckg^Iu)+@NMz9pc1j+a2iU*j}-TUdI(zyrEjm9GUV@ega@Wy8&9Kly zXH(ya?kRp()}x-a!M(?>qoe4_HvW@*y@X=ux2JTejaMZr$C|Q(8wnRh;Xi^_BLG%-0e-Uajns_|y&usj3Af)Rd$Ig*>>-m{#016c2LH?5lFsn7Yfz9l46RW8D2Z{mWIU*G7QXJTh~02Mvb zOv?aKP^dvrP+)*LIk8J);_eF=fjPk!BsZ7#;?EI66v+vaVkXE;kAs^~+S@}WIJN>a zHG^budt`8XW@G@-$;fO2j4kelL6KOUn%Tg|S%FNhZvtkaj*DIq^5oJ^F&K!l03R>~ zEQJtE&d$z@KPL!CZQy@2v#>URk7IS{0@{egP)TtEs(K^I=SQ9dh%4Udbae1Mu&{S_ zcCce?aOfNs+mFo4htSm!6;EnwbLnFRlhW4ybY!9g7ZvHyod?mww|HDkCH zlM@7zFfg_RX>o?|?AXi%$ps>E3aDzq6I=kccx(S}E`@Lj@V5drFf;h&+!omF2hrU8 zIk7P@GP1uiFgdfdG)G`+ZUF{CBR|H{;ng_@5_2o-hl{nzxe@vmvlC0>5E~^5?w7Lz zOF&YCzzRh9rsOk6rId!mG>0&k&eo@9`Go?f9n67 zqAH~+r>__Lavud;iilkE0qs89$N+g^xKRK-)e|3q`9A#EW08|i`Nutk*Z+rN<_q|` zTMC+d7NB(dG6$;o)kLrw@HeJj4=%%iD){6(?vlBdp(sE+1)M1YrcMC%gZ`o){qP?E z{)CX~*cpARs{UsHVQXS-Y3!K*L_wjeD=>XP51$46^>2G6#r<7rDrA;c*XFN%ZA&z= z1#-yEwCyi_acOf%DdfD$#Nx>C;hp7&cHOV_lnvcYfYj@3T7Mln5MKp5KpIku9@Tn& z12h1pBMUGVxgV(+ zQ1P+-Fi6()UIh98)emmqx~V@YQvSC+n32Lareh#hiXW+hOzIvKn(_;$5hzpDj~Efe z%O2El!3S<2ix+_L5Q5nPAVwrzya#1s`HdU+$m+(z(g+cx2gjPe=d|j7;xGTx52HXs z0U&WxU_$lARTu+^501V{8(Dv4->*?IW&HvRr3~yL3)+JGh6f&{?=GOX@b~Kqva@`_ z3qhFq3%2RcKXU$>e&aSZ{|4FhV`ut9`$3umOzrM2pCNI_2fh)ZqU;}d1Qbx|c=721 z-262HO#JUz1C^RSL4zjke;~n9ujiHpUs`@h*%fO2#LXZ(Hv`?y5c#OwzxKj`xwin~ z@KU1(?Ko)Dz|UlxKjp19(*Oy;mWCQqI_Ny~^Yf44dEDp%KLH;`RA>mU5qv6o#fay8DL^p#ZDSUr<4O z=Qp4rxf8(rU(_sKfQYK+j1WnMp?)tMRP+(#&yVa&e)q!g3iL8_dcPjy{K$vEd;K1X zU;*Sjn4#h7Zpd5lN_#xLyXqj=?K4mDxAHMhmVU)WFJ_LGF5&KgUs;_DpyAYo^xLxm z*40xw=dygBW@9%s2v(?{j{<%1Q zoWRwD*!>%p07EhHK%bB{#2Po@oMo42n@O8Gc5Dz z{iMN;dDOv$f_(1+89-0w-#Hv_^0dfe(R;o)Gy3~gJ@d%U{0A*+Wn;(N0n(wRQSy-Q zNPb?S1Nx?XvS8LTU6qDy&bx(ib-|oane-l+_{oO3BsI%Q6if9z-5ZXc`O%)-AME?Y zqyj`^p2DsUf~A2-73Aus4I-4G(ySF6iHoo|32r%$BhrNtj``whZsB>fd zb?fc?^zQITxKW!5N55%kdu8bHO9wTXM6|e&cdu^tC3ySqTM^me*x@#Q3{mA+fT4BC z(N!{!Ze$A zGQtbbss*ZrRsGS>z3~DS7D2{mAJkNA@MK47;NtVw(~ys0#n^iW1>+v?o+Ar0HLEb9 z1Dd2pkMr2!oKBufFmI!puTU$jO!*V*f?k%r^IZ!TlEaWfeSCcgWLD)yM4d@m{inbi zP1&CxpU=yJkq@iavDU|6ppMPWsw%dBLcGHNXlF}EZA5|(Y%Fr;Y}IuLqZT!U;wvwU4Cd1+*V&aAPWC9ueC&B0BhB=`Wg^C1*YM^* zT(Yy=HqbV`Jqps%QJu`3+xgvP2G9Ymw9RCa1Qi%q^Ky;m5i>oofy#W-oVL zL5Xsj@F0~XH6PyXiBVaXDOydi(@Y%^AuD+<9LT~=dSeGgT1ClNwUHyB_|hwOMaGrF zT$-s^WG%_m9VBQI6E}DXcvINtDferxT=ofMLB%0R?>-+6?oGnas5HiBP-AI(|Js{| zJt&>)-25C*X?QvGs_7mnHwl+>TPS5)_L01~5vR-bIJL)P)Iz@=Pf!?TD;)h|b??mc zan3nWmm|^bMqyud`n3cr@;KScuGZ-Nho;i^vvgX#T zlQalCZkeqb#NZ$uU{>|{aS;I#eiv}J1SR2IrO&xROQDc-=x4Q&k_VK6T8uXe z#}o;BIQ&OVzQ~9ors#U*Utq;if=p+UQx8WhvqP%(__1YhlPa0NZ zI9Ds~;V8X>BX$4_mj?GKYBomnXyWl4Jt^!bDYGP#unTwYP0VI;noD)aFF@&5Ry;N+ zZ14a?u&252MY68hQYLE$x4uJ;YyGjO*C%hI-6>Pg!;9JCj9e}P8N8ER$PUKHHt{hj zXWL}aDUA^gdhqEK4A+eVFK@q)<-QRmsx{rG>7GYiiu5Cjd2p~p*p3+bw>p`l6V1ET zU5m$=Jq5PdAS?QaM+gnSQzoz}0F$>yMNHabDpXS4<4ES4K@qI(mw?f*GANTy%>hh4 zOgh&lesl&M)68(~F$s<8WLAu93Y2aN8yT@zv|Rx+uz9rp|pSVd$|g5w1XwR}2k zN~aD^y{@HP8@2>d9i->Xx3Y-OF8j7@Whd7U>T@wKjMj-$?eFBUi2gD%FD^crX`XsRQ~0dXBqq@xXIw&D8@K zZy(-^Wo#LFQ2m|t>{+c|Ogt8O!Ysai=Z6)!aiZu5d@wtL6aA_-r1yAZ3aS`6%yp`k zHwWc>(D#HCe`}IlLsQ!}jpLjnp|v=Vb9j(4j$JA$F(D7V)$S7&83rCAm;BGQd<`W= z5HsvwsWr-F9q2LxLuYZuwuisl^|!TMRkv73?R^1Nv6{5*U{&`zTg9~l|p$vh6;WWG@YC7p%j|4>rz}= zsVN)A_~k(@<-oQ1y;zi5ae{kkmmlpC;EC-|T7^=GYf!}~`0IAB&3LuT z?$8hW#89p>PY-U%C|^AXys_8&DGc3h^Gt4SxoJ0-E#aE^3z=9^Zz@Np(jmH zHkQvJtmabhSMJm1*m3oD`4c2Acu&mv$kVw%fQY6<*{ z9vQ9jgV%c(a!7nv4HHj~#3(f11`L#J&nmxfB!iJ!E8IgFc9G66Z-Mt8m| zZ--Utl!R(ju~I;mxmtsq0)Ou8eCy5J=p&X;*fL3&AhV^`D~d2&v1suPwM_jOK+^#iK;h zZ~V!#?E)oJZ6$Pw=~4PUNSumEa)@`d32RB&5hA9zKhau^vhh3kfn`^YXZ+mag zUiWno45m6@g5*b%*5~6xuzQkeaA~+{t(~H&EIe8AeUk$5%7$a2$25MCg<)wuf&f(* z=3BtKtEnb5i#NkM${}(VC0g`5AN*9EUObK10rE;(lEpLQyhPkk(QoyjiYIWiz_25O zh1dh)SJoz|@Dc9P;{*^hx`XNm#iXo4b5XaPv7E3zcq}I&>@su-ERN4sR_2UZCs!=m z^zc$7RleifTTHFG1b(76o7k4{N;9nQuNTbSk~RSoQk9}e;(LW|i9dw`y4itoVFYGK ze0Zz7rBPkN+IwYGE==O-*|NoRF-41+X+o0caSomI!FWvmWj1_+(ae{1Eh+8j$JhQX zQpw^ZwDLVlGkNC;*lFVTn(EKKPdByo4O%_5(fWu1({tojBmE>&ZD)~+Qm=4>BQeAV z_jQrH`=Q@PFa6^-Wg6Ua-h2zxTYiT?wg6j#vP3CrAsEP>!uL@X_nENynbH(*$pJqVDD-d zn7=-vxG+XdBfhLh4{x3$th0qzGndj|C7-y6>B zPc}-*-te-Q!sNU6A2ma5OFKE92^X=N34d7ALbG%&3+P(e?!IiDI6Iz1*K$HVAQby~ z!xJ05Xi5aDQUJLENDy{GLpq`_`9z0Fz1d_`l0VpFu{p-AGhOKV3a7e<%Pkv^_Yti} zO}5zRJ=wOq`CvkwVvx=zghwQSV}DSdCzLc*(rb$qD!W`^iFAiat*?&-Q3qL^m)ItT z`dHT|_hzkV+ScbXZJyDyy`HiB-gM^n%UT=%1z-n3Ke(amoe%`R4^-JPG1lyI*nUlF zpZ+2T!6{>==ftC-(RmK~*8$`RoyyS&RKv-(Ve!noE_eJ+=wl-y0;C+TUCT>3qmMY~ zzE(q3dxJucc@aClz5X63yJwnp(6A{xcA?HOUzqG@-gv*Mv=P)U_PUDvJcJ%8(6GmK zLhL{&Z#cSfq{Lp;FXglVUYmG$qL<(Ow#`_1)m4=eCafk<+7Kj1! zn^!i$_bhr{pV*3|Qb%&r<}Oq9JI5X6fcD?gzo?&F`61mF#K(_w3LI1S-XomX?@g*-lQOTDVI)Zen zMfPUu-DsRzcKsWP+Xvk}{O4Q!=>$kZd`Lvz6!;FGLluCSZqEl~Dc5O^SLNR4@h_Aa z%B%y%ydLiwVu)FgZiQRx&YiYPHGiz9Ta6_h)rFQukOuE&Wx1l4#>gytpA zaP|~l5n)x|cdjs1^OaFITdZr&!UVRmnKep?)my|aG0cBggP_(|g`S`%3bu3ieWpVU z(^hB@#~K#}zplJR)Iy9_fdhoV>hfZLk~0;z;-zq$XI?8RYOne(+DFwW1+v@lRn~C?B5G3(_ClsVmOSF(Q6oIZpGen_9gq zXsleu3bTN9>_;p}Z*jIqrf(FAN05b-yewO zQN@TT;0Z7*nXzpt>=I@@i=91JMP%vW$BUcQ`EFW2pYSA;uDkplo2dNlCAP`&B5uIb zJ&F&^50^G8=83*E;XS992&{^ZiHaAzVHvkBI$2^LaQMrb;IYpdtDiolBYb&EQ~p?^ zv%Jcu-ua&AE!2m_B|#I~8}jvP_!EWZWf4_&?vT5n&hOySC7Gn%vpwnG&G*#~T2{98 zjf*vV;b4}izR{2YqTFH1?)Is%BBBzug7q;KNSw;MwY&=W3PLDwoRWEkO{GN%3>m`$ zeG%xb0N@;6x<70#QHGx*(q-B3X+{EN>G9@PGz(OBlp;qegi9nTgL<%gmLG7wk53MZ zpRvr3ODS=7;#3lyXl-i_(tnc}L>HHjo6}1j5DDMRB0~q$yI>*bQ*PYd^xK8B(BB~1 zIv75#^3Uskx7hD(`qjaG;v*rL<%8uRu{|8OQ^JV4x1HAyUk+8hD}E(|trP6P@LDxM zi?W)7a)E-1PGQ8YqJ93erXoiPgK6JJIld6d-dys&us(hT&Ymn{#j$?Wsr}u( zMX%VrC%9<66sxk`<_^Mez&73R8w(w5Q3_=Ey51}>%PgOlmn+~wjmuh4_&YZG$afWC z8$^|1n}aBI3&o>ZhpBYThOefa7Uy1 zP#-8171y!^_C}`ur)QgxY_1(UU3*40#j@8lKz6t(3;FiuKDu~hdqqUV;oLb|;HXib z`yEm^@@KWNjP~KAS}a}HFSB!Km=i`DEIkCO>bwy3;J*FtACo2uQIS*Q^k`xay;#_a zO>S@c<=DtBSe7KJVM>qO`Q{Bbi`F@*-;|XabT1$=Wn)T@U!Bcs2Q}N6HGZjFVQ)KI z*WEvHIrY=vM;>aSSSENAvw&xj-x`tFE z;G5Y~4{VKU?J3`*m|eCzf2akvvUxY{o!kfK;cHDyWuqNJ9o^0sMz&h!anQ`>n2WY+ zyjpQF8_l3}NtO@lRK?-0DWj?^)xbwPNd^(JOnSUctqu`bkhG0eA4)I`nL*uHzIbw?x*wmQf| zC1DQw5QiJ2K|qXD8u78Bnrb~=EzK5PYrJ^pFp+M$6KQ4SZ=>4B%+l*CiOQ4&DfVia zHEbV^&|3`Q$2X#nH9p)(!1LK$-TIqL)$tIiZ zh!oFd*cF66(?$%PooWH!^)%T zx#8{&wbH)x8u?R)%U9+|wQt=0rKRZBH1)Fd6!XYyqE0~rIfIZP2 zxIsd4tCU=|6Z>6MXvDkgkw+X(C|+Uu#J~8C81>45C3fTEi@*1`7z&Z)I41JzBr`C? zOecI9K!lto&i4^wTLZvXl+IIXR9Cm8?h96yZ#Poy?KxUielvrjsylEA9%B$V8P<&@bEz>Mz1Y2_kN#3Ne~GrW8etsD%E?_)%J%8WVXs z`R`7k&(WdNO!xcXy;WijDScW?T$=Q0ODR0{=01O|<%A6AikrSP++p~_xagDlv~1t< zvMT*rBned1P{2QwXXskPHl}&!{bM|)pbQUiz4iIX%W`?c>eh2fS1``^glrQ{5BuA; zAOC<#SR-#8`^)t4+KX=1)M$foe|83(CAG0J&dv3U;+ouB&tvayst;%ZvQDGfQeO4gG>U_Ih zX)J+C8@giUb$7#@1iikBojV^;P~e#LWX;pvW%k*+Q+kz$sG8Tqpi1V3HkT;uxRMBTFEi1s74Xvbmd3tiyWv{T%1*B=^zQ=|=v2V0{9u9*+DV zZq?zjFIhBu+~PX5Y>z@pK>&|>4|r`{vzjrlQXmmC>^h|eTb$v~b_WI5PDQGBr35(K zDaPwnZ?*Dc=aFTW~*ivHRybqrhu7d$VzoCqdMzjcxY#(IKE)nBvYWp#YaM? zd{2Mrdd}P?0=~wB*ah{FC%wgLdAv>r3LX{)uYi((jnjbdU^0UXTq|t|MR?os{YGIspkS}X0JLQyR)C89wgf$h>mF8M5o9+uU4$|HOb9-CB)3-)a=sX0 zBpe`b$2?LQfl#y`*zfwynafYSJuCj1{yW!-3lOZw&@i3Su;Wo*dYXT5LQOmRx;;d< z&{Ka+c;0)rT7nV@t_GmRTuO#}Zh4|Y%}KIj77vTLoUf9o6>4!FRCL`W0wX=_H5FR3 zEF@yqPakGNN}|gZ7z1mNQYV!ghuKzlIUad~qWAQK(V&R!o4aQ(!cD?m_F-D?v=oY` z52lFT%&R{FzAzxLsv$=*)aCT(gM<_TXI;nRHQrjnKuux23Vewo6~Tp?;akT|k*LZ^ zt!ij1MWBI?;%62bGvVd}a|90^!#z)J1>SdZ!q4JR@X+hV%J!7-C_(B#e&G>7HUBd;ecdf*`HH4l7DIqmH zjG#TgBz|4sr{V08p{cOZNB&|q7tT4iA|HqEg~&wWu8vU`bTl%{sCa%p#98@R?VKVo z94Q~3qAQ2ehn&}jm7bYn*+OXe*1h${A;86#AxHTEa2y+E z6|NaA8DQC@5!^5)!rr@UejwRsr}Y@mMkD`--srmOx>ge7Z-4oI?ea*gSA$!_bavF8 zEef8t#z{3*JFS#~jO~g@bq1%Bm^Ygs_l?W;cT5uCiw1fcvg~03%t~WijVJVAuIP_S zbh0bjHwyeQ4gnrf(TN9{t6x?j16apjevEvi{H~FJLO|KdDYUnDJiEHPH6a29CT^jP z0#~o{Lc;c1lG#0LMDBjk7f`zX?(4TnJ_%Kyo0gMNFP(3?M73o^JEUBcYKPJTA z6mhVolDlapyEDLK_JsRRU(k6HW^xdY1uDxC5v*}gHR(EIJ2{FZqpoS(D97T*y#)?e z97JJ;qeOq=U9ly|*mpayu>4(PG4B_iY=QT5kDki#CzB zz08N(-$%%t2R$d=qSfKnvjM~`Lq~HG6&osueS-w)@gns@kQDTBe-bUIIro!B-P#2% zR!+5f#+fH{oJf0}q!;Mwv}+wYp>UYUBXO*M@5*R%qsS%0=((*aQ{(D|J0%?0qm;EZ ziQ2(GUEvHd+w59>TWoFT#fpP%zCaHI2-_C5@dry$_4xu2s{{$&1%z zJb0F!)cz^gq|(5cwE8*+4t%5us%Y7zwfSuo3)AOOiG%|q->DiaQ{NQc__=|1n!aAh z$6s#P?2s7}ly2&mfa$H{P&pfQ1;zMmJBe| znmS`r-oKIC?Y&v(O<#Wzy&46^>;;_h`$%Jw%I|lSXQk1<@eZ@6WokU}kwbuLpcH#~ ztg*<~yh@!OtY->My2oSm9DhZ(pzi$q14=uDpsSIMGVyXVxV1jZ>RKnfNbq-u#29BQN}z1l z3B2Od4{nbX{{)?RkE1*$ssnc2fVt_JB(T^`|z$2ro1|`5g)&^JYAfELT1NLc}qUo&(DR zf~Z99B_9UDoS`xbn)Km>-qW;uqX)iJ?J9#9iF>qC z&eHnq?ufbOtbIs}tq&Em16W^XNU;dQ+hA)|;06l6Vmg`lyG7L6>acVaPwA`fQiQ$O zFYX7UQn)<9p~dQ~-UN(m$4|mzh!ZQnTT``Rv~bQ}&XMQCVf=}EMtdla$UMy3VF7h} zU#3cPhgE^aFN`^XUfN!Gp>z@?_w1K9*r^gOD&CRgfOMpzvNs`vqWRM}OEJ`&j`4fy zL#K^3^1bNbF*mG}EldWRxQ61KcE%J`!t0se{h7pw;kuCMjPDDTBK6+w*-U8CC;ThA z_$*7-7WHXp96vbLJqmjGF8`vHsUquw+%E>9C={Hx6VF14 zJ6J1L!(?asTQhT?yeAW~jqYVviB^lMr&h{XE?5c7FQg=<05%6T|q52vS`e`T9 zN-%LBp&zd?DFq`%(GexCi(O&S60y;EnkV%fWMwfEv~DWNI6XJS@kAFNtTyJd40jo? zm^s&)P9?Z=XT7_ZGN6eTU;L#jCc|vru7~=iYm$g_o4%&IjkgwVM(LCT{ zJL1`i^1F1K#5m{mlY)Z$3guDO!Y_iMXI|K-kihLXaN=I42k$<$Bh;;HBjYMCTG!lj z{$M3!l^7Tp?!RL%bsc9Z-jh78xCs{9We6~6MP)6&j#0G<%?a>;^&7oqD(vWo?2~%} zj}F8!WXtx)E2DD4&%^{nnS2-bGx^H5DU=%aSmL`>OCxtCYnv9!<&DhI$k&ze0VO9= zpsV?2_WR?e!4O{-Z)7cTAR8?A0&Op1-&YGkbm2`yE<^GkG+${e%P5ig7|DEIzgc8K z{ct=wlu^8Ht?UoReeRV)=fKy}=1*;kU@|_w4N#wEzxyOW>aO1FP{!VaC=X_tX7Hj+ zccF|~Bm_=Jt4$lgkZ|ocYCCV=wtIcd>?o3+&O-283{EN9jbaoL2vvcwE39kTRpX)oKpG$Q8Py4G8bqk4PLaByZ)r4?9BSK*k#yp5UreuAnI$VAsAI%4HK8TV z-Zst}7~M*=E3v(lK5!lW6jXMMQ?r8v_*!^To}?TRIn9CFS`sgk1|e{s1Ud@c1oKr|8|_ej1^uh8A9vOhl+eyGuG=o#Kg-*}Ui22HCEPKNe5 zs)(fs0p(fdKJ%M)AAJf+w^U5hf_gErkc)f|;*8p7hf!!eUS`UnoNNSlKOEJ$$IL~cMH=0k zQkwwfJ15yeY%a*{#$a2aNf;hNB(<}Uw)WHccW~?c*g?+A?u!6JYuqOd$vw)r#3)e2Uag9wYC38?qY);k-8` zK00noDICkYcEaZdhM6`HEUnvD=rnRlce6u0S8t@Vma17?vRj&J5z?W!>i9#BTjh3D z%|6S5f&Z$={kx;UBf<50c(U443cpwhDuL5(mUFU-E6fm5YM5yZS^QVBa3{1VC&hcH zz1Su&L%ahQ_$o8FkU6o-X>Pu5_qVglZOmWw+&^VFrha{qiG@^N-VCq~pI53p7lzot z(7U+1;YBw7AmSxINQh0%mzEX`7{WSfD>;f{B z_)}pjX>d7%--=|da0($)7NwviV0eDgdrXieI^Mm7?$|tPGzv2U$H00qw;5_{oiMn? zyiga=W4x?o-V?LdL;V~C#{k#XcNf^9z8U*Hw_f0C-@}>#Wlr6vI^5xzuF}8Eh%sR= zENUf01QV<#Llfmrv^)Bpcv~;y1HnDJyuSMNzG>GHLPU>@@YDW{)g#ES9|B-( z&b;QhI`mxqKMQAKh|Pw06Cr0nf4(dB-%rM7vq&2c%WF+X{g{g7dd>qS&;#9Pz^i5` z*X!SIa&9RIKQiddD6p{P9~&nZz%pws!QO%d3&HQkUliTXxLe5S)x#)`-WnY24GhQ9 zge+fFmCoA>bdg`I3iN5oi_=vtkI>miIQ51s*TH&L;HgW{H@T~SqU_8t3*R+D%hyUV zj}6f#xlh`K*{E*H9~*m2L~6|It;}=>IK=S zZ0UGCo;S6~t=IaJ9Ih#b0DQzgbT-JK*gpTD^myJ|rR`~r88W6FODHWPTGG{1#x^pQ zJD~_*#@wV`C$ycI(i|YjKeY|%6nTYLf9x|r7iQfDNxY3nt*~`f|GZa6v4w*1(vyra znB99WdniW}3JSO1Tj~cu!aATxq9a>I6nDGU{WPL0Lb7rN2WB7hiwkqNI3Wy|;z^+gCD`pM5^OyAR}|s)sRR4uK#~R;oR&-F zhgc$9?-SShh9aq&ZX^7xuQS6IWRz=OA$Gh38ts{6iFI07$=s^e--a_`*L6O4 zUMmv?ggpwLb<-=@h-1G8hY6<@G##MFjtiHY`DEX^(DaQ?XdrCJ;W`k;x6xHn8_=$! z`yr&NhiG~yLdZFaGpeL-M(ZK?p#!m&zeA|8-3vj)0%Z^F#-+x%-G;~ur#(e+;2?iu zkX%vX5MefVBjOAqq8nhSIP_RYLzz1gssCA>t-D|PSowKv4C9LJAX9#7c60rhvNJMC zMo!6;wEy_vuDW7cZSRd*|8UZ7NwQd3_V_Yz_A^)O#MuYv(58nzNkeUQDg3dE*5lH8S`P=97kI6KV5% z5*%h_;;%LHRw~=fTk)q;&a2f zrJGVT236Ikk}Y!s%gQq!$J7002W{T;pjMa2VOe(T&^vHkweZuN>99w1p|#$;$^uX} zwuH@!omU8QStta{zRnfYbUs0%#wyulOkUfstrNiD~f{mT)vV-m${YX8A2+_mJx0m_a;$zAuMq@=pP8+@li$S!V zgij;5_Y$cW7v@jrI>8ZwO(T5w5j7Y2G#20T85^J;->8tEyx5P;B1A){Qlum3a6UGV z)obF4wf=C?E7$ZAX%U8l;}8`32!jrEJ*296IpscSP^Mi~vPqk74DwM+YP6W7lwfrW zaL;RExMV{AwB>+3)$F_31jVtD#CE{_puul5Ajvf_Qgl}fp#7B|UrD(AxKvvZIn-_nUY7yIk z^$6gu%YQF4<$gC7h7c|O14l%Fl{h-56d98r$@Y7(g#7vqFG39tvaGd~>jrOb78}Y_ zLDMQ?ynw((RNko+f1*uBHtA=MFeQ;msWHbAGnw%L=IM7zEQqp`-wEqe0zZ+b9=Ipe zsMh;e`WcZAMI;7ZSi-l$ezK_!X9;^6bnoWoB_v|@;P{FyV0dV1YZoJMaHq*%7)7`2 ziakl%%@9S_Wvd9@RvZ!Q$Sp6o%jBa~oRby8$!&Aw54jj`M_I>>wAtt~c0jW;pJuJE z8sMYrJ1MPnr=f7poxk~6;XrpNgO?>EtVgu#F3FJ#cYZQq>)@Vn4AV3IcpNN`DXw1S zQQB;vAd9tngre%(yp>^(gV9!9pM(AR3GZ?f@v5@){TZQZsZp*6J^)?c@JdfehkHqd?O26SQ zb|W5wa0lCZMB~B0k(_}hs&T2v9q~PRBijAAQBR<6cSeh)+WQ*A`dp#djTSf)mq#$W z<|bjUyAoB#(vc^;uyg^LDW(I^^Uc4v!PGO^{(|15ja@c95vr+?e>qZnTD4R=-H@R ze8QZF#X!vm>`Uz+A5T8b&LL^Ef#E0|6RV3$Pn3BPQy4=zS{V z2D;Yr#RRSR12>kSIVg9Wz&P7+I}MW{hI5_Cb>Ri77*_7neKUwEcxx@)&-W*5r)ZkX zp&b!u2M5GocBo^$%c2?(pNh*asDoH>+HdB=6;y&tp10JZ9C2ZyoZL}r?(*=AV6=gn zk2F9G-x%lY;Na8CMTps3Dt=EMCo2o7Yj>ic+sifET~}_xpXYmspgWLYo>=7a!Yd~dUGXU;j|8ZqM6<$z}r)M zJ&(?Dd)2c$kXo2M9zwA<|5g(Zlpf;51X>F5i+p`erdq}6^uD05UU%L9E)qD_aN$~9 z5)16Cw~SDDw9 z&~^PY;zjq2!8{t~#Tg2U(-5sGO-yAL(yzb#QN^YQKC7g_Z=S+xxV<+(`cZMn&VSf7m`AP0lqY2VYPk!o zu#x#tr}G7K>?!f*$4*57=KPVOv4sW|i0VtItQjf7q3oZpax~Fp@_q4cKF9jb6)>YF z9&11Qm6a!A?Dkhxqu11>^taFk{A{V|QQ2*fFT&;vAnL$q2Ds^lJEWoA$H2`=LM>Mt z5sRmo2y2$BX=EOEl(a0wp!8?BQ?Yo3&w<8FFl5x*j5^{oZ)UV&P(M0`OJB<81C0w0 zhW00QEQ+zm6WctXs$P)Lu7cuweTqXG+7EXRm9LxGRyERTc&RZXMbjPo+LVj!GCLtE zr^3y{v7PS}F(G2pHs%u8H$`oelCY5bw;P&6(X;zeNQRg1C66#~tpgW&C-!0K3+t0* zme*t1k)?2OH0uQsVD=M>W_L&*x=Wp_0wK?`1HhqV;P>|F^pzyK)wX@cet^MWN_`&u zKoJN-*i!2FsDDXC)a#sG41s$${KQufaa*p^EHon>ks27j@7}_`TYR}UE_&j>9Wr@0 z8be*@^AZ)|R%Rm;`!Z}Hvv7S44(CeYVf&#*xmEiEPhT!W6O!E4jy|$+dzNXemYd>h z{Tg*#tQ7d{HGx-%1#aIne)VE7E?3F2 zqVGN=qPB(2Ew#>$N#?`C&>>w(!>c#sMYc>ILQ`WBYu29HYOP}u%G2$s$98|)qo6~$ zbtyh228|H6zV&?bJ~d(E@oBVX$1t<#@J=Fka^1g_9_-5-yL=CWYXL;+8fYTeS+B?V z*H$CUJi(CC7i?_ai;T>$qP!ICCx>mVjFU23Y1x_x8L@>S7Vyl^rloV>z!&ZAT4_KW zCjo9VeBa9!$+E$whqK=(MT@~wqj!kUVs=>4|!L=MZp;jc+-d z7CE0&Xy*+a^)G1p6^IpBsba5`BHCLLS1!UitCqqN?Wsfn4F+Ujk~oSdIp`k~)E52r zLban-_xT_mr%r;ZF@3tS$Ng9brj^CeIfXAOat|FN6F4V^#Sy^{Vn;)D(i;(Vi*zAz zwIS-CcIH)F;T@)^o>Vn-Zs?Y0==DmulFg0%sNvlWdd}Z-s#?4wp?Gz%e|Z)qLkfmn zDw1+U9l*n40`&T)B?hv4TPjwDM)Ky&P#m9CuD33Wf#vzyHM}cfh~J~XH9{MH<;F{m zsl?G*@$#e}q{1ah+3f(f)?MB_EQApTiHKyE+&>5sI^rJM)AWc~*lBTrRpsV8z9Pkm zx+-2U?)0p^P5mM=tGKFPYF}m; zl_lu$F_G4aNf|d*yqywF2xo)Q4@xtXD+*&oxAdm}3TM6l8gp{us2$VjwKObc=T$P? zIbB*{|Bk=3EYje6aydmNwE9Br`LVWW?Bl?>^@lG#TI)|u8uqoDB}#)pS=_clA8K;F zXDLRClJb6&z;e~|Ah0R%Nr#h($QbfH1P;AtV+Xog_lmAb`5|L;1hSDq7-zvRE5g>} z;!Apx>fetGLrzbGgQ9TRxuvus>y8H>$e2a?%>(&%7~Va1+-5?x`nNCsv>7x>?3)rA z49a+)x4P%qM6_rUrBjYL^b!hk{%*Gol4 z>GHGXCgLQg+-ep7v%(UR+o zylEfv5?8?daIhcqfd$-TiCUwJy*Mi;nuIb;;i_TyG+-n1AAOY6`yTC*&zDveI|H8k zUSsF2#q8muJ$u%~ETgWdZ7_pgxvgkk*kZC0AT;;q&N$(1II#i&UnU^O4w~*3RCQ2V zDH+E@Kk#YbB+D*_-j5xv$^;4dW#|j7A9ZBxSx8Tie_b<>Y*8efFzUZQ0p9$npvS1?$}sG1rBm^1Gp#AhaKT@R&Mb)_hi zzEW0@xv4PAY(qfTN_jV`4f1wCdwcowPNPPD>UB?^v6Cbh6&l ze=gZw`9 z&HeR3l*=bKY&xN0AsvcqlLs6J$IA4R4T!jQd;*BYuxYvsKgYVSGsPj)D)gdTa(KJn zF|0JZy6(zAl=R4ENjcWn)1q@_wH53t9}B2ELth!Az7ouhwb#jIO{sMw@J{VMw)eU0 z*WMlLyUuE%A$ZE7Nt4P8@>%n@@Gdr8TzW}I`veIym+oUxx9^}67)%`u(h_+0c!T;6 zu^o#sMI88%4ICH%T}F}Ke8Y-10H34M!qz@<0te4bOyKfArWK`IL84z!LgvzLS)sE| zZsGLnlV2V&QsgMZ>jm4xVfq?v_mN|WBW)AuM<>~Uz+NpE3D}>IT55f23Tg2r?pb8M zY8M^$$Ets(7hVY)c-zS%MD)K*e%afe~URM{^#tSKuM75kl~}3+%yRno%n|f7ya>44J!xGmOn0 zHX+AL;X?i64TD&mblMmxD(oDDbS zuRX}2fSSp+j(mmjnB^)S5;bZH(js3RGOwMo&p`;QKbE+E3Y{Y*X|78RO-b&U^Oq+x z$6PSd(k?*oO1st{@`{uD&r%l~=@X-X_{aouzYRQHD*UY64_=FQwC2y7zb$S2Y6yxtGQ)$<%P_`UpmX{<_GV z6QG@*U+AFsA5bD=nZH1SZUtLP3G4k(1{brKxVfx9Y5?bt02HCMpueQAKrJP!@y%+# z{N$TcS3G`x2mu^NsI=f`=BdQy9%=$Dr|+8lI2CLjsaTInkg$;ktp z^@dvT7CEVMhLLQjoE|qdWPI@l_Nvm}i*#OV5mq8_w{p4Jn0+p_{WE~O$BtdQ;%$?8 z6w)T}{3O`Po5=Tx-_`f*KUQU&yHhOc3G4A`iOQ%ua^;zl1-(uwz=88*VqXqQ= zhh2Sw{orx51;@dv_W0W04-L$nr-Y4WPWuIf6NT^NTIfzP#^EWTz_D+=Eey#{Cig;X z@>@tgdHc*WNCNOb0{913bbLaLd!)W@9_y$36O%&{Se?5kD z0|+-Mpuq^xHpHZs=O0{|I7@oXJ~Gj?b!p@qM6@}`5|sFqDb(dGxZzz}aA#q?@)CE0 z%!}@JwiM8s2fTE?1K>@kJ7Igu-ncHuUali6#5wBI2}FOm6tLWwT*=qTCV&4c6v#{} z-=Q6|Gj zG!u-cUb@4_acmh{p=lc=T5FqH9!lW{Ot;v-L#2;b!Tg+uMK^cZ)(HzPB&|B=?PTWd z_I$@A+^j> z?%?SS{W6!yfHbNUQJBrnSD>79V%eutXWZo+eb|1o4AmQ{=G3hpMHmZaFQ6b|f+&dD zVA5nqg zpkx>3idZgos~vWn?VdrP5YBSa>ilCH#0k`bGOY9l6d{%({@hPEA@GXgv&JDWN`AW$ zB0%?4V|wq9VA3PYObi{(FTner3Ydu1eb&tv;Sn0#y8{MA^DqtDR#}CE*+p1lmAcNh zBqRM)hfCs zy!r&gKCuGcd+>%`3btNd_&Fl~=yylmN5nQ<+De}hYtDQWuYL1B8!nLR|8pg&i;lb9 z0zumeq{Fj72g0-jdsE0sliDd^T%(*;-)S=^IW7DgRV%$XLm;4gU4y#+%7nsRgI1Qc z6gBp3r`F&gpNBeJUG!>n-osLp=8Fwaj4uI=55X2fkK44OPo=~&@1m}bZ@Wn8C+0!# zAjO*1gEL&6M`Oa6o~53S7DhEQPyTj>)DM@8H+uLOrb60`^N4ujeQ%fvx*Y+#V#B|> zr?tEg`Y%E$6)FNN8S`)=e?RD-s*ansb;NgMaHe8qn~*CDj>aMu^4|?J+5S`_XU#a9 zA9Q~cROb%4a`Y+f)ds|Bj^tc0r^s~?e2~g-a85$3kdL4hYQdVDEn2B@vWYRZSiMA( z04v$H8&w49*GoSZUfKfkwX--C<&Ou%MEhORIB@_kn;=xM1~<4hq+ucg!kId{IKd}O z_R^CQNH1vcdz-kzcqJDk!1DFR*n{wc0?Vu@EDAg~9~wB{`@nPy*CH0P8g2IYWT>7Y zhtAO7pFkYLUf@{|0m5m;^4l~fkl1&Ip2hQOk_uFwSvNc+XYgl6LcJX9)^w|GzZ{n4~>v*Dxr~ z_+=J*Ohww@V}Hfb)jOlUhxmHVCZwy+A{q-7+ZS_CaAHth%}FysEa_Q1E|1blRR<|V z7+jP0QC7Bk=iu^Q6bYJd)^dv=8PB{ECG0%E76upGhh=i9HIQFC0D>kSBfXLt)e}fHav&CcB&QU1Vz{EHV&DEVU$2FH#Xy20ky2uE8aPn zg21Ikmtjpi%@a7jUoxQUHYZLXM=<*)7J|>?Y_3Gx1$iL{&z`caeEf`DQ)|+FUZ72OCvFq(9!@xoK{5nr~K2 zF6CE`2h@Ix=t8(}-LbMZ>#GFomL7r{Fc%QID9Y0X%ZzaRh{A)X_Kj8r#o(%^N~}kF4O*J<;bHXcf*v-QYha-^l4;zN29GwfXMv@T z?uCe!^NiHP)tiPm#eGL-gZXUha7a#BUzd@`lF((;5PJQ_q3k`-=H?N-c&lqQe3tKO zv*3v&tepx?)TQL$^Y<#bD*$5nK5o_{?ye5%foglOup*(P>4`v~dkS|#f=)jj#0^`AgQ!j8^|k+`sA@eaMrJ|>OU26V3}9q znZ$2&ke{>4_as=-Hpi{Ay$+T$AJJp1OeZRP%SA>%$vn%Ck~N@hd&nqqwqfMW)>btl z&bkS|OHc{zh@%aN8$5Ko(2Byh(Q*x}upx|qTxVp-t%r?}ot%~x85sPQ6ptp200wO=Rn?~c{azIsKLe7a>uF>hLAk=2tM3i*DWy0Y61Hi!vHS`bVPedOqeC-KKY@dFi!?`IkZ^8z@3}?ad^(jzB;sh@0NI`^7_a^ z=apcSMKeMm81~pDw|XehbB81yU(*a`3L+zAPwD~- zU^ozpsR1fxAFrvn1Q~y(@g`lzMo8Z5!^>zisT)d7vXxOeti<{6W-kJndka;9)}`J1 zl==)7$?#8i4jbc`_AATQA~927|803KHUh15={v*QmxQ8?g*FJ76&bTIEGa7V?}V!m zj@xxPo)zMbp3UjVL4BMG6{2IVe0c~8VC#g7pkWh3K@(?a;* zRfe@Kc^%Hp4+~NyhZq|nW*0@DMxc!O_U^mH%qlw&W8GWN>&|plw zF3K8V_b_?1Njd&6VJR8M;m05aVeFXi=sZjyH}z|Ud#In8@hhM)*D}iLpTl*~XxueA zl1o%I2`5A!Q^BNC?))3sr(h;ag9j%?5p=f*k!`h%jOqyfhD@4jG1M3 z9O~+W++>Y#GpK_d8h5#StC1BZpJD(j_=UI z*}ZCLWm}K=7pJhFhYsc%G5N2UP*(w^jpNr2E0#eN$*r&)wEah26GvWFUJf#17Pt=r z-eB5YekwRzg8%AgI8Fio?vGz+wwrJxO&vdc#TK{cS&qdK<_-ma543Uqd*ezPwml)E zHMN=l#i^q9G;k)$4sP-(pm#Z_B>I{eAt|Y`0oi%8)#sBhB^EHA#WmEs)ApTeGN^x? zSAkiIJ;+1m2kcvQrf{7E;`4-4Wwsa^)(7%=U3svL zLVy8eNcPq~Y%Vh(8DO(vc>Q*)C69ZK( z#bkb-iSP%^6Z^_kX9!^-`fMIhYW(!`X>>{H#52S-;;i2|5!F7riV zxgU767MPJGp-^Zqt{-Cx)AzcURc=3isQYizr&9MANx>c+99}YwToAFweecU?b#>%N z0*14@=TG&G{nQte-ZQI?N=kuGaX<FnNITY5MP+@@=*lxFe+2qExc`uG5{Be88hKzrsX+bXCt1$2$c(7oNOt$$3A{Xb zyD>dayN%~bf%Wg9G@v0cvYA%KybXISF!B*RRKRWWpnTNR7j!1Kc<68u|LJI`yuZ`t zv@wK@bw!(G^=;j>?Jh%iWCl3FVL8miWs(W!YfH6UP7Em=K;0v!b8LoOxJul_JoODS z`d$UMHkQd>YO+L@Btn@>gZ{p>kJ=Q`R_}>`W_66K+HBivD#*z85+*j7aeh!ewOP@boUJXxP01ygU%B)ZD1vBa0(rutA)mWf{Lg&PUQg=M(Imc$v#FW%ADRYJQ+JDHy`f zUfa1|b4WkXRQkKsU&+116<~oeUzL6oZVoH;$ODqe(u{7>!}w6f*bU5i4S-)f8;Q}+ zMv=i~KD0rJ=<_{TUc9Ybn*0})E#0J!xyRaZPZKMp0%3=zwN=R|v-y%*hZFkVh3vNQ zv~n}t^FjZ5NJD6_uo1z$Tlo-Qt>Vl>nRnWYPdjJr8p>VGK?Ur~)(svA#_-)GDU;=X znAt;UiJr5!yO_-#xOPDJp~I-8;NjO_?Bk=rFfY^y|LQu!ZJ+38#gabKwZ7Rq0e832 z+X)hQm2m;;8*voZ2RaIA9B;>Srkzcv1&8A?f6DJ6<%bg<^jo&>L#d=sVq9tcy2@n9 zPJrN9oxL!}hV==~AXimaNh-sL?R0WtLbi)=9TKS7t!T);b2FJx?fIi5aHjiN;Y-X} zq*?*SgefB|$u;(lzcpXZg@G@Z4rVUFgJ|dhj~AKd7TlKAiik5 z`wX=HiGd!ccLHX4RHJ3o;!M!@1_FaswaQQrw{TEm%p})d#k~zjYJx1@oK3aVJPE5d zNdxk$I6%6C$e@b8r1(I*;zHhtEWBgA(lcs8ifUh{M32{_by$2Uwhx`)xRo*6o-4j3 zuGen0P{K{9a-29QFsOyFuw;}$E=HX}A;OMvgkbtxtY=oVU2S^++Ca?xV>N2a9AA)G zHjCGv_VS+SouW2>qidBzx&>{o?O(|9NU`>Lye)8XaWNu-;LiE=H_z<%*Y9cf?KjB7oPPJ%D%$01`Ub#CR|uz<&(lrQJ{ocng21HS9m|bBI7&;zaqm!PyfM z?ELWQMaWP-GrMsBco6geB&4K-cbmBRXHd`ng8dNwa2UrRE~0r5fJ1;{5)d$v51--? zxn6P<$yv?y^>J}=2y4sA5a;_8W7Gh50R`Crp$hWlVeCtIcU30-bZe*|Wh{h3a{dj- zQ;+l^hzo$nz%Twla{xGC0Yp6Wbb1h8<=_B5T>TQt*!ibmqF<)f-)R8=d-6^I1cY;a zgWvZ*s1TuV*D#?1@wK)F!T2!y5cd891pvIPHiXIaQUCyAYrjk&L%a#*e)a4aVBnht zu)bw*VC9rp0R3lBze}f(_x>FPJRv-WclxYQzfeK8O;m$=nCBNzqWL_Ke#d1%kN!e) zKCj3>%sS{G3*d-%ZASpYYusN{LpzhQYaoD5uYs18Uk!r7!M~$81r+`m3Q{^cFd+V& z!1=uhkT0P?3V3>R`ToBuU&=%v z0RS%y5Kso-F2RHlzqq)t!ni+)^N+9o??5yG<{tq7{rYu&yqX1=f8s>?zkh6gyoLuq z&^pPaM!)=|e$tdAA^0CV}F2ch50Xmm+3I}`wB`yzf2D8PdAcLjdUI)7c?e;dBklYdjresdBs z(Q$sXXCKoBev81n2KRjZXy&G#g$mjPz$11*hyAiL1%I`4am#t9CZGFSGAS55u~86X z&BdStZ=e8ge?o?MmJNCpynHaA4xZ4heg2|ZWLC1DT%gzQRqmtNU300)I2NT9BP z1XeLX>;*g#ez2;8Q3Nz@(Vw)D5P>0rwzqiVdllU1pCo=p1qBfO>vO;{fI@_E6@CGu zegb~6UUoSU2(F-n-93J|>9Fnsiwtbfs((YaK_R>b=eEJUzD9o((S|37fO`)6-ot9& z?cQHQfI>cm2!o@XB*JBaA1}jSqOe58@CRZPyN^?5)=Z*$F&I%+za9a|ZN99ZDcwl5 zKdCws%08e?6_cC-qP;)SjeFsDPeSQT&5w#0R6bXd;Xt87d-J+of*aR}F>%I7b4P0v z@QX1Rk~XvsG#tw^rgcT7oTF@eKOP=B7o8phmgxFX6}-hpQwPGO6s9h>Mm((tMjHaL zTHPg5CH4(7&P}T=n0#ZNF;d-Ym+<6&x9z5x7_HtG%LcZ7ddmvOLbQ074^$PCpHzNc z*B```z|Sg_9dFq^jO-~RawyYE$eR|?JH#Al4L7A|zSHTh?4&Ufo-OT{RN;DRUe9!k z)Nz%p<=E=H&eO;L@Q%H8F)->nSym?rOe@2Y&RBXyH|`!#+mPLz`JT?Xf8;=zc+fey@h(k!RtdiLUyFBiB|`ZJCVLSoNjcX@kq1jt0fbSE zvS@_7Ws!g~x)&14n7|PR?;p)cw8N#Xdde%eTaDkhbH;YxC~aTgRfnA;n_AH(-F*Z4 z{pEC3OwT-mxAU2g%L|!)9tQtLNziTijB{nLncBis9dy>ZGorbnOUo8vO+wcqneL@# zSyks<>P6FRLbT}6T~-QRl7J@wng5WRSBAZ|cWd#Q2X7^epr4_ecGk>*ZBos{LBBO^ zA(1uC`PuVqOocR4?JDrVsFsa2Jp=I^DNHqUQ_*3?8^(tvSL>|@LP7UAJ0T1=cyLV@ z4SnQ}UOc|Ix@lMe%^5n*An=xEy!upK83;|$ub$8?S{eUiK#Hh!>?y1qVV&7_s4w65 z(;)de9sgAZYq=pqR&}|pc;cT1G@IjyvfG6;alT15>jVt6+Uvs%0Tg9ho-)|5$SqIe z<3NRZuP;}i#5#o{-BqP#da<^XMJM}3qGpR*3dJtE!u!3qo%zbD+S_#lSv8fkrL~?A z=Lm%OZAFTj1HVq)%U)`>D2H{k?}<%SMvt<8gjLRgxR4}6y#{dvI~RSF=-RF@N3zD* z&yLDU|5Vd3aoOmN)`TDafKpQw2dD%6Jsn{{Tj!U^}B!YAu zr=`+{eg*0G?3=}6t2y^z98jW}rCcXq$SzIHLltwdlgQ_G@cnNvVPKE)AJ7lZi}f5C zDd!{kOV?xdg{`*}B9d;&6AM%Rvml0b z?I(BQiwNofq(%Kw4oMH~15MYpQH})U&=~|5HZn{q<7O%c)6jK=h zO49s;pnT`Vs`&Ktz77MK;|IhE1omUC-m{^v&tHue)`nIegpIUQp1DO4)V_yDYmqug zxw*|dN9%*Ai1%t79xlt7>{-+9MeHCl-hnMj9eo^%Z9>Q!hQoRUNzEy~$EGocDAMH= zuGyruB+@_s=(6{OlkPG3RMZu&-8sCD58crVQW$nB3>*{$e;WNH2>rN%ei@b7qCp-z zVSwLheAUTQtU>BWS9Xn=?YaA&*)s0CM})t+ zziVU^w}YZqLJfT}8Nyc`w>Bt1c zqNT$05;rFODp|`$3yvV$AmXlg-R4=X>fM{lTJ7zmDa+}MH%o4W;eQ(U@n%2Q9jp>S z<(LRk50;)^$CDV$?1w!-4wDk^?LxZ+kQ;;ok5``=-p! zeF`@KB(ptw!gDGY`?%?KTt;P@qO`(?dl&rwh|^wBuiANC-q$^8n6^S=s)~zTTl8fn8EAU^>rhe&;eJN zS`=MP(!+KUxTXJUsCAh4lj=GZ6fuylh9Z;x)fHU0r50G`Z5!nX1s6-3CXWQBo=*W` zbP1w0e3YkjyXz+fXEtqR8HVQkCgTYUGop+`| z$0E>!3|t_=@ER1E6~q9K_t-Zx_YsY&;Hi!ZBwG13QEu#`udkAr`59fG<=`f4E*n^K z*_&KM^?Xfqi=7yHq9msThqlvdVl4S`*kp?~PEHF9@luS_QvP5nvX_pZ^7fMdr)Kbu znz7=e6XaCMzBJEJ_~bxqh1f#w#pvB_23Vfx;UhkqpY*FX!^7YiM1|(EUqBPZmtBwH zZoQJxaHZbo2kHwBqLbXeBNg0xR~otHZiwUeh>-mO(V$G5bod%p>pH&u%Z51g3bY={ z7;}lkPF(&;>}=O;-VEhIld)8GY`phIIY65RZz3y+M8<-S{%Bq8)s`x;$?`IPzBj!b zLd}SZ!y{%rBKfQu-m}KmQ8RUtB8VJKnQpj!J*}xvG|9l%Yetoto)_=oj>NXObVj{X zL@yIE3hIS1V)jB%^CgrP8R_OQlNU%01&M(u;J4xUtUg6uebXQ-*|o>S9AqQ+8*b70 zS*MLQrO$-o8db>h?cb9_A8cQGJN%+qy6rKJQ|l=1LPoPZU85CKSNNoTtyKCN5Vq6& zjUfc&@JafP(i)_~q0f4#?sRUKljR6}y}saGB)u^Or%?pC#H&=Hv!`N)>3afj!DjG8 zyA$ymSrN<2s^!gHaH6%XfiHvI@r{n3-K}imJL?7A;K%0MWxLY;4e24T_5gm}V4C>Z z1wOX9LRG(DHF+RxG3zzU#}?(>gsVuKA)*g-6uo>msO>m|)>`VO0F@)a_X*29W~sof_L*hmc6Ljt7Md(dj0Q z;)S4?%g`byS))OLjbV$D*l0m2qJbgU1cO@%E1YzA&N#T#(Xha-Xd(UsPAA{#g=@DT zKbB^lf^t_TqNlM_dl3gJjaH+jK+kr`u#x9S_@RPSOMMF2x@PKKLkds6(WRz8ylo3? zMf#aX!bb0*v-*sb-snSN=VUA^yraS>_%Q~fDqqC|V?wUEH=DQfzM95t*yU(4cF)XRJ2MQWGzS$?T za3(j3r*j93Zr+KHC!yI4+gTE%#wF?VKluve@fgmyMGb5kd?3qv=#xN3r7T@Z(FzISwDmWNI!Cb0`U zF=960c`m)9pL>9m%y~Ao$E@g{9`PQb`KqX>89ct4)vmL~L-@S1Ry0&l{6s&KMafkH zmGCqMl6=Jgn#@e5R%+86oCnf8r3Z`)DARG^+kBpF^haG&Js+bEKmtOYzpGBE(Xggm z^P5AL*%EeSZJ<8E*Q@Aq;4I~W|EZf6IB-D%bR{P zg%LP&O(LIGzhXwNdRE`BXiPeB;J4E+i(KxDfWC*A7aV^dR};Ul3E7}DcH?U#yAgP1 zr1D%s>+is(|A<_ylViZo&80trXS4`2x(-D@D|3*{S18sn)4TX#(u#H4&66Rk|I6ZW z-)OfwuH(xhHGB4QgTdMTQTkOb*L&&fo@HN&)zu!M0IOh&41byYTa-HB3=*H~n?*02V`H)btLcKd-_uMCy`n9C5aCdY2<4Zk z;o>f}z?A%2giPr*_c4bagui2m&1+LoH5r=3&LmJn5}p|U0)#(k>Ry6gAj$H0mZ)fj z0^elYbUxA{dX(~V({o+7RZ^+~A3Q&``Q8C~f(X~|8mnbL!&-fK`X z+rrL!&?!#@g=RC3;tH-BzN}ER~ZwpFarO0)`4HuqZs!z9xK;E)Lx78%`zWK-I zx44Oi&11xp=nKrwQygu5;T;XrjBn!y!8V0_Thm&jiq~_VWcfJp`KVXUvt)@{T-BP> z4p%AV2yYbrrS{UUJWq;ZBb&qmwKVeg&PbWFb~D`;^nB>_d~@}>e4|s6T~QeLw*|NG z-^}s*KkIBX5(<$U0_|<)!eww+iR68Et_J32m8F15Ay-w4T&=1)4cmsRHJ8_|IZ#=+ z30_I)MVQ}T947jTGTXQWMZi7H13BX;?sO4=7_D@ zSy!AZjH*R=V3FI=_g&_;;pvj&oF*VCtbl*X=sdCIMHS~`P}yrhXO0y|cmu9TpY`Ql zlTINX!9!^(%32Py9~zKoDatS1(c_Jf=$0n=7jNvr4y}s$h7ro2aG`mgt6!eBsTcls zm6eM2w&L~pb9bJqICdQeyn*PFgjV%06elI*uLDPtAYC>n>Q;GlaNO@3S=^6|1EH&pg>u+@;xuSFobUdD{y#@_Ik__x4Se)BNdUN!QE;SxLw zanfDndNoZDcNJJUv_19WUvDVEASbt%`~hR3PqU0%q%t$tr8b8CT;g#m8LWHbux1&$ zpV$MREN*A8YcGVjKFTUY2|Yc-Rn_A?yo zdsm~Mumse*{>;$cI(3)b`f6d)Op8Q|!sGkiG!MhU69>ho4l`P;POzQK*%R-&Cuq6d zq**DBEZj+H15@KU!z!GKXiGcW~XOGTGqZ9X!$}7LR$v!sFI(hqyDVuTJ6A(5! zg?#R%xvxIg=Q%jmjZK;%Uy{C}M9l6VxoWDuxhr?c&E6`_pLH}pZf{9^+=0ln<$L3- zla@Zrrxz#J*v%P|(mZ`BdB${_NExM}7p9vDHWk+Upb*1CVK=;aW7`Fc5@ zKKFgDjdXh;M-~H_lkBCgu=>pSndu|wqABdp@x6EDayX!~6b*7c#gaQoQdjb7nCdHe z%T6G93UixcZv_n>1dj?a5COJ4jD($>< zV`eL-IvaNmiF;P=boXzBKg;MbcF98}06K3J>|c1?fxpWYvqlWgs>!Kvr>EI}sWQZ!hlIS|Xk<4?`tk|4GVrd~I_yySmwmC)(^>b%L!k z5Inu-_U(WP!oHR?)ZJulUH!v#;9(4zKeD+^nn*;70m}n0t}}?2a*v=YY6X6XhJ72e zDr6D4aWb`4UgAj3_)q=s%P$@ah1wUDxP<*}IUIwqj~pC2n)s-=ba&mqxg0>M@9ZMpxMAwv1OtC$D92g+s!no7tS(|SRxe|8I z`5ChozG&WaU;arzJMfVvvns&_=xO6M8%a2%44zg^kd(XSd9;Z`sbqQ=S%;YL=((|aShYfV=Bz?+O zP%sm*xgf|x9=`RK6=_Rdq0c^XsmU-B4EY&;)^D~vt-Nj!HEzby>>-;2q8r9tyg+zc zo58n8(Hf;kTVT_;#}zoUT5BCD2e7Sk2WyeTklmS=Q(QKzG8ibU?SOQ>6?u$syyDTS zD%mO8RF4B463)C|&f}j#jxDCD%#2`LA;hM)U!66Gv&>y%;qr4s83xmY(lg zmSVGfdcM61p;{`v@>+77*jj1QA~d6 z_cOUTc9{klDVm1E$+y=k#htI=hl?+IOLn$e(IU6@Kd2sX4rdPzy7r(9-F!yvkZPog z?^rstXNN&1?f?x$X}q%f>0FAp-z%Q8*a^;tq-sk&4NtO^({6UVo+(&=G#;3w7Ysrt5cp z@i4OQj2z6)^NH_M9G;ubR<&|^N67p!m*33}WxPn^Ow8?XdFFDcEeS1%I1Q(9vekOZ z`(4{g`#llyomrv^Fw&v5kl)TK1eve%%9HZ1xW-(yN21rOQ2XR=ry>)`4!7eEjJ^Oz zWN8}DgL?JzK-~D$DLKXaIV&!X2~bxDMV*bP0-Ab$KiX{8;$0bTeQnnjO$Wf`e*i<&7+roo)UfwVjRSpCm74VeM?{_;0l~bT$<+HMTSPXDCO&$oZcm zM<-_jMrQW^F3BrfS#2_)eD~@*@RMQJkX~9)gpleQYU67rF-}knNj9&{t&F6Oz1+H) zu2&p&!b2q7F87>fdyz0gf}{f#1X$!-fYAgcBkZMZ6A(U3quEdT|bXa-3DLIqL>Q?Y~!1Xfk*<>v4|DoPUE14?9m zT;2ig#0F#0>`y(?l8Gdea$tJuN<0v z1$y29!0YcZu(yM-TVb)rIcepjVF_+73V+E7MaE39hXs z(BaL}S5puy*l4}-vKu5w^i}42-xL2u(fU$43SB+Au3q+7v~Dq3t52*B?D!ydarWo^ zlZ5bH%i8KKg1%+@`Q)wY^3tMhU$*(Jz+KR%4=JKkM zoQVUJ>LiO?fi2|$3RM~~&5`N_YKd*GcBMqMU@2C&;(T2xc5IbE;Ts3{{3RW8s-V@Pe^pg5hczMs81 z8A%2RO_fu1yC|WD4g77NE}f149AuY=JPtym2QLhY?kC$zijaE8AkuatO@QpTDB$sn zoni5-nI8tb2_4RQ8CrgU7|NjVK?U*W1=kcowA4fKOKF&i%ng!#VeB^}4M2gP3 z0B$n0K;*-%1f&{C4Jy$SfmN63hG2*+VJHw`eK`?nB@nq@1uLNm<9&{ZOev#%#v%5t zv6WJUkqK7kXG_FWYtbTsNUzxujU$Z`V*MbWSsDjP=$S`d8;51KW)#i=X30bL6{mEf zaV_sf(q?2ft63SEYb=Xl*fcb32(bom$zfEL1LtVw!qjkvOfMI+%eN)^1FZE{&Jzw% zD9Ghk8W3q~V=*dF+vsW<3PRw5!wPRgT{PwvgF#}mPze9Bfn~yEk-@CjE$5L z+?YyIT%(-|vp_Y8iostOOs-gZyy*!quxAd_08 zNcOnhB*~qpN1HJb#HZSmSGhrSky8Z&)JWjz%AC%weqhR+JHsEj8uV_!VktH>;vN>X zK09D*$6X>dv4SyQ=J@;aBm9Uj+E3iX`Y;%9p@O{LbLz*lc7K{=7-iuz7$-9J<+#SSj4JZ;8+H8EnL*#mMtC&u?7KWA826X5(0K~| zXs!KC@2{Cqt`N{h1-vRi_Bu!uFqUdP>V9oigK0jRjj_kPZ#Jt?FNWL?!bA3F99fdZ zr>xr_7}sLT+l&doMS!amV)gJfOoPw-99((v#rJh<`*j7VKgWFUb9}s3;Iv{oWjE)= zrjT;}l@_cJ2C|0B?8*I|y(PuV&j~PBm2uwndRY|n$GyZHde69|6I(IvF4I zLsc(-1}Lecb`F0Y-mc%@p-*b1Z{~jJ+brb3*rx;JQrK-d#kg*1bCUeLTGvJ>oarX?LDh_1^7AxzxQh z@pE$fy10V9(C67m*S$8#>reIW%>Fz*jmwks`+q0po?r5A8RvO%MR&-3X8e9!OlO_` z5)6&emhBFCf%01IaKPb=a^IYOpW(~L=9=}4%~ou$=vTV>NO$-7{=7Vaif&cVXLR`_ zZuTBM2Xwa;`p9pDa;yFU=UyGZ*}lV~>{ch=PCZ1?e{srI6EMp*O02LXfxK2pvDfJ* zEQZ?0E@@{4R9-;E zZR-t@>Qf|Z123;-mlsuEuCHV+aO8U-!_P}OrJ<d2r^_ zopF_E{=IT$$JR`%+!$hOsk0Y2(rOZ0S)o#ea#>_=nD4nF%8LPCoo2kgny!lSOT-X) zUdM3NRO~#CexjU2ee_RH5wkv!(F5IV)8QAI;%&Z_f!)mqS8!3K_7p3A(>Y5yD4N}- z`mq&$;Um06ETn`&cX$arX4xX-^29ixit2vJ;|}D&;e@GV&)F+yh-~5z8cLG6rovs) zbq%Hca{jR94fux%_HkQmZ5sKN^x(C&OGRHkc8*@d*2|GED+=khy}l~y#*n2y!ho#J zm^>LW;K62v)`Zf8HNz)Ihvy?M*hpXqr2_3&Kk_yfuI?@<)2)0U{6+^mxNR%F6i%A- z5hAC+Nx0fj-2WG3zMXYb{fIbWo4jxN&VUFUc^P}>ob>oh{OsJSY;($j;5lo)L~mTA zLq5}G{KkAB1UQP2p7GLtS=2#Oh>;E6J($Zgs!u%JDiB(A)Z5e4XMlFVyh3$}454P} z%a*q`rt{40X2gmgxL)_&sb1yKjQT}|{nh^5tn;m{L@KcDX8V+IozMA)uz`@|BOn)i z>ydb8tHYGbEO0wg!{w_eGR3@#Jx1r8t+iV}_^@rtx|jV!-XX2Un5@@)acMqdi6B!E zPq_ex1E8765=DRrK%BtWe3tppqkyNy>e1XPrWoR_kaKvvORGEvu!#AN{`jx%o{#?L zh?J4J-}f9}yN}9|e|kgqGbQr0%n%ES?4}M)^Kl;+PP+$Q9T%k zxr5?M`yRAEXT+AB#vj2-4T&>?`oaMHg+L%Pz1xr35Qth!2?uB`!?gn+XbiLgo3tZR&6V9Bb6}F!)$Ub}4F(@xl0SIbm%k^N<3Rjq-YF-)B67mG|0P8M0o)1lj*FAtC0{>ZmBkK z3LR}-)6Pm){~K>`bFwlPQxh&<5u-#TwH*b~u1+ba)G zWq@BDo|D4%+8FA{-*#k!JBoTv!PI%oHr6}7ZU8T&aAkMbC8OhtEKTZhb3FSOe0Ew9_>uU9WbEGFGIcYgYdd3j)m<&R7S1EhGnL0EStb zH0Ew2o`Wo`<}SW#>aw5?NBv@}YHJO0{R)N3&@h7~+E6QR9DH5S6?yn2KjLkyTEh+GLuZ z&1rl-ha47nBD#0Abr3PF+?|_jFGeW8fAH1qF_!Ugca}1-*J;d7yuy%!4wXpV*xejo zpZt6C^Q2NJa8`DvN=b7)C<DpJr*8}xY*zkB4g1(S17=2zgaJ_dw74}90wJaVSt z&(qRnNlL?u2lL=f_1cB5vbRU$rLhNb@``@Q@g)L#5Yiv((3w#0^5?5#dTa}Oni0s0 z1zm=m@qu%2W%?rYMTE^ng>Brcd!^q0zIy+fa99S*Wr6GR!;MbQc>S1N8?bbHvviD_ zc$TfP9p=3!^&hwx-IFQxp1Z=e>+$>Wh%}Eqi0~!RA6t1)%^uA@q{%H&um5#>*hcu> zDPq^1IgY`Z;6IXxJror$HOF4_;o{lffQi{hK*a^5veN2~#0C?-pkv zE?at2Rq-m?@5{P;eq&jPzKKn{ToU_syj1S7ss~foM%P)zNvpZ5t*e{%aH!%C^|f(8 zKYv=dqUrc#!$0o>`ossdRt12~N8P8G=Y*_Wx#!4*2Y>Y3jX7uK-+)8E4}#E!3n!*N zx4e>~S?Df8{FoeB5B5re7yRWK$v(tuAvIS2`(|Dw?tDcIJDAYP)Uf&)N3@$zP z=lD$h+4d=`*LhQ)XNyedYh#c%QTzb|;|_%4PQ@3Vv>@ktV&r)*}3LQ z8)(hz9erKlx4^%#VC108Uha8l@D!fQziZu1dF89aElaFC*Z|(-Q zG><@P7p9YP(G@t1P`HZ;{@GyFMGc(S9rsho&WDz5-BS6$Ee-2^kM4!KBSY4789vht z5(&GN{SA&APqx6*z2g#`Sy7xo=e<2kI==ZU37(^_(C?-sge~@jE7RJgzTek*c>dMZ zs{D~zWn*tGn#M4&4V1iGZ0?Jw=l%lpPg^Ub~Ss%P13UN_M%@2`r>F+8on53CNjSnmHjyTJHgk_&>iwsy`=1lj}~ z|4FYY5$F=o3)|T`o7(={Wcr^w^s=TV7KTE0?*EJ!{(WqWO#k{?nEqp_VCeYIkbs5l ze;F#7I@!568k;&1Ff#ndQi*{6f92^E49!gclZG(0HL)|Yg!<3D|5{tp?9|Eqh3 ziG%sSch8JyO2=)nA@zQ$Pm%hAxl$uloSrmeuR&iC)i+=ggmHk!4&R`O(Xu|>xj$UC z>6u7xXRd{TzAO+$nIu$?sjFU{-PogVe?Q8S?E3L^zuyZxpo<$~rrd82{m`kqc_fD^ zD(&ztx%Gh;)qK?MJPX@|ed;0|54f`}`rxpX9`nJl=-({TFd%!YBCdVv;zV;mG!Hyf zPc$!YWsa}#FvQ8a#dGo)@6HZ6cV8ugrd;2s;>oz$S6!Sqp;(={rNG|0X{Lg}i%%La zHegkr^2mll8i$DUZ6qE45WDKPe`^Z|$vaaT z8gyo2_wmi=$p1MDPyk^{8RZkVC@z%vAMCwTkSuMxuG_Y4+qP}nw%tA29&OvUZH%^U z+qU-j=A8eEf5u!Z_KtPD>mV~Kvofoqj_#`WxvsmP-As!4-W{*HYUkw-BUH(;i91Qd zSk4S=cnf#mRszP&@v`fv4_`o;V4Su)&mE-|wAP#!c;cS1`>L#fLr`_ea|rm0uwQ~D z1#i|YeA`3*nao7+v5TD`Rnr|v#Z~9d0l(1Z`v|%)f zL!EqmKhUo6Y$2a;Vg4xIdYfo-kMpQ#CxI=%NMRNQoeT(aqO%?8EN(uevO+~a7+kHG zWsT0n-JY3pJ>#~5|1H1k;8VX2MgrekR^`hXo3?qGAaCo50Ak6E&otPy7@=rvgNahm zRG2M``>404I!h$kgN}(6(_iQbrV{9)m_CEhtdD=WQf6ixYNu{NXVSU)*n$G`TSWj_ z5dU7UO}z4loB-2E;?i#PvhN~dj)U`0HBP)szMGH=93Ep~S{&b+Zg4oXU&@^p9)!|o z>f_D1D>Vm_Ij=aD*@o8rlW=G6@Y5h*ER>o*CT{~fL412_0`H*khop#bd=J!Jn;qwJ z+6_P-mDponMD`Ri2m6tkB9RxN8IDZwS%sY<9I=jereSx`C!lQb0%oQcKZc-!v35lj@T*zN@mf|39axBH!2=zE5_Z~COGg28ROf$Yya|?{Y)G!0Z4#>kU z;i&)RcVKY2vPiQxtt?D!v<5^CxFDemurX6RlF3Ssjcx_aAd~c_C7&HmE5t-W+a_0Z zi(Pgwm7@AQbxm;Cn*XFnCncvv$(g%!%plQr%4AaQ84u=|euiNNZR^;+Vb&EY#EdL2 zt|-ed#0>1t27Ym%E~CycR)QNxCYuKgGsX}BWtKxMn@7l1X(!Vs9DEf`uCTNAuulRk zSiC8~@?1$j9=Vd(0CesPhhP*gE;bp~snhOA+)>goCW|XXSz{6R0@4rwy%>$4t+9=% z&}I@vEUM(M*eO%#C4wf6BWvA*H_;WBvmDUuQxX|ypDTp${zP2?n{TW?1nH|1~O*{hG z1W3U5t3C1)Md>Sdseap9gV>6+zBqK#o0tUIO#YR|Bskh-=7OQjo&T8ly6~7gYvP<2 z=uB+-HZMhyfu~F3eR?C7NM%Kq#G{k9*#G%0GQPYwp(KKM$Al(B{Utn8r7UTo6sFw} zJ)yrPAm|SURzzUKmd{-bBdcu9-ASRshK!@XT=csWo-Ndu4`;7tQ`}lZwk-=p#uv|T z0GHB`AflYpVQ6J#%DpzFjQlZ?NsfmTgqlccy?yv$)R=k*=SvpWA>FE%VH@&Ga!b?@XVyjn0yA({dE$?&>4hZscG5E*qj2e5kk3PcR<_TYi(McVK=k zY=Sho8x{)(s@}EOnxs8XH=MM$!KoOl7cL-wu^&+uDdA93P9fi*#&hl1!35lol_7$b z@ZB^uufn+&RYVjp67ZS(PG%4odg|H=AkEHYiEL6c$#V6o*kJr@EsP>NITQh>69*O) zk{p;rUDKUxLf+`ghOCoAd^m2Hea*Wn;auCbCk$+j=xRsU@%!Bq(Sf_S7F*BBIlNZLq0K*wLW`;<;fI20yq_*40KTjiu_iehtZ z6KewLbHXFopFL;8EQ3b^&~!M7NF80qq#IUV#_kt!o|Ifq)@wxyC7K8ALLw;RZTlyv z7osrfGK0N0dmjwN6be5(litAsOpMJ|YyyXBg@N~(29EGfdzC(@jub`eSJ0a~lh8G! ze&;A*Ty&$)SysDfK8E@jGZ z4~i)>R(8KHy;;!7Q+-lnoj1%T=5#J5GNG2Wm7RCPY`wIvK&MjGnQ@Yu^+L|>Tv^O* zDO`WK7B?v)V(ijfmm)aLrNYCKYSkghI$Y2eNeuElLEh`>xl9~ovB=OJeR_!eNalxM z<+9@&q zi;Y7SWeY*6;HH0VO1b*^yz}Vu!FGFj`9-`JGne+7^!gUv4UHQXstIy_IQJ&L7f}ol zDPu#ES zJr*3MmpL@+X444HJ8XM#plOZ)Qyi*0e%*};|&l!-IV@)b7Dce#Y3Dxu>jA~+?F?Jfs!^NO^o+|p*2yJmbG7Z(JdlS&H&JSs`7 zd8~7ew9oUEUZYw>e|)rvGpK*BjvgnPl#UI0M28vHi^=*;H#enu{I}rH#Ks|S2vTe^ ze!cp%D#1_H@Z9sSUt4~r1f_KsM}46e=#ljkGeh`b`%@KX_-yHcJea{rF_?FrR054i z*{YW%78fY4bVT#{kX!RHWC&CTuA9@aJw2=6SEx)D-&KvygPxNUJZ@vGS@BhC; z>}-sG7ZLw6Z8QB1?M$4^|9blG6gwj$GYivyTSkm-0#!-6LSvJWaF?b4mKd3x-`dJw z1OSF%1fHCwB%-9)l9G~ab#a%J2=h-0c6r$Q=sCfedHZSZv7geK*<88qzOmkka?$F@ znqOv+t^ zF-r>J{M9aGbArZeAz-7R(x`b;3`?|#>0DK7YUCK&l zBj%rj3-aA6gl-me3(y`22oEG4j*0>0=inHm6{HIYzXsSbZUrD~&hTh&+}sPx0q_F@ z-Zwb(aO3df@dF1E@O=c+&=APU8I-4oP)6GawhsYjK~?5R$b*OjfUx-9N;r!6_lGBV zdk{ek!320vuM{{SN>MXlUKrfZ8NA&Ql%rT*`!2%B4lj^jm?uUf&!QIE@gYbk(e7&R zMPg7}U^U+HHR$Jw6K);@eA!HI94v^H?L#N5HM@BpAIkndm|Dum$gyDX7k)Y|1|Y)j z@iE#yDv-Y}fPp+U_wEgdm)`VlZxT=M5Ipbe8^>T4ARD}`{}%zVqyiwiM&gL&c-0ieUr_t%HXdmn=} z#^T%s|FNGgqk^=!sGf4>S8mErby9qQCy+PC8wfyF7tkgE9-f|W-$Pi?j^D@}kl=Uu z0ldCx87vIJr+YiR^Sk=k^^b%9Q7)(<=%+gk>?*KxKS0V4!d9@h|Hk>=;KPs1ORvuN zkH$Cm_&+SWc6?xF;eozaN-yj;zgHacpScVCNbuthLcA6M+~+#z*&kL`ke}|3a|7$} z%!MDTWW>BM+qlqmK8B3Mu-wSZAA3%a8h|?xZEHaUH8;P;WBc~+8z1LjfqpFpj>8w| zhuy#CY5tBd(nco_57Axt#ZPHa-_`t|X=?c9K+PXLHa$Q=fYBw?!;mkB6?h4N-NA>t zK$!L}XsHLFOl-SA%eKkG8qOi4pJ2oksgn zA`%fdqsE@UrcvYg8iN?Ae>JeQ>ETz_($Z768>F?7fWLV0=$R!UTc_mE_PL%WwWEe& zTtUxEU(elVQ1dkw63K*w`uk2pA{-u_v`v$%yIrM3$jhif^bPY0=fp9_CyX$ri78bU|GIpLHs6G@X1H&* zW(gK9c^lL6pSCW7SHyVU!I?r25<^6NZZGQ0YU7o$-QO*!91LQg^Ia`r-Tx2 z7)=PR36P!a3+3C_*rih%;xn}`eNrW}$v9~%op4~7*I}%(#_A;g6b6M@(T(2546gW< zJgOP@!?EGk$hHXYxY$N@Bs`X+z+uMYm|=)m6ZN(3&WA0>0#~2jW~)(%3B%eAUxOqJ z`Rme0`3~7BH{~?V(IU;|=lHkpP@Jp`h+O@SMT&G%I_d~^`3xkVp=wYd?l<^E0wPsM zb+V|g>UHVNex)3N>f?;Bs#VX>v|RC*1w$n+aeHJ_TgX_Xi^^xZeBCH5db@$cpMlu6 z`6>R=2FSCIg@ooTk-dfG=xL}>L)SYX7;HM}{lecp`>YlIVmw2o$Zf8jA^a=)rn2*u z^T!IvGrB%BQh@$R$}%h!t6D8^&CDk+s|u2$ohWbRvyhU%Dckkyc(B)Un4C(Dn7yH6 z*O$Cp*r92M8kjp4(2K_p&cWvR*w4SH{Pz!H^K6kZ(DLu_%=%$in_2IiLa4XM6In^o#;|b?@ivtH&u-u!g}c zmt z-r%@k@s#|hYq|9hGJ79RLl;>$;(u3ddT7WVaI*6i(Lu8Lyv- z0ZZI%VxV#ZSq^Fze}zq+);3X(=vM~>Pz;se+r)P2f!@L8JozFqx5Jt1#014)HFS}o zIw+Iro4t3KWEVyyTN`U^2UD=gcCd(Auk9Ta^NQB?I&DQR@^yGJ?=8udi{FAo1p-veQVoD~^=~z~I)?}W{0PF-7Jg`k~R`s!V zH1b4;)3v?Kd@;Znq`EM_K7exo^jo;)v$g({*ped14UMQ}alNIyJ(BCMg4y`=JMT3{1J9Y0rS)X&1ihcyC) z!Ox{1Un&-jqK@+YFs-XuaM9OH_UH-sV@L*=CWy|dks^1AI%Ps83dGs_k)BSb`enK&QZlOVk9?f$I zO$se}O20ocUTD{;KNhk0Qy$cULB*1ej?7-C>b~It_CDdl?JLErv*{Q-IsL}v@CvQx zu|SW%*b+u0be{9(4^ zpG^tAWMIR>aIH;4Lcit+L40K+&vl7BfEZAc$hR?gYCzygQ#rF+%%xCMJhKpInmPn= z2UDPw5kNfS7nP zrCttAgRw-L9sUg+BkLQR^}Rg-Yb_-X~% z(yAAFGTk7Bcw(+(NIKM>iQjiwqb9XqfveKj#B5Cmw53_w+J;I%oQx+~<om@{G3I0>Y( z2;dp&@MVyo`Pcec-$pEe9>q0Z4lXURYk5Q7Rk8aH%96piL=G1LB;A-Jbi2upHWBT< z=Qd>zg8M4>l+Zp|3^YbnI=b%_RD;);#qh?N1%e&CM-xaQjFHW^mF;+5s;J+_!6(19IHKk`UXJSQepx7(I zEY%BQNdRC=sw&l_;~CMpS8q(%&=p3<>0l|-^{9WiAhhxn`CO;t_@>C~jjbs_T%0fp zlHKhP74fsvkq=Xl&$v-A?&YYNY()rh`06(>!+HP8I2xzaH?qrJJAGV?j%aB-4b*t| zT$THY-Z>*%jSTHiOv0Uy2Yx&uMO!KN&MNnCR}#F*u7d41>9yyFi+({5hN_bpwWlADu+v< zc`%h(+^%4}*s`C19d7S5Y`d#J0-H1`rsYglz9B)Vb?pWt$W%rHLNAPV9BZqB`c~#r z!zsX8>!38e>*J`#vjzq#O{qegp?Gu4(z^QGSk4l<(;;;b$0Rj;GN&&mI051By@c6l z{bBU5lO|$IL6LPQ!eZgn@25!jPJG5oB->8+r_m(*=Y1(*T%LyE01x4 zNX+XdEsq6%=ddz~UVz+4pz1?(=EWc^8NEJ5-jf~} z4m&I9a?tZr#|}Gks@Y@A2VGEz|Ka^>5G)Lbs#$I3)i5=8(w$ux(r?}y9esy@C~|;H zZp>LeGYXP7hKPsmT0aLLtz#D5W6gjspf_lNZ@R+=NDSQ_OQRbL0;#>X`XoJysHsZ0 zKke%-(_^c|8|_%<3Un?R=N`=ga76V?s}pA{NS*-k z#bX_l3M_E0vYir%;ZHOG@=dLN=h~sHD?N;O?pAY!b)-c!8*Fp>WoxvDHlyHs%4f~zZRXo-vY9xK)1#l+U!ki@}Jpl7Fpvn^&M%dHRy@CzMxTl7wlfk zUjZwD?c+o=JJ?t*`-jC={+TO3)^nyRvuzunG{9$ezy^)OT5pp!A-@8bV4 zYCk^Q;@wO906+@3p`CDj3*Rjlv`x*Q?_Nu)jet`lHn05PYsb{+dE?TjQ?y%(gLG`6 z@RE_-GA+Jp$$3Jk`)fIZl!myHf`;sOgYW>OceOttEJ$ zR|E&+yo{7UuAg~7{4{dRltY!bZ(-`&XS3=7;RSf+T}H()Gzm@b8q(BN+%&bzTKY9KJeY;0?@bDxgI9aT#08&s zEw?p|wHAGfu=wRYx=fsLddqW<f~9A@b&kd8@DSGjLi$?D2gt$g%zEg9LVAe^_3UZ2?t-sdKYRt4he6Klh1c=8}nxUx+(q&s2*p zthXRsD1TBl27jGm^gt2@`Fxm%9+25mBh5~+N|iP%o=eK1i5Ovu8#v>BK`QeXf>k?*FW6 zRIQXhcRfglL#me=Ck0sa=7{#x40(Hsxg$hkNOciBi&L~jSs>$?X6ehqNd2Cox^L?H z!<#ebU(`yOW26`6s!OJL;>%x~`>V{b36@VQrWg)Bk}- zDdkK9Pf+I4WgMM5qc$qWrWN}WGQ}b7nXiw$^ z@6MPUEO+u)Gz580?D+?KYF0*T;TaCYizZG!&8VN7^7)t=m%;^RbB}l?@G0xaKwowp z{fBtX2%tXAYO5i=0dDMEJj&N=SFUT!^pJ>J(fEZft)<5fzZ@g>b)pC}T%!+J{ceOH z21)lX!iQn)RyfRt#<<7fi$~Us9ti9Ed)H8W_D)(q?7zDlH?_8 zVNdOyo&#x?=gE*b9R~^;!PssY+oVbRDG}D&?xaWKIsZtQ$13^KYs9BhaGj8#fDl`k zLQ8~LhZ*?0BzbQjH-~N$c{E2;S|8#OExgoSgk{!}aJ4E@9&$&E*vJ{(nKt#Ur6W!& zIX!hi$Q2KItd@RfumkbxqwzV0=%kwP1=*?-W}_=@AdNR3bd3Dg$ryklv<3jxsn1F# za$KcEQBy#3i1dFbkS*kN>3LQPzP0%P zMz`(7{ZP=FxWwBcc3-G$o`??1`}DgrxUmlJiQaA8L-&D~3{$;)uZY@2M#$y4G%ZJhjzTRBgG|i2U=AK9)2A|S9K&1qp zw3=i0)KMp@Kami?ox#{r@OnL8WEHW7W&kaz$uDCm*z3z+##T;Qf4?XFx-P!g)$ zk%h)gMn6kWQ?yUSZKO##Ubq)GPI^82XnIjSoS#iSJs>2qWxUA&hI7J2vXRW=&!dxf zPn;cysJ}7+fv=dn#BMpU;MtLr(2xRCrSgke@*adA)a81sDOYmv$oZw_+KPFU!NN%x zhDC=oPyM)&2`b&iT zOBW@$`W=Ig4^>-}RM9tG&az(ZVygM@S`x>GG(twV;llUss!r*IwOq=VULep`sUAXn zZ;R$ABesl&c~x<3d=ygPPdpzoRT^*hz$35rHsu+H)Eh;Fw7BDyuLc*0jwVXf;zoAo zRHo7EA9QV1mU5s%2ONb6@__TVp7)IF1RCxRbaZ%eAB}ewQ>CU$?-KR__?>&-X!u%E z>{0F?I+*EkD>0?I+fx`PwX`;r^l9Oe1zu+;15BUI>{aD;=?A(J-^k^ZT(_=-9mLgb z+oGUxzT-+8W6aA$Q}#gWTvRj@s@r$cB;qOc(MQX48!~Xw#7UF}L4Mv$F@^2Ov5xI; zl8x5}QnpB|vCOv@3`|cgLc|7+hW=>$m>A8alEb582yV0ZuTAklBlbAn|cbPM`;(G)u~OwH+rFO)%X2CCC@ntT%jlOY8wezY%|24{kcq9h?r?LqRDSI*3iLCR}9 zzoa89Tcznz>zcs(CF4fNq9=Gj5u{fsWNs*0HC<;cCzFOS=>-aebz6_k*F7x<+kt~| zhNQU$^glxLfp>Qm^ov(z$k~T8sM*ncGG;l|rWuiJO4Xgb`2a+d=~|8%RMN7`feB2^ zB=a}gc%?&IYbc%y+8I)>TAMqwMQ~5le=UDA)@4# z)mv1}H4+M6>%nmR8rpw71s=|XFWd`XVKVthQ04Ass@5NBxM#4#!K$s<_u z4+19Hqa@xz?6Mb?y+BU#lo^@&_*5T*bfVx?tdI^Pl@;6O-x%GGJ+J<`-0n3K==Me= zreJyCIzrb-Uyv1)no5o8sG>9_(Ii@N>LEVp0MMtPBzed)(|%jBt2)D#Cu6i?nv=_H zGz3;$jD8&zJTOml4_*lVh8S$0A>EbdJrI$HC$<+h*7voM#PZ*oYUg=xM-v98K#wiiG>t_N|#s(7x_n;c<5@7qX4hcH0* zO}B=jP<1`voVdciM&@t{PuM+!idP-Dlu$(9ehgD%PYQ_#$N4HIoo#5GQ(79$0-x20 z35fHT9LFM;tNP(rYafY*6m)%UaFkQE-l}IVRsF6EvtIXxPL$ z{Q(z9ec48*q8RT;MrsXwyAG-UdPhV->zwZ-Om`Ez!XZc%XCLX781tjpbrdOV0-ON_ zexD)|vv@sXvR%)ny^Gaq$14u7r4q?NJh{cwg`-p;bTi)_|3RQgN{uVL3ysI;oDWnGdv2)IF z^I}vDNc6>J4ydxZJb{Ik?~yH?uE#7&f7d{DUY+nhX>lbG$oNFF)@y_|rraII2Q90v zywh<@m|DzJq5Z&yjnIfOjC-r$~I@v4FU{oP_R7-S{W430-5egkETpt@kRx z&*)k*K!ui+e&e;#k%;#l$ zP7R+G#DqT4-b3?-9V0#3(>K2#JNvTkid_UVSs1x)x9tD%>6jke`r00Figa^FN!ma- zW`2%e7v$fKu{$UP?Y_RA|E=BVu5zB~*2^L&sTwPm=GI(tkMJDpU&8^{IXp6DYdDhf zZ2~>gx?JM61?XK+YdsP+1dB%Me85fxewy55qq=Ze5mBISZ0>o-3v@-f*CttdZe|ja z2t2fY4$a2i%f?Zlq8*Gy@ow6o}T z9JVZ7B$`*r(zb|*a z#I-iVZ@c%*L82n}`o=?)J+k5c4$L!DT?&bNx5hU<$H!bwL2&UyJx!X}U zo4krYeIsRe!kBcNONQ=!W4L1yEemvWlQ`aOT6)~) zM@n;BqXub8gnJ0?wKgaW^cY$b^O#CP=oN{$DKfR>VSD}aotjIisb`etDLn)XV~=;$ zkq|Aj_NKR;5oiJ+v?qu30}p20(Uc+fIzg1}(PyB7j<@-HAg2YK;yf#n9^O z^CuzlfT%C^rv;L9*pC?_`Q&J9(qr7)DU-vn725Q3-^u+h-wMla#wyYqLXi(;>DD+& zM5;x#j&-T>W?Dg-Cog$MGAqwM9h z9=Gr1@S6qWh&huQ&w$;7&j4}x1TaN`F~$L=miL^elfPXCRO(1roY(IQDI;2iIE(Dv z1rNmb;>5S(sW_|mCKVQ-2o-brxG}Vog}A5jX-aPe`X~6L;G7K0o#uy1q}#ieWX*We zC4{|wl$WA$u&i$n=+Hepg%9T4Y}-OGoXD>!v%=P0FRc*AB5b$B6T56JF2Mw}wVc)P z>Ll`uD=|bg>L7^_RZmW@osyAS5JRSNp4HX8^T%-?@*X0suI(o$IvrD7akDR_PK6)V zdhC~E&-6{Z$e>!%3D!Lg1Z#iPQ){IIF}3$)Dbq$cMgcYMhP?#Y7LS!g0G~@!hnCI< zL9*k;Lh&$Dm>+v;rgMBpf}u=+Mm6m2raaa&!IeziZ2e{NVqIbOM=6*nr8{)V1- zcXs37VV(~DXq0^;)thvh!FKi8lM1UUOL`MUhYCo!l~^yPNRi~HxS}k6I>?LoK@xxw z^M2G0G2QbhJ!I*zuBCP}2JGNQ25;20c*=zY@A(Q5uRnN55B^!4h$-DUOg5{x$YZc& z=%+8*a357Eo2gKYN{U)C;tZn8fN_=Z(b^oQ!mbiTt`woZ+AvcdlGk|C&|^e%<5#?j zKdZ6(RIGA9D_ZzV4YCHEZJVNpdDf!Gol6(F8IHJ4qBqkT`-I6@`{bSr8@GFJ*N7iy zzg`um6ZLGtX_HZIp?tZ9-G(7`#n;xNh5+?bygMW@{`w0qVoIwFBw#$u_} z?|JD#Qsr7X0?CUh0sL+wDW>S%E2pv%AB7#~DzC^}F3i7W1$~trNDuO}QwZ;mzXvg~ znepJpObj_B3UKg#H-g^AQLW z)Q&Wz5zf^3_?z7d)MC`a8%k&JrUeyCV0MQZKCZE_2uA}RJ;#(6yq~D4^B)k! zbPzddEHMc0M>y$aF?J9<5umngSkZg%yUe%howk zh2;%+M++=E)@o7On@N5t|DLnhk(y@DG28{u*EcT9i2in){VJSQF|`H5Q4hO(rzu>>2x;CW70iMVh0X#7KIw}3Ipd{RoQzP-v71e7T0 z3H7bQ6ua?D6ddMZ?F+pmb}?(d6Mpk_P|<4LShkE7$f#qs?5b$Ho=LYHX+CsR7&}-v z&_^bo_%I3Ao!`+LO*rq()zmu|@G-WHnnBlxvAIq9K%_j+iqZc$B*?1%V4uqce!-o{ zo^5tmN=)K}R=?bh#Q94B)ZgN%tgJSYOh7&GljBh@13bq(W?VzE)#RXMS*WKCQczUs zF4~grIF(Z`r{Pyz@g-cb=S&#Q%QopOD%%k&E-0ai+3QP8mG)a|JIzxen6xXODVNyjfd8<-n z{M`fd=re$iSIgZqG)LlTTc@~}N?>omCe5a4^|AkOzZAn!DqTA4fEoYv&>In1HR`?28Ul^EleFh+9hO;f z@W1ojqi%6_c2|#z(uVU;oY$;-w?8Er2#);p{4N@u(08gQIaqRr>Ctc>0JhO-4YVwx z$2Sm6+bFXOe9#T^*i}U}21ha6nc=r?Tgp}Mb)~WfXgP2v?0@IPwbUU?Nths4k_+fy zNigpy$un7^uYAVq?ARx!+|MLWoasjd|6Yd!OVN#<(>Dx|7h8wRemK38%uLqnb~>{a z%`CVJKR6!#^NdpP2yJsE8&_jvY<%rzhI#6-z_~HwX;WPL<7t@l_7VkD9AnoL89F>nL%-RYX^^`jl*}EO;mvW9mkANkc%V>V2H&o zXev`{ni6nHSBK1W@MKLPKZ0LGQQ_TEmD{iP74Jg4h=~{9E0YGT^i9UPi0o&*1@eMt zm*!Wf-%ZmlrXFhG+z18kh<{A)KokuQy5(97jUO+V@&|#1z&KcInK#07^UIj$&P4}dTEL}aS-XAF)O9NL+K%iOH@dezG4ixii~6ec=;_*LtGtBs;n4$l8A4SA zrD*ZOg*Ss`k9q;M&8_~@J&$YAy+=G0I(*8qczGoip;~B7Q($^1=!*I6@xdCpR5(pnXBspG`6ILFtSPi{ST5@2fw4XMHy~v7Twg% zIYu2B#6__O2;cl}Khs4-=oEs!g&&87z20wY1{?){+Y+IOeS&=V2jp-Lpj}n1j!pmJixr) z14g!#OsWb=ESisBQdNbE`FuON zyc6-FD_i0-$?h=~JgKBlU~|@`=Ez5-AXvYBM5$}S&ar(zSy+3*Nx3|0k_zwg8{cR; zD1~H9@3jv~;2=Ep_(~I)l1q0XikRs5rw`0ZNKp)*viQu;gtbozrTK zK89i)oJ|rkDtSj7JQwOYso>+t6>8ex)gV!hT`U8nz$%lek=XF#_X10sZQ6pGNmgRA z9zUDzyl3^T{iZB$%HPtU-O^BmNl5HJ=N%yDNZkUHcLW7uC(@P#s%2iGdy(@pm(i{1 zz##_T-us>Zh>?MH;iu<~Go4Pn`pxB{PD&E#H%0K(lQZB}s|S)-Il%cIq0KxTn~}C@ zcub+Z6})z1evQ7G8sUFZL>z=9X15=H3~UG)+a{sc&MlKw-sSM8N62^(z;8Sn#J5T- z=E8I}wshsoJGS0RE8hpf<5HQVV9a+rJf@%?#RP9BE?GWLqf^V;KD>J^E8YQFy6u$y z7)ZuSEg5Fc3|poeV)QLdzszN$X}=6P?Zy$bGnp--&v|6KqdQH)CNZLk9^;EUwc3nR zSiV(>97e4TY-1t<%;f;xnFL-mXWDlDF`4CxE;YqvU(S=(kqUOXp<5b}bjxdK3?H?T zCw9-D+et;2AlHE=hrV%6u!rT(`}UyZp+RNW#)k{=sY70{4v^vSFh3IFEv`7^dUTu` z%R6A}b6b)<)%W54(K_yoL~NT(bxat z6FE8mgDCuWKJgz((qG2#|B6riXTJIW#3%l{eCdCy6Z;pR$jJQP$D*?_#$q+0=UI{dwYMBz;zd* zd%d{tEm7^VKL(RW2qQ%Nkxt|pHLkU~@qGX|+a{juWC)KGKJWH`2=%+A89nXg^Lp4j z_|ioJwL}rq%K+6xG>>2LsvQUp4|)9jh*ErR(>E}|5Jd0!b*_sk zq8)lB;6TjYW*_0zB9fI2ITajQH(_4hI=xN}615Lx_Dw}QxVS^WuMxExhcRTUYcOj^ zvH>r9cvFzExa%3lr)ee}Q*$HkqS>p3_4$9DktONK`V8G`H)X*7%3?b+4jE=Bo+=on zvs%QtiX3Ph-8FrdX?BO~+T#&N$KiVKzQ+2s!uIU^cjS2Q`r{?f3 zQ;?kMZLxnDuQ5z-bS%$n;N?!6k}9Gn>6r*7Y3;C`E2ff^gn#Mtf4*+H_uJ*-D*Xg_ z{QiTlP=o$?_RQ`pki8`2D$a(Z7PjWJ8&42LFqii75b6jztb5Hc zD$+Ncg&i_}e}?HP!CM9uybID|6Nk!75?-cIqPWuD76{oq@gAoCXInabK$l`jRL@9+{W`O{=pd^HBPy7 zJ8xg~P`$wt#$Fo*0ES4T3E3-&jsncFa6&6O)bdfjQd(m30W(>d1V3wvpi_z!Y$@o| zi-U4PToY<$9F#}Q7cxEYmoFaeq3-SM18qj#O7kKNg)6_?Q_B7)2dXssz?q}lV86I| zDFNo_+}(3o@g;`x+R~E9CiJ4zVHT5&ol9r31%QQgG%0+mTFPkZ54331_I}%ec45yt zE+%`l*;=WA#(90QO)M$xgQ;aut{lcRfkTG)H~ErkLcUd99JsU3-iH^h=g)&rFs(C z13b1C_Y5@d5VHn_#LG%a2!>gNxF!PPD1B?qo#+fESHoQtBeV>Wvy7Q$!5FqnE^L6P zNqX6xsLi^R`aLaNH4~?L+d}yc`&tcQ6Y_N!=R?{-k|QTkIDhmEpSohSwFE2ieoeH< z$=dg49=MkL;W)oE3J<}%9ObS-OaGjq7lq(y7-CrjARp5@f|!mRdNkQsz}bHAphkI_ zDD5sR?o$EgUvOXqrjfY9lH*@yUh~@XRCj)H3D@GK?te89{CAT)k^bmYSCHV>`Pi zq?Nub(YP&5pSHmsY?T)N0_WmWo#Hht8vIjSqXbo3opS3W4Uk+%{;2(IXf$4$dp{3j zPJ^VH5Sq@0aWPaXeXywVDv-LKk&%HA{Z7=NgO(|@aB#4|lB&ka>lfvUz5QefPJ|`q zyCV%P_A>}&Bp91@@&*SOf}49$j)oRX?#&H~km9ZD>I$!3)kkK3TYr#)Urc&!mbB)) z9ZeSCYnIPa4QId^v$E2uHT^Z0XE27VNG!>qkRD!1Jw6LaV7~lvE%pIq>R{amu#d`E1wQ*(eDe*{W+Dq<$v?JK+sZMo zvQ?DHC4^SApxPGU(xFJIHrq2IMpoO`N7(9am$Dul8qR`^BtFkEN!VKkp2m%i&4=Cg zTb?ZE@ujOnl`oFH?fjlJBsW|gd9HLzo4y>cIa zL@~a@@`={fyNRC!@-6bq0Cz!@Zt5xdn0F=tyj-}#}L)g^Ppf4?UldtLVY-G#(qpCkX zf`jhL>B5{KZ?0$%tG-qCL>|LRypOx-MvO_juj{tx~K2~$gRi@&B;7M8zN zs>-s4&ejC~nf~aNU5#A+L;Wgg`;SxNzx)y!@Xs&dTUQx5{^}?GRl&;4 z!NK_7g|C-eGm)m28MAk%_z?z?tC5CcX8E*%fo-?^7-=Dm7#P-NRVCnIdTpoC7Bd>q z?tpYzA&rt0BLu{9S>Y9djJG2Orq2{yEpV&z$+_;pPVT{~!M^-+%-9&d2tP?`;si_eFyM2iC+uM)a`MCP`OCS86 z_apgV6;E*h`fSb$008dL4+}m}`kxQ}@Otk?ES|vqs?~;uNtxp(5G*T{X?4xcoO1sE ze{SopiTqfiO`if1c_yJ^Em)Z|As^V$L%zw?H>Hq1kAsty5zv#ZdUs;fvqR{S(quSw zF%u`L%!mv`LREBU3H5an!1-Kh3%TbD8!5KYAN0xDcQnzX0yI$puF=#NJABiW5-qY9d4CiA z;7)dSkcbf`oE~Wof^YYI5bo;*PxMmJw+qEQH1&ZRvcUET)^PHxkdfm5&NVVFLscjW zg(xQajg8Y`jsMPEZhuKp=TcDLhBQBh3lD;Yk6%Y${@<|#(CK@cW}JMzGl1%`o#Uu0 z42Tw|MIqRJXpA!UHiEc2g%_#4NqZQ_(1dq9it6kLRHNq@SF$T*(}^O2)E-Bt$nE?p zyl!YN)YosIU#SK$s7=m=J>psBD&r8CR;dBLfdY0T#!}aZLpK4eH@a zh-pz)k|G^)Rvp#${C7Qhwru?W8SBQI(Ia{=OuUW_n*tZcvZKKu#~D9~M`|0P^o*NM z6Zp1d;KW8ypwN7r5$g^lCk-`G@3ABseJDXJ6#o<%*F{J|5F#{S?|9}roZkN#+k_7Y z1LI#u#VNR#30BC0N_Kb~5K(SZ!!FH$oc|B*@-iPMmU9ej0~eBDt*{wGy%Jix;YJ@z zHar*fBA534rbYjE{L5bxu{cUwCRN#%3HiZC8;pg66aBaY2hsVs_-QElYbbdtd%2CZ z6>un;9a6KQQRGlbFA_UYQJfOd6Gz*|CGA3-@U(v)AcOykLvu7=;hO%d{tO5P&6EmT za|-3OHydK{0;*E>Hj8686#ND>$R!T~271yBC{jYn66G**mjgP9y0{xb4a^dPQNDU( z88-n;VnthLADHq1!olyfK^4;?*=O-PkvE+1MJ-9?fa9qDNW(=_@^K!D&;)QHL%XaK zp)`}w#uIkx!gPo}lvtn`yz*Da?Y}g@?m5uy3@7-|4PQVfvzx+O$0zSX%%B65u~pch z|Hy?NXA){!lmR^q#+6HFh`KOvsM<*=wmx~5qBTM~gZyxZqGf%3NkM9l(w^Z)eh!`i zyWEe1yJX7VSjUsi(4cw+f{H0^O;IXH=3YWL)t};tXhi04>M1~1KL;F$S8cIE=6S;A za47Wv(s*$iCk6u+zQ}WBKQonpc|f*1APvII1Rzo3<<6Ov>;4C}{)0<_Kj5s$hzP&~ zgot)VC}g1_gszKVLj;#la|=N8R+&mk zqWC}y!gYG>gOVuw0488_VXQ9o^=Wz|KSbe4DyzU-= z*1zK~02g)8gA$+s2V1^ljKRcU=xBj9SwBgrgZvw2y1n8=c;BMJG2x|9?AnK(O5_93HMQfSSf)O3B@FK@a%% zvmn{(aeTnKGn(?gKnKHbbO!(w*!rD-W~aZOh0F*QqaOV4HT?W(X_^wPY|))*ik^2M z9rvqY0hoD^W(8swi!H?q1(d%ZT#8R}Mo+5+PitE)53;Eo37kiHVOpJ;kuzcax}X0f zk8o1W4y0XTEfvjCy8*Ik#Ow-BSl{kH>#ev&Qc zJ-=f_Vy#ue8{q{ADrY<7Q?T3l(U}1MkzwlaxHBC#j<^Y!!VqbF+!n#^hU!n88%!As zM*-p_bdU#MgIKjcJ6vjb z5t{k-cFd#-t^MLg9T>t*;?3JE($c};NIjC!BE%l(PK^-vtn7mL6)O19*!?@(kqnTD zHwrp?1^|OZ3n+4`TTMFnY!q7SqO{*-H-dNCFb?2tj}Tn8>x1xGC91iEH4)xtP(Ft#yeb;Vc^LR+fzvqN^#6`a*p@I5#RMUOybuinh>blA_4lp(p1BU# z=>@dFw^mL-xc)s_lW`|RabW;&a=@V*F#%#kYHkENhIqHPyW?}C4ctf&Zv0{HxSuvW zENyy@1O;R;CPg%!_I7iixLOAf`bl)x5>V-7+FNOi+AN#2#K@0E7xrH+c7P=Ee|Sm> zq>VO{IHA5Wz?T{!j)aVjqd*>rq7Z^wb}uw&@;VJqv*G7v{;!rW>oTY_EWjP&Qur0j zeNkSO=Y^wGd{fMhDKumdA~gAq9c*Q@T}m;mm75Vg34 z^{T%nx-Sq%BL-7UJihkW&&;1`lLNUM*v9yT#!}H$;P&xBsau* zFWc7BZAclKs}M6=2!RcddCe+&T7vYU3=>tQi^u;N%#&_R;Aw2w0jBWtY!&0Znkc0` z3)fA$GY*r6AzW5rq}oOs>f!I?WlX;$8YeHIA~p3H#>N5bk?W!jU0;Q@Z$nsVuL{d5 zn-PC`vn!$XaLC= zphFCa0hR&%haGxlrQ-k#8O7S;w53(n@xaY~!?N+dv9^!*9>fJgR;A+=#o-Rr@&3L@ zb}(Regu(iEWe@6ANyXtAw0e0DZF@HZ#0Nw&192#h7RZcJfB|qzL03-s>PJASR0L#> zKeSX|1ARoW(x#e9zfJ1K{Lj>wK9KS)VR`$ZWAz<4H>{?Soc06!NeO-^am>?$tLlPP zOHf=h;D;;m-DV+ApoT0)F$KKvubSwBn*X4z?*$Gy58=wh%GVQ6Tx>InF^Ilb4)B*$ zXz?scMFvjhr2-xIDY%R1S0OvVx?LcjHn|=07sq6158JD0X!CbiZa0qCMg4XSuG>v3 zCt&G~!?{L;llwNP*N6N+>01O zcX8@CpdTUzM6tYzy6Fc^ZAL{B`7}g( z15INFTHyVAZi?p923T(A;nCD)0*%IR1pdk)60wK2h$#q5xwCM`&QMcIGw|Z`)=%oNUN<*8jRKh~ zO*c9JTUVIEmrL6_|K_y2`f%gykab#e{Wlf?GzY3P2g+#-SS+ZUXKRtCE8Y~|_e7&?o1C|1ASG76Ck@R$QvC6xg)+>6}x zfoI|<`mDJY2t5A0{NHggI=D?6xXD8lesco4|AF>R6uO!tpttS9{q(27zz1pC<37K2 zV3xnHqR}iAh6275ENMT)c3|KM{|!Ap+@e*4|31j^r~`|`n)|N!Z6-$`{2SN?`{Bff zE^G{C8U$IsW`iDi!vZ&TQd0*|0Q&=X+2MpZcX<}m<0$nQfZ%=CnnX&0RuY5ikg|Uw z)CU}m*6XT`EAGq_o&at^Yg+wijp5@+*@fJp*`aV6;560{s(E?}kSka|IzoS4zA%mR zK<&K>19kfL6do&Gh6QBBgo%nvkz;H$86f?c-(wKiJR{ekT1L-;f=+SPM~ z7&M^h^By?P25l1pAg|ukt7y4v2N(7MIr{6?x5WH0}0WGG*IQy_#Uj? ze#HO7$-hJ9*C2JBzXTN}U0jb^GXz>wy)Ckpu(T*?>YX{U~RZJs_vakhH>+L>L zjg}+-*6KZl#^B#)i+&S$VcB5RdeD9HJVuBr)_TBNu$_f1wx9UV3bum(=lS0v^4}Qn zlzteL7olu@sB9=oy@UYw-qbY$C67mFqd{U&2F~C6FeqqenW3mhKqIvr?O6XC_cel= z@I0)fYR|&7W>F5Up?a*1fO4#}kZ|=pMq!htSg{j>pg#^At`g?bp2tyKDSkA4(ppV< zCvLO&&Habc3RnqZ8E&WxbD-6DC1ip<5hzN-8g3RAk{0ryZGb`vj5Z5-SdX5CB&a6> zO?0sRhlu@Nc=V3eiGa;9L@arRSUt`HqfZ4&-2&R0u1w&3c`z7y-sY5#ve9iokZA)x2l(}wP7 zRv<#8aWL}v0lK(vXnsI6^G!#C6$%^MwM=7>v_2J9&}Q;)M-#512hw*ODj)(~Xdkc@ zXu-Xqr;W=0_J(Lvi(aGo^BS~;;N?NjFizwwP16tkg{5z7QT_vftU&`GDL{w+aD#B> zrIm*qps+w&($``5mVm}L$TkOI+pQ;T`a62cqi`3GWZEhJy=M(xM8lB@HsyQ578u(b zX{qfM?d_OfYtyVYf0NK_d8Wr=Pm6sK)Vre}RMAPhe zvQVEP>kcezry%sABQ#{Ebz=^uORJeurZiDWVA07P2|6`BGN@48dOok5SpEJ)f)Do6 zJ_vYGZextLSgc@peJa*f29%K*`u5Mhst$}4xUmp}&hh4<+bc5wC@s)HsTQleo3KOM z0DI);51Es(Qbs-c3VG{l68j zHgUQP6mnv)w0x5|3YM}!YkSZymK;nTTMuZl zY;K@Ezy{b!I)87Zk#;{-29JBu2u_140>ob4tjsh}$_&bV`%nku}NI*fCVExn_h)Qh=r7p9H)Kgd=1ZT2nrG0Q& zIv=QS5|Y1Wr4e0k#9$YcT7kJ9HKZtz5c`5->k&@4da(suRy!rJ>%%(^c)6WuxkX+U zu3pg|J`lIpnsdr-U0CYo+m(5*TrAl?u1t0_yZ`YF=cgP9!S^&!NF}WFgf<3Up_e4LKkP6 zKB^Xg&>+K7RCoGE>{q5<@L&)aW)(_&j( zJN)nCY@v&vhyjPB_ttKL+sS;u1xitk?68}}h0HDlfhu-Dy&|gJh9{IB-ajUa_$8E& zkANF3hT5u7saceLp!7r|#)%aDqGoO%2=Iaa9!$-K09uA%qfsrk3+&pCy&@oc6I}43 zj9K{-C*B!tI~%;rQTuya_6KdE2hUe}^f5JjCkBCae|P{xCGwIw{{YH@Ee4$|6#r=R zE_!Us726gqA#KzbG>r0D$WR;adAt&0k?zJkm`Z-Vf~GRaRCyK0BF;q=JK0)MMiqg4 zkY&nAm0Uyo5X+9>^B$U8`?n+A=qV3_;_I-$K-n%!vReR&XXqYS=)5kfn}?(1b1c(z zy((?ZC~BcZP;QS=6psFkZ6x(V`XJi9K8vELa)e%5<#k3Ti`DsvucIfByJ*v>VQ3zw z(gvzptMRXXXrmKeLG~7k>|h!%3@57BT*{iKF)}bSNd+05B{Cv8s1?1|H@K}Hw8@0U z@3g?RM*1W1DoF?=O%29IQJJ9f?J4*8V1c$T;T2$nI4YC<0c{rYGH8p!J2z}d9JmWk zH$9gqw;9j%2)T=P;2I3H2PuCVJgW;kA0Q<;bHJZW&<5khNTIGQ;jMi&CClbQ)oWkH zOGKG!^{Q3?V>l3eDlL^fUd!x0(wH6_ zNeA!f%F5@)#~-OP*R1Alwdq;YKmE=rkR1XeoQT3jS$Q?Cdinm`k2zOUCf@6l0M#Lf zw9J@^ins7zm#L}_m<0r4Z@W;Hd^hai9YNnSWHUD@FG4DpzpXy1Z*$j7Jf6m*vSnlm z@Di0zyZi02&Fq9q-=n~dH@r6&o{|uH5wt>&KrI*9KGL)pyG8oQ!=g#~__A)Uoc+%x@O|#rd(k`7&hn)L_~sHnayHfLe26bI|a0D!_Bv=?mCz{6Xk!c3r(ZE z=o-x=fA0{gFDY@Hk#no&LU8qRPXVt+`lvN&4eho+MSDfjq|7GgHuj|PsDzqzF6OI5 zy6ryqEWlx_(NrGI>fB~OK?$0XG4pmJ<@4@k%0}@4J*io|jET3K?fqx|o}~evwuT~Z za@hN}xz$4wK1?8cYzL_h`&J|Z7>4&QGM$dLE9z7yw--w&$P~qpeng!?9$Vd!E z6RRQs5SOJM1qu(4cjP#S?#uoD_%aY|>Lfy)bvOXx21`cq_)2mUCM#|xJQfrQG7{mO z3>M|(qb!qZXzZZW1iSxAz$^dUt<^bm!(e>8G5v>DVvq`d5@+hJ#M7vSAC#z#$weg? zuTi-?2}yJ}P0NG60A{I-+J*I4K++ahea)+(#DHJhrE6Pa_%6UmBVAGbU5~ z0HVR`n)CM7pN&s!ZH^10;kUSFZHypK*W5O5+5&K!7yTMdbKi#_6ydGenazNu>H7NT zA~iEo%dMUz^k+OQ^(`DxZ2*NhR4WO?jv2KHmTPb-nl? z@lxSF{`10lftT;y^7*ZK)9q#5pXRrxC!9Qel$Kh(x9w*-eVG3JyPjI5$gj%wQL1{+ zt1gvpT}_GSqo#XjDlvcKlUW?uq|X-@C${*j!9G;#zG2A@UgjOxP{Y@TRq0oOx*9}X05yxye3YbBLw)G?hiW*ICEM%Y_~8ul zw9YMl5Su|kuqLMftRSq5lZ;fA<>t+;`?FD={ZA%F5ji#Awc1O5&roUnpQF+Uv>U1W zk5I!uq>)3-2lcCtBMq;6DJf4TQot_9;9eO0{w;j>!4}N=+P-D~(J>w2U5Lx*z@^vz z_tU*a5#;nEC~|8G(Ryn()^p&<(y$D58P2kiivl|h!JV3WZ5d@ZzM8wL_q2s?MWE6g zSez`(py=r?+98M%0`<$BE#+G^xW2_UOp4D7*a}GZzKTRB>bdJ(v^(#&2mJFlxR~Gu zKlk!7ZfSOMX3$f;Ghl=(-RvOpTYs1cpbEQj0v;ak-W=CDYh1G-KCnPZ7}l)fMjCQ) zK7}Slp6^kqzt9vN*u^>J_GC0{PO3hjU0QvsxIeRdI|6=z6kuL4NnuzQiqs>E!N2umiX*eWd}?z1N3%KxOcoVWQBcBQxEM0YT=V#H2LUYlH-;)lkDxE#1WeBoXn>HWZ?r z`V>6%=)gUdY4T_1jZ%lP?O4G{@i*1mk%kjcNEfL=f(Q$_+x%F!0FbD*WPjM5vT=zs zNeH%*8&!yHs@F9_u54x7S#LxGKWqVzo7)*WtetJPnb%<;oFQ+cf*QCDpW)Bz)v01b zkY94Z;}EST_FywxMle_IXcOPu$^A$JE8J6UlxWCnG#zut)k8+cl7$Cx7!+V}eEJ3$ z;XU*~QW5dOpoY%mo7cgjZ;DDTrEAk8M}_RFZT@G*xguixQJkG)lFqHIvq-wQAIG$I zDI?M#12+&e$|@Zp3D|9gcJirCV$NyNBf24LQz_=TjDb~eWgaKpjGc!PC zAGxoWd|g`#e3|40a6Bg%a5@CFJMV1Dq+PaLJlHtb&#onG+TR;Kh5YV)Z>b|JU6q8o zg98?I;^bg4vOph)F5gJs_wB9(Dd+I5*-_y-ziuQ#UayYW^Y}>{2pQVh-W6Nd;VaTc zZV_DDw*ThIHmEV%R3IhzIc|)xm_1$0q2n$^)w@d5;jhu9+DlH~-cqZc4}3ZE97iR8 zm;qN%trf5RHMCJ(cVVEeKS@2Jb}rXQZ>}fb@jcD~4p8fzn%le+HDvQiXvn)|WR6mi zw^YBjOV6kRLxnSIGC&XS>nX27*cdvq=nxA*=q?PEb@($)FencJp#t|HLRRs*Zus0H5>;H0Q@X`}%#05YV zcYoHN7VTBi z9)yOLgJPL&DBcAN%32Q*JlKov(0fMoOHq(T9@|$+_-)Y*P5Qt|S z>Rp)zHzl#6Y>rPkz@2yUE_7WbqcXprtfeBQh3SrWuSod~z2aq#dyE&A#L;8f^i)EU z6RJxRxUxVlL5`qG;MRQI=rHi2%akd&uQG02Om|@_u}0lm6Vdpyp>Y~d)W6@P1=0#~ zoHlthN1_GOG>F^5Wm|lQr}gWT*zqiV={md{^A4o0vMR|Ie0^GJ4+OU3WKC!0V2?;9 z9NVHHZ@I0gX3M1~)gJbR>)@+owXwLE>mb~jAZ~w)4mF?bnh$fZSy%+_ zz{CYrlT05;T*;DHg)kzwQCUc8%K*kmmq)?j))+@=5z&-0IPyx`w@uZ?pqO|L%Hk%v zX2h#B&pX|prus3eiw_Y51A*>VDUnmvl~Br=Ah@|QG&i+<)!}8|31?pKvA&(2+Yu#= z8Jneo;WSGoByl%tyQliA?=CQ4id!+S)Gx5z3;FqBy~O#5H1^iYbdzjSTuc-fn||N6 zPWz90*WzDjuA74P6&d36g?6Jz9;VPD05Z|nYcyRo2ag2nVUZy6`jsKPd#zyftXCoh-lCAF^4~eY})S4)Ajf1r2y7bY|UdnHLs8((Y zU^Li=Fy-I#B3HSp=i4M}6#X7l?(O+u-+kps6yIy0HMy@Ft2OI2n=8B2JtUJv+X)fI z{o42XIP6-t1|4yJYke8-)_ht{ICH%Y9Rk^%hUHJ2)Vhxc?TP!TlBRyjKk|a~DYFU# zof?^an8io#GdtwOIBZ&Hs(G0LCg*xnrseDzo0gh1eLfJ63M=;gc0U*YqoZs(=^4o- z)wMK<<4{7FP^qG`KhvW3!OEROHm_K3B3MB*1z7?xYwewmDfJNGX}C9V!}zUX#iH6$ zLUB%pyP{G5cQu8+r1%L%i5I3@o=kIv0)TS3l8Hb27=keme$D^JtJreM)(lX6)1>%t z4#c-6Ef+?DZ&o=oSdBRqhZ#=Cj0SxLTylz-P#=qn2l2=Ny1l4__v*?Nw~62GyBwWi zTqdYi+SGdGP&R)f-a|@${pMD2cry!^v9dq&&^;9?a{9Y;M~&eR3gauL>iOf;@@0DN z!U2j8iQdtdNIz*flIs5U)@j1QwyM(SUG5&{XA|Ni&24@=tTI_?8hI8G zJ%~D=sWlZ`l;SR%IrZO-&z6TGee-xa=n5vtn!RZ?Tl30w#nM~zT(Pz zYt4gcGY;*ZjjC}fI!2F61T*(iiJxO}OWo6#8EDxSyPseb>1KD%<9X?V`5o;H1O2{7 zF3Wgd$pdPGH@HsLy5X*k*t{xNb|-#6_v&JtSazz|x{qthwAYg{rk>3Ai{G1rG0Q3# zbtWumLWZVATS>%H;vT4y-)*!Ha@z6mn;126-OF!Ys6KxgMNnFWP;gD>hZ}ubM04Km z?=t>5(o7W>tsRx(Hsg(Xr3ar~ar#zl>q?k#KNM7cqv6o)@dxx-!#CBxjVn(@+1oN! zm;Bmi+X|{1mQW+z&VBUAZ#EFG+?!^;4mY+57nP(JX;$Sl`z)N&7HK@PL*;AoT8E%K zhlJnGFJ@HTYnrZ|JDSVCWsCdWXAACP1SMCn5dWDZy4C?nlC)a0zgCryRmg2NkjzRR zgJc%r0^nx;X-baQ;t{R9Y;QE26j_$qu7x;G#EjlJ(h)bEcV(4iBI#Gs?sq`?lvwkh z3Hz8pyts04Y*v5_)>mS_^6c?Dx!B5q3y*wG>If^d4m+(qndk)nuLllY-{|8-&Gix= zqwyhouUj{HgtGMy=*TwMI3B|$-xrRu{B9iH_WMpN`6oZm>dZS1OT+4&9SNN}fEPq) zqpsxUlDhgvYjnRA-s>W}pDmTO0W5OKHAEh%Em<73{fW8MZ%=|7JlOm*{(2f-&5Qr!OQAy z>sa>kCf%+BOVVeO&Juu;P{x6M^+@_nm@7bI9F*f_RV_m=!=ZB}tZ z?ivyQrj?b+rIB|iSRY@lo>{L}i4yYb_VkOI2n1h|o#5Z<@}!PaWjob&5-(LpW!B8` z_|GZ=(f6#)Y&EXzUoNE*CK5KLr!O;QZ&+^dZ;N1buDRm>?gRMQbm23cTde_0eM zb&M$9*zLba3fM5W&txf<4j{>%i&HPp-Ds)FMC%f8sTCwk1wS+h8dF>LCH7R~fZ0vi zd*nct^c~;I0w|Y8i2a@cx9Zw97^xp@j*Wli7~V`fYreeHvTUlisqy?m-%996p%E#lMjy2uV0_!msS{kQ`%A_YMXe2(e*Lx+OQ+PhweoT#3Rkm5%#1pmHnTd{ZNC0`IL=gk z<4-T+t9=B`-%{0DYrg|HYCORopm^4@2sq$$z5i5wj%meG)o{}pain(1cSc2aaYA^j zl~Od#BQw4^9$I0()~>IUyRUzi7~ti5Yu!0BCHK7!+s3J3@o83@VQQglLdP2NTYm6T zqH0@bNJ&)xqqq|1W7=hxing>C%MW+w`s_SULi;fdJN^jKAtg8L7dJk?eq!XAe)NaK z0qsYi04jF>`hA-LCdXXlt>$9&GSOxI+9Lk2wfE4~5Ez67;UEa}M5WT?C78(jRhZ?+ za8@45744_jp70D`zM^Dz51IcxyEf%MVxzuj_iMRNG4)S?{-7;mv0m%2E&~9i#2jEe zYzWFg93J#gx}VDv1{v2fy8|6BvAulRt3Yx{@g|sb`vEmhrJO45)@~%riFjYss!HE3 zT{Xhb>gQpO`nI70>f3!zibIn;jn_4m>`R_xar`b;=f+x+#Bm2hr~PegFy09qVpj;f zXr^LEDdXv}P@;9a!_&AhFA^ns!u@Krp-`W}C~@yWdqgQ%#)~dvbalsddqXK|R)mqy zeUhe=R2W;lO_4g_rv@x2YM%HQy09u_{!uHT^G;fRg3QwmTL$&A?m7R5liR>wzkfk6 zYTeh0X8TQ_38~Zx%o(d6&lG(4Mc?m4EFJ>Y9h4%Ej9HyK#Y2V*cXaV5Ln`hmoveD>?lVM*5Ix#CTUnP{NxN3rKimak+VDQ4)_(e;p_ZARZ{}b`{uXO4MUW^iP?1#!VYH8EQ zBl+6$zr!w|2yz)^7x_K5P4Z)& z<*%OIN;NmHN>*Hsyl<+0_a5TX)}OJG&Pzzop5ppiMC7pL`jed<>WMe6Nkxr(6Qyzv z6~T8(%#U&)e@|gWa)*&FdjDN z!ajU6imwA&cr7*0?invRbc~_x$=b+lxYt~Mv8!Z<PYP}7j_sI?pZYax|4rzC+`Z$2ybj;eCsT-NQl=7YEvlz4&t6Zuf2U!Yk%K!>S1teX z)k{#(csAmoGhMjuv)MhO>ehs_vEy`K8jUYzvMe9{1A<|``Af-aJ4w59vhQgZTc`ix z9rLY%^)S~heQMXhZk;0et$|Ge^EArR-Q`EseKYh(o+@e;-iKEBrPU689xqNz(%8Sj&1h z(2_~OIVYgo#&35Ot0@whI{2Fn+F#A$V*{U*>=*QG4xonCOjOToTpf|3rkStT@eZq% z*(-Y%1Uhd=5|5*1d!Q07R3sOj-h~gN*JO>qMZonHgge>BZ)Rh1N9ZFG*XZ0yW}_u0 zmyKjpO%vWWJ&>4Ra1!t1T4Wb)Hu_L>a&Swne%2|y&4eTXd;nF4SMo(o>(aP)-kJ?> zuKK-JrHHm&VcPWmh1;fK05D;v{(p~~{!_iIE1a1e$F@XxI-w)hyYbC*u(jT-;$UR-!~ zoZQ&k?jfn+`HN;wO}kF)tLI_(GZ^mq`C1L4pQ#JWg?rBk}!$iB2BUk1VG4UZY!@T+urXGE11 zKHFvwsr3(hnvb?tCGXzmFka!zQzHWYN36_l=|`kz3RdmsQ(fu@$Y1jUu1|*HOZWSYP(V@*5W9&giJG*0&;VIkK^2F@2X$DSJm@*v4Sz=R9RlZ z;b_y#`VX^ZD*oWY_5G8J6szKL(#t~*28HD`JF}L@gUs;sZd~i_9`ba&GetImOv|`G$FmZ zFUk*;%mGCzAXlxTX0N04DOUet$ZqN`n<7Y#n6$>PzXfYYN9xmRg&P3+6-ic?QoPnr2S8>(4R z>qQxldDF{PNuEj4yb*NJsh&{g{!Yy>!>`{L2vk{?UUo}lEp_W*0dLfxUOqpaRsv zVfh?u=rt+PZLjgCE|gywWHH{=vgk>SdMlq%U@h-gCRM(6BeTXFslA2Db+9jK&cHxD z?z0@g9QDG&RzN~N8m4)U*rgN{kJ8EQcK(*$`Z`9*%x|k7f2Y9FGRvXe_@Z5ndbYBO z)zZ#SrdAx)6_=_@eM2x6#Ie5okdSH{d(KBLwrYDmm?CDjF}d1P&JYanB*jNq%l(>%MHbs zW*pYMZHp8{_=F_ab1tV@mM|d}XMp$-)-KYIddMl>stsk&tzB=;*tG8As8Io)E;4`M z(Z~zcoJITiOu~~w;(v7)Zi*u~TX#gSvvT|bUPFnQhDpxYm zkV%fuOGUx{RmdL`^JT}o=ig#G?6N(0hW0Ejk=swLG119If(E>tkS))t7Ovpxp;bT= zHFl$hkl^}>;{e4;#Kn-u{4e|mSwhRjT|c^4ogdAaVJqsQUWu-wM}9@EnsgKtfvn3*i=QOsj4Wbn$tUeKo%!hhW;~W#!ts>$wD?bjdl1F=vnot9y?RlVY6YW@h|T zt@6l3Q`|d`Psh$84Nq>4;f*|#i~Yu^Y*H);Q+!uss=z(VF!Efy(G#L`@Du#@14z5W z+Qquj*iXlFMjaQY$-m4xe0oT0OC%dE7o)uhYs8?5&O#0NwdipM(TOC4skw=KwTxdk z*yUzec1*m|5@=ox6+Q5@MM%G689e0|?ee4_WfB=uPb_ozdC0b>sjz$Gygfg47-<*6 zm5tkTMejRIsBNMCAWZN1hG5_JZ+?$3Ly7_I!fOcVb-u)L2KiklM_POGX>P+ZC0Q2L zKGaQe(qgkZ{ZiyfhHqno3ZhipJc^g1hA#Z-0+%k4U1dF_?bL7PSIbAH1pUC3*@QDa za;s!AfUd}VF311cInEODfVRbvp`{9cxy_?khgo-4tMh(`o{5Xv@@boPgb5Y*SIwHI zodt+PY19w`7Z8=l2Ly&+tpDi^C?twCEo^JI{VdIwf&6|X;#oZ~I?HZ%EM73^L`%f_$KoQT=!~!>+$;P8n#)iU(g_YqqOp~KTPlsev=~r`)vlnbX9@bVb zm>5uSek;@e$&(J5^9JG)1s{`*lmbZ-BVMPb5~64Ja~o483t5EXvLxz6olg^g*buBu zodSg7?mO96A=snIvMhdO(ml_u!LLs%R=u7%t#zsW`BUT1%TzkK@~L=}sg+z-TfitW z?>?;6$E#90Yh{lJBMm2=UrU`ysw?@bbT(tzr%V-KVaCgO6CHa-KdE2+ze;}km1B}s zE@`bhP6Ae%@5=%Rxu5}N*oge_&_Q8mLDk(~1?d`2&WLibo%-xwnAO7iO=r*63Mf#h z(&1B+bXd0=jzVi)BZU@vUT3EvBT3}VGuQY@Jc6mk}1`wuCl^7F`NPsXv`1j3zr(Q4A+KeOBIh^hzi!RFDXIL$nq z?Oj%*^@Z#D^vJ%-m7W)7Q6BxrP35aT5~jY);+a>*)?_Zl(OK#)iXENVUGP5Q`At7l zx7T~Ts}=&C>u*IdEFuxiwoRBgZU3?-3+>E7Cv62)CQY_?ALM*l67S&nA95E%F(k5@ebIVB_dN^3t)eTG8OIhA zkXO(pc2w=EH%K&^*UNpQs=P9q-XB4}wU<}lCb@W0{wO}iE8(vCT@~_{vzI}7{|K^n zdYyaJ>>#OH!tNr;=a`rmKCs~`q_BTu2QsSl0vF8Jk|XOp6>~20QNeqc^;`7`y*o>L zqAI`@HAn_J!s7RYOLxWiO`5z?SNyfBTQn{!VZphHjcKJlzM=G~Rh3gv&l#?fE1Of! zJVW4j&`sz~WiCf31pBU8cpO-XE_y~C$DXH?OMsrK9?)4VP@fW0!qSsk|a&vvjj5NkGs3%k}M!jvT)pvm}1e?INpd z8oOvv^Ji7xrYD;tdYjv>5^M#_-lcb0H6GTo)L4u|8tt0z?TpyBoabz7l-Td-m!qLq4ZTls2gqOaqEZu6ywy#aStPVQU`>&hYdpec;Ih$@&-(fW2 zx__NPe=@9*!?o1$>0|AIsnO`soPo(F#@yUT2M>Fw1%baY6-;jDTujz~)8x1)e75$L z$+1&_gb$xqKq9z+5o5kTzqurJCtzNP)ul7G>}d38yb0ih4W$o4wBF#R{l7(Nmi-8=SjCuysym( zf9h(7aeqcr=v~)4wt`0Q?thQ;XCa19J?)ZPN@}6oe^@tiP0;g6?pw=(y&Pqh#c$2* zs2Y?TO6gU&NJ(C`CP|uX?;l_c%ASdgDmurUQ(8lFbcTp zsoAT=RffFY_x;v!+p#NN!pl0~_K4wPq9>DvO$f=gU zaV4L>HBnglSN-1Pz9m<}_o(N9Z#p^B87CFTPq~Gh$&Dn>CH>rK|7)uxuDk8ASV?L9 zxgsT}!GwpK#pNfR+&@*dxvoCydAy08^1$5gELcy(l!ty9>1}cK4!N$&_aIxB{B8n6 zcWJY>a&YKgPkoEnTTTbBKqP_*uo1Oyy!eU0qhU*n?L?_FGa31Q<#XO+`#N!$%lACE z(v9C(_9a;@C=R^o5b)gj_B6e1;i!p@^7W=biQyW`_%+JXO@F87U5gG5o{h?wc`v)l zB~5QdLn}}Ml7q{8=L*Gd9dwi>3%lFi0aD&xBK0Q^BA*dz*X2#-_kWYZV4i|S19Jo)PE#!VH^8quCc99Jl@-hHT3ez@fZegBR`A@zHc)j$Ukb2f8a=H^Iabuh zE9+lf?971e_HZHmnEd7xn`My#iZahNk1*||dw)nk!%Z^1J@JD2YERVI4W0)mC~v(z zq(+cxNe%5foYL^Cw4Xt?;&a^nb=ePoZWW(H!fqSCzU(p2$^DGKA#mmE^F0dkB8L{q zak4R61W|Qfqv8G`J~|62H)VzVLl<70oBg`BCAKxt&$HEbnwNdrzai{|)zkt-BF#Cq z>jL>@_3LT!1dp1P&f{x`teNw`Z@n)+^1n9BhD}U%)yzI>Q~Y1eo4e<>@35$ed!5wv zT(Vxab#xo~Cnj?**4)&bj`-9h$&QCOnoj&PV6zL8wXJaFdp1I=?ep_oj%ATBS zUo&Fvk%XD6mgV!*+ilD8IAP?AR;3|sUku8aHclL-BYimc5swwoEiSh2*-Xq`tq^)& zeqoo=Q>(yN&%&k^R+h5^+iiJV z+n!7n#)_9--qu7lYR%~7ZQm1PQ!lP8l(%E=nP( zpI)ak-Fz&4Q7N!c?xbDK4GiAr>vyh;fKKFeO6T79%*ilgm`~)ozqQ%2E=!qS=jsWn z$c%~RkidfFM* zp;07%25JAa|Lv>A$mzI*7$^NF~7B8ues!4 zA#tzTB0;q|n(le4_Op4?-F8p@Pi5~`b_(yk_<{K;CZx=!?6#d&)D?xG<~h=%h^zyzFL8qW)Ep<$1tD zh_mJkoc^TpPFyWPf=BAPI@13qYbL;WG4p{A?hK2&LP`URNzswa&Ck)Qnrsu&lOhw< z3*X0dJ5{a+gU&8X;PcjF%SzyfzO$u{-VQIA_uz_K`fgJB@e8$kP$Z>#>6VCBpop0Q zA0=$`dWX&X`Bi4{WgVt)v!5x9-&jRd)Y-S3hF^v)QF1Bgk_`#`Jgy@eY0=hC80*0A zYWF_6Gu_;)J|=kbXmRS`yRI`Sbe6GW_`YvSk}blX&Do-y&BqIc9C63C{Azx#`v~ng zd6LKa$jl?P72BSgaN#%^-74N4ML~al@u!{S1`hA>ykdUtnPD>*vlj1%z;~XNzf3!% zZ;!`@yxXO5OjJFi(oD08?e}-Z;T329g(1cp&O`Av)g88p zxl-MB&-d!-9>9>d>@mYqGnx1KQr|S~Pt-8-DeP)=&)Iw8P!y->hVbxO+E(W3V6{z= z*@WWTV1x5Uliw=6wuA3OzJ7U4B(D#gqJ{L1E#&DS8~Zxbvls>@VqaPMCXRU}@FHot z0_*n6i&HQ7R9v)7Ma`lv^9#T07t(P#-VI06($?<&$F8NlewUrj_Ad9JlT=ETx~51~ zo>(`(R3ASn-sRl-7QNiNj&tBwmjOYYQ>a)DuUTabSYA zB$FlmNf(>okU=T$MfXN!^H!HqI*W`&7lMmoO!5_hQtgh9!j50Yz0?KM2?iql-TmGj z=|@7(HWkoUD8^x5-5R_?;9P7Z2OdpU^RvBXzNzfP%@J?Q$f^{i6QLl`J9GIR%T(m- zS^P8u68yE_>eUO)(|^F%LmU%4w{+H*!B;-p{JK^$i?XTUTZwB-1p)-En?r9!g&rqz ze^jxT?k#Rp{KS7dXh(({|0t)y^VNW;`5v-D)G)TO>tsN~QN*`E#snbjT2oe$h zP~&DwroM`3z)7PdjlFW3q&805UB)2nh+Io_F70)x2(&~7#HdNO!)!DCbJNM;G>AwRU-1gC_ z)h`P-ic%f5SlcjyKLeS=HzSn27AvuCF>yI!F|6m7zLGArRQ+Q0;Fn_XC@RVSk88f5 zNWad%I5}TJ>&KN@KF{i}LtdNS86`7}7+e0miM7)vx6ezLjDRZy;-`jKt}AQVf0lPB zUOak&qf^o~tvO06DJ$V_N7dOwqPTj!=3HTQwXm)x6~Fa4sn1Qfx{k`SBx`;#(OF;d zGW0KItzJD;ah2tHLCeQr$NbQp1e^cI-dje+*=*~g4Fm`zxCJLja0tO&f)m`G;7)L8 zJcQs065JgcX$Te^LU0SNjceoXa9_T?#$9{gbI<>C##sHQ6S`)3&8k^7pJ%E`2d$6W zCS)$6-Sr~!b}Fjuu2RGx>6Ow~#0=ZjjdSk@)IL_iF>!9mML)f5FQuD!u|t*{IX9ZH zbL)~~y{~mQfE;LlY{UxD0$hE)3u`mIzH>e<^4e{kvkzFYo%f zAk#|gW?*{mpB7f=X3lqTj}755r|3;D6qFG$V$%_^W_`=I`svZn|9~637A-M)oPizv z#$-D{@T%P>#=!*;C%Uv#-AtC2`L#~%8w{-^x zKeOt2i}oHRZ=ZMg6TnXDLC;cxv|hjHejIYIq5rM}S&9lM2gMk=1Lr#7gb1?exq8pV zfUDih#}|)+58AEQ15QT5*F=JA&V9o}BIf(4xdiK>M2t(%Ahj$Gi?QCGzvdOsS6?Vh zq`RSPjK}hP6Bv@q=mYZ}@1(xE=9=3#GI)(7vp~3>JJ%`3Ft=%8g;q*;sJ7>nZZ2QW z9xgro=H6OspU75I^4Z)pQFngyY!4NHP_~aA07!v@Bm1w1Lp3qGM=b7c{3`CqZ% z`GKvvd~9q^7Ov-_$6)n%x*ULO{yC&*fWa^+R!HFhR>MMmUmoIP%MJm?5= z1IslBp4Q~@?q#{=r_CHJw4R^a8yCwb?>j|8NjxQVL>b-XRnlz}`<7X0UZo{TMNaG} zen>i6T%dqF%%?+=XIYOpIubEIF8#PvBJ`E9*h-t*e_0Z+`17xU#@WIP$unq+XN7I7 z?rR?7TRcv)^8HisF(OJkQE0&K z74PAF*W}n}7q9c5-Gu;8T6qM#`5iK{OQE5TJ*a+(idPITaJy=KU>+(r_{s&W*_$S7 zs+_VH|I368Qj5Wez`)5t`+3B+_4lxUiyPstHO000z-B=3SP45`+RyP4 z2&Yd7`%o)(81{Lgn;fn2Pk#8(X0EnqmB+dQ=bQ14+->p!G#%V|D`3W$)UHzwS;=Y5 zvpGpaMtJ6`djv{ZO7GrQs++l}|C)dPNjIUri^{P1RYjqPf|8^is_A=SkO{{U^A;=M zH2B3t0A4rcY&F#em~X(vs9*+xOvAV=kyEnX>oI3^#h$d)CK~!p65ys{T2Fal!>|sk zyc1Wo{xziDi9p2#1r`C{?o(I5eDng+2WqnuPKt*rI4@y8lwIPXKjb$765B0 z0-v;a|MqHbY?_+HaC3*;Sl(v4!0NL8tU!vQsfKu`hHhsxQ7dG|1{UkeZ^Py9q_>gE z7xV1>WoT}6?Hu_uB26Mmln!E`HQ@HmMIj!+q9n8BeM(ck&@$sL$Q6+>yf&es@Ka#e zhFX3u`18+z9S@}p_+Q6A#x=1%uR9-vE%pvcC?ZYHrUNcIU3XLqJ_zS78}0mQ%YAH# zvUbZHqbf& zU7l>!`Pis8;EY#yn^Ps2Ay0!2PseTLz7&ik5dypsoCC(izBX{!^iC8tBoQpk*^fdK zlHIDNMcxhUM?wRx<^yg!MUSTMQ}+&|f7^!88qUA=Q_UUC?ufmUcGA><_Hm5$49ODp zL|HNc&%L9G{yna0Sc4ony_><#CP-eK z&NM#icKUN-ZX%;r5*vZV{Ty%LAp^HfB}fZ&>bQD2aD8R^O?_IgWgvbNX}Bwi4r_Yj zVhfU#j*-{YYETM|Ol@}n2B}@>#3}3h?T|1VP=$xp=nF0yc)YU97D52N6*uIX~qk=Y=7fI46j96W+TkCWNuCCRg=RS@GK5Vq9ncb zX}J6QHyyKk)#uFZRhXU?v!zc8yT}{waLK65OL}c#0(ZZ!k1SpT9rm`w55zk6HD7a$ zE>7vkq?>ZBKdchac#+Jpq?kJ<}K!(xp$dM&BFE(qCFda2OYXfdX?;oYoaNP+UQxEy>Lu;KG_X=CS?JGYXDvdBx-XARaoC!kO+6LbuW$55L z{(VD|AWNWLQjTwEqC)OeV~iUkzz+xfh+PnhPn((8O1z+HW#hvIRrK_^G9S{XXt|GnU=*|Z*AB%I{AIp>X?S5eRvbIvVM>#g_qqA($c_0z;~v0 zd&WoNutzl&0IO2H+QNn98}b1-i(<1c)fVjnj!u$N0_gZ1gr;MFJ!_ru;`rFnZFZ6C zE*0Rq z-fq?K`=x|&TuC$0%C*W=luAgraYQ3SdR+iFSZ0+#ut&tz7~zhdk+~FhrX4{MCI_I+ zX1trCrhrNJ)bNm#rwfGlW<@Qwew)303ei9H3uXzBqImYM8^#Iv%Q>IREfh^r%)Mwj zv-aND0{2QKy-PbG6&INIl4sNv&mFb8+;EmczV0?`S+gEbeZyU|;|sU!?e(YqPU9Bf z{@#XS{|g3WIM!PSxpqZp1-5o^s^@P+__^(HE0lRL#0ZVJY63!Ar3VUBnFpN5Q>LJy z_Bu4=$S#LnJ~ z$t#v9<1K>2qsC_E%$8G73>TmcjND^2^Yg?yY|82Nwj}iJh?>;Jc}5^d3llnTUFw6|b19;?X{(Gl!mFI<*Czg2t`xbwA5T6r z{Z*z68^F82M$5dyDEQ3vF0U$|O9P*2!Z+)rS-}4dR8?J|MH#1xM~&k*OL7gCHcZgC z?ag!;9G?ZDo$$IbiUI(^R5FgKg1jZzNaQ1A-X-C02$CeUHVxjp;k)#V1J6J_8c;rt zUC5az_mH@Tl+(6l$cp} z*HWsVPv%Vhl${j1Y;~q66h0_NMAVaWF>*|Oy?r%~y7tb7rvFf4TP-8akGgUN<<6ww zxL&qF2eUUIdY8Qdak;uaXG$<`Ri-l4>#X_3V!X2v*hT} z=0pikiJuV^~<8X30HQq?ZNU zn>#<>+oD#CTCb(`rUgKUXqLQ9rnr_CK&OiAl`?d39`2qL*@+FdKKs!Bi-h|2H=#~B z0h|?so@T!mzsz-e&-*(cci+%2H8p$RI<8NyNMjN3knSSSn*4oudw8w7e$1Yore2l- zO&CQySTEt*LBHog8pD=|At`eO6s-R;HA$LfL%;+zkmXqOWPIk?wHpQa<}bDtIw(eB zJ(td=&6^@LP2o^pS%X&FPEa)QcCUcvZ6EIduITeTk<7CehC64Pez5EwUeYnBq}Th$ zee70an78__{c*R$W!6u!m`qCW=Reo6?t}{F``nR^E#n;eb`I^7+b*%yRnp~UZ0>l% z*dYLh=d4)6QX6Uuyj6{C7UUuE+#|>myNvoTZwMsidlr;QM!GyC-j9klaM<@^*l!hj zD>=i8uuQKaO1~-*U9Mhf)$htF2<;O|wjQ+ZaalDRwR9m@oge#_-Vqy1hG}(@ov0ht zW=o`7-@aG9b!*a-Th#{`fF%LVhwMTD{-6N#w_-$kq+a43E=-|kYVM1yv*bwThOi^ADRTmE1@*kdWuP*X&N8pAw-u`r5>V?@3i6&0~-s9*M zZaN8cW*e}qtFWaFG#o!(Ud+aGzlIMr9?Y>DfM3O`AI#B(?uC>%(7ud_l*m*?W4P&K z17Ctd%Jw9&Z<8cp#txmUK#t{XafU2EM1&2!g`r(DimJ5M{B2`$`r?cS(uy-#V;PFe zsWf^FtnH2bd%v9RpcxeaBgHQ-t!iSq{jtqYWSE!|B!!+FiDDc&-hji+uT~LPXRQG* z>%F-4eVaCb0%d1Fch5wbCFjQ%yv@ND{7FIU2j6Q%%5;gpfVTfUf-V zY+}nG$;wqY(0pBlXrH_fT08>0R;%~R?jzTw%VDOvEFw}FMIxzPTJj_XB;P}Y{omIg zS}OzBqHPF(hxyRbyGF47`R725S6mx5&DBgKdQJ#onys#*r)En7CE~YDZ*%(s&!nr% zW#m$=43EA+#l{vC_9KzT{tlhIf0NDl@w#cG!6Ns@eR2SR_4V^AI<;w7yu<^jU|bs) zP!ZKS8w?lJTSPz&F>3}~S2y9_l3aS1T~zvE(zg##Yj%KD;@OLxV8MhvQU`y{F(;IZ z;lok@eNIK(ngT{GFuOnoiJS^7US{m%o;9LYhBt5Ks!jT34LT5WjLbcT(KY56Wp0hh z9@!xz%Q%{^aFIvzC7_|j)oISvcPmcXA%bY-E-y)hb8Ycs3>QeXBT#sGiQT`MAe1o% zG!*|hjBSvz5_KC>xuS(gcWECVu9Gtimrf=k4c(?or!vwJMjOvn*z5QNDj{&!B?K&@eHSyLx z)C}z2>XGMmR{>yO7%KCSyw{qQQUKQS@Ph!Fzq2Y>gLGfR2W`;kP$J)^p^0&M_e+WT zQMFNsY;}Ed?~}?4hRhV~-XoMO?WweFie5FpHdO=7{1lx2Q$TE-!k`|GkR3yEdos!x zc)iEj?+uf|xYv&t(^)jRmT{9^KENbY#) zDXZc+E`s^eywL;N#ZUsDk(c^9RR~PSF?4~kG?FjSy@d8@Z*^&D)lDMlbOn3<+4HIwPq#KE z^U~DyEj7}-2iOC~Uh{p$664a+q&VMY9VO0R{{r~anF|p4jm6z+lJr2Pf3PQV`>!RR zLo3QWuudi$f7}J8*83^mHM{44-~O2)N;3-bK8sLC_{9zvP~n;+rA930R}P%}si)Gw zb!KvBd|$W?ussDz8d#rF{y@|T;V185$w=h+ld`ipvFG%vX;>|RD z(X9ShYupeM?+_zz!>07ovOK0P5mUN@l8v!uQiJ#=>c{sJ;peY0u@+NaO6fVXH{ZIv zes}7}VH~cf0x+njjwSFxq=UFIY$Gi>5f};qPc&)a{G4sDA3IJ)F-bI8w0yMO_&FQR z25F=&-Ka6wj58O;`@C%V{lw~fZ|Cytam~0bxvv^bt7^TY9l!W|3-*r|{f?v4@LwW< zR*Q_2zH@=fc2_f98wITVTL3}@5zu@>xj_wdKr^i6$5|;$U>GSpt7biGR2O_hN_Ker zjh?1kOD5>IYKFskh}-3U<*z}QrXh|p{f_bZ{TRo%**L_*PKau;Wu{8)LDx0yvw+~L zoHzn#{zOPWiEa+@~SDB9!}nc8h~K~E*toT99n-9P;^ zMVR2qO8|=dH^Z*Ab97E5X)ACjI&>lwIiDE=;6_kQ>6MC>&eo-~$cNeSB|Dm=ae7m_Y_F`$EYCdRNBYYn?@8@Ta()_(Y#;QNa&jx_n z(OjY$R?9Tl->ojUr1SiErjZ&FPYk${e`CN4TqRTs)+yyXi3cZsq_q}CI!%pP$`$&n zAF%404J%P-c0$nYV(mC>Z%>NmN62XN!J6r>DpEf;PIE6%?&2^4XaO3%RNqg(14XIc zbjT4ejvIY`PL(v44p4dAC)tw}_`g3-UB(tKeiWAIuNW`bT$*d!!GGj32BgF{2HklUhniMXwI zsr0zc-(AJVvp<;l=ew_C^@2S@h;fXl;BJ{w9E~-IA$i=8$Z3MOutf%Pe?@@C1fVlrKTn-^Zr__tl(x``fb( zi2!o}VP=4zUA9H~`)oWS?Lqb2-OBl}!;jw>2_VF=m`Hh_t^Mi5kMCDpV*C;!4woxE z>`ILdu|D)vz_MZLdSocUc17XEt*|RSENS2Lw!znN>n33>#*js=mUn=DUhfTvaqTVe zHX;3EUl_7etZGHd5@T!Ys(O3=TIY>z?T<2K{@iARai$Pj{tvIUODSIY=hNb3K(r*# zsrK8xXm594(N^!IMvIl9mS_2x&U zqARtLs8AXM%ubG*AVgd^jb^Fh>)}6@5k7}orLFNI%|9Yu>vjHp#i^oOMiz%I94D|ep+jfs($h41Y0+1<|!o3ac#+HULM z78^>eSA15qVVD_cnq<*wE24Y=@h-}}z$ilukF=S;n4afqtl6Z(vj{7@hV2wK&lzk( zZYH?^U3}?%DkNR`0&3&d`bYM(wAI`Zv?<$J?=M}Pv`4HO<2SzF6l$p-AEq)k+sh;1 z2?(GV3zzDHnuAmX^lk`W6A<#GZpIim)%CMfQcBkoPPbre&qdVQ(-ZBZ`frS!OSVy= zOXJTe)-M%4*n0UXN1-NQs;7~aI8x0NW@l~?OLrWk+R}&7F(o5SJ09(VKw?7cJewt= zN+=QQa;4_O$}+dZ=5S?z@W>+7U?B~EVQNdM?x(29j7p1&x%}AE+4;mB`&M_(j_zzy zMYdM|VYM*=jx3cI>Tp@Oe*xL##t|O$lIfqyB)gbfvKek<3%gltM@Gyz1+b>3bPmP9 zk{a8x7e`XFS}PxA*v^JqT}qu!cCD3eE~ZaCQ$8$ypojs7Z{`MD$}*t;={uQDvtY*X zIZ~qfJ3k^uI`|_wDQt5Gp$zt;twWlJ*@SL20ss7@87WjV(Q)7_}A} zdI>aEYWIGcA#h*+x#RJup)m=WFfs<_)dihu^qAGl`rl+|8@Y)DCuBTn$No6&Z9xKg z36|$A?INqez~u=fDZw-+y!bw;XVw>y<;}Dg--`D+1a47Ys)j}yRcqWhf=2-gq@C?a z9Fvk`lR;#>nEgrJw-9BA1Ji;%cl+3>S%N)rk3SF)Zsqk$NS@$cc9-9K8#{^CMKzBi zZc^XihvZ&!wcb0Dh(B7FUR(8y=ecU6NO^HAT z5FWKmCrzI`pnwwO;7hF;PmjmOv?YF_UpB=gUd+2y7XGbFHJyKDYivd9BIEnaXw);8 zQIpg8MQ4Lc3@=&I&n|Bp^{@!PEn=(U$`>4?TraQ1fA`x^C4u zeF=mID=t7@{KgD0RZ-#QRTTqKa8nZXvL@fqtZC1Zh!%%`aee>ZNN2?0pV z^HJ`&xCE?I==Wo45)q_AHrB)$-5OL@r8k^?5pw${G<05n

fjymlKchg=fDp|-X< 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

{^^0j?M8^eG4VuL zy)|jgzA!M4lz5ljLV-WoKjM zV`pXK<>X;!)%_>OpWF&2>K5AMo;DEW)*7Pw0wK#VA<6O<-kwfCbJu@aQ*<)_-y2d< zm(pgIcDJ`THF0!=Xu@>r);6x>khinBCB!l#xuyls72*mx2QwQd8y6otHy0B-GdB|( zGbbxEWV%KI+NzL8V*22u~U+${gxYLr})-5nfV$+`Y`2a(*(+#q!d(b|QD$yv1iNciL& zkPk$4SF`c4AZOzyXOWd8*AwL9;A7|E;IU-qHs!VCurTA~k4gS*vx0xvvG>tS(B?+nmDrzhm zd6EFM>(Wa4i~152_K?bBYFO> fjf?#M_63prO@MA*kQRi@&c=;QO)aG?jr>0VpL2Gx literal 0 HcmV?d00001 diff --git a/projects/2021/groupK_burgers_openmp/branch-master/CMakeLists.txt b/projects/2021/groupK_burgers_openmp/branch-master/CMakeLists.txt new file mode 100644 index 00000000..20635e44 --- /dev/null +++ b/projects/2021/groupK_burgers_openmp/branch-master/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.14) +project(HPWCProject) + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + +include(FetchContent) + +find_package(Eigen3 3.4 QUIET) +if(NOT EIGEN_FOUND) + FetchContent_Declare( + Eigen + GIT_REPOSITORY https://gitlab.com/libeigen/eigen + GIT_TAG 3.4 + ) + FetchContent_MakeAvailable(Eigen) +endif() + +FetchContent_Declare( + ProgramOptionsHxx + GIT_REPOSITORY https://github.com/Fytch/ProgramOptions.hxx +) +FetchContent_MakeAvailable(ProgramOptionsHxx) + +add_executable(HPWCProject main.cpp) +target_link_libraries(HPWCProject Eigen3::Eigen ProgramOptionsHxx) diff --git a/projects/2021/groupK_burgers_openmp/branch-master/main.cpp b/projects/2021/groupK_burgers_openmp/branch-master/main.cpp new file mode 100644 index 00000000..67a61360 --- /dev/null +++ b/projects/2021/groupK_burgers_openmp/branch-master/main.cpp @@ -0,0 +1,495 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using Scalar = double; +using TemplateParamScalar = +#if __cpp_nontype_template_args >= 201911 + Scalar +#else + long int +#endif +; +// using Vector3 = Eigen::Matrix; +using Vector = Eigen::Matrix; +using Vector2 = Eigen::Matrix; +using Matrix = Eigen::Matrix; + +template +concept Tensoroid = true; // CBA +template +concept Matrixoid = requires(T const& m) { + { m(0, 0) } -> std::convertible_to; + { m.rows() } -> std::integral; + { m.cols() } -> std::integral; + // more stuff but CBA +}; +template +concept Vectoroid = requires(T const& v) { + { v[0] } -> std::convertible_to; + // more stuff but CBA +}; + +namespace Detail { + template + struct IsEigenSequence : std::false_type {}; + template + struct IsEigenSequence> : std::true_type {}; +} +template +concept Sequenceoid = Detail::IsEigenSequence::value; + +template +[[nodiscard]] constexpr T sq(T const& x) { + return x * x; +} +[[nodiscard]] constexpr auto absi(std::signed_integral auto x) noexcept { + assert(x != std::numeric_limits::min()); + return x < 0 ? -x : x; +} +[[nodiscard]] constexpr auto absi(std::unsigned_integral auto x) noexcept { + return x; +} +[[nodiscard]] constexpr unsigned exp2i(unsigned x) noexcept { + assert(x < std::numeric_limits::digits); + return 1<; + +template +struct ScopeGuard { + Invocable invocable; + [[nodiscard]] explicit constexpr ScopeGuard(Invocable&& invocable) noexcept(std::is_nothrow_move_constructible_v) : invocable(std::move(invocable)) {} + [[nodiscard]] explicit constexpr ScopeGuard(Invocable const& invocable) noexcept(std::is_nothrow_copy_constructible_v) : invocable(invocable) {} + constexpr ~ScopeGuard() noexcept(std::is_nothrow_invocable_v) { invocable(); } +}; + +template +struct Rank1Slice { + Tensor* tensor; + std::array position; + + [[nodiscard]] constexpr Rank1Slice(Tensor& tensor, std::convertible_to auto const&... indices) + : tensor(std::addressof(tensor)), position{ indices... } { + static_assert(sizeof...(indices) == ranks); + } + + // not multi-thread friendly + [[nodiscard]] constexpr decltype(auto) operator[](IndexType i) const { + assert(tensor); + const_cast(this)->position[slicedRank] += i; + const ScopeGuard restore([this, i]{ const_cast(this)->position[slicedRank] -= i; }); + return std::apply(*tensor, position); + } +}; +template +[[nodiscard]] constexpr auto rank1Slice(Tensoroid auto& tensor, std::integral auto const&... indices) { + return Rank1Slice, sizeof...(indices), slicedRank, std::common_type_t...>>(tensor, indices...); +} + +template typename F, typename I, typename... Args> +struct FoldR; +template typename F, typename I, typename T> +struct FoldR : std::type_identity::type> {}; +template typename F, typename I, typename T, typename U, typename... Tail> +struct FoldR : std::type_identity::type>::type> {}; + +template +struct IndexCoeffPair { + static constexpr auto index = index_; + static constexpr auto factor = factor_; +}; +template +struct IsIndexCoeffPair : std::false_type {}; +template +struct IsIndexCoeffPair> : std::true_type {}; +template +concept IndexCoeff = IsIndexCoeffPair::value; + +template +struct IndexMin : std::type_identity> {}; +template +struct IndexMax : std::type_identity Rhs::index), Lhs, Rhs>> {}; + +enum class StencilType { asymmetric, symmetric, antisymmetric }; +template +struct Stencil /* 1D only */ { + static constexpr auto min_index = FoldR::max(), {}>, Pairs...>::type::index; + static constexpr auto max_index = FoldR::min(), {}>, Pairs...>::type::index; + + static constexpr auto left = type == StencilType::asymmetric ? min_index : -std::max(absi(min_index), max_index); + static constexpr auto right = type == StencilType::asymmetric ? max_index : std::max(absi(min_index), max_index); + static constexpr auto margin = sizeof...(Pairs) > 0 ? std::max(absi(left), right) : 0; + + [[nodiscard]] static constexpr auto apply(Vectoroid auto&& vector) { + switch(type) { + case StencilType::asymmetric: + return ((Pairs::factor * vector[Pairs::index]) + ...); + case StencilType::symmetric: + return ((Pairs::factor * (Pairs::index ? vector[Pairs::index] + vector[-Pairs::index] : vector[Pairs::index])) + ...); + case StencilType::antisymmetric: + return ((Pairs::factor * (Pairs::index ? vector[Pairs::index] - vector[-Pairs::index] : vector[Pairs::index])) + ...); + }; + } +}; + +class VectorField2 { + Matrix uv[2]; + +public: + [[nodiscard]] VectorField2() = default; + [[nodiscard]] explicit VectorField2(Eigen::Index rows, Eigen::Index cols) + : uv{ Matrix(rows, cols), Matrix(rows, cols) } { + } + [[nodiscard]] explicit VectorField2(Eigen::Index rows, Eigen::Index cols, Scalar fill) + : uv{ Matrix::Constant(rows, cols, fill), Matrix::Constant(rows, cols, fill) } { + } + + [[nodiscard]] constexpr Matrix const& operator[](int i) const noexcept { assert(0 <= i && i < 2); return uv[i]; } + [[nodiscard]] constexpr Matrix & operator[](int i) noexcept { assert(0 <= i && i < 2); return uv[i]; } + + [[nodiscard]] constexpr Eigen::Index rows() const noexcept { return uv[0].rows(); } + [[nodiscard]] constexpr Eigen::Index cols() const noexcept { return uv[0].cols(); } +}; + +using AdvectionStencil1 = Stencil, + IndexCoeffPair<2, TemplateParamScalar(- 9)>, + IndexCoeffPair<3, TemplateParamScalar( 1)>>; +using AdvectionStencil2 = Stencil, + IndexCoeffPair<1, TemplateParamScalar( 15)>, + IndexCoeffPair<2, TemplateParamScalar(- 6)>, + IndexCoeffPair<3, TemplateParamScalar( 1)>>; + +using DiffusionStencil = Stencil, + IndexCoeffPair<1, TemplateParamScalar( 16)>, + IndexCoeffPair<2, TemplateParamScalar(- 1)>>; + +constexpr int margin = std::max({ AdvectionStencil1::margin, AdvectionStencil2::margin, DiffusionStencil::margin }); + +[[nodiscard]] constexpr Scalar advection(Scalar d, Scalar w, Vectoroid auto const& phiSlice) { + return + ( w * AdvectionStencil1::apply(phiSlice) + - std::abs(w) * AdvectionStencil2::apply(phiSlice)) / (60 * d); +} +template +void advection(Vectoroid auto const& d, Matrixoid auto const& w, Matrixoid auto const& phi, Matrixoid auto& out, std::invocable auto assignment) { + const int nx = w.cols(), ny = w.rows(); + assert(phi.cols() == nx && phi.rows() == ny); + assert(out.cols() == nx && out.rows() == ny); + // #pragma omp parallel for schedule(static) + for(int x = margin; x < nx - margin; ++x) + for(int y = margin; y < ny - margin; ++y) + assignment(out(y, x), advection(d[advectRank], w(y, x), rank1Slice(phi, y, x))); +} +void advection(Vectoroid auto const& d, VectorField2 const& uv, VectorField2& adv) { + advection<0>(d, uv[0], uv[0], adv[0], [](Scalar& lhs, Scalar rhs) constexpr noexcept { lhs = rhs; }); + advection<1>(d, uv[1], uv[0], adv[0], [](Scalar& lhs, Scalar rhs) constexpr noexcept { lhs += rhs; }); + + advection<0>(d, uv[0], uv[1], adv[1], [](Scalar& lhs, Scalar rhs) constexpr noexcept { lhs = rhs; }); + advection<1>(d, uv[1], uv[1], adv[1], [](Scalar& lhs, Scalar rhs) constexpr noexcept { lhs += rhs; }); +} + +[[nodiscard]] constexpr Scalar diffusion(Scalar d, Vectoroid auto const& phiSlice) { + return 1 / (12 * sq(d)) * DiffusionStencil::apply(phiSlice); +} +template +void diffusion(Vectoroid auto const& d, Matrixoid auto const& phi, Matrixoid auto& out, std::invocable auto assignment) { + const int nx = phi.cols(), ny = phi.rows(); + assert(out.cols() == nx && out.rows() == ny); + // #pragma omp parallel for schedule(static) + for(int x = margin; x < nx - margin; ++x) + for(int y = margin; y < ny - margin; ++y) + assignment(out(y, x), diffusion(d[diffuseRank], rank1Slice(phi, y, x))); +} +void diffusion(Vectoroid auto const& d, VectorField2 const& uv, VectorField2& diff) { + diffusion<0>(d, uv[0], diff[0], [](Scalar& lhs, Scalar rhs) constexpr noexcept { lhs = rhs; }); + diffusion<1>(d, uv[0], diff[0], [](Scalar& lhs, Scalar rhs) constexpr noexcept { lhs += rhs; }); + + diffusion<0>(d, uv[1], diff[1], [](Scalar& lhs, Scalar rhs) constexpr noexcept { lhs = rhs; }); + diffusion<1>(d, uv[1], diff[1], [](Scalar& lhs, Scalar rhs) constexpr noexcept { lhs += rhs; }); +} + +void rk_stage( + Scalar mu, + VectorField2 const& in_now, + VectorField2 const& in_tmp, + VectorField2& out, + VectorField2& adv, + VectorField2& diff, + Scalar dt, + Vectoroid auto const& d +) { + advection(d, in_tmp, adv); + diffusion(d, in_tmp, diff); + out[0] = in_now[0] + dt * (-adv[0] + mu * diff[0]); + out[1] = in_now[1] + dt * (-adv[1] + mu * diff[1]); +} + +enum UseCase { zhao, hopf_cole }; + +[[nodiscard]] constexpr VectorField2 solution_factory(UseCase useCase, Scalar mu, Scalar t, Matrixoid auto const& x, Matrixoid auto const& y, Sequenceoid auto slice_x, Sequenceoid auto slice_y) { + const int mi = slice_x.size() ? slice_x[slice_x.size() - 1] - slice_x[0] + 1 : 0; + const int mj = slice_y.size() ? slice_y[slice_y.size() - 1] - slice_y[0] + 1 : 0; + + const Matrixoid auto x2d = x(slice_x).replicate(1, mj); + const Matrixoid auto y2d = y(slice_y).transpose().replicate(mi, 1); + + const int nx = x2d.cols(), ny = x2d.rows(); + assert(y2d.cols() == nx && y2d.rows() == ny); + + using std::exp; + VectorField2 result; + switch(useCase) { + case zhao: + result[0] = -4 * mu * pi * exp(-5 * sq(pi) * mu * t) * (2 * pi * x2d).array().cos() * (pi * y2d).array().sin() / (2 + exp(-5 * sq(pi) * mu * t) * (2 * pi * x2d).array().sin() * (pi * y2d).array().sin()); + result[1] = -2 * mu * pi * exp(-5 * sq(pi) * mu * t) * (2 * pi * x2d).array().sin() * (pi * y2d).array().cos() / (2 + exp(-5 * sq(pi) * mu * t) * (2 * pi * x2d).array().sin() * (pi * y2d).array().sin()); + break; + case hopf_cole: + result[0] = 0.75 - 1 / (4 * (1 + (-Matrix::Constant(x2d.rows(), x2d.cols(), t) - 4 * x2d + 4 * y2d).array().exp() / (32 * mu))); + result[1] = 0.75 + 1 / (4 * (1 + (-Matrix::Constant(x2d.rows(), x2d.cols(), t) - 4 * x2d + 4 * y2d).array().exp() / (32 * mu))); + break; + default: + assert(false); + } + return result; +} +[[nodiscard]] constexpr decltype(auto) solution_factory(UseCase useCase, Scalar mu, Scalar t, Matrixoid auto const& x, Matrixoid auto const& y) { + return solution_factory(useCase, mu, t, x, y, Eigen::seq(0, x.size() - 1), Eigen::seq(0, y.size() - 1)); +} + +[[nodiscard]] constexpr VectorField2 initial_solution(UseCase useCase, Scalar mu, Matrixoid auto const& x, Matrixoid auto const& y) { + return solution_factory(useCase, mu, 0, x, y); +} + +void enforce_boundary_conditions(UseCase useCase, Scalar mu, Scalar t, Matrixoid auto const& x, Matrixoid auto const& y, VectorField2& uv) { + const int nx = x.size(), ny = y.size(); + + { + auto slice_x = Eigen::seq(0, margin - 1); + auto slice_y = Eigen::seq(0, ny - 1); + VectorField2 uv_ex = solution_factory(useCase, mu, t, x, y, slice_x, slice_y); + uv[0](slice_x, slice_y) = std::move(uv_ex[0]); + uv[1](slice_x, slice_y) = std::move(uv_ex[1]); + } + { + auto slice_x = Eigen::seq(nx - margin, nx - 1); + auto slice_y = Eigen::seq(0, ny - 1); + VectorField2 uv_ex = solution_factory(useCase, mu, t, x, y, slice_x, slice_y); + uv[0](slice_x, slice_y) = std::move(uv_ex[0]); + uv[1](slice_x, slice_y) = std::move(uv_ex[1]); + } + { + auto slice_x = Eigen::seq(margin, nx - margin - 1); + auto slice_y = Eigen::seq(0, margin - 1); + VectorField2 uv_ex = solution_factory(useCase, mu, t, x, y, slice_x, slice_y); + uv[0](slice_x, slice_y) = std::move(uv_ex[0]); + uv[1](slice_x, slice_y) = std::move(uv_ex[1]); + } + { + auto slice_x = Eigen::seq(margin, nx - margin - 1); + auto slice_y = Eigen::seq(ny - margin, ny - 1); + VectorField2 uv_ex = solution_factory(useCase, mu, t, x, y, slice_x, slice_y); + uv[0](slice_x, slice_y) = std::move(uv_ex[0]); + uv[1](slice_x, slice_y) = std::move(uv_ex[1]); + } +} + +// TODO: only a makeshift because my stdlib doesn't implement this +template +std::basic_ostream& operator<<(std::basic_ostream& os, std::chrono::duration const& d) { + std::basic_ostringstream s; + s.flags(os.flags()); + s.imbue(os.getloc()); + s.precision(os.precision()); + s << d.count(); + if constexpr(std::is_same_v) s << "ns"; + else if constexpr(std::is_same_v) s << "µs"; + else if constexpr(std::is_same_v) s << "ms"; + else if constexpr(std::is_same_v>) s << "s"; + else { + s << '[' << Period::type::num; + if constexpr(Period::type::den != 1) + s << '/' << Period::type::den; + s << ']'; + } + return os << s.str(); +} + +template +struct WelfordVariance { + std::size_t n = 0; + T mean{}; + T m{}; + + constexpr void update(T const& x) { + ++n; + const T old_mean = mean; + mean = ((n - 1) * old_mean + x) / n; + m += (x - old_mean) * (x - mean); + } + + [[nodiscard]] constexpr T variance() { return m / n; } + [[nodiscard]] constexpr T sample_variance() { return m / (n - 1); } +}; + +struct BenchmarkReport { + using Duration = std::chrono::duration; + + Duration best; + Duration average; + Duration stddev; + unsigned runs; +}; +std::ostream& operator<<(std::ostream& stream, BenchmarkReport const& report) { + stream << "runtime: " << report.average << " ± " << report.stddev << "; best: " << report.best << "; n=" << report.runs << '\n'; + return stream; +} + +template +[[nodiscard]] BenchmarkReport benchmark(Invocable&& invocable, unsigned streak, Clock clock) { + assert(streak > 0); + using std::sqrt; + BenchmarkReport result; + WelfordVariance variance; + result.best = BenchmarkReport::Duration(std::numeric_limits::max()); + for(unsigned current_streak = 0; current_streak < streak; ) { + const auto start = clock.now(); + invocable(); + const auto end = clock.now(); + const auto duration = std::chrono::duration_cast(end - start); + if(duration < result.best) { + result.best = duration; + current_streak = 0; + } else { + ++current_streak; + } + variance.update(duration.count()); + } + result.average = BenchmarkReport::Duration(variance.mean); + result.stddev = BenchmarkReport::Duration(sqrt(variance.sample_variance())); + result.runs = variance.n; + return result; +} +template +[[nodiscard]] BenchmarkReport benchmark(Invocable&& invocable, unsigned streak = 100) { + if constexpr(std::chrono::high_resolution_clock::is_steady) + return benchmark(std::forward(invocable), streak, std::chrono::high_resolution_clock{}); + else + return benchmark(std::forward(invocable), streak, std::chrono::steady_clock{}); +} + +int main(int argc, char** argv) +try { + unsigned int sideLength = 21; + unsigned int iterationsOption = -1; + unsigned int streak = 100; + + po::parser parser; + auto& help = parser["help"] + .abbreviation('?') + .description("print this help screen"); + parser["sideLength"] + .abbreviation('l') + .description("set the grid side length (default: 21)") + .bind(sideLength); + parser["iterations"] + .abbreviation('i') + .description("set the grid side length (default: (sideLength-1)^2)") + .bind(iterationsOption); + parser["streak"] + .abbreviation('s') + .description("set the length of a streak required to escape the benchmarking algorithm (default: 100)") + .bind(streak); + + if(!parser(argc, argv)) + return EXIT_FAILURE; + + if(help.was_set()) { + std::cout << parser << '\n'; + return EXIT_SUCCESS; + } + + if(sideLength < 1) + throw std::range_error("sideLength shall be >= 1"); + + if(streak < 1) + throw std::range_error("streak shall be >= 1"); + + // use case + constexpr UseCase useCase = zhao; + + // diffusion coefficient + const Scalar mu = 0.1; + + // time + const Scalar cfl = 1; + const Scalar timestep = cfl / sq(sideLength - 1); + const int n_iter = iterationsOption != -1 ? iterationsOption : sq(sideLength - 1); + + // output + const int print_period = 0; + + // grid + const int nx = sideLength; + const Vector x = Vector::LinSpaced(nx, 0, 1); + const Scalar dx = 1.0 / (nx - 1); + const int ny = sideLength; + const Vector y = Vector::LinSpaced(ny, 0, 1); + const Scalar dy = 1.0 / (ny - 1); + + // vector fields + VectorField2 uv_now(ny, nx); + VectorField2 uv_new(ny, nx); + VectorField2 adv(ny, nx, 0); + VectorField2 diff(ny, nx, 0); + + const auto rk_fractions = { 1.0 / 3, 1.0 / 2, 1.0 }; + + const auto single_threaded_task = [&]{ + uv_now = VectorField2(ny, nx, 0); + uv_new = initial_solution(useCase, mu, x, y); + + Scalar t = 0; + for(int i = 0; i < n_iter; ++i) { + uv_now = uv_new; + + for(const double rk_fraction : rk_fractions) { + const Scalar dt = rk_fraction * timestep; + rk_stage(mu, uv_now, uv_new, uv_new, adv, diff, dt, Vector2{ dx, dy }); + enforce_boundary_conditions(useCase, mu, t + dt, x, y, uv_new); + } + + t += timestep; + if(print_period > 0 && ((i+1) % print_period == 0 || i+1 == n_iter)) { + VectorField2 uv_ex = solution_factory(useCase, mu, t, x, y); + const Scalar err_u = (uv_new[0].block(margin, margin, ny - 2 * margin, nx - 2 * margin) - uv_ex[0].block(margin, margin, ny - 2 * margin, nx - 2 * margin)).norm() * std::sqrt(dx * dy); + const Scalar err_v = (uv_new[1].block(margin, margin, ny - 2 * margin, nx - 2 * margin) - uv_ex[1].block(margin, margin, ny - 2 * margin, nx - 2 * margin)).norm() * std::sqrt(dx * dy); + std::cout << "Iteration " << std::right << std::setfill(' ') << std::setw(6) << i + 1; + std::cout << std::scientific << std::setprecision(4); + std::cout << ": ||u - uex|| = " << err_u << " m/s, ||v - vex|| = " << err_v << " m/s\n"; + std::cout << std::defaultfloat; + } + } + }; + std::cout << "Single-threaded benchmark:\n" << benchmark(single_threaded_task, streak); +} catch(std::exception const& exception) { + std::cerr << po::red << "exception"; + std::cerr << ": " << exception.what() << '\n'; + return EXIT_FAILURE; +} diff --git a/projects/2021/groupK_burgers_openmp/branch-omp/CMakeLists.txt b/projects/2021/groupK_burgers_openmp/branch-omp/CMakeLists.txt new file mode 100644 index 00000000..aa88cbcc --- /dev/null +++ b/projects/2021/groupK_burgers_openmp/branch-omp/CMakeLists.txt @@ -0,0 +1,29 @@ +cmake_minimum_required(VERSION 3.14) +project(HPWCProject) + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + +include(FetchContent) + +find_package(Eigen3 3.4 QUIET) +if(NOT EIGEN_FOUND) + FetchContent_Declare( + Eigen + GIT_REPOSITORY https://gitlab.com/libeigen/eigen + GIT_TAG 3.4 + ) + FetchContent_MakeAvailable(Eigen) +endif() + +FetchContent_Declare( + ProgramOptionsHxx + GIT_REPOSITORY https://github.com/Fytch/ProgramOptions.hxx +) +FetchContent_MakeAvailable(ProgramOptionsHxx) + +find_package(OpenMP REQUIRED) + +add_executable(HPWCProject main.cpp) +target_link_libraries(HPWCProject Eigen3::Eigen ProgramOptionsHxx OpenMP::OpenMP_CXX) diff --git a/projects/2021/groupK_burgers_openmp/branch-omp/bench.sh b/projects/2021/groupK_burgers_openmp/branch-omp/bench.sh new file mode 100755 index 00000000..73484687 --- /dev/null +++ b/projects/2021/groupK_burgers_openmp/branch-omp/bench.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +for (( i=1; i <= $1; ++i )) do + ./HPWCProject -l480 -i229 -s20 -n"$i" +done diff --git a/projects/2021/groupK_burgers_openmp/branch-omp/main.cpp b/projects/2021/groupK_burgers_openmp/branch-omp/main.cpp new file mode 100644 index 00000000..3de91dfd --- /dev/null +++ b/projects/2021/groupK_burgers_openmp/branch-omp/main.cpp @@ -0,0 +1,511 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using Scalar = double; +using TemplateParamScalar = +#if __cpp_nontype_template_args >= 201911 + Scalar +#else + long int +#endif +; +// using Vector3 = Eigen::Matrix; +using Vector = Eigen::Matrix; +using Vector2 = Eigen::Matrix; +using Matrix = Eigen::Matrix; + +template +concept Tensoroid = true; // CBA +template +concept Matrixoid = requires(T const& m) { + { m(0, 0) } -> std::convertible_to; + { m.rows() } -> std::integral; + { m.cols() } -> std::integral; + // more stuff but CBA +}; +template +concept Vectoroid = requires(T const& v) { + { v[0] } -> std::convertible_to; + // more stuff but CBA +}; + +namespace Detail { + template + struct IsEigenSequence : std::false_type {}; + template + struct IsEigenSequence> : std::true_type {}; +} +template +concept Sequenceoid = Detail::IsEigenSequence::value; + +template +[[nodiscard]] constexpr T sq(T const& x) { + return x * x; +} +[[nodiscard]] constexpr auto absi(std::signed_integral auto x) noexcept { + assert(x != std::numeric_limits::min()); + return x < 0 ? -x : x; +} +[[nodiscard]] constexpr auto absi(std::unsigned_integral auto x) noexcept { + return x; +} +[[nodiscard]] constexpr unsigned exp2i(unsigned x) noexcept { + assert(x < std::numeric_limits::digits); + return 1<; + +template +struct ScopeGuard { + Invocable invocable; + [[nodiscard]] explicit constexpr ScopeGuard(Invocable&& invocable) noexcept(std::is_nothrow_move_constructible_v) : invocable(std::move(invocable)) {} + [[nodiscard]] explicit constexpr ScopeGuard(Invocable const& invocable) noexcept(std::is_nothrow_copy_constructible_v) : invocable(invocable) {} + constexpr ~ScopeGuard() noexcept(std::is_nothrow_invocable_v) { invocable(); } +}; + +template +struct Rank1Slice { + Tensor* tensor; + std::array position; + + [[nodiscard]] constexpr Rank1Slice(Tensor& tensor, std::convertible_to auto const&... indices) + : tensor(std::addressof(tensor)), position{ indices... } { + static_assert(sizeof...(indices) == ranks); + } + + // not multi-thread friendly + [[nodiscard]] constexpr decltype(auto) operator[](IndexType i) const { + assert(tensor); + const_cast(this)->position[slicedRank] += i; + const ScopeGuard restore([this, i]{ const_cast(this)->position[slicedRank] -= i; }); + return std::apply(*tensor, position); + } +}; +template +[[nodiscard]] constexpr auto rank1Slice(Tensoroid auto& tensor, std::integral auto const&... indices) { + return Rank1Slice, sizeof...(indices), slicedRank, std::common_type_t...>>(tensor, indices...); +} + +template typename F, typename I, typename... Args> +struct FoldR; +template typename F, typename I, typename T> +struct FoldR : std::type_identity::type> {}; +template typename F, typename I, typename T, typename U, typename... Tail> +struct FoldR : std::type_identity::type>::type> {}; + +template +struct IndexCoeffPair { + static constexpr auto index = index_; + static constexpr auto factor = factor_; +}; +template +struct IsIndexCoeffPair : std::false_type {}; +template +struct IsIndexCoeffPair> : std::true_type {}; +template +concept IndexCoeff = IsIndexCoeffPair::value; + +template +struct IndexMin : std::type_identity> {}; +template +struct IndexMax : std::type_identity Rhs::index), Lhs, Rhs>> {}; + +enum class StencilType { asymmetric, symmetric, antisymmetric }; +template +struct Stencil /* 1D only */ { + static constexpr auto min_index = FoldR::max(), {}>, Pairs...>::type::index; + static constexpr auto max_index = FoldR::min(), {}>, Pairs...>::type::index; + + static constexpr auto left = type == StencilType::asymmetric ? min_index : -std::max(absi(min_index), max_index); + static constexpr auto right = type == StencilType::asymmetric ? max_index : std::max(absi(min_index), max_index); + static constexpr auto margin = sizeof...(Pairs) > 0 ? std::max(absi(left), right) : 0; + + [[nodiscard]] static constexpr auto apply(Vectoroid auto&& vector) { + switch(type) { + case StencilType::asymmetric: + return ((Pairs::factor * vector[Pairs::index]) + ...); + case StencilType::symmetric: + return ((Pairs::factor * (Pairs::index ? vector[Pairs::index] + vector[-Pairs::index] : vector[Pairs::index])) + ...); + case StencilType::antisymmetric: + return ((Pairs::factor * (Pairs::index ? vector[Pairs::index] - vector[-Pairs::index] : vector[Pairs::index])) + ...); + }; + } +}; + +class VectorField2 { + Matrix uv[2]; + +public: + [[nodiscard]] VectorField2() = default; + [[nodiscard]] explicit VectorField2(Eigen::Index rows, Eigen::Index cols) + : uv{ Matrix(rows, cols), Matrix(rows, cols) } { + } + [[nodiscard]] explicit VectorField2(Eigen::Index rows, Eigen::Index cols, Scalar fill) + : uv{ Matrix::Constant(rows, cols, fill), Matrix::Constant(rows, cols, fill) } { + } + + [[nodiscard]] constexpr Matrix const& operator[](int i) const noexcept { assert(0 <= i && i < 2); return uv[i]; } + [[nodiscard]] constexpr Matrix & operator[](int i) noexcept { assert(0 <= i && i < 2); return uv[i]; } + + [[nodiscard]] constexpr Eigen::Index rows() const noexcept { return uv[0].rows(); } + [[nodiscard]] constexpr Eigen::Index cols() const noexcept { return uv[0].cols(); } +}; + +using AdvectionStencil1 = Stencil, + IndexCoeffPair<2, TemplateParamScalar(- 9)>, + IndexCoeffPair<3, TemplateParamScalar( 1)>>; +using AdvectionStencil2 = Stencil, + IndexCoeffPair<1, TemplateParamScalar( 15)>, + IndexCoeffPair<2, TemplateParamScalar(- 6)>, + IndexCoeffPair<3, TemplateParamScalar( 1)>>; + +using DiffusionStencil = Stencil, + IndexCoeffPair<1, TemplateParamScalar( 16)>, + IndexCoeffPair<2, TemplateParamScalar(- 1)>>; + +constexpr int margin = std::max({ AdvectionStencil1::margin, AdvectionStencil2::margin, DiffusionStencil::margin }); + +[[nodiscard]] constexpr Scalar advection(Scalar d, Scalar w, Vectoroid auto const& phiSlice) { + return + ( w * AdvectionStencil1::apply(phiSlice) + - std::abs(w) * AdvectionStencil2::apply(phiSlice)) / (60 * d); +} +template +void advection(Vectoroid auto const& d, Matrixoid auto const& w, Matrixoid auto const& phi, Matrixoid auto& out, std::invocable auto assignment) { + const int nx = w.cols(), ny = w.rows(); + assert(phi.cols() == nx && phi.rows() == ny); + assert(out.cols() == nx && out.rows() == ny); + #pragma omp parallel for schedule(static) + // #pragma omp parallel for schedule(dynamic) + // #pragma omp parallel for schedule(static) collapse(2) + // #pragma omp parallel for schedule(dynamic) collapse(2) + for(int x = margin; x < nx - margin; ++x) + for(int y = margin; y < ny - margin; ++y) + assignment(out(y, x), advection(d[advectRank], w(y, x), rank1Slice(phi, y, x))); +} +void advection(Vectoroid auto const& d, VectorField2 const& uv, VectorField2& adv) { + advection<0>(d, uv[0], uv[0], adv[0], [](Scalar& lhs, Scalar rhs) constexpr noexcept { lhs = rhs; }); + advection<1>(d, uv[1], uv[0], adv[0], [](Scalar& lhs, Scalar rhs) constexpr noexcept { lhs += rhs; }); + + advection<0>(d, uv[0], uv[1], adv[1], [](Scalar& lhs, Scalar rhs) constexpr noexcept { lhs = rhs; }); + advection<1>(d, uv[1], uv[1], adv[1], [](Scalar& lhs, Scalar rhs) constexpr noexcept { lhs += rhs; }); +} + +[[nodiscard]] constexpr Scalar diffusion(Scalar d, Vectoroid auto const& phiSlice) { + return 1 / (12 * sq(d)) * DiffusionStencil::apply(phiSlice); +} +template +void diffusion(Vectoroid auto const& d, Matrixoid auto const& phi, Matrixoid auto& out, std::invocable auto assignment) { + const int nx = phi.cols(), ny = phi.rows(); + assert(out.cols() == nx && out.rows() == ny); + #pragma omp parallel for schedule(static) + // #pragma omp parallel for schedule(dynamic) + // #pragma omp parallel for schedule(static) collapse(2) + // #pragma omp parallel for schedule(dynamic) collapse(2) + for(int x = margin; x < nx - margin; ++x) + for(int y = margin; y < ny - margin; ++y) + assignment(out(y, x), diffusion(d[diffuseRank], rank1Slice(phi, y, x))); +} +void diffusion(Vectoroid auto const& d, VectorField2 const& uv, VectorField2& diff) { + diffusion<0>(d, uv[0], diff[0], [](Scalar& lhs, Scalar rhs) constexpr noexcept { lhs = rhs; }); + diffusion<1>(d, uv[0], diff[0], [](Scalar& lhs, Scalar rhs) constexpr noexcept { lhs += rhs; }); + + diffusion<0>(d, uv[1], diff[1], [](Scalar& lhs, Scalar rhs) constexpr noexcept { lhs = rhs; }); + diffusion<1>(d, uv[1], diff[1], [](Scalar& lhs, Scalar rhs) constexpr noexcept { lhs += rhs; }); +} + +void rk_stage( + Scalar mu, + VectorField2 const& in_now, + VectorField2 const& in_tmp, + VectorField2& out, + VectorField2& adv, + VectorField2& diff, + Scalar dt, + Vectoroid auto const& d +) { + advection(d, in_tmp, adv); + diffusion(d, in_tmp, diff); + out[0] = in_now[0] + dt * (-adv[0] + mu * diff[0]); + out[1] = in_now[1] + dt * (-adv[1] + mu * diff[1]); +} + +enum UseCase { zhao, hopf_cole }; + +[[nodiscard]] constexpr VectorField2 solution_factory(UseCase useCase, Scalar mu, Scalar t, Matrixoid auto const& x, Matrixoid auto const& y, Sequenceoid auto slice_x, Sequenceoid auto slice_y) { + const int mi = slice_x.size() ? slice_x[slice_x.size() - 1] - slice_x[0] + 1 : 0; + const int mj = slice_y.size() ? slice_y[slice_y.size() - 1] - slice_y[0] + 1 : 0; + + const Matrixoid auto x2d = x(slice_x).replicate(1, mj); + const Matrixoid auto y2d = y(slice_y).transpose().replicate(mi, 1); + + const int nx = x2d.cols(), ny = x2d.rows(); + assert(y2d.cols() == nx && y2d.rows() == ny); + + using std::exp; + VectorField2 result; + switch(useCase) { + case zhao: + result[0] = -4 * mu * pi * exp(-5 * sq(pi) * mu * t) * (2 * pi * x2d).array().cos() * (pi * y2d).array().sin() / (2 + exp(-5 * sq(pi) * mu * t) * (2 * pi * x2d).array().sin() * (pi * y2d).array().sin()); + result[1] = -2 * mu * pi * exp(-5 * sq(pi) * mu * t) * (2 * pi * x2d).array().sin() * (pi * y2d).array().cos() / (2 + exp(-5 * sq(pi) * mu * t) * (2 * pi * x2d).array().sin() * (pi * y2d).array().sin()); + break; + case hopf_cole: + result[0] = 0.75 - 1 / (4 * (1 + (-Matrix::Constant(x2d.rows(), x2d.cols(), t) - 4 * x2d + 4 * y2d).array().exp() / (32 * mu))); + result[1] = 0.75 + 1 / (4 * (1 + (-Matrix::Constant(x2d.rows(), x2d.cols(), t) - 4 * x2d + 4 * y2d).array().exp() / (32 * mu))); + break; + default: + assert(false); + } + return result; +} +[[nodiscard]] constexpr decltype(auto) solution_factory(UseCase useCase, Scalar mu, Scalar t, Matrixoid auto const& x, Matrixoid auto const& y) { + return solution_factory(useCase, mu, t, x, y, Eigen::seq(0, x.size() - 1), Eigen::seq(0, y.size() - 1)); +} + +[[nodiscard]] constexpr VectorField2 initial_solution(UseCase useCase, Scalar mu, Matrixoid auto const& x, Matrixoid auto const& y) { + return solution_factory(useCase, mu, 0, x, y); +} + +void enforce_boundary_conditions(UseCase useCase, Scalar mu, Scalar t, Matrixoid auto const& x, Matrixoid auto const& y, VectorField2& uv) { + const int nx = x.size(), ny = y.size(); + + { + auto slice_x = Eigen::seq(0, margin - 1); + auto slice_y = Eigen::seq(0, ny - 1); + VectorField2 uv_ex = solution_factory(useCase, mu, t, x, y, slice_x, slice_y); + uv[0](slice_x, slice_y) = std::move(uv_ex[0]); + uv[1](slice_x, slice_y) = std::move(uv_ex[1]); + } + { + auto slice_x = Eigen::seq(nx - margin, nx - 1); + auto slice_y = Eigen::seq(0, ny - 1); + VectorField2 uv_ex = solution_factory(useCase, mu, t, x, y, slice_x, slice_y); + uv[0](slice_x, slice_y) = std::move(uv_ex[0]); + uv[1](slice_x, slice_y) = std::move(uv_ex[1]); + } + { + auto slice_x = Eigen::seq(margin, nx - margin - 1); + auto slice_y = Eigen::seq(0, margin - 1); + VectorField2 uv_ex = solution_factory(useCase, mu, t, x, y, slice_x, slice_y); + uv[0](slice_x, slice_y) = std::move(uv_ex[0]); + uv[1](slice_x, slice_y) = std::move(uv_ex[1]); + } + { + auto slice_x = Eigen::seq(margin, nx - margin - 1); + auto slice_y = Eigen::seq(ny - margin, ny - 1); + VectorField2 uv_ex = solution_factory(useCase, mu, t, x, y, slice_x, slice_y); + uv[0](slice_x, slice_y) = std::move(uv_ex[0]); + uv[1](slice_x, slice_y) = std::move(uv_ex[1]); + } +} + +// TODO: only a makeshift because my stdlib doesn't implement this +template +std::basic_ostream& operator<<(std::basic_ostream& os, std::chrono::duration const& d) { + std::basic_ostringstream s; + s.flags(os.flags()); + s.imbue(os.getloc()); + s.precision(os.precision()); + s << d.count(); + if constexpr(std::is_same_v) s << "ns"; + else if constexpr(std::is_same_v) s << "µs"; + else if constexpr(std::is_same_v) s << "ms"; + else if constexpr(std::is_same_v>) s << "s"; + else { + s << '[' << Period::type::num; + if constexpr(Period::type::den != 1) + s << '/' << Period::type::den; + s << ']'; + } + return os << s.str(); +} + +template +struct WelfordVariance { + std::size_t n = 0; + T mean{}; + T m{}; + + constexpr void update(T const& x) { + ++n; + const T old_mean = mean; + mean = ((n - 1) * old_mean + x) / n; + m += (x - old_mean) * (x - mean); + } + + [[nodiscard]] constexpr T variance() { return m / n; } + [[nodiscard]] constexpr T sample_variance() { return m / (n - 1); } +}; + +struct BenchmarkReport { + using Duration = std::chrono::duration; + + Duration best; + Duration average; + Duration stddev; + unsigned runs; +}; +std::ostream& operator<<(std::ostream& stream, BenchmarkReport const& report) { + stream << "runtime: " << report.average << " ± " << report.stddev << "; best: " << report.best << "; n=" << report.runs << '\n'; + return stream; +} + +template +[[nodiscard]] BenchmarkReport benchmark(Invocable&& invocable, unsigned streak, Clock clock) { + assert(streak > 0); + using std::sqrt; + BenchmarkReport result; + WelfordVariance variance; + result.best = BenchmarkReport::Duration(std::numeric_limits::max()); + for(unsigned current_streak = 0; current_streak < streak; ) { + const auto start = clock.now(); + invocable(); + const auto end = clock.now(); + const auto duration = std::chrono::duration_cast(end - start); + if(duration < result.best) { + result.best = duration; + current_streak = 0; + } else { + ++current_streak; + } + variance.update(duration.count()); + } + result.average = BenchmarkReport::Duration(variance.mean); + result.stddev = BenchmarkReport::Duration(sqrt(variance.sample_variance())); + result.runs = variance.n; + return result; +} +template +[[nodiscard]] BenchmarkReport benchmark(Invocable&& invocable, unsigned streak = 100) { + if constexpr(std::chrono::high_resolution_clock::is_steady) + return benchmark(std::forward(invocable), streak, std::chrono::high_resolution_clock{}); + else + return benchmark(std::forward(invocable), streak, std::chrono::steady_clock{}); +} + +int main(int argc, char** argv) +try { + unsigned int threads = 1; + unsigned int sideLength = 21; + unsigned int iterationsOption = -1; + unsigned int streak = 100; + + po::parser parser; + auto& help = parser["help"] + .abbreviation('?') + .description("print this help screen"); + parser["threads"] + .abbreviation('n') + .description("set the number of threads (default: 1)") + .bind(threads); + parser["sideLength"] + .abbreviation('l') + .description("set the grid side length (default: 21)") + .bind(sideLength); + parser["iterations"] + .abbreviation('i') + .description("set the grid side length (default: (sideLength-1)^2)") + .bind(iterationsOption); + parser["streak"] + .abbreviation('s') + .description("set the length of a streak required to escape the benchmarking algorithm (default: 100)") + .bind(streak); + + if(!parser(argc, argv)) + return EXIT_FAILURE; + + if(help.was_set()) { + std::cout << parser << '\n'; + return EXIT_SUCCESS; + } + + if(threads < 1) + throw std::range_error("at least one thread required"); + omp_set_num_threads(threads); + + if(sideLength < 1) + throw std::range_error("sideLength shall be >= 1"); + + if(streak < 1) + throw std::range_error("streak shall be >= 1"); + + // use case + constexpr UseCase useCase = zhao; + + // diffusion coefficient + const Scalar mu = 0.1; + + // time + const Scalar cfl = 1; + const Scalar timestep = cfl / sq(sideLength - 1); + const int n_iter = iterationsOption != -1 ? iterationsOption : sq(sideLength - 1); + + // output + const int print_period = 0; + + // grid + const int nx = sideLength; + const Vector x = Vector::LinSpaced(nx, 0, 1); + const Scalar dx = 1.0 / (nx - 1); + const int ny = sideLength; + const Vector y = Vector::LinSpaced(ny, 0, 1); + const Scalar dy = 1.0 / (ny - 1); + + // vector fields + VectorField2 uv_now(ny, nx); + VectorField2 uv_new(ny, nx); + VectorField2 adv(ny, nx, 0); + VectorField2 diff(ny, nx, 0); + + const auto rk_fractions = { 1.0 / 3, 1.0 / 2, 1.0 }; + + const auto task = [&]{ + uv_now = VectorField2(ny, nx, 0); + uv_new = initial_solution(useCase, mu, x, y); + + Scalar t = 0; + for(int i = 0; i < n_iter; ++i) { + uv_now = uv_new; + + for(const double rk_fraction : rk_fractions) { + const Scalar dt = rk_fraction * timestep; + rk_stage(mu, uv_now, uv_new, uv_new, adv, diff, dt, Vector2{ dx, dy }); + enforce_boundary_conditions(useCase, mu, t + dt, x, y, uv_new); + } + + t += timestep; + if(print_period > 0 && ((i+1) % print_period == 0 || i+1 == n_iter)) { + VectorField2 uv_ex = solution_factory(useCase, mu, t, x, y); + const Scalar err_u = (uv_new[0].block(margin, margin, ny - 2 * margin, nx - 2 * margin) - uv_ex[0].block(margin, margin, ny - 2 * margin, nx - 2 * margin)).norm() * std::sqrt(dx * dy); + const Scalar err_v = (uv_new[1].block(margin, margin, ny - 2 * margin, nx - 2 * margin) - uv_ex[1].block(margin, margin, ny - 2 * margin, nx - 2 * margin)).norm() * std::sqrt(dx * dy); + std::cout << "Iteration " << std::right << std::setfill(' ') << std::setw(6) << i + 1; + std::cout << std::scientific << std::setprecision(4); + std::cout << ": ||u - uex|| = " << err_u << " m/s, ||v - vex|| = " << err_v << " m/s\n"; + std::cout << std::defaultfloat; + } + } + }; + std::cout << threads << "-threaded benchmark:" << benchmark(task, streak); +} catch(std::exception const& exception) { + std::cerr << po::red << "exception"; + std::cerr << ": " << exception.what() << '\n'; + return EXIT_FAILURE; +} diff --git a/projects/2021/groupK_burgers_openmp/branch-omp/plot b/projects/2021/groupK_burgers_openmp/branch-omp/plot new file mode 100644 index 00000000..6e13ac7d --- /dev/null +++ b/projects/2021/groupK_burgers_openmp/branch-omp/plot @@ -0,0 +1,22 @@ +# just to get GPVAL_Y_MAX +p "results-shallow-static.txt" using 1:2 \ +, "results-shallow-dynamic.txt" using 1:2 \ +, "results-collapsed-static.txt" using 1:2 \ +#, "results-collapsed-dynamic.txt" using 1:2 + +set term svg +set output "plot.svg" + +set xlabel "Threads" +set ylabel "Runtime [ms]" + +set xrange [1:24] +set yrange [0:GPVAL_Y_MAX] + +set arrow from 12, graph 0 to 12, graph 1 nohead lw 0.5 lc rgb "0xC0C0C0" + +p 1761.55 title "single-threaded" lt black \ +, "results-shallow-static.txt" using 1:2 w l title "shallow, static" \ +, "results-shallow-dynamic.txt" using 1:2 w l title "shallow, dynamic" \ +, "results-collapsed-static.txt" using 1:2 w l title "collapsed, static" \ +#, "results-collapsed-dynamic.txt" using 1:2 w l title "collapsed, dynamic" \ diff --git a/projects/2021/groupK_burgers_openmp/branch-omp/plot.svg b/projects/2021/groupK_burgers_openmp/branch-omp/plot.svg new file mode 100644 index 00000000..887be669 --- /dev/null +++ b/projects/2021/groupK_burgers_openmp/branch-omp/plot.svg @@ -0,0 +1,198 @@ + + + +Gnuplot +Produced by GNUPLOT 5.4 patchlevel 2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + 500 + + + + + 1000 + + + + + 1500 + + + + + 2000 + + + + + 2500 + + + + + 3000 + + + + + 3500 + + + + + 4000 + + + + + 5 + + + + + 10 + + + + + 15 + + + + + 20 + + + + + + + + + + + + + Runtime [ms] + + + + + Threads + + + + + single-threaded + + + single-threaded + + + + + + shallow, static + + + shallow, static + + + + + + shallow, dynamic + + + shallow, dynamic + + + + + + collapsed, static + + + collapsed, static + + + + + + + + + + + + + + + + + + diff --git a/projects/2021/groupK_burgers_openmp/branch-omp/results-collapsed-dynamic.txt b/projects/2021/groupK_burgers_openmp/branch-omp/results-collapsed-dynamic.txt new file mode 100644 index 00000000..5bf5552f --- /dev/null +++ b/projects/2021/groupK_burgers_openmp/branch-omp/results-collapsed-dynamic.txt @@ -0,0 +1,24 @@ +1 12935.7 360.757 12680.6 2 +2 111735 161.192 111621 2 +3 121632 270.072 121441 2 +4 124374 156.605 124180 5 +5 102743 17.7151 102730 2 +6 88622.3 136.157 88526 2 +7 78737.6 232.754 78573 2 +8 70705 135.711 70553.9 4 +9 66842.6 88.6509 66779.9 2 +10 64278.5 154.226 64169.4 2 +11 62228.7 183.461 62099 2 +12 60467.4 59.3568 60425.4 2 +13 58008.2 10.2265 58001 2 +14 54951.5 29.5089 54918.2 4 +15 52639.1 34.7557 52614.5 2 +16 50617.5 129.173 50526.2 2 +17 48262.1 6.0242 48257.9 2 +18 46833.2 28.7177 46812.9 2 +19 45230 12.5256 45221.1 2 +20 43992.6 0.927018 43991.9 2 +21 42174.7 7.70656 42169.2 2 +22 40838.7 21.838 40823.3 2 +23 39799.1 53.1698 39733.3 5 +24 42077 286.367 41874.5 2 diff --git a/projects/2021/groupK_burgers_openmp/branch-omp/results-collapsed-static.txt b/projects/2021/groupK_burgers_openmp/branch-omp/results-collapsed-static.txt new file mode 100644 index 00000000..9bc040ab --- /dev/null +++ b/projects/2021/groupK_burgers_openmp/branch-omp/results-collapsed-static.txt @@ -0,0 +1,24 @@ +1 3981.12 56.9674 3914.87 38 +2 2426.23 36.3124 2363.07 23 +3 1922.95 58.7132 1856.75 24 +4 1636.56 64.1493 1571.75 51 +5 1518.76 50.4952 1421.02 21 +6 1412.58 70.5845 1275.9 39 +7 1323.95 42.6127 1248.95 42 +8 1249.74 28.4438 1206.39 60 +9 1293.59 38.2212 1208.93 48 +10 1231.64 35.2432 1160.04 30 +11 1222.88 30.9767 1162.71 39 +12 1213.74 25.8987 1175.75 30 +13 1364.55 17.689 1320.49 30 +14 1546.98 8.85813 1535.59 33 +15 1333.81 113.325 1224.58 47 +16 1523.74 27.3059 1460.9 24 +17 1466.7 2.91745 1460.98 33 +18 1415.08 68.6933 1248.24 30 +19 1463.17 15.9095 1447.6 27 +20 1393.29 84.6648 1290.35 50 +21 1461.23 18.6694 1433.07 23 +22 1427.35 27.7095 1398.9 23 +23 1583.25 55.8459 1523.57 24 +24 2268.06 137.569 2103.68 22 diff --git a/projects/2021/groupK_burgers_openmp/branch-omp/results-shallow-dynamic.txt b/projects/2021/groupK_burgers_openmp/branch-omp/results-shallow-dynamic.txt new file mode 100644 index 00000000..a1a65ce1 --- /dev/null +++ b/projects/2021/groupK_burgers_openmp/branch-omp/results-shallow-dynamic.txt @@ -0,0 +1,24 @@ +1 1820.68 28.8543 1788.09 42 +2 1800.82 45.1005 1719.79 30 +3 1652.87 24.5901 1625.1 38 +4 1709.06 16.931 1677.26 29 +5 1506.15 22.8942 1472.38 50 +6 1485.3 26.5845 1457.99 33 +7 1573.28 61.0053 1468.64 42 +8 1523.51 28.4464 1471.67 21 +9 1496.66 65.6791 1397.31 36 +10 1499.12 49.2789 1399.24 26 +11 1456.79 36.713 1402.69 59 +12 1480.78 26.3377 1452.96 35 +13 1625.52 192.755 1387.4 99 +14 1565.94 176.501 1395.46 63 +15 1583.1 168.616 1386.43 60 +16 1584.13 181.155 1410.02 72 +17 1540.47 166.82 1407.7 66 +18 1565.17 161.84 1422.28 32 +19 1495.8 185.809 1364.82 62 +20 1667.31 184.946 1396.48 23 +21 1807.79 10.7196 1782.79 21 +22 1808.32 10.3299 1795.53 28 +23 1793.4 18.6433 1767.01 30 +24 2145.88 70.3782 2041.5 33 diff --git a/projects/2021/groupK_burgers_openmp/branch-omp/results-shallow-static.txt b/projects/2021/groupK_burgers_openmp/branch-omp/results-shallow-static.txt new file mode 100644 index 00000000..c56251df --- /dev/null +++ b/projects/2021/groupK_burgers_openmp/branch-omp/results-shallow-static.txt @@ -0,0 +1,24 @@ +1 1823.55 26.2263 1782.73 23 +2 1401.58 19.8054 1349.46 96 +3 1199.78 20.8571 1167.98 30 +4 1141.46 19.449 1111.81 24 +5 1122.95 22.5619 1092.07 38 +6 1015.55 47.5705 972.33 47 +7 1016.55 13.0833 995.12 24 +8 1034.47 26.4825 953.92 32 +9 1028.39 73.6957 949.22 66 +10 1021.82 30.7757 985.06 42 +11 1029.58 23.5031 996.72 54 +12 1049.21 28.4955 1012.32 27 +13 1148.73 32.048 1099.74 33 +14 1226.55 116.99 1060.86 42 +15 1104.32 64.5803 1048.97 48 +16 1381.24 11.6949 1363.26 36 +17 1246.86 125.312 1062.78 57 +18 1258.27 123.22 1072.89 39 +19 1362.96 19.4314 1333.75 33 +20 1214.86 133.691 1055.18 44 +21 1339.66 28.7203 1311.06 48 +22 1374.55 57.2419 1347.98 33 +23 1527.07 139.481 1365.03 37 +24 1943.73 351.194 1581.44 36 diff --git a/projects/2021/groupK_burgers_openmp/branch-omp/results-single.txt b/projects/2021/groupK_burgers_openmp/branch-omp/results-single.txt new file mode 100644 index 00000000..7771829d --- /dev/null +++ b/projects/2021/groupK_burgers_openmp/branch-omp/results-single.txt @@ -0,0 +1 @@ +1 1761.55 15.7786 1734.09 227 diff --git a/projects/2021/groupK_burgers_openmp/branch-upcxx/main.cpp b/projects/2021/groupK_burgers_openmp/branch-upcxx/main.cpp new file mode 100644 index 00000000..9067fe9b --- /dev/null +++ b/projects/2021/groupK_burgers_openmp/branch-upcxx/main.cpp @@ -0,0 +1,725 @@ +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using Scalar = double; +using TemplateParamScalar = +#if __cpp_nontype_template_args >= 201911 + Scalar +#else + long int +#endif +; +// using Vector3 = Eigen::Matrix; +using Vector = Eigen::Matrix; +using Vector2 = Eigen::Matrix; +using Matrix = Eigen::Matrix; + +template +concept Tensoroid = true; // CBA +template +concept Matrixoid = requires(T const& m) { + { m(0, 0) } -> std::convertible_to; + { m.rows() } -> std::integral; + { m.cols() } -> std::integral; + // more stuff but CBA +}; +template +concept VectorField = requires(T const& m) { + { m[0](0, 0) } -> std::convertible_to; + { m[0] } -> Matrixoid; + { m.rows() } -> std::integral; + { m.cols() } -> std::integral; + // more stuff but CBA +}; +template +concept Vectoroid = requires(T const& v) { + { v[0] } -> std::convertible_to; + // more stuff but CBA +}; + +namespace Detail { + template + struct IsEigenSequence : std::false_type {}; + template + struct IsEigenSequence> : std::true_type {}; +} +template +concept Sequenceoid = Detail::IsEigenSequence::value; + +template +[[nodiscard]] constexpr T sq(T const& x) { + return x * x; +} +[[nodiscard]] constexpr auto absi(std::signed_integral auto x) noexcept { + assert(x != std::numeric_limits::min()); + return x < 0 ? -x : x; +} +[[nodiscard]] constexpr auto absi(std::unsigned_integral auto x) noexcept { + return x; +} +[[nodiscard]] constexpr unsigned exp2i(unsigned x) noexcept { + assert(x < std::numeric_limits::digits); + return 1<; + +template +struct ScopeGuard { + Invocable invocable; + [[nodiscard]] explicit constexpr ScopeGuard(Invocable&& invocable) noexcept(std::is_nothrow_move_constructible_v) : invocable(std::move(invocable)) {} + [[nodiscard]] explicit constexpr ScopeGuard(Invocable const& invocable) noexcept(std::is_nothrow_copy_constructible_v) : invocable(invocable) {} + constexpr ~ScopeGuard() noexcept(std::is_nothrow_invocable_v) { invocable(); } +}; + +template +struct Rank1Slice { + Tensor* tensor; + std::array position; + + [[nodiscard]] constexpr Rank1Slice(Tensor& tensor, std::convertible_to auto const&... indices) + : tensor(std::addressof(tensor)), position{ indices... } { + static_assert(sizeof...(indices) == ranks); + } + + // not multi-thread friendly + [[nodiscard]] constexpr decltype(auto) operator[](IndexType i) const { + assert(tensor); + const_cast(this)->position[slicedRank] += i; + const ScopeGuard restore([this, i]{ const_cast(this)->position[slicedRank] -= i; }); + return std::apply(*tensor, position); + } +}; +template +[[nodiscard]] constexpr auto rank1Slice(Tensoroid auto& tensor, std::integral auto const&... indices) { + return Rank1Slice, sizeof...(indices), slicedRank, std::common_type_t...>>(tensor, indices...); +} + +template typename F, typename I, typename... Args> +struct FoldR; +template typename F, typename I, typename T> +struct FoldR : std::type_identity::type> {}; +template typename F, typename I, typename T, typename U, typename... Tail> +struct FoldR : std::type_identity::type>::type> {}; + +template +struct IndexCoeffPair { + static constexpr auto index = index_; + static constexpr auto factor = factor_; +}; +template +struct IsIndexCoeffPair : std::false_type {}; +template +struct IsIndexCoeffPair> : std::true_type {}; +template +concept IndexCoeff = IsIndexCoeffPair::value; + +template +struct IndexMin : std::type_identity> {}; +template +struct IndexMax : std::type_identity Rhs::index), Lhs, Rhs>> {}; + +enum class StencilType { asymmetric, symmetric, antisymmetric }; +template +struct Stencil /* 1D only */ { + static constexpr auto min_index = FoldR::max(), {}>, Pairs...>::type::index; + static constexpr auto max_index = FoldR::min(), {}>, Pairs...>::type::index; + + static constexpr auto left = type == StencilType::asymmetric ? min_index : -std::max(absi(min_index), max_index); + static constexpr auto right = type == StencilType::asymmetric ? max_index : std::max(absi(min_index), max_index); + static constexpr auto margin = sizeof...(Pairs) > 0 ? std::max(absi(left), right) : 0; + + [[nodiscard]] static constexpr auto apply(Vectoroid auto&& vector) { + switch(type) { + case StencilType::asymmetric: + return ((Pairs::factor * vector[Pairs::index]) + ...); + case StencilType::symmetric: + return ((Pairs::factor * (Pairs::index ? vector[Pairs::index] + vector[-Pairs::index] : vector[Pairs::index])) + ...); + case StencilType::antisymmetric: + return ((Pairs::factor * (Pairs::index ? vector[Pairs::index] - vector[-Pairs::index] : vector[Pairs::index])) + ...); + }; + } +}; + +using AdvectionStencil1 = Stencil, + IndexCoeffPair<2, TemplateParamScalar(- 9)>, + IndexCoeffPair<3, TemplateParamScalar( 1)>>; +using AdvectionStencil2 = Stencil, + IndexCoeffPair<1, TemplateParamScalar( 15)>, + IndexCoeffPair<2, TemplateParamScalar(- 6)>, + IndexCoeffPair<3, TemplateParamScalar( 1)>>; + +using DiffusionStencil = Stencil, + IndexCoeffPair<1, TemplateParamScalar( 16)>, + IndexCoeffPair<2, TemplateParamScalar(- 1)>>; + +constexpr int margin = std::max({ AdvectionStencil1::margin, AdvectionStencil2::margin, DiffusionStencil::margin }); + +enum UseCase { zhao, hopf_cole }; + +class VectorField2 { + Matrix uv[2]; + +public: + [[nodiscard]] VectorField2() = default; + [[nodiscard]] explicit VectorField2(Eigen::Index rows, Eigen::Index cols) + : uv{ Matrix(rows, cols), Matrix(rows, cols) } { + } + [[nodiscard]] explicit VectorField2(Eigen::Index rows, Eigen::Index cols, Scalar fill) + : uv{ Matrix::Constant(rows, cols, fill), Matrix::Constant(rows, cols, fill) } { + } + + [[nodiscard]] constexpr Matrix const& operator[](int i) const noexcept { assert(0 <= i && i < 2); return uv[i]; } + [[nodiscard]] constexpr Matrix & operator[](int i) noexcept { assert(0 <= i && i < 2); return uv[i]; } + + [[nodiscard]] constexpr Eigen::Index rows() const noexcept { return uv[0].rows(); } + [[nodiscard]] constexpr Eigen::Index cols() const noexcept { return uv[0].cols(); } +}; + +[[nodiscard]] constexpr VectorField2 solution_factory(UseCase useCase, Scalar mu, Scalar t, Matrixoid auto const& x, Matrixoid auto const& y, Sequenceoid auto slice_x, Sequenceoid auto slice_y) { + const int mi = slice_x.size() ? slice_x[slice_x.size() - 1] - slice_x[0] + 1 : 0; + const int mj = slice_y.size() ? slice_y[slice_y.size() - 1] - slice_y[0] + 1 : 0; + + const Matrixoid auto x2d = x(slice_x).transpose().replicate(mj, 1); + const Matrixoid auto y2d = y(slice_y).replicate(1, mi); + + const int nx = x2d.cols(), ny = x2d.rows(); + assert(nx == slice_x.size()); + assert(y2d.cols() == nx && y2d.rows() == ny); + + using std::exp; + VectorField2 result; + switch(useCase) { + case zhao: + result[0] = -4 * mu * pi * exp(-5 * sq(pi) * mu * t) * (2 * pi * x2d).array().cos() * (pi * y2d).array().sin() / (2 + exp(-5 * sq(pi) * mu * t) * (2 * pi * x2d).array().sin() * (pi * y2d).array().sin()); + result[1] = -2 * mu * pi * exp(-5 * sq(pi) * mu * t) * (2 * pi * x2d).array().sin() * (pi * y2d).array().cos() / (2 + exp(-5 * sq(pi) * mu * t) * (2 * pi * x2d).array().sin() * (pi * y2d).array().sin()); + break; + case hopf_cole: + result[0] = 0.75 - 1 / (4 * (1 + (-Matrix::Constant(x2d.rows(), x2d.cols(), t) - 4 * x2d + 4 * y2d).array().exp() / (32 * mu))); + result[1] = 0.75 + 1 / (4 * (1 + (-Matrix::Constant(x2d.rows(), x2d.cols(), t) - 4 * x2d + 4 * y2d).array().exp() / (32 * mu))); + break; + default: + assert(false); + } + return result; +} +[[nodiscard]] constexpr decltype(auto) solution_factory(UseCase useCase, Scalar mu, Scalar t, Matrixoid auto const& x, Matrixoid auto const& y) { + return solution_factory(useCase, mu, t, x, y, Eigen::seq(0, x.size() - 1), Eigen::seq(0, y.size() - 1)); +} + +[[nodiscard]] constexpr VectorField2 initial_solution(UseCase useCase, Scalar mu, Matrixoid auto const& x, Matrixoid auto const& y) { + return solution_factory(useCase, mu, 0, x, y); +} + +Vector padVector(Vectoroid auto input, int targetLength, Scalar paddingValue){ + assert(targetLength >= input.rows()); + Vector padded(targetLength); + padded << input, paddingValue * Vector::Ones(targetLength - input.rows()); + return padded; +} + +struct DistributedConfig { + + explicit DistributedConfig(int32_t globalWidth, int32_t globalHeight, int32_t ranksWidth, int32_t ranksHeight, int32_t rankIndex, int32_t margin) : + RANKS_TOTAL(ranksWidth * ranksHeight), + RANKS_WIDTH(ranksWidth), + RANKS_HEIGHT(ranksHeight), + RANK_INDEX(rankIndex), + RANK_X(rankIndex % ranksWidth), + RANK_Y(rankIndex / ranksWidth), + GLOBAL_WIDTH(globalWidth), + GLOBAL_HEIGHT(globalHeight), + LOCAL_WIDTH((globalWidth + ranksWidth - 1) / ranksWidth), + LOCAL_HEIGHT((globalHeight + ranksHeight - 1) / ranksHeight), + STORED_WIDTH(LOCAL_WIDTH + 2 * margin), + STORED_HEIGHT(LOCAL_HEIGHT + 2 * margin), + MARGIN(margin), + DX(1.0 / (globalWidth - 1)), + DY(1.0 / (globalHeight - 1)), + GLOBAL_X(Vector::LinSpaced(globalWidth, 0, 1)), + GLOBAL_Y(Vector::LinSpaced(globalHeight, 0, 1)), + LOCAL_X(padVector(GLOBAL_X, LOCAL_WIDTH * RANKS_WIDTH, 1.0).segment(RANK_X * LOCAL_WIDTH, LOCAL_WIDTH)), + LOCAL_Y(padVector(GLOBAL_Y, LOCAL_HEIGHT * RANKS_HEIGHT, 1.0).segment(RANK_Y * LOCAL_HEIGHT, LOCAL_HEIGHT)) + { + USED_WIDTH = LOCAL_WIDTH; + if (RANK_X == RANKS_WIDTH - 1) { + USED_WIDTH = GLOBAL_WIDTH - RANK_X * LOCAL_WIDTH; + } + USED_HEIGHT = LOCAL_HEIGHT; + if (RANK_Y == RANKS_HEIGHT - 1) { + USED_HEIGHT = GLOBAL_HEIGHT - RANK_Y * LOCAL_HEIGHT; + } + if (USED_WIDTH < MARGIN || USED_HEIGHT < MARGIN) { + std::cerr << "Invalid segmentation " << USED_WIDTH << "x" << USED_HEIGHT << "\n"; + std::abort(); + } + } + + // Number of rank matrix blocks + int32_t RANKS_TOTAL; + + // Number of rank matrix blocks per global matrix width + int32_t RANKS_WIDTH; + + // Number of rank matrix blocks per global matrix height + int32_t RANKS_HEIGHT; + + // Index of local rank + int32_t RANK_INDEX; + + // X coordinate of local rank's matrix block + int32_t RANK_X; + + // Y coordinate of local rank's matrix block + int32_t RANK_Y; + + // Width of entire matrix that is being distributed + int32_t GLOBAL_WIDTH; + + // Height of entire matrix that is being distributed + int32_t GLOBAL_HEIGHT; + + // Width of matrix block that is local to this rank + int32_t LOCAL_WIDTH; + + // Height of matrix block that is local to this rank + int32_t LOCAL_HEIGHT; + + // Width of matrix block that is used on this rank, i.e. without the extra cells on the right border + int32_t USED_WIDTH; + + // Height of matrix block that is used on this rank, i.e. without the extra cells on the bottom border + int32_t USED_HEIGHT; + + // Width of matrix that is local to this rank including margins + int32_t STORED_WIDTH; + + // Height of matrix that is local to this rank including margins + int32_t STORED_HEIGHT; + + // Margin around each local matrix for communication + int32_t MARGIN; + + // X coordinate spacing + Scalar DX; + + // Y coordinate spacing + Scalar DY; + + // X coordinates of entire global matrix + Vector GLOBAL_X; + + // Y coordinates of entire global matrix + Vector GLOBAL_Y; + + // X coordinates of local matrix block + Vector LOCAL_X; + + // Y coordinates of local matrix block + Vector LOCAL_Y; + +}; + +class DistributedVectorField2 { + DistributedConfig cfg; + std::reference_wrapper, 2>>> allMatrices; + std::vector> uv; + +public: + [[nodiscard]] explicit DistributedVectorField2(const VectorField2& o, std::vector, 2>>& allMatrices, DistributedConfig config) : + cfg(std::move(config)), + allMatrices(allMatrices) { + + for (Eigen::Index dim = 0; dim < 2; dim++) { + assert(cfg.GLOBAL_WIDTH == o[dim].cols() && cfg.GLOBAL_HEIGHT == o[dim].rows()); + allMatrices[cfg.RANK_INDEX][dim] = upcxx::allocate(cfg.STORED_WIDTH * cfg.STORED_HEIGHT, 256); + uv.emplace_back(Eigen::Map(allMatrices[cfg.RANK_INDEX][dim].local(), cfg.STORED_HEIGHT, cfg.STORED_WIDTH)); + for (Eigen::Index y = cfg.LOCAL_HEIGHT * cfg.RANK_Y; y < cfg.GLOBAL_HEIGHT && y < cfg.LOCAL_HEIGHT * (cfg.RANK_Y + 1); ++y) { + std::copy(o[dim].data() + y * cfg.GLOBAL_WIDTH + cfg.RANK_X * cfg.LOCAL_WIDTH, + o[dim].data() + y * cfg.GLOBAL_WIDTH + std::min(cfg.GLOBAL_WIDTH, (cfg.RANK_X + 1) * cfg.LOCAL_WIDTH), + uv[dim].data() + cfg.MARGIN + (y - cfg.RANK_Y * cfg.LOCAL_HEIGHT + cfg.MARGIN) * cfg.STORED_WIDTH); + } + } + } + + /** + * @return if x, y are in bounds + */ + [[nodiscard]] bool inBounds(Eigen::Index x, Eigen::Index y) { + if (x < 0) return false; + if (x >= cfg.RANKS_WIDTH) return false; + if (y < 0) return false; + if (y >= cfg.RANKS_HEIGHT) return false; + return true; + } + + /** + * Synchronize borders with a neighbour given an offset + * @return future for synchronization + */ + [[nodiscard]] upcxx::future<> synchronizeRight(UseCase useCase, Scalar mu, Scalar t) { + Eigen::Index otherX = cfg.RANK_X + 1; + Eigen::Index otherY = cfg.RANK_Y; + upcxx::future<> fut = upcxx::make_future(); + + if (inBounds(otherX, otherY)) { + for (Eigen::Index dim = 0; dim < 2; dim++) { + upcxx::global_ptr otherStart = allMatrices.get()[otherY * cfg.RANKS_WIDTH + otherX][dim] + cfg.STORED_WIDTH * cfg.MARGIN + cfg.MARGIN; + auto localStart = uv[dim].data() + cfg.USED_WIDTH + cfg.MARGIN + cfg.STORED_WIDTH * cfg.MARGIN; + fut = upcxx::when_all(fut, upcxx::rget_strided<2>(otherStart, + {{sizeof(Scalar), sizeof(Scalar) * cfg.STORED_WIDTH}}, + localStart, + {{sizeof(Scalar), sizeof(Scalar) * cfg.STORED_WIDTH}}, {{cfg.MARGIN, cfg.USED_HEIGHT}})); + } + } else { + + auto slice_x = Eigen::seq(cfg.USED_WIDTH - margin, cfg.USED_WIDTH - 1); + auto slice_y = Eigen::seq(0, cfg.USED_HEIGHT - 1); + VectorField2 uv_ex = solution_factory(useCase, mu, t, cfg.LOCAL_X, cfg.LOCAL_Y, slice_x, slice_y); + uv[0].block(cfg.MARGIN, cfg.MARGIN, cfg.USED_HEIGHT, cfg.USED_WIDTH)(slice_y, slice_x) = std::move(uv_ex[0]); + uv[1].block(cfg.MARGIN, cfg.MARGIN, cfg.USED_HEIGHT, cfg.USED_WIDTH)(slice_y, slice_x) = std::move(uv_ex[1]); + } + return fut; + } + + [[nodiscard]] upcxx::future<> synchronizeLeft(UseCase useCase, Scalar mu, Scalar t) { + Eigen::Index otherX = cfg.RANK_X - 1; + Eigen::Index otherY = cfg.RANK_Y; + upcxx::future<> fut = upcxx::make_future(); + + if (inBounds(otherX, otherY)) { + + for (Eigen::Index dim = 0; dim < 2; dim++) { + upcxx::global_ptr otherStart = allMatrices.get()[otherY * cfg.RANKS_WIDTH + otherX][dim] + cfg.LOCAL_WIDTH + cfg.STORED_WIDTH * cfg.MARGIN; + auto localStart = uv[dim].data() + cfg.STORED_WIDTH * cfg.MARGIN; + fut = upcxx::when_all(fut, upcxx::rget_strided<2>(otherStart, + {{sizeof(Scalar), sizeof(Scalar) * cfg.STORED_WIDTH}}, + localStart, + {{sizeof(Scalar), sizeof(Scalar) * cfg.STORED_WIDTH}}, {{cfg.MARGIN, cfg.USED_HEIGHT}})); + } + } else { + + auto slice_x = Eigen::seq(0, cfg.MARGIN - 1); + auto slice_y = Eigen::seq(0, cfg.USED_HEIGHT - 1); + VectorField2 uv_ex = solution_factory(useCase, mu, t, cfg.LOCAL_X, cfg.LOCAL_Y, slice_x, slice_y); + uv[0].block(cfg.MARGIN, cfg.MARGIN, cfg.USED_HEIGHT, cfg.USED_WIDTH)(slice_y, slice_x) = std::move(uv_ex[0]); + uv[1].block(cfg.MARGIN, cfg.MARGIN, cfg.USED_HEIGHT, cfg.USED_WIDTH)(slice_y, slice_x) = std::move(uv_ex[1]); + } + return fut; + } + + [[nodiscard]] upcxx::future<> synchronizeUp(UseCase useCase, Scalar mu, Scalar t) { + Eigen::Index otherX = cfg.RANK_X; + Eigen::Index otherY = cfg.RANK_Y - 1; + upcxx::future<> fut = upcxx::make_future(); + if (inBounds(otherX, otherY)) { + + for (Eigen::Index dim = 0; dim < 2; dim++) { + upcxx::global_ptr otherStart = allMatrices.get()[otherY * cfg.RANKS_WIDTH + otherX][dim] + cfg.MARGIN + cfg.STORED_WIDTH * cfg.LOCAL_HEIGHT; + auto localStart = uv[dim].data() + cfg.MARGIN; + fut = upcxx::when_all(fut, upcxx::rget_strided<2>(otherStart, + {{sizeof(Scalar), sizeof(Scalar) * cfg.STORED_WIDTH}}, + localStart, + {{sizeof(Scalar), sizeof(Scalar) * cfg.STORED_WIDTH}}, {{cfg.USED_WIDTH, cfg.MARGIN}})); + } + } else { + + auto slice_x = Eigen::seq(0, cfg.USED_WIDTH - 1); + auto slice_y = Eigen::seq(0, cfg.MARGIN - 1); + VectorField2 uv_ex = solution_factory(useCase, mu, t, cfg.LOCAL_X, cfg.LOCAL_Y, slice_x, slice_y); + uv[0].block(cfg.MARGIN, cfg.MARGIN, cfg.USED_HEIGHT, cfg.USED_WIDTH)(slice_y, slice_x) = std::move(uv_ex[0]); + uv[1].block(cfg.MARGIN, cfg.MARGIN, cfg.USED_HEIGHT, cfg.USED_WIDTH)(slice_y, slice_x) = std::move(uv_ex[1]); + } + return fut; + } + + [[nodiscard]] upcxx::future<> synchronizeDown(UseCase useCase, Scalar mu, Scalar t) { + Eigen::Index otherX = cfg.RANK_X; + Eigen::Index otherY = cfg.RANK_Y + 1; + upcxx::future<> fut = upcxx::make_future(); + if (inBounds(otherX, otherY)) { + + for (Eigen::Index dim = 0; dim < 2; dim++) { + upcxx::global_ptr otherStart = allMatrices.get()[otherY * cfg.RANKS_WIDTH + otherX][dim] + cfg.MARGIN + cfg.MARGIN * cfg.STORED_WIDTH; + auto localStart = uv[dim].data() + cfg.MARGIN + cfg.STORED_WIDTH * (cfg.MARGIN + cfg.USED_HEIGHT); + fut = upcxx::when_all(fut, upcxx::rget_strided<2>(otherStart, + {{sizeof(Scalar), sizeof(Scalar) * cfg.STORED_WIDTH}}, + localStart, + {{sizeof(Scalar), sizeof(Scalar) * cfg.STORED_WIDTH}}, {{cfg.USED_WIDTH, cfg.MARGIN}})); + } + } else { + + auto slice_x = Eigen::seq(0, cfg.USED_WIDTH - 1); + auto slice_y = Eigen::seq(cfg.USED_HEIGHT - cfg.MARGIN, cfg.USED_HEIGHT - 1); + VectorField2 uv_ex = solution_factory(useCase, mu, t, cfg.LOCAL_X, cfg.LOCAL_Y, slice_x, slice_y); + uv[0].block(cfg.MARGIN, cfg.MARGIN, cfg.USED_HEIGHT, cfg.USED_WIDTH)(slice_y, slice_x) = std::move(uv_ex[0]); + uv[1].block(cfg.MARGIN, cfg.MARGIN, cfg.USED_HEIGHT, cfg.USED_WIDTH)(slice_y, slice_x) = std::move(uv_ex[1]); + } + return fut; + } + + [[nodiscard]] Eigen::Map const& operator[](int i) const noexcept { assert(0 <= i && i < 2); return uv[i]; } + [[nodiscard]] Eigen::Map & operator[](int i) noexcept { assert(0 <= i && i < 2); return uv[i]; } + + [[nodiscard]] Eigen::Index rows() const noexcept { return uv[0].rows(); } + [[nodiscard]] Eigen::Index cols() const noexcept { return uv[0].cols(); } +}; + +[[nodiscard]] constexpr Scalar advection(Scalar d, Scalar w, Vectoroid auto const& phiSlice) { + return + ( w * AdvectionStencil1::apply(phiSlice) + - std::abs(w) * AdvectionStencil2::apply(phiSlice)) / (60 * d); +} +template +void advection(Vectoroid auto const& d, Matrixoid auto const& w, Matrixoid auto const& phi, Matrixoid auto& out, std::invocable auto assignment) { + const int nx = w.cols(), ny = w.rows(); + assert(phi.cols() == nx && phi.rows() == ny); + assert(out.cols() == nx && out.rows() == ny); + for(int x = margin; x < nx - margin; ++x) + for(int y = margin; y < ny - margin; ++y) + assignment(out(y, x), advection(d[advectRank], w(y, x), rank1Slice(phi, y, x))); +} +void advection(Vectoroid auto const& d, VectorField auto const& uv, VectorField auto& adv) { + advection<1>(d, uv[0], uv[0], adv[0], [](Scalar& lhs, Scalar rhs) constexpr noexcept { lhs = rhs; }); + advection<0>(d, uv[1], uv[0], adv[0], [](Scalar& lhs, Scalar rhs) constexpr noexcept { lhs += rhs; }); + + advection<1>(d, uv[0], uv[1], adv[1], [](Scalar& lhs, Scalar rhs) constexpr noexcept { lhs = rhs; }); + advection<0>(d, uv[1], uv[1], adv[1], [](Scalar& lhs, Scalar rhs) constexpr noexcept { lhs += rhs; }); +} + +[[nodiscard]] constexpr Scalar diffusion(Scalar d, Vectoroid auto const& phiSlice) { + return 1 / (12 * sq(d)) * DiffusionStencil::apply(phiSlice); +} +template +void diffusion(Vectoroid auto const& d, Matrixoid auto const& phi, Matrixoid auto& out, std::invocable auto assignment) { + const int nx = phi.cols(), ny = phi.rows(); + assert(out.cols() == nx && out.rows() == ny); + for(int x = margin; x < nx - margin; ++x) + for(int y = margin; y < ny - margin; ++y) + assignment(out(y, x), diffusion(d[diffuseRank], rank1Slice(phi, y, x))); +} +void diffusion(Vectoroid auto const& d, VectorField auto const& uv, VectorField auto& diff) { + diffusion<1>(d, uv[0], diff[0], [](Scalar& lhs, Scalar rhs) constexpr noexcept { lhs = rhs; }); + diffusion<0>(d, uv[0], diff[0], [](Scalar& lhs, Scalar rhs) constexpr noexcept { lhs += rhs; }); + + diffusion<1>(d, uv[1], diff[1], [](Scalar& lhs, Scalar rhs) constexpr noexcept { lhs = rhs; }); + diffusion<0>(d, uv[1], diff[1], [](Scalar& lhs, Scalar rhs) constexpr noexcept { lhs += rhs; }); +} + +void rk_stage( + Scalar mu, + VectorField auto const& in_now, + VectorField auto const& in_tmp, + VectorField auto& out, + VectorField auto& adv, + VectorField auto& diff, + Scalar dt, + Vectoroid auto const& d +) { + advection(d, in_tmp, adv); + diffusion(d, in_tmp, diff); + out[0] = in_now[0] + dt * (-adv[0] + mu * diff[0]); + out[1] = in_now[1] + dt * (-adv[1] + mu * diff[1]); +} + + +// TODO: only a makeshift because my stdlib doesn't implement this +template +std::basic_ostream& operator<<(std::basic_ostream& os, std::chrono::duration const& d) { + std::basic_ostringstream s; + s.flags(os.flags()); + s.imbue(os.getloc()); + s.precision(os.precision()); + s << d.count(); + if constexpr(std::is_same_v) s << "ns"; + else if constexpr(std::is_same_v) s << "µs"; + else if constexpr(std::is_same_v) s << "ms"; + else if constexpr(std::is_same_v>) s << "s"; + else { + s << '[' << Period::type::num; + if constexpr(Period::type::den != 1) + s << '/' << Period::type::den; + s << ']'; + } + return os << s.str(); +} + +template +struct WelfordVariance { + std::size_t n = 0; + T mean{}; + T m{}; + + constexpr void update(T const& x) { + ++n; + const T old_mean = mean; + mean = ((n - 1) * old_mean + x) / n; + m += (x - old_mean) * (x - mean); + } + + [[nodiscard]] constexpr T variance() { return m / n; } + [[nodiscard]] constexpr T sample_variance() { return m / (n - 1); } +}; + +struct BenchmarkReport { + using Duration = std::chrono::duration; + + Duration best; + Duration average; + Duration variance; + unsigned runs; +}; +std::ostream& operator<<(std::ostream& stream, BenchmarkReport const& report) { + stream << "runtime: " << report.average << " ± " << std::sqrt(report.variance.count()) << "ms" << "; best: " << report.best << "; n=" << report.runs << '\n'; + return stream; +} + +template +[[nodiscard]] BenchmarkReport benchmark(Invocable&& invocable, unsigned streak, Clock clock) { + assert(streak > 0); + BenchmarkReport result; + WelfordVariance variance; + result.best = BenchmarkReport::Duration(std::numeric_limits::max()); + for(unsigned current_streak = 0; current_streak < streak; ) { + upcxx::barrier(); + const auto start = clock.now(); + invocable(); + const auto end = clock.now(); + auto duration = std::chrono::duration_cast(end - start); + upcxx::barrier(); + duration = upcxx::broadcast(duration, 0).wait(); + if(duration < result.best) { + result.best = duration; + current_streak = 0; + } else { + ++current_streak; + } + variance.update(duration.count()); + } + result.average = BenchmarkReport::Duration(variance.mean); + result.variance = BenchmarkReport::Duration(variance.sample_variance()); + result.runs = variance.n; + return result; +} +template +[[nodiscard]] BenchmarkReport benchmark(Invocable&& invocable, unsigned streak = 20) { + if constexpr(std::chrono::high_resolution_clock::is_steady) + return benchmark(std::forward(invocable), streak, std::chrono::high_resolution_clock{}); + else + return benchmark(std::forward(invocable), streak, std::chrono::steady_clock{}); +} + +int main(int argc, char **argv) { + + if (argc != 5) { + std::cerr << "Usage: " << argv[0] << " " << std::endl; + return 2; + } + // use case + constexpr UseCase useCase = zhao; + + // diffusion coefficient + const Scalar mu = 0.1; + + // grid + const int factor = std::stol(argv[1]); + const uint32_t coreWidth = std::stol(argv[2]); + const uint32_t coreHeight = std::stol(argv[3]); + upcxx::init(); + const uint32_t coreIndex = upcxx::rank_me(); + const DistributedConfig cfg(factor, factor, coreWidth, coreHeight, coreIndex, margin); + + if (coreWidth * coreHeight != upcxx::rank_n()) { + std::cerr << "Using invalid number of ranks\n"; + return 1; + } + + // time + const Scalar cfl = 1; + const Scalar timestep = cfl / sq(cfg.GLOBAL_WIDTH-1); + const Scalar n_iter = sq(cfg.GLOBAL_WIDTH-1) * std::stol(argv[4]) / 1000; + // output + const int print_period = 0; + // vector fields + + const auto syncMatrices = [](std::vector, 2>>& mats) { + for (uint32_t i = 0; i < mats.size(); i++) { + mats[i] = upcxx::broadcast(mats[i], i).wait(); + } + }; + + const auto single_threaded_task = [&]{ + + std::vector, 2>> allMatricesNow(cfg.RANKS_TOTAL); + DistributedVectorField2 uv_now(VectorField2(cfg.GLOBAL_HEIGHT, cfg.GLOBAL_WIDTH, 0), allMatricesNow, cfg); + syncMatrices(allMatricesNow); + + std::vector, 2>> allMatricesNew(cfg.RANKS_TOTAL); + DistributedVectorField2 uv_new(initial_solution(useCase, mu, cfg.GLOBAL_X, cfg.GLOBAL_Y), allMatricesNew, cfg); + syncMatrices(allMatricesNew); + + upcxx::barrier(); + upcxx::when_all(uv_new.synchronizeRight(useCase, mu, 0), uv_new.synchronizeLeft(useCase, mu, 0), uv_new.synchronizeUp(useCase, mu, 0), uv_new.synchronizeDown(useCase, mu, 0)).wait(); + upcxx::barrier(); + + VectorField2 adv(uv_now[0].rows(), uv_now[0].cols(), 0); + VectorField2 diff(uv_now[0].rows(), uv_now[0].cols(), 0); + + const auto rk_fractions = { 1.0 / 3, 1.0 / 2, 1.0 }; + Scalar t = 0; + + for(int i = 0; i < n_iter; ++i) { + uv_now = uv_new; + + for(const double rk_fraction : rk_fractions) { + const Scalar dt = rk_fraction * timestep; + rk_stage(mu, uv_now, uv_new, uv_new, adv, diff, dt, Vector2{ cfg.DX, cfg.DY }); + upcxx::barrier(); + upcxx::when_all(uv_new.synchronizeRight(useCase, mu, t + dt), uv_new.synchronizeLeft(useCase, mu, t + dt), uv_new.synchronizeUp(useCase, mu, t + dt), uv_new.synchronizeDown(useCase, mu, t + dt)).wait(); + upcxx::barrier(); + } + + t += timestep; + if(print_period > 0 && ((i+1) % print_period == 0 || i+1 == n_iter)) { + VectorField2 uv_ex = solution_factory(useCase, mu, t, cfg.LOCAL_X.segment(0, cfg.USED_WIDTH), cfg.LOCAL_Y.segment(0, cfg.USED_HEIGHT)); + const Scalar local_err_u = (uv_new[0].block(cfg.MARGIN, cfg.MARGIN, cfg.USED_HEIGHT, cfg.USED_WIDTH) - uv_ex[0]).squaredNorm() * cfg.DX * cfg.DY; + const Scalar local_err_v = (uv_new[1].block(cfg.MARGIN, cfg.MARGIN, cfg.USED_HEIGHT, cfg.USED_WIDTH) - uv_ex[1]).squaredNorm() * cfg.DX * cfg.DY; + const Scalar err_u = std::sqrt(upcxx::reduce_all(local_err_u, std::plus()).wait()); + const Scalar err_v = std::sqrt(upcxx::reduce_all(local_err_v, std::plus()).wait()); + upcxx::barrier(); + if (cfg.RANK_INDEX == 0) { + std::cout << "Iteration " << std::right << std::setfill(' ') << std::setw(6) << i + 1; + std::cout << std::scientific << std::setprecision(4); + std::cout << ": ||u - uex|| = " << err_u << " m/s, ||v - vex|| = " << err_v << " m/s\n"; + std::cout << std::defaultfloat; + } + } + } + }; + if (upcxx::rank_me() == 0) { + std::cout << "Time: " << benchmark(single_threaded_task); + } else { + benchmark(single_threaded_task); + } + + upcxx::finalize(); +} diff --git a/projects/2021/groupK_burgers_openmp/branch-upcxx/upcxx_small_grid b/projects/2021/groupK_burgers_openmp/branch-upcxx/upcxx_small_grid new file mode 100644 index 00000000..bd7c891b --- /dev/null +++ b/projects/2021/groupK_burgers_openmp/branch-upcxx/upcxx_small_grid @@ -0,0 +1,10 @@ +Time: runtime: 5799.27ms ± 75.6701ms; best: 5678.92ms; n=33 +Time: runtime: 2074.05ms ± 46.3968ms; best: 1990.05ms; n=47 +Time: runtime: 1692.26ms ± 48.7114ms; best: 1609.17ms; n=43 +Time: runtime: 1392.18ms ± 57.8365ms; best: 1301.65ms; n=33 +Time: runtime: 1303.88ms ± 95.567ms; best: 1180.74ms; n=36 +Time: runtime: 5788.49ms ± 71.2364ms; best: 5660.38ms; n=45 +Time: runtime: 3537.47ms ± 59.8368ms; best: 3432.72ms; n=49 +Time: runtime: 2434.85ms ± 38.4084ms; best: 2382.31ms; n=30 +Time: runtime: 1802.55ms ± 97.6827ms; best: 1615.69ms; n=23 +Time: runtime: 1787.4ms ± 43.9987ms; best: 1720.63ms; n=48 diff --git a/projects/2021/groupK_burgers_openmp/branch-upcxx/upcxx_strong_scaling b/projects/2021/groupK_burgers_openmp/branch-upcxx/upcxx_strong_scaling new file mode 100644 index 00000000..f53c8111 --- /dev/null +++ b/projects/2021/groupK_burgers_openmp/branch-upcxx/upcxx_strong_scaling @@ -0,0 +1,10 @@ +Time: runtime: 4279.9ms ± 134.979ms; best: 4030.75ms; n=59 +Time: runtime: 1100.13ms ± 28.4733ms; best: 1066.17ms; n=35 +Time: runtime: 800.246ms ± 44.5372ms; best: 753.12ms; n=28 +Time: runtime: 546.107ms ± 17.7146ms; best: 521.13ms; n=27 +Time: runtime: 497.132ms ± 43.4852ms; best: 443.236ms; n=37 +Time: runtime: 4401.04ms ± 132.005ms; best: 4201.34ms; n=29 +Time: runtime: 2190.8ms ± 45.1649ms; best: 2107.44ms; n=38 +Time: runtime: 1183.65ms ± 24.1417ms; best: 1148.65ms; n=45 +Time: runtime: 725.589ms ± 21.6998ms; best: 688.194ms; n=60 +Time: runtime: 594.244ms ± 45.5923ms; best: 564.256ms; n=32 From 114bc60bb3868f8e7ae834e994905fe3c41ec930 Mon Sep 17 00:00:00 2001 From: DeinFreund Date: Mon, 20 Sep 2021 22:32:12 +0200 Subject: [PATCH 2/2] Fix the tabs --- .../branch-upcxx/main.cpp | 500 +++++++++--------- 1 file changed, 250 insertions(+), 250 deletions(-) diff --git a/projects/2021/groupK_burgers_openmp/branch-upcxx/main.cpp b/projects/2021/groupK_burgers_openmp/branch-upcxx/main.cpp index 9067fe9b..5c7e07ce 100644 --- a/projects/2021/groupK_burgers_openmp/branch-upcxx/main.cpp +++ b/projects/2021/groupK_burgers_openmp/branch-upcxx/main.cpp @@ -21,9 +21,9 @@ using Scalar = double; using TemplateParamScalar = #if __cpp_nontype_template_args >= 201911 - Scalar + Scalar #else - long int + long int #endif ; // using Vector3 = Eigen::Matrix; @@ -35,80 +35,80 @@ template concept Tensoroid = true; // CBA template concept Matrixoid = requires(T const& m) { - { m(0, 0) } -> std::convertible_to; - { m.rows() } -> std::integral; - { m.cols() } -> std::integral; - // more stuff but CBA + { m(0, 0) } -> std::convertible_to; + { m.rows() } -> std::integral; + { m.cols() } -> std::integral; + // more stuff but CBA }; template concept VectorField = requires(T const& m) { - { m[0](0, 0) } -> std::convertible_to; - { m[0] } -> Matrixoid; - { m.rows() } -> std::integral; - { m.cols() } -> std::integral; - // more stuff but CBA + { m[0](0, 0) } -> std::convertible_to; + { m[0] } -> Matrixoid; + { m.rows() } -> std::integral; + { m.cols() } -> std::integral; + // more stuff but CBA }; template concept Vectoroid = requires(T const& v) { - { v[0] } -> std::convertible_to; - // more stuff but CBA + { v[0] } -> std::convertible_to; + // more stuff but CBA }; namespace Detail { - template - struct IsEigenSequence : std::false_type {}; - template - struct IsEigenSequence> : std::true_type {}; + template + struct IsEigenSequence : std::false_type {}; + template + struct IsEigenSequence> : std::true_type {}; } template concept Sequenceoid = Detail::IsEigenSequence::value; template [[nodiscard]] constexpr T sq(T const& x) { - return x * x; + return x * x; } [[nodiscard]] constexpr auto absi(std::signed_integral auto x) noexcept { - assert(x != std::numeric_limits::min()); - return x < 0 ? -x : x; + assert(x != std::numeric_limits::min()); + return x < 0 ? -x : x; } [[nodiscard]] constexpr auto absi(std::unsigned_integral auto x) noexcept { - return x; + return x; } [[nodiscard]] constexpr unsigned exp2i(unsigned x) noexcept { - assert(x < std::numeric_limits::digits); - return 1<::digits); + return 1<; template struct ScopeGuard { - Invocable invocable; - [[nodiscard]] explicit constexpr ScopeGuard(Invocable&& invocable) noexcept(std::is_nothrow_move_constructible_v) : invocable(std::move(invocable)) {} - [[nodiscard]] explicit constexpr ScopeGuard(Invocable const& invocable) noexcept(std::is_nothrow_copy_constructible_v) : invocable(invocable) {} - constexpr ~ScopeGuard() noexcept(std::is_nothrow_invocable_v) { invocable(); } + Invocable invocable; + [[nodiscard]] explicit constexpr ScopeGuard(Invocable&& invocable) noexcept(std::is_nothrow_move_constructible_v) : invocable(std::move(invocable)) {} + [[nodiscard]] explicit constexpr ScopeGuard(Invocable const& invocable) noexcept(std::is_nothrow_copy_constructible_v) : invocable(invocable) {} + constexpr ~ScopeGuard() noexcept(std::is_nothrow_invocable_v) { invocable(); } }; template struct Rank1Slice { - Tensor* tensor; - std::array position; - - [[nodiscard]] constexpr Rank1Slice(Tensor& tensor, std::convertible_to auto const&... indices) - : tensor(std::addressof(tensor)), position{ indices... } { - static_assert(sizeof...(indices) == ranks); - } - - // not multi-thread friendly - [[nodiscard]] constexpr decltype(auto) operator[](IndexType i) const { - assert(tensor); - const_cast(this)->position[slicedRank] += i; - const ScopeGuard restore([this, i]{ const_cast(this)->position[slicedRank] -= i; }); - return std::apply(*tensor, position); - } + Tensor* tensor; + std::array position; + + [[nodiscard]] constexpr Rank1Slice(Tensor& tensor, std::convertible_to auto const&... indices) + : tensor(std::addressof(tensor)), position{ indices... } { + static_assert(sizeof...(indices) == ranks); + } + + // not multi-thread friendly + [[nodiscard]] constexpr decltype(auto) operator[](IndexType i) const { + assert(tensor); + const_cast(this)->position[slicedRank] += i; + const ScopeGuard restore([this, i]{ const_cast(this)->position[slicedRank] -= i; }); + return std::apply(*tensor, position); + } }; template [[nodiscard]] constexpr auto rank1Slice(Tensoroid auto& tensor, std::integral auto const&... indices) { - return Rank1Slice, sizeof...(indices), slicedRank, std::common_type_t...>>(tensor, indices...); + return Rank1Slice, sizeof...(indices), slicedRank, std::common_type_t...>>(tensor, indices...); } template typename F, typename I, typename... Args> @@ -120,8 +120,8 @@ struct FoldR : std::type_identity struct IndexCoeffPair { - static constexpr auto index = index_; - static constexpr auto factor = factor_; + static constexpr auto index = index_; + static constexpr auto factor = factor_; }; template struct IsIndexCoeffPair : std::false_type {}; @@ -138,96 +138,96 @@ struct IndexMax : std::type_identity Rhs::index enum class StencilType { asymmetric, symmetric, antisymmetric }; template struct Stencil /* 1D only */ { - static constexpr auto min_index = FoldR::max(), {}>, Pairs...>::type::index; - static constexpr auto max_index = FoldR::min(), {}>, Pairs...>::type::index; - - static constexpr auto left = type == StencilType::asymmetric ? min_index : -std::max(absi(min_index), max_index); - static constexpr auto right = type == StencilType::asymmetric ? max_index : std::max(absi(min_index), max_index); - static constexpr auto margin = sizeof...(Pairs) > 0 ? std::max(absi(left), right) : 0; - - [[nodiscard]] static constexpr auto apply(Vectoroid auto&& vector) { - switch(type) { - case StencilType::asymmetric: - return ((Pairs::factor * vector[Pairs::index]) + ...); - case StencilType::symmetric: - return ((Pairs::factor * (Pairs::index ? vector[Pairs::index] + vector[-Pairs::index] : vector[Pairs::index])) + ...); - case StencilType::antisymmetric: - return ((Pairs::factor * (Pairs::index ? vector[Pairs::index] - vector[-Pairs::index] : vector[Pairs::index])) + ...); - }; - } + static constexpr auto min_index = FoldR::max(), {}>, Pairs...>::type::index; + static constexpr auto max_index = FoldR::min(), {}>, Pairs...>::type::index; + + static constexpr auto left = type == StencilType::asymmetric ? min_index : -std::max(absi(min_index), max_index); + static constexpr auto right = type == StencilType::asymmetric ? max_index : std::max(absi(min_index), max_index); + static constexpr auto margin = sizeof...(Pairs) > 0 ? std::max(absi(left), right) : 0; + + [[nodiscard]] static constexpr auto apply(Vectoroid auto&& vector) { + switch(type) { + case StencilType::asymmetric: + return ((Pairs::factor * vector[Pairs::index]) + ...); + case StencilType::symmetric: + return ((Pairs::factor * (Pairs::index ? vector[Pairs::index] + vector[-Pairs::index] : vector[Pairs::index])) + ...); + case StencilType::antisymmetric: + return ((Pairs::factor * (Pairs::index ? vector[Pairs::index] - vector[-Pairs::index] : vector[Pairs::index])) + ...); + }; + } }; using AdvectionStencil1 = Stencil, - IndexCoeffPair<2, TemplateParamScalar(- 9)>, - IndexCoeffPair<3, TemplateParamScalar( 1)>>; + IndexCoeffPair<1, TemplateParamScalar( 45)>, + IndexCoeffPair<2, TemplateParamScalar(- 9)>, + IndexCoeffPair<3, TemplateParamScalar( 1)>>; using AdvectionStencil2 = Stencil, - IndexCoeffPair<1, TemplateParamScalar( 15)>, - IndexCoeffPair<2, TemplateParamScalar(- 6)>, - IndexCoeffPair<3, TemplateParamScalar( 1)>>; + IndexCoeffPair<0, TemplateParamScalar(-20)>, + IndexCoeffPair<1, TemplateParamScalar( 15)>, + IndexCoeffPair<2, TemplateParamScalar(- 6)>, + IndexCoeffPair<3, TemplateParamScalar( 1)>>; using DiffusionStencil = Stencil, - IndexCoeffPair<1, TemplateParamScalar( 16)>, - IndexCoeffPair<2, TemplateParamScalar(- 1)>>; + IndexCoeffPair<0, TemplateParamScalar(-30)>, + IndexCoeffPair<1, TemplateParamScalar( 16)>, + IndexCoeffPair<2, TemplateParamScalar(- 1)>>; constexpr int margin = std::max({ AdvectionStencil1::margin, AdvectionStencil2::margin, DiffusionStencil::margin }); enum UseCase { zhao, hopf_cole }; class VectorField2 { - Matrix uv[2]; + Matrix uv[2]; public: - [[nodiscard]] VectorField2() = default; - [[nodiscard]] explicit VectorField2(Eigen::Index rows, Eigen::Index cols) - : uv{ Matrix(rows, cols), Matrix(rows, cols) } { - } - [[nodiscard]] explicit VectorField2(Eigen::Index rows, Eigen::Index cols, Scalar fill) - : uv{ Matrix::Constant(rows, cols, fill), Matrix::Constant(rows, cols, fill) } { - } - - [[nodiscard]] constexpr Matrix const& operator[](int i) const noexcept { assert(0 <= i && i < 2); return uv[i]; } - [[nodiscard]] constexpr Matrix & operator[](int i) noexcept { assert(0 <= i && i < 2); return uv[i]; } - - [[nodiscard]] constexpr Eigen::Index rows() const noexcept { return uv[0].rows(); } - [[nodiscard]] constexpr Eigen::Index cols() const noexcept { return uv[0].cols(); } + [[nodiscard]] VectorField2() = default; + [[nodiscard]] explicit VectorField2(Eigen::Index rows, Eigen::Index cols) + : uv{ Matrix(rows, cols), Matrix(rows, cols) } { + } + [[nodiscard]] explicit VectorField2(Eigen::Index rows, Eigen::Index cols, Scalar fill) + : uv{ Matrix::Constant(rows, cols, fill), Matrix::Constant(rows, cols, fill) } { + } + + [[nodiscard]] constexpr Matrix const& operator[](int i) const noexcept { assert(0 <= i && i < 2); return uv[i]; } + [[nodiscard]] constexpr Matrix & operator[](int i) noexcept { assert(0 <= i && i < 2); return uv[i]; } + + [[nodiscard]] constexpr Eigen::Index rows() const noexcept { return uv[0].rows(); } + [[nodiscard]] constexpr Eigen::Index cols() const noexcept { return uv[0].cols(); } }; [[nodiscard]] constexpr VectorField2 solution_factory(UseCase useCase, Scalar mu, Scalar t, Matrixoid auto const& x, Matrixoid auto const& y, Sequenceoid auto slice_x, Sequenceoid auto slice_y) { - const int mi = slice_x.size() ? slice_x[slice_x.size() - 1] - slice_x[0] + 1 : 0; - const int mj = slice_y.size() ? slice_y[slice_y.size() - 1] - slice_y[0] + 1 : 0; + const int mi = slice_x.size() ? slice_x[slice_x.size() - 1] - slice_x[0] + 1 : 0; + const int mj = slice_y.size() ? slice_y[slice_y.size() - 1] - slice_y[0] + 1 : 0; - const Matrixoid auto x2d = x(slice_x).transpose().replicate(mj, 1); - const Matrixoid auto y2d = y(slice_y).replicate(1, mi); + const Matrixoid auto x2d = x(slice_x).transpose().replicate(mj, 1); + const Matrixoid auto y2d = y(slice_y).replicate(1, mi); - const int nx = x2d.cols(), ny = x2d.rows(); + const int nx = x2d.cols(), ny = x2d.rows(); assert(nx == slice_x.size()); - assert(y2d.cols() == nx && y2d.rows() == ny); - - using std::exp; - VectorField2 result; - switch(useCase) { - case zhao: - result[0] = -4 * mu * pi * exp(-5 * sq(pi) * mu * t) * (2 * pi * x2d).array().cos() * (pi * y2d).array().sin() / (2 + exp(-5 * sq(pi) * mu * t) * (2 * pi * x2d).array().sin() * (pi * y2d).array().sin()); - result[1] = -2 * mu * pi * exp(-5 * sq(pi) * mu * t) * (2 * pi * x2d).array().sin() * (pi * y2d).array().cos() / (2 + exp(-5 * sq(pi) * mu * t) * (2 * pi * x2d).array().sin() * (pi * y2d).array().sin()); - break; - case hopf_cole: - result[0] = 0.75 - 1 / (4 * (1 + (-Matrix::Constant(x2d.rows(), x2d.cols(), t) - 4 * x2d + 4 * y2d).array().exp() / (32 * mu))); - result[1] = 0.75 + 1 / (4 * (1 + (-Matrix::Constant(x2d.rows(), x2d.cols(), t) - 4 * x2d + 4 * y2d).array().exp() / (32 * mu))); - break; - default: - assert(false); - } - return result; + assert(y2d.cols() == nx && y2d.rows() == ny); + + using std::exp; + VectorField2 result; + switch(useCase) { + case zhao: + result[0] = -4 * mu * pi * exp(-5 * sq(pi) * mu * t) * (2 * pi * x2d).array().cos() * (pi * y2d).array().sin() / (2 + exp(-5 * sq(pi) * mu * t) * (2 * pi * x2d).array().sin() * (pi * y2d).array().sin()); + result[1] = -2 * mu * pi * exp(-5 * sq(pi) * mu * t) * (2 * pi * x2d).array().sin() * (pi * y2d).array().cos() / (2 + exp(-5 * sq(pi) * mu * t) * (2 * pi * x2d).array().sin() * (pi * y2d).array().sin()); + break; + case hopf_cole: + result[0] = 0.75 - 1 / (4 * (1 + (-Matrix::Constant(x2d.rows(), x2d.cols(), t) - 4 * x2d + 4 * y2d).array().exp() / (32 * mu))); + result[1] = 0.75 + 1 / (4 * (1 + (-Matrix::Constant(x2d.rows(), x2d.cols(), t) - 4 * x2d + 4 * y2d).array().exp() / (32 * mu))); + break; + default: + assert(false); + } + return result; } [[nodiscard]] constexpr decltype(auto) solution_factory(UseCase useCase, Scalar mu, Scalar t, Matrixoid auto const& x, Matrixoid auto const& y) { - return solution_factory(useCase, mu, t, x, y, Eigen::seq(0, x.size() - 1), Eigen::seq(0, y.size() - 1)); + return solution_factory(useCase, mu, t, x, y, Eigen::seq(0, x.size() - 1), Eigen::seq(0, y.size() - 1)); } [[nodiscard]] constexpr VectorField2 initial_solution(UseCase useCase, Scalar mu, Matrixoid auto const& x, Matrixoid auto const& y) { - return solution_factory(useCase, mu, 0, x, y); + return solution_factory(useCase, mu, 0, x, y); } Vector padVector(Vectoroid auto input, int targetLength, Scalar paddingValue){ @@ -320,22 +320,22 @@ struct DistributedConfig { int32_t MARGIN; // X coordinate spacing - Scalar DX; + Scalar DX; // Y coordinate spacing - Scalar DY; + Scalar DY; // X coordinates of entire global matrix - Vector GLOBAL_X; + Vector GLOBAL_X; // Y coordinates of entire global matrix - Vector GLOBAL_Y; + Vector GLOBAL_Y; // X coordinates of local matrix block - Vector LOCAL_X; + Vector LOCAL_X; // Y coordinates of local matrix block - Vector LOCAL_Y; + Vector LOCAL_Y; }; @@ -345,7 +345,7 @@ class DistributedVectorField2 { std::vector> uv; public: - [[nodiscard]] explicit DistributedVectorField2(const VectorField2& o, std::vector, 2>>& allMatrices, DistributedConfig config) : + [[nodiscard]] explicit DistributedVectorField2(const VectorField2& o, std::vector, 2>>& allMatrices, DistributedConfig config) : cfg(std::move(config)), allMatrices(allMatrices) { @@ -359,7 +359,7 @@ class DistributedVectorField2 { uv[dim].data() + cfg.MARGIN + (y - cfg.RANK_Y * cfg.LOCAL_HEIGHT + cfg.MARGIN) * cfg.STORED_WIDTH); } } - } + } /** * @return if x, y are in bounds @@ -477,155 +477,155 @@ class DistributedVectorField2 { return fut; } - [[nodiscard]] Eigen::Map const& operator[](int i) const noexcept { assert(0 <= i && i < 2); return uv[i]; } - [[nodiscard]] Eigen::Map & operator[](int i) noexcept { assert(0 <= i && i < 2); return uv[i]; } + [[nodiscard]] Eigen::Map const& operator[](int i) const noexcept { assert(0 <= i && i < 2); return uv[i]; } + [[nodiscard]] Eigen::Map & operator[](int i) noexcept { assert(0 <= i && i < 2); return uv[i]; } - [[nodiscard]] Eigen::Index rows() const noexcept { return uv[0].rows(); } - [[nodiscard]] Eigen::Index cols() const noexcept { return uv[0].cols(); } + [[nodiscard]] Eigen::Index rows() const noexcept { return uv[0].rows(); } + [[nodiscard]] Eigen::Index cols() const noexcept { return uv[0].cols(); } }; [[nodiscard]] constexpr Scalar advection(Scalar d, Scalar w, Vectoroid auto const& phiSlice) { - return - ( w * AdvectionStencil1::apply(phiSlice) - - std::abs(w) * AdvectionStencil2::apply(phiSlice)) / (60 * d); + return + ( w * AdvectionStencil1::apply(phiSlice) + - std::abs(w) * AdvectionStencil2::apply(phiSlice)) / (60 * d); } template void advection(Vectoroid auto const& d, Matrixoid auto const& w, Matrixoid auto const& phi, Matrixoid auto& out, std::invocable auto assignment) { - const int nx = w.cols(), ny = w.rows(); - assert(phi.cols() == nx && phi.rows() == ny); - assert(out.cols() == nx && out.rows() == ny); - for(int x = margin; x < nx - margin; ++x) - for(int y = margin; y < ny - margin; ++y) - assignment(out(y, x), advection(d[advectRank], w(y, x), rank1Slice(phi, y, x))); + const int nx = w.cols(), ny = w.rows(); + assert(phi.cols() == nx && phi.rows() == ny); + assert(out.cols() == nx && out.rows() == ny); + for(int x = margin; x < nx - margin; ++x) + for(int y = margin; y < ny - margin; ++y) + assignment(out(y, x), advection(d[advectRank], w(y, x), rank1Slice(phi, y, x))); } void advection(Vectoroid auto const& d, VectorField auto const& uv, VectorField auto& adv) { - advection<1>(d, uv[0], uv[0], adv[0], [](Scalar& lhs, Scalar rhs) constexpr noexcept { lhs = rhs; }); - advection<0>(d, uv[1], uv[0], adv[0], [](Scalar& lhs, Scalar rhs) constexpr noexcept { lhs += rhs; }); + advection<1>(d, uv[0], uv[0], adv[0], [](Scalar& lhs, Scalar rhs) constexpr noexcept { lhs = rhs; }); + advection<0>(d, uv[1], uv[0], adv[0], [](Scalar& lhs, Scalar rhs) constexpr noexcept { lhs += rhs; }); - advection<1>(d, uv[0], uv[1], adv[1], [](Scalar& lhs, Scalar rhs) constexpr noexcept { lhs = rhs; }); - advection<0>(d, uv[1], uv[1], adv[1], [](Scalar& lhs, Scalar rhs) constexpr noexcept { lhs += rhs; }); + advection<1>(d, uv[0], uv[1], adv[1], [](Scalar& lhs, Scalar rhs) constexpr noexcept { lhs = rhs; }); + advection<0>(d, uv[1], uv[1], adv[1], [](Scalar& lhs, Scalar rhs) constexpr noexcept { lhs += rhs; }); } [[nodiscard]] constexpr Scalar diffusion(Scalar d, Vectoroid auto const& phiSlice) { - return 1 / (12 * sq(d)) * DiffusionStencil::apply(phiSlice); + return 1 / (12 * sq(d)) * DiffusionStencil::apply(phiSlice); } template void diffusion(Vectoroid auto const& d, Matrixoid auto const& phi, Matrixoid auto& out, std::invocable auto assignment) { - const int nx = phi.cols(), ny = phi.rows(); - assert(out.cols() == nx && out.rows() == ny); - for(int x = margin; x < nx - margin; ++x) - for(int y = margin; y < ny - margin; ++y) - assignment(out(y, x), diffusion(d[diffuseRank], rank1Slice(phi, y, x))); + const int nx = phi.cols(), ny = phi.rows(); + assert(out.cols() == nx && out.rows() == ny); + for(int x = margin; x < nx - margin; ++x) + for(int y = margin; y < ny - margin; ++y) + assignment(out(y, x), diffusion(d[diffuseRank], rank1Slice(phi, y, x))); } void diffusion(Vectoroid auto const& d, VectorField auto const& uv, VectorField auto& diff) { - diffusion<1>(d, uv[0], diff[0], [](Scalar& lhs, Scalar rhs) constexpr noexcept { lhs = rhs; }); - diffusion<0>(d, uv[0], diff[0], [](Scalar& lhs, Scalar rhs) constexpr noexcept { lhs += rhs; }); + diffusion<1>(d, uv[0], diff[0], [](Scalar& lhs, Scalar rhs) constexpr noexcept { lhs = rhs; }); + diffusion<0>(d, uv[0], diff[0], [](Scalar& lhs, Scalar rhs) constexpr noexcept { lhs += rhs; }); - diffusion<1>(d, uv[1], diff[1], [](Scalar& lhs, Scalar rhs) constexpr noexcept { lhs = rhs; }); - diffusion<0>(d, uv[1], diff[1], [](Scalar& lhs, Scalar rhs) constexpr noexcept { lhs += rhs; }); + diffusion<1>(d, uv[1], diff[1], [](Scalar& lhs, Scalar rhs) constexpr noexcept { lhs = rhs; }); + diffusion<0>(d, uv[1], diff[1], [](Scalar& lhs, Scalar rhs) constexpr noexcept { lhs += rhs; }); } void rk_stage( - Scalar mu, - VectorField auto const& in_now, - VectorField auto const& in_tmp, - VectorField auto& out, - VectorField auto& adv, - VectorField auto& diff, - Scalar dt, - Vectoroid auto const& d + Scalar mu, + VectorField auto const& in_now, + VectorField auto const& in_tmp, + VectorField auto& out, + VectorField auto& adv, + VectorField auto& diff, + Scalar dt, + Vectoroid auto const& d ) { - advection(d, in_tmp, adv); - diffusion(d, in_tmp, diff); - out[0] = in_now[0] + dt * (-adv[0] + mu * diff[0]); - out[1] = in_now[1] + dt * (-adv[1] + mu * diff[1]); + advection(d, in_tmp, adv); + diffusion(d, in_tmp, diff); + out[0] = in_now[0] + dt * (-adv[0] + mu * diff[0]); + out[1] = in_now[1] + dt * (-adv[1] + mu * diff[1]); } // TODO: only a makeshift because my stdlib doesn't implement this template std::basic_ostream& operator<<(std::basic_ostream& os, std::chrono::duration const& d) { - std::basic_ostringstream s; - s.flags(os.flags()); - s.imbue(os.getloc()); - s.precision(os.precision()); - s << d.count(); - if constexpr(std::is_same_v) s << "ns"; - else if constexpr(std::is_same_v) s << "µs"; - else if constexpr(std::is_same_v) s << "ms"; - else if constexpr(std::is_same_v>) s << "s"; - else { - s << '[' << Period::type::num; - if constexpr(Period::type::den != 1) - s << '/' << Period::type::den; - s << ']'; - } - return os << s.str(); + std::basic_ostringstream s; + s.flags(os.flags()); + s.imbue(os.getloc()); + s.precision(os.precision()); + s << d.count(); + if constexpr(std::is_same_v) s << "ns"; + else if constexpr(std::is_same_v) s << "µs"; + else if constexpr(std::is_same_v) s << "ms"; + else if constexpr(std::is_same_v>) s << "s"; + else { + s << '[' << Period::type::num; + if constexpr(Period::type::den != 1) + s << '/' << Period::type::den; + s << ']'; + } + return os << s.str(); } template struct WelfordVariance { - std::size_t n = 0; - T mean{}; - T m{}; - - constexpr void update(T const& x) { - ++n; - const T old_mean = mean; - mean = ((n - 1) * old_mean + x) / n; - m += (x - old_mean) * (x - mean); - } - - [[nodiscard]] constexpr T variance() { return m / n; } - [[nodiscard]] constexpr T sample_variance() { return m / (n - 1); } + std::size_t n = 0; + T mean{}; + T m{}; + + constexpr void update(T const& x) { + ++n; + const T old_mean = mean; + mean = ((n - 1) * old_mean + x) / n; + m += (x - old_mean) * (x - mean); + } + + [[nodiscard]] constexpr T variance() { return m / n; } + [[nodiscard]] constexpr T sample_variance() { return m / (n - 1); } }; struct BenchmarkReport { - using Duration = std::chrono::duration; + using Duration = std::chrono::duration; - Duration best; - Duration average; - Duration variance; - unsigned runs; + Duration best; + Duration average; + Duration variance; + unsigned runs; }; std::ostream& operator<<(std::ostream& stream, BenchmarkReport const& report) { - stream << "runtime: " << report.average << " ± " << std::sqrt(report.variance.count()) << "ms" << "; best: " << report.best << "; n=" << report.runs << '\n'; - return stream; + stream << "runtime: " << report.average << " ± " << std::sqrt(report.variance.count()) << "ms" << "; best: " << report.best << "; n=" << report.runs << '\n'; + return stream; } template [[nodiscard]] BenchmarkReport benchmark(Invocable&& invocable, unsigned streak, Clock clock) { - assert(streak > 0); - BenchmarkReport result; - WelfordVariance variance; - result.best = BenchmarkReport::Duration(std::numeric_limits::max()); - for(unsigned current_streak = 0; current_streak < streak; ) { + assert(streak > 0); + BenchmarkReport result; + WelfordVariance variance; + result.best = BenchmarkReport::Duration(std::numeric_limits::max()); + for(unsigned current_streak = 0; current_streak < streak; ) { upcxx::barrier(); - const auto start = clock.now(); - invocable(); - const auto end = clock.now(); - auto duration = std::chrono::duration_cast(end - start); + const auto start = clock.now(); + invocable(); + const auto end = clock.now(); + auto duration = std::chrono::duration_cast(end - start); upcxx::barrier(); duration = upcxx::broadcast(duration, 0).wait(); - if(duration < result.best) { - result.best = duration; - current_streak = 0; - } else { - ++current_streak; - } - variance.update(duration.count()); - } - result.average = BenchmarkReport::Duration(variance.mean); - result.variance = BenchmarkReport::Duration(variance.sample_variance()); - result.runs = variance.n; - return result; + if(duration < result.best) { + result.best = duration; + current_streak = 0; + } else { + ++current_streak; + } + variance.update(duration.count()); + } + result.average = BenchmarkReport::Duration(variance.mean); + result.variance = BenchmarkReport::Duration(variance.sample_variance()); + result.runs = variance.n; + return result; } template [[nodiscard]] BenchmarkReport benchmark(Invocable&& invocable, unsigned streak = 20) { - if constexpr(std::chrono::high_resolution_clock::is_steady) - return benchmark(std::forward(invocable), streak, std::chrono::high_resolution_clock{}); - else - return benchmark(std::forward(invocable), streak, std::chrono::steady_clock{}); + if constexpr(std::chrono::high_resolution_clock::is_steady) + return benchmark(std::forward(invocable), streak, std::chrono::high_resolution_clock{}); + else + return benchmark(std::forward(invocable), streak, std::chrono::steady_clock{}); } int main(int argc, char **argv) { @@ -634,38 +634,38 @@ int main(int argc, char **argv) { std::cerr << "Usage: " << argv[0] << " " << std::endl; return 2; } - // use case - constexpr UseCase useCase = zhao; - - // diffusion coefficient - const Scalar mu = 0.1; - - // grid - const int factor = std::stol(argv[1]); - const uint32_t coreWidth = std::stol(argv[2]); - const uint32_t coreHeight = std::stol(argv[3]); - upcxx::init(); - const uint32_t coreIndex = upcxx::rank_me(); - const DistributedConfig cfg(factor, factor, coreWidth, coreHeight, coreIndex, margin); - - if (coreWidth * coreHeight != upcxx::rank_n()) { - std::cerr << "Using invalid number of ranks\n"; - return 1; - } - - // time - const Scalar cfl = 1; - const Scalar timestep = cfl / sq(cfg.GLOBAL_WIDTH-1); - const Scalar n_iter = sq(cfg.GLOBAL_WIDTH-1) * std::stol(argv[4]) / 1000; - // output - const int print_period = 0; - // vector fields - - const auto syncMatrices = [](std::vector, 2>>& mats) { - for (uint32_t i = 0; i < mats.size(); i++) { - mats[i] = upcxx::broadcast(mats[i], i).wait(); - } - }; + // use case + constexpr UseCase useCase = zhao; + + // diffusion coefficient + const Scalar mu = 0.1; + + // grid + const int factor = std::stol(argv[1]); + const uint32_t coreWidth = std::stol(argv[2]); + const uint32_t coreHeight = std::stol(argv[3]); + upcxx::init(); + const uint32_t coreIndex = upcxx::rank_me(); + const DistributedConfig cfg(factor, factor, coreWidth, coreHeight, coreIndex, margin); + + if (coreWidth * coreHeight != upcxx::rank_n()) { + std::cerr << "Using invalid number of ranks\n"; + return 1; + } + + // time + const Scalar cfl = 1; + const Scalar timestep = cfl / sq(cfg.GLOBAL_WIDTH-1); + const Scalar n_iter = sq(cfg.GLOBAL_WIDTH-1) * std::stol(argv[4]) / 1000; + // output + const int print_period = 0; + // vector fields + + const auto syncMatrices = [](std::vector, 2>>& mats) { + for (uint32_t i = 0; i < mats.size(); i++) { + mats[i] = upcxx::broadcast(mats[i], i).wait(); + } + }; const auto single_threaded_task = [&]{