From a556d0a1415c52ee93a572f33a72e7f9a5d29086 Mon Sep 17 00:00:00 2001 From: ranchuan Date: Sat, 2 Dec 2023 11:52:15 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0lzw=E5=8E=8B=E7=BC=A9?= =?UTF-8?q?=E7=AE=97=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 +- .vscode/settings.json | 3 +- hello.exe | Bin 249000 -> 0 bytes Makefile => huffman/Makefile | 0 hello.c => huffman/hello.c | 0 huffman_.c => huffman/huffman_.c | 0 huffman_.h => huffman/huffman_.h | 0 lzw-ab/.vscode/c_cpp_properties.json | 23 ++ lzw-ab/.vscode/settings.json | 6 + lzw-ab/Makefile | 15 + lzw-ab/README | 83 +++++ lzw-ab/license.txt | 25 ++ lzw-ab/lzwfilter.ctt | 191 ++++++++++ lzw-ab/lzwlib.c | 513 +++++++++++++++++++++++++++ lzw-ab/lzwlib.h | 15 + lzw-ab/lzwtester.c | 317 +++++++++++++++++ bytearray.c => other/bytearray.c | 0 bytearray.h => other/bytearray.h | 0 coder_lib.c => other/coder_lib.c | 0 coder_lib.h => other/coder_lib.h | 0 crc.c => other/crc.c | 0 crc.h => other/crc.h | 0 for_hello.c => other/for_hello.c | 0 huffman.ctt => other/huffman.ctt | 0 huffman.htt => other/huffman.htt | 0 other/lzw-ab-master.zip | Bin 0 -> 15985 bytes mystring.c => other/mystring.c | 0 mystring.h => other/mystring.h | 0 zl77/Makefile | 15 + zl77/zl77.c | 362 +++++++++++++++++++ zl77/zl77.h | 25 ++ 31 files changed, 1593 insertions(+), 2 deletions(-) delete mode 100644 hello.exe rename Makefile => huffman/Makefile (100%) rename hello.c => huffman/hello.c (100%) rename huffman_.c => huffman/huffman_.c (100%) rename huffman_.h => huffman/huffman_.h (100%) create mode 100644 lzw-ab/.vscode/c_cpp_properties.json create mode 100644 lzw-ab/.vscode/settings.json create mode 100644 lzw-ab/Makefile create mode 100644 lzw-ab/README create mode 100644 lzw-ab/license.txt create mode 100644 lzw-ab/lzwfilter.ctt create mode 100644 lzw-ab/lzwlib.c create mode 100644 lzw-ab/lzwlib.h create mode 100644 lzw-ab/lzwtester.c rename bytearray.c => other/bytearray.c (100%) rename bytearray.h => other/bytearray.h (100%) rename coder_lib.c => other/coder_lib.c (100%) rename coder_lib.h => other/coder_lib.h (100%) rename crc.c => other/crc.c (100%) rename crc.h => other/crc.h (100%) rename for_hello.c => other/for_hello.c (100%) rename huffman.ctt => other/huffman.ctt (100%) rename huffman.htt => other/huffman.htt (100%) create mode 100644 other/lzw-ab-master.zip rename mystring.c => other/mystring.c (100%) rename mystring.h => other/mystring.h (100%) create mode 100644 zl77/Makefile create mode 100644 zl77/zl77.c create mode 100644 zl77/zl77.h diff --git a/.gitignore b/.gitignore index 0e8781b..da0ba03 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,4 @@ .vs/ *.exe *.pkt - +zlib-1.3/ diff --git a/.vscode/settings.json b/.vscode/settings.json index 854061e..104bafc 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,7 @@ { "files.associations": { "coder_lib.h": "c", - "huffman_.h": "c" + "huffman_.h": "c", + "random": "c" } } \ No newline at end of file diff --git a/hello.exe b/hello.exe deleted file mode 100644 index 0576a1c7f9234f9631c97ba5eb3b13e61c606985..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 249000 zcmeFadwf*ox%fMi3nUO&Q4)=oHAaux9}lX1D$^OT!P4!bKs^EiIlU;f0?03q8Ior+aQ+G`D5qs8J)T z9nejFmuv35V_erf|BV*c7YbdcmAG67U0-sIEGQV~>ZDK?|H@ph{tBMu{DU;N{Fe6u zn{N3mmJj*qr!~V|t{YD-qFu8o>QTu~UEXaV*@t90DR#MoF4uX(?N{}?%jJ3&c)1^s z+jU>={{-fP{LA}kfR_^&+vQXnyU2w9u3zvk@25e^ zt+305gr+|JNjZU=_tPNdZdtlik{%t&uYP$u@uyAbn{UHYygo=7ftOW2r%HpAn|AdK z`JAWHXtcDqOMT>iHAuP80)+Qq|QjSJU^{yq^Y_3%uv6l&ZNr z7E`X3=SQDW?)(c>xy2qH{ggY4=M6mbei{Vc1$8RrCjz1z+mIqFKcn0vo4#s+48lW%l^Z$SSe}Ds$(Z;rs0{Brn=&bv`N_G~!4}2>^RGmUWU%bsyb^Wm}sa#81 zYbX4g1ZkDj4JL|Td>%-N%9qq*)NUSems$Ln`YisXJWOA;hw?w8DZY4#)p9SMp2kd~ zF^UfT8hyq!*Ihf^Xg?s{dc!C|*%eGsEok6Y%$_Rk98P;^+T_ ziuLcrheZb5TC|vg@nN(xx`4Od;&-33I~*tbW0)R$M~haFNn@;^$-@PtP?^8JYa^+! zIMZj{e70na+70MTQ4NA|iyUsi%QB3*86U3uG4&#Jd|bE_UX=x#fDmah4>rr&B+?WTOC(u;LX zZYj-ou@rv~L?s~d#fKx$&?)OjK=dJB^(?m*gKJ1_AKkpsJYkF!O0>8eo8Jl~-zp56 zd#xH2Dj1*eK5pJHdt>jcnp(dnOJ5)!e9dLO9+5^ab{ppV)=}OA=0U?OdLs~@@fuZ< zMr4!QdPT~3Ukg8XS;F__0izeB0&mJgfVIYbiT8N%Z+|M7idT~qA7u)@xGQK18$(j6 z^JGcCo>#N@I)0-N(U*Y|uhivhrxr~J%=XQqN;lqg^EdQa`Zv%t^g(;VS3Ns*is-Pd zAMx{l1hOZ^oNOt_K1M_v#`0}F0;x`7@u$cwUimZ1BH6V(toh{j4illH6R`u-!hqHk zruOmH88nlb%J^$8SL#|mTRW}G1y=DdpZN!L0eij;`)VG&!<2asr%tMk`exGFa}O3X z=(8MuCG^-1%G!7gv|>}@AhP}}rt%@tWj%C4zV!$&4HW-0+weQ{eo)m?YNcLKuA;%U zDKAf6uQANOLPMQlHkKRaHB~{=kD)f!7zw|}F#QLO_%;0VR|U*I!|XQVjpf!6I!4of zEbc!Bk#*nL|J zo$nI$Z9FJt+S{e9kl;Uvc9Est8j7Tryc)d?Bq~Jbg9z(rHH**YO=U(lH{@tj&2#Ye z`o)C~qNQ+o+*K^_-FB-K_QFBzE{ zT(Rm!Cu<0!6ftIBhrdcti;FM;Yrn>uin4DmZ}-YExe`gM9+o*J2OtRS1IB~ey2h%G zU;$A4l9<3r@MdPAP(&yJe7>Zhy0IKt_xLle$lX=0J4Xl_s=NJF^1VW#<=gA8x_kI~ zQQ>s)dVbUIg@;M4^hwfq)Iuom6_j`QGuk?T1}x_6O-GteR7X9xV3fP0`8{^kh#r+;Ps;^k&?Orv? zc|F@-1p-H_(qD>SgGp4m`;=PPY|++<>K_y(ap89&{$p;m{UX0-M3ZPux#8|sG7csh)OXO`6)?9- zb6&e!>AWb-*?x~W27ftP2dA7yO~i zL$2u}iqqD)?E1TgXT=zgp=KAjB&I4*mlIK7#Cs{~!b$R0O0?iTDRFToBcQ$m<`_?)y~w zDPhky9KxQKw#NOc1%*P6|3KV-0H0?&%Nbxt&HG6+ns;XlZlyKKZTtHJrm9*kK3nf-#X+2MSj`5AEU?3K8}se^sa`ay!;`%`v07+nC=q zHkQ81NLrrcK(V zQJw>1mlH4rD1uH|Uu_q~w+f|Op>#(rABmdhuAJX~2S?i6pH?=O$* zg0lufWqo})^4Tat679Y5E+rh2C1RmV{oHr#jLV!1jJE)!RiG~r#eWK$?NgRiZndLT za8uEgP@P1T_Jpg|v@0Z<3LR>P=_;NSd>`Ja`pOf1Rco*R6Q%&@4X9KOrVjrn@+Qqz zU!S7Cp9qK~(YX_eT-h>#RPHM|vSPh9h9j=T}J@aA_tdaoPL zCJ}-t(#Va4jwbvLVcym?*PY86okRLvvPj2;Cav-urXn<1QU-As=Wq`roNzu8Glzq# zX5(-N&wLPe6e_(%ij(jNStlTU!8KJK$b5((wRHqWh{^VqcX!(Q*^L7u=Mb=~6s9UP z6;1IU?kLCtmuPZOnvO8(#_NV65a2#xN20RYfj$@LamwNQ90mE@a_J07*=f}FAxV{< zs3?)PInMA@ieyo%b`9eGOigk+7e^AqwRKfClf-jR!yG4V3XM>Po%#hqlN1vfuInNs zs6mysAeBuo#O z4%J)f4+j}LI^H;dW)3Os!%)nvfXNa0UAvBi2}6_`|6z}W;9QlyeiTNqk$=kfzQGJP z$>QRQv?s*1SGB76T6H`~8K>JVa_bO>iVZXklQI-99CWBZ21r)vJjeB}x$&6YIocsQ z&g>WgMI+upJh#&W*7-AJ9F<5zLhnewn`wa3zS}cx;mm#MLS7KdQ8gy=A8n1?eRTM; zmq=l(#VE;tOkN4^SO4m`xIJ8p^hJs8UN$?LjW>;0c* zBd{;qY9VBelGoN9R_pohN7KWzA9z#=!yBj+hk-uu?&s723REPgVdF}9j zK(jHWYd)}5hPMwp$~%!;b`UT~H9jAQOCYJjz+S%!#*jgzzfh)weoiwK^Haa!O@!Yp zK~Js)eNNbD$T*7Bt$C)D&9Y@Xm{nd%l&peHL;BDBT2-YIUen4Vhm!OcY2>;7W3jF~ zHQwA^=Ra{qvIwJ07w%{o*wI4SgK*^F*i|n96K-htT}N|-)t}Yctc(m9QibO5sBwk9 zA>6V?TQz_a~D%-ed2x@eMt8@>x+58VP4;YZ!d28mY5x3 zck$KgEorTV7ej65e~JJ0TdWEvY)c3u7Xlvr$+kSSbay~-vN7)C! z=?Y)n1$>g%Mc!8GWm~baZjxP&ygu@FL#IOMMF#$U>y&q;jj@@uAgfU|qDl`MiSMcQ z4-T_bArbD#_i}??)iFDaqMKO+FTI8}`ZRZAu{s5qU9(kF`S|D}Vnq@9fK zvBya{_#ab@(b7tKxm?;Vrn?~cAbNaIsx5h6=oUcL4xnv#{%mdv|4wO(Z%a!58xZZ% zE~oVODQ&A<`({y#;|4_kOZ|I?h-0Y!drs89$N@v5*#%DN#m;;}u(YR{;jY zA$tbtAX$tFQxB<92ShF>mSV_EuW4?|Hou-P@1|8PGWt8df*SPfG!kWhv2kIq?(GU! z!DkegKm&f0rBvcX)Xc#658&btT!fps?*`N;=UVu#=37mA8hPQR>WLG@=DoH8d|P!s zbcOVJSAxzSmhF@-mj#4A?TH3L8s*p=(z6+A^bcXWxs8xi=|a$fIYlYeG3D*!4JBUx zv6VklbVwwcKQ)>t{+d%|gd)S9W%#B|2E9m*475o?^#Qx%P{_tOHTzJdbd8EFILp4{$tFCfT$QNy^9N+? zC(&oQQC!Y!r@mg6$2KbIl3%c3u&=mCIOx>tO)Fc(VV6t4(Vi?}0#IPli9hPpMXHoifO~9_HMg=QB$jQ$jq|ZxeX;4?M4ru_LA5iZ&Pfs zYaYxp*epZcMe?~6BrjAD^BK+C@~CSy)iC(DqS;Xn6IUhnWGT~DCE`}v?;c?L2$4<` zyi_<4gETL38IiTs!c2;EeM3hmVxf+CQpJO~%4HSlYtBcNeAMQ0U~(70mHA0oC6?ck z;@(Y^kRB}sZ7sH^JY;@-NS7#)sff=(6L3Bhn#l}v%PsN5O6PtNv9)TJJ#A#yfq=)H z)@9K@%C~r5M)1mhV5S<(qn%k>S?GW|2~f&5h+37~n<-wZNp<^B4o7K)vj2@}m-5+% z=F5}mdwb43JwXDQd`EMTDMm1Q9PvexV#5vN%j{KRf~a96Izw? z&d)kHB&$D9q5j3DWj6(I_w;WFp7;K|chv=)fqg3x^^4VLeBmL5L)5&65^8GH>S=I` z1xgy_nyLg6X)a~o*;Kf$QnMwcwv?3GLmK2zEv$g9g6!0l(}ksuVDWb!b8Gh>h8oIH zTtIv5$$iz$EtqF7#LgV_pJWf!mkHFN9(spbqJWMj(aP<|X~jnMjXqU6U`6D4?hv;k zp{D{t^`(}$7B#IDXUu&pxv$XMcehecfkcm*wA%ib$#nQX7P8~6NdIsKOJ;J{KJmv4 zK|U^JJ>+8odnr(^t3kBXdW>4>lkh~2w}hm1Zz~=E#WrA%sfGf_c|Lo6#nHR$kmO4O zJbukTaMvud=QAcm6Tz5E}uq3vK>8bpTHLvINWRg@x*%bv?t%KFQ{3Nt9O6>750 zTzO(MRd3WsM6PNrRke<1#h~j+*D?LgjGSv#DI65*OAo`y=-Cu2a&XQD4k@(^aqd3m zTD^TJ^R)XyB73D~iUlH21L+M0CgpL(F_~_)eMer?o|i_8t>!P}iMK(8X>bPIbY~lD z;H}+bm@UfLSj-hkpyslg-xLU9v-gMu6fp7Vkns}iQs2DS;n%Vu?U~X{%n$^B2EQ#r z#j{6Lx9cq6e6;eVZ0+eHP*WU%$j2qXSIVrr`ph-^>%wuu=&U1@VW2(ql==3YbTIy; z^%uyt16_fb12Gy966|g{4)l__PSbi-QE7RWw(IOH1y!13%0M;i);G!$4(KlYyP|eC zd~O;t{iYl{@h8w~a#6wth!b1%e+0{9WzcC+>i4|odD~;n3OaQ?64N{Jk==dgr^HY1 zvtx}Kq2)%PcND59LIofy@e)b&e<-QPfuryDDXm@C_~D6JI+J}81+?A$VJ7rDm7neO zJx-^O6fTnZX&Q=}N5%{L@-ZqRIw9h0|1tU>mRvtXT~)Vbc6w~ZQe_s{Wz3`liX9!& zs8*6uL)`H_Rd#7lyiMw9)=rtUtLw7ef6%EUbHLx zIN#duP^1$k!yH;tGEbSs^3_#mW?#LlPf4~MQ+q4K*=Dh%Wv)ySH+!&b>xpHrL)Fqb z>Kg{jUUFjD3#6ijwEWMRVZ{n^ z3q(Snpf>4J)mODjCluLCl;-Rw`g^OeL2YR}OYM)!^cnHuHzYM7VXp)qm3{Kb=<-df z)@-u(QL%GR?Vzmu$tr0e0g}spdU&6l2-@XT$X+8r){`vdH9aHh^`752pXqPLCIV>px^)Nobh8 zudBCs8Q-E$sXGAHX=KLzfUqd1fAw91x+sZ4ZRBWS=+xNG&=|E6~NcXCffgc_?;mYv-|0++w$=X$icl|!oTC&qv%_q)rP7YwAz)`O+KxbjcyU| zFm26qG$)P#D$7kd5o9VPZg)iJlI z+>?CObu#^$sCj6)@lDJyh+n&YcCfwHm=+1OEChpH>3}aCHUL3qR(A zC;h-6-VO47@8Gw|cWNoZllD!;*3IwNL?y|c7FD}IaI#-47DZ~ zFrPKpLpoEn#V}`7&kV8?b#~AUR?m|?sWsNQcyWFG=i!m{c44V5?qjy_x-GGiEq87)7R`p?GpXlqYFA+ew9Nb$3)GtyO+ zm2WWaYV`ImXU9}iN&M=PfV;2JyIH&EThO6LlCov9M)$rP-Yxqs7o!S>*&{t*^lb_N zu^5P$)c1|#n}vp(Ky9%{ww*xJQo85(wPpJHIw_ebLzKlYF_&T_X0QX-3|3WTDlhtP zz6Bb(?27xUeTk;7$iAmTOl=&C?E5%;a-{eXsz^N0bmL9>Ec7`tzz91idw6G5Ptw;H zQE`0(zkC`q!i8sq1%r8cNx*#BFsGMiD*GN+yS~ZJ^p~%*-?E3UoRaqBPN_d?Z^Fjew#YdVBhr7++79E`J1qMa z*iU?nM{n^1)R7;fcC)Av{40)=6g2ydS_0pJ;j12q$Fz}s8Ps+3Lb*BW(9f9_3k`vt-(2N~M zZFev+d4%k(UCW@t*Kx4}Zs{%Y!uV1abf=dD-B!^3t`P^NM~nUqz}lJ({Ei$g3H>H= zv|Ni#f(-46EO4N=#%$=2mWN?H7+QVi#ZbHCNBHA-<=P*?+MU|kA0Z6(O~3bFY*gM8 zOtc(x{95rH6hIe!ahL2YX1ANnco-#(=HASUkzSN(Q_V$F3<|B>nVO~4z$XyHA(&+* zM_yi{#kLA;2ub}{Ha~K-L5oFcK`?%Cptd*Q{~Wfx7Md{^kzDQEBqpI5(ggSY|f$TgzavVHzdKBe`isfYpf zwS|5Ji#bAyMr2ZRi0pC!ViBaP9&A7y#9AEBYwt0zKz(P(D|HlSgVrG zzm$jA-N?*K0dsTaMdGc|jj^{v1a8wxV4VbJH!?)p6Mhv)!br#85&4`=-68I>!IgEC zHSyw7keQf~fGnpXQ5TNViQ_g_!3BF>3H#ftHPnZ zRs|AIzrue1+YYn-CpDC4HpPqoRTT+e8!ztQ4SNay0m+AW7s(SCv{4uizASRJUbtGN zhu_1`ES568#eN?0(_1{vdCOFu^q=?$SwFU9y)pe0oS`^N$|pv7DV3?zq{L)OWFsZ} zNqpVzwGS*^#eti#>UQ%cf;OaH`Irw$&c3LCBME1)Udz-gz7U}A1LWHfMGC!|L#0^Fju zKq9ocCS8Wz1kme%_oL94_4VR64D%IZu!ynf_dyH59lKTJG`R%Z}B9NF-Ugek8OVqJjPc+aq7q!9h zZlT*3pNc+q+5DagzmrQUSouXCw-3?B_|)pdY$Y3;)&F4pjMG$mw!y%QL<1U|r%i5j z@6Kw#=%BeZkN&J4r1W@OCkh8GuZt=iN8fhQ)GMLyio^_uzRSuQ&8?Wnl2Tvc)RLgL zYY7o$H_E#+ypKVHprIW>_wMuvo;L3*P@^K+8y+5SDnnW?#kQ^ft1oVpHM(Dx3Z0!- zH5pUn?6ZU(RZC7Y+EeN)QtC1$s5h0n{BK5W(jal>^+ShGozh>4Ph>~VCIXIt`4=mo z`h!{3o<=i;UJ{>gaLuO6)K6EwRyVg;4^YHs%G^)gjq1!*&gnR?R1EzLku3ml;Tv2H z0B`|-N$sAZG2$%iZWK~LJ<}Jzp(GeT*&whpUukXMmszdFz6)=I=1$pkt(Wc$tso*b zw~_{{OY}dAztzp12!q1>-hXj}Uwe9|&zx25Yv1Q;qi+1+Y95ptBO@Y1qOwUobEk|5 z>rk3%pHGH`0kg{v+(u24=;)>|L!pY&vi?i(`Rn)i>5B-D8(bW^6!K(2-60PWGMUvr zh#b?)5UU8Jl&;@t$2XExNRka_XX+*j3mm&01WPV`>SbK>bd`e6G>7#D)H$Nr04lds%slG_Vi7^}?Z!l?$esQ|mfjQE6Z9Sm zeT}h{5$SQ~b6~Ib)D;Br!iCUwY2}YE&ub;M!rLS75n6r|vY?e|QgeD)tZS9W9yic2 zZ16yY^?f?-y!_Q~!@vgO7jRi+Z#UDa=JSf5q~NeNIXrz5()8YjEK{Qr-4p-OBEx++ z{iQ+v3cota3gXkNBi(LudbQy_9GXl?#jeewFw?8O(`#12E+*v19NO#&J!>t$3~1A< z)6X(rMg5+l0#6P=9xql+1kj;8Ag?(Pw%e?$bHMaCty8LZ)6L4?*AD1rLz&r4vj9;P z{&He!MpANo{~~cq9xnJ+0fRbWTue@B(hVW6bi3`1*j!xvV`d*^S|_#*b1<5(E~hi; zM>AtPSA5R;t09@Y&2EWFCA8INrDXq4r!_4=v?qsSZF|7KO!71L0&~kjlc8e^_V}vD zPY@r#uUXaO^~gR?{Wfh~(TGU@8@|#$y`!kqP;)a!3d2?)aTSMRU-s3$V$}%(uuaPA z5A?&`5-)~M6`*Gi0!{zY)*Jm$cSGoNlF4`=i!ps)jy^>}qxo`b8N}iDKXblAH=jpU zB1aZ!(bI7z{`iXW`Yt`bqQoD|=vtsR(slCTUh(!?>~Vov5CsSdGzPtbgqaGEh475(P>dStIh#dqwd#sbgmW6r29(shBabgSRo zrMDfuP}inzGIs6nxP(#J&hSe?@4H&`Kcuoaga78mFc138fncqr*LKl&X=@)PG0;4~ zPg3;r`V6uS@Y(QuzmV9V$SycHgh~bli&``IIJaqsjW8M0l7blLxhY2fTk@ za%SoeK+DF{j$LHk9*~z!ihmQkc-IYY8eFcNFMYlJZ!QlNm4SqMtm`2p=Ps$Ye5;-a zRcHLMw^ol$PtSv|>?Vrqcp=WKYIeJMRcxo-(e!`>`a&OfmD?BbG zANw4;Zg%M#e*LRo{Ys?SsQoS(NLpw5++8OM_6Q@8tTb(oT?`9tDLc}QorUVExU~Im z8H$_V6xGr0zlvl>PZg_W9#dozTR?`Ch&J=mGptT@0l7LdO31X1Q?GV2Oz@e_Wj5*q zhy<1pi)&H2rbLe%D1eizN(EZS>!kQPz6P{{o=Y-yWN2&afo1cNu2YL01OS!XS-xle z_L~DTz0)sQEOJ@4LI|yEP60qFz%S9;&#;ZEtZh6BXyK;r-K=Yk`L?l+6}t`6P3QQy zemGyLH<%f++o@D9+7A|o8>ts~Z|zjg`Z;AmBJ@Y4A6I1EgTqsblzN%BtUpraU&<>l zUI}g1?zvh9cF)^-phYc;D2h@al0NAFKijqsu|_}CtWyPwA^F@+_0k%1V4Q0hGe@$h zp~Ylo-H%&h?}2Tb{=}VbpV@ez`(S%ru6dD1t&OEu@1UadL{K{)n>Q;d?*xb(J{2?6!K8r<%_>yv8{1&wM z5Du`19wO3ps(yI0IKj}!*2rBRT316G<4eo98KSW#&k=6>D9>IFZEj;0nTrKF&Y`s4 z_SR~2xkM78?~@SN@Z7WZkKf!!Tod@CXbC@Ugq|wCHn#>6E8Ky@OpRaC!uOT5&YQJ$TvN%5X<7?A%kbi>~dkaRA7la9MabQ9J8Tz+=8UG$6Q** zXEprkB1em@<~N+vI%2#C*OcZa`RLSPh!%a37WNFEU?i5i#nXOq@P3MH{E>BoWQQ(7 zfXdMdsD?aG`>NjlmdgW1+tqHe-qrJbAyva$2no`s;{WpE5|ZrL#_YDkso2g{b@9tf z4s96>Z(hg2w*A!;+G_jQ2L$f)Y5}&{*2B;6v28R;wU%~MfhSzDBpTd#`E&36P*)!ZDjxc5Mp7l?MUrxQ0XWzpASR47m-{^AD zW@Q&W!||cL?o^Aa+TfxiKq^wm{3c0wwtTysM^b!x88H+As7%I7HT%L1TjFxzhWoI! zup!r1rlwM)wKFfo($>m)N|w&7AN{`UBN>d3SHCU7OBJhc3I?w6US)cLSy zs69F>F?H%dW#rC^PYBYq=v(ksd*Z4pRvEPD6MO`kebp6)NqFtVA6Luf0SP)-o_F?c z7=&LQX2PsXz$}r%>r_PMMq*{5J3UtXxqwjv9-Z|o8Pezs+lYGK2`9Xk|0 zBlS7ONvu`qJIIn4Jc`;w?sE4*Rt0kP&!s-TGW>387Ikv)(TGDm1o01nRQS6XC)4&e z?7fv2hrP3uKz1ZOA8ti=SNE<(y=Ch5>mYnww z%zw_l1mMV7zS<<~7R|}zk+C`*8V648oPo309+(XORUFcIcF%-I>&z03$1+^%%)Zad z#VEV{ekRq_JX+A%a>0zBY(=TFzQQ>YAH)Y)&eGclTx}Wl2SJ;m_6&4e z8{xN1Fx_%8=8wA0W9&XSf7Ls+95rS1BJp?nTb*{r-RwiN>M;FYmbgFHdI&Q%Lq>;=To>SxbT$4*+% z+Wxl8CO^V!Be-J|QAr7F$|Fa)mG2Q>X4m()h{R^P z{nRRZQe@01Lt7gY9tj{6S9`iAPI|e5q@2J`W?TwTU+}t(C)A8 zKD1?+7X7Wf6Z({O9!j=pu?zS-w1pVqCSD?Yi4nrQNGPOScS*|eUZmi$BHLzKf9J%A zG+3gDb9C;lD=i3pMfqCNM4xh%pUIY_50q$&8msro%+^H1`|lix!X*IWj)=7J6@PY}U7a3a|lFtFQ_gu_t58vc?M`~M+J_#ArYC%fw`x{zb#Y=yX^8cPIFT>UzPzgK_^0K}o`FG~>bv0iP zOyxc<$))GYH&b3&WWJp#E~cs|oz-8a91d+MA*v!GNnOjYrwR~FY7yL3^2u)JbM65B z1*8PyKdlz0E_+q};xjh|&F8I8>cuKY*Y9MSX*OP*)1%+5?xe8!aP@=oU=sBvH`YAf zP=g*?MkHmjtv6bI9}oHARn{2ghgTV9NI{wRse=~w z?o7Rc0OV!~2v+EayIc*-Ym~?BO5Ugk5TfBTH?R{`RK=%X~dZn6=VhpYhip($&;cq6xRN zP=-luM{ihOtF7A^XrA#smW}sk_St@MyVZeLb#SLv(G=JtU3s$r(BePS&VJSsgBI`pUMMc~rA`cp-`q;7>E-0zAuKJxI+0al=S zDBj&{ceC*t+EXkrfmi15;Pzr09sS$aC0d$i-9gd_On$JJJ_fUQfDBWwzj5 zqMYJH^$pe-mIYEbQV*pFkMN?8S~O1c6bKQbqIJUx8X}51k0&cRA{kj)pKVQ(rhlIL zBALlw)1ntZ-Q;t%XpQg)87W~ol6vwV)AtTN+-K3(EYA3k;%Nl_JoZ9n;fm@ya9jQ{ z+~@uQ+&>E3X5jt3KEUSoeRiPqtffoH#WG&4Hf0oRr1YHo{ zg<5}qyyyaY#|}5^Q}z<1Uc_rE%arlIfDz~oz)0Oog34Lu1j5sqw%3$?P**UGI66<{C#Dc_= zlWZ?URK}e>GpcXOxn>^Hu9e6$^{Gq^DNr-2AKMwLFXB>1e~+2HLp`I!%*pXd}H9z zKf$+1ri6Mwqu#myyx!lW-u?gkdXKzMz3Zr_8r2wQqLt%emrBp@maM+hskEUcBErv! zY?|4yv)3|fMUD0<{~#mfSFL}0O`4TXl>th6o8|Q?(C4+lulYVqeTQ@r2a-n;j_v-E z#I{uh=V(z~V2ep8O}0|6LRFIGKZomRt;-x}d$vGaT1qZ3U;t+K9jT`QLeOY?^i(aP zilpiUmEbW)q1IUq$gWbj@)s7fYe+} zO<_#V2J>{<=1%HVN~`@y^?M>mKEJ9;jYyn$-`yoqZ_}yX?JGZGZY1`3WKzXke-R-% zduDUl=?mPesrf--5L)Z<1zuG$VeE+ zINY0h0Xz~H4T(qDD^lMTUs9nq!tL_jQK8-U7SdrN+DP0`WhCZT)$a^8zZgjFE4VB% zc}&2)pWD^r1qp*S)2_qsqmSd+9mh1?k{flim!WsSw20j5cMir+dfctYO9GK(Q2=JK z+SD6#9}Jj1Q19*wB;WPOMm=-8ZW_mAN+Gh(9rXTr={A3Sgj|OomDra}a-v^L&J;^r zF;!3a5uzo?>$^JRBX#b6h-^~exu1*!66~wf%_hKE9y$B#ePih>Msp972QgQ?g#9q% z@Ji$1-K67Uw>EIO;^ho^%Y*|FtH|(fS%Mjbsw>jZIC?_p;lx8XL30fw%U}Ld$V1XyE8eWS}Vgq5+S8HWGt3_s2h3ijA?3bsx&jnsmJlV$vM=jef6Mh5^d7f zM5qN0v&%=k)1)W&RruUH%xy+;ug5554a)B70%o_lyOvE*GwH~VoT9CHRoEII)#8&e z#g5j1ws1d3fQohid5d=MLINB7Xa|MlM`stWj{vJF^%!4j+#=kWd8&LwRgrwff{Ac( z)FrwomV8+1{%CVkYC8SB?Jx7o6ZlE_QdM3QF|{ODPVc?6LJ*`TOD`hp+k*L~F^(Y5 zept!MSNI$COr4`j(I|&{!Jdr@)okTtTINIln`C~#ls|}rmNwNA-B7GaFu^ItYlmOK zL__3xm?hHIe2;>Wfnx3c^Qf=4cYVTxt!wQAhne5k9_XUVjL6Dr57zoE&gE%qf65p} z5{hJuAyhCFCJBIxeJn89VWy0zSztg7*UqJuqm?G>A+xGiSOGdbHBcVcz zeVZ>|{J!jjg6O>bm^VhdHh@-yU_zB1=;aI?}t zdk#b1eBP~Eq8+j@FuM8o;9~Ek6N)DLXEqd)HP=uIgzES9#C;lcn3hcCc)kOq8K6Ag1S->_pVqH-w{moHzR(rG6 z4>r7<2x*1&A**M>IMW!uxLsHpeF+pXJ2J$8NHlgv5~c-A#%O0dtG? z!>%(of&c!sxG~zHG%31Ai~R|&qxy}f$3ligX0bR$e6?@LeBtcKdqt7Ijn&-)=AV=T znMa9{R*m&3CoG)tSwE#qjoTfjVD-`O``oY4gN>A#;d{vizYpu{0D;g`pgpolc7en$ z!}c5@+&>Yd&=dU)S5BWXGJizWuiA+vhP#`|uOR57>nkZpC3FwKYpi#Zayrb-yGl zuk{KogGyx=s$W$$@pDq8QDPJKJ;Vp6yZ$(t$AkPGBb;1Cx6B5Zzslp_4|zv;l*RTd zzhEP<$AL>%M0z<4kDv0_zr(pP=4gGX-KwK(a6}S&5*rl-r@qXlDz(zJE1!2f2OGC} z6Q_V13#Mk#GdXcHWQyC4&BC4~vZcIa$r(VagXJpa-(*?y^Yqpu zXH|RTJ|N=QLoOyNhm$7r^@jO|U_qT{6lk&k25dveZ89kmWJX;&7h-l2(J;|oY|Ldn z4D9R&8i<)RdOy;l6Hs5Pjl7`wel{DTt=marH0AVKOrX=&pt&E2j)SpAvhRvT4N2)u z%&W7`rny1$1NdofvKFegcX3!l+U>!CvwMu9>M{w-MXq$KvoV$?>tDqI<1|L%M77xa zsHkc%e-Mpa23jLgPc4>0T*5Yw!D9Qo$R}Pc+C~%M)Y|V+MFi}jory)<9)o{pd8pC+ zsG);>t}ECA-5_!nwMP9(%$bXWrhdykOZDl zIY_+UI%@!BEm$|sRO0B6WJn#0AXBE^Q zNjiEa-PR-B(H)`DZ0FJL|1DD~3Lm9r(^o2!&vuxp?J_OHMn}AH<;Y12xr!c?%i>qG zx(&RFb$N7%S2Yq>5`5jnXlFb_5JCw?K8dMy9m7QkP=-_6F0#O>CW$b5B*Kv0g8)6_ zwDXDdE_M771vgP%Mv+bnY^Qx9Xr0*ZdJql*d>i5%pYEaBy#{$BwKvm1wcHZ|Zx$c@RSE@1LYbzSs$z8vfxSAFU}fIEOg)_W+V z<6e7H+f*H8SVH^X!9zji_iPK@q1@4a6^!&+y9j$l4V9_FjQhvnO~R#-zp@RYgjYSX zx`I&aG5Vh@Q&MUVoK~|>>dX}WGeHWo-$YuKx1H-~UV60Hv&cYZ5KIb;PdeQVL6e3S zFpifXCEhFK=J+KAqeVaQ?!@Y}*kzYJ>z@FajPHUJGaBJ`OmLf6(jsB&hpmzwVP z-tW*<=CHJh&#V4TaaVh&Tl4S0`zQAm5z!jyQFa`kAHLUx-X~aB5xnSNsv8apJ7)|! zL^XSGl31d3z(leLK)58G~9>n?~TM#w>2K2u>;{322q&@XyT?PDL1_jGs$WlZaK2W zjb~O)nr;jaos#`vjyZzXB^~(L3+UyKu`(o`Yf!?qs7p244gw@lTpGYyiqUfJEh0b=PKnpD z&QadACv^_ej9*%WUSO;~EpZ->3^SOG7uzJJ5R%fVFObTI4_!7TeW?w?@e6}J9-N1V6V20L9Ox&W%SVm z3g>3+%UZ@@13@}cTtQ1nT+&}S#&H?2N4^+^LI(qb18j*2jSwENDmbwoL98FUQ}08?Y6 zp)?WAU!2zyrmm6GCxia!KltP@Jg#}rwq!+UruI;m=1(U3ivYmAtoE39B% zjk^B$byd=7#y){4p7&=6SF_T|itcVG&owT!n+-sI`gA*Jl4+N(stVbLDrsLvmGFoL zwf*eRfFx7tN@^z`v~Y${pHqj_=P9mqC<{cpznKvXb5@bn{GF5UbvY7AHIhm%)RYvC**~jxwlrT~Vg7~5%;YD<-t?-wf{8g*M)Nz3iPIkrB+mOyWZzgVdJpXL#YaEw z;c4y&CN3$eeM#SyYV>Z>?&and^!;t(4xM=N2+KoiK7Uugxr2k4<|W7capRa>c=>Ba zZ90(fJ$%e(avW+~=rWlfPWzmGUGJSr)QW%Yoys(Gc7l6weI{uBE#Uod+3sxr`!l|l zA5|cW9uC&_%k;5sPOYG8`I9|4&aMt0F}Zme;@TE^gxfUIiNW|zJa6+=Trr`uUQ*U+ zuoiM!x^^&Mh|?oo9wx4roh*wBp?BnU_=nn`cIs|6J|A~~pR;}xFP=6BHa*YvWLi`v z>Y-;cp+%UBx6hb74@Gq5QJ)FJjPi)h&l`y%lNNHJqPmfX+jzp%>;%v+ zDFo6`U%Ys&dL;n57IR81;TQQPiRmXD`Ka|ZHQl(Tc(zlKi&SI{&5lpwXH*JBiBVUR zo7u(79lXejg%sjSrM%NQ=!<i(i#77PK*45oGBqd6aAKwj1q7J$PDejW`nSSph}mA1Ii*jPIfCx9`ug&y9yJ zjNDmLx~fb##rg30bRwPb<(C*fo2EEBlqmkeO~`7>+x%vvU&eBFbzi_Ns}8ZqB6T() z&rvUvYkwl-^)0yAL3LL5XDFW6#P3k+hRwUV%$Vckjy|$w?!GFH;&gLknr_NFH!Tsk z8OgNA`}}G~dw-Q{fj*~uL)B&68`|8%PCXKJb5@jtLoBrg)jb4bTdBFNBrPDt~KSbZ^lzRMF`O@N_e1p~jWFlvmB2!-F zi{;_U1kX^bIkU?6qo@GPN9AV9(H5@l5IG{Mdd7^f=Y|=Q$EBa!m9!$=#g4d^P1{gI zJ?mu|8iS$RP=ScpPh`qc8&Ok9_@S)6+(A;N(!P^g^rc2u4j_Qy|> z)nK~5P#VO9rnt~S1&bH>;$EiMSyyMt7(EKQIhNZc_m=3#I1-K{eQEhCmzqUq2Uzq4 z;_~0d_N*Q)XDZvE$i?bjXk`2n?v#C(n+ih*(JN6Y+Gd{<%HEuaP*wT7{q8j;w(uOw zfZS;vn~Vx1KQ2I*Ld)@z{;Nf%Y!tqMbP|okgsX29W={Auk8~BzA}Z)zJ3bCwYQ!%v zVuwP6{f7^2a)%BW=26trl7rvb>n=sZ)a-_gP;^EB*zF7o1-ad^XVRNMYh z`Fra{HIP(T7DlF=3JC?_Z=;)+@Rq48x&@N%vHh3WKZPYuE{RNe=LTi?GqzwSbGIN{ zw#%6xX|YT2E6luPD!0wS%S_@c+a6RWRg?EkTR4Sl$;LA_A=u5~dbeKH_|#(YPs(q~ zTwJ2^-EnF*%XlzeagUWG(6KF;yCmU7?rJKzsLlRU=634_2#?_TjwZ$P(Adb7^M!6L z77-36M$P6cQ~3oU^$t?(N*@YK7(*lUFBqz~y93MP@2`JLz?hd-7`^Zn#{8Zu$Ci*L zKQaONJwOcV-;n!aJor`f#dx5En;-};E0UiUt1ZFqzxxumvzomnx30Z~b?rNZ&kRe% z(tZqZrnIU!hJ32g%pd4H!q%VU+Xc=!*8h;e6OnL>QmDErm?*n9@+KkDYHH~lJ^bcO zbp1}f_La`~Fm_cCLr6%pi_m>2Z?#mK03aZkj%5SkS&;8EqnP69hFMhJmTOLaLPh<6e8%x4+ z)st->xzi;cfgHcHLhY2}(8)0P$22_npodQuE z5iw!<`*_i4{yb*9VkEzHv#3NoJ)TJC!PGq@oyHaw!`r+3MVucY(`ogG)Rn1tPU-0S z*>;jHFuZ?;=foc8{XqO^(A`gpEfQ_&`-c1PLHFAMZ+h89G5|MI!apuD290cFQGcDY z+nmOqXHq!97w|r_{Ph5?EkNiSdGi>&XGv*i_$1C_ve5-j$jUn&^?ko-AlA$ z)6n74%vZ&N%!5zEDvaWFXijY#qW|JAi1cm#g&qf1ptqqy70+o({+*uFxj>IA>#nNW z-~nVHar!;{RViQm#$&+*Ezq9a#HI>#$7ha+42;m$-c6y1HL}s$z4RJieA)okIzw__ z@td2dD1QOP$6uw|mF7@KV%mVO^c8(qfBSaXDq*lsB0#xMzVqB6urI7A4$HytEjUANsUEZSuh)i;0%d7{zdN7X$QNZ<1QNd)IzW z`c^SDtGr)iH^+mnI-Ml8tn3UovUyQ&x6VNyk;;s3S0ww3edh4U2V*(aGz=%=s7zL0 z>bEH<3{%*frC03Q?@Q<&0Lqv(^oMDQXu)&1b94B5CRJGn>>2_iFJM%=%r9fEr>mSNH%*nX9GB z_epsb18_eg3n1Pu?!=fHnXJ3Q@8uU}*qRx4$t=QRo?mmGUvi$OIL~3u^ALThlzZEG zzUVxAoaZ{{`5(^n0q1$I^IYaUTb<{%&hrxIInjBZ;ygd4S5x?$=ZntsDd+iH=lMhD zxypIoq@G#*zfJ;PgUw@{WrZtRRPJw9D<|^8ZagHR_liBsy3J&n7X1MT2F#KxP?-^!>vlBZXr?P_1x9n4fRB=a-Em#iN09QE?&&V20>zHoK99q-B1%jCn|3u4v*KsoB6barOf9@7v2JIMi}uBJ-`BKJqly_FHWPh0HBKDByX)7#RJ zeuwnzrE`PwW1@-KYNDWv!K^qX!-WP}!j7}ybh97|y19xb)d+JyBo|npY9rc{{#hrr z(vRf%o9unShRuERMJ^IkV6D5L1$KXv#~{0jQ7aL3Da#syzOtTH*mFix(7`&vwqq+AI&ZV=bfz!R+aqRWN2E}eyPq%%j}xwEr%xpw?NiJA0r!h-D~rx{g}5xfhre@~ z1DUd}w?Y0T{cG$oV4hda-E_J0g@N9pYGHMN4ZP`Zw|1(hIXIuG=BK#3*N6Mz%Hl*t zfViVb{_hv&wW=p^ke{hU0U_We)a znQ=GKB-PJ4&$mG--#yNAoqA^NBQtKTlfKG%E_9wZInOJc=f%!*qVxQM^BnCwKV^t6 zc;0oMuRG7@o##{Pnff@KKYiUv*EO#0oE5H#6DQV;n_HV>hwhW~nfy9`t|YcDT5|Ke zmIVtIO>B0}_sqH7Gk>AytZ_@v%IeX$W>?F?xr^quTsUs2Yi>)k{gMOcnjk;(7tU>2 zadT+SEel%I_Xw9txp3Uv@pI>d=3FS0jBj2PUKk>2gk5KXBVe!F~w%T7O`{Ba5Tl3T;K(^k*iMYqpERxL}G(1;q}m5qAfidt7Ld+Gdz zw}uzYSu#I#r>ACm;8OC`&y~wsmb5NdwA`~~&ca(;vemD=)_?US!7Hz;bv4ad5}H3} zfoH*@rAs}FT0KkW-@0&q>wNg#+~TQe3SK#Vx`H%gQRp9*nvpBza?P06;#tzNG`t|> znZMK%TC~Ws^!7Om;PWESEt0dCOq$a&*Hd%N6}~JL*DSnk;iBbE>lEEL-##ZakH*&2 zUg#OORJ3&5(wcF%j`xhawbtXQS<(_(HfO;UJ`m6Pj!b3&|BCo`AO9Za-*5Q0l7Efx zW%-2VUpvpU1a+K$dyA)a&in=8B`p`)a@FU~g`%aNaf?0k<}5|WJo9g#b8E|lr7g{& z`HL31Jf3UkFA0U`EVwG%vgA%x8QMjW#?AHIa%ZSzsb@~eGbaZnE52O4rX`C)z{=KK zK0h>1S%If+#kdtN;Ah*ucxg*`?jl&UU{UiN!R=X0)kV#V7I={1Qb`y$7tObS{#iY= zA35IDl3zYcS6hPPcgOv+?z7V#BVFFd@XVI4Sr}fhpw@N8oGV;`g)DW|xE8v?t_A#O zE7%3=I7|3n_P?u~_l3?gmY4S-?`J<@mos>_IPdNMhrRazkE=NM#^>ywt!gV-vLs8k zU8LA1qcDBkdS*Je81n!oZZ!0_IGdo-23GDf9&(j&fDglcgmSF{b=9P@vr#b)jD3( zekw+6Rd8p*QQx2MiP`x2y)ig3uKTonJYC#bx572Tk+xRr z`3LY^im5&oi?A8kyo5Zewc+4@LXg&2A1>uVNm zsu26?H}wAWwhFOg=lVC-{;r~Q`@LHx-kDVy`0(`?-<)tlY-6YyU6ufP=oJ^=qyxN5*63w*dPzy>gA7)Bn;Oq#ZE*jJZfVVEU1HNIPKqZ^F5M zsr=3Jk#@k+Ux2g&&V+v|+&sYalZ%jc!1P~&s{~B{onoXNu=E!q?SKRDf3*l{2TVV2 zG3*9R{|UHlfa%XW8fgbif5Q@_9dH=_CvZ0crvKnlq#ZDQ-!h~fF#T0<`v3>vbA$SR zz}<{;K6dwvqCEV`Rd{v)7r?&?ZWrJY z_%FlV4)_546ILRAzybK@!QBIR2mIV>%!L3hfd4AoLxgKk7I1q3hv8oX_Y~j}_;;*A z{Q|rPzUu_!GhiS5ZMDc-!1VXjVRT6u_6g^Y?57l*{{|mUPdq){ z@j|-YW8?{1gnW$WC7FKMdiEi<#-}G9jt?7ecaqrxJ=aI|#HXh*E^YDfKpg!t4JYc4 zmp>eAg{3_iaXRDS5>2=2u+uJ_<*;_Wu4h(#I~;$!M~pw;DSTTTBB{$1&e!9@y6nQ$ zW-qesWgRtz`!ci0zTURi$nq}EvisVSi;~uR!=Ama{f-0ng9hp&o}=q^yiS{NmOwVi zDUwQDMb7n(FrOpC;}D*5N0GVS9+r9;N4bu}VH1uLgSUC zuNY@!q2DRYjdFAtnXh}t-LC;GTd03_!XJj9$%jpn09RXQJ z)Dy4Q%2(F4HeFw=^7cA}w_Jusi6ER+CbYxKwRk(2#`1(Tvb;(X%8NF5ox)oZv&=9I zVH73U7GFPT-`TJ)3>ntLfw+1&R-ItoJUgy#TJ?x!(x}UX;TjWcv+~1=+rlm1qH7=C z7r%d#99VuZX2|(}L*MUD=#R(I3jdCN*`H%F@z5E6QP}0$zg_zeY5y16e^2}W)c*Lt zs&MnPze@X!+F!5z0qviyeJk#(G`>gsk8A(8+J9gBA8X(FkqS9p`-R$HuKgV0DHEA2Ir%JPb)+E8mpIW`{n zw_wy~2e#=DQITxcVFyMx#hUxqba#X*x>^UsfTJli*wWY4+Skz&>hN!A4~4nUpsKqE z){3(oO+BGdSlr}j?uo##)vY~4A@RIJ?|;zy7=(DyqR1T)xD3f@MbO+Ija4ia!C*x& z5)QR8!dvJLw)U{g4Eu&VEYhuGqr9}M9~Q9hR`7Qy|fN& zh=?ZOT>K98Z4%9d``fhS$-sKr`};OYz7TD|BcZ`yYd9Pn+#1HbL5HFYMM495X9?!8 zM6k8Jx1*;|oB^mevLP7S(mjYd0}*Uj(02j#_x8e8A)XXL>__RtJi})q*r{kI7&1a+ zU$6L~5yZ}ojbei>*xx6EFR}-R`Xp_#+1l1WFes*&s3xEYag?cIC^tL91K9r5DJlUC z4YrFKlUtC4SZ#K0M#TbjmdPz4J=lwO?!+mc0ggigiv35Z&kxlIbgO+uwUHSjhKj!;OIqpdOVNF2NF@HKHA9JRPZuyA{zQDi8fiH64 z-!}(#U@jNdExi+eBbdvD=Ns8EGBUDf$*MH z-GAMITMphLcKLP{>?+z-x+}12{jTt?ZM$~t8rijH*WO+GcOBSuaF^Ka+g-4`Xm{!E z!0z?C!@IZb-m!aR_nzHQBn(~`DBL3jBZVWSBh@3MeewI>&VhM|&?X~w%YUq;$@cu2 z!x+N)VH2l0P;z5RD1GO6Exz^MaE&RAbu6i`0##7y!`hsT-+n~-8&fQKtlvrbM-C&e z?L}2PlD)5IS$wSZNqrw5MxU}bHP@2I8laT#Gsg~~y|m3+w|niWCi z_ft{%L@}lBq>Yw7tS`#=vHUpZPsyK$o~OzWtU*e7WayYbC4YC=lE*rwlpmQfrnt`U zU06+0`mru31nZ%k<`KfB+zYzDS50@{ukuGf#yZYV=eQD@`s7`b0hbnC3j$Tg9^RaCRb3gY?ZwHf^jIiOq1f zb0Wd!cJ=i4ZNQ-s{0;SS#2Mr~D!hVSqjj4q*3m@69mSPxrit?|tuV!KYQq%W=1|cpGtG|vAsk;4HXjDpNQFin z&8X)|$%CyMDjI6)Ynsc;n*73L{)Tp6k$N$hMvM`xYpHFnX|8VcmsR>JA(FDXtkGZJ zQl~@M4VyC;?-gTpbI@NGXkMql`j*;SVUSo;0xRh+5_bBHi-altrNTkKVx4f(uPkeZ z6@<#0nj3{%(rTIlWz7}U!b8m8*x1l0yi%m0p;jajf;BZ|_01xgNK5?*^$lz4MGBEh ze??7QS*=JVQd2B^QUXA_0!l=N0v2I`g(6EurXnmAS&{&?;}r!^HlfuGHI*WV5Hh3* zIU{n31Yqz40!?LA{<6l#vUMVlXoZ6F3AZ%)8!P=)HTB5Fi6qnpn9fNGTtj#=;YNQ& zLt~|wPPnFC>7GHP#lmJ1tE#E>H`mnh%?PZ#wxL{<5rQ6nS)C|Xa6@C+O24RxG5nRm zhVoVZie^!1NyJEglBmj(sUo4GO01NAZ4(k-O%Nxmnra%55-YkIJ3}IFWyxo0#8)F4 z6qxW4Q8^(Bq~N+nKeqUk5=J)q8&|VtZ6jJ!TkBtmLi_BqIIOO$=>$k9t4}J`e*h%|j_*`Yx0ptp?bb}V z%xiSe)1f=dX!O{vmMkHr4jEIX#l;>m`7?$$A|_W@jL#&1;3LXb;a~=eRNdgNKuTSo zM}zB!qC7Z$W9VOKVE^Uj)QLWdu>CKzsqVzqlo1O9Z|68po#>05rP1ZyExxVFS2#g>m_v70~QldCco#GWAM+kKYn~BU%}YzM7YGc2Y%($&|OgDuw76iu?uR9+2J%)hZCOc|FKtS zn4>$Kzz^-=8i^fFGZ?6;S}kl@*(uBj_c;7J??c|(dU^I()(Q4Nv92Xj9AtRxVV!rj zpv6hkoKl_dHoQY+@G$F?7(ekd8L&{O<8iK0>s>}t9`(9=x5lr68R^NSCg!3s?7>EA z`TCVtp^H;!Hp=fTWV!A0D8I8%y<6Z8>SzGU-^>4& z4;buRXT<8{CShb4%2oIG2A2>yi!#6E=DkDe9A zXtuz-A?W=tKQiuKO8-mGO@`avQrl3!QrL4Q9)uSAnwt7@j$Q0$rLaF~SI9ZCb7`+! z!=AtWVksIeGJ9=64m<2ur;k^a>#!xLB9p@rv-l_`(o|s$Lxwf0%jzp@{o)FZO53D; ze=wx@VXJ`qO+-D;3}8gH(jRQDZNk{5wzj;i;so*K{0Z1sCX#qvzdH#~W&!>jR|0i# z21!C9D;Nt}S%X0i`r+%2UL*<~>+>_;Kme!QB%rSBD`aMu0oc_L! zLzr!f>2^jrHN3S$v@5zVMz6qfa(Qd}M%?$Icsb4{>_2GeJSjBLkIex+B9xy(YYUte zXvbRHvE1Dq!H$QB=v0j9!W=sV8}eOD@K{`Ndj2$~Ey+OhU=IdXqYZUt=Ddb@+*3ia z1qXW~Xgq22G*=GD9{X^#*(6WCGR5p%4$eJxjA3P)ro!P46ESC^;#gO2ph?}*6Koap z=CU|E_NBTlRrJ%vd`%BT>5K(C20FxoJbqT*V;}jxYB-ajsspNyr==eIS{*`>PZy<% zyk3*X2P+zzgLTcqSSiO)h_GX8pH3fM$=nmrh5`^9@(kpN$8H_cR+hDkE^S$9)H0@| zL)@zA)fPSW#_1W1bm01kAa1H?4~aV*YV3BEm4TxLVT_Xdo|e0OOu5KVzm~gG%k9u| z+1A?%wLh8~BiF|MoLCNU7$%JKjiX7|llKb%@@EX6gTS5~fH~CQ z2T%s*ISPMsSS8m0Xd-1A{*I;YZU7;;lo?vt>ue}jNVL^q0uPvVy4PBu~92cHPXYvtB163e1HJ zf3Wk%5RzKCZ|_4msTG?-G0xOleE^c-eAGG(z+@uSz61cTkQ6C5#b>1G1&zIhvyrWz zOK-0aF;~JZV}AcT_U_m+8Sb1ZbR#&}8}5{eu+Nh^3x$`{ox;8#cPDI1vbJ>D^K5BMGS|Tz zP5j#qcCs*OvWwJ|Aa=hE490fR*-yzP{d5Yy!nCAXmoN!iu8~b`iB-lJo{3767FOAg znZ`-Pzl@mH!ue$08!0~K+BP_jH`3?p71y}?wFft~27AyS61JR)=fZ|*n9pn*!k$Wu#Vyt_=x*J%$&ZvdERJpR1lB$W z?`uN;+g>=2uO|0lN4M_8(XAu4z+yjT+UpEF=6Khw#=G#M<6Vz5E8z)rk2UCZCk}dN zxE-qVZsttnd)Q%h-p#X8IGO1vUxy_N^P*hV1BdLpo7*Qih^U^td9e)Vwgz90fC{lA zeIJB8{Dh&SR?~J$nj@e?UYYR+irk^I!Isy?r8Jq9^LZf1?&8E=(Pv2U{q6q#fhqh z#=5d*ECh%mF^&&~vm7mf?u+9TOiCk^3uhU3a?0Dj$QCw5N2fhXxAxuI$E7gEK4)WS z12*llhc3)_~a$NJ;^MtB#ast|Ux1V;w2aJgKu#IAll4vmlpG#Q0#av8A4?$iYC9zooJP zX{~Lju$D}V`06~OjK97TORGFmPdRz1q)Y>dB_w9MkA04bZtdvcWQDO@zR-lp$wX}A zH&#g86b^lFWl-G@iTQgpQ9+yw=nZZv7RGV*+n^;oxoVyV$|75PG0Bjisak2mwun|7 zqA+SC>OP|45@D>ee=HT(UP#5b6SKP=(bZ|)5{Fd1)~#=-6h^}lwQoX@fc->hoWBHl zP-yJ-*C%-*;_hTtKac%UEs=wRF|iXoNkw^lt)(X%k@5N`ZUy;fD03YI;G&T(O1gfF zzo@)AK;xaCPyREM{){p!(Z0(dm?lAV0e=l|B$fRGxW{nFb~ccY z0Q`l>5D*h3YJ*FQS7j!uavFxzlM2aXhM*p9TgWCtJ%s>f!g(Lo=KKmo48btC!cQ8S zf4t5Y3t%4b_ptG? zdcpv>Dc3t)n{%k44_by=z<6b+_?dB8D%3DXxeH_qbut2e9qSw-jDY)9E`w7!s#TeZ zsw_jl3&~*yrJmgYZXrTF{O;X-aNdUxYv|jSp%ySf8~T`WY#P+i(1)R7FLg44rvW@k zgc1A}z^~z?p_T^I0xVUQp>IQy-9)M9PXIn7LOmE6i+=*~elV7yN0&e(A5!B`zf%?h zNrk){ZpjKDv%pE=BJkCm#`kZfj9Sx*22iBL}%Kp&j9P}?%9o?u3#Ow&up!5luw+!OTi-O6y`t&d|% z)?SN+Llxga1VuWx*6K1d-ZSi1GLL=?<{5|?H&2LVPXMv+y!|Y1zZTzw_MDRzXCPSC zXS(5HODHB`w^RJfTr4sI2<=nr8HKG79jeN$HIv|!AQ(6E`PVE=n#>|r>*caN2TeU@> z;pNK;KM!C29(FA}?5s=*2IY~&AYLf_16#2vL)@&N%=hlpOXq2S$VQv(R6kYk_@eYeT&be(1}cs9dl&v zB9U}`oc>8x9P6z(ytv>@=2kTNQq8g(C(4StB8dKF7@Ko>)RiyYCc~QfI#uU`F`R}; zwkbF*E1Kk6e-=_d4eq#c=(&c)Wl8KG*mkZ>O3{X&iAsNiG6oZUNwYMWYM!!eEQlFm z6eBgp2_os}xbSbp!dGf?CDaTB)i(5O^vw(71{oiL3OLRp&VS9sj^o+XqOjLQBoYvJd z>NYtUeN#FaZkwD?*YoK_N`#(Hx9REhQM2huoh>+yU5AVQaUfn8p6sij#JmQ7$&VrP zZU^AtpD?+O=!^`;i+j%j&12txK$SOUv#}8ai?z|?-L~)fKA;9F#ZdvZuFB*-U&tq2n$9QHghufoL;+TZL zY|ukM)YEY3ZDBv;7xf7ou)W)l^jR^PSMSArC`49okIQYSXgT? z_J%iwb8|fg~_M104XWRvoj6iX9KW0a7a;Bss3g9IYzggjKBd}27w+u z;(H1`hNwRx?o{Ywz3C?pH_`kR{>)g@lbpY{z?0AzO^b_ATOv3fX2fc5D$3 zDdc>kv2Ba^kwSJDjgheUu|lo_CoF!VkP&dY#a@N%f`V@GQ-$m?8kdTP6@0(ZxJ*2v z;Jrp;aglgbA^U(7i^mkQA4rLKTp=$3Sty=R$N?aW#6E?*17tCFmdT<&Xf$?*#m^P; zao+i;I9NV*tVRc`e}L-+5!5*GhBN7h;0Sw?Vz77z`g_EiD%^;fR2ga;+F+62QsiA` z5+^*$@%@b8iCE3j3~N@59Yzaxut$ zQSJw@*QK_8ZJ#hgB)SpoWniYYe1ujfevJng3&sxnxa3Mz{LU|>1UszEhvn8TcXW}5 z4S-wj`kHKH{s=KhL=xUJW?V|bAsfT;gLTCvOUrQmvTdWI@M1iQMs5FQ(c?(3laFO} z_l7Rf>+mfH<`!8>xXO{Bqk@zBxghty4ogNu5lP#rXf~s{b%P{a=JYaN z(`dxUdImOyI*P?N70F@XRoy?(5N>DNc)1Gb)WptCUO{q&dS1~MQnCp*-Ok7DqN02gLSQujbd2Q@|{&Y z5N16G5pj((={v~M0_WP^-Wc_}&LkGZNRpN4MdDhgmt`?xh^)li9dSC|1Z(1m;j{h1 zIerTsEN6A7wFA%DGfp>A;j9g9Xl>sr_B-9t=!(R%PB+VZgpn7EUn*=5u@do|!uAqd zD4ti?eqxKn3ko|xY_WJzVFw++juyXC7#?|`OT^$a%Q>LT%!lXVm*ibxWkmW0V)0@bHfJZY)O74Crb8hp>0%CB0F{|puNeM=x! zxDR=)zwLF&tvZ22IPZ8TPezZ$%i!_-fdG#FHRBkU@O|nHK|sFZ|LM(j09H>E-inR5 zjt9@vXI>x8bH_&<4KI>h(;0#M<50R_0gC==0IA!k%N1yD2n1{WtNpcc-4QH9Aa>zM z&;B}uT(w6O%9ufQQxca0f5!TEMd}3f_-scwusAig9LNwZEC=3?OdnX3BJ#i@Ay}ghEE0(xSR@iX zut*_5)PY4p)`3L@>jR51M(lKAr6my~ z`AHgeV37nKSd_jxut@OG1B)Jpj61MMJh~i6#99uNf_gcSaNKer(b#fe92Q*;BrSe9 z5JwuqSk~DP?8Mes++CdU8EWJ-YkY+nA#5@V4@PeiGaj7uBh-A4{onyL0-PSi-Y2}T zFfN*%GK0MVOl7&3=dePjW8PYJ{!@vGncTP&8`;KmK5X!vpE#^BhJTL{)GW2hiHlEi zy3KfaKFJSaIJOJU$2BbLnzKi}G~SCQ>=UxEWtx5Z$K2H34C*m#+@!HEdPqF(;=tr- z5Pt%foK~h%^cUFrBrL~Fk+Brh97eGy%+$QM!Aow46a1?dTtvYlksi`K7i^@0MYxh& zlkycwj$o4?iqo-F%gV^0Oacp^!a%+cD7<1UbII#PH&FtVKWC@Rv-FVBC(?t)Rd|g(f#$! zjq8N3!smM97u3LwHYjQfbeijHfbKMmf%S625Sv0?xJneC2s*8eS z$%(foyAH1f+=)!5nOO3|d0WAgWYh)@W!*7_i>~hD(Ur{M+NFcl6f09|&Tz16AlM!e z6LOtk;bi3RRO>vNtrnp3vYtXfkKL_haQsrPcT>g2&{n+HjER$PgPM$s@rOeR@myS< zP~d(KbRR^;6c4Klo(~S5rh1P7-R;A@l7nK}Bq=1^H-nZ&wUkkNP-jge52sCh@EZZo+hD+tR5LcVr6(2h#E{ zwoM}bRLbdD5cE~5GJGAf{29Yr@#6J#Rrd5$%iB@K=@VJEXK-Kv=Rt+%q1vycGK+2m zWxJxP;juU)jd?f?ubw2h$zRv%Pf*%1VS=|43Mwovn91_l0U-_tyo2I``6TQDaxVe=z7pr=BlxT0A<{K7(MH2Zlu69iVf82NQ=R8?UErNbAh2g?hxZ^-E z&T|Don@U&(cp*N3aE3I>8j}1+jj;R^OtQLatn1jmA?rIUCf4`b4dVxhBU5HUNLJtJ znOJEY3W?rS=A7I+62w<}V-LgtmKbp^+N$27>@i4ft5D^30fXRY4EM7fASB8PSv2<} zk$d30=n8IPU{N8XdmXfwNaqc+Bv(pu8s6b9xRgCwF)LpkR3dF$5Ocnv>9RcD*9fby z7GND4Z8w%4V@A)R(Fb+M;cL=l8odCPNTcV>pwavkF+Ni*Jn~teQ_N?58}I=*FP9u? z@VqRB+6&VCa4EC2EqoYkV89+OoSkS?ixhucVkRga6O+7t4Ex<|h-S!Iq0KxkYGxMe z&ufV76}XwV0NJHwCTp49(4MsmjCUdN7M$~TEinytIlr$F?j)G?h(@fOOSwoBnCCy$ zW`0$O!ry7S&gS@PFTRfjKlbh}$F_;dpGWWRRPbm<9dB0aYyUrB3$oY=8RMTQzx(<2J{9VO%Yj#Wg zy(d!OJtdHA=w;7_PC4?Cr6vBLm_CDBSQ|QJgzqa_rV-oQ`p2B~$56%?H>iClScB2PztAOjl0p#dzN_HAg|iq)=OD<=-BTq;yKaTuXLDWN$^ zlQhW+|7XRTr^1h7{Y9~kQlXlL+9IQ3{;OhR!IWii2>T<&E-}`0_bn{Z(WyK4|E3a# zwN+VdWu)Toiij0fNmO+>B0g5+u)iT_Y>VF|UTC-DgXe=1&; z){AAK_KkW4M0}!(q&l8gf&1{W)%H`x3dGC_TcQ4`SZm{0I?!i|vmQfEu9T<&ugI0p zc31T2ZQRsa*4M#gqU)%bJ#smyvU@GmV7iXJYPTKFv8%8%L?1l$&>u<_+P`N<>UR%+H;|s3+jORXMs&IftINVtbi0 z`n(lM(dNaP5s96*Iu89e!#Z!pt#fE;^m(f^#Nn1L91dAgjn$-DN2zegie&6D7~_x? zIhk>sxRX*iWJNCaB3R+#k4oW?6}kDbsu33yhphPGDu^=UL*kGXnNwxkj)PTHGd-G- z32Dc{s*{oSWai|AZ{&~P31k{y3Xb#h-O{{lgK|VRr?5wE^ zG~kklN`Dik7qDW}C^FB>=Y>zxx$#fPx7bDb(hk$WX8p~r19$@PFyfxPixnO3FCKQg zL}AIOL(#}CRWzSf-w%y#N4|?@TUF&yft~q9WiTh1HqA&lkYZ%y@_nCYeHvnQ+RtJ0 zHb`d1{w@beBy$Oza@^WknnBt%mKaYI%lV8TPswqMDmN1Lbhiz(4s69eSG{ znqL6QVz`BHZf@CpESJ?;3q{bX4GcD}E)$P?SZaPqt$-VUHb%^rHJ*PU*w21~v4D9k z$PS{mTLIY~;@=ba^H9D-TaSx3S#gyxVJU2<@VU^c$)!tp1w^ii$Auz)hf6!)ntZG>Jk9krHPP930C2joPb|$wXT*x_5zdp-wd6 zu@e0!ZJxLv0#>34#}YjW%>tVSndk)o=EKQfw5drvNEBuZGNM&4)6&N9&yaGN%z;=k zBQlxCLgg|znE)%G<6?x|q!U1RtOR`DO29P`uo6HxmVlK|TmdH&uol2-IQbhR0dYsT z+E{)CTK^Uu#2Eg2Iv-cjHnSV`@KmU3gOkbXh(4$yBp=aB!MPYtHE~*#lg((?_0Xc~ zBhj%^R%E4YGX$)Z5sszoJJ5Y4oJ`s60B(ij&%-8eomOC+4N8w!Hf#4o;66C{3_8e= zZQH{j?S+#M;!^;APJ|EQivXU7!!MzZmv5DC$_nPvHhls9wNj9^oCc(amBchQ!#uV0 z8l222f2;yj$qJB#=4l+9tmi9bJ)aD8B1x?0)v}(?209B)=I6I`oHp+9ZumIE%1@#R z`I*aC#w}Vt3S?_zb>7CZbrGT{fs@&K9DwC;_|4p*ReT-k@j+!aCMY8?=|4366wpaK z1OF$2lZ`#}OF5Z8s&NqWnPoI-;@6;cel{DlLNxEfm_MH_yPH*Ffy@{A8ZDCf;buM* z%Y1-F3{twW0v?iY7I`c&hi{i(TUvASsC7~pb2PdOJR$31bT6dtJgIw97@c9Oe>`C| zUh85ut+Hm}<^kl-7;eo(dig%CMMhLJXZT9~GJuod5?;+7E1z2sHph_R1|Zf0=O8VX z(c3{fA5LcU)c~%9!*3324?fB+Th3}pq8UEEi*JI+b#Qa}mNrh5)%OR$?}n4r_XPmY z5n=Ux4Zv^U*zr`8mXlCXjBnsC`Vod3!MOwOWjJHog{Y&P+$@2Jx>~q+N$f87BVOZP zgsa@?aGm=?b)`G~PToV(fidxX^uji@e4~nrC zyyljAf3T^d+F#jH>yM`e${L$%Fz?dnUy1&F00+7K_1M^C#D!|YsqnF-Y@?-`0<|^V z7qhYnGxX6|t*}+KWh-SgP0hG55JSYML|wz`wYUR5hO65}>S~&Bt4KvPb_OwkGbT`l zElI(OxHu{@e8ta>I3we}W)zH!yT-Abds;#N3;T`%>7IM0I4fgH^1GoX+ zk3we7l>6&(FMb88BU^N<*49=8bPdRf5&0DY#Dfh1R9)(>koBP;CZmf5ThfpxD1|98mdvcip!~K0 zGCaVfG?gQF8k)+*)R-KeoU+=QmAsdq+PSrk`HPAev}#)uF2IYL#cXRTtFFSw21d~; zYMU#?jM236W?bGLl~M_+DyxMCG#@fW<#jb;R-8!XsutY5-%^jqpcZrT(XjY#K(MBY zM?F@f(3=;jHR23Q{znBxF`_~5e%$JoniMcTdYtMM>&6aDS#vcuB_9`~s!%xjP*qnJtf($SDTw0}*(HmQj$@a`v)6)mxLQ$m z1i{f2qx=xbxL0n)C?-se){@Fm99m-4G=GevUlMEZi5IqaqAJEJt6fvJt|?fB_w2eL zUdedbE?t6efkaDHJ=<(%YW?;2GDwusR9#cmTr6s0l#~2ygw{6m#uyb>eWh3xg>9f%6XU3QtDhsh7Rg>4W9z;XGPJTr-$;fB zy-BQ#iKs-%VizaH$W}R>s8jl-7|V}$eQ-4kx+M_6V{~$iRg2;irwG+w<+qte^;gfe zorB30DP7ixE*)QuqwxTF${;D3R#LJu3lm&E$Qxc>Z4tD?J z*ZFNeTyltwrg(I4b^|-K6&(F^6ZT))@qy%UPiRYl{_2u1O0d4LR1l@e-3%5PmpI8o zA5wQrCPwr|zhGmV<6DXzzL|zW%3Qc4-n|(A1)Bv0pn?|v1)Cz$WRP|M$=f-^5>5tB z_B7!i*DUKza?ay{rf6bV6QlR8K8;b)=kjH(pJFh`QD#An8eOi0Mf}ahU=g-sOZp*q zNhTfUE=lX2+~i?|PrOU=f8tcRlM(%E_q?ZA*L>Nhc=w|eZStD08A&OCf$)~EnV$au z?6#>(zGg|5&!+D9DwMn&V7%gMw#4$)cN2KS*BnVGKu~qT*IbED$1UL2MXB?oI_r8b z+>=_3h~4_j+)C>Wj=zIu=bv!W#^`bJusV?|%(fJoSb}X0b^`Vow1~9bpouiMlLLCU z{0_L%e7%DovQV0%XT_rzEE&a8Yhs1KUC>xz3AOf$Ni^wbOfMI~xjK6X#bQR+0IY@- zOx$l0<&3-wXd7I*K4@<&^wG|*f%FwP&k|kfmLd3Ca5&q?Jz<^(P5%TDjmIPn=ytDI zZ^{cHFd#LGOk8B~RUGr#T)+vZjFWVLR}ere!Q>4za^~VCROQd*qevgZ=EvX?KNoq= z7|%-1#B-SIV>~LHwz3`-50U7jqHbONA9+$_qzOB@{%cjf4!kA;*nuD*6lK8gpM@ zy4n{AFS;)Mz~Cdn{q6nN%%`osAj+q-7q+{r@g;#6Yjy8@BNeyct@zcyBA+t z3vQ#eLE zUJ}=s!8M85RhG&!UrSCxZk0>UdU6gamMWF8>nc#^Y>CEQ1?rq5DFxB1K%H|XA^s{*=RB#iP^5DEpKvb79S393CdBuN z)8nU^Q<3SI?HUxWS*f%xm7mg4gu={KBml>@b_mR#`8ujzdh`H)x;1^BK6=Y*rX9gD z`A{A+4}Wg=wT_Hau|+y9xQ300aE~~~odgC5_aUU7fK{Rq)1#uq+q>R@d<46+0IS3;nYLM7GXOt-G?YLdZ2T= z>q3B{m?E}|9gI4YU8X6ike!NebkuM(;4@B{dJG7rerk;`ClSS3{~u8ts{rQj17@&s zS0Rj`JqP6DrqVd0b?WJ{(3k`_+LB2?cwVJ8E!bj+m)lci)CVpVoPwW@40>KEr|kczdzG zYQta`Gwu!hxyY=NqHM!sVDUB$?r)~O251m50-tGA{Z8SGi)q{Ui#(1TKTx}loV(L7LXfEy7RrfjHl*%}*Ica+VR8J~WYLgd0YmH5<_TC^I%vpAa} zWi9m_>*QW52c{C68&(GSQLY$P&kLh^P%kyNGK9Uxq}VJ9&U*50TzqE4qSUw6qXy~# zK%}XTD4}0%#TQPC(ilQQah;0GBGiXA;9^j%pay3Wd-{bh9`EWF1@Sn}zvC8A9iRoD z^cuiq(PmL$~G~zDo`VGJOSgINVC}|ZS$PyWZf1f4mcYyvt0f^5?|a1RSz~8Lt4v?#{D7Gbda#k2 zgQu%}j}iJpco`dU5<_9+dW_%EzqwD?#e5v_AHDf#h2nq`dRNyI8h|VFqQxsPc-*m8n$MS$Z4OnIRWZh}kF> z@}5f^uu008%p9$<#?aOP+{p5vrNz$4keagN(L(-=;ct&aPeZl6Ssou{d>Db6a6Z{U zXL%;lj1xfclgR3p<(Wmn9^f6ManPORIhIAiTc6Fg~rS=e`OJ8Pxxjzrp9(FhlN>@)s|*_u_b zKZlW_tyu1v@H^OQ-+A!NNj@03!ZU&I=dVH8I=Cd%0lbUEah?f$T~=hF7YmofPu2}$ zaJ5lXc*Zjk3&soaDLL{Tgy9l)BChl#GiN7a$J1+I&#xCjNE-e zkILpbGm*uZNdV2@wHMfW!IWSdRO&`05ke6D9)K#^CsLAS1{pa52f(0Sz1UKc<%rq7 z^Mf;U+GQ62f-_k2s5`4fYh#6TpP&&R5E=OghGS@_4D=Iwl?9j& zK~iq_xOr8weIhJQLEQXSojn6cA%LlHwhdaIPmcqlP|b-q8*b`n6&FnFBuQ6kbf1Zh z)nxEt)WX8{iw%kxnS-5BaniP`F2z_mPl%9Y;6hkrm2E&X9+-u1w8S%hpc(56aV@K4 z9GcO#`Q1t_tNA0A(0-PN(%!52wC8ojx4E}iOET(&tWNDLyF5kY{*psco*xWOsDLPTt zJ*N2HF{1pb<}*nzjKTkh<}*njjlnP0<;^5zA&$f>c|!AP-Xg`1Gtb?kYX!^MvKfbi zAza$2^3oYn?wRZ#CBFsge)rKNpN=R_g-epdM!deo3+`lg z`kw{y0XXOB!g$f0#qN-I7G$ zg+}Z_NNs|%bTrs;fY&QWwuMhn~1I!QF~I!oPr%al*! zxIeMDbFJ){c-XQM)nC^UhIv9hlds^3v1bb1*TLWxwNCoD>tf{DxW7T{an}Mq4deI} zJ?^UDQ{?0fz44UGO(7>vEkETN&z{R{z8Ri&jpyrn_WO{3+BK8IoyDwX&URt=+^Kxn z#2hEO%0WFA>~PBw94-k~lQ@{h2q_Y#M1~>FHc5_6vg4b84a(BhuKizDc^{@`{ET5X zf@}a*yQW7QfYq)=G<_4Qz^QQA;~^b%$+xm?XLU9|zY%n$umfb8sX`poaT%fkm8;K{G>kUG{(EqqhsZDC?7snW0Klt6o&oYcfcJ2!wFQQh3ju#s~kU`-H zWQMd1E6=M^#(H4My>JOJksVL4s};BvS; zhL4uxCaw1WT8`h+g3Rr+5w(@ussyjqT;}t)C0FJ1Gn&qPzCSLMyj$M=Qe3Dp@>yl` zeCGiz_KwPBJ}xkV**xDlE&903cP`}Pawn3w8%}2PV&|yGWwCSAycR7TMw!gk>RrbaHcu@u zvH>ocZPdGt`D~*GfcL@qLZB?A)aAg=r4*a(cOBI%%-4Yb3T_gc<_{gRFp~-}A^}Y{ z-3J}A>9)P6jbPL>;b1jyQ&XOa_m{F63;Ib@n;M(M`hxx90g3)x&n;P;AG;f9P^m?cY!|x zC%@-WNer-%rt!|yN zf+?E>F;xjz;%q;E7{@(YauxjpO=s_Aoes5$^+fex81#E5#T0M06w9|dxqCJDD@e+v znoIf{aiMOBi*V|fV%i=%MB9ou?i&_Yc50gZtm5Z#GNsoqlI*z-< z;>vyp!~QXj%Q`wLtlO`v6f<>HhQ`0rWo78@>kQ()us%!&jCY87mB>3#F#H+A1qHfB zjCagnxh+GvErgRbV!Wf6HR8*_8%bm3AMfz9^lt_}0+-Y+@>JD-1lUjDa@d>6cett9 zwzDTGEG9ZURPzCtzlO^?QCq<=sp^uj*DJdu_CtD5I9wbW=;mH2ULf^PlX;wizRy3+ zLfR|)QU5fT(xy31%v53O)sglWC_ePL7-;S2-lA8+A20)JR9>uy7XI)t85k$i_<*^9 z`r4-9{!X}=0sSDAN~|s44qe--Xb(;q*Mjqvm)TVB1-h%?XxA%~_m-K$jz{ zRV$KH5Suijryy)QJFOWARvt0KZi7acBxgJhsF?0WEO)>qF_RDAa|Gc32KWnbGO`2a z5*^vhyL19i)mFbotHa`bGliw`H-z{r+|jH;Z)#C2bs^FZOq*=bZPU@Chlp&@vw)<- zWqGyPazu$URyrtW1^K|My3a1u&Mx7;Mhi#l=~1ew$CT7Qm~|W!E`@U+cUU>uW#!B7 z1O{M!h@)bi?9TR0gJQsxGoS2;@Vz@=%J=R#PC*Wsb687KI?$^gFpuHn)HpW&17-zb z4o^3ma(EiAHAJmlO6zA@Yge4st~jk-aay}#T6?wD+L*0WYUC@e*5(ztEe=UChVMi+ z`0%x)kjOVD(B>WxI^gP%q_ zKq9^vlCx1vHFa;JBPj$Vn*)cJAo@$V9P9y^YEEahK&j<)hP%ZyGnG@#9(#C1Jtm8j zAjm<5Fy^Sb=;Tt3Fy@*$EEy*j|3VvZA-XY7vpFZgDFI`?BB;UpZF<`d`X7jHnd#|+ zUONZxVg@eI1(HWbY!IIdayDGU)Hy;tq(fuCFMpnCAT9=XE*yUDl2yuF-T{oN7_(pY z{X5wAm+xMFQXKD6;6;3i!e7b?8{hnFL5jqXy$+gFIC*Of*=51VVcd|tgu^n~{0!Nv z*jzaE0PIY=%xPz&tGg4S&eABJ*iOz}8rxz7VSLRl+eVK1zOF&J{9;_8q~%LjN0>rZMn238sjrI`85wU&V0@mjq!N}&gPTyf=yZ-{}><& zYop}@HV3O5r$kfQx?9o8K46pTUaud~hK z+Jcn7&bEZ+#=p5Xa}@>KA0pU;={rG{Xly*X8 zIN6?;*yKCwG2lOflW(ZyHaGQfSSTCL6}A*LQ@rae+29_h^5b2|zXdn*B5g*itY?^{ zL146|?KW97|AYuLN4BOv(xSNM50->%F4>x9BI!Oj*_zG*Fbyv2RV}Mq(-j(JYubny zP=(dN6}LR2O||dbg~{G?;)KFV2va(2a=(fPIIC9W7n|HmG*?Y9;jM!2S;V-bI}Wm; z1FoeH~BXMr)yH#kZn&o-4S0;`drRd6!T^K2z7)$4#?31|C_ z4$Sqa$q2^C&%hkphnh}Rjfy@Von!m@dsJkAi;gNZ#Q1ScKc{oDKGH!r0!}bfRhnyz zZ917nC;9SCI;Icg0QdzoEL$RjVaC`w9EwPkqX}A&rzG-Q=6~N7K z?m(OdRbC)otclULYJu)f$3Js&A@W>n-HQxyBs%#4W)V{|I`9J)+3Q z^mB4GC5TNtMYa+SU7bB0!nV+s%e_6$Eub&5sktS&Lkh0~5agg$KvQS9y{9!2>F(Ux zBd(O|Xhmq7@j|v;X)KZ2x^O?A?P^1*3kln|jSRkp<~Xre=vrgEoXQdln5aFv6<;F@ zkHyEO2bs4&MXvma*~B^TR{%T*m-Vp@ATxRa-=%wWC(}ea_%nt%gt9-z7YwSI3(o#3 zkX`^GIL~`PehT1XBL4uwoZA8CapS>$1;Eop_&PcWV_t>x%mlJ=F5WQ1E$&yve45%jt)5Z|`PrKt5DrYvG3YktgnSoyguoW(AmX?oI&Q?t^ z#3Rsv!`ufg4L2gdh^65N0Pco!pBJaWs+_j(HYhV*hD0h7!K%sm;I+0P=zRJ_#bqha zliax3G&fG7l_F-ru(5DwfwF+F;k}xDt{oKojA07e`@nh;z|Y}4rvq^wg~eGo&qYAy z0+>SNDj-_`1c=-KBy9lzIC~qAV*$*Dn@mI&)(bi|L;M0ZJ!8xIJBx&cbt~kqXFwL# zGXS0-!ovD9fDhnQiS)KuCGrL|Y_L0)(Oi~@s|Wxc=Sn637!Q|qnU;^0$UaRm#K+KZ zn%!}>rJ)P~R#+OE0R-UO@5O0|mdL^8Sgx`VN9C;T_0=)%k4JF_p)gB#?+@wKg5drQYp6p<&3@n|P&!Je^L^2&)#7l1l3XQtP~nWWethI=vpC7aOq&VHcv9P22k>>=lhR4t0zw~&Amos6BarV( zLPVUDN6KDc55i@=s+0U<*invXaGC-=B6*miOL)#bO=SqVqd3B(;pm-3xBnQ}v#NDr zwp9L%;h#dIGa^>yutxnB@x4eZ+C;6F+4m`skKnTNb-*`OG!AsP7C{M$sBd6XFjk05 zUDUHpKYr-A$)7RI>+KQEQW?$sh3M77Iq?-Sv2^M(=v)o7o}@mpbS?{eE074BF|bJ- z_A7V|0lLk%)Fo_5aTn1n<5gJ$nzz^ryIF^BLrmLpZ z!Nus$qbdFBI3b$gcIXQB;&^5Bfu*n~+CaI~!4#KnThsMn7<=KoD|vPy!`_>~ z+fh{ezujHCd+&YbdCGV)ha@Kh1Tvh2jF6m65T+9bL#7iVNeJWwLI?>4P!Q1*NDws! z9B?8aP9Ug=ikIL7PEnlx4naZjis;olc;$V6Ro#0y=Y;FMkN0{1&-=gq`E>8DRn=9i z)>^gJs#Vq9>D~{+r2BpDh3d7#d8lTw**(-~zmS{m^@Iy)TdL?QDCyph6I44Lo0{7A zH!2#KPQAomYGyPNg_G<#{Qvkq%0b%E*pxcUe+PXoar-FGz6LVznH=q+T&e36*X&C> zN7tE>+z!ffl`bpkvw!kD!K+FX1ki2gD_Q4NtEJQhM#Qa?aZD$cEM5FyL-vU&6;pxLkd6}Q!|_lE0ECaU9=_G+{-|4&>sNVa@$$V$@I{+-S6E=}y85?-mb zf3^#ydHZL(U^k)2{#nFJWBX^(F17aWd@5-2vTDgT*+tqmNo#6S_RnU%hZ1|pZ1w84 z^Vf)rvuR`ZhOOJJ!KzmlupD5h0MTk5JL>APC8h^eUjw8gl{>ND(-kYQeP;$`!tYPT z1&85Ct=o1jU+Ac5KtJe6*;A9Q-pmc&@Jx0Pi4n9~Y-!cpEEQ9|LTby7&E5J+fvoug zhu22sTf9^#SF*t73w}$kl!~gV%{HQCYntn7I+80>*qkjf-<9}Qu0&GHwkxigDx_?w zGhC@Z=Sn5@Y?`vx7MSe{X#SW(v`Alf1Qovoy~%|I)=qK#Jte4=psiG%?eA|$c}<0m z%Xq%x8RshFs(cq02YPxXPbX1;4Un5Q@3M%kaIE`iQbyUuCUc>~?E5Mq6jPr?tXwBX zCVPPWH>Q=T2cFD3dGjy>S4^oT8^@{8@$0H(ZW+1KOALt%kRcZ&Kt51sxu;AJ+je7f%3J)OBAM;ZI4?Nf4#1^ok%?{hTsy~;V_#vZ`$JZ zj1g?f=}dAH7`3+v_`n>`yNAOTob2^XwYAMi#ay?{A4hq>I_Z~OOK5_eg^ByWF}YPs+XwzP4W%U7?{8@avxbppQ!(47_x zE4=-K1bdG37X;h9p{tu03}4pm?H{g;8_r~c&SCf@=ziOY)FM!^kg4AODJt`QAYb4x zPPOkpRlo}tdmayZd*-V3o38Tiu)R1=`lw*rr+9Z*-SUnO&s)b~womo$ut;xMg8Xn8 zZP{JDj@Pt%cUZIsE@fFr8GObH4}BB;xx=#K88W`YVU~J#rjOC|kYyxvto06*Xk`76 z#Jv_U**j1n$orPV2@bP<0}9AHP%GeP0NgL&79JuvFhHQwR}fsWAf6*Q&??ZM&VrE~ zX3J%psBW}ie?1#GhdIYP&?Z3pN^}y3SwF=)nB4+WHRrHgWg*+WgXMy}1IR`Wv)#KZ zqjA=79{WSi6=0HgSD7H!U%=`%hgt8vv-S&!c}*uqlfy{*-q|3~nItE2jOLMO_hbO^ z?t8nPf1c^$d&#T2&YWyhPk>vmNS;ld5`1oVT#{NR6MkQr z6k5B3$rq0oe98aLTjC^@(Fvl|TL3e4XC6f+zMQ zN&8U4bk({)82aWIx@O(F4Gi|%f)zIvmb;>>%lks`kvGM#b(dYSO^-ut_l^ed+UI~R z<4`!aUF8zElknrAXk97(!Ubg93#|@uR4pO#1uh;{Vh)M#aq$g~F}kCC9T4qb_!l7M zn@LO~aSBKI4id|`SfqsZGry6G^-A1A;>}##q{My_cX07`j!djuXE3 z23ngx;9T%K=?OBtiVw%A4^ENt#;Nqb#_V9fCZ+wMLHXO%AC>;1@d?T*-a@D<*cHQNlAg`M3A#wDdBNSW;K(YykjwUhFUN4zT~}tS%bNfEjO!40 zr}jUzCnAjIPxb<4?Q?KgJlU@CuB@7__-hQ8xvW^c(-l%8*cVHNEbS%k4psEa7%Ve= zU0jit63(_u2`|UFGV|{$%2hxAGtN~rMOrWL$CV4?!TtdFhg1E%qTt^nhxkB~g-2Gl| z%n9Bd!N)j#*JbtXtGRl>k57|bO~)!Oiwmfs;K?|l z-snS~PH@zl8F6oZUQnW;!j-UW$(8t1K?!}xQ+4c7e{&`3qN2tNMUZc|IhYugt@VPRDmaR1-#&j7%utvMGh`*F$S-XGu5kC3o~t-zqv6_fYz%1 z812W}TO^tvm#~b^^}8l6pV`i*%iNvbEPT+|7M5GH_(b7OOUCe zAHnV_FQ|xf)yt=nTq~3G@@oZ|#|v=~34R!73Wb2Wb0b0sPM93qI(1MvMI*t>YR;S0 z6tYd;Y4;UtJ%5;;fBDkuwbo@FDi68Vc~2+Fd8&1;?5Xl|D>pHb60q`eZ-jOID%W}= ztzT1#!#ygin=5znJd(SZ&*lpQeoJu%lh@?@Kk-VO z|Ji$^(z!tSbKvOb;!u7PUhs><3z>`Pj*SuA&V@;01WL$ZPh#XIA0v2}oHA1sBR7RH za${ozcTfQ_@`?OqU*(SXb5WwOEujZBsThGW36K^{2L0JKh`sIBnAEmB-8i%b*$mfu zv+H&7eSC;#I09CYGphVABwiK(OI>yqC0Z`T_HzV8tmjk-atf&_f^7BX+6d$v673x2 zO$f|K;s%4{f)QeW{^CrChY?v}{1}N3S-@m(M7ba}7cmR9kPY658bLMy zS;G-r>y2m-8rPE8F2GiAr0wPb5^v+sCl@zgQ82b%@O?FFY8Y29_>HQqR^u@Ety>l$ z$lu~dQri$*yVqkRU0cuYBaSCxYQKW_qTjfs1k!Snnu$ZD4I26dFAuttWafnN(oFAo zX{O(JX~u% zCbYK14C(z%=pOy%0 zpGS_rJ*>|{mrAtlXQ9)47rMFGGKvdNN_3FGHvKG_>BF zRu$S0q`A*4r};MYOn^hf`B$)IuHf6yX+93EoDq;>4IhV2^L1#Y$Ixa!->SA>hfec( zXyG+J%zqv_&G(@NYlG1JepFfChZf3V{`=5rJ`nwBKwg;tKy*6!LUh>c3(@K16VYMO zC!*8IH==DF`ENw0laEA$WAc&cbnYwBSuvsZzxYb@4=Ix^(OB=dLwqIr#I<;QC0f0$ z=<_M)%>6@us*HZV5}kRV_20=VSIG5Zj!Mb2?=|Xq`_&QwKEUFg*1VLgtQq<{r}yLB zb9gxu`yQv2+YxH2;@te(9yGXY$RfL!S|=3-$qhmBV^lga4w8=~NUpS3emCb|bHtcT z*2g=C8WxE=aI@Vav0;^1DQRbe3AB14StbTx6-B&GOtM<}ZlRb|qf%NaHY^pdpcX>q zYR@*jnzU^gYovw^X3%E7OhWtSPWBo$^Eb3ts9agV@}cqsuxTrAGl~Q1V+1V!Cr&zS zGg&XICL6WJxmh1szq0CK(pmGwZyl*^eCIEKP7z~ZR&RKe!oghXU)Cw4dv?BxwvH(o0QkEfa})Xl$mRM z!72KPtDyCLK-jkiY_$1;8gIit6*yE6_!n@k#hVlnWefY z)tW@tKmVzeJlocR2zL<61x7Wtd^XX^pqUG%5da{Da3h(rbZ? z)p_WXzMa&q9A)c0{~JNA-lODiBKl^B-}}ipq~dJs ze%67$Lh@08E(cN~GXD#y-wU$S`*x5OUIQ*6zR$rvf^P?98v3(HohHaGAeDk#Lh2lj zVY}-Hz{cJ4lMCVs_V?SMd=eF!gB1EPrJv(SX>RaaE?(g9nlB(VF{ZVz&rwe`H7mI1 zv~6T~&8mJ;lD&}ZzXa)9lPdpA4X<#tD8trk-T;yuOk)nkNYztApifpK_QD)yCrdPU z1Q`*3+X2U&iX3;2ltB13-W@@`Xk1B!r5rHlj$n}ZFp1Pq4u2=XWk(KN-&|t4tv+|)Eb^&P?WCf6g9Ps9#koxJtFhRDFx|G9T=go8?`Ds!Q3bM&-ciniF)Yk;LW(^=~2wo!j zf(5MwRQ^4W@B_*J5D22qazq`t1}r%MZ2)G8dNJuv3tJ1QPITTua*G40ShHXsCViiU ztphYfps$epxIpn%n$v@<^!L!UNDv3CIX$QrWCp2IIhxh^kHsVjC&HpLgXlb9MghrX zlvvDR-cI6DE-vP1QK{4ifm}(7aDbP3h{SbVT&u(vNZicDjY>RC;vHPvuEa4C_i*tp zC4NETOI&<`1H+iU)3HUe9Gw}nI1%hgEWhP9P5Fa@P}KB)PZia?$!btgBR*BH)#V^v zmO)^Dh@&vqla#QeE!#<{L3c;vW+bzxk#X`K&-s1 zA$5_3s8E$^x{2fs0ib8( zMxb>h8DJWofAsBuy_(cj9Cdr+9*O}aABz+7nfU43UZ|R2Pg6j2Z4xg<=TUAinh;CS zUus?UZZL&(MQhOyIO0uuha+ATP=+7xXRfxyd%zzc;@wC4H*-L|2mE2`@+lkGcEX`9 zf82HX9+C$I+BOwXrSAJC$*(w&iq#4B@1$Q5Y?JqpBm3wsc|AnAw@sSL2EB5%&AZEE zSD{(>-yb9B|C?b|)KBdrW@t(w#6IrZ$x*LTRXwg7em2E?JnBvgJw$;cD)bQWVY0{BxD_$o&sx-LE8QCKrRr z(eLMe>e-~B@6gDzYA93OP}VGpz2>;K@5T9kaxuhJ=6%&Sg9#^Ew0}xXKUQu3eB#=g zAFILE$N9ks`u&7odAVx%4jC_S_pdoxl#%)=kiU}plj{7>_?~3UPX>XKd*V(u!lqlP zL^RsX`D|@=F8OVoD?;7taAwb17ECD$?K-GkGVFQVKZrjB|C+g4M?qp<@?}+Ii5^*p!3w>*9DmKz@ z4m8I?-L=nqx1?>n&(4r7UJ|C3%Yl ztpjAIBJU!3r$9UTV20HbkC6I=g{%Q&^~85cKI1?efLTRxob)d(Y%QQB>5hLU`H};v z*dW3FmGoaMY#pHC0%b0v=N$gdb(4UN5o|2!(SlvecR4ch3Z{~pEXX>$)pMzDjn*O{ z3k2Q8mpH0qv{sS2fTOPd?T)b4SezXvq@JvN4Ddq})TfHmInF#sSy~S>j9@yJkX=9;dii7+w`?^QIarL#HA;K>~@hDUnt$e{2k~UN!!j+P* zGKDJ*;YwBDjkOVl9b1_dUGA;Z_#Ls;TQ}I|&9Zqm$6r*Qgdd;NZT$R0Weu=xtG8&N zO1}##-pVoi2F$|O30I!Jg<lIGW$P4k7!9k$GTmGQE_;WR+3Nr*5{V1E9g)s0w{5o9&dy#|g2Lgv1NI>|+jI&&Ic zBHvPI7^R1DSPD(xVjPFJQ0+XC5c{og-k)9GqW?40%$buoDV3Vc#XRnq%~A4fe1l>I zb3nN!?v4q4cT>LYK^+TrL=A@FRUfDSm`~jS-L9f3YdUHfK#|2_PBp-64H?PLHXzWB_ z0m_)fy3z413O;xPq$^&IA?q#5Li!s*TCUTnG%||AxlXYv@;(MOABrAM3f)41Ju0LD zeQI1Nc#J|HPrYA-o&f$R1wO+u_}sWaKPX3yab9AsCsDpKhRK7X3r?#IkU_4B_1zb8 zcz>~(*5t2zkCwj1VO^EKbMZHhMdDC>d{giY`1!N^$TFv7Gc@985!7;M2&n-amP50- zn52X_bTb!k;;`MF8CT~Y=f?L1`-OnI`)&%{#SwibF3?YRO9sbz>aO0&<~S6+B?gN_ zfP%~zb#Q=Yd}qb}`l4KyWj*aQ?-R6kKZl(FKFh^7IP7%qI2XTELesr}=HewKG~N4G zF8-o~rhE389)b>bx;KK079}*@yON8`IlPky$>}|#MGLh8C_@XjMHvEkn^3k|zdbS> z)LxHOrvVItKWcQxp%+UWaC`Ma_!+M?*{<;1kNr?ZFlPL% zPy9oA3KGLIQvV15i?uSi6IIwhJIx+OKdMyTA((Qv7?a8D;OyNH6T58$oO?Zp{W8RE zWC*_;6FV`FH(Zn_b`aBf%=jCH-wBuW{N77?LGnG2jZI(X&hSCq-tRJ>@0R)a%PsT$ z&z95mCKUV5UO)6jvEKdi4_yxl%{5+={vUy~pW-lE_34FSy5Sj;PjjSsVL{q1fd7ir z|KflLRuNsrsFlF$eG|2>2M?Oj41a(J-rdd^T!^O8uZqa1i3Q$<{nNz)Z%)Vw)0-3N zgcHHWrYEV|^vea~xWHeI3*o0JUHW@Y;g57*uf^8#zd2yv6<5=H#nlupn`ZN0X)yPN zmA2~Kg0e}LUrq7aX8MA~%jd0F!54)0mg|nRKIQ18ZfhO|E7NWTH+B1+Mtb zG+F$L*Kf1#HS~l0DlxVE35sVgaIn#St@;~&SFojLUBJ7%y>Oi0@=KSVKYx)IuJ9Wb zAql?)tZwo41@q>g!-B+meWYUHPA_`M47!$_Qz(-9AQ!1yIq}MS_Xg(7yNCRhWc@Op z1K6Zn&b{J-P3t$z*Sd0gY_oc`FL&o%x?P{fN(r9&O>(6d=&#<)4rX4OvTe=A4XgD9 zIWL=SP-m65Wv#x1qNi6}R_5Az)lkVBsHJ8O?jqs6Cl)qc^YahA39&;b9UT5HEb~^1}ZueGkoqr=CuPPa%=z_=ILS$0thH9?#Hm>N~ zcKdqm?cNrl`|`US2KiNwdgg$^dREl743qP=7R)=DSahlPF%$deomT`80lho$dr zm7=fN|M=dr7vJrAosf}TS`bj%BlU4Jy#prTU1A9xqd{?Tu^<`|C&Zkx8+uiwDmp_u zYwy3VQ0yobjU{FFJ?EE-6gR|tV9IQN{vqKOY`bQicWJBm@E7{?3I~#R=^RO3#WuRl zf#j{R)SN(Kv;fd+%}DWJDXB9!EPdC-^u47}=GK?RGM5p@H3V{k-VoF-}$t zAC41N41W|S68a@Of^%Y6$LGG1hPHdj`#BPV@@!Px`PFdJuks}wiB^}r(a%4$Np7Dg zP&G;vxCflx!T|-U7Fr5iNq|&&*9|e2w0OUSFwkQ?q3)Zw+fG5jqTFy|jm=NPSwTG5oZcwEyC& zOJkE%ico}NytkM+;}kll27#_a@Nz zZ#-z<+u)XbT=(~Db$Q){o(APFXLa4v_mZC8Pv4iwd;sigaD(0kHz+i?C=$zCJ_nK* z+<)Mq{4dg2Z>yV9Zt1B+yo`-FmYXgtPuG0GeY~Lz-@$17sOT6l;#z7J4O+ zO@c~MonF&T!8=I4oum4C+IkYCD&7h7f-)_%nEjvITb6#W>zJPOmKE1~EA{phXEJaM zR>wWR5fW#+;>0~9%03+@l3S%73U5sbfz;`oYNQpKX`%KeE>a%kwbbQH?4ruc@o=8Y zwSK%RMd*pRld44A`{=>@I1K%oG)NNnIZ}@Z0wE_&5Fx)!>YE(4gHtlxwV zRz)XgRnc!K@GFjNML|ch^#xrl8`Y~<)}HXzfRa~VZ4ptrsfO1{#67S^qb86LCQ3=l zPe1>V?Lke08m{CvY_aV@&2aVLR8o@!kvW(lrmi4$rXVp>YX=It1IXnZ^*u3_&Q<07 z8a8dkFl<`S(|mZMeru`KJ^MGa@sYQj4Y$d6apOBV8jr>|kArbfqn4%e?R#$aXL34S zQ5-oM{OcWalPF-{G`HEyJ{RAvp~&wn{-oG%8O{Ieq1Zn(0FR1ePArYdg4wq(6{?Zz z;R&ZseI~L0@PyS!F#m_M*5t#0L2Jp|;8XJP;HO2PigR=W7(!K!YIm$DxO3?`<)A+@?|_3AZ@E#c-Ps6LKM<7N;q`Q(fdg6gUgTlk$i? zpH6jbTXWT#EgP8ItY-0G{bt^XnL5xSI~v}}sp6BIQoT+u)5+AmoV@VMoGQE5Y@EMB z-^rUd_nd{iVL|!f!HPd{tDnzUz3jZD=Po{X(aME$7c5*rk*f3Ou3WhMyk+qnkQyMQc(PYzOK?%`E~a=j?&1`$))tw@*A-OB;%Q#J1yF5+gK*WTtMgYZUf?z9 z3WA&iWxQr3v?IMm7w619W8vJDE9b8A1}Hh-T@TdtdFL!#xnSWLi{p2OZ^<| zE^YKsGp1*LV zKAOm#adV4}?j+$bd9_mM^JxZ#c~wd{O0bt$1y`+Hcn11L*N}1H%JU^zHz>Jy>C%N~ z!n9XkEl4e!d(IL{xLVI$b=E=w^b}ilBK&?h{Bq=$4Y%>cv_{DfB9|#$c) z`uT_I-QBN^wV$?kZ;Q2Msk@oGUk06qtsAb%sR%#)MzzCIrn0ujH{>puIoh9}Ez68X zsXv3R|0YL9GxQ&D@qG?VUw^BYXX(q&XrbT@QCfP=oWecXcoFktn{X?bbCm0ayla!i z#S*Tt9FLBDor1giT*OF@8{)1#D}4F=Yz-L2mgBz>$o+={w}oQlpT;=yceB^b;=n0nV`?Z zIy|e>0diGA!LvF%s`DV#3=Mies>72y$`}C!^rQ|C>L@v;e{Af7Iy|Q%jK&A~=X7{X zN1!%{+wW5?dQ3;i2KmQycuJ=lh!-qnhk|>ah=+9kg<3K}uZMJaMn~|npy(ML9?=PG zFI7SQ5gne;5x5ELk|%U{Ku2$_9LoEopnB%NctB?=Se0B&6`6j!!UH-du0;>%sGsRR z59mbq57mBj!YqBW9%#LQtcKpclHB3+!3w=t?X`TR#=NhjJ2Lo6TNIze(Eb0u(*Lo( zQYaUwz*kZ_=PN0Z_)4~5>?`TIz*kZ-?<*Cga=wyag}zc#XZFI<9;7eTdf7`ti78)Awo^8v>#dpJn}x3A0<>2gJ$ zh>Mi<`}|PJ_?8GSr}XVK%R|obzBIq8VW6P0bzWJ&5BZdgYdO8(MvJ~**>Fzow&vb* z+u)MM9pvgLwXOulV!zZx`aTn>AL*DPW zN&Rmb4|=ah|35gC_Z@Rw8WX&f2K4Kq|4HyJ>HoSbw%FIZ`PquMQ6$*UDc(pD3c!o$ zTs#U|0lvU`~-i_1I|J{E67@TK){hLqo zl$OpeHH=|nVId}?fy^1DGfStJF0O?^m0oFUMpqH>oy?3@pPbg}#kHq5x3kkGod;4p zVBbxq%|E?4SI{5bTj97ZMV%=hn{*;lgp)( z34*(9iP}Zp_5MD;c`wE47WujB`o&(*v`5>DUYmHXf5uVIk%%`3pIJMjH6@q`6iu~A zr1PCthciW;qNpWT5iss)3BZcpG%1B^6?v|e!8Oai@~IL&KhNhN&jAXY-Ykqv9+iat z{YZhWFA`rw!*rWx*=z;HQP}c6ksW~?=k*QVYynw|u<6^f>0NQYmZCfR>qoKZx<0gq zk^w8qj{8x$mE#yZjbV@uy~&9zW^(eL4MkGqz4aDf6(qu%1AoJF^_GsZ4CNioIk6w% z#zMKeEm5k-=UG%LPoYJ`RDW^3)qP1(BQ6p-abuybp1~xksIO&El$OHnSRxv1?eUOx zLf2R<;>iGLYU5TXCWQ=Att2C@be%CdVWZj|){@GL}<0UWc)0 ze;uPbzZY_?AM#R~8Z8sY|4$ zfEf-}EnT(OD!>|dDI(+nnk;s$b*f{a(>+4h8P!2f zz6RTINn^knR} zr&%cUOc!@C<8(?~2ujM=HO6q=T3>{AN28GsFX*4H3MvK!G z1IjUfxA>*%;XsEQsl1jLgpvf20?1(0NHJtcTnDNwFFUP8nk3c}!-|0LS^XLw4{FLJ z-oc2R0y z!IokMi<<=8dh^nCd0=r_l^m2SX-$bMhl!0REEbqZ2sT#zQmaFArb3Xsx7wP6TN4ud zu)~}Q8D6N{okDim2aSR4BEs?~aGjft6Sa$+qETql}ycUTrDlxRU| zwWemcAt_NvWDVD?NS`pjDGqKdu8n=QK`4_#it~}40)+A9`VNDk&Mj+oqhXlS>UrHd z+>*~aWb(R4NR4V_jT~6sot_i&WK;_RW(AM zN>eeQVq`@vs=r_+k(W7RwRLM6$`PG`kq|jj&8dWmL_S0Vc`o^g5n&{SLyU@-#BNER zHZ~L@f~d<`H}UN)rwZ_tCGydarxZtDL@PWcRg_8uqW2UhC*6bq9J^X47r52ASeC`M zDbcdoJh}S|T?u{Xc$Ya2m-p6hy_}>(7gah*=;a#~#!;#Zc^?nag85#aIf3hV-ZSdA ze~uiML6+cAo*sFYXr$!W;`)`$eRC?cXpoe;Zt(KR;s}u{n$sk0$b1lL$08heqrwqY z!j^C=$kQ1{<}^pjj_QKBeV90cE<~9dGBDN7SCg8FKISSZNi;!-Qg@S1$*z>3wZPWP zOq5_UwhMvf@%XYZB0R;)RJu<+w7HVR;`wY`F<(MY;;%J@onjta)Fc)*$C>)XjcBlz zCmwgjQOrhqVU>|Xm{HwS+%F)_$tZ2<%_nCs2RI`$Fd1kV)r2ywQErMVHCND*)5}Ag znPTP&xoN7^O>&)vldp)lh}gqZ{_I456v?HX52*-KQvIFUS1y^H#yHwpKcf+JZ>f)<1sTvGbTv8MKeeGS&d2Ym_f61_s4+KDd9qoF! z(90iUc_pW@GESSt#s~K;X|;8XnniaNN=bnzCyLnB-J7K7v0M`seWj_gSg%#(Bmy!@ z0IL%MbJIft%SFacR8 zOJt$-w|0#o7UiNaYGMY8Cv(=&DvBl+^3qxOs4w4o2hnAEHOm<7L`~(oUr77%gop(z zNjO~vy2~!9#r^5!K^Im;T!Zdd&F)A{(5;w!ZV4gQ{ZbT(Qm}Z&Ed+^=TI84(Xltk7 z3rt{?FgZ8XD6H?b)>NblOPvyOYm7PE$`hLQ_C6C5Cxo!7sE;*GVy!U)YLbo?YCman z#(mn^avae_@6_iw;vDFBL^n81603_iprpZ)Qx)QGK4O)hkr(;lEp99^56?$YM2CUJ zn#D=upd!TC*;HURq#5L~xE`pActOR?EYf7HZd$5YtZX<456g8>@>4KJAmkHUEXwA` z>4+lK&?RnA(N3aFodR*ZaBYlE^k<3MRb9?Lj&a_nop##TTkP&Ji%$k)E7~@8N>3^n z@U7)DrR&D^9iZb~$Zmpj(b}Z$Cb|jsq~7Xua__-ArC6PwtR_yeLPm68YK|TVPQDMP z=D@aVu4AV;oj5J;$4OI8FDA8Bl6JMF&@;%-gT+PGT?#XuB5W@P;w4)RTD1OBs0?N& zQ;XA)pq%?25Aiwq>BijN_}Tc`yuzFCaW&&u&`(LByD$gOyDw+BNz9qa%G09aGIklX zD7=vfSgWCx5cUd7;&<6+ILjO%(ndnUyGd^D5H{fJ}}QsWwaa1%|Cut=B6h7g3osdtvTg=C98+>9!3F)owyV%trTiNn;ADEQF2pPEOnG9(SAo>enqk{z?~Dr z#04!@FK&z!1rZXD%VMWq7fexG(+P8v(dKwwk#lB>*M;Ks|2WFipAzgX`SmhfP`Ze( zF|!+sfHAY1ii2Q%_QAOx5@aa$LIh=03Mgv$&`%Sf=-=&kyh-jg&*CKPRKOT8lx_WDXe~)P@_}md)c6Bx_g$y)cK)VQWuu^VLCHA%tZW06YYP=N5jmruq3)N^rK6nheES4 zoJV$bcW9zjbz#JHJ+Dw8)1EtY?$oK9_hkhs6WtLG)c<%}%+St3YT6N+4PlMhxi91s zzTCVo9B2Q1m+o@OPM2!u22*)BG_|%l{{tYmF08dk-a}qpn6ARd^!;UYQB+!}PWMNp z)MmP_*9v}_LoYS7lnV8RC2u6pF#1z;n#n0RgOk2!V=FxEL=~F%QS9p+ztKG+yQ$@& zNpCtQe?BKi=btBZuBQLBpj;dBjBFYtc^2Qc&~~C0g8QgNFYUFp2fyRW)03dQ-xCJD zoK#$!R2&#;jp&dFvE)Rxnm1B~9w5?3i)_v5pKwL393`9rR`I=Hs7?gMykLq>wn=YB zEHk&L9i-qa#}(7uLn1SNmAV(1`}Q8Oxf^Ti!%D8A?l2Xt3d=0;GJ8upx)8ylBc`G= zG8>PD#<1baW*H=;Lc&;A8gA$tVuVe|QvxX>!PsEf;Y+RJer zVcV>5+yy#=e`V(mF=!vHm@C_B!}_Q`96l=?wkoVYAK3F&zK5dkXsZ&o4Vh&xCF&(z z@KfruHVig|B|E}kLQhy?E|z{ZHQnYKMD`Ubhi*^Iis^QH0HHEV>gp-OxaopAb#yW^ zTQfEH+R=dKRcG2d!gBMYJ(-%Y(tOxI77loCShkOXJLf`(5&Bi3X^Gk?)Je@#BlAlXO<6~nz9<|OHHIgR4Vz6xJGEca z5!Ri??Q?6XRy0}=_0ULWLGRXT=(L)nuH`=6pWG3*+C-~Q_HDHz*Q#tyb!2``nRN7{ zuzFjVo)W#?T9byuk}_$f)+fX2_J~fV&5NKq8dPUN>yjf}nA1cvQ{Mwg;~sD1rqjbR zQ!ZWhg}$vH(+xNHe%y--MYDFn$`G0&qM59!_)_00GDB&@{1eDDL}o}2y40-iuB{D6 zBX48CZCY5pOcyCQ;+une#e7G1)3^_!mq+F)ZcbN67JDkHMI%$?;!bue`@UYcB+YSR zOZO{AcsUP>j^(hL!<@&Jx0jQDyI^+opEW0z;&M0mmq5aMnSY#;zF=j=Xx%?YMw%Y#Nu^5`_PO$!TZ0F7ck^XhGo{p{IIo37~i*@!w zuDqK#`F9BRZk;})(?dFaNvCh=^aGu2pB_s3^yS#%ZLGzpNhyuSH8H!|!qeupX`q_u zOJT}P4ch$YL+~w)_LJSxNrrh4jR&Thp<{7V>5}&iB`Ra7#dR2G--VRlR1~EVI+AtuIxoBVGKhOdymKLrMBBuLT z(G98SvggUfsfx_f<3(9z(Uut7I}5Nq-PVP6M<&Y-KM&GVEQEmxWb-~jzKZP8;OF-G zK?Y7;j<+OfTYW;lO=3cLA;;AmmT#r+=gK?E$^VXEKhfz0onF!D-*rltajMa2fKC&2 zvK-ttFP2Iv9`ngRTO~JG10ZuDLx@4uMt7|wMw7ydh)=7Qlaz~D!H`FCQRW@t;K=M0 zQ%Z3@qFI=*4g8zW?9Fsi&_w&|!WJ(4bs^mJO;tzNP@v|jo^V*?cTzlOpDx0JR9y*R zVl324?{F8_gw->)17A|N(YZzwJBJQMvvjvxC%7t8V_VvRm9$N*4WlWNF>4<-9gPl0 zmpO;YL|2D3DB0*d@v*X_7H@mIbYD7}ZTnTy7LJ%4mYfM&Y>(;iMd3hdFO8PsXf+|a zQEfL+v;C;Gob>dhS8VI6!t}?Xg|%+!=q8IvI=TnKG|_tm-P{OGP*v-0)#$~2uhzVSrv||2ut69q&8m# z)(_a?rO`dnkYQ=ZARACfX!lYq4l;(Ue9lGZV1s<{T?v{bS3GH(5;OU6=`eT|bCbMwul! zJTUCm`@u^4%lFa5w!^er)xIxUZBet0`{p5QrV23m8cHrQ5ASWWX!lFG9xD2}MsZ{w z*}KnTrFn-njjfTSZJ0S#U6mb_%c-8$LB85>$OV>?Y38#UJpEA+B9)nwk>V-Q0cL7q zrElKf8_geDG(WQUHAn`7&5sk^S zuOOL!bM4$(*v<=Tr(f}5(9>)XU1n8yfNrZayE<~LD~rwn^{TdLv-+>@|JiyY1zdVF zu61Poeb0Z<{hM)kV9bB+flDQkc@s(hp6Dk@pDk&h?_KvnTleqw{1*~%x2yZNs+-|t zC7=gbqpe-6|7%inOoq<W}X^mPh@=KHQSE(Y#k76@v%un;$1l{3CtnDAWX2jt_|9W}x-u zw{+Lbu2C_LvMK4D6&oJ2lM$14B6*TRFg+0G8Y?0hytGN&Qpp5+UVGqUw>wdEQluxI zO<#&)yg|y*&Zh6>%KIoMJ26}oYsx=+{;**iS54ZnWaGw3vz87UX6s%M*L~vo_TQ*T z-!omrVe3y_%$2u`lm8~cZrADNxSqNE_wN(FOfjC8@}_avdcyTwd3SR1KPcD(I(!o1(S9nxqNu1(Qb6h$aF8s>)Ux-=c{q~v8#SX2B8oE41L zK1!lm4uyW0X$r%Ja6}~E17~78o({^Uit5c}8LM*ZI&Hu}SY(m#6z;hGh-H@8e_!X! zF`e;5^tUP;@om-r24VzMZyJ3XXap&0{_3vBa6Z)519mz$;OS0~Nt^e83%3lmQG&I8 z*lGqdmo#fF3P4BL!Drs^N+HHJbamgZj8u$?E~fVtVa1#V=Z~nIbHDLHbYcp;QraR96$3 zuiIIZ-0OahX83iJ5h zeF`m@iUJzV7PsgYQZ+@CR;f$&v9XZyzAhuG_lx(2@&Lk}Jq*D%->QMHEv||^q%mP_HcT;&STrdI=an_hFKLO#JUsc5Lf z*sbBbjLXWfY?Ec|Tla#&>m#;VaZvIqa$pJuBOM`B7k=q>;=g8yC}v7}=$nC3a2nGD zqkF{YP6~7$4QowZkINxI+-AOheVb*@W19F8|HXK{#_$V;)p>c0jUlhF^u6*erj^ zuID0kC{Kyyctr;JhlC2FWTYMMLajE2Bi=<}8Iuv_OWsjRUkg}_2xl@S%*a}7q}^_0 zXR~}UjWf)2)s7JLQgKh)+b_kAU7tc=!HG| zG}ha~l4HbqDfVvcKna62%u%ExG9TOfSeR*H-cOv;ibbn<8Y_?&llrV6)Bz3&0!SY; zW0dw0KKleh?u!wF5ttjp6svDAdvNr#0(cNT9}a%108qYMj9+QFb6h6*ZWBi-U$kxe z3&U_OM!i`>K#cIi+Pg71*GeOk7w8ir?twR>2_{& zVP$xXtVzQY*^GD4ryuOoJ&O+u+dakL<>9V9p~OC@w5+QlWi_(L5^?nb^3{ z2;)uW6k%;#5}F>Y2@0?j0C)@8TI&y@A4Ulcf&~^EPN{aCq8oL_6|o6BnZllsz;4dw zFX#$WPs6JnVX0Xt{pg27X|8cbICLpB&rr#zOJ^HEK8MXEWP?|Y#-|^iisxqsGv1_& zmk`TU@#MR6V zPvr&|J*hj=z~Ww$C0q1nbFviuEzpEUEa%am!Wko}Kkb1bFgsX((VN05`|lW+fLYXC zs+N%|!h^k82ejm<8P8gg`Bn~XTQi;6B0@xF7uzL30Tdhc2fx%k6@u>>{l^<~p0+Tt zf>AUIo_z79rY0&vyR1LQ3h8wo;6vaGUr+q zAad6o6}h0#K!x_d>;ZRMus>9Pa0w?HrIzh&0PDn6-`Dq8H)6P#OlBy0X zHZr&u+lg!4kv7VmZLh7*xQZ;*_ya&&&?TjvEH3Y8Mc!l*%jOc9&<220&HS%8s5;uZRmm5L=RGC#hak#j;M=$~#g(Ko>3Q_c#V z01p|r67$Gzhlf%z9={C-Vmhb=h4$3d7)ve-Z62YUM_AdgLV(anZ!H1OPiaQ+U)Vf~ z9pP4Es&oChAz*T?{%kEG>UI&eoLw97)XUDz%)g`NY2ySv()6;#{QX*_3Cb#^agsrq zHAOA$njm#r{fVp8;>JZ7tpt0Y0E(m@>}sXiw@7iqmzWI12k0c3rH5@{R`~2l7{}B; zM2t;lq-BmZR$Jxv*s307v^f@Lu1I)U$&k?A7HyhprP$uc|l8`3g{GawQn& zUkC`}h%E1~Rd-DTVW@%T*i}?rPavAu6NTPgu8>)q`Sn%Z0+2pJdaU`)RZOR6g4`0z zyaAdY%widhs7^;Xo)C}_pQY$fHTQ+)-trz?ak&Ix^a0z@C$8jLvAJ64=XZ8d46MJW z>1NPmSLjJLvPr`{ay{7LwKBv_v(s8qsb*Rap1xrLSoU7J+K-;LJ{@B%Wc9&0{&aAe z9pB+$;sP>4EqK)MDLX4{R1an~+YvnV^00a=$rWtqKx=h{jkCha#Q^A`i&a#a^3FkECgLKg4~Sos#jSRc&jA2Q-V*(g~ZO@|{}bt3@1Zk2n@RX&o!g z?g{sI;h$r(tgVU;^vBrD&_d2Cn2P88HCQ^xJRAtUOZu=_1c9^6Ez?hj<1}#$qp8i| z48U!jOek>hX3P&yX$#w|lu?J@PS8!#M_q{CB(6?+EF8gzjOL+6WHVYi!&A*k?Ko=Z z6VbDYZg{k_Cmh@vF1cIthphDCS=>vv=Tp}Kx8j|)fixUmnT8Q;HG;C6mk6 z9a=53u{*8xo5%LzsIviL3PWWUGmk&>H;y){_VuBp^-SDgA!MD5mJ+s0*jdTnt|dU+ zP80$mK}TA-Os@*ZcOpVRRj0HJJOOd&2!jLGp9;nFk$B8;?_|bXR7gTfiS^nhDpKP3>XnDYUY)E3BM^HfuZ{;%cYO zM!CjIRqtWq<)$%MU_E;?W}jB2%zJ1Z3TSp5o0raTK4wX19~2#So(mDWoSoX|<_O*F zcN%E!rc)yjQ2Cndl|bS`RK3LE;@a9q>#S73$-3#lmRJEwvv0XV`z2VrMi9+4oimv! zzlAy=<-uJFD-jEW;O*Ka7MVx4Y3IbPuV~tF7^k3(mIx6pwdyTiQ=d*uU<m7?G@`{ji4$kc?^zKoXNChn>(rIz71U-X+M2Zcfn2*&z~iJ2P`)JW zan>g0wGqmDD?IS*7p z>HJQ*dNNXmQMf`|0v~eSDnCpm!{19{37A!fnOWSb-K81aPIv23)K?R;b9C7l^J%t= zo@_pKJ#!!PG}oojOU_&Vf3r^c+~a{(LcC(~n$DjlF7OqU(wt$QQktt}`B+wE7@n&vpM>wpnu%Vp41VhL}VV z%aw@VGlX8t%tL6aXd@fG3y^!^IwAK#a$@8j-rZ@nO^x{=d)yk#Pdsh{1U1{ERp!N% zr7%+vjKE87?ddW-EIkO-(z3 znlbMVC6OAQcd(JS$Q6Naperv-Hy4 z43b|^G#-tg4LVR+_|BOcyM6UR!Ik!7pvzYx|Sb*eNN{ zij@#F|8gaUM1~BbreN~bc1(xebYHuc!v|65e=WxuHn(2Y-s#lDK0*;v+U3!wQC*E1 zbw{bO+Wf#0_Ak4nqi+t;kb0cOH$Syw+x_S5!#bWi#h2XV&X zFxH6lfm6SN3>D@c+u(yNem9$E84;Q2fm%i%%1!GE zN39X7F@KU)0&#A~LrW4q^QCHh zli}2A75bA>=o=WISynd5y<=~u&25#oUtN&r2!JIw(FbbfCmv>gSz>-+@U}M6ff~(y zx7s>B1s&vw)R^DzM(iQS%Zyz49+xlxHHL1Cr}E~Hdw9Nq%I>n2y_i&nHcV?84?>Sn z*#ukJFH{-i{7))_ZVyAZK7$OU!D3LMw?frooGKq@HKWX{8`%=w0R{} z!^3{wG*12;otEgt{(x*S=ZZKEFv_|oJO))8@>oCy7PU_dQ|CvIgIo1PUK!rbGaT2* z;cUZgSfzgRKM^uCg#MD~H#WJWjt=6}v^U9n#073Q+i@J%hZ(l_MK>2#b#uO|DqA#U z724Ja-OyErl|Q9h6j70zo0=Kc=@Ewg5Vkr@&4Sj8t&PEu)(I!KNTg_pv{%675O;$a zQpRku%d0~*c@82xTUjP{n+%v8R<(!C#Gz+~RZHSK8pD7Yx{Z+x-R5Yckr+gOs;y%^ zGGd~rUD81`S6yV+G26GhNZ!F<)%q@%OXz29m|7Z^kJA$#3>{#0gA^CDtnrE3LUzqF zAOgI-l)|TT!|F?@>#FwI_-0I=!AV;?e8Q(G{nyzIA7YXXh|Lbm1fAi6mdp803aK;V z5T?6>rWCr=Ej9XQtwn!ySAR3(LPR;@Lbe%hvQ=@DEfyyihovgjk*m2vNxL+2Asxr^ z2hrWS2t&npwIyDZIhz~IM2(dtnst|Gr;%-KPQRU+lyu6WvP4DMb8qjcb9gRN0?Jv~ ze;-%vW@Szwj8+LC@6bYmUka~3Cmp-yLU3NF;uT3ubv$?ZhyxiTKE zzq1b{;lGc_99BewUyGfxEoIJaPSK{0rFshGlwhia_eKVdI;+Ki&!>V>z|51^1;gbd z7&edMS*_~q(r#^{nUVPfyJTwEtX+aNu(PaPJ={RhUL0n)zJh`d?6zB&s;%)=tHKiL zf{oBeb)q`>FNtP^!KL=52A=Z4N-hSMS+)!*!XagZJM8el(716~&6c4vU_qF*gO7-SZyq4>7cgYlmZde6Z!;%oZYL*e zK5p9Dfi(kD?UPX77<$A^f>FW}Q#a7JSQLZk8Eb5_e_|Sli6}Fd;bossz6-e8QC)^I znq`_;X4VXSmT7ELxqTatQp~WEr-}u&`lI0(<~`JU1<+-6F_GNUA`w$1DK9%>P?K-6 z^*i;-26#>L2o!`9!=V>2N$b%_!5uUKZLP*xKQ7v;7*0NdXRa#P-LKb1a;tFmV$=nqE zgdCQ$xOI(s_<${lMPcxOkDk}GyOMRgRf6&gGGnY!XLei3AX3kRe&V))3N4 z1D0@fci2i$jA_EQu<`LQeG@A|=Z5L!pmT;|5d32uXig48m93C)pN&V-+bnSh-16~O zA+cgYpoMX(#~ldAr`eKj@E{Z(Oc}*Y9l?~gwJpJ`v++?^UC0DiGL4sCX1?XIt3})V z#Q(B)Fu1xIMv>hfR;s0VrpM*x9RZL2m_M>R1lfJxo^A!BDnsU{@R?3#dq5oGEc!g| z+1(5)h>~LbDM*z$8V;sHG&7t;SKxu#z#iID1IDrr6zq7hjZr_D8jX!X`ngGrgl zF^CG8psIcrRBfuurBJd0!cg-OYJ=rJ-@{YKx?78zS`^42$JF^wf8UL9trvyC%{NMO zgy97t8V-(#GK!PS%DATQvE0tXtx8b?uQH_nT9#QdBbg#R#7@jPv zP3>ljmER@|kE&BYdUTSs$fcymiLp!ZREit&tt!!F_xVY-iE1B##pY?|c$kWE^GG1q z*?eL*`&vFl!#984hRfj)1E1I*kFU$!HDB@{6Be}G@zpR|+HMxv3JCPx;kVl!5HHp4 zl9*MtUS?QmM$)yC55EqxTkb$@TH?_L zX5Xx|-R&U{gud=|K{iG+{SS%ob({6-zZpdLEH&+tBalxfL+7^H$e>VBv+ zOIO;W$KDjpS9gS!(pU@zq$sLls!=jS&}eID=F=6 z`vW@E66H@W8C~Gg*7-$mI`5aQsVa2LJwSOZ%-jP$hi&Bw#Ho=8uSIr0`z9_K+f2oP zhNy@Qa(HDXpz!a#j%c5oy=f}tsG8XrS<7RV^=LJ~EuP-OQlDk-5fFBxh9F6JKdBwI z!BTYK6=B9{$5LXN+CegwMy&V50&isg)x(iPGH=;yyG;O%m@QaUMVXUOy`r6#vSZo_ znQ9*Wz%!H`aeN`hwnrWTu?uxV>hW_nnwHg*f|0>%*Q4|7SJ0>kdSbC^e#~x%^}*Z@ zDkqEGL=Np9y??V^Lkhm=gP|-HYb@9ls$}-Z7*QuR?_>8+Xm&y!6nlr1(*~Ky0X(iw z_a3l;AFVOGu!qo@x!Y==RZa8}`IH9Bnyba{2SipuKvoZi+ld8BEdVRuDz!y8wwkam zj|7^Bf)1`EqATra?_$|%hhp>~u85D8y6y<7SJ@*chTf^AvI2!q-X z9F>z|?%dO9wMCVNTKNpTce}^vIiH}5bUl%IVl<|U0LPmtFD=V+;j-BKgh1!MPF9(i zbs!``bW}pQY6DkJ?`wWVd97NSD{!;L?4x0$nBAt6wec*TN_w&ns2>ksf7Ax>8Pc=t z7Kq9>p?Tdil_|OhZurN;uF*E0^0V8U#FbcEjH7Fp;|NA}jJi8l6(0k2&fA{nGzYE!! zIn&OZIdkUBnX+%X!ftVeK%>IqKZjdFVNH>!IV?8BEEKxIZLZK3`UV4<$1Jj4fcc++ zz+SG8LQCgQaE0c`Nq`s%GB7iGiS2EUS(MvBn58KEhPaYRZSK2}S+r_G zp(#DDXF4-RCPmjkS4>x4@GMbdR_0geXV#=ZFi1Ohb9Wxh&qBKtQj61&SS+~bID?Wt zlIA0!!dC7$egG6gpiO$rWf(Xl7s6&5G7_pQG*%bh;rafB z@8xL&9?m8&P_;Sj+=^=p0p=pi@}R-ZgM}$vIItH2+3UGmh6J=WnQQ+{I>N|Jr;V#7 zd#*jd*!(bP(B`T^)Huv}keg&4r`yvIVPiG+x-k8I59Yn}ya!vA7*6GNk^tOefdX$~ z84P*6$c4qOR{2FA19OZ#l#p>#XwX4p>7(}*H=(6Cro zQX1pSxSd~Z_$7AG%#oI1rLwkz_Tt4zPN%A!%c$W}twkPj{t4u5jz6Q7U`%!<=0rg0 zLIQE#>IF}9Gt9eaJ|{+=_$UaP%MP_i(@@X!aEPc;~0z1#3J>VM_jg8w7TunwXA4p7y`z9&HiERT2H!Kh# z*Kkpb)&}z#>+%=79GnGBE#U-8qlJ{3Pz>(@qV?LINjP?s(NJ`d@e-ilJGc?K51T(uyKx8kc!kOfoHiO0>SCxd*o!X-eyl zUMunbqk0uRxD|h=@K-+0>gKRE@HzV6%g7=um%cIhGAHwE7QYtpYdOC*;LG@czK{5I zm|v&xr7dpjU$7Wst7UQ1(}jU$7;RDdU^AYB;C*;ZD#2MUC)UgCl?ig%re8K19Auv3 zxl=JR@k|SJhY8u7fMJ>?X`(r~SHv?mc;*19D&jpch{u?B5g!?go}B4&#zBV6EzuW{rWRf+G_JrufH?&KKk6i2vPaq$4Xykj=UOokjZeDOx87HeEr$hr@QN3~4` zqBDbbg-T+-z>%e59ECPGEtY`|KRH8*u{Z;xh`7Y&Yo}r2Dx0v(a(zjD2U43z@)*xeV5{blF%~CYwK%aLCOQ#jalwb1 z9W)AoTH&&P14+;lwnB_Q!#!PF-LWE&Am$>vkkoX*w*rMhMO>)kbfE*%;r%teP~$$N zB)~i@F=3i7SSMv5^)O8e)BT+2U)cM=q$g`6nmQw0M%TeO8w1gU`(*7R>BW z0z8%6kD-@@&^3A90+v=7apf5zn42}Pt;CAdX>J`@m;A`>2Qk24D9+qG@YRGEGC{VhHpXTEHR&l9{}$N%3sR8@%r>uT z9_I5{#j4ai#}?OxanWL-H;wP5X+L1?jV&ch$283TkjKY1bb+i9 zI1|^@71Tlxa!en>8x}7BUD+qayv&}5;zbAgC!MzX+$ju{I!-c@t_?b>N^`*CA+Q+5LJZz?3#fG&B9Vj~+0^wVyNMfGt!Uhz|11lTm z-$-clCZyA*20r-5s(q?2%roX*Y~pJ{h1~XXdWah<9q`aXyI=_Hy5x1U-_`=*0ud?? zgI9(W%kRco6gtm(=p-uPDX-|@&Vz^!T+ye#TwHW;-1TzjZM|I-x(le2A_vdKaiJ9l z{=}@rv#Bsz6RE#pEz408aC^2Kpwo-2AinO@_;xW(bsSuv$-r?%BwzJM@&lR*(3FFy zC=g0D+iwdYa1Ba^wU+|}Ln_pSs6wh-oc%-BAr2VMmU4~A!6k85B-;b1#)5U5)CsHFdGjT7@2@>9*uC-QOW3Q`A zh)_*yOcaE=Vp+UeRbj06|LK0U{24E5_r;ZGzdep~xj%I$;k0 zQ|;K3qD+1ukH|V);b1Jb=;^f6z-AhV3AxJ98WFZh!|>iB1U3M{;qE-z9?i-at5ik7^mN)uKm5s( zj`DH_8VtR|(;gk;PK4$Eu~wb1W(IJ;3DQ^VV0woS@7c-b@g@vc9Or>`lef+>EH~n) zd$Rk26kaJhIu6ncl+}v@o`rCkIHN|k3Bnpw-2(4$WunLTh+H5xJj9PWmtfY`9Q?S| zd6R)PZeTSdRZxZy4eTc_CDpyI%BU81MsbI)vaH;p(FHy3imwSugKD=SO@SPT78*am zjL`mcak>vI{fBQ}=x&tR2z<*#5ArLSxOLBiLV!LVf_cc@UbL^YQdE3<+|4QX{E zafq6dDtm~|j2XHvO&3;uP9ABu5p%bc&cQ2cG10NH!u6QsXif`V#IC`1x+ItogNRj4oVi)cv$iEpJnjlG%y9SVBYZKw#Bb)P49gqoXhm98TD zvxU_EuCAXgM05nAx#kIMpC=?)IcTt?`reCWU8Hhh^U?r31lyOwk$O#u32!uVhr7cN z7i3<1zP(PIFNuT9Z=Y|E%t$rP**+FMUSBT`_`V|~9H&EG;9~XRujVD=kn?IGCI<`8 zu<^xE>@{Gyjxot*(?%tSlQ1GB4u_Kv!Syc`OL@xXd9Ez6rY-$-$~*8gUVZTQ0{+Bo zVXlDB@fp61Q-q1dV*O;j9N=t^7bT-zDSCuK-%jB?SKvx%Co_G@V_+u?G2=nKs2=m1 z2(-pK?f<~vNc?F8mc!>bgfHVHVS>PU3jt~qKmd0aU`$j8JPQJIAjd`QgU7S?{VDzOdi!j5s@^-vF>I@UKf-#O_HPG$3L)gY+_JM&X02)*9DDY5~^mJk2 zr!YLFoW-II261VO^EdJ=>b#)!?Ahvl5A2yhDBi56WR1bul?KfuJmQn>fWeOmQ56va~~ zu-$UC4Lds|5KCb5=;8rtnzr>kqpb{v8Js;hIXM~n5;|J%3&i3?S`atu!_9KM-}Zp? zmDAlD#p3!}EthJE@zV@k5aDuphN6pcrctz1i%$7krvROTCjjdQT$N~*2&&_(0*Y*V zOb@eDmT9tcscbzOe7ORDACXCEo(%jIK1WJTyAIDS|G*1G#$73u@X4HA$c3akOPH0lp_|0s#U7GP35 zk;%7Q%1`vNfh!7%JI_Hhx8I9}j(te2%B_ zWeg`w`m)t4R$m6PFL}CyeF;f`yJI1Ebh5dA3+-jAy1&9LQC_O=P-OWEIPi?UNm6<@|Z_;UV*UtRdsgI|64^(?=J z^J_f5%$MmCjB{*^t7^hM1T;hO=6YS4*XvO-;EEg_*lA!NOP3oESe?m6Cwn)L&jQp! z6Kf#F_uzVTGujlG4Tgy2H6Ffm@h_JNb3e-ogkoO@Zmn!AG0}}YzZQr?ZStHer2~1V zZfWFlUPd#kCZnn38)s|y9DVQw{4k+)c-3MV)TMg^?@~%X{C2^6P|9We>4M|&!k*(! zeCdK8`2z*dLn(Xkrwjgu1;$w|O2d=z`S`Pc2!+2n!OxA-??=4%_e~^q>FFCIp1*Bl z|2RoKE4@tzK1&${?D3|%BUoXFOsIl);NfGw`quAr2Nn$7#D&enR5raR0zKa0hVw7h{ia^;$!vWaIByZ3QHJoYESYw zr9G)IsY+D+F>al>>97FpX*JZNJ#B{sYGiT@{3srNRL|W3Kei04Hc5P;e7`Tn?2zxB z^1VyGcT4PMj9Kx3w)~XVuN=>N(4r33PY$$})M$r{=SN@`(VWZtOgFQ(C!w z5SxlJmRjjoUq^qbpuVDB7UV}=wl`QkdJU9`gYhGW#nWoh0AT6udk%5@$szke{wF21 zmk-9;{WQkrgJIm#K$}yCy0oYM5Vs~q2bIo<`U2h*mMU(c#VGHCQP{0JtfuUw5X5IX z{#gHc>jwdH1?sKe%fG|y`iI)}<2fuLQ3ssXWwUjCo2>c@EyjG`k93rA!Rjx+Gc{Wo z>|j3;znnYuIC%kKexxxajIUNoOE#ZS(XI9fvcc*;ivR4kv!> z^c~vha&FdOFFenJ+x=~)PqyC7Uh9{>Bt4)j;yqw-`>E$T@PcD>|;FfaeK5>D~4kF>j_c90+TpgjBa=unn}k7mP1)CBmw z^Emu}!XMKwZLjJ2H-!1Qj(_U|=+D1;LXHL04=b#(0AP6$_v-R8?fOZUu!wQCd>U)d zBV%m&Fx-|;!|Zuvs6CGi(W5a8(+B7Hps-ffFls7pp(VrKw`9s@^oH&QEyH$NGG!Nr z9ns;qWq%XToIhzi>)UwJ4T~6N&%-5*ivvhe(zsyG_fdsNd@o)9tjoWKpS*I?r!Q&( zUoVG5P&n*;pM*X=9&`Ft-5{#WO7ibf)g zkB#s8j=FtAsg>YUw)kdx)sIv#$iIeef~C1@ylg)2@HdU`Bcv-n*W&v-=HW*yr0T0e z6i^~kEPQiR0N5X%U_E7(q&s=j;YXV^WjS99AEawMU%rm6%oCPyqxpIrlH6#%mRfDb zSJ^1<_oSAlc*kLft{T73k(;02l)J6e4kY_cx!VJY*na!zxuq-|pKIqodmKW<^g(n< zQ@)mXwGr#5_G>xg@ygMo))RMUSP4EisOK=EODIXQIc&W5Jgn(*jU4sLkL%(to%uuW@KiSf~C_TV4+d(9#HNrP^S#pfD|- zH(BDj&=Sw@Tb;J~dKJ^+@Ag38-^r~-rQp9D-)vW2Pu;Gi91-|f?HX^-L*wjuXso@S z8DqC=xZSQ2*E7_9!p<9Nrwop^LW@n-#8hat{C%tCo6&Mj{A6)=S}osYO-#EncofQm zER2Cu(!Aan@c9wwC+q2iTM*{Qk~cm*lhcUbjLdnC`Esm$&oL7|R=yj}bG?zQBsOBN zd*?ag%kmx8vjs`;@gV)F0@Rh()_!U`ve5>7d)+#)^{SzPigI9f21PPKABA= zke}Z%j@lyGjmD86rT+XIsVx5d6Os{+8KbmZy8~f0$i^S*vCk)a^aiNOm#cT{o~TZA^HLFtv_D3*G=N! zWA*3tbp9Rs!6RxiO8B=Yc=gG@nVY1x`;l^r?P`^;+l6!G^0C_W$JVKjs8cBHk1SJ# z?}-pl6g)dj(0Edq@Ut9$#D9hbf4?~Xzf;c2SnQy^0CI{ zjr5$iS)|`Wf;nj)r%OFYx0VK~(i3_6DbG5eR2j+n0ZJw6bA%7T!3+C9RVowXbEEY0 zk={Q4l%kWDntl=D_anW1_~`jk=wYvW9#IRC*nin$H(x6dEUKhfa*!6#CB<^I1*?Zk z$;%q-@kqUt_~yK%`|ojt`6*S-l&CidKW8d#L*IZiuaWOk59I;tKX29V7G3tJ)XI*XSb{;`Z=;X_UzuS z-(ycW?jF#+XJ&TqC;Hvjv-=bMdpI%?!Jwm4@4h|nLP;I7yY2gtyj-Gx@Glr+}|4rbnDZ)M-Nn(<>+k})&1FC&-CtB zx1;0E+q!1=?3>xOSNHB+AAPEKpB`NYG`%_F=EilN!C&9r{dzsqsA1PWy&pxqqs?DB zC%5jH+^}w=TO3*0{d;!n>*zTkGvk@wJ+dEnJl(C&Q#~CS8ImWXPmf3YWMn^^*)t;> zN!j|W-o5%cdiTrj)3YB^Ww&e4uxUm^N5-EYmFR2-DAK)m7MqDOpXk@KUpA86(YqJ2 z+{n|XTUK_)ogFiJ_v@YQc=Xxqo*9om)%_nmvsqQo{{6c3$>^(VC>Hr2<(BJ6s_96I zb`|OfZM*l+cGRs~5C60Jcdu6rUJr5gK=8iZ&_&(RMfKQ4gw&HR@|9OS-;K&ER!Wba zS=sfj@8^2G`*rX0RF9rFD#s5mABNqZ==&(Rty^aAx{o`aVYg?&1Lp0CmcW;l-2*HH zPuY+LqYF%flK&Oj_*3!UZU66}&kbqkhj_^(vzZp8@=IGbRO=2Y(YM=xe~D-}V9+vS zC?8&aKFvC|04+1l>CvZ8xBk7JE;Ab3fIjtnb@_Z{)05eKva+7aEVD+G#mJz<@}lMS z_#^=28|IrHJs(3?QdDGT^?(ncev}VZx-#$X?wl2R4(M5Cq`Fam`&H)WEt?+i+p~ZF zGHXOx^|ytT?R3k299;=f-}?!;H=Uod zgx56Vn&8t=%^oX04gS_3C}|S4>Djku-zWM%t7lj+!{gK=p`B>}lri`<_4P!1JIRw> zr+2>=Wi;nL1$DJAy7<455sTwiJVcy9n6ep$ka8J9`JVrMqp>({#Y487EtvtYW2cgJ z6DsiC`ji3|((H-kBG#o3p ztWrjE+3+fKa4Z}D>&WXx%j@~Q#Ptd}J+px2+oBIFCvR)6}>rE*CI!j$U9Hp(csit199@$THD^;uY zXFFdjic_n*!_q~()bvR{D8k+P$fRMZ&n!@uM$d3j%rVXS;d-SYQt0JWnW}nHO}!p{ zduM6Q{Eu3mZcMh~wb``_w0GZ3zgGY8(WtAE?=lftQc{_Stm2s27>cWj;A0aV>Bj{B zfxhqczuNb9ZC;mb{-5dlGH#duO#d79#Cn-oJ^ld;b#b}&8<|R#HJV?n)>sZ?1!m(q zARHC+5_t#0=mr)T9cyW>J~p$=w#8IgYpGeLtjA{5gJ|oA-GMS0o-D9TM&~t{`Ec}& z%F?DF$@)z9EN`R!_skq++k9Ued_G_E|F~=xLiK&LfA$m4l+CPDw$1lp=JWZQZ%@$v zqa@}Y^>HWl`8IL{HuWWcy$}JO-R5FIwVl1i3j;DI}!v=5f z9vPX~YVO+;TdQSi2>VwDY}wAJB7bhwz#GT;PrW{72K_a|mTXNcD@N6846GmiQ6|H^ z?6~x|_DVGu7el{Tz~*0nxqAK1k&d)y9VpEA^2 zZm3Wcud#TjEE^@0QjfCPI+Nl3+pY3dDb4Z)%d%aM^?l-hw^eq9(k46bA3cEbe}(@) zr9cDJ&L^*YA9df~j1Fq7G0%WA&sbm>_erGs+atz(>XBYX2S+r{()wpoj;e^NT2IY3 z?kmuV0ZG%4G#?~gL((;b303_p@TJBoBgkyEOdrlI zP^*j`2q$~PJB-f|&hv&pGrmUnac}r*lpJJkw!@CU;kdC66;+_-D)bvaM7a1zz3n>e z0-A?i$6U@#hx)~p<3`u#xYxM>UFY89CUjH4;Q%HII2OR*R{<}05PZQi*2CZ@p3fNk z%yX2%VxQs_I#H4fzm1WmK6M>*B|M7@OOp)G)pFuAty;fMs^N%>E>H(u=UhgHn&DpQ zM%tC`HSR=7>kPUoiJhMMzQk+XJKae9VZgxvXSPEf4EQPl!3zNw1CaM(z|{aFU0n?r z>_KR-XSgS3fMcMe(g4Q*hbP%r$Z*eO4|09tIp%TJ_i?Ch3;P`1d0brp9YHW4*9n9| zwVl-LfF%I{E(us0;C{}L>9x~XL0t~J$=Oun1FxNi_^<;tK2{nc;Frb<>T=j|&c;#>y?*6Lmr6Ny8f5fO zV+BzTKA@+Xj6MSGR(rO4IM&s6&nKGNYCS;4Ll{2dV||v_J)=)5vs*!wW%|-sUOSBy z)b%;kPWM?icuk#k&kitnIm7o+ncFD|w;Ma1Mpw1dxyz{~SF$m${s`5Ct8rd!-I%=u&clDZw5%S*2N)d8seP}ni<^zanCmAM)$R+ zh-O9)3l;-dH#Ew>Cc(t}r5q8cB_a#d$ja8l$^Ohh=riL8Nq5Bf+!DK=Q|xwC7mZ66 z;F7W0BAd4~wBs)igER%ka#C-MbEXr{8s{E5UpsS2wlU_*bY`1x!U6l^!B3r^uHT<> z_a#BIR|s8K7;Es##{Y1b| z3ctoN+g2Rx_V~NH`ZT+G%>Pn-nq55rQhl0TJpfXDnq55rQhl0TJpiZG6@>}mimu*I zhw!hOeqDXKT|LwasXpDV9ssF6-L4)0sXpDV9ssF6-L4)0sXpDV9;yaEkRj965(Npg zM7>4gEJsF>_5iHXK1t|MdCt{NBv{Qc+EEQLadDhPRKv}e0H8duxKphM6O%3WkeSoq z>}SUP&hHtLU-TiSE;hv=*pq=eNo+rgEH3H3|%)GX~BqYjn*r zmJz-T!wv9D#uW>G#mIGDBjxN;(oo8)1_acrx)gNJEMu_&{1$WUcEZ?|QUI4y?Aa0d zR~vf`V7k}%iF(u(<0?Z}SrsQqRk??_@U?7(h*n)8!D<&%ju17&{VsKzcLR>V;lOsN z1MVO2Hn#e~eIy|4e{P?opecBgtNjn=Y{tGtWk~B&2s+eJ_dKcq^8ywJL=;P11#f;V z4tR@^Z=v+-BAMHvR=GE_vd!)TaL5GonFA7JjyWM^J9w{Cov^W*R{~ZPM(Uh<7?qw^ z0%iu7Po@^AnE}8o%@M%7!vZ+q?GJuTdMVYurLH&i_)~AX3JEB5;U!0FKuSOs0BWTB zC8%POTfN4t>Bz7F4iTo$M!3*55{e@bM&^$h543g>CTJ8=3$f5pXViI)!6G#r8X?P} z&wLUM=SLki*KrW6Q`_O_e#uj>FvlwZg$?lb%K)oiUQ*kr=RztPDo-s|Wc$U)-!Rir zEOC{XNuo$5`JhPy97%1H=J)la&hJ}(zQe-cBIFsW%SCA#LHYziC<}Yc{iekQYNfdz zepP7hAqXv@&&;%1BCVO>T+hL@-nqe=%QrX=5OBabRgYaZnE|0U{O>SBy4v9U5Dv?v z&!+ML=M*Lcl@B<7U_3G$C#(ZIn=qTotQ?U!#&{0P@y2ir4K>_3%EDrla~c8DoCO*H zI;*t?v=8#P+G5}*Cc1*6fF0%pLf{+5T1Eq-x8d`)(wdQLYvvJ#)pN83L00AtlzBTr zi>pMxI2Dlq1QTncStvTOw%Olig!;E2;+6q6SE7(x?gHel0a4)7Dqc1~K#$K>&j@

