From octave-maintainers-request at bevo dot che dot wisc dot edu Wed Jan 21 16:59:33 2004 Subject: Re: benchmarks - sort From: taltman at lbl dot gov To: David Bateman cc: THOMAS Paul Richard , Date: Wed, 21 Jan 2004 22:51:10 +0000 (UTC) This message is in MIME format. The first part should be readable text, while the remaining parts are likely unreadable without MIME-aware tools. Send mail to mime at docserver dot cac dot washington dot edu for more info. --Boundary_(ID_uUCajPRxyEKqzJ8/7Mhlng) Content-Type: TEXT/PLAIN; CHARSET=iso-8859-1 Content-Transfer-Encoding: 8BIT Content-ID: The Scheme Library has a nice solution for merge-sort functionality: SLIB http://www.swiss.ai.mit.edu/~jaffer/slib_7.html#SEC199 You use it like this: guile> (sort (list 3 3 8 1 9 4) <) (1 3 3 4 8 9) So, 'sort' is a function that accepts two arguments: the first one is the list ( or, in Octave's case, a one-dimensional array/cell-array ), and a function which tells the sorting function how to compare two objects. By passing the comparison function to the sort algorithm, it allows sort to be generic; any data structure that an end-user might have to work with can be sorted, provided that they make a simple predicate function that can compare any two of them. I imagine that this can be accomplished in Octave via function handles, no? Just my $0.02, ~Tomer On Jan 21, 2004 at 11:09pm, David Bateman wrote: David. >Date: Wed, 21 Jan 2004 23:09:52 +0100 David. >From: David Bateman David. >To: THOMAS Paul Richard David. >Cc: octave-maintainers at bevo dot che dot wisc dot edu David. >Subject: Re: benchmarks - sort David. >Resent-Date: Wed, 21 Jan 2004 16:14:17 -0600 David. >Resent-From: octave-maintainers at bevo dot che dot wisc dot edu David. > David. >Hi Thomas, David. > David. >Well the fact is I've come a bit further in testing some sorting David. >algorithms. I've tried several different cases. Firstly, what Alois David. >said about sorting IEEE754 as integers numbers made me starting David. >looking at radix sorting. Then Paul Kienzle strongly suggested the David. >Python mergesort algorithm as having great abilities especially for David. >partially ordered lists. I've taken the Python code and implemented it David. >as a class and use it to sort either directly on the doubles or David. >recasting as uint64 and use the same trick I used for the radix David. >sort. David. > David. >One problem I have with the Python code, is that when calling David. >"[b,bi] = sort(a)", I have to create a new class containing the element and David. >the index like David. > David. >template David. >class David. >vec_index David. >{ David. > public: David. > vec_index (void) : vec (0), indx (-1) { } David. > vec_index (T v, int i) : vec (v), indx (i) { } David. > vec_index &operator = (const vec_index &x); David. > T vec; David. > int indx; David. >}; David. > David. >template vec_index; David. > David. >bool David. >operator < (const vec_index &a, const vec_index &b) David. >{ David. > return (xisnan(b.vec) || (a.vec < b.vec)); David. >} David. > David. >This is due to the fact that the calls in the class to sort the David. >elements are of the form "tmp = *a; *a = *b; *b = tmp;". This imposes David. >quite a penalty on the mergesort. I can really see another way to do David. >this without writing specific versions of the code for all David. >instantiations of the mergesort class for with and without indexing David. >(Ugly)... Any suggestions are welcome. David. > David. >In any case there are 5 test case, with and without indexing David. > David. >1a) Matlab R12 "b = sort(a)" - baseline for unindexed octave tests David. >1b) Matlab R12 "[b,bi] = sort(a)" - baseline for indexed octave tests David. >2a) Octave "b = sort(a)" - orginal octave code David. >2b) Octave "[b,bi] = sort(a)" - orginal octave code with indexing David. >3a) Octave "b = radix(a)" - Radix sort test code David. >3b) Octave "[b,bi] = radix(a)" - Radix sort test code with indexing David. >4a) Octave "b = merge_double(a)" - Mergesort on doubles David. >4b) Octave "[b,bi] = merge_double(a)" - Mergesort on doubles with indexing David. >5a) Octave "b = merge_ieee7543(a)" - Mergesort on IEEE754 case as uint64 David. >5b) Octave "[b,bi] = merge_double(a)" - Mergesort on IEEE754 case as uint64 David. > with indexing David. > David. >I've benchmarked the matlab code seperately (in "matlab.log") and used David. >this to benchmark the other four versions of the code, with and without David. >returning the index array. All tests were run on the same machine under David. >the same conditions. I also trying to do a bit of averaging in the tests David. >to remove variation in the runtimes. I attach the code I used in the tarball David. >in this mail. David. > David. >The names of the tests I used are the same as those in the Python code and David. >are David. > David. >*sort Randomly distributed lists David. >\sort Descending list David. >/sort Ascending list David. >3sort Ascending list with 3 values randomly interchanged David. >+sort Ascending list with the last 10 values replace with random data David. >=sort All values equal David. > David. >There are two tables in "octave.log" for each test. The first table is the David. >runtime of each iteration, while the second table is the relative time wrt David. >Matlab. So as to not bias the results against Octave, with its problems David. >with "for" loops, I've assumed that David. > David. > a = randn(n,rep) David. > t = cputime; David. > b = sort(a); David. > time (cputime - t) / rep; David. > David. >gives the runtime of "b = sort(a)", where "a = randn(n,1)". David. > David. >The basic result is that the radix sort compares well against Matlab David. >for randomly distributed values (1.10 times the speed of Matlab), but David. >as this sort takes no advantage of partial ordering, it breaks down in David. >these cases. The mergesort with double values is faster than Matlab David. >for partailly ordered lists, but about 2.5 to 3 times slower than David. >Matlab for random lists. Interestingly, although merge_double is David. >significantly slower with indexing, it maintains the same relationship David. >with Matlab. David. > David. >The clear winner for me is the mergesort with integer comparison of David. >IEEE754 values. This is roughly two times faster than Matlab for David. >partially ordered lists, while being only slightly slower (1.29 David. >relative to Matlab) than the radix sort (1.10 relative to Matlab). David. >This algorithm is roughly 6 times faster than the current Octave David. >sort code. The performance degrades slightly with indexing (roughly David. >2.0 relative to Matlab). David. > David. >Note that my test code, checked the correctness of the sorting David. >algorithms, that it sorted NaN, Inf and -Inf correctly and that David. >it was stable. David. > David. >There are several questions to answer before this might be rewritten David. >for inclusion either in octave or octave-forge. David. > David. >* Does octave support any platform with 8-byte integers? If so the David. > mergesort class could be used with doubles in this case. If not I David. > can simplify the code. In any case having mergesort as a class David. > means that other parts of octave might use this class (sort char David. > matrices for instance). David. > David. >* Is there any other way to win back the speed loss I get for sorting David. > with indexing with the mergesort class? Maybe someone could look at David. > merge.cc and oct-sort.cc and give their thoughts? David. > David. >* Is there any chance of this going into octave, or should I be targeting David. > octave-forge? David. > David. >* Should I bother implementing complex sorting (done it for radix sort David. > but not in the attached tar-ball)? David. > David. >Cheers David. >David David. > David. >Daprès THOMAS Paul Richard (le 21/01/2004): David. >> For what it is worth ( 0.02 euros?), in the course of educating myself about David. >> the C++ standard library, I did a test of the sorting capability of David. >> multimaps. It turns out to be a bit off the performance discussion, in that David. >> the timing is EXACTLY the same as that of octave's sort and about a factor David. >> of five slower than Matlab R13 on the same machine (not very surprising, David. >> since the standard library uses exactly the same algorithm as octave!). David. >> However, it is interesting just how concise a routine, exploiting the David. >> standard library can become. Please find the routine below. David. >> David. >> Paul Thomas David. >> David. >> //Test of auto-sorting properties of standard library multi-map David. >> //In input vector x is inserted element by element into a David. >> //multi-map vmap, together with the input index of the element. David. >> //Since multi-map insert sorts according to the value of the first David. >> //element, reading the map pairs back, using the multi-map iterator, David. >> //yields the sorted values and the sorted index. David. >> // David. >> //Paul Thomas 17/01/04 David. >> David. >> #include David. >> #include David. >> #include David. >> using namespace std; David. >> David. >> DEFUN_DLD (mysort, args, , David. >> "mysort. Call using \ David. >> [a,b]=mysort(x)") David. >> { David. >> typedef multimap ddmap; // David. >> ColumnVector vin(args(0).vector_value()); //turn input into David. >> ColumnVector David. >> int vinlen=vin.length(); //number of input elements David. >> ddmap vmap; //multimap container for x David. >> and its index David. >> ddmap::iterator pos; //iterator for the multimap David. >> double didx=1; //double index David. >> for (int idx=0;idx> by value David. >> { David. >> vmap.insert(make_pair(vin(idx),didx++)); //insert value,index David. >> } David. >> int idx=0; //output counter David. >> ColumnVector idxout(vinlen); //sorted index David. >> for (pos=vmap.begin();pos!=vmap.end();pos++,idx++) David. >> { David. >> vin(idx)=pos->first; //sorted value David. >> idxout(idx)=pos->second; //sorted index David. >> } David. >> octave_value_list retval(vin); //sorted value to output David. >> retval.append(octave_value(idxout)); //sorted index to output David. >> return retval; //return David. >> } David. >> David. >> David. >> --- David. >> Outgoing mail is certified Virus Free. David. >> Checked by AVG anti-virus system (http://www.grisoft.com). David. >> Version: 6.0.564 / Virus Database: 356 - Release Date: 19/01/04 David. >> David. > David. > --Boundary_(ID_uUCajPRxyEKqzJ8/7Mhlng) Content-Type: APPLICATION/OCTET-STREAM; NAME="sort.tgz" Content-Transfer-Encoding: BASE64 Content-ID: Content-Description: Content-Disposition: ATTACHMENT; FILENAME="sort.tgz" H4sIAGHyDkAAA+w8a1PbSLbzFf2K3mzVrA3GqPV2GLJDMjBDFSEpQmYrlcylhC1AiSx5JWHI Zvjv95x+HEmWIGZ2gN1745qMZXWfR5/T59V098vwU3QaJ9F39/gxuWl6jvOdCR+Hm/htea4n fsOHm5b5HXQxbdeyPBPec8u2ne+YeZ9M6c9FUYY5Y99NTsIymobpTf1OinIW5Q/B0YN+wiR5 yvJwEl8Ns3HJplF+Fh3HURT5rlN7M8kuTpIIXxhG1ZsgjZXpJ3iBE4mtZzV8ul0DEch43IAZ V6+NNg9PF/laoHcT11X/RaQaJRBk0H+9yPKy8Xy+wN76T3s7OzsAS3DQYa5+tDhgmmAlNxqE ftU5hlr/hd4LCOsDWG4E1L2DccJqPPZ8/PZ52M80LJPwZJhkZ/dH42v+3/dd5f8d0/V89P+e 533z/w/xOYqKkmWnrDyPGLqNOD1jpxfpuIyzlPXwTZ8tfl5uH+1vP2eH3DIM/P2BsQPGfudD 04zWTIsx9WTTk0NPLj15jBmC+gfE8buxisQEfsDkm9E69rWG1gieHHzybXgCnPbQw1ag4w45 PnHA9KEOzT0JzYe2L6EBoyuhAaMroe2hFSjojTq06WtoTZsPPY+guYY2NbTdoG0SbU7Qjobm gYYmztfq0C7X0IGnxy0oinGbinNn6LkKeqsObRG062tobmna3kjT9n0FbSyj/su4PGdxOomu sPUB1G9JtbliyJYcCDCtxOBK9oFOMHQ61e9ZHUJ0tBD5SAuR213qd0iBnqWhTa6FGNhaiKK1 pf5KgZ5N0CZB0+TxOtRv0eSxhg5Bj5QCHZo8bgXdUP/I1dAeSc3ztdS44tyTxoXQYP86K7hP H3O7/7d8x7Up//ctmf9b/jf//xCfjVXjRTb7nMdn5yXrvegzC/TAfgrn8YQ9lxIBL3EeF2yW Z2d5OGXweJpH6C5Oy8swjzbZ5+yCjcOU5dEkLso8PrkoIxaXLEwnG1nOptkkPv0ML4wLcCK5 8DVllE8L7Xh+PnjLfo7SKA8T9hoS0XjM9uNxlBYRC4EuvinOowk7+YzdjV2k/kZRZ7sZYA3R X22yCDwVEJhHeYH+yxowIN8LS+QwZ9kMe/WBrc9GAkOjjsP2CKuBTMD1CS7PsxnwfQ7YYGiX cZKwk4hdFNHpRTJg0JP9Y+/ol1dvj4ztg3fsH9uHh9sHR+82hffMoDWaRxJPPJ0lMaAF7vMw LT+jFF7uHL74BfpvP9/b3zt6B2wbu3tHBztv3rDdV4dsm73ePjzae/F2f/uQvX57+PrVm50h Y2+i6CvyM06F/EFMk6gM46SAob4DbRXAUjJh5+E8Aq2No3gODIVsDDPh60oxwiSDQCDCQlmT 2yYrFEOi5Hjx6vW7vYOfgc+9U5Zm5YBd5jFMjDITfVCLRocWB8wdsaMIhBSx10k4htqFvblA QNs2B+x5VpTY6eU2Y6bFOV/ntukP2Ns32zC2vZSFk0ksopei05xpr/cHYroiTTDnaVyihqFr EqefjPpo5PhgrrBXM9DcG5hBwItqHODEnESncVpNy3q3vRR4gOGAeHuXl5dDmDppIZqGWX7W N1Y3DOOvcTpOLiYR+wGKNFDEBnwNz5+13yfZ+jScAbdFZ/M4S0/js86mf4LcbkKJtWpnG6gh XAek80brk1qN+cQwSlQQ2BD7YZyERcGOnhniwZhH42ORKxhfDGm646eQJdBr1ptn8aQP5Su8 Yj2zP8DUAl6v8z77wq6bfY/YHNvB5AhiThBxC+CHo2fse5B1HpYw77dYD4YBGUaz/aq/CTBH +BYfBHbAt2lcb3aOqwld//X06ddpoRgE41vsakgkgX38LekyMMHyIod8axUnILB3jbPjFOYX U4sOhrGxgWZ0CYacpX8rpeVGwmmffEZvm5bRGcwQmpTQE1wy9AQPJa10nE0iRJsi3p29n385 On7+7mjneO/gyPhrlOfoKp8cZCxYr2Nk5Wdwe+EcnEd4kkRP+tA3BX9uGBA3S3AKcQqmA44w LeIzJNzEzHaTLCx3k3jWu6nHqZTRTc3TsPgEwlrvNd/3e6fs2TPm2X32OxNpqHkVmM3P2/39 mnRP2f8IZEK8X+F6789iu1exuc448nonNmk6VtPqBoLPYPKeZFli0JT8oT0lb4Jl34cDZqyg FJcHOZEC0HM3xNkNRE/wu9/kXnqWY3Qft/Df2X0JTgD0r1ECcalDWnJhaynhqK5CFje2LQz6 Ki7SMO3JMbPff18Ug5SDIC1RHI+z6QyDT0/+ZkBMPd2AWqFFlP1bxEoD7WztGIqQWsOSFcA8 TC6iY0i5SuH6RIHRO8wuf43GKDn0gJDvwJAUq8fxRLg5g7UxYBf4pf1slETTKC0LMAzAMhyH s3AcQwbUEy45PmW9qscWmIuw6y+GXHXA5jrFFYm7B1a1xSr+CMUAK02BGD+qs9mXtGuvUdoV m0xEFJxOTX6eVewsuGaJaGOVobsQWQZGUJ01ziVXRaZSR5CCmgKQlKSIBNeUzyBTUIjYqoAb ZzkkZlCb55AyQ91NrRvq6SbHszqDERorN/qt1T6KHvLCErLPYxFSSUiYLfZEQAQc5iZ8/UA6 g19rayD12fv4N2glB8l6+AZQ3KSmL+hYMHwVODCY+iEkziWm35ehyDYxLcSVBTE/gWGccYXO mxUwi65mCdQR0A2lU5vbTAZq4BqSuKwUqV4xi8Yx5K3jsIiKvxuI464+RblDxZNe2RfwmwLh qxdH27/uHO+/erG9f/z87e7uziEkJ1/FjH52ZUUpcx4PSL59iXYZFchpuKJxgPiHMsNATWw2 G1SuEbM1xlXTtSDUNbKhNPYOtir7ijH1+neZVpOIeCemATvmdVs17htct8wMSyuV3N9uagLL KqtbXLehrUgru8Ow1Gj2OmxCsnwk5z38Ky8zcDYzYAmQiHpHTNiD8GDIXkFCoutKVIQsTLC0 kKyfRGdxmqIJNAcMZbY0ClH8qrIHXPsQM8aqVlVYhIpVJ8I4gJLtCtPE9KxgF7NhTQhoz0km pskxTukTwNhT1gRs9xdVi/L6RPokM6jEqJtU2Fudq2iw6JJUt8tzLCZ1OJy/B7H/1q+aO81Q ooY6oZzO4P8i9SIIodUGXx+lej+CeqEvhyeh2hUEl6rFaflxSRQUMtaV1Wl0ICKAn7//KKb+ +49r8TpHc11hCr8mhA1IbOX6doKLlAbsU5uNTSYoIBPQ3sFJpctFXnD4n36rMSK+ZKxkMu7G wj6vle8XWZh0+MukfKzpVYXL7XBHs5Y3+uYF/tO9wL3b/R8zwbbx3cW+Fg2ribRhR8parlVl 8l+YGlGdQJmCqmCWToEUhsGfnubA/yFJuGuiU2P/wfIcyekfynTabrbTzy5hTR1lIqsJQ4dL XZpKoA5pNYQlprYsHyVPnQXWtWG0aqzrWwrO6ZVi6WVY5uCLvp92lppfrzRTXJKbDvPsstDV Jb4di7fjLLmYprJB1Z3YHypO9v332OkZM+9QeypeAccAgG8uO6fLFp3AzLMuXrorz/oMmLb0 v0y1eFuteM913f/Zsi7Nlc9Qs0O4EzlDFp1JLXClYx1VlMYVyj+4uqDBIeAvlfAwivcUFBe8 XZprP6eTyJpfbmc+VY8F97xyTWP7SiFKguyUw90SPymKe5NFRwZI4ulXyXU8+Njy+zV5/HuZ Ym2cjdzubtliDUudwnIZY1NyS2SOSnydOWM9xEE9gt5K/+7PZPtCpiiKNp0s3mTRN1SIK12p YCJVnlB5mEili9EhtUSXiMng4zJYwL9TRlnD9cXQHmROWOVTrVLUqUMyoHpRNBNlkXd2ciCK w4FgpMGBmsqEHnmiUvEmxharxkW+qtpRs1TN8BlbQxa+ku78mVXlMr72P9jV3rzmqiXfWTX/ V7jO28vmbw7xz3eIt5bOdc/wsXIBAslH8kj1tatudA08SuOd+JqO5GYn8a2Wplr6z8kt/2iW NxUJzN1yu+7au+GfluJj2kyeZD19e1p114XL28upP1pO36YQtqCRztJbyEpH4S7TELW4bO8o Om8oxBcKyp92dt8eHP+0/xPrNQ60DMD1nhXABHyBsQyUJba666yq1Vsx92R9dZ2VuI/4NGPw /CH9YPwIDOAek9OUfdnPwgnuMmG7agvyNfvy/sd5mH8prgdMPMTX4DSupfPtiTdX133EcygH V21iU416n1pULefRg9iBdya8FqKI03EehYUIDhjPhozt4v45tLJxBCP6EffQfEHa17JH0UQM qUIUjs8Rl1xjGOIj/kM80VWIu9oG+t2P6oV4Psuzixk+yZG95wNmbeIORnuT2QPGfxODFOr9 EYLfRVJ+uWaMw3/0Hj8W/Nd4gVueJTEIcERE/KqRx38QYxsDpG3gU/CfYQLJgdzvKNajZ3k2 uRijkxXSuZJDhogcp+Q88xiCIhhcnl2iI0AR6qBbl5jeeh5NEIlEpyS/nMTeg2ZEDnEX0eEe hJb0ugRYk+ECiliisDtQtNDaCu1yakBvEf3zAmRXbWYQW0eVFDERKi7G5zJdEwJt9EY82AcX xqoNrGLGShDcTggdak1KVwgxJNbINJ98bdVNL7CByQPKLeEBhkmUnoHt1ZfZZPtfWps7ZpA8 lscXRXgGicsTVOST/q3LZfC1sDCISYf0OLh6trm4HwVZUoz1zIoj+D2Mi2Ow++RYbHXr9Zuc qRg7lbBDOT8VytoCG+L6CxPb6I5xeTPSKQk20EKk2tbS9Pc3rEyq1mpFeg7yGy/8BWQxYI4p YM7l6vK0Zw7iWphVQVCs0R5TdKllUpu1iCnDYgOMVmini1DX7YVMJVyMhEl01ZSv3nEoIsdT sX88zUppwwpA7j38HKm5QNnfWR7PouPLPEvPBM5jVK2aNSL4SLW0w93GqrG5ucn2szGM5dcw jzHYFE/Z6qpsmIL3e8perK3Rm510Ipshf3/srfr38pEm8pjn/7hvmY46/+H5vinO//nmt/N/ D/JZ5gTYPR3z8oa+Oqg1GpqePiunT+dZQ0cdsLKHjgOYzOYxL2doK2hXns4DaH/I1UEthYeL s3CWgt6oQ/uuhvZHGtoNJPRoGKhDYhzPz0no2jEvd+ioE4aepOPgYTQz0LRNU9Mm6LU67RHX tAOi7VkEbRG0qaC3GpxbHdC+5ly0Ss65gjbYQZZPwyT+FyZv8RQziDPI1EArL8Xx33tSsI0n 0gQL8OTJJweFLJ48PNGnn9y2gm088KlgOD2ZCo87dB39zrO7FOxQuzMi2j698zVnntNWMKiI evr0NCIu3BFB87aCbZwUqp0THYfe2QqPOOfYUjDIytQ9fYLxrEWK1nCkOb/7Mc57M2nX1SYt DtdKk3a0SdueNmnb6zRpMgyP66lt+mTSNpk079K475FJW2TSpjYMj2vDMEddJi34lSbNO0y6 MkqvrXFnGHQYZUDuxPNb7qRh0uJoroAeeYsOoWHSGvqxTNpCIauJaNLUtl0yTzI102wr2EJP raFpQnN6F1RG6bUVbOPRXNXu2mQi9FS1mrytYBungqbDiUuHKBIeq8Nnw9Q1tdk5ZL4+vbPJ KM0Onw0w1G751FM5Qk4Gz3GiLGXS4raU+wrMICA6h1ydYnZdfZLYtvU55FHH+WtbnnKW0Jyg R/oU88jX0HR6u6HkwCFoU0N7dPbbNFvQdjfn1RF4zyZouwXd8Nt+0DFuOkGtU5PauBt+Owja tKtx6+P3LqUmj2jFlq1nHFe2O5JqFS7OoZnJO9y0uDdBz1yunzSMuK9Az2Yd1hsK1sHTIjvl FJgB2tPvKCloKFiHUU4pBceJsmCHAK2DY8OK3YpfvjhGjo5WPVmdgbk2Mod6WosU+dDWAWYp K36QyOzIyOIql7mu7lRQszOQ1m2JuN1h0w7NbWVh8m4BV0Obo9aNDBv12Gqabdo6ZQ3IpgMZ rfliZK5Bc4Ie3QLdTLYdDe2N2tA6to4qzrfqtMWtCYu0Fee+jPqWeDIf3aZ17BUJl3oyaXbW bLojMlcx06KYyCkmWpRsW+hCu2ya7NemWBZY+l1QJbydNl1Fz8qzBEQxcAm6I/WqcFaVHicv UpeKF3RFZo88oUPQptnGSJ7wKzZd/0vIfQVoV15i4uIE5qr+HFGA5vLOF173cs0LUkxbX1Ji 0h01pk3Qrk43battzCM56T2kOKJk3w00Fz6lrfqqlKauNeeAnQoE0yHaNtH22sbMyQ1xLKwU tEecB1RomHbbmOuc+77mXF8Ro/htpOuPWDmbVPm5lB5XCSwn0/I7AnQgBcHRL9kq13AxuVZP eno4Uv0tBfNAQ/tcw+grgxzyk0qVC97aqiWzulb3hrZDtEcajz3qUrB2XR46Ej0GxY8nL0CS 0F5bwQGNzMOwrHrqq5JserJQpktdgNQw5geJ0z4t7yhDtOkiKoHdDfQYeMeaibqpyFVuXOWg XE1sS+atllqD6Lj7aER3H41sbV6jQEPbtDTnu23NixUXfWlXoGnr6t2iWGnTwl7TjQd0exGn e5dqV37RxVmjDtPm8pYkyblFnNOVX3ZAnOtLux7PtK2q3uVUu1L27FPccztMux7bdRwfUeIz kokYF2mR26Vgm3JdPtLQgathrJE2Oa8jEasWnDjV2ryWLZgtfpqmrWkH5FaqmiOQRaOgrZda Fny3S+6AnJJ+cmQMEE+ciqtlTFttcLivQG3hOqPKH22P8ke1JuXQmpRXCfxDwxObOmBpux7J oCz4cE3tFYKOQB3Ie748IXBHQ3Oya5tWlRyvrWyRMCqYEdH2KGS7joYe8S5lc1radyjgV6tp fhWo/bayA+mpJec2cU6pSuUNnceupHmtHtVLykK0Og+lfNYata3Zp0DtySUDTssr4p1H7yhg NRTMqad2ay7ZnisXWoRNdLlrTnmzT9irhQ1f/kVG4OZ+W8E+ZpY6pJuaTjCidIEs03HaCvbJ SquRORTwHVmWipAdaGd/J2t+kEjtytTRFdUfrRjbVRqtBlFNkaYjDygJ98mqgpGOd9VFkV5H Rc1rWYJHduFTrPUcDW12qN6WYaJxQ6LyIfKaSYJ2O1Rv0Uo5lyvuMscgzl3lV2r3K27dwDl5 Mp+u1/QpQ6Ew8HgVtUNVbbVmZVE1apK96zXohVtIbYqHvo5yOvUZybSK0xJES8EWQY8s6jmi uOkQRrutYIvKB+DC0Xg41xNSrzyPbnDeumb26U8uvnTjjTFUiXnTeQeUhFfJfkBeySKv5Gra j/038P/Pn9q1bvdG4/b9H45r+w7d/+k6eP+nDa+/7f94iM+3+z+/3f/57f7Ph77/E2xuAhZU ZgnAwPxKQkhf2SyEIHqaZ1P2+jNMmvRvxUBsyJX++dEuDa2u/jx/AhzIYbO93f2jXjg46cst rvpeu60tdvB2f5/9Xd9Zx54yuvMuHOAldrgPkx1GaHy4gbyAqRWhgkIxWBTHDPU+kKJIMnYx Qw31oivgpwCZ9tl5PMQTVV23dWbxxKgf0cBrOnNJ7FiQ6h2x1SQbMPg6j+W+5vX18xh3mKqD U0DyByDRZ42NwEesZFsIqvclwyO+kKDixTluxS31z7W1qq+mgBtkr7uvGe1i/CROw/yz3HBb Z1t8YeAq9aWBZ7jVO8fX4I1WZ/Av32w2zOJ5VtK+Z+R9iykUklvxQ3QQW4s3ZasQxaZuXpAJ KLKI8Gwr6OdSnLqSXIFrRB9RVNfV4d7hShx4O4MiJ18I5lCa+WaFei+d4x7dtCyeVpfjyZ7P tlgIHhjmynsUStIfLvYAvnWPfKAGWuuE2+yLCMxggu5+Ho4vsosiAUvOcau43FQvgCoYPZRJ xtTebjx9l7A11uvhabekj1d9qpum0DxYT7CC+lB7vnHcs83m1mqUzGwND05dM0VBz0MYQ96v CeRInAHQQgH+MAqdZ8lkgGc3b5AMhmGgJFsroSRaKDVYrTUYfwJ++yArkUcZ8071sbq8fpJG HDsoFTyeLZ5lMTbQlUWncQ42/b/tfX13E0ey9/3X+hQT9gRLtiT0bmJhNiSYLOcAyQGyu/ca X5+RNDITSzN6NJKxk/B89lu/qn6bF9kSIYRkpc1iaaa7uru6qrqquqs6mRB0f7yQ1X9K7MBQ dxMa6rUsIkzk+LvAoWwETr6ahCR94kuJx5z6F7RWxfEUr771l5Dxh7T+wg8wDaZTKofqU4RF UHPvqJaoG89f/fNbrwukvwt2qfM4Zb5MqN8021SL60PMo49J3U4zM8HMECpN9kNv0qeuYzI5 b8ZeecaJurQ4wEQKkwmjmzPo+vC5ilECbanYCLUuzZeRE5kK9MdVExvD8pEnk2QSTYsSTyUa 7ZwmIEQcB613NCHza3p95xHA3QEyuCGaUdi3fjJEGBaBT6hSEEHAYokT43kSnzROvQfg0ZOm /tLiL/U6LazxPAVsFKwB7aEC9lDBeiigvolp1SNtcc8BgnkPOJq2oYdN6J/S7CG2ktU4etfU 70h0EinVOaoq5CiiBQEiNCDZcYggMKEiud0IlFVVDD0Ph4soSIxCMELcWTwu3bGdYcxFQTDi GFEbYjMkiuEORV7ijwOinrlZw2ztksaHUfwuw5j6y6iiToUTTngqPSGUkF6wRJi1Za4oFrYq GS6joZ8TdlTANofxkChT1JR4NcYLEIXXHFdRLxWvjoSo3BozJNVrcUYkk1lhEFrizJEsNByr wmuEO30cmWwXPLu+YIFluSeEL1E5iA9q8TcRktzoHtUgZkrH3qTbaKbSlPLiO4n3kcEgNosU QO3vRxUtoYtaYKmbEcKDeeBf5INYUr35GM1m27FhKkZIIDplIXo0aZukwZFMTUSlpem9CK4V hccc4C7h630ln3U0uwrFS0pErIqMrKwmEDp2R1rR4MPplCw4ahzrYKzE1BhEV9Lfp6R+p4PN SOKcnBNrxLMzNiLLFVoghaCJT6a0WFwNg9lCNZiUUi2qVsT61LIQP/LteGUaIsnpSv20VLrj M5dmsCAqe+QEzbHoViLVJ5lUB/VNyeSH7fbQaxAX3XlLNC3QInEZozCtwAivi0Uqy2ACfz58 WyUJ9QCEHWExjQggFuXhJE6CeYmfhnr1o7WPwx85XlAE0NhPZA2E7F5GCVuegZ4MCSpTclsy dlDbjXo9stF+ImD9k4saxDSTA3WHfhNWZgRHcQtLrb2yj6z6WBXDaAkxST2C+EGyA/8kOsWr 2cR5A2Pt+39VSwDrKAOClos+yZ4qF1DDw9J+YbUB1uGVaTmDWTkKSkxsOrkCiSESH7ULXWgc E928wyDS4gyrGYsxsXGNDbS4WjAXcvxwLNMyDUjMjjYReIpaQc4k8riDJPJ8kXiR/MFMWokX jxOdQgxDcH5esBzzEZCNKnisSmihKF9ZdimpQC1Ro2lJR8qdfwIIelJJQ5J+Cj9USZkhbc/q r1KadE/VXIoY1Cs8zmmvktocBab+lXQuIuWVe79D3bhLhAHaItJ4Sy1jtTd1lV6KWg9U9YzI 80/QqBpgOszR4oXxp57KEwH5ABnybfo+WUj4DeGygs7xZNCiOwbZIKXGjtSXvmRDF1GjCCcm GUdaGtv2HurBlTLwrSY+96OEaW3gDy/A8PF4TCoMVLKJGP707K7IHGsEKRQ41KJxkHpUvP5k R3PqEAmIeRWN1LxC+qgZ0lmHRhT6mppGGkwh0LM3IxDIJDx1SURPQ36Iuu8yYXkKWkk9t1OO JT5DPB+DDGRpuwzWogdkZHIESppL7PhdOjHPLyyp+F5NU0+Ju/WCxuifFEkG4c6ElQAj4ZN4 Goj1rsw2ph6zKOsuwcdJyumYllR4WeU9LTTQS8hw8h7HyLnCHguBoFdMtRur7Fbbs8wShr6x tc34IaXKYkYbxKonDzwhLJc7mFotPtkqx19D5sY6VxW0wJoacWVxP90XQsdb1UUzaaI0qnL9 lIyZnupi761ix0MQ1e74yh8uSLmahGTLussQsYNSk7SxDZj+hBhjdE2vsACy2nfSOIxOqyVa rUfJrcrbjWoVKxu/Vf84krEr/YNWZtgixgZh2Mgo4Y2WM7JifelogvtN4McTtzkrQ/RfEMXL 87feKByPiRSpdSSZiqRRsdyTRTi8YO0m9u48uKP8imGCHFDKMb+rPABvfUl2EGsdIxyX4H4m /Qiu2ziCL2G5CCOx0xBkTlqKJH+6I0qvovC/3/HGE//8AxQMUYf/AA2DG9zzcxqGnqsPWTyO UrX/oMVDBqZWkM9DvyhE0++hX/wRC0uhDmL01KMPVVQztPSHKKpil/CaU6SFpPXF1LT+GbSQ j62M3qph2Cn9/DSMdN8+uYahKG16WinQGlJKg9YtVukhR64iUqhheN/GEdQI8W773nP4P18h Hc1uIgw1X8JTstHumTpbF4ULubuPF61pUvfRwaQOMNjKvu6rxyQMyPRHYuzjl98dv3r96PXx 2evj5z+cvXr6P8eqUKQXL/o+DaMzJUKoztMXZ989evbs+x/0kHi7H7sWsps7ncHdH8+vvfid 3X11RsouGd4JEDcP+21HJWRufEur/3W8hC4xivXS72JJXBVIeGUq0rcxNtAXqIwsZnu8gfwO dAb1Yq72vN2eEVVOronQNkYyoBEMB8+cPgi4/iKNbFncuXV+X+l/tEkRtB+zY1prZe7o4IHZ hYN8lxOoqZ0T9qDpawIxdk87dBpw1ZACOYTfHfgVJVGcNwxRbioklJ/H0NBWYq5I2RLEnQcL 4I31K+qZxR1+gXMsDlIeaaZBGu1jvlURWaCozBegIFIn4eofQmMeXg8nAbv1+IQEZ8yajDiN KuuwIozM5YxDuPHfyf6Wch4OCOyFFT3p2fbcyYMXvkIkiI6o7pOcC38OSE6WX1fMTWk86Uo2 pSYYVfq5Mb4vahWiBZlUmZITP+ItT8I491HVrjUlU6Da9mfyOfvu+PXz4+flF8fHjyskBeVv Csve32neD3feIC36TmqOuLAcAmDGY/xEvnUjuk7bmW/z90WDFWUGoDZ32+edfw0lu8bnCODz 9ZnuCIDj+xVepwb28f7oiOAw2T5HEc53x8djxJM6G5Cs3pv5Vfk9I93Dx+LiOElVwlhlbwES D1uacQ/cUGuEqmiwyrvJ53Xg4nS4CPtiY81EfOIoZWltzC+TGHQ20yaJzwbKbKB+DqxhciGX pWInZqFNEvFoE6nVZHU6X4aTxbUoftizuORDUxGRQaR0Ml46XTGfEvvmUEKKuCIi7wf68gOH GEHH0+Hsmjmg6mEMhFHNI5pF0F/sx/r4MVNS0Tc7V4v9fWzgzgb7+yhQq0UDzVhEJUdHul0S SLH3CmgXppIkds7thFwAJ+i+cU5O9DVjYtw+b7CxaAWy/sYEwqeYH3nv4kgIdy76oK4zWFnn m1ydktICH8d6j9OH3kQ9eUdGsOQiVnODLRTsWVbEAF5GJa2kcz5AlnDvsJdImgKOjUQLXsYc tdwZX0rJYdohetJZ73I43oG+JcPiHw5W8FMmYCczAzv5KVBFFIIeHjlkVbjFpo2YfLd80y3f dmuQ65Zvu+W76fvciVcF/HU79d5M2vcyD1g836nd/yRO4V8EjgCTswrXetYG2Hp+uzyHIoOd qFdEAXOpIFIH24BhtAyc6o51tufQQ6SOTqIvDjEMAtMtt0+GbKJrCKs0iezvu5yNJzgwI3NB k+CIgZqLKEnauJPVB11YOzBrU84VJjuRAFUPWR13DF0B25iUC8mvq9wE/ETEivIB8Dw+Ib1F WfdKuIBQBPRFRrZwKRYv+0fmpruZ7/6K2F7Sv/K0k6MepoXIPzpqgBLCKRn7SYiVLGLXlUq1 rr1dCsiejX8JE2d+xK1mLoCmtWA5DUwdfYI1THRycm2H2n5msOMy3/vSTp63FfdmeTddOTV9 7PXk9QczGA3U7A0KZs9k0XTnLT1r6vyPnrRB4aSlp4wWdPOd+mym61b5k0GArxHgawQ4M+3O suDzvTY0raywFg9u+h0UPFdHjFKMhWVhFkQcFYPphGCeBD4fZ3KEBZyvii9v4izWD9UYD1n3 Uys8dEeg+dCsfbLs5bikYAk2+TcBix4wIg5L5iQb7wbr3X1a4Gb+anVKdKm61p6z000zVqQA nESDU5klpz/GwvmP1T4f/tHa59vwk2qfBGDgJ4Hft98HGtrGWulglVaqNc4BpnSAG2Xyumox qXLnjLLK3TP6Kksq+ZGCKwsOFhp1qopxVKsJuddqSqv100rrTVrtoEirfZTWanP+sE2V2w9U b3+jgrueiuv4nu2AU3vXVslVyoyqlkW9ep7SLFkLTGuX+BgNM78C7+QWX11mhaK5Y13Yzi5F 9noBt7eDVG8H6d76hb0dpHurqUb1VtGMU2KFpp7t63tnon+DUvwR1OLfrhjnVWOHtPLqsXui /Bbt+OZVfEc2fvIaMgsYUZKxcFT6t6tUF56SLhdpc81qSRf5iysgAR3Fl6VU6re7cu83oTns N9PKmufc8Rplat/OHu+NkZch8AL7MmfIPZIs6YVaKgtlUVSjwQYYHBgMDj4Qg4McBrXixQgc ZBHo4m9QgL8bGRZWyGAzK+TD7JBiSyR7TZJVxNeabN9OdtZqX6XM/wZ1/Dcr5Lep5BjhCp08 pZIPcip5rcxE6pDtbco5k4Gjm8vZTlc5H2S1zfE8jhZF6rkm4kj73sz3YvYvMB32lDJFDHyz 5s7XgS0j7hSp38MLc0dGyKI+3G+u3Iuopo6abq7F+gu5fkHUVaXQqh5rvTYyv+Qch/ZEzuSc Lq4qwhyhUJR/NQkiVwM0b/abTrWil1xRZvNlMIzno4KYE+LkAccvAn98gDzUZ3/a81EN1pns a2DpIwlQFbMkcaJytBGHEmU5Mh0m4PUwuownl9h188Q44kM+jLaKPjK9nPMpH17o95vEmcjr gLu6oP1F1xzQ4OyYZBEj69O+Zx23IRidt7FqXruibV4XL1lMtU5FTUYlja9/8TY1H2EfqAg4 dOjvnnfsXFrj221BtVE0UJva4XkUIyKnrE9v6XjGih3M7X6s1OKCkaRMDeNtctbIAjXfsk1u aD4bi9S1QWZgAxOm9QHjYlp0105tqVo3j1o9jXx/kO0t5lO6K1yOfTR6N0U4gxMuRdwrsV++ 7E3KTiSHIHF3SZSWhQErxm63HVWo4m2YVOtmd0RPhvQ7ff9IqizZsrmyagf1yp9iy0yFEpJs ou6zsHrny1V0okgynFGV//KIRj/5Q8UaCYSX2DYWjBMCiJ3GeVAL2PXAUfIkxPdQqVkHv5/U 2hyAhW+tU5zCwbfmKUq06ub5Q+c5Xt3uGfi9hOownkz8WRI4W+ByaMFLJHxXrqy2bMzUolZx Zn4cwcgbqpFnZENLr99MBXDG4KrtGZ8mYslCZEG/5Ps+viqRasxBVHTLu2VEzyAVxGggZrWI Ko6y6DB0eqtCAXe7UtT+ZlBL2t4StSK/pL4MzsmYnqjQOEthQpZyAINpV4VdCCUKZcYRWWRk cIMmFKfqQxj0H18ZtsKhx/T1O1ITke3wM6GpNI0wfdga+clMyfviKfuWVHFk2vBp7YxH6vTu WEVqkuQJp8spL6+y7vdJRhEAX81j8hahU/OSKOJqhYY4GcQx3xoGF+c4xAWXNLuXoT54RSNP gvmC02bIxCG9A/W61zFRZaQN8FHcRUz6wpTP7pCkk9O17FAd+9HwmiZhOR5XWD87VpQfqUCs ACelvRmH8RLBtAzodsuWV484bosUrCq95ENS+Ae9sVekRfcu2DZBmBb1RR3a2FMBoTiRDcIH HqpFrdfXFosbSzuewjOaLQRgMlFZ7+fceMgGpMTBPcZeVyhHTZoNJf6Tt+EY8xWPx8pfpig3 gtnS6+i96Ln3K05Q3tVxlPT6oTo27FAXJN68v0mOApOd4FL8t3q1tWdwjN/8YfbaNx6wiAyJ 8dRF+3rH8LVKs3DZtw84zcIlddSUdpxHz3Ei0OqnohfEHKDM57qJEtVBVRyiR6suW1RdDw7u 5tMBdcwuaQ5CUDrPW1rB8Dwv7e1UhY68wjm3wzd2pXUHobqNge3rR5F4KpAiYUTtIrtORF1F t+rKhEZ7NrJXgser3l0nntdayFkXxli7MPDWjQBWS4ybTINzDMTQwyv67CzJA8ZWVaFPIaos A646E17RvdXdkCI5t4g9CswCHaq/JZoHRxrDf3cfH6qn1vlqcmnYTjO49ACENY7kletpoJH9 sEzeskSNcQ2wWixqIk6xHprjgwPXIob7LIHMlLXkgff80b/PZFPhh+MXj5+++K6iXXvaNEFB MfFU2oyi18oIUocYxIZJKQdm3fMqK6eYRvVodOkjYB2PQ2xUZUgJ2NHtOAiuyTPjQkkRcm5t y6zEpkdOb0pj5dVgy63ghFxhToXthX6/6WNz+/x+bdyc/61x0G63Jf9bp9frHrRx/1+vs73/ 75N8tvnftvnftvnf/kT538beF7rhsqOKn72tmDPaqcde85NmjSupDYSpf8X2Z7ScDsSKQn6i MFDe01RgSl6RYhvvdTowFEfUoYOzRs8zij0DlRzOH8Ri0eFDZuCeNyMrYW8vr2upQBDMP5X4 /0ecQfk+Uen9Lhqbh6NwuJxIMjCZFmm/KlY2GIpEHXeCQYFKWnt7vY5rBdBUmQPz2Q5QQ4yl fyGg5F3AqX1C6JPpXaIq3hEyrlVqIHG1wIhWPkSQDVmt6ARxkUTKRu72FbTmYLiU+C+crljr yI/TcwvqgHv8CPafDk1ARWXbG/+rpM9KhQpkIk28ZqPVKbQt+YtrXMJ8ZNk/hE7ovPDEj+Mm FkTKQbJzPRuq5EFnFH0xVZUvDS/voWaFrNaq97qSgiQviiB5MEkZAystXui9s3l4SSNTe2k4 ymBpXUdyp3xoyPCD/RIVHk10bV1jJDvhR/lpqfdiIKMjWklC+IexWQI7BBiUwA1/Djnq+dOY c8DQohVMAF9v0Dou8IwHrKSNcnVASvRtjkeWTaj3fcEALtymCbb1neEZIPcU9+KkxTyeJBJ6 pYh9D9S+lyF3PdSQJSfn+i4pQ5yGaEmx7hkfvRhbygnvaUszWo7OWfvgoNA56FQDouV2RMJV wnZQWdLEgZJReHKtBrXEPgdKpQ82p4+L9c0Z7l1/lzfOwAYk0ue4w546AtSLeJD55BGazEyc ys7tnI6bUWIy3TSix9kRhNA0TrHHy5sO8uKt2VQAgYIms6g7+shuQ0Ra6IowuZYQILMZQX19 SWbu30LZAcP2qunnaDSHswxEchKeOm6SRO15R3hshKGaV39C1JqYKUWWxXISc0I5rKWScUB2 bn2WRiTqiJSTiiQAkHq6Oj6ZHVQ46jP7g0debsM0A4c6gOMJrAsNlzrpo8ygOFLDRHQ7dmf6 mH7I/ykcK1WDEcLARRAwKes4Rc5QFFwh6wGRYsI63zhUabGQEiFPWsohnOFLPYTcMnKanlsQ oZt7MVQ8p89wVIn6WTnmVWK6JDIQ2mRKqVtCM0R1UiS/udX3jkhjNnCEKk1eRcSqkheOeJgm fUeKpvxI6fSmFbfcGjlQDSqAx3Xz2cn5zmiR2rC8MVtDtsYaCR64iiybmSja7JtU6KdpqTi6 MfP6tmCuTPHbTt9miptjDpnn6V2VzMuijZdc/QLfd79E60zpb5ii8da98wk+fAXp75n8/79u 8/+0W712S+X/bzYb3QP4f9qt7tb/8yk+W//P1v+z9f98cv+Pso5GnG4LmikZI+EAyOajFHLK SUTzbMYa5kAloVAJraBsloaac2llfalLH9JEIs+oN57EnHe4JgYDgxPbdRRMYzZf0qz/j2A+ RgYRHAkF/GfPvoU4aNIUPiJyf4mCifcySII50QtrsD8mgXKJXEschs6NUWWjlbBPFafqFBfe jWKVrEUSq7MfDEE7IdIt3/GTWpjcUXlcMSmSMBmKc6oVOf6Pg2zv5kSL9T/sbgQHJC4fK3wH S7IGs138Y/fADyZXBLNgwFMwuF5w2rXgnHpmqMucn0Zu64UmGzgCI5jhx0+/+8frs2/+m5T0 py9ek+aEkzJe+c6L2LtfcyGy4W4zdNypGC0LrgPi7kdQ+h9Q6Yel4Twg+XjGaV/PxMJ0zybY kh6p/RGr3xwxw3oiH1qgPw/IovHC/X3Z8UdsToVehftN50TvRHbx7nnPkd19isx4Y0KHn4TB vKQ9DekhYjy9Tt+8JfM1PAeiMsWWqhygH32cD0CNJ+EMDAbeEh+Y3EWHd56k5Xv19LsXEDjj mfJ+1vklDtjCimwiq8e5CAcGU6nyeXECnLD9iJMdqRoNr2yyf+VqsM1KGOBTWB9zsIoswmgC Z56g03uC5p9Qw2X1YCwkoX5N/QRnW2v8qzxGPqReu+L96jWu7jfSnx+fPXMIYez9L1dmeki3 zDaSafffuuG7v7VlavLItvk7Ugkn5SLeIG1jYQdS4SlWtPuOlhPUIZKWDQB/ECM/YhIfakrg OQ5T5FNIBkQ93GK2nkNERQRn6nwsLKTp5ul6hFO2M1fDkbsNCQey1fgP4a6R9ELJDGqEPhnH KyDJ0QWv5Enda7kprOcAcv/iG60ikY7HXm7jOUE+oGdNkslDxvjPQVL19NF33iIoGYkkXgDV 0Emr0bl/KvKoRh9vuSB9TJY1PuuIde2rGqbv/y1pAZVVj3RPuX2aJYLktQp8ne8Sw7nvjIXV mla3Z8dD9dHHKpJpKinlk7qz8CcaOeoKCR3ncf+C1yFCCzeWwQLq2+2Ycah2LtAPg5NYIYlW dQwrplW2bvYEzhrlq8pO2UVRpXzl3aV5fvLE7mCdNQuLEWncz5dtrSrb7OULt1cVbnXyhTur Crdb+cLdVYU7jXzh3srCBQM8WFW426swPT2Wgnzu0x/OY+/x92cvjx89O3v1/cvXhvCH0CD1 CXqrDPpMWhyHJWd1F+9CHIqK9SUWrH7G7pUW5mZV3UW3vbJNv8+qQ9VbTGeVnZ2dN6VfdtTn DTjfZZOwr1+4Re7tpcnb3Tc59Pbu6XJyPiwF8OIfIUcQETf0C1vcGzQ456UC3i9oPlO+SeWp 0r7AXgW1hVLN20q1Uap1W6kOSrVvK9VFqc5tpXoo1b2t1AFK9TKlXJyInmd1PMEzzZPoerqY R5jCNgAfYF0xtbArZj5MnmBiJ2IKOchbWnZ+s43aU6Jo07ONpggMH73YoLJdgtQadLciju7w tNLPdVCNgQTWOKycevv7/cy75glJqRXvWicklVa8a5+QEFrxrnNCMmfFu+4JiZgV73onJFFW vDs4IQFS9O69HW5mZlpwLiyn4vaw7EeLVuAjubJ+JHcOwYMQz0c8YQoAPpw0w+z+8+n0RF0L wVf+LJJgMq7rwE+1G8IAMrOYItFkOQXfNnC6e9o031rmW1torrhqxxTrmm898+1gZdUFvU3h rpANcuSYGsoOgLAIAWPs80iM1NHcwsNDSgf9Qo031YECmE0D01aVh0eCqAzM5howWwZmy8Js GZitLMzWGjDbBmbbwmwbmO0szPYaMDsGZsfC7BiYnSzMzhowuwZm18LsGpjdLMzuGjB7BmbP wuwZmL0szN4aMA8MzAML88DAPMjCPMjCFDJ1RMFNcoH9CY1DsWvYxsHpc9IqmLsRo+GP7omX z8iIqiMW5BU0CG3srPNR9T/OIqAlfj9VwjEvSVJmkJOSBGRDERRZFfpuKVJyTvb3iY+pxCnQ Pw7TbcAj/N9nr78/e/38h7Pjf79++aisSruAbkF+83AFkuEK3OEV04hg6pFXe6giIFYg9iOt rwlffEkYyCK2CHfNcpLBnUwKYa9psJdksAekEe4EiQp7zU2x17oJe14ae4I2wh/Q+LGw592A PkOZ3q0YbDEGUwuNIr+Wi8A0oCL6a+Ux6DmIK8JhewMcfjQKdJGY6tUKGrwdhe08Cg0Vtlcj sYgM25sjsXMLEr0NKdFbD42mh794N2JxA1LsrCTFzmak2Nkci91NsLgGLX5kLK5Ni90baLG7 GS12N8di7y9Di72VtNjbjBZ7m2Px4EYs3hWPMDQfRtD6VJlC7caycgVi/Y3I86DsryTPA4NY x8Prh8qeXk2nBzdi2O4BcMQpx+yJG9Tbu6p6+iuNoCjkVA1yj71bR54y9vcqVLzvvBacO++v +jbNeQFVUIetT65gTPye4Kd8b3lnGHqFo1B/W/L+Xb4h/SbfBOfFgBdYXxXL2W+CGVK4Rwve Peed7hf+izqfPNanFNQtmebuDQJibxuOUzeH6qsaJVhb+XaDaFTHrqU9+CBAGMOqjAGIwNor ycqXeMsZtnnlQtgz7JCegb7g5NbBC9TZzK2vacegpy6KwEdFGl6FSeRH5asTovfTigmbZb5I Vf5JmOQnh0nIIAr5fhbvJ2xN7lyd/ATqpT/7Ya15ejOsAiAp/kuBtOPTsYtpsvaYrs/gU5Wd 1rVIXJ1jpApX+ivcq7834Xto5YS/YmxoHsLjNn6QgraakjlbNvm0bHIql2Up9Jv5I+4xcfZr M4+mcg7OdrnnVIWnj9RD+SbP36/NVlVOjtQo4Cx6k2vY5bF04xjqBQZoc65b9lPV2GtxhnCY Ek2rChB5Gb/7p8zx3cuqnGyWrcazcHQlfJarjhL0yyT+QnqC+tCf+UO+7LtiUslGTo5VkwOB nrst7AiwchPHJWxvylHVa9YbRtqpUo2KmxzBZHXT3XHu8dKZSTLNf//t60f/PD579v23xIzf /PjkyfFLT0ki3rmp8qncVX3lybCdpIdyIGQnc0rkyCs6U8KQd1b0IcQhotD2gMplBKZXvqwT RS3mfnRGE+jhGkUpX/Vg/1OHJ7kCLC65gzcdWZGE6KMrObQyKYeqB+7c0Ou+80zPRCbvzi+6 46t7W7kBjHtFuJ7Wmwh5eqXo+Lm/mJOAuTv9UCJG9pFpfR6/S5iC1dMhPx3Gk+U0SlKkPWfa RtobKvRQZ/Vai8pVXwkGYWO4ms6na9P5HIS+qi96cfWmlzya9Kz012eM+W2coQYmbMGDW5fi 56qgIVJHHEdDLYRlVGoPZR2G02DxyXHT9NIMrHoj5xhRnuWeuWafHead6k+We3T+0ktOJjE3 mTXW4appMVdtgBvhCWeAN/SosPGbmLH0+PjJjy/OHj97TDSAjXVoMecJksLNz8nmQ6TQndpe zVtg13wce/T9TfSm9DXpLzjGNo68X57F/oizxz9RoXrvvV9Ovr70578k76sefwnf08r2Xg2F n1y9rwCOStJuz++qlzZ5vVlhzRc+fHzOizBAhBHIhc+gxLg5te55T3B0GPQ7xBGXr3Hq8Be0 /V5KJGnAYcR7g4AlwqGOr/g/4ARXPg70VvWzr9UD/n4+j5czfJORnTSrXquPw9vtvtcmYXDK g+S5+lrylf7y3iPu9prmOT4t+i/1oE3/SWOkrJlG+JfTPP6PgGV3gCafLcLtOOulHPVm3XA2 j0fLIR8vYu6WIXNUX6iiLuN5SFoe8gQhca4Ka1MKpIsxfRwpGAGIgFOYXw9jJ7AH2K2xAer4 ttgs9ooQ6OAwAyIUEO0CEDmwbQV2vWkAT8sFxdYkyAYH2rxejNBUacBBGaxo9ux+LLcBo4ok 8XZfqblCDUO0LjUgtCFLBIxvRDBNSHCKTZCo5D/CMTg/xQNTG9/cb7EvmCsJlTOqpsyCEKx2 HoWLJSJhnxgcmIcJEwJf+PwW0Y7aGuGcb6MAh9zJDMtcCa3P+rB4QGip4IgH+VTeMTTpHQ+R m60WgknjWaEPoFIYzHSGBmZvqI7S3VFTWjfkYMThndtUFK2N+MiYyU7C86Su0tu6Oom8/yKn c8/mVP1smSDQs3wH83KncqNuUfKyWpR3pMW75GbP9BddUh0rN2yP6Hc9TM5w0eAZH8guZ6w6 pTFMpW5dZIICWU6rG19IWsQzDv2uuKkhtdbmpjk3S+EKNU69tbr8JeFveMt6PzTr/aVoytNy oxo6OoZgERqtMbAuq64umr2twKSxlGpGnZ1ma73Pa30KuYot0/jV5+J5fT5kno7iRZqPucJ1 oGjBpHs9n4ez4IwDDRjmGaZWUQ2v9DIteb3gzxC+uEDq2MmkPv0d27gl/1OT/qfi/zqNZruL +L9uc5v/6ZN8hhNaDb09ZF9joTgu776Jdomi2TpA2hBsFQSSMaS8i3/xdmVpZUvk6lS9k9Oq XI6cqcocmW+JHxc1ZcsXtCW1VjcmocdixeXbdN8WNZ2rXdCDFIzbOgJX30G3s6on6vXqrqxZ 3+lGgnijmp8Mw1Al/0+wyGyDpf9DP5pkfs8F4Gb53+o2ek0l/3vtZofz/x10t/Hfn+RjTF3S WxwJ4pXxgj2p7M4q8dVESsw06s2+96X3XKWY5qcINAnIDB4hx8t8qYuSNUolHwdJOJebJvKF o2E8h68RFACwL7JnhpXdgK7hKYqThhoh91UJ0H+cjZBdhMokganDIccqVysCC59+89x73WqL 8UVK9sQfeC+bLYyLf5zBjDhpogvSkWbQwT9d/NPjfUFdMJ5PPS5cP2gEtUa3SgZuvfUVfe3w 14M2fSXr22vXeyhA5rjXrTfxlfDmpYxj+TTrzZ6C1Ky3DxQkgt9VkAh+V0Fq11v3b4LUODCQ TJ+a9V7PQmoaSI0bITUbtk9NC6ljIDXvG0g3j67bNJDu9wyeuCOCp4YeXafe694EqWUhdQ8M pGbL9Kn3lenTAQrIlq6dPb1gn7QE0V1pv6VgUS3dq64AAKz79c6N4+u1CsfXMeNrfmXG12zf BKljcd5rGUiNphnf/bYZHxdYB+e9toXUsJAsHfRuGF3L0kGr3rGQvtI471g66N4IqVn/qmsg 9SzGewcG4009up7wVvM0a8s/0Ka8Muh2tcQ65NQ48KeoLWkWY1q87YpJF41y4FoC7nb2N/Yg 3zWTBNPZ4rocKfNyHQDSfnEv5L4acSs0Ml1lAYzqC7kU6WT3BHe6sd+PVDsM0at6u2W/0t9N 99RUGKwsmuvLQ313Th7BSOc/RUYEKrlkL1AKrV86W+49WUmqaqMciRVVkAiLciwC7OlDOAn3 Ugxo6ubPwTxOyr2qeHOA4H4OEUYXfq3WBO1IhQPWrGjlL5OKSjag4tXeRKQ8CxrSJv76AHMg zNhRE2Ny1qcMJGexm/pX5XaVfzEY3P2E9HRRuek8DbAJAfToG3OA/PKg3Dwsc6Fas1KhCRuU W4dSyZk5d+LCSHVK9+SLL8zMIQNAqv/u0Kn/T6MxT+IL/wX6KZs09LBP31v4js13+t7G9xpe FHUcna7AEYcS3q96IC09kFaFnVV4i6jfgRkf6kiVer1e2qF6BdVUrS/kwIOqXKm4lfQrt2pl Fb5oSMgcg3ahRSjk4dpJ3lMbucjzssTpoBK38iB/hdwLiSfhUfOw2VAio3jSddGfqGhLF+Wz Dd6RXGskqKmOJzF1m3/tAQxBIXztk4A0cDBhVHGfJ42/mlcii/hbarLwSXxW3jgbfNnL0Bvh 2yE45xYTnpuwjMpMlfKV2q6Y3uQwbTAk6po4xTWC3W6mRKdhV7x588bzXnjer7smDwWQbMRH mr+/7NZbgQdZGJXDiuFgp8QbtVakRQIaoTbkpeUXX+eUlMUGl+aVOIUfS10+iCVy1nag1mwk v1L7VKjSz6yQX4pj2osIb4qsOGNoeVftF//z+OWrp9+/2FUoHY8ny+RtOVmM4uXCHQyQAJXa okElF/wZbutyqH4aAvTKyc/iIJBuIPmj1bnV5QCT2B/ZA0slTTqeSztfek9ANP5sNo+vjL7P KU4XwZzPXnG5eYAbd9RNJOq8UrOS5QvpFpU15IAVYjhbAmrfIV8vTb/K+FAFvZq3cC/b4WcP tT1jidNzrkhy+UP62tqjv+4yTsKcGHCWGGnucfLVsh70Pe6G5hAibbO44c5DrqreYbo4DSdm TN5sNFyCjVaTStGYdWeJswKWIAHJQdRoqaaYqe95ZnQFvMJ1VXO3EmURWdpu0CJP4+e9AoZ6 AweWlOmoEjZyRlaHu968+TOw10ny82GNZP7p7mfEW8GMrKGy7Rqx/pbN/nJs1tqAzR6t4rJ7 fwomax4mP3+OHCb92rLXX5G92h/MXmKUtrXuGFwN3+IsVuKwXXvLdh+f7chEayobivRKMZ9o WJIYnui5XRHzySnf2qQ8W22Mu7ZhRwR4selFbVebh253vPRjXaxVXKxli6l4jgyD/4cJle18 /yWlauc3StVmQ4tVffDO3DzriNf9z1u8Ggkr3qHkZ+paVdNd1l3DknjQ154kFDz9jESyMwKX yvNOp9w4UNwE5P0nSrdPiro/m6DobiIoJhM5vuqIgKPPWwTIpMYR4ZjWos/JM6f7tDVo/mIc 1SviKEXphlTh/lc/9HkI1QCfwJ1MJMYx8y7FmG8i70U8n8olT3Izmeef41KkhTqZwZtsFXPY +QZ3v56nvMt/Bc6M2z9NTDm5kXpYuAXAs5f39Kfb3UCgFA9lh096m82lleMyftV77jkVfuRo lmbDcwM4EpueBWR3j1bhMIMi1137B+KolcdR60Nw1CrAURbQxji691mgqJ1HUftDUNQuQFEW 0MYoan8WKOrkUdT5EBR1ClCUBbQxivY/CxR18yjqfgiKugUoygLaGEVHnwWKenkU9T4ERb0C FGUB3Y4i+1LtsktAS4l+6RMw0Kf/6AOr28/2s/1sP9vP9rP9bD/bz/az/Ww/28/2s/1sP9vP 9rP9bD/bz1qf/wOyuq86AEABAA== --Boundary_(ID_uUCajPRxyEKqzJ8/7Mhlng)--