From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 62186 invoked by alias); 11 Aug 2016 16:44:45 -0000 Mailing-List: contact fortran-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Post: List-Help: , Sender: fortran-owner@gcc.gnu.org Received: (qmail 62164 invoked by uid 89); 11 Aug 2016 16:44:45 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.9 required=5.0 tests=AWL,BAYES_00,RCVD_IN_DNSWL_NONE,SPF_PASS autolearn=ham version=3.3.2 spammy=mutually, defeat, race, corresponds X-Spam-User: qpsmtpd, 2 recipients X-HELO: relay1.mentorg.com Received: from relay1.mentorg.com (HELO relay1.mentorg.com) (192.94.38.131) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 11 Aug 2016 16:44:34 +0000 Received: from svr-orw-fem-03.mgc.mentorg.com ([147.34.97.39]) by relay1.mentorg.com with esmtp id 1bXt5s-0001Jn-Fh from Cesar_Philippidis@mentor.com ; Thu, 11 Aug 2016 09:44:32 -0700 Received: from [127.0.0.1] (147.34.91.1) by svr-orw-fem-03.mgc.mentorg.com (147.34.97.39) with Microsoft SMTP Server id 14.3.224.2; Thu, 11 Aug 2016 09:44:31 -0700 Subject: Re: [WIP] [PR fortran/72741] Rework Fortran OpenACC routine clause handling To: Thomas Schwinge , "gcc-patches@gcc.gnu.org" , Fortran List References: <579973CB.3070006@codesourcery.com> <579AD9C9.3030804@codesourcery.com> <5776D55A.4030002@codesourcery.com> <878tw35o6k.fsf@kepler.schwinge.homeip.net> CC: Tobias Burnus , Jakub Jelinek From: Cesar Philippidis Message-ID: Date: Thu, 11 Aug 2016 16:44:00 -0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.2.0 MIME-Version: 1.0 In-Reply-To: <878tw35o6k.fsf@kepler.schwinge.homeip.net> Content-Type: multipart/mixed; boundary="------------2EF99C5F038630DB88AA4280" X-IsSubscribed: yes X-SW-Source: 2016-08/txt/msg00055.txt.bz2 --------------2EF99C5F038630DB88AA4280 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Content-length: 15956 On 08/11/2016 08:18 AM, Thomas Schwinge wrote: >> --- a/gcc/fortran/module.c >> +++ b/gcc/fortran/module.c > >> [...] >> +DECL_MIO_NAME (oacc_function) >> [...] > > As discussed between Cesar and Tobias, these module.c/symbol.c changes > introduce an incompatibility in the Fortran module file format, which > we'll want to avoid. Reverting that to use individual bit flags instead > of the "enum oacc_function", I think that we're safe (but I have not > verified that). On the other hand, given that I'm not at all handling in > module.c/symbol.c the new "locus omp_clauses_locus" and "struct > symbol_attribute *next" members that I'm adding to "symbol_attribute", > I'm not sure whether I'm actually testing this properly. ;-) I guess I'm > not. How are you testing it? Basically, what you need to do is create two source files, one containing a module and another with the program unit. Then compile one of those files with the old, say gcc6 fortran, and the other with trunk gfortran and try to link the .o files together. I've attached some test cases so that you can experiment with. Each driver file corresponds to a test file, with the exception of test-driver which uses both test-interface.f90 and test-module.f90. >> --- a/gcc/fortran/openmp.c >> +++ b/gcc/fortran/openmp.c > >> @@ -1814,7 +1824,10 @@ gfc_match_oacc_routine (void) >> != MATCH_YES)) >> return MATCH_ERROR; >> >> - if (sym != NULL) >> + if (isym != NULL) >> + /* There is nothing to do for intrinsic procedures. */ >> + ; > > We will want to check that no incompatible clauses are being specified, > for example (but, low priority). I'm adding a hacky implementation of > that. So this is what I was overlooking in PR72741. For some reason I was only considering invalid clauses of the form !$acc routine gang worker and not actually checking for compatible parallelism at the call sites. The title "Fortran OpenACC routine directive doesn't properly handle clauses specifying the level of parallelism" was kind of misleading. Shouldn't the oaccdevlow pass already catch these types of errors already? >> --- /dev/null >> +++ b/gcc/testsuite/gfortran.dg/goacc/routine-7.f90 >> @@ -0,0 +1,69 @@ >> +! Test acc routines inside modules. >> + >> +! { dg-additional-options "-O0" } > > -O0 to prevent inlining of functions tagged with OpenACC routine > directives, or another reason? I'm not sure why, but that's probably it. >> --- a/libgomp/testsuite/libgomp.oacc-fortran/routine-7.f90 >> +++ b/libgomp/testsuite/libgomp.oacc-fortran/routine-7.f90 >> @@ -1,121 +1,95 @@ >> +! Test acc routines inside modules. >> >> ! { dg-do run } >> -! { dg-additional-options "-cpp" } >> >> -#define M 8 >> -#define N 32 >> +module routines >> + integer, parameter :: N = 32 >> >> -program main >> - integer :: i >> - integer :: a(N) >> - integer :: b(M * N) >> - >> - do i = 1, N >> - a(i) = 0 >> - end do >> +contains >> + subroutine vector (a) >> + implicit none >> + !$acc routine vector >> + integer, intent (inout) :: a(N) >> + integer :: i >> [...] > > This seems to completely rewrite the test case. Is that intentional, or > should the original test case be preserved, and the changed/new/rewritten > one be added as a new test case? The original test was completely bogus because it had a lot of race conditions when writing to variables. I could restore it, but then you'd need to remove all of the gang, worker, vector clauses and force it to run in seq. But that would defeat the intent behind the patch. > Now, my hacky WIP patch. > > One big chunk of the gcc/fortran/gfortran.h changes is just to move some > stuff around, without any changes, so that I can use "locus" in > "symbol_attribute". I agree with Jakub about creating a new gfc_acc_routine struct to contain the locus and clauses for acc routines. That way, you can also link them together for device_type. But at the same time, since device_type isn't a priority for in the near term, we might be better off using the existing oacc_function and nohost attribute bits instead of introducing a new struct. > I very much "cargo cult"ed all that "oacc_routine*" bit flag stuff in > module.c/symbol.c, replicating what's being done for "omp target > declare", without really knowing what I'm doing there. I will appreciate > test cases actually exercising this code -- which doesn't currently at > all handle the new "locus omp_clauses_locus" and "struct symbol_attribute > *next" members that I'm adding to "symbol_attribute", as I've mentioned > before. (But I suppose it should?) > > We're not implementing the OpenACC device_type clause at the moment, so > the "TODO: handle device_type clauses" comment in > gcc/fortran/openmp.c:gfc_match_oacc_routine is not a concern right now. > > With these changes, we're now actually also paying attention the clauses > specified with the OpenACC routine directive with a name -- one of the > things mentioned as missing in "Fortran > OpenACC routine directive doesn't properly handle clauses specifying the > level of parallelism". > > To handle several "pending" OpenACC routine directives, I had to add the > "struct symbol_attribute *next" member to "symbol_attribute" -- I hope > that doesn't disqualify the proposed changes as too ugly. (Several other > structs already contain such "next" pointers, and the use is very much > confined to only the OpenACC routine directive.) I will of course be > happy to learn about a better/different way to do this. > > commit ca4a098dab72f27c6e1121aa7e5e49764921974e > Author: Thomas Schwinge > Date: Thu Aug 11 16:34:22 2016 +0200 > > [WIP] [PR fortran/72741] Rework Fortran OpenACC routine clause handling > /* Structure and list of supported extension attributes. */ > typedef enum > { > @@ -729,7 +839,7 @@ ext_attr_t; > extern const ext_attr_t ext_attr_list[]; > > /* Symbol attribute structure. */ > -typedef struct > +typedef struct symbol_attribute > { > /* Variable attributes. */ > unsigned allocatable:1, dimension:1, codimension:1, external:1, intrinsic:1, > @@ -864,6 +974,13 @@ typedef struct > /* Mentioned in OMP DECLARE TARGET. */ > unsigned omp_declare_target:1; > > + /* OpenACC routine. */ > + unsigned oacc_routine:1; > + unsigned oacc_routine_gang:1; > + unsigned oacc_routine_worker:1; > + unsigned oacc_routine_vector:1; > + unsigned oacc_routine_seq:1; > + > /* Mentioned in OACC DECLARE. */ > unsigned oacc_declare_create:1; > unsigned oacc_declare_copyin:1; > @@ -871,137 +988,24 @@ typedef struct > unsigned oacc_declare_device_resident:1; > unsigned oacc_declare_link:1; > > - /* This is an OpenACC acclerator function at level N - 1 */ > - ENUM_BITFIELD (oacc_function) oacc_function:3; > - I'm not sure what's better from a stylistic standpoint. Personally, I'd prefer if all of these extra bits were coalesced into an oacc_routine and oacc_declare enums. At least for acc routines, gang, worker, vector and seq are all mutually exclusive. > +++ gcc/fortran/module.c > @@ -1986,6 +1986,7 @@ enum ab_attribute > AB_IS_CLASS, AB_PROCEDURE, AB_PROC_POINTER, AB_ASYNCHRONOUS, AB_CODIMENSION, > AB_COARRAY_COMP, AB_VTYPE, AB_VTAB, AB_CONTIGUOUS, AB_CLASS_POINTER, > AB_IMPLICIT_PURE, AB_ARTIFICIAL, AB_UNLIMITED_POLY, AB_OMP_DECLARE_TARGET, > + AB_OACC_ROUTINE, AB_OACC_ROUTINE_GANG, AB_OACC_ROUTINE_WORKER, AB_OACC_ROUTINE_VECTOR, AB_OACC_ROUTINE_SEQ, > AB_ARRAY_OUTER_DEPENDENCY, AB_MODULE_PROCEDURE, AB_OACC_DECLARE_CREATE, > AB_OACC_DECLARE_COPYIN, AB_OACC_DECLARE_DEVICEPTR, > AB_OACC_DECLARE_DEVICE_RESIDENT, AB_OACC_DECLARE_LINK > @@ -2044,6 +2045,11 @@ static const mstring attr_bits[] = > minit ("IMPLICIT_PURE", AB_IMPLICIT_PURE), > minit ("UNLIMITED_POLY", AB_UNLIMITED_POLY), > minit ("OMP_DECLARE_TARGET", AB_OMP_DECLARE_TARGET), > + minit ("OACC_ROUTINE", AB_OACC_ROUTINE), > + minit ("OACC_ROUTINE_GANG", AB_OACC_ROUTINE_GANG), > + minit ("OACC_ROUTINE_WORKER", AB_OACC_ROUTINE_WORKER), > + minit ("OACC_ROUTINE_VECTOR", AB_OACC_ROUTINE_VECTOR), > + minit ("OACC_ROUTINE_SEQ", AB_OACC_ROUTINE_SEQ), > minit ("ARRAY_OUTER_DEPENDENCY", AB_ARRAY_OUTER_DEPENDENCY), > minit ("MODULE_PROCEDURE", AB_MODULE_PROCEDURE), > minit ("OACC_DECLARE_CREATE", AB_OACC_DECLARE_CREATE), > @@ -2095,7 +2101,6 @@ DECL_MIO_NAME (procedure_type) > DECL_MIO_NAME (ref_type) > DECL_MIO_NAME (sym_flavor) > DECL_MIO_NAME (sym_intent) > -DECL_MIO_NAME (oacc_function) > #undef DECL_MIO_NAME > > /* Symbol attributes are stored in list with the first three elements > @@ -2117,8 +2122,6 @@ mio_symbol_attribute (symbol_attribute *attr) > attr->proc = MIO_NAME (procedure_type) (attr->proc, procedures); > attr->if_source = MIO_NAME (ifsrc) (attr->if_source, ifsrc_types); > attr->save = MIO_NAME (save_state) (attr->save, save_status); > - attr->oacc_function = MIO_NAME (oacc_function) (attr->oacc_function, > - oacc_function_types); > > ext_attr = attr->ext_attr; > mio_integer ((int *) &ext_attr); > @@ -2236,6 +2239,16 @@ mio_symbol_attribute (symbol_attribute *attr) > MIO_NAME (ab_attribute) (AB_VTAB, attr_bits); > if (attr->omp_declare_target) > MIO_NAME (ab_attribute) (AB_OMP_DECLARE_TARGET, attr_bits); > + if (attr->oacc_routine) > + MIO_NAME (ab_attribute) (AB_OACC_ROUTINE, attr_bits); > + if (attr->oacc_routine_gang) > + MIO_NAME (ab_attribute) (AB_OACC_ROUTINE_GANG, attr_bits); > + if (attr->oacc_routine_worker) > + MIO_NAME (ab_attribute) (AB_OACC_ROUTINE_WORKER, attr_bits); > + if (attr->oacc_routine_vector) > + MIO_NAME (ab_attribute) (AB_OACC_ROUTINE_VECTOR, attr_bits); > + if (attr->oacc_routine_seq) > + MIO_NAME (ab_attribute) (AB_OACC_ROUTINE_SEQ, attr_bits); > if (attr->array_outer_dependency) > MIO_NAME (ab_attribute) (AB_ARRAY_OUTER_DEPENDENCY, attr_bits); > if (attr->module_procedure) > @@ -2422,6 +2435,21 @@ mio_symbol_attribute (symbol_attribute *attr) > case AB_OMP_DECLARE_TARGET: > attr->omp_declare_target = 1; > break; > + case AB_OACC_ROUTINE: > + attr->oacc_routine = 1; > + break; > + case AB_OACC_ROUTINE_GANG: > + attr->oacc_routine_gang = 1; > + break; > + case AB_OACC_ROUTINE_WORKER: > + attr->oacc_routine_worker = 1; > + break; > + case AB_OACC_ROUTINE_VECTOR: > + attr->oacc_routine_vector = 1; > + break; > + case AB_OACC_ROUTINE_SEQ: > + attr->oacc_routine_seq = 1; > + break; > case AB_ARRAY_OUTER_DEPENDENCY: > attr->array_outer_dependency =1; > break; That seems similar to what my patch is did, albeit with some checking deferred. I don't think this would maintain backwards compatibility with object files generated by older versions of gcc. Regarding backwards compatibility, maybe we should teach gfortran to default to seq parallelism if an oacc_function attribute is missing in an older version of the .mod file? I'm not sure if there's anything we can do about forwards compatibility, i.e., linking a module generated by gcc7 with gcc6. > diff --git gcc/fortran/openmp.c gcc/fortran/openmp.c > index 05e4661..5a69e38 100644 > --- gcc/fortran/openmp.c > +++ gcc/fortran/openmp.c > @@ -1714,44 +1714,6 @@ gfc_match_oacc_cache (void) > return MATCH_YES; > } > > -/* Determine the loop level for a routine. Returns OACC_FUNCTION_NONE if > - any error is detected. */ > - > -static oacc_function > -gfc_oacc_routine_dims (gfc_omp_clauses *clauses) > -{ > - int level = -1; > - oacc_function ret = OACC_FUNCTION_SEQ; > - > - if (clauses) > - { > - unsigned mask = 0; > - > - if (clauses->gang) > - { > - level = GOMP_DIM_GANG, mask |= GOMP_DIM_MASK (level); > - ret = OACC_FUNCTION_GANG; > - } > - if (clauses->worker) > - { > - level = GOMP_DIM_WORKER, mask |= GOMP_DIM_MASK (level); > - ret = OACC_FUNCTION_WORKER; > - } > - if (clauses->vector) > - { > - level = GOMP_DIM_VECTOR, mask |= GOMP_DIM_MASK (level); > - ret = OACC_FUNCTION_VECTOR; > - } > - if (clauses->seq) > - level = GOMP_DIM_MAX, mask |= GOMP_DIM_MASK (level); > - > - if (mask != (mask & -mask)) > - ret = OACC_FUNCTION_NONE; > - } > - > - return ret; > -} > - > match > gfc_match_oacc_routine (void) > { > @@ -1761,7 +1723,8 @@ gfc_match_oacc_routine (void) > gfc_omp_clauses *c = NULL; > gfc_oacc_routine_name *n = NULL; > gfc_intrinsic_sym *isym = NULL; > - oacc_function dims = OACC_FUNCTION_NONE; > + symbol_attribute *add_attr = NULL; > + const char *add_attr_name = NULL; > > old_loc = gfc_current_locus; > > @@ -1828,19 +1791,26 @@ gfc_match_oacc_routine (void) > != MATCH_YES)) > return MATCH_ERROR; > > - dims = gfc_oacc_routine_dims (c); > - if (dims == OACC_FUNCTION_NONE) > - { > - gfc_error ("Multiple loop axes specified for routine %C"); > - gfc_current_locus = old_loc; > - return MATCH_ERROR; > - } > - > if (isym != NULL) > - /* There is nothing to do for intrinsic procedures. */ > - ; > + { > + //TODO gfc_intrinsic_sym doesn't have symbol_attribute? > + //add_attr = &isym->attr; > + //add_attr_name = NULL; //TODO > + /* Fake it. TODO: handle device_type clauses... */ > + if (c->gang || c->worker || c->vector) > + { > + gfc_error ("Intrinsic symbol specified in !$ACC ROUTINE ( NAME )" > + " at %C, with incompatible clauses specifying the level" > + " of parallelism"); > + gfc_current_locus = old_loc; > + return MATCH_ERROR; > + } > + } > else if (sym != NULL) > { > + add_attr = &sym->attr; > + add_attr_name = NULL; //TODO > + > n = gfc_get_oacc_routine_name (); > n->sym = sym; > n->clauses = NULL; > @@ -1852,11 +1822,41 @@ gfc_match_oacc_routine (void) > } > else if (gfc_current_ns->proc_name) > { > - if (!gfc_add_omp_declare_target (&gfc_current_ns->proc_name->attr, > - gfc_current_ns->proc_name->name, > - &old_loc)) > + add_attr = &gfc_current_ns->proc_name->attr; > + add_attr_name = gfc_current_ns->proc_name->name; > + } > + else > + gcc_unreachable (); > + > + if (add_attr != NULL) > + { > + if (!gfc_add_omp_declare_target (add_attr, add_attr_name, &old_loc)) > goto cleanup; > - gfc_current_ns->proc_name->attr.oacc_function = dims; > + /* Skip over any existing symbol attributes capturing OpenACC routine > + directives. */ > + while (add_attr->next != NULL) > + add_attr = add_attr->next; > + if (add_attr->oacc_routine) > + { > + add_attr->next = XCNEW (symbol_attribute); > + gfc_clear_attr (add_attr->next); > + add_attr = add_attr->next; > + } > + if (!gfc_add_oacc_routine (add_attr, add_attr_name, &old_loc)) > + goto cleanup; > + if (c && c->gang > + && !gfc_add_oacc_routine_gang (add_attr, add_attr_name, &old_loc)) > + goto cleanup; > + if (c && c->worker > + && !gfc_add_oacc_routine_worker (add_attr, add_attr_name, &old_loc)) > + goto cleanup; > + if (c && c->vector > + && !gfc_add_oacc_routine_vector (add_attr, add_attr_name, &old_loc)) > + goto cleanup; > + if (c && c->seq > + && !gfc_add_oacc_routine_seq (add_attr, add_attr_name, &old_loc)) > + goto cleanup; > + add_attr->omp_clauses_locus = old_loc; //TODO OK to just assign that? > } This is another stylistic thing I don't like. Instead of having a single function for mutually exclusive attributes, you need five. And each of those functions are extremely similar, and I copy and paste issues when dealing with such functions in the past. With that in mind, I do see some value in preserving the routine clauses and location information for device_type. But I thought that device_type was more of a future project. Cesar --------------2EF99C5F038630DB88AA4280 Content-Type: application/x-tar; name="module-test.tar" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="module-test.tar" Content-length: 13884 Zm9ydHJhbi1yb3V0aW5lcy8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAADAwMDA3NzUAMDAwMDc2NAAwMDAwNzY0ADAwMDAwMDAwMDAw ADEyNzQ2NDc1MjEzADAxMzQ2MAAgNQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1c3RhciAgAGppbW15 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAamltbXkAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAABmb3J0cmFuLXJvdXRpbmVzL3Rlc3QtaW50ZXJm YWNlLmY5MAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDAwMDY2NAAwMDAwNzY0ADAw MDA3NjQAMDAwMDAwMDAzMzEAMTI3NDY0Njc2MzEAMDE2NzE3ACAwAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAHVzdGFyICAAamltbXkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABq aW1teQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHN1YnJvdXRpbmUg aXN1bW1hdGlvbihyZXN1bHQsIG4pCiAgaW1wbGljaXQgbm9uZQogIGludGVn ZXIgbiwgcmVzdWx0LCBpCiAgISRhY2Mgcm91dGluZSB2ZWN0b3IKCiAgcmVz dWx0ID0gMAoKICAhJGFjYyBsb29wIHJlZHVjdGlvbigrOnJlc3VsdCkKICBk byBpID0gMSwgbgogICAgIHJlc3VsdCA9IHJlc3VsdCArIDEKICBlbmQgZG8K ZW5kIHN1YnJvdXRpbmUgaXN1bW1hdGlvbgoAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAZm9ydHJhbi1yb3V0aW5lcy9pbnRlcmZhY2UtZHJpdmVyLmY5MAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAADAwMDA2NjQAMDAwMDc2NAAwMDAwNzY0ADAwMDAw MDAwNjE0ADEyNzQ2NDcyMTMzADAxNzIzMAAgMAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1c3RhciAg AGppbW15AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAamltbXkAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwcm9ncmFtIG1haW4KICBpbXBsaWNp dCBub25lCiAgaW50ZWdlciwgcGFyYW1ldGVyIDo6IG4gPSAxMAogIGludGVn ZXIgdmFscyhuKSwgaSwgdG1wCgogIGludGVyZmFjZQogICAgIHN1YnJvdXRp bmUgaXN1bW1hdGlvbihhLCBiKQogICAgICAgaW50ZWdlciBhLCBiCiEgICAg ICAgISRhY2Mgcm91dGluZSB2ZWN0b3IKICAgICBlbmQgc3Vicm91dGluZSBp c3VtbWF0aW9uCiAgZW5kIGludGVyZmFjZQoKICAhJGFjYyBwYXJhbGxlbCBs b29wIHByaXZhdGUodG1wKQogIGRvIGkgPSAxLCBuCiAgICAgY2FsbCBpc3Vt bWF0aW9uICh0bXAsIGkpCiAgICAgdmFscyhpKSA9IHRtcAogIGVuZCBkbwog ICEkYWNjIGVuZCBwYXJhbGxlbCBsb29wCgogIHByaW50ICosIHZhbHMKZW5k IHByb2dyYW0gbWFpbgoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGZvcnRy YW4tcm91dGluZXMvdGVzdC1kcml2ZXIuZjkwAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAwMDAwNjY0ADAwMDA3NjQAMDAwMDc2NAAwMDAwMDAwMTA1NAAxMjc0 NjQ3MDI2NQAwMTYyNTIAIDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdXN0YXIgIABqaW1teQAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAGppbW15AAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAcHJvZ3JhbSBtYWluCiAgdXNlIHRlc3QKICBpbXBsaWNp dCBub25lCiAgaW50ZWdlciwgcGFyYW1ldGVyIDo6IG4gPSAxMAogIGludGVn ZXIgdmFscyhuKSwgaSwgdG1wCgogIGludGVyZmFjZQogICAgIHN1YnJvdXRp bmUgaXN1bW1hdGlvbihhLCBiKQogICAgICAgaW50ZWdlciBhLCBiCiAgICAg ICAhJGFjYyByb3V0aW5lIHZlY3RvcgogICAgIGVuZCBzdWJyb3V0aW5lIGlz dW1tYXRpb24KICBlbmQgaW50ZXJmYWNlCgogICEkYWNjIHBhcmFsbGVsIGxv b3AgcHJpdmF0ZSh0bXApCiAgZG8gaSA9IDEsIG4KICAgICBjYWxsIHN1bW1h dGlvbiAodG1wLCBpKQogICAgIHZhbHMoaSkgPSB0bXAKICBlbmQgZG8KICAh JGFjYyBlbmQgcGFyYWxsZWwgbG9vcAoKICBwcmludCAqLCB2YWxzCgogICEk YWNjIHBhcmFsbGVsIGxvb3AgcHJpdmF0ZSh0bXApCiAgZG8gaSA9IDEsIG4K ICAgICBjYWxsIGlzdW1tYXRpb24gKHRtcCwgaSkKICAgICB2YWxzKGkpID0g dG1wCiAgZW5kIGRvCiAgISRhY2MgZW5kIHBhcmFsbGVsIGxvb3AKCiAgcHJp bnQgKiwgdmFscwplbmQgcHJvZ3JhbSBtYWluCgAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AGZvcnRyYW4tcm91dGluZXMvbW9kdWxlLWRyaXZlci5mOTAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAwMDAwNjY0ADAwMDA3NjQAMDAwMDc2NAAwMDAwMDAwMDQx MAAxMjc0NjQ3MTM0MwAwMTY1NTEAIDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdXN0YXIgIABqaW1t eQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGppbW15AAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAcHJvZ3JhbSBtYWluCiAgdXNlIHRlc3QKICBp bXBsaWNpdCBub25lCiAgaW50ZWdlciwgcGFyYW1ldGVyIDo6IG4gPSAxMAog IGludGVnZXIgdmFscyhuKSwgaSwgdG1wCgogICEkYWNjIHBhcmFsbGVsIGxv b3AgcHJpdmF0ZSh0bXApCiAgZG8gaSA9IDEsIG4KICAgICBjYWxsIHN1bW1h dGlvbiAodG1wLCBpKQogICAgIHZhbHMoaSkgPSB0bXAKICBlbmQgZG8KICAh JGFjYyBlbmQgcGFyYWxsZWwgbG9vcAoKICBwcmludCAqLCB2YWxzCmVuZCBw cm9ncmFtIG1haW4KAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABmb3J0cmFuLXJv dXRpbmVzL3Rlc3QtbW9kdWxlLmY5MAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA MDAwMDY2NAAwMDAwNzY0ADAwMDA3NjQAMDAwMDAwMDA0MjAAMTI3NDY0NzAz NDIAMDE2MjM0ACAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAHVzdGFyICAAamltbXkAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAABqaW1teQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAG1vZHVsZSB0ZXN0CmNvbnRhaW5zCiAgc3Vicm91dGluZSBzdW1t YXRpb24ocmVzdWx0LCBuKQogICAgaW1wbGljaXQgbm9uZQogICAgaW50ZWdl ciBuLCByZXN1bHQsIGkKICAgICEkYWNjIHJvdXRpbmUgdmVjdG9yCgogICAg cmVzdWx0ID0gMAoKICAgICEkYWNjIGxvb3AgcmVkdWN0aW9uKCs6cmVzdWx0 KQogICAgZG8gaSA9IDEsIG4KICAgICAgIHJlc3VsdCA9IHJlc3VsdCArIDEK ICAgIGVuZCBkbwogIGVuZCBzdWJyb3V0aW5lIHN1bW1hdGlvbgplbmQgbW9k dWxlIHRlc3QKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== --------------2EF99C5F038630DB88AA4280--