SwfxVxZL+||a174Sktnu=>;Jfxa1 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 diff --git a/Makefile b/huffman/Makefile similarity index 100% rename from Makefile rename to huffman/Makefile diff --git a/hello.c b/huffman/hello.c similarity index 100% rename from hello.c rename to huffman/hello.c diff --git a/huffman_.c b/huffman/huffman_.c similarity index 100% rename from huffman_.c rename to huffman/huffman_.c diff --git a/huffman_.h b/huffman/huffman_.h similarity index 100% rename from huffman_.h rename to huffman/huffman_.h diff --git a/lzw-ab/.vscode/c_cpp_properties.json b/lzw-ab/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..f3679c6 --- /dev/null +++ b/lzw-ab/.vscode/c_cpp_properties.json @@ -0,0 +1,23 @@ +{ + "configurations": [ + { + "name": "Win32", + "includePath": [ + "${workspaceFolder}/**", + "C:/MinGW/include/" + ], + "defines": [ + "_DEBUG", + "UNICODE", + "_UNICODE", + "__WIN32__", + "DLL_EXPORT" + ], + "cStandard": "c17", + "cppStandard": "gnu++17", + "intelliSenseMode": "windows-gcc-x64", + "compilerPath": "C:/MinGW/bin/gcc.exe" + } + ], + "version": 4 +} \ No newline at end of file diff --git a/lzw-ab/.vscode/settings.json b/lzw-ab/.vscode/settings.json new file mode 100644 index 0000000..854061e --- /dev/null +++ b/lzw-ab/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "files.associations": { + "coder_lib.h": "c", + "huffman_.h": "c" + } +} \ No newline at end of file diff --git a/lzw-ab/Makefile b/lzw-ab/Makefile new file mode 100644 index 0000000..1a1dd1f --- /dev/null +++ b/lzw-ab/Makefile @@ -0,0 +1,15 @@ + + +CC = gcc + + +SRCS = $(wildcard *.c) + + +STR = $(subst from,to,from your heart) + +all: + $(CC) $(SRCS) -o hello + +clean: + rm -rf *.exe diff --git a/lzw-ab/README b/lzw-ab/README new file mode 100644 index 0000000..e77444e --- /dev/null +++ b/lzw-ab/README @@ -0,0 +1,83 @@ +//////////////////////////////////////////////////////////////////////////// +// **** LZW-AB **** // +// Adjusted Binary LZW Compressor/Decompressor // +// Copyright (c) 2016-2020 David Bryant // +// All Rights Reserved // +// Distributed under the BSD Software License (see license.txt) // +//////////////////////////////////////////////////////////////////////////// + +This is an implementation of the Lempel-Ziv-Welch general-purpose data +compression algorithm. It is targeted at embedded applications that require +high speed compression or decompression facilities where lots of RAM for +large dictionaries might not be available. I have used this in several +projects for storing compressed firmware images, and once I even coded the +decompressor in Z-80 assembly language for speed! Depending on the maximum +symbol size selected, the implementation can require from 2368 to 335616 +bytes of RAM for decoding (and about half again more for encoding). + +This is a streaming compressor in that the data is not divided into blocks +and no context information like dictionaries or Huffman tables are sent +ahead of the compressed data (except for one byte to signal the maximum +bit depth). This limits the maximum possible compression ratio compared to +algorithms that significantly preprocess the data, but with the help of +some enhancements to the LZW algorithm (described below) it is able to +compress better than the UNIX "compress" utility (which is also LZW) and +is in fact closer to and sometimes beats the compression level of "gzip". + +The symbols are stored in "adjusted binary" which provides somewhat better +compression (with virtually no speed penalty) compared to the fixed word +sizes normally used. Once the dictionary is full, the encoder returns to +the beginning and recycles string codes that have not been used yet for +longer strings. In this way the dictionary constantly "churns" based on the +the incoming stream, thereby improving and adapting to optimal compression. +The compression performance is constantly monitored and a dictionary flush +is forced on stretches of negative compression which limits worst-case +performance to about 8% inflation. + +LZW-AB consists of three standard C files: the library, a command-line +filter demo using pipes, and a command-line test harness. Each program +builds with a single command on most platforms. It has been designed with +maximum portability in mind and should work correctly on big-endian as well +as little-endian machines. + +Linux: +% gcc -O3 lzwfilter.c lzwlib.c -o lzwfilter +% gcc -O3 lzwtester.c lzwlib.c -o lzwtester + +Darwin/Mac: +% clang -O3 lzwfilter.c lzwlib.c -o lzwfilter +% clang -O3 lzwtester.c lzwlib.c -o lzwtester + +MS Visual Studio: +cl -O2 lzwfilter.c lzwlib.c +cl -O2 lzwtester.c lzwlib.c + +There are Windows binaries (built on MinGW) for the filter and the tester on the +GitHub release page (v3). The "help" display for the filter looks like this: + + Usage: lzwfilter [-options] [< infile] [> outfile] + + Operation: compression is default, use -d to decompress + + Options: -d = decompress + -h = display this "help" message + -1 = maximum symbol size = 9 bits + -2 = maximum symbol size = 10 bits + -3 = maximum symbol size = 11 bits + -4 = maximum symbol size = 12 bits + -5 = maximum symbol size = 13 bits + -6 = maximum symbol size = 14 bits + -7 = maximum symbol size = 15 bits + -8 = maximum symbol size = 16 bits (default) + -v = verbose (display ratio and checksum) + +Here's the "help" display for the tester: + + Usage: lzwtester [options] file [...] + + Options: -1 ... -8 = test using only specified max symbol size (9 - 16) + -0 = cycle through all maximum symbol sizes (default) + -e = exhaustive test (by successive truncation) + -f = fuzz test (randomly corrupt compressed data) + -q = quiet mode (only reports errors and summary) + diff --git a/lzw-ab/license.txt b/lzw-ab/license.txt new file mode 100644 index 0000000..65d4a2e --- /dev/null +++ b/lzw-ab/license.txt @@ -0,0 +1,25 @@ + Copyright (c) David Bryant + All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Conifer Software nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/lzw-ab/lzwfilter.ctt b/lzw-ab/lzwfilter.ctt new file mode 100644 index 0000000..40920a7 --- /dev/null +++ b/lzw-ab/lzwfilter.ctt @@ -0,0 +1,191 @@ +//////////////////////////////////////////////////////////////////////////// +// **** LZW-AB **** // +// Adjusted Binary LZW Compressor/Decompressor // +// Copyright (c) 2016-2020 David Bryant // +// All Rights Reserved // +// Distributed under the BSD Software License (see license.txt) // +//////////////////////////////////////////////////////////////////////////// + + +#include +#include +#include + +#ifdef _WIN32 +#include +#endif + +#include "lzwlib.h" + +/* This module provides a command-line filter for testing the lzw library. + * It can also optionally calculate and display the compression ratio and + * a simple checksum for informational purposes. Other command-line + * arguments select decoding mode or the maximum symbol size (9 to 16 bits) + * for encoding. + */ + +static const char *usage = +" Usage: lzwfilter [-options] [< infile] [> outfile]\n\n" +" Operation: compression is default, use -d to decompress\n\n" +" Options: -d = decompress\n" +" -h = display this \"help\" message\n" +" -1 = maximum symbol size = 9 bits\n" +" -2 = maximum symbol size = 10 bits\n" +" -3 = maximum symbol size = 11 bits\n" +" -4 = maximum symbol size = 12 bits\n" +" -5 = maximum symbol size = 13 bits\n" +" -6 = maximum symbol size = 14 bits\n" +" -7 = maximum symbol size = 15 bits\n" +" -8 = maximum symbol size = 16 bits (default)\n" +" -v = verbose (display ratio and checksum)\n\n" +" Web: Visit www.github.com/dbry/lzw-ab for latest version and info\n\n"; + +typedef struct { + unsigned char buffer [65536]; + int checksum, head, tail; + size_t byte_count; +} streamer; + +static int read_buff (void *ctx) +{ + streamer *stream = ctx; + int value; + + if (stream->head == stream->tail) + stream->tail = (stream->head = 0) + fread (stream->buffer, 1, sizeof (stream->buffer), stdin); + + if (stream->head < stream->tail) { + value = stream->buffer [stream->head++]; + stream->checksum = stream->checksum * 3 + (unsigned char) value; + stream->byte_count++; + } + else + value = EOF; + + return value; +} + +static void write_buff (int value, void *ctx) +{ + streamer *stream = ctx; + + if (value == EOF) { + fwrite (stream->buffer, 1, stream->head, stdout); + return; + } + + stream->buffer [stream->head++] = value; + + if (stream->head == sizeof (stream->buffer)) { + fwrite (stream->buffer, 1, stream->head, stdout); + stream->head = 0; + } + + stream->checksum = stream->checksum * 3 + (unsigned char) value; + stream->byte_count++; +} + +int main (int argc, char **argv) +{ + int decompress = 0, maxbits = 16, verbose = 0, error = 0; + streamer reader, writer; + + memset (&reader, 0, sizeof (reader)); + memset (&writer, 0, sizeof (writer)); + reader.checksum = writer.checksum = -1; + + while (--argc) { + if ((**++argv == '-') && (*argv)[1]) + while (*++*argv) + switch (**argv) { + case '1': + maxbits = 9; + break; + + case '2': + maxbits = 10; + break; + + case '3': + maxbits = 11; + break; + + case '4': + maxbits = 12; + break; + + case '5': + maxbits = 13; + break; + + case '6': + maxbits = 14; + break; + + case '7': + maxbits = 15; + break; + + case '8': + maxbits = 16; + break; + + case 'D': case 'd': + decompress = 1; + break; + + case 'H': case 'h': + fprintf (stderr, "%s", usage); + return 0; + break; + + case 'V': case 'v': + verbose = 1; + break; + + default: + fprintf (stderr, "illegal option: %c !\n", **argv); + error = 1; + break; + } + else { + fprintf (stderr, "unknown argument: %s\n", *argv); + error = 1; + } + } + + if (error) { + fprintf (stderr, "%s", usage); + return 0; + } + +#ifdef _WIN32 + setmode (fileno (stdin), O_BINARY); + setmode (fileno (stdout), O_BINARY); +#endif + + if (decompress) { + if (lzw_decompress (write_buff, &writer, read_buff, &reader)) { + fprintf (stderr, "lzw_decompress() returned non-zero!\n"); + return 1; + } + + write_buff (EOF, &writer); + + if (verbose && writer.byte_count) + fprintf (stderr, "output checksum = %x, ratio = %.2f%%\n", writer.checksum, reader.byte_count * 100.0 / writer.byte_count); + } + else { + if (lzw_compress (write_buff, &writer, read_buff, &reader, maxbits)) { + fprintf (stderr, "lzw_compress() returned non-zero!\n"); + return 1; + } + + write_buff (EOF, &writer); + + if (verbose && reader.byte_count) + fprintf (stderr, "source checksum = %x, ratio = %.2f%%\n", reader.checksum, writer.byte_count * 100.0 / reader.byte_count); + } + + return 0; +} diff --git a/lzw-ab/lzwlib.c b/lzw-ab/lzwlib.c new file mode 100644 index 0000000..636472b --- /dev/null +++ b/lzw-ab/lzwlib.c @@ -0,0 +1,513 @@ +//////////////////////////////////////////////////////////////////////////// +// **** LZW-AB **** // +// Adjusted Binary LZW Compressor/Decompressor // +// Copyright (c) 2016-2020 David Bryant // +// All Rights Reserved // +// Distributed under the BSD Software License (see license.txt) // +//////////////////////////////////////////////////////////////////////////// + +#include +#include +#include + +#include "lzwlib.h" + +/* This library implements the LZW general-purpose data compression algorithm. + * The algorithm was originally described as a hardware implementation by + * Terry Welsh here: + * + * Welch, T.A. “A Technique for High-Performance Data Compression.” + * IEEE Computer 17,6 (June 1984), pp. 8-19. + * + * Since then there have been enumerable refinements and variations on the + * basic technique, and this implementation is no different. The target of + * the present implementation is embedded systems, and so emphasis was placed + * on simplicity, fast execution, and minimal RAM usage. + * + * This is a streaming compressor in that the data is not divided into blocks + * and no context information like dictionaries or Huffman tables are sent + * ahead of the compressed data (except for one byte to signal the maximum + * bit depth). This limits the maximum possible compression ratio compared to + * algorithms that significantly preprocess the data, but with the help of + * some enhancements to the LZW algorithm (described below) it is able to + * compress better than the UNIX "compress" utility (which is also LZW) and + * is in fact closer to and sometimes beats the compression level of "gzip". + * + * The symbols are stored in "adjusted binary" which provides somewhat better + * compression, with virtually no speed penalty, compared to the fixed word + * sizes normally used. These are sometimes called "phased-in" binary codes + * and their use in LZW is described here: + * + * R. N. Horspool, "Improving LZW (data compression algorithm)", Data + * Compression Conference, pp. 332-341, 1991. + * + * Earlier versions of this compressor would reset as soon as the dictionary + * became full to ensure good performance on heterogenous data (such as tar + * files or executable images). While trivial to implement, this is not + * particularly efficient with homogeneous data (or in general) because we + * spend a lot of time sending short symbols where the compression is poor. + * + * This newer version utilizes a technique such that once the dictionary is + * full, we restart at the beginning and recycle only those codes that were + * seen only once. We know this because they are not referenced by longer + * strings, and are easy to replace in the dictionary for the same reason. + * Since they have only been seen once it's also more likely that we will + * be replacing them with a more common string, and this is especially + * true if the data characteristics are changing. + * + * Replacing string codes in this manner has the interesting side effect that + * some older shorter strings that the removed strings were based on will + * possibly become unreferenced themselves and be recycled on the next pass. + * In this way, the entire dictionary constantly "churns" based on the + * incoming stream, thereby improving and adapting to optimal compression. + * + * Even with this technique there is still a possibility that a sudden change + * in the data characteristics will appear, resulting in significant negative + * compression (up to 100% for 16-bit codes). To detect this case we generate + * an exponentially decaying average of the current compression ratio and reset + * when this hits about 1.06, which limits worst case inflation to about 8%. + * + * The maximum symbol size is configurable on the encode side (from 9 bits to + * 16 bits) and determines the RAM footprint required by both sides and, to a + * large extent, the compression performance. This information is communicated + * to the decoder in the first stream byte so that it can allocate accordingly. + * The RAM requirements are as follows: + * + * maximum encoder RAM decoder RAM + * symbol size requirement requirement + * ----------------------------------------- + * 9-bit 4096 bytes 2368 bytes + * 10-bit 8192 bytes 4992 bytes + * 11-bit 16384 bytes 10240 bytes + * 12-bit 32768 bytes 20736 bytes + * 13-bit 65536 bytes 41728 bytes + * 14-bit 131072 bytes 83712 bytes + * 15-bit 262144 bytes 167680 bytes + * 16-bit 524288 bytes 335616 bytes + * + * This implementation uses malloc(), but obviously an embedded version could + * use static arrays instead if desired (assuming that the maxbits was + * controlled outside). + */ + +#define NULL_CODE 65535 // indicates a NULL prefix (must be unsigned short) +#define CLEAR_CODE 256 // code to flush dictionary and restart decoder +#define FIRST_STRING 257 // code of first dictionary string + +/* This macro determines the number of bits required to represent the given value, + * not counting the implied MSB. For GNU C it will use the provided built-in, + * otherwise a comparison tree is employed. Note that in the non-GNU case, only + * values up to 65535 (15 bits) are supported. + */ + +#ifdef __GNUC__ +#define CODE_BITS(n) (31 - __builtin_clz(n)) +#else +#define CODE_BITS(n) ((n) < 4096 ? \ + ((n) < 1024 ? 8 + ((n) >= 512) : 10 + ((n) >= 2048)) : \ + ((n) < 16384 ? 12 + ((n) >= 8192) : 14 + ((n) >= 32768))) +#endif + +/* This macro writes the adjusted-binary symbol "code" given the maximum + * symbol "maxcode". A macro is used here just to avoid the duplication in + * the lzw_compress() function. The idea is that if "maxcode" is not one + * less than a power of two (which it rarely will be) then this code can + * often send fewer bits that would be required with a fixed-sized code. + * + * For example, the first code we send will have a "maxcode" of 257, so + * every "code" would normally consume 9 bits. But with adjusted binary we + * can actually represent any code from 0 to 253 with just 8 bits -- only + * the 4 codes from 254 to 257 take 9 bits. + */ + +#define WRITE_CODE(code,maxcode) do { \ + unsigned int code_bits = CODE_BITS (maxcode); \ + unsigned int extras = (2 << code_bits) - (maxcode) - 1; \ + if ((code) < extras) { \ + shifter |= ((code) << bits); \ + bits += code_bits; \ + } \ + else { \ + shifter |= ((((code) + extras) >> 1) << bits); \ + bits += code_bits; \ + shifter |= ((((code) + extras) & 1) << bits++); \ + } \ + do { (*dst)(shifter,dstctx); shifter >>= 8; \ + output_bytes += 256; \ + } while ((bits -= 8) >= 8); \ +} while (0) + +/* LZW compression function. Bytes (8-bit) are read and written through callbacks and the + * "maxbits" parameter specifies the maximum symbol size (9-16), which in turn determines + * the RAM requirement and, to a large extent, the level of compression achievable. A return + * value of EOF from the "src" callback terminates the compression process. A non-zero return + * value indicates one of the two possible errors -- bad "maxbits" param or failed malloc(). + * There are contexts (void pointers) that are passed to the callbacks to easily facilitate + * multiple instances of the compression operation (but simple applications can ignore these). + */ + +typedef struct { + unsigned short first_reference, next_reference, back_reference; + unsigned char terminator; +} encoder_entry_t; + +int lzw_compress (void (*dst)(int,void*), void *dstctx, int (*src)(void*), void *srcctx, int maxbits) +{ + unsigned int maxcode = FIRST_STRING, next_string = FIRST_STRING, prefix = NULL_CODE, total_codes; + unsigned int dictionary_full = 0, available_entries, max_available_entries, max_available_code; + unsigned int input_bytes = 65536, output_bytes = 65536; + unsigned int shifter = 0, bits = 0; + encoder_entry_t *dictionary; + int c; + + if (maxbits < 9 || maxbits > 16) // check for valid "maxbits" setting + return 1; + + // based on the "maxbits" parameter, compute total codes and allocate dictionary storage + + total_codes = 1 << maxbits; + dictionary = malloc (total_codes * sizeof (encoder_entry_t)); + max_available_entries = total_codes - FIRST_STRING - 1; + max_available_code = total_codes - 2; + + if (!dictionary) + return 1; // failed malloc() + + // clear the dictionary + + available_entries = max_available_entries; + memset (dictionary, 0, 256 * sizeof (encoder_entry_t)); + + (*dst)(maxbits - 9, dstctx); // first byte in output stream indicates the maximum symbol bits + + // This is the main loop where we read input bytes and compress them. We always keep track of the + // "prefix", which represents a pending byte (if < 256) or string entry (if >= FIRST_STRING) that + // has not been sent to the decoder yet. The output symbols are kept in the "shifter" and "bits" + // variables and are sent to the output every time 8 bits are available (done in the macro). + + while ((c = (*src)(srcctx)) != EOF) { + unsigned int cti; // coding table index + + input_bytes += 256; + + if (prefix == NULL_CODE) { // this only happens the very first byte when we don't yet have a prefix + prefix = c; + continue; + } + + memset (dictionary + next_string, 0, sizeof (encoder_entry_t)); + + if ((cti = dictionary [prefix].first_reference)) { // if any longer strings are built on the current prefix... + while (1) + if (dictionary [cti].terminator == c) { // we found a matching string, so we just update the prefix + prefix = cti; // to that string and continue without sending anything + break; + } + else if (!dictionary [cti].next_reference) { // this string did not match the new character and + dictionary [cti].next_reference = next_string; // there aren't any more, so we'll add a new string, + // point to it with "next_reference", and also make the + dictionary [next_string].back_reference = cti; // "back_reference" which is used for recycling entries + cti = 0; + break; + } + else + cti = dictionary [cti].next_reference; // there are more possible matches to check, so loop back + } + else { // no longer strings are based on the current prefix, so now + dictionary [prefix].first_reference = next_string; // the current prefix plus the new byte will be the next string + dictionary [next_string].back_reference = prefix; // also make the back_reference used for recycling + if (prefix >= FIRST_STRING) available_entries--; // the codes 0-255 are never available for recycling + } + + // If "cti" is zero, we could not simply extend our "prefix" to a longer string because we did not find a + // dictionary match, so we send the symbol representing the current "prefix" and add the new string to the + // dictionary. Since the current byte "c" was not included in the prefix, that now becomes our new prefix. + + if (!cti) { + WRITE_CODE (prefix, maxcode); // send symbol for current prefix (0 to maxcode-1) + dictionary [next_string].terminator = c; // newly created string has current byte as the terminator + prefix = c; // current byte also becomes new prefix for next string + + // If the dictionary is not full yet, we bump the maxcode and next_string and check to see if the + // dictionary is now full. If it is we set the dictionary_full flag and leave maxcode set to two + // less than total_codes because every string entry is now available for matching, but the actual + // maximum code is reserved for EOF. + + if (!dictionary_full) { + dictionary_full = (++next_string > max_available_code); + maxcode++; + } + + // If the dictionary is full we look for an entry to recycle starting at next_string (the one we + // just created or recycled) plus one (with check for wrap check). We know there is one because at + // a minimum the string we just added. This also takes care of removing the entry to be recycled + // (which is possible/easy because no longer strings have been based on it). + + if (dictionary_full) { + for (next_string++; next_string <= max_available_code || (next_string = FIRST_STRING); next_string++) + if (!dictionary [next_string].first_reference) + break; + + cti = dictionary [next_string].back_reference; // dictionary [cti] references the entry we're + // trying to recycle (either as a first or a next) + + if (dictionary [cti].first_reference == next_string) { + dictionary [cti].first_reference = dictionary [next_string].next_reference; + + // if we just cleared a first reference, and that string is not 0-255, + // then that's a newly available entry + if (!dictionary [cti].first_reference && cti >= FIRST_STRING) + available_entries++; + } + else if (dictionary [cti].next_reference == next_string) // fixup a "next_reference" + dictionary [cti].next_reference = dictionary [next_string].next_reference; + + // If the entry we're recycling had a next reference, then update the back reference + // so it's completely out of the chain. Of course we know it didn't have a first + // reference because then we wouldn't be recycling it. + + if (dictionary [next_string].next_reference) + dictionary [dictionary [next_string].next_reference].back_reference = cti; + + // This check is technically not needed because there will always be an available entry + // (the last string we added at a minimum) but we don't want to get in a situation where + // we only have a few entries that we're cycling though. I pulled the limits (16 entries + // or 1% of total) out of a hat. + + if (available_entries < 16 || available_entries * 100 < max_available_entries) { + // clear the dictionary and reset the byte counters -- basically everything starts over + // except that we keep the last pending "prefix" (which, of course, was never sent) + + WRITE_CODE (CLEAR_CODE, maxcode); + memset (dictionary, 0, 256 * sizeof (encoder_entry_t)); + available_entries = max_available_entries; + next_string = maxcode = FIRST_STRING; + input_bytes = output_bytes = 65536; + dictionary_full = 0; + } + } + + // This is similar to the above check, except that it's used whether the dictionary is full or not. + // It uses an exponentially decaying average of the current compression ratio, so it can terminate + // very early if the incoming data is uncompressible or it can terminate any later time that the + // dictionary no longer compresses the incoming stream. + + if (output_bytes > input_bytes + (input_bytes >> 4)) { + WRITE_CODE (CLEAR_CODE, maxcode); + memset (dictionary, 0, 256 * sizeof (encoder_entry_t)); + available_entries = max_available_entries; + next_string = maxcode = FIRST_STRING; + input_bytes = output_bytes = 65536; + dictionary_full = 0; + } + else { + output_bytes -= output_bytes >> 8; + input_bytes -= input_bytes >> 8; + } + } + } + + // we're done with input, so if we've received anything we still need to send that pesky pending prefix... + + if (prefix != NULL_CODE) { + WRITE_CODE (prefix, maxcode); + + if (!dictionary_full) + maxcode++; + } + + WRITE_CODE (maxcode, maxcode); // the maximum possible code is always reserved for our END_CODE + + if (bits) // finally, flush any pending bits from the shifter + (*dst)(shifter, dstctx); + + free (dictionary); + return 0; +} + +/* LZW decompression function. Bytes (8-bit) are read and written through callbacks. The + * "maxbits" parameter is read as the first byte in the stream and controls how much memory + * is allocated for decoding. A return value of EOF from the "src" callback terminates the + * decompression process (although this should not normally occur). A non-zero return value + * indicates an error, which in this case can be a bad "maxbits" read from the stream, a + * failed malloc(), or if an EOF is read from the input stream before the decompression + * terminates naturally with END_CODE. There are contexts (void pointers) that are passed + * to the callbacks to easily facilitate multiple instances of the decompression operation + * (but simple applications can ignore these). + */ + +typedef struct { + unsigned char terminator, extra_references; + unsigned short prefix; +} decoder_entry_t; + +int lzw_decompress (void (*dst)(int,void*), void *dstctx, int (*src)(void*), void *srcctx) +{ + unsigned int maxcode = FIRST_STRING, next_string = FIRST_STRING - 1, prefix = CLEAR_CODE; + unsigned int dictionary_full = 0, max_available_code, total_codes; + unsigned int shifter = 0, bits = 0, read_byte, i; + unsigned char *reverse_buffer, *referenced; + decoder_entry_t *dictionary; + + if ((read_byte = ((*src)(srcctx))) == EOF || (read_byte & 0xf8)) //sanitize first byte + return 1; + + // based on the "maxbits" parameter, compute total codes and allocate dictionary storage + + total_codes = 512 << (read_byte & 0x7); + max_available_code = total_codes - 2; + dictionary = malloc (total_codes * sizeof (decoder_entry_t)); + reverse_buffer = malloc (total_codes - 256); + referenced = malloc (total_codes / 8); // bitfield indicating code is referenced at least once + + // Note that to implement the dictionary entry recycling we have to keep track of how many + // longer strings are based on each string in the dictionary. This can be between 0 (no + // references) to 256 (every possible next byte), but unfortunately that's one more value + // than what can be stored in a byte. The solution is to have a single bit for each entry + // indicating any references (i.e., the code cannot be recycled) and an additional byte + // in the dictionary entry struct counting the "extra" references (beyond one). + + if (!reverse_buffer || !dictionary) // check for malloc() failure + return 1; + + for (i = 0; i < 256; ++i) { // these never change + dictionary [i].prefix = NULL_CODE; + dictionary [i].terminator = i; + } + + // This is the main loop where we read input symbols. The values range from 0 to the code value + // of the "next" string in the dictionary (although the actual "next" code cannot be used yet, + // and so we reserve that code for the END_CODE). Note that receiving an EOF from the input + // stream is actually an error because we should have gotten the END_CODE first. + + while (1) { + unsigned int code_bits = CODE_BITS (maxcode), code; + unsigned int extras = (2 << code_bits) - maxcode - 1; + + do { + if ((read_byte = ((*src)(srcctx))) == EOF) { + free (dictionary); free (reverse_buffer); free (referenced); + return 1; + } + + shifter |= read_byte << bits; + } while ((bits += 8) < code_bits); + + // first we assume the code will fit in the minimum number of required bits + + code = shifter & ((1 << code_bits) - 1); + shifter >>= code_bits; + bits -= code_bits; + + // but if code >= extras, then we need to read another bit to calculate the real code + // (this is the "adjusted binary" part) + + if (code >= extras) { + if (!bits) { + if ((read_byte = ((*src)(srcctx))) == EOF) { + free (dictionary); free (reverse_buffer); free (referenced); + return 1; + } + + shifter = read_byte; + bits = 8; + } + + code = (code << 1) - extras + (shifter & 1); + shifter >>= 1; + bits--; + } + + if (code == maxcode) // sending the maximum code is reserved for the end of the file + break; + else if (code == CLEAR_CODE) { // otherwise check for a CLEAR_CODE to start over early + next_string = FIRST_STRING - 1; + maxcode = FIRST_STRING; + dictionary_full = 0; + } + else if (prefix == CLEAR_CODE) { // this only happens at the first symbol which is always sent + (*dst)(code, dstctx); // literally and becomes our initial prefix + next_string++; + maxcode++; + } + // Otherwise we have a valid prefix so we step through the string from end to beginning storing the + // bytes in the "reverse_buffer", and then we send them out in the proper order. One corner-case + // we have to handle here is that the string might be the same one that is actually being defined + // now (code == next_string). + else { + unsigned int cti = (code == next_string) ? prefix : code; + unsigned char *rbp = reverse_buffer, c; + + do { + *rbp++ = dictionary [cti].terminator; + if (rbp == reverse_buffer + total_codes - 256) { + free (dictionary); free (reverse_buffer); free (referenced); + return 1; + } + } while ((cti = dictionary [cti].prefix) != NULL_CODE); + + c = *--rbp; // the first byte in this string is the terminator for the last string, which is + // the one that we'll create a new dictionary entry for this time + + do // send string in corrected order (except for the terminator which we don't know yet) + (*dst)(*rbp, dstctx); + while (rbp-- != reverse_buffer); + + if (code == next_string) { + (*dst)(c,dstctx); + } + + // This should always execute (the conditional is to catch corruptions) and is where we add a new string to + // the dictionary, either at the end or elsewhere when we are "recycling" entries that were never referenced + + if (next_string >= FIRST_STRING && next_string < total_codes) { + if (referenced [prefix >> 3] & (1 << (prefix & 7))) // increment reference count on prefix + dictionary [prefix].extra_references++; + else + referenced [prefix >> 3] |= 1 << (prefix & 7); + + dictionary [next_string].prefix = prefix; // now update the next dictionary entry with the new string + dictionary [next_string].terminator = c; // (but we're always one behind, so it's not the string just sent) + dictionary [next_string].extra_references = 0; // newly created string has not been referenced + referenced [next_string >> 3] &= ~(1 << (next_string & 7)); + } + + // If the dictionary is not full yet, we bump the maxcode and next_string and check to see if the + // dictionary is now full. If it is we set the dictionary_full flag and set next_string back to the + // beginning of the dictionary strings to start recycling them. Note that then maxcode will remain + // two less than total_codes because every string entry is available for matching, and the actual + // maximum code is reserved for EOF. + + if (!dictionary_full) { + maxcode++; + + if (++next_string > max_available_code) { + dictionary_full = 1; + maxcode--; + } + } + + // If the dictionary is full we look for an entry to recycle starting at next_string (the one we + // created or recycled) plus one. We know there is one because at a minimum the string we just added + // has not been referenced). This also takes care of removing the entry to be recycled (which is + // possible/easy because no longer strings have been based on it). + + if (dictionary_full) { + for (next_string++; next_string <= max_available_code || (next_string = FIRST_STRING); next_string++) + if (!(referenced [next_string >> 3] & (1 << (next_string & 7)))) + break; + + if (dictionary [dictionary [next_string].prefix].extra_references) + dictionary [dictionary [next_string].prefix].extra_references--; + else + referenced [dictionary [next_string].prefix >> 3] &= ~(1 << (dictionary [next_string].prefix & 7)); + } + } + + prefix = code; // the code we just received becomes the prefix for the next dictionary string entry + // (which we'll create once we find out the terminator) + } + + free (dictionary); free (reverse_buffer); free (referenced); + return 0; +} diff --git a/lzw-ab/lzwlib.h b/lzw-ab/lzwlib.h new file mode 100644 index 0000000..246ca24 --- /dev/null +++ b/lzw-ab/lzwlib.h @@ -0,0 +1,15 @@ +//////////////////////////////////////////////////////////////////////////// +// **** LZW-AB **** // +// Adjusted Binary LZW Compressor/Decompressor // +// Copyright (c) 2016-2020 David Bryant // +// All Rights Reserved // +// Distributed under the BSD Software License (see license.txt) // +//////////////////////////////////////////////////////////////////////////// + +#ifndef LZWLIB_H_ +#define LZWLIB_H_ + +int lzw_compress (void (*dst)(int,void*), void *dstctx, int (*src)(void*), void *srcctx, int maxbits); +int lzw_decompress (void (*dst)(int,void*), void *dstctx, int (*src)(void*), void *srcctx); + +#endif /* LZWLIB_H_ */ diff --git a/lzw-ab/lzwtester.c b/lzw-ab/lzwtester.c new file mode 100644 index 0000000..35007d7 --- /dev/null +++ b/lzw-ab/lzwtester.c @@ -0,0 +1,317 @@ +//////////////////////////////////////////////////////////////////////////// +// **** LZW-AB **** // +// Adjusted Binary LZW Compressor/Decompressor // +// Copyright (c) 2016-2020 David Bryant // +// All Rights Reserved // +// Distributed under the BSD Software License (see license.txt) // +//////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#endif + +#include "lzwlib.h" + +/* This module provides a command-line test harness for the lzw library. + * Given a list of files, it will read each one and byte-for-byte verify + * the data after a round-trip through a compression / decompression cycle + * at each of the 8 available maximum symbol size settings. + * + * It can also optionally perform fuzz testing by randomly corrupting the + * compressed bitstream. Obviously this will introduce integrity failures, + * but it should not cause a crash. It also has an "exhaustive" mode that + * creates hundreds of simulated images from each input file by successive + * truncation from both ends. + */ + +static const char *usage = +" Usage: lzwtester [options] file [...]\n\n" +" Options: -1 ... -8 = test using only specified max symbol size (9 - 16)\n" +" -0 = cycle through all maximum symbol sizes (default)\n" +" -e = exhaustive test (by successive truncation)\n" +" -f = fuzz test (randomly corrupt compressed data)\n" +" -q = quiet mode (only reports errors and summary)\n\n" +" Web: Visit www.github.com/dbry/lzw-ab for latest version and info\n\n"; + +typedef struct { + unsigned int size, index, wrapped, byte_errors, first_error, fuzz_testing; + unsigned char *buffer; +} streamer; + +static int read_buff (void *ctx) +{ + streamer *stream = ctx; + + if (stream->index == stream->size) + return EOF; + + return stream->buffer [stream->index++]; +} + +static void write_buff (int value, void *ctx) +{ + streamer *stream = ctx; + + // for fuzz testing, randomly corrupt 1 byte in every 65536 (on average) + + if (stream->fuzz_testing) { + static unsigned long long kernel = 0x3141592653589793; + kernel = ((kernel << 4) - kernel) ^ 1; + kernel = ((kernel << 4) - kernel) ^ 1; + kernel = ((kernel << 4) - kernel) ^ 1; + + if (!(kernel >> 48)) + value ^= (int)(kernel >> 40); + } + + if (stream->index == stream->size) { + stream->index = 0; + stream->wrapped++; + } + + stream->buffer [stream->index++] = value; +} + +static void check_buff (int value, void *ctx) +{ + streamer *stream = ctx; + + if (stream->index == stream->size) { + stream->wrapped++; + return; + } + + if (stream->buffer [stream->index] != value) + if (!stream->byte_errors++) + stream->first_error = stream->index; + + stream->index++; +} + +#ifdef _WIN32 + +long long DoGetFileSize (FILE *hFile) +{ + LARGE_INTEGER Size; + HANDLE fHandle; + + if (hFile == NULL) + return 0; + + fHandle = (HANDLE)_get_osfhandle(_fileno(hFile)); + if (fHandle == INVALID_HANDLE_VALUE) + return 0; + + Size.u.LowPart = GetFileSize(fHandle, &Size.u.HighPart); + + if (Size.u.LowPart == INVALID_FILE_SIZE && GetLastError() != NO_ERROR) + return 0; + + return (long long)Size.QuadPart; +} + +#else + +long long DoGetFileSize (FILE *hFile) +{ + struct stat statbuf; + + if (!hFile || fstat (fileno (hFile), &statbuf) || !S_ISREG(statbuf.st_mode)) + return 0; + + return (long long) statbuf.st_size; +} + +#endif + +int main (int argc, char **argv) +{ + int index, checked = 0, tests = 0, skipped = 0, errors = 0; + int set_maxbits = 0, quiet_mode = 0, exhaustive_mode = 0; + long long total_input_bytes = 0, total_output_bytes = 0; + streamer reader, writer, checker; + + memset (&reader, 0, sizeof (reader)); + memset (&writer, 0, sizeof (writer)); + memset (&checker, 0, sizeof (checker)); + + if (argc < 2) { + printf ("%s", usage); + return 0; + } + + for (index = 1; index < argc; ++index) { + const char *filename = argv [index]; + int test_size, bytes_read, maxbits; + unsigned char *file_buffer; + long long file_size; + FILE *infile; + + if (!strcmp (filename, "-q")) { + quiet_mode = 1; + continue; + } + + if (!strcmp (filename, "-e")) { + exhaustive_mode = 1; + continue; + } + + if (!strcmp (filename, "-f")) { + writer.fuzz_testing = 1; + continue; + } + + if (strlen (filename) == 2 && filename [0] == '-' && filename [1] >= '0' && filename [1] <= '8') { + if (filename [1] > '0') + set_maxbits = filename [1] - '0' + 8; + else + set_maxbits = 0; + + continue; + } + + infile = fopen (filename, "rb"); + + if (!infile) { + printf ("\ncan't open file %s!\n", filename); + skipped++; + continue; + } + + file_size = DoGetFileSize (infile); + + if (!file_size) { + printf ("\ncan't get file size of %s (may be zero)!\n", filename); + skipped++; + continue; + } + + if (file_size > 1024LL * 1024LL * 1024LL) { + printf ("\nfile %s is too big!\n", filename); + skipped++; + continue; + } + + file_buffer = malloc (file_size); + writer.size = (unsigned int)(file_size * 2 + 10); + writer.buffer = malloc (writer.size); + + if (!file_buffer || !writer.buffer) { + printf ("\nfile %s is too big!\n", filename); + if (writer.buffer) free (writer.buffer); + if (file_buffer) free (file_buffer); + skipped++; + continue; + } + + bytes_read = fread (file_buffer, 1, (int) file_size, infile); + fclose (infile); + + if (bytes_read != (int) file_size) { + printf ("\nfile %s could not be read!\n", filename); + free (writer.buffer); + free (file_buffer); + skipped++; + continue; + } + + if (!quiet_mode) + printf ("\n"); + + test_size = file_size; + checked++; + + do { + for (maxbits = set_maxbits ? set_maxbits : 9; maxbits <= (set_maxbits ? set_maxbits : 16); ++maxbits) { + int res, got_error = 0; + + reader.buffer = file_buffer + (file_size - test_size) / 2; + reader.size = test_size; + + reader.index = writer.index = writer.wrapped = 0; + + if (lzw_compress (write_buff, &writer, read_buff, &reader, maxbits)) { + printf ("\nlzw_compress() returned error on file %s, maxbits = %d\n", filename, maxbits); + errors++; + continue; + } + + if (writer.wrapped) { + printf ("\nover 100%% inflation on file %s, maxbits = %d!\n", filename, maxbits); + errors++; + continue; + } + + checker.buffer = reader.buffer; + checker.size = reader.size; + checker.wrapped = checker.byte_errors = checker.index = 0; + + reader.buffer = writer.buffer; + reader.size = writer.index; + reader.index = 0; + + res = lzw_decompress (check_buff, &checker, read_buff, &reader); + + reader.buffer = checker.buffer; + reader.size = checker.size; + + got_error = res || checker.index != checker.size || checker.wrapped || checker.byte_errors; + + if (!quiet_mode || got_error) + printf ("file %s, maxbits = %2d: %u bytes --> %u bytes, %.2f%%\n", filename, maxbits, + reader.size, writer.index, writer.index * 100.0 / reader.size); + + if (got_error) { + if (res) + printf ("decompressor returned an error\n"); + + if (!checker.index) + printf ("decompression didn't generate any data\n"); + else if (checker.index != checker.size) + printf ("decompression terminated %u bytes early\n", checker.size - checker.index); + else if (checker.wrapped) + printf ("decompression generated %u extra bytes\n", checker.wrapped); + + if (checker.byte_errors) + printf ("there were %u byte data errors starting at index %u\n", + checker.byte_errors, checker.first_error); + else if (checker.index != checker.size || checker.wrapped) + printf ("(but the data generated was all correct)\n"); + + printf ("\n"); + errors++; + } + else { + total_input_bytes += reader.size; + total_output_bytes += writer.index; + } + + tests++; + + if (exhaustive_mode) + test_size -= (test_size + 98) / 100; + } + + } while (exhaustive_mode && test_size > 1 && test_size > file_size / 100); + + free (writer.buffer); + free (file_buffer); + } + + if (errors) + printf ("\n***** %d errors detected in %d tests using %d files (%d skipped) *****\n\n", errors, tests, checked, skipped); + else { + printf ("\nsuccessfully ran %d tests using %d files (%d skipped) with no errors detected\n", tests, checked, skipped); + printf ("cumulative results: %llu bytes --> %llu bytes, %.2f%%\n\n", total_input_bytes, total_output_bytes, + total_output_bytes * 100.0 / total_input_bytes); + } + + return errors; +} diff --git a/bytearray.c b/other/bytearray.c similarity index 100% rename from bytearray.c rename to other/bytearray.c diff --git a/bytearray.h b/other/bytearray.h similarity index 100% rename from bytearray.h rename to other/bytearray.h diff --git a/coder_lib.c b/other/coder_lib.c similarity index 100% rename from coder_lib.c rename to other/coder_lib.c diff --git a/coder_lib.h b/other/coder_lib.h similarity index 100% rename from coder_lib.h rename to other/coder_lib.h diff --git a/crc.c b/other/crc.c similarity index 100% rename from crc.c rename to other/crc.c diff --git a/crc.h b/other/crc.h similarity index 100% rename from crc.h rename to other/crc.h diff --git a/for_hello.c b/other/for_hello.c similarity index 100% rename from for_hello.c rename to other/for_hello.c diff --git a/huffman.ctt b/other/huffman.ctt similarity index 100% rename from huffman.ctt rename to other/huffman.ctt diff --git a/huffman.htt b/other/huffman.htt similarity index 100% rename from huffman.htt rename to other/huffman.htt diff --git a/other/lzw-ab-master.zip b/other/lzw-ab-master.zip new file mode 100644 index 0000000000000000000000000000000000000000..809259d74513b125755b6291364fa5026dddbf1a GIT binary patch literal 15985 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 literal 0 HcmV?d00001 diff --git a/mystring.c b/other/mystring.c similarity index 100% rename from mystring.c rename to other/mystring.c diff --git a/mystring.h b/other/mystring.h similarity index 100% rename from mystring.h rename to other/mystring.h diff --git a/zl77/Makefile b/zl77/Makefile new file mode 100644 index 0000000..a2d3d43 --- /dev/null +++ b/zl77/Makefile @@ -0,0 +1,15 @@ + + +CC = gcc + + +# SRCS = $(wildcard *.c) +SRCS = zl77.c ../huffman/huffman_.c + +STR = $(subst from,to,from your heart) + +all: + $(CC) $(SRCS) -o hello + +clean: + rm -rf *.exe diff --git a/zl77/zl77.c b/zl77/zl77.c new file mode 100644 index 0000000..dcb3936 --- /dev/null +++ b/zl77/zl77.c @@ -0,0 +1,362 @@ + + +#include "zl77.h" +#include "stdio.h" +#include "stdlib.h" +#include "string.h" +#include "../huffman/huffman_.h" + +// zl77 算法的实现 + +#define DBG_WARN printf +#define DBG_LOG printf + + + +// 定义数据缓冲区步长 +#define LZ77_BUFF_STEP_SIZE 10 + + +typedef struct _buff_item{ + uint8_t data[LZ77_BUFF_STEP_SIZE]; + struct _buff_item *next; + struct _buff_item *prev; +}buff_item; + + +typedef struct _buff_def{ + buff_item *current; + buff_item *head; + int used; + int all; + int current_index; + int bit_used; +}buff_def; + + + +typedef struct _zl77_def +{ + int dict_len;// 字典长度 + int tran_len;// 转换区长度 + int index;// 窗口位置 + buff_def buff_chars;//字符编码区 + buff_def buff_pos;//标号编码区 + buff_def buff_bits;//编码类型标识区(1,字符;0,标号) + const uint8_t *in; + int in_len; + uint8_t cmp_pos;// 匹配到的pos距离 + uint8_t cmp_len;// 匹配到的长度 + uint8_t cmp_skip;// 窗口移动的距离 +}zl77_def; + + + +uint8_t zl77_buff_get_byte(buff_def *buff,int index); +void zl77_buff_set_byte(buff_def *buff,int index,uint8_t d); +void zl77_buff_append_bit(buff_def *buff,int bit); +void zl77_buff_append_byte(buff_def *buff, const uint8_t d); +int zl77_buff_get_bit(buff_def *buff, int index); + + + +zl77_def *zl77_creat(void) +{ + zl77_def *z=calloc(1,sizeof(zl77_def)); + z->dict_len=5; + z->tran_len=3; +} + + + +// 删除缓存 +void zl77_del_buff(buff_def *buff) +{ + buff_item *t=buff->head; + buff_item *o; + while(t){ + o=t; + t=t->next; + free(o); + } +} + +// 添加一个字节 +void zl77_buff_append_byte(buff_def *buff, const uint8_t d) +{ + if(buff->used>=buff->all){ + buff_item *t=buff->head; + buff_item *t_old=0; + while (t) + { + t_old=t; + t=t->next; + } + t=calloc(1,sizeof(buff_item)); + if(t_old){ + t_old->next=t; + t->prev=t_old; + }else{ + buff->head=t; + } + buff->all+=LZ77_BUFF_STEP_SIZE; + buff->current=t; + buff->current_index=buff->used; + } + while((buff->used/LZ77_BUFF_STEP_SIZE)>(buff->current_index/LZ77_BUFF_STEP_SIZE)){ + buff->current=buff->current->next; + buff->current_index+=LZ77_BUFF_STEP_SIZE; + } + buff->current->data[buff->used%LZ77_BUFF_STEP_SIZE]=d; + buff->used++; +} + +// 添加一个位 +void zl77_buff_append_bit(buff_def *buff,int bit) +{ + if(buff->bit_used/8>=buff->used){ + zl77_buff_append_byte(buff,0); + } + uint8_t d=zl77_buff_get_byte(buff,buff->bit_used/8); + d|=bit<<(buff->bit_used%8); + zl77_buff_set_byte(buff,-1,d); + buff->bit_used++; +} + +// 调整最近使用的缓冲区 +static void zl77_buff_adjust_current(buff_def *buff,int index){ + while((index/LZ77_BUFF_STEP_SIZE)>(buff->current_index/LZ77_BUFF_STEP_SIZE)){ + buff->current=buff->current->next; + buff->current_index+=LZ77_BUFF_STEP_SIZE; + } + while((index/LZ77_BUFF_STEP_SIZE)<(buff->current_index/LZ77_BUFF_STEP_SIZE)){ + buff->current=buff->current->prev; + buff->current_index-=LZ77_BUFF_STEP_SIZE; + } +} + + +// 获取指定字节 +uint8_t zl77_buff_get_byte(buff_def *buff,int index){ + if(index<0) index=buff->used+index; + if(index>=buff->used||index<0) return 0; + zl77_buff_adjust_current(buff,index); + return buff->current->data[index%LZ77_BUFF_STEP_SIZE]; +} + +// 设置指定字节 +void zl77_buff_set_byte(buff_def *buff,int index,uint8_t d){ + if(index<0) index=buff->used+index; + if(index>=buff->used||index<0) return ; + zl77_buff_adjust_current(buff,index); + buff->current->data[index%LZ77_BUFF_STEP_SIZE]=d; +} + + +// 获取指定位 +int zl77_buff_get_bit(buff_def *buff, int index){ + uint8_t d=zl77_buff_get_byte(buff,index/8); + return (d&(1<<(index%8)))?1:0; +} + + + + +void zl77_buff_print(buff_def *buff) +{ + DBG_LOG("buff:["); + for(int i=0;iused;i++){ + DBG_LOG("%02x ",zl77_buff_get_byte(buff,i)); + } + DBG_LOG("]\n"); +} + + + +static uint8_t zl77_get_char(zl77_def *z,int index) +{ + // DBG_LOG("get_char:[%d]\n",index); + if(index<0||index>=z->in_len) return 0; + return z->in[index]; +} + +// 比对,找到了返回0没找到返回1 +// 0记录标号,1记录原始数据 +static int zl77_cmp(zl77_def *z,int index){ + uint8_t pos=0; + uint8_t len=0; + // DBG_LOG("index=%d\n",index); + for(int i=z->dict_len;i>0;i--){ + if(zl77_get_char(z,index-i)==zl77_get_char(z,index)){ + pos=i; + len=0; + for(int j=0;jz->cmp_len){ + z->cmp_len=len; + z->cmp_pos=pos; + } + }else{ + len=0; + break; + } + } + } + } + if((pos|len)==0){ + z->cmp_skip=1; + return 1; + } + else{ + // for(int i=0;icmp_len;i++){ + // DBG_LOG("%02x|%02x ",zl77_get_char(z,index-z->cmp_pos+i),zl77_get_char(z,index+i)); + // } + z->cmp_skip=z->cmp_len; + return 0; + } +} + + + +static inline void zl77_append_u32(uint8_t *data,int *index,uint32_t value){ + data[(*index)++]=value&0xff; + data[(*index)++]=(value>>8)&0xff; + data[(*index)++]=(value>>16)&0xff; + data[(*index)++]=(value>>24)&0xff; +} + +static inline uint32_t zl77_get_u32(const uint8_t *data,int index){ + uint32_t ret=0; + for(int i=0;i<4;i++){ + ret|=data[index+i]<<(8*i); + } + return ret; +} + + +int zl77_encode(const uint8_t *in,const int in_len,uint8_t **out,int *out_len) +{ + int ret; + zl77_def *z=zl77_creat(); + z->in=in; + z->in_len=in_len; + for(int i=0;iin_len;){ + z->cmp_pos=0; + z->cmp_len=0; + ret=zl77_cmp(z,i); + if(ret){ + zl77_buff_append_byte(&z->buff_chars,zl77_get_char(z,i)); + // DBG_LOG("char(%c);",zl77_get_char(z,i)); + }else{ + zl77_buff_append_byte(&z->buff_pos,((z->cmp_pos&0xf)<<4)|(z->cmp_len&0xf)); + // DBG_LOG("pos(%d,%d);",z->cmp_pos,z->cmp_len); + if((z->cmp_pos|z->cmp_len)==0){ + exit(1); + } + } + zl77_buff_append_bit(&z->buff_bits,ret); + i+=z->cmp_skip; + } + // DBG_LOG("\n"); + // zl77_buff_print(&z->buff_chars); + // zl77_buff_print(&z->buff_pos); + // zl77_buff_print(&z->buff_bits); + uint32_t size_chars=z->buff_chars.used; + uint32_t size_pos=z->buff_pos.used; + uint32_t size_bits=z->buff_bits.used; + uint32_t size_unpack=z->in_len; + int index=0; + (*out_len)=16+size_chars+size_pos+size_bits; + (*out)=calloc(*out_len,sizeof(uint8_t)); + zl77_append_u32(*out,&index,size_chars); + zl77_append_u32(*out,&index,size_pos); + zl77_append_u32(*out,&index,size_bits); + zl77_append_u32(*out,&index,size_unpack); + for(int i=0;ibuff_chars,i); + } + for(int i=0;ibuff_pos,i); + } + for(int i=0;ibuff_bits,i); + } + zl77_del_buff(&z->buff_chars); + zl77_del_buff(&z->buff_pos); + zl77_del_buff(&z->buff_bits); + free(z); + + DBG_LOG("in_len=%d,out_len=%d\n",in_len,*out_len); + return 0; +} + + +static inline int zl77_get_bit(const uint8_t *data,int index){ + uint8_t c=data[index/8]; + return c&(1<<(index%8))?1:0; +} + +int zl77_decode(const uint8_t* in, const int in_len, uint8_t** out, int* out_len) +{ + int ret; + int index_chars=0; + int index_pos=0; + int index_bits=0; + uint8_t cmp_pos,cmp_len,ch; + zl77_def *z=zl77_creat(); + uint32_t size_chars=zl77_get_u32(in,0); + uint32_t size_pos=zl77_get_u32(in,4); + uint32_t size_bits=zl77_get_u32(in,8); + uint32_t size_unpack=zl77_get_u32(in,12); + const uint8_t *chars=in+16; + const uint8_t *pos=in+16+size_chars; + const uint8_t *bits=in+16+size_chars+size_pos; + (*out)=calloc(size_unpack+1,sizeof(uint8_t)); + for(int i=0;i>4; + cmp_len=pos[index_pos]&0xf;index_pos++; + // DBG_LOG("pos(%d,%d)",cmp_pos,cmp_len); + memcpy(&(*out)[i],&(*out)[i-cmp_pos],cmp_len); + i+=cmp_len; + } + } + // DBG_LOG("\n"); + free(z); + return 0; +} + + + + + +void main(int argc,const char *argv[]) +{ + uint8_t *encode_data=0; + int encode_len=0; + uint8_t *decode_data=0; + int decode_len=0; + hm_encode(argv[1],strlen(argv[1]),&encode_data,&encode_len); + // for(int i=0;i